@clinebot/core 0.0.34 → 0.0.35
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 +12 -8
- package/dist/ClineCore.d.ts +48 -29
- package/dist/ClineCore.d.ts.map +1 -1
- package/dist/extensions/config/agent-config-loader.d.ts +2 -2
- package/dist/extensions/config/agent-config-loader.d.ts.map +1 -1
- package/dist/extensions/config/agent-config-parser.d.ts +1 -1
- package/dist/extensions/config/agent-config-parser.d.ts.map +1 -1
- package/dist/extensions/config/hooks-config-loader.d.ts +2 -2
- package/dist/extensions/config/hooks-config-loader.d.ts.map +1 -1
- package/dist/extensions/config/index.d.ts +3 -3
- package/dist/extensions/config/index.d.ts.map +1 -1
- package/dist/extensions/config/user-instruction-config-loader.d.ts +2 -2
- package/dist/extensions/config/user-instruction-config-loader.d.ts.map +1 -1
- package/dist/extensions/plugin-sandbox-bootstrap.js +248 -248
- package/dist/extensions/tools/constants.d.ts.map +1 -0
- package/dist/extensions/tools/definitions.d.ts.map +1 -0
- package/dist/extensions/tools/executors/apply-patch-parser.d.ts.map +1 -0
- package/dist/extensions/tools/executors/apply-patch.d.ts.map +1 -0
- package/dist/extensions/tools/executors/bash.d.ts.map +1 -0
- package/dist/extensions/tools/executors/editor.d.ts.map +1 -0
- package/dist/extensions/tools/executors/file-read.d.ts.map +1 -0
- package/dist/extensions/tools/executors/index.d.ts.map +1 -0
- package/dist/extensions/tools/executors/search.d.ts.map +1 -0
- package/dist/extensions/tools/executors/web-fetch.d.ts.map +1 -0
- package/dist/extensions/tools/helpers.d.ts.map +1 -0
- package/dist/extensions/tools/index.d.ts.map +1 -0
- package/dist/{tools → extensions/tools}/model-tool-routing.d.ts +1 -1
- package/dist/extensions/tools/model-tool-routing.d.ts.map +1 -0
- package/dist/{tools → extensions/tools}/presets.d.ts +1 -2
- package/dist/extensions/tools/presets.d.ts.map +1 -0
- package/dist/extensions/tools/schemas.d.ts.map +1 -0
- package/dist/extensions/tools/team/delegated-agent.d.ts.map +1 -0
- package/dist/extensions/tools/team/index.d.ts.map +1 -0
- package/dist/{team → extensions/tools/team}/multi-agent.d.ts +1 -3
- package/dist/extensions/tools/team/multi-agent.d.ts.map +1 -0
- package/dist/extensions/tools/team/projections.d.ts.map +1 -0
- package/dist/extensions/tools/team/runtime.d.ts.map +1 -0
- package/dist/{team → extensions/tools/team}/spawn-agent-tool.d.ts +0 -1
- package/dist/extensions/tools/team/spawn-agent-tool.d.ts.map +1 -0
- package/dist/extensions/tools/team/subagent-prompts.d.ts.map +1 -0
- package/dist/extensions/tools/team/team-tools.d.ts.map +1 -0
- package/dist/{tools → extensions/tools}/types.d.ts +4 -3
- package/dist/extensions/tools/types.d.ts.map +1 -0
- package/dist/{runtime → hooks}/checkpoint-hooks.d.ts +7 -0
- package/dist/hooks/checkpoint-hooks.d.ts.map +1 -0
- package/dist/{runtime → hooks}/hook-file-hooks.d.ts +0 -2
- package/dist/hooks/hook-file-hooks.d.ts.map +1 -0
- package/dist/hooks/subprocess.d.ts +3 -130
- package/dist/hooks/subprocess.d.ts.map +1 -1
- package/dist/index.d.ts +35 -33
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +381 -379
- package/dist/runtime/history.d.ts +4 -0
- package/dist/runtime/history.d.ts.map +1 -0
- package/dist/runtime/host.d.ts +9 -0
- package/dist/runtime/host.d.ts.map +1 -0
- package/dist/{session → runtime}/rpc-runtime-ensure.d.ts +13 -1
- package/dist/{session → runtime}/rpc-runtime-ensure.d.ts.map +1 -1
- package/dist/{session → runtime}/rpc-spawn-lease.d.ts.map +1 -1
- package/dist/runtime/runtime-builder.d.ts.map +1 -1
- package/dist/{session/session-manager.d.ts → runtime/runtime-host.d.ts} +55 -12
- package/dist/runtime/runtime-host.d.ts.map +1 -0
- package/dist/{session → runtime}/runtime-oauth-token-manager.d.ts +1 -1
- package/dist/{session → runtime}/runtime-oauth-token-manager.d.ts.map +1 -1
- package/dist/runtime/session-runtime.d.ts +2 -2
- package/dist/runtime/session-runtime.d.ts.map +1 -1
- package/dist/{session/session-agent-events.d.ts → services/agent-events.d.ts} +4 -4
- package/dist/services/agent-events.d.ts.map +1 -0
- package/dist/services/config.d.ts +3 -0
- package/dist/services/config.d.ts.map +1 -0
- package/dist/services/local-runtime-bootstrap.d.ts +41 -0
- package/dist/services/local-runtime-bootstrap.d.ts.map +1 -0
- package/dist/services/providers/local-provider-registry.d.ts.map +1 -0
- package/dist/services/providers/local-provider-service.d.ts.map +1 -0
- package/dist/{session → services}/session-artifacts.d.ts +0 -4
- package/dist/services/session-artifacts.d.ts.map +1 -0
- package/dist/{session/utils/helpers.d.ts → services/session-data.d.ts} +19 -27
- package/dist/services/session-data.d.ts.map +1 -0
- package/dist/{session → services}/session-telemetry.d.ts +2 -2
- package/dist/services/session-telemetry.d.ts.map +1 -0
- package/dist/{storage → services/storage}/file-team-store.d.ts +2 -2
- package/dist/services/storage/file-team-store.d.ts.map +1 -0
- package/dist/{storage → services/storage}/provider-settings-legacy-migration.d.ts +1 -1
- package/dist/services/storage/provider-settings-legacy-migration.d.ts.map +1 -0
- package/dist/{storage → services/storage}/provider-settings-manager.d.ts +1 -1
- package/dist/services/storage/provider-settings-manager.d.ts.map +1 -0
- package/dist/{storage → services/storage}/sqlite-session-store.d.ts +3 -3
- package/dist/services/storage/sqlite-session-store.d.ts.map +1 -0
- package/dist/{storage → services/storage}/sqlite-team-store.d.ts +2 -2
- package/dist/services/storage/sqlite-team-store.d.ts.map +1 -0
- package/dist/{storage → services/storage}/team-store.d.ts +1 -1
- package/dist/services/storage/team-store.d.ts.map +1 -0
- package/dist/services/telemetry/ITelemetryAdapter.d.ts.map +1 -0
- package/dist/services/telemetry/OpenTelemetryAdapter.d.ts.map +1 -0
- package/dist/services/telemetry/OpenTelemetryProvider.d.ts.map +1 -0
- package/dist/services/telemetry/TelemetryLoggerSink.d.ts.map +1 -0
- package/dist/services/telemetry/TelemetryService.d.ts.map +1 -0
- package/dist/services/telemetry/core-events.d.ts.map +1 -0
- package/dist/services/telemetry/distinct-id.d.ts.map +1 -0
- package/dist/services/telemetry/index.d.ts.map +1 -0
- package/dist/{telemetry → services/telemetry}/index.js +6 -6
- package/dist/{session/utils → services}/usage.d.ts +1 -1
- package/dist/services/usage.d.ts.map +1 -0
- package/dist/services/workspace/file-indexer.d.ts.map +1 -0
- package/dist/services/workspace/index.d.ts.map +1 -0
- package/dist/services/workspace/mention-enricher.d.ts.map +1 -0
- package/dist/services/workspace-manifest.d.ts.map +1 -0
- package/dist/session/file-session-service.d.ts +4 -1
- package/dist/session/file-session-service.d.ts.map +1 -1
- package/dist/session/persistence-service.d.ts +8 -6
- package/dist/session/persistence-service.d.ts.map +1 -1
- package/dist/session/rpc-session-service.d.ts +3 -0
- package/dist/session/rpc-session-service.d.ts.map +1 -1
- package/dist/session/session-service.d.ts +8 -9
- package/dist/session/session-service.d.ts.map +1 -1
- package/dist/session/session-team-coordination.d.ts +4 -4
- package/dist/session/session-team-coordination.d.ts.map +1 -1
- package/dist/session/sqlite-rpc-session-backend.d.ts.map +1 -1
- package/dist/{session/default-session-manager.d.ts → transports/local.d.ts} +24 -14
- package/dist/transports/local.d.ts.map +1 -0
- package/dist/transports/rpc.d.ts +51 -0
- package/dist/transports/rpc.d.ts.map +1 -0
- package/dist/transports/runtime-host-support.d.ts +21 -0
- package/dist/transports/runtime-host-support.d.ts.map +1 -0
- package/dist/types/chat-schema.d.ts.map +1 -0
- package/dist/types/config.d.ts +2 -2
- package/dist/types/config.d.ts.map +1 -1
- package/dist/{session/utils/types.d.ts → types/session.d.ts} +15 -6
- package/dist/types/session.d.ts.map +1 -0
- package/dist/types/sessions.d.ts +19 -0
- package/dist/types/sessions.d.ts.map +1 -1
- package/dist/types/storage.d.ts +1 -3
- package/dist/types/storage.d.ts.map +1 -1
- package/dist/types.d.ts +7 -6
- package/dist/types.d.ts.map +1 -1
- package/package.json +7 -12
- package/src/ClineCore.test.ts +95 -19
- package/src/ClineCore.ts +120 -50
- package/src/auth/cline.ts +1 -1
- package/src/auth/codex.ts +1 -1
- package/src/auth/oca.ts +1 -1
- package/src/extensions/config/agent-config-loader.test.ts +3 -3
- package/src/extensions/config/agent-config-loader.ts +1 -5
- package/src/extensions/config/agent-config-parser.ts +1 -1
- package/src/extensions/config/hooks-config-loader.ts +1 -2
- package/src/extensions/config/index.ts +0 -4
- package/src/extensions/config/user-instruction-config-loader.ts +0 -4
- package/src/extensions/plugin/plugin-config-loader.test.ts +6 -4
- package/src/{tools → extensions/tools}/definitions.ts +1 -1
- package/src/extensions/tools/executors/file-read.test.ts +125 -0
- package/src/{tools → extensions/tools}/executors/file-read.ts +29 -4
- package/src/{tools → extensions/tools}/executors/search.ts +1 -1
- package/src/{tools → extensions/tools}/model-tool-routing.ts +1 -1
- package/src/{tools → extensions/tools}/presets.ts +2 -3
- package/src/extensions/tools/team/multi-agent.lifecycle.test.ts +455 -0
- package/src/{team → extensions/tools/team}/multi-agent.ts +80 -17
- package/src/{team → extensions/tools/team}/spawn-agent-tool.test.ts +0 -6
- package/src/{team → extensions/tools/team}/spawn-agent-tool.ts +1 -7
- package/src/{team → extensions/tools/team}/subagent-prompts.ts +2 -2
- package/src/{team → extensions/tools/team}/team-tools.test.ts +43 -31
- package/src/{team → extensions/tools/team}/team-tools.ts +63 -53
- package/src/{tools → extensions/tools}/types.ts +5 -3
- package/src/{runtime → hooks}/checkpoint-hooks.ts +27 -0
- package/src/{runtime → hooks}/hook-file-hooks.ts +6 -11
- package/src/hooks/subprocess.ts +48 -257
- package/src/index.ts +167 -158
- package/src/runtime/history.test.ts +114 -0
- package/src/runtime/history.ts +237 -0
- package/src/runtime/host.test.ts +230 -0
- package/src/runtime/host.ts +362 -0
- package/src/runtime/rpc-runtime-ensure.test.ts +123 -0
- package/src/{session → runtime}/rpc-runtime-ensure.ts +165 -27
- package/src/{session → runtime}/rpc-spawn-lease.test.ts +33 -1
- package/src/{session → runtime}/rpc-spawn-lease.ts +54 -20
- package/src/runtime/runtime-builder.team-persistence.test.ts +6 -3
- package/src/runtime/runtime-builder.test.ts +3 -4
- package/src/runtime/runtime-builder.ts +13 -21
- package/src/runtime/runtime-host.ts +178 -0
- package/src/{session → runtime}/runtime-oauth-token-manager.ts +1 -1
- package/src/runtime/runtime-parity.test.ts +1 -1
- package/src/runtime/session-runtime.ts +2 -2
- package/src/{session/session-agent-events.ts → services/agent-events.ts} +7 -7
- package/src/services/config.ts +5 -0
- package/src/services/local-runtime-bootstrap.ts +280 -0
- package/src/{providers → services/providers}/local-provider-service.ts +4 -4
- package/src/{session → services}/session-artifacts.ts +7 -19
- package/src/{session/utils/helpers.test.ts → services/session-data.test.ts} +1 -1
- package/src/{session/utils/helpers.ts → services/session-data.ts} +76 -72
- package/src/{session → services}/session-telemetry.ts +7 -9
- package/src/services/storage/artifact-store.ts +1 -0
- package/src/{storage → services/storage}/file-team-store.ts +2 -2
- package/src/{storage → services/storage}/provider-settings-legacy-migration.test.ts +1 -1
- package/src/{storage → services/storage}/provider-settings-legacy-migration.ts +2 -2
- package/src/{storage → services/storage}/provider-settings-manager.ts +2 -2
- package/src/services/storage/session-store.ts +1 -0
- package/src/{storage → services/storage}/sqlite-session-store.ts +7 -12
- package/src/{storage → services/storage}/sqlite-team-store.ts +4 -4
- package/src/{storage → services/storage}/team-store.ts +1 -1
- package/src/{session/utils → services}/usage.ts +1 -1
- package/src/{input → services/workspace}/file-indexer.test.ts +30 -1
- package/src/{input → services/workspace}/file-indexer.ts +26 -2
- package/src/{input → services/workspace}/mention-enricher.test.ts +21 -0
- package/src/{input → services/workspace}/mention-enricher.ts +1 -1
- package/src/session/file-session-service.ts +9 -7
- package/src/session/index.ts +25 -17
- package/src/session/persistence-service.test.ts +86 -27
- package/src/session/persistence-service.ts +104 -103
- package/src/session/rpc-session-service.ts +9 -2
- package/src/session/session-service.team-persistence.test.ts +1 -1
- package/src/session/session-service.ts +32 -19
- package/src/session/session-team-coordination.ts +13 -6
- package/src/session/sqlite-rpc-session-backend.ts +4 -6
- package/src/session/workspace-manager.ts +1 -1
- package/src/{session/default-session-manager.e2e.test.ts → transports/local.e2e.test.ts} +13 -17
- package/src/{session/default-session-manager.test.ts → transports/local.test.ts} +316 -230
- package/src/{session/default-session-manager.ts → transports/local.ts} +137 -169
- package/src/transports/rpc.test.ts +82 -0
- package/src/transports/rpc.ts +665 -0
- package/src/transports/runtime-host-support.ts +86 -0
- package/src/types/config.ts +2 -2
- package/src/{session/utils/types.ts → types/session.ts} +18 -5
- package/src/types/sessions.ts +21 -0
- package/src/types/storage.ts +1 -6
- package/src/types.ts +25 -18
- package/dist/chat/chat-schema.d.ts.map +0 -1
- package/dist/input/file-indexer.d.ts.map +0 -1
- package/dist/input/index.d.ts.map +0 -1
- package/dist/input/mention-enricher.d.ts.map +0 -1
- package/dist/prompt/default-system.d.ts +0 -2
- package/dist/prompt/default-system.d.ts.map +0 -1
- package/dist/providers/local-provider-registry.d.ts.map +0 -1
- package/dist/providers/local-provider-service.d.ts.map +0 -1
- package/dist/runtime/checkpoint-hooks.d.ts.map +0 -1
- package/dist/runtime/hook-file-hooks.d.ts.map +0 -1
- package/dist/session/default-session-manager.d.ts.map +0 -1
- package/dist/session/session-agent-events.d.ts.map +0 -1
- package/dist/session/session-artifacts.d.ts.map +0 -1
- package/dist/session/session-config-builder.d.ts +0 -16
- package/dist/session/session-config-builder.d.ts.map +0 -1
- package/dist/session/session-host.d.ts +0 -15
- package/dist/session/session-host.d.ts.map +0 -1
- package/dist/session/session-manager.d.ts.map +0 -1
- package/dist/session/session-telemetry.d.ts.map +0 -1
- package/dist/session/utils/helpers.d.ts.map +0 -1
- package/dist/session/utils/types.d.ts.map +0 -1
- package/dist/session/utils/usage.d.ts.map +0 -1
- package/dist/session/workspace-manifest.d.ts.map +0 -1
- package/dist/storage/file-team-store.d.ts.map +0 -1
- package/dist/storage/provider-settings-legacy-migration.d.ts.map +0 -1
- package/dist/storage/provider-settings-manager.d.ts.map +0 -1
- package/dist/storage/sqlite-session-store.d.ts.map +0 -1
- package/dist/storage/sqlite-team-store.d.ts.map +0 -1
- package/dist/storage/team-store.d.ts.map +0 -1
- package/dist/team/delegated-agent.d.ts.map +0 -1
- package/dist/team/index.d.ts.map +0 -1
- package/dist/team/multi-agent.d.ts.map +0 -1
- package/dist/team/projections.d.ts.map +0 -1
- package/dist/team/runtime.d.ts.map +0 -1
- package/dist/team/spawn-agent-tool.d.ts.map +0 -1
- package/dist/team/subagent-prompts.d.ts.map +0 -1
- package/dist/team/team-tools.d.ts.map +0 -1
- package/dist/telemetry/ITelemetryAdapter.d.ts.map +0 -1
- package/dist/telemetry/OpenTelemetryAdapter.d.ts.map +0 -1
- package/dist/telemetry/OpenTelemetryProvider.d.ts.map +0 -1
- package/dist/telemetry/TelemetryLoggerSink.d.ts.map +0 -1
- package/dist/telemetry/TelemetryService.d.ts.map +0 -1
- package/dist/telemetry/core-events.d.ts.map +0 -1
- package/dist/telemetry/distinct-id.d.ts.map +0 -1
- package/dist/telemetry/index.d.ts.map +0 -1
- package/dist/tools/constants.d.ts.map +0 -1
- package/dist/tools/definitions.d.ts.map +0 -1
- package/dist/tools/executors/apply-patch-parser.d.ts.map +0 -1
- package/dist/tools/executors/apply-patch.d.ts.map +0 -1
- package/dist/tools/executors/bash.d.ts.map +0 -1
- package/dist/tools/executors/editor.d.ts.map +0 -1
- package/dist/tools/executors/file-read.d.ts.map +0 -1
- package/dist/tools/executors/index.d.ts.map +0 -1
- package/dist/tools/executors/search.d.ts.map +0 -1
- package/dist/tools/executors/web-fetch.d.ts.map +0 -1
- package/dist/tools/helpers.d.ts.map +0 -1
- package/dist/tools/index.d.ts.map +0 -1
- package/dist/tools/model-tool-routing.d.ts.map +0 -1
- package/dist/tools/presets.d.ts.map +0 -1
- package/dist/tools/schemas.d.ts.map +0 -1
- package/dist/tools/types.d.ts.map +0 -1
- package/src/prompt/default-system.ts +0 -21
- package/src/session/session-config-builder.ts +0 -172
- package/src/session/session-host.test.ts +0 -89
- package/src/session/session-host.ts +0 -213
- package/src/session/session-manager.ts +0 -74
- package/src/storage/artifact-store.ts +0 -1
- package/src/storage/session-store.ts +0 -1
- package/src/team/multi-agent.lifecycle.test.ts +0 -201
- package/src/tools/executors/file-read.test.ts +0 -49
- /package/dist/{tools → extensions/tools}/constants.d.ts +0 -0
- /package/dist/{tools → extensions/tools}/definitions.d.ts +0 -0
- /package/dist/{tools → extensions/tools}/executors/apply-patch-parser.d.ts +0 -0
- /package/dist/{tools → extensions/tools}/executors/apply-patch.d.ts +0 -0
- /package/dist/{tools → extensions/tools}/executors/bash.d.ts +0 -0
- /package/dist/{tools → extensions/tools}/executors/editor.d.ts +0 -0
- /package/dist/{tools → extensions/tools}/executors/file-read.d.ts +0 -0
- /package/dist/{tools → extensions/tools}/executors/index.d.ts +0 -0
- /package/dist/{tools → extensions/tools}/executors/search.d.ts +0 -0
- /package/dist/{tools → extensions/tools}/executors/web-fetch.d.ts +0 -0
- /package/dist/{tools → extensions/tools}/helpers.d.ts +0 -0
- /package/dist/{tools → extensions/tools}/index.d.ts +0 -0
- /package/dist/{tools → extensions/tools}/schemas.d.ts +0 -0
- /package/dist/{team → extensions/tools/team}/delegated-agent.d.ts +0 -0
- /package/dist/{team → extensions/tools/team}/index.d.ts +0 -0
- /package/dist/{team → extensions/tools/team}/projections.d.ts +0 -0
- /package/dist/{team → extensions/tools/team}/runtime.d.ts +0 -0
- /package/dist/{team → extensions/tools/team}/subagent-prompts.d.ts +0 -0
- /package/dist/{team → extensions/tools/team}/team-tools.d.ts +0 -0
- /package/dist/{session → runtime}/rpc-spawn-lease.d.ts +0 -0
- /package/dist/{providers → services/providers}/local-provider-registry.d.ts +0 -0
- /package/dist/{providers → services/providers}/local-provider-service.d.ts +0 -0
- /package/dist/{telemetry → services/telemetry}/ITelemetryAdapter.d.ts +0 -0
- /package/dist/{telemetry → services/telemetry}/OpenTelemetryAdapter.d.ts +0 -0
- /package/dist/{telemetry → services/telemetry}/OpenTelemetryProvider.d.ts +0 -0
- /package/dist/{telemetry → services/telemetry}/TelemetryLoggerSink.d.ts +0 -0
- /package/dist/{telemetry → services/telemetry}/TelemetryService.d.ts +0 -0
- /package/dist/{telemetry → services/telemetry}/core-events.d.ts +0 -0
- /package/dist/{telemetry → services/telemetry}/distinct-id.d.ts +0 -0
- /package/dist/{telemetry → services/telemetry}/index.d.ts +0 -0
- /package/dist/{input → services/workspace}/file-indexer.d.ts +0 -0
- /package/dist/{input → services/workspace}/index.d.ts +0 -0
- /package/dist/{input → services/workspace}/mention-enricher.d.ts +0 -0
- /package/dist/{session → services}/workspace-manifest.d.ts +0 -0
- /package/dist/{chat → types}/chat-schema.d.ts +0 -0
- /package/src/{tools → extensions/tools}/constants.ts +0 -0
- /package/src/{tools → extensions/tools}/definitions.test.ts +0 -0
- /package/src/{tools → extensions/tools}/executors/apply-patch-parser.ts +0 -0
- /package/src/{tools → extensions/tools}/executors/apply-patch.ts +0 -0
- /package/src/{tools → extensions/tools}/executors/bash.test.ts +0 -0
- /package/src/{tools → extensions/tools}/executors/bash.ts +0 -0
- /package/src/{tools → extensions/tools}/executors/editor.test.ts +0 -0
- /package/src/{tools → extensions/tools}/executors/editor.ts +0 -0
- /package/src/{tools → extensions/tools}/executors/index.ts +0 -0
- /package/src/{tools → extensions/tools}/executors/web-fetch.ts +0 -0
- /package/src/{tools → extensions/tools}/helpers.ts +0 -0
- /package/src/{tools → extensions/tools}/index.ts +0 -0
- /package/src/{tools → extensions/tools}/model-tool-routing.test.ts +0 -0
- /package/src/{tools → extensions/tools}/presets.test.ts +0 -0
- /package/src/{tools → extensions/tools}/schemas.ts +0 -0
- /package/src/{team → extensions/tools/team}/delegated-agent.ts +0 -0
- /package/src/{team → extensions/tools/team}/index.ts +0 -0
- /package/src/{team → extensions/tools/team}/projections.ts +0 -0
- /package/src/{team → extensions/tools/team}/runtime.ts +0 -0
- /package/src/{runtime → hooks}/checkpoint-hooks.test.ts +0 -0
- /package/src/{runtime → hooks}/hook-file-hooks.test.ts +0 -0
- /package/src/{session → runtime}/runtime-oauth-token-manager.test.ts +0 -0
- /package/src/{providers → services/providers}/local-provider-registry.ts +0 -0
- /package/src/{providers → services/providers}/local-provider-service.test.ts +0 -0
- /package/src/{storage → services/storage}/index.ts +0 -0
- /package/src/{storage → services/storage}/provider-settings-manager.test.ts +0 -0
- /package/src/{telemetry → services/telemetry}/ITelemetryAdapter.ts +0 -0
- /package/src/{telemetry → services/telemetry}/OpenTelemetryAdapter.test.ts +0 -0
- /package/src/{telemetry → services/telemetry}/OpenTelemetryAdapter.ts +0 -0
- /package/src/{telemetry → services/telemetry}/OpenTelemetryProvider.test.ts +0 -0
- /package/src/{telemetry → services/telemetry}/OpenTelemetryProvider.ts +0 -0
- /package/src/{telemetry → services/telemetry}/TelemetryLoggerSink.test.ts +0 -0
- /package/src/{telemetry → services/telemetry}/TelemetryLoggerSink.ts +0 -0
- /package/src/{telemetry → services/telemetry}/TelemetryService.test.ts +0 -0
- /package/src/{telemetry → services/telemetry}/TelemetryService.ts +0 -0
- /package/src/{telemetry → services/telemetry}/core-events.ts +0 -0
- /package/src/{telemetry → services/telemetry}/distinct-id.test.ts +0 -0
- /package/src/{telemetry → services/telemetry}/distinct-id.ts +0 -0
- /package/src/{telemetry → services/telemetry}/index.ts +0 -0
- /package/src/{input → services/workspace}/file-indexer.d.ts +0 -0
- /package/src/{input → services/workspace}/index.ts +0 -0
- /package/src/{session → services}/workspace-manifest.ts +0 -0
- /package/src/{chat → types}/chat-schema.ts +0 -0
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
import type { AgentEvent } from "@clinebot/shared";
|
|
2
|
+
import { describe, expect, it, vi } from "vitest";
|
|
3
|
+
import {
|
|
4
|
+
AgentTeamsRuntime,
|
|
5
|
+
type TeamEvent,
|
|
6
|
+
TeamMessageType,
|
|
7
|
+
} from "./multi-agent";
|
|
8
|
+
|
|
9
|
+
const { createAgentMock } = vi.hoisted(() => ({
|
|
10
|
+
createAgentMock: vi.fn(),
|
|
11
|
+
}));
|
|
12
|
+
|
|
13
|
+
vi.mock("@clinebot/agents", async () => {
|
|
14
|
+
const actual =
|
|
15
|
+
await vi.importActual<typeof import("@clinebot/agents")>(
|
|
16
|
+
"@clinebot/agents",
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
...actual,
|
|
21
|
+
createAgent: createAgentMock,
|
|
22
|
+
};
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
describe("AgentTeamsRuntime teammate lifecycle events", () => {
|
|
26
|
+
it("spawns teammates with a 10 minute API timeout", () => {
|
|
27
|
+
createAgentMock.mockReturnValueOnce({
|
|
28
|
+
abort: vi.fn(),
|
|
29
|
+
run: vi.fn(),
|
|
30
|
+
continue: vi.fn(),
|
|
31
|
+
canStartRun: vi.fn(() => true),
|
|
32
|
+
getAgentId: vi.fn(() => "teammate-1"),
|
|
33
|
+
getConversationId: vi.fn(() => "conv-1"),
|
|
34
|
+
getMessages: vi.fn(() => []),
|
|
35
|
+
});
|
|
36
|
+
const runtime = new AgentTeamsRuntime({
|
|
37
|
+
teamName: "test-team",
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
runtime.spawnTeammate({
|
|
41
|
+
agentId: "python-poet",
|
|
42
|
+
config: {
|
|
43
|
+
providerId: "anthropic",
|
|
44
|
+
modelId: "claude-sonnet-4-5-20250929",
|
|
45
|
+
systemPrompt: "Write concise Python-focused haiku",
|
|
46
|
+
tools: [],
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
expect(createAgentMock).toHaveBeenCalledWith(
|
|
51
|
+
expect.objectContaining({
|
|
52
|
+
apiTimeoutMs: 10 * 60 * 1000,
|
|
53
|
+
}),
|
|
54
|
+
);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("does not emit task_start when teammate is already busy", async () => {
|
|
58
|
+
const events: TeamEvent[] = [];
|
|
59
|
+
createAgentMock.mockReturnValueOnce({
|
|
60
|
+
abort: vi.fn(),
|
|
61
|
+
run: vi.fn(),
|
|
62
|
+
continue: vi.fn(),
|
|
63
|
+
canStartRun: vi.fn(() => false),
|
|
64
|
+
getAgentId: vi.fn(() => "teammate-1"),
|
|
65
|
+
getConversationId: vi.fn(() => "conv-1"),
|
|
66
|
+
getMessages: vi.fn(() => []),
|
|
67
|
+
});
|
|
68
|
+
const runtime = new AgentTeamsRuntime({
|
|
69
|
+
teamName: "test-team",
|
|
70
|
+
onTeamEvent: (event) => events.push(event),
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
runtime.spawnTeammate({
|
|
74
|
+
agentId: "python-poet",
|
|
75
|
+
config: {
|
|
76
|
+
providerId: "anthropic",
|
|
77
|
+
modelId: "claude-sonnet-4-5-20250929",
|
|
78
|
+
systemPrompt: "Write concise Python-focused haiku",
|
|
79
|
+
maxIterations: 7,
|
|
80
|
+
tools: [],
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
await expect(
|
|
85
|
+
runtime.routeToTeammate("python-poet", "write something"),
|
|
86
|
+
).rejects.toThrow(
|
|
87
|
+
"Cannot start a new run while another run is already in progress",
|
|
88
|
+
);
|
|
89
|
+
expect(
|
|
90
|
+
events.some((event) => event.type === TeamMessageType.TaskStart),
|
|
91
|
+
).toBe(false);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it("emits teammate_spawned with lifecycle payload", () => {
|
|
95
|
+
const events: TeamEvent[] = [];
|
|
96
|
+
createAgentMock.mockReturnValueOnce({
|
|
97
|
+
abort: vi.fn(),
|
|
98
|
+
run: vi.fn(),
|
|
99
|
+
continue: vi.fn(),
|
|
100
|
+
canStartRun: vi.fn(() => true),
|
|
101
|
+
getAgentId: vi.fn(() => "teammate-1"),
|
|
102
|
+
getConversationId: vi.fn(() => "conv-1"),
|
|
103
|
+
getMessages: vi.fn(() => []),
|
|
104
|
+
});
|
|
105
|
+
const runtime = new AgentTeamsRuntime({
|
|
106
|
+
teamName: "test-team",
|
|
107
|
+
onTeamEvent: (event) => events.push(event),
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
runtime.spawnTeammate({
|
|
111
|
+
agentId: "python-poet",
|
|
112
|
+
config: {
|
|
113
|
+
providerId: "anthropic",
|
|
114
|
+
modelId: "claude-sonnet-4-5-20250929",
|
|
115
|
+
systemPrompt: "Write concise Python-focused haiku",
|
|
116
|
+
maxIterations: 7,
|
|
117
|
+
tools: [],
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
expect(events).toContainEqual({
|
|
122
|
+
type: TeamMessageType.TeammateSpawned,
|
|
123
|
+
agentId: "python-poet",
|
|
124
|
+
role: undefined,
|
|
125
|
+
teammate: {
|
|
126
|
+
rolePrompt: "Write concise Python-focused haiku",
|
|
127
|
+
modelId: "claude-sonnet-4-5-20250929",
|
|
128
|
+
maxIterations: 7,
|
|
129
|
+
runtimeAgentId: "teammate-1",
|
|
130
|
+
conversationId: "conv-1",
|
|
131
|
+
parentAgentId: null,
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it("swallows abort-like shutdown errors from teammates", () => {
|
|
137
|
+
const events: TeamEvent[] = [];
|
|
138
|
+
createAgentMock.mockReturnValueOnce({
|
|
139
|
+
abort: vi.fn(() => {
|
|
140
|
+
throw new DOMException("This operation was aborted", "AbortError");
|
|
141
|
+
}),
|
|
142
|
+
run: vi.fn(),
|
|
143
|
+
continue: vi.fn(),
|
|
144
|
+
canStartRun: vi.fn(() => true),
|
|
145
|
+
getAgentId: vi.fn(() => "teammate-1"),
|
|
146
|
+
getConversationId: vi.fn(() => "conv-1"),
|
|
147
|
+
getMessages: vi.fn(() => []),
|
|
148
|
+
});
|
|
149
|
+
const runtime = new AgentTeamsRuntime({
|
|
150
|
+
teamName: "test-team",
|
|
151
|
+
onTeamEvent: (event) => events.push(event),
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
runtime.spawnTeammate({
|
|
155
|
+
agentId: "python-poet",
|
|
156
|
+
config: {
|
|
157
|
+
providerId: "anthropic",
|
|
158
|
+
modelId: "claude-sonnet-4-5-20250929",
|
|
159
|
+
systemPrompt: "Write concise Python-focused haiku",
|
|
160
|
+
tools: [],
|
|
161
|
+
},
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
expect(() =>
|
|
165
|
+
runtime.shutdownTeammate("python-poet", "manual_restart"),
|
|
166
|
+
).not.toThrow();
|
|
167
|
+
expect(runtime.getSnapshot().members).toContainEqual(
|
|
168
|
+
expect.objectContaining({
|
|
169
|
+
agentId: "python-poet",
|
|
170
|
+
status: "stopped",
|
|
171
|
+
}),
|
|
172
|
+
);
|
|
173
|
+
expect(events).toContainEqual({
|
|
174
|
+
type: TeamMessageType.TeammateShutdown,
|
|
175
|
+
agentId: "python-poet",
|
|
176
|
+
reason: "manual_restart",
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it("prepends unread mailbox notification to teammate message", async () => {
|
|
181
|
+
let routedMessage: string | undefined;
|
|
182
|
+
createAgentMock.mockReturnValueOnce({
|
|
183
|
+
abort: vi.fn(),
|
|
184
|
+
run: vi.fn(async (message) => {
|
|
185
|
+
routedMessage = message;
|
|
186
|
+
return {
|
|
187
|
+
text: "Task completed",
|
|
188
|
+
iterations: 1,
|
|
189
|
+
finishReason: "end_turn",
|
|
190
|
+
durationMs: 100,
|
|
191
|
+
usage: {
|
|
192
|
+
inputTokens: 10,
|
|
193
|
+
outputTokens: 20,
|
|
194
|
+
cacheReadTokens: 0,
|
|
195
|
+
cacheWriteTokens: 0,
|
|
196
|
+
totalCost: 0,
|
|
197
|
+
},
|
|
198
|
+
messages: [],
|
|
199
|
+
};
|
|
200
|
+
}),
|
|
201
|
+
continue: vi.fn(),
|
|
202
|
+
canStartRun: vi.fn(() => true),
|
|
203
|
+
getAgentId: vi.fn(() => "teammate-1"),
|
|
204
|
+
getConversationId: vi.fn(() => "conv-1"),
|
|
205
|
+
getMessages: vi.fn(() => []),
|
|
206
|
+
});
|
|
207
|
+
const runtime = new AgentTeamsRuntime({
|
|
208
|
+
teamName: "test-team",
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
runtime.spawnTeammate({
|
|
212
|
+
agentId: "alice",
|
|
213
|
+
config: {
|
|
214
|
+
providerId: "anthropic",
|
|
215
|
+
modelId: "claude-sonnet-4-5-20250929",
|
|
216
|
+
systemPrompt: "Helper teammate",
|
|
217
|
+
tools: [],
|
|
218
|
+
},
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
// Send message from lead to alice
|
|
222
|
+
runtime.sendMessage(
|
|
223
|
+
"lead",
|
|
224
|
+
"alice",
|
|
225
|
+
"Status check",
|
|
226
|
+
"How is your work going?",
|
|
227
|
+
);
|
|
228
|
+
|
|
229
|
+
// Route task to alice
|
|
230
|
+
await runtime.routeToTeammate("alice", "Complete your task");
|
|
231
|
+
|
|
232
|
+
// Verify the routed message includes mailbox notification
|
|
233
|
+
expect(routedMessage).toBeDefined();
|
|
234
|
+
expect(routedMessage).toContain("[MAILBOX]");
|
|
235
|
+
expect(routedMessage).toContain("You have 1 unread message(s)");
|
|
236
|
+
expect(routedMessage).toContain(
|
|
237
|
+
"Message from lead | subject: Status check",
|
|
238
|
+
);
|
|
239
|
+
expect(routedMessage).toContain("How is your work going?");
|
|
240
|
+
expect(routedMessage).toContain("Complete your task");
|
|
241
|
+
|
|
242
|
+
// Verify message is marked as read
|
|
243
|
+
const unreadAfter = runtime.listMailbox("alice", { unreadOnly: true });
|
|
244
|
+
expect(unreadAfter).toHaveLength(0);
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
it("does not prepend notification when no unread mail", async () => {
|
|
248
|
+
let routedMessage: string | undefined;
|
|
249
|
+
createAgentMock.mockReturnValueOnce({
|
|
250
|
+
abort: vi.fn(),
|
|
251
|
+
run: vi.fn(async (message) => {
|
|
252
|
+
routedMessage = message;
|
|
253
|
+
return {
|
|
254
|
+
text: "Task completed",
|
|
255
|
+
iterations: 1,
|
|
256
|
+
finishReason: "end_turn",
|
|
257
|
+
durationMs: 100,
|
|
258
|
+
usage: {
|
|
259
|
+
inputTokens: 10,
|
|
260
|
+
outputTokens: 20,
|
|
261
|
+
cacheReadTokens: 0,
|
|
262
|
+
cacheWriteTokens: 0,
|
|
263
|
+
totalCost: 0,
|
|
264
|
+
},
|
|
265
|
+
messages: [],
|
|
266
|
+
};
|
|
267
|
+
}),
|
|
268
|
+
continue: vi.fn(),
|
|
269
|
+
canStartRun: vi.fn(() => true),
|
|
270
|
+
getAgentId: vi.fn(() => "teammate-1"),
|
|
271
|
+
getConversationId: vi.fn(() => "conv-1"),
|
|
272
|
+
getMessages: vi.fn(() => []),
|
|
273
|
+
});
|
|
274
|
+
const runtime = new AgentTeamsRuntime({
|
|
275
|
+
teamName: "test-team",
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
runtime.spawnTeammate({
|
|
279
|
+
agentId: "bob",
|
|
280
|
+
config: {
|
|
281
|
+
providerId: "anthropic",
|
|
282
|
+
modelId: "claude-sonnet-4-5-20250929",
|
|
283
|
+
systemPrompt: "Helper teammate",
|
|
284
|
+
tools: [],
|
|
285
|
+
},
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
// Route task to bob with no prior messages
|
|
289
|
+
await runtime.routeToTeammate("bob", "Complete your task");
|
|
290
|
+
|
|
291
|
+
// Verify the routed message does not contain mailbox notification
|
|
292
|
+
expect(routedMessage).toBeDefined();
|
|
293
|
+
expect(routedMessage).toBe("Complete your task");
|
|
294
|
+
expect(routedMessage).not.toContain("[MAILBOX]");
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
it("queues steer message notification when recipient is running", () => {
|
|
298
|
+
let consumePendingMessage: (() => string | undefined) | undefined;
|
|
299
|
+
createAgentMock.mockImplementationOnce((config) => {
|
|
300
|
+
consumePendingMessage = config.consumePendingUserMessage;
|
|
301
|
+
return {
|
|
302
|
+
abort: vi.fn(),
|
|
303
|
+
run: vi.fn(),
|
|
304
|
+
continue: vi.fn(),
|
|
305
|
+
canStartRun: vi.fn(() => true),
|
|
306
|
+
getAgentId: vi.fn(() => "teammate-1"),
|
|
307
|
+
getConversationId: vi.fn(() => "conv-1"),
|
|
308
|
+
getMessages: vi.fn(() => []),
|
|
309
|
+
};
|
|
310
|
+
});
|
|
311
|
+
const runtime = new AgentTeamsRuntime({
|
|
312
|
+
teamName: "test-team",
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
runtime.spawnTeammate({
|
|
316
|
+
agentId: "charlie",
|
|
317
|
+
config: {
|
|
318
|
+
providerId: "anthropic",
|
|
319
|
+
modelId: "claude-sonnet-4-5-20250929",
|
|
320
|
+
systemPrompt: "Helper teammate",
|
|
321
|
+
tools: [],
|
|
322
|
+
},
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
// Simulate teammate is running by incrementing runningCount
|
|
326
|
+
const runtimeMembers = (
|
|
327
|
+
runtime as unknown as { members: Map<string, { runningCount: number }> }
|
|
328
|
+
).members;
|
|
329
|
+
const member = runtimeMembers.get("charlie");
|
|
330
|
+
if (member) {
|
|
331
|
+
member.runningCount = 1;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// Send message from lead while charlie is running
|
|
335
|
+
runtime.sendMessage("lead", "charlie", "urgent update", "Fix the bug now!");
|
|
336
|
+
|
|
337
|
+
// Verify steer message is queued
|
|
338
|
+
expect(consumePendingMessage).toBeDefined();
|
|
339
|
+
const steerMsg = consumePendingMessage?.();
|
|
340
|
+
expect(steerMsg).toBeDefined();
|
|
341
|
+
expect(steerMsg).toContain("[MAILBOX]");
|
|
342
|
+
expect(steerMsg).toContain("lead");
|
|
343
|
+
expect(steerMsg).toContain("urgent update");
|
|
344
|
+
expect(steerMsg).toContain("team_read_mailbox");
|
|
345
|
+
|
|
346
|
+
// Verify consuming again returns undefined
|
|
347
|
+
expect(consumePendingMessage?.()).toBeUndefined();
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
it("does not queue steer message when recipient is idle", () => {
|
|
351
|
+
let consumePendingMessage: (() => string | undefined) | undefined;
|
|
352
|
+
createAgentMock.mockImplementationOnce((config) => {
|
|
353
|
+
consumePendingMessage = config.consumePendingUserMessage;
|
|
354
|
+
return {
|
|
355
|
+
abort: vi.fn(),
|
|
356
|
+
run: vi.fn(),
|
|
357
|
+
continue: vi.fn(),
|
|
358
|
+
canStartRun: vi.fn(() => true),
|
|
359
|
+
getAgentId: vi.fn(() => "teammate-1"),
|
|
360
|
+
getConversationId: vi.fn(() => "conv-1"),
|
|
361
|
+
getMessages: vi.fn(() => []),
|
|
362
|
+
};
|
|
363
|
+
});
|
|
364
|
+
const runtime = new AgentTeamsRuntime({
|
|
365
|
+
teamName: "test-team",
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
runtime.spawnTeammate({
|
|
369
|
+
agentId: "diana",
|
|
370
|
+
config: {
|
|
371
|
+
providerId: "anthropic",
|
|
372
|
+
modelId: "claude-sonnet-4-5-20250929",
|
|
373
|
+
systemPrompt: "Helper teammate",
|
|
374
|
+
tools: [],
|
|
375
|
+
},
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
// Send message from lead while diana is idle (runningCount = 0)
|
|
379
|
+
runtime.sendMessage("lead", "diana", "hello", "Hi there");
|
|
380
|
+
|
|
381
|
+
// Verify no steer message is queued
|
|
382
|
+
expect(consumePendingMessage?.()).toBeUndefined();
|
|
383
|
+
|
|
384
|
+
// Message should still be in mailbox for next route
|
|
385
|
+
const mailbox = runtime.listMailbox("diana", { unreadOnly: true });
|
|
386
|
+
expect(mailbox).toHaveLength(1);
|
|
387
|
+
expect(mailbox[0].subject).toBe("hello");
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
it("includes tool and run error details in run_progress activity", async () => {
|
|
391
|
+
const events: TeamEvent[] = [];
|
|
392
|
+
let wrappedOnEvent: ((event: AgentEvent) => void) | undefined;
|
|
393
|
+
createAgentMock.mockImplementationOnce((config) => {
|
|
394
|
+
wrappedOnEvent = config.onEvent;
|
|
395
|
+
return {
|
|
396
|
+
abort: vi.fn(),
|
|
397
|
+
run: vi.fn(async () => {
|
|
398
|
+
wrappedOnEvent?.({
|
|
399
|
+
type: "content_end",
|
|
400
|
+
contentType: "tool",
|
|
401
|
+
toolName: "team_mission_log",
|
|
402
|
+
error: "RPC backend returned 500 while appending mission log",
|
|
403
|
+
});
|
|
404
|
+
wrappedOnEvent?.({
|
|
405
|
+
type: "error",
|
|
406
|
+
error: new Error("API request timed out after 120000ms"),
|
|
407
|
+
recoverable: false,
|
|
408
|
+
iteration: 11,
|
|
409
|
+
});
|
|
410
|
+
throw new Error("API request timed out after 120000ms");
|
|
411
|
+
}),
|
|
412
|
+
continue: vi.fn(),
|
|
413
|
+
canStartRun: vi.fn(() => true),
|
|
414
|
+
getAgentId: vi.fn(() => "teammate-1"),
|
|
415
|
+
getConversationId: vi.fn(() => "conv-1"),
|
|
416
|
+
getMessages: vi.fn(() => []),
|
|
417
|
+
};
|
|
418
|
+
});
|
|
419
|
+
const runtime = new AgentTeamsRuntime({
|
|
420
|
+
teamName: "test-team",
|
|
421
|
+
onTeamEvent: (event) => events.push(event),
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
runtime.spawnTeammate({
|
|
425
|
+
agentId: "providers-investigator",
|
|
426
|
+
config: {
|
|
427
|
+
providerId: "anthropic",
|
|
428
|
+
modelId: "claude-sonnet-4-5-20250929",
|
|
429
|
+
systemPrompt: "Investigate providers thoroughly",
|
|
430
|
+
tools: [],
|
|
431
|
+
},
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
const run = runtime.startTeammateRun(
|
|
435
|
+
"providers-investigator",
|
|
436
|
+
"Investigate providers",
|
|
437
|
+
);
|
|
438
|
+
const settled = await runtime.awaitRun(run.id);
|
|
439
|
+
|
|
440
|
+
expect(settled.status).toBe("failed");
|
|
441
|
+
expect(events).toContainEqual(
|
|
442
|
+
expect.objectContaining({
|
|
443
|
+
type: TeamMessageType.RunProgress,
|
|
444
|
+
message:
|
|
445
|
+
"tool_team_mission_log_error: RPC backend returned 500 while appending mission log",
|
|
446
|
+
}),
|
|
447
|
+
);
|
|
448
|
+
expect(events).toContainEqual(
|
|
449
|
+
expect.objectContaining({
|
|
450
|
+
type: TeamMessageType.RunProgress,
|
|
451
|
+
message: "run_error: API request timed out after 120000ms",
|
|
452
|
+
}),
|
|
453
|
+
);
|
|
454
|
+
});
|
|
455
|
+
});
|
|
@@ -138,6 +138,23 @@ export interface SpawnTeammateOptions {
|
|
|
138
138
|
config: TeamMemberConfig;
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
+
function isAbortLikeError(error: unknown): boolean {
|
|
142
|
+
if (
|
|
143
|
+
typeof DOMException !== "undefined" &&
|
|
144
|
+
error instanceof DOMException &&
|
|
145
|
+
error.name === "AbortError"
|
|
146
|
+
) {
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
if (!(error instanceof Error)) {
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
return (
|
|
153
|
+
error.name === "AbortError" ||
|
|
154
|
+
error.message.toLowerCase().includes("aborted")
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
141
158
|
// =============================================================================
|
|
142
159
|
// AgentTeam
|
|
143
160
|
// =============================================================================
|
|
@@ -484,6 +501,7 @@ interface TeamMemberState extends TeamMemberSnapshot {
|
|
|
484
501
|
runningCount: number;
|
|
485
502
|
lastMissionStep: number;
|
|
486
503
|
lastMissionAt: number;
|
|
504
|
+
pendingSteerMessage?: string;
|
|
487
505
|
}
|
|
488
506
|
|
|
489
507
|
export class AgentTeamsRuntime {
|
|
@@ -568,8 +586,6 @@ export class AgentTeamsRuntime {
|
|
|
568
586
|
listTaskItems(options?: {
|
|
569
587
|
status?: TeamTaskStatus;
|
|
570
588
|
assignee?: string;
|
|
571
|
-
unassignedOnly?: boolean;
|
|
572
|
-
readyOnly?: boolean;
|
|
573
589
|
}): TeamTaskListItem[] {
|
|
574
590
|
return Array.from(this.tasks.values())
|
|
575
591
|
.map((task) => {
|
|
@@ -590,12 +606,6 @@ export class AgentTeamsRuntime {
|
|
|
590
606
|
if (options?.assignee && task.assignee !== options.assignee) {
|
|
591
607
|
return false;
|
|
592
608
|
}
|
|
593
|
-
if (options?.unassignedOnly && !!task.assignee) {
|
|
594
|
-
return false;
|
|
595
|
-
}
|
|
596
|
-
if (options?.readyOnly && !task.isReady) {
|
|
597
|
-
return false;
|
|
598
|
-
}
|
|
599
609
|
return true;
|
|
600
610
|
});
|
|
601
611
|
}
|
|
@@ -825,6 +835,15 @@ export class AgentTeamsRuntime {
|
|
|
825
835
|
const wrappedConfig: TeamMemberConfig = {
|
|
826
836
|
...config,
|
|
827
837
|
apiTimeoutMs: TEAMMATE_API_TIMEOUT_MS,
|
|
838
|
+
consumePendingUserMessage: () => {
|
|
839
|
+
const member = this.members.get(agentId);
|
|
840
|
+
if (!member || !member.pendingSteerMessage) {
|
|
841
|
+
return undefined;
|
|
842
|
+
}
|
|
843
|
+
const message = member.pendingSteerMessage;
|
|
844
|
+
member.pendingSteerMessage = undefined;
|
|
845
|
+
return message;
|
|
846
|
+
},
|
|
828
847
|
onEvent: (event: AgentEvent) => {
|
|
829
848
|
config.onEvent?.(event);
|
|
830
849
|
this.emitEvent({ type: TeamMessageType.AgentEvent, agentId, event });
|
|
@@ -870,7 +889,13 @@ export class AgentTeamsRuntime {
|
|
|
870
889
|
if (!member || member.role !== "teammate") {
|
|
871
890
|
throw new Error(`Teammate "${agentId}" was not found`);
|
|
872
891
|
}
|
|
873
|
-
|
|
892
|
+
try {
|
|
893
|
+
member.agent?.abort();
|
|
894
|
+
} catch (error) {
|
|
895
|
+
if (!isAbortLikeError(error)) {
|
|
896
|
+
throw error;
|
|
897
|
+
}
|
|
898
|
+
}
|
|
874
899
|
member.status = "stopped";
|
|
875
900
|
this.emitEvent({ type: TeamMessageType.TeammateShutdown, agentId, reason });
|
|
876
901
|
}
|
|
@@ -986,9 +1011,17 @@ export class AgentTeamsRuntime {
|
|
|
986
1011
|
this.emitEvent({ type: TeamMessageType.TaskStart, agentId, message });
|
|
987
1012
|
|
|
988
1013
|
try {
|
|
1014
|
+
const unreadMail = this.listMailbox(agentId, {
|
|
1015
|
+
unreadOnly: true,
|
|
1016
|
+
markRead: true,
|
|
1017
|
+
});
|
|
1018
|
+
const enrichedMessage =
|
|
1019
|
+
unreadMail.length > 0
|
|
1020
|
+
? `${this.buildMailboxNotification(unreadMail)}\n\n${message}`
|
|
1021
|
+
: message;
|
|
989
1022
|
const result = options?.continueConversation
|
|
990
|
-
? await member.agent.continue(
|
|
991
|
-
: await member.agent.run(
|
|
1023
|
+
? await member.agent.continue(enrichedMessage)
|
|
1024
|
+
: await member.agent.run(enrichedMessage);
|
|
992
1025
|
this.emitEvent({ type: TeamMessageType.TaskEnd, agentId, result });
|
|
993
1026
|
this.recordProgressStep(
|
|
994
1027
|
agentId,
|
|
@@ -1254,7 +1287,8 @@ export class AgentTeamsRuntime {
|
|
|
1254
1287
|
if (!this.members.has(fromAgentId)) {
|
|
1255
1288
|
throw new Error(`Unknown sender "${fromAgentId}"`);
|
|
1256
1289
|
}
|
|
1257
|
-
|
|
1290
|
+
const recipient = this.members.get(toAgentId);
|
|
1291
|
+
if (!recipient) {
|
|
1258
1292
|
throw new Error(`Unknown recipient "${toAgentId}"`);
|
|
1259
1293
|
}
|
|
1260
1294
|
const message: TeamMailboxMessage = {
|
|
@@ -1272,6 +1306,13 @@ export class AgentTeamsRuntime {
|
|
|
1272
1306
|
type: TeamMessageType.TeamMessage,
|
|
1273
1307
|
message: { ...message },
|
|
1274
1308
|
});
|
|
1309
|
+
if (
|
|
1310
|
+
recipient.role === "teammate" &&
|
|
1311
|
+
recipient.runningCount > 0 &&
|
|
1312
|
+
recipient.agent
|
|
1313
|
+
) {
|
|
1314
|
+
recipient.pendingSteerMessage = `[MAILBOX] You got a message from ${fromAgentId}. Subject: "${subject}". Use the team_read_mailbox tool to read it at your convenience.`;
|
|
1315
|
+
}
|
|
1275
1316
|
return { ...message };
|
|
1276
1317
|
}
|
|
1277
1318
|
|
|
@@ -1279,15 +1320,14 @@ export class AgentTeamsRuntime {
|
|
|
1279
1320
|
fromAgentId: string,
|
|
1280
1321
|
subject: string,
|
|
1281
1322
|
body: string,
|
|
1282
|
-
options?: {
|
|
1323
|
+
options?: { taskId?: string },
|
|
1283
1324
|
): TeamMailboxMessage[] {
|
|
1284
|
-
const includeLead = options?.includeLead ?? false;
|
|
1285
1325
|
const messages: TeamMailboxMessage[] = [];
|
|
1286
1326
|
for (const member of this.members.values()) {
|
|
1287
1327
|
if (member.agentId === fromAgentId) {
|
|
1288
1328
|
continue;
|
|
1289
1329
|
}
|
|
1290
|
-
if (
|
|
1330
|
+
if (member.role === "lead") {
|
|
1291
1331
|
continue;
|
|
1292
1332
|
}
|
|
1293
1333
|
messages.push(
|
|
@@ -1458,7 +1498,13 @@ export class AgentTeamsRuntime {
|
|
|
1458
1498
|
|
|
1459
1499
|
for (const member of this.members.values()) {
|
|
1460
1500
|
if (member.role === "teammate") {
|
|
1461
|
-
|
|
1501
|
+
try {
|
|
1502
|
+
member.agent?.abort();
|
|
1503
|
+
} catch (error) {
|
|
1504
|
+
if (!isAbortLikeError(error)) {
|
|
1505
|
+
throw error;
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1462
1508
|
}
|
|
1463
1509
|
}
|
|
1464
1510
|
|
|
@@ -1526,7 +1572,7 @@ export class AgentTeamsRuntime {
|
|
|
1526
1572
|
this.appendMissionLog({
|
|
1527
1573
|
agentId,
|
|
1528
1574
|
kind: "done",
|
|
1529
|
-
summary: `
|
|
1575
|
+
summary: `Completed a delegated run (${event.iterations} iterations)`,
|
|
1530
1576
|
});
|
|
1531
1577
|
return;
|
|
1532
1578
|
}
|
|
@@ -1638,6 +1684,23 @@ export class AgentTeamsRuntime {
|
|
|
1638
1684
|
});
|
|
1639
1685
|
}
|
|
1640
1686
|
|
|
1687
|
+
private buildMailboxNotification(messages: TeamMailboxMessage[]): string {
|
|
1688
|
+
if (messages.length === 0) {
|
|
1689
|
+
return "";
|
|
1690
|
+
}
|
|
1691
|
+
const lines: string[] = [
|
|
1692
|
+
`[MAILBOX] You have ${messages.length} unread message(s):`,
|
|
1693
|
+
];
|
|
1694
|
+
for (const msg of messages) {
|
|
1695
|
+
lines.push(
|
|
1696
|
+
`--- Message from ${msg.fromAgentId} | subject: ${msg.subject} ---`,
|
|
1697
|
+
);
|
|
1698
|
+
lines.push(msg.body);
|
|
1699
|
+
}
|
|
1700
|
+
lines.push("---");
|
|
1701
|
+
return lines.join("\n");
|
|
1702
|
+
}
|
|
1703
|
+
|
|
1641
1704
|
private emitEvent(event: TeamEvent): void {
|
|
1642
1705
|
try {
|
|
1643
1706
|
this.onTeamEvent?.(event);
|
|
@@ -180,7 +180,6 @@ describe("createSpawnAgentTool", () => {
|
|
|
180
180
|
{
|
|
181
181
|
systemPrompt: "System",
|
|
182
182
|
task: "Fail task",
|
|
183
|
-
maxIterations: 6,
|
|
184
183
|
},
|
|
185
184
|
{
|
|
186
185
|
agentId: "parent-2",
|
|
@@ -197,11 +196,6 @@ describe("createSpawnAgentTool", () => {
|
|
|
197
196
|
error: expect.any(Error),
|
|
198
197
|
}),
|
|
199
198
|
);
|
|
200
|
-
expect(agentConstructorSpy).toHaveBeenCalledWith(
|
|
201
|
-
expect.objectContaining({
|
|
202
|
-
maxIterations: 6,
|
|
203
|
-
}),
|
|
204
|
-
);
|
|
205
199
|
});
|
|
206
200
|
|
|
207
201
|
it("leaves maxIterations unset when neither input nor default is provided", async () => {
|
|
@@ -32,12 +32,6 @@ export const SpawnAgentInputSchema = z.object({
|
|
|
32
32
|
.string()
|
|
33
33
|
.describe("System prompt defining the sub-agent's behavior"),
|
|
34
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
35
|
});
|
|
42
36
|
|
|
43
37
|
export type SpawnAgentInput = z.infer<typeof SpawnAgentInputSchema>;
|
|
@@ -136,7 +130,7 @@ export function createSpawnAgentTool(
|
|
|
136
130
|
prompt: input.systemPrompt,
|
|
137
131
|
configProvider: config.configProvider,
|
|
138
132
|
tools,
|
|
139
|
-
maxIterations:
|
|
133
|
+
maxIterations: config.defaultMaxIterations,
|
|
140
134
|
parentAgentId: context.agentId,
|
|
141
135
|
abortSignal: context.abortSignal,
|
|
142
136
|
onEvent: config.onSubAgentEvent,
|
|
@@ -11,7 +11,7 @@ export function buildTeammateSystemPrompt(
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
return buildClineSystemPrompt({
|
|
14
|
-
ide: config.clineIdeName?.trim() || "Terminal
|
|
14
|
+
ide: config.clineIdeName?.trim() || "Terminal",
|
|
15
15
|
workspaceRoot: config.cwd?.trim() || "/",
|
|
16
16
|
providerId: config.providerId,
|
|
17
17
|
rules: `# Team Teammate Role\n${trimmedPrompt}`,
|
|
@@ -31,7 +31,7 @@ export function buildSubAgentSystemPrompt(
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
return buildClineSystemPrompt({
|
|
34
|
-
ide: "Terminal
|
|
34
|
+
ide: config.clineIdeName || "Terminal",
|
|
35
35
|
workspaceRoot: config.cwd?.trim() || "/",
|
|
36
36
|
providerId: config.providerId,
|
|
37
37
|
overridePrompt: trimmedPrompt,
|