@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
|
@@ -2,30 +2,30 @@ import { existsSync, readFileSync } from "node:fs";
|
|
|
2
2
|
import { readFile, stat } from "node:fs/promises";
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
4
|
import { isAbsolute, join, resolve } from "node:path";
|
|
5
|
+
import { Agent } from "@clinebot/agents";
|
|
6
|
+
import type * as LlmsProviders from "@clinebot/llms";
|
|
5
7
|
import {
|
|
6
|
-
Agent,
|
|
7
8
|
type AgentConfig,
|
|
8
9
|
type AgentEvent,
|
|
9
10
|
type AgentResult,
|
|
10
|
-
createSpawnAgentTool,
|
|
11
|
-
type TeamEvent,
|
|
12
|
-
type Tool,
|
|
13
|
-
type ToolApprovalRequest,
|
|
14
|
-
type ToolApprovalResult,
|
|
15
|
-
} from "@clinebot/agents";
|
|
16
|
-
import type * as LlmsProviders from "@clinebot/llms/providers";
|
|
17
|
-
import {
|
|
18
11
|
createSessionId,
|
|
19
12
|
type ITelemetryService,
|
|
20
13
|
isLikelyAuthError,
|
|
21
14
|
normalizeUserInput,
|
|
15
|
+
type Tool,
|
|
16
|
+
type ToolApprovalRequest,
|
|
17
|
+
type ToolApprovalResult,
|
|
22
18
|
} from "@clinebot/shared";
|
|
23
19
|
import { setHomeDirIfUnset } from "@clinebot/shared/storage";
|
|
24
20
|
import { nanoid } from "nanoid";
|
|
21
|
+
import { createContextCompactionPrepareTurn } from "../extensions/context/compaction";
|
|
25
22
|
import { enrichPromptWithMentions } from "../input";
|
|
23
|
+
import { createCheckpointHooks } from "../runtime/checkpoint-hooks";
|
|
24
|
+
import { mergeAgentHooks } from "../runtime/hook-file-hooks";
|
|
26
25
|
import { DefaultRuntimeBuilder } from "../runtime/runtime-builder";
|
|
27
26
|
import type { RuntimeBuilder } from "../runtime/session-runtime";
|
|
28
27
|
import { ProviderSettingsManager } from "../storage/provider-settings-manager";
|
|
28
|
+
import { createSpawnAgentTool, type TeamEvent } from "../team";
|
|
29
29
|
import {
|
|
30
30
|
captureAgentCreated,
|
|
31
31
|
captureAgentTeamCreated,
|
|
@@ -35,7 +35,12 @@ import {
|
|
|
35
35
|
captureTaskCompleted,
|
|
36
36
|
} from "../telemetry/core-events";
|
|
37
37
|
import { resolveCoreDistinctId } from "../telemetry/distinct-id";
|
|
38
|
-
import {
|
|
38
|
+
import {
|
|
39
|
+
createBuiltinTools,
|
|
40
|
+
resolveToolPresetName,
|
|
41
|
+
type ToolExecutors,
|
|
42
|
+
ToolPresets,
|
|
43
|
+
} from "../tools";
|
|
39
44
|
import { SessionSource, type SessionStatus } from "../types/common";
|
|
40
45
|
import type { CoreSessionConfig } from "../types/config";
|
|
41
46
|
import type { CoreSessionEvent } from "../types/events";
|
|
@@ -67,7 +72,10 @@ import type {
|
|
|
67
72
|
StartSessionInput,
|
|
68
73
|
StartSessionResult,
|
|
69
74
|
} from "./session-manager";
|
|
70
|
-
import {
|
|
75
|
+
import {
|
|
76
|
+
type SessionManifest,
|
|
77
|
+
SessionManifestSchema,
|
|
78
|
+
} from "./session-manifest";
|
|
71
79
|
import type {
|
|
72
80
|
CoreSessionService,
|
|
73
81
|
RootSessionArtifacts,
|
|
@@ -89,7 +97,6 @@ import {
|
|
|
89
97
|
emitSessionCreationTelemetry,
|
|
90
98
|
} from "./session-telemetry";
|
|
91
99
|
import {
|
|
92
|
-
extractWorkspaceMetadataFromSystemPrompt,
|
|
93
100
|
toSessionRecord,
|
|
94
101
|
withLatestAssistantTurnMetadata,
|
|
95
102
|
} from "./utils/helpers";
|
|
@@ -98,6 +105,7 @@ import {
|
|
|
98
105
|
accumulateUsageTotals,
|
|
99
106
|
createInitialAccumulatedUsage,
|
|
100
107
|
} from "./utils/usage";
|
|
108
|
+
import { buildWorkspaceMetadata } from "./workspace-manifest";
|
|
101
109
|
|
|
102
110
|
type SessionBackend =
|
|
103
111
|
| CoreSessionService
|
|
@@ -107,6 +115,11 @@ type SessionBackend =
|
|
|
107
115
|
const MAX_SCAN_LIMIT = 5000;
|
|
108
116
|
const MAX_USER_FILE_BYTES = 20 * 1_000 * 1_024;
|
|
109
117
|
|
|
118
|
+
// NOTE: Temporarily disabled until checkpoint is ready for production.
|
|
119
|
+
function isCheckpointFeatureEnabled(): boolean {
|
|
120
|
+
return process?.env?.CLINE_CHECKPOINT === "true";
|
|
121
|
+
}
|
|
122
|
+
|
|
110
123
|
async function loadUserFileContent(path: string): Promise<string> {
|
|
111
124
|
const fileStat = await stat(path);
|
|
112
125
|
if (!fileStat.isFile()) {
|
|
@@ -187,6 +200,21 @@ export class DefaultSessionManager implements SessionManager {
|
|
|
187
200
|
const startedAt = nowIso();
|
|
188
201
|
const requestedSessionId = input.config.sessionId?.trim() ?? "";
|
|
189
202
|
const sessionId = requestedSessionId || createSessionId();
|
|
203
|
+
const resumedRow = requestedSessionId
|
|
204
|
+
? await this.getRow(sessionId)
|
|
205
|
+
: undefined;
|
|
206
|
+
const startInput: StartSessionInput =
|
|
207
|
+
resumedRow &&
|
|
208
|
+
!input.config.teamName?.trim() &&
|
|
209
|
+
resumedRow.teamName?.trim()
|
|
210
|
+
? {
|
|
211
|
+
...input,
|
|
212
|
+
config: {
|
|
213
|
+
...input.config,
|
|
214
|
+
teamName: resumedRow.teamName,
|
|
215
|
+
},
|
|
216
|
+
}
|
|
217
|
+
: input;
|
|
190
218
|
this.usageBySession.set(sessionId, createInitialAccumulatedUsage());
|
|
191
219
|
|
|
192
220
|
const sessionsDir =
|
|
@@ -214,26 +242,29 @@ export class DefaultSessionManager implements SessionManager {
|
|
|
214
242
|
started_at: startedAt,
|
|
215
243
|
status: "running",
|
|
216
244
|
interactive: input.interactive === true,
|
|
217
|
-
provider:
|
|
218
|
-
model:
|
|
219
|
-
cwd:
|
|
245
|
+
provider: startInput.config.providerId,
|
|
246
|
+
model: startInput.config.modelId,
|
|
247
|
+
cwd: startInput.config.cwd,
|
|
220
248
|
workspace_root: workspacePath,
|
|
221
|
-
team_name:
|
|
222
|
-
enable_tools:
|
|
223
|
-
enable_spawn:
|
|
224
|
-
enable_teams:
|
|
225
|
-
prompt:
|
|
249
|
+
team_name: startInput.config.teamName,
|
|
250
|
+
enable_tools: startInput.config.enableTools,
|
|
251
|
+
enable_spawn: startInput.config.enableSpawnAgent,
|
|
252
|
+
enable_teams: startInput.config.enableAgentTeams,
|
|
253
|
+
prompt: startInput.prompt?.trim() || undefined,
|
|
226
254
|
messages_path: messagesPath,
|
|
227
255
|
});
|
|
228
256
|
|
|
229
257
|
const { config: effectiveConfig, pluginSandboxShutdown } =
|
|
230
258
|
await buildEffectiveConfig(
|
|
231
|
-
|
|
259
|
+
startInput,
|
|
232
260
|
hookPath,
|
|
233
261
|
sessionId,
|
|
234
262
|
this.defaultTelemetry,
|
|
235
263
|
(e) => void this.handlePluginEvent(sessionId, e),
|
|
236
264
|
);
|
|
265
|
+
const workspaceMetadata = await buildWorkspaceMetadata(
|
|
266
|
+
startInput.config.cwd,
|
|
267
|
+
);
|
|
237
268
|
const providerConfig = buildResolvedProviderConfig(
|
|
238
269
|
effectiveConfig,
|
|
239
270
|
this.providerSettingsManager,
|
|
@@ -242,11 +273,29 @@ export class DefaultSessionManager implements SessionManager {
|
|
|
242
273
|
const configWithProvider: CoreSessionConfig = {
|
|
243
274
|
...effectiveConfig,
|
|
244
275
|
providerConfig,
|
|
276
|
+
workspaceMetadata,
|
|
245
277
|
};
|
|
278
|
+
configWithProvider.hooks = mergeAgentHooks([
|
|
279
|
+
effectiveConfig.hooks,
|
|
280
|
+
isCheckpointFeatureEnabled()
|
|
281
|
+
? createCheckpointHooks({
|
|
282
|
+
cwd: configWithProvider.cwd,
|
|
283
|
+
sessionId,
|
|
284
|
+
logger: configWithProvider.logger,
|
|
285
|
+
readSessionMetadata: async () =>
|
|
286
|
+
(await this.get(sessionId))?.metadata as
|
|
287
|
+
| Record<string, unknown>
|
|
288
|
+
| undefined,
|
|
289
|
+
writeSessionMetadata: async (metadata) => {
|
|
290
|
+
await this.persistSessionMetadata(sessionId, () => metadata);
|
|
291
|
+
},
|
|
292
|
+
})
|
|
293
|
+
: undefined,
|
|
294
|
+
]);
|
|
246
295
|
|
|
247
|
-
const runtime = this.runtimeBuilder.build({
|
|
296
|
+
const runtime = await this.runtimeBuilder.build({
|
|
248
297
|
config: configWithProvider,
|
|
249
|
-
hooks:
|
|
298
|
+
hooks: configWithProvider.hooks,
|
|
250
299
|
extensions: effectiveConfig.extensions,
|
|
251
300
|
logger: configWithProvider.logger,
|
|
252
301
|
telemetry: configWithProvider.telemetry,
|
|
@@ -260,6 +309,7 @@ export class DefaultSessionManager implements SessionManager {
|
|
|
260
309
|
userInstructionWatcher: input.userInstructionWatcher,
|
|
261
310
|
defaultToolExecutors:
|
|
262
311
|
input.defaultToolExecutors ?? this.defaultToolExecutors,
|
|
312
|
+
teamToolsFactory: input.teamToolsFactory,
|
|
263
313
|
});
|
|
264
314
|
if (runtime.teamRuntime && !configWithProvider.teamName?.trim()) {
|
|
265
315
|
configWithProvider.teamName = runtime.teamRuntime.getTeamName();
|
|
@@ -267,7 +317,7 @@ export class DefaultSessionManager implements SessionManager {
|
|
|
267
317
|
|
|
268
318
|
const tools = [...runtime.tools, ...(configWithProvider.extraTools ?? [])];
|
|
269
319
|
|
|
270
|
-
const
|
|
320
|
+
const agentConfig = {
|
|
271
321
|
providerId: providerConfig.providerId,
|
|
272
322
|
modelId: providerConfig.modelId,
|
|
273
323
|
apiKey: providerConfig.apiKey,
|
|
@@ -281,8 +331,9 @@ export class DefaultSessionManager implements SessionManager {
|
|
|
281
331
|
systemPrompt: configWithProvider.systemPrompt,
|
|
282
332
|
maxIterations: configWithProvider.maxIterations,
|
|
283
333
|
execution: configWithProvider.execution,
|
|
334
|
+
prepareTurn: createContextCompactionPrepareTurn(configWithProvider),
|
|
284
335
|
tools,
|
|
285
|
-
hooks:
|
|
336
|
+
hooks: configWithProvider.hooks,
|
|
286
337
|
extensions: effectiveConfig.extensions,
|
|
287
338
|
hookErrorMode: configWithProvider.hookErrorMode,
|
|
288
339
|
initialMessages: input.initialMessages,
|
|
@@ -294,9 +345,12 @@ export class DefaultSessionManager implements SessionManager {
|
|
|
294
345
|
configWithProvider.onConsecutiveMistakeLimitReached,
|
|
295
346
|
completionGuard: runtime.completionGuard,
|
|
296
347
|
logger: runtime.logger ?? configWithProvider.logger,
|
|
348
|
+
extensionContext: configWithProvider.extensionContext,
|
|
297
349
|
onEvent: (event: AgentEvent) =>
|
|
298
350
|
this.onAgentEvent(sessionId, configWithProvider, event),
|
|
299
|
-
}
|
|
351
|
+
} as AgentConfig;
|
|
352
|
+
const agent = this.createAgentInstance(agentConfig);
|
|
353
|
+
runtime.registerLeadAgent?.(agent);
|
|
300
354
|
const rootAgentIdentity = buildTelemetryAgentIdentity({
|
|
301
355
|
agentId: this.readAgentId(agent),
|
|
302
356
|
conversationId: this.readAgentConversationId(agent),
|
|
@@ -341,7 +395,7 @@ export class DefaultSessionManager implements SessionManager {
|
|
|
341
395
|
started: false,
|
|
342
396
|
aborting: false,
|
|
343
397
|
interactive: input.interactive === true,
|
|
344
|
-
persistedMessages:
|
|
398
|
+
persistedMessages: startInput.initialMessages,
|
|
345
399
|
activeTeamRunIds: new Set<string>(),
|
|
346
400
|
pendingTeamRunUpdates: [],
|
|
347
401
|
teamRunWaiters: [],
|
|
@@ -354,11 +408,11 @@ export class DefaultSessionManager implements SessionManager {
|
|
|
354
408
|
|
|
355
409
|
let result: AgentResult | undefined;
|
|
356
410
|
try {
|
|
357
|
-
if (
|
|
411
|
+
if (startInput.prompt?.trim()) {
|
|
358
412
|
result = await this.runTurn(active, {
|
|
359
|
-
prompt:
|
|
360
|
-
userImages:
|
|
361
|
-
userFiles:
|
|
413
|
+
prompt: startInput.prompt,
|
|
414
|
+
userImages: startInput.userImages,
|
|
415
|
+
userFiles: startInput.userFiles,
|
|
362
416
|
});
|
|
363
417
|
if (!active.interactive) {
|
|
364
418
|
await this.finalizeSingleRun(active, result.finishReason);
|
|
@@ -650,10 +704,15 @@ export class DefaultSessionManager implements SessionManager {
|
|
|
650
704
|
baselineMessages,
|
|
651
705
|
);
|
|
652
706
|
session.persistedMessages = persistedMessages;
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
707
|
+
const accumulatedUsage = accumulateUsageTotals(
|
|
708
|
+
usageBaseline,
|
|
709
|
+
result.usage,
|
|
656
710
|
);
|
|
711
|
+
this.usageBySession.set(session.sessionId, accumulatedUsage);
|
|
712
|
+
await this.persistSessionMetadata(session.sessionId, (current) => ({
|
|
713
|
+
...(current ?? {}),
|
|
714
|
+
totalCost: accumulatedUsage.totalCost,
|
|
715
|
+
}));
|
|
657
716
|
await this.invoke<void>(
|
|
658
717
|
"persistSessionMessages",
|
|
659
718
|
session.sessionId,
|
|
@@ -744,6 +803,37 @@ export class DefaultSessionManager implements SessionManager {
|
|
|
744
803
|
})) as RootSessionArtifacts;
|
|
745
804
|
}
|
|
746
805
|
|
|
806
|
+
private async persistSessionMetadata(
|
|
807
|
+
sessionId: string,
|
|
808
|
+
resolveMetadata: (
|
|
809
|
+
current: Record<string, unknown> | undefined,
|
|
810
|
+
) => Record<string, unknown> | undefined,
|
|
811
|
+
): Promise<void> {
|
|
812
|
+
const session = this.sessions.get(sessionId);
|
|
813
|
+
const currentManifest =
|
|
814
|
+
(await this.invokeOptionalValue<SessionManifest>(
|
|
815
|
+
"readSessionManifest",
|
|
816
|
+
sessionId,
|
|
817
|
+
)) ?? session?.artifacts?.manifest;
|
|
818
|
+
const metadata = resolveMetadata(
|
|
819
|
+
currentManifest?.metadata as Record<string, unknown> | undefined,
|
|
820
|
+
);
|
|
821
|
+
if (!session?.artifacts) {
|
|
822
|
+
return;
|
|
823
|
+
}
|
|
824
|
+
const result = await this.invokeOptionalValue<{ updated?: boolean }>(
|
|
825
|
+
"updateSession",
|
|
826
|
+
{
|
|
827
|
+
sessionId,
|
|
828
|
+
metadata,
|
|
829
|
+
},
|
|
830
|
+
);
|
|
831
|
+
if (result?.updated === false) {
|
|
832
|
+
return;
|
|
833
|
+
}
|
|
834
|
+
session.artifacts.manifest.metadata = metadata;
|
|
835
|
+
}
|
|
836
|
+
|
|
747
837
|
private async finalizeSingleRun(
|
|
748
838
|
session: ActiveSession,
|
|
749
839
|
finishReason: AgentResult["finishReason"],
|
|
@@ -818,14 +908,19 @@ export class DefaultSessionManager implements SessionManager {
|
|
|
818
908
|
exitCode,
|
|
819
909
|
);
|
|
820
910
|
if (!result.updated) return;
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
911
|
+
const latestManifest =
|
|
912
|
+
(await this.invokeOptionalValue<SessionManifest>(
|
|
913
|
+
"readSessionManifest",
|
|
914
|
+
session.sessionId,
|
|
915
|
+
)) ?? session.artifacts.manifest;
|
|
916
|
+
latestManifest.status = status;
|
|
917
|
+
latestManifest.ended_at = result.endedAt ?? nowIso();
|
|
918
|
+
latestManifest.exit_code = typeof exitCode === "number" ? exitCode : null;
|
|
919
|
+
session.artifacts.manifest = latestManifest;
|
|
825
920
|
await this.invoke<void>(
|
|
826
921
|
"writeSessionManifest",
|
|
827
922
|
session.artifacts.manifestPath,
|
|
828
|
-
|
|
923
|
+
latestManifest,
|
|
829
924
|
);
|
|
830
925
|
this.emitStatus(session.sessionId, status);
|
|
831
926
|
}
|
|
@@ -1065,9 +1160,12 @@ export class DefaultSessionManager implements SessionManager {
|
|
|
1065
1160
|
const tools: Tool[] = config.enableTools
|
|
1066
1161
|
? createBuiltinTools({
|
|
1067
1162
|
cwd: config.cwd,
|
|
1068
|
-
...
|
|
1069
|
-
|
|
1070
|
-
|
|
1163
|
+
...ToolPresets[
|
|
1164
|
+
resolveToolPresetName({
|
|
1165
|
+
mode: config.mode,
|
|
1166
|
+
yolo: config.yolo,
|
|
1167
|
+
})
|
|
1168
|
+
],
|
|
1071
1169
|
executors: this.defaultToolExecutors,
|
|
1072
1170
|
})
|
|
1073
1171
|
: [];
|
|
@@ -1092,10 +1190,6 @@ export class DefaultSessionManager implements SessionManager {
|
|
|
1092
1190
|
providerConfig: config.providerConfig,
|
|
1093
1191
|
knownModels: config.knownModels,
|
|
1094
1192
|
thinking: config.thinking,
|
|
1095
|
-
clineWorkspaceMetadata:
|
|
1096
|
-
config.providerId === "cline"
|
|
1097
|
-
? extractWorkspaceMetadataFromSystemPrompt(config.systemPrompt)
|
|
1098
|
-
: undefined,
|
|
1099
1193
|
maxIterations: config.maxIterations,
|
|
1100
1194
|
hooks: config.hooks,
|
|
1101
1195
|
extensions: config.extensions,
|
|
@@ -7,12 +7,12 @@ import {
|
|
|
7
7
|
} from "node:fs";
|
|
8
8
|
import { join } from "node:path";
|
|
9
9
|
import { resolveSessionDataDir } from "@clinebot/shared/storage";
|
|
10
|
-
import type { SessionRow } from "./session-service";
|
|
11
10
|
import type {
|
|
12
11
|
PersistedSessionUpdateInput,
|
|
13
12
|
SessionPersistenceAdapter,
|
|
14
|
-
} from "./
|
|
15
|
-
import { UnifiedSessionPersistenceService } from "./
|
|
13
|
+
} from "./persistence-service";
|
|
14
|
+
import { UnifiedSessionPersistenceService } from "./persistence-service";
|
|
15
|
+
import type { SessionRow } from "./session-service";
|
|
16
16
|
|
|
17
17
|
interface FileSessionIndex {
|
|
18
18
|
version: 1;
|
package/src/session/index.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
export {
|
|
2
|
+
upsertWorkspaceInfo,
|
|
3
|
+
type WorkspaceInfo,
|
|
4
|
+
type WorkspaceManifest,
|
|
5
|
+
WorkspaceManifestSchema,
|
|
6
|
+
} from "@clinebot/shared";
|
|
1
7
|
export type {
|
|
2
8
|
ClineCore,
|
|
3
9
|
ClineCoreOptions,
|
|
@@ -33,13 +39,7 @@ export type {
|
|
|
33
39
|
WorkspaceManagerEvent,
|
|
34
40
|
} from "./workspace-manager";
|
|
35
41
|
export { InMemoryWorkspaceManager } from "./workspace-manager";
|
|
36
|
-
export type { WorkspaceManifest } from "./workspace-manifest";
|
|
37
42
|
export {
|
|
38
|
-
buildWorkspaceMetadata,
|
|
39
|
-
emptyWorkspaceManifest,
|
|
40
43
|
generateWorkspaceInfo,
|
|
41
44
|
normalizeWorkspacePath,
|
|
42
|
-
upsertWorkspaceInfo,
|
|
43
|
-
WorkspaceInfoSchema,
|
|
44
|
-
WorkspaceManifestSchema,
|
|
45
45
|
} from "./workspace-manifest";
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { afterEach, describe, expect, it } from "vitest";
|
|
5
|
+
import { SqliteSessionStore } from "../storage/sqlite-session-store";
|
|
6
|
+
import { SessionSource } from "../types/common";
|
|
7
|
+
import { CoreSessionService } from "./session-service";
|
|
8
|
+
|
|
9
|
+
describe("UnifiedSessionPersistenceService", () => {
|
|
10
|
+
const tempDirs: string[] = [];
|
|
11
|
+
const stores: Array<SqliteSessionStore> = [];
|
|
12
|
+
|
|
13
|
+
afterEach(() => {
|
|
14
|
+
for (const store of stores.splice(0)) {
|
|
15
|
+
store.close();
|
|
16
|
+
}
|
|
17
|
+
for (const dir of tempDirs.splice(0)) {
|
|
18
|
+
rmSync(dir, { recursive: true, force: true });
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("reconciles dead running sessions into failed manifests with terminal markers", async () => {
|
|
23
|
+
const sessionsDir = mkdtempSync(join(tmpdir(), "stale-session-reconcile-"));
|
|
24
|
+
tempDirs.push(sessionsDir);
|
|
25
|
+
|
|
26
|
+
const store = new SqliteSessionStore({ sessionsDir });
|
|
27
|
+
stores.push(store);
|
|
28
|
+
const service = new CoreSessionService(store);
|
|
29
|
+
const sessionId = "stale-root-session";
|
|
30
|
+
const artifacts = await service.createRootSessionWithArtifacts({
|
|
31
|
+
sessionId,
|
|
32
|
+
source: SessionSource.CLI,
|
|
33
|
+
pid: 999_999_999,
|
|
34
|
+
interactive: false,
|
|
35
|
+
provider: "mock-provider",
|
|
36
|
+
model: "mock-model",
|
|
37
|
+
cwd: "/tmp/project",
|
|
38
|
+
workspaceRoot: "/tmp/project",
|
|
39
|
+
enableTools: true,
|
|
40
|
+
enableSpawn: true,
|
|
41
|
+
enableTeams: false,
|
|
42
|
+
prompt: "hello",
|
|
43
|
+
startedAt: "2026-01-01T00:00:00.000Z",
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const reconciled = await service.reconcileDeadSessions();
|
|
47
|
+
expect(reconciled).toBe(1);
|
|
48
|
+
|
|
49
|
+
const rows = await service.listSessions(10);
|
|
50
|
+
expect(rows).toHaveLength(1);
|
|
51
|
+
expect(rows[0]).toMatchObject({
|
|
52
|
+
sessionId,
|
|
53
|
+
status: "failed",
|
|
54
|
+
exitCode: 1,
|
|
55
|
+
});
|
|
56
|
+
expect(rows[0]?.endedAt).toBeTruthy();
|
|
57
|
+
|
|
58
|
+
const manifest = JSON.parse(
|
|
59
|
+
readFileSync(artifacts.manifestPath, "utf8"),
|
|
60
|
+
) as Record<string, unknown>;
|
|
61
|
+
expect(manifest.status).toBe("failed");
|
|
62
|
+
expect(manifest.exit_code).toBe(1);
|
|
63
|
+
expect(manifest.ended_at).toBeTruthy();
|
|
64
|
+
expect(manifest.metadata).toMatchObject({
|
|
65
|
+
terminal_marker: "failed_external_process_exit",
|
|
66
|
+
terminal_marker_pid: 999_999_999,
|
|
67
|
+
terminal_marker_source: "stale_session_reconciler",
|
|
68
|
+
});
|
|
69
|
+
expect(
|
|
70
|
+
(manifest.metadata as Record<string, unknown>).terminal_marker_at,
|
|
71
|
+
).toBeTruthy();
|
|
72
|
+
|
|
73
|
+
expect(existsSync(artifacts.hookPath)).toBe(true);
|
|
74
|
+
expect(existsSync(artifacts.transcriptPath)).toBe(true);
|
|
75
|
+
expect(readFileSync(artifacts.hookPath, "utf8")).toContain(
|
|
76
|
+
'"hookName":"session_shutdown"',
|
|
77
|
+
);
|
|
78
|
+
expect(readFileSync(artifacts.hookPath, "utf8")).toContain(
|
|
79
|
+
'"reason":"failed_external_process_exit"',
|
|
80
|
+
);
|
|
81
|
+
expect(readFileSync(artifacts.transcriptPath, "utf8")).toContain(
|
|
82
|
+
"[shutdown] failed_external_process_exit",
|
|
83
|
+
);
|
|
84
|
+
}, 15_000);
|
|
85
|
+
|
|
86
|
+
it("persists teammate task metadata in the file envelope and usage on messages", async () => {
|
|
87
|
+
const sessionsDir = mkdtempSync(join(tmpdir(), "team-task-messages-"));
|
|
88
|
+
tempDirs.push(sessionsDir);
|
|
89
|
+
|
|
90
|
+
const store = new SqliteSessionStore({ sessionsDir });
|
|
91
|
+
stores.push(store);
|
|
92
|
+
const service = new CoreSessionService(store);
|
|
93
|
+
const rootSessionId = "root-session";
|
|
94
|
+
await service.createRootSessionWithArtifacts({
|
|
95
|
+
sessionId: rootSessionId,
|
|
96
|
+
source: SessionSource.CLI,
|
|
97
|
+
pid: process.pid,
|
|
98
|
+
interactive: false,
|
|
99
|
+
provider: "anthropic",
|
|
100
|
+
model: "claude-sonnet-4-6",
|
|
101
|
+
cwd: "/tmp/project",
|
|
102
|
+
workspaceRoot: "/tmp/project",
|
|
103
|
+
enableTools: true,
|
|
104
|
+
enableSpawn: true,
|
|
105
|
+
enableTeams: true,
|
|
106
|
+
prompt: "lead task",
|
|
107
|
+
startedAt: "2026-04-10T19:00:00.000Z",
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
await service.onTeamTaskStart(
|
|
111
|
+
rootSessionId,
|
|
112
|
+
"java-haiku-agent",
|
|
113
|
+
"Write a haiku about Java",
|
|
114
|
+
);
|
|
115
|
+
await service.onTeamTaskEnd(
|
|
116
|
+
rootSessionId,
|
|
117
|
+
"java-haiku-agent",
|
|
118
|
+
"completed",
|
|
119
|
+
"[done] completed",
|
|
120
|
+
{
|
|
121
|
+
text: "Classes wrap the world\nWrite once, run on every machine —\nVerbose, yet it soars",
|
|
122
|
+
usage: {
|
|
123
|
+
inputTokens: 42,
|
|
124
|
+
outputTokens: 17,
|
|
125
|
+
cacheReadTokens: 9,
|
|
126
|
+
cacheWriteTokens: 0,
|
|
127
|
+
totalCost: 0.123,
|
|
128
|
+
},
|
|
129
|
+
messages: [
|
|
130
|
+
{
|
|
131
|
+
role: "user",
|
|
132
|
+
content: "Write a haiku about Java. Return only the haiku.",
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
role: "assistant",
|
|
136
|
+
content: [
|
|
137
|
+
{
|
|
138
|
+
type: "text",
|
|
139
|
+
text: "Classes wrap the world\nWrite once, run on every machine —\nVerbose, yet it soars",
|
|
140
|
+
},
|
|
141
|
+
],
|
|
142
|
+
},
|
|
143
|
+
],
|
|
144
|
+
toolCalls: [],
|
|
145
|
+
iterations: 1,
|
|
146
|
+
finishReason: "completed",
|
|
147
|
+
model: {
|
|
148
|
+
id: "claude-sonnet-4-6",
|
|
149
|
+
provider: "anthropic",
|
|
150
|
+
info: { id: "claude-sonnet-4-6" },
|
|
151
|
+
},
|
|
152
|
+
startedAt: new Date("2026-04-10T19:00:01.000Z"),
|
|
153
|
+
endedAt: new Date("2026-04-10T19:00:02.000Z"),
|
|
154
|
+
durationMs: 1000,
|
|
155
|
+
},
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
const childSessions = await service.listSessions(10);
|
|
159
|
+
const teammateSessionId = childSessions.find((row) =>
|
|
160
|
+
row.sessionId.includes("__teamtask__java-haiku-agent__"),
|
|
161
|
+
)?.sessionId;
|
|
162
|
+
expect(teammateSessionId).toBeTruthy();
|
|
163
|
+
const path = join(
|
|
164
|
+
sessionsDir,
|
|
165
|
+
rootSessionId,
|
|
166
|
+
"java-haiku-agent__" +
|
|
167
|
+
teammateSessionId?.slice(teammateSessionId?.lastIndexOf("__") + 2) +
|
|
168
|
+
".messages.json",
|
|
169
|
+
);
|
|
170
|
+
const payload = JSON.parse(readFileSync(path, "utf8")) as {
|
|
171
|
+
agent?: string;
|
|
172
|
+
sessionId?: string;
|
|
173
|
+
taskType?: string;
|
|
174
|
+
messages: Array<Record<string, unknown>>;
|
|
175
|
+
};
|
|
176
|
+
const user = payload.messages[0] as Record<string, unknown>;
|
|
177
|
+
const assistant = payload.messages[1] as Record<string, unknown>;
|
|
178
|
+
|
|
179
|
+
expect(payload.agent).toBe("teammate");
|
|
180
|
+
expect(payload.sessionId).toBe(rootSessionId);
|
|
181
|
+
expect(payload.taskType).toBe("team");
|
|
182
|
+
expect(assistant.id).toEqual(expect.any(String));
|
|
183
|
+
expect(user.agent).toBeUndefined();
|
|
184
|
+
expect(user.sessionId).toBeUndefined();
|
|
185
|
+
expect(assistant.agent).toBeUndefined();
|
|
186
|
+
expect(assistant.sessionId).toBeUndefined();
|
|
187
|
+
expect(assistant.modelInfo).toMatchObject({
|
|
188
|
+
id: "claude-sonnet-4-6",
|
|
189
|
+
provider: "anthropic",
|
|
190
|
+
});
|
|
191
|
+
expect(assistant.metrics).toMatchObject({
|
|
192
|
+
inputTokens: 42,
|
|
193
|
+
outputTokens: 17,
|
|
194
|
+
cacheReadTokens: 9,
|
|
195
|
+
cacheWriteTokens: 0,
|
|
196
|
+
cost: 0.123,
|
|
197
|
+
});
|
|
198
|
+
const row = childSessions.find(
|
|
199
|
+
(item) => item.sessionId === teammateSessionId,
|
|
200
|
+
);
|
|
201
|
+
expect(row?.messagesPath).toBe(path);
|
|
202
|
+
expect(row?.transcriptPath).toBe(
|
|
203
|
+
join(
|
|
204
|
+
sessionsDir,
|
|
205
|
+
rootSessionId,
|
|
206
|
+
"java-haiku-agent__" +
|
|
207
|
+
teammateSessionId?.slice(teammateSessionId?.lastIndexOf("__") + 2) +
|
|
208
|
+
".log",
|
|
209
|
+
),
|
|
210
|
+
);
|
|
211
|
+
});
|
|
212
|
+
});
|