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
@@ -1,7 +1,11 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
- import { safePath, copyRecursive } from '../utils/safePath.js';
3
+ import { safePath, copyRecursive, projectRootOf, mutablePath } from '../utils/safePath.js';
4
4
  import { loadIgnoredNames } from '../utils/ignorePaths.js';
5
+ // the largest file sent to the app in one read
6
+ export const MAX_READ_BYTES = 5 * 1024 * 1024;
7
+ // how many folder entries one search may look at before giving up
8
+ export const MAX_SEARCH_VISITS = 50_000;
5
9
  // translate any thrown error into a string message
6
10
  function errMsg(e) {
7
11
  return e instanceof Error ? e.message : String(e);
@@ -15,10 +19,19 @@ function guard(fn) {
15
19
  return { ok: false, error: errMsg(e) };
16
20
  }
17
21
  }
22
+ // size of a file, 0 when it cannot be read (a broken link, no permission)
23
+ function sizeOf(file) {
24
+ try {
25
+ return fs.statSync(file).size;
26
+ }
27
+ catch {
28
+ return 0;
29
+ }
30
+ }
18
31
  // list directory entries (non-hidden) sorted dirs first
19
32
  export function list(requestedPath, cwd) {
20
33
  return guard(() => {
21
- const projectRoot = cwd && path.isAbsolute(cwd) ? safePath(cwd) : process.cwd();
34
+ const projectRoot = projectRootOf(cwd);
22
35
  const resolved = requestedPath
23
36
  ? safePath(requestedPath, projectRoot)
24
37
  : projectRoot;
@@ -28,24 +41,33 @@ export function list(requestedPath, cwd) {
28
41
  name: e.name,
29
42
  path: path.relative(projectRoot, path.resolve(resolved, e.name)).replace(/\\/g, '/'),
30
43
  isDirectory: e.isDirectory(),
31
- size: e.isDirectory() ? 0 : fs.statSync(path.resolve(resolved, e.name)).size,
44
+ size: e.isDirectory() ? 0 : sizeOf(path.resolve(resolved, e.name)),
32
45
  }))
33
46
  .sort((a, b) => a.isDirectory !== b.isDirectory ? (a.isDirectory ? -1 : 1) : a.name.localeCompare(b.name));
34
47
  return { entries, projectName: path.basename(projectRoot) };
35
48
  });
36
49
  }
37
50
  export function read(filePath, cwd) {
38
- return guard(() => fs.readFileSync(safePath(filePath, cwd), 'utf-8'));
51
+ return guard(() => {
52
+ const resolved = safePath(filePath, projectRootOf(cwd));
53
+ const stat = fs.statSync(resolved);
54
+ if (!stat.isFile())
55
+ throw new Error('not a file');
56
+ if (stat.size > MAX_READ_BYTES)
57
+ throw new Error(`file too large (${stat.size} bytes, max ${MAX_READ_BYTES})`);
58
+ return fs.readFileSync(resolved, 'utf-8');
59
+ });
39
60
  }
40
61
  export function write(filePath, content, cwd) {
41
62
  return guard(() => {
42
- const resolved = safePath(filePath, cwd);
43
- fs.writeFileSync(resolved, content, 'utf-8');
63
+ if (typeof content !== 'string')
64
+ throw new Error('content is required');
65
+ fs.writeFileSync(mutablePath(filePath, projectRootOf(cwd)), content, 'utf-8');
44
66
  });
45
67
  }
46
68
  export function create(targetPath, isDir, cwd) {
47
69
  return guard(() => {
48
- const resolved = safePath(targetPath, cwd);
70
+ const resolved = mutablePath(targetPath, projectRootOf(cwd));
49
71
  if (isDir)
50
72
  fs.mkdirSync(resolved, { recursive: true });
51
73
  else {
@@ -55,25 +77,33 @@ export function create(targetPath, isDir, cwd) {
55
77
  });
56
78
  }
57
79
  export function remove(targetPath, cwd) {
58
- return guard(() => fs.rmSync(safePath(targetPath, cwd), { recursive: true, force: false }));
80
+ return guard(() => fs.rmSync(mutablePath(targetPath, projectRootOf(cwd)), { recursive: true, force: false }));
59
81
  }
60
82
  export function rename(oldPath, newName, cwd) {
61
83
  return guard(() => {
62
- const projectRoot = cwd ? path.resolve(cwd) : process.cwd();
63
- const resolvedOld = safePath(oldPath, projectRoot);
64
- const resolvedNew = path.join(path.dirname(resolvedOld), newName);
65
- safePath(path.relative(projectRoot, resolvedNew), projectRoot);
84
+ if (typeof newName !== 'string' || !newName || newName === '.' || newName === '..' || /[\\/]/.test(newName)) {
85
+ throw new Error('invalid name');
86
+ }
87
+ const projectRoot = projectRootOf(cwd);
88
+ const resolvedOld = mutablePath(oldPath, projectRoot);
89
+ const resolvedNew = safePath(path.join(path.dirname(resolvedOld), newName), projectRoot);
66
90
  fs.renameSync(resolvedOld, resolvedNew);
67
91
  return { newPath: path.relative(projectRoot, resolvedNew).replace(/\\/g, '/') };
68
92
  });
69
93
  }
70
94
  export function copy(src, dest, cwd) {
71
- return guard(() => copyRecursive(safePath(src, cwd), safePath(dest, cwd)));
95
+ return guard(() => {
96
+ const projectRoot = projectRootOf(cwd);
97
+ copyRecursive(mutablePath(src, projectRoot), mutablePath(dest, projectRoot));
98
+ });
72
99
  }
73
100
  export function move(src, dest, cwd) {
74
- return guard(() => fs.renameSync(safePath(src, cwd), safePath(dest, cwd)));
101
+ return guard(() => {
102
+ const projectRoot = projectRootOf(cwd);
103
+ fs.renameSync(mutablePath(src, projectRoot), mutablePath(dest, projectRoot));
104
+ });
75
105
  }
76
- // recursive case-insensitive name search, bounded by limit
106
+ // recursive case-insensitive name search, bounded by limit and by how many entries it looks at
77
107
  export function search(query, basePath, limit) {
78
108
  return guard(() => {
79
109
  const q = query.trim().toLowerCase();
@@ -84,7 +114,8 @@ export function search(query, basePath, limit) {
84
114
  const ignored = loadIgnoredNames(projectRoot);
85
115
  const results = [];
86
116
  const stack = [baseResolved];
87
- while (stack.length > 0 && results.length < limit) {
117
+ let visits = 0;
118
+ while (stack.length > 0 && results.length < limit && visits < MAX_SEARCH_VISITS) {
88
119
  const dir = stack.pop();
89
120
  let dirEntries;
90
121
  try {
@@ -94,22 +125,17 @@ export function search(query, basePath, limit) {
94
125
  continue;
95
126
  }
96
127
  for (const e of dirEntries) {
128
+ if (++visits >= MAX_SEARCH_VISITS)
129
+ break;
97
130
  if (e.name.startsWith('.') || ignored.has(e.name))
98
131
  continue;
99
132
  const full = path.resolve(dir, e.name);
100
133
  if (e.name.toLowerCase().includes(q)) {
101
- let size = 0;
102
- if (!e.isDirectory()) {
103
- try {
104
- size = fs.statSync(full).size;
105
- }
106
- catch { }
107
- }
108
134
  results.push({
109
135
  name: e.name,
110
136
  path: path.relative(projectRoot, full).replace(/\\/g, '/'),
111
137
  isDirectory: e.isDirectory(),
112
- size,
138
+ size: e.isDirectory() ? 0 : sizeOf(full),
113
139
  });
114
140
  if (results.length >= limit)
115
141
  break;
@@ -1 +1 @@
1
- {"version":3,"file":"fileService.js","sourceRoot":"","sources":["../../src/services/fileService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fileService.js","sourceRoot":"","sources":["../../src/services/fileService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,120 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import fs from 'node:fs';
3
+ import os from 'node:os';
4
+ import path from 'node:path';
5
+ import { findSessionJsonl } from './sessionService.js';
6
+ import { str } from '../utils/json.js';
7
+ function promptText(entry) {
8
+ const content = entry['message']?.['content'];
9
+ if (typeof content === 'string')
10
+ return content;
11
+ if (!Array.isArray(content))
12
+ return '';
13
+ return content
14
+ .filter((b) => !!b && typeof b === 'object' && b['type'] === 'text')
15
+ .map((b) => str(b['text']))
16
+ .join('');
17
+ }
18
+ function readEntries(file) {
19
+ return fs.readFileSync(file, 'utf-8').split('\n').flatMap((line) => {
20
+ if (!line.trim())
21
+ return [];
22
+ try {
23
+ return [JSON.parse(line)];
24
+ }
25
+ catch {
26
+ return [];
27
+ }
28
+ });
29
+ }
30
+ // the user's rename, else claude's title, of the source session
31
+ function titleOf(entries) {
32
+ let custom = '';
33
+ let ai = '';
34
+ for (const entry of entries) {
35
+ if (entry['type'] === 'custom-title')
36
+ custom = str(entry['customTitle']) || custom;
37
+ if (entry['type'] === 'ai-title')
38
+ ai = str(entry['aiTitle']) || ai;
39
+ }
40
+ return custom || ai;
41
+ }
42
+ // checkpoints of the kept messages stay usable in the fork: hard-link their backups
43
+ function linkBackups(sourceId, forkId, backups) {
44
+ if (!backups || typeof backups !== 'object')
45
+ return;
46
+ const root = path.join(os.homedir(), '.claude', 'file-history');
47
+ for (const backup of Object.values(backups)) {
48
+ const name = str(backup?.['backupFileName']);
49
+ if (!name || name !== path.basename(name))
50
+ continue;
51
+ const from = path.join(root, sourceId, name);
52
+ const to = path.join(root, forkId, name);
53
+ if (!fs.existsSync(from) || fs.existsSync(to))
54
+ continue;
55
+ fs.mkdirSync(path.dirname(to), { recursive: true });
56
+ try {
57
+ fs.linkSync(from, to);
58
+ }
59
+ catch {
60
+ fs.copyFileSync(from, to);
61
+ }
62
+ }
63
+ }
64
+ // fork a conversation right before one of its prompts, as the VS Code extension does: the
65
+ // chain up to that prompt's parent is copied under fresh uuids into a new transcript next to
66
+ // the source, its file-history checkpoints follow along, and the copy is titled "(fork)"
67
+ export function forkSession(sourceId, userMessageId) {
68
+ const file = findSessionJsonl(sourceId);
69
+ if (!file)
70
+ throw new Error('Session transcript not found');
71
+ const entries = readEntries(file);
72
+ const byUuid = new Map();
73
+ for (const entry of entries)
74
+ if (str(entry['uuid']))
75
+ byUuid.set(str(entry['uuid']), entry);
76
+ const chosen = byUuid.get(userMessageId);
77
+ if (!chosen || chosen['type'] !== 'user')
78
+ throw new Error('That message is not in this session');
79
+ const prompt = promptText(chosen);
80
+ const resumeAt = str(chosen['parentUuid']);
81
+ if (!resumeAt)
82
+ return { sessionId: null, prompt };
83
+ // walk back from the kept tail to the root; progress entries drop out of the copy
84
+ const chain = [];
85
+ const visited = new Set();
86
+ for (let entry = byUuid.get(resumeAt); entry && !visited.has(str(entry['uuid'])); entry = byUuid.get(str(entry['parentUuid']))) {
87
+ visited.add(str(entry['uuid']));
88
+ if (entry['type'] !== 'progress')
89
+ chain.unshift(entry);
90
+ }
91
+ if (chain.length === 0)
92
+ return { sessionId: null, prompt };
93
+ const forkId = randomUUID();
94
+ const ids = new Map(chain.map((entry) => [str(entry['uuid']), randomUUID()]));
95
+ const out = chain.map((entry, i) => {
96
+ const { logicalParentUuid: _logical, ...rest } = entry;
97
+ return {
98
+ ...rest,
99
+ uuid: ids.get(str(entry['uuid'])),
100
+ parentUuid: i === 0 ? null : ids.get(str(chain[i - 1]['uuid'])),
101
+ sessionId: forkId,
102
+ ...(i === chain.length - 1 ? { timestamp: new Date().toISOString() } : {}),
103
+ };
104
+ });
105
+ for (const entry of entries) {
106
+ if (entry['type'] !== 'file-history-snapshot')
107
+ continue;
108
+ const messageId = ids.get(str(entry['messageId']));
109
+ if (!messageId)
110
+ continue;
111
+ const snapshot = { ...entry['snapshot'], messageId };
112
+ out.push({ ...entry, messageId, snapshot });
113
+ linkBackups(sourceId, forkId, snapshot['trackedFileBackups']);
114
+ }
115
+ const title = titleOf(entries) || prompt.split('\n')[0].slice(0, 60);
116
+ out.push({ type: 'custom-title', customTitle: `${title} (fork)`, sessionId: forkId });
117
+ fs.writeFileSync(path.join(path.dirname(file), `${forkId}.jsonl`), `${out.map((e) => JSON.stringify(e)).join('\n')}\n`, 'utf-8');
118
+ return { sessionId: forkId, prompt };
119
+ }
120
+ //# sourceMappingURL=forkService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forkService.js","sourceRoot":"","sources":["../../src/services/forkService.ts"],"names":[],"mappings":"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"}
@@ -1,89 +1,102 @@
1
1
  import { httpRequest } from '../http/httpClient.js';
2
2
  import { SERVER_HTTP } from '../core/config.js';
3
3
  import { ClaudeAdapterProxy } from './claudeAdapterProxy.js';
4
- // strip any existing --model / --model=... / -m flag pairs
5
- export function removeModelArgs(args) {
6
- const result = [];
7
- for (let i = 0; i < args.length; i++) {
8
- const a = args[i];
9
- if (a === '--model' || a === '-m') {
10
- i++;
11
- continue;
12
- }
13
- if (a.startsWith('--model='))
14
- continue;
15
- result.push(a);
4
+ import { isLocalHost } from '../utils/localHost.js';
5
+ // distinct provider configs kept running; above the live-session cap so live sessions keep theirs
6
+ const MAX_ADAPTER_PROXIES = 8;
7
+ // parse a backend model payload: object = explicit model, null = claude's own default, otherwise device default
8
+ export function parseModelPayload(payload) {
9
+ if (payload === null)
10
+ return null;
11
+ if (!payload || typeof payload !== 'object')
12
+ return undefined;
13
+ const p = payload;
14
+ const model = {
15
+ model: typeof p['model'] === 'string' ? p['model'].trim() : '',
16
+ baseURL: typeof p['baseURL'] === 'string' && p['baseURL'] ? p['baseURL'] : undefined,
17
+ apiKey: typeof p['apiKey'] === 'string' && p['apiKey'] ? p['apiKey'] : undefined,
18
+ };
19
+ const contextWindow = p['contextWindow'];
20
+ if (typeof contextWindow === 'number' && Number.isInteger(contextWindow) && contextWindow > 0)
21
+ model.contextWindow = contextWindow;
22
+ return model.model || model.baseURL || model.apiKey ? model : undefined;
23
+ }
24
+ // a provider url must be https, or http on a local host
25
+ export function assertProviderURL(baseURL) {
26
+ let url;
27
+ try {
28
+ url = new URL(baseURL);
29
+ }
30
+ catch {
31
+ throw new Error(`invalid provider url: ${baseURL}`);
16
32
  }
17
- return result;
33
+ if (url.protocol === 'https:')
34
+ return;
35
+ if (url.protocol === 'http:' && isLocalHost(url.hostname))
36
+ return;
37
+ throw new Error(`provider url must use https: ${url.origin}`);
18
38
  }
19
- // orchestrates the currently-active model pushed from backend via ws
39
+ // provider connection for claude processes: env overrides, adapter proxies and the device default model
20
40
  export class ModelService {
21
- current = null;
22
- suppressDefaultFallback = false;
23
- adapterProxy = new ClaudeAdapterProxy();
24
- getCurrent() { return this.current; }
25
- // cache incoming connection settings and rebuild the runtime model args
26
- apply(payload, args) {
27
- const cleaned = removeModelArgs(args);
28
- if (payload && typeof payload === 'object') {
29
- const p = payload;
30
- const current = {
31
- model: typeof p['model'] === 'string' && p['model'].trim()
32
- ? p['model'].trim()
33
- : this.current?.model ?? '',
34
- baseURL: typeof p['baseURL'] === 'string' ? p['baseURL'] : undefined,
35
- apiKey: typeof p['apiKey'] === 'string' ? p['apiKey'] : undefined,
36
- };
37
- if (current.model || current.baseURL || current.apiKey) {
38
- this.current = current;
39
- this.suppressDefaultFallback = false;
40
- if (current.model)
41
- cleaned.push('--model', current.model);
42
- return cleaned;
43
- }
44
- }
45
- this.current = null;
46
- this.suppressDefaultFallback = payload === null;
47
- return cleaned;
48
- }
49
- // build env overrides for claude pty based on current model
50
- async buildEnv() {
41
+ adapterProxies = new Map();
42
+ // build env overrides for a claude process running the given model
43
+ async buildEnv(model) {
51
44
  const env = {
52
45
  ANTHROPIC_BASE_URL: undefined,
53
46
  ANTHROPIC_API_KEY: undefined,
54
47
  ANTHROPIC_AUTH_TOKEN: undefined,
55
48
  };
56
- if (this.current?.baseURL) {
57
- env.ANTHROPIC_BASE_URL = await this.resolveClaudeBaseURL(this.current);
58
- env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
49
+ let proxyToken;
50
+ if (model?.baseURL) {
51
+ assertProviderURL(model.baseURL.trim());
52
+ const endpoint = await this.resolveEndpoint(model);
53
+ env.ANTHROPIC_BASE_URL = endpoint.url;
54
+ proxyToken = endpoint.token;
55
+ // the local adapter holds the provider key and takes its own token; without a key of its
56
+ // own claude would send its claude.ai login to that host
57
+ if (proxyToken)
58
+ env.ANTHROPIC_AUTH_TOKEN = proxyToken;
59
+ else if (!model.apiKey)
60
+ env.ANTHROPIC_AUTH_TOKEN = 'none';
61
+ // claude turns tool search off for hosts that are not anthropic's, then sends every mcp
62
+ // tool's schema each turn and can outgrow a provider's input limit; on unless the user
63
+ // set it themselves
64
+ if (process.env['ENABLE_TOOL_SEARCH'] === undefined)
65
+ env.ENABLE_TOOL_SEARCH = 'true';
59
66
  }
60
- else {
61
- await this.adapterProxy.stop();
62
- }
63
- if (this.current?.apiKey)
64
- env.ANTHROPIC_API_KEY = this.current.apiKey;
65
- if (env.ANTHROPIC_BASE_URL?.startsWith('http://127.0.0.1:'))
66
- env.ANTHROPIC_AUTH_TOKEN = 'default';
67
+ if (model?.apiKey && !proxyToken)
68
+ env.ANTHROPIC_API_KEY = model.apiKey;
69
+ if (model?.contextWindow)
70
+ env.CLAUDE_CODE_AUTO_COMPACT_WINDOW = String(model.contextWindow);
67
71
  return env;
68
72
  }
69
73
  // normalize provider endpoints into Claude-compatible base urls
70
74
  async resolveClaudeBaseURL(model) {
75
+ return (await this.resolveEndpoint(model)).url;
76
+ }
77
+ // the claude-compatible url of a provider, with the token of the adapter proxy started for it;
78
+ // one proxy per provider config, the least recently used closed past MAX_ADAPTER_PROXIES
79
+ async resolveEndpoint(model) {
71
80
  const baseURL = (model.baseURL ?? '').trim().replace(/\/+$/, '');
72
81
  if (!baseURL)
73
- return baseURL;
74
- if (/\/v1\/messages$/i.test(baseURL)) {
75
- await this.adapterProxy.stop();
76
- return baseURL.replace(/\/v1\/messages$/i, '');
77
- }
78
- if (/\/v1\/chat\/completions$/i.test(baseURL)) {
79
- return this.adapterProxy.start({
80
- baseURL,
81
- apiKey: model.apiKey ?? '',
82
- model: model.model,
83
- });
82
+ return { url: baseURL };
83
+ if (/\/v1\/messages$/i.test(baseURL))
84
+ return { url: baseURL.replace(/\/v1\/messages$/i, '') };
85
+ if (!/\/v1\/chat\/completions$/i.test(baseURL))
86
+ return { url: baseURL };
87
+ const config = { baseURL, apiKey: model.apiKey ?? '', model: model.model };
88
+ const key = JSON.stringify(config);
89
+ const proxy = this.adapterProxies.get(key) ?? new ClaudeAdapterProxy();
90
+ this.adapterProxies.delete(key);
91
+ this.adapterProxies.set(key, proxy);
92
+ for (const [oldKey, old] of this.adapterProxies) {
93
+ if (this.adapterProxies.size <= MAX_ADAPTER_PROXIES)
94
+ break;
95
+ this.adapterProxies.delete(oldKey);
96
+ void old.stop();
84
97
  }
85
- await this.adapterProxy.stop();
86
- return baseURL;
98
+ const url = await proxy.start(config);
99
+ return { url, token: proxy.token ?? undefined };
87
100
  }
88
101
  // fetch the user's current default model from backend using deviceToken
89
102
  async fetchDefault(deviceToken) {
@@ -91,36 +104,20 @@ export class ModelService {
91
104
  return null;
92
105
  try {
93
106
  const res = await httpRequest('GET', `${SERVER_HTTP()}/api/cli/default-model`, { token: deviceToken });
94
- if (res.status !== 200 || !res.data || typeof res.data !== 'object')
107
+ if (res.status !== 200)
95
108
  return null;
96
- const d = res.data;
97
- const model = typeof d['model'] === 'string' ? d['model'] : '';
98
- if (!model)
99
- return null;
100
- return {
101
- model,
102
- baseURL: typeof d['baseURL'] === 'string' ? d['baseURL'] : undefined,
103
- apiKey: typeof d['apiKey'] === 'string' ? d['apiKey'] : undefined,
104
- };
109
+ const model = parseModelPayload(res.data);
110
+ return model?.model ? model : null;
105
111
  }
106
112
  catch {
107
113
  return null;
108
114
  }
109
115
  }
110
- // refresh from backend when no current model is set; returns new args list
111
- async ensureBeforeSpawn(args, deviceToken) {
112
- if (this.current)
113
- return args;
114
- if (this.suppressDefaultFallback)
115
- return args;
116
- const def = await this.fetchDefault(deviceToken);
117
- if (def)
118
- return this.apply({ model: def.model, baseURL: def.baseURL, apiKey: def.apiKey }, args);
119
- return args;
120
- }
121
116
  // release local adapter resources
122
117
  async dispose() {
123
- await this.adapterProxy.stop();
118
+ const proxies = [...this.adapterProxies.values()];
119
+ this.adapterProxies.clear();
120
+ await Promise.all(proxies.map((proxy) => proxy.stop()));
124
121
  }
125
122
  }
126
123
  //# sourceMappingURL=modelService.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"modelService.js","sourceRoot":"","sources":["../../src/services/modelService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"modelService.js","sourceRoot":"","sources":["../../src/services/modelService.ts"],"names":[],"mappings":"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"}