@linzumi/cli 0.0.83-beta → 0.0.85-beta
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 +1 -1
- package/dist/index.js +1216 -516
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9822,7 +9822,11 @@ async function handleKandanChatEvent(args, state, runnerIdentity, payloadContext
|
|
|
9822
9822
|
seq: event.seq,
|
|
9823
9823
|
actor_slug: event.actorSlug ?? null,
|
|
9824
9824
|
actor_user_id: event.actorUserId ?? null,
|
|
9825
|
-
reason: "different_thread"
|
|
9825
|
+
reason: "different_thread",
|
|
9826
|
+
thread_id: event.threadId ?? null,
|
|
9827
|
+
bound_thread_id: state.kandanThreadId ?? null,
|
|
9828
|
+
codex_thread_id: state.codexThreadId ?? null,
|
|
9829
|
+
body_preview: runnerConsoleBodyPreview(event.body)
|
|
9826
9830
|
});
|
|
9827
9831
|
return;
|
|
9828
9832
|
}
|
|
@@ -11564,6 +11568,21 @@ function createClaudeCodeSessionPipeline(host) {
|
|
|
11564
11568
|
handleToolResult(ensureTurn(), event);
|
|
11565
11569
|
return;
|
|
11566
11570
|
}
|
|
11571
|
+
case "command_output_delta": {
|
|
11572
|
+
const turn = activeTurn;
|
|
11573
|
+
const pending = turn?.pendingTools.get(event.itemKey);
|
|
11574
|
+
if (turn === void 0 || pending === void 0) {
|
|
11575
|
+
return;
|
|
11576
|
+
}
|
|
11577
|
+
submit("item/commandExecution/outputDelta", {
|
|
11578
|
+
turnId: turn.turnId,
|
|
11579
|
+
itemId: `tool:${event.itemKey}`,
|
|
11580
|
+
command: claudeToolCommandLabel(pending.toolName, pending.input),
|
|
11581
|
+
stream: "stdout",
|
|
11582
|
+
delta: event.delta
|
|
11583
|
+
});
|
|
11584
|
+
return;
|
|
11585
|
+
}
|
|
11567
11586
|
case "command_output": {
|
|
11568
11587
|
const turn = ensureTurn();
|
|
11569
11588
|
const item = {
|
|
@@ -11945,13 +11964,304 @@ var init_claudeCodePlanMirror = __esm({
|
|
|
11945
11964
|
}
|
|
11946
11965
|
});
|
|
11947
11966
|
|
|
11967
|
+
// src/claudeCodeLiveBashOutput.ts
|
|
11968
|
+
import {
|
|
11969
|
+
mkdirSync as mkdirSync2,
|
|
11970
|
+
rmSync,
|
|
11971
|
+
writeFileSync,
|
|
11972
|
+
promises as fsPromises
|
|
11973
|
+
} from "node:fs";
|
|
11974
|
+
import { join as join6 } from "node:path";
|
|
11975
|
+
import { StringDecoder } from "node:string_decoder";
|
|
11976
|
+
function shellSingleQuoted(value) {
|
|
11977
|
+
return `'${value.replaceAll("'", `'\\''`)}'`;
|
|
11978
|
+
}
|
|
11979
|
+
function claudeLiveBashWrappedCommand(command, captureFile) {
|
|
11980
|
+
return `__lz_live_out=${shellSingleQuoted(captureFile)}; if ! : >> "$__lz_live_out" 2>/dev/null; then __lz_live_out=/dev/null; fi; { ${command}${wrapperTail}`;
|
|
11981
|
+
}
|
|
11982
|
+
function isClaudeLiveBashWrappedCommand(command) {
|
|
11983
|
+
return wrapperHeadPattern.test(command) && command.endsWith(wrapperTail);
|
|
11984
|
+
}
|
|
11985
|
+
function claudeLiveBashOriginalCommand(command) {
|
|
11986
|
+
const head = command.match(wrapperHeadPattern)?.[0];
|
|
11987
|
+
if (head === void 0 || !command.endsWith(wrapperTail)) {
|
|
11988
|
+
return command;
|
|
11989
|
+
}
|
|
11990
|
+
return command.slice(head.length, command.length - wrapperTail.length);
|
|
11991
|
+
}
|
|
11992
|
+
function claudeLiveBashCaptureEnabled(env) {
|
|
11993
|
+
const value = env.LINZUMI_CLAUDE_LIVE_BASH?.trim().toLowerCase();
|
|
11994
|
+
return !(value === "0" || value === "false" || value === "off" || value === "no");
|
|
11995
|
+
}
|
|
11996
|
+
function createClaudeCodeLiveBashCapture(host) {
|
|
11997
|
+
const pollIntervalMs = host.pollIntervalMs ?? defaultPollIntervalMs;
|
|
11998
|
+
const maxEmittedBytes = host.maxEmittedBytesPerTool ?? defaultMaxEmittedBytesPerTool;
|
|
11999
|
+
const tails = /* @__PURE__ */ new Map();
|
|
12000
|
+
let closed = false;
|
|
12001
|
+
const stopTail = (toolUseId) => {
|
|
12002
|
+
const tail = tails.get(toolUseId);
|
|
12003
|
+
if (tail === void 0) {
|
|
12004
|
+
return;
|
|
12005
|
+
}
|
|
12006
|
+
tails.delete(toolUseId);
|
|
12007
|
+
if (tail.timer !== void 0) {
|
|
12008
|
+
clearInterval(tail.timer);
|
|
12009
|
+
tail.timer = void 0;
|
|
12010
|
+
}
|
|
12011
|
+
try {
|
|
12012
|
+
rmSync(tail.file, { force: true });
|
|
12013
|
+
} catch (_error) {
|
|
12014
|
+
}
|
|
12015
|
+
};
|
|
12016
|
+
const pollTail = async (toolUseId, tail) => {
|
|
12017
|
+
if (tail.reading) {
|
|
12018
|
+
return;
|
|
12019
|
+
}
|
|
12020
|
+
tail.reading = true;
|
|
12021
|
+
try {
|
|
12022
|
+
const stat2 = await fsPromises.stat(tail.file);
|
|
12023
|
+
if (stat2.size <= tail.offset) {
|
|
12024
|
+
return;
|
|
12025
|
+
}
|
|
12026
|
+
const length = Math.min(
|
|
12027
|
+
stat2.size - tail.offset,
|
|
12028
|
+
maxReadBytesPerPoll,
|
|
12029
|
+
maxEmittedBytes - tail.emittedBytes
|
|
12030
|
+
);
|
|
12031
|
+
if (length <= 0) {
|
|
12032
|
+
stopTail(toolUseId);
|
|
12033
|
+
return;
|
|
12034
|
+
}
|
|
12035
|
+
const handle = await fsPromises.open(tail.file, "r");
|
|
12036
|
+
try {
|
|
12037
|
+
const buffer = Buffer.alloc(length);
|
|
12038
|
+
const { bytesRead } = await handle.read(buffer, 0, length, tail.offset);
|
|
12039
|
+
if (bytesRead <= 0) {
|
|
12040
|
+
return;
|
|
12041
|
+
}
|
|
12042
|
+
tail.offset += bytesRead;
|
|
12043
|
+
tail.emittedBytes += bytesRead;
|
|
12044
|
+
const delta = tail.decoder.write(buffer.subarray(0, bytesRead));
|
|
12045
|
+
if (delta !== "" && tails.get(toolUseId) === tail) {
|
|
12046
|
+
host.onOutputDelta(toolUseId, delta);
|
|
12047
|
+
}
|
|
12048
|
+
if (tail.emittedBytes >= maxEmittedBytes) {
|
|
12049
|
+
host.log?.("claude_live_bash.output_budget_exhausted", {
|
|
12050
|
+
tool_use_id: toolUseId,
|
|
12051
|
+
emitted_bytes: tail.emittedBytes
|
|
12052
|
+
});
|
|
12053
|
+
stopTail(toolUseId);
|
|
12054
|
+
}
|
|
12055
|
+
} finally {
|
|
12056
|
+
await handle.close();
|
|
12057
|
+
}
|
|
12058
|
+
} catch (error) {
|
|
12059
|
+
if (tails.get(toolUseId) === tail) {
|
|
12060
|
+
host.log?.("claude_live_bash.tail_read_failed", {
|
|
12061
|
+
tool_use_id: toolUseId,
|
|
12062
|
+
message: error instanceof Error ? error.message : String(error)
|
|
12063
|
+
});
|
|
12064
|
+
stopTail(toolUseId);
|
|
12065
|
+
}
|
|
12066
|
+
} finally {
|
|
12067
|
+
tail.reading = false;
|
|
12068
|
+
}
|
|
12069
|
+
};
|
|
12070
|
+
const startTail = (toolUseId, file) => {
|
|
12071
|
+
stopTail(toolUseId);
|
|
12072
|
+
const tail = {
|
|
12073
|
+
file,
|
|
12074
|
+
decoder: new StringDecoder("utf8"),
|
|
12075
|
+
offset: 0,
|
|
12076
|
+
emittedBytes: 0,
|
|
12077
|
+
reading: false,
|
|
12078
|
+
timer: void 0
|
|
12079
|
+
};
|
|
12080
|
+
tails.set(toolUseId, tail);
|
|
12081
|
+
const timer = setInterval(() => {
|
|
12082
|
+
void pollTail(toolUseId, tail);
|
|
12083
|
+
}, pollIntervalMs);
|
|
12084
|
+
timer.unref?.();
|
|
12085
|
+
tail.timer = timer;
|
|
12086
|
+
};
|
|
12087
|
+
const wrapToolInput = (toolUseId, toolInput) => {
|
|
12088
|
+
if (closed) {
|
|
12089
|
+
return void 0;
|
|
12090
|
+
}
|
|
12091
|
+
const command = toolInput.command;
|
|
12092
|
+
if (typeof command !== "string" || command.trim() === "" || // Background commands are polled by the model itself (TaskOutput);
|
|
12093
|
+
// the foreground live stream does not apply.
|
|
12094
|
+
toolInput.run_in_background === true || // Defensive: never double-wrap (e.g. a model echoing a wrapped
|
|
12095
|
+
// command back from its own transcript).
|
|
12096
|
+
isClaudeLiveBashWrappedCommand(command)) {
|
|
12097
|
+
return void 0;
|
|
12098
|
+
}
|
|
12099
|
+
const file = join6(
|
|
12100
|
+
host.captureDir,
|
|
12101
|
+
`${toolUseId.replaceAll(/[^\w-]/g, "_")}.out`
|
|
12102
|
+
);
|
|
12103
|
+
try {
|
|
12104
|
+
mkdirSync2(host.captureDir, { recursive: true });
|
|
12105
|
+
writeFileSync(file, "");
|
|
12106
|
+
} catch (error) {
|
|
12107
|
+
host.log?.("claude_live_bash.capture_file_failed", {
|
|
12108
|
+
tool_use_id: toolUseId,
|
|
12109
|
+
message: error instanceof Error ? error.message : String(error)
|
|
12110
|
+
});
|
|
12111
|
+
return void 0;
|
|
12112
|
+
}
|
|
12113
|
+
startTail(toolUseId, file);
|
|
12114
|
+
return {
|
|
12115
|
+
...toolInput,
|
|
12116
|
+
command: claudeLiveBashWrappedCommand(command, file)
|
|
12117
|
+
};
|
|
12118
|
+
};
|
|
12119
|
+
const preToolUseHook = async (input) => {
|
|
12120
|
+
const passthrough = { continue: true };
|
|
12121
|
+
if (typeof input !== "object" || input === null) {
|
|
12122
|
+
return passthrough;
|
|
12123
|
+
}
|
|
12124
|
+
const hookInput = input;
|
|
12125
|
+
if (hookInput.hook_event_name !== "PreToolUse" || hookInput.tool_name !== "Bash" || typeof hookInput.tool_use_id !== "string" || hookInput.tool_use_id === "" || typeof hookInput.tool_input !== "object" || hookInput.tool_input === null || // Hook-path wrapping ONLY in bypassPermissions, where every command
|
|
12126
|
+
// auto-allows and the rewrite cannot perturb a permission decision.
|
|
12127
|
+
// In ask-capable modes, PreToolUse updatedInput propagates into rule
|
|
12128
|
+
// matching and sandbox auto-allow analysis (verified empirically
|
|
12129
|
+
// 2026-06-12: a sandbox-auto-allowed `false` started prompting once
|
|
12130
|
+
// wrapped), so those modes wrap at canUseTool-allow time instead
|
|
12131
|
+
// (wrapApprovedTool below) - the command was already being asked, so
|
|
12132
|
+
// wrapping there adds zero prompts.
|
|
12133
|
+
hookInput.permission_mode !== "bypassPermissions") {
|
|
12134
|
+
return passthrough;
|
|
12135
|
+
}
|
|
12136
|
+
const updatedInput = wrapToolInput(
|
|
12137
|
+
hookInput.tool_use_id,
|
|
12138
|
+
hookInput.tool_input
|
|
12139
|
+
);
|
|
12140
|
+
if (updatedInput === void 0) {
|
|
12141
|
+
return passthrough;
|
|
12142
|
+
}
|
|
12143
|
+
return {
|
|
12144
|
+
continue: true,
|
|
12145
|
+
hookSpecificOutput: {
|
|
12146
|
+
hookEventName: "PreToolUse",
|
|
12147
|
+
updatedInput
|
|
12148
|
+
}
|
|
12149
|
+
};
|
|
12150
|
+
};
|
|
12151
|
+
return {
|
|
12152
|
+
hookMatchers: [{ matcher: "Bash", hooks: [preToolUseHook] }],
|
|
12153
|
+
wrapApprovedTool: wrapToolInput,
|
|
12154
|
+
settleTool: stopTail,
|
|
12155
|
+
settleAll: () => {
|
|
12156
|
+
for (const toolUseId of [...tails.keys()]) {
|
|
12157
|
+
stopTail(toolUseId);
|
|
12158
|
+
}
|
|
12159
|
+
},
|
|
12160
|
+
close: () => {
|
|
12161
|
+
closed = true;
|
|
12162
|
+
for (const toolUseId of [...tails.keys()]) {
|
|
12163
|
+
stopTail(toolUseId);
|
|
12164
|
+
}
|
|
12165
|
+
try {
|
|
12166
|
+
rmSync(host.captureDir, { recursive: true, force: true });
|
|
12167
|
+
} catch (_error) {
|
|
12168
|
+
}
|
|
12169
|
+
}
|
|
12170
|
+
};
|
|
12171
|
+
}
|
|
12172
|
+
var wrapperHeadPattern, wrapperTail, defaultPollIntervalMs, defaultMaxEmittedBytesPerTool, maxReadBytesPerPoll;
|
|
12173
|
+
var init_claudeCodeLiveBashOutput = __esm({
|
|
12174
|
+
"src/claudeCodeLiveBashOutput.ts"() {
|
|
12175
|
+
"use strict";
|
|
12176
|
+
wrapperHeadPattern = /^__lz_live_out='(?:[^']|'\\'')*'; if ! : >> "\$__lz_live_out" 2>\/dev\/null; then __lz_live_out=\/dev\/null; fi; \{ /;
|
|
12177
|
+
wrapperTail = '\n} > >(tee -a -- "$__lz_live_out") 2> >(tee -a -- "$__lz_live_out" >&2)';
|
|
12178
|
+
defaultPollIntervalMs = 200;
|
|
12179
|
+
defaultMaxEmittedBytesPerTool = 262144;
|
|
12180
|
+
maxReadBytesPerPoll = 65536;
|
|
12181
|
+
}
|
|
12182
|
+
});
|
|
12183
|
+
|
|
11948
12184
|
// src/claudeCodeSession.ts
|
|
11949
12185
|
import { existsSync as existsSync4, readFileSync as readFileSync5 } from "node:fs";
|
|
11950
12186
|
import { homedir as homedir5 } from "node:os";
|
|
11951
|
-
import { join as
|
|
12187
|
+
import { join as join7 } from "node:path";
|
|
11952
12188
|
function claudeCodeSettingSources() {
|
|
11953
12189
|
return ["user", "project", "local"];
|
|
11954
12190
|
}
|
|
12191
|
+
function claudeCodeTokenUsageSummaryText(usage) {
|
|
12192
|
+
const cached = usage.cacheReadInputTokens === void 0 && usage.cacheCreationInputTokens === void 0 ? void 0 : (usage.cacheReadInputTokens ?? 0) + (usage.cacheCreationInputTokens ?? 0);
|
|
12193
|
+
const parts = [
|
|
12194
|
+
usage.inputTokens === void 0 ? void 0 : `${usage.inputTokens} in`,
|
|
12195
|
+
usage.outputTokens === void 0 ? void 0 : `${usage.outputTokens} out`,
|
|
12196
|
+
cached === void 0 ? void 0 : `${cached} cached`,
|
|
12197
|
+
usage.totalCostUsd === void 0 ? void 0 : `$${usage.totalCostUsd.toFixed(4)}`
|
|
12198
|
+
].filter((part) => part !== void 0);
|
|
12199
|
+
return parts.length === 0 ? void 0 : parts.join(" / ");
|
|
12200
|
+
}
|
|
12201
|
+
function createClaudeCodeStreamUsageTracker() {
|
|
12202
|
+
const completed = {
|
|
12203
|
+
inputTokens: 0,
|
|
12204
|
+
outputTokens: 0,
|
|
12205
|
+
cacheCreationInputTokens: 0,
|
|
12206
|
+
cacheReadInputTokens: 0
|
|
12207
|
+
};
|
|
12208
|
+
let current;
|
|
12209
|
+
let lastEmittedKey;
|
|
12210
|
+
const totalsFromUsage = (usage, previous) => ({
|
|
12211
|
+
inputTokens: integerValue(usage.input_tokens) ?? previous?.inputTokens ?? 0,
|
|
12212
|
+
outputTokens: integerValue(usage.output_tokens) ?? previous?.outputTokens ?? 0,
|
|
12213
|
+
cacheCreationInputTokens: integerValue(usage.cache_creation_input_tokens) ?? previous?.cacheCreationInputTokens ?? 0,
|
|
12214
|
+
cacheReadInputTokens: integerValue(usage.cache_read_input_tokens) ?? previous?.cacheReadInputTokens ?? 0
|
|
12215
|
+
});
|
|
12216
|
+
const snapshotIfChanged = () => {
|
|
12217
|
+
const inputTokens = completed.inputTokens + (current?.inputTokens ?? 0);
|
|
12218
|
+
const outputTokens = completed.outputTokens + (current?.outputTokens ?? 0);
|
|
12219
|
+
const cacheCreationInputTokens = completed.cacheCreationInputTokens + (current?.cacheCreationInputTokens ?? 0);
|
|
12220
|
+
const cacheReadInputTokens = completed.cacheReadInputTokens + (current?.cacheReadInputTokens ?? 0);
|
|
12221
|
+
const key = `${inputTokens}:${outputTokens}:${cacheCreationInputTokens}:${cacheReadInputTokens}`;
|
|
12222
|
+
if (key === lastEmittedKey) {
|
|
12223
|
+
return void 0;
|
|
12224
|
+
}
|
|
12225
|
+
lastEmittedKey = key;
|
|
12226
|
+
return {
|
|
12227
|
+
inputTokens,
|
|
12228
|
+
outputTokens,
|
|
12229
|
+
cacheCreationInputTokens,
|
|
12230
|
+
cacheReadInputTokens,
|
|
12231
|
+
totalCostUsd: void 0
|
|
12232
|
+
};
|
|
12233
|
+
};
|
|
12234
|
+
return {
|
|
12235
|
+
observeStreamEvent: (event) => {
|
|
12236
|
+
switch (stringValue(event?.type)) {
|
|
12237
|
+
case "message_start": {
|
|
12238
|
+
const usage = objectValue(objectValue(event?.message)?.usage);
|
|
12239
|
+
if (usage === void 0) {
|
|
12240
|
+
return void 0;
|
|
12241
|
+
}
|
|
12242
|
+
if (current !== void 0) {
|
|
12243
|
+
completed.inputTokens += current.inputTokens;
|
|
12244
|
+
completed.outputTokens += current.outputTokens;
|
|
12245
|
+
completed.cacheCreationInputTokens += current.cacheCreationInputTokens;
|
|
12246
|
+
completed.cacheReadInputTokens += current.cacheReadInputTokens;
|
|
12247
|
+
}
|
|
12248
|
+
current = totalsFromUsage(usage, void 0);
|
|
12249
|
+
return snapshotIfChanged();
|
|
12250
|
+
}
|
|
12251
|
+
case "message_delta": {
|
|
12252
|
+
const usage = objectValue(event?.usage);
|
|
12253
|
+
if (usage === void 0) {
|
|
12254
|
+
return void 0;
|
|
12255
|
+
}
|
|
12256
|
+
current = totalsFromUsage(usage, current);
|
|
12257
|
+
return snapshotIfChanged();
|
|
12258
|
+
}
|
|
12259
|
+
default:
|
|
12260
|
+
return void 0;
|
|
12261
|
+
}
|
|
12262
|
+
}
|
|
12263
|
+
};
|
|
12264
|
+
}
|
|
11955
12265
|
function parseClaudeCodeRateLimitInfo(info) {
|
|
11956
12266
|
if (info === void 0) {
|
|
11957
12267
|
return void 0;
|
|
@@ -12051,7 +12361,7 @@ async function probeClaudeCodeAvailability(args) {
|
|
|
12051
12361
|
}
|
|
12052
12362
|
}
|
|
12053
12363
|
function hasClaudeCodeAuthHint(env, deps) {
|
|
12054
|
-
const configDir = env.CLAUDE_CONFIG_DIR ??
|
|
12364
|
+
const configDir = env.CLAUDE_CONFIG_DIR ?? join7(deps.homeDir, ".claude");
|
|
12055
12365
|
return hasAnthropicCredentialEnv(env) || hasClaudeCloudProviderEnv(env) || hasClaudeCodeFileCredential(configDir, deps) || hasClaudeCodeApiKeyHelper(configDir, deps) || hasMacClaudeCodeKeychainAnchor(deps);
|
|
12056
12366
|
}
|
|
12057
12367
|
function claudeCodePolicyDeferHooks() {
|
|
@@ -12086,14 +12396,14 @@ function hasClaudeCloudProviderEnv(env) {
|
|
|
12086
12396
|
return trueishEnv(env.CLAUDE_CODE_USE_BEDROCK) || trueishEnv(env.CLAUDE_CODE_USE_VERTEX) || trueishEnv(env.CLAUDE_CODE_USE_FOUNDRY) || trueishEnv(env.CLAUDE_CODE_USE_ANTHROPIC_AWS) || trueishEnv(env.CLAUDE_CODE_USE_MANTLE);
|
|
12087
12397
|
}
|
|
12088
12398
|
function hasClaudeCodeFileCredential(configDir, deps) {
|
|
12089
|
-
return deps.fileExists(
|
|
12399
|
+
return deps.fileExists(join7(configDir, ".credentials.json")) || deps.fileExists(join7(configDir, ".claude.json")) || deps.fileExists(join7(deps.homeDir, ".claude.json"));
|
|
12090
12400
|
}
|
|
12091
12401
|
function hasClaudeCodeApiKeyHelper(configDir, deps) {
|
|
12092
12402
|
return [
|
|
12093
|
-
|
|
12094
|
-
|
|
12095
|
-
|
|
12096
|
-
|
|
12403
|
+
join7(configDir, "settings.json"),
|
|
12404
|
+
join7(configDir, "settings.local.json"),
|
|
12405
|
+
join7(deps.cwd, ".claude", "settings.json"),
|
|
12406
|
+
join7(deps.cwd, ".claude", "settings.local.json")
|
|
12097
12407
|
].some((path2) => settingsFileHasApiKeyHelper(path2, deps));
|
|
12098
12408
|
}
|
|
12099
12409
|
function settingsFileHasApiKeyHelper(path2, deps) {
|
|
@@ -12113,9 +12423,9 @@ function hasMacClaudeCodeKeychainAnchor(deps) {
|
|
|
12113
12423
|
return false;
|
|
12114
12424
|
}
|
|
12115
12425
|
return [
|
|
12116
|
-
|
|
12117
|
-
|
|
12118
|
-
|
|
12426
|
+
join7(deps.homeDir, "Library", "Application Support", "claude-cli-nodejs"),
|
|
12427
|
+
join7(deps.homeDir, "Library", "Application Support", "Claude"),
|
|
12428
|
+
join7(deps.homeDir, "Library", "Preferences", "claude-cli-nodejs")
|
|
12119
12429
|
].some((path2) => deps.fileExists(path2));
|
|
12120
12430
|
}
|
|
12121
12431
|
function readTextFileIfPresent(path2) {
|
|
@@ -12134,82 +12444,83 @@ async function startClaudeCodeSession(options) {
|
|
|
12134
12444
|
assistantTextByKey: /* @__PURE__ */ new Map(),
|
|
12135
12445
|
usage: void 0,
|
|
12136
12446
|
startedSessionIds: /* @__PURE__ */ new Set(),
|
|
12137
|
-
completedTurnCount: 0
|
|
12447
|
+
completedTurnCount: 0,
|
|
12448
|
+
lastCompletedTurnBody: void 0
|
|
12138
12449
|
};
|
|
12139
|
-
|
|
12140
|
-
|
|
12141
|
-
const
|
|
12142
|
-
|
|
12143
|
-
state.
|
|
12144
|
-
|
|
12145
|
-
|
|
12146
|
-
|
|
12147
|
-
|
|
12148
|
-
|
|
12149
|
-
|
|
12150
|
-
|
|
12151
|
-
|
|
12152
|
-
|
|
12153
|
-
|
|
12154
|
-
|
|
12155
|
-
|
|
12156
|
-
|
|
12157
|
-
|
|
12158
|
-
if (resultOutcome.text !== void 0) {
|
|
12159
|
-
state.resultText = resultOutcome.text;
|
|
12160
|
-
}
|
|
12161
|
-
state.usage = extractClaudeUsage(message) ?? state.usage;
|
|
12162
|
-
state.completedTurnCount += 1;
|
|
12163
|
-
const queuedTurnCountBeforeTranscript = options.streamingInput === void 0 ? void 0 : options.streamingInput.queuedTurnCount();
|
|
12164
|
-
if (options.streamingInput !== void 0) {
|
|
12165
|
-
await emitClaudeCodeTurnCompleted(options, state);
|
|
12166
|
-
}
|
|
12167
|
-
if (options.streamingInput !== void 0 && queuedTurnCountBeforeTranscript !== void 0 && state.completedTurnCount >= Math.max(
|
|
12168
|
-
queuedTurnCountBeforeTranscript,
|
|
12169
|
-
options.streamingInput.queuedTurnCount()
|
|
12170
|
-
)) {
|
|
12171
|
-
options.streamingInput.close();
|
|
12172
|
-
return completeClaudeCodeSession(options, state);
|
|
12173
|
-
}
|
|
12174
|
-
if (options.streamingInput !== void 0) {
|
|
12175
|
-
await options.onTurnCompleted?.();
|
|
12176
|
-
resetClaudeAssistantAggregate(state);
|
|
12177
|
-
state.resultText = void 0;
|
|
12450
|
+
const streamUsageTracker = createClaudeCodeStreamUsageTracker();
|
|
12451
|
+
try {
|
|
12452
|
+
for await (const message of runner(options)) {
|
|
12453
|
+
state.sessionId = state.sessionId ?? extractClaudeSessionId(message);
|
|
12454
|
+
const sessionId = extractClaudeSessionId(message) ?? state.sessionId;
|
|
12455
|
+
if (sessionId !== void 0 && !state.startedSessionIds.has(sessionId)) {
|
|
12456
|
+
state.startedSessionIds.add(sessionId);
|
|
12457
|
+
await options.onTranscriptEvent?.({
|
|
12458
|
+
type: "session_started",
|
|
12459
|
+
sessionId
|
|
12460
|
+
});
|
|
12461
|
+
}
|
|
12462
|
+
for (const event of transcriptEventsForClaudeMessage(
|
|
12463
|
+
message,
|
|
12464
|
+
sessionId,
|
|
12465
|
+
streamUsageTracker
|
|
12466
|
+
)) {
|
|
12467
|
+
if (event.type === "assistant_message") {
|
|
12468
|
+
recordClaudeAssistantAggregate(state, event);
|
|
12178
12469
|
}
|
|
12179
|
-
|
|
12470
|
+
if (event.type === "usage") {
|
|
12471
|
+
state.usage = event.usage;
|
|
12472
|
+
}
|
|
12473
|
+
await options.onTranscriptEvent?.(event);
|
|
12180
12474
|
}
|
|
12181
|
-
|
|
12182
|
-
|
|
12183
|
-
|
|
12184
|
-
|
|
12185
|
-
|
|
12186
|
-
|
|
12187
|
-
|
|
12475
|
+
const resultOutcome = extractClaudeResultOutcome(message);
|
|
12476
|
+
switch (resultOutcome.type) {
|
|
12477
|
+
case "success": {
|
|
12478
|
+
if (resultOutcome.text !== void 0) {
|
|
12479
|
+
state.resultText = resultOutcome.text;
|
|
12480
|
+
}
|
|
12481
|
+
state.usage = extractClaudeUsage(message) ?? state.usage;
|
|
12482
|
+
state.completedTurnCount += 1;
|
|
12483
|
+
if (options.streamingInput !== void 0) {
|
|
12484
|
+
await emitClaudeCodeTurnCompleted(options, state);
|
|
12485
|
+
state.lastCompletedTurnBody = state.resultText ?? nonEmptyText(claudeAssistantAggregateText(state)) ?? "";
|
|
12486
|
+
await options.onTurnCompleted?.();
|
|
12487
|
+
resetClaudeAssistantAggregate(state);
|
|
12488
|
+
state.resultText = void 0;
|
|
12489
|
+
}
|
|
12490
|
+
break;
|
|
12188
12491
|
}
|
|
12189
|
-
|
|
12190
|
-
|
|
12191
|
-
|
|
12192
|
-
|
|
12492
|
+
case "interrupted": {
|
|
12493
|
+
state.completedTurnCount += 1;
|
|
12494
|
+
if (state.sessionId !== void 0) {
|
|
12495
|
+
await options.onTranscriptEvent?.({
|
|
12496
|
+
type: "turn_interrupted",
|
|
12497
|
+
sessionId: state.sessionId
|
|
12498
|
+
});
|
|
12499
|
+
}
|
|
12500
|
+
if (options.streamingInput !== void 0) {
|
|
12501
|
+
await options.onTurnCompleted?.();
|
|
12502
|
+
resetClaudeAssistantAggregate(state);
|
|
12503
|
+
state.resultText = void 0;
|
|
12504
|
+
}
|
|
12505
|
+
break;
|
|
12193
12506
|
}
|
|
12194
|
-
|
|
12507
|
+
case "error":
|
|
12508
|
+
return await failClaudeCodeSession(
|
|
12509
|
+
options,
|
|
12510
|
+
state.sessionId,
|
|
12511
|
+
`Claude Code failed: ${resultOutcome.reason}`
|
|
12512
|
+
);
|
|
12513
|
+
case "none":
|
|
12514
|
+
break;
|
|
12195
12515
|
}
|
|
12196
|
-
case "error":
|
|
12197
|
-
return await failClaudeCodeSession(
|
|
12198
|
-
options,
|
|
12199
|
-
state.sessionId,
|
|
12200
|
-
`Claude Code failed: ${resultOutcome.reason}`
|
|
12201
|
-
);
|
|
12202
|
-
case "none":
|
|
12203
|
-
break;
|
|
12204
12516
|
}
|
|
12517
|
+
} finally {
|
|
12518
|
+
options.streamingInput?.close();
|
|
12205
12519
|
}
|
|
12206
12520
|
return completeClaudeCodeSession(options, state);
|
|
12207
12521
|
}
|
|
12208
12522
|
async function emitClaudeCodeTurnCompleted(options, state) {
|
|
12209
|
-
const body = state.resultText ?? nonEmptyText(claudeAssistantAggregateText(state));
|
|
12210
|
-
if (body === void 0) {
|
|
12211
|
-
return;
|
|
12212
|
-
}
|
|
12523
|
+
const body = state.resultText ?? nonEmptyText(claudeAssistantAggregateText(state)) ?? "";
|
|
12213
12524
|
if (state.sessionId === void 0) {
|
|
12214
12525
|
return;
|
|
12215
12526
|
}
|
|
@@ -12221,7 +12532,7 @@ async function emitClaudeCodeTurnCompleted(options, state) {
|
|
|
12221
12532
|
});
|
|
12222
12533
|
}
|
|
12223
12534
|
async function completeClaudeCodeSession(options, state) {
|
|
12224
|
-
const body = state.resultText ?? nonEmptyText(claudeAssistantAggregateText(state));
|
|
12535
|
+
const body = state.resultText ?? nonEmptyText(claudeAssistantAggregateText(state)) ?? state.lastCompletedTurnBody;
|
|
12225
12536
|
if (body === void 0) {
|
|
12226
12537
|
return await failClaudeCodeSession(
|
|
12227
12538
|
options,
|
|
@@ -12314,6 +12625,11 @@ async function failClaudeCodeSession(options, sessionId, reason) {
|
|
|
12314
12625
|
async function* defaultClaudeCodeRunner(options) {
|
|
12315
12626
|
const sdk = await import("@anthropic-ai/claude-agent-sdk");
|
|
12316
12627
|
const prompt = options.streamingInput?.messages ?? options.prompt;
|
|
12628
|
+
const preToolUseMatchers = [
|
|
12629
|
+
...options.preToolUseHookMatchers ?? [],
|
|
12630
|
+
...options.canUseTool === void 0 ? claudeCodePolicyDeferHooks().PreToolUse ?? [] : []
|
|
12631
|
+
];
|
|
12632
|
+
const hooks = preToolUseMatchers.length === 0 ? void 0 : { PreToolUse: preToolUseMatchers };
|
|
12317
12633
|
const query = sdk.query({
|
|
12318
12634
|
prompt,
|
|
12319
12635
|
options: {
|
|
@@ -12334,7 +12650,13 @@ async function* defaultClaudeCodeRunner(options) {
|
|
|
12334
12650
|
},
|
|
12335
12651
|
...options.allowedTools === void 0 ? {} : { allowedTools: [...options.allowedTools] },
|
|
12336
12652
|
...options.env === void 0 ? {} : { env: options.env },
|
|
12337
|
-
...
|
|
12653
|
+
...hooks === void 0 ? {} : { hooks },
|
|
12654
|
+
...options.canUseTool === void 0 ? {} : {
|
|
12655
|
+
canUseTool: claudeCodeCanUseTool(
|
|
12656
|
+
options.canUseTool,
|
|
12657
|
+
options.wrapApprovedToolInput
|
|
12658
|
+
)
|
|
12659
|
+
},
|
|
12338
12660
|
...options.model === void 0 ? {} : { model: options.model }
|
|
12339
12661
|
// exactOptionalPropertyTypes: the conditional spreads build a union the
|
|
12340
12662
|
// SDK's Options cannot absorb verbatim; the shape is correct field-wise.
|
|
@@ -12425,7 +12747,7 @@ function boundedPositiveInteger(value, fallback, min, max) {
|
|
|
12425
12747
|
}
|
|
12426
12748
|
return value;
|
|
12427
12749
|
}
|
|
12428
|
-
function claudeCodeCanUseTool(handler) {
|
|
12750
|
+
function claudeCodeCanUseTool(handler, wrapApprovedToolInput) {
|
|
12429
12751
|
return async (toolName2, input, options) => {
|
|
12430
12752
|
const decision = await handler(
|
|
12431
12753
|
{
|
|
@@ -12436,7 +12758,11 @@ function claudeCodeCanUseTool(handler) {
|
|
|
12436
12758
|
description: options.description,
|
|
12437
12759
|
decisionReason: options.decisionReason,
|
|
12438
12760
|
blockedPath: options.blockedPath,
|
|
12439
|
-
|
|
12761
|
+
// Approval prompts render the human-facing command: when the live
|
|
12762
|
+
// Bash output capture wrapped it (PreToolUse updatedInput), show
|
|
12763
|
+
// the original. The SDK still receives the raw input on allow so
|
|
12764
|
+
// the wrapped (live-streaming) command is what executes.
|
|
12765
|
+
input: displayClaudeToolInput(toolName2, input)
|
|
12440
12766
|
},
|
|
12441
12767
|
options.signal
|
|
12442
12768
|
);
|
|
@@ -12445,7 +12771,11 @@ function claudeCodeCanUseTool(handler) {
|
|
|
12445
12771
|
return {
|
|
12446
12772
|
behavior: "allow",
|
|
12447
12773
|
toolUseID: options.toolUseID,
|
|
12448
|
-
|
|
12774
|
+
// Live Bash output for ask-capable permission modes: the approved
|
|
12775
|
+
// command gains the tee wrapper HERE (it was already prompting,
|
|
12776
|
+
// so wrapping at this point can never add a prompt - see
|
|
12777
|
+
// claudeCodeLiveBashOutput).
|
|
12778
|
+
updatedInput: wrapApprovedToolInput?.(options.toolUseID, toolName2, input) ?? input
|
|
12449
12779
|
};
|
|
12450
12780
|
case "deny":
|
|
12451
12781
|
return {
|
|
@@ -12456,6 +12786,17 @@ function claudeCodeCanUseTool(handler) {
|
|
|
12456
12786
|
}
|
|
12457
12787
|
};
|
|
12458
12788
|
}
|
|
12789
|
+
function displayClaudeToolInput(toolName2, input) {
|
|
12790
|
+
if (toolName2 !== "Bash") {
|
|
12791
|
+
return input;
|
|
12792
|
+
}
|
|
12793
|
+
const command = stringValue(input.command);
|
|
12794
|
+
if (command === void 0) {
|
|
12795
|
+
return input;
|
|
12796
|
+
}
|
|
12797
|
+
const original = claudeLiveBashOriginalCommand(command);
|
|
12798
|
+
return original === command ? input : { ...input, command: original };
|
|
12799
|
+
}
|
|
12459
12800
|
function extractClaudeSessionId(message) {
|
|
12460
12801
|
const messageObject = objectValue(message);
|
|
12461
12802
|
const directSessionId = stringValue(messageObject?.session_id) ?? stringValue(messageObject?.sessionId);
|
|
@@ -12492,11 +12833,11 @@ function extractClaudeResultErrorReason(message, subtype) {
|
|
|
12492
12833
|
const explicitErrors = arrayValue(message.errors)?.map((error) => stringValue(error)).filter((error) => nonEmptyText(error) !== void 0).join("; ");
|
|
12493
12834
|
return nonEmptyText(explicitErrors) ?? nonEmptyText(stringValue(message.result)) ?? nonEmptyText(stringValue(message.error)) ?? subtype ?? "error";
|
|
12494
12835
|
}
|
|
12495
|
-
function transcriptEventsForClaudeMessage(message, sessionId) {
|
|
12836
|
+
function transcriptEventsForClaudeMessage(message, sessionId, usageTracker) {
|
|
12496
12837
|
const messageObject = objectValue(message);
|
|
12497
12838
|
switch (stringValue(messageObject?.type)) {
|
|
12498
12839
|
case "stream_event":
|
|
12499
|
-
return streamTranscriptEvents(messageObject, sessionId);
|
|
12840
|
+
return streamTranscriptEvents(messageObject, sessionId, usageTracker);
|
|
12500
12841
|
case "assistant":
|
|
12501
12842
|
return assistantTranscriptEvents(messageObject, sessionId);
|
|
12502
12843
|
case "user":
|
|
@@ -12513,11 +12854,16 @@ function transcriptEventsForClaudeMessage(message, sessionId) {
|
|
|
12513
12854
|
return unknownTranscriptEvent(messageObject, sessionId);
|
|
12514
12855
|
}
|
|
12515
12856
|
}
|
|
12516
|
-
function streamTranscriptEvents(message, sessionId) {
|
|
12857
|
+
function streamTranscriptEvents(message, sessionId, usageTracker) {
|
|
12517
12858
|
if (sessionId === void 0) {
|
|
12518
12859
|
return [];
|
|
12519
12860
|
}
|
|
12520
12861
|
const event = objectValue(message?.event);
|
|
12862
|
+
const runningUsage = usageTracker?.observeStreamEvent(event);
|
|
12863
|
+
const usageEvents = runningUsage === void 0 ? [] : [{ type: "usage", sessionId, usage: runningUsage }];
|
|
12864
|
+
return [...usageEvents, ...streamContentEvents(event, message, sessionId)];
|
|
12865
|
+
}
|
|
12866
|
+
function streamContentEvents(event, message, sessionId) {
|
|
12521
12867
|
switch (stringValue(event?.type)) {
|
|
12522
12868
|
case "content_block_delta": {
|
|
12523
12869
|
const delta = objectValue(event?.delta);
|
|
@@ -12719,6 +13065,7 @@ var init_claudeCodeSession = __esm({
|
|
|
12719
13065
|
"src/claudeCodeSession.ts"() {
|
|
12720
13066
|
"use strict";
|
|
12721
13067
|
init_json();
|
|
13068
|
+
init_claudeCodeLiveBashOutput();
|
|
12722
13069
|
claudeRateLimitWindowLabels = {
|
|
12723
13070
|
five_hour: "5h window",
|
|
12724
13071
|
seven_day: "7d window",
|
|
@@ -12733,10 +13080,10 @@ var init_claudeCodeSession = __esm({
|
|
|
12733
13080
|
import { appendFileSync, openSync as openSync2 } from "node:fs";
|
|
12734
13081
|
import { createWriteStream } from "node:fs";
|
|
12735
13082
|
import { homedir as homedir6 } from "node:os";
|
|
12736
|
-
import { dirname as dirname3, join as
|
|
12737
|
-
import { mkdirSync as
|
|
13083
|
+
import { dirname as dirname3, join as join8 } from "node:path";
|
|
13084
|
+
import { mkdirSync as mkdirSync3 } from "node:fs";
|
|
12738
13085
|
function createRunnerLogger(logFile, consoleReporter) {
|
|
12739
|
-
|
|
13086
|
+
mkdirSync3(dirname3(logFile), { recursive: true });
|
|
12740
13087
|
const fd = openSync2(logFile, "a");
|
|
12741
13088
|
const stream = createWriteStream("", { fd, flags: "a", autoClose: true });
|
|
12742
13089
|
const logger = ((event, payload) => {
|
|
@@ -12756,7 +13103,7 @@ function createRunnerLogger(logFile, consoleReporter) {
|
|
|
12756
13103
|
function writeCliAuditEvent(event, payload, options = {}) {
|
|
12757
13104
|
const logFile = options.logFile ?? defaultCliAuditLogFile();
|
|
12758
13105
|
try {
|
|
12759
|
-
|
|
13106
|
+
mkdirSync3(dirname3(logFile), { recursive: true });
|
|
12760
13107
|
appendFileSync(
|
|
12761
13108
|
logFile,
|
|
12762
13109
|
`${JSON.stringify({
|
|
@@ -12774,10 +13121,10 @@ function writeCliAuditEvent(event, payload, options = {}) {
|
|
|
12774
13121
|
}
|
|
12775
13122
|
function defaultCliAuditLogFile() {
|
|
12776
13123
|
const override = process.env.LINZUMI_CLI_AUDIT_LOG?.trim();
|
|
12777
|
-
return override === void 0 || override === "" ?
|
|
13124
|
+
return override === void 0 || override === "" ? join8(homedir6(), ".linzumi", "logs", "command-events.jsonl") : override;
|
|
12778
13125
|
}
|
|
12779
13126
|
function defaultRunnerLogFile() {
|
|
12780
|
-
return
|
|
13127
|
+
return join8(homedir6(), ".linzumi", "logs", "linzumi-runner.log");
|
|
12781
13128
|
}
|
|
12782
13129
|
function redactForCliLog(value) {
|
|
12783
13130
|
return redactObject(value);
|
|
@@ -13060,7 +13407,10 @@ var init_mcpConfig = __esm({
|
|
|
13060
13407
|
import {
|
|
13061
13408
|
spawn as spawn2
|
|
13062
13409
|
} from "node:child_process";
|
|
13410
|
+
import { readFileSync as readFileSync6 } from "node:fs";
|
|
13063
13411
|
import { createServer } from "node:net";
|
|
13412
|
+
import { homedir as homedir7 } from "node:os";
|
|
13413
|
+
import { join as join9 } from "node:path";
|
|
13064
13414
|
import { WebSocket as NodeWebSocket } from "ws";
|
|
13065
13415
|
async function chooseLoopbackPort() {
|
|
13066
13416
|
return new Promise((resolve12, reject) => {
|
|
@@ -13277,10 +13627,46 @@ function codexModelProviderConfigArgs(provider) {
|
|
|
13277
13627
|
"-c",
|
|
13278
13628
|
`model_providers.${provider.id}.http_headers.${header}=${JSON.stringify(value)}`
|
|
13279
13629
|
]),
|
|
13630
|
+
// env_http_headers values are env var NAMES, not secrets: codex resolves
|
|
13631
|
+
// them from its environment per request, keeping tokens out of argv.
|
|
13632
|
+
...Object.entries(provider.envHttpHeaders ?? {}).flatMap(
|
|
13633
|
+
([header, envVar]) => [
|
|
13634
|
+
"-c",
|
|
13635
|
+
`model_providers.${provider.id}.env_http_headers.${header}=${JSON.stringify(envVar)}`
|
|
13636
|
+
]
|
|
13637
|
+
),
|
|
13280
13638
|
"-c",
|
|
13281
13639
|
`model_provider=${JSON.stringify(provider.id)}`
|
|
13282
13640
|
];
|
|
13283
13641
|
}
|
|
13642
|
+
function resolveForwardableOpenAiApiKey(env = process.env) {
|
|
13643
|
+
const fromEnv = env.OPENAI_API_KEY?.trim();
|
|
13644
|
+
if (fromEnv !== void 0 && fromEnv !== "") {
|
|
13645
|
+
return fromEnv;
|
|
13646
|
+
}
|
|
13647
|
+
const codexHomeRaw = env.CODEX_HOME?.trim();
|
|
13648
|
+
const codexHome = codexHomeRaw !== void 0 && codexHomeRaw !== "" ? codexHomeRaw : join9(homedir7(), ".codex");
|
|
13649
|
+
let raw;
|
|
13650
|
+
try {
|
|
13651
|
+
raw = readFileSync6(join9(codexHome, "auth.json"), "utf8");
|
|
13652
|
+
} catch (_error) {
|
|
13653
|
+
return void 0;
|
|
13654
|
+
}
|
|
13655
|
+
let parsed;
|
|
13656
|
+
try {
|
|
13657
|
+
parsed = JSON.parse(raw);
|
|
13658
|
+
} catch (_error) {
|
|
13659
|
+
return void 0;
|
|
13660
|
+
}
|
|
13661
|
+
if (!isJsonObject(parsed)) {
|
|
13662
|
+
return void 0;
|
|
13663
|
+
}
|
|
13664
|
+
const apiKey = parsed.OPENAI_API_KEY;
|
|
13665
|
+
if (typeof apiKey === "string" && apiKey.trim() !== "") {
|
|
13666
|
+
return apiKey.trim();
|
|
13667
|
+
}
|
|
13668
|
+
return void 0;
|
|
13669
|
+
}
|
|
13284
13670
|
async function connectCodexAppServer(websocketUrl, socketFactory = (url) => new NodeWebSocket(url)) {
|
|
13285
13671
|
const websocket = await openCodexAppServerWebSocket(
|
|
13286
13672
|
websocketUrl,
|
|
@@ -13604,22 +13990,22 @@ var init_codexAppServer = __esm({
|
|
|
13604
13990
|
// src/codexProjectTrust.ts
|
|
13605
13991
|
import {
|
|
13606
13992
|
existsSync as existsSync5,
|
|
13607
|
-
mkdirSync as
|
|
13608
|
-
readFileSync as
|
|
13993
|
+
mkdirSync as mkdirSync4,
|
|
13994
|
+
readFileSync as readFileSync7,
|
|
13609
13995
|
realpathSync,
|
|
13610
|
-
writeFileSync
|
|
13996
|
+
writeFileSync as writeFileSync2
|
|
13611
13997
|
} from "node:fs";
|
|
13612
|
-
import { homedir as
|
|
13613
|
-
import { join as
|
|
13998
|
+
import { homedir as homedir8 } from "node:os";
|
|
13999
|
+
import { join as join10, resolve as resolve3 } from "node:path";
|
|
13614
14000
|
function ensureCodexProjectTrusted(projectPath, options = {}) {
|
|
13615
14001
|
const trustedPath = realpathSync(resolve3(projectPath));
|
|
13616
|
-
const configHome = options.configHome ?? process.env.CODEX_HOME ??
|
|
13617
|
-
const configPath =
|
|
13618
|
-
const currentConfig = existsSync5(configPath) ?
|
|
14002
|
+
const configHome = options.configHome ?? process.env.CODEX_HOME ?? join10(homedir8(), ".codex");
|
|
14003
|
+
const configPath = join10(configHome, "config.toml");
|
|
14004
|
+
const currentConfig = existsSync5(configPath) ? readFileSync7(configPath, "utf8") : "";
|
|
13619
14005
|
const nextConfig = codexConfigWithTrustedProject(currentConfig, trustedPath);
|
|
13620
14006
|
if (nextConfig !== currentConfig) {
|
|
13621
|
-
|
|
13622
|
-
|
|
14007
|
+
mkdirSync4(configHome, { recursive: true });
|
|
14008
|
+
writeFileSync2(configPath, nextConfig);
|
|
13623
14009
|
}
|
|
13624
14010
|
return trustedPath;
|
|
13625
14011
|
}
|
|
@@ -13964,7 +14350,7 @@ var init_codexNotificationConsoleStats = __esm({
|
|
|
13964
14350
|
|
|
13965
14351
|
// src/localCapabilities.ts
|
|
13966
14352
|
import { realpathSync as realpathSync2 } from "node:fs";
|
|
13967
|
-
import { homedir as
|
|
14353
|
+
import { homedir as homedir9 } from "node:os";
|
|
13968
14354
|
import { isAbsolute as isAbsolute3, relative as relative2, resolve as resolve4 } from "node:path";
|
|
13969
14355
|
function parseAllowedCwdList(value) {
|
|
13970
14356
|
if (value === void 0) {
|
|
@@ -14013,7 +14399,7 @@ function expandUserPath(pathValue) {
|
|
|
14013
14399
|
}
|
|
14014
14400
|
function currentHomeDirectory() {
|
|
14015
14401
|
const configuredHome = process.env.HOME;
|
|
14016
|
-
return configuredHome === void 0 || configuredHome.trim() === "" ?
|
|
14402
|
+
return configuredHome === void 0 || configuredHome.trim() === "" ? homedir9() : configuredHome;
|
|
14017
14403
|
}
|
|
14018
14404
|
function resolveAllowedCwd(requestedCwd, allowedRoots) {
|
|
14019
14405
|
if (requestedCwd === void 0 || requestedCwd.trim() === "") {
|
|
@@ -14413,17 +14799,17 @@ import {
|
|
|
14413
14799
|
chmodSync,
|
|
14414
14800
|
existsSync as existsSync6,
|
|
14415
14801
|
linkSync,
|
|
14416
|
-
mkdirSync as
|
|
14417
|
-
readFileSync as
|
|
14802
|
+
mkdirSync as mkdirSync5,
|
|
14803
|
+
readFileSync as readFileSync8,
|
|
14418
14804
|
realpathSync as realpathSync3,
|
|
14419
14805
|
unlinkSync,
|
|
14420
|
-
writeFileSync as
|
|
14806
|
+
writeFileSync as writeFileSync3
|
|
14421
14807
|
} from "node:fs";
|
|
14422
|
-
import { homedir as
|
|
14423
|
-
import { basename as basename5, dirname as dirname4, join as
|
|
14808
|
+
import { homedir as homedir10 } from "node:os";
|
|
14809
|
+
import { basename as basename5, dirname as dirname4, join as join11, resolve as resolve5 } from "node:path";
|
|
14424
14810
|
function localConfigPath(env = process.env) {
|
|
14425
14811
|
const override = env.LINZUMI_CONFIG_FILE;
|
|
14426
|
-
return override !== void 0 && override.trim() !== "" ? resolve5(expandUserPath(override)) : resolve5(
|
|
14812
|
+
return override !== void 0 && override.trim() !== "" ? resolve5(expandUserPath(override)) : resolve5(homedir10(), ".linzumi", "config.json");
|
|
14427
14813
|
}
|
|
14428
14814
|
function localConfigScopeKey(linzumiUrl) {
|
|
14429
14815
|
const normalizedUrl = kandanHttpBaseUrl(linzumiUrl);
|
|
@@ -14504,21 +14890,21 @@ function ensureLocalRunnerId(path2 = localConfigPath(), createRunnerId = default
|
|
|
14504
14890
|
}
|
|
14505
14891
|
function localMachineIdSeedPath(configPath = localConfigPath(), linzumiUrl) {
|
|
14506
14892
|
if (linzumiUrl !== void 0 && localConfigScopeKey(linzumiUrl) !== prodConfigScope) {
|
|
14507
|
-
return
|
|
14893
|
+
return join11(
|
|
14508
14894
|
dirname4(configPath),
|
|
14509
14895
|
`${basename5(configPath)}.${localConfigScopeFileStem(linzumiUrl)}.machine-id`
|
|
14510
14896
|
);
|
|
14511
14897
|
}
|
|
14512
|
-
return
|
|
14898
|
+
return join11(dirname4(configPath), `${basename5(configPath)}.machine-id`);
|
|
14513
14899
|
}
|
|
14514
14900
|
function localRunnerIdSeedPath(configPath = localConfigPath(), linzumiUrl) {
|
|
14515
14901
|
if (linzumiUrl !== void 0 && localConfigScopeKey(linzumiUrl) !== prodConfigScope) {
|
|
14516
|
-
return
|
|
14902
|
+
return join11(
|
|
14517
14903
|
dirname4(configPath),
|
|
14518
14904
|
`${basename5(configPath)}.${localConfigScopeFileStem(linzumiUrl)}.runner-id`
|
|
14519
14905
|
);
|
|
14520
14906
|
}
|
|
14521
|
-
return
|
|
14907
|
+
return join11(dirname4(configPath), `${basename5(configPath)}.runner-id`);
|
|
14522
14908
|
}
|
|
14523
14909
|
function readConfiguredAllowedCwdDetailsForLinzumiUrl(linzumiUrl, path2 = localConfigPath()) {
|
|
14524
14910
|
return readConfiguredAllowedCwdDetailsFromConfig(
|
|
@@ -14648,7 +15034,7 @@ function writeLocalSignupAuth(auth, path2 = localConfigPath()) {
|
|
|
14648
15034
|
version: 1,
|
|
14649
15035
|
signupAuth: nextSignupAuth
|
|
14650
15036
|
};
|
|
14651
|
-
|
|
15037
|
+
mkdirSync5(dirname4(path2), { recursive: true });
|
|
14652
15038
|
writeLocalConfigJson(path2, next);
|
|
14653
15039
|
return signupAuthFromJson(nextSignupAuth);
|
|
14654
15040
|
}
|
|
@@ -14656,7 +15042,7 @@ function writeLocalConfigJson(path2, payload) {
|
|
|
14656
15042
|
if (existsSync6(path2)) {
|
|
14657
15043
|
chmodSync(path2, localConfigFileMode);
|
|
14658
15044
|
}
|
|
14659
|
-
|
|
15045
|
+
writeFileSync3(path2, `${JSON.stringify(payload, null, 2)}
|
|
14660
15046
|
`, {
|
|
14661
15047
|
encoding: "utf8",
|
|
14662
15048
|
mode: localConfigFileMode
|
|
@@ -14683,7 +15069,7 @@ function readLocalConfigFile(path2) {
|
|
|
14683
15069
|
if (!existsSync6(path2)) {
|
|
14684
15070
|
return { version: 1, allowedCwds: [] };
|
|
14685
15071
|
}
|
|
14686
|
-
const parsed = JSON.parse(
|
|
15072
|
+
const parsed = JSON.parse(readFileSync8(path2, "utf8"));
|
|
14687
15073
|
if (!isConfigPayload(parsed)) {
|
|
14688
15074
|
throw new Error(`invalid Linzumi config: ${path2}`);
|
|
14689
15075
|
}
|
|
@@ -14712,7 +15098,7 @@ function writeLocalConfigSection(config, path2, linzumiUrl) {
|
|
|
14712
15098
|
version: 1,
|
|
14713
15099
|
[scopeKey]: nextSection
|
|
14714
15100
|
};
|
|
14715
|
-
|
|
15101
|
+
mkdirSync5(dirname4(path2), { recursive: true });
|
|
14716
15102
|
writeLocalConfigJson(path2, next);
|
|
14717
15103
|
}
|
|
14718
15104
|
function isConfigPayload(value) {
|
|
@@ -14787,12 +15173,12 @@ function ensureLocalMachineIdSeed(configPath, createMachineId, linzumiUrl) {
|
|
|
14787
15173
|
if (!machineIdValid(machineId)) {
|
|
14788
15174
|
throw new Error(`invalid generated Linzumi machine id: ${machineId}`);
|
|
14789
15175
|
}
|
|
14790
|
-
|
|
14791
|
-
const tempPath =
|
|
15176
|
+
mkdirSync5(dirname4(seedPath), { recursive: true });
|
|
15177
|
+
const tempPath = join11(
|
|
14792
15178
|
dirname4(seedPath),
|
|
14793
15179
|
`.${basename5(seedPath)}.${process.pid}.${randomUUID2()}.tmp`
|
|
14794
15180
|
);
|
|
14795
|
-
|
|
15181
|
+
writeFileSync3(tempPath, `${machineId}
|
|
14796
15182
|
`, { encoding: "utf8", flag: "wx" });
|
|
14797
15183
|
try {
|
|
14798
15184
|
linkSync(tempPath, seedPath);
|
|
@@ -14815,12 +15201,12 @@ function ensureLocalRunnerIdSeed(configPath, createRunnerId, linzumiUrl) {
|
|
|
14815
15201
|
if (!runnerIdValid(runnerId)) {
|
|
14816
15202
|
throw new Error(`invalid generated Linzumi runner id: ${runnerId}`);
|
|
14817
15203
|
}
|
|
14818
|
-
|
|
14819
|
-
const tempPath =
|
|
15204
|
+
mkdirSync5(dirname4(seedPath), { recursive: true });
|
|
15205
|
+
const tempPath = join11(
|
|
14820
15206
|
dirname4(seedPath),
|
|
14821
15207
|
`.${basename5(seedPath)}.${process.pid}.${randomUUID2()}.tmp`
|
|
14822
15208
|
);
|
|
14823
|
-
|
|
15209
|
+
writeFileSync3(tempPath, `${runnerId}
|
|
14824
15210
|
`, { encoding: "utf8", flag: "wx" });
|
|
14825
15211
|
try {
|
|
14826
15212
|
linkSync(tempPath, seedPath);
|
|
@@ -14835,14 +15221,14 @@ function ensureLocalRunnerIdSeed(configPath, createRunnerId, linzumiUrl) {
|
|
|
14835
15221
|
}
|
|
14836
15222
|
}
|
|
14837
15223
|
function readMachineIdSeed(seedPath) {
|
|
14838
|
-
const machineId =
|
|
15224
|
+
const machineId = readFileSync8(seedPath, "utf8").trim();
|
|
14839
15225
|
if (!machineIdValid(machineId)) {
|
|
14840
15226
|
throw new Error(`invalid Linzumi machine id seed: ${seedPath}`);
|
|
14841
15227
|
}
|
|
14842
15228
|
return machineId;
|
|
14843
15229
|
}
|
|
14844
15230
|
function readRunnerIdSeed(seedPath) {
|
|
14845
|
-
const runnerId =
|
|
15231
|
+
const runnerId = readFileSync8(seedPath, "utf8").trim();
|
|
14846
15232
|
if (!runnerIdValid(runnerId)) {
|
|
14847
15233
|
throw new Error(`invalid Linzumi runner id seed: ${seedPath}`);
|
|
14848
15234
|
}
|
|
@@ -15141,8 +15527,8 @@ var init_remoteCodexExecutionContext = __esm({
|
|
|
15141
15527
|
});
|
|
15142
15528
|
|
|
15143
15529
|
// src/helloLinzumiProject.ts
|
|
15144
|
-
import { existsSync as existsSync7, mkdirSync as
|
|
15145
|
-
import { dirname as dirname5, join as
|
|
15530
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync6, readFileSync as readFileSync9, rmSync as rmSync2, writeFileSync as writeFileSync4 } from "node:fs";
|
|
15531
|
+
import { dirname as dirname5, join as join12, resolve as resolve6 } from "node:path";
|
|
15146
15532
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
15147
15533
|
function createHelloLinzumiProject(input = {}) {
|
|
15148
15534
|
const options = typeof input === "string" ? { rootPath: input } : input;
|
|
@@ -15151,9 +15537,9 @@ function createHelloLinzumiProject(input = {}) {
|
|
|
15151
15537
|
const host = normalizeHost(options.host);
|
|
15152
15538
|
assertTcpPort(port);
|
|
15153
15539
|
assertWritableDemoRoot(root, options.reset === true);
|
|
15154
|
-
|
|
15540
|
+
mkdirSync6(join12(root, "src"), { recursive: true });
|
|
15155
15541
|
for (const file of demoFiles({ root, port, host })) {
|
|
15156
|
-
|
|
15542
|
+
writeFileSync4(join12(root, file.path), file.content, "utf8");
|
|
15157
15543
|
}
|
|
15158
15544
|
return {
|
|
15159
15545
|
root,
|
|
@@ -15197,10 +15583,10 @@ function assertWritableDemoRoot(root, reset) {
|
|
|
15197
15583
|
if (!existsSync7(root)) {
|
|
15198
15584
|
return;
|
|
15199
15585
|
}
|
|
15200
|
-
const markerPath =
|
|
15201
|
-
const isDemoRoot = existsSync7(markerPath) &&
|
|
15586
|
+
const markerPath = join12(root, markerFile);
|
|
15587
|
+
const isDemoRoot = existsSync7(markerPath) && readFileSync9(markerPath, "utf8").trim() === "hello-linzumi";
|
|
15202
15588
|
if (isDemoRoot && reset) {
|
|
15203
|
-
|
|
15589
|
+
rmSync2(root, { recursive: true, force: true });
|
|
15204
15590
|
return;
|
|
15205
15591
|
}
|
|
15206
15592
|
if (isDemoRoot) {
|
|
@@ -15233,7 +15619,7 @@ var init_helloLinzumiProject = __esm({
|
|
|
15233
15619
|
defaultHelloLinzumiHost = "0.0.0.0";
|
|
15234
15620
|
markerFile = ".linzumi-demo-project";
|
|
15235
15621
|
moduleDir = dirname5(fileURLToPath2(import.meta.url));
|
|
15236
|
-
linzumiLogoSvg =
|
|
15622
|
+
linzumiLogoSvg = readFileSync9(join12(moduleDir, "assets", "linzumi-logo.svg"), "utf8");
|
|
15237
15623
|
packageJson = `${JSON.stringify(
|
|
15238
15624
|
{
|
|
15239
15625
|
name: "hello-linzumi",
|
|
@@ -16035,14 +16421,14 @@ import {
|
|
|
16035
16421
|
copyFileSync,
|
|
16036
16422
|
cpSync,
|
|
16037
16423
|
existsSync as existsSync8,
|
|
16038
|
-
mkdirSync as
|
|
16424
|
+
mkdirSync as mkdirSync7,
|
|
16039
16425
|
mkdtempSync,
|
|
16040
|
-
readFileSync as
|
|
16426
|
+
readFileSync as readFileSync10,
|
|
16041
16427
|
realpathSync as realpathSync4,
|
|
16042
|
-
writeFileSync as
|
|
16428
|
+
writeFileSync as writeFileSync5
|
|
16043
16429
|
} from "node:fs";
|
|
16044
16430
|
import { tmpdir } from "node:os";
|
|
16045
|
-
import { basename as basename6, delimiter, dirname as dirname6, join as
|
|
16431
|
+
import { basename as basename6, delimiter, dirname as dirname6, join as join13 } from "node:path";
|
|
16046
16432
|
function isStartLocalEditorControl(control) {
|
|
16047
16433
|
return control.type === "start_local_editor";
|
|
16048
16434
|
}
|
|
@@ -16260,24 +16646,24 @@ function codeServerArgs(port, cwd, userDataDir, extensionsDir) {
|
|
|
16260
16646
|
}
|
|
16261
16647
|
function prepareCodeServerProfile(collaboration, editorRuntime) {
|
|
16262
16648
|
try {
|
|
16263
|
-
const userDataDir = mkdtempSync(
|
|
16264
|
-
const extensionsDir =
|
|
16265
|
-
const collaborationServerDir =
|
|
16266
|
-
const tempDir =
|
|
16267
|
-
const userSettingsDir =
|
|
16268
|
-
|
|
16269
|
-
|
|
16270
|
-
|
|
16271
|
-
|
|
16649
|
+
const userDataDir = mkdtempSync(join13(tmpdir(), "kandan-local-editor-"));
|
|
16650
|
+
const extensionsDir = join13(userDataDir, "extensions");
|
|
16651
|
+
const collaborationServerDir = join13(userDataDir, "collaboration-server");
|
|
16652
|
+
const tempDir = join13(userDataDir, "tmp");
|
|
16653
|
+
const userSettingsDir = join13(userDataDir, "User");
|
|
16654
|
+
mkdirSync7(userSettingsDir, { recursive: true });
|
|
16655
|
+
mkdirSync7(extensionsDir, { recursive: true });
|
|
16656
|
+
mkdirSync7(collaborationServerDir, { recursive: true });
|
|
16657
|
+
mkdirSync7(tempDir, { recursive: true });
|
|
16272
16658
|
if (editorRuntime !== void 0) {
|
|
16273
16659
|
ensureCodeServerBrowserExtensionAssets(editorRuntime);
|
|
16274
16660
|
installDirectory(
|
|
16275
16661
|
editorRuntime.assets.documentStateExtensionDir,
|
|
16276
|
-
|
|
16662
|
+
join13(extensionsDir, "kandan.document-state-telemetry")
|
|
16277
16663
|
);
|
|
16278
16664
|
}
|
|
16279
|
-
|
|
16280
|
-
|
|
16665
|
+
writeFileSync5(
|
|
16666
|
+
join13(userSettingsDir, "settings.json"),
|
|
16281
16667
|
JSON.stringify(codeServerSettings(collaboration), null, 2)
|
|
16282
16668
|
);
|
|
16283
16669
|
return { ok: true, userDataDir, extensionsDir, collaborationServerDir };
|
|
@@ -16289,14 +16675,14 @@ function ensureCodeServerBrowserExtensionAssets(runtime) {
|
|
|
16289
16675
|
const vscodeRoot = codeServerVscodeRoot(runtime);
|
|
16290
16676
|
const repairs = [
|
|
16291
16677
|
{
|
|
16292
|
-
source:
|
|
16678
|
+
source: join13(
|
|
16293
16679
|
vscodeRoot,
|
|
16294
16680
|
"extensions",
|
|
16295
16681
|
"git-base",
|
|
16296
16682
|
"dist",
|
|
16297
16683
|
"extension.js"
|
|
16298
16684
|
),
|
|
16299
|
-
target:
|
|
16685
|
+
target: join13(
|
|
16300
16686
|
vscodeRoot,
|
|
16301
16687
|
"extensions",
|
|
16302
16688
|
"git-base",
|
|
@@ -16307,14 +16693,14 @@ function ensureCodeServerBrowserExtensionAssets(runtime) {
|
|
|
16307
16693
|
required: true
|
|
16308
16694
|
},
|
|
16309
16695
|
{
|
|
16310
|
-
source:
|
|
16696
|
+
source: join13(
|
|
16311
16697
|
vscodeRoot,
|
|
16312
16698
|
"extensions",
|
|
16313
16699
|
"git-base",
|
|
16314
16700
|
"dist",
|
|
16315
16701
|
"extension.js.map"
|
|
16316
16702
|
),
|
|
16317
|
-
target:
|
|
16703
|
+
target: join13(
|
|
16318
16704
|
vscodeRoot,
|
|
16319
16705
|
"extensions",
|
|
16320
16706
|
"git-base",
|
|
@@ -16325,14 +16711,14 @@ function ensureCodeServerBrowserExtensionAssets(runtime) {
|
|
|
16325
16711
|
required: false
|
|
16326
16712
|
},
|
|
16327
16713
|
{
|
|
16328
|
-
source:
|
|
16714
|
+
source: join13(
|
|
16329
16715
|
vscodeRoot,
|
|
16330
16716
|
"extensions",
|
|
16331
16717
|
"merge-conflict",
|
|
16332
16718
|
"dist",
|
|
16333
16719
|
"mergeConflictMain.js"
|
|
16334
16720
|
),
|
|
16335
|
-
target:
|
|
16721
|
+
target: join13(
|
|
16336
16722
|
vscodeRoot,
|
|
16337
16723
|
"extensions",
|
|
16338
16724
|
"merge-conflict",
|
|
@@ -16343,14 +16729,14 @@ function ensureCodeServerBrowserExtensionAssets(runtime) {
|
|
|
16343
16729
|
required: true
|
|
16344
16730
|
},
|
|
16345
16731
|
{
|
|
16346
|
-
source:
|
|
16732
|
+
source: join13(
|
|
16347
16733
|
vscodeRoot,
|
|
16348
16734
|
"extensions",
|
|
16349
16735
|
"merge-conflict",
|
|
16350
16736
|
"dist",
|
|
16351
16737
|
"mergeConflictMain.js.map"
|
|
16352
16738
|
),
|
|
16353
|
-
target:
|
|
16739
|
+
target: join13(
|
|
16354
16740
|
vscodeRoot,
|
|
16355
16741
|
"extensions",
|
|
16356
16742
|
"merge-conflict",
|
|
@@ -16368,7 +16754,7 @@ function ensureCodeServerBrowserExtensionAssets(runtime) {
|
|
|
16368
16754
|
case (!required3 && !existsSync8(source)):
|
|
16369
16755
|
return;
|
|
16370
16756
|
default:
|
|
16371
|
-
|
|
16757
|
+
mkdirSync7(dirname6(target), { recursive: true });
|
|
16372
16758
|
copyFileSync(source, target);
|
|
16373
16759
|
return;
|
|
16374
16760
|
}
|
|
@@ -16376,10 +16762,10 @@ function ensureCodeServerBrowserExtensionAssets(runtime) {
|
|
|
16376
16762
|
}
|
|
16377
16763
|
function codeServerVscodeRoot(runtime) {
|
|
16378
16764
|
const roots = uniquePaths([
|
|
16379
|
-
|
|
16380
|
-
|
|
16765
|
+
join13(runtime.root, "lib", "vscode"),
|
|
16766
|
+
join13(dirname6(dirname6(runtime.codeServerBin)), "lib", "vscode"),
|
|
16381
16767
|
...wrappedCodeServerBin(runtime.codeServerBin).map(
|
|
16382
|
-
(codeServerBin) =>
|
|
16768
|
+
(codeServerBin) => join13(dirname6(dirname6(codeServerBin)), "lib", "vscode")
|
|
16383
16769
|
)
|
|
16384
16770
|
]);
|
|
16385
16771
|
const rootWithRequiredAssets = roots.find(
|
|
@@ -16395,7 +16781,7 @@ function codeServerVscodeRoot(runtime) {
|
|
|
16395
16781
|
}
|
|
16396
16782
|
function wrappedCodeServerBin(codeServerBin) {
|
|
16397
16783
|
try {
|
|
16398
|
-
const script =
|
|
16784
|
+
const script = readFileSync10(codeServerBin, "utf8");
|
|
16399
16785
|
const match = script.match(
|
|
16400
16786
|
/exec\s+(?:"([^"]+)"|'([^']+)'|([^\s]+))\s+"\$@"/u
|
|
16401
16787
|
);
|
|
@@ -16407,8 +16793,8 @@ function wrappedCodeServerBin(codeServerBin) {
|
|
|
16407
16793
|
}
|
|
16408
16794
|
function codeServerBrowserAssetSources(vscodeRoot) {
|
|
16409
16795
|
return [
|
|
16410
|
-
|
|
16411
|
-
|
|
16796
|
+
join13(vscodeRoot, "extensions", "git-base", "dist", "extension.js"),
|
|
16797
|
+
join13(
|
|
16412
16798
|
vscodeRoot,
|
|
16413
16799
|
"extensions",
|
|
16414
16800
|
"merge-conflict",
|
|
@@ -16487,10 +16873,10 @@ function prepareLinuxCodeServerLaunch(options) {
|
|
|
16487
16873
|
options.cwd,
|
|
16488
16874
|
"--setenv",
|
|
16489
16875
|
"XDG_DATA_HOME",
|
|
16490
|
-
|
|
16876
|
+
join13(options.userDataDir, "data"),
|
|
16491
16877
|
"--setenv",
|
|
16492
16878
|
"XDG_CONFIG_HOME",
|
|
16493
|
-
|
|
16879
|
+
join13(options.userDataDir, "config"),
|
|
16494
16880
|
...readOnlyRoots.flatMap((path2) => ["--ro-bind-try", path2, path2]),
|
|
16495
16881
|
"--bind",
|
|
16496
16882
|
options.cwd,
|
|
@@ -16531,7 +16917,7 @@ function resolveCodeServerExecutable(command, envPath) {
|
|
|
16531
16917
|
if (directory.trim() === "") {
|
|
16532
16918
|
continue;
|
|
16533
16919
|
}
|
|
16534
|
-
const candidate =
|
|
16920
|
+
const candidate = join13(directory, command);
|
|
16535
16921
|
if (!existsSync8(candidate)) {
|
|
16536
16922
|
continue;
|
|
16537
16923
|
}
|
|
@@ -16617,7 +17003,7 @@ async function startCollaborationSidecar(collaboration, profile, editorRuntime,
|
|
|
16617
17003
|
]);
|
|
16618
17004
|
const command = nodeRuntimeExecutable();
|
|
16619
17005
|
const args = [
|
|
16620
|
-
|
|
17006
|
+
join13(
|
|
16621
17007
|
profile.collaborationServerDir,
|
|
16622
17008
|
"open-collaboration-server",
|
|
16623
17009
|
"bundle",
|
|
@@ -16712,11 +17098,11 @@ function nodeRuntimeExecutable(env = process.env, execPath = process.execPath) {
|
|
|
16712
17098
|
return basename6(execPath).toLowerCase().includes("bun") ? "node" : execPath;
|
|
16713
17099
|
}
|
|
16714
17100
|
async function installLocalTarball(archivePath, destinationDir) {
|
|
16715
|
-
|
|
17101
|
+
mkdirSync7(destinationDir, { recursive: true });
|
|
16716
17102
|
await runProcess("tar", ["-xzf", archivePath, "-C", destinationDir]);
|
|
16717
17103
|
}
|
|
16718
17104
|
function installDirectory(sourceDir, destinationDir) {
|
|
16719
|
-
|
|
17105
|
+
mkdirSync7(dirname6(destinationDir), { recursive: true });
|
|
16720
17106
|
cpSync(sourceDir, destinationDir, { recursive: true });
|
|
16721
17107
|
}
|
|
16722
17108
|
function codeServerEnv(env, cwd, userDataDir, collaboration) {
|
|
@@ -16734,7 +17120,7 @@ function codeServerEnv(env, cwd, userDataDir, collaboration) {
|
|
|
16734
17120
|
KANDAN_EDITOR_COLLABORATION_ENTRY_MODE: "kandan_auto_host_or_join",
|
|
16735
17121
|
KANDAN_EDITOR_COLLABORATION_ROOM_ID: collaboration.roomId,
|
|
16736
17122
|
KANDAN_EDITOR_COLLABORATION_SERVER_URL: collaboration.bootstrapServerUrl,
|
|
16737
|
-
KANDAN_EDITOR_COLLABORATION_AUTO_HOST_CLAIM_PATH:
|
|
17123
|
+
KANDAN_EDITOR_COLLABORATION_AUTO_HOST_CLAIM_PATH: join13(
|
|
16738
17124
|
userDataDir,
|
|
16739
17125
|
"kandan-oct-auto-host.lock"
|
|
16740
17126
|
)
|
|
@@ -16943,15 +17329,15 @@ import {
|
|
|
16943
17329
|
createReadStream,
|
|
16944
17330
|
createWriteStream as createWriteStream2,
|
|
16945
17331
|
existsSync as existsSync9,
|
|
16946
|
-
mkdirSync as
|
|
17332
|
+
mkdirSync as mkdirSync8,
|
|
16947
17333
|
mkdtempSync as mkdtempSync2,
|
|
16948
|
-
readFileSync as
|
|
17334
|
+
readFileSync as readFileSync11,
|
|
16949
17335
|
renameSync,
|
|
16950
|
-
rmSync as
|
|
16951
|
-
writeFileSync as
|
|
17336
|
+
rmSync as rmSync3,
|
|
17337
|
+
writeFileSync as writeFileSync6
|
|
16952
17338
|
} from "node:fs";
|
|
16953
|
-
import { homedir as
|
|
16954
|
-
import { dirname as dirname7, join as
|
|
17339
|
+
import { homedir as homedir11 } from "node:os";
|
|
17340
|
+
import { dirname as dirname7, join as join14, resolve as resolve7 } from "node:path";
|
|
16955
17341
|
import { Readable } from "node:stream";
|
|
16956
17342
|
import { pipeline } from "node:stream/promises";
|
|
16957
17343
|
async function resolveEditorRuntime(options) {
|
|
@@ -17142,14 +17528,14 @@ function normalizeRuntimeAssets(value) {
|
|
|
17142
17528
|
}
|
|
17143
17529
|
function installedRuntime(cacheRoot, manifest) {
|
|
17144
17530
|
const runtimeRoot = runtimeInstallRoot(cacheRoot, manifest);
|
|
17145
|
-
const manifestPath =
|
|
17146
|
-
const codeServerBin =
|
|
17531
|
+
const manifestPath = join14(runtimeRoot, manifest.manifestPath);
|
|
17532
|
+
const codeServerBin = join14(runtimeRoot, manifest.codeServerBinPath);
|
|
17147
17533
|
const assets = verifiedRuntimeAssetPaths(runtimeRoot, manifest);
|
|
17148
17534
|
if (!existsSync9(manifestPath) || !existsSync9(codeServerBin) || assets === void 0) {
|
|
17149
17535
|
return { ok: false };
|
|
17150
17536
|
}
|
|
17151
17537
|
try {
|
|
17152
|
-
const installed = JSON.parse(
|
|
17538
|
+
const installed = JSON.parse(readFileSync11(manifestPath, "utf8"));
|
|
17153
17539
|
if (isJsonObject(installed) && installed.version === manifest.version && installed.platform === manifest.platform && (installed.archiveSha256 === void 0 || installed.archiveSha256 === manifest.archiveSha256)) {
|
|
17154
17540
|
return {
|
|
17155
17541
|
ok: true,
|
|
@@ -17167,10 +17553,10 @@ function installedRuntime(cacheRoot, manifest) {
|
|
|
17167
17553
|
return { ok: false };
|
|
17168
17554
|
}
|
|
17169
17555
|
async function installRuntime(args) {
|
|
17170
|
-
|
|
17171
|
-
const tempRoot = mkdtempSync2(
|
|
17172
|
-
const archivePath =
|
|
17173
|
-
const extractRoot =
|
|
17556
|
+
mkdirSync8(args.cacheRoot, { recursive: true });
|
|
17557
|
+
const tempRoot = mkdtempSync2(join14(args.cacheRoot, ".install-"));
|
|
17558
|
+
const archivePath = join14(tempRoot, "runtime.tar.gz");
|
|
17559
|
+
const extractRoot = join14(tempRoot, "runtime");
|
|
17174
17560
|
try {
|
|
17175
17561
|
const downloaded = await downloadArchive({
|
|
17176
17562
|
kandanUrl: args.kandanUrl,
|
|
@@ -17182,7 +17568,7 @@ async function installRuntime(args) {
|
|
|
17182
17568
|
if (!downloaded.ok) {
|
|
17183
17569
|
return downloaded;
|
|
17184
17570
|
}
|
|
17185
|
-
|
|
17571
|
+
mkdirSync8(extractRoot, { recursive: true });
|
|
17186
17572
|
if (!await args.extractArchive(archivePath, extractRoot)) {
|
|
17187
17573
|
return { ok: false, reason: "archive_extract_failed" };
|
|
17188
17574
|
}
|
|
@@ -17195,14 +17581,14 @@ async function installRuntime(args) {
|
|
|
17195
17581
|
if (!assetsInstalled) {
|
|
17196
17582
|
return { ok: false, reason: "install_failed" };
|
|
17197
17583
|
}
|
|
17198
|
-
const manifestPath =
|
|
17199
|
-
const codeServerBin =
|
|
17584
|
+
const manifestPath = join14(extractRoot, args.manifest.manifestPath);
|
|
17585
|
+
const codeServerBin = join14(extractRoot, args.manifest.codeServerBinPath);
|
|
17200
17586
|
const assets = verifiedRuntimeAssetPaths(extractRoot, args.manifest);
|
|
17201
17587
|
if (!existsSync9(codeServerBin) || assets === void 0) {
|
|
17202
17588
|
return { ok: false, reason: "invalid_archive" };
|
|
17203
17589
|
}
|
|
17204
|
-
|
|
17205
|
-
|
|
17590
|
+
mkdirSync8(dirname7(manifestPath), { recursive: true });
|
|
17591
|
+
writeFileSync6(
|
|
17206
17592
|
manifestPath,
|
|
17207
17593
|
JSON.stringify(
|
|
17208
17594
|
{
|
|
@@ -17219,29 +17605,29 @@ async function installRuntime(args) {
|
|
|
17219
17605
|
)
|
|
17220
17606
|
);
|
|
17221
17607
|
const targetRoot = runtimeInstallRoot(args.cacheRoot, args.manifest);
|
|
17222
|
-
|
|
17223
|
-
|
|
17608
|
+
rmSync3(targetRoot, { recursive: true, force: true });
|
|
17609
|
+
mkdirSync8(dirname7(targetRoot), { recursive: true });
|
|
17224
17610
|
renameSync(extractRoot, targetRoot);
|
|
17225
17611
|
return {
|
|
17226
17612
|
ok: true,
|
|
17227
17613
|
runtime: {
|
|
17228
17614
|
mode: "server_managed",
|
|
17229
17615
|
root: targetRoot,
|
|
17230
|
-
codeServerBin:
|
|
17616
|
+
codeServerBin: join14(targetRoot, args.manifest.codeServerBinPath),
|
|
17231
17617
|
assets: {
|
|
17232
|
-
collaborationExtensionTarball:
|
|
17618
|
+
collaborationExtensionTarball: join14(
|
|
17233
17619
|
targetRoot,
|
|
17234
17620
|
"kandan",
|
|
17235
17621
|
"editor_extensions",
|
|
17236
17622
|
"typefox.open-collaboration-tools.tar.gz"
|
|
17237
17623
|
),
|
|
17238
|
-
collaborationServerTarball:
|
|
17624
|
+
collaborationServerTarball: join14(
|
|
17239
17625
|
targetRoot,
|
|
17240
17626
|
"kandan",
|
|
17241
17627
|
"editor_servers",
|
|
17242
17628
|
"open-collaboration-server.tar.gz"
|
|
17243
17629
|
),
|
|
17244
|
-
documentStateExtensionDir:
|
|
17630
|
+
documentStateExtensionDir: join14(
|
|
17245
17631
|
targetRoot,
|
|
17246
17632
|
"kandan",
|
|
17247
17633
|
"editor_extensions",
|
|
@@ -17253,12 +17639,12 @@ async function installRuntime(args) {
|
|
|
17253
17639
|
} catch (_error) {
|
|
17254
17640
|
return { ok: false, reason: "install_failed" };
|
|
17255
17641
|
} finally {
|
|
17256
|
-
|
|
17642
|
+
rmSync3(tempRoot, { recursive: true, force: true });
|
|
17257
17643
|
}
|
|
17258
17644
|
}
|
|
17259
17645
|
async function materializeRuntimeAssets(args) {
|
|
17260
17646
|
for (const asset of args.manifest.assets) {
|
|
17261
|
-
const targetPath =
|
|
17647
|
+
const targetPath = join14(args.runtimeRoot, asset.path);
|
|
17262
17648
|
try {
|
|
17263
17649
|
const bytes = await runtimeAssetBytes({
|
|
17264
17650
|
kandanUrl: args.kandanUrl,
|
|
@@ -17268,8 +17654,8 @@ async function materializeRuntimeAssets(args) {
|
|
|
17268
17654
|
if (bytes === void 0) {
|
|
17269
17655
|
continue;
|
|
17270
17656
|
}
|
|
17271
|
-
|
|
17272
|
-
|
|
17657
|
+
mkdirSync8(dirname7(targetPath), { recursive: true });
|
|
17658
|
+
writeFileSync6(targetPath, bytes);
|
|
17273
17659
|
} catch (_error) {
|
|
17274
17660
|
return false;
|
|
17275
17661
|
}
|
|
@@ -17359,19 +17745,19 @@ function runtimeInstallRoot(cacheRoot, manifest) {
|
|
|
17359
17745
|
return resolve7(cacheRoot, manifest.platform, manifest.archiveSha256);
|
|
17360
17746
|
}
|
|
17361
17747
|
function verifiedRuntimeAssetPaths(runtimeRoot, manifest) {
|
|
17362
|
-
const collaborationExtensionTarball =
|
|
17748
|
+
const collaborationExtensionTarball = join14(
|
|
17363
17749
|
runtimeRoot,
|
|
17364
17750
|
"kandan",
|
|
17365
17751
|
"editor_extensions",
|
|
17366
17752
|
"typefox.open-collaboration-tools.tar.gz"
|
|
17367
17753
|
);
|
|
17368
|
-
const collaborationServerTarball =
|
|
17754
|
+
const collaborationServerTarball = join14(
|
|
17369
17755
|
runtimeRoot,
|
|
17370
17756
|
"kandan",
|
|
17371
17757
|
"editor_servers",
|
|
17372
17758
|
"open-collaboration-server.tar.gz"
|
|
17373
17759
|
);
|
|
17374
|
-
const documentStateExtensionDir =
|
|
17760
|
+
const documentStateExtensionDir = join14(
|
|
17375
17761
|
runtimeRoot,
|
|
17376
17762
|
"kandan",
|
|
17377
17763
|
"editor_extensions",
|
|
@@ -17380,7 +17766,7 @@ function verifiedRuntimeAssetPaths(runtimeRoot, manifest) {
|
|
|
17380
17766
|
const codeServerRoot = codeServerRuntimeRoot(manifest.codeServerBinPath);
|
|
17381
17767
|
const requiredPaths = [
|
|
17382
17768
|
manifest.codeServerBinPath,
|
|
17383
|
-
|
|
17769
|
+
join14(
|
|
17384
17770
|
codeServerRoot,
|
|
17385
17771
|
"lib",
|
|
17386
17772
|
"vscode",
|
|
@@ -17390,7 +17776,7 @@ function verifiedRuntimeAssetPaths(runtimeRoot, manifest) {
|
|
|
17390
17776
|
"web",
|
|
17391
17777
|
"vsda.js"
|
|
17392
17778
|
),
|
|
17393
|
-
|
|
17779
|
+
join14(
|
|
17394
17780
|
codeServerRoot,
|
|
17395
17781
|
"lib",
|
|
17396
17782
|
"vscode",
|
|
@@ -17411,7 +17797,7 @@ function verifiedRuntimeAssetPaths(runtimeRoot, manifest) {
|
|
|
17411
17797
|
if (expectedSha256 === void 0 && relativePath !== manifest.codeServerBinPath) {
|
|
17412
17798
|
return void 0;
|
|
17413
17799
|
}
|
|
17414
|
-
const absolutePath =
|
|
17800
|
+
const absolutePath = join14(runtimeRoot, relativePath);
|
|
17415
17801
|
if (!existsSync9(absolutePath)) {
|
|
17416
17802
|
return void 0;
|
|
17417
17803
|
}
|
|
@@ -17440,10 +17826,10 @@ function manifestAssetChecksums(assets) {
|
|
|
17440
17826
|
return checksums;
|
|
17441
17827
|
}
|
|
17442
17828
|
function fileSha256Sync(path2) {
|
|
17443
|
-
return createHash4("sha256").update(
|
|
17829
|
+
return createHash4("sha256").update(readFileSync11(path2)).digest("hex");
|
|
17444
17830
|
}
|
|
17445
17831
|
function defaultEditorRuntimeCacheRoot() {
|
|
17446
|
-
return
|
|
17832
|
+
return join14(homedir11(), ".linzumi", "editor-runtimes");
|
|
17447
17833
|
}
|
|
17448
17834
|
function nonEmptyString(value) {
|
|
17449
17835
|
return typeof value === "string" && value.trim() !== "" ? value.trim() : void 0;
|
|
@@ -17463,7 +17849,7 @@ var init_localEditorRuntime = __esm({
|
|
|
17463
17849
|
|
|
17464
17850
|
// src/dependencyStatus.ts
|
|
17465
17851
|
import { spawn as spawn6, spawnSync as spawnSync4 } from "node:child_process";
|
|
17466
|
-
import { delimiter as delimiter2, dirname as dirname8, join as
|
|
17852
|
+
import { delimiter as delimiter2, dirname as dirname8, join as join15 } from "node:path";
|
|
17467
17853
|
function probeTool(command, cwd) {
|
|
17468
17854
|
return new Promise((resolve12) => {
|
|
17469
17855
|
const args = ["--version"];
|
|
@@ -17620,8 +18006,8 @@ function voltaCommandCandidates(args) {
|
|
|
17620
18006
|
new Set(
|
|
17621
18007
|
[
|
|
17622
18008
|
voltaBinBesideCodexShim(args.codexBin),
|
|
17623
|
-
env.VOLTA_HOME === void 0 ? void 0 :
|
|
17624
|
-
env.HOME === void 0 ? void 0 :
|
|
18009
|
+
env.VOLTA_HOME === void 0 ? void 0 : join15(env.VOLTA_HOME, "bin", "volta"),
|
|
18010
|
+
env.HOME === void 0 ? void 0 : join15(env.HOME, ".volta", "bin", "volta"),
|
|
17625
18011
|
...pathVoltaCandidates(env.PATH)
|
|
17626
18012
|
].filter((candidate) => candidate !== void 0)
|
|
17627
18013
|
)
|
|
@@ -17629,10 +18015,10 @@ function voltaCommandCandidates(args) {
|
|
|
17629
18015
|
}
|
|
17630
18016
|
function voltaBinBesideCodexShim(codexBin) {
|
|
17631
18017
|
const normalizedCodexBin = codexBin.replaceAll("\\", "/");
|
|
17632
|
-
return normalizedCodexBin.endsWith("/.volta/bin/codex") ?
|
|
18018
|
+
return normalizedCodexBin.endsWith("/.volta/bin/codex") ? join15(dirname8(codexBin), "volta") : void 0;
|
|
17633
18019
|
}
|
|
17634
18020
|
function pathVoltaCandidates(pathValue) {
|
|
17635
|
-
return pathValue === void 0 ? [] : pathValue.split(delimiter2).filter((entry) => entry !== "").map((entry) =>
|
|
18021
|
+
return pathValue === void 0 ? [] : pathValue.split(delimiter2).filter((entry) => entry !== "").map((entry) => join15(entry, "volta"));
|
|
17636
18022
|
}
|
|
17637
18023
|
function codeServerDependencyStatus(args) {
|
|
17638
18024
|
switch (args.editorRuntime?.status) {
|
|
@@ -17741,7 +18127,7 @@ var linzumiCliVersion, linzumiCliVersionText;
|
|
|
17741
18127
|
var init_version = __esm({
|
|
17742
18128
|
"src/version.ts"() {
|
|
17743
18129
|
"use strict";
|
|
17744
|
-
linzumiCliVersion = "0.0.
|
|
18130
|
+
linzumiCliVersion = "0.0.85-beta";
|
|
17745
18131
|
linzumiCliVersionText = `linzumi ${linzumiCliVersion}`;
|
|
17746
18132
|
}
|
|
17747
18133
|
});
|
|
@@ -17750,21 +18136,21 @@ var init_version = __esm({
|
|
|
17750
18136
|
import {
|
|
17751
18137
|
closeSync as closeSync2,
|
|
17752
18138
|
existsSync as existsSync10,
|
|
17753
|
-
mkdirSync as
|
|
18139
|
+
mkdirSync as mkdirSync9,
|
|
17754
18140
|
openSync as openSync3,
|
|
17755
|
-
readFileSync as
|
|
18141
|
+
readFileSync as readFileSync12,
|
|
17756
18142
|
renameSync as renameSync2,
|
|
17757
18143
|
unlinkSync as unlinkSync2,
|
|
17758
|
-
writeFileSync as
|
|
18144
|
+
writeFileSync as writeFileSync7,
|
|
17759
18145
|
writeSync
|
|
17760
18146
|
} from "node:fs";
|
|
17761
|
-
import { dirname as dirname9, join as
|
|
18147
|
+
import { dirname as dirname9, join as join16 } from "node:path";
|
|
17762
18148
|
function isRunnerLockHeldError(error) {
|
|
17763
18149
|
return error instanceof RunnerLockHeldError || error instanceof Error && error.name === runnerLockHeldErrorName && "lockPath" in error && "heldBy" in error;
|
|
17764
18150
|
}
|
|
17765
18151
|
function runnerLockPath(machineId, configPath = localConfigPath(), linzumiUrl) {
|
|
17766
18152
|
const lockName = linzumiUrl === void 0 ? encodeURIComponent(machineId) : localConfigScopeFileStem(linzumiUrl);
|
|
17767
|
-
return
|
|
18153
|
+
return join16(dirname9(configPath), "runners", `${lockName}.lock`);
|
|
17768
18154
|
}
|
|
17769
18155
|
function acquireRunnerLock(options) {
|
|
17770
18156
|
const path2 = runnerLockPath(
|
|
@@ -17832,7 +18218,7 @@ function stampRunnerLockHeartbeat(path2, record, now) {
|
|
|
17832
18218
|
heartbeatAt: now().toISOString()
|
|
17833
18219
|
};
|
|
17834
18220
|
const tmpPath = `${path2}.tmp`;
|
|
17835
|
-
|
|
18221
|
+
writeFileSync7(tmpPath, `${JSON.stringify(next, null, 2)}
|
|
17836
18222
|
`, "utf8");
|
|
17837
18223
|
renameSync2(tmpPath, path2);
|
|
17838
18224
|
} catch (_error) {
|
|
@@ -17944,7 +18330,7 @@ function writeLockOrHandleExisting(path2, record, isPidAlive, now, killPid, onTa
|
|
|
17944
18330
|
});
|
|
17945
18331
|
}
|
|
17946
18332
|
function tryCreateLock(path2, record) {
|
|
17947
|
-
|
|
18333
|
+
mkdirSync9(dirname9(path2), { recursive: true });
|
|
17948
18334
|
try {
|
|
17949
18335
|
const fd = openSync3(path2, "wx");
|
|
17950
18336
|
try {
|
|
@@ -18000,7 +18386,7 @@ function withStaleReplacementLock(path2, isPidAlive, callback) {
|
|
|
18000
18386
|
function readReplacementLockPidIfPresent(path2) {
|
|
18001
18387
|
let value;
|
|
18002
18388
|
try {
|
|
18003
|
-
value =
|
|
18389
|
+
value = readFileSync12(path2, "utf8").trim();
|
|
18004
18390
|
} catch (error) {
|
|
18005
18391
|
if (isNodeErrorCode2(error, "ENOENT")) {
|
|
18006
18392
|
return void 0;
|
|
@@ -18040,7 +18426,7 @@ function readRunnerLockIfPresent(path2) {
|
|
|
18040
18426
|
}
|
|
18041
18427
|
}
|
|
18042
18428
|
function readRunnerLock(path2) {
|
|
18043
|
-
const parsed = JSON.parse(
|
|
18429
|
+
const parsed = JSON.parse(readFileSync12(path2, "utf8"));
|
|
18044
18430
|
if (!isRunnerLockRecord(parsed)) {
|
|
18045
18431
|
throw new Error(`invalid Linzumi runner lock: ${path2}`);
|
|
18046
18432
|
}
|
|
@@ -18327,6 +18713,19 @@ function updateRunnerConsoleDashboard(state, event, payload, nowMs) {
|
|
|
18327
18713
|
job.updatedAtMs = nowMs;
|
|
18328
18714
|
break;
|
|
18329
18715
|
}
|
|
18716
|
+
// Live token counter parity with codex.notification token_usage_summary:
|
|
18717
|
+
// mid-turn usage events advance the dashboard counters per model round.
|
|
18718
|
+
case "claude_code.token_usage": {
|
|
18719
|
+
const tokenUsage = stringValue5(payload.token_usage_summary);
|
|
18720
|
+
const job = claudeDashboardJob(state, payload, nowMs);
|
|
18721
|
+
if (tokenUsage !== void 0) {
|
|
18722
|
+
state.tokenUsage = tokenUsage;
|
|
18723
|
+
job.tokenUsage = tokenUsage;
|
|
18724
|
+
}
|
|
18725
|
+
job.eventType = "token_usage";
|
|
18726
|
+
job.updatedAtMs = nowMs;
|
|
18727
|
+
break;
|
|
18728
|
+
}
|
|
18330
18729
|
default:
|
|
18331
18730
|
break;
|
|
18332
18731
|
}
|
|
@@ -18787,6 +19186,8 @@ function formatRunnerConsoleEvent(event, payload) {
|
|
|
18787
19186
|
return `Claude Code turn ${text(payload.outcome)}: id=${text(payload.turn_id)}`;
|
|
18788
19187
|
case "claude_code.rate_limit":
|
|
18789
19188
|
return `Claude Code rate limit: ${stringValue5(payload.rate_limit_summary) ?? "seen (no details)"}`;
|
|
19189
|
+
case "claude_code.token_usage":
|
|
19190
|
+
return `Claude Code token usage: ${stringValue5(payload.token_usage_summary) ?? "seen (no details)"}`;
|
|
18790
19191
|
default:
|
|
18791
19192
|
return void 0;
|
|
18792
19193
|
}
|
|
@@ -18849,7 +19250,9 @@ function ignoredMessage(payload) {
|
|
|
18849
19250
|
`reason=${text(payload.reason)}`,
|
|
18850
19251
|
optionalField("type", payload.type),
|
|
18851
19252
|
optionalField("thread", payload.thread_id),
|
|
19253
|
+
optionalField("bound_thread", payload.bound_thread_id),
|
|
18852
19254
|
optionalField("body_chars", payload.body_length),
|
|
19255
|
+
optionalField("body", payload.body_preview),
|
|
18853
19256
|
optionalField("attachments", payload.attachment_count),
|
|
18854
19257
|
optionalField("local_event", payload.local_runner_event_type)
|
|
18855
19258
|
].filter((part) => part !== void 0).join(" ");
|
|
@@ -19730,8 +20133,8 @@ var init_runnerConsoleReporter = __esm({
|
|
|
19730
20133
|
});
|
|
19731
20134
|
|
|
19732
20135
|
// src/telemetry.ts
|
|
19733
|
-
import { mkdirSync as
|
|
19734
|
-
import { dirname as dirname10, basename as basename7, join as
|
|
20136
|
+
import { mkdirSync as mkdirSync10, readFileSync as readFileSync13, writeFileSync as writeFileSync8 } from "node:fs";
|
|
20137
|
+
import { dirname as dirname10, basename as basename7, join as join17 } from "node:path";
|
|
19735
20138
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
19736
20139
|
function peekFlagValue(args, flags) {
|
|
19737
20140
|
for (let index = 0; index < args.length; index += 1) {
|
|
@@ -19770,12 +20173,12 @@ function telemetryBaseUrl(apiUrl, env = process.env) {
|
|
|
19770
20173
|
}
|
|
19771
20174
|
}
|
|
19772
20175
|
function telemetryInstallIdPath(env = process.env) {
|
|
19773
|
-
return
|
|
20176
|
+
return join17(dirname10(localConfigPath(env)), "install-id");
|
|
19774
20177
|
}
|
|
19775
20178
|
function ensureTelemetryInstallId(env = process.env) {
|
|
19776
20179
|
const path2 = telemetryInstallIdPath(env);
|
|
19777
20180
|
try {
|
|
19778
|
-
const existing =
|
|
20181
|
+
const existing = readFileSync13(path2, "utf8").trim();
|
|
19779
20182
|
if (existing !== "" && existing.length <= 128) {
|
|
19780
20183
|
return existing;
|
|
19781
20184
|
}
|
|
@@ -19783,8 +20186,8 @@ function ensureTelemetryInstallId(env = process.env) {
|
|
|
19783
20186
|
}
|
|
19784
20187
|
const installId = randomUUID3();
|
|
19785
20188
|
try {
|
|
19786
|
-
|
|
19787
|
-
|
|
20189
|
+
mkdirSync10(dirname10(path2), { recursive: true });
|
|
20190
|
+
writeFileSync8(path2, `${installId}
|
|
19788
20191
|
`, { mode: 384 });
|
|
19789
20192
|
} catch {
|
|
19790
20193
|
}
|
|
@@ -19971,17 +20374,17 @@ var init_linzumiApiClient = __esm({
|
|
|
19971
20374
|
});
|
|
19972
20375
|
|
|
19973
20376
|
// src/authCache.ts
|
|
19974
|
-
import { existsSync as existsSync11, mkdirSync as
|
|
19975
|
-
import { homedir as
|
|
19976
|
-
import { dirname as dirname11, join as
|
|
20377
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync11, readFileSync as readFileSync14, writeFileSync as writeFileSync9 } from "node:fs";
|
|
20378
|
+
import { homedir as homedir12 } from "node:os";
|
|
20379
|
+
import { dirname as dirname11, join as join18 } from "node:path";
|
|
19977
20380
|
function defaultAuthFilePath() {
|
|
19978
|
-
return
|
|
20381
|
+
return join18(homedir12(), ".linzumi", "auth.json");
|
|
19979
20382
|
}
|
|
19980
20383
|
function readCachedLocalRunnerToken(kandanUrl, authFilePath = defaultAuthFilePath()) {
|
|
19981
20384
|
if (!existsSync11(authFilePath)) {
|
|
19982
20385
|
return void 0;
|
|
19983
20386
|
}
|
|
19984
|
-
const authFile = parseAuthFile(
|
|
20387
|
+
const authFile = parseAuthFile(readFileSync14(authFilePath, "utf8"));
|
|
19985
20388
|
const kandanBaseUrl = kandanHttpBaseUrl(kandanUrl);
|
|
19986
20389
|
const entry = authFile.local_codex_runner?.[kandanBaseUrl];
|
|
19987
20390
|
if (entry === void 0 || entry.access_token.trim() === "") {
|
|
@@ -20003,7 +20406,7 @@ function readPersonalAgentDelegationToken(authFilePath) {
|
|
|
20003
20406
|
`missing personal-agent delegation auth file: ${authFilePath}`
|
|
20004
20407
|
);
|
|
20005
20408
|
}
|
|
20006
|
-
const authFile = parseAuthFile(
|
|
20409
|
+
const authFile = parseAuthFile(readFileSync14(authFilePath, "utf8"));
|
|
20007
20410
|
const entry = authFile.personal_agent_delegation;
|
|
20008
20411
|
if (entry === void 0 || entry.access_token.trim() === "") {
|
|
20009
20412
|
throw new Error(
|
|
@@ -20021,7 +20424,7 @@ function readPersonalAgentDelegationToken(authFilePath) {
|
|
|
20021
20424
|
}
|
|
20022
20425
|
function writeCachedLocalRunnerToken(args) {
|
|
20023
20426
|
const authFilePath = args.authFilePath ?? defaultAuthFilePath();
|
|
20024
|
-
const existing = existsSync11(authFilePath) ? parseAuthFile(
|
|
20427
|
+
const existing = existsSync11(authFilePath) ? parseAuthFile(readFileSync14(authFilePath, "utf8")) : { version: 1 };
|
|
20025
20428
|
const kandanBaseUrl = kandanHttpBaseUrl(args.kandanUrl);
|
|
20026
20429
|
const issuedAt = /* @__PURE__ */ new Date();
|
|
20027
20430
|
const expiresAt = args.expiresInSeconds === void 0 ? void 0 : new Date(
|
|
@@ -20039,8 +20442,8 @@ function writeCachedLocalRunnerToken(args) {
|
|
|
20039
20442
|
}
|
|
20040
20443
|
}
|
|
20041
20444
|
};
|
|
20042
|
-
|
|
20043
|
-
|
|
20445
|
+
mkdirSync11(dirname11(authFilePath), { recursive: true });
|
|
20446
|
+
writeFileSync9(authFilePath, `${JSON.stringify(next, null, 2)}
|
|
20044
20447
|
`, "utf8");
|
|
20045
20448
|
return {
|
|
20046
20449
|
accessToken: args.accessToken,
|
|
@@ -20485,9 +20888,9 @@ var init_threadCodexWorkerIpc = __esm({
|
|
|
20485
20888
|
|
|
20486
20889
|
// src/signupTaskSuggestions.ts
|
|
20487
20890
|
import { spawn as spawn7 } from "node:child_process";
|
|
20488
|
-
import { mkdtempSync as mkdtempSync3, readFileSync as
|
|
20891
|
+
import { mkdtempSync as mkdtempSync3, readFileSync as readFileSync15, rmSync as rmSync4, writeFileSync as writeFileSync10 } from "node:fs";
|
|
20489
20892
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
20490
|
-
import { join as
|
|
20893
|
+
import { join as join19 } from "node:path";
|
|
20491
20894
|
async function suggestSignupTasksWithCodex(args) {
|
|
20492
20895
|
const attempts = 2;
|
|
20493
20896
|
let previousResponse;
|
|
@@ -20509,11 +20912,11 @@ async function suggestSignupTasksWithCodex(args) {
|
|
|
20509
20912
|
);
|
|
20510
20913
|
}
|
|
20511
20914
|
async function runCodexTaskSuggestion(args) {
|
|
20512
|
-
const tempRoot = mkdtempSync3(
|
|
20513
|
-
const schemaPath =
|
|
20514
|
-
const outputPath =
|
|
20915
|
+
const tempRoot = mkdtempSync3(join19(tmpdir2(), "linzumi-signup-codex-tasks-"));
|
|
20916
|
+
const schemaPath = join19(tempRoot, "task-suggestions.schema.json");
|
|
20917
|
+
const outputPath = join19(tempRoot, "task-suggestions.json");
|
|
20515
20918
|
const prompt = taskSuggestionPrompt(args.previousResponse);
|
|
20516
|
-
|
|
20919
|
+
writeFileSync10(
|
|
20517
20920
|
schemaPath,
|
|
20518
20921
|
`${JSON.stringify(taskSuggestionJsonSchema(), null, 2)}
|
|
20519
20922
|
`,
|
|
@@ -20530,9 +20933,9 @@ async function runCodexTaskSuggestion(args) {
|
|
|
20530
20933
|
prompt
|
|
20531
20934
|
})
|
|
20532
20935
|
);
|
|
20533
|
-
return
|
|
20936
|
+
return readFileSync15(outputPath, "utf8");
|
|
20534
20937
|
} finally {
|
|
20535
|
-
|
|
20938
|
+
rmSync4(tempRoot, { recursive: true, force: true });
|
|
20536
20939
|
}
|
|
20537
20940
|
}
|
|
20538
20941
|
function codexTaskSuggestionProcess(args) {
|
|
@@ -20979,25 +21382,25 @@ import { createHash as createHash5, randomUUID as randomUUID4 } from "node:crypt
|
|
|
20979
21382
|
import {
|
|
20980
21383
|
chmodSync as chmodSync2,
|
|
20981
21384
|
lstatSync,
|
|
20982
|
-
mkdirSync as
|
|
21385
|
+
mkdirSync as mkdirSync12,
|
|
20983
21386
|
mkdtempSync as mkdtempSync4,
|
|
20984
21387
|
readdirSync as readdirSync4,
|
|
20985
|
-
readFileSync as
|
|
21388
|
+
readFileSync as readFileSync16,
|
|
20986
21389
|
realpathSync as realpathSync6,
|
|
20987
21390
|
renameSync as renameSync3,
|
|
20988
|
-
rmSync as
|
|
21391
|
+
rmSync as rmSync5,
|
|
20989
21392
|
statSync as statSync3,
|
|
20990
|
-
writeFileSync as
|
|
21393
|
+
writeFileSync as writeFileSync11
|
|
20991
21394
|
} from "node:fs";
|
|
20992
21395
|
import { readFile as readFile2 } from "node:fs/promises";
|
|
20993
21396
|
import { createServer as createServer3 } from "node:http";
|
|
20994
|
-
import { homedir as
|
|
21397
|
+
import { homedir as homedir13, hostname as hostname2, tmpdir as tmpdir3 } from "node:os";
|
|
20995
21398
|
import {
|
|
20996
21399
|
basename as basename8,
|
|
20997
21400
|
dirname as dirname13,
|
|
20998
21401
|
extname as extname2,
|
|
20999
21402
|
isAbsolute as isAbsolute5,
|
|
21000
|
-
join as
|
|
21403
|
+
join as join20,
|
|
21001
21404
|
resolve as resolve8
|
|
21002
21405
|
} from "node:path";
|
|
21003
21406
|
async function runLocalCodexRunner(options) {
|
|
@@ -21243,6 +21646,9 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
|
|
|
21243
21646
|
defaultAgentProvider: "codex",
|
|
21244
21647
|
startInstance: allowedCwds.value.length > 0,
|
|
21245
21648
|
durableClaudeSessionStore: true,
|
|
21649
|
+
// Honest capability: no faithful Claude Code rewind exists yet; the
|
|
21650
|
+
// rewind_thread control responds with a clean rejection (spec:
|
|
21651
|
+
// plans/2026-06-12-claude-steer-rewind-parity-note.md item B).
|
|
21246
21652
|
claudeCodeCheckpointRewind: false,
|
|
21247
21653
|
allowedCwds: allowedCwds.value,
|
|
21248
21654
|
missingAllowedCwds: missingAllowedCwds.value,
|
|
@@ -22188,7 +22594,29 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
|
|
|
22188
22594
|
);
|
|
22189
22595
|
dynamicChannelSessions.clear();
|
|
22190
22596
|
dynamicChannelSessionCodexClients.clear();
|
|
22191
|
-
|
|
22597
|
+
const claudeSessions = [...activeClaudeCodeSessions.values()];
|
|
22598
|
+
for (const session of claudeSessions) {
|
|
22599
|
+
try {
|
|
22600
|
+
session.closeInput();
|
|
22601
|
+
} catch (error) {
|
|
22602
|
+
log2("claude_code.session_input_close_failed", {
|
|
22603
|
+
linzumi_thread_id: session.threadId,
|
|
22604
|
+
message: error instanceof Error ? error.message : String(error)
|
|
22605
|
+
});
|
|
22606
|
+
}
|
|
22607
|
+
}
|
|
22608
|
+
await Promise.race([
|
|
22609
|
+
Promise.allSettled(
|
|
22610
|
+
claudeSessions.flatMap((session) => {
|
|
22611
|
+
const work = session.sessionWork();
|
|
22612
|
+
return work === void 0 ? [] : [work];
|
|
22613
|
+
})
|
|
22614
|
+
),
|
|
22615
|
+
new Promise((resolve12) => {
|
|
22616
|
+
setTimeout(resolve12, 1e4).unref?.();
|
|
22617
|
+
})
|
|
22618
|
+
]);
|
|
22619
|
+
for (const session of claudeSessions) {
|
|
22192
22620
|
session.abortController.abort(new Error("local runner stopped"));
|
|
22193
22621
|
}
|
|
22194
22622
|
activeClaudeCodeSessions.clear();
|
|
@@ -22333,13 +22761,14 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
|
|
|
22333
22761
|
if (workspaceSlug === void 0 || channelSlug === void 0 || kandanThreadId === void 0) {
|
|
22334
22762
|
return void 0;
|
|
22335
22763
|
}
|
|
22336
|
-
const
|
|
22337
|
-
|
|
22764
|
+
const providerResolution = resolveControlCodexModelProvider(control);
|
|
22765
|
+
const providerResolutionError = codexModelProviderResolutionError(providerResolution);
|
|
22766
|
+
if (providerResolutionError !== void 0) {
|
|
22338
22767
|
return {
|
|
22339
22768
|
instanceId,
|
|
22340
22769
|
controlType: control.type,
|
|
22341
22770
|
ok: false,
|
|
22342
|
-
error:
|
|
22771
|
+
error: providerResolutionError,
|
|
22343
22772
|
kandanThreadId,
|
|
22344
22773
|
cwd
|
|
22345
22774
|
};
|
|
@@ -22954,14 +23383,14 @@ function commanderOutboxPersistDir() {
|
|
|
22954
23383
|
if (override !== void 0 && override !== "") {
|
|
22955
23384
|
return override;
|
|
22956
23385
|
}
|
|
22957
|
-
return
|
|
23386
|
+
return join20(homedir13(), ".linzumi", "commander-outbox");
|
|
22958
23387
|
}
|
|
22959
23388
|
function controlCursorStorePath(runnerId) {
|
|
22960
23389
|
const sanitized = runnerId.replace(/[^A-Za-z0-9._-]+/g, "-").replace(/^[-.]+|[-.]+$/g, "").slice(0, 80);
|
|
22961
23390
|
const digest = createHash5("sha256").update(runnerId).digest("hex").slice(0, 8);
|
|
22962
23391
|
const stem = sanitized === "" ? "runner" : sanitized;
|
|
22963
|
-
return
|
|
22964
|
-
|
|
23392
|
+
return join20(
|
|
23393
|
+
homedir13(),
|
|
22965
23394
|
".linzumi",
|
|
22966
23395
|
"control-cursors",
|
|
22967
23396
|
`${stem}.${digest}.json`
|
|
@@ -22971,8 +23400,8 @@ function appliedStartTurnStorePath(runnerId) {
|
|
|
22971
23400
|
const sanitized = runnerId.replace(/[^A-Za-z0-9._-]+/g, "-").replace(/^[-.]+|[-.]+$/g, "").slice(0, 80);
|
|
22972
23401
|
const digest = createHash5("sha256").update(runnerId).digest("hex").slice(0, 8);
|
|
22973
23402
|
const stem = sanitized === "" ? "runner" : sanitized;
|
|
22974
|
-
return
|
|
22975
|
-
|
|
23403
|
+
return join20(
|
|
23404
|
+
homedir13(),
|
|
22976
23405
|
".linzumi",
|
|
22977
23406
|
"control-cursors",
|
|
22978
23407
|
`${stem}.${digest}.start-turn.json`
|
|
@@ -23094,9 +23523,9 @@ function createControlCursorFileStore(path2, log2, options) {
|
|
|
23094
23523
|
}
|
|
23095
23524
|
dirty = false;
|
|
23096
23525
|
try {
|
|
23097
|
-
|
|
23526
|
+
mkdirSync12(dirname13(path2), { recursive: true });
|
|
23098
23527
|
const tmpPath = `${path2}.tmp`;
|
|
23099
|
-
|
|
23528
|
+
writeFileSync11(
|
|
23100
23529
|
tmpPath,
|
|
23101
23530
|
`${JSON.stringify({
|
|
23102
23531
|
...epoch === void 0 ? {} : { [controlCursorEpochKey]: epoch },
|
|
@@ -23204,7 +23633,7 @@ function readControlCursorFile(path2, log2) {
|
|
|
23204
23633
|
const cursors = /* @__PURE__ */ new Map();
|
|
23205
23634
|
let raw;
|
|
23206
23635
|
try {
|
|
23207
|
-
raw =
|
|
23636
|
+
raw = readFileSync16(path2, "utf8");
|
|
23208
23637
|
} catch (error) {
|
|
23209
23638
|
if (!isErrnoCode2(error, "ENOENT")) {
|
|
23210
23639
|
log2("control_cursor_store.read_failed", {
|
|
@@ -23798,18 +24227,18 @@ async function applyControl(codex, kandan, topic, instanceId, options, agentProv
|
|
|
23798
24227
|
return delegated;
|
|
23799
24228
|
}
|
|
23800
24229
|
if (agentProvider === "codex") {
|
|
23801
|
-
const
|
|
24230
|
+
const providerControlError = codexModelProviderControlError(
|
|
23802
24231
|
options,
|
|
23803
24232
|
control
|
|
23804
24233
|
);
|
|
23805
|
-
if (
|
|
24234
|
+
if (providerControlError !== void 0) {
|
|
23806
24235
|
try {
|
|
23807
24236
|
await publishStartInstanceMessageState(
|
|
23808
24237
|
kandan,
|
|
23809
24238
|
topic,
|
|
23810
24239
|
control,
|
|
23811
24240
|
"failed",
|
|
23812
|
-
|
|
24241
|
+
providerControlError,
|
|
23813
24242
|
{ instanceId }
|
|
23814
24243
|
);
|
|
23815
24244
|
} catch (error) {
|
|
@@ -23821,7 +24250,7 @@ async function applyControl(codex, kandan, topic, instanceId, options, agentProv
|
|
|
23821
24250
|
instanceId,
|
|
23822
24251
|
controlType: control.type,
|
|
23823
24252
|
ok: false,
|
|
23824
|
-
error:
|
|
24253
|
+
error: providerControlError
|
|
23825
24254
|
};
|
|
23826
24255
|
}
|
|
23827
24256
|
}
|
|
@@ -23969,16 +24398,16 @@ async function applyControl(codex, kandan, topic, instanceId, options, agentProv
|
|
|
23969
24398
|
return delegated;
|
|
23970
24399
|
}
|
|
23971
24400
|
if (agentProvider === "codex") {
|
|
23972
|
-
const
|
|
24401
|
+
const providerControlError = codexModelProviderControlError(
|
|
23973
24402
|
options,
|
|
23974
24403
|
control
|
|
23975
24404
|
);
|
|
23976
|
-
if (
|
|
24405
|
+
if (providerControlError !== void 0) {
|
|
23977
24406
|
return {
|
|
23978
24407
|
instanceId,
|
|
23979
24408
|
controlType: control.type,
|
|
23980
24409
|
ok: false,
|
|
23981
|
-
error:
|
|
24410
|
+
error: providerControlError
|
|
23982
24411
|
};
|
|
23983
24412
|
}
|
|
23984
24413
|
}
|
|
@@ -24044,10 +24473,28 @@ async function applyControl(codex, kandan, topic, instanceId, options, agentProv
|
|
|
24044
24473
|
};
|
|
24045
24474
|
}
|
|
24046
24475
|
try {
|
|
24047
|
-
activeSession.enqueueInput({
|
|
24476
|
+
const enqueueResult = activeSession.enqueueInput({
|
|
24048
24477
|
content: contentResult.content,
|
|
24049
24478
|
sourceSeq
|
|
24050
24479
|
});
|
|
24480
|
+
if (enqueueResult === "duplicate") {
|
|
24481
|
+
log2("claude_code.message_duplicate_ignored", {
|
|
24482
|
+
linzumi_thread_id: optionalThreadControlField(control, "threadId") ?? null,
|
|
24483
|
+
claude_session_id: codexThreadId,
|
|
24484
|
+
body_preview: claudeConsoleBodyPreview(workDescription),
|
|
24485
|
+
source_seq: sourceSeq ?? null
|
|
24486
|
+
});
|
|
24487
|
+
return {
|
|
24488
|
+
instanceId,
|
|
24489
|
+
controlType: control.type,
|
|
24490
|
+
agentProvider: "claude-code",
|
|
24491
|
+
cwd: cwd.cwd,
|
|
24492
|
+
matchedRoot: cwd.matchedRoot,
|
|
24493
|
+
codexThreadId,
|
|
24494
|
+
queuedInput: true,
|
|
24495
|
+
duplicate: true
|
|
24496
|
+
};
|
|
24497
|
+
}
|
|
24051
24498
|
log2("claude_code.message_queued", {
|
|
24052
24499
|
linzumi_thread_id: optionalThreadControlField(control, "threadId") ?? null,
|
|
24053
24500
|
claude_session_id: codexThreadId,
|
|
@@ -24299,18 +24746,30 @@ async function applyControl(codex, kandan, topic, instanceId, options, agentProv
|
|
|
24299
24746
|
error: "claude_code_steer_requires_text_input"
|
|
24300
24747
|
};
|
|
24301
24748
|
}
|
|
24302
|
-
|
|
24303
|
-
|
|
24304
|
-
|
|
24305
|
-
|
|
24306
|
-
|
|
24307
|
-
|
|
24308
|
-
|
|
24749
|
+
let steered;
|
|
24750
|
+
try {
|
|
24751
|
+
steered = claudeSession.steerTurn(steerText);
|
|
24752
|
+
} catch (steerError) {
|
|
24753
|
+
const message = steerError instanceof Error ? steerError.message : String(steerError);
|
|
24754
|
+
log2("claude_code.steer_failed", {
|
|
24755
|
+
thread_id: control.threadId,
|
|
24756
|
+
message
|
|
24757
|
+
});
|
|
24758
|
+
return {
|
|
24759
|
+
instanceId,
|
|
24760
|
+
controlType: control.type,
|
|
24761
|
+
agentProvider: "claude-code",
|
|
24762
|
+
ok: false,
|
|
24763
|
+
error: "claude_code_steer_failed",
|
|
24764
|
+
message,
|
|
24765
|
+
threadId: control.threadId
|
|
24766
|
+
};
|
|
24767
|
+
}
|
|
24309
24768
|
return {
|
|
24310
24769
|
instanceId,
|
|
24311
24770
|
controlType: control.type,
|
|
24312
24771
|
agentProvider: "claude-code",
|
|
24313
|
-
steered
|
|
24772
|
+
steered,
|
|
24314
24773
|
threadId: control.threadId
|
|
24315
24774
|
};
|
|
24316
24775
|
}
|
|
@@ -24349,6 +24808,30 @@ ${steerText}`,
|
|
|
24349
24808
|
response
|
|
24350
24809
|
};
|
|
24351
24810
|
}
|
|
24811
|
+
case "rewind_thread": {
|
|
24812
|
+
const claudeSession = activeClaudeCodeSessions.get(control.threadId);
|
|
24813
|
+
if (claudeSession !== void 0 || control.agentProvider === "claude-code") {
|
|
24814
|
+
return {
|
|
24815
|
+
instanceId,
|
|
24816
|
+
controlType: control.type,
|
|
24817
|
+
agentProvider: "claude-code",
|
|
24818
|
+
requestId: stringValue(control.requestId) ?? null,
|
|
24819
|
+
threadId: control.threadId,
|
|
24820
|
+
ok: false,
|
|
24821
|
+
error: "claude_code_rewind_unsupported",
|
|
24822
|
+
message: "Claude Code does not support rewind yet"
|
|
24823
|
+
};
|
|
24824
|
+
}
|
|
24825
|
+
return {
|
|
24826
|
+
instanceId,
|
|
24827
|
+
controlType: control.type,
|
|
24828
|
+
requestId: stringValue(control.requestId) ?? null,
|
|
24829
|
+
threadId: control.threadId,
|
|
24830
|
+
ok: false,
|
|
24831
|
+
error: "rewind_not_supported",
|
|
24832
|
+
message: "This runner does not support rewinding threads yet"
|
|
24833
|
+
};
|
|
24834
|
+
}
|
|
24352
24835
|
case "interrupt_queued_messages": {
|
|
24353
24836
|
const agentProvider = stringValue(control.agentProvider)?.trim();
|
|
24354
24837
|
if (agentProvider !== "claude-code") {
|
|
@@ -24515,7 +24998,24 @@ ${steerText}`,
|
|
|
24515
24998
|
};
|
|
24516
24999
|
}
|
|
24517
25000
|
case "stop_instance":
|
|
24518
|
-
case "kill_instance":
|
|
25001
|
+
case "kill_instance": {
|
|
25002
|
+
const controlThreadId2 = "threadId" in control && typeof control.threadId === "string" ? control.threadId : void 0;
|
|
25003
|
+
const activeSession = controlThreadId2 === void 0 ? void 0 : activeClaudeCodeSessions.get(controlThreadId2);
|
|
25004
|
+
if (activeSession !== void 0) {
|
|
25005
|
+
await activeSession.interruptTurn("Claude Code stopped by Linzumi");
|
|
25006
|
+
activeSession.abortController.abort(
|
|
25007
|
+
new Error("Claude Code stopped by Linzumi")
|
|
25008
|
+
);
|
|
25009
|
+
return {
|
|
25010
|
+
instanceId,
|
|
25011
|
+
controlType: control.type,
|
|
25012
|
+
agentProvider: "claude-code",
|
|
25013
|
+
threadId: controlThreadId2,
|
|
25014
|
+
stopped: true
|
|
25015
|
+
};
|
|
25016
|
+
}
|
|
25017
|
+
return { instanceId, controlType: control.type, skipped: true };
|
|
25018
|
+
}
|
|
24519
25019
|
case "resolve_port_forward_request":
|
|
24520
25020
|
case "update_thread_interaction_access":
|
|
24521
25021
|
case "set_port_forward_enabled":
|
|
@@ -24816,10 +25316,24 @@ function startInstanceAgentLabel(provider) {
|
|
|
24816
25316
|
return "Claude Code";
|
|
24817
25317
|
}
|
|
24818
25318
|
}
|
|
24819
|
-
function
|
|
25319
|
+
function resolveControlCodexModelProvider(control) {
|
|
24820
25320
|
const modelProvider = stringValue(control.modelProvider)?.trim();
|
|
25321
|
+
const llmProxy = objectValue(control.llmProxy);
|
|
25322
|
+
const baseUrl = stringValue(llmProxy?.baseUrl)?.trim();
|
|
25323
|
+
const token = stringValue(llmProxy?.token)?.trim();
|
|
25324
|
+
const binding = baseUrl !== void 0 && baseUrl !== "" && token !== void 0 && token !== "" ? { baseUrl, token } : void 0;
|
|
24821
25325
|
if (modelProvider === void 0 || modelProvider === "") {
|
|
24822
|
-
|
|
25326
|
+
if (binding === void 0) {
|
|
25327
|
+
return { type: "none" };
|
|
25328
|
+
}
|
|
25329
|
+
return {
|
|
25330
|
+
type: "provider",
|
|
25331
|
+
runtime: {
|
|
25332
|
+
provider: "openai-proxy",
|
|
25333
|
+
llmProxyBaseUrl: binding.baseUrl,
|
|
25334
|
+
llmProxyToken: binding.token
|
|
25335
|
+
}
|
|
25336
|
+
};
|
|
24823
25337
|
}
|
|
24824
25338
|
if (modelProvider !== "wafer") {
|
|
24825
25339
|
return {
|
|
@@ -24827,40 +25341,84 @@ function resolveControlWaferModelProvider(control) {
|
|
|
24827
25341
|
error: `model_provider_unsupported:${modelProvider}`
|
|
24828
25342
|
};
|
|
24829
25343
|
}
|
|
24830
|
-
|
|
24831
|
-
const baseUrl = stringValue(llmProxy?.baseUrl)?.trim();
|
|
24832
|
-
const token = stringValue(llmProxy?.token)?.trim();
|
|
24833
|
-
if (baseUrl === void 0 || baseUrl === "" || token === void 0 || token === "") {
|
|
25344
|
+
if (binding === void 0) {
|
|
24834
25345
|
return { type: "error", error: "wafer_model_provider_missing_llm_proxy" };
|
|
24835
25346
|
}
|
|
24836
25347
|
return {
|
|
24837
|
-
type: "
|
|
25348
|
+
type: "provider",
|
|
24838
25349
|
runtime: {
|
|
24839
25350
|
provider: "wafer",
|
|
24840
|
-
llmProxyBaseUrl: baseUrl,
|
|
24841
|
-
llmProxyToken: token
|
|
25351
|
+
llmProxyBaseUrl: binding.baseUrl,
|
|
25352
|
+
llmProxyToken: binding.token
|
|
24842
25353
|
}
|
|
24843
25354
|
};
|
|
24844
25355
|
}
|
|
24845
|
-
function
|
|
24846
|
-
|
|
25356
|
+
function codexModelProviderResolutionError(resolution) {
|
|
25357
|
+
if (resolution.type === "error") {
|
|
25358
|
+
return resolution.error;
|
|
25359
|
+
}
|
|
25360
|
+
if (resolution.type === "provider" && resolution.runtime.provider === "openai-proxy" && resolveForwardableOpenAiApiKey() === void 0) {
|
|
25361
|
+
return "codex_llm_proxy_requires_openai_api_key";
|
|
25362
|
+
}
|
|
25363
|
+
return void 0;
|
|
25364
|
+
}
|
|
25365
|
+
function codexModelProviderControlError(options, control) {
|
|
25366
|
+
const resolution = resolveControlCodexModelProvider(control);
|
|
24847
25367
|
switch (resolution.type) {
|
|
24848
25368
|
case "none":
|
|
24849
25369
|
return void 0;
|
|
24850
25370
|
case "error":
|
|
24851
25371
|
return resolution.error;
|
|
24852
|
-
case "
|
|
24853
|
-
|
|
25372
|
+
case "provider": {
|
|
25373
|
+
const gateError = codexModelProviderResolutionError(resolution);
|
|
25374
|
+
if (gateError !== void 0) {
|
|
25375
|
+
return gateError;
|
|
25376
|
+
}
|
|
25377
|
+
return options.codexModelProvider?.provider === resolution.runtime.provider ? void 0 : resolution.runtime.provider === "wafer" ? "wafer_model_provider_requires_thread_worker" : "llm_proxy_model_provider_requires_thread_worker";
|
|
25378
|
+
}
|
|
24854
25379
|
}
|
|
24855
25380
|
}
|
|
24856
25381
|
function linzumiCodexModelProviderConfig(runtime) {
|
|
24857
|
-
|
|
24858
|
-
|
|
24859
|
-
|
|
24860
|
-
|
|
24861
|
-
|
|
24862
|
-
|
|
24863
|
-
|
|
25382
|
+
const baseUrl = `${runtime.llmProxyBaseUrl.replace(/\/+$/, "")}/v1`;
|
|
25383
|
+
switch (runtime.provider) {
|
|
25384
|
+
case "wafer":
|
|
25385
|
+
return {
|
|
25386
|
+
id: "linzumi",
|
|
25387
|
+
name: "Linzumi Proxy",
|
|
25388
|
+
baseUrl,
|
|
25389
|
+
envKey: "LINZUMI_LLM_PROXY_TOKEN",
|
|
25390
|
+
wireApi: "responses"
|
|
25391
|
+
};
|
|
25392
|
+
case "openai-proxy":
|
|
25393
|
+
return {
|
|
25394
|
+
id: "linzumi",
|
|
25395
|
+
name: "Linzumi Proxy",
|
|
25396
|
+
baseUrl,
|
|
25397
|
+
envKey: "OPENAI_API_KEY",
|
|
25398
|
+
wireApi: "responses",
|
|
25399
|
+
envHttpHeaders: {
|
|
25400
|
+
"x-linzumi-llm-proxy-token": "LINZUMI_LLM_PROXY_TOKEN"
|
|
25401
|
+
}
|
|
25402
|
+
};
|
|
25403
|
+
}
|
|
25404
|
+
}
|
|
25405
|
+
function codexModelProviderAppServerEnv(runtime) {
|
|
25406
|
+
switch (runtime.provider) {
|
|
25407
|
+
case "wafer":
|
|
25408
|
+
return { LINZUMI_LLM_PROXY_TOKEN: runtime.llmProxyToken };
|
|
25409
|
+
case "openai-proxy": {
|
|
25410
|
+
const openAiApiKey = resolveForwardableOpenAiApiKey();
|
|
25411
|
+
if (openAiApiKey === void 0) {
|
|
25412
|
+
throw new Error(
|
|
25413
|
+
"codex llm proxy requires API-key auth (OPENAI_API_KEY in the environment or $CODEX_HOME/auth.json); ChatGPT OAuth credentials cannot be forwarded"
|
|
25414
|
+
);
|
|
25415
|
+
}
|
|
25416
|
+
return {
|
|
25417
|
+
LINZUMI_LLM_PROXY_TOKEN: runtime.llmProxyToken,
|
|
25418
|
+
OPENAI_API_KEY: openAiApiKey
|
|
25419
|
+
};
|
|
25420
|
+
}
|
|
25421
|
+
}
|
|
24864
25422
|
}
|
|
24865
25423
|
async function startCodexProviderInstance(args) {
|
|
24866
25424
|
if (args.options.codexUrl === void 0) {
|
|
@@ -24957,10 +25515,10 @@ function createClaudeCodeInputQueue(input) {
|
|
|
24957
25515
|
claudeCodeUserInputMessage(input.content)
|
|
24958
25516
|
];
|
|
24959
25517
|
const pendingSourceSeqs = [input.sourceSeq];
|
|
25518
|
+
const deferredFollowUps = [];
|
|
24960
25519
|
const waiters = [];
|
|
24961
25520
|
const state = {
|
|
24962
|
-
closed: false
|
|
24963
|
-
queuedTurnCount: 1
|
|
25521
|
+
closed: false
|
|
24964
25522
|
};
|
|
24965
25523
|
const drainClosedWaiters = () => {
|
|
24966
25524
|
while (state.closed) {
|
|
@@ -24971,19 +25529,42 @@ function createClaudeCodeInputQueue(input) {
|
|
|
24971
25529
|
waiter({ done: true, value: void 0 });
|
|
24972
25530
|
}
|
|
24973
25531
|
};
|
|
25532
|
+
const deliverNow = (message, sourceSeq) => {
|
|
25533
|
+
pendingSourceSeqs.push(sourceSeq);
|
|
25534
|
+
const waiter = waiters.shift();
|
|
25535
|
+
if (waiter === void 0) {
|
|
25536
|
+
pendingMessages.push(message);
|
|
25537
|
+
return;
|
|
25538
|
+
}
|
|
25539
|
+
waiter({ done: false, value: message });
|
|
25540
|
+
};
|
|
24974
25541
|
const enqueue = (next) => {
|
|
24975
25542
|
if (state.closed) {
|
|
24976
25543
|
throw new Error("Claude Code streaming input is closed");
|
|
24977
25544
|
}
|
|
24978
25545
|
const message = claudeCodeUserInputMessage(next.content);
|
|
24979
|
-
pendingSourceSeqs.
|
|
24980
|
-
|
|
25546
|
+
if (pendingSourceSeqs.length > 0) {
|
|
25547
|
+
deferredFollowUps.push({ message, sourceSeq: next.sourceSeq });
|
|
25548
|
+
return;
|
|
25549
|
+
}
|
|
25550
|
+
deliverNow(message, next.sourceSeq);
|
|
25551
|
+
};
|
|
25552
|
+
const enqueueSteer = (content) => {
|
|
25553
|
+
if (state.closed) {
|
|
25554
|
+
throw new Error("Claude Code streaming input is closed");
|
|
25555
|
+
}
|
|
25556
|
+
if (pendingSourceSeqs.length === 0) {
|
|
25557
|
+
enqueue({ content, sourceSeq: void 0 });
|
|
25558
|
+
return "steered_queued";
|
|
25559
|
+
}
|
|
25560
|
+
const message = claudeCodeUserInputMessage(content);
|
|
24981
25561
|
const waiter = waiters.shift();
|
|
24982
25562
|
if (waiter === void 0) {
|
|
24983
25563
|
pendingMessages.push(message);
|
|
24984
|
-
|
|
25564
|
+
} else {
|
|
25565
|
+
waiter({ done: false, value: message });
|
|
24985
25566
|
}
|
|
24986
|
-
|
|
25567
|
+
return "steered_live";
|
|
24987
25568
|
};
|
|
24988
25569
|
return {
|
|
24989
25570
|
messages: {
|
|
@@ -25004,13 +25585,30 @@ function createClaudeCodeInputQueue(input) {
|
|
|
25004
25585
|
};
|
|
25005
25586
|
}
|
|
25006
25587
|
},
|
|
25007
|
-
queuedTurnCount: () => state.queuedTurnCount,
|
|
25008
25588
|
close: () => {
|
|
25589
|
+
if (pendingSourceSeqs.length === 0) {
|
|
25590
|
+
while (deferredFollowUps.length > 0) {
|
|
25591
|
+
const followUp = deferredFollowUps.shift();
|
|
25592
|
+
if (followUp !== void 0) {
|
|
25593
|
+
deliverNow(followUp.message, followUp.sourceSeq);
|
|
25594
|
+
}
|
|
25595
|
+
}
|
|
25596
|
+
}
|
|
25009
25597
|
state.closed = true;
|
|
25010
25598
|
drainClosedWaiters();
|
|
25011
25599
|
},
|
|
25012
25600
|
enqueue,
|
|
25013
|
-
|
|
25601
|
+
enqueueSteer,
|
|
25602
|
+
completeTurn: () => {
|
|
25603
|
+
const completed = pendingSourceSeqs.shift();
|
|
25604
|
+
if (!state.closed && pendingSourceSeqs.length === 0) {
|
|
25605
|
+
const nextFollowUp = deferredFollowUps.shift();
|
|
25606
|
+
if (nextFollowUp !== void 0) {
|
|
25607
|
+
deliverNow(nextFollowUp.message, nextFollowUp.sourceSeq);
|
|
25608
|
+
}
|
|
25609
|
+
}
|
|
25610
|
+
return completed;
|
|
25611
|
+
},
|
|
25014
25612
|
currentSourceSeq: () => pendingSourceSeqs[0]
|
|
25015
25613
|
};
|
|
25016
25614
|
}
|
|
@@ -25258,6 +25856,11 @@ async function startClaudeCodeProviderInstance(args) {
|
|
|
25258
25856
|
codexVersion: void 0
|
|
25259
25857
|
};
|
|
25260
25858
|
const abortController = new AbortController();
|
|
25859
|
+
const acceptedSourceSeqs = new Set(
|
|
25860
|
+
sourceSeq === void 0 ? [] : [sourceSeq]
|
|
25861
|
+
);
|
|
25862
|
+
const sessionWorkHandle = { value: void 0 };
|
|
25863
|
+
let startControlResponded = false;
|
|
25261
25864
|
let activeSessionId;
|
|
25262
25865
|
let sessionControls;
|
|
25263
25866
|
const planMirrorClient = createLinzumiMcpApiClient({
|
|
@@ -25331,6 +25934,24 @@ async function startClaudeCodeProviderInstance(args) {
|
|
|
25331
25934
|
onTodoWriteCompleted: planMirror.handleTodoWrite,
|
|
25332
25935
|
log: args.log
|
|
25333
25936
|
});
|
|
25937
|
+
const liveBashCapture = args.options.claudeCodeRunner === void 0 && claudeLiveBashCaptureEnabled(process.env) ? createClaudeCodeLiveBashCapture({
|
|
25938
|
+
captureDir: join20(
|
|
25939
|
+
tmpdir3(),
|
|
25940
|
+
`linzumi-claude-live-bash-${args.instanceId}`
|
|
25941
|
+
),
|
|
25942
|
+
onOutputDelta: (toolUseId, delta) => {
|
|
25943
|
+
if (activeSessionId === void 0) {
|
|
25944
|
+
return;
|
|
25945
|
+
}
|
|
25946
|
+
adapter.handleTranscriptEvent({
|
|
25947
|
+
type: "command_output_delta",
|
|
25948
|
+
sessionId: activeSessionId,
|
|
25949
|
+
itemKey: toolUseId,
|
|
25950
|
+
delta
|
|
25951
|
+
});
|
|
25952
|
+
},
|
|
25953
|
+
log: (event, fields) => args.log(event, fields)
|
|
25954
|
+
}) : void 0;
|
|
25334
25955
|
let mcpAuthCleanup;
|
|
25335
25956
|
let mcpServers;
|
|
25336
25957
|
try {
|
|
@@ -25374,7 +25995,7 @@ async function startClaudeCodeProviderInstance(args) {
|
|
|
25374
25995
|
rootSeq,
|
|
25375
25996
|
log: args.log
|
|
25376
25997
|
};
|
|
25377
|
-
|
|
25998
|
+
const lastRateLimitSignatureByWindow = /* @__PURE__ */ new Map();
|
|
25378
25999
|
const reportClaudeCodeRateLimit = async (event) => {
|
|
25379
26000
|
const nowMs = Date.now();
|
|
25380
26001
|
const summary = claudeCodeRateLimitSummaryText(event.rateLimit, nowMs);
|
|
@@ -25390,13 +26011,13 @@ async function startClaudeCodeProviderInstance(args) {
|
|
|
25390
26011
|
utilization_percent: event.rateLimit.utilizationPercent ?? null,
|
|
25391
26012
|
resets_at_ms: event.rateLimit.resetsAtMs ?? null
|
|
25392
26013
|
});
|
|
26014
|
+
const windowKey = event.rateLimit.rateLimitType ?? "account";
|
|
25393
26015
|
const signature = claudeRateLimitSignature(event.rateLimit);
|
|
25394
|
-
if (signature ===
|
|
26016
|
+
if (signature === lastRateLimitSignatureByWindow.get(windowKey)) {
|
|
25395
26017
|
return;
|
|
25396
26018
|
}
|
|
25397
|
-
lastRateLimitSignature = signature;
|
|
25398
26019
|
try {
|
|
25399
|
-
await
|
|
26020
|
+
await publishClaudeCodeRateLimitState({
|
|
25400
26021
|
kandan: args.kandan,
|
|
25401
26022
|
topic: args.topic,
|
|
25402
26023
|
workspace,
|
|
@@ -25405,6 +26026,7 @@ async function startClaudeCodeProviderInstance(args) {
|
|
|
25405
26026
|
claudeSessionId: event.sessionId ?? activeSessionId,
|
|
25406
26027
|
rateLimit: event.rateLimit
|
|
25407
26028
|
});
|
|
26029
|
+
lastRateLimitSignatureByWindow.set(windowKey, signature);
|
|
25408
26030
|
} catch (error) {
|
|
25409
26031
|
args.log("claude_code.rate_limit_post_failed", {
|
|
25410
26032
|
thread_id: threadId,
|
|
@@ -25412,6 +26034,10 @@ async function startClaudeCodeProviderInstance(args) {
|
|
|
25412
26034
|
});
|
|
25413
26035
|
}
|
|
25414
26036
|
};
|
|
26037
|
+
let settleFirstTurn = () => void 0;
|
|
26038
|
+
const firstTurnSettled = new Promise((resolve12) => {
|
|
26039
|
+
settleFirstTurn = resolve12;
|
|
26040
|
+
});
|
|
25415
26041
|
const onTranscriptEvent = async (event) => {
|
|
25416
26042
|
try {
|
|
25417
26043
|
await mirrorClaudeSessionStoreAppend(mirrorArgs, event);
|
|
@@ -25434,7 +26060,20 @@ async function startClaudeCodeProviderInstance(args) {
|
|
|
25434
26060
|
channel,
|
|
25435
26061
|
threadId,
|
|
25436
26062
|
currentSourceSeq: inputQueue.currentSourceSeq,
|
|
25437
|
-
enqueueInput:
|
|
26063
|
+
enqueueInput: (input) => {
|
|
26064
|
+
if (input.sourceSeq !== void 0 && acceptedSourceSeqs.has(input.sourceSeq)) {
|
|
26065
|
+
return "duplicate";
|
|
26066
|
+
}
|
|
26067
|
+
inputQueue.enqueue(input);
|
|
26068
|
+
if (input.sourceSeq !== void 0) {
|
|
26069
|
+
acceptedSourceSeqs.add(input.sourceSeq);
|
|
26070
|
+
}
|
|
26071
|
+
return "queued";
|
|
26072
|
+
},
|
|
26073
|
+
closeInput: inputQueue.close,
|
|
26074
|
+
hasActiveTurn: () => adapter.activeTurnId() !== void 0,
|
|
26075
|
+
sessionWork: () => sessionWorkHandle.value,
|
|
26076
|
+
steerTurn: inputQueue.enqueueSteer,
|
|
25438
26077
|
interruptTurn: async (reason) => {
|
|
25439
26078
|
const aborted = adapter.interruptActiveTurn(reason);
|
|
25440
26079
|
await sessionControls?.interrupt();
|
|
@@ -25489,10 +26128,30 @@ async function startClaudeCodeProviderInstance(args) {
|
|
|
25489
26128
|
claude_session_id: event.sessionId,
|
|
25490
26129
|
body_preview: claudeConsoleBodyPreview(event.body)
|
|
25491
26130
|
});
|
|
26131
|
+
settleFirstTurn();
|
|
26132
|
+
}
|
|
26133
|
+
if (event.type === "turn_interrupted") {
|
|
26134
|
+
settleFirstTurn();
|
|
25492
26135
|
}
|
|
25493
26136
|
if (event.type === "rate_limit") {
|
|
25494
26137
|
await reportClaudeCodeRateLimit(event);
|
|
25495
26138
|
}
|
|
26139
|
+
if (event.type === "tool_result") {
|
|
26140
|
+
liveBashCapture?.settleTool(event.itemKey);
|
|
26141
|
+
}
|
|
26142
|
+
if (event.type === "turn_interrupted" || event.type === "session_failed") {
|
|
26143
|
+
liveBashCapture?.settleAll();
|
|
26144
|
+
}
|
|
26145
|
+
if (event.type === "usage") {
|
|
26146
|
+
const summary = claudeCodeTokenUsageSummaryText(event.usage);
|
|
26147
|
+
if (summary !== void 0) {
|
|
26148
|
+
args.log("claude_code.token_usage", {
|
|
26149
|
+
linzumi_thread_id: threadId,
|
|
26150
|
+
claude_session_id: event.sessionId,
|
|
26151
|
+
token_usage_summary: summary
|
|
26152
|
+
});
|
|
26153
|
+
}
|
|
26154
|
+
}
|
|
25496
26155
|
adapter.handleTranscriptEvent(event);
|
|
25497
26156
|
};
|
|
25498
26157
|
const llmProxy = objectValue(args.control.llmProxy);
|
|
@@ -25519,75 +26178,97 @@ async function startClaudeCodeProviderInstance(args) {
|
|
|
25519
26178
|
request,
|
|
25520
26179
|
signal
|
|
25521
26180
|
});
|
|
25522
|
-
|
|
25523
|
-
|
|
26181
|
+
const runSession = async () => {
|
|
26182
|
+
let result2;
|
|
25524
26183
|
try {
|
|
25525
|
-
|
|
25526
|
-
|
|
25527
|
-
prompt: workDescription,
|
|
25528
|
-
developerInstructions: commanderDeveloperInstructions({
|
|
26184
|
+
try {
|
|
26185
|
+
result2 = await startClaudeCodeSession({
|
|
25529
26186
|
cwd: args.cwd,
|
|
25530
|
-
|
|
25531
|
-
|
|
25532
|
-
|
|
25533
|
-
|
|
25534
|
-
|
|
25535
|
-
|
|
25536
|
-
|
|
25537
|
-
|
|
25538
|
-
|
|
25539
|
-
|
|
25540
|
-
|
|
25541
|
-
|
|
25542
|
-
|
|
25543
|
-
|
|
25544
|
-
|
|
25545
|
-
|
|
25546
|
-
|
|
25547
|
-
|
|
25548
|
-
|
|
25549
|
-
|
|
25550
|
-
|
|
25551
|
-
|
|
25552
|
-
|
|
25553
|
-
|
|
25554
|
-
|
|
25555
|
-
|
|
25556
|
-
|
|
25557
|
-
|
|
25558
|
-
|
|
25559
|
-
|
|
25560
|
-
|
|
26187
|
+
prompt: workDescription,
|
|
26188
|
+
developerInstructions: commanderDeveloperInstructions({
|
|
26189
|
+
cwd: args.cwd,
|
|
26190
|
+
agentLabel: "Claude Code",
|
|
26191
|
+
planTool: "todo-write",
|
|
26192
|
+
developerPrompt,
|
|
26193
|
+
linzumiContext
|
|
26194
|
+
}),
|
|
26195
|
+
model: claudeCodeModelForRuntimeModel(runtimeSettings.model),
|
|
26196
|
+
resumeSessionId: args.resumeSessionId,
|
|
26197
|
+
abortController,
|
|
26198
|
+
streamingInput: inputQueue,
|
|
26199
|
+
runner: args.options.claudeCodeRunner,
|
|
26200
|
+
canUseTool,
|
|
26201
|
+
...mcpServers === void 0 ? {} : { mcpServers },
|
|
26202
|
+
...liveBashCapture === void 0 ? {} : {
|
|
26203
|
+
preToolUseHookMatchers: liveBashCapture.hookMatchers,
|
|
26204
|
+
wrapApprovedToolInput: (toolUseId, toolName2, input) => toolName2 === "Bash" ? liveBashCapture.wrapApprovedTool(toolUseId, input) : void 0
|
|
26205
|
+
},
|
|
26206
|
+
env: sessionEnv,
|
|
26207
|
+
// The built-in Linzumi MCP is trusted like the codex side: its tools
|
|
26208
|
+
// run without an approval round-trip. SDK allowedTools matches MCP
|
|
26209
|
+
// tools as mcp__<server>__<tool>; the __* suffix covers the server.
|
|
26210
|
+
allowedTools: ["mcp__linzumi__*"],
|
|
26211
|
+
onSessionControls: (controls) => {
|
|
26212
|
+
sessionControls = controls;
|
|
26213
|
+
},
|
|
26214
|
+
onTurnCompleted: () => {
|
|
26215
|
+
inputQueue.completeTurn();
|
|
26216
|
+
settleFirstTurn();
|
|
26217
|
+
},
|
|
26218
|
+
onTranscriptEvent
|
|
26219
|
+
});
|
|
26220
|
+
} finally {
|
|
26221
|
+
inputQueue.close();
|
|
26222
|
+
mcpAuthCleanup?.();
|
|
26223
|
+
liveBashCapture?.close();
|
|
26224
|
+
if (activeSessionId !== void 0) {
|
|
26225
|
+
args.activeClaudeCodeSessions.delete(activeSessionId);
|
|
26226
|
+
await args.disposeClaudeCodeForwardPortSession?.(activeSessionId);
|
|
26227
|
+
}
|
|
25561
26228
|
}
|
|
26229
|
+
} catch (error) {
|
|
26230
|
+
adapter.submitLifecycle(
|
|
26231
|
+
"codexDied",
|
|
26232
|
+
error instanceof Error ? error.message : String(error)
|
|
26233
|
+
);
|
|
26234
|
+
await adapter.close(5e3).catch(() => void 0);
|
|
26235
|
+
await Promise.race([
|
|
26236
|
+
planMirror.settle().catch(() => void 0),
|
|
26237
|
+
new Promise((resolve12) => {
|
|
26238
|
+
setTimeout(resolve12, 5e3).unref?.();
|
|
26239
|
+
})
|
|
26240
|
+
]);
|
|
26241
|
+
logStartFailureTerminal(
|
|
26242
|
+
error instanceof Error ? error.message : String(error)
|
|
26243
|
+
);
|
|
26244
|
+
if (!startControlResponded) {
|
|
26245
|
+
args.setStartupStage("claude_code_session_failed");
|
|
26246
|
+
}
|
|
26247
|
+
throw error;
|
|
25562
26248
|
}
|
|
25563
|
-
|
|
25564
|
-
|
|
25565
|
-
|
|
25566
|
-
|
|
25567
|
-
);
|
|
25568
|
-
await adapter.close(5e3).catch(() => void 0);
|
|
26249
|
+
if (!startControlResponded) {
|
|
26250
|
+
args.setStartupStage("posting_claude_code_output");
|
|
26251
|
+
}
|
|
26252
|
+
await adapter.awaitTurnsSettled(3e4);
|
|
26253
|
+
await adapter.close(3e4);
|
|
25569
26254
|
await Promise.race([
|
|
25570
|
-
planMirror.settle()
|
|
26255
|
+
planMirror.settle(),
|
|
25571
26256
|
new Promise((resolve12) => {
|
|
25572
|
-
setTimeout(resolve12,
|
|
26257
|
+
setTimeout(resolve12, 1e4).unref?.();
|
|
25573
26258
|
})
|
|
25574
26259
|
]);
|
|
25575
|
-
|
|
25576
|
-
|
|
25577
|
-
|
|
25578
|
-
|
|
25579
|
-
|
|
25580
|
-
|
|
25581
|
-
|
|
25582
|
-
|
|
25583
|
-
|
|
25584
|
-
|
|
25585
|
-
planMirror.settle(),
|
|
25586
|
-
new Promise((resolve12) => {
|
|
25587
|
-
setTimeout(resolve12, 1e4).unref?.();
|
|
25588
|
-
})
|
|
26260
|
+
return result2;
|
|
26261
|
+
};
|
|
26262
|
+
const sessionWork = runSession();
|
|
26263
|
+
sessionWorkHandle.value = sessionWork;
|
|
26264
|
+
const settled = await Promise.race([
|
|
26265
|
+
sessionWork.then((result2) => ({
|
|
26266
|
+
type: "session_ended",
|
|
26267
|
+
result: result2
|
|
26268
|
+
})),
|
|
26269
|
+
firstTurnSettled.then(() => ({ type: "first_turn_settled" }))
|
|
25589
26270
|
]);
|
|
25590
|
-
|
|
26271
|
+
const respondWithSessionId = (sessionId) => ({
|
|
25591
26272
|
controlResponse: {
|
|
25592
26273
|
instanceId: args.instanceId,
|
|
25593
26274
|
controlType: args.control.type,
|
|
@@ -25595,16 +26276,52 @@ async function startClaudeCodeProviderInstance(args) {
|
|
|
25595
26276
|
cwd: args.cwd,
|
|
25596
26277
|
matchedRoot: args.matchedRoot,
|
|
25597
26278
|
response: {
|
|
25598
|
-
session: { id:
|
|
26279
|
+
session: { id: sessionId }
|
|
25599
26280
|
}
|
|
25600
26281
|
},
|
|
25601
26282
|
providerSession: {
|
|
25602
26283
|
provider: "claude-code",
|
|
25603
26284
|
cwd: args.cwd,
|
|
25604
26285
|
matchedRoot: args.matchedRoot,
|
|
25605
|
-
sessionId
|
|
26286
|
+
sessionId
|
|
25606
26287
|
}
|
|
25607
|
-
};
|
|
26288
|
+
});
|
|
26289
|
+
if (settled.type === "session_ended") {
|
|
26290
|
+
return respondWithSessionId(settled.result.sessionId);
|
|
26291
|
+
}
|
|
26292
|
+
args.setStartupStage("posting_claude_code_output");
|
|
26293
|
+
startControlResponded = true;
|
|
26294
|
+
await adapter.awaitTurnsSettled(3e4);
|
|
26295
|
+
try {
|
|
26296
|
+
await adapter.flush(3e4);
|
|
26297
|
+
} catch (error) {
|
|
26298
|
+
args.log("claude_code.first_turn_flush_timeout", {
|
|
26299
|
+
linzumi_thread_id: threadId,
|
|
26300
|
+
claude_session_id: activeSessionId ?? null,
|
|
26301
|
+
message: error instanceof Error ? error.message : String(error)
|
|
26302
|
+
});
|
|
26303
|
+
}
|
|
26304
|
+
void sessionWork.then(
|
|
26305
|
+
() => {
|
|
26306
|
+
args.log("claude_code.session_loop_ended", {
|
|
26307
|
+
linzumi_thread_id: threadId,
|
|
26308
|
+
claude_session_id: activeSessionId ?? null
|
|
26309
|
+
});
|
|
26310
|
+
},
|
|
26311
|
+
(error) => {
|
|
26312
|
+
args.log("claude_code.session_loop_failed", {
|
|
26313
|
+
linzumi_thread_id: threadId,
|
|
26314
|
+
claude_session_id: activeSessionId ?? null,
|
|
26315
|
+
message: error instanceof Error ? error.message : String(error)
|
|
26316
|
+
});
|
|
26317
|
+
}
|
|
26318
|
+
);
|
|
26319
|
+
const liveSessionId = activeSessionId ?? args.resumeSessionId;
|
|
26320
|
+
if (liveSessionId !== void 0) {
|
|
26321
|
+
return respondWithSessionId(liveSessionId);
|
|
26322
|
+
}
|
|
26323
|
+
const result = await sessionWork;
|
|
26324
|
+
return respondWithSessionId(result.sessionId);
|
|
25608
26325
|
}
|
|
25609
26326
|
function claudePermissionModeForApprovalPolicy(approvalPolicy) {
|
|
25610
26327
|
switch (approvalPolicy) {
|
|
@@ -25710,6 +26427,8 @@ function claudeSessionStoreEntryPayload(args, event) {
|
|
|
25710
26427
|
itemKey: event.itemKey,
|
|
25711
26428
|
body: event.content
|
|
25712
26429
|
};
|
|
26430
|
+
case "command_output_delta":
|
|
26431
|
+
return void 0;
|
|
25713
26432
|
case "usage":
|
|
25714
26433
|
return { usage: event.usage };
|
|
25715
26434
|
case "rate_limit":
|
|
@@ -25844,50 +26563,26 @@ function claudeRateLimitSignature(rateLimit) {
|
|
|
25844
26563
|
rateLimit.resetsAtMs ?? "na"
|
|
25845
26564
|
].join(":");
|
|
25846
26565
|
}
|
|
25847
|
-
async function
|
|
25848
|
-
|
|
25849
|
-
const summary = claudeCodeRateLimitSummaryText(args.rateLimit, nowMs);
|
|
25850
|
-
const headline = `Claude Code rate limit: ${summary}`;
|
|
25851
|
-
const resetLabel = claudeCodeRateLimitResetLabel(
|
|
25852
|
-
args.rateLimit.resetsAtMs,
|
|
25853
|
-
nowMs
|
|
25854
|
-
);
|
|
25855
|
-
const richUi = args.rateLimit.utilizationPercent === void 0 ? [{ primitive: "label", label: headline }] : [
|
|
25856
|
-
{
|
|
25857
|
-
primitive: "progress",
|
|
25858
|
-
value: Math.min(
|
|
25859
|
-
100,
|
|
25860
|
-
Math.max(0, Math.round(args.rateLimit.utilizationPercent))
|
|
25861
|
-
),
|
|
25862
|
-
max: 100,
|
|
25863
|
-
label: `Claude Code rate limit${resetLabel === void 0 ? "" : ` - ${resetLabel}`}`
|
|
25864
|
-
}
|
|
25865
|
-
];
|
|
25866
|
-
await args.kandan.push(args.topic, "session:post_thread_message", {
|
|
26566
|
+
async function publishClaudeCodeRateLimitState(args) {
|
|
26567
|
+
await args.kandan.push(args.topic, "claude_rate_limit_state", {
|
|
25867
26568
|
workspace: args.workspace,
|
|
25868
26569
|
channel: args.channel,
|
|
25869
26570
|
thread_id: args.threadId,
|
|
25870
|
-
|
|
25871
|
-
|
|
25872
|
-
|
|
25873
|
-
|
|
25874
|
-
|
|
25875
|
-
|
|
25876
|
-
|
|
25877
|
-
|
|
25878
|
-
|
|
25879
|
-
|
|
26571
|
+
agent_provider: "claude-code",
|
|
26572
|
+
...args.claudeSessionId === void 0 ? {} : { claude_session_id: args.claudeSessionId },
|
|
26573
|
+
// "account" mirrors the server-side default for SDK frames that omit a
|
|
26574
|
+
// window type; sending it explicitly keeps the wire contract obvious.
|
|
26575
|
+
rate_limit_type: args.rateLimit.rateLimitType ?? "account",
|
|
26576
|
+
status: args.rateLimit.status ?? "allowed",
|
|
26577
|
+
...args.rateLimit.utilizationPercent === void 0 ? {} : {
|
|
26578
|
+
utilization_percent: Math.min(
|
|
26579
|
+
100,
|
|
26580
|
+
Math.max(0, Math.round(args.rateLimit.utilizationPercent))
|
|
26581
|
+
)
|
|
25880
26582
|
},
|
|
25881
|
-
|
|
25882
|
-
args.threadId,
|
|
25883
|
-
args.rateLimit
|
|
25884
|
-
)
|
|
26583
|
+
...args.rateLimit.resetsAtMs === void 0 ? {} : { resets_at_ms: args.rateLimit.resetsAtMs }
|
|
25885
26584
|
});
|
|
25886
26585
|
}
|
|
25887
|
-
function claudeRateLimitClientMessageId(threadId, rateLimit) {
|
|
25888
|
-
const digest = createHash5("sha256").update(`${threadId}:${claudeRateLimitSignature(rateLimit)}`).digest("hex").slice(0, 32);
|
|
25889
|
-
return `claude-rate-limit-${digest}`;
|
|
25890
|
-
}
|
|
25891
26586
|
async function publishStartInstanceMessageState(kandan, topic, control, status, reason, diagnostics = {}) {
|
|
25892
26587
|
const payload = startInstanceMessageStatePayload(
|
|
25893
26588
|
control,
|
|
@@ -26128,7 +26823,7 @@ function threadRunnerOptions(args) {
|
|
|
26128
26823
|
args.options,
|
|
26129
26824
|
args.control
|
|
26130
26825
|
);
|
|
26131
|
-
const
|
|
26826
|
+
const providerResolution = resolveControlCodexModelProvider(args.control);
|
|
26132
26827
|
return {
|
|
26133
26828
|
...args.options,
|
|
26134
26829
|
clientId: void 0,
|
|
@@ -26145,7 +26840,7 @@ function threadRunnerOptions(args) {
|
|
|
26145
26840
|
role: "thread",
|
|
26146
26841
|
kandanThreadId: args.kandanThreadId
|
|
26147
26842
|
},
|
|
26148
|
-
codexModelProvider:
|
|
26843
|
+
codexModelProvider: providerResolution.type === "provider" ? providerResolution.runtime : void 0,
|
|
26149
26844
|
spawnThreadRunner: void 0,
|
|
26150
26845
|
threadRunnerReadyTimeoutMs: args.options.threadRunnerReadyTimeoutMs,
|
|
26151
26846
|
runtimeDefaults: {
|
|
@@ -26182,6 +26877,7 @@ async function spawnLocalThreadRunnerProcess(options) {
|
|
|
26182
26877
|
scriptPath,
|
|
26183
26878
|
redactedThreadRunnerCliArgs(args)
|
|
26184
26879
|
);
|
|
26880
|
+
const forwardableOpenAiApiKey = options.codexModelProvider?.provider === "openai-proxy" ? resolveForwardableOpenAiApiKey() : void 0;
|
|
26185
26881
|
const env = {
|
|
26186
26882
|
...process.env,
|
|
26187
26883
|
LINZUMI_THREAD_RUNNER_ROLE: "thread",
|
|
@@ -26189,7 +26885,8 @@ async function spawnLocalThreadRunnerProcess(options) {
|
|
|
26189
26885
|
LINZUMI_THREAD_RUNNER_TOKEN: options.token,
|
|
26190
26886
|
// The LLM proxy credential travels via env (like the runner token), not
|
|
26191
26887
|
// argv, so the spawned worker's command line never carries it.
|
|
26192
|
-
...options.codexModelProvider === void 0 ? {} : { LINZUMI_LLM_PROXY_TOKEN: options.codexModelProvider.llmProxyToken }
|
|
26888
|
+
...options.codexModelProvider === void 0 ? {} : { LINZUMI_LLM_PROXY_TOKEN: options.codexModelProvider.llmProxyToken },
|
|
26889
|
+
...forwardableOpenAiApiKey === void 0 ? {} : { OPENAI_API_KEY: forwardableOpenAiApiKey }
|
|
26193
26890
|
};
|
|
26194
26891
|
writeCliAuditEvent("process.spawn", {
|
|
26195
26892
|
command: process.execPath,
|
|
@@ -27395,16 +28092,16 @@ async function startOwnedCodexAppServer(options, args = { linzumiMcp: true }) {
|
|
|
27395
28092
|
model: defaults.model,
|
|
27396
28093
|
reasoningEffort: defaults.reasoningEffort,
|
|
27397
28094
|
fast: options.fast,
|
|
27398
|
-
//
|
|
27399
|
-
// Kandan LLM proxy via a custom Linzumi model provider
|
|
27400
|
-
//
|
|
28095
|
+
// Proxy-routed thread workers point their owned app-server at the
|
|
28096
|
+
// Kandan LLM proxy via a custom Linzumi model provider. Wafer routes
|
|
28097
|
+
// ride the session token as the bearer; openai-proxy routes (parity
|
|
28098
|
+
// backlog item 50) additionally materialize the user's own
|
|
28099
|
+
// OPENAI_API_KEY as the passthrough upstream credential.
|
|
27401
28100
|
...options.codexModelProvider === void 0 ? {} : {
|
|
27402
28101
|
modelProvider: linzumiCodexModelProviderConfig(
|
|
27403
28102
|
options.codexModelProvider
|
|
27404
28103
|
),
|
|
27405
|
-
env:
|
|
27406
|
-
LINZUMI_LLM_PROXY_TOKEN: options.codexModelProvider.llmProxyToken
|
|
27407
|
-
}
|
|
28104
|
+
env: codexModelProviderAppServerEnv(options.codexModelProvider)
|
|
27408
28105
|
},
|
|
27409
28106
|
mcpServers: mcpAuth === void 0 ? [] : [
|
|
27410
28107
|
linzumiMcpServerConfig({
|
|
@@ -27452,9 +28149,9 @@ function mcpOwnerUsername(options) {
|
|
|
27452
28149
|
return options.channelSession?.listenUser ?? identityFromAccessToken(options.token).actorUsername;
|
|
27453
28150
|
}
|
|
27454
28151
|
function writeEphemeralMcpAuthFile(options) {
|
|
27455
|
-
const directory = mkdtempSync4(
|
|
28152
|
+
const directory = mkdtempSync4(join20(tmpdir3(), "linzumi-mcp-auth-"));
|
|
27456
28153
|
chmodSync2(directory, 448);
|
|
27457
|
-
const path2 =
|
|
28154
|
+
const path2 = join20(directory, "auth.json");
|
|
27458
28155
|
writeCachedLocalRunnerToken({
|
|
27459
28156
|
kandanUrl: options.kandanUrl,
|
|
27460
28157
|
accessToken: options.token,
|
|
@@ -27463,7 +28160,7 @@ function writeEphemeralMcpAuthFile(options) {
|
|
|
27463
28160
|
chmodSync2(path2, 384);
|
|
27464
28161
|
return {
|
|
27465
28162
|
path: path2,
|
|
27466
|
-
cleanup: () =>
|
|
28163
|
+
cleanup: () => rmSync5(directory, { recursive: true, force: true })
|
|
27467
28164
|
};
|
|
27468
28165
|
}
|
|
27469
28166
|
function once(action) {
|
|
@@ -27530,7 +28227,7 @@ function configuredAllowedCwds(values, options = {}) {
|
|
|
27530
28227
|
const absolutePath = resolve8(expandUserPath(value));
|
|
27531
28228
|
try {
|
|
27532
28229
|
if (options.createMissing === true) {
|
|
27533
|
-
|
|
28230
|
+
mkdirSync12(absolutePath, { recursive: true });
|
|
27534
28231
|
}
|
|
27535
28232
|
const realPath = realpathSync6(absolutePath);
|
|
27536
28233
|
allowedCwds.push(
|
|
@@ -27567,7 +28264,7 @@ function allowedCwdProjects(allowedCwds) {
|
|
|
27567
28264
|
});
|
|
27568
28265
|
}
|
|
27569
28266
|
function isGitProjectDirectory(cwd) {
|
|
27570
|
-
const gitPath =
|
|
28267
|
+
const gitPath = join20(cwd, ".git");
|
|
27571
28268
|
try {
|
|
27572
28269
|
const gitPathStats = statSync3(gitPath);
|
|
27573
28270
|
return gitPathStats.isDirectory() || gitPathStats.isFile();
|
|
@@ -27592,7 +28289,7 @@ function browseRunnerDirectory(control, options) {
|
|
|
27592
28289
|
}
|
|
27593
28290
|
const parent = dirname13(currentPath);
|
|
27594
28291
|
const entries = readdirSync4(currentPath, { withFileTypes: true }).filter((entry) => entry.isDirectory()).filter((entry) => visibleRunnerDirectoryEntryName(entry.name)).map((entry) => {
|
|
27595
|
-
const path2 =
|
|
28292
|
+
const path2 = join20(currentPath, entry.name);
|
|
27596
28293
|
return {
|
|
27597
28294
|
name: entry.name,
|
|
27598
28295
|
path: path2,
|
|
@@ -27633,7 +28330,7 @@ function projectDirectoryName(name) {
|
|
|
27633
28330
|
function availableProjectDirectoryName(projectsRoot, baseName, suffix = 0) {
|
|
27634
28331
|
for (let nextSuffix = suffix; ; nextSuffix += 1) {
|
|
27635
28332
|
const candidate = nextSuffix === 0 ? baseName : `${baseName}-${nextSuffix}`;
|
|
27636
|
-
if (!projectPathExists(
|
|
28333
|
+
if (!projectPathExists(join20(projectsRoot, candidate))) {
|
|
27637
28334
|
return candidate;
|
|
27638
28335
|
}
|
|
27639
28336
|
}
|
|
@@ -27661,9 +28358,9 @@ function createRunnerProject(control, options, allowedCwds) {
|
|
|
27661
28358
|
error: "invalid_project_template"
|
|
27662
28359
|
};
|
|
27663
28360
|
}
|
|
27664
|
-
const projectsRoot =
|
|
28361
|
+
const projectsRoot = join20(currentHomeDirectory(), "linzumi");
|
|
27665
28362
|
const resolvedProjectDirName = template === "hello_linzumi_demo" ? availableProjectDirectoryName(projectsRoot, projectDirName) : projectDirName;
|
|
27666
|
-
const projectPath =
|
|
28363
|
+
const projectPath = join20(projectsRoot, resolvedProjectDirName);
|
|
27667
28364
|
let createdProjectPath = false;
|
|
27668
28365
|
try {
|
|
27669
28366
|
if (template !== "hello_linzumi_demo" && projectPathExists(projectPath)) {
|
|
@@ -27675,7 +28372,7 @@ function createRunnerProject(control, options, allowedCwds) {
|
|
|
27675
28372
|
error: "project_directory_exists"
|
|
27676
28373
|
};
|
|
27677
28374
|
}
|
|
27678
|
-
|
|
28375
|
+
mkdirSync12(projectsRoot, { recursive: true });
|
|
27679
28376
|
if (template === "hello_linzumi_demo") {
|
|
27680
28377
|
createdProjectPath = true;
|
|
27681
28378
|
createHelloLinzumiProject({
|
|
@@ -27683,7 +28380,7 @@ function createRunnerProject(control, options, allowedCwds) {
|
|
|
27683
28380
|
name: resolvedProjectDirName
|
|
27684
28381
|
});
|
|
27685
28382
|
} else {
|
|
27686
|
-
|
|
28383
|
+
mkdirSync12(projectPath, { recursive: false });
|
|
27687
28384
|
createdProjectPath = true;
|
|
27688
28385
|
}
|
|
27689
28386
|
const git = spawnSync5("git", ["init"], {
|
|
@@ -27741,7 +28438,7 @@ function createRunnerProject(control, options, allowedCwds) {
|
|
|
27741
28438
|
}
|
|
27742
28439
|
function removeCreatedProjectDirectory(projectPath) {
|
|
27743
28440
|
try {
|
|
27744
|
-
|
|
28441
|
+
rmSync5(projectPath, { recursive: true, force: true });
|
|
27745
28442
|
return void 0;
|
|
27746
28443
|
} catch (error) {
|
|
27747
28444
|
return error instanceof Error ? error.message : "cleanup_failed";
|
|
@@ -27805,6 +28502,7 @@ var init_runner = __esm({
|
|
|
27805
28502
|
init_commanderAttachments();
|
|
27806
28503
|
init_claudeCodePipeline();
|
|
27807
28504
|
init_claudeCodePlanMirror();
|
|
28505
|
+
init_claudeCodeLiveBashOutput();
|
|
27808
28506
|
init_claudeCodeSession();
|
|
27809
28507
|
init_codexAppServer();
|
|
27810
28508
|
init_codexProjectTrust();
|
|
@@ -27866,7 +28564,7 @@ var init_runner = __esm({
|
|
|
27866
28564
|
});
|
|
27867
28565
|
|
|
27868
28566
|
// src/kandanTls.ts
|
|
27869
|
-
import { existsSync as existsSync13, readFileSync as
|
|
28567
|
+
import { existsSync as existsSync13, readFileSync as readFileSync17 } from "node:fs";
|
|
27870
28568
|
import { Agent } from "undici";
|
|
27871
28569
|
import WsWebSocket from "ws";
|
|
27872
28570
|
function kandanTlsTrustFromEnv() {
|
|
@@ -27880,7 +28578,7 @@ function kandanTlsTrustFromCaFile(caFile) {
|
|
|
27880
28578
|
if (!existsSync13(trimmed)) {
|
|
27881
28579
|
throw new Error(`KANDAN_TLS_CA_FILE does not exist: ${trimmed}`);
|
|
27882
28580
|
}
|
|
27883
|
-
const ca =
|
|
28581
|
+
const ca = readFileSync17(trimmed, "utf8");
|
|
27884
28582
|
return {
|
|
27885
28583
|
caFile: trimmed,
|
|
27886
28584
|
ca,
|
|
@@ -42989,9 +43687,9 @@ var require_internal = __commonJS({
|
|
|
42989
43687
|
}
|
|
42990
43688
|
InternalCodec.prototype.encoder = InternalEncoder;
|
|
42991
43689
|
InternalCodec.prototype.decoder = InternalDecoder;
|
|
42992
|
-
var
|
|
43690
|
+
var StringDecoder2 = __require("string_decoder").StringDecoder;
|
|
42993
43691
|
function InternalDecoder(options, codec) {
|
|
42994
|
-
this.decoder = new
|
|
43692
|
+
this.decoder = new StringDecoder2(codec.enc);
|
|
42995
43693
|
}
|
|
42996
43694
|
InternalDecoder.prototype.write = function(buf) {
|
|
42997
43695
|
if (!Buffer4.isBuffer(buf)) {
|
|
@@ -46664,7 +47362,7 @@ var init_RemoveFileError = __esm({
|
|
|
46664
47362
|
|
|
46665
47363
|
// ../../node_modules/@inquirer/external-editor/dist/esm/index.js
|
|
46666
47364
|
import { spawn as spawn11, spawnSync as spawnSync6 } from "child_process";
|
|
46667
|
-
import { readFileSync as
|
|
47365
|
+
import { readFileSync as readFileSync20, unlinkSync as unlinkSync3, writeFileSync as writeFileSync14 } from "fs";
|
|
46668
47366
|
import path from "node:path";
|
|
46669
47367
|
import os from "node:os";
|
|
46670
47368
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
@@ -46781,14 +47479,14 @@ var init_esm5 = __esm({
|
|
|
46781
47479
|
if (Object.prototype.hasOwnProperty.call(this.fileOptions, "mode")) {
|
|
46782
47480
|
opt.mode = this.fileOptions.mode;
|
|
46783
47481
|
}
|
|
46784
|
-
|
|
47482
|
+
writeFileSync14(this.tempFile, this.text, opt);
|
|
46785
47483
|
} catch (createFileError) {
|
|
46786
47484
|
throw new CreateFileError(createFileError);
|
|
46787
47485
|
}
|
|
46788
47486
|
}
|
|
46789
47487
|
readTemporaryFile() {
|
|
46790
47488
|
try {
|
|
46791
|
-
const tempFileBuffer =
|
|
47489
|
+
const tempFileBuffer = readFileSync20(this.tempFile);
|
|
46792
47490
|
if (tempFileBuffer.length === 0) {
|
|
46793
47491
|
this.text = "";
|
|
46794
47492
|
} else {
|
|
@@ -48157,17 +48855,17 @@ import { spawn as spawn12, spawnSync as spawnSync7 } from "node:child_process";
|
|
|
48157
48855
|
import {
|
|
48158
48856
|
existsSync as existsSync16,
|
|
48159
48857
|
constants as fsConstants,
|
|
48160
|
-
mkdirSync as
|
|
48858
|
+
mkdirSync as mkdirSync15,
|
|
48161
48859
|
mkdtempSync as mkdtempSync5,
|
|
48162
|
-
readFileSync as
|
|
48860
|
+
readFileSync as readFileSync21,
|
|
48163
48861
|
readdirSync as readdirSync5,
|
|
48164
|
-
rmSync as
|
|
48862
|
+
rmSync as rmSync6,
|
|
48165
48863
|
statSync as statSync4,
|
|
48166
|
-
writeFileSync as
|
|
48864
|
+
writeFileSync as writeFileSync15
|
|
48167
48865
|
} from "node:fs";
|
|
48168
48866
|
import { access } from "node:fs/promises";
|
|
48169
|
-
import { homedir as
|
|
48170
|
-
import { delimiter as delimiter3, dirname as dirname16, join as
|
|
48867
|
+
import { homedir as homedir16, tmpdir as tmpdir4 } from "node:os";
|
|
48868
|
+
import { delimiter as delimiter3, dirname as dirname16, join as join23, resolve as resolve10 } from "node:path";
|
|
48171
48869
|
import { stdin as defaultStdin, stdout as defaultStdout } from "node:process";
|
|
48172
48870
|
import { emitKeypressEvents } from "node:readline";
|
|
48173
48871
|
function signupHelpText() {
|
|
@@ -48288,7 +48986,7 @@ function defaultSignupDraftStore(serviceUrl) {
|
|
|
48288
48986
|
}
|
|
48289
48987
|
let parsed;
|
|
48290
48988
|
try {
|
|
48291
|
-
parsed = JSON.parse(
|
|
48989
|
+
parsed = JSON.parse(readFileSync21(path2, "utf8"));
|
|
48292
48990
|
} catch (_error) {
|
|
48293
48991
|
return void 0;
|
|
48294
48992
|
}
|
|
@@ -48298,20 +48996,20 @@ function defaultSignupDraftStore(serviceUrl) {
|
|
|
48298
48996
|
return comparableServiceUrl(parsed.serviceUrl) === comparableServiceUrl(serviceUrl) ? parsed : void 0;
|
|
48299
48997
|
},
|
|
48300
48998
|
write: (draft) => {
|
|
48301
|
-
|
|
48302
|
-
|
|
48999
|
+
mkdirSync15(dirname16(path2), { recursive: true });
|
|
49000
|
+
writeFileSync15(path2, `${JSON.stringify(draft, null, 2)}
|
|
48303
49001
|
`, {
|
|
48304
49002
|
encoding: "utf8",
|
|
48305
49003
|
mode: 384
|
|
48306
49004
|
});
|
|
48307
49005
|
},
|
|
48308
49006
|
clear: () => {
|
|
48309
|
-
|
|
49007
|
+
rmSync6(path2, { force: true });
|
|
48310
49008
|
}
|
|
48311
49009
|
};
|
|
48312
49010
|
}
|
|
48313
49011
|
function defaultSignupDraftPath(serviceUrl) {
|
|
48314
|
-
return
|
|
49012
|
+
return join23(
|
|
48315
49013
|
dirname16(localConfigPath()),
|
|
48316
49014
|
`signup-draft.${localConfigScopeFileStem(serviceUrl)}.json`
|
|
48317
49015
|
);
|
|
@@ -48346,8 +49044,8 @@ function defaultSignupTaskCacheStore(serviceUrl) {
|
|
|
48346
49044
|
}
|
|
48347
49045
|
}
|
|
48348
49046
|
};
|
|
48349
|
-
|
|
48350
|
-
|
|
49047
|
+
mkdirSync15(dirname16(path2), { recursive: true });
|
|
49048
|
+
writeFileSync15(path2, `${JSON.stringify(next, null, 2)}
|
|
48351
49049
|
`, {
|
|
48352
49050
|
encoding: "utf8",
|
|
48353
49051
|
mode: 384
|
|
@@ -48356,7 +49054,7 @@ function defaultSignupTaskCacheStore(serviceUrl) {
|
|
|
48356
49054
|
};
|
|
48357
49055
|
}
|
|
48358
49056
|
function defaultSignupTaskCachePath(serviceUrl) {
|
|
48359
|
-
return
|
|
49057
|
+
return join23(
|
|
48360
49058
|
dirname16(localConfigPath()),
|
|
48361
49059
|
`signup-task-cache.${localConfigScopeFileStem(serviceUrl)}.json`
|
|
48362
49060
|
);
|
|
@@ -48367,7 +49065,7 @@ function readSignupTaskCache(path2) {
|
|
|
48367
49065
|
}
|
|
48368
49066
|
let parsed;
|
|
48369
49067
|
try {
|
|
48370
|
-
parsed = JSON.parse(
|
|
49068
|
+
parsed = JSON.parse(readFileSync21(path2, "utf8"));
|
|
48371
49069
|
} catch (_error) {
|
|
48372
49070
|
return { version: 1, entries: {} };
|
|
48373
49071
|
}
|
|
@@ -50252,7 +50950,7 @@ function autocompletePathSuggestions(pathInput) {
|
|
|
50252
50950
|
try {
|
|
50253
50951
|
const showHidden = prefix.startsWith(".");
|
|
50254
50952
|
const currentPath = directoryExists(normalizedInput) ? [normalizedInput.replace(/\/$/, "") || "/"] : [];
|
|
50255
|
-
const childPaths = readdirSync5(directoryPath, { withFileTypes: true }).filter((entry) => entry.isDirectory()).filter((entry) => showHidden || !entry.name.startsWith(".")).map((entry) =>
|
|
50953
|
+
const childPaths = readdirSync5(directoryPath, { withFileTypes: true }).filter((entry) => entry.isDirectory()).filter((entry) => showHidden || !entry.name.startsWith(".")).map((entry) => join23(directoryPath, entry.name)).map((path2) => ({
|
|
50256
50954
|
path: path2,
|
|
50257
50955
|
score: fuzzyPathSegmentScore(path2.split("/").at(-1) ?? path2, prefix)
|
|
50258
50956
|
})).filter((candidate) => candidate.score !== void 0).sort((left, right) => {
|
|
@@ -50498,7 +51196,7 @@ async function runSignupPreflights(runtime) {
|
|
|
50498
51196
|
function defaultPreflightRuntime() {
|
|
50499
51197
|
return {
|
|
50500
51198
|
cwd: process.cwd(),
|
|
50501
|
-
homeDir:
|
|
51199
|
+
homeDir: homedir16(),
|
|
50502
51200
|
probeTool,
|
|
50503
51201
|
readGitEmail,
|
|
50504
51202
|
discoverCodeRoots,
|
|
@@ -50643,13 +51341,13 @@ async function suggestTasksWithCodex(projectPath, retryPolicy) {
|
|
|
50643
51341
|
);
|
|
50644
51342
|
}
|
|
50645
51343
|
async function runCodexTaskSuggestion2(projectPath, previousResponse, retryPolicy) {
|
|
50646
|
-
const tempRoot = mkdtempSync5(
|
|
50647
|
-
const schemaPath =
|
|
50648
|
-
const outputPath =
|
|
51344
|
+
const tempRoot = mkdtempSync5(join23(tmpdir4(), "linzumi-signup-codex-tasks-"));
|
|
51345
|
+
const schemaPath = join23(tempRoot, "task-suggestions.schema.json");
|
|
51346
|
+
const outputPath = join23(tempRoot, "task-suggestions.json");
|
|
50649
51347
|
const model = process.env.LINZUMI_SIGNUP_TASK_MODEL ?? "gpt-5.4-mini";
|
|
50650
51348
|
const prompt = taskSuggestionPrompt2(previousResponse);
|
|
50651
51349
|
const codexCommand = await resolveSignupCodexCommand();
|
|
50652
|
-
|
|
51350
|
+
writeFileSync15(
|
|
50653
51351
|
schemaPath,
|
|
50654
51352
|
`${JSON.stringify(taskSuggestionJsonSchema2(), null, 2)}
|
|
50655
51353
|
`,
|
|
@@ -50670,9 +51368,9 @@ async function runCodexTaskSuggestion2(projectPath, previousResponse, retryPolic
|
|
|
50670
51368
|
),
|
|
50671
51369
|
retryPolicy
|
|
50672
51370
|
);
|
|
50673
|
-
return
|
|
51371
|
+
return readFileSync21(outputPath, "utf8");
|
|
50674
51372
|
} finally {
|
|
50675
|
-
|
|
51373
|
+
rmSync6(tempRoot, { recursive: true, force: true });
|
|
50676
51374
|
}
|
|
50677
51375
|
}
|
|
50678
51376
|
function codexTaskSuggestionProcess2(args) {
|
|
@@ -50707,7 +51405,7 @@ function codexTaskSuggestionProcess2(args) {
|
|
|
50707
51405
|
function signupCodexTaskSuggestionProcessForTest(args) {
|
|
50708
51406
|
return codexTaskSuggestionProcess2(args);
|
|
50709
51407
|
}
|
|
50710
|
-
async function resolveSignupCodexCommand(env = process.env, homeDir =
|
|
51408
|
+
async function resolveSignupCodexCommand(env = process.env, homeDir = homedir16(), executableExists = fileIsExecutable) {
|
|
50711
51409
|
const override = firstConfiguredValue([
|
|
50712
51410
|
env.LINZUMI_SIGNUP_CODEX_BIN,
|
|
50713
51411
|
env.LINZUMI_CODEX_BIN
|
|
@@ -50762,7 +51460,7 @@ function resolveHomePath(path2, homeDir) {
|
|
|
50762
51460
|
return homeDir;
|
|
50763
51461
|
}
|
|
50764
51462
|
if (path2.startsWith("~/")) {
|
|
50765
|
-
return
|
|
51463
|
+
return join23(homeDir, path2.slice(2));
|
|
50766
51464
|
}
|
|
50767
51465
|
return resolve10(path2);
|
|
50768
51466
|
}
|
|
@@ -50775,9 +51473,9 @@ function commandLooksPathLike(command) {
|
|
|
50775
51473
|
}
|
|
50776
51474
|
function homeManagedCodexCandidates(homeDir) {
|
|
50777
51475
|
return [
|
|
50778
|
-
|
|
50779
|
-
|
|
50780
|
-
|
|
51476
|
+
join23(homeDir, ".volta", "bin", "codex"),
|
|
51477
|
+
join23(homeDir, ".local", "bin", "codex"),
|
|
51478
|
+
join23(homeDir, "bin", "codex")
|
|
50781
51479
|
];
|
|
50782
51480
|
}
|
|
50783
51481
|
async function firstExecutablePath(paths, executableExists) {
|
|
@@ -50792,7 +51490,7 @@ function commandPathCandidates(path2) {
|
|
|
50792
51490
|
if (path2 === void 0 || path2.trim() === "") {
|
|
50793
51491
|
return [];
|
|
50794
51492
|
}
|
|
50795
|
-
return path2.split(delimiter3).filter((entry) => entry.trim() !== "").map((entry) =>
|
|
51493
|
+
return path2.split(delimiter3).filter((entry) => entry.trim() !== "").map((entry) => join23(entry, "codex"));
|
|
50796
51494
|
}
|
|
50797
51495
|
async function fileIsExecutable(path2) {
|
|
50798
51496
|
try {
|
|
@@ -51025,11 +51723,11 @@ function codexPreflightLocation(command, homeDir) {
|
|
|
51025
51723
|
switch (command) {
|
|
51026
51724
|
case "codex":
|
|
51027
51725
|
return "on PATH";
|
|
51028
|
-
case
|
|
51726
|
+
case join23(homeDir, ".volta", "bin", "codex"):
|
|
51029
51727
|
return "via Volta";
|
|
51030
|
-
case
|
|
51728
|
+
case join23(homeDir, ".local", "bin", "codex"):
|
|
51031
51729
|
return "via ~/.local/bin";
|
|
51032
|
-
case
|
|
51730
|
+
case join23(homeDir, "bin", "codex"):
|
|
51033
51731
|
return "via ~/bin";
|
|
51034
51732
|
default:
|
|
51035
51733
|
return "from configured path";
|
|
@@ -51188,7 +51886,7 @@ function probeToolWithArgs(command, args, cwd) {
|
|
|
51188
51886
|
}
|
|
51189
51887
|
async function discoverCodeRoots(homeDir) {
|
|
51190
51888
|
const candidates = ["src", "code", "projects"].map(
|
|
51191
|
-
(name) =>
|
|
51889
|
+
(name) => join23(homeDir, name)
|
|
51192
51890
|
);
|
|
51193
51891
|
return candidates.filter((path2) => existsSync16(path2)).flatMap((path2) => discoveredProjectNames(path2));
|
|
51194
51892
|
}
|
|
@@ -51242,7 +51940,7 @@ function discoverProjectsFromCurrentDirectory(cwd) {
|
|
|
51242
51940
|
}
|
|
51243
51941
|
function discoverProjectsFromGuessedRoots(homeDir) {
|
|
51244
51942
|
const guessedRoots = ["src", "code", "projects"].map(
|
|
51245
|
-
(name) =>
|
|
51943
|
+
(name) => join23(homeDir, name)
|
|
51246
51944
|
);
|
|
51247
51945
|
const projects = guessedRoots.flatMap(
|
|
51248
51946
|
(root) => discoverProjectsUnderRoot(root)
|
|
@@ -51294,25 +51992,25 @@ function looksLikeProject(path2) {
|
|
|
51294
51992
|
"pnpm-lock.yaml",
|
|
51295
51993
|
"yarn.lock",
|
|
51296
51994
|
"package-lock.json"
|
|
51297
|
-
].some((name) => existsSync16(
|
|
51995
|
+
].some((name) => existsSync16(join23(path2, name)));
|
|
51298
51996
|
}
|
|
51299
51997
|
function detectProjectLanguage(path2) {
|
|
51300
|
-
if (existsSync16(
|
|
51998
|
+
if (existsSync16(join23(path2, "pyproject.toml")) || existsSync16(join23(path2, "requirements.txt"))) {
|
|
51301
51999
|
return "Python";
|
|
51302
52000
|
}
|
|
51303
|
-
if (existsSync16(
|
|
52001
|
+
if (existsSync16(join23(path2, "Cargo.toml"))) {
|
|
51304
52002
|
return "Rust";
|
|
51305
52003
|
}
|
|
51306
|
-
if (existsSync16(
|
|
52004
|
+
if (existsSync16(join23(path2, "go.mod"))) {
|
|
51307
52005
|
return "Go";
|
|
51308
52006
|
}
|
|
51309
|
-
if (existsSync16(
|
|
52007
|
+
if (existsSync16(join23(path2, "mix.exs"))) {
|
|
51310
52008
|
return "Elixir";
|
|
51311
52009
|
}
|
|
51312
|
-
if (existsSync16(
|
|
52010
|
+
if (existsSync16(join23(path2, "tsconfig.json")) || packageJsonMentionsTypeScript(path2)) {
|
|
51313
52011
|
return "TypeScript";
|
|
51314
52012
|
}
|
|
51315
|
-
if (existsSync16(
|
|
52013
|
+
if (existsSync16(join23(path2, "package.json"))) {
|
|
51316
52014
|
return "JavaScript";
|
|
51317
52015
|
}
|
|
51318
52016
|
return "Project";
|
|
@@ -51320,7 +52018,7 @@ function detectProjectLanguage(path2) {
|
|
|
51320
52018
|
function packageJsonMentionsTypeScript(path2) {
|
|
51321
52019
|
try {
|
|
51322
52020
|
const packageJson2 = JSON.parse(
|
|
51323
|
-
|
|
52021
|
+
readFileSync21(join23(path2, "package.json"), "utf8")
|
|
51324
52022
|
);
|
|
51325
52023
|
return packageJson2.dependencies?.typescript !== void 0 || packageJson2.devDependencies?.typescript !== void 0;
|
|
51326
52024
|
} catch {
|
|
@@ -51328,11 +52026,11 @@ function packageJsonMentionsTypeScript(path2) {
|
|
|
51328
52026
|
}
|
|
51329
52027
|
}
|
|
51330
52028
|
function hasGitMetadata(path2) {
|
|
51331
|
-
return existsSync16(
|
|
52029
|
+
return existsSync16(join23(path2, ".git"));
|
|
51332
52030
|
}
|
|
51333
52031
|
function childDirectories(root) {
|
|
51334
52032
|
try {
|
|
51335
|
-
return readdirSync5(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) =>
|
|
52033
|
+
return readdirSync5(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join23(root, entry.name));
|
|
51336
52034
|
} catch {
|
|
51337
52035
|
return [];
|
|
51338
52036
|
}
|
|
@@ -51358,10 +52056,10 @@ function directoryExists(path2) {
|
|
|
51358
52056
|
}
|
|
51359
52057
|
function expandHomePath(path2) {
|
|
51360
52058
|
if (path2 === "~") {
|
|
51361
|
-
return
|
|
52059
|
+
return homedir16();
|
|
51362
52060
|
}
|
|
51363
52061
|
if (path2.startsWith("~/")) {
|
|
51364
|
-
return
|
|
52062
|
+
return join23(homedir16(), path2.slice(2));
|
|
51365
52063
|
}
|
|
51366
52064
|
return resolve10(path2);
|
|
51367
52065
|
}
|
|
@@ -51451,8 +52149,8 @@ init_onboardingDiscoveryChildProcess();
|
|
|
51451
52149
|
init_runner();
|
|
51452
52150
|
init_claudeCodeSession();
|
|
51453
52151
|
init_authCache();
|
|
51454
|
-
import { existsSync as existsSync17, readFileSync as
|
|
51455
|
-
import { homedir as
|
|
52152
|
+
import { existsSync as existsSync17, readFileSync as readFileSync22, realpathSync as realpathSync7 } from "node:fs";
|
|
52153
|
+
import { homedir as homedir17 } from "node:os";
|
|
51456
52154
|
import { resolve as resolve11 } from "node:path";
|
|
51457
52155
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
51458
52156
|
|
|
@@ -51547,9 +52245,9 @@ init_kandanTls();
|
|
|
51547
52245
|
init_protocol();
|
|
51548
52246
|
init_json();
|
|
51549
52247
|
init_defaultUrls();
|
|
51550
|
-
import { existsSync as existsSync14, mkdirSync as
|
|
51551
|
-
import { dirname as dirname14, join as
|
|
51552
|
-
import { homedir as
|
|
52248
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync13, readFileSync as readFileSync18, writeFileSync as writeFileSync12 } from "node:fs";
|
|
52249
|
+
import { dirname as dirname14, join as join21 } from "node:path";
|
|
52250
|
+
import { homedir as homedir14 } from "node:os";
|
|
51553
52251
|
async function runAgentCliCommand(args, deps = {
|
|
51554
52252
|
fetchImpl: fetch,
|
|
51555
52253
|
stdout: process.stdout,
|
|
@@ -52257,7 +52955,7 @@ function agentTokenFile(flags) {
|
|
|
52257
52955
|
return flags.get("agent-token-file") ?? defaultAgentTokenFilePath();
|
|
52258
52956
|
}
|
|
52259
52957
|
function defaultAgentTokenFilePath() {
|
|
52260
|
-
return
|
|
52958
|
+
return join21(homedir14(), ".linzumi", "agent-token.json");
|
|
52261
52959
|
}
|
|
52262
52960
|
function normalizedApiUrl(apiUrl) {
|
|
52263
52961
|
return apiUrl.endsWith("/") ? apiUrl : `${apiUrl}/`;
|
|
@@ -52266,11 +52964,11 @@ function authorizationHeaders(token) {
|
|
|
52266
52964
|
return { authorization: `Bearer ${token}` };
|
|
52267
52965
|
}
|
|
52268
52966
|
function readOptionalTextFile(path2) {
|
|
52269
|
-
return existsSync14(path2) ?
|
|
52967
|
+
return existsSync14(path2) ? readFileSync18(path2, "utf8") : void 0;
|
|
52270
52968
|
}
|
|
52271
52969
|
function writeTextFile(path2, content) {
|
|
52272
|
-
|
|
52273
|
-
|
|
52970
|
+
mkdirSync13(dirname14(path2), { recursive: true });
|
|
52971
|
+
writeFileSync12(path2, content);
|
|
52274
52972
|
}
|
|
52275
52973
|
function readStoredAgentTokenFile(path2, readTextFile = readOptionalTextFile) {
|
|
52276
52974
|
const content = readTextFile(path2);
|
|
@@ -52359,25 +53057,25 @@ init_runnerLogger();
|
|
|
52359
53057
|
import {
|
|
52360
53058
|
existsSync as existsSync15,
|
|
52361
53059
|
closeSync as closeSync3,
|
|
52362
|
-
mkdirSync as
|
|
53060
|
+
mkdirSync as mkdirSync14,
|
|
52363
53061
|
openSync as openSync4,
|
|
52364
|
-
readFileSync as
|
|
53062
|
+
readFileSync as readFileSync19,
|
|
52365
53063
|
watch,
|
|
52366
|
-
writeFileSync as
|
|
53064
|
+
writeFileSync as writeFileSync13
|
|
52367
53065
|
} from "node:fs";
|
|
52368
|
-
import { homedir as
|
|
52369
|
-
import { dirname as dirname15, join as
|
|
53066
|
+
import { homedir as homedir15 } from "node:os";
|
|
53067
|
+
import { dirname as dirname15, join as join22, resolve as resolve9 } from "node:path";
|
|
52370
53068
|
import { execFileSync, spawn as spawn10 } from "node:child_process";
|
|
52371
53069
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
52372
53070
|
var connectedMarkers = ["Connected to Linzumi", "Runner connected:"];
|
|
52373
53071
|
function commanderStatusDir() {
|
|
52374
|
-
return
|
|
53072
|
+
return join22(homedir15(), ".linzumi", "commanders");
|
|
52375
53073
|
}
|
|
52376
53074
|
function commanderStatusFile(runnerId, statusDir = commanderStatusDir()) {
|
|
52377
|
-
return
|
|
53075
|
+
return join22(statusDir, `${safeRunnerId(runnerId)}.json`);
|
|
52378
53076
|
}
|
|
52379
53077
|
function defaultCommanderLogFile(runnerId) {
|
|
52380
|
-
return
|
|
53078
|
+
return join22(homedir15(), ".linzumi", "logs", `${safeRunnerId(runnerId)}.log`);
|
|
52381
53079
|
}
|
|
52382
53080
|
function commanderLogIsConnected(log2) {
|
|
52383
53081
|
return connectedMarkers.some((marker) => log2.includes(marker));
|
|
@@ -52398,8 +53096,8 @@ function startCommanderDaemon(options) {
|
|
|
52398
53096
|
"--log-file",
|
|
52399
53097
|
logFile
|
|
52400
53098
|
];
|
|
52401
|
-
|
|
52402
|
-
|
|
53099
|
+
mkdirSync14(statusDir, { recursive: true });
|
|
53100
|
+
mkdirSync14(dirname15(logFile), { recursive: true });
|
|
52403
53101
|
const out = openSync4(logFile, "a");
|
|
52404
53102
|
const err = openSync4(logFile, "a");
|
|
52405
53103
|
writeCliAuditEvent(
|
|
@@ -52445,7 +53143,7 @@ function startCommanderDaemon(options) {
|
|
|
52445
53143
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
52446
53144
|
command: [nodeBin, ...command]
|
|
52447
53145
|
};
|
|
52448
|
-
|
|
53146
|
+
writeFileSync13(statusFile, `${JSON.stringify(record, null, 2)}
|
|
52449
53147
|
`);
|
|
52450
53148
|
return record;
|
|
52451
53149
|
}
|
|
@@ -52454,12 +53152,12 @@ function commanderDaemonStatus(runnerId, statusDir = commanderStatusDir(), proce
|
|
|
52454
53152
|
if (!existsSync15(statusFile)) {
|
|
52455
53153
|
return { status: "missing", runnerId, statusFile };
|
|
52456
53154
|
}
|
|
52457
|
-
const record = parseRecord(
|
|
53155
|
+
const record = parseRecord(readFileSync19(statusFile, "utf8"));
|
|
52458
53156
|
return processIsRunning(record.pid) && processMatchesRecord(record, processIdentityReader) ? { status: "running", record } : { status: "stopped", record };
|
|
52459
53157
|
}
|
|
52460
53158
|
async function waitForCommanderDaemon(options) {
|
|
52461
53159
|
const now = options.now ?? (() => Date.now());
|
|
52462
|
-
const readTextFile = options.readTextFile ?? ((path2) => existsSync15(path2) ?
|
|
53160
|
+
const readTextFile = options.readTextFile ?? ((path2) => existsSync15(path2) ? readFileSync19(path2, "utf8") : void 0);
|
|
52463
53161
|
const statusImpl = options.statusImpl ?? commanderDaemonStatus;
|
|
52464
53162
|
const deadline = now() + options.timeoutMs;
|
|
52465
53163
|
while (now() <= deadline) {
|
|
@@ -66401,7 +67099,7 @@ async function parseAgentRunnerArgs(args, deps = {
|
|
|
66401
67099
|
};
|
|
66402
67100
|
}
|
|
66403
67101
|
function readAgentTokenTextFile(path2) {
|
|
66404
|
-
return existsSync17(path2) ?
|
|
67102
|
+
return existsSync17(path2) ? readFileSync22(path2, "utf8") : void 0;
|
|
66405
67103
|
}
|
|
66406
67104
|
function rejectAgentRunnerTargetingFlags(values) {
|
|
66407
67105
|
const unsupportedFlags = [
|
|
@@ -66711,10 +67409,10 @@ function rejectStartTargetingFlags(values) {
|
|
|
66711
67409
|
}
|
|
66712
67410
|
function resolveUserPath(pathValue) {
|
|
66713
67411
|
if (pathValue === "~") {
|
|
66714
|
-
return
|
|
67412
|
+
return homedir17();
|
|
66715
67413
|
}
|
|
66716
67414
|
if (pathValue.startsWith("~/")) {
|
|
66717
|
-
return resolve11(
|
|
67415
|
+
return resolve11(homedir17(), pathValue.slice(2));
|
|
66718
67416
|
}
|
|
66719
67417
|
return resolve11(pathValue);
|
|
66720
67418
|
}
|
|
@@ -66817,21 +67515,23 @@ function threadRunnerCodexModelProvider(values) {
|
|
|
66817
67515
|
if (modelProvider === void 0) {
|
|
66818
67516
|
return void 0;
|
|
66819
67517
|
}
|
|
66820
|
-
if (modelProvider !== "wafer") {
|
|
67518
|
+
if (modelProvider !== "wafer" && modelProvider !== "openai-proxy") {
|
|
66821
67519
|
throw new Error(`unsupported --model-provider: ${modelProvider}`);
|
|
66822
67520
|
}
|
|
66823
67521
|
const llmProxyBaseUrl = stringValue8(values, "llm-proxy-base-url");
|
|
66824
67522
|
const llmProxyToken = process.env.LINZUMI_LLM_PROXY_TOKEN?.trim();
|
|
66825
67523
|
if (llmProxyBaseUrl === void 0) {
|
|
66826
|
-
throw new Error(
|
|
67524
|
+
throw new Error(
|
|
67525
|
+
`--model-provider ${modelProvider} requires --llm-proxy-base-url`
|
|
67526
|
+
);
|
|
66827
67527
|
}
|
|
66828
67528
|
if (llmProxyToken === void 0 || llmProxyToken === "") {
|
|
66829
67529
|
throw new Error(
|
|
66830
|
-
|
|
67530
|
+
`--model-provider ${modelProvider} requires the LINZUMI_LLM_PROXY_TOKEN env credential`
|
|
66831
67531
|
);
|
|
66832
67532
|
}
|
|
66833
67533
|
return {
|
|
66834
|
-
provider:
|
|
67534
|
+
provider: modelProvider,
|
|
66835
67535
|
llmProxyBaseUrl,
|
|
66836
67536
|
llmProxyToken
|
|
66837
67537
|
};
|