kumo-cli 1.1.0 → 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.
- package/README.md +140 -131
- package/dist/auth/credentialsStore.js +19 -6
- package/dist/auth/credentialsStore.js.map +1 -1
- package/dist/claude/conversation.js +272 -0
- package/dist/claude/conversation.js.map +1 -0
- package/dist/claude/transcriptParser.js +98 -93
- package/dist/claude/transcriptParser.js.map +1 -1
- package/dist/commands/cliArgs.js +1 -0
- package/dist/commands/cliArgs.js.map +1 -1
- package/dist/core/config.js +0 -5
- package/dist/core/config.js.map +1 -1
- package/dist/core/logger.js +47 -6
- package/dist/core/logger.js.map +1 -1
- package/dist/core/projectFileWatcher.js +100 -36
- package/dist/core/projectFileWatcher.js.map +1 -1
- package/dist/engine/claudeArgs.js +4 -0
- package/dist/engine/claudeArgs.js.map +1 -1
- package/dist/engine/claudeBinary.js +14 -5
- package/dist/engine/claudeBinary.js.map +1 -1
- package/dist/engine/claudeConfig.js +20 -6
- package/dist/engine/claudeConfig.js.map +1 -1
- package/dist/engine/claudeLogin.js +76 -0
- package/dist/engine/claudeLogin.js.map +1 -0
- package/dist/engine/controlChannel.js +13 -1
- package/dist/engine/controlChannel.js.map +1 -1
- package/dist/engine/liveTranscript.js +70 -21
- package/dist/engine/liveTranscript.js.map +1 -1
- package/dist/engine/ndjson.js +15 -10
- package/dist/engine/ndjson.js.map +1 -1
- package/dist/engine/permissions.js +5 -2
- package/dist/engine/permissions.js.map +1 -1
- package/dist/engine/probePool.js +51 -0
- package/dist/engine/probePool.js.map +1 -0
- package/dist/engine/processTree.js +45 -0
- package/dist/engine/processTree.js.map +1 -0
- package/dist/engine/remoteConfig.js +17 -0
- package/dist/engine/remoteConfig.js.map +1 -0
- package/dist/engine/sessionManager.js +99 -84
- package/dist/engine/sessionManager.js.map +1 -1
- package/dist/engine/settingsCommands.js +56 -0
- package/dist/engine/settingsCommands.js.map +1 -1
- package/dist/engine/streamSession.js +59 -66
- package/dist/engine/streamSession.js.map +1 -1
- package/dist/engine/taskTracker.js +1 -1
- package/dist/engine/taskTracker.js.map +1 -1
- package/dist/engine/toolLabels.js +32 -0
- package/dist/engine/toolLabels.js.map +1 -0
- package/dist/handlers/controlRequest.js +17 -0
- package/dist/handlers/controlRequest.js.map +1 -0
- package/dist/handlers/fileHandlers.js +12 -0
- package/dist/handlers/fileHandlers.js.map +1 -1
- package/dist/handlers/messageRouter.js +8 -1
- package/dist/handlers/messageRouter.js.map +1 -1
- package/dist/handlers/promptImages.js +0 -55
- package/dist/handlers/promptImages.js.map +1 -1
- package/dist/handlers/runtimeHandlers.js +51 -151
- package/dist/handlers/runtimeHandlers.js.map +1 -1
- package/dist/handlers/sessionHandlers.js +48 -14
- package/dist/handlers/sessionHandlers.js.map +1 -1
- package/dist/handlers/terminalHandlers.js +9 -2
- package/dist/handlers/terminalHandlers.js.map +1 -1
- package/dist/http/httpClient.js +6 -0
- package/dist/http/httpClient.js.map +1 -1
- package/dist/index.js +58 -16
- package/dist/index.js.map +1 -1
- package/dist/pty/terminalManager.js +58 -11
- package/dist/pty/terminalManager.js.map +1 -1
- package/dist/services/bootstrapService.js +17 -1
- package/dist/services/bootstrapService.js.map +1 -1
- package/dist/services/claudeAdapterProxy.js +68 -21
- package/dist/services/claudeAdapterProxy.js.map +1 -1
- package/dist/services/cliRuntime.js +5 -5
- package/dist/services/cliRuntime.js.map +1 -1
- package/dist/services/fileService.js +50 -24
- package/dist/services/fileService.js.map +1 -1
- package/dist/services/forkService.js +1 -1
- package/dist/services/forkService.js.map +1 -1
- package/dist/services/modelService.js +62 -18
- package/dist/services/modelService.js.map +1 -1
- package/dist/services/pairingService.js +21 -15
- package/dist/services/pairingService.js.map +1 -1
- package/dist/services/sessionService.js +204 -85
- package/dist/services/sessionService.js.map +1 -1
- package/dist/services/tunnelHelpers.js +9 -5
- package/dist/services/tunnelHelpers.js.map +1 -1
- package/dist/services/tunnelService.js +17 -0
- package/dist/services/tunnelService.js.map +1 -1
- package/dist/transport/wsClient.js +60 -38
- package/dist/transport/wsClient.js.map +1 -1
- package/dist/utils/json.js +7 -0
- package/dist/utils/json.js.map +1 -0
- package/dist/utils/localHost.js +17 -0
- package/dist/utils/localHost.js.map +1 -0
- package/dist/utils/safePath.js +51 -20
- package/dist/utils/safePath.js.map +1 -1
- package/package.json +62 -62
|
@@ -1,28 +1,50 @@
|
|
|
1
|
-
//
|
|
1
|
+
// thinking blocks, whose text the app never shows
|
|
2
|
+
export const isThinkingBlock = (block) => {
|
|
3
|
+
const type = block?.type;
|
|
4
|
+
return type === 'thinking' || type === 'redacted_thinking';
|
|
5
|
+
};
|
|
6
|
+
// milliseconds of thinking as the whole seconds the app shows, at least one
|
|
7
|
+
export const thinkingSeconds = (ms) => Math.max(1, Math.round(ms / 1000));
|
|
8
|
+
// a compaction as the app draws it, from a jsonl compact_boundary line or the live frame
|
|
9
|
+
export function compactBoundaryMessage(entry, timestamp) {
|
|
10
|
+
const meta = (entry['compactMetadata'] ?? entry['compact_metadata'] ?? {});
|
|
11
|
+
const pre = meta['preTokens'] ?? meta['pre_tokens'];
|
|
12
|
+
const post = meta['postTokens'] ?? meta['post_tokens'];
|
|
13
|
+
return {
|
|
14
|
+
role: 'compact',
|
|
15
|
+
content: 'Conversation compacted',
|
|
16
|
+
id: typeof entry['uuid'] === 'string' ? entry['uuid'] : undefined,
|
|
17
|
+
timestamp: timestamp ?? (typeof entry['timestamp'] === 'string' ? entry['timestamp'] : undefined),
|
|
18
|
+
...(typeof pre === 'number' && typeof post === 'number' ? { savedTokens: Math.max(0, pre - post) } : {}),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
// record the tool results carried by a user message, failed or rejected ones flagged
|
|
2
22
|
export function rememberToolResults(msg, results) {
|
|
3
23
|
const content = msg.message?.content;
|
|
4
24
|
if (!Array.isArray(content))
|
|
5
|
-
return
|
|
6
|
-
const
|
|
25
|
+
return;
|
|
26
|
+
const result = typeof msg.toolUseResult === 'object' ? msg.toolUseResult : undefined;
|
|
7
27
|
for (const block of content) {
|
|
8
28
|
if (block.type !== 'tool_result' || typeof block.tool_use_id !== 'string')
|
|
9
29
|
continue;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
30
|
+
if (!msg.toolUseResult && !block.is_error)
|
|
31
|
+
continue;
|
|
32
|
+
results.set(block.tool_use_id, {
|
|
33
|
+
type: result?.type,
|
|
34
|
+
originalFile: result?.originalFile,
|
|
35
|
+
structuredPatch: result?.structuredPatch,
|
|
36
|
+
...(block.is_error ? { isError: true } : {}),
|
|
37
|
+
});
|
|
17
38
|
}
|
|
18
|
-
return failed;
|
|
19
39
|
}
|
|
20
|
-
|
|
21
|
-
const
|
|
40
|
+
// each rule matches the whole message, so a prompt that only mentions these words still shows
|
|
41
|
+
const NOISE_TAGS_RE = /^\s*<(local-command-|\/local-command-|command-name>|command-message>|command-args>)/i;
|
|
42
|
+
const NOISE_INTERRUPT_RE = /^\[?(request )?interrupted (by user|the running process)[^\]\n]*\]?$/i;
|
|
22
43
|
const UUID_LINE_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\s*$/i;
|
|
23
44
|
const NO_RESPONSE_TEXT = 'No response requested.';
|
|
45
|
+
const FILE_TOOLS = new Set(['Write', 'Edit', 'SearchReplace']);
|
|
24
46
|
// parse one claude jsonl message into the app-facing transcript shape
|
|
25
|
-
export function parseTranscriptMessage(message, options) {
|
|
47
|
+
export function parseTranscriptMessage(message, options = {}) {
|
|
26
48
|
if (message.type !== 'user' && message.type !== 'assistant')
|
|
27
49
|
return null;
|
|
28
50
|
if (!message.message)
|
|
@@ -32,14 +54,11 @@ export function parseTranscriptMessage(message, options) {
|
|
|
32
54
|
const role = message.message.role;
|
|
33
55
|
if (!role || role === 'system')
|
|
34
56
|
return null;
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
if (message.uuid)
|
|
38
|
-
options.seenUuids?.add(message.uuid);
|
|
39
|
-
const { content, toolUses } = parseMessageContent(message.message.content ?? '', options);
|
|
40
|
-
if (!content && toolUses.length === 0)
|
|
57
|
+
const { content, toolUses, images } = parseMessageContent(message.message.content ?? '', options);
|
|
58
|
+
if (!content && toolUses.length === 0 && images.length === 0)
|
|
41
59
|
return null;
|
|
42
|
-
|
|
60
|
+
// only claude code's own user entries are noise; an assistant reply is never dropped
|
|
61
|
+
if (!options.includeNoise && role === 'user' && content && isNoiseTranscript(content))
|
|
43
62
|
return null;
|
|
44
63
|
return {
|
|
45
64
|
role,
|
|
@@ -47,7 +66,7 @@ export function parseTranscriptMessage(message, options) {
|
|
|
47
66
|
id: message.uuid,
|
|
48
67
|
timestamp: options.timestamp ?? message.timestamp,
|
|
49
68
|
toolUses: toolUses.length > 0 ? toolUses : undefined,
|
|
50
|
-
|
|
69
|
+
images: images.length > 0 ? images : undefined,
|
|
51
70
|
agentId: message.agentId,
|
|
52
71
|
isSidechain: message.isSidechain,
|
|
53
72
|
};
|
|
@@ -58,53 +77,53 @@ export function isNoiseTranscript(content) {
|
|
|
58
77
|
return false;
|
|
59
78
|
if (NOISE_TAGS_RE.test(content))
|
|
60
79
|
return true;
|
|
61
|
-
if (NOISE_INTERRUPT_RE.test(content))
|
|
80
|
+
if (NOISE_INTERRUPT_RE.test(content.trim()))
|
|
62
81
|
return true;
|
|
63
82
|
if (UUID_LINE_RE.test(content.trim()))
|
|
64
83
|
return true;
|
|
65
84
|
return false;
|
|
66
85
|
}
|
|
67
|
-
//
|
|
86
|
+
// the base64 image blocks of a message content, in order
|
|
87
|
+
export function imageBlocks(content) {
|
|
88
|
+
if (!Array.isArray(content))
|
|
89
|
+
return [];
|
|
90
|
+
return content
|
|
91
|
+
.filter((block) => block?.type === 'image' && block.source?.type === 'base64' && typeof block.source.data === 'string')
|
|
92
|
+
.map((block) => ({ mimeType: block.source.media_type ?? 'image/png', data: block.source.data }));
|
|
93
|
+
}
|
|
94
|
+
// flatten mixed text/tool/image blocks into user-visible content, tool metadata and image refs
|
|
68
95
|
function parseMessageContent(content, options) {
|
|
69
|
-
if (typeof content === 'string')
|
|
70
|
-
return { content, toolUses: [] };
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
return { content: '', toolUses: [] };
|
|
74
|
-
}
|
|
96
|
+
if (typeof content === 'string')
|
|
97
|
+
return { content, toolUses: [], images: [] };
|
|
98
|
+
if (!Array.isArray(content))
|
|
99
|
+
return { content: '', toolUses: [], images: [] };
|
|
75
100
|
const textContent = content
|
|
76
101
|
.filter((block) => block.type === 'text' && block.text && block.text.trim() !== NO_RESPONSE_TEXT)
|
|
77
102
|
.map((block) => block.text ?? '')
|
|
78
103
|
.join('');
|
|
79
|
-
const toolUses =
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
toolUse.input['tool_error'] = true;
|
|
89
|
-
if (result?.structuredPatch)
|
|
90
|
-
toolUse.input['structuredPatch'] = result.structuredPatch;
|
|
91
|
-
if (result?.type)
|
|
92
|
-
toolUse.input['file_change_type'] = result.type;
|
|
93
|
-
if (result && 'originalFile' in result)
|
|
94
|
-
toolUse.input['original_file'] = result.originalFile;
|
|
95
|
-
enrichFileChangeTool(toolUse, options);
|
|
96
|
-
toolUses.push(toolUse);
|
|
97
|
-
}
|
|
98
|
-
return { content: textContent, toolUses };
|
|
99
|
-
}
|
|
100
|
-
function getToolFilePath(toolUse) {
|
|
101
|
-
return toolUse.input['file_path'] ?? toolUse.input['path'] ?? '';
|
|
104
|
+
const toolUses = content
|
|
105
|
+
.filter((block) => block.type === 'tool_use' && block.name)
|
|
106
|
+
.map((block) => toToolUse(block, options.toolResults));
|
|
107
|
+
const images = imageBlocks(content).map((image, index) => ({
|
|
108
|
+
index,
|
|
109
|
+
mimeType: image.mimeType,
|
|
110
|
+
sizeBytes: Math.floor((image.data.length * 3) / 4),
|
|
111
|
+
}));
|
|
112
|
+
return { content: textContent, toolUses, images };
|
|
102
113
|
}
|
|
103
|
-
function
|
|
104
|
-
|
|
114
|
+
function toToolUse(block, results) {
|
|
115
|
+
const toolUse = { toolName: block.name, input: { ...(block.input ?? {}) } };
|
|
116
|
+
if (typeof block.id !== 'string')
|
|
117
|
+
return toolUse;
|
|
118
|
+
toolUse.input['tool_use_id'] = block.id;
|
|
119
|
+
const result = results?.get(block.id);
|
|
120
|
+
if (result?.isError)
|
|
121
|
+
toolUse.input['tool_error'] = true;
|
|
122
|
+
if (FILE_TOOLS.has(toolUse.toolName))
|
|
123
|
+
addDiffHints(toolUse, result);
|
|
124
|
+
return toolUse;
|
|
105
125
|
}
|
|
106
|
-
function parseStructuredPatch(
|
|
107
|
-
const raw = input['structured_patch'] ?? input['structuredPatch'];
|
|
126
|
+
function parseStructuredPatch(raw) {
|
|
108
127
|
if (!Array.isArray(raw))
|
|
109
128
|
return [];
|
|
110
129
|
const patches = [];
|
|
@@ -119,13 +138,17 @@ function parseStructuredPatch(input) {
|
|
|
119
138
|
patches.push({
|
|
120
139
|
oldStart,
|
|
121
140
|
newStart,
|
|
122
|
-
oldLines: typeof patch['oldLines'] === 'number' ? patch['oldLines'] : undefined,
|
|
123
|
-
newLines: typeof patch['newLines'] === 'number' ? patch['newLines'] : undefined,
|
|
124
141
|
lines: Array.isArray(patch['lines']) ? patch['lines'].filter((line) => typeof line === 'string') : undefined,
|
|
125
142
|
});
|
|
126
143
|
}
|
|
127
144
|
return patches;
|
|
128
145
|
}
|
|
146
|
+
// a patch hunk as the old and the new text it spans, context lines on both sides
|
|
147
|
+
function toHunk(patch) {
|
|
148
|
+
const lines = patch.lines ?? [];
|
|
149
|
+
const side = (other) => lines.filter((line) => !line.startsWith(other) && !line.startsWith('\\')).map((line) => line.slice(1)).join('\n');
|
|
150
|
+
return { oldStart: patch.oldStart, newStart: patch.newStart, oldText: side('+'), newText: side('-') };
|
|
151
|
+
}
|
|
129
152
|
export function findStartLine(content, needle) {
|
|
130
153
|
if (!needle)
|
|
131
154
|
return null;
|
|
@@ -140,43 +163,25 @@ function setStartLines(toolUse, oldStart, newStart) {
|
|
|
140
163
|
if (newStart !== null)
|
|
141
164
|
toolUse.input['new_start_line'] = newStart;
|
|
142
165
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
const
|
|
147
|
-
if (
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
}
|
|
154
|
-
function addDiffHints(toolUse, filePath, options) {
|
|
155
|
-
const patches = parseStructuredPatch(toolUse.input);
|
|
156
|
-
if (patches.length > 0)
|
|
157
|
-
setStartLines(toolUse, patches[0].oldStart, patches[0].newStart);
|
|
158
|
-
// the tool result carries the file as it was
|
|
159
|
-
const original = toolUse.input['original_file'];
|
|
160
|
-
const oldContent = typeof original === 'string'
|
|
161
|
-
? original
|
|
162
|
-
: original === null ? null : options.fileContentReader?.(options.sessionId, filePath) ?? null;
|
|
163
|
-
if (toolUse.toolName !== 'Write') {
|
|
164
|
-
if (toolUse.input['old_start_line'] !== undefined)
|
|
165
|
-
return;
|
|
166
|
-
const oldStr = getToolString(toolUse, 'old_string', 'old_str');
|
|
167
|
-
const startLine = oldContent === null ? null : findStartLine(oldContent, oldStr);
|
|
168
|
-
setStartLines(toolUse, startLine, startLine);
|
|
166
|
+
// what the app needs to draw a file change: start lines, and for an overwrite only the
|
|
167
|
+
// changed hunks; whole files stay on the machine
|
|
168
|
+
function addDiffHints(toolUse, result) {
|
|
169
|
+
const patches = parseStructuredPatch(result?.structuredPatch);
|
|
170
|
+
if (toolUse.toolName === 'Write') {
|
|
171
|
+
if (patches.length > 0 && result?.type !== 'create') {
|
|
172
|
+
toolUse.input['hunks'] = patches.map(toHunk);
|
|
173
|
+
delete toolUse.input['content'];
|
|
174
|
+
}
|
|
175
|
+
setStartLines(toolUse, patches[0]?.oldStart ?? 1, patches[0]?.newStart ?? 1);
|
|
169
176
|
return;
|
|
170
177
|
}
|
|
171
|
-
if (
|
|
172
|
-
|
|
173
|
-
setStartLines(toolUse, 1, 1);
|
|
178
|
+
if (patches.length > 0) {
|
|
179
|
+
setStartLines(toolUse, patches[0].oldStart, patches[0].newStart);
|
|
174
180
|
return;
|
|
175
181
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
setStartLines(toolUse, 1, 1);
|
|
182
|
+
// no patch yet: place the edit in the file as it was
|
|
183
|
+
const original = typeof result?.originalFile === 'string' ? result.originalFile : null;
|
|
184
|
+
const startLine = original === null ? null : findStartLine(original, (toolUse.input['old_string'] ?? toolUse.input['old_str'] ?? ''));
|
|
185
|
+
setStartLines(toolUse, startLine, startLine);
|
|
181
186
|
}
|
|
182
187
|
//# sourceMappingURL=transcriptParser.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transcriptParser.js","sourceRoot":"","sources":["../../src/claude/transcriptParser.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"transcriptParser.js","sourceRoot":"","sources":["../../src/claude/transcriptParser.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/cliArgs.js
CHANGED
|
@@ -51,6 +51,7 @@ export function printHelp() {
|
|
|
51
51
|
console.log(' - run `kumo` without `claude` or `codex` to choose from the menu');
|
|
52
52
|
console.log(' - codex is currently under development');
|
|
53
53
|
console.log(' - `reset` clears only the selected agent credentials and keeps the device identity');
|
|
54
|
+
console.log(' - `kumo claude --allow-remote-config` lets the app change user-wide hooks, permission rules and mcp servers');
|
|
54
55
|
console.log('');
|
|
55
56
|
}
|
|
56
57
|
//# sourceMappingURL=cliArgs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cliArgs.js","sourceRoot":"","sources":["../../src/commands/cliArgs.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cliArgs.js","sourceRoot":"","sources":["../../src/commands/cliArgs.ts"],"names":[],"mappings":"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"}
|
package/dist/core/config.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
|
-
import { fileURLToPath } from 'node:url';
|
|
3
1
|
// normalize raw user-supplied url into an http/https origin (no trailing /ws)
|
|
4
2
|
export function normalizeServerHttpUrl(input) {
|
|
5
3
|
const u = new URL(input);
|
|
@@ -37,9 +35,6 @@ export function SERVER_WS() {
|
|
|
37
35
|
_serverWs = normalizeServerWsUrl(process.env.KUMO_SERVER_WS_URL ?? process.env.KUMO_SERVER_URL ?? 'wss://kumocli.com/ws');
|
|
38
36
|
return _serverWs;
|
|
39
37
|
}
|
|
40
|
-
// resolve project-relative directories from this module's compiled location (dist/core/config.js)
|
|
41
|
-
const moduleDir = path.resolve(fileURLToPath(import.meta.url), '..');
|
|
42
|
-
export const LOGS_DIR = path.resolve(moduleDir, '..', '..', 'logs');
|
|
43
38
|
// file watcher debounce
|
|
44
39
|
export const FILE_WATCH_DEBOUNCE_MS = 300;
|
|
45
40
|
//# sourceMappingURL=config.js.map
|
package/dist/core/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,MAAM,UAAU,sBAAsB,CAAC,KAAa;IAClD,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IACzB,IAAI,CAAC,CAAC,QAAQ,KAAK,KAAK;QAAE,CAAC,CAAC,QAAQ,GAAG,OAAO,CAAC;IAC/C,IAAI,CAAC,CAAC,QAAQ,KAAK,MAAM;QAAE,CAAC,CAAC,QAAQ,GAAG,QAAQ,CAAC;IACjD,IAAI,CAAC,CAAC,QAAQ,KAAK,KAAK;QAAE,CAAC,CAAC,QAAQ,GAAG,GAAG,CAAC;IAC3C,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;IAC5E,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACzC,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,oBAAoB,CAAC,KAAa;IAChD,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IACzB,IAAI,CAAC,CAAC,QAAQ,KAAK,OAAO;QAAE,CAAC,CAAC,QAAQ,GAAG,KAAK,CAAC;IAC/C,IAAI,CAAC,CAAC,QAAQ,KAAK,QAAQ;QAAE,CAAC,CAAC,QAAQ,GAAG,MAAM,CAAC;IACjD,IAAI,CAAC,CAAC,QAAQ,KAAK,GAAG,IAAI,CAAC,CAAC,QAAQ,KAAK,EAAE;QAAE,CAAC,CAAC,QAAQ,GAAG,KAAK,CAAC;IAChE,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACzC,CAAC;AAED,mEAAmE;AACnE,IAAI,WAAW,GAAkB,IAAI,CAAC;AACtC,IAAI,SAAS,GAAkB,IAAI,CAAC;AAEpC,MAAM,UAAU,WAAW;IACzB,IAAI,CAAC,WAAW;QAAE,WAAW,GAAG,sBAAsB,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,qBAAqB,CAAC,CAAC;IACjJ,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,IAAI,CAAC,SAAS;QAAE,SAAS,GAAG,oBAAoB,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,sBAAsB,CAAC,CAAC;IAC1I,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,wBAAwB;AACxB,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,CAAC"}
|
package/dist/core/logger.js
CHANGED
|
@@ -1,14 +1,55 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import {
|
|
3
|
+
import { kumoDir } from '../auth/credentialsStore.js';
|
|
4
|
+
// each run writes one log; only the newest few are kept
|
|
5
|
+
const KEEP_LOGS = 10;
|
|
4
6
|
let eventStream = null;
|
|
7
|
+
// the log folder could not be written: the cli goes on without a log
|
|
8
|
+
let disabled = false;
|
|
9
|
+
// in the user's kumo folder, not the package: a global npm install may not be writable and is
|
|
10
|
+
// replaced on every upgrade
|
|
11
|
+
export function logsDir() {
|
|
12
|
+
return path.join(kumoDir(), 'logs');
|
|
13
|
+
}
|
|
14
|
+
// delete all but the newest [keep] cli logs in [dir]
|
|
15
|
+
export function pruneLogs(dir, keep) {
|
|
16
|
+
try {
|
|
17
|
+
const logs = fs
|
|
18
|
+
.readdirSync(dir)
|
|
19
|
+
.filter((name) => name.startsWith('cli-') && name.endsWith('.log'))
|
|
20
|
+
.map((name) => path.join(dir, name))
|
|
21
|
+
.sort((a, b) => fs.statSync(b).mtimeMs - fs.statSync(a).mtimeMs);
|
|
22
|
+
for (const old of logs.slice(keep)) {
|
|
23
|
+
try {
|
|
24
|
+
fs.unlinkSync(old);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// still open in another cli; it goes next time
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
// nothing to prune
|
|
33
|
+
}
|
|
34
|
+
}
|
|
5
35
|
// lazily create the log directory and stream on first use to avoid import side effects
|
|
6
36
|
function ensureStream() {
|
|
7
|
-
if (
|
|
8
|
-
|
|
9
|
-
|
|
37
|
+
if (eventStream || disabled)
|
|
38
|
+
return eventStream;
|
|
39
|
+
try {
|
|
40
|
+
const dir = logsDir();
|
|
41
|
+
fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
42
|
+
pruneLogs(dir, KEEP_LOGS - 1);
|
|
10
43
|
const sessionStart = new Date().toISOString().replace(/[:.]/g, '-');
|
|
11
|
-
eventStream = fs.createWriteStream(path.join(
|
|
44
|
+
eventStream = fs.createWriteStream(path.join(dir, `cli-${sessionStart}.log`), { flags: 'w', mode: 0o600 });
|
|
45
|
+
// a write error later (disk full, folder removed) turns logging off instead of crashing the cli
|
|
46
|
+
eventStream.on('error', () => {
|
|
47
|
+
disabled = true;
|
|
48
|
+
eventStream = null;
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
disabled = true;
|
|
12
53
|
}
|
|
13
54
|
return eventStream;
|
|
14
55
|
}
|
|
@@ -17,6 +58,6 @@ function redact(data) {
|
|
|
17
58
|
}
|
|
18
59
|
// log a structured event line with iso timestamp
|
|
19
60
|
export function log(msg) {
|
|
20
|
-
ensureStream()
|
|
61
|
+
ensureStream()?.write(`[${new Date().toISOString()}] ${redact(msg)}\n`);
|
|
21
62
|
}
|
|
22
63
|
//# sourceMappingURL=logger.js.map
|
package/dist/core/logger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/core/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/core/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,56 +1,120 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
2
3
|
import { FILE_WATCH_DEBOUNCE_MS } from './config.js';
|
|
3
4
|
import { log } from './logger.js';
|
|
4
|
-
import {
|
|
5
|
-
// watch the
|
|
5
|
+
import { projectRootOf, safePath } from '../utils/safePath.js';
|
|
6
|
+
// watch a project only while the app's Files tab is on screen, and only what it shows: the
|
|
7
|
+
// listed folder and the open file's folder, each without descending into subfolders
|
|
6
8
|
export class ProjectFileWatcher {
|
|
7
9
|
send;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
+
watchers = new Map();
|
|
11
|
+
target = null;
|
|
12
|
+
pending = new Map();
|
|
13
|
+
flushTimer = null;
|
|
10
14
|
constructor(send) {
|
|
11
15
|
this.send = send;
|
|
12
16
|
}
|
|
13
|
-
//
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const previous = this.debounceMap.get(normalized);
|
|
27
|
-
if (previous)
|
|
28
|
-
clearTimeout(previous);
|
|
29
|
-
this.debounceMap.set(normalized, setTimeout(() => {
|
|
30
|
-
this.debounceMap.delete(normalized);
|
|
31
|
-
this.send({ type: 'file_changed', path: normalized, event });
|
|
32
|
-
log(`[watcher] ${event}: ${normalized}`);
|
|
33
|
-
}, FILE_WATCH_DEBOUNCE_MS));
|
|
34
|
-
});
|
|
35
|
-
log(`[watcher] watching ${projectRoot}`);
|
|
17
|
+
// follow the Files tab; null (tab hidden, app gone) stops watching altogether
|
|
18
|
+
subscribe(target) {
|
|
19
|
+
if (!target)
|
|
20
|
+
return this.stop();
|
|
21
|
+
if (target.root !== this.target?.root)
|
|
22
|
+
this.stop();
|
|
23
|
+
this.target = target;
|
|
24
|
+
const dirs = new Set([target.dir, ...(target.file ? [path.posix.dirname(target.file).replace(/^\.$/, '')] : [])]);
|
|
25
|
+
for (const [dir, watcher] of this.watchers) {
|
|
26
|
+
if (dirs.has(dir))
|
|
27
|
+
continue;
|
|
28
|
+
watcher.close();
|
|
29
|
+
this.watchers.delete(dir);
|
|
36
30
|
}
|
|
37
|
-
|
|
38
|
-
|
|
31
|
+
for (const dir of dirs) {
|
|
32
|
+
if (!this.watchers.has(dir))
|
|
33
|
+
this.watch(target.root, dir);
|
|
39
34
|
}
|
|
40
35
|
}
|
|
41
|
-
// stop the
|
|
36
|
+
// stop the watchers and drop changes that were not sent yet
|
|
42
37
|
stop() {
|
|
43
|
-
|
|
38
|
+
for (const watcher of this.watchers.values()) {
|
|
44
39
|
try {
|
|
45
|
-
|
|
40
|
+
watcher.close();
|
|
46
41
|
}
|
|
47
42
|
catch { }
|
|
48
|
-
this.watcher = null;
|
|
49
43
|
}
|
|
50
|
-
|
|
51
|
-
|
|
44
|
+
this.watchers.clear();
|
|
45
|
+
this.target = null;
|
|
46
|
+
if (this.flushTimer)
|
|
47
|
+
clearTimeout(this.flushTimer);
|
|
48
|
+
this.flushTimer = null;
|
|
49
|
+
this.pending.clear();
|
|
50
|
+
}
|
|
51
|
+
watch(root, dir) {
|
|
52
|
+
try {
|
|
53
|
+
const watcher = fs.watch(path.join(root, dir), (event, filename) => {
|
|
54
|
+
if (!filename)
|
|
55
|
+
return;
|
|
56
|
+
const file = dir ? `${dir}/${filename}` : filename.toString();
|
|
57
|
+
if (!this.visible(file))
|
|
58
|
+
return;
|
|
59
|
+
// a folder "changes" whenever its own content does; only its creation or removal shows in the listing
|
|
60
|
+
if (event === 'change' && isDirectory(path.join(root, file)))
|
|
61
|
+
return;
|
|
62
|
+
this.pending.set(file, event);
|
|
63
|
+
this.flushTimer ??= setTimeout(() => this.flush(), FILE_WATCH_DEBOUNCE_MS);
|
|
64
|
+
});
|
|
65
|
+
// the folder went away: a later subscribe watches it again
|
|
66
|
+
watcher.on('error', () => {
|
|
67
|
+
watcher.close();
|
|
68
|
+
this.watchers.delete(dir);
|
|
69
|
+
});
|
|
70
|
+
this.watchers.set(dir, watcher);
|
|
71
|
+
log(`[watcher] watching ${path.join(root, dir)}`);
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
log(`[watcher] cannot watch ${dir || '.'}: ${error}`);
|
|
52
75
|
}
|
|
53
|
-
this.debounceMap.clear();
|
|
54
76
|
}
|
|
77
|
+
// the open file, or a non-hidden direct child of the listed folder
|
|
78
|
+
visible(file) {
|
|
79
|
+
const target = this.target;
|
|
80
|
+
if (!target)
|
|
81
|
+
return false;
|
|
82
|
+
if (file === target.file)
|
|
83
|
+
return true;
|
|
84
|
+
const prefix = target.dir ? `${target.dir}/` : '';
|
|
85
|
+
const child = file.startsWith(prefix) ? file.slice(prefix.length) : '';
|
|
86
|
+
return child !== '' && !child.includes('/') && !child.startsWith('.');
|
|
87
|
+
}
|
|
88
|
+
flush() {
|
|
89
|
+
this.flushTimer = null;
|
|
90
|
+
const changes = [...this.pending].map(([file, event]) => ({ path: file, event }));
|
|
91
|
+
this.pending.clear();
|
|
92
|
+
if (changes.length === 0)
|
|
93
|
+
return;
|
|
94
|
+
this.send({ type: 'file_changed', changes });
|
|
95
|
+
log(`[watcher] ${changes.length} change(s)`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// whether a path is a folder; a file being deleted can fail to stat (EPERM on windows)
|
|
99
|
+
function isDirectory(file) {
|
|
100
|
+
try {
|
|
101
|
+
return fs.statSync(file, { throwIfNoEntry: false })?.isDirectory() ?? false;
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// the watch target of a file_watch message; a missing dir means the Files tab is not on screen.
|
|
108
|
+
// dir and file must stay inside the project root
|
|
109
|
+
export function parseFileWatchTarget(msg) {
|
|
110
|
+
if (typeof msg['dir'] !== 'string')
|
|
111
|
+
return null;
|
|
112
|
+
const root = projectRootOf(msg['cwd']);
|
|
113
|
+
const clean = (value) => {
|
|
114
|
+
const relative = value.replace(/\\/g, '/').replace(/^\/+|\/+$/g, '');
|
|
115
|
+
safePath(relative, root);
|
|
116
|
+
return relative;
|
|
117
|
+
};
|
|
118
|
+
return { root, dir: clean(msg['dir']), file: typeof msg['file'] === 'string' ? clean(msg['file']) : null };
|
|
55
119
|
}
|
|
56
120
|
//# sourceMappingURL=projectFileWatcher.js.map
|