@nebutra/agent-runtime 0.2.1 → 2.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.
Files changed (114) hide show
  1. package/LICENSE +21 -676
  2. package/README.md +33 -10
  3. package/dist/adapters/index.d.ts +24 -5
  4. package/dist/adapters/index.js +27 -0
  5. package/dist/adapters/index.js.map +1 -1
  6. package/dist/{chunk-KCNN4QUQ.js → chunk-5UGIUYJR.js} +4 -4
  7. package/dist/chunk-7ELA4SWE.js +73 -0
  8. package/dist/chunk-7ELA4SWE.js.map +1 -0
  9. package/dist/chunk-Q62VKHIT.js +178 -0
  10. package/dist/chunk-Q62VKHIT.js.map +1 -0
  11. package/dist/chunk-VXILZAXK.js +541 -0
  12. package/dist/chunk-VXILZAXK.js.map +1 -0
  13. package/dist/command-exec.d.ts +45 -0
  14. package/dist/command-exec.js +15 -0
  15. package/dist/command-exec.js.map +1 -0
  16. package/dist/index.d.ts +3 -2
  17. package/dist/index.js +81 -28
  18. package/dist/index.js.map +1 -1
  19. package/dist/orchestration.d.ts +42 -1
  20. package/dist/orchestration.js +7 -3
  21. package/dist/pulsar.js +2 -2
  22. package/dist/sandbox-DfcRttXt.d.ts +219 -0
  23. package/dist/sandbox.d.ts +2 -64
  24. package/dist/sandbox.js +25 -3
  25. package/package.json +81 -30
  26. package/.turbo/turbo-build.log +0 -130
  27. package/.turbo/turbo-test.log +0 -47
  28. package/.turbo/turbo-typecheck.log +0 -4
  29. package/CHANGELOG.md +0 -250
  30. package/dist/chunk-MUF7ZZTO.js +0 -57
  31. package/dist/chunk-MUF7ZZTO.js.map +0 -1
  32. package/dist/chunk-MX2WL43P.js +0 -90
  33. package/dist/chunk-MX2WL43P.js.map +0 -1
  34. package/examples/pulsar-quickstart.ts +0 -35
  35. package/examples/resume-branch.ts +0 -45
  36. package/examples/subagent-fanout.ts +0 -20
  37. package/src/adapters/dispatcher-sse.test.ts +0 -218
  38. package/src/adapters/dispatcher-sse.ts +0 -222
  39. package/src/adapters/index.ts +0 -18
  40. package/src/adapters/mcp-catalog.test.ts +0 -213
  41. package/src/adapters/mcp-catalog.ts +0 -188
  42. package/src/adapters/prisma-rollout.test.ts +0 -153
  43. package/src/adapters/prisma-rollout.ts +0 -104
  44. package/src/agent-runtime.test.ts +0 -176
  45. package/src/artifact-stream.test.ts +0 -330
  46. package/src/artifact-stream.ts +0 -453
  47. package/src/channel-gateway.test.ts +0 -432
  48. package/src/channel-gateway.ts +0 -357
  49. package/src/cli.ts +0 -49
  50. package/src/code-review.test.ts +0 -501
  51. package/src/code-review.ts +0 -495
  52. package/src/command-suggestions.test.ts +0 -251
  53. package/src/command-suggestions.ts +0 -338
  54. package/src/commands.test.ts +0 -184
  55. package/src/commands.ts +0 -140
  56. package/src/commit-message.test.ts +0 -249
  57. package/src/commit-message.ts +0 -180
  58. package/src/context-compaction.test.ts +0 -522
  59. package/src/context-compaction.ts +0 -438
  60. package/src/definitions.test.ts +0 -78
  61. package/src/definitions.ts +0 -190
  62. package/src/deployment-status.test.ts +0 -215
  63. package/src/deployment-status.ts +0 -227
  64. package/src/design-context.test.ts +0 -195
  65. package/src/design-context.ts +0 -198
  66. package/src/dispatcher.test.ts +0 -234
  67. package/src/dispatcher.ts +0 -189
  68. package/src/durable-turn.test.ts +0 -209
  69. package/src/durable-turn.ts +0 -135
  70. package/src/edit-planner.test.ts +0 -204
  71. package/src/edit-planner.ts +0 -325
  72. package/src/fuzzy-match.test.ts +0 -311
  73. package/src/fuzzy-match.ts +0 -444
  74. package/src/hook-pipeline.test.ts +0 -279
  75. package/src/hook-pipeline.ts +0 -373
  76. package/src/inbound-admission.test.ts +0 -394
  77. package/src/inbound-admission.ts +0 -246
  78. package/src/index.ts +0 -49
  79. package/src/loop.test.ts +0 -161
  80. package/src/loop.ts +0 -211
  81. package/src/mcp-bridge.test.ts +0 -165
  82. package/src/mcp-bridge.ts +0 -81
  83. package/src/memory-provider.test.ts +0 -232
  84. package/src/memory-provider.ts +0 -257
  85. package/src/model.ts +0 -168
  86. package/src/orchestration.test.ts +0 -53
  87. package/src/orchestration.ts +0 -146
  88. package/src/permission-ruleset.test.ts +0 -301
  89. package/src/permission-ruleset.ts +0 -1
  90. package/src/policy.ts +0 -151
  91. package/src/project-repo.test.ts +0 -232
  92. package/src/project-repo.ts +0 -311
  93. package/src/protocol.ts +0 -159
  94. package/src/pulsar.test.ts +0 -156
  95. package/src/pulsar.ts +0 -322
  96. package/src/rollout-store-persistent.test.ts +0 -217
  97. package/src/rollout-store-persistent.ts +0 -166
  98. package/src/rollout.ts +0 -150
  99. package/src/sandbox.ts +0 -113
  100. package/src/session-share.test.ts +0 -360
  101. package/src/session-share.ts +0 -310
  102. package/src/skill-distillation.test.ts +0 -177
  103. package/src/skill-distillation.ts +0 -369
  104. package/src/skills.test.ts +0 -277
  105. package/src/skills.ts +0 -277
  106. package/src/subagents.test.ts +0 -290
  107. package/src/subagents.ts +0 -332
  108. package/src/tools.test.ts +0 -12
  109. package/src/tools.ts +0 -129
  110. package/src/workbench.test.ts +0 -0
  111. package/src/workbench.ts +0 -0
  112. package/tsconfig.json +0 -12
  113. package/tsup.config.ts +0 -36
  114. /package/dist/{chunk-KCNN4QUQ.js.map → chunk-5UGIUYJR.js.map} +0 -0
package/README.md CHANGED
@@ -1,13 +1,19 @@
1
1
  # @nebutra/agent-runtime
2
2
 
3
- Status: **WIP**
3
+ Status: **WIP** — Track A live (grammar + gateway demo); Track B Phase 1 docked
4
4
 
5
- > Status: WIP — not yet integrated into a production app. Track-B kernel
6
- > transport and durable-turn queue binding are interface-only.
5
+ | Layer | State |
6
+ |-------|--------|
7
+ | Track A grammar (`runTurn`, policy, rollout, tools) | Shipped; gateway demo route behind `agent-runtime-demo` |
8
+ | Track B adapter (`createCarinaSandbox` → Carina JSON-RPC) | **Phase 1 done** ([#382](https://github.com/Nebutra/Nebutra-Sailor/pull/382)) |
9
+ | Track B host wire (env, ensureSession, `command_exec`, gateway bundle) | **Phase 2a done** (#386) |
10
+ | Track B ship (workspace map, approval resolve, auto-approve, status) | **Phase 2b done** |
11
+ | Product HITL UI (beyond API) | Optional |
12
+ | Default without Carina endpoint | **Fail-closed** (`REFUSING_SANDBOX`) |
7
13
 
8
14
  Multi-tenant **agent-runtime grammar**. A faithful re-expression of a terminal
9
15
  coding-agent's runtime *design* into Sailor's grammar — TypeScript,
10
- multi-tenant, zero infra changes, **no in-process untrusted-code execution**.
16
+ multi-tenant, zero in-process untrusted-code execution.
11
17
 
12
18
  ## Why this exists
13
19
 
@@ -24,9 +30,26 @@ them.
24
30
 
25
31
  - **Track A (this package)** — policy, protocol contract, model, rollout. All
26
32
  tenant-scoped. Runs inside Sailor's TS web runtime.
27
- - **Track B (decoupled, not this repo)** — an optional self-hosted isolator /
28
- kernel sidecar that implements `ExternalSandbox` over the `./protocol`
29
- contract. The protocol is the only coupling seam.
33
+ - **Track B (Carina upstream)** — the **Nebutra/carina** kernel is the sole
34
+ product isolator. Self-deployed, local-first. Sailor docks via
35
+ `createCarinaSandbox` / `ExternalSandbox` — **kernel protocol is maintained
36
+ in Carina**, not reimplemented here.
37
+
38
+ ```ts
39
+ import {
40
+ createCarinaSandbox,
41
+ REFUSING_SANDBOX,
42
+ type ExternalSandbox,
43
+ } from "@nebutra/agent-runtime";
44
+
45
+ // Production: only when a reachable Carina JSON-RPC base URL is configured.
46
+ // Same-host co-deploy (default): unix socket /var/carina/run/daemon.sock
47
+ import { resolveCarinaSandboxFromEnv } from "@nebutra/agent-runtime";
48
+ const sandbox = resolveCarinaSandboxFromEnv();
49
+ // Opt out: CARINA_CODEPLOY=0 | optional HTTP: CARINA_JSONRPC_URL=…
50
+ ```
51
+
52
+ See `docs/architecture/2026-08-03-carina-track-b-upstream.md`.
30
53
 
31
54
  ## Modules
32
55
 
@@ -37,16 +60,16 @@ them.
37
60
  | `./protocol` | JSON-RPC contract | method registry, **tenant+thread serialization scope**, server-initiated approval requests, notifications |
38
61
  | `./tools` | uniform tool/MCP | `ToolRegistry` (registry→router→hooks), `adaptMcpTool` (MCP-as-adapter) |
39
62
  | `./rollout` | event-sourced trace | append-only typed log, replay-to-state, compaction marker, per-item persistence policy |
40
- | `./sandbox` | external-sandbox seam | `ExternalSandbox` delegation interface; fail-closed `REFUSING_SANDBOX` default |
63
+ | `./sandbox` | external-sandbox seam | `ExternalSandbox`; `createCarinaSandbox` (Track B); `REFUSING_SANDBOX` default; `createHttpSandbox` generic helper |
41
64
  | `./adapters/*` | reusable concrete bindings | MCP catalog, Web-standard SSE transport, and Prisma rollout persistence without a separate package |
42
65
 
43
66
  ## Non-negotiables enforced here
44
67
 
45
68
  - **Multi-tenant**: every scope, store key, and dispatch carries `tenantId`;
46
69
  cross-tenant requests can never share a serialization scope.
47
- - **No infra change**: no sandbox runtime, no new datastore — only interfaces.
48
70
  - **No in-process untrusted exec**: the default executor refuses; real
49
- execution is delegated to a decoupled isolator.
71
+ execution is delegated to self-deployed Carina (or another `ExternalSandbox`).
72
+ - **No second kernel**: OS sandbox / capability enforcement stay in Carina.
50
73
 
51
74
  See `docs/capabilities/agent-runtime/` for the capability map and replication
52
75
  guide.
@@ -1,12 +1,31 @@
1
+ import { ModelInvoker } from '../loop.js';
1
2
  export { NotificationFrame, SseOptions, createRpcHandler, sseResponse, subscribeNotifications } from './dispatcher-sse.js';
2
3
  export { McpExecutorLike, McpRegistryLike, createMcpClientPort, createMcpServerCatalog } from './mcp-catalog.js';
3
4
  export { PrismaRolloutDelegate, RolloutDelegateResolver, createPrismaRolloutPersistence } from './prisma-rollout.js';
4
- import '../dispatcher.js';
5
- import '../protocol.js';
6
- import 'zod';
7
5
  import '../model.js';
6
+ import '../policy.js';
7
+ import 'zod';
8
+ import '../protocol.js';
9
+ import '../rollout.js';
10
+ import '../tools.js';
11
+ import '../dispatcher.js';
8
12
  import '@nebutra/mcp';
9
13
  import '../mcp-bridge.js';
10
- import '../tools.js';
11
14
  import '../rollout-store-persistent.js';
12
- import '../rollout.js';
15
+
16
+ /**
17
+ * AgentsModelInvoker — the ONE bridge that makes the substrate's `runTurn` use
18
+ * the real provider stack. Implements `ModelInvoker` over @nebutra/agents
19
+ * `generateText` (which resolves the provider + model and runs the AI SDK).
20
+ * Each round sends the running history at the round's `config.model` — which is
21
+ * how a per-node model (resolved from a node's NodeModelSpec) reaches the
22
+ * provider.
23
+ *
24
+ * Tools are NOT passed here: the runtime's own ToolRegistry/loop owns tool
25
+ * dispatch; this round is a plain text completion. Errors propagate to the loop
26
+ * (which records them on the rollout), not swallowed.
27
+ */
28
+
29
+ declare function createAgentsModelInvoker(): ModelInvoker;
30
+
31
+ export { createAgentsModelInvoker };
@@ -11,7 +11,34 @@ import {
11
11
  createPrismaRolloutPersistence
12
12
  } from "../chunk-57W3AR43.js";
13
13
  import "../chunk-424PT5DM.js";
14
+
15
+ // src/adapters/agents-model-invoker.ts
16
+ import { generateText } from "@nebutra/agents";
17
+ function toRole(role) {
18
+ return role === "assistant" || role === "system" ? role : "user";
19
+ }
20
+ function createAgentsModelInvoker() {
21
+ return {
22
+ async invoke(request) {
23
+ const messages = request.history.map((m) => ({
24
+ role: toRole(m.role),
25
+ content: m.content
26
+ }));
27
+ const result = await generateText(messages, { model: request.config.model });
28
+ const text = result.text ?? "";
29
+ const usage = result.usage;
30
+ return {
31
+ emissions: text.length > 0 ? [{ kind: "text", text }] : [],
32
+ usage: {
33
+ inputTokens: usage?.inputTokens ?? 0,
34
+ outputTokens: usage?.outputTokens ?? 0
35
+ }
36
+ };
37
+ }
38
+ };
39
+ }
14
40
  export {
41
+ createAgentsModelInvoker,
15
42
  createMcpClientPort,
16
43
  createMcpServerCatalog,
17
44
  createPrismaRolloutPersistence,
@@ -1 +1 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
1
+ {"version":3,"sources":["../../src/adapters/agents-model-invoker.ts"],"sourcesContent":["/**\n * AgentsModelInvoker — the ONE bridge that makes the substrate's `runTurn` use\n * the real provider stack. Implements `ModelInvoker` over @nebutra/agents\n * `generateText` (which resolves the provider + model and runs the AI SDK).\n * Each round sends the running history at the round's `config.model` — which is\n * how a per-node model (resolved from a node's NodeModelSpec) reaches the\n * provider.\n *\n * Tools are NOT passed here: the runtime's own ToolRegistry/loop owns tool\n * dispatch; this round is a plain text completion. Errors propagate to the loop\n * (which records them on the rollout), not swallowed.\n */\n\nimport { generateText } from \"@nebutra/agents\";\nimport type { ModelInvoker, ModelRoundRequest, ModelRoundResult } from \"../loop\";\n\ntype Role = \"user\" | \"assistant\" | \"system\";\n\nfunction toRole(role: string): Role {\n return role === \"assistant\" || role === \"system\" ? role : \"user\";\n}\n\nexport function createAgentsModelInvoker(): ModelInvoker {\n return {\n async invoke(request: ModelRoundRequest): Promise<ModelRoundResult> {\n const messages = request.history.map((m) => ({\n role: toRole(m.role),\n content: m.content,\n }));\n\n const result = await generateText(messages, { model: request.config.model });\n\n const text = result.text ?? \"\";\n const usage = result.usage;\n return {\n emissions: text.length > 0 ? [{ kind: \"text\", text }] : [],\n usage: {\n inputTokens: usage?.inputTokens ?? 0,\n outputTokens: usage?.outputTokens ?? 0,\n },\n };\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;AAaA,SAAS,oBAAoB;AAK7B,SAAS,OAAO,MAAoB;AAClC,SAAO,SAAS,eAAe,SAAS,WAAW,OAAO;AAC5D;AAEO,SAAS,2BAAyC;AACvD,SAAO;AAAA,IACL,MAAM,OAAO,SAAuD;AAClE,YAAM,WAAW,QAAQ,QAAQ,IAAI,CAAC,OAAO;AAAA,QAC3C,MAAM,OAAO,EAAE,IAAI;AAAA,QACnB,SAAS,EAAE;AAAA,MACb,EAAE;AAEF,YAAM,SAAS,MAAM,aAAa,UAAU,EAAE,OAAO,QAAQ,OAAO,MAAM,CAAC;AAE3E,YAAM,OAAO,OAAO,QAAQ;AAC5B,YAAM,QAAQ,OAAO;AACrB,aAAO;AAAA,QACL,WAAW,KAAK,SAAS,IAAI,CAAC,EAAE,MAAM,QAAQ,KAAK,CAAC,IAAI,CAAC;AAAA,QACzD,OAAO;AAAA,UACL,aAAa,OAAO,eAAe;AAAA,UACnC,cAAc,OAAO,gBAAgB;AAAA,QACvC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
@@ -4,15 +4,15 @@ import {
4
4
  import {
5
5
  replay
6
6
  } from "./chunk-37BBB2P2.js";
7
- import {
8
- RuntimeToolRegistry
9
- } from "./chunk-4Y25ZTKI.js";
10
7
  import {
11
8
  isTurnTerminal
12
9
  } from "./chunk-6EGG2OZC.js";
13
10
  import {
14
11
  DEFAULT_APPROVAL_POLICY
15
12
  } from "./chunk-CGRCUKGT.js";
13
+ import {
14
+ RuntimeToolRegistry
15
+ } from "./chunk-4Y25ZTKI.js";
16
16
 
17
17
  // src/pulsar.ts
18
18
  function newId(prefix) {
@@ -252,4 +252,4 @@ export {
252
252
  PulsarBuilder,
253
253
  Pulsar
254
254
  };
255
- //# sourceMappingURL=chunk-KCNN4QUQ.js.map
255
+ //# sourceMappingURL=chunk-5UGIUYJR.js.map
@@ -0,0 +1,73 @@
1
+ import {
2
+ isCarinaSandbox
3
+ } from "./chunk-VXILZAXK.js";
4
+ import {
5
+ DEFAULT_CAPABILITY_POLICY
6
+ } from "./chunk-CGRCUKGT.js";
7
+ import {
8
+ RuntimeToolRegistry
9
+ } from "./chunk-4Y25ZTKI.js";
10
+
11
+ // src/command-exec.ts
12
+ import { z } from "zod";
13
+ var COMMAND_EXEC_TOOL_NAME = "command_exec";
14
+ var commandExecInputSchema = z.object({
15
+ command: z.string().min(1)
16
+ });
17
+ function registerCommandExecTool(registry, options) {
18
+ const {
19
+ sandbox,
20
+ workspaceRoot,
21
+ capabilityPolicy = DEFAULT_CAPABILITY_POLICY,
22
+ profile,
23
+ approvalMode
24
+ } = options;
25
+ registry.register(
26
+ {
27
+ name: COMMAND_EXEC_TOOL_NAME,
28
+ description: "Run a shell command in the external sandbox (Carina Track B). Never executes in the Sailor web process.",
29
+ inputSchema: commandExecInputSchema
30
+ },
31
+ async (input, ctx) => {
32
+ if (isCarinaSandbox(sandbox)) {
33
+ const root = workspaceRoot?.trim();
34
+ if (!root) {
35
+ throw new Error(
36
+ "command_exec: CARINA_WORKSPACE_ROOT / workspaceRoot required to create a Carina session before command.exec"
37
+ );
38
+ }
39
+ await sandbox.ensureSession({
40
+ threadId: ctx.threadId,
41
+ workspaceRoot: root,
42
+ tenantId: ctx.tenantId,
43
+ ...profile ? { profile } : {},
44
+ ...approvalMode ? { approvalMode } : {}
45
+ });
46
+ }
47
+ const result = await sandbox.exec({
48
+ tenantId: ctx.tenantId,
49
+ threadId: ctx.threadId,
50
+ command: input.command,
51
+ capabilityPolicy
52
+ });
53
+ return {
54
+ exitCode: result.exitCode,
55
+ aggregatedOutput: result.aggregatedOutput,
56
+ executedOn: result.executedOn,
57
+ ...result.decisionId !== void 0 ? { decisionId: result.decisionId } : {}
58
+ };
59
+ }
60
+ );
61
+ }
62
+ function buildSandboxToolRegistry(sandbox, options = {}) {
63
+ const registry = new RuntimeToolRegistry();
64
+ registerCommandExecTool(registry, { sandbox, ...options });
65
+ return registry;
66
+ }
67
+
68
+ export {
69
+ COMMAND_EXEC_TOOL_NAME,
70
+ registerCommandExecTool,
71
+ buildSandboxToolRegistry
72
+ };
73
+ //# sourceMappingURL=chunk-7ELA4SWE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/command-exec.ts"],"sourcesContent":["/**\n * Native command-exec tool that delegates to {@link ExternalSandbox}.\n * Product Track B: pair with {@link createCarinaSandbox} + ensureSession.\n */\n\nimport { z } from \"zod\";\n\nimport { type CapabilityPolicy, DEFAULT_CAPABILITY_POLICY } from \"./policy\";\nimport { type ExternalSandbox, isCarinaSandbox, type SandboxExecResult } from \"./sandbox\";\nimport { RuntimeToolRegistry } from \"./tools\";\n\nexport const COMMAND_EXEC_TOOL_NAME = \"command_exec\" as const;\n\nconst commandExecInputSchema = z.object({\n command: z.string().min(1),\n});\n\nexport type CommandExecToolInput = z.infer<typeof commandExecInputSchema>;\n\nexport type CommandExecToolOutput = {\n readonly exitCode: number;\n readonly aggregatedOutput: string;\n readonly executedOn: string;\n readonly decisionId?: string;\n};\n\nexport type RegisterCommandExecToolOptions = {\n readonly sandbox: ExternalSandbox;\n /**\n * Absolute workspace on the Carina host. Required when sandbox is Carina\n * (session.create). Gateway reads `CARINA_WORKSPACE_ROOT`.\n */\n readonly workspaceRoot?: string;\n readonly capabilityPolicy?: CapabilityPolicy;\n readonly profile?: string;\n readonly approvalMode?: string;\n};\n\n/**\n * Register `command_exec` on a tool registry. For Carina sandboxes, ensures a\n * session for the turn thread before `command.exec`.\n */\nexport function registerCommandExecTool(\n registry: RuntimeToolRegistry,\n options: RegisterCommandExecToolOptions,\n): void {\n const {\n sandbox,\n workspaceRoot,\n capabilityPolicy = DEFAULT_CAPABILITY_POLICY,\n profile,\n approvalMode,\n } = options;\n\n registry.register(\n {\n name: COMMAND_EXEC_TOOL_NAME,\n description:\n \"Run a shell command in the external sandbox (Carina Track B). \" +\n \"Never executes in the Sailor web process.\",\n inputSchema: commandExecInputSchema,\n },\n async (input, ctx): Promise<CommandExecToolOutput> => {\n if (isCarinaSandbox(sandbox)) {\n const root = workspaceRoot?.trim();\n if (!root) {\n throw new Error(\n \"command_exec: CARINA_WORKSPACE_ROOT / workspaceRoot required \" +\n \"to create a Carina session before command.exec\",\n );\n }\n await sandbox.ensureSession({\n threadId: ctx.threadId,\n workspaceRoot: root,\n tenantId: ctx.tenantId,\n ...(profile ? { profile } : {}),\n ...(approvalMode ? { approvalMode } : {}),\n });\n }\n\n const result: SandboxExecResult = await sandbox.exec({\n tenantId: ctx.tenantId,\n threadId: ctx.threadId,\n command: input.command,\n capabilityPolicy,\n });\n\n return {\n exitCode: result.exitCode,\n aggregatedOutput: result.aggregatedOutput,\n executedOn: result.executedOn,\n ...(result.decisionId !== undefined ? { decisionId: result.decisionId } : {}),\n };\n },\n );\n}\n\n/**\n * Build a registry that includes `command_exec` delegated to the given sandbox.\n * Prefer this only when a real isolator is configured; with\n * {@link REFUSING_SANDBOX} the tool will throw NoExecutorConfiguredError on use.\n */\nexport function buildSandboxToolRegistry(\n sandbox: ExternalSandbox,\n options: Omit<RegisterCommandExecToolOptions, \"sandbox\"> = {},\n): RuntimeToolRegistry {\n const registry = new RuntimeToolRegistry();\n registerCommandExecTool(registry, { sandbox, ...options });\n return registry;\n}\n"],"mappings":";;;;;;;;;;;AAKA,SAAS,SAAS;AAMX,IAAM,yBAAyB;AAEtC,IAAM,yBAAyB,EAAE,OAAO;AAAA,EACtC,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC;AAC3B,CAAC;AA2BM,SAAS,wBACd,UACA,SACM;AACN,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,mBAAmB;AAAA,IACnB;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,WAAS;AAAA,IACP;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MAEF,aAAa;AAAA,IACf;AAAA,IACA,OAAO,OAAO,QAAwC;AACpD,UAAI,gBAAgB,OAAO,GAAG;AAC5B,cAAM,OAAO,eAAe,KAAK;AACjC,YAAI,CAAC,MAAM;AACT,gBAAM,IAAI;AAAA,YACR;AAAA,UAEF;AAAA,QACF;AACA,cAAM,QAAQ,cAAc;AAAA,UAC1B,UAAU,IAAI;AAAA,UACd,eAAe;AAAA,UACf,UAAU,IAAI;AAAA,UACd,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,UAC7B,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC;AAAA,QACzC,CAAC;AAAA,MACH;AAEA,YAAM,SAA4B,MAAM,QAAQ,KAAK;AAAA,QACnD,UAAU,IAAI;AAAA,QACd,UAAU,IAAI;AAAA,QACd,SAAS,MAAM;AAAA,QACf;AAAA,MACF,CAAC;AAED,aAAO;AAAA,QACL,UAAU,OAAO;AAAA,QACjB,kBAAkB,OAAO;AAAA,QACzB,YAAY,OAAO;AAAA,QACnB,GAAI,OAAO,eAAe,SAAY,EAAE,YAAY,OAAO,WAAW,IAAI,CAAC;AAAA,MAC7E;AAAA,IACF;AAAA,EACF;AACF;AAOO,SAAS,yBACd,SACA,UAA2D,CAAC,GACvC;AACrB,QAAM,WAAW,IAAI,oBAAoB;AACzC,0BAAwB,UAAU,EAAE,SAAS,GAAG,QAAQ,CAAC;AACzD,SAAO;AACT;","names":[]}
@@ -0,0 +1,178 @@
1
+ // src/orchestration.ts
2
+ import { hasCycleFrom } from "@nebutra/graph-model";
3
+ import { z } from "zod";
4
+ var budgetCapSchema = z.object({
5
+ durationMs: z.number().positive(),
6
+ costUsd: z.number().nonnegative(),
7
+ tokenLimit: z.number().positive()
8
+ });
9
+ var briefSchema = z.object({
10
+ id: z.string().trim().min(1),
11
+ objective: z.string().trim().min(1),
12
+ outputFormat: z.record(z.string(), z.unknown()),
13
+ allowedTools: z.array(z.string()).min(1),
14
+ contextRefs: z.array(z.string()),
15
+ boundaries: z.array(z.string()).min(1),
16
+ budget: budgetCapSchema,
17
+ dependsOn: z.array(z.string()).optional(),
18
+ model: z.object({
19
+ id: z.string().trim().min(1).optional(),
20
+ reasoningEffort: z.enum(["low", "medium", "high", "xhigh"]).optional(),
21
+ modality: z.enum(["text", "image", "video", "audio", "embedding"]).optional(),
22
+ capabilities: z.object({
23
+ vision: z.boolean().optional(),
24
+ toolCall: z.boolean().optional(),
25
+ reasoning: z.boolean().optional()
26
+ }).optional()
27
+ }).optional()
28
+ });
29
+ function fail(message, suggestion) {
30
+ throw new Error(`${message}. Suggestion: ${suggestion}`);
31
+ }
32
+ var BRIEF_FIELD_FAILURE = {
33
+ id: { message: "brief.id is required", suggestion: "Use a stable role or task id." },
34
+ objective: {
35
+ message: "brief.objective is required",
36
+ suggestion: "Write a concrete objective before dispatching."
37
+ },
38
+ outputFormat: {
39
+ message: "brief.outputFormat is invalid",
40
+ suggestion: "Provide an output schema object the worker must conform to."
41
+ },
42
+ allowedTools: {
43
+ message: "brief.allowedTools is required",
44
+ suggestion: "Constrain each subagent to an explicit tool scope."
45
+ },
46
+ contextRefs: {
47
+ message: "brief.contextRefs is invalid",
48
+ suggestion: "Pass an array of context references (may be empty)."
49
+ },
50
+ boundaries: {
51
+ message: "brief.boundaries is required",
52
+ suggestion: "State at least one boundary for the worker."
53
+ },
54
+ budget: {
55
+ message: "brief.budget is invalid",
56
+ suggestion: "Set positive token/time caps and a non-negative cost cap."
57
+ },
58
+ dependsOn: {
59
+ message: "brief.dependsOn is invalid",
60
+ suggestion: "List dependency brief ids as an array of strings."
61
+ },
62
+ model: {
63
+ message: "brief.model is invalid",
64
+ suggestion: "Use a preset alias or 'provider/model' id, or omit to inherit the run default."
65
+ }
66
+ };
67
+ function validateBrief(brief) {
68
+ const result = briefSchema.safeParse(brief);
69
+ if (result.success) return;
70
+ const topLevelField = result.error.issues[0]?.path[0];
71
+ const failure = typeof topLevelField === "string" ? BRIEF_FIELD_FAILURE[topLevelField] : void 0;
72
+ if (failure) fail(failure.message, failure.suggestion);
73
+ fail("brief is invalid", "Provide every required brief field with valid values.");
74
+ }
75
+ function dependencySet(briefs) {
76
+ const dependencies = /* @__PURE__ */ new Set();
77
+ for (const brief of briefs) {
78
+ for (const dep of brief.dependsOn ?? []) dependencies.add(dep);
79
+ }
80
+ return dependencies;
81
+ }
82
+ function briefEdges(briefs) {
83
+ const ids = new Set(briefs.map((brief) => brief.id));
84
+ const edges = [];
85
+ for (const brief of briefs) {
86
+ for (const dep of brief.dependsOn ?? []) {
87
+ if (ids.has(dep)) edges.push({ from: dep, to: brief.id });
88
+ }
89
+ }
90
+ return edges;
91
+ }
92
+ function assertAcyclic(briefs, edges) {
93
+ for (const brief of briefs) {
94
+ if (hasCycleFrom(edges, brief.id)) {
95
+ fail(
96
+ `subagent dependency cycle includes '${brief.id}'`,
97
+ "Remove the cycle or collapse the dependent work into one sequential brief."
98
+ );
99
+ }
100
+ }
101
+ }
102
+ function planWaves(briefs) {
103
+ const edges = briefEdges(briefs);
104
+ assertAcyclic(briefs, edges);
105
+ const byId = new Map(briefs.map((brief) => [brief.id, brief]));
106
+ const done = /* @__PURE__ */ new Set();
107
+ const waves = [];
108
+ while (done.size < briefs.length) {
109
+ const wave = [];
110
+ for (const brief of briefs) {
111
+ if (done.has(brief.id)) continue;
112
+ const deps = (brief.dependsOn ?? []).filter((dep) => byId.has(dep));
113
+ if (deps.every((dep) => done.has(dep))) wave.push(brief);
114
+ }
115
+ if (wave.length === 0) {
116
+ fail(
117
+ "subagent dependencies cannot be resolved into waves",
118
+ "Ensure every dependsOn id references a brief in the set."
119
+ );
120
+ }
121
+ for (const brief of wave) done.add(brief.id);
122
+ waves.push(wave);
123
+ }
124
+ return waves;
125
+ }
126
+ function topologicalOrder(briefs) {
127
+ return planWaves(briefs).flat();
128
+ }
129
+ function planSubagentDispatch(briefs, options = {}) {
130
+ if (briefs.length === 0) {
131
+ fail("at least one brief is required", "Create a concrete worker brief before dispatching.");
132
+ }
133
+ for (const brief of briefs) validateBrief(brief);
134
+ const dependencies = dependencySet(briefs);
135
+ if ((options.strategy ?? "auto") === "fanout" && dependencies.size > 0) {
136
+ fail(
137
+ "fan-out cannot run briefs that depend on each other",
138
+ "Use sequential dispatch for dependent work or split independent briefs only."
139
+ );
140
+ }
141
+ const order = topologicalOrder(briefs);
142
+ const strategy = options.strategy === "fanout" || options.strategy === "auto" && dependencies.size === 0 ? "fanout" : "sequential";
143
+ return { strategy, order };
144
+ }
145
+ async function fanOutSubagents(briefs, run) {
146
+ const plan = planSubagentDispatch(briefs, { strategy: "fanout" });
147
+ return Promise.all(plan.order.map((brief) => run(brief)));
148
+ }
149
+ async function runAgentWaves(briefs, run) {
150
+ for (const brief of briefs) validateBrief(brief);
151
+ const results = [];
152
+ for (const wave of planWaves(briefs)) {
153
+ const waveResults = await Promise.all(wave.map((brief) => run(brief)));
154
+ results.push(...waveResults);
155
+ }
156
+ return results;
157
+ }
158
+ function costReport(results) {
159
+ return {
160
+ totalInputTokens: results.reduce((sum, result) => sum + result.usage.inputTokens, 0),
161
+ totalOutputTokens: results.reduce((sum, result) => sum + result.usage.outputTokens, 0),
162
+ totalReasoningTokens: results.reduce(
163
+ (sum, result) => sum + result.usage.reasoningOutputTokens,
164
+ 0
165
+ ),
166
+ maxDurationMs: results.reduce((max, result) => Math.max(max, result.durationMs), 0),
167
+ subagents: results.length
168
+ };
169
+ }
170
+
171
+ export {
172
+ planWaves,
173
+ planSubagentDispatch,
174
+ fanOutSubagents,
175
+ runAgentWaves,
176
+ costReport
177
+ };
178
+ //# sourceMappingURL=chunk-Q62VKHIT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/orchestration.ts"],"sourcesContent":["import { type GraphEdge, hasCycleFrom } from \"@nebutra/graph-model\";\nimport { z } from \"zod\";\nimport type { TurnUsage } from \"./model\";\n\nexport interface BudgetCap {\n readonly durationMs: number;\n readonly costUsd: number;\n readonly tokenLimit: number;\n}\n\n/** Thinking/reasoning effort for a node (maps to provider reasoning controls). */\nexport type ReasoningEffort = \"low\" | \"medium\" | \"high\" | \"xhigh\";\n\n/** Output modality a node produces. Mirrors @nebutra/ai-providers ModelModality. */\nexport type ModelModality = \"text\" | \"image\" | \"video\" | \"audio\" | \"embedding\";\n\n/**\n * Per-node model selection — the full model meta-info a node can declare. ALL\n * fields optional; an unset field inherits the run-level default\n * (WorkflowDefinition.defaultModel / runTurn config). The executor resolves\n * these HINTS against @nebutra/ai-providers/catalog (listModelsByModality /\n * resolveFrontierModel) to a concrete model — so a node can either PIN one\n * (`id`) or DESCRIBE what it needs (\"the latest fast text model with vision\").\n */\nexport interface NodeModelSpec {\n /** Explicit pin: preset alias (`flagship`/`reasoning`/`fast`) or `provider/model` id. */\n readonly id?: string;\n /** Thinking effort: `low` → cheap/quick, `xhigh` → deepest reasoning. */\n readonly reasoningEffort?: ReasoningEffort;\n /** Output modality — selects a model of this modality when `id` is unset. */\n readonly modality?: ModelModality;\n /** Capabilities the selected model MUST have (e.g. a node needing image input). */\n readonly capabilities?: {\n readonly vision?: boolean;\n readonly toolCall?: boolean;\n readonly reasoning?: boolean;\n };\n}\n\nexport interface Brief {\n readonly id: string;\n readonly objective: string;\n readonly outputFormat: Record<string, unknown>;\n readonly allowedTools: readonly string[];\n readonly contextRefs: readonly string[];\n readonly boundaries: readonly string[];\n readonly budget: BudgetCap;\n readonly dependsOn?: readonly string[];\n /** Per-node model meta-info (id/preset · thinking effort · modality · capabilities). */\n readonly model?: NodeModelSpec;\n}\n\n/**\n * Runtime shape + semantic validation for {@link Brief}. The public type keeps\n * its `readonly` immutability contract (see project immutability rules), so we\n * validate against this schema at the boundary rather than deriving the type\n * from it. Each rule mirrors a tailored DX suggestion surfaced via {@link fail}.\n */\nconst budgetCapSchema = z.object({\n durationMs: z.number().positive(),\n costUsd: z.number().nonnegative(),\n tokenLimit: z.number().positive(),\n});\n\nconst briefSchema = z.object({\n id: z.string().trim().min(1),\n objective: z.string().trim().min(1),\n outputFormat: z.record(z.string(), z.unknown()),\n allowedTools: z.array(z.string()).min(1),\n contextRefs: z.array(z.string()),\n boundaries: z.array(z.string()).min(1),\n budget: budgetCapSchema,\n dependsOn: z.array(z.string()).optional(),\n model: z\n .object({\n id: z.string().trim().min(1).optional(),\n reasoningEffort: z.enum([\"low\", \"medium\", \"high\", \"xhigh\"]).optional(),\n modality: z.enum([\"text\", \"image\", \"video\", \"audio\", \"embedding\"]).optional(),\n capabilities: z\n .object({\n vision: z.boolean().optional(),\n toolCall: z.boolean().optional(),\n reasoning: z.boolean().optional(),\n })\n .optional(),\n })\n .optional(),\n});\n\nexport type DispatchStrategy = \"auto\" | \"sequential\" | \"fanout\";\n\nexport interface DispatchPlan {\n readonly strategy: Exclude<DispatchStrategy, \"auto\">;\n readonly order: readonly Brief[];\n}\n\nexport interface DispatchPlanOptions {\n readonly strategy?: DispatchStrategy;\n}\n\nexport interface SubagentResult {\n readonly briefId: string;\n readonly output: unknown;\n readonly usage: TurnUsage;\n readonly durationMs: number;\n}\n\nexport interface SubagentCostReport {\n readonly totalInputTokens: number;\n readonly totalOutputTokens: number;\n readonly totalReasoningTokens: number;\n readonly maxDurationMs: number;\n readonly subagents: number;\n}\n\nfunction fail(message: string, suggestion: string): never {\n throw new Error(`${message}. Suggestion: ${suggestion}`);\n}\n\n/**\n * Per-top-level-field DX messages, keyed by the failing schema path. Keeps the\n * exact \"message. Suggestion: …\" surface the callers (and tests) rely on while\n * the heavy lifting (shape + bounds) moves into {@link briefSchema}.\n */\nconst BRIEF_FIELD_FAILURE: Record<string, { message: string; suggestion: string }> = {\n id: { message: \"brief.id is required\", suggestion: \"Use a stable role or task id.\" },\n objective: {\n message: \"brief.objective is required\",\n suggestion: \"Write a concrete objective before dispatching.\",\n },\n outputFormat: {\n message: \"brief.outputFormat is invalid\",\n suggestion: \"Provide an output schema object the worker must conform to.\",\n },\n allowedTools: {\n message: \"brief.allowedTools is required\",\n suggestion: \"Constrain each subagent to an explicit tool scope.\",\n },\n contextRefs: {\n message: \"brief.contextRefs is invalid\",\n suggestion: \"Pass an array of context references (may be empty).\",\n },\n boundaries: {\n message: \"brief.boundaries is required\",\n suggestion: \"State at least one boundary for the worker.\",\n },\n budget: {\n message: \"brief.budget is invalid\",\n suggestion: \"Set positive token/time caps and a non-negative cost cap.\",\n },\n dependsOn: {\n message: \"brief.dependsOn is invalid\",\n suggestion: \"List dependency brief ids as an array of strings.\",\n },\n model: {\n message: \"brief.model is invalid\",\n suggestion: \"Use a preset alias or 'provider/model' id, or omit to inherit the run default.\",\n },\n};\n\nfunction validateBrief(brief: Brief): void {\n const result = briefSchema.safeParse(brief);\n if (result.success) return;\n\n const topLevelField = result.error.issues[0]?.path[0];\n const failure =\n typeof topLevelField === \"string\" ? BRIEF_FIELD_FAILURE[topLevelField] : undefined;\n if (failure) fail(failure.message, failure.suggestion);\n fail(\"brief is invalid\", \"Provide every required brief field with valid values.\");\n}\n\nfunction dependencySet(briefs: readonly Brief[]): Set<string> {\n const dependencies = new Set<string>();\n for (const brief of briefs) {\n for (const dep of brief.dependsOn ?? []) dependencies.add(dep);\n }\n return dependencies;\n}\n\n/** Dependency edges (dep → brief) over the brief set; refs to unknown ids drop. */\nfunction briefEdges(briefs: readonly Brief[]): GraphEdge[] {\n const ids = new Set(briefs.map((brief) => brief.id));\n const edges: GraphEdge[] = [];\n for (const brief of briefs) {\n for (const dep of brief.dependsOn ?? []) {\n if (ids.has(dep)) edges.push({ from: dep, to: brief.id });\n }\n }\n return edges;\n}\n\n/**\n * Cycle guard via the SINGLE repo-wide cycle-detection algorithm\n * (`@nebutra/graph-model` `hasCycleFrom`). No private DFS cycle-walker lives here.\n */\nfunction assertAcyclic(briefs: readonly Brief[], edges: readonly GraphEdge[]): void {\n for (const brief of briefs) {\n if (hasCycleFrom(edges, brief.id)) {\n fail(\n `subagent dependency cycle includes '${brief.id}'`,\n \"Remove the cycle or collapse the dependent work into one sequential brief.\",\n );\n }\n }\n}\n\n/**\n * Dependency-resolved execution WAVES — the agent node-topology scheduler. Each\n * wave is the set of briefs whose dependencies are satisfied by earlier waves;\n * waves run in order, briefs within a wave run in parallel. Input order is\n * preserved within a wave.\n */\nexport function planWaves(briefs: readonly Brief[]): readonly (readonly Brief[])[] {\n const edges = briefEdges(briefs);\n assertAcyclic(briefs, edges);\n\n const byId = new Map(briefs.map((brief) => [brief.id, brief]));\n const done = new Set<string>();\n const waves: Brief[][] = [];\n\n while (done.size < briefs.length) {\n const wave: Brief[] = [];\n for (const brief of briefs) {\n if (done.has(brief.id)) continue;\n const deps = (brief.dependsOn ?? []).filter((dep) => byId.has(dep));\n if (deps.every((dep) => done.has(dep))) wave.push(brief);\n }\n if (wave.length === 0) {\n // assertAcyclic already ruled out cycles; only a logic bug reaches here.\n fail(\n \"subagent dependencies cannot be resolved into waves\",\n \"Ensure every dependsOn id references a brief in the set.\",\n );\n }\n for (const brief of wave) done.add(brief.id);\n waves.push(wave);\n }\n return waves;\n}\n\nfunction topologicalOrder(briefs: readonly Brief[]): Brief[] {\n return planWaves(briefs).flat();\n}\n\nexport function planSubagentDispatch(\n briefs: readonly Brief[],\n options: DispatchPlanOptions = {},\n): DispatchPlan {\n if (briefs.length === 0) {\n fail(\"at least one brief is required\", \"Create a concrete worker brief before dispatching.\");\n }\n for (const brief of briefs) validateBrief(brief);\n\n const dependencies = dependencySet(briefs);\n if ((options.strategy ?? \"auto\") === \"fanout\" && dependencies.size > 0) {\n fail(\n \"fan-out cannot run briefs that depend on each other\",\n \"Use sequential dispatch for dependent work or split independent briefs only.\",\n );\n }\n\n const order = topologicalOrder(briefs);\n const strategy =\n options.strategy === \"fanout\" || (options.strategy === \"auto\" && dependencies.size === 0)\n ? \"fanout\"\n : \"sequential\";\n return { strategy, order };\n}\n\nexport async function fanOutSubagents(\n briefs: readonly Brief[],\n run: (brief: Brief) => Promise<SubagentResult>,\n): Promise<readonly SubagentResult[]> {\n const plan = planSubagentDispatch(briefs, { strategy: \"fanout\" });\n return Promise.all(plan.order.map((brief) => run(brief)));\n}\n\n/**\n * Execute briefs as a dependency graph: each wave runs in parallel, waves run\n * sequentially. The node-topology execution path — `fanOutSubagents` is the\n * degenerate single-wave (all-independent) case of this.\n */\nexport async function runAgentWaves(\n briefs: readonly Brief[],\n run: (brief: Brief) => Promise<SubagentResult>,\n): Promise<readonly SubagentResult[]> {\n for (const brief of briefs) validateBrief(brief);\n const results: SubagentResult[] = [];\n for (const wave of planWaves(briefs)) {\n const waveResults = await Promise.all(wave.map((brief) => run(brief)));\n results.push(...waveResults);\n }\n return results;\n}\n\nexport function costReport(results: readonly SubagentResult[]): SubagentCostReport {\n return {\n totalInputTokens: results.reduce((sum, result) => sum + result.usage.inputTokens, 0),\n totalOutputTokens: results.reduce((sum, result) => sum + result.usage.outputTokens, 0),\n totalReasoningTokens: results.reduce(\n (sum, result) => sum + result.usage.reasoningOutputTokens,\n 0,\n ),\n maxDurationMs: results.reduce((max, result) => Math.max(max, result.durationMs), 0),\n subagents: results.length,\n };\n}\n"],"mappings":"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","names":[]}