@geminixiang/mikan 1.0.0-beta.20 → 1.0.0-beta.21
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 +34 -0
- package/README.md +18 -11
- package/dist/adapters/buffered-responder.d.ts +60 -0
- package/dist/adapters/buffered-responder.d.ts.map +1 -0
- package/dist/adapters/buffered-responder.js +201 -0
- package/dist/adapters/buffered-responder.js.map +1 -0
- package/dist/adapters/discord/context.d.ts.map +1 -1
- package/dist/adapters/discord/context.js +42 -177
- package/dist/adapters/discord/context.js.map +1 -1
- package/dist/adapters/github/bot.d.ts +14 -76
- package/dist/adapters/github/bot.d.ts.map +1 -1
- package/dist/adapters/github/bot.js +52 -443
- package/dist/adapters/github/bot.js.map +1 -1
- package/dist/adapters/github/client.d.ts +4 -0
- package/dist/adapters/github/client.d.ts.map +1 -1
- package/dist/adapters/github/client.js +5 -0
- package/dist/adapters/github/client.js.map +1 -1
- package/dist/adapters/github/context.d.ts.map +1 -1
- package/dist/adapters/github/context.js +32 -104
- package/dist/adapters/github/context.js.map +1 -1
- package/dist/adapters/github/github-ops.d.ts +90 -0
- package/dist/adapters/github/github-ops.d.ts.map +1 -0
- package/dist/adapters/github/github-ops.js +405 -0
- package/dist/adapters/github/github-ops.js.map +1 -0
- package/dist/adapters/github/repo.d.ts +2 -0
- package/dist/adapters/github/repo.d.ts.map +1 -1
- package/dist/adapters/github/repo.js +5 -0
- package/dist/adapters/github/repo.js.map +1 -1
- package/dist/adapters/github/tools/checks.d.ts.map +1 -1
- package/dist/adapters/github/tools/checks.js +6 -17
- package/dist/adapters/github/tools/checks.js.map +1 -1
- package/dist/adapters/github/tools/issue.d.ts.map +1 -1
- package/dist/adapters/github/tools/issue.js +6 -17
- package/dist/adapters/github/tools/issue.js.map +1 -1
- package/dist/adapters/github/tools/pr.d.ts.map +1 -1
- package/dist/adapters/github/tools/pr.js +6 -17
- package/dist/adapters/github/tools/pr.js.map +1 -1
- package/dist/adapters/github/tools/read.d.ts.map +1 -1
- package/dist/adapters/github/tools/read.js +6 -17
- package/dist/adapters/github/tools/read.js.map +1 -1
- package/dist/adapters/github/tools/review-reply.d.ts.map +1 -1
- package/dist/adapters/github/tools/review-reply.js +6 -17
- package/dist/adapters/github/tools/review-reply.js.map +1 -1
- package/dist/adapters/github/tools/sync.d.ts.map +1 -1
- package/dist/adapters/github/tools/sync.js +6 -17
- package/dist/adapters/github/tools/sync.js.map +1 -1
- package/dist/adapters/slack/bot.js +1 -1
- package/dist/adapters/slack/bot.js.map +1 -1
- package/dist/adapters/telegram/context.d.ts.map +1 -1
- package/dist/adapters/telegram/context.js +33 -151
- package/dist/adapters/telegram/context.js.map +1 -1
- package/dist/agent.d.ts +0 -1
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +28 -32
- package/dist/agent.js.map +1 -1
- package/dist/cli/arg-grammar.d.ts +25 -0
- package/dist/cli/arg-grammar.d.ts.map +1 -0
- package/dist/cli/arg-grammar.js +59 -0
- package/dist/cli/arg-grammar.js.map +1 -0
- package/dist/cli/boot.d.ts +16 -0
- package/dist/cli/boot.d.ts.map +1 -0
- package/dist/cli/boot.js +119 -0
- package/dist/cli/boot.js.map +1 -0
- package/dist/cli/ext.js +9 -11
- package/dist/cli/ext.js.map +1 -1
- package/dist/commands/extensions.js +2 -2
- package/dist/commands/extensions.js.map +1 -1
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +5 -2
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/model.d.ts.map +1 -1
- package/dist/commands/model.js +8 -8
- package/dist/commands/model.js.map +1 -1
- package/dist/commands/sandbox.d.ts.map +1 -1
- package/dist/commands/sandbox.js +7 -5
- package/dist/commands/sandbox.js.map +1 -1
- package/dist/config.d.ts +0 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +8 -41
- package/dist/config.js.map +1 -1
- package/dist/env-manifest.d.ts +35 -0
- package/dist/env-manifest.d.ts.map +1 -0
- package/dist/env-manifest.js +225 -0
- package/dist/env-manifest.js.map +1 -0
- package/dist/events.d.ts +0 -10
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +9 -82
- package/dist/events.js.map +1 -1
- package/dist/execution-resolver.d.ts +1 -0
- package/dist/execution-resolver.d.ts.map +1 -1
- package/dist/execution-resolver.js +33 -36
- package/dist/execution-resolver.js.map +1 -1
- package/dist/harness/event-format.d.ts +66 -0
- package/dist/harness/event-format.d.ts.map +1 -0
- package/dist/harness/event-format.js +112 -0
- package/dist/harness/event-format.js.map +1 -0
- package/dist/harness/extensions/loader.d.ts +9 -6
- package/dist/harness/extensions/loader.d.ts.map +1 -1
- package/dist/harness/extensions/loader.js +35 -50
- package/dist/harness/extensions/loader.js.map +1 -1
- package/dist/harness/extensions/types.d.ts +10 -14
- package/dist/harness/extensions/types.d.ts.map +1 -1
- package/dist/harness/extensions/types.js.map +1 -1
- package/dist/harness/index.d.ts +1 -0
- package/dist/harness/index.d.ts.map +1 -1
- package/dist/harness/index.js +1 -0
- package/dist/harness/index.js.map +1 -1
- package/dist/harness/runner.d.ts +16 -0
- package/dist/harness/runner.d.ts.map +1 -1
- package/dist/harness/runner.js +27 -1
- package/dist/harness/runner.js.map +1 -1
- package/dist/harness/subagent-runner.d.ts +18 -1
- package/dist/harness/subagent-runner.d.ts.map +1 -1
- package/dist/harness/subagent-runner.js +62 -30
- package/dist/harness/subagent-runner.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/main.js +69 -121
- package/dist/main.js.map +1 -1
- package/dist/observability/instrument.js +6 -4
- package/dist/observability/instrument.js.map +1 -1
- package/dist/observability/sentry.d.ts.map +1 -1
- package/dist/observability/sentry.js +3 -2
- package/dist/observability/sentry.js.map +1 -1
- package/dist/runtime/conversation-runtime.js +13 -3
- package/dist/runtime/conversation-runtime.js.map +1 -1
- package/dist/runtime/types.d.ts +4 -0
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/runtime/types.js.map +1 -1
- package/dist/sandbox/cloudflare.d.ts +1 -0
- package/dist/sandbox/cloudflare.d.ts.map +1 -1
- package/dist/sandbox/cloudflare.js +4 -1
- package/dist/sandbox/cloudflare.js.map +1 -1
- package/dist/sandbox/container.d.ts +1 -0
- package/dist/sandbox/container.d.ts.map +1 -1
- package/dist/sandbox/container.js +4 -1
- package/dist/sandbox/container.js.map +1 -1
- package/dist/sandbox/firecracker.d.ts +1 -0
- package/dist/sandbox/firecracker.d.ts.map +1 -1
- package/dist/sandbox/firecracker.js +4 -1
- package/dist/sandbox/firecracker.js.map +1 -1
- package/dist/sandbox/gondolin-bootstrap.d.ts +26 -0
- package/dist/sandbox/gondolin-bootstrap.d.ts.map +1 -0
- package/dist/sandbox/gondolin-bootstrap.js +27 -0
- package/dist/sandbox/gondolin-bootstrap.js.map +1 -0
- package/dist/sandbox/gondolin-contract.d.ts +125 -0
- package/dist/sandbox/gondolin-contract.d.ts.map +1 -0
- package/dist/sandbox/gondolin-contract.js +155 -0
- package/dist/sandbox/gondolin-contract.js.map +1 -0
- package/dist/sandbox/gondolin-fleet.d.ts +1 -1
- package/dist/sandbox/gondolin-fleet.d.ts.map +1 -1
- package/dist/sandbox/gondolin-fleet.js +1 -1
- package/dist/sandbox/gondolin-fleet.js.map +1 -1
- package/dist/sandbox/gondolin-gateway.d.ts +1 -0
- package/dist/sandbox/gondolin-gateway.d.ts.map +1 -1
- package/dist/sandbox/gondolin-gateway.js +13 -6
- package/dist/sandbox/gondolin-gateway.js.map +1 -1
- package/dist/sandbox/gondolin-inventory.d.ts +2 -16
- package/dist/sandbox/gondolin-inventory.d.ts.map +1 -1
- package/dist/sandbox/gondolin-inventory.js +2 -12
- package/dist/sandbox/gondolin-inventory.js.map +1 -1
- package/dist/sandbox/gondolin-placement.d.ts +0 -2
- package/dist/sandbox/gondolin-placement.d.ts.map +1 -1
- package/dist/sandbox/gondolin-placement.js +0 -6
- package/dist/sandbox/gondolin-placement.js.map +1 -1
- package/dist/sandbox/gondolin-recovery.d.ts +33 -0
- package/dist/sandbox/gondolin-recovery.d.ts.map +1 -0
- package/dist/sandbox/gondolin-recovery.js +39 -0
- package/dist/sandbox/gondolin-recovery.js.map +1 -0
- package/dist/sandbox/gondolin-remote.d.ts +2 -5
- package/dist/sandbox/gondolin-remote.d.ts.map +1 -1
- package/dist/sandbox/gondolin-remote.js +12 -39
- package/dist/sandbox/gondolin-remote.js.map +1 -1
- package/dist/sandbox/gondolin-worker-client.d.ts +8 -12
- package/dist/sandbox/gondolin-worker-client.d.ts.map +1 -1
- package/dist/sandbox/gondolin-worker-client.js +13 -15
- package/dist/sandbox/gondolin-worker-client.js.map +1 -1
- package/dist/sandbox/gondolin-worker.d.ts +2 -40
- package/dist/sandbox/gondolin-worker.d.ts.map +1 -1
- package/dist/sandbox/gondolin-worker.js.map +1 -1
- package/dist/sandbox/gondolin.d.ts +1 -0
- package/dist/sandbox/gondolin.d.ts.map +1 -1
- package/dist/sandbox/gondolin.js +8 -4
- package/dist/sandbox/gondolin.js.map +1 -1
- package/dist/sandbox/host.d.ts +1 -0
- package/dist/sandbox/host.d.ts.map +1 -1
- package/dist/sandbox/host.js +3 -0
- package/dist/sandbox/host.js.map +1 -1
- package/dist/sandbox/index.d.ts +9 -1
- package/dist/sandbox/index.d.ts.map +1 -1
- package/dist/sandbox/index.js +14 -0
- package/dist/sandbox/index.js.map +1 -1
- package/dist/sandbox/types.d.ts +5 -0
- package/dist/sandbox/types.d.ts.map +1 -1
- package/dist/sandbox/types.js.map +1 -1
- package/dist/sandbox/utils.d.ts +1 -0
- package/dist/sandbox/utils.d.ts.map +1 -1
- package/dist/sandbox/utils.js +5 -2
- package/dist/sandbox/utils.js.map +1 -1
- package/dist/sessions/chat-history-sync.d.ts +32 -0
- package/dist/sessions/chat-history-sync.d.ts.map +1 -0
- package/dist/sessions/{agent-memory-file-manager.js → chat-history-sync.js} +24 -83
- package/dist/sessions/chat-history-sync.js.map +1 -0
- package/dist/sessions/conversation-log.d.ts +13 -0
- package/dist/sessions/conversation-log.d.ts.map +1 -0
- package/dist/sessions/conversation-log.js +47 -0
- package/dist/sessions/conversation-log.js.map +1 -0
- package/dist/sessions/rotation.d.ts +2 -0
- package/dist/sessions/rotation.d.ts.map +1 -0
- package/dist/sessions/rotation.js +39 -0
- package/dist/sessions/rotation.js.map +1 -0
- package/dist/sessions/store.d.ts.map +1 -1
- package/dist/sessions/store.js +4 -10
- package/dist/sessions/store.js.map +1 -1
- package/dist/sessions/types.d.ts +2 -2
- package/dist/sessions/types.d.ts.map +1 -1
- package/dist/sessions/types.js.map +1 -1
- package/dist/settings-mutation.d.ts +23 -0
- package/dist/settings-mutation.d.ts.map +1 -0
- package/dist/settings-mutation.js +42 -0
- package/dist/settings-mutation.js.map +1 -0
- package/dist/tools/event.d.ts.map +1 -1
- package/dist/tools/event.js +27 -46
- package/dist/tools/event.js.map +1 -1
- package/dist/tools/host-fn-tool.d.ts +21 -0
- package/dist/tools/host-fn-tool.d.ts.map +1 -0
- package/dist/tools/host-fn-tool.js +32 -0
- package/dist/tools/host-fn-tool.js.map +1 -0
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +1 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/react.d.ts.map +1 -1
- package/dist/tools/react.js +6 -17
- package/dist/tools/react.js.map +1 -1
- package/dist/tools/read.d.ts.map +1 -1
- package/dist/tools/read.js +7 -26
- package/dist/tools/read.js.map +1 -1
- package/dist/tools/sandbox.d.ts.map +1 -1
- package/dist/tools/sandbox.js +5 -2
- package/dist/tools/sandbox.js.map +1 -1
- package/dist/tools/subagent-slots.d.ts +28 -0
- package/dist/tools/subagent-slots.d.ts.map +1 -0
- package/dist/tools/subagent-slots.js +57 -0
- package/dist/tools/subagent-slots.js.map +1 -0
- package/dist/tools/subagent.d.ts +7 -2
- package/dist/tools/subagent.d.ts.map +1 -1
- package/dist/tools/subagent.js +160 -111
- package/dist/tools/subagent.js.map +1 -1
- package/dist/tools/types.d.ts +10 -9
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/types.js.map +1 -1
- package/dist/types.d.ts +5 -24
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/date.d.ts +1 -1
- package/dist/utils/date.js +1 -1
- package/dist/utils/date.js.map +1 -1
- package/dist/vault/disabled.d.ts.map +1 -1
- package/dist/vault/disabled.js +0 -1
- package/dist/vault/disabled.js.map +1 -1
- package/dist/vault/index.d.ts +0 -2
- package/dist/vault/index.d.ts.map +1 -1
- package/dist/vault/index.js +0 -10
- package/dist/vault/index.js.map +1 -1
- package/dist/vault/injection.d.ts +20 -0
- package/dist/vault/injection.d.ts.map +1 -0
- package/dist/vault/injection.js +27 -0
- package/dist/vault/injection.js.map +1 -0
- package/dist/vault/types.d.ts +0 -2
- package/dist/vault/types.d.ts.map +1 -1
- package/dist/vault/types.js.map +1 -1
- package/dist/web/admin/portal.d.ts +3 -3
- package/dist/web/admin/portal.d.ts.map +1 -1
- package/dist/web/admin/portal.js +41 -39
- package/dist/web/admin/portal.js.map +1 -1
- package/dist/web/admin/types.d.ts +3 -0
- package/dist/web/admin/types.d.ts.map +1 -1
- package/dist/web/admin/types.js.map +1 -1
- package/dist/web/agent-events/portal.d.ts.map +1 -1
- package/dist/web/agent-events/portal.js +2 -1
- package/dist/web/agent-events/portal.js.map +1 -1
- package/package.json +1 -1
- package/dist/sessions/agent-memory-file-manager.d.ts +0 -19
- package/dist/sessions/agent-memory-file-manager.d.ts.map +0 -1
- package/dist/sessions/agent-memory-file-manager.js.map +0 -1
- package/dist/vault/routing.d.ts +0 -4
- package/dist/vault/routing.d.ts.map +0 -1
- package/dist/vault/routing.js +0 -6
- package/dist/vault/routing.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../../src/tools/sandbox.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAGzC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../../src/tools/sandbox.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport { Type } from \"@sinclair/typebox\";\nimport type { SandboxConfig } from \"../sandbox/index.js\";\nimport type { ResourceLimits, SandboxResourceController } from \"../types.js\";\nimport { actorKey } from \"../sandbox/identity.js\";\n\nconst sandboxSchema = Type.Object({\n action: Type.Union([Type.Literal(\"status\"), Type.Literal(\"set\")], {\n description: \"Use status to inspect current limits, or set to apply temporary limits.\",\n }),\n cpus: Type.Optional(\n Type.String({\n description: \"CPU limit for action=set, for example '0.5', '1', or '2'.\",\n }),\n ),\n memory: Type.Optional(\n Type.String({\n description: \"Docker memory limit for action=set, for example '512m', '1g', or '4g'.\",\n }),\n ),\n});\n\ntype SandboxToolParams = {\n action: \"status\" | \"set\";\n cpus?: string;\n memory?: string;\n};\n\ninterface SandboxToolContext {\n userId: string;\n conversationId: string;\n}\n\ninterface SandboxToolController {\n sandbox: SandboxConfig;\n resourceController?: Pick<SandboxResourceController, \"getLimitStatus\" | \"setLimits\">;\n}\n\nexport function createSandboxTool(controller: SandboxToolController): {\n tool: AgentTool<typeof sandboxSchema>;\n setSandboxContext: (context: SandboxToolContext) => void;\n} {\n let sandboxContext: SandboxToolContext | null = null;\n\n const tool: AgentTool<typeof sandboxSchema> = {\n name: \"sandbox\",\n label: \"sandbox\",\n description:\n \"Inspect or temporarily set CPU/memory limits for the current managed sandbox. Limits apply to this conversation's runtime and are cleared when it stops.\",\n parameters: sandboxSchema,\n execute: async (_toolCallId: string, params: SandboxToolParams, signal?: AbortSignal) => {\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n if (!sandboxContext) {\n throw new Error(\"Sandbox context not configured\");\n }\n if (\n (controller.sandbox.type !== \"image\" && controller.sandbox.type !== \"gondolin\") ||\n !controller.resourceController\n ) {\n throw new Error(\"The sandbox tool only supports image:* and gondolin:* managed sandboxes\");\n }\n\n const containerKey = actorKey(controller.sandbox, {\n userId: sandboxContext.userId,\n conversationId: sandboxContext.conversationId,\n });\n\n if (params.action === \"set\") {\n const limits = normalizeLimits(params);\n const status = await controller.resourceController.setLimits(containerKey, limits);\n return textResult(\n `Updated sandbox limits for ${containerKey}: ${formatLimits(status.limits)}. These temporary limits are cleared when the sandbox runtime stops.`,\n );\n }\n\n const status = controller.resourceController.getLimitStatus(containerKey);\n return textResult(\n `Sandbox limits for ${containerKey}: ${formatLimits(status.limits)}${status.boosted ? \" (boosted)\" : \"\"}.`,\n );\n },\n };\n\n return {\n tool,\n setSandboxContext: (context: SandboxToolContext) => {\n sandboxContext = context;\n },\n };\n}\n\nfunction normalizeLimits(params: SandboxToolParams): ResourceLimits {\n const cpus = normalizeLimitValue(\"cpus\", params.cpus);\n const memory = normalizeLimitValue(\"memory\", params.memory);\n if (!cpus && !memory) {\n throw new Error(\"action=set requires cpus and/or memory\");\n }\n return { ...(cpus ? { cpus } : {}), ...(memory ? { memory } : {}) };\n}\n\nfunction normalizeLimitValue(name: string, value: string | undefined): string | undefined {\n if (value === undefined) return undefined;\n const trimmed = value.trim();\n if (!trimmed) return undefined;\n if (!/^[A-Za-z0-9_.-]+$/.test(trimmed)) {\n throw new Error(`${name} must not contain whitespace or shell metacharacters`);\n }\n return trimmed;\n}\n\nfunction formatLimits(limits: ResourceLimits | undefined): string {\n return `CPU ${limits?.cpus ?? \"unlimited\"} / Memory ${limits?.memory ?? \"unlimited\"}`;\n}\n\nfunction textResult(text: string): {\n content: Array<{ type: \"text\"; text: string }>;\n details: undefined;\n} {\n return { content: [{ type: \"text\", text }], details: undefined };\n}\n"]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Process-wide subagent fan-out account. The per-conversation queues
|
|
3
|
+
* serialize agent runs, and each run's subagent tool bounds its own fan-out
|
|
4
|
+
* — but without a shared ceiling, N busy conversations hold N × per-run-cap
|
|
5
|
+
* live subagent sessions. Every subagent launch draws a slot from one shared
|
|
6
|
+
* pool; the per-run cap and this global ceiling are the two bounds, both
|
|
7
|
+
* enforced at the same seam (the tool's slot acquisition).
|
|
8
|
+
*/
|
|
9
|
+
/** Default process-wide ceiling on concurrently live subagent sessions. */
|
|
10
|
+
export declare const DEFAULT_GLOBAL_SUBAGENT_SLOTS = 8;
|
|
11
|
+
/** Async slot pool: at most `capacity` concurrent holders, FIFO waiters. */
|
|
12
|
+
export declare class SubagentSlotPool {
|
|
13
|
+
readonly capacity: number;
|
|
14
|
+
private held;
|
|
15
|
+
private waiters;
|
|
16
|
+
constructor(capacity: number);
|
|
17
|
+
/** Currently held slots (for tests and capacity reporting). */
|
|
18
|
+
get inFlight(): number;
|
|
19
|
+
/**
|
|
20
|
+
* Resolve with a release function once a slot frees up. Call the release
|
|
21
|
+
* exactly once; releasing hands the slot to the oldest waiter.
|
|
22
|
+
*/
|
|
23
|
+
acquire(): Promise<() => void>;
|
|
24
|
+
private releaser;
|
|
25
|
+
}
|
|
26
|
+
/** A pool that never blocks — the default when no shared ceiling is wired. */
|
|
27
|
+
export declare function unboundedSlotPool(): SubagentSlotPool;
|
|
28
|
+
//# sourceMappingURL=subagent-slots.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subagent-slots.d.ts","sourceRoot":"","sources":["../../src/tools/subagent-slots.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,2EAA2E;AAC3E,eAAO,MAAM,6BAA6B,IAAI,CAAC;AAE/C,4EAA4E;AAC5E,qBAAa,gBAAgB;IAIf,QAAQ,CAAC,QAAQ,EAAE,MAAM;IAHrC,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,OAAO,CAAyB;IAExC,YAAqB,QAAQ,EAAE,MAAM,EAIpC;IAED,+DAA+D;IAC/D,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED;;;OAGG;IACG,OAAO,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC,CAUnC;IAED,OAAO,CAAC,QAAQ;CAUjB;AAED,8EAA8E;AAC9E,wBAAgB,iBAAiB,IAAI,gBAAgB,CAEpD"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Process-wide subagent fan-out account. The per-conversation queues
|
|
3
|
+
* serialize agent runs, and each run's subagent tool bounds its own fan-out
|
|
4
|
+
* — but without a shared ceiling, N busy conversations hold N × per-run-cap
|
|
5
|
+
* live subagent sessions. Every subagent launch draws a slot from one shared
|
|
6
|
+
* pool; the per-run cap and this global ceiling are the two bounds, both
|
|
7
|
+
* enforced at the same seam (the tool's slot acquisition).
|
|
8
|
+
*/
|
|
9
|
+
/** Default process-wide ceiling on concurrently live subagent sessions. */
|
|
10
|
+
export const DEFAULT_GLOBAL_SUBAGENT_SLOTS = 8;
|
|
11
|
+
/** Async slot pool: at most `capacity` concurrent holders, FIFO waiters. */
|
|
12
|
+
export class SubagentSlotPool {
|
|
13
|
+
constructor(capacity) {
|
|
14
|
+
this.capacity = capacity;
|
|
15
|
+
this.held = 0;
|
|
16
|
+
this.waiters = [];
|
|
17
|
+
if (!(capacity >= 1)) {
|
|
18
|
+
throw new Error(`SubagentSlotPool capacity must be >= 1, got ${capacity}`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/** Currently held slots (for tests and capacity reporting). */
|
|
22
|
+
get inFlight() {
|
|
23
|
+
return this.held;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Resolve with a release function once a slot frees up. Call the release
|
|
27
|
+
* exactly once; releasing hands the slot to the oldest waiter.
|
|
28
|
+
*/
|
|
29
|
+
async acquire() {
|
|
30
|
+
if (this.held < this.capacity) {
|
|
31
|
+
this.held += 1;
|
|
32
|
+
return this.releaser();
|
|
33
|
+
}
|
|
34
|
+
await new Promise((resolve) => {
|
|
35
|
+
this.waiters.push(resolve);
|
|
36
|
+
});
|
|
37
|
+
this.held += 1;
|
|
38
|
+
return this.releaser();
|
|
39
|
+
}
|
|
40
|
+
releaser() {
|
|
41
|
+
let released = false;
|
|
42
|
+
return () => {
|
|
43
|
+
if (released)
|
|
44
|
+
return;
|
|
45
|
+
released = true;
|
|
46
|
+
this.held -= 1;
|
|
47
|
+
const next = this.waiters.shift();
|
|
48
|
+
if (next)
|
|
49
|
+
next();
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/** A pool that never blocks — the default when no shared ceiling is wired. */
|
|
54
|
+
export function unboundedSlotPool() {
|
|
55
|
+
return new SubagentSlotPool(Number.MAX_SAFE_INTEGER);
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=subagent-slots.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subagent-slots.js","sourceRoot":"","sources":["../../src/tools/subagent-slots.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,2EAA2E;AAC3E,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,CAAC;AAE/C,4EAA4E;AAC5E,MAAM,OAAO,gBAAgB;IAI3B,YAAqB,QAAgB;QAAhB,aAAQ,GAAR,QAAQ,CAAQ;QAH7B,SAAI,GAAG,CAAC,CAAC;QACT,YAAO,GAAsB,EAAE,CAAC;QAGtC,IAAI,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,+CAA+C,QAAQ,EAAE,CAAC,CAAC;QAC7E,CAAC;IACH,CAAC;IAED,+DAA+D;IAC/D,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,OAAO;QACX,IAAI,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC9B,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC;YACf,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC;QACzB,CAAC;QACD,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YAClC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC;QACf,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC;IACzB,CAAC;IAEO,QAAQ;QACd,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,OAAO,GAAG,EAAE;YACV,IAAI,QAAQ;gBAAE,OAAO;YACrB,QAAQ,GAAG,IAAI,CAAC;YAChB,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC;YACf,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YAClC,IAAI,IAAI;gBAAE,IAAI,EAAE,CAAC;QACnB,CAAC,CAAC;IACJ,CAAC;CACF;AAED,8EAA8E;AAC9E,MAAM,UAAU,iBAAiB;IAC/B,OAAO,IAAI,gBAAgB,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;AACvD,CAAC","sourcesContent":["/**\n * Process-wide subagent fan-out account. The per-conversation queues\n * serialize agent runs, and each run's subagent tool bounds its own fan-out\n * — but without a shared ceiling, N busy conversations hold N × per-run-cap\n * live subagent sessions. Every subagent launch draws a slot from one shared\n * pool; the per-run cap and this global ceiling are the two bounds, both\n * enforced at the same seam (the tool's slot acquisition).\n */\n\n/** Default process-wide ceiling on concurrently live subagent sessions. */\nexport const DEFAULT_GLOBAL_SUBAGENT_SLOTS = 8;\n\n/** Async slot pool: at most `capacity` concurrent holders, FIFO waiters. */\nexport class SubagentSlotPool {\n private held = 0;\n private waiters: Array<() => void> = [];\n\n constructor(readonly capacity: number) {\n if (!(capacity >= 1)) {\n throw new Error(`SubagentSlotPool capacity must be >= 1, got ${capacity}`);\n }\n }\n\n /** Currently held slots (for tests and capacity reporting). */\n get inFlight(): number {\n return this.held;\n }\n\n /**\n * Resolve with a release function once a slot frees up. Call the release\n * exactly once; releasing hands the slot to the oldest waiter.\n */\n async acquire(): Promise<() => void> {\n if (this.held < this.capacity) {\n this.held += 1;\n return this.releaser();\n }\n await new Promise<void>((resolve) => {\n this.waiters.push(resolve);\n });\n this.held += 1;\n return this.releaser();\n }\n\n private releaser(): () => void {\n let released = false;\n return () => {\n if (released) return;\n released = true;\n this.held -= 1;\n const next = this.waiters.shift();\n if (next) next();\n };\n }\n}\n\n/** A pool that never blocks — the default when no shared ceiling is wired. */\nexport function unboundedSlotPool(): SubagentSlotPool {\n return new SubagentSlotPool(Number.MAX_SAFE_INTEGER);\n}\n"]}
|
package/dist/tools/subagent.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AgentTool } from "@earendil-works/pi-agent-core";
|
|
2
2
|
import { type TSchema } from "@sinclair/typebox";
|
|
3
3
|
import type { SubagentRunOutput, SubagentRunRequest, SubagentRunResult } from "../harness/types.js";
|
|
4
|
+
import { type SubagentSlotPool } from "./subagent-slots.js";
|
|
4
5
|
declare const subagentSchema: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
|
|
5
6
|
task: import("@sinclair/typebox").TString;
|
|
6
7
|
label: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
@@ -63,7 +64,11 @@ declare const subagentSchema: import("@sinclair/typebox").TUnion<[import("@sincl
|
|
|
63
64
|
}>;
|
|
64
65
|
}>]>;
|
|
65
66
|
type RunSubagent = <TOutputSchema extends TSchema | undefined = undefined>(request: SubagentRunRequest<TOutputSchema>) => Promise<SubagentRunResult<SubagentRunOutput<TOutputSchema>>>;
|
|
66
|
-
/**
|
|
67
|
-
|
|
67
|
+
/**
|
|
68
|
+
* Create the normal agent's bounded subagent delegation and DAG tool.
|
|
69
|
+
* `globalSlots` is the process-wide fan-out account shared across every
|
|
70
|
+
* conversation's tool instance; omitted, fan-out is bounded per run only.
|
|
71
|
+
*/
|
|
72
|
+
export declare function createSubagentTool(runSubagent: RunSubagent, globalSlots?: SubagentSlotPool): AgentTool<typeof subagentSchema>;
|
|
68
73
|
export {};
|
|
69
74
|
//# sourceMappingURL=subagent.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subagent.d.ts","sourceRoot":"","sources":["../../src/tools/subagent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAA2B,MAAM,+BAA+B,CAAC;AACxF,OAAO,EAAqB,KAAK,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACpE,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"subagent.d.ts","sourceRoot":"","sources":["../../src/tools/subagent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAA2B,MAAM,+BAA+B,CAAC;AACxF,OAAO,EAAqB,KAAK,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACpE,OAAO,KAAK,EACV,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EAElB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAqD/E,QAAA,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAwBlB,CAAC;AAMH,KAAK,WAAW,GAAG,CAAC,aAAa,SAAS,OAAO,GAAG,SAAS,GAAG,SAAS,EACvE,OAAO,EAAE,kBAAkB,CAAC,aAAa,CAAC,KACvC,OAAO,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;AA8RlE;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,WAAW,EACxB,WAAW,GAAE,gBAAsC,GAClD,SAAS,CAAC,OAAO,cAAc,CAAC,CAgElC"}
|
package/dist/tools/subagent.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { Type } from "@sinclair/typebox";
|
|
2
|
+
import { unboundedSlotPool } from "./subagent-slots.js";
|
|
2
3
|
const MAX_DAG_NODES = 8;
|
|
3
4
|
const MAX_DAG_EDGES = 16;
|
|
4
5
|
const MAX_DAG_DEPTH = 4;
|
|
5
|
-
const
|
|
6
|
+
const MAX_CONCURRENT_SUBAGENTS = 4;
|
|
6
7
|
const MAX_DEPENDENCY_OUTPUT_CHARS = 4000;
|
|
7
8
|
const taskProperties = {
|
|
8
|
-
task: Type.String({ description: "Self-contained task for a fresh subagent." }),
|
|
9
|
+
task: Type.String({ minLength: 1, description: "Self-contained task for a fresh subagent." }),
|
|
9
10
|
label: Type.Optional(Type.String({ maxLength: 64, description: "Short progress label for this subagent." })),
|
|
10
11
|
systemPrompt: Type.Optional(Type.String({ description: "Optional role or behavior instructions for the subagent." })),
|
|
11
12
|
input: Type.Optional(Type.Unknown({ description: "Optional JSON-serializable structured input for the task." })),
|
|
@@ -48,11 +49,26 @@ const subagentSchema = Type.Union([
|
|
|
48
49
|
Type.Object({
|
|
49
50
|
dag: Type.Object({
|
|
50
51
|
nodes: Type.Array(dagNodeSchema, { minItems: 1, maxItems: MAX_DAG_NODES }),
|
|
51
|
-
maxConcurrency: Type.Optional(Type.Integer({
|
|
52
|
+
maxConcurrency: Type.Optional(Type.Integer({
|
|
53
|
+
minimum: 1,
|
|
54
|
+
maximum: MAX_CONCURRENT_SUBAGENTS,
|
|
55
|
+
default: MAX_CONCURRENT_SUBAGENTS,
|
|
56
|
+
})),
|
|
52
57
|
}),
|
|
53
58
|
...sharedProperties,
|
|
54
59
|
}),
|
|
55
60
|
]);
|
|
61
|
+
const STATUS_MARKER = {
|
|
62
|
+
pending: "○",
|
|
63
|
+
running: "●",
|
|
64
|
+
completed: "✓",
|
|
65
|
+
failed: "✗",
|
|
66
|
+
cancelled: "✗",
|
|
67
|
+
timeout: "✗",
|
|
68
|
+
budget_exceeded: "✗",
|
|
69
|
+
invalid_output: "✗",
|
|
70
|
+
skipped: "⊘",
|
|
71
|
+
};
|
|
56
72
|
class SubagentProgressTracker {
|
|
57
73
|
constructor(mode, items, onUpdate) {
|
|
58
74
|
this.mode = mode;
|
|
@@ -73,18 +89,11 @@ class SubagentProgressTracker {
|
|
|
73
89
|
...item,
|
|
74
90
|
status: this.states.get(item.id) ?? "pending",
|
|
75
91
|
}));
|
|
76
|
-
const settled = nodes.filter((node) =>
|
|
77
|
-
const marker = {
|
|
78
|
-
pending: "○",
|
|
79
|
-
running: "●",
|
|
80
|
-
completed: "✓",
|
|
81
|
-
failed: "✗",
|
|
82
|
-
skipped: "⊘",
|
|
83
|
-
};
|
|
92
|
+
const settled = nodes.filter((node) => node.status !== "pending" && node.status !== "running").length;
|
|
84
93
|
const modeLabel = this.mode === "dag" ? "DAG" : this.mode === "parallel" ? "parallel" : "run";
|
|
85
94
|
const progressLabel = [
|
|
86
95
|
`Subagent ${modeLabel} ${settled}/${nodes.length}`,
|
|
87
|
-
...nodes.map((node) => `${
|
|
96
|
+
...nodes.map((node) => `${STATUS_MARKER[node.status]} ${node.label}`),
|
|
88
97
|
].join(" · ");
|
|
89
98
|
this.onUpdate({
|
|
90
99
|
content: [],
|
|
@@ -95,14 +104,13 @@ class SubagentProgressTracker {
|
|
|
95
104
|
function taskLabel(task, fallback) {
|
|
96
105
|
return task.label?.trim() || task.task.trim().slice(0, 48) || fallback;
|
|
97
106
|
}
|
|
98
|
-
function
|
|
99
|
-
|
|
100
|
-
}
|
|
101
|
-
function formatResult(result) {
|
|
102
|
-
if (result.status !== "completed") {
|
|
103
|
-
return `Subagent ${result.status}${result.error ? `: ${result.error}` : ""}`;
|
|
107
|
+
function formatOutcome(outcome) {
|
|
108
|
+
if (outcome.status !== "completed") {
|
|
109
|
+
return `Subagent ${outcome.status}${outcome.error ? `: ${outcome.error}` : ""}`;
|
|
104
110
|
}
|
|
105
|
-
return typeof
|
|
111
|
+
return typeof outcome.output === "string"
|
|
112
|
+
? outcome.output
|
|
113
|
+
: JSON.stringify(outcome.output, null, 2);
|
|
106
114
|
}
|
|
107
115
|
function buildRequest(task, shared, signal) {
|
|
108
116
|
const outputSchema = shared.outputSchema;
|
|
@@ -166,6 +174,48 @@ function buildDagWaves(nodes) {
|
|
|
166
174
|
}
|
|
167
175
|
return waves;
|
|
168
176
|
}
|
|
177
|
+
function itemForNode(node) {
|
|
178
|
+
return {
|
|
179
|
+
id: node.id,
|
|
180
|
+
label: node.label?.trim() || node.id,
|
|
181
|
+
task: node,
|
|
182
|
+
dependsOn: node.dependsOn ?? [],
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
/** Normalize every tool mode into one plan: nodes, waves, concurrency. */
|
|
186
|
+
function buildPlan(params) {
|
|
187
|
+
if ("dag" in params) {
|
|
188
|
+
const waves = buildDagWaves(params.dag.nodes).map((wave) => wave.map(itemForNode));
|
|
189
|
+
const requested = params.dag.maxConcurrency ?? MAX_CONCURRENT_SUBAGENTS;
|
|
190
|
+
return {
|
|
191
|
+
mode: "dag",
|
|
192
|
+
items: params.dag.nodes.map(itemForNode),
|
|
193
|
+
waves,
|
|
194
|
+
concurrency: Math.max(1, Math.min(MAX_CONCURRENT_SUBAGENTS, Math.floor(requested))),
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
if ("tasks" in params) {
|
|
198
|
+
const items = params.tasks.map((task, index) => ({
|
|
199
|
+
id: String(index),
|
|
200
|
+
label: taskLabel(task, String(index + 1)),
|
|
201
|
+
task,
|
|
202
|
+
dependsOn: [],
|
|
203
|
+
}));
|
|
204
|
+
return { mode: "parallel", items, waves: [items], concurrency: MAX_CONCURRENT_SUBAGENTS };
|
|
205
|
+
}
|
|
206
|
+
const item = { id: "0", label: taskLabel(params, "subagent"), task: params, dependsOn: [] };
|
|
207
|
+
return { mode: "single", items: [item], waves: [[item]], concurrency: 1 };
|
|
208
|
+
}
|
|
209
|
+
/** Run `worker` over every item with at most `limit` in flight. */
|
|
210
|
+
async function forEachConcurrent(items, limit, worker) {
|
|
211
|
+
let cursor = 0;
|
|
212
|
+
await Promise.all(Array.from({ length: Math.min(limit, items.length) }, async () => {
|
|
213
|
+
while (cursor < items.length) {
|
|
214
|
+
const index = cursor++;
|
|
215
|
+
await worker(items[index], index);
|
|
216
|
+
}
|
|
217
|
+
}));
|
|
218
|
+
}
|
|
169
219
|
function dependencyOutput(outcome) {
|
|
170
220
|
if (outcome.status !== "completed")
|
|
171
221
|
return undefined;
|
|
@@ -175,111 +225,110 @@ function dependencyOutput(outcome) {
|
|
|
175
225
|
return null;
|
|
176
226
|
if (serialized.length <= MAX_DEPENDENCY_OUTPUT_CHARS)
|
|
177
227
|
return value;
|
|
228
|
+
// Oversized structured output becomes a marked string — the shape is lost,
|
|
229
|
+
// which the tool description warns downstream consumers about.
|
|
178
230
|
return `${serialized.slice(0, MAX_DEPENDENCY_OUTPUT_CHARS)}\n[truncated]`;
|
|
179
231
|
}
|
|
180
|
-
function
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
232
|
+
function planRequest(item, shared, outcomes, signal) {
|
|
233
|
+
if (item.dependsOn.length === 0)
|
|
234
|
+
return buildRequest(item.task, shared, signal);
|
|
235
|
+
const dependencies = Object.fromEntries(item.dependsOn.map((id) => [id, dependencyOutput(outcomes.get(id))]));
|
|
236
|
+
const input = {
|
|
237
|
+
...(item.task.input !== undefined ? { input: item.task.input } : {}),
|
|
238
|
+
dependencies,
|
|
239
|
+
};
|
|
240
|
+
return buildRequest({ ...item.task, input }, shared, signal);
|
|
186
241
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
242
|
+
/**
|
|
243
|
+
* One executor for every mode: wave barriers, a bounded slot pool inside
|
|
244
|
+
* each wave, and one global slot per actual subagent launch — the seam where
|
|
245
|
+
* both the per-run cap and the process-wide ceiling are enforced.
|
|
246
|
+
*/
|
|
247
|
+
async function runWaves(plan, shared, runSubagent, progress, globalSlots, signal) {
|
|
190
248
|
const outcomes = new Map();
|
|
191
|
-
for (const wave of waves) {
|
|
192
|
-
|
|
193
|
-
const
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
249
|
+
for (const wave of plan.waves) {
|
|
250
|
+
await forEachConcurrent(wave, plan.concurrency, async (item) => {
|
|
251
|
+
const failedDependency = item.dependsOn.find((id) => outcomes.get(id)?.status !== "completed");
|
|
252
|
+
if (failedDependency) {
|
|
253
|
+
outcomes.set(item.id, {
|
|
254
|
+
id: item.id,
|
|
255
|
+
status: "skipped",
|
|
256
|
+
error: `Dependency ${failedDependency} did not complete`,
|
|
257
|
+
});
|
|
258
|
+
progress.update(item.id, "skipped");
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
const release = await globalSlots.acquire();
|
|
262
|
+
let result;
|
|
263
|
+
try {
|
|
264
|
+
progress.update(item.id, "running");
|
|
265
|
+
result = await runSubagent(planRequest(item, shared, outcomes, signal));
|
|
266
|
+
}
|
|
267
|
+
finally {
|
|
268
|
+
release();
|
|
269
|
+
}
|
|
270
|
+
outcomes.set(item.id, { id: item.id, ...result });
|
|
271
|
+
progress.update(item.id, result.status);
|
|
272
|
+
});
|
|
212
273
|
}
|
|
213
|
-
return
|
|
214
|
-
waves: waves.map((wave) => wave.map((node) => node.id)),
|
|
215
|
-
results: nodes.map((node) => outcomes.get(node.id)),
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
function formatDagOutcome(outcome) {
|
|
219
|
-
if (outcome.status === "skipped")
|
|
220
|
-
return `Subagent skipped: ${outcome.error}`;
|
|
221
|
-
return formatResult(outcome);
|
|
274
|
+
return plan.items.map((item) => outcomes.get(item.id));
|
|
222
275
|
}
|
|
223
|
-
/**
|
|
224
|
-
|
|
276
|
+
/**
|
|
277
|
+
* Create the normal agent's bounded subagent delegation and DAG tool.
|
|
278
|
+
* `globalSlots` is the process-wide fan-out account shared across every
|
|
279
|
+
* conversation's tool instance; omitted, fan-out is bounded per run only.
|
|
280
|
+
*/
|
|
281
|
+
export function createSubagentTool(runSubagent, globalSlots = unboundedSlotPool()) {
|
|
225
282
|
return {
|
|
226
283
|
name: "subagent",
|
|
227
284
|
label: "Subagent",
|
|
228
|
-
description:
|
|
285
|
+
description: `Run fresh isolated subagents. Use task for one subagent, tasks for independent concurrent work, or dag.nodes for a bounded dependency graph. At most ${MAX_CONCURRENT_SUBAGENTS} subagents run concurrently. DAG limits: ${MAX_DAG_NODES} nodes, ${MAX_DAG_EDGES} edges, depth ${MAX_DAG_DEPTH}; failed dependencies skip descendants, and dependency outputs larger than ${MAX_DEPENDENCY_OUTPUT_CHARS} characters reach downstream nodes as a truncated string. ` +
|
|
286
|
+
"Subagents have no history or tools unless explicitly provided; nested subagents are not allowed.",
|
|
229
287
|
parameters: subagentSchema,
|
|
230
288
|
execute: async (_toolCallId, params, signal, onUpdate) => {
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
if ("tasks" in params) {
|
|
251
|
-
const progress = new SubagentProgressTracker("parallel", params.tasks.map((task, index) => ({
|
|
252
|
-
id: String(index),
|
|
253
|
-
label: taskLabel(task, String(index + 1)),
|
|
254
|
-
})), onUpdate);
|
|
255
|
-
progress.emit();
|
|
256
|
-
const results = await Promise.all(params.tasks.map(async (task, index) => {
|
|
257
|
-
const id = String(index);
|
|
258
|
-
progress.update(id, "running");
|
|
259
|
-
const result = await runSubagent(buildRequest(task, params, signal));
|
|
260
|
-
progress.update(id, resultProgressStatus(result));
|
|
261
|
-
return result;
|
|
262
|
-
}));
|
|
263
|
-
return {
|
|
264
|
-
content: [
|
|
265
|
-
{
|
|
266
|
-
type: "text",
|
|
267
|
-
text: results
|
|
268
|
-
.map((result, index) => `[${index + 1}] ${formatResult(result)}`)
|
|
269
|
-
.join("\n\n"),
|
|
289
|
+
const plan = buildPlan(params);
|
|
290
|
+
const progress = new SubagentProgressTracker(plan.mode, plan.items.map(({ id, label }) => ({ id, label })), onUpdate);
|
|
291
|
+
progress.emit();
|
|
292
|
+
const ordered = await runWaves(plan, params, runSubagent, progress, globalSlots, signal);
|
|
293
|
+
switch (plan.mode) {
|
|
294
|
+
case "dag":
|
|
295
|
+
return {
|
|
296
|
+
content: [
|
|
297
|
+
{
|
|
298
|
+
type: "text",
|
|
299
|
+
text: ordered
|
|
300
|
+
.map((outcome) => `[${outcome.id}] ${formatOutcome(outcome)}`)
|
|
301
|
+
.join("\n\n"),
|
|
302
|
+
},
|
|
303
|
+
],
|
|
304
|
+
details: {
|
|
305
|
+
mode: "dag",
|
|
306
|
+
waves: plan.waves.map((wave) => wave.map((item) => item.id)),
|
|
307
|
+
results: ordered,
|
|
270
308
|
},
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
309
|
+
};
|
|
310
|
+
case "parallel": {
|
|
311
|
+
const results = ordered.map(({ id: _id, ...result }) => result);
|
|
312
|
+
return {
|
|
313
|
+
content: [
|
|
314
|
+
{
|
|
315
|
+
type: "text",
|
|
316
|
+
text: results
|
|
317
|
+
.map((result, index) => `[${index + 1}] ${formatOutcome(result)}`)
|
|
318
|
+
.join("\n\n"),
|
|
319
|
+
},
|
|
320
|
+
],
|
|
321
|
+
details: { mode: "parallel", results },
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
case "single": {
|
|
325
|
+
const { id: _id, ...result } = ordered[0];
|
|
326
|
+
return {
|
|
327
|
+
content: [{ type: "text", text: formatOutcome(result) }],
|
|
328
|
+
details: result,
|
|
329
|
+
};
|
|
330
|
+
}
|
|
274
331
|
}
|
|
275
|
-
const progress = new SubagentProgressTracker("single", [{ id: "0", label: taskLabel(params, "subagent") }], onUpdate);
|
|
276
|
-
progress.update("0", "running");
|
|
277
|
-
const result = await runSubagent(buildRequest(params, params, signal));
|
|
278
|
-
progress.update("0", resultProgressStatus(result));
|
|
279
|
-
return {
|
|
280
|
-
content: [{ type: "text", text: formatResult(result) }],
|
|
281
|
-
details: result,
|
|
282
|
-
};
|
|
283
332
|
},
|
|
284
333
|
};
|
|
285
334
|
}
|