@namzu/sdk 31.1.0 → 33.0.0
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.
- package/CHANGELOG.md +188 -0
- package/dist/agents/ReactiveAgent.d.ts.map +1 -1
- package/dist/agents/ReactiveAgent.js +4 -0
- package/dist/agents/ReactiveAgent.js.map +1 -1
- package/dist/agents/SupervisorAgent.d.ts.map +1 -1
- package/dist/agents/SupervisorAgent.js +4 -0
- package/dist/agents/SupervisorAgent.js.map +1 -1
- package/dist/agents/runAgent.d.ts +4 -0
- package/dist/agents/runAgent.d.ts.map +1 -1
- package/dist/agents/runAgent.js +4 -0
- package/dist/agents/runAgent.js.map +1 -1
- package/dist/authorization/gate.d.ts +1 -1
- package/dist/authorization/gate.js +1 -1
- package/dist/connector/index.d.ts +1 -1
- package/dist/connector/index.d.ts.map +1 -1
- package/dist/connector/index.js +1 -1
- package/dist/connector/index.js.map +1 -1
- package/dist/connector/mcp/adapter.d.ts.map +1 -1
- package/dist/connector/mcp/adapter.js +71 -16
- package/dist/connector/mcp/adapter.js.map +1 -1
- package/dist/connector/mcp/client.d.ts.map +1 -1
- package/dist/connector/mcp/client.js +3 -2
- package/dist/connector/mcp/client.js.map +1 -1
- package/dist/connector/mcp/http-redirect.d.ts +17 -0
- package/dist/connector/mcp/http-redirect.d.ts.map +1 -0
- package/dist/connector/mcp/http-redirect.js +31 -0
- package/dist/connector/mcp/http-redirect.js.map +1 -0
- package/dist/connector/mcp/http-sse.d.ts.map +1 -1
- package/dist/connector/mcp/http-sse.js +5 -0
- package/dist/connector/mcp/http-sse.js.map +1 -1
- package/dist/connector/mcp/image-admission.d.ts +16 -0
- package/dist/connector/mcp/image-admission.d.ts.map +1 -0
- package/dist/connector/mcp/image-admission.js +288 -0
- package/dist/connector/mcp/image-admission.js.map +1 -0
- package/dist/connector/mcp/stdio.d.ts +13 -0
- package/dist/connector/mcp/stdio.d.ts.map +1 -1
- package/dist/connector/mcp/stdio.js +66 -23
- package/dist/connector/mcp/stdio.js.map +1 -1
- package/dist/connector/mcp/streamable-http.d.ts.map +1 -1
- package/dist/connector/mcp/streamable-http.js +3 -0
- package/dist/connector/mcp/streamable-http.js.map +1 -1
- package/dist/constants/tools/index.js +1 -1
- package/dist/constants/tools/index.js.map +1 -1
- package/dist/directory/derive-supervisor.d.ts.map +1 -1
- package/dist/directory/derive-supervisor.js +5 -0
- package/dist/directory/derive-supervisor.js.map +1 -1
- package/dist/directory/derive.d.ts.map +1 -1
- package/dist/directory/derive.js +5 -0
- package/dist/directory/derive.js.map +1 -1
- package/dist/directory/load.d.ts.map +1 -1
- package/dist/directory/load.js +1 -0
- package/dist/directory/load.js.map +1 -1
- package/dist/directory/types.d.ts +2 -0
- package/dist/directory/types.d.ts.map +1 -1
- package/dist/execution/base.d.ts +13 -0
- package/dist/execution/base.d.ts.map +1 -1
- package/dist/execution/base.js +103 -8
- package/dist/execution/base.js.map +1 -1
- package/dist/execution/code-runtime/types.d.ts +11 -1
- package/dist/execution/code-runtime/types.d.ts.map +1 -1
- package/dist/execution/code-runtime/types.js.map +1 -1
- package/dist/execution/code-runtime/worker.d.ts.map +1 -1
- package/dist/execution/code-runtime/worker.js +67 -9
- package/dist/execution/code-runtime/worker.js.map +1 -1
- package/dist/execution/errors.d.ts +12 -0
- package/dist/execution/errors.d.ts.map +1 -0
- package/dist/execution/errors.js +21 -0
- package/dist/execution/errors.js.map +1 -0
- package/dist/execution/factory.d.ts.map +1 -1
- package/dist/execution/factory.js +1 -0
- package/dist/execution/factory.js.map +1 -1
- package/dist/execution/hybrid.d.ts +5 -0
- package/dist/execution/hybrid.d.ts.map +1 -1
- package/dist/execution/hybrid.js +36 -16
- package/dist/execution/hybrid.js.map +1 -1
- package/dist/execution/index.d.ts +1 -0
- package/dist/execution/index.d.ts.map +1 -1
- package/dist/execution/index.js +1 -0
- package/dist/execution/index.js.map +1 -1
- package/dist/execution/local.d.ts +13 -0
- package/dist/execution/local.d.ts.map +1 -1
- package/dist/execution/local.js +145 -19
- package/dist/execution/local.js.map +1 -1
- package/dist/execution/output.d.ts +27 -0
- package/dist/execution/output.d.ts.map +1 -0
- package/dist/execution/output.js +105 -0
- package/dist/execution/output.js.map +1 -0
- package/dist/execution/remote.d.ts +26 -2
- package/dist/execution/remote.d.ts.map +1 -1
- package/dist/execution/remote.js +86 -15
- package/dist/execution/remote.js.map +1 -1
- package/dist/manager/agent/lifecycle.d.ts.map +1 -1
- package/dist/manager/agent/lifecycle.js +1 -0
- package/dist/manager/agent/lifecycle.js.map +1 -1
- package/dist/plugin/lifecycle.d.ts.map +1 -1
- package/dist/plugin/lifecycle.js +9 -3
- package/dist/plugin/lifecycle.js.map +1 -1
- package/dist/process/kill-tree.d.ts +11 -13
- package/dist/process/kill-tree.d.ts.map +1 -1
- package/dist/process/kill-tree.js +11 -13
- package/dist/process/kill-tree.js.map +1 -1
- package/dist/provider/errors.d.ts +1 -0
- package/dist/provider/errors.d.ts.map +1 -1
- package/dist/provider/errors.js +39 -1
- package/dist/provider/errors.js.map +1 -1
- package/dist/provider/fallback.d.ts.map +1 -1
- package/dist/provider/fallback.js +31 -0
- package/dist/provider/fallback.js.map +1 -1
- package/dist/provider/idle-timeout.d.ts.map +1 -1
- package/dist/provider/idle-timeout.js +5 -0
- package/dist/provider/idle-timeout.js.map +1 -1
- package/dist/provider/retry.d.ts.map +1 -1
- package/dist/provider/retry.js +5 -0
- package/dist/provider/retry.js.map +1 -1
- package/dist/public-runtime.d.ts +7 -5
- package/dist/public-runtime.d.ts.map +1 -1
- package/dist/public-runtime.js +9 -4
- package/dist/public-runtime.js.map +1 -1
- package/dist/public-types.d.ts +2 -1
- package/dist/public-types.d.ts.map +1 -1
- package/dist/registry/tool/execute.d.ts +7 -1
- package/dist/registry/tool/execute.d.ts.map +1 -1
- package/dist/registry/tool/execute.js +201 -54
- package/dist/registry/tool/execute.js.map +1 -1
- package/dist/run/command-gate.d.ts.map +1 -1
- package/dist/run/command-gate.js +11 -0
- package/dist/run/command-gate.js.map +1 -1
- package/dist/run/reporter.d.ts.map +1 -1
- package/dist/run/reporter.js +6 -1
- package/dist/run/reporter.js.map +1 -1
- package/dist/run/workspace-fingerprint.d.ts +4 -4
- package/dist/run/workspace-fingerprint.d.ts.map +1 -1
- package/dist/run/workspace-fingerprint.js +6 -4
- package/dist/run/workspace-fingerprint.js.map +1 -1
- package/dist/runtime/bidi/index.d.ts +1 -1
- package/dist/runtime/bidi/index.d.ts.map +1 -1
- package/dist/runtime/bidi/index.js +1 -1
- package/dist/runtime/bidi/index.js.map +1 -1
- package/dist/runtime/bidi/session.d.ts +19 -0
- package/dist/runtime/bidi/session.d.ts.map +1 -1
- package/dist/runtime/bidi/session.js +150 -26
- package/dist/runtime/bidi/session.js.map +1 -1
- package/dist/runtime/query/executor.d.ts +43 -1
- package/dist/runtime/query/executor.d.ts.map +1 -1
- package/dist/runtime/query/executor.js +824 -174
- package/dist/runtime/query/executor.js.map +1 -1
- package/dist/runtime/query/index.d.ts +5 -0
- package/dist/runtime/query/index.d.ts.map +1 -1
- package/dist/runtime/query/index.js +47 -4
- package/dist/runtime/query/index.js.map +1 -1
- package/dist/runtime/query/iteration/index.d.ts +1 -0
- package/dist/runtime/query/iteration/index.d.ts.map +1 -1
- package/dist/runtime/query/iteration/index.js +34 -14
- package/dist/runtime/query/iteration/index.js.map +1 -1
- package/dist/runtime/query/iteration/phases/advisory.js +2 -2
- package/dist/runtime/query/iteration/phases/advisory.js.map +1 -1
- package/dist/runtime/query/iteration/phases/tool-review.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/tool-review.js +84 -22
- package/dist/runtime/query/iteration/phases/tool-review.js.map +1 -1
- package/dist/runtime/query/iteration/provider-rejected-image.d.ts +13 -0
- package/dist/runtime/query/iteration/provider-rejected-image.d.ts.map +1 -0
- package/dist/runtime/query/iteration/provider-rejected-image.js +91 -0
- package/dist/runtime/query/iteration/provider-rejected-image.js.map +1 -0
- package/dist/runtime/query/iteration/stream-turn.d.ts +4 -1
- package/dist/runtime/query/iteration/stream-turn.d.ts.map +1 -1
- package/dist/runtime/query/iteration/stream-turn.js +7 -3
- package/dist/runtime/query/iteration/stream-turn.js.map +1 -1
- package/dist/runtime/query/request-rich-content.d.ts +13 -0
- package/dist/runtime/query/request-rich-content.d.ts.map +1 -1
- package/dist/runtime/query/request-rich-content.js +173 -17
- package/dist/runtime/query/request-rich-content.js.map +1 -1
- package/dist/runtime/query/result.d.ts.map +1 -1
- package/dist/runtime/query/result.js +1 -0
- package/dist/runtime/query/result.js.map +1 -1
- package/dist/runtime/query/resume-pending.d.ts +5 -1
- package/dist/runtime/query/resume-pending.d.ts.map +1 -1
- package/dist/runtime/query/resume-pending.js +66 -1
- package/dist/runtime/query/resume-pending.js.map +1 -1
- package/dist/runtime/query/tool-output-budget.d.ts.map +1 -1
- package/dist/runtime/query/tool-output-budget.js +45 -16
- package/dist/runtime/query/tool-output-budget.js.map +1 -1
- package/dist/runtime/query/tooling.d.ts +6 -0
- package/dist/runtime/query/tooling.d.ts.map +1 -1
- package/dist/runtime/query/tooling.js +4 -0
- package/dist/runtime/query/tooling.js.map +1 -1
- package/dist/sandbox/provider/local.d.ts.map +1 -1
- package/dist/sandbox/provider/local.js +193 -41
- package/dist/sandbox/provider/local.js.map +1 -1
- package/dist/scheduler/delegating.d.ts +2 -1
- package/dist/scheduler/delegating.d.ts.map +1 -1
- package/dist/scheduler/delegating.js +6 -5
- package/dist/scheduler/delegating.js.map +1 -1
- package/dist/scheduler/local.d.ts +2 -1
- package/dist/scheduler/local.d.ts.map +1 -1
- package/dist/scheduler/local.js +2 -2
- package/dist/scheduler/local.js.map +1 -1
- package/dist/session/workspace/driver.d.ts +12 -4
- package/dist/session/workspace/driver.d.ts.map +1 -1
- package/dist/session/workspace/git-worktree.d.ts +17 -3
- package/dist/session/workspace/git-worktree.d.ts.map +1 -1
- package/dist/session/workspace/git-worktree.js +153 -34
- package/dist/session/workspace/git-worktree.js.map +1 -1
- package/dist/skills/registry.d.ts +15 -0
- package/dist/skills/registry.d.ts.map +1 -1
- package/dist/skills/registry.js +33 -0
- package/dist/skills/registry.js.map +1 -1
- package/dist/store/attachment/index.d.ts +24 -2
- package/dist/store/attachment/index.d.ts.map +1 -1
- package/dist/store/attachment/index.js +52 -5
- package/dist/store/attachment/index.js.map +1 -1
- package/dist/tools/builtins/computer-use.d.ts.map +1 -1
- package/dist/tools/builtins/computer-use.js +39 -2
- package/dist/tools/builtins/computer-use.js.map +1 -1
- package/dist/tools/builtins/lsp.d.ts +1 -1
- package/dist/tools/builtins/run-code.d.ts.map +1 -1
- package/dist/tools/builtins/run-code.js +24 -16
- package/dist/tools/builtins/run-code.js.map +1 -1
- package/dist/tools/builtins/skill.d.ts +2 -1
- package/dist/tools/builtins/skill.d.ts.map +1 -1
- package/dist/tools/builtins/skill.js +250 -6
- package/dist/tools/builtins/skill.js.map +1 -1
- package/dist/tools/coordinator/agent.d.ts.map +1 -1
- package/dist/tools/coordinator/agent.js +100 -30
- package/dist/tools/coordinator/agent.js.map +1 -1
- package/dist/types/agent/base.d.ts +4 -0
- package/dist/types/agent/base.d.ts.map +1 -1
- package/dist/types/agent/factory.d.ts +1 -0
- package/dist/types/agent/factory.d.ts.map +1 -1
- package/dist/types/agent/manager.d.ts +1 -1
- package/dist/types/agent/manager.d.ts.map +1 -1
- package/dist/types/agent/scheduler.d.ts +10 -1
- package/dist/types/agent/scheduler.d.ts.map +1 -1
- package/dist/types/authorization/index.d.ts +12 -12
- package/dist/types/bidi/index.d.ts +19 -2
- package/dist/types/bidi/index.d.ts.map +1 -1
- package/dist/types/computer-use/index.d.ts +18 -0
- package/dist/types/computer-use/index.d.ts.map +1 -1
- package/dist/types/connector/execution-context.d.ts +3 -1
- package/dist/types/connector/execution-context.d.ts.map +1 -1
- package/dist/types/execution/index.d.ts +43 -1
- package/dist/types/execution/index.d.ts.map +1 -1
- package/dist/types/hitl/index.d.ts +11 -0
- package/dist/types/hitl/index.d.ts.map +1 -1
- package/dist/types/hitl/index.js.map +1 -1
- package/dist/types/message/index.d.ts +31 -1
- package/dist/types/message/index.d.ts.map +1 -1
- package/dist/types/message/index.js +43 -0
- package/dist/types/message/index.js.map +1 -1
- package/dist/types/plugin/index.d.ts +14 -1
- package/dist/types/plugin/index.d.ts.map +1 -1
- package/dist/types/plugin/index.js +1 -0
- package/dist/types/plugin/index.js.map +1 -1
- package/dist/types/provider/error.d.ts +4 -1
- package/dist/types/provider/error.d.ts.map +1 -1
- package/dist/types/provider/interface.d.ts +14 -0
- package/dist/types/provider/interface.d.ts.map +1 -1
- package/dist/types/run/events.d.ts +10 -2
- package/dist/types/run/events.d.ts.map +1 -1
- package/dist/types/run/events.js.map +1 -1
- package/dist/types/sandbox/index.d.ts +15 -10
- package/dist/types/sandbox/index.d.ts.map +1 -1
- package/dist/types/sandbox/index.js.map +1 -1
- package/dist/types/tool/index.d.ts +129 -12
- package/dist/types/tool/index.d.ts.map +1 -1
- package/dist/types/tool/index.js.map +1 -1
- package/dist/types/workspace/ref.d.ts +5 -0
- package/dist/types/workspace/ref.d.ts.map +1 -1
- package/dist/utils/abort.d.ts +8 -0
- package/dist/utils/abort.d.ts.map +1 -1
- package/dist/utils/abort.js +16 -0
- package/dist/utils/abort.js.map +1 -1
- package/package.json +4 -4
- package/src/agents/ReactiveAgent.ts +4 -0
- package/src/agents/SupervisorAgent.ts +4 -0
- package/src/agents/runAgent.ts +8 -0
- package/src/authorization/gate.ts +1 -1
- package/src/connector/index.ts +2 -0
- package/src/connector/mcp/adapter.ts +82 -21
- package/src/connector/mcp/client.ts +2 -1
- package/src/connector/mcp/http-redirect.ts +32 -0
- package/src/connector/mcp/http-sse.ts +5 -0
- package/src/connector/mcp/image-admission.ts +272 -0
- package/src/connector/mcp/stdio.ts +63 -21
- package/src/connector/mcp/streamable-http.ts +3 -0
- package/src/constants/tools/index.ts +1 -1
- package/src/directory/derive-supervisor.ts +5 -0
- package/src/directory/derive.ts +5 -0
- package/src/directory/load.ts +1 -0
- package/src/directory/types.ts +2 -0
- package/src/execution/base.ts +124 -7
- package/src/execution/code-runtime/types.ts +15 -1
- package/src/execution/code-runtime/worker.ts +72 -9
- package/src/execution/errors.ts +24 -0
- package/src/execution/factory.ts +1 -0
- package/src/execution/hybrid.ts +47 -16
- package/src/execution/index.ts +1 -0
- package/src/execution/local.ts +164 -19
- package/src/execution/output.ts +104 -0
- package/src/execution/remote.ts +122 -17
- package/src/manager/agent/lifecycle.ts +1 -0
- package/src/plugin/lifecycle.ts +9 -3
- package/src/process/kill-tree.ts +11 -13
- package/src/provider/errors.ts +40 -1
- package/src/provider/fallback.ts +39 -0
- package/src/provider/idle-timeout.ts +8 -0
- package/src/provider/retry.ts +8 -0
- package/src/public-runtime.ts +23 -2
- package/src/public-types.ts +11 -0
- package/src/registry/tool/execute.ts +230 -64
- package/src/run/command-gate.ts +12 -0
- package/src/run/reporter.ts +7 -1
- package/src/run/workspace-fingerprint.ts +5 -4
- package/src/runtime/bidi/index.ts +1 -1
- package/src/runtime/bidi/session.ts +177 -28
- package/src/runtime/query/executor.ts +987 -172
- package/src/runtime/query/index.ts +59 -6
- package/src/runtime/query/iteration/index.ts +69 -29
- package/src/runtime/query/iteration/phases/advisory.ts +2 -2
- package/src/runtime/query/iteration/phases/tool-review.ts +87 -23
- package/src/runtime/query/iteration/provider-rejected-image.ts +106 -0
- package/src/runtime/query/iteration/stream-turn.ts +12 -2
- package/src/runtime/query/request-rich-content.ts +213 -15
- package/src/runtime/query/result.ts +1 -0
- package/src/runtime/query/resume-pending.ts +83 -1
- package/src/runtime/query/tool-output-budget.ts +52 -17
- package/src/runtime/query/tooling.ts +10 -0
- package/src/sandbox/provider/local.ts +213 -45
- package/src/scheduler/delegating.ts +6 -5
- package/src/scheduler/local.ts +3 -2
- package/src/session/workspace/driver.ts +12 -4
- package/src/session/workspace/git-worktree.ts +173 -34
- package/src/skills/registry.ts +47 -0
- package/src/store/attachment/index.ts +100 -15
- package/src/tools/builtins/computer-use.ts +45 -2
- package/src/tools/builtins/run-code.ts +24 -16
- package/src/tools/builtins/skill.ts +325 -7
- package/src/tools/coordinator/agent.ts +108 -33
- package/src/types/agent/base.ts +4 -0
- package/src/types/agent/factory.ts +1 -0
- package/src/types/agent/manager.ts +1 -1
- package/src/types/agent/scheduler.ts +10 -1
- package/src/types/bidi/index.ts +19 -2
- package/src/types/computer-use/index.ts +19 -0
- package/src/types/connector/execution-context.ts +3 -0
- package/src/types/execution/index.ts +46 -1
- package/src/types/hitl/index.ts +11 -0
- package/src/types/message/index.ts +78 -1
- package/src/types/plugin/index.ts +15 -0
- package/src/types/provider/error.ts +4 -1
- package/src/types/provider/interface.ts +18 -0
- package/src/types/run/events.ts +18 -4
- package/src/types/sandbox/index.ts +15 -10
- package/src/types/tool/index.ts +159 -15
- package/src/types/workspace/ref.ts +5 -0
- package/src/utils/abort.ts +18 -0
package/src/execution/base.ts
CHANGED
|
@@ -12,6 +12,21 @@ export interface BaseExecutionEvent {
|
|
|
12
12
|
|
|
13
13
|
export type ExecutionEventListener = (event: BaseExecutionEvent) => void
|
|
14
14
|
|
|
15
|
+
type ExecutionLifecycleState =
|
|
16
|
+
| 'idle'
|
|
17
|
+
| 'initializing'
|
|
18
|
+
| 'ready'
|
|
19
|
+
| 'tearing-down'
|
|
20
|
+
| 'teardown-failed'
|
|
21
|
+
| 'torn-down'
|
|
22
|
+
|
|
23
|
+
class InitializationSupersededError extends Error {
|
|
24
|
+
constructor(contextId: string) {
|
|
25
|
+
super(`Execution context "${contextId}" initialization was superseded by teardown`)
|
|
26
|
+
this.name = 'InitializationSupersededError'
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
15
30
|
export abstract class BaseExecutionContext implements ExecutionContextLifecycle {
|
|
16
31
|
abstract readonly id: string
|
|
17
32
|
abstract readonly environment: ExecutionEnvironment
|
|
@@ -19,6 +34,9 @@ export abstract class BaseExecutionContext implements ExecutionContextLifecycle
|
|
|
19
34
|
protected log: Logger
|
|
20
35
|
protected ready = false
|
|
21
36
|
private listeners: ExecutionEventListener[] = []
|
|
37
|
+
private lifecycleState: ExecutionLifecycleState = 'idle'
|
|
38
|
+
private initializationOperation: Promise<void> | undefined
|
|
39
|
+
private teardownOperation: Promise<void> | undefined
|
|
22
40
|
|
|
23
41
|
constructor(log?: Logger) {
|
|
24
42
|
this.log = resolveLogger(log).child({
|
|
@@ -27,17 +45,62 @@ export abstract class BaseExecutionContext implements ExecutionContextLifecycle
|
|
|
27
45
|
})
|
|
28
46
|
}
|
|
29
47
|
|
|
30
|
-
|
|
48
|
+
initialize(): Promise<void> {
|
|
49
|
+
if (this.lifecycleState === 'ready') return Promise.resolve()
|
|
50
|
+
if (this.lifecycleState === 'initializing' && this.initializationOperation) {
|
|
51
|
+
return this.initializationOperation
|
|
52
|
+
}
|
|
53
|
+
if (this.lifecycleState === 'tearing-down') {
|
|
54
|
+
return Promise.reject(
|
|
55
|
+
new Error(`Execution context "${this.id}" cannot initialize while teardown is in progress`),
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
if (this.lifecycleState === 'teardown-failed') {
|
|
59
|
+
return Promise.reject(
|
|
60
|
+
new Error(
|
|
61
|
+
`Execution context "${this.id}" cannot initialize until its failed teardown is retried`,
|
|
62
|
+
),
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
this.lifecycleState = 'initializing'
|
|
67
|
+
const operation = this.performInitialize()
|
|
68
|
+
this.initializationOperation = operation
|
|
69
|
+
void operation.then(
|
|
70
|
+
() => this.releaseInitialization(operation),
|
|
71
|
+
() => this.releaseInitialization(operation),
|
|
72
|
+
)
|
|
73
|
+
return operation
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
private async performInitialize(): Promise<void> {
|
|
31
77
|
try {
|
|
78
|
+
this.onInitializationStarted()
|
|
32
79
|
await this.doInitialize()
|
|
80
|
+
if (this.lifecycleState !== 'initializing') {
|
|
81
|
+
throw new InitializationSupersededError(this.id)
|
|
82
|
+
}
|
|
83
|
+
this.onInitializationCommitted()
|
|
84
|
+
if (this.lifecycleState !== 'initializing') {
|
|
85
|
+
throw new InitializationSupersededError(this.id)
|
|
86
|
+
}
|
|
33
87
|
this.ready = true
|
|
34
|
-
this.
|
|
35
|
-
this.emit({ type: 'context_ready', contextId: this.id })
|
|
88
|
+
this.lifecycleState = 'ready'
|
|
36
89
|
this.log.info('Execution context initialized', {
|
|
37
90
|
'namzu.execution.context_id': this.id,
|
|
38
91
|
'namzu.execution.environment': this.environment,
|
|
39
92
|
})
|
|
93
|
+
this.emit({
|
|
94
|
+
type: 'context_initialized',
|
|
95
|
+
contextId: this.id,
|
|
96
|
+
environment: this.environment,
|
|
97
|
+
})
|
|
98
|
+
if (this.lifecycleState !== 'ready') return
|
|
99
|
+
this.emit({ type: 'context_ready', contextId: this.id })
|
|
40
100
|
} catch (err) {
|
|
101
|
+
if (err instanceof InitializationSupersededError) throw err
|
|
102
|
+
this.ready = false
|
|
103
|
+
if (this.lifecycleState === 'initializing') this.lifecycleState = 'idle'
|
|
41
104
|
const message = toErrorMessage(err)
|
|
42
105
|
this.emit({ type: 'context_error', contextId: this.id, error: message })
|
|
43
106
|
this.log.error('Execution context initialization failed', {
|
|
@@ -48,20 +111,65 @@ export abstract class BaseExecutionContext implements ExecutionContextLifecycle
|
|
|
48
111
|
}
|
|
49
112
|
}
|
|
50
113
|
|
|
114
|
+
private releaseInitialization(operation: Promise<void>): void {
|
|
115
|
+
if (this.initializationOperation === operation) this.initializationOperation = undefined
|
|
116
|
+
}
|
|
117
|
+
|
|
51
118
|
isReady(): boolean {
|
|
52
119
|
return this.ready
|
|
53
120
|
}
|
|
54
121
|
|
|
55
|
-
|
|
122
|
+
teardown(): Promise<void> {
|
|
123
|
+
if (this.lifecycleState === 'tearing-down' && this.teardownOperation) {
|
|
124
|
+
return this.teardownOperation
|
|
125
|
+
}
|
|
126
|
+
if (this.lifecycleState === 'torn-down') return Promise.resolve()
|
|
127
|
+
|
|
128
|
+
this.ready = false
|
|
129
|
+
this.lifecycleState = 'tearing-down'
|
|
130
|
+
const operation = this.performTeardown(this.initializationOperation)
|
|
131
|
+
this.teardownOperation = operation
|
|
132
|
+
void operation.then(
|
|
133
|
+
() => this.releaseTeardown(operation),
|
|
134
|
+
() => this.releaseTeardown(operation),
|
|
135
|
+
)
|
|
136
|
+
return operation
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
private async performTeardown(pendingInitialization: Promise<void> | undefined): Promise<void> {
|
|
56
140
|
try {
|
|
141
|
+
// Runs before the first await. Subclasses close public admission here so
|
|
142
|
+
// work cannot slip behind an initialization this teardown must await.
|
|
143
|
+
this.onTeardownRequested()
|
|
144
|
+
if (pendingInitialization) {
|
|
145
|
+
try {
|
|
146
|
+
await pendingInitialization
|
|
147
|
+
} catch {
|
|
148
|
+
// Initialization errors are reported by their owner. Cleanup still runs.
|
|
149
|
+
}
|
|
150
|
+
}
|
|
57
151
|
await this.doTeardown()
|
|
58
|
-
|
|
59
|
-
this.
|
|
152
|
+
this.lifecycleState = 'torn-down'
|
|
153
|
+
this.log.info('Execution context torn down', {
|
|
154
|
+
'namzu.execution.context_id': this.id,
|
|
155
|
+
})
|
|
60
156
|
this.emit({ type: 'context_teardown', contextId: this.id })
|
|
61
|
-
|
|
157
|
+
} catch (err) {
|
|
158
|
+
this.lifecycleState = 'teardown-failed'
|
|
159
|
+
const message = toErrorMessage(err)
|
|
160
|
+
this.emit({ type: 'context_error', contextId: this.id, error: message })
|
|
161
|
+
this.log.error('Execution context teardown failed', {
|
|
162
|
+
'namzu.execution.context_id': this.id,
|
|
163
|
+
'exception.message': message,
|
|
164
|
+
})
|
|
165
|
+
throw err
|
|
62
166
|
}
|
|
63
167
|
}
|
|
64
168
|
|
|
169
|
+
private releaseTeardown(operation: Promise<void>): void {
|
|
170
|
+
if (this.teardownOperation === operation) this.teardownOperation = undefined
|
|
171
|
+
}
|
|
172
|
+
|
|
65
173
|
on(listener: ExecutionEventListener): void {
|
|
66
174
|
this.listeners.push(listener)
|
|
67
175
|
}
|
|
@@ -85,4 +193,13 @@ export abstract class BaseExecutionContext implements ExecutionContextLifecycle
|
|
|
85
193
|
|
|
86
194
|
protected abstract doInitialize(): Promise<void>
|
|
87
195
|
protected abstract doTeardown(): Promise<void>
|
|
196
|
+
|
|
197
|
+
/** Fence subclass-owned public admission before initialization begins. */
|
|
198
|
+
protected onInitializationStarted(): void {}
|
|
199
|
+
|
|
200
|
+
/** Reopen admission only after Base has proved initialization was not superseded. */
|
|
201
|
+
protected onInitializationCommitted(): void {}
|
|
202
|
+
|
|
203
|
+
/** Fence subclass-owned public admission synchronously when teardown is requested. */
|
|
204
|
+
protected onTeardownRequested(): void {}
|
|
88
205
|
}
|
|
@@ -42,6 +42,17 @@ export interface HostCallResult {
|
|
|
42
42
|
readonly error?: string
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
/** Authority and provenance for one call from a running program. */
|
|
46
|
+
export interface HostCallContext {
|
|
47
|
+
/** Unique within this program execution. */
|
|
48
|
+
readonly runtimeToolCallId: string
|
|
49
|
+
/**
|
|
50
|
+
* Revoked when the caller cancels or the program's own wall clock expires.
|
|
51
|
+
* A conforming host threads this into the operation it starts.
|
|
52
|
+
*/
|
|
53
|
+
readonly signal: AbortSignal
|
|
54
|
+
}
|
|
55
|
+
|
|
45
56
|
/**
|
|
46
57
|
* What the host will answer.
|
|
47
58
|
*
|
|
@@ -50,7 +61,10 @@ export interface HostCallResult {
|
|
|
50
61
|
* exactly the point: the program's reach is the run's reach, resolved at
|
|
51
62
|
* the moment of the call rather than frozen when the program started.
|
|
52
63
|
*/
|
|
53
|
-
export type HostCallHandler = (
|
|
64
|
+
export type HostCallHandler = (
|
|
65
|
+
request: HostCallRequest,
|
|
66
|
+
context: HostCallContext,
|
|
67
|
+
) => Promise<HostCallResult>
|
|
54
68
|
|
|
55
69
|
export interface RunCodeOptions {
|
|
56
70
|
/** The program. Untrusted text, from the model. */
|
|
@@ -105,6 +105,17 @@ export class WorkerCodeRuntime implements CodeRuntime {
|
|
|
105
105
|
let output = ''
|
|
106
106
|
let truncated = false
|
|
107
107
|
|
|
108
|
+
// A withdrawn caller owns admission. Do not start an isolate merely to
|
|
109
|
+
// discover the signal was already aborted after construction.
|
|
110
|
+
if (options.signal?.aborted) {
|
|
111
|
+
return {
|
|
112
|
+
outcome: { status: 'cancelled' },
|
|
113
|
+
output,
|
|
114
|
+
outputTruncated: truncated,
|
|
115
|
+
calls,
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
108
119
|
const appendOutput = (lines: readonly string[]): void => {
|
|
109
120
|
for (const line of lines) {
|
|
110
121
|
if (truncated) return
|
|
@@ -143,6 +154,10 @@ export class WorkerCodeRuntime implements CodeRuntime {
|
|
|
143
154
|
|
|
144
155
|
return await new Promise<CodeRunResult>((resolve) => {
|
|
145
156
|
let settled = false
|
|
157
|
+
let terminal: CodeRunResult | undefined
|
|
158
|
+
const inFlight = new Set<Promise<void>>()
|
|
159
|
+
const operation = new AbortController()
|
|
160
|
+
|
|
146
161
|
const finish = (result: CodeRunResult): void => {
|
|
147
162
|
// The Promise already ignores a second `resolve`, so removing
|
|
148
163
|
// this guard changes no result — a mutation removing it
|
|
@@ -153,18 +168,42 @@ export class WorkerCodeRuntime implements CodeRuntime {
|
|
|
153
168
|
// then `exit` is the ordinary sequence, not an edge case.
|
|
154
169
|
if (settled) return
|
|
155
170
|
settled = true
|
|
171
|
+
// Terminating the worker only stops the program. Host work already
|
|
172
|
+
// admitted through onHostCall lives outside it, so revoke the signal
|
|
173
|
+
// that was handed to every such call before reporting settlement.
|
|
174
|
+
if (!operation.signal.aborted) {
|
|
175
|
+
operation.abort(new Error(`Code runtime settled with status ${result.outcome.status}`))
|
|
176
|
+
}
|
|
156
177
|
clearTimeout(deadline)
|
|
157
178
|
options.signal?.removeEventListener('abort', onAbort)
|
|
158
179
|
void worker.terminate()
|
|
159
|
-
|
|
180
|
+
// A late, non-cooperative host call must not mutate a result the
|
|
181
|
+
// caller already received.
|
|
182
|
+
resolve({ ...result, calls: [...calls] })
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const finishTerminalWhenHostCallsSettle = (): void => {
|
|
186
|
+
if (terminal && inFlight.size === 0) finish(terminal)
|
|
160
187
|
}
|
|
161
188
|
|
|
162
189
|
const deadline = setTimeout(() => {
|
|
163
|
-
|
|
190
|
+
operation.abort(new Error(`Code runtime exceeded ${options.timeoutMs}ms`))
|
|
191
|
+
finish({
|
|
192
|
+
outcome: { status: 'timed-out' },
|
|
193
|
+
output,
|
|
194
|
+
outputTruncated: truncated,
|
|
195
|
+
calls,
|
|
196
|
+
})
|
|
164
197
|
}, options.timeoutMs)
|
|
165
198
|
|
|
166
199
|
const onAbort = (): void => {
|
|
167
|
-
|
|
200
|
+
operation.abort(options.signal?.reason)
|
|
201
|
+
finish({
|
|
202
|
+
outcome: { status: 'cancelled' },
|
|
203
|
+
output,
|
|
204
|
+
outputTruncated: truncated,
|
|
205
|
+
calls,
|
|
206
|
+
})
|
|
168
207
|
}
|
|
169
208
|
options.signal?.addEventListener('abort', onAbort, { once: true })
|
|
170
209
|
if (options.signal?.aborted) {
|
|
@@ -185,13 +224,23 @@ export class WorkerCodeRuntime implements CodeRuntime {
|
|
|
185
224
|
kind: 'call-result',
|
|
186
225
|
id,
|
|
187
226
|
ok: false,
|
|
188
|
-
error: new HostCallDeniedError({
|
|
227
|
+
error: new HostCallDeniedError({
|
|
228
|
+
name,
|
|
229
|
+
allowed: options.allowedCalls,
|
|
230
|
+
}).message,
|
|
189
231
|
})
|
|
190
232
|
return
|
|
191
233
|
}
|
|
192
|
-
|
|
193
|
-
|
|
234
|
+
const runtimeToolCallId = String(id)
|
|
235
|
+
const hostCall = Promise.resolve()
|
|
236
|
+
.then(() =>
|
|
237
|
+
options.onHostCall(
|
|
238
|
+
{ name, input: message.input },
|
|
239
|
+
{ runtimeToolCallId, signal: operation.signal },
|
|
240
|
+
),
|
|
241
|
+
)
|
|
194
242
|
.then((result) => {
|
|
243
|
+
if (settled) return
|
|
195
244
|
calls.push({ name, ok: result.ok })
|
|
196
245
|
worker.postMessage({
|
|
197
246
|
kind: 'call-result',
|
|
@@ -202,6 +251,7 @@ export class WorkerCodeRuntime implements CodeRuntime {
|
|
|
202
251
|
})
|
|
203
252
|
})
|
|
204
253
|
.catch((err: unknown) => {
|
|
254
|
+
if (settled) return
|
|
205
255
|
calls.push({ name, ok: false })
|
|
206
256
|
worker.postMessage({
|
|
207
257
|
kind: 'call-result',
|
|
@@ -210,6 +260,11 @@ export class WorkerCodeRuntime implements CodeRuntime {
|
|
|
210
260
|
error: err instanceof Error ? err.message : String(err),
|
|
211
261
|
})
|
|
212
262
|
})
|
|
263
|
+
.finally(() => {
|
|
264
|
+
inFlight.delete(hostCall)
|
|
265
|
+
finishTerminalWhenHostCallsSettle()
|
|
266
|
+
})
|
|
267
|
+
inFlight.add(hostCall)
|
|
213
268
|
return
|
|
214
269
|
}
|
|
215
270
|
|
|
@@ -219,12 +274,17 @@ export class WorkerCodeRuntime implements CodeRuntime {
|
|
|
219
274
|
}
|
|
220
275
|
|
|
221
276
|
if (message.kind === 'done') {
|
|
222
|
-
|
|
277
|
+
// A program may start a host call without awaiting it. The worker
|
|
278
|
+
// declaring its JavaScript body complete is not evidence that the
|
|
279
|
+
// effect it started is complete, so keep the runtime open until the
|
|
280
|
+
// already-admitted host calls settle (or the deadline revokes them).
|
|
281
|
+
terminal = {
|
|
223
282
|
outcome: { status: 'completed', result: message.result },
|
|
224
283
|
output,
|
|
225
284
|
outputTruncated: truncated,
|
|
226
285
|
calls,
|
|
227
|
-
}
|
|
286
|
+
}
|
|
287
|
+
finishTerminalWhenHostCallsSettle()
|
|
228
288
|
return
|
|
229
289
|
}
|
|
230
290
|
|
|
@@ -255,7 +315,10 @@ export class WorkerCodeRuntime implements CodeRuntime {
|
|
|
255
315
|
// `error` message — a hard crash, or a program that called
|
|
256
316
|
// `process.exit` through something we failed to withhold.
|
|
257
317
|
finish({
|
|
258
|
-
outcome: {
|
|
318
|
+
outcome: {
|
|
319
|
+
status: 'failed',
|
|
320
|
+
error: `The program exited with code ${code}.`,
|
|
321
|
+
},
|
|
259
322
|
output,
|
|
260
323
|
outputTruncated: truncated,
|
|
261
324
|
calls,
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export class CommandCancellationUnsupportedError extends Error {
|
|
2
|
+
readonly code = 'command_cancellation_unsupported' as const
|
|
3
|
+
|
|
4
|
+
constructor(readonly contextId: string) {
|
|
5
|
+
super(
|
|
6
|
+
`Remote execution context "${contextId}" cannot accept command cancellation because its generic executor has no reservation and terminal-acknowledgement protocol. No remote command was started. Use the Sandbox.exec() contract for cancellable remote command execution.`,
|
|
7
|
+
)
|
|
8
|
+
this.name = 'CommandCancellationUnsupportedError'
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export class RemoteExecutionBusyError extends Error {
|
|
13
|
+
readonly code = 'remote_execution_busy' as const
|
|
14
|
+
|
|
15
|
+
constructor(
|
|
16
|
+
readonly contextId: string,
|
|
17
|
+
readonly activeCommandCount: number,
|
|
18
|
+
) {
|
|
19
|
+
super(
|
|
20
|
+
`Remote execution context "${contextId}" still owns ${activeCommandCount} active command${activeCommandCount === 1 ? '' : 's'}. Disconnect or teardown was refused; wait for the command${activeCommandCount === 1 ? '' : 's'} to settle, then retry.`,
|
|
21
|
+
)
|
|
22
|
+
this.name = 'RemoteExecutionBusyError'
|
|
23
|
+
}
|
|
24
|
+
}
|
package/src/execution/factory.ts
CHANGED
package/src/execution/hybrid.ts
CHANGED
|
@@ -21,6 +21,7 @@ export interface HybridExecutionContextOptions {
|
|
|
21
21
|
envVars?: Record<string, string>
|
|
22
22
|
capabilities?: ExecutionCapability[]
|
|
23
23
|
shell?: string
|
|
24
|
+
maxOutputBytes?: number
|
|
24
25
|
}
|
|
25
26
|
remotes: RemoteTarget[]
|
|
26
27
|
routingStrategy?: ExecutionRoutingStrategy
|
|
@@ -36,6 +37,7 @@ export class HybridExecutionContext extends BaseExecutionContext implements Comm
|
|
|
36
37
|
private remoteTargets: RemoteTarget[]
|
|
37
38
|
private routingStrategy: ExecutionRoutingStrategy
|
|
38
39
|
private roundRobinIndex = 0
|
|
40
|
+
private admissionsOpen = true
|
|
39
41
|
|
|
40
42
|
constructor(options: HybridExecutionContextOptions) {
|
|
41
43
|
super(options.log)
|
|
@@ -50,6 +52,7 @@ export class HybridExecutionContext extends BaseExecutionContext implements Comm
|
|
|
50
52
|
envVars: options.local.envVars,
|
|
51
53
|
capabilities: options.local.capabilities,
|
|
52
54
|
shell: options.local.shell,
|
|
55
|
+
maxOutputBytes: options.local.maxOutputBytes,
|
|
53
56
|
log: options.log,
|
|
54
57
|
})
|
|
55
58
|
|
|
@@ -83,13 +86,29 @@ export class HybridExecutionContext extends BaseExecutionContext implements Comm
|
|
|
83
86
|
})
|
|
84
87
|
}
|
|
85
88
|
|
|
89
|
+
protected override onInitializationStarted(): void {
|
|
90
|
+
this.admissionsOpen = false
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
protected override onInitializationCommitted(): void {
|
|
94
|
+
this.admissionsOpen = true
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
protected override onTeardownRequested(): void {
|
|
98
|
+
this.admissionsOpen = false
|
|
99
|
+
}
|
|
100
|
+
|
|
86
101
|
protected async doTeardown(): Promise<void> {
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
102
|
+
const contexts: BaseExecutionContext[] = [this.localCtx, ...this.remoteCtxs.values()]
|
|
103
|
+
const results = await Promise.allSettled(contexts.map((context) => context.teardown()))
|
|
104
|
+
const failures = results.flatMap((result) =>
|
|
105
|
+
result.status === 'rejected' ? [result.reason] : [],
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
if (failures.length === 1) throw failures[0]
|
|
109
|
+
if (failures.length > 1) {
|
|
110
|
+
throw new AggregateError(failures, 'Multiple hybrid execution contexts failed to tear down')
|
|
90
111
|
}
|
|
91
|
-
await Promise.allSettled(teardownPromises)
|
|
92
|
-
await this.localCtx.teardown()
|
|
93
112
|
}
|
|
94
113
|
|
|
95
114
|
getLocal(): LocalExecutionContext {
|
|
@@ -122,11 +141,16 @@ export class HybridExecutionContext extends BaseExecutionContext implements Comm
|
|
|
122
141
|
}
|
|
123
142
|
|
|
124
143
|
async disconnectAllRemotes(): Promise<void> {
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
144
|
+
const results = await Promise.allSettled(
|
|
145
|
+
Array.from(this.remoteCtxs.values(), (remote) => remote.disconnect()),
|
|
146
|
+
)
|
|
147
|
+
const failures = results.flatMap((result) =>
|
|
148
|
+
result.status === 'rejected' ? [result.reason] : [],
|
|
149
|
+
)
|
|
150
|
+
if (failures.length === 1) throw failures[0]
|
|
151
|
+
if (failures.length > 1) {
|
|
152
|
+
throw new AggregateError(failures, 'Multiple remote execution contexts failed to disconnect')
|
|
128
153
|
}
|
|
129
|
-
await Promise.allSettled(promises)
|
|
130
154
|
}
|
|
131
155
|
|
|
132
156
|
async executeCommand(
|
|
@@ -134,6 +158,11 @@ export class HybridExecutionContext extends BaseExecutionContext implements Comm
|
|
|
134
158
|
args: string[] = [],
|
|
135
159
|
options?: CommandOptions,
|
|
136
160
|
): Promise<CommandResult> {
|
|
161
|
+
if (!this.admissionsOpen) {
|
|
162
|
+
throw new Error(
|
|
163
|
+
`Hybrid execution context "${this.id}" is initializing, tearing down, or torn down. Wait for initialization to commit before executing another command.`,
|
|
164
|
+
)
|
|
165
|
+
}
|
|
137
166
|
switch (this.routingStrategy) {
|
|
138
167
|
case 'local-first':
|
|
139
168
|
return this.localCtx.executeCommand(command, args, options)
|
|
@@ -141,8 +170,7 @@ export class HybridExecutionContext extends BaseExecutionContext implements Comm
|
|
|
141
170
|
case 'remote-first': {
|
|
142
171
|
const connectedRemote = this.getFirstConnectedRemote()
|
|
143
172
|
if (connectedRemote) {
|
|
144
|
-
|
|
145
|
-
return connectedRemote.executeRemote(fullCommand, options)
|
|
173
|
+
return connectedRemote.executeCommand(command, args, options)
|
|
146
174
|
}
|
|
147
175
|
return this.localCtx.executeCommand(command, args, options)
|
|
148
176
|
}
|
|
@@ -162,8 +190,7 @@ export class HybridExecutionContext extends BaseExecutionContext implements Comm
|
|
|
162
190
|
if (target === this.localCtx) {
|
|
163
191
|
return this.localCtx.executeCommand(command, args, options)
|
|
164
192
|
}
|
|
165
|
-
|
|
166
|
-
return (target as RemoteExecutionContext).executeRemote(fullCommand, options)
|
|
193
|
+
return (target as RemoteExecutionContext).executeCommand(command, args, options)
|
|
167
194
|
}
|
|
168
195
|
|
|
169
196
|
default: {
|
|
@@ -174,13 +201,17 @@ export class HybridExecutionContext extends BaseExecutionContext implements Comm
|
|
|
174
201
|
}
|
|
175
202
|
|
|
176
203
|
toConfig(): HybridExecutionContextConfig {
|
|
204
|
+
const local = this.localCtx.toConfig()
|
|
177
205
|
return {
|
|
178
206
|
id: this.id,
|
|
179
207
|
environment: 'hybrid',
|
|
180
208
|
local: {
|
|
181
|
-
cwd:
|
|
182
|
-
fsAccess:
|
|
183
|
-
envVars:
|
|
209
|
+
cwd: local.cwd,
|
|
210
|
+
fsAccess: local.fsAccess,
|
|
211
|
+
envVars: local.envVars,
|
|
212
|
+
capabilities: local.capabilities,
|
|
213
|
+
shell: local.shell,
|
|
214
|
+
maxOutputBytes: local.maxOutputBytes,
|
|
184
215
|
},
|
|
185
216
|
remotes: this.remoteTargets.map((t) => ({ ...t })),
|
|
186
217
|
routingStrategy: this.routingStrategy,
|
package/src/execution/index.ts
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
20
|
export { BaseExecutionContext } from './base.js'
|
|
21
|
+
export { CommandCancellationUnsupportedError, RemoteExecutionBusyError } from './errors.js'
|
|
21
22
|
export { ExecutionContextFactory } from './factory.js'
|
|
22
23
|
export { HybridExecutionContext } from './hybrid.js'
|
|
23
24
|
export type { HybridExecutionContextOptions } from './hybrid.js'
|