kumo-cli 1.0.6 → 1.2.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 (241) hide show
  1. package/README.md +26 -13
  2. package/dist/auth/credentialsStore.js +20 -7
  3. package/dist/auth/credentialsStore.js.map +1 -1
  4. package/dist/claude/conversation.js +272 -0
  5. package/dist/claude/conversation.js.map +1 -0
  6. package/dist/claude/transcriptParser.js +140 -36
  7. package/dist/claude/transcriptParser.js.map +1 -1
  8. package/dist/commands/cliArgs.js +1 -0
  9. package/dist/commands/cliArgs.js.map +1 -1
  10. package/dist/core/config.js +1 -9
  11. package/dist/core/config.js.map +1 -1
  12. package/dist/core/logger.js +50 -21
  13. package/dist/core/logger.js.map +1 -1
  14. package/dist/core/projectFileWatcher.js +100 -36
  15. package/dist/core/projectFileWatcher.js.map +1 -1
  16. package/dist/engine/claudeArgs.js +106 -0
  17. package/dist/engine/claudeArgs.js.map +1 -0
  18. package/dist/engine/claudeBinary.js +94 -0
  19. package/dist/engine/claudeBinary.js.map +1 -0
  20. package/dist/engine/claudeConfig.js +127 -0
  21. package/dist/engine/claudeConfig.js.map +1 -0
  22. package/dist/engine/claudeLogin.js +76 -0
  23. package/dist/engine/claudeLogin.js.map +1 -0
  24. package/dist/engine/controlChannel.js +75 -0
  25. package/dist/engine/controlChannel.js.map +1 -0
  26. package/dist/engine/liveTranscript.js +150 -0
  27. package/dist/engine/liveTranscript.js.map +1 -0
  28. package/dist/engine/ndjson.js +48 -0
  29. package/dist/engine/ndjson.js.map +1 -0
  30. package/dist/engine/permissions.js +101 -0
  31. package/dist/engine/permissions.js.map +1 -0
  32. package/dist/engine/probePool.js +51 -0
  33. package/dist/engine/probePool.js.map +1 -0
  34. package/dist/engine/processTree.js +45 -0
  35. package/dist/engine/processTree.js.map +1 -0
  36. package/dist/engine/remoteConfig.js +17 -0
  37. package/dist/engine/remoteConfig.js.map +1 -0
  38. package/dist/engine/sessionManager.js +444 -0
  39. package/dist/engine/sessionManager.js.map +1 -0
  40. package/dist/engine/settingsCommands.js +260 -0
  41. package/dist/engine/settingsCommands.js.map +1 -0
  42. package/dist/engine/streamSession.js +502 -0
  43. package/dist/engine/streamSession.js.map +1 -0
  44. package/dist/engine/taskTracker.js +110 -0
  45. package/dist/engine/taskTracker.js.map +1 -0
  46. package/dist/engine/toolLabels.js +32 -0
  47. package/dist/engine/toolLabels.js.map +1 -0
  48. package/dist/handlers/controlRequest.js +17 -0
  49. package/dist/handlers/controlRequest.js.map +1 -0
  50. package/dist/handlers/fileHandlers.js +12 -0
  51. package/dist/handlers/fileHandlers.js.map +1 -1
  52. package/dist/handlers/messageRouter.js +8 -1
  53. package/dist/handlers/messageRouter.js.map +1 -1
  54. package/dist/handlers/promptImages.js +5 -91
  55. package/dist/handlers/promptImages.js.map +1 -1
  56. package/dist/handlers/runtimeHandlers.js +100 -32
  57. package/dist/handlers/runtimeHandlers.js.map +1 -1
  58. package/dist/handlers/sessionHandlers.js +85 -80
  59. package/dist/handlers/sessionHandlers.js.map +1 -1
  60. package/dist/handlers/terminalHandlers.js +9 -2
  61. package/dist/handlers/terminalHandlers.js.map +1 -1
  62. package/dist/http/httpClient.js +6 -0
  63. package/dist/http/httpClient.js.map +1 -1
  64. package/dist/index.js +87 -50
  65. package/dist/index.js.map +1 -1
  66. package/dist/pty/terminalManager.js +58 -11
  67. package/dist/pty/terminalManager.js.map +1 -1
  68. package/dist/services/bootstrapService.js +17 -1
  69. package/dist/services/bootstrapService.js.map +1 -1
  70. package/dist/services/claudeAdapterProxy.js +68 -21
  71. package/dist/services/claudeAdapterProxy.js.map +1 -1
  72. package/dist/services/cliRuntime.js +39 -32
  73. package/dist/services/cliRuntime.js.map +1 -1
  74. package/dist/services/effortService.js +13 -60
  75. package/dist/services/effortService.js.map +1 -1
  76. package/dist/services/fileService.js +50 -24
  77. package/dist/services/fileService.js.map +1 -1
  78. package/dist/services/forkService.js +120 -0
  79. package/dist/services/forkService.js.map +1 -0
  80. package/dist/services/modelService.js +86 -89
  81. package/dist/services/modelService.js.map +1 -1
  82. package/dist/services/pairingService.js +21 -15
  83. package/dist/services/pairingService.js.map +1 -1
  84. package/dist/services/sessionListService.js +7 -9
  85. package/dist/services/sessionListService.js.map +1 -1
  86. package/dist/services/sessionService.js +245 -106
  87. package/dist/services/sessionService.js.map +1 -1
  88. package/dist/services/tunnelHelpers.js +9 -5
  89. package/dist/services/tunnelHelpers.js.map +1 -1
  90. package/dist/services/tunnelService.js +21 -5
  91. package/dist/services/tunnelService.js.map +1 -1
  92. package/dist/transport/wsClient.js +60 -42
  93. package/dist/transport/wsClient.js.map +1 -1
  94. package/dist/utils/ignorePaths.js +3 -3
  95. package/dist/utils/ignorePaths.js.map +1 -1
  96. package/dist/utils/json.js +7 -0
  97. package/dist/utils/json.js.map +1 -0
  98. package/dist/utils/localHost.js +17 -0
  99. package/dist/utils/localHost.js.map +1 -0
  100. package/dist/utils/safePath.js +51 -20
  101. package/dist/utils/safePath.js.map +1 -1
  102. package/package.json +5 -12
  103. package/dist/ansiCodes.js +0 -107
  104. package/dist/ansiCodes.js.map +0 -1
  105. package/dist/auth/credentialsStore.test.js +0 -60
  106. package/dist/auth/credentialsStore.test.js.map +0 -1
  107. package/dist/claude/fileHistory.js +0 -79
  108. package/dist/claude/fileHistory.js.map +0 -1
  109. package/dist/claude/generateHookSettings.js +0 -23
  110. package/dist/claude/generateHookSettings.js.map +0 -1
  111. package/dist/claude/hookServer.js +0 -33
  112. package/dist/claude/hookServer.js.map +0 -1
  113. package/dist/claude/sessionScanner.js +0 -162
  114. package/dist/claude/sessionScanner.js.map +0 -1
  115. package/dist/claude/sessionScanner.test.js +0 -24
  116. package/dist/claude/sessionScanner.test.js.map +0 -1
  117. package/dist/claude/transcriptParser.test.js +0 -78
  118. package/dist/claude/transcriptParser.test.js.map +0 -1
  119. package/dist/commands/cliArgs.test.js +0 -25
  120. package/dist/commands/cliArgs.test.js.map +0 -1
  121. package/dist/config.js +0 -40
  122. package/dist/config.js.map +0 -1
  123. package/dist/credentialsStore.js +0 -57
  124. package/dist/credentialsStore.js.map +0 -1
  125. package/dist/generateHookSettings.js +0 -30
  126. package/dist/generateHookSettings.js.map +0 -1
  127. package/dist/handlers/fileHandlerPayloads.test.js +0 -55
  128. package/dist/handlers/fileHandlerPayloads.test.js.map +0 -1
  129. package/dist/handlers/promptImages.test.js +0 -52
  130. package/dist/handlers/promptImages.test.js.map +0 -1
  131. package/dist/hookServer.js +0 -32
  132. package/dist/hookServer.js.map +0 -1
  133. package/dist/ignorePaths.js +0 -68
  134. package/dist/ignorePaths.js.map +0 -1
  135. package/dist/loadDotEnv.js +0 -79
  136. package/dist/loadDotEnv.js.map +0 -1
  137. package/dist/logger.js +0 -29
  138. package/dist/logger.js.map +0 -1
  139. package/dist/portForwardManager.js +0 -97
  140. package/dist/portForwardManager.js.map +0 -1
  141. package/dist/projectHistoryReader.js +0 -85
  142. package/dist/projectHistoryReader.js.map +0 -1
  143. package/dist/pty/ansiCodes.js +0 -14
  144. package/dist/pty/ansiCodes.js.map +0 -1
  145. package/dist/pty/notificationDetector.js +0 -29
  146. package/dist/pty/notificationDetector.js.map +0 -1
  147. package/dist/pty/notificationDetector.test.js +0 -24
  148. package/dist/pty/notificationDetector.test.js.map +0 -1
  149. package/dist/pty/ptyMenuParser.js +0 -91
  150. package/dist/pty/ptyMenuParser.js.map +0 -1
  151. package/dist/pty/ptyMenuParser.test.js +0 -26
  152. package/dist/pty/ptyMenuParser.test.js.map +0 -1
  153. package/dist/pty/ptySnapshotRenderer.js +0 -71
  154. package/dist/pty/ptySnapshotRenderer.js.map +0 -1
  155. package/dist/pty/selectionMenuDetector.js +0 -49
  156. package/dist/pty/selectionMenuDetector.js.map +0 -1
  157. package/dist/pty/selectionMenuDetector.test.js +0 -62
  158. package/dist/pty/selectionMenuDetector.test.js.map +0 -1
  159. package/dist/pty/selectionMenuMeta.js +0 -54
  160. package/dist/pty/selectionMenuMeta.js.map +0 -1
  161. package/dist/pty/selectionMenuMeta.test.js +0 -26
  162. package/dist/pty/selectionMenuMeta.test.js.map +0 -1
  163. package/dist/pty/selectionMenuParser.js +0 -83
  164. package/dist/pty/selectionMenuParser.js.map +0 -1
  165. package/dist/pty/selectionMenuParser.test.js +0 -30
  166. package/dist/pty/selectionMenuParser.test.js.map +0 -1
  167. package/dist/pty/spawn.js +0 -104
  168. package/dist/pty/spawn.js.map +0 -1
  169. package/dist/pty/spawn.test.js +0 -17
  170. package/dist/pty/spawn.test.js.map +0 -1
  171. package/dist/pty/statusSessionDetector.js +0 -28
  172. package/dist/pty/statusSessionDetector.js.map +0 -1
  173. package/dist/pty/statusSessionDetector.test.js +0 -23
  174. package/dist/pty/statusSessionDetector.test.js.map +0 -1
  175. package/dist/pty/textInputDetector.js +0 -60
  176. package/dist/pty/textInputDetector.js.map +0 -1
  177. package/dist/pty/textInputDetector.test.js +0 -32
  178. package/dist/pty/textInputDetector.test.js.map +0 -1
  179. package/dist/ptyMenuParser.js +0 -470
  180. package/dist/ptyMenuParser.js.map +0 -1
  181. package/dist/ptySnapshotRenderer.js +0 -78
  182. package/dist/ptySnapshotRenderer.js.map +0 -1
  183. package/dist/services/checkpointService.js +0 -113
  184. package/dist/services/checkpointService.js.map +0 -1
  185. package/dist/services/checkpointService.test.js +0 -61
  186. package/dist/services/checkpointService.test.js.map +0 -1
  187. package/dist/services/claudeMenuBridge.js +0 -116
  188. package/dist/services/claudeMenuBridge.js.map +0 -1
  189. package/dist/services/claudeMenuBridge.test.js +0 -90
  190. package/dist/services/claudeMenuBridge.test.js.map +0 -1
  191. package/dist/services/claudeService.js +0 -146
  192. package/dist/services/claudeService.js.map +0 -1
  193. package/dist/services/claudeService.test.js +0 -39
  194. package/dist/services/claudeService.test.js.map +0 -1
  195. package/dist/services/cliRuntime.test.js +0 -55
  196. package/dist/services/cliRuntime.test.js.map +0 -1
  197. package/dist/services/modelAdapter.test.js +0 -47
  198. package/dist/services/modelAdapter.test.js.map +0 -1
  199. package/dist/services/modelArgs.test.js +0 -64
  200. package/dist/services/modelArgs.test.js.map +0 -1
  201. package/dist/services/modelBaseUrl.test.js +0 -32
  202. package/dist/services/modelBaseUrl.test.js.map +0 -1
  203. package/dist/services/modelService.test.js +0 -136
  204. package/dist/services/modelService.test.js.map +0 -1
  205. package/dist/services/notificationDedupe.js +0 -23
  206. package/dist/services/notificationDedupe.js.map +0 -1
  207. package/dist/services/notificationDedupe.test.js +0 -20
  208. package/dist/services/notificationDedupe.test.js.map +0 -1
  209. package/dist/services/sessionListService.test.js +0 -22
  210. package/dist/services/sessionListService.test.js.map +0 -1
  211. package/dist/services/sessionRollbackService.js +0 -195
  212. package/dist/services/sessionRollbackService.js.map +0 -1
  213. package/dist/services/sessionRollbackService.test.js +0 -142
  214. package/dist/services/sessionRollbackService.test.js.map +0 -1
  215. package/dist/services/tunnelHelpers.test.js +0 -42
  216. package/dist/services/tunnelHelpers.test.js.map +0 -1
  217. package/dist/services/tunnelService.test.js +0 -91
  218. package/dist/services/tunnelService.test.js.map +0 -1
  219. package/dist/sessionScanner.js +0 -271
  220. package/dist/sessionScanner.js.map +0 -1
  221. package/dist/snapshotScanner.js +0 -154
  222. package/dist/snapshotScanner.js.map +0 -1
  223. package/dist/spawn.js +0 -79
  224. package/dist/spawn.js.map +0 -1
  225. package/dist/terminalManager.js +0 -73
  226. package/dist/terminalManager.js.map +0 -1
  227. package/dist/transport/directWsServer.js +0 -135
  228. package/dist/transport/directWsServer.js.map +0 -1
  229. package/dist/transport/webrtcTransport.js +0 -145
  230. package/dist/transport/webrtcTransport.js.map +0 -1
  231. package/dist/transport/webrtcTransport.test.js +0 -104
  232. package/dist/transport/webrtcTransport.test.js.map +0 -1
  233. package/dist/transport/webrtcTypes.js +0 -29
  234. package/dist/transport/webrtcTypes.js.map +0 -1
  235. package/dist/transport/webrtcTypes.test.js +0 -20
  236. package/dist/transport/webrtcTypes.test.js.map +0 -1
  237. package/dist/utils/ptyBuffer.js +0 -46
  238. package/dist/utils/ptyBuffer.js.map +0 -1
  239. package/scripts/claude_launcher.cjs +0 -71
  240. package/scripts/run-tests.mjs +0 -46
  241. package/scripts/session_hook_forwarder.cjs +0 -44
@@ -0,0 +1,106 @@
1
+ import { isPermissionMode } from './permissions.js';
2
+ // flags owned by the engine; the value is consumed when the flag takes one
3
+ const OWNED_FLAGS = {
4
+ '-p': false,
5
+ '--print': false,
6
+ '-c': false,
7
+ '--continue': false,
8
+ '--replay-user-messages': false,
9
+ '--output-format': true,
10
+ '--input-format': true,
11
+ '--permission-prompt-tool': true,
12
+ '--permission-mode': true,
13
+ '--session-id': true,
14
+ '--resume': true,
15
+ '-r': true,
16
+ };
17
+ // strip user passthrough flags that conflict with the stream-json engine, keeping the user's intent
18
+ export function filterPassthroughArgs(args) {
19
+ const passthrough = [];
20
+ let permissionMode;
21
+ let allowBypass = false;
22
+ for (let i = 0; i < args.length; i++) {
23
+ const arg = args[i];
24
+ if (arg === '--dangerously-skip-permissions') {
25
+ allowBypass = true;
26
+ permissionMode ??= 'bypassPermissions';
27
+ continue;
28
+ }
29
+ if (arg === '--allow-dangerously-skip-permissions') {
30
+ allowBypass = true;
31
+ continue;
32
+ }
33
+ const [flag, inlineValue] = arg.includes('=') ? [arg.slice(0, arg.indexOf('=')), arg.slice(arg.indexOf('=') + 1)] : [arg, undefined];
34
+ if (!(flag in OWNED_FLAGS)) {
35
+ passthrough.push(arg);
36
+ continue;
37
+ }
38
+ let value = inlineValue;
39
+ if (OWNED_FLAGS[flag] && value === undefined && args[i + 1] !== undefined && !args[i + 1].startsWith('-'))
40
+ value = args[++i];
41
+ if (flag === '--permission-mode' && isPermissionMode(value))
42
+ permissionMode = value;
43
+ }
44
+ return { passthrough, permissionMode, allowBypass };
45
+ }
46
+ // drop `flag value`, `flag=value` (and aliases) so the engine's own value wins
47
+ function withoutFlag(args, ...flags) {
48
+ const result = [];
49
+ for (let i = 0; i < args.length; i++) {
50
+ const arg = args[i];
51
+ if (flags.includes(arg)) {
52
+ i++;
53
+ continue;
54
+ }
55
+ if (flags.some((flag) => arg.startsWith(`${flag}=`)))
56
+ continue;
57
+ result.push(arg);
58
+ }
59
+ return result;
60
+ }
61
+ // model ids as providers spell them: claude-sonnet-4-5[1m], openrouter/x/y, qwen:7b, claude@2024
62
+ const MODEL_ID = /^[\w.:/@[\]-]{1,200}$/;
63
+ // build the claude argv for one stream-json session
64
+ export function buildClaudeArgs(options) {
65
+ if (options.model && !MODEL_ID.test(options.model))
66
+ throw new Error(`invalid model id: ${JSON.stringify(options.model.slice(0, 80))}`);
67
+ const args = [
68
+ '--output-format', 'stream-json',
69
+ '--verbose',
70
+ '--input-format', 'stream-json',
71
+ '--permission-prompt-tool', 'stdio',
72
+ '--permission-mode', options.permissionMode,
73
+ '--replay-user-messages',
74
+ '--setting-sources=user,project,local',
75
+ options.resume ? `--resume=${options.sessionId}` : `--session-id=${options.sessionId}`,
76
+ ];
77
+ if (options.allowBypass)
78
+ args.push('--allow-dangerously-skip-permissions');
79
+ let extra = options.passthrough ?? [];
80
+ if (options.model) {
81
+ extra = withoutFlag(extra, '--model', '-m');
82
+ args.push('--model', options.model);
83
+ }
84
+ if (options.effort) {
85
+ extra = withoutFlag(extra, '--effort');
86
+ args.push('--effort', options.effort);
87
+ }
88
+ return [...args, ...extra];
89
+ }
90
+ // build the child env: model overrides plus sdk entrypoint, minus vars leaking from a parent claude/node
91
+ export function buildClaudeEnv(base, overrides = {}) {
92
+ const env = { ...base };
93
+ for (const [key, value] of Object.entries(overrides)) {
94
+ if (value === undefined)
95
+ delete env[key];
96
+ else
97
+ env[key] = value;
98
+ }
99
+ env['CLAUDE_CODE_ENTRYPOINT'] = 'sdk-ts';
100
+ env['CLAUDE_CODE_ENABLE_SDK_FILE_CHECKPOINTING'] = 'true';
101
+ delete env['CLAUDECODE'];
102
+ delete env['CLAUDE_CODE_CHILD_SESSION'];
103
+ delete env['NODE_OPTIONS'];
104
+ return env;
105
+ }
106
+ //# sourceMappingURL=claudeArgs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claudeArgs.js","sourceRoot":"","sources":["../../src/engine/claudeArgs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,94 @@
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
+ // $PATH: keeps `where` from looking in the current folder first, where a cloned repo could plant a claude.exe
30
+ const cwd = path.resolve(process.cwd());
31
+ const found = lookup('where $PATH:claude').filter((p) => path.dirname(path.resolve(p)).toLowerCase() !== cwd.toLowerCase());
32
+ const exe = found.find((p) => /\.exe$/i.test(p));
33
+ if (exe)
34
+ return { cmd: exe, shell: false };
35
+ 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);
36
+ if (!shim)
37
+ return null;
38
+ const native = nativeExeFor(shim);
39
+ return native ? { cmd: native, shell: false } : { cmd: shim, shell: true };
40
+ }
41
+ function findOnPosix() {
42
+ const found = lookup('which claude')[0];
43
+ return found ? { cmd: found, shell: false } : null;
44
+ }
45
+ function find() {
46
+ return process.platform === 'win32' ? findOnWindows() : findOnPosix();
47
+ }
48
+ // install the claude cli globally when it is missing from the host machine
49
+ function installClaudeCli() {
50
+ console.log(`[kumo-cli] claude cli not found, installing ${CLAUDE_PACKAGE}...`);
51
+ execSync(`npm install -g --allow-scripts=${CLAUDE_PACKAGE} ${CLAUDE_PACKAGE}`, { stdio: 'inherit' });
52
+ }
53
+ // resolve the claude executable on first use (never at import); KUMO_CLAUDE_BIN overrides discovery
54
+ export function resolveClaudeCommand() {
55
+ if (cached)
56
+ return cached;
57
+ const override = process.env['KUMO_CLAUDE_BIN'];
58
+ if (override) {
59
+ cached = { cmd: override, shell: process.platform === 'win32' && /\.(cmd|bat)$/i.test(override) };
60
+ }
61
+ else {
62
+ let found = find();
63
+ if (!found) {
64
+ try {
65
+ installClaudeCli();
66
+ }
67
+ catch (error) {
68
+ log(`[claude-bin] install failed: ${error}`);
69
+ }
70
+ found = find();
71
+ }
72
+ // a bare `claude` through cmd.exe would also run one from the current folder
73
+ if (!found)
74
+ throw new Error(`claude cli not found: install ${CLAUDE_PACKAGE} or set KUMO_CLAUDE_BIN`);
75
+ cached = found;
76
+ }
77
+ log(`[claude-bin] using ${cached.cmd} (shell=${cached.shell})`);
78
+ return cached;
79
+ }
80
+ // quote one argument for a cmd.exe command line. inside quotes cmd.exe still ends the quote at `"`,
81
+ // expands %VAR% (and !VAR!) and splits at line breaks, and no escaping is reliable for a .cmd
82
+ // shim, so such arguments are refused instead
83
+ export function quoteWindowsArg(arg) {
84
+ if (/["%!\r\n]/.test(arg))
85
+ throw new Error(`argument not safe for cmd.exe: ${JSON.stringify(arg.slice(0, 80))}`);
86
+ if (arg && !/[\s&|<>^()!,;=]/.test(arg))
87
+ return arg;
88
+ return `"${arg.replace(/(\\+)$/, '$1$1')}"`;
89
+ }
90
+ // build a single shell command line so node never joins unquoted args (avoids DEP0190)
91
+ export function buildShellCommandLine(cmd, args) {
92
+ return [cmd, ...args].map(quoteWindowsArg).join(' ');
93
+ }
94
+ //# 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,127 @@
1
+ import { list, obj, pick } from '../utils/json.js';
2
+ const MODEL_KEYS = ['value', 'resolvedModel', 'displayName', 'description', 'supportsEffort', 'supportedEffortLevels', 'supportsAdaptiveThinking', 'supportsFastMode', 'supportsAutoMode'];
3
+ const COMMAND_KEYS = ['name', 'description', 'argumentHint'];
4
+ export function commandsOf(value) {
5
+ return list(value).map((command) => pick(command, COMMAND_KEYS));
6
+ }
7
+ // app-facing claude_config payload from an initialize response
8
+ export function toClaudeConfig(init) {
9
+ return {
10
+ models: list(init['models']).map((model) => pick(model, MODEL_KEYS)),
11
+ commands: commandsOf(init['commands']),
12
+ account: pick(obj(init['account']), ['email', 'organization', 'subscriptionType', 'apiProvider']),
13
+ outputStyle: init['output_style'] ?? null,
14
+ availableOutputStyles: Array.isArray(init['available_output_styles']) ? init['available_output_styles'] : [],
15
+ version: init['claude_code_version'] ?? null,
16
+ fastModeState: init['fast_mode_state'] ?? null,
17
+ };
18
+ }
19
+ // what a claude running another provider reports of its own: that provider's models and account,
20
+ // not claude's, so it never replaces those in the shared config (the app's model picker)
21
+ export function withoutProviderConfig(patch) {
22
+ const { models: _models, account: _account, fastModeState: _fastModeState, ...rest } = patch;
23
+ return rest;
24
+ }
25
+ // control requests the app may run through claude_control
26
+ export const CONTROL_WHITELIST = new Set([
27
+ 'get_status', 'get_usage', 'get_context_usage', 'get_settings', 'export_conversation', 'side_question',
28
+ 'mcp_status', 'mcp_toggle', 'mcp_reconnect', 'list_permission_rules', 'update_settings', 'rewind_files',
29
+ 'stop_task', 'cancel_async_message',
30
+ 'get_hooks_listing', 'get_sandbox_dialog', 'get_skills_dialog', 'get_memory_dialog', 'reload_plugins', 'reload_skills',
31
+ ]);
32
+ const NOT_RUNNING = 'This session is no longer running.';
33
+ // requests about the running process itself, with the reason a stopped session can't answer;
34
+ // file checkpoints live in the process that ran the turns, a resumed one has none
35
+ export const LIVE_ONLY_CONTROLS = new Map([
36
+ ['rewind_files', "Code checkpoints only last while this session's Claude process runs, and it has stopped. You can still fork the conversation."],
37
+ ['stop_task', NOT_RUNNING],
38
+ ['cancel_async_message', NOT_RUNNING],
39
+ ]);
40
+ // requests answered from the target session's own context
41
+ export const SESSION_SCOPED_CONTROLS = new Set(['get_context_usage', 'export_conversation', 'side_question']);
42
+ // mcp servers live in the chat's own process: shown, switched and reconnected there, which is
43
+ // started when it is not running; a throwaway probe would only ever see them connecting
44
+ export const OWN_PROCESS_CONTROLS = new Set(['mcp_status', 'mcp_toggle', 'mcp_reconnect']);
45
+ // side questions run a model call (5 min like the extension), the rest are quick reads
46
+ export const controlTimeoutMs = (subtype) => (subtype === 'side_question' ? 300_000 : undefined);
47
+ const text = (source, key, max = 4000) => {
48
+ const value = typeof source[key] === 'string' ? source[key].trim().slice(0, max) : '';
49
+ if (!value)
50
+ throw new Error(`${key} is required`);
51
+ return value;
52
+ };
53
+ // the only payload fields forwarded to claude per request
54
+ export function controlPayload(subtype, payload) {
55
+ const source = obj(payload);
56
+ switch (subtype) {
57
+ case 'side_question':
58
+ return { question: text(source, 'question') };
59
+ case 'mcp_reconnect':
60
+ return { serverName: text(source, 'serverName', 200) };
61
+ case 'mcp_toggle':
62
+ if (typeof source['enabled'] !== 'boolean')
63
+ throw new Error('enabled is required');
64
+ return { serverName: text(source, 'serverName', 200), enabled: source['enabled'] };
65
+ case 'stop_task':
66
+ return { task_id: text(source, 'taskId', 100) };
67
+ case 'cancel_async_message':
68
+ return { message_uuid: text(source, 'uuid', 100) };
69
+ case 'rewind_files':
70
+ return { user_message_id: text(source, 'userMessageId', 100), dry_run: source['dryRun'] === true };
71
+ case 'update_settings':
72
+ // only the output style may be changed from the app, and only for this project
73
+ return { source: 'localSettings', settings: { outputStyle: text(source, 'outputStyle', 200) } };
74
+ default:
75
+ return {};
76
+ }
77
+ }
78
+ // keep only what the app renders; get_settings.effective carries mcp env secrets and never leaves the machine
79
+ export function sanitizeControlResponse(subtype, response) {
80
+ switch (subtype) {
81
+ case 'get_settings': {
82
+ const outputStyle = obj(response['effective'])['outputStyle'];
83
+ return { applied: obj(response['applied']), outputStyle: typeof outputStyle === 'string' ? outputStyle : null };
84
+ }
85
+ case 'mcp_status':
86
+ // server configs carry urls, headers and env secrets; of the tools only names and hints
87
+ return {
88
+ mcpServers: list(response['mcpServers']).map((server) => ({
89
+ ...pick(server, ['name', 'status', 'scope', 'error']),
90
+ type: obj(server['config'])['type'] ?? null,
91
+ tools: list(server['tools']).map((tool) => {
92
+ const hints = obj(tool['annotations']);
93
+ return {
94
+ name: tool['name'] ?? '',
95
+ ...(hints['readOnly'] === true ? { readOnly: true } : {}),
96
+ ...(hints['destructive'] === true ? { destructive: true } : {}),
97
+ };
98
+ }),
99
+ })),
100
+ };
101
+ case 'list_permission_rules':
102
+ return { rules: list(obj(response['state'])['rules']).map((rule) => pick(rule, ['rule', 'behavior', 'source'])) };
103
+ case 'get_context_usage': {
104
+ const { gridRows: _grid, ...rest } = response;
105
+ return rest;
106
+ }
107
+ case 'reload_plugins':
108
+ // the payload repeats every command, agent and mcp config; the app only needs the outcome
109
+ return {
110
+ plugins: list(response['plugins']).map((plugin) => pick(plugin, ['name', 'version', 'source'])),
111
+ error_count: response['error_count'] ?? 0,
112
+ };
113
+ case 'reload_skills':
114
+ return { count: list(response['skills']).length };
115
+ case 'get_usage': {
116
+ const limits = obj(response['rate_limits']);
117
+ return {
118
+ session: obj(response['session']),
119
+ subscription_type: response['subscription_type'] ?? null,
120
+ rate_limits: pick(limits, ['five_hour', 'seven_day', 'limits', 'model_scoped']),
121
+ };
122
+ }
123
+ default:
124
+ return response;
125
+ }
126
+ }
127
+ //# 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,76 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { StreamSession } from './streamSession.js';
3
+ const LOGIN_TIMEOUT_MS = 10 * 60_000;
4
+ // sign claude in with its own oauth over the control channel of a throwaway process, as the
5
+ // extension does: the link comes back to open on the phone, the code that page shows goes to
6
+ // submitCode, and claude reports when it is done
7
+ export class ClaudeLogin {
8
+ options;
9
+ // the process running the sign-in, null when none is in progress
10
+ session = null;
11
+ constructor(options) {
12
+ this.options = options;
13
+ }
14
+ get running() {
15
+ return this.session?.alive === true;
16
+ }
17
+ async start(useConsole = false) {
18
+ await this.cancel();
19
+ const sessionId = randomUUID();
20
+ const session = new StreamSession({ sessionId, permissionMode: 'default', emit: () => undefined, closeGraceMs: this.options.closeGraceMs });
21
+ // taken before the spec is built, so a second tap meanwhile replaces this one instead of
22
+ // starting a process nobody closes
23
+ this.session = session;
24
+ const spec = await this.options.spawnSpec({ sessionId, resume: false, permissionMode: 'default', allowBypass: false, model: null });
25
+ if (this.session !== session)
26
+ throw new Error('Sign-in was started again');
27
+ session.start(spec);
28
+ try {
29
+ const response = await session.controlRequest({ subtype: 'claude_authenticate', loginWithClaudeAi: !useConsole });
30
+ const url = typeof response['manualUrl'] === 'string' ? response['manualUrl'] : '';
31
+ if (!url)
32
+ throw new Error('Claude did not return a sign-in link');
33
+ session.controlRequest({ subtype: 'claude_oauth_wait_for_completion' }, LOGIN_TIMEOUT_MS)
34
+ .then(() => this.finish(session, null), (error) => this.finish(session, error));
35
+ return url;
36
+ }
37
+ catch (error) {
38
+ await this.cancel();
39
+ throw error;
40
+ }
41
+ }
42
+ // the code the sign-in page shows, `code#state`
43
+ async submitCode(code) {
44
+ const session = this.session;
45
+ if (!session?.alive)
46
+ throw new Error('No sign-in is in progress, start it again');
47
+ const value = code.trim();
48
+ const hash = value.indexOf('#');
49
+ try {
50
+ await session.controlRequest({
51
+ subtype: 'claude_oauth_callback',
52
+ authorizationCode: hash < 0 ? value : value.slice(0, hash),
53
+ state: hash < 0 ? '' : value.slice(hash + 1),
54
+ }, 60_000);
55
+ }
56
+ catch (error) {
57
+ // the token endpoint answers a bad or stale code with a bare 4xx
58
+ if (/status code 4\d\d/.test(error.message))
59
+ throw new Error('That code did not work, copy it again from the sign-in page');
60
+ throw error;
61
+ }
62
+ }
63
+ async cancel() {
64
+ const session = this.session;
65
+ this.session = null;
66
+ await session?.close('login_cancelled');
67
+ }
68
+ async finish(session, error) {
69
+ if (this.session !== session)
70
+ return;
71
+ this.session = null;
72
+ await session.close('login_done');
73
+ await this.options.onFinish(error);
74
+ }
75
+ }
76
+ //# sourceMappingURL=claudeLogin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claudeLogin.js","sourceRoot":"","sources":["../../src/engine/claudeLogin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,75 @@
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
+ // write answers false when nothing could reach claude (its stdin is gone)
9
+ constructor(write) {
10
+ this.write = write;
11
+ }
12
+ // send a control request and resolve with its success payload
13
+ request(request, timeoutMs = CONTROL_TIMEOUT_MS) {
14
+ const requestId = `kumo-${randomUUID()}`;
15
+ const promise = new Promise((resolve, reject) => {
16
+ const timer = setTimeout(() => {
17
+ this.cancel(requestId, `control request ${request.subtype} timed out after ${timeoutMs}ms`);
18
+ }, timeoutMs);
19
+ this.pending.set(requestId, { subtype: request.subtype, resolve, reject, timer });
20
+ });
21
+ // claude is exiting: fail now instead of at the timeout (5 minutes for a side question)
22
+ if (this.write({ type: 'control_request', request_id: requestId, request }) === false) {
23
+ this.settle(requestId, new Error(`control request ${request.subtype} could not be sent: claude is not running`));
24
+ }
25
+ return promise;
26
+ }
27
+ // settle the matching pending request; unknown ids (e.g. echoed host responses) are ignored
28
+ handleResponse(msg) {
29
+ const response = msg['response'];
30
+ const requestId = response?.['request_id'];
31
+ if (typeof requestId !== 'string')
32
+ return false;
33
+ const entry = this.pending.get(requestId);
34
+ if (!entry)
35
+ return false;
36
+ this.pending.delete(requestId);
37
+ clearTimeout(entry.timer);
38
+ if (response?.['subtype'] === 'success')
39
+ entry.resolve(response['response'] ?? {});
40
+ else
41
+ entry.reject(new Error(String(response?.['error'] ?? `control request ${entry.subtype} failed`)));
42
+ return true;
43
+ }
44
+ settle(requestId, error) {
45
+ const entry = this.pending.get(requestId);
46
+ if (!entry)
47
+ return;
48
+ this.pending.delete(requestId);
49
+ clearTimeout(entry.timer);
50
+ entry.reject(error);
51
+ }
52
+ // drop a pending request locally and tell the cli to stop working on it
53
+ cancel(requestId, reason = 'cancelled') {
54
+ const entry = this.pending.get(requestId);
55
+ if (!entry)
56
+ return;
57
+ this.pending.delete(requestId);
58
+ clearTimeout(entry.timer);
59
+ try {
60
+ this.write({ type: 'control_cancel_request', request_id: requestId });
61
+ }
62
+ catch { }
63
+ entry.reject(new Error(reason));
64
+ }
65
+ // fail every pending request, used when the process exits
66
+ rejectAll(reason) {
67
+ for (const [requestId, entry] of this.pending) {
68
+ clearTimeout(entry.timer);
69
+ entry.reject(new Error(reason));
70
+ this.pending.delete(requestId);
71
+ }
72
+ }
73
+ get size() { return this.pending.size; }
74
+ }
75
+ //# 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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"}