@clinebot/core 0.0.28 → 0.0.30
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 +11 -11
- 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 +9 -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 +15 -12
- 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 +168 -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 +162 -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/OpenTelemetryAdapter.ts +1 -1
- package/src/telemetry/OpenTelemetryProvider.test.ts +216 -3
- package/src/telemetry/OpenTelemetryProvider.ts +110 -20
- 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,
|
|
@@ -293,10 +344,14 @@ export class DefaultSessionManager implements SessionManager {
|
|
|
293
344
|
onConsecutiveMistakeLimitReached:
|
|
294
345
|
configWithProvider.onConsecutiveMistakeLimitReached,
|
|
295
346
|
completionGuard: runtime.completionGuard,
|
|
347
|
+
consumePendingUserMessage: () => this.consumeSteerMessage(sessionId),
|
|
296
348
|
logger: runtime.logger ?? configWithProvider.logger,
|
|
349
|
+
extensionContext: configWithProvider.extensionContext,
|
|
297
350
|
onEvent: (event: AgentEvent) =>
|
|
298
351
|
this.onAgentEvent(sessionId, configWithProvider, event),
|
|
299
|
-
}
|
|
352
|
+
} as AgentConfig;
|
|
353
|
+
const agent = this.createAgentInstance(agentConfig);
|
|
354
|
+
runtime.registerLeadAgent?.(agent);
|
|
300
355
|
const rootAgentIdentity = buildTelemetryAgentIdentity({
|
|
301
356
|
agentId: this.readAgentId(agent),
|
|
302
357
|
conversationId: this.readAgentConversationId(agent),
|
|
@@ -341,7 +396,7 @@ export class DefaultSessionManager implements SessionManager {
|
|
|
341
396
|
started: false,
|
|
342
397
|
aborting: false,
|
|
343
398
|
interactive: input.interactive === true,
|
|
344
|
-
persistedMessages:
|
|
399
|
+
persistedMessages: startInput.initialMessages,
|
|
345
400
|
activeTeamRunIds: new Set<string>(),
|
|
346
401
|
pendingTeamRunUpdates: [],
|
|
347
402
|
teamRunWaiters: [],
|
|
@@ -354,11 +409,11 @@ export class DefaultSessionManager implements SessionManager {
|
|
|
354
409
|
|
|
355
410
|
let result: AgentResult | undefined;
|
|
356
411
|
try {
|
|
357
|
-
if (
|
|
412
|
+
if (startInput.prompt?.trim()) {
|
|
358
413
|
result = await this.runTurn(active, {
|
|
359
|
-
prompt:
|
|
360
|
-
userImages:
|
|
361
|
-
userFiles:
|
|
414
|
+
prompt: startInput.prompt,
|
|
415
|
+
userImages: startInput.userImages,
|
|
416
|
+
userFiles: startInput.userFiles,
|
|
362
417
|
});
|
|
363
418
|
if (!active.interactive) {
|
|
364
419
|
await this.finalizeSingleRun(active, result.finishReason);
|
|
@@ -650,10 +705,15 @@ export class DefaultSessionManager implements SessionManager {
|
|
|
650
705
|
baselineMessages,
|
|
651
706
|
);
|
|
652
707
|
session.persistedMessages = persistedMessages;
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
708
|
+
const accumulatedUsage = accumulateUsageTotals(
|
|
709
|
+
usageBaseline,
|
|
710
|
+
result.usage,
|
|
656
711
|
);
|
|
712
|
+
this.usageBySession.set(session.sessionId, accumulatedUsage);
|
|
713
|
+
await this.persistSessionMetadata(session.sessionId, (current) => ({
|
|
714
|
+
...(current ?? {}),
|
|
715
|
+
totalCost: accumulatedUsage.totalCost,
|
|
716
|
+
}));
|
|
657
717
|
await this.invoke<void>(
|
|
658
718
|
"persistSessionMessages",
|
|
659
719
|
session.sessionId,
|
|
@@ -744,6 +804,37 @@ export class DefaultSessionManager implements SessionManager {
|
|
|
744
804
|
})) as RootSessionArtifacts;
|
|
745
805
|
}
|
|
746
806
|
|
|
807
|
+
private async persistSessionMetadata(
|
|
808
|
+
sessionId: string,
|
|
809
|
+
resolveMetadata: (
|
|
810
|
+
current: Record<string, unknown> | undefined,
|
|
811
|
+
) => Record<string, unknown> | undefined,
|
|
812
|
+
): Promise<void> {
|
|
813
|
+
const session = this.sessions.get(sessionId);
|
|
814
|
+
const currentManifest =
|
|
815
|
+
(await this.invokeOptionalValue<SessionManifest>(
|
|
816
|
+
"readSessionManifest",
|
|
817
|
+
sessionId,
|
|
818
|
+
)) ?? session?.artifacts?.manifest;
|
|
819
|
+
const metadata = resolveMetadata(
|
|
820
|
+
currentManifest?.metadata as Record<string, unknown> | undefined,
|
|
821
|
+
);
|
|
822
|
+
if (!session?.artifacts) {
|
|
823
|
+
return;
|
|
824
|
+
}
|
|
825
|
+
const result = await this.invokeOptionalValue<{ updated?: boolean }>(
|
|
826
|
+
"updateSession",
|
|
827
|
+
{
|
|
828
|
+
sessionId,
|
|
829
|
+
metadata,
|
|
830
|
+
},
|
|
831
|
+
);
|
|
832
|
+
if (result?.updated === false) {
|
|
833
|
+
return;
|
|
834
|
+
}
|
|
835
|
+
session.artifacts.manifest.metadata = metadata;
|
|
836
|
+
}
|
|
837
|
+
|
|
747
838
|
private async finalizeSingleRun(
|
|
748
839
|
session: ActiveSession,
|
|
749
840
|
finishReason: AgentResult["finishReason"],
|
|
@@ -818,14 +909,19 @@ export class DefaultSessionManager implements SessionManager {
|
|
|
818
909
|
exitCode,
|
|
819
910
|
);
|
|
820
911
|
if (!result.updated) return;
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
912
|
+
const latestManifest =
|
|
913
|
+
(await this.invokeOptionalValue<SessionManifest>(
|
|
914
|
+
"readSessionManifest",
|
|
915
|
+
session.sessionId,
|
|
916
|
+
)) ?? session.artifacts.manifest;
|
|
917
|
+
latestManifest.status = status;
|
|
918
|
+
latestManifest.ended_at = result.endedAt ?? nowIso();
|
|
919
|
+
latestManifest.exit_code = typeof exitCode === "number" ? exitCode : null;
|
|
920
|
+
session.artifacts.manifest = latestManifest;
|
|
825
921
|
await this.invoke<void>(
|
|
826
922
|
"writeSessionManifest",
|
|
827
923
|
session.artifacts.manifestPath,
|
|
828
|
-
|
|
924
|
+
latestManifest,
|
|
829
925
|
);
|
|
830
926
|
this.emitStatus(session.sessionId, status);
|
|
831
927
|
}
|
|
@@ -869,6 +965,27 @@ export class DefaultSessionManager implements SessionManager {
|
|
|
869
965
|
});
|
|
870
966
|
}
|
|
871
967
|
|
|
968
|
+
/**
|
|
969
|
+
* Consume the first steer-delivery pending prompt for injection into the
|
|
970
|
+
* running agent loop. Called synchronously by the agent between iterations.
|
|
971
|
+
*/
|
|
972
|
+
private consumeSteerMessage(sessionId: string): string | undefined {
|
|
973
|
+
const session = this.sessions.get(sessionId);
|
|
974
|
+
if (!session) {
|
|
975
|
+
return undefined;
|
|
976
|
+
}
|
|
977
|
+
const steerIndex = session.pendingPrompts.findIndex(
|
|
978
|
+
(entry) => entry.delivery === "steer",
|
|
979
|
+
);
|
|
980
|
+
if (steerIndex < 0) {
|
|
981
|
+
return undefined;
|
|
982
|
+
}
|
|
983
|
+
const [steer] = session.pendingPrompts.splice(steerIndex, 1);
|
|
984
|
+
this.emitPendingPrompts(session);
|
|
985
|
+
this.emitPendingPromptSubmitted(session, steer);
|
|
986
|
+
return steer.prompt;
|
|
987
|
+
}
|
|
988
|
+
|
|
872
989
|
private enqueuePendingPrompt(
|
|
873
990
|
sessionId: string,
|
|
874
991
|
entry: {
|
|
@@ -1065,9 +1182,12 @@ export class DefaultSessionManager implements SessionManager {
|
|
|
1065
1182
|
const tools: Tool[] = config.enableTools
|
|
1066
1183
|
? createBuiltinTools({
|
|
1067
1184
|
cwd: config.cwd,
|
|
1068
|
-
...
|
|
1069
|
-
|
|
1070
|
-
|
|
1185
|
+
...ToolPresets[
|
|
1186
|
+
resolveToolPresetName({
|
|
1187
|
+
mode: config.mode,
|
|
1188
|
+
yolo: config.yolo,
|
|
1189
|
+
})
|
|
1190
|
+
],
|
|
1071
1191
|
executors: this.defaultToolExecutors,
|
|
1072
1192
|
})
|
|
1073
1193
|
: [];
|
|
@@ -1092,10 +1212,6 @@ export class DefaultSessionManager implements SessionManager {
|
|
|
1092
1212
|
providerConfig: config.providerConfig,
|
|
1093
1213
|
knownModels: config.knownModels,
|
|
1094
1214
|
thinking: config.thinking,
|
|
1095
|
-
clineWorkspaceMetadata:
|
|
1096
|
-
config.providerId === "cline"
|
|
1097
|
-
? extractWorkspaceMetadataFromSystemPrompt(config.systemPrompt)
|
|
1098
|
-
: undefined,
|
|
1099
1215
|
maxIterations: config.maxIterations,
|
|
1100
1216
|
hooks: config.hooks,
|
|
1101
1217
|
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
|
+
});
|