diff --git a/.gitignore b/.gitignore index a77b285..42aa0e8 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ __pycache__/ .venv/ node_modules/ web/dist/ +sidecar/claude-sdk/dist/ state/scratch-compaction-*.md experiments/images/ target/ diff --git a/crates/ghostlight-dungeon/src/world/sdk_inference.rs b/crates/ghostlight-dungeon/src/world/sdk_inference.rs index 4ba19da..c14ef7c 100644 --- a/crates/ghostlight-dungeon/src/world/sdk_inference.rs +++ b/crates/ghostlight-dungeon/src/world/sdk_inference.rs @@ -1377,6 +1377,52 @@ mod tests { ); } + /// The Rust half of the sidecar's schema-grammar pair (spec test 17): + /// publishes every `parameters_json` the two catalogs actually emit, so the + /// sidecar's closed converter is tested against real strings rather than + /// hand-written ones. + #[test] + fn schema_fixtures_match_the_checked_in_sidecar_grammar() { + let granted = vec![AffordanceSnapshot { + id: AffordanceId::issue(), + entry: kernel_speak_entry(), + }]; + let mut emitted: Vec<(String, String)> = patch_tools() + .into_iter() + .chain(catalog_tools("", &granted)) + .chain(catalog_tools("c3__", &granted)) + .map(|tool| (tool.name, tool.parameters_json)) + .collect(); + emitted.sort(); + emitted.dedup(); + let rendered = serde_json::to_string_pretty( + &emitted + .into_iter() + .map( + |(name, schema)| serde_json::json!({ "name": name, "parameters_json": schema }), + ) + .collect::>(), + ) + .unwrap(); + let path = std::path::Path::new(env!("CARGO_MANIFEST_DIR")) + .join("../../sidecar/claude-sdk/test/schemas.json"); + if std::env::var_os("GHOSTLIGHT_WRITE_SIDECAR_FIXTURES").is_some() { + std::fs::create_dir_all(path.parent().unwrap()).unwrap(); + std::fs::write(&path, format!("{rendered}\n")).unwrap(); + } + let on_disk = std::fs::read_to_string(&path).unwrap_or_else(|error| { + panic!( + "the sidecar schema fixture {} is missing ({error}); regenerate with GHOSTLIGHT_WRITE_SIDECAR_FIXTURES=1", + path.display() + ) + }); + assert_eq!( + on_disk.replace("\r\n", "\n"), + format!("{rendered}\n"), + "the emitted tool schemas drifted from the sidecar's converter fixture" + ); + } + /// The Rust half of the sidecar's frame round-trip pair (spec test 18): /// pins the exact `rmp_serde::to_vec_named` bytes the TypeScript decoder is /// tested against, so the two halves cannot drift apart silently. diff --git a/package.json b/package.json index 876fbad..29d2640 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,8 @@ "dungeon:build": "cargo build --workspace && npm --prefix web run build", "dungeon:test": "cargo test --workspace && npm --prefix web run build", "dungeon:run": "cargo run -p ghostlight-dungeon", + "sdk:build": "npm --prefix sidecar/claude-sdk run build", + "sdk:test": "npm --prefix sidecar/claude-sdk test", "state:status": "\"C:\\Users\\Meta\\.cache\\codex-runtimes\\codex-primary-runtime\\dependencies\\python\\python.exe\" .\\tools\\ghostlight_state.py status", "state:prepare-compaction": "\"C:\\Users\\Meta\\.cache\\codex-runtimes\\codex-primary-runtime\\dependencies\\python\\python.exe\" .\\tools\\ghostlight_prepare_compaction.py", "agent-state:validate": "\"C:\\Users\\Meta\\.cache\\codex-runtimes\\codex-primary-runtime\\dependencies\\python\\python.exe\" .\\tools\\validate_agent_state.py", diff --git a/sidecar/claude-sdk/package-lock.json b/sidecar/claude-sdk/package-lock.json new file mode 100644 index 0000000..fd71505 --- /dev/null +++ b/sidecar/claude-sdk/package-lock.json @@ -0,0 +1,1558 @@ +{ + "name": "ghostlight-claude-sdk-sidecar", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "ghostlight-claude-sdk-sidecar", + "version": "0.1.0", + "dependencies": { + "@anthropic-ai/claude-agent-sdk": "0.3.261", + "@msgpack/msgpack": "3.1.3", + "zod": "4.5.4" + }, + "devDependencies": { + "@types/node": "24.13.3", + "typescript": "5.9.3" + }, + "engines": { + "node": ">=24 <25" + } + }, + "node_modules/@anthropic-ai/claude-agent-sdk": { + "version": "0.3.261", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.3.261.tgz", + "integrity": "sha512-CDG9z14JVKYRHjpp/g6zJ2k8xM5uSoRgjGdpTiK9woLDZxXtXcxV93ipCh55jQ3REj7M7H3GieMsETGZXB/ydw==", + "license": "SEE LICENSE IN README.md", + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "@anthropic-ai/claude-agent-sdk-darwin-arm64": "0.3.261", + "@anthropic-ai/claude-agent-sdk-darwin-x64": "0.3.261", + "@anthropic-ai/claude-agent-sdk-linux-arm64": "0.3.261", + "@anthropic-ai/claude-agent-sdk-linux-arm64-musl": "0.3.261", + "@anthropic-ai/claude-agent-sdk-linux-x64": "0.3.261", + "@anthropic-ai/claude-agent-sdk-linux-x64-musl": "0.3.261", + "@anthropic-ai/claude-agent-sdk-win32-arm64": "0.3.261", + "@anthropic-ai/claude-agent-sdk-win32-x64": "0.3.261" + }, + "peerDependencies": { + "@anthropic-ai/sdk": ">=0.93.0", + "@modelcontextprotocol/sdk": "^1.29.0", + "zod": "^4.0.0" + } + }, + "node_modules/@anthropic-ai/claude-agent-sdk-darwin-arm64": { + "version": "0.3.261", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-arm64/-/claude-agent-sdk-darwin-arm64-0.3.261.tgz", + "integrity": "sha512-oI8SPd6g+xUF6EnEqIInxz5CjSSJXoDlaqefjbSJvTFCawGGBhxlQs0g9jzsYou6Rdu+i2tJBToJZLsKSnN/0Q==", + "cpu": [ + "arm64" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@anthropic-ai/claude-agent-sdk-darwin-x64": { + "version": "0.3.261", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-x64/-/claude-agent-sdk-darwin-x64-0.3.261.tgz", + "integrity": "sha512-PODd45XbrKxwngebFmc60Xd68QDb7xCo+0toYTJKfFumU24b/JT2WpO5sTSfc5+fahd/P11q0uF5v9YeSjWmjg==", + "cpu": [ + "x64" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@anthropic-ai/claude-agent-sdk-linux-arm64": { + "version": "0.3.261", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64/-/claude-agent-sdk-linux-arm64-0.3.261.tgz", + "integrity": "sha512-C+y3N3MD2ExrwrbCYcbLdM39VkbJkQKUv23oubvoZr0CtHiH2LESyUUC3JsUbHJ1TRKO8fbzLqvPkjZ9UsBIcw==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@anthropic-ai/claude-agent-sdk-linux-arm64-musl": { + "version": "0.3.261", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64-musl/-/claude-agent-sdk-linux-arm64-musl-0.3.261.tgz", + "integrity": "sha512-BAUG2EremVyy8bA14jKF35VRJjGE2TqREpFerA0CRBWg9/sUJZVWdmIRXUiXCKh0MvenPRUJbEgwcHFllQETOw==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@anthropic-ai/claude-agent-sdk-linux-x64": { + "version": "0.3.261", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64/-/claude-agent-sdk-linux-x64-0.3.261.tgz", + "integrity": "sha512-MdojjfN0HJHT0JMiZJ6rTj3/ODNi5OdY0py1JZmVVEVTYOdvgH6OG3oy9/BmmJTx0mp/BBCHbOGNpibtnqE+1g==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@anthropic-ai/claude-agent-sdk-linux-x64-musl": { + "version": "0.3.261", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64-musl/-/claude-agent-sdk-linux-x64-musl-0.3.261.tgz", + "integrity": "sha512-H7sCtM7X9OyQ+ZCEhh6TY/Z1i+5WIn8YyHRVJ2LrZRFOaszPeDbl1SzSxxuOd5ibwJZA9gx+2uQ78dx+bDkQUA==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@anthropic-ai/claude-agent-sdk-win32-arm64": { + "version": "0.3.261", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-arm64/-/claude-agent-sdk-win32-arm64-0.3.261.tgz", + "integrity": "sha512-zvZfec4+wDooqF/ZOI3lthgq9WfZLIrSserS6tULpBqCLKNRbTIpARDcljY7SrRuMGb3Ex+LFn/yXazgajpwzg==", + "cpu": [ + "arm64" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@anthropic-ai/claude-agent-sdk-win32-x64": { + "version": "0.3.261", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-x64/-/claude-agent-sdk-win32-x64-0.3.261.tgz", + "integrity": "sha512-tepSwNpNsl4tyDdJ1+YcRXeY7VZNirPqpCtKDuh2YVwDkMfzQevCqojURtACAdLwI8BUXeOGaecwRbh3zoSUtA==", + "cpu": [ + "x64" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@anthropic-ai/sdk": { + "version": "0.124.0", + "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.124.0.tgz", + "integrity": "sha512-cN5O8i9UVxHeOQAzj/XjshWXG8KiibJDw9OGpH2Z/eR3n/RBxdoLxDJOcfqAJWvjaMDFfHTBADU04hWRJVkDyA==", + "license": "MIT", + "peer": true, + "dependencies": { + "json-schema-to-ts": "^3.1.1", + "standardwebhooks": "^1.0.0" + }, + "bin": { + "anthropic-ai-sdk": "bin/cli" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + }, + "peerDependenciesMeta": { + "zod": { + "optional": true + } + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@hono/node-server": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-2.1.1.tgz", + "integrity": "sha512-ELuehkj5VCBdgEw9zs+ivkKwyzzUCSQuE96YmiPvn1ECBoZCczbFXJLeEGMTYjphP6gydh4pHMqEYPVMYUVgQg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=20" + }, + "peerDependencies": { + "hono": "^4" + } + }, + "node_modules/@modelcontextprotocol/sdk": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.30.0.tgz", + "integrity": "sha512-xKd8OIzlqNzcqcNumGAa6g+PW2kjD5vrpcKOnfldAUPP3j7lnqMPwlTXQm8gF+UwH72z0lqaRbjr9hqGz0eITA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@hono/node-server": "^1.19.9 || ^2.0.5", + "ajv": "^8.17.1", + "ajv-formats": "^3.0.1", + "content-type": "^1.0.5", + "cors": "^2.8.5", + "cross-spawn": "^7.0.5", + "eventsource": "^3.0.2", + "eventsource-parser": "^3.0.0", + "express": "^5.2.1", + "express-rate-limit": "^8.2.1", + "hono": "^4.11.4", + "jose": "^6.1.3", + "json-schema-typed": "^8.0.2", + "pkce-challenge": "^5.0.0", + "raw-body": "^3.0.0", + "zod": "^3.25 || ^4.0", + "zod-to-json-schema": "^3.25.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@cfworker/json-schema": "^4.1.1", + "zod": "^3.25 || ^4.0" + }, + "peerDependenciesMeta": { + "@cfworker/json-schema": { + "optional": true + }, + "zod": { + "optional": false + } + } + }, + "node_modules/@msgpack/msgpack": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@msgpack/msgpack/-/msgpack-3.1.3.tgz", + "integrity": "sha512-47XIizs9XZXvuJgoaJUIE2lFoID8ugvc0jzSHP+Ptfk8nTbnR8g788wv48N03Kx0UkAv559HWRQ3yzOgzlRNUA==", + "license": "ISC", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@stablelib/base64": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/base64/-/base64-1.0.1.tgz", + "integrity": "sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ==", + "license": "MIT", + "peer": true + }, + "node_modules/@types/node": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.3.tgz", + "integrity": "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.18.0" + } + }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "peer": true, + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "license": "MIT", + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/body-parser": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.3.0.tgz", + "integrity": "sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==", + "license": "MIT", + "peer": true, + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^2.0.0", + "debug": "^4.4.3", + "http-errors": "^2.0.1", + "iconv-lite": "^0.7.2", + "on-finished": "^2.4.1", + "qs": "^6.15.2", + "raw-body": "^3.0.2", + "type-is": "^2.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/body-parser/node_modules/content-type": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.1.0.tgz", + "integrity": "sha512-mj7UPXE0jaqaOsukNZRUEfEi2AcL7C/vwmwcHV0O97eO1E1pxBZuyjlZrx5seTaNBg1U6+o35wpa35Qfcc+7ag==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "peer": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/content-disposition": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.1.0.tgz", + "integrity": "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/cors": { + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", + "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", + "license": "MIT", + "peer": true, + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "peer": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "peer": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT", + "peer": true + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "license": "MIT", + "peer": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT", + "peer": true + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventsource": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz", + "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==", + "license": "MIT", + "peer": true, + "dependencies": { + "eventsource-parser": "^3.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/eventsource-parser": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.1.1.tgz", + "integrity": "sha512-EKN1vKAMcZ8MlYMpaNuxN6R9yakzH6uajHcHVTqWJzvu5pWw9DyhbP35HH8MVBQ+dZjAfDxk+A8NiR9KWaXiyQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/express": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", + "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", + "license": "MIT", + "peer": true, + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.1", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "depd": "^2.0.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express-rate-limit": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.7.0.tgz", + "integrity": "sha512-hOwV7WOxXfjRpAM1DSJWZDXx3GhplwD8IfwuwvogD8i1Qnkgosw/H45s4ZnFAUHDAhPjlY9hLBvJhKmGMyY26g==", + "license": "MIT", + "peer": true, + "dependencies": { + "debug": "^4.4.3", + "ip-address": "^10.2.0" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/express-rate-limit" + }, + "peerDependencies": { + "express": ">= 4.11" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT", + "peer": true + }, + "node_modules/fast-sha256": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-sha256/-/fast-sha256-1.3.0.tgz", + "integrity": "sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ==", + "license": "Unlicense", + "peer": true + }, + "node_modules/fast-uri": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.7.tgz", + "integrity": "sha512-dOvZVzjdZdz7phd9v6jCbwxrBW3fK6n8Rc0CtdmM4bumzMnxywBYhuph6J819RRw/ku+rLbelwfMunktuzVVHg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/finalhandler": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", + "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", + "license": "MIT", + "peer": true, + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "peer": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "peer": true, + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", + "peer": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hono": { + "version": "4.13.7", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.13.7.tgz", + "integrity": "sha512-c8/gF9ac8Y78/agExVocyLevgR+JlpNB444Py0FSX8pJoPdYUfUzRcXtYEYGwt6l19qIlVZPN5Mfsw9jFShmQQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=16.9.0" + } + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/iconv-lite": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.3.tgz", + "integrity": "sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC", + "peer": true + }, + "node_modules/ip-address": { + "version": "10.7.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.7.0.tgz", + "integrity": "sha512-BGFsyJd5mpXp3rK6jIdADLNgpJUK1jnjzvYF8lK+VyDab9JAmqN0YOKDdP17HlgKb2+ehPgDc8EtnRLbGCAMhA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT", + "peer": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC", + "peer": true + }, + "node_modules/jose": { + "version": "6.2.12", + "resolved": "https://registry.npmjs.org/jose/-/jose-6.2.12.tgz", + "integrity": "sha512-9NiFmJEex0sy2Dk58j2UGBSHgUs2ypF9eZSu4L6vjOX3Dp96Sw1F3uL+H+D1sx02jZZdzUT0HgvCy59CuvXcWw==", + "license": "MIT", + "peer": true, + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/json-schema-to-ts": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/json-schema-to-ts/-/json-schema-to-ts-3.1.1.tgz", + "integrity": "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.18.3", + "ts-algebra": "^2.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT", + "peer": true + }, + "node_modules/json-schema-typed": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-8.0.2.tgz", + "integrity": "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==", + "license": "BSD-2-Clause", + "peer": true + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.1.tgz", + "integrity": "sha512-yz3xRaG20c6/BOzvYoDaGtPmGscs7YivItZEEqe6GbwNfHuxu9YNmvnEkMzKldAGY4/80pRcQRZSEnhquk9XuQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", + "license": "MIT", + "peer": true, + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT", + "peer": true + }, + "node_modules/negotiator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.1.0.tgz", + "integrity": "sha512-NMPBRMJgiQHjbd8phG3Vebdx4kZ1H121rbl5IkMqeOsahptB9BKo/d7oJ3zTXqTgagn2bWlNSXkh0QUGM31RYg==", + "license": "MIT", + "peer": true, + "dependencies": { + "content-type": "^2.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/negotiator/node_modules/content-type": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.1.0.tgz", + "integrity": "sha512-mj7UPXE0jaqaOsukNZRUEfEi2AcL7C/vwmwcHV0O97eO1E1pxBZuyjlZrx5seTaNBg1U6+o35wpa35Qfcc+7ag==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "peer": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "peer": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-to-regexp": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.2.tgz", + "integrity": "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==", + "license": "MIT", + "peer": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/pkce-challenge": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.1.tgz", + "integrity": "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "peer": true, + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.16.0.tgz", + "integrity": "sha512-h6fhOIaRrID2CbEY2fqs+7t+UXZo+MLAnU5gRIq85uFtdiUPCdsApMlHhXogKVM4HM2DVbIjGNTTYH2OcmP1vA==", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "es-define-property": "^1.0.1", + "side-channel": "^1.1.1" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.3.0.tgz", + "integrity": "sha512-hek2mFQpPuI4E1BBKrSto+BU3e3x4xuarsbiwr3+lf7p44juvFMV0XFWQAP3xUyqXA4RrXLIoaSUGbSt056ZMw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/raw-body": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", + "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", + "license": "MIT", + "peer": true, + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.7.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT", + "peer": true + }, + "node_modules/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", + "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "debug": "^4.4.3", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.1", + "mime-types": "^3.0.2", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/serve-static": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", + "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", + "license": "MIT", + "peer": true, + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC", + "peer": true + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "peer": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "license": "MIT", + "peer": true, + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "peer": true, + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "peer": true, + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/standardwebhooks": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/standardwebhooks/-/standardwebhooks-1.1.1.tgz", + "integrity": "sha512-bCbX9ZEyFkWPsRz7Bl3NuQUJohmwGSev/yhr7vhaGPlc4AfIrspIRa6cPTBuI1ItmrTDJ4d/S2hCsfe4+vQGnQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@stablelib/base64": "^1.0.0", + "fast-sha256": "^1.3.0" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/ts-algebra": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ts-algebra/-/ts-algebra-2.0.0.tgz", + "integrity": "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==", + "license": "MIT", + "peer": true + }, + "node_modules/type-is": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.1.0.tgz", + "integrity": "sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==", + "license": "MIT", + "peer": true, + "dependencies": { + "content-type": "^2.0.0", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/type-is/node_modules/content-type": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.1.0.tgz", + "integrity": "sha512-mj7UPXE0jaqaOsukNZRUEfEi2AcL7C/vwmwcHV0O97eO1E1pxBZuyjlZrx5seTaNBg1U6+o35wpa35Qfcc+7ag==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", + "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "peer": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC", + "peer": true + }, + "node_modules/zod": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.5.4.tgz", + "integrity": "sha512-sC95tT5iHHH9gtpj6A81kh+NEaRAUFN+qlUPDUbRfOMvNf5QCBqsb3WgvnpVtK5Y+4UfA6KqufotuTvMGiTlsA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-to-json-schema": { + "version": "3.25.2", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.2.tgz", + "integrity": "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==", + "license": "ISC", + "peer": true, + "peerDependencies": { + "zod": "^3.25.28 || ^4" + } + } + } +} diff --git a/sidecar/claude-sdk/package.json b/sidecar/claude-sdk/package.json new file mode 100644 index 0000000..4c104bb --- /dev/null +++ b/sidecar/claude-sdk/package.json @@ -0,0 +1,18 @@ +{ + "name": "ghostlight-claude-sdk-sidecar", + "version": "0.1.0", + "private": true, + "type": "module", + "description": "Ghostlight's Claude Agent SDK sidecar. Reads length-prefixed MessagePack frames on stdin, runs one SDK query, and answers every tool call by asking Rust. It computes nothing and holds no credential.", + "engines": { "node": ">=24 <25" }, + "scripts": { + "build": "tsc -p .", + "test": "node --experimental-strip-types --test \"test/**/*.test.ts\"" + }, + "dependencies": { + "@anthropic-ai/claude-agent-sdk": "0.3.261", + "@msgpack/msgpack": "3.1.3", + "zod": "4.5.4" + }, + "devDependencies": { "@types/node": "24.13.3", "typescript": "5.9.3" } +} diff --git a/sidecar/claude-sdk/src/frames.ts b/sidecar/claude-sdk/src/frames.ts new file mode 100644 index 0000000..dbe5fa7 --- /dev/null +++ b/sidecar/claude-sdk/src/frames.ts @@ -0,0 +1,158 @@ +// The wire between Rust and this sidecar: a 4-byte big-endian length prefix +// followed by MessagePack with string keys, matching `rmp_serde::to_vec_named`. +// Rust owns the shapes; this file only encodes and decodes them. + +import { decode, encode } from "@msgpack/msgpack"; + +/** The connector's own frame cap. Rust refuses anything larger on its side too. */ +export const MAX_FRAME_BYTES = 1_052_672; + +export interface SidecarTool { + name: string; + description: string; + parameters_json: string; +} + +export type SidecarEvent = + | { kind: "text"; text: string } + | { + kind: "tool_call"; + call_id: string; + name: string; + arguments: string; + dispatched: boolean; + }; + +export interface SdkModelUsage { + model: string; + input_tokens: number; + output_tokens: number; + cache_read_input_tokens: number; + cache_creation_input_tokens: number; +} + +export interface SdkResultMaterial { + session_id: string; + result_uuid: string; + subtype: string; + stop_reason: string | null; + num_turns: number; + assistant_message_uuids: string[]; + assistant_request_ids: string[]; + usage: SdkModelUsage[]; + total_cost_usd_estimate: string; +} + +/** + * The closed set of failures this sidecar may name. It reports a reason; Rust + * assigns the disposition, so nothing here can quarantine the world. + */ +export type SidecarFaultReason = + | "rate_limited" + | "overloaded" + | "server_error" + | "api_timeout" + | "authentication_failed" + | "org_not_allowed" + | "billing_error" + | "invalid_request" + | "model_not_found" + | "max_output_tokens" + | "max_budget_usd" + | "execution_error" + | "unknown" + | "protocol_violation" + | "tool_registration_failed" + | "turn_cap_refused"; + +export type SidecarFrame = + | { + kind: "query"; + query_id: number; + model: string; + instructions: string; + prompt: string; + transcript: string[]; + tools: SidecarTool[]; + effort: string | null; + max_output_tokens: number | null; + turn_cap: number; + } + | { + kind: "tool_call"; + query_id: number; + call_id: string; + name: string; + arguments: string; + } + | { + kind: "tool_result"; + query_id: number; + call_id: string; + output: string; + } + | { + kind: "output"; + query_id: number; + events: SidecarEvent[]; + receipt: SdkResultMaterial; + } + | { + kind: "fault"; + query_id: number; + reason: SidecarFaultReason; + detail: string; + }; + +export function encodeFrame(frame: SidecarFrame): Uint8Array { + const body = encode(frame, { useBigInt64: false }); + if (body.length > MAX_FRAME_BYTES) { + throw new Error(`frame of ${body.length} bytes exceeds ${MAX_FRAME_BYTES}`); + } + const framed = new Uint8Array(4 + body.length); + new DataView(framed.buffer).setUint32(0, body.length, false); + framed.set(body, 4); + return framed; +} + +export function decodeFrameBody(body: Uint8Array): SidecarFrame { + const value = decode(body); + if (typeof value !== "object" || value === null || !("kind" in value)) { + throw new Error("a sidecar frame decoded to something without a kind"); + } + return value as SidecarFrame; +} + +/** Reassembles frames from an arbitrarily chunked byte stream. */ +export class FrameReader { + #buffer = new Uint8Array(0); + + push(chunk: Uint8Array): void { + const grown = new Uint8Array(this.#buffer.length + chunk.length); + grown.set(this.#buffer, 0); + grown.set(chunk, this.#buffer.length); + this.#buffer = grown; + } + + /** The next whole frame, or null while one is still arriving. */ + next(): SidecarFrame | null { + if (this.#buffer.length < 4) { + return null; + } + const length = new DataView( + this.#buffer.buffer, + this.#buffer.byteOffset, + 4, + ).getUint32(0, false); + if (length === 0 || length > MAX_FRAME_BYTES) { + throw new Error(`frame length ${length} is outside 1..=${MAX_FRAME_BYTES}`); + } + if (this.#buffer.length < 4 + length) { + return null; + } + const body = this.#buffer.subarray(4, 4 + length); + const frame = decodeFrameBody(body); + this.#buffer = this.#buffer.slice(4 + length); + return frame; + } +} diff --git a/sidecar/claude-sdk/src/main.ts b/sidecar/claude-sdk/src/main.ts new file mode 100644 index 0000000..0582881 --- /dev/null +++ b/sidecar/claude-sdk/src/main.ts @@ -0,0 +1,491 @@ +// Ghostlight's Claude Agent SDK sidecar. +// +// One query at a time, one child process for many queries. Every tool call is +// forwarded to Rust and answered by Rust: this process computes no tool result, +// reads no credential, logs no prompt, argument, or result, and writes nothing +// outside its own stdout. +// +// Operator prerequisites, none of which Ghostlight performs: install the Claude +// Code CLI, sign in with `/login` or mint a token with `claude setup-token`, +// verify with one plain `claude -p` query, then `npm --prefix sidecar/claude-sdk +// install` and `npm run sdk:build`. The SDK finds that login on its own through +// the ambient environment. Nothing in this repository reads, copies, forwards, +// or logs the credential. +// +// Runtime binding: `GHOSTLIGHT_SDK_SIDECAR` is this file's built path +// (`sidecar/claude-sdk/dist/main.js`) and `GHOSTLIGHT_SDK_MODEL_PREFIX` +// (default `claude`) is the model-name prefix that routes a lane here. + +import { + createSdkMcpServer, + query, + tool, + type Options, +} from "@anthropic-ai/claude-agent-sdk"; +import { + FrameReader, + encodeFrame, + type SdkModelUsage, + type SdkResultMaterial, + type SidecarEvent, + type SidecarFaultReason, + type SidecarFrame, + type SidecarTool, +} from "./frames.ts"; +import { toolRawShape } from "./schema.ts"; +import { resolve } from "node:path"; +import { pathToFileURL } from "node:url"; + +const SERVER_NAME = "ghostlight"; +const QUALIFIED_PREFIX = `mcp__${SERVER_NAME}__`; +/** The header a prior round's rendered transcript is folded under. */ +const TRANSCRIPT_HEADER = + "Earlier turns in this same request, as they happened:"; +/** No deadline tighter than the Rust side's own response timeout. */ +const RENDEZVOUS_TIMEOUT_MS = 900_000; +/** The largest round budget any Ghostlight lane carries. */ +const MAX_TURN_CAP = 24; + +export class SidecarFault extends Error { + readonly reason: SidecarFaultReason; + + constructor(reason: SidecarFaultReason, detail: string) { + super(detail); + this.reason = reason; + } +} + +interface Dispatch { + call_id: string; + name: string; + arguments: string; +} + +/** One in-flight query's rendezvous with Rust. */ +export class QuerySession { + readonly dispatches: Dispatch[] = []; + readonly queryId: number; + readonly #pending = new Map void>(); + readonly #write: (frame: SidecarFrame) => void; + #nextCall = 0; + + constructor(queryId: number, write: (frame: SidecarFrame) => void) { + this.queryId = queryId; + this.#write = write; + } + + /** Sends one call to Rust and resolves when Rust answers it. */ + async ask(name: string, args: unknown): Promise { + const call_id = `c${this.#nextCall++}`; + const argumentsJson = JSON.stringify(args ?? {}); + this.dispatches.push({ call_id, name, arguments: argumentsJson }); + const answer = new Promise((resolve) => { + this.#pending.set(call_id, resolve); + }); + this.#write({ + kind: "tool_call", + query_id: this.queryId, + call_id, + name, + arguments: argumentsJson, + }); + return answer; + } + + answer(call_id: string, output: string): void { + const resolve = this.#pending.get(call_id); + if (!resolve) { + throw new SidecarFault( + "protocol_violation", + `a tool result arrived for the unissued call ${call_id}`, + ); + } + this.#pending.delete(call_id); + resolve(output); + } +} + +function apiRetryReason(category: unknown): SidecarFaultReason { + switch (category) { + case "rate_limit": + return "rate_limited"; + case "overloaded": + return "overloaded"; + case "server_error": + return "server_error"; + case "authentication_failed": + return "authentication_failed"; + case "oauth_org_not_allowed": + return "org_not_allowed"; + case "billing_error": + return "billing_error"; + case "invalid_request": + return "invalid_request"; + case "model_not_found": + return "model_not_found"; + case "max_output_tokens": + return "max_output_tokens"; + default: + return "unknown"; + } +} + +function resultReason(subtype: string, apiErrorStatus: unknown): SidecarFaultReason { + if (typeof apiErrorStatus === "number") { + if (apiErrorStatus === 429) { + return "rate_limited"; + } + if (apiErrorStatus >= 500) { + return "server_error"; + } + } + switch (subtype) { + case "error_max_budget_usd": + return "max_budget_usd"; + case "error_during_execution": + case "error_max_structured_output_retries": + return "execution_error"; + default: + return "unknown"; + } +} + +function usageRows(modelUsage: unknown): SdkModelUsage[] { + if (typeof modelUsage !== "object" || modelUsage === null) { + return []; + } + return Object.entries(modelUsage as Record>).map( + ([model, row]) => ({ + model, + input_tokens: Number(row?.inputTokens ?? row?.input_tokens ?? 0), + output_tokens: Number(row?.outputTokens ?? row?.output_tokens ?? 0), + cache_read_input_tokens: Number( + row?.cacheReadInputTokens ?? row?.cache_read_input_tokens ?? 0, + ), + cache_creation_input_tokens: Number( + row?.cacheCreationInputTokens ?? row?.cache_creation_input_tokens ?? 0, + ), + }), + ); +} + +/** + * The `query()` options one frame lowers to. Exported so a test can assert the + * hygiene — no CLAUDE.md, no settings, no built-in tools, no persisted session + * — against a stub instead of a live query. + */ +export function lowerQuery( + frame: Extract, + session: QuerySession, +): { prompt: string; options: Options } { + if (frame.turn_cap < 1 || frame.turn_cap > MAX_TURN_CAP) { + throw new SidecarFault( + "turn_cap_refused", + `turn cap ${frame.turn_cap} is outside 1..=${MAX_TURN_CAP}`, + ); + } + const tools = frame.tools.map((entry: SidecarTool) => { + let shape; + try { + shape = toolRawShape(entry.parameters_json, entry.name); + } catch (error) { + throw new SidecarFault("tool_registration_failed", String(error)); + } + return tool( + entry.name, + entry.description, + shape, + async (args: unknown) => ({ + content: [ + { type: "text" as const, text: await session.ask(entry.name, args) }, + ], + }), + { alwaysLoad: true }, + ); + }); + const prompt = frame.transcript.length + ? `${frame.prompt}\n\n${TRANSCRIPT_HEADER}\n${frame.transcript.join("\n")}` + : frame.prompt; + const options: Record = { + systemPrompt: { type: "custom", prompt: frame.instructions }, + // No CLAUDE.md, no settings.json, no output styles, no built-in tools. + settingSources: [], + tools: [], + strictMcpConfig: true, + model: frame.model, + maxTurns: frame.turn_cap, + includePartialMessages: false, + persistSession: false, + }; + if (frame.effort) { + options.effort = frame.effort; + } + if (tools.length) { + options.mcpServers = { + [SERVER_NAME]: createSdkMcpServer({ + name: SERVER_NAME, + tools, + alwaysLoad: true, + timeout: RENDEZVOUS_TIMEOUT_MS, + }), + }; + options.allowedTools = [`${QUALIFIED_PREFIX}*`]; + } + return { prompt, options: options as unknown as Options }; +} + +function strip(name: string): string { + return name.startsWith(QUALIFIED_PREFIX) + ? name.slice(QUALIFIED_PREFIX.length) + : name; +} + +/** + * Walks the assistant messages in order and pairs each registered tool_use + * block with the dispatch it caused, so the ids Rust answered and the ids + * reported here are the same ids. + */ +export function assembleEvents( + messages: { content: unknown }[], + registered: Set, + dispatches: Dispatch[], +): SidecarEvent[] { + const events: SidecarEvent[] = []; + let taken = 0; + let undispatched = 0; + for (const message of messages) { + const blocks = Array.isArray(message.content) ? message.content : []; + for (const block of blocks as Record[]) { + if (block.type === "text" && typeof block.text === "string") { + events.push({ kind: "text", text: block.text }); + continue; + } + if (block.type !== "tool_use") { + continue; + } + const name = strip(String(block.name ?? "")); + if (registered.has(name)) { + const dispatch = dispatches[taken++]; + if (!dispatch || dispatch.name !== name) { + throw new SidecarFault( + "protocol_violation", + `a registered tool_use block for ${name} has no matching dispatch`, + ); + } + events.push({ kind: "tool_call", ...dispatch, dispatched: true }); + continue; + } + events.push({ + kind: "tool_call", + call_id: `u${undispatched++}`, + name, + arguments: JSON.stringify(block.input ?? {}), + dispatched: false, + }); + } + } + if (taken !== dispatches.length) { + throw new SidecarFault( + "protocol_violation", + "more tool calls were dispatched than the assistant messages report", + ); + } + return events; +} + +async function runQuery( + frame: Extract, + write: (frame: SidecarFrame) => void, + session: QuerySession, +): Promise { + const registered = new Set(frame.tools.map((entry) => entry.name)); + const { prompt, options } = lowerQuery(frame, session); + const assistant: { content: unknown }[] = []; + const material: SdkResultMaterial = { + session_id: "", + result_uuid: "", + subtype: "", + stop_reason: null, + num_turns: 0, + assistant_message_uuids: [], + assistant_request_ids: [], + usage: [], + total_cost_usd_estimate: "0", + }; + let sawResult = false; + const stream = query({ prompt, options }); + try { + for await (const message of stream as AsyncIterable>) { + if (message.type === "assistant") { + const inner = message.message as Record | undefined; + assistant.push({ content: inner?.content }); + if (typeof message.uuid === "string") { + material.assistant_message_uuids.push(message.uuid); + } + if (typeof message.request_id === "string") { + material.assistant_request_ids.push(message.request_id); + } + continue; + } + if (message.type === "system" && message.subtype === "api_retry") { + // The harness owns its own retries; only an exhausted one reaches a + // result, so this is recorded and not raised. + continue; + } + if (message.type !== "result") { + continue; + } + sawResult = true; + const subtype = String(message.subtype ?? ""); + material.session_id = String(message.session_id ?? ""); + material.result_uuid = String(message.uuid ?? ""); + material.subtype = subtype; + material.stop_reason = + typeof message.stop_reason === "string" ? message.stop_reason : null; + material.num_turns = Number(message.num_turns ?? 0); + material.usage = usageRows(message.modelUsage); + material.total_cost_usd_estimate = String(message.total_cost_usd ?? 0); + // `error_max_turns` is not a fault: the cap is the lane's own remaining + // round budget, so reaching it means the model spent turns the evaluator + // would also have allowed. The lane sees one ordinary round. + if (subtype !== "success" && subtype !== "error_max_turns") { + const errors = Array.isArray(message.errors) + ? (message.errors as unknown[]).map(String).join("; ") + : ""; + const category = Array.isArray(message.errors) + ? undefined + : (message as Record).error; + const reason = + category === undefined + ? resultReason(subtype, message.api_error_status) + : apiRetryReason(category); + throw new SidecarFault(reason, `${subtype}: ${errors}`); + } + } + } catch (error) { + // The TS SDK throws after yielding an error result. A result already + // collected for `error_max_turns` is the normal path, so only an + // unaccounted throw becomes a fault. + if (error instanceof SidecarFault) { + throw error; + } + if (!sawResult) { + throw new SidecarFault("execution_error", String(error)); + } + } + if (!sawResult) { + throw new SidecarFault("execution_error", "the SDK query produced no result"); + } + write({ + kind: "output", + query_id: frame.query_id, + events: assembleEvents(assistant, registered, session.dispatches), + receipt: material, + }); +} + +async function main(): Promise { + const reader = new FrameReader(); + const write = (frame: SidecarFrame) => { + process.stdout.write(encodeFrame(frame)); + }; + let live: QuerySession | null = null; + let running: Promise = Promise.resolve(); + + for await (const chunk of process.stdin) { + reader.push(chunk as Uint8Array); + for (;;) { + let frame: SidecarFrame | null; + try { + frame = reader.next(); + } catch (error) { + write({ + kind: "fault", + query_id: live?.queryId ?? 0, + reason: "protocol_violation", + detail: String(error), + }); + return; + } + if (!frame) { + break; + } + if (frame.kind === "query") { + if (live) { + write({ + kind: "fault", + query_id: frame.query_id, + reason: "protocol_violation", + detail: "a second query arrived while one was in flight", + }); + continue; + } + const opening = frame; + const session = new QuerySession(opening.query_id, write); + live = session; + running = (async () => { + try { + await runQuery(opening, write, session); + } catch (error) { + const fault = + error instanceof SidecarFault + ? error + : new SidecarFault("execution_error", String(error)); + write({ + kind: "fault", + query_id: opening.query_id, + reason: fault.reason, + detail: fault.message, + }); + } finally { + live = null; + } + })(); + void running; + continue; + } + if (frame.kind === "tool_result") { + if (!live || live.queryId !== frame.query_id) { + write({ + kind: "fault", + query_id: frame.query_id, + reason: "protocol_violation", + detail: "a tool result arrived outside its query", + }); + continue; + } + try { + live.answer(frame.call_id, frame.output); + } catch (error) { + const fault = + error instanceof SidecarFault + ? error + : new SidecarFault("protocol_violation", String(error)); + write({ + kind: "fault", + query_id: frame.query_id, + reason: fault.reason, + detail: fault.message, + }); + } + continue; + } + write({ + kind: "fault", + query_id: 0, + reason: "protocol_violation", + detail: `frame kind ${frame.kind} is not one this sidecar accepts`, + }); + } + } + await running; +} + +// Only run the loop when this file is the entry point, so the tests can import +// its pure halves without starting a stdin reader. +if ( + process.argv[1] && + import.meta.url === pathToFileURL(resolve(process.argv[1])).href +) { + await main(); +} diff --git a/sidecar/claude-sdk/src/schema.ts b/sidecar/claude-sdk/src/schema.ts new file mode 100644 index 0000000..cf885c7 --- /dev/null +++ b/sidecar/claude-sdk/src/schema.ts @@ -0,0 +1,134 @@ +// The JSON Schema grammar Ghostlight's one emitter produces, converted to the +// Zod raw shape the SDK's `tool()` takes. It is closed on purpose: anything +// outside the grammar throws, so an emitter that grows a construct fails a test +// here rather than silently registering a looser tool. + +import { z } from "zod"; + +type Json = Record; + +const FORBIDDEN = ["oneOf", "allOf", "not", "$ref"] as const; + +function isObject(value: unknown): value is Json { + return typeof value === "object" && value !== null && !Array.isArray(value); +} + +function convert(node: unknown, at: string): z.ZodTypeAny { + if (!isObject(node)) { + throw new Error(`${at}: schema node is not an object`); + } + for (const forbidden of FORBIDDEN) { + if (forbidden in node) { + throw new Error(`${at}: \`${forbidden}\` is outside the emitted grammar`); + } + } + if ("anyOf" in node) { + const branches = node.anyOf; + if (!Array.isArray(branches) || branches.length === 0) { + throw new Error(`${at}: anyOf must be a nonempty array`); + } + // The nullable shape the emitter uses for an optional argument. + if ( + branches.length === 2 && + isObject(branches[1]) && + branches[1].type === "null" + ) { + return convert(branches[0], `${at}/anyOf/0`).nullable(); + } + const converted = branches.map((branch, index) => + convert(branch, `${at}/anyOf/${index}`), + ); + if (converted.length === 1) { + return converted[0]!; + } + return z.union(converted as [z.ZodTypeAny, z.ZodTypeAny, ...z.ZodTypeAny[]]); + } + const kind = node.type; + if (typeof kind !== "string") { + throw new Error(`${at}: schema node names no type`); + } + switch (kind) { + case "object": + return z.object(rawShape(node, at)).strict(); + case "string": { + if ("const" in node) { + if (typeof node.const !== "string") { + throw new Error(`${at}: a string const must be a string`); + } + return z.literal(node.const); + } + if ("enum" in node) { + const values = node.enum; + if ( + !Array.isArray(values) || + values.length === 0 || + values.some((value) => typeof value !== "string") + ) { + throw new Error(`${at}: enum must be a nonempty array of strings`); + } + return z.enum(values as [string, ...string[]]); + } + return z.string(); + } + case "integer": { + let schema = z.number().int(); + if (typeof node.minimum === "number") { + schema = schema.min(node.minimum); + } + if (typeof node.maximum === "number") { + schema = schema.max(node.maximum); + } + return schema; + } + case "boolean": + return z.boolean(); + case "null": + return z.null(); + case "array": + return z.array(convert(node.items, `${at}/items`)); + default: + throw new Error(`${at}: type \`${kind}\` is outside the emitted grammar`); + } +} + +function rawShape(node: Json, at: string): Record { + if (node.additionalProperties !== false) { + throw new Error(`${at}: every emitted object is closed`); + } + const properties = node.properties; + if (!isObject(properties)) { + throw new Error(`${at}: object without properties`); + } + const names = Object.keys(properties).sort(); + const required = Array.isArray(node.required) + ? [...(node.required as unknown[])].map(String).sort() + : []; + if (names.length !== required.length || names.some((name, index) => name !== required[index])) { + throw new Error(`${at}: every emitted property is required`); + } + const shape: Record = {}; + for (const name of names) { + shape[name] = convert(properties[name], `${at}/${name}`); + } + return shape; +} + +/** + * One tool's `parameters_json` as the raw shape `tool()` takes. Throws on any + * node outside the grammar the emitter produces. + */ +export function toolRawShape( + parametersJson: string, + at: string, +): Record { + let parsed: unknown; + try { + parsed = JSON.parse(parametersJson); + } catch (error) { + throw new Error(`${at}: parameters_json is not JSON (${String(error)})`); + } + if (!isObject(parsed) || parsed.type !== "object") { + throw new Error(`${at}: a tool's parameters must be an object schema`); + } + return rawShape(parsed, at); +} diff --git a/sidecar/claude-sdk/test/frames.test.ts b/sidecar/claude-sdk/test/frames.test.ts new file mode 100644 index 0000000..884a19f --- /dev/null +++ b/sidecar/claude-sdk/test/frames.test.ts @@ -0,0 +1,99 @@ +// Spec test 18: the frame bytes Rust writes decode here, and the bytes this +// side encodes are byte-identical to Rust's. The `.bin` fixtures are written by +// the Rust test `frame_fixtures_match_the_checked_in_sidecar_bytes`. + +import assert from "node:assert/strict"; +import { readFileSync } from "node:fs"; +import { fileURLToPath } from "node:url"; +import test from "node:test"; +import { + FrameReader, + MAX_FRAME_BYTES, + decodeFrameBody, + encodeFrame, + type SidecarFrame, +} from "../src/frames.ts"; + +function fixture(name: string): Uint8Array { + return new Uint8Array( + readFileSync(fileURLToPath(new URL(`./frames/${name}.bin`, import.meta.url))), + ); +} + +const NAMES = ["query", "tool_call", "tool_result", "output", "fault"]; + +test("every Rust frame fixture decodes and re-encodes to the same bytes", () => { + for (const name of NAMES) { + const bytes = fixture(name); + const frame = decodeFrameBody(bytes.subarray(4)); + assert.equal(frame.kind, name, `${name} decoded to the wrong kind`); + assert.deepEqual( + Array.from(encodeFrame(frame)), + Array.from(bytes), + `${name} did not re-encode to Rust's bytes`, + ); + } +}); + +test("the query fixture carries the fields the lowering reads", () => { + const frame = decodeFrameBody(fixture("query").subarray(4)) as Extract< + SidecarFrame, + { kind: "query" } + >; + assert.equal(frame.query_id, 7); + assert.equal(frame.model, "claude-opus-5"); + assert.equal(frame.turn_cap, 24); + assert.equal(frame.effort, "medium"); + assert.equal(frame.max_output_tokens, 4000); + assert.deepEqual(frame.transcript, ["assistant: thinking", "tool result: ok"]); + assert.equal(frame.tools.length, 1); + assert.equal(frame.tools[0]!.name, "submit"); +}); + +test("the output fixture reports dispatch honestly", () => { + const frame = decodeFrameBody(fixture("output").subarray(4)) as Extract< + SidecarFrame, + { kind: "output" } + >; + assert.deepEqual(frame.events[0], { kind: "text", text: "Done." }); + assert.deepEqual(frame.events[1], { + kind: "tool_call", + call_id: "call-0", + name: "submit", + arguments: "{}", + dispatched: true, + }); + assert.equal(frame.receipt.session_id, "session-one"); + assert.equal(frame.receipt.usage[0]!.output_tokens, 34); +}); + +test("a chunked stream reassembles into whole frames", () => { + const reader = new FrameReader(); + const stream = new Uint8Array([ + ...fixture("tool_call"), + ...fixture("tool_result"), + ]); + const seen: SidecarFrame[] = []; + for (let at = 0; at < stream.length; at += 3) { + reader.push(stream.subarray(at, Math.min(at + 3, stream.length))); + for (;;) { + const frame = reader.next(); + if (!frame) { + break; + } + seen.push(frame); + } + } + assert.deepEqual( + seen.map((frame) => frame.kind), + ["tool_call", "tool_result"], + ); +}); + +test("a length prefix outside the cap is refused", () => { + const reader = new FrameReader(); + const prefix = new Uint8Array(4); + new DataView(prefix.buffer).setUint32(0, MAX_FRAME_BYTES + 1, false); + reader.push(prefix); + assert.throws(() => reader.next()); +}); diff --git a/sidecar/claude-sdk/test/lowering.test.ts b/sidecar/claude-sdk/test/lowering.test.ts new file mode 100644 index 0000000..41b3d8d --- /dev/null +++ b/sidecar/claude-sdk/test/lowering.test.ts @@ -0,0 +1,113 @@ +// Spec test 16: the hygiene the query options must carry, asserted against the +// same function `main.ts` uses. No credential, no network, no query. + +import assert from "node:assert/strict"; +import test from "node:test"; +import { QuerySession, lowerQuery, SidecarFault } from "../src/main.ts"; +import type { SidecarFrame } from "../src/frames.ts"; + +const EMPTY_SCHEMA = JSON.stringify({ + type: "object", + additionalProperties: false, + required: [], + properties: {}, +}); + +function queryFrame( + overrides: Partial> = {}, +): Extract { + return { + kind: "query", + query_id: 1, + model: "claude-opus-5", + instructions: "Author the shortfall.", + prompt: "Answer the deficit.", + transcript: [], + tools: [ + { name: "submit", description: "Submit the draft.", parameters_json: EMPTY_SCHEMA }, + { name: "record_gap", description: "Record a gap.", parameters_json: EMPTY_SCHEMA }, + ], + effort: "medium", + max_output_tokens: 4000, + turn_cap: 24, + ...overrides, + }; +} + +function session(frame: Extract): QuerySession { + return new QuerySession(frame.query_id, () => {}); +} + +test("lowers a query to SDK options that load nothing ambient", () => { + const frame = queryFrame(); + const { prompt, options } = lowerQuery(frame, session(frame)); + const raw = options as unknown as Record; + + assert.equal(prompt, frame.prompt, "a first round carried a transcript header"); + assert.deepEqual(raw.systemPrompt, { + type: "custom", + prompt: frame.instructions, + }); + assert.deepEqual(raw.settingSources, [], "settings sources were not emptied"); + assert.deepEqual(raw.tools, [], "built-in tools were not stripped"); + assert.equal(raw.strictMcpConfig, true); + assert.equal(raw.persistSession, false, "the caller's conversation would persist"); + assert.equal(raw.includePartialMessages, false); + assert.equal(raw.maxTurns, frame.turn_cap); + assert.equal(raw.model, frame.model); + assert.equal(raw.effort, frame.effort); + assert.deepEqual(raw.allowedTools, ["mcp__ghostlight__*"]); + + const servers = raw.mcpServers as Record>; + assert.ok(servers.ghostlight, "the ghostlight MCP server was not registered"); + const registered = servers.ghostlight.instance ?? servers.ghostlight; + assert.ok(registered, "the in-process server carries no instance"); +}); + +test("a request with no tools registers no MCP server", () => { + const frame = queryFrame({ tools: [], turn_cap: 1 }); + const { options } = lowerQuery(frame, session(frame)); + const raw = options as unknown as Record; + assert.equal(raw.mcpServers, undefined); + assert.equal(raw.allowedTools, undefined); + assert.equal(raw.maxTurns, 1); +}); + +test("a prior round's transcript is folded under one fixed header", () => { + const frame = queryFrame({ + transcript: ["assistant: thinking", "tool result: ok"], + }); + const { prompt } = lowerQuery(frame, session(frame)); + assert.equal( + prompt, + "Answer the deficit.\n\nEarlier turns in this same request, as they happened:\nassistant: thinking\ntool result: ok", + ); +}); + +test("a turn cap outside the lane budgets is refused", () => { + for (const turn_cap of [0, 25]) { + const frame = queryFrame({ turn_cap }); + assert.throws( + () => lowerQuery(frame, session(frame)), + (error: unknown) => + error instanceof SidecarFault && error.reason === "turn_cap_refused", + ); + } +}); + +test("a tool schema outside the emitted grammar refuses registration", () => { + const frame = queryFrame({ + tools: [ + { + name: "submit", + description: "Submit the draft.", + parameters_json: JSON.stringify({ oneOf: [{ type: "string" }] }), + }, + ], + }); + assert.throws( + () => lowerQuery(frame, session(frame)), + (error: unknown) => + error instanceof SidecarFault && error.reason === "tool_registration_failed", + ); +}); diff --git a/sidecar/claude-sdk/test/schema.test.ts b/sidecar/claude-sdk/test/schema.test.ts new file mode 100644 index 0000000..8d151f4 --- /dev/null +++ b/sidecar/claude-sdk/test/schema.test.ts @@ -0,0 +1,95 @@ +// Spec test 17: every schema Ghostlight's one emitter actually produces +// converts, and everything outside that grammar throws. `schemas.json` is +// written by the Rust test `schema_fixtures_match_the_checked_in_sidecar_grammar`, +// so the two halves cannot drift apart. + +import assert from "node:assert/strict"; +import { readFileSync } from "node:fs"; +import { fileURLToPath } from "node:url"; +import test from "node:test"; +import { toolRawShape } from "../src/schema.ts"; + +const emitted: { name: string; parameters_json: string }[] = JSON.parse( + readFileSync(fileURLToPath(new URL("./schemas.json", import.meta.url)), "utf8"), +); + +test("every emitted tool schema converts", () => { + assert.ok(emitted.length > 0, "the schema fixture is empty"); + for (const entry of emitted) { + const shape = toolRawShape(entry.parameters_json, entry.name); + const declared = Object.keys( + JSON.parse(entry.parameters_json).properties as Record, + ).sort(); + assert.deepEqual(Object.keys(shape).sort(), declared, entry.name); + } +}); + +test("a converted shape accepts a value its schema admits", () => { + const shape = toolRawShape( + JSON.stringify({ + type: "object", + additionalProperties: false, + required: ["detail", "count", "flag", "choice", "maybe", "many"], + properties: { + detail: { type: "string" }, + count: { type: "integer", minimum: 1, maximum: 4 }, + flag: { type: "boolean" }, + choice: { type: "string", enum: ["a", "b"] }, + maybe: { anyOf: [{ type: "string" }, { type: "null" }] }, + many: { type: "array", items: { type: "string" } }, + }, + }), + "sample", + ); + assert.equal(shape.detail!.safeParse("ok").success, true); + assert.equal(shape.count!.safeParse(2).success, true); + assert.equal(shape.count!.safeParse(9).success, false); + assert.equal(shape.choice!.safeParse("c").success, false); + assert.equal(shape.maybe!.safeParse(null).success, true); + assert.equal(shape.many!.safeParse(["a"]).success, true); +}); + +test("anything outside the grammar throws", () => { + const refused = [ + { oneOf: [{ type: "string" }] }, + { allOf: [{ type: "string" }] }, + { $ref: "#/definitions/thing" }, + { description: "no type at all" }, + { type: "number" }, + ]; + for (const node of refused) { + assert.throws( + () => + toolRawShape( + JSON.stringify({ + type: "object", + additionalProperties: false, + required: ["field"], + properties: { field: node }, + }), + "refused", + ), + `${JSON.stringify(node)} was accepted`, + ); + } +}); + +test("an open object or a partly optional one throws", () => { + assert.throws(() => + toolRawShape( + JSON.stringify({ type: "object", required: [], properties: {} }), + "open", + ), + ); + assert.throws(() => + toolRawShape( + JSON.stringify({ + type: "object", + additionalProperties: false, + required: ["a"], + properties: { a: { type: "string" }, b: { type: "string" } }, + }), + "partial", + ), + ); +}); diff --git a/sidecar/claude-sdk/test/schemas.json b/sidecar/claude-sdk/test/schemas.json new file mode 100644 index 0000000..597afe8 --- /dev/null +++ b/sidecar/claude-sdk/test/schemas.json @@ -0,0 +1,178 @@ +[ + { + "name": "acquire_knowledge", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"confidence\":{\"enum\":[\"doubted\",\"believed\",\"certain\"],\"type\":\"string\"},\"fact\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing fact\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"source\":{\"anyOf\":[{\"additionalProperties\":false,\"properties\":{\"source\":{\"const\":\"witnessed\",\"type\":\"string\"}},\"required\":[\"source\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"source\":{\"const\":\"evidenced\",\"type\":\"string\"}},\"required\":[\"source\"],\"type\":\"object\"}]},\"subject\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"subject\",\"fact\",\"source\",\"confidence\"],\"type\":\"object\"}" + }, + { + "name": "admit", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"evidence\":{\"description\":\"an exact evidence receipt retrieved for this answer\",\"type\":\"string\"},\"holder\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"qty\":{\"maximum\":18446744073709551615,\"minimum\":1,\"type\":\"integer\"},\"resource\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing resource\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"holder\",\"resource\",\"qty\",\"evidence\"],\"type\":\"object\"}" + }, + { + "name": "advance_pressure", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"by\":{\"maximum\":4294967295,\"minimum\":1,\"type\":\"integer\"},\"source\":{\"anyOf\":[{\"additionalProperties\":false,\"properties\":{\"from\":{\"const\":\"commitment\",\"type\":\"string\"},\"of\":{\"additionalProperties\":false,\"properties\":{\"key\":{\"additionalProperties\":false,\"properties\":{\"command\":{\"description\":\"the command id that created the commitment\",\"type\":\"string\"},\"index\":{\"maximum\":4294967295,\"minimum\":0,\"type\":\"integer\"}},\"required\":[\"command\",\"index\"],\"type\":\"object\"},\"subject\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"subject\",\"key\"],\"type\":\"object\"}},\"required\":[\"from\",\"of\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"from\":{\"const\":\"dependency\",\"type\":\"string\"},\"of\":{\"anyOf\":[{\"additionalProperties\":false,\"properties\":{\"ref\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing resource\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"target\":{\"const\":\"resource\",\"type\":\"string\"}},\"required\":[\"target\",\"ref\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"ref\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing route\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"target\":{\"const\":\"route\",\"type\":\"string\"}},\"required\":[\"target\",\"ref\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"ref\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"target\":{\"const\":\"subject\",\"type\":\"string\"}},\"required\":[\"target\",\"ref\"],\"type\":\"object\"}]}},\"required\":[\"from\",\"of\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"from\":{\"const\":\"subject\",\"type\":\"string\"},\"of\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"from\",\"of\"],\"type\":\"object\"}]},\"target\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"source\",\"target\",\"by\"],\"type\":\"object\"}" + }, + { + "name": "alter_cost", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"cost\":{\"maximum\":525600,\"minimum\":1,\"type\":\"integer\"},\"route\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing route\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"route\",\"cost\"],\"type\":\"object\"}" + }, + { + "name": "bind", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"subject\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"target\":{\"anyOf\":[{\"additionalProperties\":false,\"properties\":{\"ref\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing resource\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"target\":{\"const\":\"resource\",\"type\":\"string\"}},\"required\":[\"target\",\"ref\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"ref\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing route\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"target\":{\"const\":\"route\",\"type\":\"string\"}},\"required\":[\"target\",\"ref\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"ref\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"target\":{\"const\":\"subject\",\"type\":\"string\"}},\"required\":[\"target\",\"ref\"],\"type\":\"object\"}]}},\"required\":[\"subject\",\"target\"],\"type\":\"object\"}" + }, + { + "name": "c3__finish_without_proposal", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{},\"type\":\"object\"}" + }, + { + "name": "c3__record_need", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"detail\":{\"description\":\"what the agent would need and does not have\",\"type\":\"string\"}},\"required\":[\"detail\"],\"type\":\"object\"}" + }, + { + "name": "c3__speak", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"text\":{\"description\":\"the utterance this invocation carries\",\"type\":\"string\"}},\"required\":[\"text\"],\"type\":\"object\"}" + }, + { + "name": "close_forum", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"grievance\":{\"description\":\"the grievance kind\",\"type\":\"string\"}},\"required\":[\"grievance\"],\"type\":\"object\"}" + }, + { + "name": "close_office", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"institution\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"office\":{\"description\":\"the office's name\",\"type\":\"string\"}},\"required\":[\"institution\",\"office\"],\"type\":\"object\"}" + }, + { + "name": "close_route", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"route\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing route\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"route\"],\"type\":\"object\"}" + }, + { + "name": "communicate", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"fact\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing fact\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"speaker\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"to\":{\"anyOf\":[{\"const\":\"colocated\",\"type\":\"string\"},{\"additionalProperties\":false,\"properties\":{\"channel\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing channel\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"channel\"],\"type\":\"object\"}]}},\"required\":[\"speaker\",\"fact\",\"to\"],\"type\":\"object\"}" + }, + { + "name": "consume", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"holder\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"qty\":{\"maximum\":18446744073709551615,\"minimum\":1,\"type\":\"integer\"},\"resource\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing resource\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"holder\",\"resource\",\"qty\"],\"type\":\"object\"}" + }, + { + "name": "create_commitment", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"checks\":{\"items\":{\"anyOf\":[{\"additionalProperties\":false,\"properties\":{\"at\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing place\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"precondition\":{\"const\":\"present\",\"type\":\"string\"}},\"required\":[\"precondition\",\"at\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"precondition\":{\"const\":\"reachable\",\"type\":\"string\"},\"to\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing place\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"within\":{\"maximum\":525600,\"minimum\":1,\"type\":\"integer\"}},\"required\":[\"precondition\",\"to\",\"within\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"at_least\":{\"maximum\":18446744073709551615,\"minimum\":1,\"type\":\"integer\"},\"precondition\":{\"const\":\"holds\",\"type\":\"string\"},\"resource\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing resource\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"precondition\",\"resource\",\"at_least\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"kind\":{\"description\":\"the authority kind\",\"type\":\"string\"},\"over\":{\"anyOf\":[{\"additionalProperties\":false,\"properties\":{\"over\":{\"const\":\"subject\",\"type\":\"string\"},\"ref\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"over\",\"ref\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"over\":{\"const\":\"place_subtree\",\"type\":\"string\"},\"ref\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing place\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"over\",\"ref\"],\"type\":\"object\"}]},\"precondition\":{\"const\":\"authorized\",\"type\":\"string\"}},\"required\":[\"precondition\",\"over\",\"kind\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"grievance\":{\"description\":\"the grievance kind\",\"type\":\"string\"},\"precondition\":{\"const\":\"has_standing\",\"type\":\"string\"}},\"required\":[\"precondition\",\"grievance\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"at_least\":{\"enum\":[\"doubted\",\"believed\",\"certain\"],\"type\":\"string\"},\"fact\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing fact\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"precondition\":{\"const\":\"knows\",\"type\":\"string\"}},\"required\":[\"precondition\",\"fact\",\"at_least\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"precondition\":{\"const\":\"can_broadcast\",\"type\":\"string\"},\"via\":{\"anyOf\":[{\"const\":\"colocated\",\"type\":\"string\"},{\"additionalProperties\":false,\"properties\":{\"channel\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing channel\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"channel\"],\"type\":\"object\"}]}},\"required\":[\"precondition\",\"via\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"precondition\":{\"const\":\"can_reach\",\"type\":\"string\"},\"subject\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"via\":{\"anyOf\":[{\"const\":\"colocated\",\"type\":\"string\"},{\"additionalProperties\":false,\"properties\":{\"channel\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing channel\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"channel\"],\"type\":\"object\"}]}},\"required\":[\"precondition\",\"subject\",\"via\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"kind\":{\"enum\":[\"routine\",\"obligation\",\"goal\"],\"type\":\"string\"},\"precondition\":{\"const\":\"committed\",\"type\":\"string\"},\"to\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"precondition\",\"to\",\"kind\"],\"type\":\"object\"}]},\"type\":\"array\"},\"counterparty\":{\"anyOf\":[{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},{\"type\":\"null\"}]},\"due\":{\"maximum\":18446744073709551615,\"minimum\":0,\"type\":\"integer\"},\"kind\":{\"enum\":[\"routine\",\"obligation\",\"goal\"],\"type\":\"string\"},\"period\":{\"anyOf\":[{\"maximum\":525600,\"minimum\":1,\"type\":\"integer\"},{\"type\":\"null\"}]},\"subject\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"subject\",\"counterparty\",\"kind\",\"due\",\"period\",\"checks\"],\"type\":\"object\"}" + }, + { + "name": "declare_affordance", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"carries_speech\":{\"type\":\"boolean\"},\"effect_slots\":{\"items\":{\"additionalProperties\":false,\"properties\":{\"bounds\":{\"anyOf\":[{\"additionalProperties\":false,\"properties\":{\"bound\":{\"const\":\"none\",\"type\":\"string\"}},\"required\":[\"bound\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"bound\":{\"const\":\"quantity\",\"type\":\"string\"},\"max\":{\"maximum\":18446744073709551615,\"minimum\":1,\"type\":\"integer\"}},\"required\":[\"bound\",\"max\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"bound\":{\"const\":\"cost\",\"type\":\"string\"},\"max\":{\"maximum\":525600,\"minimum\":1,\"type\":\"integer\"}},\"required\":[\"bound\",\"max\"],\"type\":\"object\"}]},\"op_kind\":{\"anyOf\":[{\"additionalProperties\":false,\"properties\":{\"op\":{\"const\":\"relocate\",\"type\":\"string\"}},\"required\":[\"op\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"op\":{\"const\":\"open_route\",\"type\":\"string\"}},\"required\":[\"op\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"op\":{\"const\":\"close_route\",\"type\":\"string\"}},\"required\":[\"op\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"op\":{\"const\":\"alter_cost\",\"type\":\"string\"}},\"required\":[\"op\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"op\":{\"const\":\"transfer\",\"type\":\"string\"}},\"required\":[\"op\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"op\":{\"const\":\"transform\",\"type\":\"string\"}},\"required\":[\"op\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"op\":{\"const\":\"consume\",\"type\":\"string\"}},\"required\":[\"op\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"op\":{\"const\":\"bind\",\"type\":\"string\"}},\"required\":[\"op\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"op\":{\"const\":\"release\",\"type\":\"string\"}},\"required\":[\"op\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"kind\":{\"description\":\"the authority kind\",\"type\":\"string\"},\"op\":{\"const\":\"grant_authority\",\"type\":\"string\"}},\"required\":[\"op\",\"kind\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"kind\":{\"description\":\"the authority kind\",\"type\":\"string\"},\"op\":{\"const\":\"revoke_authority\",\"type\":\"string\"}},\"required\":[\"op\",\"kind\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"office\":{\"description\":\"the office's name\",\"type\":\"string\"},\"op\":{\"const\":\"install_incumbent\",\"type\":\"string\"}},\"required\":[\"op\",\"office\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"office\":{\"description\":\"the office's name\",\"type\":\"string\"},\"op\":{\"const\":\"vacate_office\",\"type\":\"string\"}},\"required\":[\"op\",\"office\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"confidence\":{\"enum\":[\"doubted\",\"believed\",\"certain\"],\"type\":\"string\"},\"op\":{\"const\":\"acquire_knowledge\",\"type\":\"string\"}},\"required\":[\"op\",\"confidence\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"op\":{\"const\":\"forget\",\"type\":\"string\"}},\"required\":[\"op\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"horizon\":{\"maximum\":525600,\"minimum\":1,\"type\":\"integer\"},\"kind\":{\"enum\":[\"routine\",\"obligation\",\"goal\"],\"type\":\"string\"},\"op\":{\"const\":\"create_commitment\",\"type\":\"string\"},\"period\":{\"anyOf\":[{\"maximum\":525600,\"minimum\":1,\"type\":\"integer\"},{\"type\":\"null\"}]}},\"required\":[\"op\",\"kind\",\"horizon\",\"period\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"by\":{\"maximum\":4294967295,\"minimum\":1,\"type\":\"integer\"},\"op\":{\"const\":\"advance_pressure\",\"type\":\"string\"}},\"required\":[\"op\",\"by\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"by\":{\"maximum\":4294967295,\"minimum\":1,\"type\":\"integer\"},\"op\":{\"const\":\"reduce_pressure\",\"type\":\"string\"}},\"required\":[\"op\",\"by\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"op\":{\"const\":\"resolve_pressure\",\"type\":\"string\"}},\"required\":[\"op\"],\"type\":\"object\"}]},\"roles\":{\"items\":{\"description\":\"a declared role name\",\"type\":\"string\"},\"type\":\"array\"}},\"required\":[\"op_kind\",\"roles\",\"bounds\"],\"type\":\"object\"},\"type\":\"array\"},\"handle\":{\"description\":\"a new draft handle, unique within this patch\",\"type\":\"string\"},\"kind\":{\"description\":\"the affordance's tool name\",\"type\":\"string\"},\"outcome_bands\":{\"items\":{\"additionalProperties\":false,\"properties\":{\"effects\":{\"items\":{\"maximum\":4294967295,\"minimum\":0,\"type\":\"integer\"},\"type\":\"array\"},\"weight\":{\"maximum\":4294967295,\"minimum\":1,\"type\":\"integer\"}},\"required\":[\"weight\",\"effects\"],\"type\":\"object\"},\"type\":\"array\"},\"preconditions\":{\"items\":{\"anyOf\":[{\"additionalProperties\":false,\"properties\":{\"at\":{\"description\":\"a declared role name\",\"type\":\"string\"},\"precondition\":{\"const\":\"present\",\"type\":\"string\"}},\"required\":[\"precondition\",\"at\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"precondition\":{\"const\":\"reachable\",\"type\":\"string\"},\"to\":{\"description\":\"a declared role name\",\"type\":\"string\"},\"within\":{\"maximum\":525600,\"minimum\":1,\"type\":\"integer\"}},\"required\":[\"precondition\",\"to\",\"within\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"at_least\":{\"maximum\":18446744073709551615,\"minimum\":1,\"type\":\"integer\"},\"precondition\":{\"const\":\"holds\",\"type\":\"string\"},\"resource\":{\"description\":\"a declared role name\",\"type\":\"string\"}},\"required\":[\"precondition\",\"resource\",\"at_least\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"kind\":{\"description\":\"the authority kind\",\"type\":\"string\"},\"over\":{\"description\":\"a declared role name\",\"type\":\"string\"},\"precondition\":{\"const\":\"authorized\",\"type\":\"string\"}},\"required\":[\"precondition\",\"over\",\"kind\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"grievance\":{\"description\":\"the grievance kind\",\"type\":\"string\"},\"precondition\":{\"const\":\"has_standing\",\"type\":\"string\"}},\"required\":[\"precondition\",\"grievance\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"at_least\":{\"enum\":[\"doubted\",\"believed\",\"certain\"],\"type\":\"string\"},\"fact\":{\"description\":\"a declared role name\",\"type\":\"string\"},\"precondition\":{\"const\":\"knows\",\"type\":\"string\"}},\"required\":[\"precondition\",\"fact\",\"at_least\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"precondition\":{\"const\":\"can_broadcast\",\"type\":\"string\"},\"via\":{\"anyOf\":[{\"const\":\"colocated\",\"type\":\"string\"},{\"additionalProperties\":false,\"properties\":{\"channel\":{\"description\":\"a declared role name\",\"type\":\"string\"}},\"required\":[\"channel\"],\"type\":\"object\"}]}},\"required\":[\"precondition\",\"via\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"precondition\":{\"const\":\"can_reach\",\"type\":\"string\"},\"subject\":{\"description\":\"a declared role name\",\"type\":\"string\"},\"via\":{\"anyOf\":[{\"const\":\"colocated\",\"type\":\"string\"},{\"additionalProperties\":false,\"properties\":{\"channel\":{\"description\":\"a declared role name\",\"type\":\"string\"}},\"required\":[\"channel\"],\"type\":\"object\"}]}},\"required\":[\"precondition\",\"subject\",\"via\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"kind\":{\"enum\":[\"routine\",\"obligation\",\"goal\"],\"type\":\"string\"},\"precondition\":{\"const\":\"committed\",\"type\":\"string\"},\"to\":{\"description\":\"a declared role name\",\"type\":\"string\"}},\"required\":[\"precondition\",\"to\",\"kind\"],\"type\":\"object\"}]},\"type\":\"array\"},\"roles\":{\"items\":{\"additionalProperties\":false,\"properties\":{\"kind\":{\"anyOf\":[{\"additionalProperties\":false,\"properties\":{\"kind\":{\"anyOf\":[{\"enum\":[\"person\",\"institution\",\"population\"],\"type\":\"string\"},{\"type\":\"null\"}]},\"namespace\":{\"const\":\"subject\",\"type\":\"string\"}},\"required\":[\"namespace\",\"kind\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"kind\":{\"enum\":[\"place\",\"resource\",\"fact\",\"channel\"],\"type\":\"string\"},\"namespace\":{\"const\":\"entity\",\"type\":\"string\"}},\"required\":[\"namespace\",\"kind\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"kind\":{\"enum\":[\"route\"],\"type\":\"string\"},\"namespace\":{\"const\":\"edge\",\"type\":\"string\"}},\"required\":[\"namespace\",\"kind\"],\"type\":\"object\"}]},\"role\":{\"description\":\"the slot's parameter name\",\"type\":\"string\"}},\"required\":[\"role\",\"kind\"],\"type\":\"object\"},\"type\":\"array\"}},\"required\":[\"handle\",\"kind\",\"roles\",\"preconditions\",\"effect_slots\",\"outcome_bands\",\"carries_speech\"],\"type\":\"object\"}" + }, + { + "name": "declare_channel", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"controller\":{\"anyOf\":[{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},{\"type\":\"null\"}]},\"handle\":{\"description\":\"a new draft handle, unique within this patch\",\"type\":\"string\"},\"label\":{\"description\":\"a display label\",\"type\":\"string\"},\"reach\":{\"anyOf\":[{\"additionalProperties\":false,\"properties\":{\"of\":{\"items\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"type\":\"array\"},\"reach\":{\"const\":\"subjects\",\"type\":\"string\"}},\"required\":[\"reach\",\"of\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"of\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing place\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"reach\":{\"const\":\"place\",\"type\":\"string\"}},\"required\":[\"reach\",\"of\"],\"type\":\"object\"}]}},\"required\":[\"handle\",\"label\",\"reach\",\"controller\"],\"type\":\"object\"}" + }, + { + "name": "declare_fact", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"handle\":{\"description\":\"a new draft handle, unique within this patch\",\"type\":\"string\"},\"label\":{\"description\":\"a display label\",\"type\":\"string\"},\"standing\":{\"anyOf\":[{\"additionalProperties\":false,\"properties\":{\"evidence\":{\"description\":\"an exact evidence receipt\",\"type\":\"string\"},\"standing\":{\"const\":\"canonical\",\"type\":\"string\"}},\"required\":[\"standing\",\"evidence\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"by\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"standing\":{\"const\":\"claimed\",\"type\":\"string\"}},\"required\":[\"standing\",\"by\"],\"type\":\"object\"}]},\"statement\":{\"description\":\"the committed world text this fact carries\",\"type\":\"string\"}},\"required\":[\"handle\",\"label\",\"statement\",\"standing\"],\"type\":\"object\"}" + }, + { + "name": "declare_place", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"container\":{\"anyOf\":[{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing place\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},{\"type\":\"null\"}]},\"handle\":{\"description\":\"a new draft handle, unique within this patch\",\"type\":\"string\"},\"label\":{\"description\":\"a display label\",\"type\":\"string\"}},\"required\":[\"handle\",\"label\",\"container\"],\"type\":\"object\"}" + }, + { + "name": "declare_resource", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"handle\":{\"description\":\"a new draft handle, unique within this patch\",\"type\":\"string\"},\"label\":{\"description\":\"a display label\",\"type\":\"string\"}},\"required\":[\"handle\",\"label\"],\"type\":\"object\"}" + }, + { + "name": "declare_route", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"access\":{\"anyOf\":[{\"additionalProperties\":false,\"properties\":{\"access\":{\"const\":\"public\",\"type\":\"string\"}},\"required\":[\"access\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"access\":{\"const\":\"restricted\",\"type\":\"string\"},\"requires\":{\"description\":\"the authority kind that opens this route\",\"type\":\"string\"}},\"required\":[\"access\",\"requires\"],\"type\":\"object\"}]},\"cost\":{\"maximum\":525600,\"minimum\":1,\"type\":\"integer\"},\"from\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing place\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"handle\":{\"description\":\"a new draft handle, unique within this patch\",\"type\":\"string\"},\"label\":{\"description\":\"a display label\",\"type\":\"string\"},\"to\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing place\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"handle\",\"label\",\"from\",\"to\",\"access\",\"cost\"],\"type\":\"object\"}" + }, + { + "name": "declare_subject", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"affordances\":{\"items\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing affordance\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"type\":\"array\"},\"controller\":{\"anyOf\":[{\"additionalProperties\":false,\"properties\":{\"type\":{\"const\":\"narrative_persona\",\"type\":\"string\"}},\"required\":[\"type\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"type\":{\"const\":\"operational_agent\",\"type\":\"string\"}},\"required\":[\"type\"],\"type\":\"object\"}]},\"handle\":{\"description\":\"a new draft handle, unique within this patch\",\"type\":\"string\"},\"kind\":{\"enum\":[\"person\",\"institution\",\"population\"],\"type\":\"string\"},\"label\":{\"description\":\"a display label\",\"type\":\"string\"},\"position\":{\"anyOf\":[{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing place\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},{\"type\":\"null\"}]}},\"required\":[\"handle\",\"label\",\"kind\",\"controller\",\"affordances\",\"position\"],\"type\":\"object\"}" + }, + { + "name": "discharge_commitment", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"key\":{\"additionalProperties\":false,\"properties\":{\"command\":{\"description\":\"the command id that created the commitment\",\"type\":\"string\"},\"index\":{\"maximum\":4294967295,\"minimum\":0,\"type\":\"integer\"}},\"required\":[\"command\",\"index\"],\"type\":\"object\"},\"subject\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"subject\",\"key\"],\"type\":\"object\"}" + }, + { + "name": "finish_without_proposal", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{},\"type\":\"object\"}" + }, + { + "name": "forget", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"fact\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing fact\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"subject\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"subject\",\"fact\"],\"type\":\"object\"}" + }, + { + "name": "grant_authority", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"grant\":{\"additionalProperties\":false,\"properties\":{\"kind\":{\"description\":\"the authority kind\",\"type\":\"string\"},\"over\":{\"anyOf\":[{\"additionalProperties\":false,\"properties\":{\"over\":{\"const\":\"subject\",\"type\":\"string\"},\"ref\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"over\",\"ref\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"over\":{\"const\":\"place_subtree\",\"type\":\"string\"},\"ref\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing place\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"over\",\"ref\"],\"type\":\"object\"}]}},\"required\":[\"kind\",\"over\"],\"type\":\"object\"},\"holder\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"holder\",\"grant\"],\"type\":\"object\"}" + }, + { + "name": "install_incumbent", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"incumbent\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"institution\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"office\":{\"description\":\"the office's name\",\"type\":\"string\"}},\"required\":[\"institution\",\"office\",\"incumbent\"],\"type\":\"object\"}" + }, + { + "name": "open_forum", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"forum\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"grievance\":{\"description\":\"the grievance kind\",\"type\":\"string\"},\"standing\":{\"anyOf\":[{\"additionalProperties\":false,\"properties\":{\"over\":{\"const\":\"subject\",\"type\":\"string\"},\"ref\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"over\",\"ref\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"over\":{\"const\":\"place_subtree\",\"type\":\"string\"},\"ref\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing place\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"over\",\"ref\"],\"type\":\"object\"}]}},\"required\":[\"grievance\",\"forum\",\"standing\"],\"type\":\"object\"}" + }, + { + "name": "open_office", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"delegated\":{\"items\":{\"description\":\"an authority kind the office lends\",\"type\":\"string\"},\"type\":\"array\"},\"institution\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"office\":{\"description\":\"the office's name\",\"type\":\"string\"}},\"required\":[\"institution\",\"office\",\"delegated\"],\"type\":\"object\"}" + }, + { + "name": "open_route", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"route\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing route\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"route\"],\"type\":\"object\"}" + }, + { + "name": "record_gap", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"detail\":{\"description\":\"what the world needs and this vocabulary cannot express\",\"type\":\"string\"}},\"required\":[\"detail\"],\"type\":\"object\"}" + }, + { + "name": "record_need", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"detail\":{\"description\":\"what the agent would need and does not have\",\"type\":\"string\"}},\"required\":[\"detail\"],\"type\":\"object\"}" + }, + { + "name": "reduce_pressure", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"by\":{\"maximum\":4294967295,\"minimum\":1,\"type\":\"integer\"},\"source\":{\"anyOf\":[{\"additionalProperties\":false,\"properties\":{\"from\":{\"const\":\"commitment\",\"type\":\"string\"},\"of\":{\"additionalProperties\":false,\"properties\":{\"key\":{\"additionalProperties\":false,\"properties\":{\"command\":{\"description\":\"the command id that created the commitment\",\"type\":\"string\"},\"index\":{\"maximum\":4294967295,\"minimum\":0,\"type\":\"integer\"}},\"required\":[\"command\",\"index\"],\"type\":\"object\"},\"subject\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"subject\",\"key\"],\"type\":\"object\"}},\"required\":[\"from\",\"of\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"from\":{\"const\":\"dependency\",\"type\":\"string\"},\"of\":{\"anyOf\":[{\"additionalProperties\":false,\"properties\":{\"ref\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing resource\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"target\":{\"const\":\"resource\",\"type\":\"string\"}},\"required\":[\"target\",\"ref\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"ref\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing route\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"target\":{\"const\":\"route\",\"type\":\"string\"}},\"required\":[\"target\",\"ref\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"ref\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"target\":{\"const\":\"subject\",\"type\":\"string\"}},\"required\":[\"target\",\"ref\"],\"type\":\"object\"}]}},\"required\":[\"from\",\"of\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"from\":{\"const\":\"subject\",\"type\":\"string\"},\"of\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"from\",\"of\"],\"type\":\"object\"}]},\"target\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"source\",\"target\",\"by\"],\"type\":\"object\"}" + }, + { + "name": "release", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"subject\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"target\":{\"anyOf\":[{\"additionalProperties\":false,\"properties\":{\"ref\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing resource\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"target\":{\"const\":\"resource\",\"type\":\"string\"}},\"required\":[\"target\",\"ref\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"ref\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing route\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"target\":{\"const\":\"route\",\"type\":\"string\"}},\"required\":[\"target\",\"ref\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"ref\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"target\":{\"const\":\"subject\",\"type\":\"string\"}},\"required\":[\"target\",\"ref\"],\"type\":\"object\"}]}},\"required\":[\"subject\",\"target\"],\"type\":\"object\"}" + }, + { + "name": "relocate", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"subject\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"via\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing route\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"subject\",\"via\"],\"type\":\"object\"}" + }, + { + "name": "resolve_pressure", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"source\":{\"anyOf\":[{\"additionalProperties\":false,\"properties\":{\"from\":{\"const\":\"commitment\",\"type\":\"string\"},\"of\":{\"additionalProperties\":false,\"properties\":{\"key\":{\"additionalProperties\":false,\"properties\":{\"command\":{\"description\":\"the command id that created the commitment\",\"type\":\"string\"},\"index\":{\"maximum\":4294967295,\"minimum\":0,\"type\":\"integer\"}},\"required\":[\"command\",\"index\"],\"type\":\"object\"},\"subject\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"subject\",\"key\"],\"type\":\"object\"}},\"required\":[\"from\",\"of\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"from\":{\"const\":\"dependency\",\"type\":\"string\"},\"of\":{\"anyOf\":[{\"additionalProperties\":false,\"properties\":{\"ref\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing resource\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"target\":{\"const\":\"resource\",\"type\":\"string\"}},\"required\":[\"target\",\"ref\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"ref\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing route\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"target\":{\"const\":\"route\",\"type\":\"string\"}},\"required\":[\"target\",\"ref\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"ref\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"target\":{\"const\":\"subject\",\"type\":\"string\"}},\"required\":[\"target\",\"ref\"],\"type\":\"object\"}]}},\"required\":[\"from\",\"of\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"from\":{\"const\":\"subject\",\"type\":\"string\"},\"of\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"from\",\"of\"],\"type\":\"object\"}]},\"target\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"source\",\"target\"],\"type\":\"object\"}" + }, + { + "name": "revoke_authority", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"grant\":{\"additionalProperties\":false,\"properties\":{\"kind\":{\"description\":\"the authority kind\",\"type\":\"string\"},\"over\":{\"anyOf\":[{\"additionalProperties\":false,\"properties\":{\"over\":{\"const\":\"subject\",\"type\":\"string\"},\"ref\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"over\",\"ref\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"over\":{\"const\":\"place_subtree\",\"type\":\"string\"},\"ref\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing place\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"over\",\"ref\"],\"type\":\"object\"}]}},\"required\":[\"kind\",\"over\"],\"type\":\"object\"},\"holder\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"holder\",\"grant\"],\"type\":\"object\"}" + }, + { + "name": "set_controller", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"channel\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing channel\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"controller\":{\"anyOf\":[{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},{\"type\":\"null\"}]}},\"required\":[\"channel\",\"controller\"],\"type\":\"object\"}" + }, + { + "name": "set_reach", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"channel\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing channel\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"reach\":{\"anyOf\":[{\"additionalProperties\":false,\"properties\":{\"of\":{\"items\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"type\":\"array\"},\"reach\":{\"const\":\"subjects\",\"type\":\"string\"}},\"required\":[\"reach\",\"of\"],\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"of\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing place\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"reach\":{\"const\":\"place\",\"type\":\"string\"}},\"required\":[\"reach\",\"of\"],\"type\":\"object\"}]}},\"required\":[\"channel\",\"reach\"],\"type\":\"object\"}" + }, + { + "name": "speak", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"text\":{\"description\":\"the utterance this invocation carries\",\"type\":\"string\"}},\"required\":[\"text\"],\"type\":\"object\"}" + }, + { + "name": "submit", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{},\"required\":[],\"type\":\"object\"}" + }, + { + "name": "transfer", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"from\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"qty\":{\"maximum\":18446744073709551615,\"minimum\":1,\"type\":\"integer\"},\"resource\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing resource\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"to\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"from\",\"to\",\"resource\",\"qty\"],\"type\":\"object\"}" + }, + { + "name": "transform", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"from_resource\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing resource\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"holder\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"into_resource\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing resource\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"qty\":{\"maximum\":18446744073709551615,\"minimum\":1,\"type\":\"integer\"}},\"required\":[\"holder\",\"from_resource\",\"into_resource\",\"qty\"],\"type\":\"object\"}" + }, + { + "name": "vacate_office", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"institution\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing subject\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"office\":{\"description\":\"the office's name\",\"type\":\"string\"}},\"required\":[\"institution\",\"office\"],\"type\":\"object\"}" + }, + { + "name": "witness", + "parameters_json": "{\"additionalProperties\":false,\"properties\":{\"confidence\":{\"enum\":[\"doubted\",\"believed\",\"certain\"],\"type\":\"string\"},\"fact\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing fact\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"},\"place\":{\"additionalProperties\":false,\"properties\":{\"ref\":{\"enum\":[\"draft\",\"existing\"],\"type\":\"string\"},\"value\":{\"description\":\"a draft handle declared in this same patch, or the canonical id of an existing place\",\"type\":\"string\"}},\"required\":[\"ref\",\"value\"],\"type\":\"object\"}},\"required\":[\"fact\",\"place\",\"confidence\"],\"type\":\"object\"}" + } +] diff --git a/sidecar/claude-sdk/tsconfig.json b/sidecar/claude-sdk/tsconfig.json new file mode 100644 index 0000000..4d199af --- /dev/null +++ b/sidecar/claude-sdk/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "outDir": "dist", + "rootDir": "src", + "declaration": false, + "sourceMap": false, + "skipLibCheck": true, + "allowImportingTsExtensions": true, + "rewriteRelativeImportExtensions": true + }, + "include": ["src/**/*.ts"] +}