@cloudcli-ai/cloudcli 1.37.0 → 1.37.2
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/dist/assets/abnfDiagram-N423BO3Z-C4UAoHJb.js +1 -0
- package/dist/assets/arc-B8jF-ja9.js +1 -0
- package/dist/assets/architectureDiagram-T3A2C74G-C_Wur_CU.js +36 -0
- package/dist/assets/blockDiagram-VBNYF7ZC-Cq4P1i8t.js +132 -0
- package/dist/assets/c4Diagram-5PPSVZJV-C1wG4eUj.js +10 -0
- package/dist/assets/channel-_falYbU1.js +1 -0
- package/dist/assets/chunk-2GRJ4B5K-B8fnBG6E.js +1 -0
- package/dist/assets/chunk-2Q5K7J3B-WdfPooPJ.js +1 -0
- package/dist/assets/chunk-5RXB4S5H-DhZJuG2E.js +231 -0
- package/dist/assets/chunk-5VM5RSS4-B0rjslal.js +15 -0
- package/dist/assets/chunk-6Q2QTUOP-CG2Oj4jL.js +88 -0
- package/dist/assets/chunk-GF5L2VYU-rrl2lRxY.js +206 -0
- package/dist/assets/chunk-JWPE2WC7-CjVbrVMA.js +1 -0
- package/dist/assets/chunk-KBJHAD2P-CRzKgU8S.js +1 -0
- package/dist/assets/chunk-RYQCIY6F-DBz4GTZF.js +1 -0
- package/dist/assets/chunk-XXDRQBXY-wHxalsXk.js +1 -0
- package/dist/assets/classDiagram-JCYQIIEL-Dn-3CfpR.js +1 -0
- package/dist/assets/classDiagram-v2-OCEON4UE-Dn-3CfpR.js +1 -0
- package/dist/assets/cose-bilkent-JH36ORCC-s1hygY8e.js +1 -0
- package/dist/assets/cynefin-VYW2F7L2-C4LGV15i.js +178 -0
- package/dist/assets/cynefinDiagram-MW4NZA55-C5uhu7B3.js +62 -0
- package/dist/assets/cytoscape.esm-C10L9Icf.js +331 -0
- package/dist/assets/dagre-VZM6K2ZE-B-OBTewm.js +4 -0
- package/dist/assets/defaultLocale-DX6XiGOO.js +1 -0
- package/dist/assets/diagram-7IWD3JNH-BjGKQxih.js +30 -0
- package/dist/assets/diagram-B4RE2ZJO-BMKz1X2L.js +3 -0
- package/dist/assets/diagram-LBJQPF4R-DNh-GhKC.js +24 -0
- package/dist/assets/diagram-Q27KOJAE-BaTG9jPT.js +24 -0
- package/dist/assets/diagram-UB23O5K3-BUwo2OvJ.js +41 -0
- package/dist/assets/ebnfDiagram-BXEA7PRR-DAZgfzX2.js +1 -0
- package/dist/assets/erDiagram-JOGREHBK-1w1CcGEb.js +85 -0
- package/dist/assets/flowDiagram-UKHOOZJN-D4EII8Jj.js +156 -0
- package/dist/assets/ganttDiagram-PKOTCBZU-ChvJZAgB.js +292 -0
- package/dist/assets/gitGraphDiagram-DS77QQ5N-DtOn41S8.js +106 -0
- package/dist/assets/graph-Cx-EqisW.js +1 -0
- package/dist/assets/index-CzPLBvXT.css +32 -0
- package/dist/assets/index-DFkBBuSA.js +1549 -0
- package/dist/assets/infoDiagram-6WML65LV-DN_PVEJZ.js +2 -0
- package/dist/assets/init-Gi6I4Gst.js +1 -0
- package/dist/assets/ishikawaDiagram-WSZJBQD7-DbkF1kXb.js +70 -0
- package/dist/assets/journeyDiagram-NVQOT4AX-pJwmhddE.js +139 -0
- package/dist/assets/kanban-definition-27J2QSJJ-PPAPgNp5.js +89 -0
- package/dist/assets/layout-D6BstSzF.js +1 -0
- package/dist/assets/linear-iPR-J9f7.js +1 -0
- package/dist/assets/map-CV9uif0g.js +1 -0
- package/dist/assets/mermaid.core-BEUL86Z6.js +312 -0
- package/dist/assets/mindmap-definition-FAOFIHXS-BvZoBib7.js +96 -0
- package/dist/assets/ordinal-Cboi1Yqb.js +1 -0
- package/dist/assets/pegDiagram-VL7TDLO6-DhYreaUd.js +1 -0
- package/dist/assets/pieDiagram-7S7Q4E2Y-CrOHlyD0.js +39 -0
- package/dist/assets/quadrantDiagram-CIZ2JOQS-D4g5yH3t.js +7 -0
- package/dist/assets/railroadDiagram-AXF67PYL-Dj39lHlf.js +1 -0
- package/dist/assets/requirementDiagram-LRYGKXZP-1AS4Zgm_.js +84 -0
- package/dist/assets/sankeyDiagram-W5VNT64P-CKlMn19P.js +40 -0
- package/dist/assets/sequenceDiagram-SI44F4Z6-B_j3qyvo.js +162 -0
- package/dist/assets/sizeCapture-X5ZJPWSS-Bp2Op16v.js +1 -0
- package/dist/assets/stateDiagram-OKZ733FA-C0cN6DoY.js +1 -0
- package/dist/assets/stateDiagram-v2-UEYNNEHI-BvBxUUrZ.js +1 -0
- package/dist/assets/swimlanes-SLNWSIFB-BEvXOV9b.js +2 -0
- package/dist/assets/swimlanesDiagram-ULZ7WXOC-CsE-x4YK.js +8 -0
- package/dist/assets/timeline-definition-Z64GVDOM-zdJQinvZ.js +120 -0
- package/dist/assets/vennDiagram-T6HMQDX7-DuF1uZMY.js +34 -0
- package/dist/assets/wardleyDiagram-T6FBY63Y-B9AlLQup.js +78 -0
- package/dist/assets/xychartDiagram-ELKLHX3M-DTJX48Qg.js +7 -0
- package/dist/index.html +2 -2
- package/dist-server/server/index.js +1 -2
- package/dist-server/server/index.js.map +1 -1
- package/dist-server/server/modules/agent/agent.module.js +2 -1
- package/dist-server/server/modules/agent/agent.module.js.map +1 -1
- package/dist-server/server/modules/auth/auth.middleware.js +1 -1
- package/dist-server/server/modules/auth/auth.middleware.js.map +1 -1
- package/dist-server/server/modules/browser-use/browser-use-runtime.js +10 -0
- package/dist-server/server/modules/browser-use/browser-use-runtime.js.map +1 -0
- package/dist-server/server/modules/browser-use/browser-use.service.js +3 -6
- package/dist-server/server/modules/browser-use/browser-use.service.js.map +1 -1
- package/dist-server/server/modules/browser-use/index.js +2 -0
- package/dist-server/server/modules/browser-use/index.js.map +1 -1
- package/dist-server/server/modules/cli/cli.js +9 -3
- package/dist-server/server/modules/cli/cli.js.map +1 -1
- package/dist-server/server/modules/cli/cli.module.js +0 -1
- package/dist-server/server/modules/cli/cli.module.js.map +1 -1
- package/dist-server/server/modules/cli/cli.service.js +0 -18
- package/dist-server/server/modules/cli/cli.service.js.map +1 -1
- package/dist-server/server/modules/cli/tests/cli-environment-bootstrap.test.js +154 -0
- package/dist-server/server/modules/cli/tests/cli-environment-bootstrap.test.js.map +1 -0
- package/dist-server/server/modules/cli/tests/cli.service.test.js +0 -3
- package/dist-server/server/modules/cli/tests/cli.service.test.js.map +1 -1
- package/dist-server/server/modules/commands/commands.routes.js +3 -3
- package/dist-server/server/modules/commands/commands.routes.js.map +1 -1
- package/dist-server/server/modules/commands/tests/commands.test.js +2 -7
- package/dist-server/server/modules/commands/tests/commands.test.js.map +1 -1
- package/dist-server/server/modules/database/index.js +2 -0
- package/dist-server/server/modules/database/index.js.map +1 -1
- package/dist-server/server/modules/database/migrations.js +18 -1
- package/dist-server/server/modules/database/migrations.js.map +1 -1
- package/dist-server/server/modules/database/repositories/provider-models.js +112 -0
- package/dist-server/server/modules/database/repositories/provider-models.js.map +1 -0
- package/dist-server/server/modules/database/repositories/sessions.db.js +63 -7
- package/dist-server/server/modules/database/repositories/sessions.db.js.map +1 -1
- package/dist-server/server/modules/database/schema.js +28 -3
- package/dist-server/server/modules/database/schema.js.map +1 -1
- package/dist-server/server/modules/database/tests/provider-models.db.integration.test.js +102 -0
- package/dist-server/server/modules/database/tests/provider-models.db.integration.test.js.map +1 -0
- package/dist-server/server/modules/database/tests/sessions-provider-mapping.test.js +2 -1
- package/dist-server/server/modules/database/tests/sessions-provider-mapping.test.js.map +1 -1
- package/dist-server/server/modules/database/tests/sessions.db.integration.test.js +22 -0
- package/dist-server/server/modules/database/tests/sessions.db.integration.test.js.map +1 -1
- package/dist-server/server/modules/file-tree/file-tree.module.js +5 -1
- package/dist-server/server/modules/file-tree/file-tree.module.js.map +1 -1
- package/dist-server/server/modules/file-tree/file-tree.service.js +60 -20
- package/dist-server/server/modules/file-tree/file-tree.service.js.map +1 -1
- package/dist-server/server/modules/file-tree/tests/file-tree.service.test.js +143 -16
- package/dist-server/server/modules/file-tree/tests/file-tree.service.test.js.map +1 -1
- package/dist-server/server/modules/git/git-branch.service.js +15 -0
- package/dist-server/server/modules/git/git-branch.service.js.map +1 -0
- package/dist-server/server/modules/git/git.routes.js +15 -7
- package/dist-server/server/modules/git/git.routes.js.map +1 -1
- package/dist-server/server/modules/git/tests/git-branch.service.test.js +52 -0
- package/dist-server/server/modules/git/tests/git-branch.service.test.js.map +1 -0
- package/dist-server/server/modules/git/tests/git-init.routes.test.js +84 -0
- package/dist-server/server/modules/git/tests/git-init.routes.test.js.map +1 -1
- package/dist-server/server/modules/notifications/index.js +3 -1
- package/dist-server/server/modules/notifications/index.js.map +1 -1
- package/dist-server/server/modules/notifications/services/notification-orchestrator.service.js +22 -1
- package/dist-server/server/modules/notifications/services/notification-orchestrator.service.js.map +1 -1
- package/dist-server/server/modules/providers/list/claude/claude-models.provider.js +46 -14
- package/dist-server/server/modules/providers/list/claude/claude-models.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/claude/claude-runtime.provider.js +259 -60
- package/dist-server/server/modules/providers/list/claude/claude-runtime.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/codex/codex-models.provider.js +58 -71
- package/dist-server/server/modules/providers/list/codex/codex-models.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/codex/codex-session-synchronizer.provider.js +1 -54
- package/dist-server/server/modules/providers/list/codex/codex-session-synchronizer.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js +7 -7
- package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/cursor/cursor-models.provider.js +32 -669
- package/dist-server/server/modules/providers/list/cursor/cursor-models.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/opencode/opencode-models.provider.js +105 -328
- package/dist-server/server/modules/providers/list/opencode/opencode-models.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.js +0 -12
- package/dist-server/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.js.map +1 -1
- package/dist-server/server/modules/providers/provider.routes.js +144 -31
- package/dist-server/server/modules/providers/provider.routes.js.map +1 -1
- package/dist-server/server/modules/providers/services/provider-models.service.js +167 -199
- package/dist-server/server/modules/providers/services/provider-models.service.js.map +1 -1
- package/dist-server/server/modules/providers/services/provider-runtime.service.js +2 -2
- package/dist-server/server/modules/providers/services/provider-runtime.service.js.map +1 -1
- package/dist-server/server/modules/providers/services/session-conversations-search.service.js +75 -11
- package/dist-server/server/modules/providers/services/session-conversations-search.service.js.map +1 -1
- package/dist-server/server/modules/providers/services/sessions.service.js +62 -3
- package/dist-server/server/modules/providers/services/sessions.service.js.map +1 -1
- package/dist-server/server/modules/providers/tests/codex-sessions.test.js +53 -17
- package/dist-server/server/modules/providers/tests/codex-sessions.test.js.map +1 -1
- package/dist-server/server/modules/providers/tests/opencode-models.test.js +15 -126
- package/dist-server/server/modules/providers/tests/opencode-models.test.js.map +1 -1
- package/dist-server/server/modules/providers/tests/opencode-sessions.test.js +5 -5
- package/dist-server/server/modules/providers/tests/opencode-sessions.test.js.map +1 -1
- package/dist-server/server/modules/providers/tests/provider-models.service.test.js +175 -292
- package/dist-server/server/modules/providers/tests/provider-models.service.test.js.map +1 -1
- package/dist-server/server/modules/providers/tests/provider-runtime.service.test.js +2 -6
- package/dist-server/server/modules/providers/tests/provider-runtime.service.test.js.map +1 -1
- package/dist-server/server/modules/providers/tests/provider-token-usage.service.test.js +1 -0
- package/dist-server/server/modules/providers/tests/provider-token-usage.service.test.js.map +1 -1
- package/dist-server/server/modules/providers/tests/provider.routes.test.js +161 -0
- package/dist-server/server/modules/providers/tests/provider.routes.test.js.map +1 -0
- package/dist-server/server/modules/providers/tests/sessions.service.test.js +87 -0
- package/dist-server/server/modules/providers/tests/sessions.service.test.js.map +1 -0
- package/dist-server/server/modules/websocket/services/chat-websocket.service.js +5 -1
- package/dist-server/server/modules/websocket/services/chat-websocket.service.js.map +1 -1
- package/dist-server/server/shared/utils.js +8 -0
- package/dist-server/server/shared/utils.js.map +1 -1
- package/package.json +8 -4
- package/scripts/promote-dist-server.mjs +50 -0
- package/server/index.ts +1 -2
- package/server/modules/agent/agent.module.ts +2 -1
- package/server/modules/auth/auth.middleware.ts +2 -2
- package/server/modules/browser-use/browser-use-runtime.ts +10 -0
- package/server/modules/browser-use/browser-use.service.ts +5 -8
- package/server/modules/browser-use/index.ts +3 -0
- package/server/modules/cli/cli.module.ts +0 -1
- package/server/modules/cli/cli.service.ts +0 -20
- package/server/modules/cli/cli.ts +9 -3
- package/server/modules/cli/tests/cli-environment-bootstrap.test.ts +186 -0
- package/server/modules/cli/tests/cli.service.test.ts +0 -3
- package/server/modules/commands/commands.routes.ts +3 -3
- package/server/modules/commands/tests/commands.test.ts +2 -7
- package/server/modules/database/index.ts +2 -0
- package/server/modules/database/migrations.ts +20 -0
- package/server/modules/database/repositories/provider-models.ts +168 -0
- package/server/modules/database/repositories/sessions.db.ts +85 -8
- package/server/modules/database/schema.ts +29 -3
- package/server/modules/database/tests/provider-models.db.integration.test.ts +125 -0
- package/server/modules/database/tests/sessions-provider-mapping.test.ts +2 -1
- package/server/modules/database/tests/sessions.db.integration.test.ts +32 -0
- package/server/modules/file-tree/file-tree.module.ts +5 -1
- package/server/modules/file-tree/file-tree.service.ts +81 -22
- package/server/modules/file-tree/tests/file-tree.service.test.ts +167 -16
- package/server/modules/git/git-branch.service.ts +43 -0
- package/server/modules/git/git.routes.ts +16 -9
- package/server/modules/git/tests/git-branch.service.test.ts +60 -0
- package/server/modules/git/tests/git-init.routes.test.ts +83 -0
- package/server/modules/notifications/index.ts +2 -0
- package/server/modules/notifications/services/notification-orchestrator.service.js +24 -1
- package/server/modules/providers/list/claude/claude-models.provider.ts +46 -14
- package/server/modules/providers/list/claude/claude-runtime.provider.js +280 -67
- package/server/modules/providers/list/codex/codex-models.provider.ts +58 -99
- package/server/modules/providers/list/codex/codex-session-synchronizer.provider.ts +1 -60
- package/server/modules/providers/list/codex/codex-sessions.provider.ts +7 -7
- package/server/modules/providers/list/cursor/cursor-models.provider.ts +32 -710
- package/server/modules/providers/list/opencode/opencode-models.provider.ts +105 -413
- package/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.ts +0 -13
- package/server/modules/providers/provider.routes.ts +190 -33
- package/server/modules/providers/services/provider-models.service.ts +223 -288
- package/server/modules/providers/services/provider-runtime.service.ts +2 -3
- package/server/modules/providers/services/session-conversations-search.service.ts +106 -11
- package/server/modules/providers/services/sessions.service.ts +87 -3
- package/server/modules/providers/tests/codex-sessions.test.ts +57 -18
- package/server/modules/providers/tests/opencode-models.test.ts +34 -135
- package/server/modules/providers/tests/opencode-sessions.test.ts +5 -5
- package/server/modules/providers/tests/provider-models.service.test.ts +353 -450
- package/server/modules/providers/tests/provider-runtime.service.test.ts +2 -6
- package/server/modules/providers/tests/provider-token-usage.service.test.ts +1 -0
- package/server/modules/providers/tests/provider.routes.test.ts +244 -0
- package/server/modules/providers/tests/sessions.service.test.ts +127 -0
- package/server/modules/websocket/services/chat-websocket.service.ts +5 -1
- package/server/shared/interfaces.ts +4 -6
- package/server/shared/types.ts +29 -18
- package/server/shared/utils.ts +10 -0
- package/server/tsconfig.json +6 -2
- package/README.de.md +0 -257
- package/README.ja.md +0 -249
- package/README.ko.md +0 -249
- package/README.md +0 -269
- package/README.ru.md +0 -257
- package/README.tr.md +0 -258
- package/README.zh-CN.md +0 -249
- package/README.zh-TW.md +0 -249
- package/dist/assets/index-DSlds633.css +0 -32
- package/dist/assets/index-eGqPeIEu.js +0 -1531
- package/dist-server/server/constants/config.js +0 -6
- package/dist-server/server/constants/config.js.map +0 -1
- package/server/constants/config.ts +0 -5
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
2
|
import { sessionsDb } from '../../../../modules/database/index.js';
|
|
3
3
|
import { buildDefaultProviderCurrentActiveModel } from '../../../../shared/utils.js';
|
|
4
|
-
export const
|
|
4
|
+
export const CLAUDE_PREDEFINED_MODELS = {
|
|
5
5
|
OPTIONS: [
|
|
6
6
|
{
|
|
7
7
|
value: 'default',
|
|
8
8
|
label: 'Default (recommended)',
|
|
9
|
-
description: 'Use the
|
|
9
|
+
description: 'Use the recommended model for your Claude account and deployment.',
|
|
10
10
|
effort: {
|
|
11
11
|
default: 'high',
|
|
12
12
|
values: [
|
|
@@ -17,10 +17,25 @@ export const CLAUDE_FALLBACK_MODELS = {
|
|
|
17
17
|
],
|
|
18
18
|
},
|
|
19
19
|
},
|
|
20
|
+
{
|
|
21
|
+
value: 'best',
|
|
22
|
+
label: 'Best available',
|
|
23
|
+
description: 'Use Fable 5 when available, otherwise the latest Opus model.',
|
|
24
|
+
effort: {
|
|
25
|
+
default: 'high',
|
|
26
|
+
values: [
|
|
27
|
+
{ value: 'low' },
|
|
28
|
+
{ value: 'medium' },
|
|
29
|
+
{ value: 'high' },
|
|
30
|
+
{ value: 'xhigh' },
|
|
31
|
+
{ value: 'max' },
|
|
32
|
+
],
|
|
33
|
+
},
|
|
34
|
+
},
|
|
20
35
|
{
|
|
21
36
|
value: 'fable',
|
|
22
|
-
label: 'Fable',
|
|
23
|
-
description: '
|
|
37
|
+
label: 'Fable 5',
|
|
38
|
+
description: 'Most capable Claude model for the hardest, longest-running tasks.',
|
|
24
39
|
effort: {
|
|
25
40
|
default: 'high',
|
|
26
41
|
values: [
|
|
@@ -33,15 +48,16 @@ export const CLAUDE_FALLBACK_MODELS = {
|
|
|
33
48
|
},
|
|
34
49
|
},
|
|
35
50
|
{
|
|
36
|
-
value:
|
|
37
|
-
label:
|
|
38
|
-
description:
|
|
51
|
+
value: 'sonnet',
|
|
52
|
+
label: 'Sonnet',
|
|
53
|
+
description: 'Latest Sonnet model for everyday coding tasks.',
|
|
39
54
|
effort: {
|
|
40
55
|
default: 'high',
|
|
41
56
|
values: [
|
|
42
57
|
{ value: 'low' },
|
|
43
58
|
{ value: 'medium' },
|
|
44
59
|
{ value: 'high' },
|
|
60
|
+
{ value: 'xhigh' },
|
|
45
61
|
{ value: 'max' },
|
|
46
62
|
],
|
|
47
63
|
},
|
|
@@ -49,13 +65,14 @@ export const CLAUDE_FALLBACK_MODELS = {
|
|
|
49
65
|
{
|
|
50
66
|
value: 'sonnet[1m]',
|
|
51
67
|
label: 'Sonnet (1M context)',
|
|
52
|
-
description: 'Sonnet
|
|
68
|
+
description: 'Latest Sonnet model with a 1M context window.',
|
|
53
69
|
effort: {
|
|
54
70
|
default: 'high',
|
|
55
71
|
values: [
|
|
56
72
|
{ value: 'low' },
|
|
57
73
|
{ value: 'medium' },
|
|
58
74
|
{ value: 'high' },
|
|
75
|
+
{ value: 'xhigh' },
|
|
59
76
|
{ value: 'max' },
|
|
60
77
|
],
|
|
61
78
|
},
|
|
@@ -63,7 +80,7 @@ export const CLAUDE_FALLBACK_MODELS = {
|
|
|
63
80
|
{
|
|
64
81
|
value: 'opus',
|
|
65
82
|
label: 'Opus',
|
|
66
|
-
description: 'Opus
|
|
83
|
+
description: 'Latest Opus model for complex reasoning and coding tasks.',
|
|
67
84
|
effort: {
|
|
68
85
|
default: 'high',
|
|
69
86
|
values: [
|
|
@@ -77,8 +94,8 @@ export const CLAUDE_FALLBACK_MODELS = {
|
|
|
77
94
|
},
|
|
78
95
|
{
|
|
79
96
|
value: 'opus[1m]',
|
|
80
|
-
label: 'Opus
|
|
81
|
-
description: 'Opus
|
|
97
|
+
label: 'Opus (1M context)',
|
|
98
|
+
description: 'Latest Opus model with a 1M context window.',
|
|
82
99
|
effort: {
|
|
83
100
|
default: 'high',
|
|
84
101
|
values: [
|
|
@@ -93,7 +110,22 @@ export const CLAUDE_FALLBACK_MODELS = {
|
|
|
93
110
|
{
|
|
94
111
|
value: 'haiku',
|
|
95
112
|
label: 'Haiku',
|
|
96
|
-
description: '
|
|
113
|
+
description: 'Fast and efficient Claude model for simple tasks.',
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
value: 'opusplan',
|
|
117
|
+
label: 'Opus Plan',
|
|
118
|
+
description: 'Use Opus while planning, then switch to Sonnet for execution.',
|
|
119
|
+
effort: {
|
|
120
|
+
default: 'high',
|
|
121
|
+
values: [
|
|
122
|
+
{ value: 'low' },
|
|
123
|
+
{ value: 'medium' },
|
|
124
|
+
{ value: 'high' },
|
|
125
|
+
{ value: 'xhigh' },
|
|
126
|
+
{ value: 'max' },
|
|
127
|
+
],
|
|
128
|
+
},
|
|
97
129
|
},
|
|
98
130
|
],
|
|
99
131
|
DEFAULT: 'default',
|
|
@@ -103,7 +135,7 @@ export const findClaudeModelOption = (model) => {
|
|
|
103
135
|
if (!normalizedModel) {
|
|
104
136
|
return null;
|
|
105
137
|
}
|
|
106
|
-
return
|
|
138
|
+
return CLAUDE_PREDEFINED_MODELS.OPTIONS.find((option) => option.value === normalizedModel) ?? null;
|
|
107
139
|
};
|
|
108
140
|
const ANSI_PATTERN = new RegExp('[\\u001B\\u009B][[\\]()#;?]*(?:'
|
|
109
141
|
+ '(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]'
|
|
@@ -193,7 +225,7 @@ export class ClaudeProviderModels {
|
|
|
193
225
|
// const supportedModels = await queryInstance.supportedModels();
|
|
194
226
|
// queryInstance.close();
|
|
195
227
|
// return buildClaudeModelsDefinition(supportedModels);
|
|
196
|
-
return
|
|
228
|
+
return CLAUDE_PREDEFINED_MODELS;
|
|
197
229
|
}
|
|
198
230
|
async getCurrentActiveModel(sessionId) {
|
|
199
231
|
if (!sessionId?.trim()) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-models.provider.js","sourceRoot":"","sources":["../../../../../../server/modules/providers/list/claude/claude-models.provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAOzD,OAAO,EAAE,sCAAsC,EAAE,MAAM,mBAAmB,CAAC;AAE3E,MAAM,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"claude-models.provider.js","sourceRoot":"","sources":["../../../../../../server/modules/providers/list/claude/claude-models.provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -17,9 +17,9 @@ import os from 'os';
|
|
|
17
17
|
import path from 'path';
|
|
18
18
|
import { query } from '@anthropic-ai/claude-agent-sdk';
|
|
19
19
|
import { appendFilesInputTag, buildClaudeUserContent, normalizeImageDescriptors } from '../../../../shared/image-attachments.js';
|
|
20
|
-
import {
|
|
20
|
+
import { CLAUDE_PREDEFINED_MODELS } from '../../../../modules/providers/list/claude/claude-models.provider.js';
|
|
21
21
|
import { resolveClaudeCodeExecutablePath } from '../../../../shared/claude-cli-path.js';
|
|
22
|
-
import { createNotificationEvent, notifyRunFailed, notifyRunStopped, notifyUserIfEnabled } from '../../../../modules/notifications/index.js';
|
|
22
|
+
import { createNotificationEvent, notifyBackgroundWorkCompleted, notifyRunFailed, notifyRunStopped, notifyUserIfEnabled } from '../../../../modules/notifications/index.js';
|
|
23
23
|
import { createCompleteMessage, createNormalizedMessage } from '../../../../shared/utils.js';
|
|
24
24
|
const activeSessions = new Map();
|
|
25
25
|
const pendingToolApprovals = new Map();
|
|
@@ -27,9 +27,31 @@ const pendingToolApprovals = new Map();
|
|
|
27
27
|
// terminal `complete` (aborted: true) to the client, so the run loop must not
|
|
28
28
|
// emit a second one when its generator winds down.
|
|
29
29
|
const abortedSessionIds = new Set();
|
|
30
|
+
// Query instances interrupted because a newer run took over their session id
|
|
31
|
+
// (see addSession). Their run loops must stay silent on wind-down: the map
|
|
32
|
+
// entry, the abort flag, and all client-facing events belong to the new run.
|
|
33
|
+
const supersededInstances = new WeakSet();
|
|
30
34
|
const TOOL_APPROVAL_TIMEOUT_MS = parseInt(process.env.CLAUDE_TOOL_APPROVAL_TIMEOUT_MS, 10) || 55000;
|
|
35
|
+
// How long background work is allowed to keep running after a turn ends. This drives
|
|
36
|
+
// two halves of the same behaviour:
|
|
37
|
+
//
|
|
38
|
+
// 1. Passed to the spawned CLI as CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS, which is how
|
|
39
|
+
// long it waits for still-running background *agents* before killing them.
|
|
40
|
+
// 2. A backstop on how long we hold the SDK's stdin open after a turn's `result`.
|
|
41
|
+
// The SDK closes stdin as soon as a turn ends, and the CLI reads that EOF as
|
|
42
|
+
// "print wind-down" — killing background *shells* after a short grace period,
|
|
43
|
+
// which the ceiling above does not cover. Holding stdin open also lets the CLI
|
|
44
|
+
// push follow-up turns (background-task completions, Monitor notifications,
|
|
45
|
+
// scheduled wake-ups).
|
|
46
|
+
//
|
|
47
|
+
// The hold normally ends long before this: a turn with nothing outstanding closes
|
|
48
|
+
// stdin immediately, background work releases it as soon as it reports back, and a
|
|
49
|
+
// new turn supersedes the previous hold. This ceiling only catches background work
|
|
50
|
+
// that never reports at all, so an abandoned session cannot leak a CLI process
|
|
51
|
+
// forever. The timer resets on every message, so it measures silence, not total time.
|
|
52
|
+
const BG_WAIT_CEILING_MS = 30 * 60 * 1000;
|
|
31
53
|
const TOOLS_REQUIRING_INTERACTION = new Set(['AskUserQuestion', 'ExitPlanMode']);
|
|
32
|
-
function resolveClaudeEffort(model, effort, modelsDefinition =
|
|
54
|
+
function resolveClaudeEffort(model, effort, modelsDefinition = CLAUDE_PREDEFINED_MODELS) {
|
|
33
55
|
const selectedModel = modelsDefinition?.OPTIONS?.find((option) => option.value === model) || null;
|
|
34
56
|
const allowedEfforts = selectedModel?.effort?.values
|
|
35
57
|
?.map((value) => value.value) || [];
|
|
@@ -131,7 +153,7 @@ function mapCliOptionsToSDK(options = {}) {
|
|
|
131
153
|
const sdkOptions = {};
|
|
132
154
|
// Forward all host env vars (e.g. ANTHROPIC_BASE_URL) to the subprocess.
|
|
133
155
|
// Since SDK 0.2.113, options.env replaces process.env instead of overlaying it.
|
|
134
|
-
sdkOptions.env = { ...process.env };
|
|
156
|
+
sdkOptions.env = { ...process.env, CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS: String(BG_WAIT_CEILING_MS) };
|
|
135
157
|
// Resolve the executable eagerly on Windows because the SDK uses raw child_process.spawn,
|
|
136
158
|
// which does not reliably follow npm's shell wrappers like cross-spawn does.
|
|
137
159
|
sdkOptions.pathToClaudeCodeExecutable = resolveClaudeCodeExecutablePath(process.env.CLAUDE_CLI_PATH);
|
|
@@ -164,8 +186,8 @@ function mapCliOptionsToSDK(options = {}) {
|
|
|
164
186
|
// but being explicit ensures forward compatibility and clarity.
|
|
165
187
|
sdkOptions.tools = { type: 'preset', preset: 'claude_code' };
|
|
166
188
|
sdkOptions.disallowedTools = settings.disallowedTools || [];
|
|
167
|
-
sdkOptions.model = options.model ||
|
|
168
|
-
const resolvedEffort = resolveClaudeEffort(sdkOptions.model, effort, options.effortModels ||
|
|
189
|
+
sdkOptions.model = options.model || CLAUDE_PREDEFINED_MODELS.DEFAULT;
|
|
190
|
+
const resolvedEffort = resolveClaudeEffort(sdkOptions.model, effort, options.effortModels || CLAUDE_PREDEFINED_MODELS);
|
|
169
191
|
if (resolvedEffort) {
|
|
170
192
|
sdkOptions.effort = resolvedEffort;
|
|
171
193
|
}
|
|
@@ -185,13 +207,35 @@ function mapCliOptionsToSDK(options = {}) {
|
|
|
185
207
|
* @param {string} sessionId - Session identifier
|
|
186
208
|
* @param {Object} queryInstance - SDK query instance
|
|
187
209
|
* @param {Object} writer - WebSocket writer for reconnect support
|
|
210
|
+
* @param {Function} releaseInput - Closes the held stdin stream so the CLI can exit
|
|
188
211
|
*/
|
|
189
|
-
function addSession(sessionId, queryInstance, writer = null) {
|
|
212
|
+
function addSession(sessionId, queryInstance, writer = null, releaseInput = null) {
|
|
213
|
+
const existing = activeSessions.get(sessionId);
|
|
214
|
+
// A different live instance under the same key means an earlier run was
|
|
215
|
+
// superseded without being stopped (e.g. an abort that raced run setup and
|
|
216
|
+
// found nothing to interrupt). Overwriting it here would strand its
|
|
217
|
+
// generator forever — this map entry is the only handle for interrupting
|
|
218
|
+
// it. Stop it directly rather than via abortClaudeSDKSession, whose
|
|
219
|
+
// session-keyed abortedSessionIds flag would be consumed by the new run
|
|
220
|
+
// and suppress its terminal `complete`.
|
|
221
|
+
const superseding = Boolean(existing && existing.status === 'active' && existing.instance && existing.instance !== queryInstance);
|
|
222
|
+
if (superseding) {
|
|
223
|
+
supersededInstances.add(existing.instance);
|
|
224
|
+
Promise.resolve()
|
|
225
|
+
.then(() => existing.instance.interrupt())
|
|
226
|
+
.catch((error) => {
|
|
227
|
+
console.error(`Error interrupting superseded run for session ${sessionId}:`, error?.message || error);
|
|
228
|
+
});
|
|
229
|
+
existing.releaseInput?.();
|
|
230
|
+
}
|
|
231
|
+
const carried = superseding ? null : existing;
|
|
190
232
|
activeSessions.set(sessionId, {
|
|
191
233
|
instance: queryInstance,
|
|
192
|
-
startTime: Date.now(),
|
|
234
|
+
startTime: carried?.startTime || Date.now(),
|
|
193
235
|
status: 'active',
|
|
194
|
-
writer
|
|
236
|
+
writer,
|
|
237
|
+
// Re-registered mid-run once the provider session id lands; keep the closer.
|
|
238
|
+
releaseInput: releaseInput || carried?.releaseInput || null
|
|
195
239
|
});
|
|
196
240
|
}
|
|
197
241
|
/**
|
|
@@ -294,28 +338,55 @@ function extractTokenBudget(sdkMessage) {
|
|
|
294
338
|
},
|
|
295
339
|
};
|
|
296
340
|
}
|
|
341
|
+
// Tool calls that leave work running past the end of a turn. Bash only counts
|
|
342
|
+
// when it is explicitly backgrounded; the rest defer or watch work by nature.
|
|
343
|
+
const DEFERRED_WORK_TOOLS = new Set(['Monitor', 'ScheduleWakeup', 'CronCreate', 'TaskCreate']);
|
|
344
|
+
/**
|
|
345
|
+
* Detects tool calls that keep working after the turn's `result` arrives.
|
|
346
|
+
*
|
|
347
|
+
* Only turns that start background work need their CLI process held open; every
|
|
348
|
+
* other turn can let it exit immediately, as it did before the hold existed.
|
|
349
|
+
*
|
|
350
|
+
* @param {Object} sdkMessage - SDK stream message
|
|
351
|
+
* @returns {boolean} True when the message launches work that outlives the turn
|
|
352
|
+
*/
|
|
353
|
+
function startsBackgroundWork(sdkMessage) {
|
|
354
|
+
const content = sdkMessage?.message?.content;
|
|
355
|
+
if (!Array.isArray(content)) {
|
|
356
|
+
return false;
|
|
357
|
+
}
|
|
358
|
+
return content.some((block) => {
|
|
359
|
+
if (block?.type !== 'tool_use') {
|
|
360
|
+
return false;
|
|
361
|
+
}
|
|
362
|
+
if (block.name === 'Bash') {
|
|
363
|
+
return block.input?.run_in_background === true;
|
|
364
|
+
}
|
|
365
|
+
return DEFERRED_WORK_TOOLS.has(block.name);
|
|
366
|
+
});
|
|
367
|
+
}
|
|
297
368
|
/**
|
|
298
|
-
* Builds the SDK
|
|
369
|
+
* Builds the SDK user messages for one turn.
|
|
299
370
|
*
|
|
300
|
-
*
|
|
301
|
-
*
|
|
302
|
-
*
|
|
303
|
-
*
|
|
371
|
+
* Always returns SDKUserMessage records rather than a bare string: a string
|
|
372
|
+
* prompt makes the SDK flag the query as single-turn and close stdin the moment
|
|
373
|
+
* the turn's `result` arrives, which kills the CLI's background tasks. Plain
|
|
374
|
+
* text turns carry string content; turns with image attachments carry the
|
|
375
|
+
* prompt text plus one base64 `image` block per attachment (read from the
|
|
376
|
+
* global `~/.cloudcli/assets` folder).
|
|
304
377
|
*
|
|
305
378
|
* @param {string} command - User prompt
|
|
306
379
|
* @param {Array} images - Image descriptors ({ path, name?, mimeType? })
|
|
307
380
|
* @param {Array} files - Non-image attachment descriptors
|
|
308
381
|
* @param {string} cwd - Project working directory attachment paths resolve against
|
|
309
|
-
* @returns {Promise<
|
|
382
|
+
* @returns {Promise<Array<Object>>} SDKUserMessage records for the turn
|
|
310
383
|
*/
|
|
311
|
-
async function
|
|
384
|
+
async function buildPromptMessages(command, images, files, cwd) {
|
|
312
385
|
const promptWithFiles = appendFilesInputTag(command, files);
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
return (async function* () {
|
|
318
|
-
yield {
|
|
386
|
+
const content = normalizeImageDescriptors(images).length === 0
|
|
387
|
+
? promptWithFiles
|
|
388
|
+
: await buildClaudeUserContent(promptWithFiles, images, cwd);
|
|
389
|
+
return [{
|
|
319
390
|
type: 'user',
|
|
320
391
|
message: {
|
|
321
392
|
role: 'user',
|
|
@@ -323,8 +394,30 @@ async function buildPromptPayload(command, images, files, cwd) {
|
|
|
323
394
|
},
|
|
324
395
|
parent_tool_use_id: null,
|
|
325
396
|
timestamp: new Date().toISOString()
|
|
326
|
-
};
|
|
397
|
+
}];
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* Wraps prompt messages in an async iterable that yields them and then parks.
|
|
401
|
+
*
|
|
402
|
+
* The SDK closes the CLI's stdin as soon as its input iterable is exhausted (and
|
|
403
|
+
* immediately on `result` for string prompts). The CLI reads that EOF as the end
|
|
404
|
+
* of the run and kills anything still going in the background, so the iterable
|
|
405
|
+
* has to stay pending until we actually want the process gone.
|
|
406
|
+
*
|
|
407
|
+
* @param {Array<Object>} messages - SDKUserMessage records to send
|
|
408
|
+
* @returns {{ stream: AsyncIterable, release: () => void }} Stream plus its closer
|
|
409
|
+
*/
|
|
410
|
+
function createHeldPromptStream(messages) {
|
|
411
|
+
let release;
|
|
412
|
+
const held = new Promise((resolve) => { release = resolve; });
|
|
413
|
+
const stream = (async function* () {
|
|
414
|
+
for (const message of messages) {
|
|
415
|
+
yield message;
|
|
416
|
+
}
|
|
417
|
+
// Keeps stdin open — the CLI stays alive until release() is called.
|
|
418
|
+
await held;
|
|
327
419
|
})();
|
|
420
|
+
return { stream, release };
|
|
328
421
|
}
|
|
329
422
|
/**
|
|
330
423
|
* Loads MCP server configurations from ~/.claude.json
|
|
@@ -406,9 +499,43 @@ async function queryClaudeSDK(command, options = {}, ws, context) {
|
|
|
406
499
|
event
|
|
407
500
|
});
|
|
408
501
|
};
|
|
502
|
+
// Closes the held stdin stream so the CLI can wind down. Replaced once the
|
|
503
|
+
// stream exists; the finally block calls it no matter how the run ends.
|
|
504
|
+
let releasePromptStream = () => { };
|
|
505
|
+
let idleReleaseTimer = null;
|
|
506
|
+
// The client is told the turn is over as soon as `result` lands, even though
|
|
507
|
+
// the process lingers, so the UI never waits out the idle hold.
|
|
508
|
+
let turnCompleteSent = false;
|
|
509
|
+
// Set when a turn starts background work, cleared when the next `result`
|
|
510
|
+
// arrives — only turns with work still outstanding hold their process open.
|
|
511
|
+
let backgroundWorkPending = false;
|
|
512
|
+
// True while the process is being held open for background work, so a later
|
|
513
|
+
// `result` can be recognised as that work reporting back.
|
|
514
|
+
let heldForBackgroundWork = false;
|
|
515
|
+
// A new turn supersedes any earlier one still holding this session's process
|
|
516
|
+
// open, so held runs cannot stack up across a conversation.
|
|
517
|
+
if (sessionKey()) {
|
|
518
|
+
getSession(sessionKey())?.releaseInput?.();
|
|
519
|
+
}
|
|
520
|
+
// Arms (or re-arms) the idle countdown that eventually closes stdin.
|
|
521
|
+
const scheduleRelease = () => {
|
|
522
|
+
if (idleReleaseTimer) {
|
|
523
|
+
clearTimeout(idleReleaseTimer);
|
|
524
|
+
idleReleaseTimer = null;
|
|
525
|
+
}
|
|
526
|
+
idleReleaseTimer = setTimeout(() => {
|
|
527
|
+
idleReleaseTimer = null;
|
|
528
|
+
releasePromptStream();
|
|
529
|
+
}, BG_WAIT_CEILING_MS);
|
|
530
|
+
// Never let the hold keep the server process alive on its own.
|
|
531
|
+
idleReleaseTimer.unref?.();
|
|
532
|
+
};
|
|
533
|
+
// Hoisted above the try so the catch's cleanup can tell whether this run
|
|
534
|
+
// still owns the activeSessions entry (or was superseded by a newer run).
|
|
535
|
+
let queryInstance = null;
|
|
409
536
|
try {
|
|
410
537
|
const resolvedModel = await context.resolveResumeModel(sessionId, options.model);
|
|
411
|
-
let effortModels =
|
|
538
|
+
let effortModels = CLAUDE_PREDEFINED_MODELS;
|
|
412
539
|
try {
|
|
413
540
|
effortModels = await context.getProviderModels();
|
|
414
541
|
}
|
|
@@ -425,10 +552,10 @@ async function queryClaudeSDK(command, options = {}, ws, context) {
|
|
|
425
552
|
if (mcpServers) {
|
|
426
553
|
sdkOptions.mcpServers = mcpServers;
|
|
427
554
|
}
|
|
428
|
-
//
|
|
429
|
-
//
|
|
430
|
-
// async generator cannot be replayed once consumed.
|
|
431
|
-
const
|
|
555
|
+
// Every turn uses streaming input so stdin stays open past the turn's
|
|
556
|
+
// `result`. The message list is reusable, but each query attempt needs its
|
|
557
|
+
// own stream because an async generator cannot be replayed once consumed.
|
|
558
|
+
const promptMessages = await buildPromptMessages(command, options.images, options.files, options.cwd);
|
|
432
559
|
sdkOptions.hooks = {
|
|
433
560
|
Notification: [{
|
|
434
561
|
matcher: '',
|
|
@@ -516,13 +643,11 @@ async function queryClaudeSDK(command, options = {}, ws, context) {
|
|
|
516
643
|
}
|
|
517
644
|
return { behavior: 'deny', message: decision.message ?? 'User denied tool use' };
|
|
518
645
|
};
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
process.env.CLAUDE_CODE_STREAM_CLOSE_TIMEOUT = '300000';
|
|
522
|
-
let queryInstance;
|
|
646
|
+
let heldPrompt = createHeldPromptStream(promptMessages);
|
|
647
|
+
releasePromptStream = heldPrompt.release;
|
|
523
648
|
try {
|
|
524
649
|
queryInstance = query({
|
|
525
|
-
prompt:
|
|
650
|
+
prompt: heldPrompt.stream,
|
|
526
651
|
options: sdkOptions
|
|
527
652
|
});
|
|
528
653
|
}
|
|
@@ -531,21 +656,18 @@ async function queryClaudeSDK(command, options = {}, ws, context) {
|
|
|
531
656
|
// Keep notification behavior operational via runtime events even if hook registration fails.
|
|
532
657
|
console.warn('Failed to initialize Claude query with hooks, retrying without hooks:', hookError?.message || hookError);
|
|
533
658
|
delete sdkOptions.hooks;
|
|
659
|
+
// Discard the abandoned stream and build a fresh one for the retry.
|
|
660
|
+
heldPrompt.release();
|
|
661
|
+
heldPrompt = createHeldPromptStream(promptMessages);
|
|
662
|
+
releasePromptStream = heldPrompt.release;
|
|
534
663
|
queryInstance = query({
|
|
535
|
-
prompt:
|
|
664
|
+
prompt: heldPrompt.stream,
|
|
536
665
|
options: sdkOptions
|
|
537
666
|
});
|
|
538
667
|
}
|
|
539
|
-
// Restore immediately — Query constructor already captured the value
|
|
540
|
-
if (prevStreamTimeout !== undefined) {
|
|
541
|
-
process.env.CLAUDE_CODE_STREAM_CLOSE_TIMEOUT = prevStreamTimeout;
|
|
542
|
-
}
|
|
543
|
-
else {
|
|
544
|
-
delete process.env.CLAUDE_CODE_STREAM_CLOSE_TIMEOUT;
|
|
545
|
-
}
|
|
546
668
|
// Track the query instance for abort capability
|
|
547
669
|
if (sessionKey()) {
|
|
548
|
-
addSession(sessionKey(), queryInstance, ws);
|
|
670
|
+
addSession(sessionKey(), queryInstance, ws, releasePromptStream);
|
|
549
671
|
}
|
|
550
672
|
// Process streaming messages
|
|
551
673
|
console.log('Starting async generator loop for session:', capturedSessionId || 'NEW');
|
|
@@ -553,7 +675,7 @@ async function queryClaudeSDK(command, options = {}, ws, context) {
|
|
|
553
675
|
// Capture session ID from first message
|
|
554
676
|
if (message.session_id && !capturedSessionId) {
|
|
555
677
|
capturedSessionId = message.session_id;
|
|
556
|
-
addSession(sessionKey(), queryInstance, ws);
|
|
678
|
+
addSession(sessionKey(), queryInstance, ws, releasePromptStream);
|
|
557
679
|
// Set session ID on writer
|
|
558
680
|
if (ws.setSessionId && typeof ws.setSessionId === 'function') {
|
|
559
681
|
ws.setSessionId(capturedSessionId);
|
|
@@ -584,32 +706,93 @@ async function queryClaudeSDK(command, options = {}, ws, context) {
|
|
|
584
706
|
if (tokenBudgetData) {
|
|
585
707
|
ws.send(createNormalizedMessage({ kind: 'status', text: 'token_budget', tokenBudget: tokenBudgetData, sessionId: capturedSessionId || sessionId || null, provider: 'claude' }));
|
|
586
708
|
}
|
|
709
|
+
if (startsBackgroundWork(message)) {
|
|
710
|
+
backgroundWorkPending = true;
|
|
711
|
+
}
|
|
712
|
+
if (message.type === 'result') {
|
|
713
|
+
// The turn is done as far as the client is concerned.
|
|
714
|
+
const abortPending = sessionKey() ? abortedSessionIds.has(sessionKey()) : false;
|
|
715
|
+
if (!turnCompleteSent && !abortPending) {
|
|
716
|
+
turnCompleteSent = true;
|
|
717
|
+
ws.send(createCompleteMessage({ provider: 'claude', sessionId: capturedSessionId || sessionId || null, exitCode: 0 }));
|
|
718
|
+
notifyRunStopped({
|
|
719
|
+
userId: ws?.userId || null,
|
|
720
|
+
provider: 'claude',
|
|
721
|
+
sessionId: sessionId || capturedSessionId || null,
|
|
722
|
+
sessionName: sessionSummary,
|
|
723
|
+
stopReason: 'completed'
|
|
724
|
+
});
|
|
725
|
+
}
|
|
726
|
+
else if (heldForBackgroundWork && !abortPending) {
|
|
727
|
+
// A result after the turn already reported complete means the work we
|
|
728
|
+
// held the process open for has finished and pushed a follow-up turn.
|
|
729
|
+
notifyBackgroundWorkCompleted({
|
|
730
|
+
userId: ws?.userId || null,
|
|
731
|
+
provider: 'claude',
|
|
732
|
+
sessionId: sessionId || capturedSessionId || null,
|
|
733
|
+
sessionName: sessionSummary
|
|
734
|
+
});
|
|
735
|
+
}
|
|
736
|
+
if (backgroundWorkPending) {
|
|
737
|
+
// Work started during this turn is still running. Hold the process
|
|
738
|
+
// open so it can finish and report back in a follow-up turn; the
|
|
739
|
+
// ceiling is only a backstop for work that never reports.
|
|
740
|
+
backgroundWorkPending = false;
|
|
741
|
+
heldForBackgroundWork = true;
|
|
742
|
+
scheduleRelease();
|
|
743
|
+
}
|
|
744
|
+
else {
|
|
745
|
+
// Either nothing was backgrounded, or the background work just
|
|
746
|
+
// reported in — let the CLI exit now, as it always has.
|
|
747
|
+
heldForBackgroundWork = false;
|
|
748
|
+
releasePromptStream();
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
else if (idleReleaseTimer) {
|
|
752
|
+
// Background activity after the turn — push the countdown back out.
|
|
753
|
+
scheduleRelease();
|
|
754
|
+
}
|
|
587
755
|
}
|
|
588
|
-
// Clean up session on completion
|
|
589
|
-
|
|
756
|
+
// Clean up session on completion — only while this run still owns the map
|
|
757
|
+
// entry. A superseding run may have replaced it, and deleting here would
|
|
758
|
+
// strand that run.
|
|
759
|
+
if (sessionKey() && getSession(sessionKey())?.instance === queryInstance) {
|
|
590
760
|
removeSession(sessionKey());
|
|
591
761
|
}
|
|
762
|
+
// A superseded run winds down silently: the map entry, the abort flag,
|
|
763
|
+
// and all client-facing events belong to the run that replaced it.
|
|
764
|
+
const superseded = supersededInstances.has(queryInstance);
|
|
592
765
|
// Send the terminal completion event — skipped for aborted runs, whose
|
|
593
|
-
// terminal `complete` (aborted: true) was already sent by abort-session
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
766
|
+
// terminal `complete` (aborted: true) was already sent by abort-session, and
|
|
767
|
+
// for runs that already reported completion when their `result` arrived.
|
|
768
|
+
const wasAborted = !superseded && sessionKey() ? abortedSessionIds.delete(sessionKey()) : false;
|
|
769
|
+
if (!turnCompleteSent && !superseded) {
|
|
770
|
+
turnCompleteSent = true;
|
|
771
|
+
if (!wasAborted) {
|
|
772
|
+
ws.send(createCompleteMessage({ provider: 'claude', sessionId: capturedSessionId || sessionId || null, exitCode: 0 }));
|
|
773
|
+
}
|
|
774
|
+
notifyRunStopped({
|
|
775
|
+
userId: ws?.userId || null,
|
|
776
|
+
provider: 'claude',
|
|
777
|
+
sessionId: sessionId || capturedSessionId || null,
|
|
778
|
+
sessionName: sessionSummary,
|
|
779
|
+
stopReason: wasAborted ? 'aborted' : 'completed'
|
|
780
|
+
});
|
|
597
781
|
}
|
|
598
|
-
notifyRunStopped({
|
|
599
|
-
userId: ws?.userId || null,
|
|
600
|
-
provider: 'claude',
|
|
601
|
-
sessionId: sessionId || capturedSessionId || null,
|
|
602
|
-
sessionName: sessionSummary,
|
|
603
|
-
stopReason: wasAborted ? 'aborted' : 'completed'
|
|
604
|
-
});
|
|
605
782
|
// Complete
|
|
606
783
|
}
|
|
607
784
|
catch (error) {
|
|
608
785
|
console.error('SDK query error:', error);
|
|
609
|
-
// Clean up session on error
|
|
610
|
-
|
|
786
|
+
// Clean up session on error — only while this run still owns the map entry
|
|
787
|
+
// (a superseding run may have replaced it).
|
|
788
|
+
if (sessionKey() && getSession(sessionKey())?.instance === queryInstance) {
|
|
611
789
|
removeSession(sessionKey());
|
|
612
790
|
}
|
|
791
|
+
if (supersededInstances.has(queryInstance)) {
|
|
792
|
+
// Interrupted because a newer run took over this session id; that run
|
|
793
|
+
// owns the abort flag and all further client-facing events.
|
|
794
|
+
return;
|
|
795
|
+
}
|
|
613
796
|
const wasAborted = sessionKey() ? abortedSessionIds.delete(sessionKey()) : false;
|
|
614
797
|
if (wasAborted) {
|
|
615
798
|
// The abort already produced the terminal complete; a generator throw
|
|
@@ -621,9 +804,13 @@ async function queryClaudeSDK(command, options = {}, ws, context) {
|
|
|
621
804
|
const errorContent = !installed
|
|
622
805
|
? 'Claude Code is not installed. Please install it first: https://docs.anthropic.com/en/docs/claude-code'
|
|
623
806
|
: error.message;
|
|
624
|
-
// Send error to WebSocket, then the terminal complete
|
|
807
|
+
// Send error to WebSocket, then the terminal complete. A run that already
|
|
808
|
+
// reported completion and then failed during its post-turn hold still
|
|
809
|
+
// surfaces the error, but must not emit a second terminal complete.
|
|
625
810
|
ws.send(createNormalizedMessage({ kind: 'error', content: errorContent, sessionId: capturedSessionId || sessionId || null, provider: 'claude' }));
|
|
626
|
-
|
|
811
|
+
if (!turnCompleteSent) {
|
|
812
|
+
ws.send(createCompleteMessage({ provider: 'claude', sessionId: capturedSessionId || sessionId || null, exitCode: 1 }));
|
|
813
|
+
}
|
|
627
814
|
notifyRunFailed({
|
|
628
815
|
userId: ws?.userId || null,
|
|
629
816
|
provider: 'claude',
|
|
@@ -632,6 +819,15 @@ async function queryClaudeSDK(command, options = {}, ws, context) {
|
|
|
632
819
|
error
|
|
633
820
|
});
|
|
634
821
|
}
|
|
822
|
+
finally {
|
|
823
|
+
// Always close stdin — otherwise an aborted or failed run leaves the CLI
|
|
824
|
+
// process (and its MCP servers) alive until the server exits.
|
|
825
|
+
if (idleReleaseTimer) {
|
|
826
|
+
clearTimeout(idleReleaseTimer);
|
|
827
|
+
idleReleaseTimer = null;
|
|
828
|
+
}
|
|
829
|
+
releasePromptStream();
|
|
830
|
+
}
|
|
635
831
|
}
|
|
636
832
|
/**
|
|
637
833
|
* Aborts an active SDK session
|
|
@@ -651,6 +847,9 @@ async function abortClaudeSDKSession(sessionId) {
|
|
|
651
847
|
abortedSessionIds.add(sessionId);
|
|
652
848
|
// Call interrupt() on the query instance
|
|
653
849
|
await session.instance.interrupt();
|
|
850
|
+
// Release the held stdin stream; without this the CLI stays up for the rest
|
|
851
|
+
// of the post-turn hold even though the user cancelled.
|
|
852
|
+
session.releaseInput?.();
|
|
654
853
|
// Update session status
|
|
655
854
|
session.status = 'aborted';
|
|
656
855
|
// Clean up session
|