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.
- package/README.md +26 -13
- package/dist/auth/credentialsStore.js +20 -7
- 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 +140 -36
- 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 +1 -9
- package/dist/core/config.js.map +1 -1
- package/dist/core/logger.js +50 -21
- 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 +106 -0
- package/dist/engine/claudeArgs.js.map +1 -0
- package/dist/engine/claudeBinary.js +94 -0
- package/dist/engine/claudeBinary.js.map +1 -0
- package/dist/engine/claudeConfig.js +127 -0
- package/dist/engine/claudeConfig.js.map +1 -0
- package/dist/engine/claudeLogin.js +76 -0
- package/dist/engine/claudeLogin.js.map +1 -0
- package/dist/engine/controlChannel.js +75 -0
- package/dist/engine/controlChannel.js.map +1 -0
- package/dist/engine/liveTranscript.js +150 -0
- package/dist/engine/liveTranscript.js.map +1 -0
- package/dist/engine/ndjson.js +48 -0
- package/dist/engine/ndjson.js.map +1 -0
- package/dist/engine/permissions.js +101 -0
- package/dist/engine/permissions.js.map +1 -0
- 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 +444 -0
- package/dist/engine/sessionManager.js.map +1 -0
- package/dist/engine/settingsCommands.js +260 -0
- package/dist/engine/settingsCommands.js.map +1 -0
- package/dist/engine/streamSession.js +502 -0
- package/dist/engine/streamSession.js.map +1 -0
- package/dist/engine/taskTracker.js +110 -0
- package/dist/engine/taskTracker.js.map +1 -0
- 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 +5 -91
- package/dist/handlers/promptImages.js.map +1 -1
- package/dist/handlers/runtimeHandlers.js +100 -32
- package/dist/handlers/runtimeHandlers.js.map +1 -1
- package/dist/handlers/sessionHandlers.js +85 -80
- 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 +87 -50
- 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 +39 -32
- package/dist/services/cliRuntime.js.map +1 -1
- package/dist/services/effortService.js +13 -60
- package/dist/services/effortService.js.map +1 -1
- package/dist/services/fileService.js +50 -24
- package/dist/services/fileService.js.map +1 -1
- package/dist/services/forkService.js +120 -0
- package/dist/services/forkService.js.map +1 -0
- package/dist/services/modelService.js +86 -89
- 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/sessionListService.js +7 -9
- package/dist/services/sessionListService.js.map +1 -1
- package/dist/services/sessionService.js +245 -106
- 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 +21 -5
- package/dist/services/tunnelService.js.map +1 -1
- package/dist/transport/wsClient.js +60 -42
- package/dist/transport/wsClient.js.map +1 -1
- package/dist/utils/ignorePaths.js +3 -3
- package/dist/utils/ignorePaths.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 +5 -12
- package/dist/ansiCodes.js +0 -107
- package/dist/ansiCodes.js.map +0 -1
- package/dist/auth/credentialsStore.test.js +0 -60
- package/dist/auth/credentialsStore.test.js.map +0 -1
- package/dist/claude/fileHistory.js +0 -79
- package/dist/claude/fileHistory.js.map +0 -1
- package/dist/claude/generateHookSettings.js +0 -23
- package/dist/claude/generateHookSettings.js.map +0 -1
- package/dist/claude/hookServer.js +0 -33
- package/dist/claude/hookServer.js.map +0 -1
- package/dist/claude/sessionScanner.js +0 -162
- package/dist/claude/sessionScanner.js.map +0 -1
- package/dist/claude/sessionScanner.test.js +0 -24
- package/dist/claude/sessionScanner.test.js.map +0 -1
- package/dist/claude/transcriptParser.test.js +0 -78
- package/dist/claude/transcriptParser.test.js.map +0 -1
- package/dist/commands/cliArgs.test.js +0 -25
- package/dist/commands/cliArgs.test.js.map +0 -1
- package/dist/config.js +0 -40
- package/dist/config.js.map +0 -1
- package/dist/credentialsStore.js +0 -57
- package/dist/credentialsStore.js.map +0 -1
- package/dist/generateHookSettings.js +0 -30
- package/dist/generateHookSettings.js.map +0 -1
- package/dist/handlers/fileHandlerPayloads.test.js +0 -55
- package/dist/handlers/fileHandlerPayloads.test.js.map +0 -1
- package/dist/handlers/promptImages.test.js +0 -52
- package/dist/handlers/promptImages.test.js.map +0 -1
- package/dist/hookServer.js +0 -32
- package/dist/hookServer.js.map +0 -1
- package/dist/ignorePaths.js +0 -68
- package/dist/ignorePaths.js.map +0 -1
- package/dist/loadDotEnv.js +0 -79
- package/dist/loadDotEnv.js.map +0 -1
- package/dist/logger.js +0 -29
- package/dist/logger.js.map +0 -1
- package/dist/portForwardManager.js +0 -97
- package/dist/portForwardManager.js.map +0 -1
- package/dist/projectHistoryReader.js +0 -85
- package/dist/projectHistoryReader.js.map +0 -1
- package/dist/pty/ansiCodes.js +0 -14
- package/dist/pty/ansiCodes.js.map +0 -1
- package/dist/pty/notificationDetector.js +0 -29
- package/dist/pty/notificationDetector.js.map +0 -1
- package/dist/pty/notificationDetector.test.js +0 -24
- package/dist/pty/notificationDetector.test.js.map +0 -1
- package/dist/pty/ptyMenuParser.js +0 -91
- package/dist/pty/ptyMenuParser.js.map +0 -1
- package/dist/pty/ptyMenuParser.test.js +0 -26
- package/dist/pty/ptyMenuParser.test.js.map +0 -1
- package/dist/pty/ptySnapshotRenderer.js +0 -71
- package/dist/pty/ptySnapshotRenderer.js.map +0 -1
- package/dist/pty/selectionMenuDetector.js +0 -49
- package/dist/pty/selectionMenuDetector.js.map +0 -1
- package/dist/pty/selectionMenuDetector.test.js +0 -62
- package/dist/pty/selectionMenuDetector.test.js.map +0 -1
- package/dist/pty/selectionMenuMeta.js +0 -54
- package/dist/pty/selectionMenuMeta.js.map +0 -1
- package/dist/pty/selectionMenuMeta.test.js +0 -26
- package/dist/pty/selectionMenuMeta.test.js.map +0 -1
- package/dist/pty/selectionMenuParser.js +0 -83
- package/dist/pty/selectionMenuParser.js.map +0 -1
- package/dist/pty/selectionMenuParser.test.js +0 -30
- package/dist/pty/selectionMenuParser.test.js.map +0 -1
- package/dist/pty/spawn.js +0 -104
- package/dist/pty/spawn.js.map +0 -1
- package/dist/pty/spawn.test.js +0 -17
- package/dist/pty/spawn.test.js.map +0 -1
- package/dist/pty/statusSessionDetector.js +0 -28
- package/dist/pty/statusSessionDetector.js.map +0 -1
- package/dist/pty/statusSessionDetector.test.js +0 -23
- package/dist/pty/statusSessionDetector.test.js.map +0 -1
- package/dist/pty/textInputDetector.js +0 -60
- package/dist/pty/textInputDetector.js.map +0 -1
- package/dist/pty/textInputDetector.test.js +0 -32
- package/dist/pty/textInputDetector.test.js.map +0 -1
- package/dist/ptyMenuParser.js +0 -470
- package/dist/ptyMenuParser.js.map +0 -1
- package/dist/ptySnapshotRenderer.js +0 -78
- package/dist/ptySnapshotRenderer.js.map +0 -1
- package/dist/services/checkpointService.js +0 -113
- package/dist/services/checkpointService.js.map +0 -1
- package/dist/services/checkpointService.test.js +0 -61
- package/dist/services/checkpointService.test.js.map +0 -1
- package/dist/services/claudeMenuBridge.js +0 -116
- package/dist/services/claudeMenuBridge.js.map +0 -1
- package/dist/services/claudeMenuBridge.test.js +0 -90
- package/dist/services/claudeMenuBridge.test.js.map +0 -1
- package/dist/services/claudeService.js +0 -146
- package/dist/services/claudeService.js.map +0 -1
- package/dist/services/claudeService.test.js +0 -39
- package/dist/services/claudeService.test.js.map +0 -1
- package/dist/services/cliRuntime.test.js +0 -55
- package/dist/services/cliRuntime.test.js.map +0 -1
- package/dist/services/modelAdapter.test.js +0 -47
- package/dist/services/modelAdapter.test.js.map +0 -1
- package/dist/services/modelArgs.test.js +0 -64
- package/dist/services/modelArgs.test.js.map +0 -1
- package/dist/services/modelBaseUrl.test.js +0 -32
- package/dist/services/modelBaseUrl.test.js.map +0 -1
- package/dist/services/modelService.test.js +0 -136
- package/dist/services/modelService.test.js.map +0 -1
- package/dist/services/notificationDedupe.js +0 -23
- package/dist/services/notificationDedupe.js.map +0 -1
- package/dist/services/notificationDedupe.test.js +0 -20
- package/dist/services/notificationDedupe.test.js.map +0 -1
- package/dist/services/sessionListService.test.js +0 -22
- package/dist/services/sessionListService.test.js.map +0 -1
- package/dist/services/sessionRollbackService.js +0 -195
- package/dist/services/sessionRollbackService.js.map +0 -1
- package/dist/services/sessionRollbackService.test.js +0 -142
- package/dist/services/sessionRollbackService.test.js.map +0 -1
- package/dist/services/tunnelHelpers.test.js +0 -42
- package/dist/services/tunnelHelpers.test.js.map +0 -1
- package/dist/services/tunnelService.test.js +0 -91
- package/dist/services/tunnelService.test.js.map +0 -1
- package/dist/sessionScanner.js +0 -271
- package/dist/sessionScanner.js.map +0 -1
- package/dist/snapshotScanner.js +0 -154
- package/dist/snapshotScanner.js.map +0 -1
- package/dist/spawn.js +0 -79
- package/dist/spawn.js.map +0 -1
- package/dist/terminalManager.js +0 -73
- package/dist/terminalManager.js.map +0 -1
- package/dist/transport/directWsServer.js +0 -135
- package/dist/transport/directWsServer.js.map +0 -1
- package/dist/transport/webrtcTransport.js +0 -145
- package/dist/transport/webrtcTransport.js.map +0 -1
- package/dist/transport/webrtcTransport.test.js +0 -104
- package/dist/transport/webrtcTransport.test.js.map +0 -1
- package/dist/transport/webrtcTypes.js +0 -29
- package/dist/transport/webrtcTypes.js.map +0 -1
- package/dist/transport/webrtcTypes.test.js +0 -20
- package/dist/transport/webrtcTypes.test.js.map +0 -1
- package/dist/utils/ptyBuffer.js +0 -46
- package/dist/utils/ptyBuffer.js.map +0 -1
- package/scripts/claude_launcher.cjs +0 -71
- package/scripts/run-tests.mjs +0 -46
- package/scripts/session_hook_forwarder.cjs +0 -44
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { compactBoundaryMessage, isThinkingBlock, parseTranscriptMessage, thinkingSeconds, rememberToolResults, } from '../claude/transcriptParser.js';
|
|
2
|
+
import { str } from '../utils/json.js';
|
|
3
|
+
// enough history to fold late tool results into their message without growing forever
|
|
4
|
+
const MAX_TRACKED = 300;
|
|
5
|
+
const blocksOf = (content) => Array.isArray(content) ? content.filter((b) => !!b && typeof b === 'object') : [];
|
|
6
|
+
// a block claude may send again: a tool use by its id, text by itself, anything else whole
|
|
7
|
+
const blockKey = (block) => block['type'] === 'tool_use' ? `tool_use:${str(block['id'])}`
|
|
8
|
+
: block['type'] === 'text' ? `text:${str(block['text'])}`
|
|
9
|
+
: JSON.stringify(block);
|
|
10
|
+
// thinking and other blocks show nothing in the app
|
|
11
|
+
const isVisible = (block) => block['type'] === 'text' || block['type'] === 'tool_use';
|
|
12
|
+
// turns stream-json stdout frames into app transcript messages the way the extension renders a
|
|
13
|
+
// live turn: assistant blocks merged by message id (one frame per block), tool results folded
|
|
14
|
+
// into their tool use, prompts from the --replay-user-messages echo under the uuid we sent.
|
|
15
|
+
// every update re-emits the whole message under the same id, so the app replaces it; updates of
|
|
16
|
+
// one tick go out together (parallel tool results) and a change the app cannot see (a thinking
|
|
17
|
+
// block) sends nothing
|
|
18
|
+
export class LiveTranscript {
|
|
19
|
+
emit;
|
|
20
|
+
now;
|
|
21
|
+
assistants = new Map();
|
|
22
|
+
owners = new Map();
|
|
23
|
+
results = new Map();
|
|
24
|
+
dirty = new Set();
|
|
25
|
+
flushTimer = null;
|
|
26
|
+
// the last frame of each thread (the main one, each subagent): a thinking block took the time
|
|
27
|
+
// since then
|
|
28
|
+
lastFrameAt = new Map();
|
|
29
|
+
constructor(emit, now = Date.now) {
|
|
30
|
+
this.emit = emit;
|
|
31
|
+
this.now = now;
|
|
32
|
+
}
|
|
33
|
+
handle(frame) {
|
|
34
|
+
if (frame['type'] === 'assistant')
|
|
35
|
+
this.assistant(frame);
|
|
36
|
+
else if (frame['type'] === 'user')
|
|
37
|
+
this.user(frame);
|
|
38
|
+
else if (frame['type'] === 'system' && frame['subtype'] === 'compact_boundary') {
|
|
39
|
+
this.flush();
|
|
40
|
+
this.emit(compactBoundaryMessage(frame, new Date().toISOString()));
|
|
41
|
+
}
|
|
42
|
+
this.lastFrameAt.set(str(frame['parent_tool_use_id']), this.now());
|
|
43
|
+
}
|
|
44
|
+
// emit the messages updated since the last flush; the session calls it before any other event
|
|
45
|
+
// so the app sees the transcript and the turn state in order
|
|
46
|
+
flush() {
|
|
47
|
+
if (this.flushTimer)
|
|
48
|
+
clearImmediate(this.flushTimer);
|
|
49
|
+
this.flushTimer = null;
|
|
50
|
+
for (const id of this.dirty)
|
|
51
|
+
this.emitAssistant(id);
|
|
52
|
+
this.dirty.clear();
|
|
53
|
+
}
|
|
54
|
+
assistant(frame) {
|
|
55
|
+
const message = frame['message'];
|
|
56
|
+
const id = str(message?.['id']) || str(frame['uuid']);
|
|
57
|
+
if (!id)
|
|
58
|
+
return;
|
|
59
|
+
const entry = this.assistants.get(id) ?? { blocks: [], seen: new Set(), timestamp: new Date().toISOString(), version: 0, sent: 0 };
|
|
60
|
+
for (const block of blocksOf(message?.['content'])) {
|
|
61
|
+
const key = blockKey(block);
|
|
62
|
+
if (entry.seen.has(key))
|
|
63
|
+
continue;
|
|
64
|
+
entry.seen.add(key);
|
|
65
|
+
entry.blocks.push(block);
|
|
66
|
+
// shown with the message's next visible block
|
|
67
|
+
const since = this.lastFrameAt.get(str(frame['parent_tool_use_id']));
|
|
68
|
+
if (isThinkingBlock(block) && since !== undefined)
|
|
69
|
+
entry.thinkingMs = (entry.thinkingMs ?? 0) + this.now() - since;
|
|
70
|
+
if (isVisible(block))
|
|
71
|
+
entry.version++;
|
|
72
|
+
if (block['type'] === 'tool_use' && typeof block['id'] === 'string')
|
|
73
|
+
this.owners.set(block['id'], id);
|
|
74
|
+
}
|
|
75
|
+
entry.parentToolUseId = str(frame['parent_tool_use_id']) || entry.parentToolUseId;
|
|
76
|
+
this.track(id, entry);
|
|
77
|
+
this.publish(id);
|
|
78
|
+
}
|
|
79
|
+
user(frame) {
|
|
80
|
+
// claude's own messages, such as the summary a compaction starts from, are no prompts
|
|
81
|
+
if (frame['isSynthetic'] === true)
|
|
82
|
+
return;
|
|
83
|
+
const parentToolUseId = str(frame['parent_tool_use_id']) || undefined;
|
|
84
|
+
const message = frame['message'];
|
|
85
|
+
const jsonl = {
|
|
86
|
+
type: 'user',
|
|
87
|
+
uuid: str(frame['uuid']) || undefined,
|
|
88
|
+
message,
|
|
89
|
+
toolUseResult: frame['tool_use_result'],
|
|
90
|
+
isSidechain: parentToolUseId !== undefined,
|
|
91
|
+
};
|
|
92
|
+
const toolResults = blocksOf(message?.content).filter((b) => b['type'] === 'tool_result');
|
|
93
|
+
if (toolResults.length > 0) {
|
|
94
|
+
rememberToolResults(jsonl, this.results);
|
|
95
|
+
const owners = new Set(toolResults.map((b) => this.owners.get(str(b['tool_use_id']))));
|
|
96
|
+
for (const owner of owners) {
|
|
97
|
+
const entry = owner ? this.assistants.get(owner) : undefined;
|
|
98
|
+
if (!entry)
|
|
99
|
+
continue;
|
|
100
|
+
entry.version++;
|
|
101
|
+
this.publish(owner);
|
|
102
|
+
}
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const parsed = parseTranscriptMessage(jsonl, { timestamp: new Date().toISOString() });
|
|
106
|
+
if (!parsed)
|
|
107
|
+
return;
|
|
108
|
+
this.flush();
|
|
109
|
+
this.emit(parentToolUseId ? { ...parsed, parentToolUseId } : parsed);
|
|
110
|
+
}
|
|
111
|
+
publish(id) {
|
|
112
|
+
this.dirty.add(id);
|
|
113
|
+
this.flushTimer ??= setImmediate(() => this.flush());
|
|
114
|
+
}
|
|
115
|
+
emitAssistant(id) {
|
|
116
|
+
const entry = this.assistants.get(id);
|
|
117
|
+
if (!entry || entry.sent === entry.version)
|
|
118
|
+
return;
|
|
119
|
+
const parsed = parseTranscriptMessage({
|
|
120
|
+
type: 'assistant',
|
|
121
|
+
uuid: id,
|
|
122
|
+
message: { role: 'assistant', content: entry.blocks },
|
|
123
|
+
isSidechain: entry.parentToolUseId !== undefined,
|
|
124
|
+
}, { timestamp: entry.timestamp, toolResults: this.results });
|
|
125
|
+
entry.sent = entry.version;
|
|
126
|
+
if (!parsed)
|
|
127
|
+
return;
|
|
128
|
+
this.emit({
|
|
129
|
+
...parsed,
|
|
130
|
+
...(entry.parentToolUseId ? { parentToolUseId: entry.parentToolUseId } : {}),
|
|
131
|
+
...(entry.thinkingMs !== undefined ? { thinkingSeconds: thinkingSeconds(entry.thinkingMs) } : {}),
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
track(id, entry) {
|
|
135
|
+
this.assistants.delete(id);
|
|
136
|
+
this.assistants.set(id, entry);
|
|
137
|
+
while (this.assistants.size > MAX_TRACKED) {
|
|
138
|
+
const [oldest, old] = this.assistants.entries().next().value;
|
|
139
|
+
this.assistants.delete(oldest);
|
|
140
|
+
for (const block of old.blocks) {
|
|
141
|
+
const toolId = str(block['id']);
|
|
142
|
+
if (toolId && this.owners.get(toolId) === oldest) {
|
|
143
|
+
this.owners.delete(toolId);
|
|
144
|
+
this.results.delete(toolId);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=liveTranscript.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"liveTranscript.js","sourceRoot":"","sources":["../../src/engine/liveTranscript.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { log } from '../core/logger.js';
|
|
2
|
+
// read line-delimited json from a stream, tolerating partial chunks and skipping blank/non-json lines
|
|
3
|
+
export function readNdjson(stream, onMessage) {
|
|
4
|
+
// the start of a line still waiting for its newline, in pieces: joined once when it ends,
|
|
5
|
+
// so a 20 MB line (an echoed prompt with images) is not copied and searched per chunk
|
|
6
|
+
let parts = [];
|
|
7
|
+
const handleLine = (raw) => {
|
|
8
|
+
const line = raw.trim();
|
|
9
|
+
if (!line)
|
|
10
|
+
return;
|
|
11
|
+
let parsed;
|
|
12
|
+
try {
|
|
13
|
+
parsed = JSON.parse(line);
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
log(`[ndjson] skipped non-json line: ${line.slice(0, 200)}`);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed))
|
|
20
|
+
onMessage(parsed);
|
|
21
|
+
};
|
|
22
|
+
stream.setEncoding('utf8');
|
|
23
|
+
stream.on('data', (chunk) => {
|
|
24
|
+
// only the new chunk is searched for line ends
|
|
25
|
+
let start = 0;
|
|
26
|
+
for (let index = chunk.indexOf('\n'); index >= 0; index = chunk.indexOf('\n', start)) {
|
|
27
|
+
parts.push(chunk.slice(start, index));
|
|
28
|
+
handleLine(parts.join(''));
|
|
29
|
+
parts = [];
|
|
30
|
+
start = index + 1;
|
|
31
|
+
}
|
|
32
|
+
if (start < chunk.length)
|
|
33
|
+
parts.push(chunk.slice(start));
|
|
34
|
+
});
|
|
35
|
+
stream.on('end', () => {
|
|
36
|
+
if (parts.length > 0)
|
|
37
|
+
handleLine(parts.join(''));
|
|
38
|
+
parts = [];
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
// write one json message followed by a newline; returns false when the stream is no longer writable
|
|
42
|
+
export function writeNdjson(stream, msg) {
|
|
43
|
+
if (stream.destroyed || stream.writableEnded)
|
|
44
|
+
return false;
|
|
45
|
+
stream.write(`${JSON.stringify(msg)}\n`);
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=ndjson.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ndjson.js","sourceRoot":"","sources":["../../src/engine/ndjson.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAIxC,sGAAsG;AACtG,MAAM,UAAU,UAAU,CAAC,MAAgB,EAAE,SAAoC;IAC/E,0FAA0F;IAC1F,sFAAsF;IACtF,IAAI,KAAK,GAAa,EAAE,CAAC;IACzB,MAAM,UAAU,GAAG,CAAC,GAAW,EAAQ,EAAE;QACvC,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;QACxB,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,IAAI,MAAe,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;QAAC,MAAM,CAAC;YACP,GAAG,CAAC,mCAAmC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;YAC7D,OAAO;QACT,CAAC;QACD,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,SAAS,CAAC,MAAoB,CAAC,CAAC;IACtG,CAAC,CAAC;IACF,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3B,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;QAClC,+CAA+C;QAC/C,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,KAAK,IAAI,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC;YACrF,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;YACtC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YAC3B,KAAK,GAAG,EAAE,CAAC;YACX,KAAK,GAAG,KAAK,GAAG,CAAC,CAAC;QACpB,CAAC;QACD,IAAI,KAAK,GAAG,KAAK,CAAC,MAAM;YAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IACH,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;QACpB,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QACjD,KAAK,GAAG,EAAE,CAAC;IACb,CAAC,CAAC,CAAC;AACL,CAAC;AAED,oGAAoG;AACpG,MAAM,UAAU,WAAW,CAAC,MAAgB,EAAE,GAAY;IACxD,IAAI,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,aAAa;QAAE,OAAO,KAAK,CAAC;IAC3D,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACzC,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { remoteUserConfigAllowed } from './remoteConfig.js';
|
|
2
|
+
const PERMISSION_MODES = new Set(['default', 'acceptEdits', 'plan', 'bypassPermissions', 'auto', 'dontAsk']);
|
|
3
|
+
const DESTINATIONS = new Set(['userSettings', 'projectSettings', 'localSettings', 'session', 'cliArg']);
|
|
4
|
+
// approving a plan with "manually approve edits" sends this update even though the cli never suggests it
|
|
5
|
+
const RESET_MODE_UPDATE = { type: 'setMode', mode: 'default', destination: 'session' };
|
|
6
|
+
export const DEFAULT_DENY_MESSAGE = "The user doesn't want to proceed with this tool use. The tool use was rejected (eg. if it was a file edit, the new_string was NOT written to the file). STOP what you are doing and wait for the user to tell you how to proceed.";
|
|
7
|
+
export function isPermissionMode(value) {
|
|
8
|
+
return typeof value === 'string' && PERMISSION_MODES.has(value);
|
|
9
|
+
}
|
|
10
|
+
const str = (value) => (typeof value === 'string' ? value : undefined);
|
|
11
|
+
const bool = (value) => (typeof value === 'boolean' ? value : undefined);
|
|
12
|
+
export const stripAnsi = (value) => value?.replace(/\x1b\[[0-9;]*[A-Za-z]/g, '');
|
|
13
|
+
function kindOf(toolName) {
|
|
14
|
+
if (toolName === 'AskUserQuestion')
|
|
15
|
+
return 'ask_user_question';
|
|
16
|
+
if (toolName === 'ExitPlanMode')
|
|
17
|
+
return 'exit_plan_mode';
|
|
18
|
+
return 'tool';
|
|
19
|
+
}
|
|
20
|
+
// map a cli can_use_tool request into the ws v2 claude_permission_request payload
|
|
21
|
+
export function toPermissionRequest(sessionId, requestId, request) {
|
|
22
|
+
const toolName = str(request['tool_name']) ?? 'unknown';
|
|
23
|
+
const input = request['input'] && typeof request['input'] === 'object' ? request['input'] : {};
|
|
24
|
+
const suggestions = Array.isArray(request['permission_suggestions'])
|
|
25
|
+
? request['permission_suggestions'].filter((s) => !!s && typeof s === 'object')
|
|
26
|
+
: [];
|
|
27
|
+
return {
|
|
28
|
+
type: 'claude_permission_request',
|
|
29
|
+
sessionId,
|
|
30
|
+
requestId,
|
|
31
|
+
kind: kindOf(toolName),
|
|
32
|
+
toolName,
|
|
33
|
+
displayName: str(request['display_name']),
|
|
34
|
+
title: str(request['title']),
|
|
35
|
+
description: str(request['description']),
|
|
36
|
+
input,
|
|
37
|
+
toolUseId: str(request['tool_use_id']),
|
|
38
|
+
suggestions,
|
|
39
|
+
decisionReason: stripAnsi(str(request['decision_reason'])),
|
|
40
|
+
blockedPath: str(request['blocked_path']),
|
|
41
|
+
defaultToNo: bool(request['default_to_no']),
|
|
42
|
+
suppressAlwaysAllowRule: bool(request['suppress_always_allow_rule']),
|
|
43
|
+
requiresUserInteraction: bool(request['requires_user_interaction']),
|
|
44
|
+
agentId: str(request['agent_id']),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
// json with sorted object keys so structurally equal updates compare equal
|
|
48
|
+
function canonical(value) {
|
|
49
|
+
return JSON.stringify(value, (_key, v) => (v && typeof v === 'object' && !Array.isArray(v)
|
|
50
|
+
? Object.fromEntries(Object.entries(v).sort(([a], [b]) => (a < b ? -1 : 1)))
|
|
51
|
+
: v));
|
|
52
|
+
}
|
|
53
|
+
// keep only updates the prompt offered (rules may change destination); drop bypass unless allowed.
|
|
54
|
+
// without --allow-remote-config a rule meant for user settings lands in this project's local ones
|
|
55
|
+
export function filterPermissionUpdates(updates, suggestions, allowBypass) {
|
|
56
|
+
if (!Array.isArray(updates))
|
|
57
|
+
return [];
|
|
58
|
+
const resetMode = canonical(RESET_MODE_UPDATE);
|
|
59
|
+
const local = (u) => u['destination'] === 'userSettings' && !remoteUserConfigAllowed() ? { ...u, destination: 'localSettings' } : u;
|
|
60
|
+
return updates.filter((update) => {
|
|
61
|
+
if (!update || typeof update !== 'object')
|
|
62
|
+
return false;
|
|
63
|
+
const u = update;
|
|
64
|
+
if (u['type'] === 'setMode' && u['mode'] === 'bypassPermissions' && !allowBypass)
|
|
65
|
+
return false;
|
|
66
|
+
const key = canonical(u);
|
|
67
|
+
if (key === resetMode)
|
|
68
|
+
return true;
|
|
69
|
+
const destination = u['destination'];
|
|
70
|
+
return suggestions.some((s) => (s['type'] === 'setMode'
|
|
71
|
+
? key === canonical(s)
|
|
72
|
+
: typeof destination === 'string' && DESTINATIONS.has(destination) && key === canonical({ ...s, destination })));
|
|
73
|
+
}).map(local);
|
|
74
|
+
}
|
|
75
|
+
// build the PermissionResult written back to the cli for a can_use_tool request
|
|
76
|
+
export function buildPermissionResult(pending, decision, allowBypass) {
|
|
77
|
+
if (decision.behavior === 'allow') {
|
|
78
|
+
return {
|
|
79
|
+
behavior: 'allow',
|
|
80
|
+
updatedInput: decision.updatedInput ?? pending.input,
|
|
81
|
+
updatedPermissions: filterPermissionUpdates(decision.updatedPermissions, pending.suggestions, allowBypass),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
const message = decision.message?.trim() ? decision.message : DEFAULT_DENY_MESSAGE;
|
|
85
|
+
return { behavior: 'deny', message, interrupt: decision.interrupt ?? !decision.message?.trim() };
|
|
86
|
+
}
|
|
87
|
+
// validate a claude_permission_response payload coming from the app
|
|
88
|
+
export function parsePermissionDecision(msg) {
|
|
89
|
+
const behavior = msg['behavior'];
|
|
90
|
+
if (behavior !== 'allow' && behavior !== 'deny')
|
|
91
|
+
return null;
|
|
92
|
+
const updatedInput = msg['updatedInput'];
|
|
93
|
+
return {
|
|
94
|
+
behavior,
|
|
95
|
+
updatedInput: updatedInput && typeof updatedInput === 'object' && !Array.isArray(updatedInput) ? updatedInput : undefined,
|
|
96
|
+
updatedPermissions: msg['updatedPermissions'],
|
|
97
|
+
message: str(msg['message']),
|
|
98
|
+
interrupt: bool(msg['interrupt']),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=permissions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../src/engine/permissions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// how long the shared probe waits for the next account-wide read before it closes
|
|
2
|
+
const PROBE_IDLE_MS = 60_000;
|
|
3
|
+
// one silent claude answers account-wide reads while no chat runs, instead of a claude per
|
|
4
|
+
// read; it closes once nothing used it for a while, and starts again when needed
|
|
5
|
+
export class ProbePool {
|
|
6
|
+
startProbe;
|
|
7
|
+
idleMs;
|
|
8
|
+
probe = null;
|
|
9
|
+
users = 0;
|
|
10
|
+
idle = null;
|
|
11
|
+
constructor(startProbe, idleMs = PROBE_IDLE_MS) {
|
|
12
|
+
this.startProbe = startProbe;
|
|
13
|
+
this.idleMs = idleMs;
|
|
14
|
+
}
|
|
15
|
+
async use(fn) {
|
|
16
|
+
if (this.idle)
|
|
17
|
+
clearTimeout(this.idle);
|
|
18
|
+
this.idle = null;
|
|
19
|
+
this.users++;
|
|
20
|
+
try {
|
|
21
|
+
return await fn(await this.live());
|
|
22
|
+
}
|
|
23
|
+
finally {
|
|
24
|
+
this.users--;
|
|
25
|
+
if (this.users === 0 && this.probe) {
|
|
26
|
+
this.idle = setTimeout(() => void this.close(), this.idleMs);
|
|
27
|
+
this.idle.unref?.();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async close() {
|
|
32
|
+
if (this.idle)
|
|
33
|
+
clearTimeout(this.idle);
|
|
34
|
+
this.idle = null;
|
|
35
|
+
const starting = this.probe;
|
|
36
|
+
this.probe = null;
|
|
37
|
+
const probe = await starting?.catch(() => null);
|
|
38
|
+
await probe?.close('probe');
|
|
39
|
+
}
|
|
40
|
+
// the shared probe, started again when it never came up or has exited since
|
|
41
|
+
async live() {
|
|
42
|
+
const current = this.probe;
|
|
43
|
+
const probe = await current?.catch(() => null);
|
|
44
|
+
if (probe?.alive)
|
|
45
|
+
return probe;
|
|
46
|
+
if (this.probe === current)
|
|
47
|
+
this.probe = this.startProbe();
|
|
48
|
+
return this.probe;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=probePool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"probePool.js","sourceRoot":"","sources":["../../src/engine/probePool.ts"],"names":[],"mappings":"AAEA,kFAAkF;AAClF,MAAM,aAAa,GAAG,MAAM,CAAC;AAE7B,2FAA2F;AAC3F,iFAAiF;AACjF,MAAM,OAAO,SAAS;IAMD;IACA;IANX,KAAK,GAAkC,IAAI,CAAC;IAC5C,KAAK,GAAG,CAAC,CAAC;IACV,IAAI,GAA0B,IAAI,CAAC;IAE3C,YACmB,UAAwC,EACxC,SAAS,aAAa;QADtB,eAAU,GAAV,UAAU,CAA8B;QACxC,WAAM,GAAN,MAAM,CAAgB;IACtC,CAAC;IAEJ,KAAK,CAAC,GAAG,CAAI,EAA0C;QACrD,IAAI,IAAI,CAAC,IAAI;YAAE,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACrC,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,KAAK,EAAE,CAAC;YACb,IAAI,IAAI,CAAC,KAAK,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;gBACnC,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;gBAC7D,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;YACtB,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,IAAI;YAAE,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC;QAC5B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,MAAM,KAAK,GAAG,MAAM,QAAQ,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QAChD,MAAM,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAC9B,CAAC;IAED,4EAA4E;IACpE,KAAK,CAAC,IAAI;QAChB,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC;QAC3B,MAAM,KAAK,GAAG,MAAM,OAAO,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QAC/C,IAAI,KAAK,EAAE,KAAK;YAAE,OAAO,KAAK,CAAC;QAC/B,IAAI,IAAI,CAAC,KAAK,KAAK,OAAO;YAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;QAC3D,OAAO,IAAI,CAAC,KAAM,CAAC;IACrB,CAAC;CACF"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
// on posix each claude leads its own process group, so a kill reaches the jobs it started (a
|
|
3
|
+
// Bash tool left running) too; windows kills the tree with taskkill /T instead
|
|
4
|
+
export const OWN_GROUP = process.platform !== 'win32';
|
|
5
|
+
// groups still running when the cli exits go with it, as they would have with the terminal's
|
|
6
|
+
// ctrl+c had they stayed in its group
|
|
7
|
+
const liveGroups = new Set();
|
|
8
|
+
let exitHookSet = false;
|
|
9
|
+
function killGroup(pid) {
|
|
10
|
+
try {
|
|
11
|
+
process.kill(-pid, 'SIGKILL');
|
|
12
|
+
}
|
|
13
|
+
catch { }
|
|
14
|
+
}
|
|
15
|
+
// a child spawned as the leader of its own group (detached: OWN_GROUP)
|
|
16
|
+
export function trackGroup(pid) {
|
|
17
|
+
liveGroups.add(pid);
|
|
18
|
+
if (exitHookSet)
|
|
19
|
+
return;
|
|
20
|
+
exitHookSet = true;
|
|
21
|
+
process.on('exit', () => {
|
|
22
|
+
for (const group of liveGroups)
|
|
23
|
+
killGroup(group);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
// the child exited: its pid may be handed to another process from now on
|
|
27
|
+
export function untrackGroup(pid) {
|
|
28
|
+
liveGroups.delete(pid);
|
|
29
|
+
}
|
|
30
|
+
// kill a child and everything it started
|
|
31
|
+
export function killTree(child) {
|
|
32
|
+
if (process.platform === 'win32' && child.pid) {
|
|
33
|
+
spawnSync('taskkill', ['/pid', String(child.pid), '/T', '/F'], { windowsHide: true, stdio: 'ignore' });
|
|
34
|
+
}
|
|
35
|
+
else if (OWN_GROUP && child.pid) {
|
|
36
|
+
killGroup(child.pid);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
try {
|
|
40
|
+
child.kill('SIGKILL');
|
|
41
|
+
}
|
|
42
|
+
catch { }
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=processTree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"processTree.js","sourceRoot":"","sources":["../../src/engine/processTree.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAqB,MAAM,oBAAoB,CAAC;AAElE,6FAA6F;AAC7F,+EAA+E;AAC/E,MAAM,CAAC,MAAM,SAAS,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC;AAEtD,6FAA6F;AAC7F,sCAAsC;AACtC,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;AACrC,IAAI,WAAW,GAAG,KAAK,CAAC;AAExB,SAAS,SAAS,CAAC,GAAW;IAC5B,IAAI,CAAC;QAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;AACjD,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACpB,IAAI,WAAW;QAAE,OAAO;IACxB,WAAW,GAAG,IAAI,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE;QACtB,KAAK,MAAM,KAAK,IAAI,UAAU;YAAE,SAAS,CAAC,KAAK,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;AACL,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED,yCAAyC;AACzC,MAAM,UAAU,QAAQ,CAAC,KAAmB;IAC1C,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,KAAK,CAAC,GAAG,EAAE,CAAC;QAC9C,SAAS,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IACzG,CAAC;SAAM,IAAI,SAAS,IAAI,KAAK,CAAC,GAAG,EAAE,CAAC;QAClC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACvB,CAAC;SAAM,CAAC;QACN,IAAI,CAAC;YAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;IACzC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// whether the app may change settings that apply to every claude session on this machine
|
|
2
|
+
// (~/.claude/settings.json hooks and rules, user-scope mcp servers). they outlive kumo, so the app
|
|
3
|
+
// only gets them when kumo runs with --allow-remote-config
|
|
4
|
+
let allowed = false;
|
|
5
|
+
export const ALLOW_REMOTE_CONFIG_FLAG = '--allow-remote-config';
|
|
6
|
+
export function allowRemoteUserConfig(value) {
|
|
7
|
+
allowed = value;
|
|
8
|
+
}
|
|
9
|
+
export function remoteUserConfigAllowed() {
|
|
10
|
+
return allowed;
|
|
11
|
+
}
|
|
12
|
+
export function assertUserConfigAllowed() {
|
|
13
|
+
if (!allowed) {
|
|
14
|
+
throw new Error(`Changing user settings from the app needs kumo started with ${ALLOW_REMOTE_CONFIG_FLAG}. Use project or local settings instead.`);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=remoteConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remoteConfig.js","sourceRoot":"","sources":["../../src/engine/remoteConfig.ts"],"names":[],"mappings":"AAAA,yFAAyF;AACzF,mGAAmG;AACnG,2DAA2D;AAC3D,IAAI,OAAO,GAAG,KAAK,CAAC;AAEpB,MAAM,CAAC,MAAM,wBAAwB,GAAG,uBAAuB,CAAC;AAEhE,MAAM,UAAU,qBAAqB,CAAC,KAAc;IAClD,OAAO,GAAG,KAAK,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,uBAAuB;IACrC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,uBAAuB;IACrC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,+DAA+D,wBAAwB,0CAA0C,CAAC,CAAC;IACrJ,CAAC;AACH,CAAC"}
|