@sanqianx/claude-ai-workbench 0.13.2 → 0.13.3

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 (120) hide show
  1. package/LICENSE +201 -201
  2. package/README.md +156 -156
  3. package/apps/agent-terminal/app.css +636 -613
  4. package/apps/agent-terminal/app.js +125 -65
  5. package/apps/agent-terminal/conversation-composer.js +44 -0
  6. package/apps/agent-terminal/index.html +171 -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 +187 -159
  10. package/apps/agent-terminal/right-workspace-dock.js +623 -519
  11. package/apps/ai-profile-settings-host/index.html +25 -25
  12. package/apps/ai-profile-settings-host/page.css +1 -1
  13. package/apps/ai-profile-settings-host/page.js +113 -113
  14. package/apps/minimal-test-host/README.md +15 -15
  15. package/apps/minimal-test-host/host.css +2 -2
  16. package/apps/minimal-test-host/host.js +35 -35
  17. package/apps/minimal-test-host/index.html +58 -58
  18. package/apps/minimal-test-host/optional-mock/fault-injection.js +15 -15
  19. package/docs/sdk/FILE_LAYOUT.md +31 -31
  20. package/docs/sdk/INTEGRATION.md +126 -126
  21. package/docs/sdk/README.md +21 -21
  22. package/docs/sdk/SESSION_EVENTS.md +13 -13
  23. package/docs/sdk/openapi.yaml +8 -1
  24. package/package.json +1 -1
  25. package/packages/client/README.md +29 -29
  26. package/packages/client/index.d.ts +122 -122
  27. package/packages/client/index.js +260 -260
  28. package/packages/client/package.json +2 -2
  29. package/packages/contracts/README.md +9 -9
  30. package/packages/contracts/index.d.ts +519 -517
  31. package/packages/contracts/index.js +312 -312
  32. package/packages/contracts/package.json +1 -1
  33. package/packages/core/README.md +8 -8
  34. package/packages/core/index.d.ts +76 -76
  35. package/packages/core/index.js +222 -222
  36. package/packages/core/package.json +2 -2
  37. package/packages/server/README.md +17 -17
  38. package/packages/server/bin/agent-terminal-server.js +42 -42
  39. package/packages/server/bin/claude-workbench.js +225 -225
  40. package/packages/server/index.d.ts +171 -171
  41. package/packages/server/index.js +230 -230
  42. package/packages/server/lib/agent-discovery.js +133 -133
  43. package/packages/server/lib/agent-registry.js +143 -143
  44. package/packages/server/lib/agent-spawn-env.js +17 -17
  45. package/packages/server/lib/attachment-store.js +78 -78
  46. package/packages/server/lib/bridges/app-server-bridge.js +373 -373
  47. package/packages/server/lib/bridges/opencode-server-bridge.js +506 -506
  48. package/packages/server/lib/capture-settings-store.js +35 -35
  49. package/packages/server/lib/claude-history-recovery.js +87 -87
  50. package/packages/server/lib/cli-session-recovery.js +28 -28
  51. package/packages/server/lib/context-resolver.js +55 -55
  52. package/packages/server/lib/conversation-capture.js +51 -51
  53. package/packages/server/lib/delegation-phase-store.js +357 -357
  54. package/packages/server/lib/delegation-store.js +474 -468
  55. package/packages/server/lib/diagnostics.js +32 -32
  56. package/packages/server/lib/drivers/cli-json-runner.js +974 -974
  57. package/packages/server/lib/drivers/codex-driver.js +1442 -1442
  58. package/packages/server/lib/drivers/opencode-driver.js +1554 -1554
  59. package/packages/server/lib/drivers/zcode-driver.js +1250 -1250
  60. package/packages/server/lib/drivers/zcode-profile-runtime.js +71 -71
  61. package/packages/server/lib/event-stream.js +138 -138
  62. package/packages/server/lib/folder-picker.js +623 -623
  63. package/packages/server/lib/http-handler.js +339 -339
  64. package/packages/server/lib/json-file.js +26 -26
  65. package/packages/server/lib/knowledge-context.js +33 -33
  66. package/packages/server/lib/model-detection.js +295 -295
  67. package/packages/server/lib/parent-context.js +44 -0
  68. package/packages/server/lib/profile-store.js +283 -283
  69. package/packages/server/lib/project-store.js +102 -102
  70. package/packages/server/lib/runtime-loader.js +120 -120
  71. package/packages/server/lib/session-archive-store.js +53 -53
  72. package/packages/server/lib/session-history.js +612 -612
  73. package/packages/server/lib/system-doctor.js +125 -125
  74. package/packages/server/lib/ui-preferences-store.js +48 -48
  75. package/packages/server/lib/workbench-service.js +1696 -1675
  76. package/packages/server/package.json +2 -2
  77. package/packages/ui/README.md +30 -30
  78. package/packages/ui/ai-profile-settings.d.ts +45 -45
  79. package/packages/ui/ai-profile-settings.js +283 -283
  80. package/packages/ui/claude-terminal.d.ts +31 -31
  81. package/packages/ui/claude-terminal.js +343 -343
  82. package/packages/ui/index.d.ts +18 -18
  83. package/packages/ui/index.js +51 -51
  84. package/packages/ui/package.json +2 -2
  85. package/packages/ui/theme.css +13 -13
  86. package/src/assets/claude-prompts.json +21 -21
  87. package/src/backend/http/ai-profile-routes.js +61 -61
  88. package/src/backend/http/claude-routes.js +170 -170
  89. package/src/backend/http/node-helpers.js +45 -45
  90. package/src/backend/index.js +21 -21
  91. package/src/backend/lib/ai-adapter.js +144 -144
  92. package/src/backend/lib/ai-profile-store.js +259 -259
  93. package/src/backend/lib/ai-vendor-presets.js +83 -83
  94. package/src/backend/lib/ai-workspace.js +140 -140
  95. package/src/backend/lib/automation-config.js +253 -253
  96. package/src/backend/lib/claude-cli-runner.js +2392 -2392
  97. package/src/backend/lib/data-dir.js +169 -169
  98. package/src/backend/lib/llm-client.js +176 -176
  99. package/src/backend/lib/model-context-windows.js +82 -82
  100. package/src/backend/lib/native-task-control.js +217 -217
  101. package/src/backend/lib/native-task-history-index.js +475 -475
  102. package/src/backend/lib/native-task-history-reader.js +526 -526
  103. package/src/backend/lib/native-task-messages.js +457 -457
  104. package/src/backend/lib/native-task-registry.js +325 -325
  105. package/src/backend/lib/native-task-runtime.js +242 -242
  106. package/src/backend/lib/native-task-trace.js +440 -440
  107. package/src/backend/lib/native-task-transcript.js +393 -393
  108. package/src/backend/lib/prompt-registry.js +166 -166
  109. package/src/backend/lib/runtime-config.js +121 -121
  110. package/src/backend/lib/sdk-session-stream.js +143 -143
  111. package/src/backend/lib/sdk-turn-stream.js +16 -16
  112. package/src/backend/lib/store-scope.js +131 -131
  113. package/src/backend/lib/task-identity.js +104 -104
  114. package/src/backend/lib/task-state-projection.js +58 -58
  115. package/src/index.js +7 -7
  116. package/src/sdk-wave-a.ts +1 -1
  117. package/src/sdk-wave-b.ts +1 -1
  118. package/src/sdk-wave-c.ts +1 -1
  119. package/src/sdk-wave-d.ts +1 -1
  120. 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