kumo-cli 1.0.5 → 1.1.0

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 (197) hide show
  1. package/README.md +131 -127
  2. package/dist/auth/credentialsStore.js +1 -1
  3. package/dist/auth/credentialsStore.js.map +1 -1
  4. package/dist/claude/transcriptParser.js +110 -11
  5. package/dist/claude/transcriptParser.js.map +1 -1
  6. package/dist/core/config.js +1 -4
  7. package/dist/core/config.js.map +1 -1
  8. package/dist/core/logger.js +6 -18
  9. package/dist/core/logger.js.map +1 -1
  10. package/dist/engine/claudeArgs.js +102 -0
  11. package/dist/engine/claudeArgs.js.map +1 -0
  12. package/dist/engine/claudeBinary.js +85 -0
  13. package/dist/engine/claudeBinary.js.map +1 -0
  14. package/dist/engine/claudeConfig.js +113 -0
  15. package/dist/engine/claudeConfig.js.map +1 -0
  16. package/dist/engine/controlChannel.js +63 -0
  17. package/dist/engine/controlChannel.js.map +1 -0
  18. package/dist/engine/liveTranscript.js +101 -0
  19. package/dist/engine/liveTranscript.js.map +1 -0
  20. package/dist/engine/ndjson.js +43 -0
  21. package/dist/engine/ndjson.js.map +1 -0
  22. package/dist/engine/permissions.js +98 -0
  23. package/dist/engine/permissions.js.map +1 -0
  24. package/dist/engine/sessionManager.js +429 -0
  25. package/dist/engine/sessionManager.js.map +1 -0
  26. package/dist/engine/settingsCommands.js +204 -0
  27. package/dist/engine/settingsCommands.js.map +1 -0
  28. package/dist/engine/streamSession.js +509 -0
  29. package/dist/engine/streamSession.js.map +1 -0
  30. package/dist/engine/taskTracker.js +110 -0
  31. package/dist/engine/taskTracker.js.map +1 -0
  32. package/dist/handlers/promptImages.js +8 -39
  33. package/dist/handlers/promptImages.js.map +1 -1
  34. package/dist/handlers/runtimeHandlers.js +195 -27
  35. package/dist/handlers/runtimeHandlers.js.map +1 -1
  36. package/dist/handlers/sessionHandlers.js +41 -70
  37. package/dist/handlers/sessionHandlers.js.map +1 -1
  38. package/dist/index.js +35 -40
  39. package/dist/index.js.map +1 -1
  40. package/dist/services/cliRuntime.js +37 -30
  41. package/dist/services/cliRuntime.js.map +1 -1
  42. package/dist/services/effortService.js +13 -60
  43. package/dist/services/effortService.js.map +1 -1
  44. package/dist/services/forkService.js +120 -0
  45. package/dist/services/forkService.js.map +1 -0
  46. package/dist/services/modelService.js +37 -84
  47. package/dist/services/modelService.js.map +1 -1
  48. package/dist/services/sessionListService.js +7 -9
  49. package/dist/services/sessionListService.js.map +1 -1
  50. package/dist/services/sessionService.js +77 -57
  51. package/dist/services/sessionService.js.map +1 -1
  52. package/dist/services/tunnelService.js +4 -5
  53. package/dist/services/tunnelService.js.map +1 -1
  54. package/dist/transport/wsClient.js +0 -4
  55. package/dist/transport/wsClient.js.map +1 -1
  56. package/dist/utils/ignorePaths.js +3 -3
  57. package/dist/utils/ignorePaths.js.map +1 -1
  58. package/package.json +62 -69
  59. package/dist/ansiCodes.js +0 -107
  60. package/dist/ansiCodes.js.map +0 -1
  61. package/dist/auth/credentialsStore.test.js +0 -60
  62. package/dist/auth/credentialsStore.test.js.map +0 -1
  63. package/dist/claude/fileHistory.js +0 -79
  64. package/dist/claude/fileHistory.js.map +0 -1
  65. package/dist/claude/generateHookSettings.js +0 -23
  66. package/dist/claude/generateHookSettings.js.map +0 -1
  67. package/dist/claude/hookServer.js +0 -33
  68. package/dist/claude/hookServer.js.map +0 -1
  69. package/dist/claude/sessionScanner.js +0 -162
  70. package/dist/claude/sessionScanner.js.map +0 -1
  71. package/dist/claude/sessionScanner.test.js +0 -24
  72. package/dist/claude/sessionScanner.test.js.map +0 -1
  73. package/dist/claude/transcriptParser.test.js +0 -78
  74. package/dist/claude/transcriptParser.test.js.map +0 -1
  75. package/dist/commands/cliArgs.test.js +0 -25
  76. package/dist/commands/cliArgs.test.js.map +0 -1
  77. package/dist/config.js +0 -40
  78. package/dist/config.js.map +0 -1
  79. package/dist/credentialsStore.js +0 -57
  80. package/dist/credentialsStore.js.map +0 -1
  81. package/dist/generateHookSettings.js +0 -30
  82. package/dist/generateHookSettings.js.map +0 -1
  83. package/dist/handlers/fileHandlerPayloads.test.js +0 -55
  84. package/dist/handlers/fileHandlerPayloads.test.js.map +0 -1
  85. package/dist/handlers/promptImages.test.js +0 -52
  86. package/dist/handlers/promptImages.test.js.map +0 -1
  87. package/dist/hookServer.js +0 -32
  88. package/dist/hookServer.js.map +0 -1
  89. package/dist/ignorePaths.js +0 -68
  90. package/dist/ignorePaths.js.map +0 -1
  91. package/dist/loadDotEnv.js +0 -79
  92. package/dist/loadDotEnv.js.map +0 -1
  93. package/dist/logger.js +0 -29
  94. package/dist/logger.js.map +0 -1
  95. package/dist/portForwardManager.js +0 -97
  96. package/dist/portForwardManager.js.map +0 -1
  97. package/dist/projectHistoryReader.js +0 -85
  98. package/dist/projectHistoryReader.js.map +0 -1
  99. package/dist/pty/ansiCodes.js +0 -14
  100. package/dist/pty/ansiCodes.js.map +0 -1
  101. package/dist/pty/notificationDetector.js +0 -29
  102. package/dist/pty/notificationDetector.js.map +0 -1
  103. package/dist/pty/notificationDetector.test.js +0 -24
  104. package/dist/pty/notificationDetector.test.js.map +0 -1
  105. package/dist/pty/ptyMenuParser.js +0 -91
  106. package/dist/pty/ptyMenuParser.js.map +0 -1
  107. package/dist/pty/ptyMenuParser.test.js +0 -26
  108. package/dist/pty/ptyMenuParser.test.js.map +0 -1
  109. package/dist/pty/ptySnapshotRenderer.js +0 -71
  110. package/dist/pty/ptySnapshotRenderer.js.map +0 -1
  111. package/dist/pty/selectionMenuDetector.js +0 -49
  112. package/dist/pty/selectionMenuDetector.js.map +0 -1
  113. package/dist/pty/selectionMenuDetector.test.js +0 -62
  114. package/dist/pty/selectionMenuDetector.test.js.map +0 -1
  115. package/dist/pty/selectionMenuMeta.js +0 -54
  116. package/dist/pty/selectionMenuMeta.js.map +0 -1
  117. package/dist/pty/selectionMenuMeta.test.js +0 -26
  118. package/dist/pty/selectionMenuMeta.test.js.map +0 -1
  119. package/dist/pty/selectionMenuParser.js +0 -83
  120. package/dist/pty/selectionMenuParser.js.map +0 -1
  121. package/dist/pty/selectionMenuParser.test.js +0 -30
  122. package/dist/pty/selectionMenuParser.test.js.map +0 -1
  123. package/dist/pty/spawn.js +0 -103
  124. package/dist/pty/spawn.js.map +0 -1
  125. package/dist/pty/spawn.test.js +0 -16
  126. package/dist/pty/spawn.test.js.map +0 -1
  127. package/dist/pty/statusSessionDetector.js +0 -28
  128. package/dist/pty/statusSessionDetector.js.map +0 -1
  129. package/dist/pty/statusSessionDetector.test.js +0 -23
  130. package/dist/pty/statusSessionDetector.test.js.map +0 -1
  131. package/dist/pty/textInputDetector.js +0 -60
  132. package/dist/pty/textInputDetector.js.map +0 -1
  133. package/dist/pty/textInputDetector.test.js +0 -32
  134. package/dist/pty/textInputDetector.test.js.map +0 -1
  135. package/dist/ptyMenuParser.js +0 -470
  136. package/dist/ptyMenuParser.js.map +0 -1
  137. package/dist/ptySnapshotRenderer.js +0 -78
  138. package/dist/ptySnapshotRenderer.js.map +0 -1
  139. package/dist/services/checkpointService.js +0 -113
  140. package/dist/services/checkpointService.js.map +0 -1
  141. package/dist/services/checkpointService.test.js +0 -61
  142. package/dist/services/checkpointService.test.js.map +0 -1
  143. package/dist/services/claudeMenuBridge.js +0 -116
  144. package/dist/services/claudeMenuBridge.js.map +0 -1
  145. package/dist/services/claudeMenuBridge.test.js +0 -90
  146. package/dist/services/claudeMenuBridge.test.js.map +0 -1
  147. package/dist/services/claudeService.js +0 -146
  148. package/dist/services/claudeService.js.map +0 -1
  149. package/dist/services/claudeService.test.js +0 -39
  150. package/dist/services/claudeService.test.js.map +0 -1
  151. package/dist/services/cliRuntime.test.js +0 -55
  152. package/dist/services/cliRuntime.test.js.map +0 -1
  153. package/dist/services/modelAdapter.test.js +0 -47
  154. package/dist/services/modelAdapter.test.js.map +0 -1
  155. package/dist/services/modelArgs.test.js +0 -64
  156. package/dist/services/modelArgs.test.js.map +0 -1
  157. package/dist/services/modelBaseUrl.test.js +0 -32
  158. package/dist/services/modelBaseUrl.test.js.map +0 -1
  159. package/dist/services/modelService.test.js +0 -136
  160. package/dist/services/modelService.test.js.map +0 -1
  161. package/dist/services/notificationDedupe.js +0 -23
  162. package/dist/services/notificationDedupe.js.map +0 -1
  163. package/dist/services/notificationDedupe.test.js +0 -20
  164. package/dist/services/notificationDedupe.test.js.map +0 -1
  165. package/dist/services/sessionListService.test.js +0 -22
  166. package/dist/services/sessionListService.test.js.map +0 -1
  167. package/dist/services/sessionRollbackService.js +0 -195
  168. package/dist/services/sessionRollbackService.js.map +0 -1
  169. package/dist/services/sessionRollbackService.test.js +0 -142
  170. package/dist/services/sessionRollbackService.test.js.map +0 -1
  171. package/dist/services/tunnelHelpers.test.js +0 -42
  172. package/dist/services/tunnelHelpers.test.js.map +0 -1
  173. package/dist/services/tunnelService.test.js +0 -91
  174. package/dist/services/tunnelService.test.js.map +0 -1
  175. package/dist/sessionScanner.js +0 -271
  176. package/dist/sessionScanner.js.map +0 -1
  177. package/dist/snapshotScanner.js +0 -154
  178. package/dist/snapshotScanner.js.map +0 -1
  179. package/dist/spawn.js +0 -79
  180. package/dist/spawn.js.map +0 -1
  181. package/dist/terminalManager.js +0 -73
  182. package/dist/terminalManager.js.map +0 -1
  183. package/dist/transport/directWsServer.js +0 -135
  184. package/dist/transport/directWsServer.js.map +0 -1
  185. package/dist/transport/webrtcTransport.js +0 -145
  186. package/dist/transport/webrtcTransport.js.map +0 -1
  187. package/dist/transport/webrtcTransport.test.js +0 -104
  188. package/dist/transport/webrtcTransport.test.js.map +0 -1
  189. package/dist/transport/webrtcTypes.js +0 -29
  190. package/dist/transport/webrtcTypes.js.map +0 -1
  191. package/dist/transport/webrtcTypes.test.js +0 -20
  192. package/dist/transport/webrtcTypes.test.js.map +0 -1
  193. package/dist/utils/ptyBuffer.js +0 -46
  194. package/dist/utils/ptyBuffer.js.map +0 -1
  195. package/scripts/claude_launcher.cjs +0 -71
  196. package/scripts/run-tests.mjs +0 -46
  197. package/scripts/session_hook_forwarder.cjs +0 -44
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claudeArgs.js","sourceRoot":"","sources":["../../src/engine/claudeArgs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ import { execSync } from 'node:child_process';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { log } from '../core/logger.js';
5
+ const CLAUDE_PACKAGE = '@anthropic-ai/claude-code';
6
+ const NATIVE_EXE = ['node_modules', '@anthropic-ai', 'claude-code', 'bin', 'claude.exe'];
7
+ let cached = null;
8
+ function lookup(command) {
9
+ try {
10
+ return execSync(command, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] })
11
+ .split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
12
+ }
13
+ catch {
14
+ return [];
15
+ }
16
+ }
17
+ // prefer the native claude.exe shipped inside the npm package next to a claude.cmd shim
18
+ function nativeExeFor(shimPath) {
19
+ const candidate = path.join(path.dirname(shimPath), ...NATIVE_EXE);
20
+ return fs.existsSync(candidate) ? candidate : null;
21
+ }
22
+ function findOnWindows() {
23
+ const appData = process.env['APPDATA'] ?? '';
24
+ if (appData) {
25
+ const exe = path.join(appData, 'npm', ...NATIVE_EXE);
26
+ if (fs.existsSync(exe))
27
+ return { cmd: exe, shell: false };
28
+ }
29
+ const found = lookup('where claude');
30
+ const exe = found.find((p) => /\.exe$/i.test(p));
31
+ if (exe)
32
+ return { cmd: exe, shell: false };
33
+ const shim = found.find((p) => /\.cmd$/i.test(p)) ?? (appData && fs.existsSync(path.join(appData, 'npm', 'claude.cmd')) ? path.join(appData, 'npm', 'claude.cmd') : undefined);
34
+ if (!shim)
35
+ return null;
36
+ const native = nativeExeFor(shim);
37
+ return native ? { cmd: native, shell: false } : { cmd: shim, shell: true };
38
+ }
39
+ function findOnPosix() {
40
+ const found = lookup('which claude')[0];
41
+ return found ? { cmd: found, shell: false } : null;
42
+ }
43
+ function find() {
44
+ return process.platform === 'win32' ? findOnWindows() : findOnPosix();
45
+ }
46
+ // install the claude cli globally when it is missing from the host machine
47
+ function installClaudeCli() {
48
+ console.log(`[kumo-cli] claude cli not found, installing ${CLAUDE_PACKAGE}...`);
49
+ execSync(`npm install -g --allow-scripts=${CLAUDE_PACKAGE} ${CLAUDE_PACKAGE}`, { stdio: 'inherit' });
50
+ }
51
+ // resolve the claude executable on first use (never at import); KUMO_CLAUDE_BIN overrides discovery
52
+ export function resolveClaudeCommand() {
53
+ if (cached)
54
+ return cached;
55
+ const override = process.env['KUMO_CLAUDE_BIN'];
56
+ if (override) {
57
+ cached = { cmd: override, shell: process.platform === 'win32' && /\.(cmd|bat)$/i.test(override) };
58
+ }
59
+ else {
60
+ let found = find();
61
+ if (!found) {
62
+ try {
63
+ installClaudeCli();
64
+ }
65
+ catch (error) {
66
+ log(`[claude-bin] install failed: ${error}`);
67
+ }
68
+ found = find();
69
+ }
70
+ cached = found ?? { cmd: 'claude', shell: process.platform === 'win32' };
71
+ }
72
+ log(`[claude-bin] using ${cached.cmd} (shell=${cached.shell})`);
73
+ return cached;
74
+ }
75
+ // quote one argument for a cmd.exe command line
76
+ export function quoteWindowsArg(arg) {
77
+ if (arg && !/[\s"&|<>^%()!,;=]/.test(arg))
78
+ return arg;
79
+ return `"${arg.replace(/(\\*)"/g, '$1$1\\"').replace(/(\\+)$/, '$1$1')}"`;
80
+ }
81
+ // build a single shell command line so node never joins unquoted args (avoids DEP0190)
82
+ export function buildShellCommandLine(cmd, args) {
83
+ return [cmd, ...args].map(quoteWindowsArg).join(' ');
84
+ }
85
+ //# sourceMappingURL=claudeBinary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claudeBinary.js","sourceRoot":"","sources":["../../src/engine/claudeBinary.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,113 @@
1
+ const obj = (value) => (value && typeof value === 'object' && !Array.isArray(value) ? value : {});
2
+ const list = (value) => (Array.isArray(value) ? value.map(obj) : []);
3
+ const pick = (source, keys) => Object.fromEntries(keys.filter((key) => source[key] !== undefined && source[key] !== null).map((key) => [key, source[key]]));
4
+ const MODEL_KEYS = ['value', 'resolvedModel', 'displayName', 'description', 'supportsEffort', 'supportedEffortLevels', 'supportsAdaptiveThinking', 'supportsFastMode', 'supportsAutoMode'];
5
+ const COMMAND_KEYS = ['name', 'description', 'argumentHint'];
6
+ export function commandsOf(value) {
7
+ return list(value).map((command) => pick(command, COMMAND_KEYS));
8
+ }
9
+ // app-facing claude_config payload from an initialize response
10
+ export function toClaudeConfig(init) {
11
+ return {
12
+ models: list(init['models']).map((model) => pick(model, MODEL_KEYS)),
13
+ commands: commandsOf(init['commands']),
14
+ account: pick(obj(init['account']), ['email', 'organization', 'subscriptionType', 'apiProvider']),
15
+ outputStyle: init['output_style'] ?? null,
16
+ availableOutputStyles: Array.isArray(init['available_output_styles']) ? init['available_output_styles'] : [],
17
+ version: init['claude_code_version'] ?? null,
18
+ fastModeState: init['fast_mode_state'] ?? null,
19
+ };
20
+ }
21
+ // control requests the app may run through claude_control
22
+ export const CONTROL_WHITELIST = new Set([
23
+ 'get_status', 'get_usage', 'get_context_usage', 'get_settings', 'export_conversation', 'side_question',
24
+ 'mcp_status', 'mcp_toggle', 'mcp_reconnect', 'list_permission_rules', 'update_settings', 'rewind_files',
25
+ 'stop_task', 'cancel_async_message',
26
+ 'get_hooks_listing', 'get_sandbox_dialog', 'get_skills_dialog', 'get_memory_dialog', 'reload_plugins', 'reload_skills',
27
+ ]);
28
+ const NOT_RUNNING = 'This session is no longer running.';
29
+ // requests about the running process itself, with the reason a stopped session can't answer;
30
+ // file checkpoints live in the process that ran the turns, a resumed one has none
31
+ export const LIVE_ONLY_CONTROLS = new Map([
32
+ ['rewind_files', "Code checkpoints only last while this session's Claude process runs, and it has stopped. You can still fork the conversation."],
33
+ ['stop_task', NOT_RUNNING],
34
+ ['cancel_async_message', NOT_RUNNING],
35
+ ]);
36
+ // requests answered from the target session's own context
37
+ export const SESSION_SCOPED_CONTROLS = new Set(['get_context_usage', 'export_conversation', 'side_question', 'mcp_toggle', 'mcp_reconnect']);
38
+ // side questions run a model call (5 min like the extension), the rest are quick reads
39
+ export const controlTimeoutMs = (subtype) => (subtype === 'side_question' ? 300_000 : undefined);
40
+ const text = (source, key, max = 4000) => {
41
+ const value = typeof source[key] === 'string' ? source[key].trim().slice(0, max) : '';
42
+ if (!value)
43
+ throw new Error(`${key} is required`);
44
+ return value;
45
+ };
46
+ // the only payload fields forwarded to claude per request
47
+ export function controlPayload(subtype, payload) {
48
+ const source = obj(payload);
49
+ switch (subtype) {
50
+ case 'side_question':
51
+ return { question: text(source, 'question') };
52
+ case 'mcp_reconnect':
53
+ return { serverName: text(source, 'serverName', 200) };
54
+ case 'mcp_toggle':
55
+ if (typeof source['enabled'] !== 'boolean')
56
+ throw new Error('enabled is required');
57
+ return { serverName: text(source, 'serverName', 200), enabled: source['enabled'] };
58
+ case 'stop_task':
59
+ return { task_id: text(source, 'taskId', 100) };
60
+ case 'cancel_async_message':
61
+ return { message_uuid: text(source, 'uuid', 100) };
62
+ case 'rewind_files':
63
+ return { user_message_id: text(source, 'userMessageId', 100), dry_run: source['dryRun'] === true };
64
+ case 'update_settings':
65
+ // only the output style may be changed from the app, and only for this project
66
+ return { source: 'localSettings', settings: { outputStyle: text(source, 'outputStyle', 200) } };
67
+ default:
68
+ return {};
69
+ }
70
+ }
71
+ // keep only what the app renders; get_settings.effective carries mcp env secrets and never leaves the machine
72
+ export function sanitizeControlResponse(subtype, response) {
73
+ switch (subtype) {
74
+ case 'get_settings': {
75
+ const outputStyle = obj(response['effective'])['outputStyle'];
76
+ return { applied: obj(response['applied']), outputStyle: typeof outputStyle === 'string' ? outputStyle : null };
77
+ }
78
+ case 'mcp_status':
79
+ // server configs carry urls, headers and env secrets
80
+ return {
81
+ mcpServers: list(response['mcpServers']).map((server) => ({
82
+ ...pick(server, ['name', 'status', 'scope', 'error']),
83
+ type: obj(server['config'])['type'] ?? null,
84
+ toolCount: Array.isArray(server['tools']) ? server['tools'].length : 0,
85
+ })),
86
+ };
87
+ case 'list_permission_rules':
88
+ return { rules: list(obj(response['state'])['rules']).map((rule) => pick(rule, ['rule', 'behavior', 'source'])) };
89
+ case 'get_context_usage': {
90
+ const { gridRows: _grid, ...rest } = response;
91
+ return rest;
92
+ }
93
+ case 'reload_plugins':
94
+ // the payload repeats every command, agent and mcp config; the app only needs the outcome
95
+ return {
96
+ plugins: list(response['plugins']).map((plugin) => pick(plugin, ['name', 'version', 'source'])),
97
+ error_count: response['error_count'] ?? 0,
98
+ };
99
+ case 'reload_skills':
100
+ return { count: list(response['skills']).length };
101
+ case 'get_usage': {
102
+ const limits = obj(response['rate_limits']);
103
+ return {
104
+ session: obj(response['session']),
105
+ subscription_type: response['subscription_type'] ?? null,
106
+ rate_limits: pick(limits, ['five_hour', 'seven_day', 'limits', 'model_scoped']),
107
+ };
108
+ }
109
+ default:
110
+ return response;
111
+ }
112
+ }
113
+ //# sourceMappingURL=claudeConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claudeConfig.js","sourceRoot":"","sources":["../../src/engine/claudeConfig.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ const CONTROL_TIMEOUT_MS = 30_000;
3
+ export const INITIALIZE_TIMEOUT_MS = 60_000;
4
+ // correlate host -> cli control requests with their responses by request_id
5
+ export class ControlChannel {
6
+ write;
7
+ pending = new Map();
8
+ constructor(write) {
9
+ this.write = write;
10
+ }
11
+ // send a control request and resolve with its success payload
12
+ request(request, timeoutMs = CONTROL_TIMEOUT_MS) {
13
+ const requestId = `kumo-${randomUUID()}`;
14
+ const promise = new Promise((resolve, reject) => {
15
+ const timer = setTimeout(() => {
16
+ this.cancel(requestId, `control request ${request.subtype} timed out after ${timeoutMs}ms`);
17
+ }, timeoutMs);
18
+ this.pending.set(requestId, { subtype: request.subtype, resolve, reject, timer });
19
+ });
20
+ this.write({ type: 'control_request', request_id: requestId, request });
21
+ return promise;
22
+ }
23
+ // settle the matching pending request; unknown ids (e.g. echoed host responses) are ignored
24
+ handleResponse(msg) {
25
+ const response = msg['response'];
26
+ const requestId = response?.['request_id'];
27
+ if (typeof requestId !== 'string')
28
+ return false;
29
+ const entry = this.pending.get(requestId);
30
+ if (!entry)
31
+ return false;
32
+ this.pending.delete(requestId);
33
+ clearTimeout(entry.timer);
34
+ if (response?.['subtype'] === 'success')
35
+ entry.resolve(response['response'] ?? {});
36
+ else
37
+ entry.reject(new Error(String(response?.['error'] ?? `control request ${entry.subtype} failed`)));
38
+ return true;
39
+ }
40
+ // drop a pending request locally and tell the cli to stop working on it
41
+ cancel(requestId, reason = 'cancelled') {
42
+ const entry = this.pending.get(requestId);
43
+ if (!entry)
44
+ return;
45
+ this.pending.delete(requestId);
46
+ clearTimeout(entry.timer);
47
+ try {
48
+ this.write({ type: 'control_cancel_request', request_id: requestId });
49
+ }
50
+ catch { }
51
+ entry.reject(new Error(reason));
52
+ }
53
+ // fail every pending request, used when the process exits
54
+ rejectAll(reason) {
55
+ for (const [requestId, entry] of this.pending) {
56
+ clearTimeout(entry.timer);
57
+ entry.reject(new Error(reason));
58
+ this.pending.delete(requestId);
59
+ }
60
+ }
61
+ get size() { return this.pending.size; }
62
+ }
63
+ //# sourceMappingURL=controlChannel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"controlChannel.js","sourceRoot":"","sources":["../../src/engine/controlChannel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,101 @@
1
+ import { parseTranscriptMessage, rememberToolResults, } from '../claude/transcriptParser.js';
2
+ // enough history to fold late tool results into their message without growing forever
3
+ const MAX_TRACKED = 300;
4
+ const str = (value) => (typeof value === 'string' ? value : '');
5
+ const blocksOf = (content) => Array.isArray(content) ? content.filter((b) => !!b && typeof b === 'object') : [];
6
+ // turns stream-json stdout frames into app transcript messages the way the extension renders a
7
+ // live turn: assistant blocks merged by message id (one frame per block), tool results folded
8
+ // into their tool use, prompts from the --replay-user-messages echo under the uuid we sent.
9
+ // every update re-emits the whole message under the same id, so the app replaces it
10
+ export class LiveTranscript {
11
+ sessionId;
12
+ emit;
13
+ assistants = new Map();
14
+ owners = new Map();
15
+ results = new Map();
16
+ constructor(sessionId, emit) {
17
+ this.sessionId = sessionId;
18
+ this.emit = emit;
19
+ }
20
+ handle(frame) {
21
+ if (frame['type'] === 'assistant')
22
+ this.assistant(frame);
23
+ else if (frame['type'] === 'user')
24
+ this.user(frame);
25
+ }
26
+ assistant(frame) {
27
+ const message = frame['message'];
28
+ const id = str(message?.['id']) || str(frame['uuid']);
29
+ if (!id)
30
+ return;
31
+ const entry = this.assistants.get(id) ?? { blocks: [], seen: new Set(), timestamp: new Date().toISOString() };
32
+ for (const block of blocksOf(message?.['content'])) {
33
+ const key = JSON.stringify(block);
34
+ if (entry.seen.has(key))
35
+ continue;
36
+ entry.seen.add(key);
37
+ entry.blocks.push(block);
38
+ if (block['type'] === 'tool_use' && typeof block['id'] === 'string')
39
+ this.owners.set(block['id'], id);
40
+ }
41
+ entry.stopReason = str(message?.['stop_reason']) || entry.stopReason;
42
+ entry.parentToolUseId = str(frame['parent_tool_use_id']) || entry.parentToolUseId;
43
+ this.track(id, entry);
44
+ this.publish(id);
45
+ }
46
+ user(frame) {
47
+ const parentToolUseId = str(frame['parent_tool_use_id']) || undefined;
48
+ const message = frame['message'];
49
+ const jsonl = {
50
+ type: 'user',
51
+ uuid: str(frame['uuid']) || undefined,
52
+ message,
53
+ toolUseResult: frame['tool_use_result'],
54
+ isSidechain: parentToolUseId !== undefined,
55
+ };
56
+ const toolResults = blocksOf(message?.content).filter((b) => b['type'] === 'tool_result');
57
+ if (toolResults.length > 0) {
58
+ rememberToolResults(jsonl, this.results);
59
+ const owners = new Set(toolResults.map((b) => this.owners.get(str(b['tool_use_id']))));
60
+ for (const owner of owners)
61
+ if (owner)
62
+ this.publish(owner);
63
+ return;
64
+ }
65
+ const parsed = parseTranscriptMessage(jsonl, { sessionId: this.sessionId, timestamp: new Date().toISOString() });
66
+ if (parsed)
67
+ this.emit(parentToolUseId ? { ...parsed, parentToolUseId } : parsed);
68
+ }
69
+ publish(id) {
70
+ const entry = this.assistants.get(id);
71
+ if (!entry)
72
+ return;
73
+ const parsed = parseTranscriptMessage({
74
+ type: 'assistant',
75
+ uuid: id,
76
+ message: { role: 'assistant', content: entry.blocks, stop_reason: entry.stopReason },
77
+ isSidechain: entry.parentToolUseId !== undefined,
78
+ },
79
+ // no file-history reads mid-turn: the tool result brings the original file
80
+ { sessionId: this.sessionId, timestamp: entry.timestamp, toolResults: this.results, fileContentReader: () => null });
81
+ if (!parsed)
82
+ return;
83
+ this.emit(entry.parentToolUseId ? { ...parsed, parentToolUseId: entry.parentToolUseId } : parsed);
84
+ }
85
+ track(id, entry) {
86
+ this.assistants.delete(id);
87
+ this.assistants.set(id, entry);
88
+ while (this.assistants.size > MAX_TRACKED) {
89
+ const [oldest, old] = this.assistants.entries().next().value;
90
+ this.assistants.delete(oldest);
91
+ for (const block of old.blocks) {
92
+ const toolId = str(block['id']);
93
+ if (toolId && this.owners.get(toolId) === oldest) {
94
+ this.owners.delete(toolId);
95
+ this.results.delete(toolId);
96
+ }
97
+ }
98
+ }
99
+ }
100
+ }
101
+ //# sourceMappingURL=liveTranscript.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"liveTranscript.js","sourceRoot":"","sources":["../../src/engine/liveTranscript.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ import { log } from '../core/logger.js';
2
+ // read line-delimited json from a stream, tolerating partial chunks and skipping blank/non-json lines
3
+ export function readNdjson(stream, onMessage) {
4
+ let buffer = '';
5
+ const handleLine = (raw) => {
6
+ const line = raw.trim();
7
+ if (!line)
8
+ return;
9
+ let parsed;
10
+ try {
11
+ parsed = JSON.parse(line);
12
+ }
13
+ catch {
14
+ log(`[ndjson] skipped non-json line: ${line.slice(0, 200)}`);
15
+ return;
16
+ }
17
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed))
18
+ onMessage(parsed);
19
+ };
20
+ stream.setEncoding('utf8');
21
+ stream.on('data', (chunk) => {
22
+ buffer += chunk;
23
+ let index = buffer.indexOf('\n');
24
+ while (index >= 0) {
25
+ handleLine(buffer.slice(0, index));
26
+ buffer = buffer.slice(index + 1);
27
+ index = buffer.indexOf('\n');
28
+ }
29
+ });
30
+ stream.on('end', () => {
31
+ if (buffer)
32
+ handleLine(buffer);
33
+ buffer = '';
34
+ });
35
+ }
36
+ // write one json message followed by a newline; returns false when the stream is no longer writable
37
+ export function writeNdjson(stream, msg) {
38
+ if (stream.destroyed || stream.writableEnded)
39
+ return false;
40
+ stream.write(`${JSON.stringify(msg)}\n`);
41
+ return true;
42
+ }
43
+ //# sourceMappingURL=ndjson.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ndjson.js","sourceRoot":"","sources":["../../src/engine/ndjson.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAIxC,sGAAsG;AACtG,MAAM,UAAU,UAAU,CAAC,MAAgB,EAAE,SAAoC;IAC/E,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,MAAM,UAAU,GAAG,CAAC,GAAW,EAAQ,EAAE;QACvC,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;QACxB,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,IAAI,MAAe,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;QAAC,MAAM,CAAC;YACP,GAAG,CAAC,mCAAmC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;YAC7D,OAAO;QACT,CAAC;QACD,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,SAAS,CAAC,MAAoB,CAAC,CAAC;IACtG,CAAC,CAAC;IACF,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3B,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;QAClC,MAAM,IAAI,KAAK,CAAC;QAChB,IAAI,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACjC,OAAO,KAAK,IAAI,CAAC,EAAE,CAAC;YAClB,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;YACnC,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;YACjC,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC,CAAC,CAAC;IACH,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;QACpB,IAAI,MAAM;YAAE,UAAU,CAAC,MAAM,CAAC,CAAC;QAC/B,MAAM,GAAG,EAAE,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC;AAED,oGAAoG;AACpG,MAAM,UAAU,WAAW,CAAC,MAAgB,EAAE,GAAY;IACxD,IAAI,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,aAAa;QAAE,OAAO,KAAK,CAAC;IAC3D,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACzC,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,98 @@
1
+ const PERMISSION_MODES = new Set(['default', 'acceptEdits', 'plan', 'bypassPermissions', 'auto', 'dontAsk']);
2
+ const DESTINATIONS = new Set(['userSettings', 'projectSettings', 'localSettings', 'session', 'cliArg']);
3
+ // approving a plan with "manually approve edits" sends this update even though the cli never suggests it
4
+ const RESET_MODE_UPDATE = { type: 'setMode', mode: 'default', destination: 'session' };
5
+ export const DEFAULT_DENY_MESSAGE = "The user doesn't want to proceed with this tool use. The tool use was rejected (eg. if it was a file edit, the new_string was NOT written to the file). STOP what you are doing and wait for the user to tell you how to proceed.";
6
+ export function isPermissionMode(value) {
7
+ return typeof value === 'string' && PERMISSION_MODES.has(value);
8
+ }
9
+ const str = (value) => (typeof value === 'string' ? value : undefined);
10
+ const bool = (value) => (typeof value === 'boolean' ? value : undefined);
11
+ export const stripAnsi = (value) => value?.replace(/\x1b\[[0-9;]*[A-Za-z]/g, '');
12
+ function kindOf(toolName) {
13
+ if (toolName === 'AskUserQuestion')
14
+ return 'ask_user_question';
15
+ if (toolName === 'ExitPlanMode')
16
+ return 'exit_plan_mode';
17
+ return 'tool';
18
+ }
19
+ // map a cli can_use_tool request into the ws v2 claude_permission_request payload
20
+ export function toPermissionRequest(sessionId, requestId, request) {
21
+ const toolName = str(request['tool_name']) ?? 'unknown';
22
+ const input = request['input'] && typeof request['input'] === 'object' ? request['input'] : {};
23
+ const suggestions = Array.isArray(request['permission_suggestions'])
24
+ ? request['permission_suggestions'].filter((s) => !!s && typeof s === 'object')
25
+ : [];
26
+ return {
27
+ type: 'claude_permission_request',
28
+ sessionId,
29
+ requestId,
30
+ kind: kindOf(toolName),
31
+ toolName,
32
+ displayName: str(request['display_name']),
33
+ title: str(request['title']),
34
+ description: str(request['description']),
35
+ input,
36
+ toolUseId: str(request['tool_use_id']),
37
+ suggestions,
38
+ decisionReason: stripAnsi(str(request['decision_reason'])),
39
+ blockedPath: str(request['blocked_path']),
40
+ defaultToNo: bool(request['default_to_no']),
41
+ suppressAlwaysAllowRule: bool(request['suppress_always_allow_rule']),
42
+ requiresUserInteraction: bool(request['requires_user_interaction']),
43
+ agentId: str(request['agent_id']),
44
+ };
45
+ }
46
+ // json with sorted object keys so structurally equal updates compare equal
47
+ function canonical(value) {
48
+ return JSON.stringify(value, (_key, v) => (v && typeof v === 'object' && !Array.isArray(v)
49
+ ? Object.fromEntries(Object.entries(v).sort(([a], [b]) => (a < b ? -1 : 1)))
50
+ : v));
51
+ }
52
+ // keep only updates the prompt offered (rules may change destination); drop bypass unless allowed
53
+ export function filterPermissionUpdates(updates, suggestions, allowBypass) {
54
+ if (!Array.isArray(updates))
55
+ return [];
56
+ const resetMode = canonical(RESET_MODE_UPDATE);
57
+ return updates.filter((update) => {
58
+ if (!update || typeof update !== 'object')
59
+ return false;
60
+ const u = update;
61
+ if (u['type'] === 'setMode' && u['mode'] === 'bypassPermissions' && !allowBypass)
62
+ return false;
63
+ const key = canonical(u);
64
+ if (key === resetMode)
65
+ return true;
66
+ const destination = u['destination'];
67
+ return suggestions.some((s) => (s['type'] === 'setMode'
68
+ ? key === canonical(s)
69
+ : typeof destination === 'string' && DESTINATIONS.has(destination) && key === canonical({ ...s, destination })));
70
+ });
71
+ }
72
+ // build the PermissionResult written back to the cli for a can_use_tool request
73
+ export function buildPermissionResult(pending, decision, allowBypass) {
74
+ if (decision.behavior === 'allow') {
75
+ return {
76
+ behavior: 'allow',
77
+ updatedInput: decision.updatedInput ?? pending.input,
78
+ updatedPermissions: filterPermissionUpdates(decision.updatedPermissions, pending.suggestions, allowBypass),
79
+ };
80
+ }
81
+ const message = decision.message?.trim() ? decision.message : DEFAULT_DENY_MESSAGE;
82
+ return { behavior: 'deny', message, interrupt: decision.interrupt ?? !decision.message?.trim() };
83
+ }
84
+ // validate a claude_permission_response payload coming from the app
85
+ export function parsePermissionDecision(msg) {
86
+ const behavior = msg['behavior'];
87
+ if (behavior !== 'allow' && behavior !== 'deny')
88
+ return null;
89
+ const updatedInput = msg['updatedInput'];
90
+ return {
91
+ behavior,
92
+ updatedInput: updatedInput && typeof updatedInput === 'object' && !Array.isArray(updatedInput) ? updatedInput : undefined,
93
+ updatedPermissions: msg['updatedPermissions'],
94
+ message: str(msg['message']),
95
+ interrupt: bool(msg['interrupt']),
96
+ };
97
+ }
98
+ //# sourceMappingURL=permissions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../src/engine/permissions.ts"],"names":[],"mappings":"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"}