@kingsoftcloud/agentkit-harness-node 0.0.0-stage → 0.0.2

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 (151) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +1 -0
  3. package/README.md +124 -2
  4. package/THIRD_PARTY_NOTICES.md +66 -0
  5. package/ZCode-LICENSE +202 -0
  6. package/dist/index.mjs +4871 -0
  7. package/dist/native-command-plan.LICENSE.txt +221 -0
  8. package/dist/native-command-plan.json +16 -0
  9. package/dist/native-command-plan.mjs +8 -0
  10. package/dist/rpc-entry.mjs +5682 -0
  11. package/package.json +169 -4
  12. package/src/native/a2a-receipt-source.mjs +19 -0
  13. package/src/native/a2a-tools.mjs +517 -0
  14. package/src/native/activity-status.mjs +30 -0
  15. package/src/native/artifact-codec.mjs +481 -0
  16. package/src/native/artifact-store.mjs +1162 -0
  17. package/src/native/assistant-stream.mjs +76 -0
  18. package/src/native/background-command-port.mjs +95 -0
  19. package/src/native/browser-action-observation.mjs +43 -0
  20. package/src/native/browser-availability.mjs +22 -0
  21. package/src/native/browser-canvas-metrics.mjs +71 -0
  22. package/src/native/browser-dom.mjs +193 -0
  23. package/src/native/browser-playwright.mjs +1249 -0
  24. package/src/native/browser-vision.mjs +369 -0
  25. package/src/native/browser-workspace-policy.mjs +22 -0
  26. package/src/native/browser-workspace-protocol.mjs +95 -0
  27. package/src/native/browser-workspace-server.mjs +164 -0
  28. package/src/native/browser-workspace.mjs +355 -0
  29. package/src/native/captured-source.mjs +3 -0
  30. package/src/native/child-budget-allocation.mjs +87 -0
  31. package/src/native/child-capabilities.mjs +35 -0
  32. package/src/native/child-command-resource.mjs +20 -0
  33. package/src/native/child-history.mjs +188 -0
  34. package/src/native/child-merge.mjs +98 -0
  35. package/src/native/child-model-surface.mjs +19 -0
  36. package/src/native/child-observation.mjs +100 -0
  37. package/src/native/child-owner.mjs +620 -0
  38. package/src/native/child-publication.mjs +76 -0
  39. package/src/native/child-readers.mjs +366 -0
  40. package/src/native/child-tools.mjs +46 -0
  41. package/src/native/child-workspace-binding.mjs +29 -0
  42. package/src/native/child-workspace-tools.mjs +1 -0
  43. package/src/native/child-workspaces.mjs +655 -0
  44. package/src/native/children.mjs +365 -0
  45. package/src/native/command-plan-worker.mjs +14 -0
  46. package/src/native/command-plan.mjs +31 -0
  47. package/src/native/command-progress.mjs +64 -0
  48. package/src/native/command-shell.mjs +9 -0
  49. package/src/native/command-workspace-observation.mjs +36 -0
  50. package/src/native/component-tools.mjs +280 -0
  51. package/src/native/context-counter.mjs +133 -0
  52. package/src/native/context-markers.mjs +51 -0
  53. package/src/native/context-profile.mjs +72 -0
  54. package/src/native/context-status.mjs +27 -0
  55. package/src/native/conversation-command-control.mjs +133 -0
  56. package/src/native/delivery-timeline.mjs +39 -0
  57. package/src/native/dsh-background-ownership.mjs +102 -0
  58. package/src/native/dsh-managed-ownership.mjs +23 -0
  59. package/src/native/dsh-turn-contract.mjs +3 -0
  60. package/src/native/dsh-turn-ownership.mjs +54 -0
  61. package/src/native/dsh-turn-runtime.mjs +498 -0
  62. package/src/native/e2b-background-supervisor.mjs +347 -0
  63. package/src/native/e2b-background.mjs +368 -0
  64. package/src/native/e2b-command-state.mjs +40 -0
  65. package/src/native/e2b-command-tools.mjs +486 -0
  66. package/src/native/e2b-sandbox-owner.mjs +227 -0
  67. package/src/native/hook-executor.mjs +249 -0
  68. package/src/native/instruction-assembly.mjs +60 -0
  69. package/src/native/instruction-context.mjs +54 -0
  70. package/src/native/local-background-supervisor.mjs +108 -0
  71. package/src/native/local-background.mjs +207 -0
  72. package/src/native/local-command-evidence.mjs +57 -0
  73. package/src/native/local-command-policy-worker.mjs +197 -0
  74. package/src/native/local-command-policy.mjs +46 -0
  75. package/src/native/local-command-state.mjs +177 -0
  76. package/src/native/local-command-tools.mjs +302 -0
  77. package/src/native/local-execution-profile.mjs +36 -0
  78. package/src/native/local-output-policy.mjs +92 -0
  79. package/src/native/local-process-bin/darwin-arm64/launcher +0 -0
  80. package/src/native/local-process-bin/darwin-x64/launcher +0 -0
  81. package/src/native/local-process-bin/linux-arm64/launcher +0 -0
  82. package/src/native/local-process-bin/linux-x64/launcher +0 -0
  83. package/src/native/local-process-launcher.c +183 -0
  84. package/src/native/local-process-licenses/GCC-COPYING.RUNTIME +72 -0
  85. package/src/native/local-process-licenses/GCC-COPYING3 +674 -0
  86. package/src/native/local-process-licenses/NOTICE +21 -0
  87. package/src/native/local-process-licenses/musl-COPYRIGHT +193 -0
  88. package/src/native/local-process-manifest.json +32 -0
  89. package/src/native/local-process.mjs +246 -0
  90. package/src/native/local-resource-profile.mjs +32 -0
  91. package/src/native/memory-candidate.mjs +121 -0
  92. package/src/native/memory-extraction-run.mjs +60 -0
  93. package/src/native/memory-extraction-tools.mjs +116 -0
  94. package/src/native/memory-recall.mjs +65 -0
  95. package/src/native/memory-store.mjs +334 -0
  96. package/src/native/memory-tools.mjs +329 -0
  97. package/src/native/model-anthropic-cache.mjs +49 -0
  98. package/src/native/model-anthropic-tool-search.mjs +85 -0
  99. package/src/native/model-anthropic.mjs +753 -0
  100. package/src/native/model-chat-usage.mjs +24 -0
  101. package/src/native/model-inline-reasoning.mjs +111 -0
  102. package/src/native/model-media.mjs +174 -0
  103. package/src/native/model-normalize.mjs +228 -0
  104. package/src/native/model-openai-chat.mjs +561 -0
  105. package/src/native/model-port.mjs +361 -0
  106. package/src/native/model-provider-compat.mjs +129 -0
  107. package/src/native/model-replay.mjs +153 -0
  108. package/src/native/model-request.mjs +15 -0
  109. package/src/native/model-responses.mjs +1205 -0
  110. package/src/native/model-sse.mjs +171 -0
  111. package/src/native/model-surface-host.mjs +27 -0
  112. package/src/native/model-tool-search-policy.mjs +16 -0
  113. package/src/native/model-transport-observation.mjs +27 -0
  114. package/src/native/owned-child.mjs +114 -0
  115. package/src/native/owned-command.mjs +106 -0
  116. package/src/native/python-syntax-worker.mjs +60 -0
  117. package/src/native/python-syntax.mjs +50 -0
  118. package/src/native/read-interruption.mjs +16 -0
  119. package/src/native/result-stream.mjs +63 -0
  120. package/src/native/ruff-ast.mjs +95 -0
  121. package/src/native/run-observation.mjs +128 -0
  122. package/src/native/session-delivery-journal.mjs +96 -0
  123. package/src/native/session-delivery.mjs +434 -0
  124. package/src/native/shell-analysis.mjs +50 -0
  125. package/src/native/skill-disclosure.mjs +404 -0
  126. package/src/native/skill-events.mjs +164 -0
  127. package/src/native/skill-tools.mjs +813 -0
  128. package/src/native/source-page.mjs +73 -0
  129. package/src/native/sqlite-session-inbox.mjs +42 -0
  130. package/src/native/sqlite-store.mjs +617 -0
  131. package/src/native/tool-authority.mjs +99 -0
  132. package/src/native/tool-guidance.mjs +12 -0
  133. package/src/native/tool-observation.mjs +75 -0
  134. package/src/native/tool-states.mjs +14 -0
  135. package/src/native/verification-authority.mjs +37 -0
  136. package/src/native/web-tools.mjs +643 -0
  137. package/src/native/workspace-checkpoints.mjs +312 -0
  138. package/src/native/workspace-context.mjs +61 -0
  139. package/src/native/workspace-display.mjs +39 -0
  140. package/src/native/workspace-edit-match.mjs +19 -0
  141. package/src/native/workspace-edit-worker.mjs +15 -0
  142. package/src/native/workspace-editing.mjs +447 -0
  143. package/src/native/workspace-image.mjs +72 -0
  144. package/src/native/workspace-instructions.mjs +107 -0
  145. package/src/native/workspace-mutation-lock.mjs +74 -0
  146. package/src/native/workspace-patch-worker.mjs +17 -0
  147. package/src/native/workspace-patch.mjs +17 -0
  148. package/src/native/workspace-paths.mjs +225 -0
  149. package/src/native/workspace-state.mjs +272 -0
  150. package/src/native/workspace-subject-observer.mjs +84 -0
  151. package/src/native/workspace-tools.mjs +1740 -0
@@ -0,0 +1,486 @@
1
+ // E2B remote background command ToolPort — Node Native tool definitions + factory.
2
+ //
3
+ // Key contracts:
4
+ // - Uses canonical backgroundCommandPolicy 'owned-command-launch/v1' and ref
5
+ // {taskId, sourceRunId, operationKey}.
6
+ // - A UNIFIED guard checks authority+drift+abort using the ORIGINAL snapshot.
7
+ // - After a side-effect: uncertain with known locator, NOT executed:false.
8
+ // - budget: EVERY return path is bounded so canonical(content) <= maxOutputBytes.
9
+ // If the budget cannot hold the minimal uncertain result with the FULL original
10
+ // identity (operationKey NOT truncated), the command is REJECTED before any
11
+ // ensure/start with executed:false — no remote side-effect, no fake success.
12
+ // A successful background launch preserves status=ok and backgroundCommandRef;
13
+ // only the presentation content is truncated. Identity fields are never
14
+ // truncated or dropped to fit a budget.
15
+ import { canonical, copy, invariant, scopeKey, toolInputRejection } from '@kingsoftcloud/agentkit-harness-core';
16
+ import { TERMINAL, delay } from './e2b-command-state.mjs';
17
+ import { createHash } from 'node:crypto';
18
+
19
+ export const E2B_COMMAND_TOOLS_CONTRACT = 'agentkit.native-e2b-command-tools/v1';
20
+
21
+ const schemas = { nullableSeconds: { anyOf: [{ type: 'integer', minimum: 1 }, { type: 'null' }] },
22
+ cursor: { type: 'integer', minimum: 0, maximum: Number.MAX_SAFE_INTEGER } };
23
+
24
+ function base(name, description, properties, required, mutating, timeoutMs) {
25
+ return { name, description, parameters: { type: 'object', properties, required, additionalProperties: false },
26
+ readOnly: !mutating, concurrentSafe: !mutating, permissions: mutating ? [name === 'stop_command' ? 'sandbox:cancel' : 'sandbox:execute'] : [],
27
+ timeoutMs, contextRole: 'none', observationRole: 'none', progressObservation: false, contextRetention: 'normal',
28
+ ...(!mutating ? { recoveryPolicy: 'safe-read/v1' } : {}) };
29
+ }
30
+
31
+ export function e2bCommandToolDefinitions(foregroundTimeoutSeconds = 300) {
32
+ invariant(Number.isSafeInteger(foregroundTimeoutSeconds) && foregroundTimeoutSeconds > 0
33
+ && foregroundTimeoutSeconds <= 86400, 'e2b_command_foreground_limit_invalid');
34
+ return [
35
+ base('sandbox_status', 'Report the bound E2B remote sandbox backend and its execution boundary.', {}, [], false, 10000),
36
+ { ...base('run_command', 'Run a command inside the bound E2B remote sandbox. background=true returns an owned task_id for non-blocking reads via read_command_output; stop_command requests cancellation. The sandbox is remote — cwd is a remote path, not a host-local one. An unknown outcome is never re-launched.',
37
+ { command: { type: 'string', minLength: 1 }, cwd: { anyOf: [{ type: 'string' }, { type: 'null' }] },
38
+ timeout: schemas.nullableSeconds, env: { anyOf: [{ type: 'object', additionalProperties: { type: 'string' } }, { type: 'null' }] },
39
+ background: { type: 'boolean' }, background_timeout: schemas.nullableSeconds },
40
+ ['command'], true, foregroundTimeoutSeconds * 1000 + 20000), backgroundCommandPolicy: 'owned-command-launch/v1' },
41
+ base('read_command_output', 'Read an owned E2B command status and UTF-8 byte cursors. Reusing a cursor is read-only. Waiting never changes the command deadline. No sandbox creation or command restart.',
42
+ { task_id: { type: 'string', pattern: '^[a-f0-9]{64}$' }, stdout_cursor: schemas.cursor,
43
+ stderr_cursor: schemas.cursor, max_bytes: { type: 'integer', minimum: 4, maximum: 65536 },
44
+ wait_seconds: { type: 'integer', minimum: 0, maximum: 600 } }, ['task_id'], false, 610000),
45
+ base('stop_command', 'Request cancellation of one E2B command launched by this Session. Read its output to confirm the final status; a cancel request is not proof of completion.',
46
+ { task_id: { type: 'string', pattern: '^[a-f0-9]{64}$' } }, ['task_id'], true, 10000),
47
+ ];
48
+ }
49
+
50
+ export const E2B_CODE_TOOLS_CONTRACT = 'agentkit.native-e2b-code-tools/v1';
51
+ export const DSH_E2B_CODE_TOOLS_CONTRACT = 'agentkit.dsh-e2b-code-tools/v1';
52
+ export function e2bCodeToolDefinitions(timeoutSeconds = 300, name = 'run_code') {
53
+ e2bCommandToolDefinitions(timeoutSeconds); // Same Host timeout bounds.
54
+ invariant(['run_code', 'sandbox_run_code'].includes(name), 'e2b_code_name_invalid');
55
+ return [base(name, 'Execute a Python, JavaScript or Bash snippet in an isolated remote sandbox. Requires E2B; never runs a snippet on the Host. Unknown outcomes require reconciliation of the original task.',
56
+ { code: { type: 'string', minLength: 1 }, language: { type: 'string' }, timeout: schemas.nullableSeconds,
57
+ env: { anyOf: [{ type: 'object', additionalProperties: { type: 'string' } }, { type: 'null' }] } },
58
+ ['code'], true, timeoutSeconds * 1000 + 20000)];
59
+ }
60
+
61
+ function snippetCommand(args, before) {
62
+ const aliases = { py: 'python', python3: 'python', js: 'javascript', node: 'javascript', nodejs: 'javascript', sh: 'bash', shell: 'bash' };
63
+ const selected = (args.language || 'python').trim().toLowerCase(), language = aliases[selected] ?? selected;
64
+ const runner = { python: ['.py', 'python'], javascript: ['.js', 'node'], bash: ['.sh', 'bash'] }[language];
65
+ if (!runner) return null;
66
+ const path = `/tmp/ksadk-run-code-${createHash('sha256').update(before.body).digest('hex')}${runner[0]}`;
67
+ return { path, language, command: `${runner[1]} '${path}'`,
68
+ launch: `chmod 600 '${path}' && exec ${runner[1]} '${path}'` };
69
+ }
70
+
71
+ const commandOutput = result => ({ status: result.status, stdout: result.stdout, stderr: result.stderr,
72
+ exit_code: result.exitCode, stdout_cursor: result.stdoutCursor, stderr_cursor: result.stderrCursor,
73
+ cancel_requested: result.cancelRequested, output_may_be_truncated: result.outputMayBeTruncated,
74
+ evidence_incomplete: result.evidenceIncomplete, observed_exit_code: result.observedExitCode,
75
+ ...(result.outcomeReason ? { outcome_reason: result.outcomeReason } : {}) });
76
+ const errorResult = (code, extra = {}) => ({ status: 'error', content: { ok: false, error_type: code, ...extra } });
77
+ function utf8Preview(text, maxBytes) {
78
+ return new TextDecoder('utf8', { ignoreBOM: true }).decode(Buffer.from(text).subarray(0, maxBytes), { stream: true });
79
+ }
80
+
81
+ function syncValue(value) {
82
+ if (value && typeof value.then === 'function') {
83
+ Promise.resolve(value).catch(() => {});
84
+ invariant(false, 'e2b_command_sync_contract_invalid');
85
+ }
86
+ return value;
87
+ }
88
+
89
+ function abortable(promise, signal) {
90
+ return new Promise((resolve, reject) => {
91
+ const aborted = () => { signal.removeEventListener('abort', aborted); reject(signal.reason); };
92
+ signal.addEventListener('abort', aborted, { once: true });
93
+ Promise.resolve(promise).then(value => { signal.removeEventListener('abort', aborted); resolve(value); },
94
+ error => { signal.removeEventListener('abort', aborted); reject(error); });
95
+ if (signal.aborted) aborted();
96
+ });
97
+ }
98
+
99
+ export function createNativeE2BCommandTools(options = {}) {
100
+ return createNativeTools(options, false);
101
+ }
102
+ export function createNativeE2BCodeTools(options = {}) {
103
+ return createNativeTools(options, true);
104
+ }
105
+ function createNativeTools(options, codeOnly) {
106
+ invariant(options.scope, 'e2b_command_scope_required');
107
+ const fixedScope = copy(options.scope); scopeKey(fixedScope);
108
+ return createCommandTools(options, { codeOnly, contract: codeOnly ? E2B_CODE_TOOLS_CONTRACT : E2B_COMMAND_TOOLS_CONTRACT, fields: { scope: fixedScope },
109
+ identity(request) {
110
+ invariant(request.scope && canonical(request.scope) === canonical(fixedScope), 'e2b_command_scope_unbound');
111
+ invariant(['runId','turnId','buildId','taskChainId'].every(k => typeof request[k] === 'string' && request[k].trim()),
112
+ 'e2b_command_identity_required');
113
+ invariant(request.parentRunId === null || typeof request.parentRunId === 'string' && request.parentRunId.trim(),
114
+ 'e2b_command_parent_run_id_invalid');
115
+ invariant(Number.isSafeInteger(request.executionFence) && request.executionFence > 0, 'e2b_command_fence_required');
116
+ return { scope: copy(request.scope), runId: request.runId, turnId: request.turnId, buildId: request.buildId,
117
+ parentRunId: request.parentRunId, taskChainId: request.taskChainId, executionFence: request.executionFence };
118
+ }, backgroundRef: (before, taskId) => ({ taskId, sourceRunId: before.identity.runId, operationKey: before.operationKey }) });
119
+ }
120
+
121
+ export const DSH_E2B_COMMAND_TOOLS_CONTRACT = 'agentkit.dsh-e2b-command-tools/v1';
122
+ /** Share command semantics with Native, using real DSH ownership only. */
123
+ export function createDshE2BCommandTools(options = {}) {
124
+ return createDshTools(options, false);
125
+ }
126
+ export function createDshE2BCodeTools(options = {}) {
127
+ return createDshTools(options, true);
128
+ }
129
+ function createDshTools(options, codeOnly) {
130
+ const { agentId } = options;
131
+ invariant(typeof agentId === 'string' && agentId.trim(), 'e2b_command_agent_required');
132
+ return createCommandTools(options, { codeOnly, contract: codeOnly ? DSH_E2B_CODE_TOOLS_CONTRACT : DSH_E2B_COMMAND_TOOLS_CONTRACT, fields: { agentId },
133
+ identity(request) {
134
+ invariant(request.agentId === agentId && ['scope','runId','turnId','buildId','taskChainId','parentRunId','executionFence']
135
+ .every(key => request[key] === undefined), 'e2b_command_identity_required');
136
+ return { agentId };
137
+ }, backgroundRef: (before, taskId) => ({ taskId, agentId, sessionId: before.sessionId,
138
+ sourceCallId: before.callId, operationKey: before.operationKey }) });
139
+ }
140
+
141
+ function createCommandTools({ sessionId, owner, storeFactory,
142
+ authorize, assertAuthority, resolveOwnedCommand, artifacts, publishSnippet, maxOutputBytes = 24000,
143
+ allowInternetAccess = false, foregroundTimeoutSeconds = 300, backgroundTimeoutSeconds = 300 }, ownership) {
144
+ invariant(typeof sessionId === 'string' && !!sessionId.trim(), 'e2b_command_scope_required');
145
+ invariant(Number.isSafeInteger(maxOutputBytes) && maxOutputBytes >= 256, 'e2b_command_max_output_bytes_invalid');
146
+ invariant(owner && typeof owner.ensure === 'function' && typeof owner.inspect === 'function', 'e2b_command_owner_required');
147
+ invariant(typeof storeFactory === 'function', 'e2b_command_store_factory_required');
148
+ invariant(!ownership.codeOnly || typeof publishSnippet === 'function', 'e2b_code_publication_required');
149
+ invariant(typeof authorize === 'function', 'e2b_command_authorize_required');
150
+ invariant(typeof assertAuthority === 'function', 'e2b_command_assert_authority_required');
151
+ invariant(typeof resolveOwnedCommand === 'function', 'e2b_command_resolve_owned_required');
152
+ invariant(Number.isSafeInteger(backgroundTimeoutSeconds) && backgroundTimeoutSeconds > 0
153
+ && backgroundTimeoutSeconds <= 86400, 'e2b_command_background_limit_invalid');
154
+ const definitions = ownership.codeOnly ? e2bCodeToolDefinitions(foregroundTimeoutSeconds, ownership.fields.agentId ? 'sandbox_run_code' : 'run_code')
155
+ : e2bCommandToolDefinitions(foregroundTimeoutSeconds);
156
+ const formal = new Map(definitions.map(d => [d.name, copy(d)]));
157
+ let store = null;
158
+
159
+ function snapshot(request) {
160
+ invariant(request && request.call && typeof request.call.name === 'string' && typeof request.call.callId === 'string' && request.call.callId.trim(),
161
+ 'e2b_command_request_unbound');
162
+ invariant(typeof request.operationKey === 'string' && request.operationKey.trim(), 'e2b_command_operation_key_required');
163
+ const def = formal.get(request.call.name);
164
+ invariant(def, 'e2b_command_tool_unbound');
165
+ invariant(request.definition && canonical(request.definition) === canonical(def), 'e2b_command_definition_unbound');
166
+ invariant(request.signal instanceof AbortSignal, 'e2b_command_signal_unbound');
167
+ invariant(typeof request.sessionId === 'string' && request.sessionId === sessionId, 'e2b_command_session_unbound');
168
+ const identity = ownership.identity(request);
169
+ const { signal: _signal, ...body } = request;
170
+ return { body: canonical(body), signal: request.signal,
171
+ identity, sessionId: request.sessionId, operationKey: request.operationKey,
172
+ callId: request.call.callId };
173
+ }
174
+
175
+ function drifted(request, before) {
176
+ if (before.signal !== request.signal) return true;
177
+ const { signal: _signal, ...body } = request;
178
+ return before.body !== canonical(body);
179
+ }
180
+
181
+ function checkAuthority(request) {
182
+ const result = assertAuthority(request);
183
+ if (result === true) return true;
184
+ if (result && typeof result.then === 'function')
185
+ result.then(() => {}, () => {});
186
+ return false;
187
+ }
188
+
189
+ // The full original identity — NEVER truncated or dropped. This is the
190
+ // minimum that must fit in maxOutputBytes for any uncertain/error result
191
+ // to be representable. If it does not fit, the command is rejected before
192
+ // any side-effect.
193
+ function originLocator(before, sandboxId, taskId) {
194
+ return { ...copy(before.identity), sessionId: before.sessionId, operationKey: before.operationKey, callId: before.callId,
195
+ ...(sandboxId ? { sandbox_id: sandboxId } : {}),
196
+ ...(taskId ? { task_id: taskId } : {}) };
197
+ }
198
+
199
+ // Reserve complete ownership plus the largest validated remote identifiers
200
+ // and fixed receipt fields BEFORE any owner/command effect. A rejected call
201
+ // has no external locator to preserve; its full request remains in the intent.
202
+ function minimalUncertainBudget(before) {
203
+ const sample = { ok: false, error_type: 'e2b_command_evidence_incomplete',
204
+ evidence_incomplete: true, observed_result: 'output_limit',
205
+ ...originLocator(before, 's'.repeat(128), 'a'.repeat(64)) };
206
+ return Buffer.byteLength(canonical(sample)) + 512;
207
+ }
208
+
209
+ function uncertainResult(known, before, reason, sandboxId, taskId) {
210
+ const loc = originLocator(before, sandboxId ?? known?.content?.sandbox_id, taskId ?? known?.content?.task_id);
211
+ const code = typeof reason === 'string' && /^[a-z0-9_]{1,96}$/.test(reason)
212
+ ? reason : 'e2b_command_evidence_incomplete';
213
+ const content = { ok: false, error_type: code, evidence_incomplete: true,
214
+ observed_result: TERMINAL.has(known?.content?.status) ? known.content.status : null, ...loc };
215
+ const bgRef = known?.backgroundCommandRef;
216
+ return { status: 'uncertain', content, ...(bgRef ? { backgroundCommandRef: bgRef } : {}) };
217
+ }
218
+
219
+ // Enforce budget on shrinkable content fields only (command, stdout, stderr).
220
+ // Identity fields (operationKey, runId, scope, etc.) are NEVER truncated.
221
+ function enforceBudget(content) {
222
+ const keys = ['command', 'stdout', 'stderr', 'instruction', 'outcome_reason'];
223
+ for (let iter = 0; iter < 40; iter++) {
224
+ if (Buffer.byteLength(canonical(content)) <= maxOutputBytes) return true;
225
+ let largest = null, largestLen = 0;
226
+ for (const key of keys) {
227
+ const len = typeof content[key] === 'string' ? Buffer.byteLength(content[key]) : 0;
228
+ if (len > largestLen) { largest = key; largestLen = len; }
229
+ }
230
+ if (!largest || largestLen <= 1) { if (largest) content[largest] = ''; break; }
231
+ content[largest] = utf8Preview(content[largest], Math.floor(largestLen / 2));
232
+ }
233
+ return Buffer.byteLength(canonical(content)) <= maxOutputBytes;
234
+ }
235
+
236
+ // Every return is bounded. Admission reserves the complete fixed receipt;
237
+ // only presentation text may be shortened after dispatch.
238
+ function boundResult(result) {
239
+ if (Buffer.byteLength(canonical(result.content)) <= maxOutputBytes) return result;
240
+ const content = { ...result.content };
241
+ if (enforceBudget(content)) return { ...result, content };
242
+ invariant(false, 'e2b_command_result_budget_contract_violation');
243
+ }
244
+
245
+ async function budget(result, request, before, sandboxId, taskId) {
246
+ if (request.resultGovernance === 'runtime-artifacts/v1') return guard(request, before, true, result) ?? result;
247
+ const body = canonical(result.content);
248
+ if (Buffer.byteLength(body) <= maxOutputBytes) return result;
249
+ const guardResult = guard(request, before, true, result);
250
+ if (guardResult) return guardResult;
251
+ const content = { ...result.content };
252
+ if (typeof artifacts?.write === 'function') {
253
+ try {
254
+ const ref = await abortable(artifacts.write({ ...request, operationKey: `${request.operationKey}:command-output`,
255
+ content: body, mediaType: 'application/json', metadata: { toolName: request.call.name, sessionId } }), before.signal);
256
+ const guardResult2 = guard(request, before, true, result);
257
+ if (guardResult2) return guardResult2;
258
+ content.output_budget = { truncated: true, artifact_uri: ref.uri, size_bytes: ref.sizeBytes };
259
+ if (enforceBudget(content)) return { ...result, content, artifactRefs: [...result.artifactRefs ?? [], ref] };
260
+ content.output_budget = { truncated: true };
261
+ if (enforceBudget(content)) return { ...result, content, artifactRefs: [...result.artifactRefs ?? [], ref] };
262
+ } catch {
263
+ const guardResult3 = guard(request, before, true, result);
264
+ if (guardResult3) return guardResult3;
265
+ }
266
+ }
267
+ content.output_budget = { truncated: true };
268
+ if (enforceBudget(content)) return { ...result, content };
269
+ return boundResult(result);
270
+ }
271
+
272
+ function guard(request, before, dispatched, known) {
273
+ before.signal.throwIfAborted();
274
+ if (drifted(request, before)) return dispatched
275
+ ? uncertainResult(known, before, 'e2b_command_request_drifted')
276
+ : { status: 'error', content: { code: 'e2b_command_request_drifted', executed: false } };
277
+ if (!checkAuthority(request)) return dispatched
278
+ ? uncertainResult(known, before, 'e2b_command_authority_lost')
279
+ : { status: 'error', content: { error_type: 'e2b_command_authority_unproven', executed: false } };
280
+ // The synchronous authority callback is also an external boundary.
281
+ before.signal.throwIfAborted();
282
+ if (drifted(request, before)) return dispatched
283
+ ? uncertainResult(known, before, 'e2b_command_request_drifted')
284
+ : { status: 'error', content: { code: 'e2b_command_request_drifted', executed: false } };
285
+ return null;
286
+ }
287
+
288
+ async function execute(request) {
289
+ let dispatched = false, known, sandboxId, taskId;
290
+ let before;
291
+ try {
292
+ before = snapshot(request);
293
+ const minBudget = minimalUncertainBudget(before);
294
+ if (minBudget > maxOutputBytes) return errorResult('e2b_command_budget_below_minimum_identity',
295
+ { executed: false, required_bytes: minBudget, max_output_bytes: maxOutputBytes });
296
+ request.signal.throwIfAborted();
297
+ const rejection = toolInputRejection(formal.get(request.call.name), request.call);
298
+ if (rejection) return Buffer.byteLength(canonical(rejection)) <= maxOutputBytes
299
+ ? { status: 'error', content: rejection } : errorResult('e2b_command_arguments_invalid', { executed: false });
300
+ request.signal.throwIfAborted();
301
+
302
+ const decision = await abortable(authorize(request), before.signal);
303
+ const guardResult = guard(request, before, false, null);
304
+ if (guardResult) return guardResult;
305
+ if (decision !== 'allow') return decision?.status === 'approval_required' && typeof decision.interactionId === 'string'
306
+ ? decision : errorResult('policy_denied');
307
+
308
+ if (request.call.name === 'sandbox_status') {
309
+ const guardResult = guard(request, before, false, null);
310
+ if (guardResult) return guardResult;
311
+ const inspect = syncValue(owner.inspect());
312
+ invariant(!inspect || (inspect.sandboxId == null || typeof inspect.sandboxId === 'string' && /^[A-Za-z0-9_-]{1,128}$/.test(inspect.sandboxId))
313
+ && ['absent','creating','ready','closing','closed','unknown'].includes(inspect.phase), 'e2b_owner_status_invalid');
314
+ const afterInspect = guard(request, before, false, null); if (afterInspect) return afterInspect;
315
+ return { status: 'ok', content: { ok: true, backend: 'e2b', enabled: true, isolated: true,
316
+ sandbox_id: inspect?.sandboxId ?? null, sandbox_phase: inspect?.phase ?? 'absent',
317
+ allow_internet_access: allowInternetAccess,
318
+ boundary: 'Remote E2B sandbox. The Host filesystem is not shared.',
319
+ contracts: [ownership.contract] } };
320
+ }
321
+
322
+ if (request.call.name === 'read_command_output' || request.call.name === 'stop_command') {
323
+ const args = request.call.arguments;
324
+ const guardResult = guard(request, before, false, null);
325
+ if (guardResult) return guardResult;
326
+ const owned = syncValue(resolveOwnedCommand(request, args.task_id));
327
+ invariant(owned?.backend === 'e2b' && owned.ref?.taskId === args.task_id, 'e2b_command_backend_mismatch');
328
+ const afterResolve = guard(request, before, false, null); if (afterResolve) return afterResolve;
329
+ taskId = args.task_id;
330
+ if (!store) store = syncValue(storeFactory({ ...copy(ownership.fields), sessionId }));
331
+ invariant(typeof store.commandId === 'function'
332
+ && syncValue(store.commandId(owned.ref.operationKey)) === taskId, 'e2b_command_owned_operation_mismatch');
333
+ const handle = syncValue(store.connect(owned.ref.taskId));
334
+ const afterConnect = guard(request, before, false, null); if (afterConnect) return afterConnect;
335
+ known = { content: { task_id: args.task_id, ...originLocator(before, undefined, taskId) } };
336
+ if (request.call.name === 'stop_command') {
337
+ dispatched = true;
338
+ const cancelOutput = syncValue(handle.requestCancel());
339
+ const guardResult = guard(request, before, dispatched, known);
340
+ if (guardResult) return guardResult;
341
+ const uncertain = cancelOutput.status === 'unknown' || cancelOutput.evidenceIncomplete;
342
+ known = { status: uncertain ? 'uncertain' : 'ok', content: { ok: !uncertain, task_id: args.task_id,
343
+ ...commandOutput(cancelOutput), ...originLocator(before, undefined, taskId) } };
344
+ } else {
345
+ const until = performance.now() + (args.wait_seconds ?? 0) * 1000;
346
+ let interval = 50;
347
+ while (!TERMINAL.has(syncValue(handle.readOutput()).status) && performance.now() < until) {
348
+ const guardResult = guard(request, before, false, known);
349
+ if (guardResult) return guardResult;
350
+ await delay(Math.min(interval, Math.max(0, until - performance.now())));
351
+ interval = Math.min(1000, interval * 2);
352
+ }
353
+ const guardResult = guard(request, before, false, known);
354
+ if (guardResult) return guardResult;
355
+ const output = handle.readOutput({ stdoutCursor: args.stdout_cursor ?? 0,
356
+ stderrCursor: args.stderr_cursor ?? 0, maxBytes: args.max_bytes ?? 65536 });
357
+ const uncertain = output.status === 'unknown' || output.evidenceIncomplete;
358
+ known = { status: uncertain ? 'uncertain' : 'ok', content: { ok: !uncertain, task_id: args.task_id,
359
+ ...commandOutput(output), ...originLocator(before, undefined, taskId) } };
360
+ }
361
+ const afterRead = guard(request, before, dispatched, known); if (afterRead) return afterRead;
362
+ return await budget(known, request, before, undefined, taskId);
363
+ }
364
+
365
+ // The original durable tool intent surrounds both source publication
366
+ // and its supervised execution. Never put source in a shell argument:
367
+ // even a valid large snippet can exceed the remote OS argv limit.
368
+ const args = request.call.arguments;
369
+ const snippet = ownership.codeOnly ? snippetCommand(args, before) : null;
370
+ if (ownership.codeOnly && !snippet) return errorResult('unsupported_language', { executed: false });
371
+ const command = snippet?.launch ?? args.command.trim();
372
+ if (!command) return errorResult('command_required');
373
+ if (!args.background && args.background_timeout != null) return errorResult('background_timeout_requires_background');
374
+
375
+ known = { content: { ...originLocator(before) } };
376
+ const ownerRequest = { ...request, definition: formal.get(request.call.name) };
377
+ const guardResult0 = guard(request, before, false, known);
378
+ if (guardResult0) return guardResult0;
379
+ let ensured;
380
+ dispatched = true;
381
+ try { ensured = await abortable(owner.ensure(ownerRequest), before.signal); }
382
+ catch (error) {
383
+ if (error?.uncertain) return uncertainResult(known, before, 'e2b_sandbox_outcome_unknown');
384
+ throw error;
385
+ }
386
+ invariant(typeof ensured?.sandboxId === 'string' && /^[A-Za-z0-9_-]{1,128}$/.test(ensured.sandboxId), 'e2b_sandbox_identity_invalid');
387
+ sandboxId = ensured.sandboxId;
388
+ known = { content: { ...originLocator(before, sandboxId) } };
389
+ const guardResult1 = guard(request, before, dispatched, known);
390
+ if (guardResult1) return guardResult1;
391
+
392
+ if (!store) store = syncValue(storeFactory({ ...copy(ownership.fields), sessionId, sandboxId }));
393
+ const suppliedTimeout = args.background ? (args.background_timeout ?? backgroundTimeoutSeconds)
394
+ : (args.timeout ?? foregroundTimeoutSeconds);
395
+ const maximum = args.background ? 86400 : foregroundTimeoutSeconds;
396
+ const timeoutSeconds = Number(suppliedTimeout > maximum ? maximum : suppliedTimeout);
397
+ const afterFactory = guard(request, before, dispatched, known); if (afterFactory) return afterFactory;
398
+ if (typeof store.commandId === 'function') {
399
+ taskId = syncValue(store.commandId(before.operationKey));
400
+ invariant(typeof taskId === 'string' && /^[a-f0-9]{64}$/.test(taskId), 'e2b_command_identity_invalid');
401
+ known = { content: { ...originLocator(before, sandboxId, taskId) } };
402
+ const afterId = guard(request, before, dispatched, known); if (afterId) return afterId;
403
+ }
404
+ if (snippet) {
405
+ const assertCurrent = () => { invariant(!guard(request, before, dispatched, known), 'e2b_code_authority_lost'); return true; };
406
+ await abortable(publishSnippet({ request, sandboxId, path: snippet.path, source: args.code, assertCurrent }), before.signal);
407
+ const afterPublish = guard(request, before, dispatched, known); if (afterPublish) return afterPublish;
408
+ }
409
+ const handle = await abortable(store.start({ operationKey: before.operationKey, command,
410
+ cwd: args.cwd ?? null, env: args.env ?? null, timeoutSeconds,
411
+ assertCurrent: () => {
412
+ const rejected = guard(request, before, dispatched, known);
413
+ invariant(!rejected, 'e2b_command_authority_lost'); return true;
414
+ } }), before.signal);
415
+ invariant(typeof handle?.commandId === 'string' && /^[a-f0-9]{64}$/.test(handle.commandId), 'e2b_command_identity_invalid');
416
+ invariant(taskId === undefined || taskId === handle.commandId, 'e2b_command_identity_changed');
417
+ taskId = handle.commandId;
418
+ known = { content: { ...originLocator(before, sandboxId, taskId) },
419
+ ...(args.background ? { backgroundCommandRef: ownership.backgroundRef(before, taskId) } : {}) };
420
+ const guardResult2 = guard(request, before, dispatched, known);
421
+ if (guardResult2) return guardResult2;
422
+
423
+ if (args.background) {
424
+ const observed = syncValue(handle.readOutput());
425
+ const uncertain = observed.status === 'unknown' || observed.evidenceIncomplete;
426
+ known = { status: uncertain ? 'uncertain' : 'ok',
427
+ content: { ok: !uncertain, backend: 'sandbox/e2b', sandbox_id: sandboxId,
428
+ task_id: taskId, ...commandOutput(observed), ...originLocator(before, sandboxId, taskId),
429
+ process_timeout_seconds: timeoutSeconds },
430
+ backgroundCommandRef: ownership.backgroundRef(before, taskId) };
431
+ } else {
432
+ const until = performance.now() + timeoutSeconds * 1000 + 15000;
433
+ let output;
434
+ while (!TERMINAL.has((output = handle.readOutput()).status) && performance.now() < until) {
435
+ const guardResult = guard(request, before, dispatched, known);
436
+ if (guardResult) return guardResult;
437
+ await delay(50);
438
+ }
439
+ const guardResult3 = guard(request, before, dispatched, known);
440
+ if (guardResult3) return guardResult3;
441
+ // The model sees a bounded preview, but its artifact must contain all
442
+ // retained foreground output, not just the first 64 KiB cursor window.
443
+ const stdout = [], stderr = []; let stdoutCursor = 0, stderrCursor = 0, bytes = 0;
444
+ for (;;) {
445
+ const rejected = guard(request, before, dispatched, known); if (rejected) return rejected;
446
+ output = syncValue(handle.readOutput({ stdoutCursor, stderrCursor, maxBytes: 65536 }));
447
+ invariant(typeof output.stdout === 'string' && typeof output.stderr === 'string', 'e2b_command_output_invalid');
448
+ bytes += Buffer.byteLength(output.stdout) + Buffer.byteLength(output.stderr);
449
+ invariant(bytes <= 16 * 1024 * 1024, 'e2b_command_retained_output_too_large');
450
+ stdout.push(output.stdout); stderr.push(output.stderr);
451
+ if (!output.outputMayBeTruncated) break;
452
+ invariant(Number.isSafeInteger(output.stdoutCursor) && output.stdoutCursor >= stdoutCursor
453
+ && Number.isSafeInteger(output.stderrCursor) && output.stderrCursor >= stderrCursor
454
+ && (output.stdoutCursor > stdoutCursor || output.stderrCursor > stderrCursor), 'e2b_command_output_cursor_stalled');
455
+ stdoutCursor = output.stdoutCursor; stderrCursor = output.stderrCursor;
456
+ }
457
+ output = { ...output, stdout: stdout.join(''), stderr: stderr.join('') };
458
+ const uncertain = output.status === 'unknown' || output.evidenceIncomplete
459
+ || !TERMINAL.has(output.status)
460
+ || (['timed_out', 'canceled'].includes(output.status) && output.exitCode === null);
461
+ known = { status: uncertain ? 'uncertain' : 'ok',
462
+ content: { ok: !uncertain, status: output.status, backend: 'sandbox/e2b', sandbox_id: sandboxId, command,
463
+ ...(snippet ? { execution_model: 'snippet_runner', language: snippet.language, path: snippet.path, command: snippet.command } : {}),
464
+ task_id: taskId, ...originLocator(before, sandboxId, taskId),
465
+ stdout: output.stdout, stderr: output.stderr,
466
+ exit_code: uncertain ? null : output.exitCode,
467
+ observed_exit_code: uncertain ? output.exitCode : null,
468
+ evidence_incomplete: uncertain,
469
+ ...(output.outcomeReason ? { outcome_reason: output.outcomeReason } : {}) } };
470
+ }
471
+ const afterOutput = guard(request, before, dispatched, known); if (afterOutput) return afterOutput;
472
+ return await budget(known, request, before, sandboxId, taskId);
473
+ } catch (error) {
474
+ if (!before) return errorResult('e2b_command_request_invalid', { executed: false });
475
+ const originalAborted = before.signal.aborted;
476
+ return dispatched
477
+ ? uncertainResult(known, before, originalAborted ? 'e2b_command_aborted' : (error?.code ?? 'e2b_command_evidence_incomplete'), sandboxId, taskId)
478
+ : errorResult(originalAborted ? 'canceled' : 'e2b_command_error', { executed: false });
479
+ }
480
+ }
481
+
482
+ return Object.freeze({ definitions: copy(definitions), async execute(request) {
483
+ const result = await execute(request);
484
+ return result.content === undefined || request.resultGovernance === 'runtime-artifacts/v1' ? result : boundResult(result);
485
+ }, contract: ownership.contract });
486
+ }