@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.
- package/LICENSE +201 -201
- package/README.md +156 -156
- package/apps/agent-terminal/app.css +636 -613
- package/apps/agent-terminal/app.js +125 -65
- package/apps/agent-terminal/conversation-composer.js +44 -0
- package/apps/agent-terminal/index.html +171 -170
- package/apps/agent-terminal/panel-host-proof.html +152 -152
- package/apps/agent-terminal/panel-proof-content.html +41 -41
- package/apps/agent-terminal/right-workspace-dock.css +187 -159
- package/apps/agent-terminal/right-workspace-dock.js +623 -519
- package/apps/ai-profile-settings-host/index.html +25 -25
- package/apps/ai-profile-settings-host/page.css +1 -1
- package/apps/ai-profile-settings-host/page.js +113 -113
- package/apps/minimal-test-host/README.md +15 -15
- package/apps/minimal-test-host/host.css +2 -2
- package/apps/minimal-test-host/host.js +35 -35
- package/apps/minimal-test-host/index.html +58 -58
- package/apps/minimal-test-host/optional-mock/fault-injection.js +15 -15
- package/docs/sdk/FILE_LAYOUT.md +31 -31
- package/docs/sdk/INTEGRATION.md +126 -126
- package/docs/sdk/README.md +21 -21
- package/docs/sdk/SESSION_EVENTS.md +13 -13
- package/docs/sdk/openapi.yaml +8 -1
- package/package.json +1 -1
- package/packages/client/README.md +29 -29
- package/packages/client/index.d.ts +122 -122
- package/packages/client/index.js +260 -260
- package/packages/client/package.json +2 -2
- package/packages/contracts/README.md +9 -9
- package/packages/contracts/index.d.ts +519 -517
- package/packages/contracts/index.js +312 -312
- package/packages/contracts/package.json +1 -1
- package/packages/core/README.md +8 -8
- package/packages/core/index.d.ts +76 -76
- package/packages/core/index.js +222 -222
- package/packages/core/package.json +2 -2
- package/packages/server/README.md +17 -17
- package/packages/server/bin/agent-terminal-server.js +42 -42
- package/packages/server/bin/claude-workbench.js +225 -225
- package/packages/server/index.d.ts +171 -171
- package/packages/server/index.js +230 -230
- package/packages/server/lib/agent-discovery.js +133 -133
- package/packages/server/lib/agent-registry.js +143 -143
- package/packages/server/lib/agent-spawn-env.js +17 -17
- package/packages/server/lib/attachment-store.js +78 -78
- package/packages/server/lib/bridges/app-server-bridge.js +373 -373
- package/packages/server/lib/bridges/opencode-server-bridge.js +506 -506
- package/packages/server/lib/capture-settings-store.js +35 -35
- package/packages/server/lib/claude-history-recovery.js +87 -87
- package/packages/server/lib/cli-session-recovery.js +28 -28
- package/packages/server/lib/context-resolver.js +55 -55
- package/packages/server/lib/conversation-capture.js +51 -51
- package/packages/server/lib/delegation-phase-store.js +357 -357
- package/packages/server/lib/delegation-store.js +474 -468
- package/packages/server/lib/diagnostics.js +32 -32
- package/packages/server/lib/drivers/cli-json-runner.js +974 -974
- package/packages/server/lib/drivers/codex-driver.js +1442 -1442
- package/packages/server/lib/drivers/opencode-driver.js +1554 -1554
- package/packages/server/lib/drivers/zcode-driver.js +1250 -1250
- package/packages/server/lib/drivers/zcode-profile-runtime.js +71 -71
- package/packages/server/lib/event-stream.js +138 -138
- package/packages/server/lib/folder-picker.js +623 -623
- package/packages/server/lib/http-handler.js +339 -339
- package/packages/server/lib/json-file.js +26 -26
- package/packages/server/lib/knowledge-context.js +33 -33
- package/packages/server/lib/model-detection.js +295 -295
- package/packages/server/lib/parent-context.js +44 -0
- package/packages/server/lib/profile-store.js +283 -283
- package/packages/server/lib/project-store.js +102 -102
- package/packages/server/lib/runtime-loader.js +120 -120
- package/packages/server/lib/session-archive-store.js +53 -53
- package/packages/server/lib/session-history.js +612 -612
- package/packages/server/lib/system-doctor.js +125 -125
- package/packages/server/lib/ui-preferences-store.js +48 -48
- package/packages/server/lib/workbench-service.js +1696 -1675
- package/packages/server/package.json +2 -2
- package/packages/ui/README.md +30 -30
- package/packages/ui/ai-profile-settings.d.ts +45 -45
- package/packages/ui/ai-profile-settings.js +283 -283
- package/packages/ui/claude-terminal.d.ts +31 -31
- package/packages/ui/claude-terminal.js +343 -343
- package/packages/ui/index.d.ts +18 -18
- package/packages/ui/index.js +51 -51
- package/packages/ui/package.json +2 -2
- package/packages/ui/theme.css +13 -13
- package/src/assets/claude-prompts.json +21 -21
- package/src/backend/http/ai-profile-routes.js +61 -61
- package/src/backend/http/claude-routes.js +170 -170
- package/src/backend/http/node-helpers.js +45 -45
- package/src/backend/index.js +21 -21
- package/src/backend/lib/ai-adapter.js +144 -144
- package/src/backend/lib/ai-profile-store.js +259 -259
- package/src/backend/lib/ai-vendor-presets.js +83 -83
- package/src/backend/lib/ai-workspace.js +140 -140
- package/src/backend/lib/automation-config.js +253 -253
- package/src/backend/lib/claude-cli-runner.js +2392 -2392
- package/src/backend/lib/data-dir.js +169 -169
- package/src/backend/lib/llm-client.js +176 -176
- package/src/backend/lib/model-context-windows.js +82 -82
- package/src/backend/lib/native-task-control.js +217 -217
- package/src/backend/lib/native-task-history-index.js +475 -475
- package/src/backend/lib/native-task-history-reader.js +526 -526
- package/src/backend/lib/native-task-messages.js +457 -457
- package/src/backend/lib/native-task-registry.js +325 -325
- package/src/backend/lib/native-task-runtime.js +242 -242
- package/src/backend/lib/native-task-trace.js +440 -440
- package/src/backend/lib/native-task-transcript.js +393 -393
- package/src/backend/lib/prompt-registry.js +166 -166
- package/src/backend/lib/runtime-config.js +121 -121
- package/src/backend/lib/sdk-session-stream.js +143 -143
- package/src/backend/lib/sdk-turn-stream.js +16 -16
- package/src/backend/lib/store-scope.js +131 -131
- package/src/backend/lib/task-identity.js +104 -104
- package/src/backend/lib/task-state-projection.js +58 -58
- package/src/index.js +7 -7
- package/src/sdk-wave-a.ts +1 -1
- package/src/sdk-wave-b.ts +1 -1
- package/src/sdk-wave-c.ts +1 -1
- package/src/sdk-wave-d.ts +1 -1
- package/src/sdk-wave-e.ts +1 -1
|
@@ -1,78 +1,78 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const crypto = require('crypto');
|
|
4
|
-
const fs = require('fs');
|
|
5
|
-
const path = require('path');
|
|
6
|
-
const { cleanId, normalizeAttachments, IMAGE_MEDIA_TYPES } = require('../../contracts');
|
|
7
|
-
|
|
8
|
-
const EXTENSIONS = {
|
|
9
|
-
'image/jpeg': '.jpg', 'image/png': '.png', 'image/gif': '.gif', 'image/webp': '.webp',
|
|
10
|
-
'text/plain': '.txt', 'text/markdown': '.md', 'application/json': '.json.txt', 'text/csv': '.csv',
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
class AttachmentStore {
|
|
14
|
-
constructor(options = {}) {
|
|
15
|
-
if (!options.root) throw new Error('AttachmentStore root is required');
|
|
16
|
-
this.root = path.resolve(options.root);
|
|
17
|
-
fs.mkdirSync(this.root, { recursive: true });
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
saveMany(sessionId, input) {
|
|
21
|
-
const id = cleanId(sessionId, 'sessionId');
|
|
22
|
-
const items = normalizeAttachments(input);
|
|
23
|
-
for (const item of items) if (IMAGE_MEDIA_TYPES.includes(item.mediaType)) verifyImage(Buffer.from(item.data, 'base64'), item.mediaType);
|
|
24
|
-
return items.map(item => this.save(id, item));
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
save(sessionId, input) {
|
|
28
|
-
const sid = cleanId(sessionId, 'sessionId');
|
|
29
|
-
const item = normalizeAttachments([input])[0];
|
|
30
|
-
const isImage = IMAGE_MEDIA_TYPES.includes(item.mediaType);
|
|
31
|
-
const id = item.id || `${isImage ? 'img' : 'file'}-${crypto.randomUUID()}`;
|
|
32
|
-
const buffer = Buffer.from(item.data, 'base64');
|
|
33
|
-
if (isImage) verifyImage(buffer, item.mediaType);
|
|
34
|
-
const directory = path.join(this.root, hash(sid));
|
|
35
|
-
const stem = hash(id);
|
|
36
|
-
const extension = EXTENSIONS[item.mediaType];
|
|
37
|
-
fs.mkdirSync(directory, { recursive: true });
|
|
38
|
-
const file = path.join(directory, `${stem}${extension}`);
|
|
39
|
-
const metaFile = path.join(directory, `${stem}.json`);
|
|
40
|
-
fs.writeFileSync(file, buffer, { mode: 0o600 });
|
|
41
|
-
const metadata = {
|
|
42
|
-
id, sessionId: sid, name: item.name, mediaType: item.mediaType, size: buffer.length,
|
|
43
|
-
width: item.width, height: item.height, createdAt: new Date().toISOString(), file: path.basename(file),
|
|
44
|
-
};
|
|
45
|
-
fs.writeFileSync(metaFile, `${JSON.stringify(metadata, null, 2)}\n`, { encoding: 'utf8', mode: 0o600 });
|
|
46
|
-
return metadata;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
read(sessionId, attachmentId) {
|
|
50
|
-
const sid = cleanId(sessionId, 'sessionId');
|
|
51
|
-
const id = cleanId(attachmentId, 'attachmentId');
|
|
52
|
-
const directory = path.join(this.root, hash(sid));
|
|
53
|
-
const metaFile = path.join(directory, `${hash(id)}.json`);
|
|
54
|
-
if (!fs.existsSync(metaFile)) return null;
|
|
55
|
-
const metadata = JSON.parse(fs.readFileSync(metaFile, 'utf8'));
|
|
56
|
-
if (metadata.id !== id || metadata.sessionId !== sid) return null;
|
|
57
|
-
const file = path.resolve(directory, metadata.file);
|
|
58
|
-
if (!file.startsWith(`${directory}${path.sep}`) || !fs.existsSync(file)) return null;
|
|
59
|
-
return { metadata, data: fs.readFileSync(file) };
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function hash(value) { return crypto.createHash('sha256').update(String(value)).digest('hex'); }
|
|
64
|
-
|
|
65
|
-
function verifyImage(buffer, mediaType) {
|
|
66
|
-
const valid = mediaType === 'image/png'
|
|
67
|
-
? buffer.length >= 8 && buffer.subarray(0, 8).equals(Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]))
|
|
68
|
-
: mediaType === 'image/jpeg'
|
|
69
|
-
? buffer.length >= 3 && buffer[0] === 0xff && buffer[1] === 0xd8 && buffer[2] === 0xff
|
|
70
|
-
: mediaType === 'image/gif'
|
|
71
|
-
? buffer.length >= 6 && ['GIF87a', 'GIF89a'].includes(buffer.subarray(0, 6).toString('ascii'))
|
|
72
|
-
: mediaType === 'image/webp'
|
|
73
|
-
? buffer.length >= 12 && buffer.subarray(0, 4).toString('ascii') === 'RIFF' && buffer.subarray(8, 12).toString('ascii') === 'WEBP'
|
|
74
|
-
: false;
|
|
75
|
-
if (!valid) throw Object.assign(new Error(`attachment content does not match ${mediaType}`), { status: 415 });
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
module.exports = { AttachmentStore, verifyImage };
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const crypto = require('crypto');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const { cleanId, normalizeAttachments, IMAGE_MEDIA_TYPES } = require('../../contracts');
|
|
7
|
+
|
|
8
|
+
const EXTENSIONS = {
|
|
9
|
+
'image/jpeg': '.jpg', 'image/png': '.png', 'image/gif': '.gif', 'image/webp': '.webp',
|
|
10
|
+
'text/plain': '.txt', 'text/markdown': '.md', 'application/json': '.json.txt', 'text/csv': '.csv',
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
class AttachmentStore {
|
|
14
|
+
constructor(options = {}) {
|
|
15
|
+
if (!options.root) throw new Error('AttachmentStore root is required');
|
|
16
|
+
this.root = path.resolve(options.root);
|
|
17
|
+
fs.mkdirSync(this.root, { recursive: true });
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
saveMany(sessionId, input) {
|
|
21
|
+
const id = cleanId(sessionId, 'sessionId');
|
|
22
|
+
const items = normalizeAttachments(input);
|
|
23
|
+
for (const item of items) if (IMAGE_MEDIA_TYPES.includes(item.mediaType)) verifyImage(Buffer.from(item.data, 'base64'), item.mediaType);
|
|
24
|
+
return items.map(item => this.save(id, item));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
save(sessionId, input) {
|
|
28
|
+
const sid = cleanId(sessionId, 'sessionId');
|
|
29
|
+
const item = normalizeAttachments([input])[0];
|
|
30
|
+
const isImage = IMAGE_MEDIA_TYPES.includes(item.mediaType);
|
|
31
|
+
const id = item.id || `${isImage ? 'img' : 'file'}-${crypto.randomUUID()}`;
|
|
32
|
+
const buffer = Buffer.from(item.data, 'base64');
|
|
33
|
+
if (isImage) verifyImage(buffer, item.mediaType);
|
|
34
|
+
const directory = path.join(this.root, hash(sid));
|
|
35
|
+
const stem = hash(id);
|
|
36
|
+
const extension = EXTENSIONS[item.mediaType];
|
|
37
|
+
fs.mkdirSync(directory, { recursive: true });
|
|
38
|
+
const file = path.join(directory, `${stem}${extension}`);
|
|
39
|
+
const metaFile = path.join(directory, `${stem}.json`);
|
|
40
|
+
fs.writeFileSync(file, buffer, { mode: 0o600 });
|
|
41
|
+
const metadata = {
|
|
42
|
+
id, sessionId: sid, name: item.name, mediaType: item.mediaType, size: buffer.length,
|
|
43
|
+
width: item.width, height: item.height, createdAt: new Date().toISOString(), file: path.basename(file),
|
|
44
|
+
};
|
|
45
|
+
fs.writeFileSync(metaFile, `${JSON.stringify(metadata, null, 2)}\n`, { encoding: 'utf8', mode: 0o600 });
|
|
46
|
+
return metadata;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
read(sessionId, attachmentId) {
|
|
50
|
+
const sid = cleanId(sessionId, 'sessionId');
|
|
51
|
+
const id = cleanId(attachmentId, 'attachmentId');
|
|
52
|
+
const directory = path.join(this.root, hash(sid));
|
|
53
|
+
const metaFile = path.join(directory, `${hash(id)}.json`);
|
|
54
|
+
if (!fs.existsSync(metaFile)) return null;
|
|
55
|
+
const metadata = JSON.parse(fs.readFileSync(metaFile, 'utf8'));
|
|
56
|
+
if (metadata.id !== id || metadata.sessionId !== sid) return null;
|
|
57
|
+
const file = path.resolve(directory, metadata.file);
|
|
58
|
+
if (!file.startsWith(`${directory}${path.sep}`) || !fs.existsSync(file)) return null;
|
|
59
|
+
return { metadata, data: fs.readFileSync(file) };
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function hash(value) { return crypto.createHash('sha256').update(String(value)).digest('hex'); }
|
|
64
|
+
|
|
65
|
+
function verifyImage(buffer, mediaType) {
|
|
66
|
+
const valid = mediaType === 'image/png'
|
|
67
|
+
? buffer.length >= 8 && buffer.subarray(0, 8).equals(Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]))
|
|
68
|
+
: mediaType === 'image/jpeg'
|
|
69
|
+
? buffer.length >= 3 && buffer[0] === 0xff && buffer[1] === 0xd8 && buffer[2] === 0xff
|
|
70
|
+
: mediaType === 'image/gif'
|
|
71
|
+
? buffer.length >= 6 && ['GIF87a', 'GIF89a'].includes(buffer.subarray(0, 6).toString('ascii'))
|
|
72
|
+
: mediaType === 'image/webp'
|
|
73
|
+
? buffer.length >= 12 && buffer.subarray(0, 4).toString('ascii') === 'RIFF' && buffer.subarray(8, 12).toString('ascii') === 'WEBP'
|
|
74
|
+
: false;
|
|
75
|
+
if (!valid) throw Object.assign(new Error(`attachment content does not match ${mediaType}`), { status: 415 });
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
module.exports = { AttachmentStore, verifyImage };
|