@clinebot/core 0.0.27 → 0.0.29
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/README.md +7 -0
- package/dist/ClineCore.d.ts +28 -2
- package/dist/ClineCore.d.ts.map +1 -1
- package/dist/account/cline-account-service.d.ts +1 -1
- package/dist/account/cline-account-service.d.ts.map +1 -1
- package/dist/account/index.d.ts +1 -1
- package/dist/account/index.d.ts.map +1 -1
- package/dist/account/types.d.ts +5 -0
- package/dist/account/types.d.ts.map +1 -1
- package/dist/auth/bounded-ttl-cache.d.ts +14 -0
- package/dist/auth/bounded-ttl-cache.d.ts.map +1 -0
- package/dist/auth/cline.d.ts +27 -2
- package/dist/auth/cline.d.ts.map +1 -1
- package/dist/auth/oca.d.ts.map +1 -1
- package/dist/chat/chat-schema.d.ts +8 -8
- package/dist/extensions/config/agent-config-loader.d.ts.map +1 -0
- package/dist/{agents → extensions/config}/agent-config-parser.d.ts +2 -2
- package/dist/extensions/config/agent-config-parser.d.ts.map +1 -0
- package/dist/{agents → extensions/config}/hooks-config-loader.d.ts +1 -1
- package/dist/extensions/config/hooks-config-loader.d.ts.map +1 -0
- package/dist/{agents → extensions/config}/index.d.ts +2 -4
- package/dist/extensions/config/index.d.ts.map +1 -0
- package/dist/{runtime/commands.d.ts → extensions/config/runtime-commands.d.ts} +2 -3
- package/dist/extensions/config/runtime-commands.d.ts.map +1 -0
- package/dist/extensions/config/unified-config-file-watcher.d.ts.map +1 -0
- package/dist/extensions/config/user-instruction-config-loader.d.ts.map +1 -0
- package/dist/extensions/context/agentic-compaction.d.ts +13 -0
- package/dist/extensions/context/agentic-compaction.d.ts.map +1 -0
- package/dist/extensions/context/basic-compaction.d.ts +9 -0
- package/dist/extensions/context/basic-compaction.d.ts.map +1 -0
- package/dist/extensions/context/compaction-shared.d.ts +60 -0
- package/dist/extensions/context/compaction-shared.d.ts.map +1 -0
- package/dist/extensions/context/compaction.d.ts +20 -0
- package/dist/extensions/context/compaction.d.ts.map +1 -0
- package/dist/extensions/index.d.ts +5 -0
- package/dist/extensions/index.d.ts.map +1 -0
- package/dist/extensions/mcp/client.d.ts +3 -0
- package/dist/extensions/mcp/client.d.ts.map +1 -0
- package/dist/extensions/mcp/config-loader.d.ts.map +1 -0
- package/dist/extensions/mcp/index.d.ts +9 -0
- package/dist/extensions/mcp/index.d.ts.map +1 -0
- package/dist/{mcp → extensions/mcp}/manager.d.ts +1 -2
- package/dist/extensions/mcp/manager.d.ts.map +1 -0
- package/dist/extensions/mcp/name-transform.d.ts +3 -0
- package/dist/extensions/mcp/name-transform.d.ts.map +1 -0
- package/dist/extensions/mcp/policies.d.ts +15 -0
- package/dist/extensions/mcp/policies.d.ts.map +1 -0
- package/dist/extensions/mcp/tools.d.ts +4 -0
- package/dist/extensions/mcp/tools.d.ts.map +1 -0
- package/dist/{mcp → extensions/mcp}/types.d.ts +29 -1
- package/dist/extensions/mcp/types.d.ts.map +1 -0
- package/dist/{agents → extensions/plugin}/plugin-config-loader.d.ts +1 -1
- package/dist/extensions/plugin/plugin-config-loader.d.ts.map +1 -0
- package/dist/{agents → extensions/plugin}/plugin-loader.d.ts +1 -1
- package/dist/extensions/plugin/plugin-loader.d.ts.map +1 -0
- package/dist/extensions/plugin/plugin-module-import.d.ts +5 -0
- package/dist/extensions/plugin/plugin-module-import.d.ts.map +1 -0
- package/dist/{agents → extensions/plugin}/plugin-sandbox.d.ts +1 -1
- package/dist/extensions/plugin/plugin-sandbox.d.ts.map +1 -0
- package/dist/extensions/plugin-sandbox-bootstrap.js +485 -0
- package/dist/hooks/index.d.ts +4 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/persistent.d.ts +64 -0
- package/dist/hooks/persistent.d.ts.map +1 -0
- package/dist/hooks/subprocess-runner.d.ts +22 -0
- package/dist/hooks/subprocess-runner.d.ts.map +1 -0
- package/dist/hooks/subprocess.d.ts +189 -0
- package/dist/hooks/subprocess.d.ts.map +1 -0
- package/dist/index.d.ts +22 -25
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +560 -447
- package/dist/prompt/default-system.d.ts +2 -0
- package/dist/prompt/default-system.d.ts.map +1 -0
- package/dist/providers/local-provider-service.d.ts +1 -1
- package/dist/providers/local-provider-service.d.ts.map +1 -1
- package/dist/runtime/checkpoint-hooks.d.ts +21 -0
- package/dist/runtime/checkpoint-hooks.d.ts.map +1 -0
- package/dist/runtime/hook-file-hooks.d.ts +1 -1
- package/dist/runtime/hook-file-hooks.d.ts.map +1 -1
- package/dist/runtime/rules.d.ts +1 -1
- package/dist/runtime/rules.d.ts.map +1 -1
- package/dist/runtime/runtime-builder.d.ts +1 -1
- package/dist/runtime/runtime-builder.d.ts.map +1 -1
- package/dist/runtime/session-runtime.d.ts +25 -5
- package/dist/runtime/session-runtime.d.ts.map +1 -1
- package/dist/runtime/subprocess-sandbox.d.ts.map +1 -0
- package/dist/runtime/team-runtime-registry.d.ts +1 -1
- package/dist/runtime/team-runtime-registry.d.ts.map +1 -1
- package/dist/runtime/tool-approval.d.ts +1 -1
- package/dist/session/default-session-manager.d.ts +4 -3
- package/dist/session/default-session-manager.d.ts.map +1 -1
- package/dist/session/file-session-service.d.ts +1 -1
- package/dist/session/file-session-service.d.ts.map +1 -1
- package/dist/session/{unified-session-persistence-service.d.ts → persistence-service.d.ts} +11 -42
- package/dist/session/persistence-service.d.ts.map +1 -0
- package/dist/session/rpc-session-service.d.ts +1 -1
- package/dist/session/rpc-session-service.d.ts.map +1 -1
- package/dist/session/session-agent-events.d.ts +1 -1
- package/dist/session/session-artifacts.d.ts.map +1 -1
- package/dist/session/session-config-builder.d.ts.map +1 -1
- package/dist/session/session-graph.d.ts +1 -1
- package/dist/session/session-graph.d.ts.map +1 -1
- package/dist/session/session-host.d.ts.map +1 -1
- package/dist/session/session-manager.d.ts +6 -5
- package/dist/session/session-manager.d.ts.map +1 -1
- package/dist/session/session-manifest.d.ts +1 -1
- package/dist/session/session-service.d.ts +3 -2
- package/dist/session/session-service.d.ts.map +1 -1
- package/dist/session/session-team-coordination.d.ts +2 -1
- package/dist/session/session-team-coordination.d.ts.map +1 -1
- package/dist/session/utils/helpers.d.ts +51 -3
- package/dist/session/utils/helpers.d.ts.map +1 -1
- package/dist/session/utils/types.d.ts +41 -7
- package/dist/session/utils/types.d.ts.map +1 -1
- package/dist/session/workspace-manager.d.ts +1 -2
- package/dist/session/workspace-manager.d.ts.map +1 -1
- package/dist/session/workspace-manifest.d.ts +1 -22
- package/dist/session/workspace-manifest.d.ts.map +1 -1
- package/dist/storage/file-team-store.d.ts +2 -1
- package/dist/storage/file-team-store.d.ts.map +1 -1
- package/dist/storage/sqlite-team-store.d.ts +4 -1
- package/dist/storage/sqlite-team-store.d.ts.map +1 -1
- package/dist/storage/team-store.d.ts.map +1 -1
- package/dist/team/delegated-agent.d.ts +44 -0
- package/dist/team/delegated-agent.d.ts.map +1 -0
- package/dist/team/index.d.ts +1 -0
- package/dist/team/index.d.ts.map +1 -1
- package/dist/team/multi-agent.d.ts +229 -0
- package/dist/team/multi-agent.d.ts.map +1 -0
- package/dist/team/projections.d.ts +2 -2
- package/dist/team/projections.d.ts.map +1 -1
- package/dist/team/runtime.d.ts +5 -0
- package/dist/team/runtime.d.ts.map +1 -0
- package/dist/team/spawn-agent-tool.d.ts +85 -0
- package/dist/team/spawn-agent-tool.d.ts.map +1 -0
- package/dist/team/subagent-prompts.d.ts +4 -0
- package/dist/team/subagent-prompts.d.ts.map +1 -0
- package/dist/team/team-tools.d.ts +35 -0
- package/dist/team/team-tools.d.ts.map +1 -0
- package/dist/telemetry/OpenTelemetryProvider.d.ts +11 -1
- package/dist/telemetry/OpenTelemetryProvider.d.ts.map +1 -1
- package/dist/telemetry/{LoggerTelemetryAdapter.d.ts → TelemetryLoggerSink.d.ts} +10 -4
- package/dist/telemetry/TelemetryLoggerSink.d.ts.map +1 -0
- package/dist/telemetry/TelemetryService.d.ts.map +1 -1
- package/dist/telemetry/index.js +15 -28
- package/dist/tools/definitions.d.ts +4 -3
- package/dist/tools/definitions.d.ts.map +1 -1
- package/dist/tools/index.d.ts +5 -5
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/model-tool-routing.d.ts.map +1 -1
- package/dist/tools/presets.d.ts +26 -0
- package/dist/tools/presets.d.ts.map +1 -1
- package/dist/tools/schemas.d.ts +8 -0
- package/dist/tools/schemas.d.ts.map +1 -1
- package/dist/tools/types.d.ts +23 -2
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/types/config.d.ts +47 -3
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/events.d.ts +1 -1
- package/dist/types/provider-settings.d.ts +1 -1
- package/dist/types/provider-settings.d.ts.map +1 -1
- package/dist/types/storage.d.ts +2 -1
- package/dist/types/storage.d.ts.map +1 -1
- package/dist/types.d.ts +7 -16
- package/dist/types.d.ts.map +1 -1
- package/package.json +16 -13
- package/src/ClineCore.test.ts +150 -0
- package/src/ClineCore.ts +114 -8
- package/src/account/cline-account-service.test.ts +84 -0
- package/src/account/cline-account-service.ts +2 -2
- package/src/account/index.ts +1 -0
- package/src/account/types.ts +6 -0
- package/src/auth/bounded-ttl-cache.test.ts +38 -0
- package/src/auth/bounded-ttl-cache.ts +53 -0
- package/src/auth/cline.test.ts +173 -36
- package/src/auth/cline.ts +395 -93
- package/src/auth/oca.test.ts +125 -0
- package/src/auth/oca.ts +17 -4
- package/src/{agents → extensions/config}/agent-config-loader.test.ts +1 -1
- package/src/{agents → extensions/config}/agent-config-parser.ts +2 -2
- package/src/{agents → extensions/config}/hooks-config-loader.ts +1 -1
- package/src/{agents → extensions/config}/index.ts +7 -11
- package/src/{runtime/commands.test.ts → extensions/config/runtime-commands.test.ts} +20 -3
- package/src/{runtime/commands.ts → extensions/config/runtime-commands.ts} +1 -8
- package/src/{agents → extensions/config}/unified-config-file-watcher.ts +15 -2
- package/src/{agents → extensions/config}/user-instruction-config-loader.test.ts +90 -2
- package/src/{agents → extensions/config}/user-instruction-config-loader.ts +126 -12
- package/src/extensions/context/agentic-compaction.ts +119 -0
- package/src/extensions/context/basic-compaction.ts +275 -0
- package/src/extensions/context/compaction-shared.ts +458 -0
- package/src/extensions/context/compaction.test.ts +477 -0
- package/src/extensions/context/compaction.ts +203 -0
- package/src/extensions/index.ts +12 -0
- package/src/extensions/mcp/client.ts +420 -0
- package/src/{mcp → extensions/mcp}/index.ts +16 -0
- package/src/{mcp → extensions/mcp}/manager.test.ts +1 -2
- package/src/{mcp → extensions/mcp}/manager.ts +3 -5
- package/src/extensions/mcp/name-transform.ts +33 -0
- package/src/extensions/mcp/policies.ts +47 -0
- package/src/extensions/mcp/tools.ts +47 -0
- package/src/{mcp → extensions/mcp}/types.ts +35 -7
- package/src/{agents → extensions/plugin}/plugin-config-loader.test.ts +18 -13
- package/src/{agents → extensions/plugin}/plugin-config-loader.ts +1 -1
- package/src/{agents → extensions/plugin}/plugin-loader.test.ts +41 -4
- package/src/extensions/plugin/plugin-loader.ts +106 -0
- package/src/extensions/plugin/plugin-module-import.ts +278 -0
- package/src/{agents → extensions/plugin}/plugin-sandbox-bootstrap.ts +30 -92
- package/src/{agents → extensions/plugin}/plugin-sandbox.test.ts +60 -3
- package/src/{agents → extensions/plugin}/plugin-sandbox.ts +146 -56
- package/src/hooks/index.ts +25 -0
- package/src/hooks/persistent.ts +661 -0
- package/src/hooks/subprocess-runner.ts +196 -0
- package/src/hooks/subprocess.ts +669 -0
- package/src/index.ts +200 -118
- package/src/prompt/default-system.ts +21 -0
- package/src/providers/local-provider-registry.ts +1 -1
- package/src/providers/local-provider-service.test.ts +23 -2
- package/src/providers/local-provider-service.ts +2 -2
- package/src/runtime/checkpoint-hooks.test.ts +167 -0
- package/src/runtime/checkpoint-hooks.ts +186 -0
- package/src/runtime/hook-file-hooks.test.ts +40 -1
- package/src/runtime/hook-file-hooks.ts +35 -16
- package/src/runtime/index.ts +4 -19
- package/src/runtime/rules.ts +4 -1
- package/src/runtime/runtime-builder.team-persistence.test.ts +3 -6
- package/src/runtime/runtime-builder.test.ts +266 -160
- package/src/runtime/runtime-builder.ts +120 -47
- package/src/runtime/runtime-parity.test.ts +22 -22
- package/src/runtime/session-runtime.ts +36 -6
- package/src/runtime/{sandbox/subprocess-sandbox.ts → subprocess-sandbox.ts} +24 -3
- package/src/runtime/team-runtime-registry.ts +1 -4
- package/src/runtime/tool-approval.ts +1 -1
- package/src/session/default-session-manager.e2e.test.ts +2 -2
- package/src/session/default-session-manager.test.ts +553 -9
- package/src/session/default-session-manager.ts +140 -46
- package/src/session/file-session-service.ts +3 -3
- package/src/session/index.ts +6 -6
- package/src/session/persistence-service.test.ts +212 -0
- package/src/session/{unified-session-persistence-service.ts → persistence-service.ts} +106 -172
- package/src/session/rpc-session-service.ts +3 -3
- package/src/session/runtime-oauth-token-manager.ts +1 -1
- package/src/session/session-agent-events.ts +1 -1
- package/src/session/session-artifacts.ts +32 -4
- package/src/session/session-config-builder.ts +22 -9
- package/src/session/session-graph.ts +1 -1
- package/src/session/session-host.ts +19 -11
- package/src/session/session-manager.ts +11 -6
- package/src/session/session-service.team-persistence.test.ts +1 -1
- package/src/session/session-service.ts +6 -9
- package/src/session/session-team-coordination.ts +7 -3
- package/src/session/session-telemetry.ts +1 -1
- package/src/session/utils/helpers.test.ts +160 -0
- package/src/session/utils/helpers.ts +289 -42
- package/src/session/utils/types.ts +47 -7
- package/src/session/workspace-manager.ts +5 -3
- package/src/session/workspace-manifest.ts +3 -49
- package/src/storage/file-team-store.ts +2 -5
- package/src/storage/provider-settings-legacy-migration.ts +2 -2
- package/src/storage/provider-settings-manager.test.ts +1 -1
- package/src/storage/sqlite-team-store.ts +212 -125
- package/src/storage/team-store.ts +1 -5
- package/src/team/delegated-agent.ts +131 -0
- package/src/team/index.ts +1 -0
- package/src/team/multi-agent.lifecycle.test.ts +201 -0
- package/src/team/multi-agent.ts +1666 -0
- package/src/team/projections.ts +2 -4
- package/src/team/runtime.ts +54 -0
- package/src/team/spawn-agent-tool.test.ts +387 -0
- package/src/team/spawn-agent-tool.ts +207 -0
- package/src/team/subagent-prompts.ts +41 -0
- package/src/team/team-tools.test.ts +802 -0
- package/src/team/team-tools.ts +792 -0
- package/src/telemetry/OpenTelemetryProvider.test.ts +25 -3
- package/src/telemetry/OpenTelemetryProvider.ts +108 -18
- package/src/telemetry/TelemetryLoggerSink.test.ts +42 -0
- package/src/telemetry/{LoggerTelemetryAdapter.ts → TelemetryLoggerSink.ts} +21 -14
- package/src/telemetry/TelemetryService.test.ts +7 -7
- package/src/telemetry/TelemetryService.ts +2 -4
- package/src/tools/definitions.test.ts +76 -0
- package/src/tools/definitions.ts +41 -2
- package/src/tools/executors/apply-patch.ts +1 -1
- package/src/tools/executors/editor.ts +1 -1
- package/src/tools/executors/file-read.ts +1 -1
- package/src/tools/executors/search.ts +1 -1
- package/src/tools/executors/web-fetch.ts +1 -1
- package/src/tools/index.ts +6 -1
- package/src/tools/model-tool-routing.ts +2 -0
- package/src/tools/presets.test.ts +8 -0
- package/src/tools/presets.ts +40 -2
- package/src/tools/schemas.ts +19 -0
- package/src/tools/types.ts +31 -2
- package/src/types/config.ts +61 -7
- package/src/types/events.ts +1 -1
- package/src/types/index.ts +0 -1
- package/src/types/provider-settings.ts +1 -1
- package/src/types/storage.ts +2 -5
- package/src/types.ts +32 -44
- package/dist/agents/agent-config-loader.d.ts.map +0 -1
- package/dist/agents/agent-config-parser.d.ts.map +0 -1
- package/dist/agents/hooks-config-loader.d.ts.map +0 -1
- package/dist/agents/index.d.ts.map +0 -1
- package/dist/agents/plugin-config-loader.d.ts.map +0 -1
- package/dist/agents/plugin-loader.d.ts.map +0 -1
- package/dist/agents/plugin-sandbox-bootstrap.js +0 -446
- package/dist/agents/plugin-sandbox.d.ts.map +0 -1
- package/dist/agents/unified-config-file-watcher.d.ts.map +0 -1
- package/dist/agents/user-instruction-config-loader.d.ts.map +0 -1
- package/dist/mcp/config-loader.d.ts.map +0 -1
- package/dist/mcp/index.d.ts +0 -5
- package/dist/mcp/index.d.ts.map +0 -1
- package/dist/mcp/manager.d.ts.map +0 -1
- package/dist/mcp/types.d.ts.map +0 -1
- package/dist/runtime/commands.d.ts.map +0 -1
- package/dist/runtime/sandbox/subprocess-sandbox.d.ts.map +0 -1
- package/dist/runtime/skills.d.ts +0 -14
- package/dist/runtime/skills.d.ts.map +0 -1
- package/dist/runtime/workflows.d.ts +0 -14
- package/dist/runtime/workflows.d.ts.map +0 -1
- package/dist/session/unified-session-persistence-service.d.ts.map +0 -1
- package/dist/telemetry/LoggerTelemetryAdapter.d.ts.map +0 -1
- package/dist/types/workspace.d.ts +0 -8
- package/dist/types/workspace.d.ts.map +0 -1
- package/src/agents/plugin-loader.ts +0 -175
- package/src/runtime/skills.ts +0 -44
- package/src/runtime/workflows.test.ts +0 -119
- package/src/runtime/workflows.ts +0 -45
- package/src/session/unified-session-persistence-service.test.ts +0 -85
- package/src/telemetry/LoggerTelemetryAdapter.test.ts +0 -42
- package/src/types/workspace.ts +0 -7
- /package/dist/{agents → extensions/config}/agent-config-loader.d.ts +0 -0
- /package/dist/{agents → extensions/config}/unified-config-file-watcher.d.ts +0 -0
- /package/dist/{agents → extensions/config}/user-instruction-config-loader.d.ts +0 -0
- /package/dist/{mcp → extensions/mcp}/config-loader.d.ts +0 -0
- /package/dist/runtime/{sandbox/subprocess-sandbox.d.ts → subprocess-sandbox.d.ts} +0 -0
- /package/src/{agents → extensions/config}/agent-config-loader.ts +0 -0
- /package/src/{agents → extensions/config}/hooks-config-loader.test.ts +0 -0
- /package/src/{agents → extensions/config}/unified-config-file-watcher.test.ts +0 -0
- /package/src/{mcp → extensions/mcp}/config-loader.test.ts +0 -0
- /package/src/{mcp → extensions/mcp}/config-loader.ts +0 -0
package/src/team/projections.ts
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import type {
|
|
2
|
-
TeamEvent,
|
|
3
2
|
TeamOutcome,
|
|
4
3
|
TeamOutcomeFragment,
|
|
5
|
-
TeamRuntimeState,
|
|
6
|
-
} from "@clinebot/agents";
|
|
7
|
-
import type {
|
|
8
4
|
TeamProgressLifecycleEvent,
|
|
9
5
|
TeamProgressSummary,
|
|
6
|
+
TeamRuntimeState,
|
|
10
7
|
} from "@clinebot/shared";
|
|
8
|
+
import type { TeamEvent } from "./multi-agent";
|
|
11
9
|
|
|
12
10
|
function toIsoNow(): string {
|
|
13
11
|
return new Date().toISOString();
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export {
|
|
2
|
+
buildDelegatedAgentConfig,
|
|
3
|
+
createDelegatedAgent,
|
|
4
|
+
createDelegatedAgentConfigProvider,
|
|
5
|
+
type DelegatedAgentConfigProvider,
|
|
6
|
+
type DelegatedAgentConnectionConfig,
|
|
7
|
+
type DelegatedAgentKind,
|
|
8
|
+
type DelegatedAgentRuntimeConfig,
|
|
9
|
+
} from "./delegated-agent";
|
|
10
|
+
|
|
11
|
+
// =============================================================================
|
|
12
|
+
// Spawn Agent Tool
|
|
13
|
+
// =============================================================================
|
|
14
|
+
|
|
15
|
+
export {
|
|
16
|
+
createSpawnAgentTool,
|
|
17
|
+
type SpawnAgentInput,
|
|
18
|
+
type SpawnAgentOutput,
|
|
19
|
+
type SpawnAgentToolConfig,
|
|
20
|
+
type SubAgentEndContext,
|
|
21
|
+
type SubAgentStartContext,
|
|
22
|
+
} from "./spawn-agent-tool";
|
|
23
|
+
|
|
24
|
+
// =============================================================================
|
|
25
|
+
// Multi-Agent
|
|
26
|
+
// =============================================================================
|
|
27
|
+
|
|
28
|
+
export {
|
|
29
|
+
type AgentTask,
|
|
30
|
+
AgentTeam,
|
|
31
|
+
AgentTeamsRuntime,
|
|
32
|
+
type AgentTeamsRuntimeOptions,
|
|
33
|
+
createAgentTeam,
|
|
34
|
+
createWorkerReviewerTeam,
|
|
35
|
+
type SpawnTeammateOptions,
|
|
36
|
+
type TaskResult,
|
|
37
|
+
type TeamEvent,
|
|
38
|
+
type TeamMemberConfig,
|
|
39
|
+
} from "./multi-agent";
|
|
40
|
+
|
|
41
|
+
// =============================================================================
|
|
42
|
+
// Team Tools
|
|
43
|
+
// =============================================================================
|
|
44
|
+
|
|
45
|
+
export {
|
|
46
|
+
type BootstrapAgentTeamsOptions,
|
|
47
|
+
type BootstrapAgentTeamsResult,
|
|
48
|
+
bootstrapAgentTeams,
|
|
49
|
+
type CreateAgentTeamsToolsOptions,
|
|
50
|
+
createAgentTeamsTools,
|
|
51
|
+
reviveTeamStateDates,
|
|
52
|
+
sanitizeTeamName,
|
|
53
|
+
type TeamTeammateRuntimeConfig,
|
|
54
|
+
} from "./team-tools";
|
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
import type { AgentConfig } from "@clinebot/shared";
|
|
2
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
3
|
+
import { createDelegatedAgentConfigProvider } from "./delegated-agent";
|
|
4
|
+
|
|
5
|
+
type AgentExtension = NonNullable<AgentConfig["extensions"]>[number];
|
|
6
|
+
|
|
7
|
+
const runMock = vi.fn();
|
|
8
|
+
const getAgentIdMock = vi.fn(() => "sub-agent-1");
|
|
9
|
+
const getConversationIdMock = vi.fn(() => "conv-sub-1");
|
|
10
|
+
const agentConstructorSpy = vi.fn();
|
|
11
|
+
|
|
12
|
+
vi.mock("@clinebot/agents", async () => {
|
|
13
|
+
const actual =
|
|
14
|
+
await vi.importActual<typeof import("@clinebot/agents")>(
|
|
15
|
+
"@clinebot/agents",
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
...actual,
|
|
20
|
+
Agent: class MockAgent {
|
|
21
|
+
constructor(config: unknown) {
|
|
22
|
+
agentConstructorSpy(config);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
getAgentId(): string {
|
|
26
|
+
return getAgentIdMock();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
getConversationId(): string {
|
|
30
|
+
return getConversationIdMock();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async run(input: string): Promise<unknown> {
|
|
34
|
+
return runMock(input);
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
describe("createSpawnAgentTool", () => {
|
|
41
|
+
beforeEach(() => {
|
|
42
|
+
vi.clearAllMocks();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("creates a sub-agent, forwards callbacks, and returns normalized output", async () => {
|
|
46
|
+
const { createSpawnAgentTool } = await import("./spawn-agent-tool.js");
|
|
47
|
+
runMock.mockResolvedValue({
|
|
48
|
+
text: "sub-agent result",
|
|
49
|
+
iterations: 2,
|
|
50
|
+
finishReason: "completed",
|
|
51
|
+
usage: { inputTokens: 11, outputTokens: 7 },
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const onSubAgentStart = vi.fn();
|
|
55
|
+
const onSubAgentEnd = vi.fn();
|
|
56
|
+
const createSubAgentTools = vi.fn().mockResolvedValue([]);
|
|
57
|
+
const extensions = [
|
|
58
|
+
{
|
|
59
|
+
name: "sample-ext",
|
|
60
|
+
manifest: { capabilities: ["hooks"], hookStages: ["runtime_event"] },
|
|
61
|
+
onRuntimeEvent: vi.fn(),
|
|
62
|
+
} as AgentExtension,
|
|
63
|
+
];
|
|
64
|
+
|
|
65
|
+
const tool = createSpawnAgentTool({
|
|
66
|
+
configProvider: createDelegatedAgentConfigProvider({
|
|
67
|
+
providerId: "anthropic",
|
|
68
|
+
modelId: "mock-model",
|
|
69
|
+
extensions,
|
|
70
|
+
}),
|
|
71
|
+
defaultMaxIterations: 4,
|
|
72
|
+
createSubAgentTools,
|
|
73
|
+
onSubAgentStart,
|
|
74
|
+
onSubAgentEnd,
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
const output = await tool.execute(
|
|
78
|
+
{
|
|
79
|
+
systemPrompt: "You are focused",
|
|
80
|
+
task: "Do delegated work",
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
agentId: "parent-1",
|
|
84
|
+
conversationId: "conv-parent",
|
|
85
|
+
iteration: 3,
|
|
86
|
+
},
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
expect(createSubAgentTools).toHaveBeenCalledTimes(1);
|
|
90
|
+
expect(runMock).toHaveBeenCalledWith("Do delegated work");
|
|
91
|
+
expect(onSubAgentStart).toHaveBeenCalledTimes(1);
|
|
92
|
+
expect(onSubAgentEnd).toHaveBeenCalledTimes(1);
|
|
93
|
+
expect(output).toEqual({
|
|
94
|
+
text: "sub-agent result",
|
|
95
|
+
iterations: 2,
|
|
96
|
+
finishReason: "completed",
|
|
97
|
+
usage: {
|
|
98
|
+
inputTokens: 11,
|
|
99
|
+
outputTokens: 7,
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
expect(agentConstructorSpy).toHaveBeenCalledWith(
|
|
103
|
+
expect.objectContaining({
|
|
104
|
+
parentAgentId: "parent-1",
|
|
105
|
+
maxIterations: 4,
|
|
106
|
+
extensions,
|
|
107
|
+
}),
|
|
108
|
+
);
|
|
109
|
+
expect(agentConstructorSpy).toHaveBeenCalledWith(
|
|
110
|
+
expect.not.objectContaining({
|
|
111
|
+
prepareTurn: expect.anything(),
|
|
112
|
+
}),
|
|
113
|
+
);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it("passes extension hooks through delegated config", async () => {
|
|
117
|
+
const { createSpawnAgentTool } = await import("./spawn-agent-tool.js");
|
|
118
|
+
runMock.mockResolvedValue({
|
|
119
|
+
text: "sub-agent result",
|
|
120
|
+
iterations: 1,
|
|
121
|
+
finishReason: "completed",
|
|
122
|
+
usage: { inputTokens: 1, outputTokens: 1 },
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
const extensions = [
|
|
126
|
+
{
|
|
127
|
+
name: "before-start-ext",
|
|
128
|
+
manifest: {
|
|
129
|
+
capabilities: ["hooks"],
|
|
130
|
+
hookStages: ["before_agent_start"],
|
|
131
|
+
},
|
|
132
|
+
onBeforeAgentStart: vi.fn(),
|
|
133
|
+
} as AgentExtension,
|
|
134
|
+
];
|
|
135
|
+
|
|
136
|
+
const tool = createSpawnAgentTool({
|
|
137
|
+
configProvider: createDelegatedAgentConfigProvider({
|
|
138
|
+
providerId: "anthropic",
|
|
139
|
+
modelId: "mock-model",
|
|
140
|
+
extensions,
|
|
141
|
+
}),
|
|
142
|
+
subAgentTools: [],
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
await tool.execute(
|
|
146
|
+
{
|
|
147
|
+
systemPrompt: "You are focused",
|
|
148
|
+
task: "Do delegated work",
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
agentId: "parent-1",
|
|
152
|
+
conversationId: "conv-parent",
|
|
153
|
+
iteration: 3,
|
|
154
|
+
},
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
expect(agentConstructorSpy).toHaveBeenCalledWith(
|
|
158
|
+
expect.objectContaining({
|
|
159
|
+
extensions,
|
|
160
|
+
}),
|
|
161
|
+
);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it("propagates sub-agent errors and still reports onSubAgentEnd", async () => {
|
|
165
|
+
const { createSpawnAgentTool } = await import("./spawn-agent-tool.js");
|
|
166
|
+
runMock.mockRejectedValue(new Error("sub-agent failed"));
|
|
167
|
+
const onSubAgentEnd = vi.fn();
|
|
168
|
+
|
|
169
|
+
const tool = createSpawnAgentTool({
|
|
170
|
+
configProvider: createDelegatedAgentConfigProvider({
|
|
171
|
+
providerId: "anthropic",
|
|
172
|
+
modelId: "mock-model",
|
|
173
|
+
}),
|
|
174
|
+
subAgentTools: [],
|
|
175
|
+
onSubAgentEnd,
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
await expect(
|
|
179
|
+
tool.execute(
|
|
180
|
+
{
|
|
181
|
+
systemPrompt: "System",
|
|
182
|
+
task: "Fail task",
|
|
183
|
+
maxIterations: 6,
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
agentId: "parent-2",
|
|
187
|
+
conversationId: "conv-parent",
|
|
188
|
+
iteration: 1,
|
|
189
|
+
},
|
|
190
|
+
),
|
|
191
|
+
).rejects.toThrow("sub-agent failed");
|
|
192
|
+
|
|
193
|
+
expect(onSubAgentEnd).toHaveBeenCalledTimes(1);
|
|
194
|
+
expect(onSubAgentEnd).toHaveBeenCalledWith(
|
|
195
|
+
expect.objectContaining({
|
|
196
|
+
parentAgentId: "parent-2",
|
|
197
|
+
error: expect.any(Error),
|
|
198
|
+
}),
|
|
199
|
+
);
|
|
200
|
+
expect(agentConstructorSpy).toHaveBeenCalledWith(
|
|
201
|
+
expect.objectContaining({
|
|
202
|
+
maxIterations: 6,
|
|
203
|
+
}),
|
|
204
|
+
);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
it("leaves maxIterations unset when neither input nor default is provided", async () => {
|
|
208
|
+
const { createSpawnAgentTool } = await import("./spawn-agent-tool.js");
|
|
209
|
+
runMock.mockResolvedValue({
|
|
210
|
+
text: "sub-agent result",
|
|
211
|
+
iterations: 1,
|
|
212
|
+
finishReason: "completed",
|
|
213
|
+
usage: { inputTokens: 1, outputTokens: 1 },
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
const tool = createSpawnAgentTool({
|
|
217
|
+
configProvider: createDelegatedAgentConfigProvider({
|
|
218
|
+
providerId: "anthropic",
|
|
219
|
+
modelId: "mock-model",
|
|
220
|
+
}),
|
|
221
|
+
subAgentTools: [],
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
await tool.execute(
|
|
225
|
+
{
|
|
226
|
+
systemPrompt: "System",
|
|
227
|
+
task: "Do task",
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
agentId: "parent-3",
|
|
231
|
+
conversationId: "conv-parent",
|
|
232
|
+
iteration: 1,
|
|
233
|
+
},
|
|
234
|
+
);
|
|
235
|
+
|
|
236
|
+
expect(agentConstructorSpy).toHaveBeenCalledWith(
|
|
237
|
+
expect.objectContaining({
|
|
238
|
+
maxIterations: undefined,
|
|
239
|
+
}),
|
|
240
|
+
);
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
it("appends workspace metadata for cline sub-agents when missing", async () => {
|
|
244
|
+
const { createSpawnAgentTool } = await import("./spawn-agent-tool.js");
|
|
245
|
+
runMock.mockResolvedValue({
|
|
246
|
+
text: "ok",
|
|
247
|
+
iterations: 1,
|
|
248
|
+
finishReason: "completed",
|
|
249
|
+
usage: { inputTokens: 1, outputTokens: 1 },
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
const workspaceMetadata = `# Workspace Configuration
|
|
253
|
+
{
|
|
254
|
+
"workspaces": {
|
|
255
|
+
"/repo/demo": {
|
|
256
|
+
"hint": "demo"
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}`;
|
|
260
|
+
|
|
261
|
+
const tool = createSpawnAgentTool({
|
|
262
|
+
configProvider: createDelegatedAgentConfigProvider({
|
|
263
|
+
providerId: "cline",
|
|
264
|
+
modelId: "anthropic/claude-sonnet-4.6",
|
|
265
|
+
cwd: "/repo/demo",
|
|
266
|
+
workspaceMetadata,
|
|
267
|
+
}),
|
|
268
|
+
subAgentTools: [],
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
await tool.execute(
|
|
272
|
+
{
|
|
273
|
+
systemPrompt: "You are a specialist teammate.",
|
|
274
|
+
task: "Investigate module boundaries",
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
agentId: "parent-4",
|
|
278
|
+
conversationId: "conv-parent",
|
|
279
|
+
iteration: 1,
|
|
280
|
+
},
|
|
281
|
+
);
|
|
282
|
+
|
|
283
|
+
expect(agentConstructorSpy).toHaveBeenCalledWith(
|
|
284
|
+
expect.objectContaining({
|
|
285
|
+
systemPrompt: expect.stringContaining(workspaceMetadata),
|
|
286
|
+
}),
|
|
287
|
+
);
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
it("does not duplicate workspace metadata for cline sub-agents", async () => {
|
|
291
|
+
const { createSpawnAgentTool } = await import("./spawn-agent-tool.js");
|
|
292
|
+
runMock.mockResolvedValue({
|
|
293
|
+
text: "ok",
|
|
294
|
+
iterations: 1,
|
|
295
|
+
finishReason: "completed",
|
|
296
|
+
usage: { inputTokens: 1, outputTokens: 1 },
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
const inputSystemPrompt = `You are a specialist teammate.
|
|
300
|
+
|
|
301
|
+
# Workspace Configuration
|
|
302
|
+
{
|
|
303
|
+
"workspaces": {
|
|
304
|
+
"/repo/demo": {
|
|
305
|
+
"hint": "demo"
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}`;
|
|
309
|
+
|
|
310
|
+
const tool = createSpawnAgentTool({
|
|
311
|
+
configProvider: createDelegatedAgentConfigProvider({
|
|
312
|
+
providerId: "cline",
|
|
313
|
+
modelId: "anthropic/claude-sonnet-4.6",
|
|
314
|
+
cwd: "/repo/demo",
|
|
315
|
+
workspaceMetadata: "# Workspace Configuration\n{}",
|
|
316
|
+
}),
|
|
317
|
+
subAgentTools: [],
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
await tool.execute(
|
|
321
|
+
{
|
|
322
|
+
systemPrompt: inputSystemPrompt,
|
|
323
|
+
task: "Investigate module boundaries",
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
agentId: "parent-5",
|
|
327
|
+
conversationId: "conv-parent",
|
|
328
|
+
iteration: 1,
|
|
329
|
+
},
|
|
330
|
+
);
|
|
331
|
+
|
|
332
|
+
expect(agentConstructorSpy).toHaveBeenCalledWith(
|
|
333
|
+
expect.objectContaining({
|
|
334
|
+
systemPrompt: inputSystemPrompt,
|
|
335
|
+
}),
|
|
336
|
+
);
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
it("resolves connection settings lazily at execution time", async () => {
|
|
340
|
+
const { createSpawnAgentTool } = await import("./spawn-agent-tool.js");
|
|
341
|
+
runMock.mockResolvedValue({
|
|
342
|
+
text: "ok",
|
|
343
|
+
iterations: 1,
|
|
344
|
+
finishReason: "completed",
|
|
345
|
+
usage: { inputTokens: 1, outputTokens: 1 },
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
const configProvider = createDelegatedAgentConfigProvider({
|
|
349
|
+
providerId: "cline",
|
|
350
|
+
modelId: "stale-model",
|
|
351
|
+
apiKey: "oauth-access-old",
|
|
352
|
+
});
|
|
353
|
+
const updateConnectionDefaults = vi.spyOn(
|
|
354
|
+
configProvider,
|
|
355
|
+
"updateConnectionDefaults",
|
|
356
|
+
);
|
|
357
|
+
configProvider.updateConnectionDefaults({
|
|
358
|
+
apiKey: "oauth-access-new",
|
|
359
|
+
modelId: "updated-model",
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
const tool = createSpawnAgentTool({
|
|
363
|
+
configProvider,
|
|
364
|
+
subAgentTools: [],
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
await tool.execute(
|
|
368
|
+
{
|
|
369
|
+
systemPrompt: "System",
|
|
370
|
+
task: "Do task",
|
|
371
|
+
},
|
|
372
|
+
{
|
|
373
|
+
agentId: "parent-6",
|
|
374
|
+
conversationId: "conv-parent",
|
|
375
|
+
iteration: 1,
|
|
376
|
+
},
|
|
377
|
+
);
|
|
378
|
+
|
|
379
|
+
expect(updateConnectionDefaults).toHaveBeenCalledTimes(1);
|
|
380
|
+
expect(agentConstructorSpy).toHaveBeenCalledWith(
|
|
381
|
+
expect.objectContaining({
|
|
382
|
+
apiKey: "oauth-access-new",
|
|
383
|
+
modelId: "updated-model",
|
|
384
|
+
}),
|
|
385
|
+
);
|
|
386
|
+
});
|
|
387
|
+
});
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reusable spawn_agent tool for delegating tasks to sub-agents.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
type AgentConfig,
|
|
7
|
+
type AgentEvent,
|
|
8
|
+
type AgentHooks,
|
|
9
|
+
type AgentResult,
|
|
10
|
+
type BasicLogger,
|
|
11
|
+
createTool,
|
|
12
|
+
type HookErrorMode,
|
|
13
|
+
type ITelemetryService,
|
|
14
|
+
type Tool,
|
|
15
|
+
type ToolApprovalRequest,
|
|
16
|
+
type ToolApprovalResult,
|
|
17
|
+
type ToolContext,
|
|
18
|
+
type ToolPolicy,
|
|
19
|
+
zodToJsonSchema,
|
|
20
|
+
} from "@clinebot/shared";
|
|
21
|
+
import { z } from "zod";
|
|
22
|
+
import {
|
|
23
|
+
createDelegatedAgent,
|
|
24
|
+
type DelegatedAgentConfigProvider,
|
|
25
|
+
} from "./delegated-agent";
|
|
26
|
+
|
|
27
|
+
type AgentExtension = NonNullable<AgentConfig["extensions"]>[number];
|
|
28
|
+
type AgentFinishReason = AgentResult["finishReason"];
|
|
29
|
+
|
|
30
|
+
export const SpawnAgentInputSchema = z.object({
|
|
31
|
+
systemPrompt: z
|
|
32
|
+
.string()
|
|
33
|
+
.describe("System prompt defining the sub-agent's behavior"),
|
|
34
|
+
task: z.string().describe("Task for the sub-agent to complete"),
|
|
35
|
+
maxIterations: z
|
|
36
|
+
.number()
|
|
37
|
+
.int()
|
|
38
|
+
.min(1)
|
|
39
|
+
.optional()
|
|
40
|
+
.describe("Max iterations for the sub-agent"),
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
export type SpawnAgentInput = z.infer<typeof SpawnAgentInputSchema>;
|
|
44
|
+
|
|
45
|
+
export interface SpawnAgentOutput {
|
|
46
|
+
text: string;
|
|
47
|
+
iterations: number;
|
|
48
|
+
finishReason: AgentFinishReason;
|
|
49
|
+
usage: {
|
|
50
|
+
inputTokens: number;
|
|
51
|
+
outputTokens: number;
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface SubAgentStartContext {
|
|
56
|
+
subAgentId: string;
|
|
57
|
+
conversationId: string;
|
|
58
|
+
parentAgentId: string;
|
|
59
|
+
input: SpawnAgentInput;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface SubAgentEndContext {
|
|
63
|
+
subAgentId: string;
|
|
64
|
+
conversationId: string;
|
|
65
|
+
parentAgentId: string;
|
|
66
|
+
input: SpawnAgentInput;
|
|
67
|
+
result?: SpawnAgentOutput;
|
|
68
|
+
error?: Error;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface SpawnAgentToolConfig {
|
|
72
|
+
configProvider: DelegatedAgentConfigProvider;
|
|
73
|
+
defaultMaxIterations?: number;
|
|
74
|
+
subAgentTools?: Tool[];
|
|
75
|
+
createSubAgentTools?: (
|
|
76
|
+
input: SpawnAgentInput,
|
|
77
|
+
context: ToolContext,
|
|
78
|
+
) => Tool[] | Promise<Tool[]>;
|
|
79
|
+
onSubAgentEvent?: (event: AgentEvent) => void;
|
|
80
|
+
/**
|
|
81
|
+
* Lifecycle hooks forwarded to spawned sub-agent runs.
|
|
82
|
+
*/
|
|
83
|
+
hooks?: AgentHooks;
|
|
84
|
+
/**
|
|
85
|
+
* Extension list forwarded to spawned sub-agent runs.
|
|
86
|
+
*/
|
|
87
|
+
extensions?: AgentExtension[];
|
|
88
|
+
/**
|
|
89
|
+
* Error handling mode for forwarded lifecycle hooks.
|
|
90
|
+
*/
|
|
91
|
+
hookErrorMode?: HookErrorMode;
|
|
92
|
+
/**
|
|
93
|
+
* Called after a sub-agent instance is created and before it starts running.
|
|
94
|
+
* Errors are ignored so lifecycle observers cannot break task execution.
|
|
95
|
+
*/
|
|
96
|
+
onSubAgentStart?: (context: SubAgentStartContext) => void | Promise<void>;
|
|
97
|
+
/**
|
|
98
|
+
* Called once a sub-agent run finishes (success or error).
|
|
99
|
+
* Errors are ignored so lifecycle observers cannot break task execution.
|
|
100
|
+
*/
|
|
101
|
+
onSubAgentEnd?: (context: SubAgentEndContext) => void | Promise<void>;
|
|
102
|
+
/**
|
|
103
|
+
* Optional per-tool policy for spawned sub-agents.
|
|
104
|
+
*/
|
|
105
|
+
toolPolicies?: Record<string, ToolPolicy>;
|
|
106
|
+
/**
|
|
107
|
+
* Optional approval callback for spawned sub-agent tool calls.
|
|
108
|
+
*/
|
|
109
|
+
requestToolApproval?: (
|
|
110
|
+
request: ToolApprovalRequest,
|
|
111
|
+
) => Promise<ToolApprovalResult> | ToolApprovalResult;
|
|
112
|
+
/**
|
|
113
|
+
* Optional logger forwarded to spawned sub-agent runs.
|
|
114
|
+
*/
|
|
115
|
+
logger?: BasicLogger;
|
|
116
|
+
telemetry?: ITelemetryService;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Create a spawn_agent tool that can run a delegated task with a focused sub-agent.
|
|
121
|
+
*/
|
|
122
|
+
export function createSpawnAgentTool(
|
|
123
|
+
config: SpawnAgentToolConfig,
|
|
124
|
+
): Tool<SpawnAgentInput, SpawnAgentOutput> {
|
|
125
|
+
return createTool<SpawnAgentInput, SpawnAgentOutput>({
|
|
126
|
+
name: "spawn_agent",
|
|
127
|
+
description: `Spawn a sub-agent with a custom system prompt for specialized tasks. Use when delegating work that benefits from focused expertise.`,
|
|
128
|
+
inputSchema: zodToJsonSchema(SpawnAgentInputSchema),
|
|
129
|
+
execute: async (input, context) => {
|
|
130
|
+
const tools = config.createSubAgentTools
|
|
131
|
+
? await config.createSubAgentTools(input, context)
|
|
132
|
+
: (config.subAgentTools ?? []);
|
|
133
|
+
|
|
134
|
+
const subAgent = createDelegatedAgent({
|
|
135
|
+
kind: "subagent",
|
|
136
|
+
prompt: input.systemPrompt,
|
|
137
|
+
configProvider: config.configProvider,
|
|
138
|
+
tools,
|
|
139
|
+
maxIterations: input.maxIterations ?? config.defaultMaxIterations,
|
|
140
|
+
parentAgentId: context.agentId,
|
|
141
|
+
abortSignal: context.abortSignal,
|
|
142
|
+
onEvent: config.onSubAgentEvent,
|
|
143
|
+
hookErrorMode: config.hookErrorMode,
|
|
144
|
+
toolPolicies: config.toolPolicies,
|
|
145
|
+
requestToolApproval: config.requestToolApproval,
|
|
146
|
+
});
|
|
147
|
+
const subAgentId = subAgent.getAgentId();
|
|
148
|
+
const conversationId = subAgent.getConversationId();
|
|
149
|
+
const parentAgentId = context.agentId;
|
|
150
|
+
if (config.onSubAgentStart) {
|
|
151
|
+
try {
|
|
152
|
+
await config.onSubAgentStart({
|
|
153
|
+
subAgentId,
|
|
154
|
+
conversationId,
|
|
155
|
+
parentAgentId,
|
|
156
|
+
input,
|
|
157
|
+
});
|
|
158
|
+
} catch {
|
|
159
|
+
// Best-effort observer callback.
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
try {
|
|
163
|
+
const result = await subAgent.run(input.task);
|
|
164
|
+
const output: SpawnAgentOutput = {
|
|
165
|
+
text: result.text,
|
|
166
|
+
iterations: result.iterations,
|
|
167
|
+
finishReason: result.finishReason,
|
|
168
|
+
usage: {
|
|
169
|
+
inputTokens: result.usage.inputTokens,
|
|
170
|
+
outputTokens: result.usage.outputTokens,
|
|
171
|
+
},
|
|
172
|
+
};
|
|
173
|
+
if (config.onSubAgentEnd) {
|
|
174
|
+
try {
|
|
175
|
+
await config.onSubAgentEnd({
|
|
176
|
+
subAgentId,
|
|
177
|
+
conversationId,
|
|
178
|
+
parentAgentId,
|
|
179
|
+
input,
|
|
180
|
+
result: output,
|
|
181
|
+
});
|
|
182
|
+
} catch {
|
|
183
|
+
// Best-effort observer callback.
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return output;
|
|
187
|
+
} catch (error) {
|
|
188
|
+
if (config.onSubAgentEnd) {
|
|
189
|
+
try {
|
|
190
|
+
await config.onSubAgentEnd({
|
|
191
|
+
subAgentId,
|
|
192
|
+
conversationId,
|
|
193
|
+
parentAgentId,
|
|
194
|
+
input,
|
|
195
|
+
error: error instanceof Error ? error : new Error(String(error)),
|
|
196
|
+
});
|
|
197
|
+
} catch {
|
|
198
|
+
// Best-effort observer callback.
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
throw error;
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
timeoutMs: 300000,
|
|
205
|
+
retryable: false,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { buildClineSystemPrompt } from "@clinebot/shared";
|
|
2
|
+
import type { DelegatedAgentRuntimeConfig } from "./delegated-agent";
|
|
3
|
+
|
|
4
|
+
export function buildTeammateSystemPrompt(
|
|
5
|
+
prompt: string,
|
|
6
|
+
config: DelegatedAgentRuntimeConfig,
|
|
7
|
+
): string {
|
|
8
|
+
const trimmedPrompt = prompt.trim();
|
|
9
|
+
if (config.providerId.toLowerCase() !== "cline") {
|
|
10
|
+
return trimmedPrompt;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return buildClineSystemPrompt({
|
|
14
|
+
ide: config.clineIdeName?.trim() || "Terminal Shell",
|
|
15
|
+
workspaceRoot: config.cwd?.trim() || "/",
|
|
16
|
+
providerId: config.providerId,
|
|
17
|
+
rules: `# Team Teammate Role\n${trimmedPrompt}`,
|
|
18
|
+
platform: config.clinePlatform,
|
|
19
|
+
metadata: config.workspaceMetadata,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function buildSubAgentSystemPrompt(
|
|
24
|
+
// The prompt provided when spawning the subagent
|
|
25
|
+
prompt: string,
|
|
26
|
+
config: DelegatedAgentRuntimeConfig,
|
|
27
|
+
): string {
|
|
28
|
+
const trimmedPrompt = prompt.trim();
|
|
29
|
+
if (config.providerId.toLowerCase() !== "cline") {
|
|
30
|
+
return trimmedPrompt;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return buildClineSystemPrompt({
|
|
34
|
+
ide: "Terminal Shell",
|
|
35
|
+
workspaceRoot: config.cwd?.trim() || "/",
|
|
36
|
+
providerId: config.providerId,
|
|
37
|
+
overridePrompt: trimmedPrompt,
|
|
38
|
+
metadata: config.workspaceMetadata,
|
|
39
|
+
platform: config.clinePlatform,
|
|
40
|
+
});
|
|
41
|
+
}
|