beeos-claw 0.6.66 → 0.6.67

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/README.md +0 -13
  2. package/dist/a2a/tools.js +1 -1
  3. package/dist/acp-gateway/beeos-file-resolver.js +1 -1
  4. package/dist/acp-gateway/bridge-core.js +1 -1
  5. package/dist/acp-gateway/gateway-events.js +1 -1
  6. package/dist/acp-gateway/local-session-history.js +1 -1
  7. package/dist/acp-gateway/mcp-desired-state-controller.js +1 -1
  8. package/dist/acp-gateway/mcp-desired-state-store.js +1 -1
  9. package/dist/acp-gateway/mcp-service.js +1 -1
  10. package/dist/acp-server.js +1 -1
  11. package/dist/agent-sync.js +1 -1
  12. package/dist/approval/bridge.js +1 -0
  13. package/dist/approval/presentation.js +1 -0
  14. package/dist/approval/protocol.generated.js +1 -0
  15. package/dist/auto-reply-tokens.js +1 -1
  16. package/dist/automation/tools.js +1 -1
  17. package/dist/canvas/relay-client.js +1 -1
  18. package/dist/canvas/static-html.js +1 -1
  19. package/dist/canvas/tools.js +1 -1
  20. package/dist/canvas/ws-provider.js +1 -1
  21. package/dist/canvas-orchestrator.js +1 -1
  22. package/dist/chat-envelope.js +1 -0
  23. package/dist/connectors/harness-connector-mcp.js +1 -0
  24. package/dist/files/fetch-tool.js +1 -1
  25. package/dist/files/list-tool.js +1 -1
  26. package/dist/gateway-client.js +1 -1
  27. package/dist/im-inbound-handler.js +1 -1
  28. package/dist/im-runtime-dispatch.js +1 -1
  29. package/dist/index.js +1 -1
  30. package/dist/media/arouter-config.js +1 -1
  31. package/dist/media/image-provider.js +1 -1
  32. package/dist/media/video-provider.js +1 -1
  33. package/dist/message-client-composition.js +1 -1
  34. package/dist/message-projection-inbound-consumer.js +1 -1
  35. package/dist/plugin-registration-plan.js +1 -1
  36. package/dist/runtime/agent-projection-production.js +1 -1
  37. package/dist/runtime/assistant-message-commit-router.js +1 -1
  38. package/dist/runtime/callback-queue.js +1 -1
  39. package/dist/runtime/chat-handler-port.js +1 -0
  40. package/dist/runtime/conversation-title.js +1 -1
  41. package/dist/runtime/core-execution-attempt-context.js +1 -1
  42. package/dist/runtime/deepseek-reasoning-stream.js +1 -1
  43. package/dist/runtime/im-reply-sink.js +1 -1
  44. package/dist/runtime/message-service-conversation-clear-http-authority.js +1 -1
  45. package/dist/runtime/message-service-conversation-run-boundary.js +1 -1
  46. package/dist/runtime/message-service-cron-delivery-http-authority.js +1 -1
  47. package/dist/runtime/message-service-runtime-authenticated-fetch.js +1 -1
  48. package/dist/runtime/message-service-runtime-claim-authority.js +1 -1
  49. package/dist/runtime/message-service-runtime-message-channel.js +1 -1
  50. package/dist/runtime/message-service-session-model-http-authority.js +1 -1
  51. package/dist/runtime/ms-runtime-message-channel-adapter.js +1 -1
  52. package/dist/runtime/ms-runtime-message-channel-consumer-factory.js +1 -1
  53. package/dist/runtime/ms-runtime-rpc-adapter.js +1 -1
  54. package/dist/runtime/native-cloud-chat-composition.js +1 -0
  55. package/dist/runtime/native-cloud-prompt-bridge.js +1 -0
  56. package/dist/runtime/native-input-files-http.js +1 -0
  57. package/dist/runtime/native-input-files.js +1 -0
  58. package/dist/runtime/native-output-file-attempt.js +1 -0
  59. package/dist/runtime/native-prompt-authority.js +1 -0
  60. package/dist/runtime/native-prompt-preflight.js +1 -0
  61. package/dist/runtime/native-session-new-bridge.js +1 -0
  62. package/dist/runtime/openclaw-runtime-capabilities.js +1 -1
  63. package/dist/runtime/openclaw-session-model.js +1 -0
  64. package/dist/runtime/openclaw-session-write-quiescence.js +1 -1
  65. package/dist/runtime/reply-router.js +1 -1
  66. package/dist/runtime/runtime-command-dispatcher.js +1 -1
  67. package/dist/runtime/runtime-command-journal.js +1 -1
  68. package/dist/runtime/runtime-error-part.js +1 -0
  69. package/dist/runtime/runtime-local-parity-matrix.js +1 -1
  70. package/dist/runtime/runtime-message-channel-contract.js +1 -1
  71. package/dist/runtime/runtime-operation-resource-resolver.js +1 -1
  72. package/dist/runtime/runtime-parity-manifest-digest.js +1 -1
  73. package/dist/runtime/runtime-parity-manifest.js +1 -1
  74. package/dist/runtime/runtime-production-authority.js +1 -1
  75. package/dist/runtime/runtime-service-contract-compatibility.js +1 -1
  76. package/dist/runtime/runtime-service-production-candidate.js +1 -1
  77. package/dist/runtime/runtime-session-control-service.js +1 -1
  78. package/dist/runtime/runtime-skills-service.js +1 -1
  79. package/dist/runtime/session-mutation-coordinator.js +1 -1
  80. package/dist/runtime/session-new-runtime-delivery-bridge.js +1 -1
  81. package/dist/runtime/session-set-model-mapping.js +1 -1
  82. package/dist/runtime/write-runtime-failure.js +1 -1
  83. package/dist/terminal/runtime-terminal-outbound-registration.js +1 -1
  84. package/dist/terminal/runtime-terminal-service.js +1 -1
  85. package/dist/terminal/terminal-authority-admission.js +1 -1
  86. package/dist/terminal/terminal-authority-contract.js +1 -1
  87. package/dist/terminal/terminal-lease-bound-bridge-client.js +1 -1
  88. package/dist/upload/desktop-screenshot-tool.js +1 -1
  89. package/dist/upload/finalize-hook.js +1 -1
  90. package/dist/upload/native-output-tool-hook.js +1 -0
  91. package/dist/upload/tool-artifact-enrichment.js +1 -1
  92. package/dist/upload/tool.js +1 -1
  93. package/dist/upload/upload-file.js +1 -1
  94. package/openclaw.plugin.json +1 -1
  95. package/package.json +12 -12
  96. package/runtime-service-wire-identity.v1.json +12 -12
  97. package/scripts/runtime-blackbox-worker-main.mjs +5 -2
  98. package/dist/agent-auth.js +0 -1
  99. package/dist/bridge-discovery.js +0 -1
  100. package/dist/contracts/question/codec.js +0 -1
  101. package/dist/mcp-connector-proxy.js +0 -1
  102. package/dist/runtime/agent-gateway-runtime-attempt-authorization.js +0 -1
  103. package/dist/runtime/message-service-runtime-invocation-authority.js +0 -1
  104. package/dist/runtime/message-service-session-reasoning-http-authority.js +0 -1
  105. package/dist/runtime/openclaw-native-sessions.js +0 -1
  106. package/dist/runtime/openclaw-question-adapter.js +0 -1
  107. package/dist/runtime/question-wire.js +0 -1
  108. package/dist/runtime/runtime-jwks-verifier.js +0 -1
  109. package/dist/runtime/runtime-reasoning.js +0 -1
  110. package/dist/runtime/runtime-registration.js +0 -1
  111. package/dist/runtime/runtime-transport-failure-policy.js +0 -1
  112. package/dist/runtime/split-runtime-authorization-verifier.js +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "beeos-claw",
3
- "version": "0.6.66",
3
+ "version": "0.6.67",
4
4
  "description": "OpenClaw plugin that bridges the BeeOS platform with the local OpenClaw Gateway, providing file transfer, ACP bridge, and observability.",
5
5
  "license": "MIT",
6
6
  "author": "BeeOS <dev@beeos.ai>",
@@ -44,7 +44,7 @@
44
44
  "verify:release-evidence": "node ./scripts/verify-release-evidence.mjs",
45
45
  "verify:release-types-pin": "node ./scripts/verify-release-types-pin.mjs",
46
46
  "verify:release-package": "npm run build:release && node ./scripts/verify-release-package.mjs",
47
- "test:release-workflows": "node ./scripts/test-release-workflows.mjs && node --test ./scripts/run-ci-gates.test.mjs ./scripts/openclaw-promotion-receipt.test.mjs ./scripts/verify-tag-release-request.test.mjs ./scripts/openclaw-release-authority.test.mjs ./scripts/openclaw-release-dispatch.test.mjs ./scripts/openclaw-release-finalizer.test.mjs ./scripts/openclaw-release-completion.test.mjs ./scripts/openclaw-release-recovery.test.mjs ./scripts/verify-openclaw-dispatch-contract.test.mjs ./scripts/verify-promotion-evidence.test.mjs ./scripts/verify-package-equivalence.test.mjs ./scripts/verify-package-equivalence.e2e.test.mjs",
47
+ "test:release-workflows": "node ./scripts/test-release-workflows.mjs && node --test ./scripts/run-ci-gates.test.mjs ./scripts/openclaw-promotion-receipt.test.mjs ./scripts/verify-tag-release-request.test.mjs ./scripts/openclaw-release-authority.test.mjs ./scripts/openclaw-release-dispatch.test.mjs ./scripts/openclaw-release-finalizer.test.mjs ./scripts/openclaw-release-completion.test.mjs ./scripts/openclaw-release-recovery.test.mjs ./scripts/verify-openclaw-dispatch-contract.test.mjs ./scripts/verify-promotion-evidence.test.mjs ./scripts/verify-package-equivalence.test.mjs ./scripts/verify-package-equivalence.e2e.test.mjs ./scripts/cloud-staging-publish.test.mjs",
48
48
  "ci:gates": "node ./scripts/run-ci-gates.mjs",
49
49
  "check:runtime-blackbox-worker": "node --check ./scripts/runtime-blackbox-worker.mjs && node --check ./scripts/runtime-blackbox-worker-main.mjs && node --check ./scripts/runtime-blackbox-worker-lease.mjs && node --check ./scripts/runtime-blackbox-worker-lifecycle.mjs && node --check ./scripts/runtime-journal-checkpoint.mjs && node --test ./scripts/runtime-blackbox-worker-lease.test.mjs ./scripts/runtime-blackbox-worker-lifecycle.test.mjs ./scripts/runtime-blackbox-worker-launcher.test.mjs",
50
50
  "prepublishOnly": "npm run verify:release-types-pin",
@@ -58,18 +58,18 @@
58
58
  "build": "npm run clean && tsc -p tsconfig.build.json",
59
59
  "build:release": "npm run build && npm run minify",
60
60
  "typecheck": "tsc -p tsconfig.json --noEmit",
61
- "lint": "npm run question:verify && npm run typecheck && eslint \"src/**/*.ts\"",
61
+ "lint": "npm run typecheck && eslint \"src/**/*.ts\"",
62
62
  "minify": "find dist -name '*.js' -exec sh -c 'for file do terser \"$file\" --compress drop_console=true,drop_debugger=true --mangle --output \"$file.min\" && mv \"$file.min\" \"$file\" || exit 1; done' sh {} + && find dist -name '*.d.ts' -delete && find dist -name '*.d.ts.map' -delete",
63
63
  "test": "npm run test:ci",
64
64
  "test:ci": "node ./scripts/test-ci.mjs",
65
- "test:watch": "vitest",
66
- "question:verify": "node src/contracts/question/verify.mjs"
65
+ "test:watch": "vitest"
67
66
  },
68
67
  "dependencies": {
69
- "@beeos-ai/beeos-types": "4.4.2-thinking.0",
68
+ "@beeos-ai/beeos-types": "4.4.2-cloud.3",
70
69
  "@beeos-ai/bridge-client": "^0.1.0",
71
- "@beeos-ai/message-sdk": "2.0.18-question.0",
72
- "@modelcontextprotocol/sdk": "^1.32.1",
70
+ "@beeos-ai/cloud-harness-sdk": "1.0.0-cloud.6",
71
+ "@beeos-ai/message-sdk": "2.0.16",
72
+ "@modelcontextprotocol/sdk": "^1.29.0",
73
73
  "adm-zip": "0.6.1",
74
74
  "ws": "^8.18.0"
75
75
  },
@@ -82,11 +82,11 @@
82
82
  "eslint": "^9.39.4",
83
83
  "terser": "^5.39.0",
84
84
  "typescript": "^5.6.3",
85
- "vitest": "^4.1.11"
85
+ "vitest": "^4.1.0"
86
86
  },
87
87
  "overrides": {
88
- "fast-uri": ">=4.2.1",
89
- "brace-expansion": ">=5.0.12"
88
+ "fast-uri": ">=3.1.4",
89
+ "brace-expansion": ">=5.0.9"
90
90
  },
91
- "gitHead": "eed840d08e6a23e0abe6e625ca32f0a2e639c069"
91
+ "gitHead": "395ab323adebc9feca82717be4842393f4f2dc46"
92
92
  }
@@ -4,32 +4,32 @@
4
4
  "hashAlgorithm": "SHA-256",
5
5
  "canonicalTypes": {
6
6
  "package": "@beeos-ai/beeos-types",
7
- "version": "4.4.2-thinking.0",
7
+ "version": "4.4.2-cloud.3",
8
8
  "runtimeRpcContractRevision": "2026-07-14.3",
9
- "runtimeMethodManifestRawSHA256": "dd0eca4c8229ef26b788a86b39dfd2b05ab1a096d94b53ae355511f4c99756ed",
10
- "runtimeMethodManifestJcsSHA256": "de658b3a2ac506d1199c8972dc081f35ead75e601a2bf36dd567ba7634d883ac"
9
+ "runtimeMethodManifestRawSHA256": "f75832c57a18ca614e946a3b1d194828df76d600907f378efe28633df94146fc",
10
+ "runtimeMethodManifestJcsSHA256": "2e58dbc13b8bef2491b95f89920945cb905085828b2fa7a4d4f621624971b186"
11
11
  },
12
12
  "artifacts": [
13
13
  {
14
14
  "name": "runtime-parity-manifest",
15
15
  "path": "openapi/runtime-parity-manifest-v1.json",
16
- "revision": "beeos.runtime-parity.v1.2.0",
17
- "rawSHA256": "a88335bd662d3ef94c24aa01f0174e6917524766c6c6cac3695c7282a239ff7d",
18
- "jcsSHA256": "a49592ac3be446dc20537cf1d7fe3b0c517a9ccb5e6aca8b69b421f777066f52"
16
+ "revision": "beeos.runtime-parity.v1.1.0",
17
+ "rawSHA256": "f1030e7bf2084f584d558c22b9bffde0f823d6950c696a6f0571adaffcdbcee0",
18
+ "jcsSHA256": "c98ed2aa822b29530cb02badd51654f2766f1dc0ff2c53b660be6431b1f23747"
19
19
  },
20
20
  {
21
21
  "name": "runtime-message-channel",
22
22
  "path": "openapi/runtime-message-channel-v1.contract.json",
23
- "revision": "beeos.runtime-message-channel.v2.1.0",
24
- "rawSHA256": "79e66c441fac7f1bd493f837a4814b1c1d82fb0110863d99bcc8d85fe040d5e9",
25
- "jcsSHA256": "cec634cca225629056b7bff9605008ee975249da11e493f0c54da85c848635b2"
23
+ "revision": "beeos.runtime-message-channel.v2.0.0",
24
+ "rawSHA256": "dd791ce5f49b7bee1dba21a71e7b2cfbf4db7d77cb787aab5f04c7f4b0e3101b",
25
+ "jcsSHA256": "e950f1a86bf2bd8bf472603a91111c15b920fcac4c06fd8ac70e2c3f4c3a408f"
26
26
  },
27
27
  {
28
28
  "name": "runtime-authority-ports",
29
29
  "path": "openapi/runtime-authority-ports-v1.contract.json",
30
- "revision": "beeos.runtime-authority-ports.v2.1.0",
31
- "rawSHA256": "42b99ef67bb889375ede81803d3800c47a52ce5ea10faffa1ccfb7d3062afcde",
32
- "jcsSHA256": "8ebee5df8bd325da15bc47e75db444eb25390d61285f579bb54e31f114f70e36"
30
+ "revision": "beeos.runtime-authority-ports.v2.0.0",
31
+ "rawSHA256": "a2e9565ae617bcaeb4d837fe176a3602be041913d28a3f0a3a9ec2e3dae0d7b4",
32
+ "jcsSHA256": "3bd582f1f6babcdbe953a082faf813247c960f6bbf4c0f713e7fd92e27d163f5"
33
33
  }
34
34
  ]
35
35
  }
@@ -2,7 +2,7 @@ import { readFile } from "node:fs/promises";
2
2
  import { createHash } from "node:crypto";
3
3
  import { join } from "node:path";
4
4
  import { GatewayClient } from "../dist/gateway-client.js";
5
- import { loadAgentKeyPair, agentBoundFetch } from "../dist/agent-auth.js";
5
+ import { agentIdentityFromKeyPair, authenticatedAgentFetch, loadAgentKeyPair } from "@beeos-ai/cloud-harness-sdk";
6
6
  import { OpenClawRuntimeCapabilities } from "../dist/runtime/openclaw-runtime-capabilities.js";
7
7
  import { OpenClawRuntimeCommandDispatcher } from "../dist/runtime/runtime-command-dispatcher.js";
8
8
  import { FileRuntimeAgentIdentityRegistry } from "../dist/runtime/runtime-agent-identity-registry.js";
@@ -48,6 +48,7 @@ export async function main() {
48
48
  if (agentKeys.publicKey.length !== 32 || agentKeys.privateKey.length !== 32) {
49
49
  throw new Error("blackbox Agent identity must contain 32-byte Ed25519 public/seed keys");
50
50
  }
51
+ const agentIdentity = agentIdentityFromKeyPair(agentKeys);
51
52
  const leaseClaims = decodeRuntimeLease(nonempty(authority.runtimeLeaseCredential,
52
53
  "authority.runtimeLeaseCredential"));
53
54
  const instanceId = requiredEnvironment("FIXTURE_INSTANCE_ID");
@@ -101,11 +102,13 @@ export async function main() {
101
102
  });
102
103
  const messageFetch = messageComposition.nodeTransport;
103
104
  const boundAgentFetch = async (url, init = {}) => {
105
+ // The Gateway v2 signing preimage covers the path only, so a query would be unsigned.
106
+ if (new URL(url).search !== "") throw new Error("body-bound agent authority routes forbid query parameters");
104
107
  const headers = new Headers(init.headers);
105
108
  headers.set("X-Instance-ID", instanceId);
106
109
  headers.set("X-Instance-Owner-ID", ownerId);
107
110
  httpRequests += 1;
108
- return await withinDeadline((signal) => agentBoundFetch(url, agentKeys, { ...init, headers, signal }), deadline);
111
+ return await withinDeadline((signal) => authenticatedAgentFetch(url, agentIdentity, { ...init, headers, signal }), deadline);
109
112
  };
110
113
  const statePrefix = join(receiptDir, "claw-worker");
111
114
  const commandJournal = new FileRuntimeCommandJournal(`${statePrefix}-commands.json`);
@@ -1 +0,0 @@
1
- import*as crypto from"node:crypto";import*as fs from"node:fs";import*as path from"node:path";export const EMPTY_BODY_SHA256="e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";const ED25519_PKCS8_PREFIX=Buffer.from("302e020100300506032b657004220420","hex");function wrapPrivateKey(e){return 32===e.length?Buffer.concat([ED25519_PKCS8_PREFIX,Buffer.from(e)]):Buffer.from(e)}const ED25519_SPKI_PREFIX=Buffer.from("302a300506032b6570032100","hex");function derivePublicKey(e){const r=crypto.createPrivateKey({key:wrapPrivateKey(e),format:"der",type:"pkcs8"}),t=crypto.createPublicKey(r).export({type:"spki",format:"der"});return 44===t.length?new Uint8Array(t.subarray(12)):new Uint8Array(t)}export function loadAgentKeyPair(e){if(!fs.existsSync(e))return generateAgentKeyPair(e);const r=fs.readFileSync(e,"utf-8").trim();try{const e=JSON.parse(r);if(e.publicKey&&e.privateKey)return{publicKey:new Uint8Array(Buffer.from(e.publicKey,"base64")),privateKey:new Uint8Array(Buffer.from(e.privateKey,"base64"))}}catch{}const t=new Uint8Array(Buffer.from(r,"base64"));if(32===t.length)return{publicKey:derivePublicKey(t),privateKey:t};throw new Error(`Invalid key file format at ${e}`)}function generateAgentKeyPair(e){const r=crypto.generateKeyPairSync("ed25519",{publicKeyEncoding:{type:"spki",format:"der"},privateKeyEncoding:{type:"pkcs8",format:"der"}}),t=r.publicKey,n=r.privateKey,o=new Uint8Array(44===t.length?t.subarray(12):t),a=new Uint8Array(48===n.length?n.subarray(16):n),i=path.dirname(e);return fs.existsSync(i)||fs.mkdirSync(i,{recursive:!0}),fs.writeFileSync(e,JSON.stringify({publicKey:Buffer.from(o).toString("base64"),privateKey:Buffer.from(a).toString("base64")},null,2),{mode:384}),{publicKey:o,privateKey:a}}export function signAgentMessage(e,r){const t=crypto.createPrivateKey({key:wrapPrivateKey(r),format:"der",type:"pkcs8"});return new Uint8Array(crypto.sign(null,Buffer.from(e),t))}export function bodyHashHex(e){const r=null==e?Buffer.alloc(0):"string"==typeof e?Buffer.from(e,"utf8"):Buffer.from(e);return crypto.createHash("sha256").update(r).digest("hex")}export function agentAuthHeaders(e,r,t,n){const o=Math.floor(Date.now()/1e3).toString(),a=crypto.randomUUID(),i=bodyHashHex(n),f=signAgentMessage(`${e.toUpperCase()}|${r}||${i}|${o}|${a}`,t.privateKey);return{"X-Agent-Public-Key":Buffer.from(t.publicKey).toString("base64"),"X-Agent-Signature":Buffer.from(f).toString("base64"),"X-Agent-Timestamp":o,"X-Agent-Nonce":a}}export function agentBoundAuthHeaders(e,r,t,n){return agentAuthHeaders(e,r,n,t)}export async function agentFetch(e,r,t){const n="string"==typeof e?new URL(e):e,o=t?.method?.toUpperCase()??"GET",a=decodeURIComponent(n.pathname);let i;if(void 0!==t?.body&&null!==t.body){if(!("string"==typeof t.body||t.body instanceof Uint8Array))throw new Error("agent-authenticated request body must be string or Uint8Array for exact signing");i=t.body}const f=agentAuthHeaders(o,a,r,i),s=new Headers(t?.headers);for(const[e,r]of Object.entries(f))s.set(e,r);s.delete("X-Agent-Body-SHA256");const c=await fetch(n,{...t,method:o,headers:s,redirect:"error"});return assertFixedOrigin(n,c),c}export async function agentBoundFetch(e,r,t){if(""!==("string"==typeof e?new URL(e):e).search)throw new Error("body-bound agent authority routes forbid query parameters");return agentFetch(e,r,t)}function assertFixedOrigin(e,r){if(r.url&&new URL(r.url).origin!==e.origin)throw new Error("agent-authenticated response origin changed")}
@@ -1 +0,0 @@
1
- export async function discoverBridgeFromGW(o,n,r){try{const i=r?`?region=${encodeURIComponent(r)}`:"",e=await n(`${o}/api/v1/bridge/config${i}`,{method:"GET"});if(e.ok){const o=await e.json();if(o.url)return{url:o.url,region:o.region}}}catch{}}
@@ -1 +0,0 @@
1
- export const QUESTION_SCHEMA="beeos.question.v1";export class QuestionError extends Error{code;constructor(e){super(e),this.code=e}}export const object=e=>"object"!=typeof e||null===e||Array.isArray(e)?void 0:e;function fail(e="INVALID_CONTENT"){throw new QuestionError(e)}const exact=(e,t,s=[])=>{(t.some(t=>!Object.hasOwn(e,t))||Object.keys(e).some(e=>!t.includes(e)&&!s.includes(e)))&&fail()},bounded=(e,t)=>"string"==typeof e&&[...e].length<=t,text=(e,t)=>bounded(e,t)&&e.trim().length>0,ascii=(e,t)=>text(e,t)&&/^[\x21-\x7e]+$/.test(e),unique=e=>new Set(e).size===e.length,record=e=>object(e)??fail();function base(e,t,s){let i;try{const t=JSON.stringify(e);if(void 0===t)return fail();i=[...t].reduce((e,t)=>{const s=t.codePointAt(0);return e+(s<128?1:s<2048?2:s<65536?3:4)},0)}catch{return fail()}i>65536&&fail("CONTENT_TOO_LARGE");const o=record(e);return o.schema_version!==QUESTION_SCHEMA&&fail("UNSUPPORTED_SCHEMA"),("question"===s?"agent.input_required"===t:"user.continue"===t)&&o.kind===s||fail("INVALID_ENVELOPE_KIND"),ascii(o.request_id,128)||fail(),o}function timestamp(e){if("string"!=typeof e||!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/.test(e))return!1;const[t,s,i,o,n,r]=e.slice(0,19).split(/[-T:]/).map(Number),a=new Date(Date.UTC(t,s,0)).getUTCDate(),c=/([+-])(\d{2}):(\d{2})$/.exec(e);return s>=1&&s<=12&&i>=1&&i<=a&&o<=23&&n<=59&&r<=59&&(!c||Number(c[2])<=23&&Number(c[3])<=59)&&Number.isFinite(Date.parse(e))}export function decodeQuestion(e,t="agent.input_required"){const s=base(e,t,"question");exact(s,["schema_version","kind","request_id","message","expires_at","questions"]),(!text(s.message,2048)||!timestamp(s.expires_at)||!Array.isArray(s.questions)||s.questions.length<1||s.questions.length>3)&&fail();const i=[];for(const e of s.questions){const t=record(e);!0!==t.is_secret&&!0!==t.isSecret||fail("SECRET_INPUT_UNSUPPORTED"),exact(t,["id","header","text","input"]),ascii(t.id,64)&&text(t.header,80)&&text(t.text,2048)||fail(),i.push(t.id);const s=record(t.input);if("text"===s.type)exact(s,["type"]);else{exact(s,["type","allow_other","options"]),(!["single_select","multi_select"].includes(String(s.type))||"boolean"!=typeof s.allow_other||!Array.isArray(s.options)||s.options.length<2||s.options.length>10)&&fail();const e=[];for(const t of s.options){const s=record(t);exact(s,["value","label"],["description"]),ascii(s.value,128)&&text(s.label,200)&&(void 0===s.description||bounded(s.description,1024))||fail(),e.push(s.value)}unique(e)||fail()}}return unique(i)||fail(),s}export function decodeResponse(e,t="user.continue"){const s=base(e,t,"question_response");if(exact(s,["schema_version","kind","request_id","outcome",..."answered"===s.outcome?["answers"]:[]],["message"]),void 0===s.message||bounded(s.message,2048)||fail(),"cancelled"===s.outcome)return s;"answered"!==s.outcome&&fail();const i=record(s.answers);(Object.keys(i).length<1||Object.keys(i).length>3)&&fail();for(const[e,t]of Object.entries(i)){ascii(e,64)||fail();const s=record(t);Object.hasOwn(s,"text")?(exact(s,["text"]),text(s.text,4096)||fail()):(exact(s,["values"]),(!Array.isArray(s.values)||s.values.length<1||s.values.length>10||!s.values.every(e=>ascii(e,128))||!unique(s.values))&&fail())}return s}export function validateResponse(e,t){if(e.request_id!==t.request_id&&fail("PENDING_NOT_FOUND"),"cancelled"!==t.outcome){Object.keys(t.answers).sort().join("\0")!==e.questions.map(e=>e.id).sort().join("\0")&&fail();for(const s of e.questions){const e=t.answers[s.id];if("text"===s.input.type)void 0===e.text&&fail();else if(void 0!==e.text)s.input.allow_other||fail();else{const t=s.input;("single_select"===t.type&&1!==e.values.length||e.values.some(e=>!t.options.some(t=>t.value===e)))&&fail()}}}}
@@ -1 +0,0 @@
1
- import{agentFetch}from"./agent-auth.js";export const CONNECTOR_MCP_PROXY_PATH="/beeos/connectors/mcp";export const CONNECTOR_MCP_UPSTREAM_PATH="/api/v1/agent/connectors/mcp";export const CONNECTOR_MCP_MAX_BODY_BYTES=262144;class RequestBodyTooLargeError extends Error{}export function isLoopbackAddress(e){return"127.0.0.1"===e||"::1"===e||"::ffff:127.0.0.1"===e}export function isLoopbackRequest(e){return isLoopbackAddress(e.socket.remoteAddress)}export function readBoundedRawBody(e,t=262144){return new Promise((r,o)=>{const n=[];let s=0,a=!1;const c=()=>{e.off("data",u),e.off("end",i),e.off("error",p),e.off("aborted",f)},d=e=>{a||(a=!0,c(),o(e))},u=r=>{const o=Buffer.isBuffer(r)?r:Buffer.from(r);if(s+=o.byteLength,s>t)return c(),e.resume(),void d(new RequestBodyTooLargeError("connector MCP request body is too large"));n.push(o)},i=()=>{a||(a=!0,c(),r(Buffer.concat(n,s)))},p=e=>d(e),f=()=>d(new Error("connector MCP request was aborted"));e.on("data",u),e.on("end",i),e.on("error",p),e.on("aborted",f)})}function writeTextResponse(e,t,r){e.statusCode=t,e.setHeader("Content-Type","text/plain; charset=utf-8"),e.end(r)}function copyRequestHeader(e,t,r){const o=e.headers[r.toLowerCase()];"string"==typeof o?t.set(r,o):Array.isArray(o)&&t.set(r,o.join(", "))}export async function handleConnectorMcpRequest(e,t,r){if(!isLoopbackRequest(e))return e.resume(),void writeTextResponse(t,403,"loopback access required");if("POST"!==e.method)return e.resume(),t.setHeader("Allow","POST"),void writeTextResponse(t,405,"method not allowed");if(e.url?.includes("?"))return e.resume(),void writeTextResponse(t,400,"query parameters are not supported");if(!r.agentKeys||!r.agentGatewayUrl)return e.resume(),void writeTextResponse(t,503,"connector MCP proxy is not configured");let o;try{o=await readBoundedRawBody(e)}catch(e){return e instanceof RequestBodyTooLargeError?void writeTextResponse(t,413,"request body too large"):(r.logger?.warn?.(`[connector-mcp] failed to read request: ${String(e)}`),void(t.writableEnded||writeTextResponse(t,400,"invalid request body")))}const n=new Headers;copyRequestHeader(e,n,"Content-Type"),copyRequestHeader(e,n,"Accept"),copyRequestHeader(e,n,"MCP-Protocol-Version");const s=`${r.agentGatewayUrl.replace(/\/+$/,"")}${CONNECTOR_MCP_UPSTREAM_PATH}`;try{const e=await(r.fetcher??agentFetch)(s,r.agentKeys,{method:"POST",headers:n,body:new Uint8Array(o)}),a=Buffer.from(await e.arrayBuffer());t.statusCode=e.status;const c=e.headers.get("content-type");c&&t.setHeader("Content-Type",c),t.end(a)}catch(e){r.logger?.warn?.(`[connector-mcp] upstream request failed: ${String(e)}`),t.writableEnded||writeTextResponse(t,502,"connector MCP upstream unavailable")}}
@@ -1 +0,0 @@
1
- import{canonicalizeJcs}from"@beeos-ai/beeos-types/runtime";const GRANT_ISSUER="beeos-gateway",BOUNDARY_ISSUER="message-service";export class AgentGatewayRuntimeAttemptAuthorizationClient{options;constructor(e){this.options=e}async authorize(e){if(!sameLeaseFence(e.lease,e.fence)||e.request.payload.instanceId!==e.lease.instanceId)return{status:"fenced"};const t="start",n=JSON.stringify({executionGrantRef:e.request.payload.executionGrantRef,operationId:e.request.operationId,requestMessageId:e.request.messageId,method:e.request.payload.request.method,paramsHash:e.request.payload.paramsHash,runtimeLeaseCredential:e.lease.runtimeLeaseCredential,fence:e.fence,journalAttestationHash:e.journal.journalAttestationHash,journalRevisionBeforeAttempt:e.journal.journalRevisionBeforeAttempt,preparedEntryHash:e.journal.preparedEntryHash,executionMode:t}),a=await this.options.boundAgentFetch(new URL(this.options.authorizationUrl),{method:"POST",headers:{"content-type":"application/json"},body:n});if(401===a.status||403===a.status)return{status:"fenced"};if(!a.ok)throw new Error(`Agent Gateway runtime authorization failed (${a.status})`);const o=await a.json();if(isTerminalAuthorization(o))return{status:o.status};if(!isAuthorizedResponse(o))return{status:"invalid"};if(o.operationId!==e.request.operationId||o.requestMessageId!==e.request.messageId||o.method!==e.request.payload.request.method||o.paramsHash!==e.request.payload.paramsHash||canonicalizeJcs(o.command)!==canonicalizeJcs(e.request.payload.command))return{status:"invalid"};await this.options.verifier.refresh();let i=this.options.verifier.verifyAndDecodeGrant(o.runtimeExecutionGrant),r=this.options.verifier.verifyAndDecodeBoundary(o.executionBoundaryAssertion);if(i&&r||(await this.options.verifier.refresh(!0),i=this.options.verifier.verifyAndDecodeGrant(o.runtimeExecutionGrant),r=this.options.verifier.verifyAndDecodeBoundary(o.executionBoundaryAssertion)),!i||!r||o.executionBoundaryId!==r.claims.executionBoundaryId||o.executionBoundaryId!==r.claims.jti)return{status:"invalid"};const s=invocationContext(e.request,e.fence,i.claims,t,this.options.messageServicePublisherIdentityId??BOUNDARY_ISSUER,Math.floor((this.options.now??Date.now)()/1e3));if(!s)return{status:"invalid"};const d={grant:{header:i.header,claims:i.claims,grantJwt:o.runtimeExecutionGrant},boundary:{header:r.header,claims:r.claims,assertionJwt:o.executionBoundaryAssertion}};return{status:"authorized",attempt:{command:o.command,validationContext:s,authorization:d,derivationContext:{invocation:s,boundaryIssuer:BOUNDARY_ISSUER,boundarySubject:e.request.payload.instanceId,nowEpochSeconds:s.nowEpochSeconds,localJournalRevision:e.journal.journalRevisionBeforeAttempt,localPreparedEntryHash:e.journal.preparedEntryHash},executionBoundaryId:o.executionBoundaryId,boundaryAssertionHash:r.compactHash,executionMode:t}}}}function invocationContext(e,t,n,a,o,i){const r=e.payload.command,s={operationId:e.operationId,requestMessageId:e.messageId,dispatchEpoch:r.context.dispatchEpoch,activeRuntimeEpoch:t.runtimeEpoch,requestId:e.payload.request.id,method:e.payload.request.method,gatewayPublisherIdentityId:e.publisherIdentityId,messageServicePublisherIdentityId:o,runtimePublisherIdentityId:t.handlerIdentity,requestHash:e.payload.requestHash,paramsHash:e.payload.paramsHash,commandHash:e.payload.commandHash,idempotencyKeyHash:e.payload.idempotencyKeyHash,idempotencyFingerprint:e.payload.idempotencyFingerprint,callerIntentHash:e.payload.callerIntentHash,callerUserId:e.payload.callerUserId,callerIdentityId:e.payload.callerIdentityId,instanceId:e.payload.instanceId,runtimeInstanceUid:r.context.runtimeInstanceUid,executionGrantRef:e.payload.executionGrantRef,executionGrantHash:e.payload.executionGrantHash,claimDeadlineAt:e.payload.claimDeadlineAt,executionDeadlineAt:e.payload.executionDeadlineAt,grantIssuer:GRANT_ISSUER,grantSubject:t.handlerIdentity,grantJti:`${t.claimId}:${a}`,grantStartDeadline:Math.floor(Date.parse(e.payload.claimDeadlineAt)/1e3),grantExecutionMode:a,nowEpochSeconds:i,activeFence:t};return Number.isSafeInteger(s.grantStartDeadline)?"instance"===n.scope?{...s,scope:"instance",...void 0===n.runtimeAgentUid?{}:{runtimeAgentUid:n.runtimeAgentUid}}:"agent"===n.scope&&"agent"===r.context.scope&&n.platformAgentId&&n.runtimeAgentUid?{...s,scope:"agent",platformAgentId:n.platformAgentId,runtimeAgentUid:n.runtimeAgentUid,runtimeLocalKey:r.context.agent.runtimeLocalKey}:"conversation"===n.scope&&"conversation"===r.context.scope&&n.platformAgentId&&n.runtimeAgentUid&&n.platformConversationId&&n.runtimeConversationUid&&n.runtimeSessionKey?{...s,scope:"conversation",platformAgentId:n.platformAgentId,runtimeAgentUid:n.runtimeAgentUid,platformConversationId:n.platformConversationId,runtimeConversationUid:n.runtimeConversationUid,runtimeSessionKey:n.runtimeSessionKey}:null:null}function sameLeaseFence(e,t){return e.runtimeEpoch===t.runtimeEpoch&&e.handlerIdentity===t.handlerIdentity}function isTerminalAuthorization(e){return isRecord(e)&&1===Object.keys(e).length&&("expired"===e.status||"terminal"===e.status)}function isAuthorizedResponse(e){if(!isRecord(e))return!1;const t=Object.keys(e).sort(),n=["authorizedAt","command","disposition","executionBoundaryAssertion","executionBoundaryId","expiresAt","method","operationId","paramsHash","requestMessageId","runtimeExecutionGrant","status"].sort();return t.length===n.length&&t.every((e,t)=>e===n[t])&&"authorized"===e.status&&("created"===e.disposition||"reused"===e.disposition)&&[e.operationId,e.requestMessageId,e.method,e.paramsHash,e.runtimeExecutionGrant,e.executionBoundaryAssertion,e.executionBoundaryId,e.authorizedAt,e.expiresAt].every(e=>"string"==typeof e&&e.length>0)&&isRecord(e.command)&&Number.isFinite(Date.parse(e.authorizedAt))&&Number.isFinite(Date.parse(e.expiresAt))}function isRecord(e){return null!==e&&"object"==typeof e&&!Array.isArray(e)}
@@ -1 +0,0 @@
1
- import{createHash}from"node:crypto";import{RUNTIME_ERROR_DESCRIPTORS,RUNTIME_HASH_DOMAINS,runtimeHashPreimage}from"@beeos-ai/beeos-types/runtime";import{MessageServiceRuntimeClaimHttpAuthority}from"./message-service-runtime-claim-authority.js";const QUERY_METHODS=new Set(["skills/list","models/list","cron/list","cron/status","cron/runs","mcp/list"]),PROJECTION_METHODS=new Set(["agent/create","agent/update","agent/delete","agent/applyTemplate","session/set_model","session/set_reasoning"]);export class MessageServiceRuntimeInvocationHttpAuthority{deps;constructor(e){this.deps=e}claimNext=e=>this.claimAuthority().claimNext(e);claimExact=e=>this.claimAuthority().claimExact(e);renewClaim=e=>this.claimAuthority().renewClaim(e);releaseClaim=e=>this.claimAuthority().releaseClaim(e);authorize=e=>this.deps.authorization.authorize(e);async appendStarted(e){await this.append(e,"runtime_operation_started",{claimedAt:this.now(),leaseExpiresAt:e.claimLeaseExpiresAt,executionMode:e.attempt.executionMode,executionBoundaryId:e.attempt.executionBoundaryId,boundaryAssertionHash:e.attempt.boundaryAssertionHash,...e.attempt.handoffId?{handoffId:e.attempt.handoffId}:{}})}async appendProgress(e){await this.append(e,"runtime_operation_progress",{executionBoundaryId:e.attempt.executionBoundaryId,phase:e.progress.phase,...void 0===e.progress.current?{}:{current:e.progress.current},...void 0===e.progress.total?{}:{total:e.progress.total}})}async commitResult(e){const t=e.request.payload.request.method;if(PROJECTION_METHODS.has(t))throw new Error(`projection-required runtime method is not enabled by this authority: ${t}`);const o=this.now(),a=e.result,s=hash(RUNTIME_HASH_DOMAINS.serviceResult,{method:t,result:a});let r;if(!QUERY_METHODS.has(t)){const s=hash(RUNTIME_HASH_DOMAINS.coreResult,{method:t,result:a}),n={schemaVersion:1,operationId:e.operationId,method:t,coreResultRef:`sha256:${s}`,coreResultHash:s},i={schemaVersion:1,operationId:e.operationId,requestMessageId:e.requestMessageId,method:t,commandHash:e.request.payload.commandHash,executionBoundaryId:e.attempt.executionBoundaryId,boundaryAssertionHash:e.attempt.boundaryAssertionHash,fence:e.fence,journalRevision:"3",coreResultHash:s,effectRecordHash:hash(RUNTIME_HASH_DOMAINS.effectRecord,n),projection:{state:"not_required"},committedAt:o};r=hash(RUNTIME_HASH_DOMAINS.effectReceipt,i),await this.append(e,"runtime_effect_committed",{executionBoundaryId:e.attempt.executionBoundaryId,committedAt:o,effectReceipt:i,effectReceiptHash:r})}const n={schemaVersion:1,operationId:e.operationId,method:t,outcome:"succeeded",serviceResultRef:`sha256:${s}`,serviceResultHash:s},i={schemaVersion:1,operationId:e.operationId,requestMessageId:e.requestMessageId,method:t,commandHash:e.request.payload.commandHash,executionBoundaryId:e.attempt.executionBoundaryId,boundaryAssertionHash:e.attempt.boundaryAssertionHash,fence:e.fence,journalRevision:"3",terminalRecordHash:hash(RUNTIME_HASH_DOMAINS.terminalRecord,n),completedAt:o,outcome:"succeeded",serviceResultHash:s,...r?{effectReceiptHash:r}:{}};await this.appendTerminal(e,i,{outcome:"succeeded",response:{jsonrpc:"2.0",id:e.request.payload.request.id,result:a},serviceResultHash:s,terminalAuthority:r?{kind:"effect_receipt",effectReceiptHash:r}:{kind:"query_execution",executionBoundaryId:e.attempt.executionBoundaryId,boundaryAssertionHash:e.attempt.boundaryAssertionHash},completedAt:o})}async commitFailure(e){const t=e.request.payload.request.method,o=this.now(),a=normalizeErrorCode(e.outcome,e.code),s=RUNTIME_ERROR_DESCRIPTORS[a],r="outcome_unknown"===e.outcome?"outcome_unknown":"cancelled"===e.outcome?"cancelled":"expired"===e.outcome?"expired":"failed",n={code:s.jsonRpcCode,message:a,data:{code:a,operationId:e.operationId,effectState:r,retryMode:s.retryMode}},i=hash(RUNTIME_HASH_DOMAINS.terminalRecord,{operationId:e.operationId,method:t,outcome:e.outcome,code:a}),c="outcome_unknown"===e.outcome?{schemaVersion:1,operationId:e.operationId,method:t,outcome:e.outcome,uncertaintyRef:`sha256:${i}`,uncertaintyHash:i}:{schemaVersion:1,operationId:e.operationId,method:t,outcome:e.outcome,errorRef:`sha256:${i}`,errorHash:i},d={schemaVersion:1,operationId:e.operationId,requestMessageId:e.requestMessageId,method:t,commandHash:e.request.payload.commandHash,executionBoundaryId:e.attempt.executionBoundaryId,boundaryAssertionHash:e.attempt.boundaryAssertionHash,fence:e.fence,journalRevision:"2",terminalRecordHash:hash(RUNTIME_HASH_DOMAINS.terminalRecord,c),completedAt:o},u="outcome_unknown"===e.outcome?{...d,outcome:"outcome_unknown",uncertaintyHash:i}:{...d,outcome:e.outcome,noEffect:!0,errorHash:i},m={jsonrpc:"2.0",id:e.request.payload.request.id,error:n},p=terminalFailurePayload(e.outcome,o,m,e.attempt.executionBoundaryId,e.attempt.boundaryAssertionHash);await this.appendTerminal(e,u,p)}claimAuthority(){return new MessageServiceRuntimeClaimHttpAuthority({messageServiceUrl:this.deps.messageServiceUrl,fetchAuthorized:(e,t)=>this.deps.fetchMessageService(e,t)})}async append(e,t,o){await this.post(e.operationId,{schemaVersion:1,type:t,operationId:e.operationId,conversationId:e.operationId,requestMessageId:e.requestMessageId,dispatchEpoch:e.request.payload.command.context.dispatchEpoch,fence:e.fence,payload:o})}async appendTerminal(e,t,o){await this.post(e.operationId,{schemaVersion:1,type:"runtime_rpc_response",operationId:e.operationId,conversationId:e.operationId,requestMessageId:e.requestMessageId,dispatchEpoch:e.request.payload.command.context.dispatchEpoch,fence:e.fence,payload:o,replyTo:e.requestMessageId,terminalReceipt:t,terminalReceiptHash:hash(RUNTIME_HASH_DOMAINS.terminalReceipt,t)})}async post(e,t){const o=await this.deps.fetchMessageService(new URL(`/api/v1/runtime/operations/${encodeURIComponent(e)}/events`,this.deps.messageServiceUrl),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(t)});if(201!==o.status)throw new Error(`Message Service runtime event append failed (${o.status})`)}now(){return(this.deps.now??(()=>new Date))().toISOString()}}function hash(e,t){return createHash("sha256").update(runtimeHashPreimage(e,t)).digest("hex")}function normalizeErrorCode(e,t){return"outcome_unknown"===e?"OUTCOME_UNKNOWN":"cancelled"===e?"OPERATION_CANCELLED":"expired"===e?"COMMAND_EXPIRED":t in RUNTIME_ERROR_DESCRIPTORS?t:"RUNTIME_EXECUTION_FAILED"}function terminalFailurePayload(e,t,o,a,s){if("outcome_unknown"===e)return{outcome:e,response:o,terminalAuthority:{kind:"uncertain_effect",executionBoundaryId:a,boundaryAssertionHash:s},completedAt:t};const r={kind:"definitive_no_effect",journalPhase:"prepared",observedAt:t};return"cancelled"===e?{outcome:e,response:o,cancellationEvidence:r,completedAt:t}:"expired"===e?{outcome:e,response:o,expirationEvidence:r,completedAt:t}:{outcome:e,response:o,failureEvidence:r,completedAt:t}}
@@ -1 +0,0 @@
1
- export async function projectSessionReasoning(e){const n=await e.fetchAuthorized(new URL(`/api/v1/runtime/conversations/${encodeURIComponent(e.conversationId)}/metadata/reasoning`,e.messageServiceUrl),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({schemaVersion:1,operationId:e.operationId,requestMessageId:e.requestMessageId,requestHash:e.requestHash,runtimeLeaseCredential:e.runtimeLeaseCredential,reasoning:e.reasoning})}),s=await n.json(),o=s.data??s;if(!n.ok||"projected"!==o.status||o.conversationId!==e.conversationId||!o.reasoning||Object.keys(e.reasoning).some(n=>o.reasoning[n]!==e.reasoning[n]))throw new Error("Message Service reasoning projection receipt mismatch")}
@@ -1 +0,0 @@
1
- import{existsSync,readFileSync,readdirSync,realpathSync}from"node:fs";import{createRequire}from"node:module";import{dirname,join,resolve}from"node:path";const adapters=new Map;export function getOpenClawNativeSessions(){const e=process.env.OPENCLAW_ROOT?.trim()||hostRoot();if(!e)return;const n=JSON.parse(readFileSync(join(e,"package.json"),"utf8"));if("openclaw"!==n.name)return;if("2026.9.8"!==n.version&&"2026.9.9"!==n.version)throw new Error(`unsupported OpenClaw native session contract: ${n.version}`);const t=adapters.get(e);if(t)return t;const r=createRequire(join(e,"package.json")),s=r("openclaw/plugin-sdk/session-store-runtime"),o=join(e,"dist"),i=readdirSync(o).filter(e=>/^runs-.*\.mjs$/u.test(e)&&/export \{[^}]*\bwaitForEmbeddedAgentRunEnd\s*[,}]/u.test(readFileSync(join(o,e),"utf8")));if(1!==i.length)throw new Error("OpenClaw native run-end facade is missing or ambiguous");const a=r(join(o,i[0]));if("function"!=typeof s.getSessionEntry||"function"!=typeof s.loadTranscriptEventsSync||"function"!=typeof s.readTranscriptStatsSync||"function"!=typeof a.waitForEmbeddedAgentRunEnd)throw new Error("OpenClaw native session contract is unavailable");const c={getEntry:(e,n)=>s.getSessionEntry({agentId:e,sessionKey:n,readConsistency:"latest"}),readEvents:(e,n,t)=>{const r={agentId:e,sessionKey:n,sessionId:t},o=s.readTranscriptStatsSync(r);if(!Number.isSafeInteger(o.sizeBytes)||o.sizeBytes<0||o.sizeBytes>1048576||!Number.isSafeInteger(o.eventCount)||o.eventCount<0||o.eventCount>6400)throw new Error("native transcript exceeds the local recovery budget; use Gateway history pagination");return s.loadTranscriptEventsSync(r)},waitForRunEnd:(e,n)=>a.waitForEmbeddedAgentRunEnd(e,n)};return adapters.set(e,c),c}function hostRoot(){if(!process.argv[1]||!existsSync(process.argv[1]))return;let e=dirname(realpathSync(resolve(process.argv[1])));for(let n=0;n<4;n++){const n=join(e,"package.json");if(existsSync(n)&&"openclaw"===JSON.parse(readFileSync(n,"utf8")).name)return e;const t=dirname(e);if(t===e)break;e=t}}
@@ -1 +0,0 @@
1
- import{decodeResponse,QuestionError}from"../contracts/question/codec.js";import{createHash,randomUUID}from"node:crypto";import{isDeepStrictEqual}from"node:util";import{asRecord,nativeAnswers,nonEmpty,projectQuestion,questionRecord,USER_INPUT_SCHEMA}from"./question-wire.js";export function observeQuestionTool(e,t,s){const i=asRecord(t),n=asRecord(s);if(!i||!n)return;const r=i.toolName;if("ask_user"!==r)return;const o=n.runId??i.runId,a=n.toolCallId??i.toolCallId;nonEmpty(n.sessionKey)&&nonEmpty(a)&&nonEmpty(o)&&(void 0===n.agentId||nonEmpty(n.agentId))&&e.observeNativeTool(r,{sessionKey:n.sessionKey,toolCallId:a,runId:o,agentId:n.agentId})}export class OpenClawQuestionAdapter{options;turns=new Set;allowed=new Map;routes=new Map;byWire=new Map;tasks=new Set;timer;polling=!1;started=!1;onEvent=(...e)=>{if("question.requested"===e[0]&&this.background(this.accept(e[1])),"question.resolved"===e[0]){const t=asRecord(e[1])?.id;"string"==typeof t&&this.background(this.refreshRoute(t))}};onConnected=()=>{this.background(this.reconcile())};constructor(e){this.options=e}start(){this.started||(this.started=!0,this.options.gateway.on("gateway-event",this.onEvent),this.options.gateway.on("connected",this.onConnected),this.timer=setInterval(()=>this.background(this.reconcile()),this.options.heartbeatMs??3e4),this.timer.unref?.())}beginTurn(e){if(!this.started||!e.senderId.startsWith("user:")||e.senderId.length<=5)throw new Error("Question turn requires an authenticated human source");e.assertCurrent();const t=asRecord(e.deliveryContext),s=asRecord(t?.scope);if(t?.parent_message_id!==e.turnMessageId||t?.target_agent_id!==e.targetAgentId||t?.delivery_principal!==e.instanceId||t?.runtime_epoch!==e.runtimeEpoch||!["task","conversation_turn"].includes(String(s?.kind))||!nonEmpty(s?.id))throw new Error("Question origin is not source bound");const i={context:e,live:!0,ids:new Set};return this.turns.add(i),{bindRun:e=>{i.live&&(i.context.runId=e)},observeTool:(e,t)=>{this.observeTool(i,e,t)},close:()=>this.closeTurn(i)}}observeNativeTool(e,t){if(t.sessionKey&&t.toolCallId)for(const s of this.turns){const i=s.context;i.sessionKey!==t.sessionKey||t.runId&&i.runId!==t.runId||t.agentId&&i.localAgentId!==t.agentId||this.observeTool(s,e,t.toolCallId)}}observeTool(e,t,s){if("ask_user"!==t||!s||!this.current(e))return;const i=`ask_${createHash("sha256").update(`${e.context.runId}\0${s}`).digest("hex").slice(0,32)}`;e.ids.add(i),this.allowed.set(i,e),this.background(this.refreshRoute(i))}async stop(){this.started=!1,this.timer&&clearInterval(this.timer),this.options.gateway.off("gateway-event",this.onEvent),this.options.gateway.off("connected",this.onConnected),await Promise.allSettled([...this.turns].map(async e=>{try{await e.context.cancelRun("question_adapter_shutdown")}finally{this.closeTurn(e)}})),await Promise.allSettled([...this.tasks])}async handleContinue(e){const t=asRecord(e.content),s="string"==typeof t?.request_id?this.byWire.get(t.request_id):void 0;if(!s)return this.rejectMissing(e);if(!this.authorized(s,e))return;const i=(s.answering??Promise.resolve()).then(async()=>{if(!this.authorized(s,e))return;if(s.terminal)return void this.reject(s,e.id,"expired"===s.terminal?"PENDING_EXPIRED":"PENDING_ALREADY_RESOLVED");if(!s.delivered)return void this.reject(s,e.id,"PENDING_NOT_FOUND");if(s.attempt?.uncertain&&(await this.receipt(s),s.attempt?.uncertain&&!s.terminal))return"deferred";let t;try{t=decodeResponse(e.content,e.type),nativeAnswers(s.native,t)}catch(t){return void this.reject(s,e.id,t instanceof QuestionError?t.code:"INVALID_CONTENT")}await this.submit(s,e,t)});s.answering=i;try{return await i}finally{s.answering===i&&(s.answering=void 0)}}async reconcile(){if(this.started&&!this.polling&&0!==this.allowed.size){this.polling=!0;try{const e=asRecord(await this.options.gateway.request("question.list",{},5e3));if(!Array.isArray(e?.questions))throw new Error("Invalid question.list result");const t=new Set;for(const s of e.questions){const e=asRecord(s)?.id;if("string"!=typeof e||!this.allowed.has(e))continue;t.add(e),await this.accept(s);const i=this.routes.get(e);i&&i.attempt?.uncertain&&await this.receipt(i)}for(const[e,s]of this.routes)!this.current(s.turn)||s.terminal||t.has(e)||await this.refreshRoute(e)}finally{this.polling=!1}}}current(e){if(!this.started||!e.live||e.context.signal.aborted)return!1;try{return e.context.assertCurrent(),!0}catch{return!1}}authorized(e,t){return this.authorizedTurn(e.turn,t)}authorizedTurn(e,t){const s=e.context,i=asRecord(t.deliveryContext),n=asRecord(s.deliveryContext),r=asRecord(i?.scope),o=asRecord(n?.scope);return this.current(e)&&t.conversationId===s.conversationId&&t.senderId===s.senderId&&i?.target_agent_id===s.targetAgentId&&i.delivery_principal===s.instanceId&&i.runtime_epoch===s.runtimeEpoch&&i.parent_message_id===s.turnMessageId&&r?.kind===o?.kind&&r?.id===o?.id&&void 0!==o?.id&&void 0===t.replyTo&&(void 0===s.historyGeneration||t.historyGeneration===s.historyGeneration)}async rejectMissing(e){if(!this.started)return;const t=asRecord(e.content);if(!nonEmpty(t?.request_id))return;let s="PENDING_NOT_FOUND";try{decodeResponse(e.content,e.type)}catch(e){s=e instanceof QuestionError?e.code:"INVALID_CONTENT"}for(const i of this.turns)if(this.authorizedTurn(i,e))return void i.context.publishStatus({request_id:t.request_id,status:"rejected",response_message_id:e.id,error_code:s,updated_at_ms:Date.now()});const i=asRecord(e.deliveryContext);if(this.options.assertDeliveryCurrent&&i&&nonEmpty(i.parent_message_id)&&void 0===e.replyTo&&e.senderId?.startsWith("user:"))try{this.options.assertDeliveryCurrent(e);const n=await this.options.client.messages.getEnvelope(e.conversationId,i.parent_message_id);this.options.assertDeliveryCurrent(e);const r=asRecord(n.deliveryContext);if("chat_message"!==n.type||n.conversationId!==e.conversationId||n.senderId!==e.senderId||n.historyGeneration!==e.historyGeneration||!sameOrigin(r,e.deliveryContext))return;const o=`receipt_${createHash("sha256").update(`${e.conversationId}\0${e.id}\0${i.delivery_principal}`).digest("hex").slice(0,32)}`,a={conversationId:e.conversationId,clientMessageId:o,idempotencyKey:o,type:"agent_reply",deliveryContext:e.deliveryContext,content:{}},d=this.options.client.messages.startStream(a),c=await d.opened();if(this.options.assertDeliveryCurrent(e),"duplicate"===c.outcome)return;d.addPart({type:"custom",kind:"message_processing_receipt",data:{request_id:t.request_id,response_message_id:e.id,status:"rejected",error_code:s,observed_at_ms:Date.now()}}),await d.finalize()}catch{return"deferred"}}owns(e,t){const s=e.context;return t.agentId===s.localAgentId&&t.sessionKey===s.sessionKey&&t.runId===s.runId}async refreshRoute(e){const t=this.allowed.get(e);if(!t||!this.current(t))return;const s=this.routes.get(e);try{const t=asRecord(await this.options.gateway.request("question.get",{id:e},5e3));if(asRecord(t?.question)?.id!==e)return void this.markUnavailable(e,s);await this.accept(t?.question);const i=questionRecord(t?.question);if(!i||i.id!==e)return void this.markUnavailable(e,s)}catch(t){if("INVALID_REQUEST"===asRecord(t)?.code)return void this.markUnavailable(e,s);throw t}}markUnavailable(e,t){const s=this.routes.get(e);t&&s===t&&!s.terminal&&this.current(s.turn)&&(this.status(s,"unavailable"),s.terminal="unavailable")}async accept(e){const t=questionRecord(e);if(!t){const t=asRecord(e),s="string"==typeof t?.id?this.allowed.get(t.id):void 0;if(!s||!this.current(s)||t?.agentId!==s.context.localAgentId||t.sessionKey!==s.context.sessionKey||t.runId!==s.context.runId||"pending"!==t.status)return;const i=Array.isArray(t.questions)&&t.questions.some(e=>{const t=asRecord(e);return!0===t?.isSecret||void 0!==t?.secretStore});return this.sourceError(s,i?"SECRET_INPUT_UNSUPPORTED":"INVALID_CONTENT"),void await s.context.cancelRun("question_profile_unsupported")}const s=this.allowed.get(t.id);if(!s||!this.current(s)||!this.owns(s,t))return;let i=this.routes.get(t.id);if(i){if(i.terminal)return;if(i.turn!==s||JSON.stringify(i.native.questions)!==JSON.stringify(t.questions))return;i.native=t}else{if("pending"!==t.status)return;try{projectQuestion(t,"profile_validation")}catch{return this.sourceError(s,"INVALID_CONTENT"),void await s.context.cancelRun("question_profile_unsupported")}if([...this.routes.values()].some(e=>e.turn===s&&!e.terminal))return this.sourceError(s,"PENDING_INPUT_EXISTS"),void await s.context.cancelRun("question_profile_multiple_pending");i={turn:s,native:t,requestId:`qreq_${randomUUID()}`,messageId:randomUUID(),delivered:!1},this.routes.set(t.id,i),this.byWire.set(i.requestId,i)}"pending"===t.status?(i.delivered||await this.deliver(i),i.attempt?i.attempt.uncertain&&this.status(i,"unconfirmed",{submission_message_id:i.attempt.messageId}):this.status(i,i.delivered?"pending":"delivery_unconfirmed")):"answered"===t.status?i.attempt?await this.receipt(i):(this.status(i,"answered_elsewhere"),i.terminal="answered_elsewhere"):i.attempt&&"cancelled"===t.status?(this.status(i,"unconfirmed",{submission_message_id:i.attempt.messageId,native_status:"cancelled"}),i.terminal="unconfirmed"):i.attempt&&"expired"===t.status?(this.reject(i,i.attempt.messageId,"PENDING_EXPIRED"),i.terminal="expired"):(this.status(i,t.status),i.terminal=t.status)}async deliver(e){if(e.sending)return await e.sending,void(e.delivered||await this.reconcileDelivery(e));const t=(async()=>{const t=e.turn.context;if(this.current(e.turn))try{const s={conversationId:t.conversationId,agentId:t.targetAgentId,clientMessageId:e.messageId,idempotencyKey:e.messageId,type:"agent.input_required",deliveryContext:t.deliveryContext,content:projectQuestion(e.native,e.requestId)};"outcome_unknown"===(await this.options.client.messages.send(s)).outcome?await this.reconcileDelivery(e):this.current(e.turn)&&(e.delivered=!0)}catch(t){await this.reconcileDelivery(e),e.delivered||(this.status(e,"delivery_unconfirmed"),this.options.logger.warn?.("[question] durable prompt delivery unconfirmed"))}})();e.sending=t,await t}async reconcileDelivery(e){if(!this.current(e.turn))return;const t=e.turn.context;try{const s=await this.options.client.messages.getEnvelope(t.conversationId,e.messageId);!this.current(e.turn)||"agent.input_required"!==s.type||s.conversationId!==t.conversationId||s.senderId!==t.instanceId&&s.senderId!==t.targetAgentId||void 0!==t.historyGeneration&&s.historyGeneration!==t.historyGeneration||!sameOrigin(asRecord(s.deliveryContext),t.deliveryContext)||!isDeepStrictEqual(s.content,projectQuestion(e.native,e.requestId))||(e.delivered=!0)}catch{}}async submit(e,t,s){let i=!1;try{const n=asRecord(await this.options.gateway.request("question.get",{id:e.native.id},5e3)),r=questionRecord(n?.question);if(!r||!this.owns(e.turn,r)||!this.authorized(e,t))return;if("pending"!==r.status)return await this.accept(r),void this.reject(e,t.id,"expired"===r.status?"PENDING_EXPIRED":"PENDING_ALREADY_RESOLVED");if(JSON.stringify(r.questions)!==JSON.stringify(e.native.questions))return;if(Date.now()>=r.expiresAtMs)return void this.reject(e,t.id,"PENDING_EXPIRED");const o=nativeAnswers(r,s);if(!this.authorized(e,t))return;e.attempt={messageId:t.id,resolutionId:randomUUID(),uncertain:!1},this.status(e,"submitted",{submission_message_id:t.id}),i=!0;const a=asRecord(await this.options.gateway.request("question.resolve","cancelled"===s.outcome?{id:r.id,cancel:!0,resolvedBy:t.senderId}:{id:r.id,answers:o,resolvedBy:t.senderId,resolutionId:e.attempt.resolutionId},5e3));if(a?.status!==("cancelled"===s.outcome?"cancelled":"answered"))throw new Error("Invalid question.resolve result");if(!this.current(e.turn))return;this.status(e,"cancelled"===s.outcome?"cancelled":"accepted",{submission_message_id:t.id}),e.terminal="cancelled"===s.outcome?"cancelled":"accepted"}catch(s){if(!this.current(e.turn)||e.terminal)return;i&&e.attempt?!0===asRecord(s)?.gatewayRejected?(e.attempt=void 0,this.reject(e,t.id,"INVALID_CONTENT"),await this.refreshRoute(e.native.id)):(e.attempt.uncertain=!0,this.status(e,"unconfirmed",{submission_message_id:t.id}),await this.receipt(e)):this.status(e,"pending",{error_code:"question_read_unavailable"})}}async receipt(e){const t=e.attempt;if(t&&!e.terminal&&this.current(e.turn))try{const s=asRecord(await this.options.gateway.request("question.waitAnswer",{id:e.native.id,timeoutMs:1,includeResolutionId:!0},3e3));if(!this.current(e.turn)||e.attempt!==t||e.terminal)return;if("answered"===s?.status){const i=nonEmpty(s.resolutionId)?s.resolutionId===t.resolutionId?"accepted":"answered_elsewhere":"unconfirmed";"answered_elsewhere"===i?this.reject(e,t.messageId,"PENDING_ALREADY_RESOLVED"):this.status(e,i,{submission_message_id:t.messageId,native_status:"answered"}),e.terminal=i}else"cancelled"!==s?.status&&"expired"!==s?.status||("expired"===s.status?this.reject(e,t.messageId,"PENDING_EXPIRED"):this.status(e,"unconfirmed",{submission_message_id:t.messageId,native_status:"cancelled"}),e.terminal="expired"===s.status?"expired":"unconfirmed")}catch{}}sourceError(e,t){this.current(e)&&e.context.publishStatus({request_id:`qreq_${randomUUID()}`,status:"unsupported",error_code:t,updated_at_ms:Date.now()})}status(e,t,s={}){this.current(e.turn)&&e.turn.context.publishStatus({schema_version:USER_INPUT_SCHEMA,request_id:e.requestId,status:t,updated_at_ms:Date.now(),...s})}reject(e,t,s){this.status(e,"rejected",{response_message_id:t,error_code:s})}closeTurn(e){e.live=!1,this.turns.delete(e);for(const t of e.ids){this.allowed.get(t)===e&&this.allowed.delete(t);const s=this.routes.get(t);s?.turn===e&&(this.routes.delete(t),this.byWire.delete(s.requestId))}}background(e){const t=e.catch(()=>{this.options.logger.warn?.("[question] native question observation unavailable")}).finally(()=>this.tasks.delete(t));this.tasks.add(t)}}function sameOrigin(e,t){const s=asRecord(t),i=asRecord(e?.scope),n=asRecord(s?.scope);return!!(e&&s&&i&&n&&e.target_agent_id===s.target_agent_id&&e.delivery_principal===s.delivery_principal&&e?.runtime_epoch===s.runtime_epoch&&e?.parent_message_id===s.parent_message_id&&i.kind===n.kind&&i.id===n.id)}
@@ -1 +0,0 @@
1
- import{QUESTION_SCHEMA,decodeQuestion,decodeResponse,validateResponse,QuestionError}from"../contracts/question/codec.js";export const USER_INPUT_SCHEMA=QUESTION_SCHEMA;export const LEGACY_USER_INPUT_SCHEMA="openclaw.user_input.v1";export const questionRecord=e=>{const t=asRecord(e);if(!(t&&nonEmpty(t.id)&&nonEmpty(t.agentId)&&nonEmpty(t.sessionKey)&&nonEmpty(t.runId)&&["pending","answered","cancelled","expired"].includes(String(t.status))&&"number"==typeof t.expiresAtMs&&Number.isFinite(t.expiresAtMs)&&Array.isArray(t.questions)&&0!==t.questions.length))return;const o=[];for(const e of t.questions){const t=asRecord(e);if(!(t&&!0!==t.isSecret&&void 0===t.secretStore&&void 0===t.url&&nonEmpty(t.questionId)&&"string"==typeof t.header&&nonEmpty(t.question)&&Array.isArray(t.options)))return;const s=[];for(const e of t.options){const t=asRecord(e);if(!t||!nonEmpty(t.label)||void 0!==t.description&&"string"!=typeof t.description)return;s.push({label:t.label,..."string"==typeof t.description?{description:t.description}:{}})}if(void 0!==t.multiSelect&&"boolean"!=typeof t.multiSelect||void 0!==t.isOther&&"boolean"!=typeof t.isOther)return;o.push({questionId:t.questionId,header:t.header,question:t.question,options:s,multiSelect:!0===t.multiSelect,isOther:!0===t.isOther})}return new Set(o.map(e=>e.questionId)).size===o.length?{id:t.id,agentId:t.agentId,sessionKey:t.sessionKey,runId:t.runId,status:t.status,expiresAtMs:t.expiresAtMs,questions:o}:void 0};export function projectQuestion(e,t){for(const t of e.questions)if(t.options.length<2||new Set(t.options.map(e=>e.label)).size!==t.options.length)throw new QuestionError("INVALID_CONTENT");return decodeQuestion({schema_version:USER_INPUT_SCHEMA,kind:"question",request_id:t,message:"请回答以下问题,以继续当前任务。",expires_at:new Date(e.expiresAtMs).toISOString(),questions:e.questions.map((e,t)=>({id:e.questionId,header:e.header||`问题 ${t+1}`,text:e.question,input:{type:e.multiSelect?"multi_select":"single_select",allow_other:!0===e.isOther,options:e.options.map((e,t)=>({value:`option_${t+1}`,...e}))}}))})}export function parseContinue(e){try{return decodeResponse(e)}catch{return}}export function nativeAnswers(e,t){if(validateResponse(projectQuestion(e,t.request_id),t),"cancelled"===t.outcome)return;const o=Object.create(null);for(const s of e.questions){const e=t.answers[s.questionId];o[s.questionId]=void 0!==e.text?[e.text]:e.values.map(e=>{const t=Number(e.slice(7))-1;return s.options[t].label})}return{answers:o}}export const asRecord=e=>"object"!=typeof e||null===e||Array.isArray(e)?void 0:e;export const nonEmpty=e=>"string"==typeof e&&e.length>0;
@@ -1 +0,0 @@
1
- import{createHash,createPublicKey,verify}from"node:crypto";import{validateRuntimeExecutionGrant}from"@beeos-ai/beeos-types/runtime";export class RuntimeJwksVerifier{jwksUrl;fetcher;ttlMs;now;keys=new Map;expiresAt=0;inflight;provenance;keyMaterials=Object.freeze([]);keysetUrl;constructor(e,t=fetch,r=3e5,s=Date.now){this.jwksUrl=e,this.fetcher=t,this.ttlMs=r,this.now=s,this.keysetUrl=new URL(e).toString()}async refresh(e=!1){if(!(!e&&this.keys.size>0&&this.now()<this.expiresAt)){if(this.inflight)return await this.inflight;this.inflight=this.load();try{await this.inflight}finally{this.inflight=void 0}}}hasKid(e){return this.keys.has(e)}trustedKids(){return Object.freeze([...this.keys.keys()].sort())}trustedKeyMaterials(){return this.keyMaterials}documentProvenance(){return this.provenance}verifyAndDecodeGrant(e){const t=this.verifyCompact(e);return t?{header:t.header,claims:t.claims,compactHash:sha256(e)}:null}verifyAndValidateGrant(e,t){const r=this.verifyAndDecodeGrant(e);return r&&0===validateRuntimeExecutionGrant(r.claims,t).length?r:null}verifyAndDecodeBoundary(e){const t=this.verifyCompact(e);return t?{header:t.header,claims:t.claims,compactHash:sha256(e)}:null}async load(){const e=await this.fetcher(this.jwksUrl,{signal:AbortSignal.timeout(1e4),redirect:"error"});if(!e.ok)throw new Error(`JWKS fetch failed: HTTP ${e.status}`);const t=await e.json(),r=new Map,s=[];for(const e of t.keys??[]){if("RSA"!==e.kty||"sig"!==e.use||"RS256"!==e.alg||"string"!=typeof e.kid||!e.kid)continue;if(r.has(e.kid))throw new Error(`JWKS contains duplicate kid: ${e.kid}`);const t=createPublicKey({key:e,format:"jwk"});if((t.asymmetricKeyDetails?.modulusLength??0)<2048)continue;const i=t.export({format:"jwk"});"RSA"===i.kty&&"string"==typeof i.n&&"string"==typeof i.e&&(r.set(e.kid,t),s.push(Object.freeze({jwkThumbprint:sha256(JSON.stringify({e:i.e,kty:"RSA",n:i.n})),spkiSha256:createHash("sha256").update(t.export({format:"der",type:"spki"})).digest("hex")})))}if(0===r.size)throw new Error("JWKS contains no trusted RS256 keys");const i=e.url?new URL(e.url).toString():this.keysetUrl;if(i!==this.keysetUrl)throw new Error("JWKS response provenance URL mismatch");this.keys=r,this.keyMaterials=Object.freeze(s.sort((e,t)=>e.jwkThumbprint.localeCompare(t.jwkThumbprint)||e.spkiSha256.localeCompare(t.spkiSha256))),this.provenance=Object.freeze({sourceUrl:i,etag:e.headers.get("etag")??"",issuer:"string"==typeof t.issuer?t.issuer:"",audience:"string"==typeof t.audience?t.audience:"",purpose:"string"==typeof t.purpose?t.purpose:"",maxClaimTtlSeconds:"number"==typeof t.maxClaimTtlSeconds?t.maxClaimTtlSeconds:Number.NaN}),this.expiresAt=this.now()+this.ttlMs}verifyCompact(e){const t=e.split(".");if(3!==t.length)return null;try{if(!t.every(isCanonicalBase64Url))return null;const e=JSON.parse(decodeBase64Url(t[0]));if("RS256"!==e.alg||"JWT"!==e.typ||"string"!=typeof e.kid)return null;const r=this.keys.get(e.kid);if(!r)return null;const s=Buffer.from(`${t[0]}.${t[1]}`),i=Buffer.from(t[2],"base64url");if(!verify("RSA-SHA256",s,r,i))return null;const n=JSON.parse(decodeBase64Url(t[1]));return null===n||"object"!=typeof n||Array.isArray(n)?null:{header:e,claims:n}}catch{return null}}}function isCanonicalBase64Url(e){if(!e||!/^[A-Za-z0-9_-]+$/.test(e))return!1;return Buffer.from(e,"base64url").toString("base64url")===e}function decodeBase64Url(e){return Buffer.from(e,"base64url").toString("utf8")}function sha256(e){return createHash("sha256").update(e).digest("hex")}
@@ -1 +0,0 @@
1
- export function runtimeReasoningOptions(e){const t=e.reasoningOptions&&"object"==typeof e.reasoningOptions?e.reasoningOptions:void 0,n=t?.levels??e.thinkingLevels;if(!Array.isArray(n)||!n.length||n.length>32)return;const i=new Map;for(const e of n){const t="string"==typeof e?{id:e}:e;if(!t||"object"!=typeof t||"string"!=typeof t.id||!t.id.trim()||t.id.length>64||/\s/.test(t.id)||i.has(t.id))return;if(void 0!==t.label&&("string"!=typeof t.label||t.label.length>128))return;i.set(t.id,{id:t.id,..."string"==typeof t.label?{label:t.label}:{}})}const l=t&&"defaultLevel"in t?t.defaultLevel:e.thinkingDefault;return null!=l&&"string"!=typeof l||"string"==typeof l&&!i.has(l)?void 0:{levels:[...i.values()],defaultLevel:"string"==typeof l?l:null}}
@@ -1 +0,0 @@
1
- import{createHash,randomBytes,sign}from"node:crypto";import{RUNTIME_INTERNAL_API_V1_ROUTE_CONTRACTS,RUNTIME_HASH_DOMAINS,RUNTIME_RPC_PROTOCOL_VERSION,runtimeHashPreimage,runtimeIdentitySignatureMessage,validateRuntimeInternalRegistrationResult}from"@beeos-ai/beeos-types/runtime";import{RuntimeTransportFailurePolicy}from"./runtime-transport-failure-policy.js";export class RuntimeRegistrationLeaseExpiredError extends Error{constructor(){super("Instance authority returned an expired active lease"),this.name="RuntimeRegistrationLeaseExpiredError"}}export class RuntimeRegistrationHandoffRequiredError extends Error{retryAfterMs;constructor(e=65e3){super("Instance authority requires waiting for the active runtime lease to expire"),this.name="RuntimeRegistrationHandoffRequiredError",this.retryAfterMs=e}}export class RuntimeRegistrationOwnerResetRequiredError extends Error{constructor(){super("Instance authority requires owner reset authorization after a journal store change"),this.name="RuntimeRegistrationOwnerResetRequiredError"}}export class RuntimeRegistrationJournalAdvanceRequiredError extends Error{currentJournalGeneration;expectedJournalGeneration;constructor(e){super("Instance authority requires journal generation to advance exactly once after lease expiry"),this.name="RuntimeRegistrationJournalAdvanceRequiredError",this.currentJournalGeneration=e?.currentJournalGeneration,this.expectedJournalGeneration=e?.expectedJournalGeneration}}export class RuntimeRegistrationCoordinator{transport;config;onLeaseLost;now;active=null;timer;expiryTimer;stopped=!1;generation=0;heartbeatTransportFailurePolicy=new RuntimeTransportFailurePolicy;authorityListeners=new Set;constructor(e,t,i,r=Date.now){this.transport=e,this.config=t,this.onLeaseLost=i,this.now=r}get lease(){return!this.active||Date.parse(this.active.leaseExpiresAt)<=this.now()?null:this.active}get canClaimMutations(){return null!==this.lease}get authorityLease(){const e=this.lease;return e?Object.freeze({...e,handlerIdentity:this.config.handlerIdentity}):null}subscribeAuthority(e){return this.authorityListeners.add(e),()=>{this.authorityListeners.delete(e)}}async start(){const e=++this.generation;return this.stopped=!1,await this.registerOnce(e)}async registerOnce(e){if(!this.isCurrent(e))return null;this.timer=void 0,this.active&&(this.clearLeaseExpiry(),this.active=null,this.notifyAuthority());const t={registrationId:this.config.registrationId,handlerIdentity:this.config.handlerIdentity,contractRevision:this.config.contractRevision,runtimeRpcProtocolVersion:RUNTIME_RPC_PROTOCOL_VERSION,runtimeMethods:this.config.runtimeMethods,capabilities:this.config.capabilities,manifestDigest:this.config.manifestDigest,journalStoreId:this.config.journalStoreId,journalGeneration:this.config.journalGeneration};let i;try{i=await this.transport.register(this.signProof("runtime.register",t))}catch(t){if(!this.isCurrent(e))return null;if(t instanceof RuntimeRegistrationLeaseExpiredError||t instanceof RuntimeRegistrationJournalAdvanceRequiredError||t instanceof RuntimeRegistrationOwnerResetRequiredError)return this.onLeaseLost(t instanceof RuntimeRegistrationLeaseExpiredError?"expired":"heartbeat_failed",t),null;this.onLeaseLost("heartbeat_failed",t);const i=t instanceof RuntimeRegistrationHandoffRequiredError?t.retryAfterMs:5e3;return this.scheduleRegistration(i,e),null}return this.isCurrent(e)?"active"!==i.status?("fenced"===i.status?this.onLeaseLost("fenced"):this.scheduleRegistration(i.retryAfterMs,e),null):(this.active={instanceId:i.instanceId,leaseId:i.leaseId,runtimeEpoch:i.runtimeEpoch,runtimeLeaseCredential:i.runtimeLeaseCredential,leaseExpiresAt:i.leaseExpiresAt},this.heartbeatTransportFailurePolicy.recordSuccess(),this.notifyAuthority(),this.scheduleLeaseExpiry(this.active,e),this.schedule(i.heartbeatIntervalMs,e),this.active):null}stop(){this.generation++,this.stopped=!0,this.timer&&clearTimeout(this.timer),this.expiryTimer&&clearTimeout(this.expiryTimer),this.timer=void 0,this.expiryTimer=void 0,this.active=null,this.notifyAuthority()}schedule(e,t){if(!this.isCurrent(t))return;const i=this.active;i&&(this.timer=setTimeout(()=>{this.sendHeartbeat(e,t,i)},e),this.timer.unref?.())}scheduleRegistration(e,t){this.isCurrent(t)&&(this.timer=setTimeout(()=>{this.registerOnce(t)},e))}async sendHeartbeat(e,t,i){if(!this.isCurrentLease(t,i))return;const r={leaseId:i.leaseId,handlerIdentity:this.config.handlerIdentity,runtimeEpoch:i.runtimeEpoch},s=this.config.getMSConnectionStatus?{...r,msConnectionStatus:this.config.getMSConnectionStatus(i)}:r;try{const r=await this.transport.heartbeat(this.signProof("runtime.heartbeat",s));if(!this.isCurrentLease(t,i))return;if("renewed"!==r.status)return this.heartbeatTransportFailurePolicy.recordSuccess(),this.active=null,this.clearLeaseExpiry(),this.notifyAuthority(),void this.onLeaseLost(r.status);this.heartbeatTransportFailurePolicy.recordSuccess(),this.active={...i,runtimeLeaseCredential:r.runtimeLeaseCredential,leaseExpiresAt:r.leaseExpiresAt},this.notifyAuthority(),this.scheduleLeaseExpiry(this.active,t),this.schedule(e,t)}catch(r){if(!this.isCurrentLease(t,i))return;if(!this.heartbeatTransportFailurePolicy.recordFailure())return void this.schedule(Math.min(e,5e3),t);this.active=null,this.clearLeaseExpiry(),this.notifyAuthority(),this.onLeaseLost("heartbeat_failed",r),this.scheduleRegistration(5e3,t)}}scheduleLeaseExpiry(e,t){this.clearLeaseExpiry();const i=`${e.leaseId}\0${e.runtimeEpoch}\0${e.leaseExpiresAt}`,r=()=>{const s=Date.parse(e.leaseExpiresAt)-this.now();if(s>0)return this.expiryTimer=setTimeout(r,Math.min(2147483647,s)),void this.expiryTimer.unref?.();const n=this.active;this.isCurrentLease(t,e)&&n&&`${n.leaseId}\0${n.runtimeEpoch}\0${n.leaseExpiresAt}`===i&&(this.active=null,this.expiryTimer=void 0,this.notifyAuthority(),this.onLeaseLost("expired"))};r()}clearLeaseExpiry(){this.expiryTimer&&clearTimeout(this.expiryTimer),this.expiryTimer=void 0}isCurrent(e){return!this.stopped&&e===this.generation}isCurrentLease(e,t){return this.isCurrent(e)&&this.active===t}notifyAuthority(){const e=this.authorityLease;for(const t of this.authorityListeners)try{t(e)}catch{}}signProof(e,t){const i=new Date(this.now()).toISOString(),r=randomBytes(18).toString("base64url"),s="runtime.register"===e?RUNTIME_HASH_DOMAINS.registration:RUNTIME_HASH_DOMAINS.heartbeat,n=createHash("sha256").update(runtimeHashPreimage(s,t)).digest("hex"),a=runtimeIdentitySignatureMessage({purpose:e,instanceIdentityKeyId:this.config.instanceIdentityKeyId,signedAt:i,nonce:r,payloadHash:n});return{...t,signaturePurpose:e,instanceIdentityKeyId:this.config.instanceIdentityKeyId,signedAt:i,nonce:r,payloadHash:n,signature:sign(null,a,this.config.privateKey).toString("base64url")}}}export class InstanceAuthorityRuntimeRegistrationTransport{options;constructor(e){this.options=e}async register(e){if(e.registrationId!==this.options.registrationId)throw new Error("runtime registration id mismatch");const t=await this.post(RUNTIME_INTERNAL_API_V1_ROUTE_CONTRACTS.runtimeRegister.path,e);if("active"===t.status&&Number.isFinite(Date.parse(t.leaseExpiresAt))&&Date.parse(t.leaseExpiresAt)<=Date.now())throw new RuntimeRegistrationLeaseExpiredError;if(validateRuntimeInternalRegistrationResult(t)||"fenced"!==t.status&&(t.journalStoreId!==e.journalStoreId||t.journalGeneration!==e.journalGeneration)||"active"===t.status&&(!t.instanceId||!t.leaseId||!t.runtimeLeaseCredential||!Number.isInteger(t.heartbeatIntervalMs)||!Number.isFinite(Date.parse(t.leaseExpiresAt))||Date.parse(t.leaseExpiresAt)<=Date.now()))throw new Error("Instance authority returned an invalid registration binding");return t}async heartbeat(e){const t=await this.post(RUNTIME_INTERNAL_API_V1_ROUTE_CONTRACTS.runtimeHeartbeat.path.replace("{registrationId}",encodeURIComponent(this.options.registrationId)),e);if(!(t&&["renewed","fenced","expired"].includes(t.status)&&("renewed"!==t.status||t.runtimeLeaseCredential&&Number.isFinite(Date.parse(t.leaseExpiresAt)))))throw new Error("Instance authority returned an invalid heartbeat result");return t}async post(e,t){const i=new URL(e,this.options.agentGatewayUrl),r=await this.options.agentFetch(i,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(t)});if(!r.ok){const e=await r.text().catch(()=>"");if(409===r.status&&i.pathname.endsWith("/runtime/registrations"))throw classifyRuntimeRegistrationConflict(e);throw new Error(`runtime Instance authority request failed (${r.status} ${r.statusText}) ${i.pathname}`+(e?`: ${e.slice(0,240)}`:""))}return await r.json()}}export function classifyRuntimeRegistrationConflict(e){const t=extractConflictMessage(e);if(/journal store change requires owner reset authorization/i.test(t))return new RuntimeRegistrationOwnerResetRequiredError;if(/journal generation must advance exactly once/i.test(t)){const e=t.match(/\bcurrent=(\d+)\b/i)?.[1],i=t.match(/\bexpected=(\d+)\b/i)?.[1];return new RuntimeRegistrationJournalAdvanceRequiredError({currentJournalGeneration:e&&/^[1-9][0-9]*$/.test(e)?e:void 0,expectedJournalGeneration:i&&/^[1-9][0-9]*$/.test(i)?i:void 0})}return/active runtime lease requires explicit handoff/i.test(t)||/waiting for the active runtime lease/i.test(t),new RuntimeRegistrationHandoffRequiredError}function extractConflictMessage(e){if(!e)return"";try{const t=JSON.parse(e),i=t.error?.message;if("string"==typeof i)return i;if("string"==typeof t.message)return t.message}catch{}return e}
@@ -1 +0,0 @@
1
- export class RuntimeTransportFailurePolicy{threshold;consecutiveFailures=0;constructor(e=3){if(this.threshold=e,!Number.isSafeInteger(e)||e<=0)throw new Error("transport failure threshold must be a positive integer")}recordSuccess(){this.consecutiveFailures=0}recordFailure(){return this.consecutiveFailures+=1,!(this.consecutiveFailures<this.threshold)&&(this.consecutiveFailures=0,!0)}}
@@ -1 +0,0 @@
1
- const GATEWAY_GRANT_PROVENANCE=Object.freeze({issuer:"beeos-gateway",audience:"beeos-runtime-command",purpose:"runtime-execution-grant",maxClaimTtlSeconds:60}),MESSAGE_BOUNDARY_PROVENANCE=Object.freeze({issuer:"message-service",audience:"beeos-runtime-execution-boundary",purpose:"runtime-execution-boundary",maxClaimTtlSeconds:60});export class GatewayGrantJwksVerifier{verifier;purpose="gateway-runtime-grant";keysetProvenance;constructor(e){this.verifier=e,this.keysetProvenance=e.keysetUrl}async refresh(e=!1){await this.verifier.refresh(e),assertResponseProvenance(this.verifier,GATEWAY_GRANT_PROVENANCE)}trustedKeyMaterials(){return this.verifier.trustedKeyMaterials()}responseProvenance(){return this.verifier.documentProvenance()}verifyAndDecodeGrant(e){const r=this.verifier.verifyAndDecodeGrant(e);return"beeos-gateway"===r?.claims.iss&&"beeos-runtime-command"===r.claims.aud&&"runtime-execution-grant"===r.claims.purpose?r:null}}export class MessageServiceBoundaryJwksVerifier{verifier;purpose="message-service-execution-boundary";keysetProvenance;constructor(e){this.verifier=e,this.keysetProvenance=e.keysetUrl}async refresh(e=!1){await this.verifier.refresh(e),assertResponseProvenance(this.verifier,MESSAGE_BOUNDARY_PROVENANCE)}trustedKeyMaterials(){return this.verifier.trustedKeyMaterials()}responseProvenance(){return this.verifier.documentProvenance()}verifyAndDecodeBoundary(e){const r=this.verifier.verifyAndDecodeBoundary(e);return"message-service"===r?.claims.iss&&"beeos-runtime-execution-boundary"===r.claims.aud?r:null}}export class SplitIssuerRuntimeAuthorizationVerifier{grant;boundary;constructor(e,r){if(this.grant=e,this.boundary=r,e.keysetProvenance===r.keysetProvenance)throw new Error("grant and boundary JWKS keysets require distinct provenance")}async refresh(e=!1){await Promise.all([this.grant.refresh(e),this.boundary.refresh(e)]);const r=this.grant.responseProvenance(),s=this.boundary.responseProvenance();if(!r||!s||r.sourceUrl===s.sourceUrl||r.etag===s.etag)throw new Error("grant and boundary JWKS responses require distinct provenance");const n=new Set(this.boundary.trustedKeyMaterials().flatMap(e=>[e.jwkThumbprint,e.spkiSha256]));if(this.grant.trustedKeyMaterials().some(e=>n.has(e.jwkThumbprint)||n.has(e.spkiSha256)))throw new Error("grant and boundary JWKS keysets reuse public-key material")}verifyAndDecodeGrant(e){return this.grant.verifyAndDecodeGrant(e)}verifyAndDecodeBoundary(e){return this.boundary.verifyAndDecodeBoundary(e)}}function assertResponseProvenance(e,r){const s=e.documentProvenance();if(!s||!s.etag||s.sourceUrl!==e.keysetUrl||s.issuer!==r.issuer||s.audience!==r.audience||s.purpose!==r.purpose||s.maxClaimTtlSeconds!==r.maxClaimTtlSeconds)throw new Error(`JWKS response provenance mismatch for ${r.purpose}`)}