@sanqianx/claude-ai-workbench 0.13.2 → 0.13.4

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.
Files changed (122) hide show
  1. package/LICENSE +201 -201
  2. package/README.md +156 -156
  3. package/apps/agent-terminal/app.css +652 -613
  4. package/apps/agent-terminal/app.js +143 -67
  5. package/apps/agent-terminal/conversation-composer.js +44 -0
  6. package/apps/agent-terminal/index.html +172 -170
  7. package/apps/agent-terminal/panel-host-proof.html +152 -152
  8. package/apps/agent-terminal/panel-proof-content.html +41 -41
  9. package/apps/agent-terminal/right-workspace-dock.css +189 -159
  10. package/apps/agent-terminal/right-workspace-dock.js +652 -521
  11. package/apps/agent-terminal/user-question-card.js +68 -0
  12. package/apps/ai-profile-settings-host/index.html +25 -25
  13. package/apps/ai-profile-settings-host/page.css +1 -1
  14. package/apps/ai-profile-settings-host/page.js +113 -113
  15. package/apps/minimal-test-host/README.md +15 -15
  16. package/apps/minimal-test-host/host.css +2 -2
  17. package/apps/minimal-test-host/host.js +35 -35
  18. package/apps/minimal-test-host/index.html +58 -58
  19. package/apps/minimal-test-host/optional-mock/fault-injection.js +15 -15
  20. package/docs/sdk/FILE_LAYOUT.md +31 -31
  21. package/docs/sdk/INTEGRATION.md +126 -126
  22. package/docs/sdk/README.md +21 -21
  23. package/docs/sdk/SESSION_EVENTS.md +15 -13
  24. package/docs/sdk/openapi.yaml +16 -1
  25. package/package.json +1 -1
  26. package/packages/client/README.md +29 -29
  27. package/packages/client/index.d.ts +122 -122
  28. package/packages/client/index.js +260 -260
  29. package/packages/client/package.json +2 -2
  30. package/packages/contracts/README.md +9 -9
  31. package/packages/contracts/index.d.ts +519 -517
  32. package/packages/contracts/index.js +312 -312
  33. package/packages/contracts/package.json +1 -1
  34. package/packages/core/README.md +8 -8
  35. package/packages/core/index.d.ts +76 -76
  36. package/packages/core/index.js +222 -222
  37. package/packages/core/package.json +2 -2
  38. package/packages/server/README.md +17 -17
  39. package/packages/server/bin/agent-terminal-server.js +42 -42
  40. package/packages/server/bin/claude-workbench.js +225 -225
  41. package/packages/server/index.d.ts +171 -171
  42. package/packages/server/index.js +230 -230
  43. package/packages/server/lib/agent-discovery.js +133 -133
  44. package/packages/server/lib/agent-registry.js +143 -143
  45. package/packages/server/lib/agent-spawn-env.js +17 -17
  46. package/packages/server/lib/attachment-store.js +78 -78
  47. package/packages/server/lib/bridges/app-server-bridge.js +373 -373
  48. package/packages/server/lib/bridges/opencode-server-bridge.js +506 -506
  49. package/packages/server/lib/capture-settings-store.js +35 -35
  50. package/packages/server/lib/claude-history-recovery.js +87 -87
  51. package/packages/server/lib/cli-session-recovery.js +28 -28
  52. package/packages/server/lib/context-resolver.js +55 -55
  53. package/packages/server/lib/conversation-capture.js +51 -51
  54. package/packages/server/lib/delegation-phase-store.js +357 -357
  55. package/packages/server/lib/delegation-store.js +474 -468
  56. package/packages/server/lib/diagnostics.js +32 -32
  57. package/packages/server/lib/drivers/cli-json-runner.js +974 -974
  58. package/packages/server/lib/drivers/codex-driver.js +1461 -1442
  59. package/packages/server/lib/drivers/opencode-driver.js +1554 -1554
  60. package/packages/server/lib/drivers/zcode-driver.js +1250 -1250
  61. package/packages/server/lib/drivers/zcode-profile-runtime.js +71 -71
  62. package/packages/server/lib/event-stream.js +138 -138
  63. package/packages/server/lib/folder-picker.js +623 -623
  64. package/packages/server/lib/http-handler.js +339 -339
  65. package/packages/server/lib/json-file.js +26 -26
  66. package/packages/server/lib/knowledge-context.js +33 -33
  67. package/packages/server/lib/model-detection.js +295 -295
  68. package/packages/server/lib/parent-context.js +44 -0
  69. package/packages/server/lib/profile-store.js +283 -283
  70. package/packages/server/lib/project-store.js +102 -102
  71. package/packages/server/lib/runtime-loader.js +120 -120
  72. package/packages/server/lib/session-archive-store.js +53 -53
  73. package/packages/server/lib/session-history.js +612 -612
  74. package/packages/server/lib/system-doctor.js +125 -125
  75. package/packages/server/lib/ui-preferences-store.js +48 -48
  76. package/packages/server/lib/user-questions.js +67 -0
  77. package/packages/server/lib/workbench-service.js +1696 -1675
  78. package/packages/server/package.json +2 -2
  79. package/packages/ui/README.md +30 -30
  80. package/packages/ui/ai-profile-settings.d.ts +45 -45
  81. package/packages/ui/ai-profile-settings.js +283 -283
  82. package/packages/ui/claude-terminal.d.ts +31 -31
  83. package/packages/ui/claude-terminal.js +343 -343
  84. package/packages/ui/index.d.ts +18 -18
  85. package/packages/ui/index.js +51 -51
  86. package/packages/ui/package.json +2 -2
  87. package/packages/ui/theme.css +13 -13
  88. package/src/assets/claude-prompts.json +21 -21
  89. package/src/backend/http/ai-profile-routes.js +61 -61
  90. package/src/backend/http/claude-routes.js +170 -170
  91. package/src/backend/http/node-helpers.js +45 -45
  92. package/src/backend/index.js +21 -21
  93. package/src/backend/lib/ai-adapter.js +144 -144
  94. package/src/backend/lib/ai-profile-store.js +259 -259
  95. package/src/backend/lib/ai-vendor-presets.js +83 -83
  96. package/src/backend/lib/ai-workspace.js +140 -140
  97. package/src/backend/lib/automation-config.js +253 -253
  98. package/src/backend/lib/claude-cli-runner.js +2408 -2392
  99. package/src/backend/lib/data-dir.js +169 -169
  100. package/src/backend/lib/llm-client.js +176 -176
  101. package/src/backend/lib/model-context-windows.js +82 -82
  102. package/src/backend/lib/native-task-control.js +217 -217
  103. package/src/backend/lib/native-task-history-index.js +475 -475
  104. package/src/backend/lib/native-task-history-reader.js +526 -526
  105. package/src/backend/lib/native-task-messages.js +457 -457
  106. package/src/backend/lib/native-task-registry.js +325 -325
  107. package/src/backend/lib/native-task-runtime.js +242 -242
  108. package/src/backend/lib/native-task-trace.js +440 -440
  109. package/src/backend/lib/native-task-transcript.js +393 -393
  110. package/src/backend/lib/prompt-registry.js +166 -166
  111. package/src/backend/lib/runtime-config.js +121 -121
  112. package/src/backend/lib/sdk-session-stream.js +143 -143
  113. package/src/backend/lib/sdk-turn-stream.js +16 -16
  114. package/src/backend/lib/store-scope.js +131 -131
  115. package/src/backend/lib/task-identity.js +104 -104
  116. package/src/backend/lib/task-state-projection.js +58 -58
  117. package/src/index.js +7 -7
  118. package/src/sdk-wave-a.ts +1 -1
  119. package/src/sdk-wave-b.ts +1 -1
  120. package/src/sdk-wave-c.ts +1 -1
  121. package/src/sdk-wave-d.ts +1 -1
  122. package/src/sdk-wave-e.ts +1 -1
@@ -1,104 +1,104 @@
1
- // Task identity - pure helpers for background-task scope and native-task refs.
2
- //
3
- // Canonical shapes (see packages/contracts/index.d.ts):
4
- // scope: { storeScope, contextId, parentSessionId }
5
- // native: { kind: 'native-task', ...scope, ownerRunId, taskId }
6
- //
7
- // Every field is an already-resolved opaque string kept verbatim: identities
8
- // are never trimmed or rewritten (leading/trailing spaces are part of the id;
9
- // only all-whitespace values are invalid). Inputs are snapshotted - returned
10
- // objects share nothing with the caller input. No owner is derived here:
11
- // ownerRunId must come from the real parent tool-call relation, and volatile
12
- // state (runtimeEpoch, ports, PIDs, selected panel, turn numbers, timestamps)
13
- // never enters a persistent key.
14
-
15
- const SCOPE_FIELDS = ['storeScope', 'contextId', 'parentSessionId'];
16
- const NATIVE_TASK_KIND = 'native-task';
17
- const NATIVE_TASK_KEY_VERSION = 1;
18
-
19
- function isResolvedId(value) {
20
- return typeof value === 'string' && value.trim() !== '';
21
- }
22
-
23
- /**
24
- * Snapshot the canonical session scope { storeScope, contextId, parentSessionId }.
25
- * Returns null when input is not an object, or any required field is missing,
26
- * not a string, or whitespace-only. Extra fields are ignored.
27
- */
28
- function createTaskScope(input) {
29
- if (!input || typeof input !== 'object') return null;
30
- const scope = {};
31
- for (const field of SCOPE_FIELDS) {
32
- const value = input[field];
33
- if (!isResolvedId(value)) return null;
34
- scope[field] = value;
35
- }
36
- return scope;
37
- }
38
-
39
- /**
40
- * Snapshot a native background task reference. Requires the explicit kind
41
- * 'native-task' (other kinds must not impersonate native tasks), a complete
42
- * scope, plus ownerRunId and taskId. ownerRunId is never defaulted from the
43
- * current turn or any other ambient state.
44
- */
45
- function createNativeTaskRef(input) {
46
- if (!input || typeof input !== 'object') return null;
47
- if (input.kind !== NATIVE_TASK_KIND) return null;
48
- const scope = createTaskScope(input);
49
- if (!scope) return null;
50
- if (!isResolvedId(input.ownerRunId)) return null;
51
- if (!isResolvedId(input.taskId)) return null;
52
- return {
53
- kind: NATIVE_TASK_KIND,
54
- storeScope: scope.storeScope,
55
- contextId: scope.contextId,
56
- parentSessionId: scope.parentSessionId,
57
- ownerRunId: input.ownerRunId,
58
- taskId: input.taskId,
59
- };
60
- }
61
-
62
- /**
63
- * Persistent key for a native task: an unambiguous JSON tuple with a fixed
64
- * version and fixed field order, so ids containing separators, quotes or
65
- * Unicode cannot collide or be rewritten. Returns null for anything that is
66
- * not a valid native-task reference. Only identity fields participate -
67
- * runtimeEpoch/ports/PIDs/selected panel/turn/time stay out of the key.
68
- */
69
- function nativeTaskKey(ref) {
70
- const taskRef = createNativeTaskRef(ref);
71
- if (!taskRef) return null;
72
- return JSON.stringify([
73
- 'native-task',
74
- NATIVE_TASK_KEY_VERSION,
75
- taskRef.storeScope,
76
- taskRef.contextId,
77
- taskRef.parentSessionId,
78
- taskRef.ownerRunId,
79
- taskRef.taskId,
80
- ]);
81
- }
82
-
83
- /**
84
- * Compare two objects by exactly the three canonical scope fields. Incomplete
85
- * or invalid scopes never compare equal; other fields (kind, taskId, ...) are
86
- * ignored, so two different tasks in the same scope still share a scope.
87
- * This is identity comparison only and carries no authorization meaning -
88
- * real access checks belong to the API layer.
89
- */
90
- function sameTaskScope(a, b) {
91
- if (!a || typeof a !== 'object') return false;
92
- if (!b || typeof b !== 'object') return false;
93
- for (const field of SCOPE_FIELDS) {
94
- if (!isResolvedId(a[field]) || a[field] !== b[field]) return false;
95
- }
96
- return true;
97
- }
98
-
99
- module.exports = {
100
- createTaskScope,
101
- createNativeTaskRef,
102
- nativeTaskKey,
103
- sameTaskScope,
104
- };
1
+ // Task identity - pure helpers for background-task scope and native-task refs.
2
+ //
3
+ // Canonical shapes (see packages/contracts/index.d.ts):
4
+ // scope: { storeScope, contextId, parentSessionId }
5
+ // native: { kind: 'native-task', ...scope, ownerRunId, taskId }
6
+ //
7
+ // Every field is an already-resolved opaque string kept verbatim: identities
8
+ // are never trimmed or rewritten (leading/trailing spaces are part of the id;
9
+ // only all-whitespace values are invalid). Inputs are snapshotted - returned
10
+ // objects share nothing with the caller input. No owner is derived here:
11
+ // ownerRunId must come from the real parent tool-call relation, and volatile
12
+ // state (runtimeEpoch, ports, PIDs, selected panel, turn numbers, timestamps)
13
+ // never enters a persistent key.
14
+
15
+ const SCOPE_FIELDS = ['storeScope', 'contextId', 'parentSessionId'];
16
+ const NATIVE_TASK_KIND = 'native-task';
17
+ const NATIVE_TASK_KEY_VERSION = 1;
18
+
19
+ function isResolvedId(value) {
20
+ return typeof value === 'string' && value.trim() !== '';
21
+ }
22
+
23
+ /**
24
+ * Snapshot the canonical session scope { storeScope, contextId, parentSessionId }.
25
+ * Returns null when input is not an object, or any required field is missing,
26
+ * not a string, or whitespace-only. Extra fields are ignored.
27
+ */
28
+ function createTaskScope(input) {
29
+ if (!input || typeof input !== 'object') return null;
30
+ const scope = {};
31
+ for (const field of SCOPE_FIELDS) {
32
+ const value = input[field];
33
+ if (!isResolvedId(value)) return null;
34
+ scope[field] = value;
35
+ }
36
+ return scope;
37
+ }
38
+
39
+ /**
40
+ * Snapshot a native background task reference. Requires the explicit kind
41
+ * 'native-task' (other kinds must not impersonate native tasks), a complete
42
+ * scope, plus ownerRunId and taskId. ownerRunId is never defaulted from the
43
+ * current turn or any other ambient state.
44
+ */
45
+ function createNativeTaskRef(input) {
46
+ if (!input || typeof input !== 'object') return null;
47
+ if (input.kind !== NATIVE_TASK_KIND) return null;
48
+ const scope = createTaskScope(input);
49
+ if (!scope) return null;
50
+ if (!isResolvedId(input.ownerRunId)) return null;
51
+ if (!isResolvedId(input.taskId)) return null;
52
+ return {
53
+ kind: NATIVE_TASK_KIND,
54
+ storeScope: scope.storeScope,
55
+ contextId: scope.contextId,
56
+ parentSessionId: scope.parentSessionId,
57
+ ownerRunId: input.ownerRunId,
58
+ taskId: input.taskId,
59
+ };
60
+ }
61
+
62
+ /**
63
+ * Persistent key for a native task: an unambiguous JSON tuple with a fixed
64
+ * version and fixed field order, so ids containing separators, quotes or
65
+ * Unicode cannot collide or be rewritten. Returns null for anything that is
66
+ * not a valid native-task reference. Only identity fields participate -
67
+ * runtimeEpoch/ports/PIDs/selected panel/turn/time stay out of the key.
68
+ */
69
+ function nativeTaskKey(ref) {
70
+ const taskRef = createNativeTaskRef(ref);
71
+ if (!taskRef) return null;
72
+ return JSON.stringify([
73
+ 'native-task',
74
+ NATIVE_TASK_KEY_VERSION,
75
+ taskRef.storeScope,
76
+ taskRef.contextId,
77
+ taskRef.parentSessionId,
78
+ taskRef.ownerRunId,
79
+ taskRef.taskId,
80
+ ]);
81
+ }
82
+
83
+ /**
84
+ * Compare two objects by exactly the three canonical scope fields. Incomplete
85
+ * or invalid scopes never compare equal; other fields (kind, taskId, ...) are
86
+ * ignored, so two different tasks in the same scope still share a scope.
87
+ * This is identity comparison only and carries no authorization meaning -
88
+ * real access checks belong to the API layer.
89
+ */
90
+ function sameTaskScope(a, b) {
91
+ if (!a || typeof a !== 'object') return false;
92
+ if (!b || typeof b !== 'object') return false;
93
+ for (const field of SCOPE_FIELDS) {
94
+ if (!isResolvedId(a[field]) || a[field] !== b[field]) return false;
95
+ }
96
+ return true;
97
+ }
98
+
99
+ module.exports = {
100
+ createTaskScope,
101
+ createNativeTaskRef,
102
+ nativeTaskKey,
103
+ sameTaskScope,
104
+ };
@@ -1,58 +1,58 @@
1
- 'use strict';
2
-
3
- // Pure projection of one claude/task-* fact onto the session's task index.
4
- // The raw normalized event is immutable input: it flows untouched into the
5
- // sequence/SSE/history stream, and only the indexed row is governed here:
6
- // - known-status whitelist (pending/running/completed/failed/stopped)
7
- // - the first terminal status is never revived or rewritten by later facts
8
- // - an unknown or missing status never overwrites an existing row's status
9
- // - a first-seen task without a usable status is explicitly 'unknown',
10
- // never defaulted to running or completed
11
- // Rows are keyed by (sdkSessionId, taskId): a fact without real SDK
12
- // identity stays in the null bucket instead of borrowing the current
13
- // SDK session's identity.
14
- const KNOWN_TASK_STATUSES = new Set(['pending', 'running', 'completed', 'failed', 'stopped']);
15
- const TERMINAL_TASK_STATUSES = new Set(['completed', 'failed', 'stopped']);
16
-
17
- function normalizeSdkSessionId(value) {
18
- return typeof value === 'string' && value !== '' ? value : null;
19
- }
20
-
21
- // Returns { index, task } where `task` is a freshly built row (never the
22
- // prior row, never the event) and `index` is -1 when the caller must insert.
23
- // Returns null when the fact carries no task id at all.
24
- function projectTaskStatus(existingTasks, event) {
25
- if (!event || typeof event !== 'object') return null;
26
- const taskId = typeof event.taskId === 'string' && event.taskId !== '' ? event.taskId : null;
27
- if (!taskId) return null;
28
- const tasks = Array.isArray(existingTasks) ? existingTasks : [];
29
- const sdkSessionId = normalizeSdkSessionId(event.sdkSessionId);
30
- const index = tasks.findIndex(task => task && task.taskId === taskId
31
- && normalizeSdkSessionId(task.sdkSessionId) === sdkSessionId);
32
- const prior = index < 0 ? null : tasks[index];
33
- const incoming = typeof event.status === 'string' && KNOWN_TASK_STATUSES.has(event.status)
34
- ? event.status : null;
35
- let status;
36
- let diagnostic = null;
37
- if (!prior) {
38
- if (incoming === null) {
39
- status = 'unknown';
40
- diagnostic = 'first-seen-unknown-status';
41
- } else status = incoming;
42
- } else if (incoming === null) {
43
- status = prior.status;
44
- diagnostic = 'unknown-status-kept';
45
- } else if (TERMINAL_TASK_STATUSES.has(prior.status) && prior.status !== incoming) {
46
- status = prior.status;
47
- diagnostic = TERMINAL_TASK_STATUSES.has(incoming) ? 'first-terminal-kept' : 'terminal-not-revived';
48
- } else {
49
- status = incoming;
50
- }
51
- const task = { ...(prior || {}), ...event };
52
- task.status = status;
53
- if (diagnostic) task.diagnostic = diagnostic;
54
- else delete task.diagnostic;
55
- return { index, task };
56
- }
57
-
58
- module.exports = { projectTaskStatus, KNOWN_TASK_STATUSES, TERMINAL_TASK_STATUSES };
1
+ 'use strict';
2
+
3
+ // Pure projection of one claude/task-* fact onto the session's task index.
4
+ // The raw normalized event is immutable input: it flows untouched into the
5
+ // sequence/SSE/history stream, and only the indexed row is governed here:
6
+ // - known-status whitelist (pending/running/completed/failed/stopped)
7
+ // - the first terminal status is never revived or rewritten by later facts
8
+ // - an unknown or missing status never overwrites an existing row's status
9
+ // - a first-seen task without a usable status is explicitly 'unknown',
10
+ // never defaulted to running or completed
11
+ // Rows are keyed by (sdkSessionId, taskId): a fact without real SDK
12
+ // identity stays in the null bucket instead of borrowing the current
13
+ // SDK session's identity.
14
+ const KNOWN_TASK_STATUSES = new Set(['pending', 'running', 'completed', 'failed', 'stopped']);
15
+ const TERMINAL_TASK_STATUSES = new Set(['completed', 'failed', 'stopped']);
16
+
17
+ function normalizeSdkSessionId(value) {
18
+ return typeof value === 'string' && value !== '' ? value : null;
19
+ }
20
+
21
+ // Returns { index, task } where `task` is a freshly built row (never the
22
+ // prior row, never the event) and `index` is -1 when the caller must insert.
23
+ // Returns null when the fact carries no task id at all.
24
+ function projectTaskStatus(existingTasks, event) {
25
+ if (!event || typeof event !== 'object') return null;
26
+ const taskId = typeof event.taskId === 'string' && event.taskId !== '' ? event.taskId : null;
27
+ if (!taskId) return null;
28
+ const tasks = Array.isArray(existingTasks) ? existingTasks : [];
29
+ const sdkSessionId = normalizeSdkSessionId(event.sdkSessionId);
30
+ const index = tasks.findIndex(task => task && task.taskId === taskId
31
+ && normalizeSdkSessionId(task.sdkSessionId) === sdkSessionId);
32
+ const prior = index < 0 ? null : tasks[index];
33
+ const incoming = typeof event.status === 'string' && KNOWN_TASK_STATUSES.has(event.status)
34
+ ? event.status : null;
35
+ let status;
36
+ let diagnostic = null;
37
+ if (!prior) {
38
+ if (incoming === null) {
39
+ status = 'unknown';
40
+ diagnostic = 'first-seen-unknown-status';
41
+ } else status = incoming;
42
+ } else if (incoming === null) {
43
+ status = prior.status;
44
+ diagnostic = 'unknown-status-kept';
45
+ } else if (TERMINAL_TASK_STATUSES.has(prior.status) && prior.status !== incoming) {
46
+ status = prior.status;
47
+ diagnostic = TERMINAL_TASK_STATUSES.has(incoming) ? 'first-terminal-kept' : 'terminal-not-revived';
48
+ } else {
49
+ status = incoming;
50
+ }
51
+ const task = { ...(prior || {}), ...event };
52
+ task.status = status;
53
+ if (diagnostic) task.diagnostic = diagnostic;
54
+ else delete task.diagnostic;
55
+ return { index, task };
56
+ }
57
+
58
+ module.exports = { projectTaskStatus, KNOWN_TASK_STATUSES, TERMINAL_TASK_STATUSES };
package/src/index.js CHANGED
@@ -1,7 +1,7 @@
1
- module.exports = {
2
- contracts: require('../packages/contracts'),
3
- client: require('../packages/client'),
4
- core: require('../packages/core'),
5
- server: require('../packages/server'),
6
- backend: require('./backend')
7
- };
1
+ module.exports = {
2
+ contracts: require('../packages/contracts'),
3
+ client: require('../packages/client'),
4
+ core: require('../packages/core'),
5
+ server: require('../packages/server'),
6
+ backend: require('./backend')
7
+ };
package/src/sdk-wave-a.ts CHANGED
@@ -1 +1 @@
1
- // new wave a
1
+ // new wave a
package/src/sdk-wave-b.ts CHANGED
@@ -1 +1 @@
1
- // new wave b
1
+ // new wave b
package/src/sdk-wave-c.ts CHANGED
@@ -1 +1 @@
1
- // new wave c
1
+ // new wave c
package/src/sdk-wave-d.ts CHANGED
@@ -1 +1 @@
1
- // new wave d
1
+ // new wave d
package/src/sdk-wave-e.ts CHANGED
@@ -1 +1 @@
1
- // new wave e
1
+ // new wave e