@linzumi/cli 0.0.83-beta → 0.0.84-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 +897 -333
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11564,6 +11564,21 @@ function createClaudeCodeSessionPipeline(host) {
|
|
|
11564
11564
|
handleToolResult(ensureTurn(), event);
|
|
11565
11565
|
return;
|
|
11566
11566
|
}
|
|
11567
|
+
case "command_output_delta": {
|
|
11568
|
+
const turn = activeTurn;
|
|
11569
|
+
const pending = turn?.pendingTools.get(event.itemKey);
|
|
11570
|
+
if (turn === void 0 || pending === void 0) {
|
|
11571
|
+
return;
|
|
11572
|
+
}
|
|
11573
|
+
submit("item/commandExecution/outputDelta", {
|
|
11574
|
+
turnId: turn.turnId,
|
|
11575
|
+
itemId: `tool:${event.itemKey}`,
|
|
11576
|
+
command: claudeToolCommandLabel(pending.toolName, pending.input),
|
|
11577
|
+
stream: "stdout",
|
|
11578
|
+
delta: event.delta
|
|
11579
|
+
});
|
|
11580
|
+
return;
|
|
11581
|
+
}
|
|
11567
11582
|
case "command_output": {
|
|
11568
11583
|
const turn = ensureTurn();
|
|
11569
11584
|
const item = {
|
|
@@ -11945,13 +11960,304 @@ var init_claudeCodePlanMirror = __esm({
|
|
|
11945
11960
|
}
|
|
11946
11961
|
});
|
|
11947
11962
|
|
|
11963
|
+
// src/claudeCodeLiveBashOutput.ts
|
|
11964
|
+
import {
|
|
11965
|
+
mkdirSync as mkdirSync2,
|
|
11966
|
+
rmSync,
|
|
11967
|
+
writeFileSync,
|
|
11968
|
+
promises as fsPromises
|
|
11969
|
+
} from "node:fs";
|
|
11970
|
+
import { join as join6 } from "node:path";
|
|
11971
|
+
import { StringDecoder } from "node:string_decoder";
|
|
11972
|
+
function shellSingleQuoted(value) {
|
|
11973
|
+
return `'${value.replaceAll("'", `'\\''`)}'`;
|
|
11974
|
+
}
|
|
11975
|
+
function claudeLiveBashWrappedCommand(command, captureFile) {
|
|
11976
|
+
return `__lz_live_out=${shellSingleQuoted(captureFile)}; if ! : >> "$__lz_live_out" 2>/dev/null; then __lz_live_out=/dev/null; fi; { ${command}${wrapperTail}`;
|
|
11977
|
+
}
|
|
11978
|
+
function isClaudeLiveBashWrappedCommand(command) {
|
|
11979
|
+
return wrapperHeadPattern.test(command) && command.endsWith(wrapperTail);
|
|
11980
|
+
}
|
|
11981
|
+
function claudeLiveBashOriginalCommand(command) {
|
|
11982
|
+
const head = command.match(wrapperHeadPattern)?.[0];
|
|
11983
|
+
if (head === void 0 || !command.endsWith(wrapperTail)) {
|
|
11984
|
+
return command;
|
|
11985
|
+
}
|
|
11986
|
+
return command.slice(head.length, command.length - wrapperTail.length);
|
|
11987
|
+
}
|
|
11988
|
+
function claudeLiveBashCaptureEnabled(env) {
|
|
11989
|
+
const value = env.LINZUMI_CLAUDE_LIVE_BASH?.trim().toLowerCase();
|
|
11990
|
+
return !(value === "0" || value === "false" || value === "off" || value === "no");
|
|
11991
|
+
}
|
|
11992
|
+
function createClaudeCodeLiveBashCapture(host) {
|
|
11993
|
+
const pollIntervalMs = host.pollIntervalMs ?? defaultPollIntervalMs;
|
|
11994
|
+
const maxEmittedBytes = host.maxEmittedBytesPerTool ?? defaultMaxEmittedBytesPerTool;
|
|
11995
|
+
const tails = /* @__PURE__ */ new Map();
|
|
11996
|
+
let closed = false;
|
|
11997
|
+
const stopTail = (toolUseId) => {
|
|
11998
|
+
const tail = tails.get(toolUseId);
|
|
11999
|
+
if (tail === void 0) {
|
|
12000
|
+
return;
|
|
12001
|
+
}
|
|
12002
|
+
tails.delete(toolUseId);
|
|
12003
|
+
if (tail.timer !== void 0) {
|
|
12004
|
+
clearInterval(tail.timer);
|
|
12005
|
+
tail.timer = void 0;
|
|
12006
|
+
}
|
|
12007
|
+
try {
|
|
12008
|
+
rmSync(tail.file, { force: true });
|
|
12009
|
+
} catch (_error) {
|
|
12010
|
+
}
|
|
12011
|
+
};
|
|
12012
|
+
const pollTail = async (toolUseId, tail) => {
|
|
12013
|
+
if (tail.reading) {
|
|
12014
|
+
return;
|
|
12015
|
+
}
|
|
12016
|
+
tail.reading = true;
|
|
12017
|
+
try {
|
|
12018
|
+
const stat2 = await fsPromises.stat(tail.file);
|
|
12019
|
+
if (stat2.size <= tail.offset) {
|
|
12020
|
+
return;
|
|
12021
|
+
}
|
|
12022
|
+
const length = Math.min(
|
|
12023
|
+
stat2.size - tail.offset,
|
|
12024
|
+
maxReadBytesPerPoll,
|
|
12025
|
+
maxEmittedBytes - tail.emittedBytes
|
|
12026
|
+
);
|
|
12027
|
+
if (length <= 0) {
|
|
12028
|
+
stopTail(toolUseId);
|
|
12029
|
+
return;
|
|
12030
|
+
}
|
|
12031
|
+
const handle = await fsPromises.open(tail.file, "r");
|
|
12032
|
+
try {
|
|
12033
|
+
const buffer = Buffer.alloc(length);
|
|
12034
|
+
const { bytesRead } = await handle.read(buffer, 0, length, tail.offset);
|
|
12035
|
+
if (bytesRead <= 0) {
|
|
12036
|
+
return;
|
|
12037
|
+
}
|
|
12038
|
+
tail.offset += bytesRead;
|
|
12039
|
+
tail.emittedBytes += bytesRead;
|
|
12040
|
+
const delta = tail.decoder.write(buffer.subarray(0, bytesRead));
|
|
12041
|
+
if (delta !== "" && tails.get(toolUseId) === tail) {
|
|
12042
|
+
host.onOutputDelta(toolUseId, delta);
|
|
12043
|
+
}
|
|
12044
|
+
if (tail.emittedBytes >= maxEmittedBytes) {
|
|
12045
|
+
host.log?.("claude_live_bash.output_budget_exhausted", {
|
|
12046
|
+
tool_use_id: toolUseId,
|
|
12047
|
+
emitted_bytes: tail.emittedBytes
|
|
12048
|
+
});
|
|
12049
|
+
stopTail(toolUseId);
|
|
12050
|
+
}
|
|
12051
|
+
} finally {
|
|
12052
|
+
await handle.close();
|
|
12053
|
+
}
|
|
12054
|
+
} catch (error) {
|
|
12055
|
+
if (tails.get(toolUseId) === tail) {
|
|
12056
|
+
host.log?.("claude_live_bash.tail_read_failed", {
|
|
12057
|
+
tool_use_id: toolUseId,
|
|
12058
|
+
message: error instanceof Error ? error.message : String(error)
|
|
12059
|
+
});
|
|
12060
|
+
stopTail(toolUseId);
|
|
12061
|
+
}
|
|
12062
|
+
} finally {
|
|
12063
|
+
tail.reading = false;
|
|
12064
|
+
}
|
|
12065
|
+
};
|
|
12066
|
+
const startTail = (toolUseId, file) => {
|
|
12067
|
+
stopTail(toolUseId);
|
|
12068
|
+
const tail = {
|
|
12069
|
+
file,
|
|
12070
|
+
decoder: new StringDecoder("utf8"),
|
|
12071
|
+
offset: 0,
|
|
12072
|
+
emittedBytes: 0,
|
|
12073
|
+
reading: false,
|
|
12074
|
+
timer: void 0
|
|
12075
|
+
};
|
|
12076
|
+
tails.set(toolUseId, tail);
|
|
12077
|
+
const timer = setInterval(() => {
|
|
12078
|
+
void pollTail(toolUseId, tail);
|
|
12079
|
+
}, pollIntervalMs);
|
|
12080
|
+
timer.unref?.();
|
|
12081
|
+
tail.timer = timer;
|
|
12082
|
+
};
|
|
12083
|
+
const wrapToolInput = (toolUseId, toolInput) => {
|
|
12084
|
+
if (closed) {
|
|
12085
|
+
return void 0;
|
|
12086
|
+
}
|
|
12087
|
+
const command = toolInput.command;
|
|
12088
|
+
if (typeof command !== "string" || command.trim() === "" || // Background commands are polled by the model itself (TaskOutput);
|
|
12089
|
+
// the foreground live stream does not apply.
|
|
12090
|
+
toolInput.run_in_background === true || // Defensive: never double-wrap (e.g. a model echoing a wrapped
|
|
12091
|
+
// command back from its own transcript).
|
|
12092
|
+
isClaudeLiveBashWrappedCommand(command)) {
|
|
12093
|
+
return void 0;
|
|
12094
|
+
}
|
|
12095
|
+
const file = join6(
|
|
12096
|
+
host.captureDir,
|
|
12097
|
+
`${toolUseId.replaceAll(/[^\w-]/g, "_")}.out`
|
|
12098
|
+
);
|
|
12099
|
+
try {
|
|
12100
|
+
mkdirSync2(host.captureDir, { recursive: true });
|
|
12101
|
+
writeFileSync(file, "");
|
|
12102
|
+
} catch (error) {
|
|
12103
|
+
host.log?.("claude_live_bash.capture_file_failed", {
|
|
12104
|
+
tool_use_id: toolUseId,
|
|
12105
|
+
message: error instanceof Error ? error.message : String(error)
|
|
12106
|
+
});
|
|
12107
|
+
return void 0;
|
|
12108
|
+
}
|
|
12109
|
+
startTail(toolUseId, file);
|
|
12110
|
+
return {
|
|
12111
|
+
...toolInput,
|
|
12112
|
+
command: claudeLiveBashWrappedCommand(command, file)
|
|
12113
|
+
};
|
|
12114
|
+
};
|
|
12115
|
+
const preToolUseHook = async (input) => {
|
|
12116
|
+
const passthrough = { continue: true };
|
|
12117
|
+
if (typeof input !== "object" || input === null) {
|
|
12118
|
+
return passthrough;
|
|
12119
|
+
}
|
|
12120
|
+
const hookInput = input;
|
|
12121
|
+
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
|
|
12122
|
+
// auto-allows and the rewrite cannot perturb a permission decision.
|
|
12123
|
+
// In ask-capable modes, PreToolUse updatedInput propagates into rule
|
|
12124
|
+
// matching and sandbox auto-allow analysis (verified empirically
|
|
12125
|
+
// 2026-06-12: a sandbox-auto-allowed `false` started prompting once
|
|
12126
|
+
// wrapped), so those modes wrap at canUseTool-allow time instead
|
|
12127
|
+
// (wrapApprovedTool below) - the command was already being asked, so
|
|
12128
|
+
// wrapping there adds zero prompts.
|
|
12129
|
+
hookInput.permission_mode !== "bypassPermissions") {
|
|
12130
|
+
return passthrough;
|
|
12131
|
+
}
|
|
12132
|
+
const updatedInput = wrapToolInput(
|
|
12133
|
+
hookInput.tool_use_id,
|
|
12134
|
+
hookInput.tool_input
|
|
12135
|
+
);
|
|
12136
|
+
if (updatedInput === void 0) {
|
|
12137
|
+
return passthrough;
|
|
12138
|
+
}
|
|
12139
|
+
return {
|
|
12140
|
+
continue: true,
|
|
12141
|
+
hookSpecificOutput: {
|
|
12142
|
+
hookEventName: "PreToolUse",
|
|
12143
|
+
updatedInput
|
|
12144
|
+
}
|
|
12145
|
+
};
|
|
12146
|
+
};
|
|
12147
|
+
return {
|
|
12148
|
+
hookMatchers: [{ matcher: "Bash", hooks: [preToolUseHook] }],
|
|
12149
|
+
wrapApprovedTool: wrapToolInput,
|
|
12150
|
+
settleTool: stopTail,
|
|
12151
|
+
settleAll: () => {
|
|
12152
|
+
for (const toolUseId of [...tails.keys()]) {
|
|
12153
|
+
stopTail(toolUseId);
|
|
12154
|
+
}
|
|
12155
|
+
},
|
|
12156
|
+
close: () => {
|
|
12157
|
+
closed = true;
|
|
12158
|
+
for (const toolUseId of [...tails.keys()]) {
|
|
12159
|
+
stopTail(toolUseId);
|
|
12160
|
+
}
|
|
12161
|
+
try {
|
|
12162
|
+
rmSync(host.captureDir, { recursive: true, force: true });
|
|
12163
|
+
} catch (_error) {
|
|
12164
|
+
}
|
|
12165
|
+
}
|
|
12166
|
+
};
|
|
12167
|
+
}
|
|
12168
|
+
var wrapperHeadPattern, wrapperTail, defaultPollIntervalMs, defaultMaxEmittedBytesPerTool, maxReadBytesPerPoll;
|
|
12169
|
+
var init_claudeCodeLiveBashOutput = __esm({
|
|
12170
|
+
"src/claudeCodeLiveBashOutput.ts"() {
|
|
12171
|
+
"use strict";
|
|
12172
|
+
wrapperHeadPattern = /^__lz_live_out='(?:[^']|'\\'')*'; if ! : >> "\$__lz_live_out" 2>\/dev\/null; then __lz_live_out=\/dev\/null; fi; \{ /;
|
|
12173
|
+
wrapperTail = '\n} > >(tee -a -- "$__lz_live_out") 2> >(tee -a -- "$__lz_live_out" >&2)';
|
|
12174
|
+
defaultPollIntervalMs = 200;
|
|
12175
|
+
defaultMaxEmittedBytesPerTool = 262144;
|
|
12176
|
+
maxReadBytesPerPoll = 65536;
|
|
12177
|
+
}
|
|
12178
|
+
});
|
|
12179
|
+
|
|
11948
12180
|
// src/claudeCodeSession.ts
|
|
11949
12181
|
import { existsSync as existsSync4, readFileSync as readFileSync5 } from "node:fs";
|
|
11950
12182
|
import { homedir as homedir5 } from "node:os";
|
|
11951
|
-
import { join as
|
|
12183
|
+
import { join as join7 } from "node:path";
|
|
11952
12184
|
function claudeCodeSettingSources() {
|
|
11953
12185
|
return ["user", "project", "local"];
|
|
11954
12186
|
}
|
|
12187
|
+
function claudeCodeTokenUsageSummaryText(usage) {
|
|
12188
|
+
const cached = usage.cacheReadInputTokens === void 0 && usage.cacheCreationInputTokens === void 0 ? void 0 : (usage.cacheReadInputTokens ?? 0) + (usage.cacheCreationInputTokens ?? 0);
|
|
12189
|
+
const parts = [
|
|
12190
|
+
usage.inputTokens === void 0 ? void 0 : `${usage.inputTokens} in`,
|
|
12191
|
+
usage.outputTokens === void 0 ? void 0 : `${usage.outputTokens} out`,
|
|
12192
|
+
cached === void 0 ? void 0 : `${cached} cached`,
|
|
12193
|
+
usage.totalCostUsd === void 0 ? void 0 : `$${usage.totalCostUsd.toFixed(4)}`
|
|
12194
|
+
].filter((part) => part !== void 0);
|
|
12195
|
+
return parts.length === 0 ? void 0 : parts.join(" / ");
|
|
12196
|
+
}
|
|
12197
|
+
function createClaudeCodeStreamUsageTracker() {
|
|
12198
|
+
const completed = {
|
|
12199
|
+
inputTokens: 0,
|
|
12200
|
+
outputTokens: 0,
|
|
12201
|
+
cacheCreationInputTokens: 0,
|
|
12202
|
+
cacheReadInputTokens: 0
|
|
12203
|
+
};
|
|
12204
|
+
let current;
|
|
12205
|
+
let lastEmittedKey;
|
|
12206
|
+
const totalsFromUsage = (usage, previous) => ({
|
|
12207
|
+
inputTokens: integerValue(usage.input_tokens) ?? previous?.inputTokens ?? 0,
|
|
12208
|
+
outputTokens: integerValue(usage.output_tokens) ?? previous?.outputTokens ?? 0,
|
|
12209
|
+
cacheCreationInputTokens: integerValue(usage.cache_creation_input_tokens) ?? previous?.cacheCreationInputTokens ?? 0,
|
|
12210
|
+
cacheReadInputTokens: integerValue(usage.cache_read_input_tokens) ?? previous?.cacheReadInputTokens ?? 0
|
|
12211
|
+
});
|
|
12212
|
+
const snapshotIfChanged = () => {
|
|
12213
|
+
const inputTokens = completed.inputTokens + (current?.inputTokens ?? 0);
|
|
12214
|
+
const outputTokens = completed.outputTokens + (current?.outputTokens ?? 0);
|
|
12215
|
+
const cacheCreationInputTokens = completed.cacheCreationInputTokens + (current?.cacheCreationInputTokens ?? 0);
|
|
12216
|
+
const cacheReadInputTokens = completed.cacheReadInputTokens + (current?.cacheReadInputTokens ?? 0);
|
|
12217
|
+
const key = `${inputTokens}:${outputTokens}:${cacheCreationInputTokens}:${cacheReadInputTokens}`;
|
|
12218
|
+
if (key === lastEmittedKey) {
|
|
12219
|
+
return void 0;
|
|
12220
|
+
}
|
|
12221
|
+
lastEmittedKey = key;
|
|
12222
|
+
return {
|
|
12223
|
+
inputTokens,
|
|
12224
|
+
outputTokens,
|
|
12225
|
+
cacheCreationInputTokens,
|
|
12226
|
+
cacheReadInputTokens,
|
|
12227
|
+
totalCostUsd: void 0
|
|
12228
|
+
};
|
|
12229
|
+
};
|
|
12230
|
+
return {
|
|
12231
|
+
observeStreamEvent: (event) => {
|
|
12232
|
+
switch (stringValue(event?.type)) {
|
|
12233
|
+
case "message_start": {
|
|
12234
|
+
const usage = objectValue(objectValue(event?.message)?.usage);
|
|
12235
|
+
if (usage === void 0) {
|
|
12236
|
+
return void 0;
|
|
12237
|
+
}
|
|
12238
|
+
if (current !== void 0) {
|
|
12239
|
+
completed.inputTokens += current.inputTokens;
|
|
12240
|
+
completed.outputTokens += current.outputTokens;
|
|
12241
|
+
completed.cacheCreationInputTokens += current.cacheCreationInputTokens;
|
|
12242
|
+
completed.cacheReadInputTokens += current.cacheReadInputTokens;
|
|
12243
|
+
}
|
|
12244
|
+
current = totalsFromUsage(usage, void 0);
|
|
12245
|
+
return snapshotIfChanged();
|
|
12246
|
+
}
|
|
12247
|
+
case "message_delta": {
|
|
12248
|
+
const usage = objectValue(event?.usage);
|
|
12249
|
+
if (usage === void 0) {
|
|
12250
|
+
return void 0;
|
|
12251
|
+
}
|
|
12252
|
+
current = totalsFromUsage(usage, current);
|
|
12253
|
+
return snapshotIfChanged();
|
|
12254
|
+
}
|
|
12255
|
+
default:
|
|
12256
|
+
return void 0;
|
|
12257
|
+
}
|
|
12258
|
+
}
|
|
12259
|
+
};
|
|
12260
|
+
}
|
|
11955
12261
|
function parseClaudeCodeRateLimitInfo(info) {
|
|
11956
12262
|
if (info === void 0) {
|
|
11957
12263
|
return void 0;
|
|
@@ -12051,7 +12357,7 @@ async function probeClaudeCodeAvailability(args) {
|
|
|
12051
12357
|
}
|
|
12052
12358
|
}
|
|
12053
12359
|
function hasClaudeCodeAuthHint(env, deps) {
|
|
12054
|
-
const configDir = env.CLAUDE_CONFIG_DIR ??
|
|
12360
|
+
const configDir = env.CLAUDE_CONFIG_DIR ?? join7(deps.homeDir, ".claude");
|
|
12055
12361
|
return hasAnthropicCredentialEnv(env) || hasClaudeCloudProviderEnv(env) || hasClaudeCodeFileCredential(configDir, deps) || hasClaudeCodeApiKeyHelper(configDir, deps) || hasMacClaudeCodeKeychainAnchor(deps);
|
|
12056
12362
|
}
|
|
12057
12363
|
function claudeCodePolicyDeferHooks() {
|
|
@@ -12086,14 +12392,14 @@ function hasClaudeCloudProviderEnv(env) {
|
|
|
12086
12392
|
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
12393
|
}
|
|
12088
12394
|
function hasClaudeCodeFileCredential(configDir, deps) {
|
|
12089
|
-
return deps.fileExists(
|
|
12395
|
+
return deps.fileExists(join7(configDir, ".credentials.json")) || deps.fileExists(join7(configDir, ".claude.json")) || deps.fileExists(join7(deps.homeDir, ".claude.json"));
|
|
12090
12396
|
}
|
|
12091
12397
|
function hasClaudeCodeApiKeyHelper(configDir, deps) {
|
|
12092
12398
|
return [
|
|
12093
|
-
|
|
12094
|
-
|
|
12095
|
-
|
|
12096
|
-
|
|
12399
|
+
join7(configDir, "settings.json"),
|
|
12400
|
+
join7(configDir, "settings.local.json"),
|
|
12401
|
+
join7(deps.cwd, ".claude", "settings.json"),
|
|
12402
|
+
join7(deps.cwd, ".claude", "settings.local.json")
|
|
12097
12403
|
].some((path2) => settingsFileHasApiKeyHelper(path2, deps));
|
|
12098
12404
|
}
|
|
12099
12405
|
function settingsFileHasApiKeyHelper(path2, deps) {
|
|
@@ -12113,9 +12419,9 @@ function hasMacClaudeCodeKeychainAnchor(deps) {
|
|
|
12113
12419
|
return false;
|
|
12114
12420
|
}
|
|
12115
12421
|
return [
|
|
12116
|
-
|
|
12117
|
-
|
|
12118
|
-
|
|
12422
|
+
join7(deps.homeDir, "Library", "Application Support", "claude-cli-nodejs"),
|
|
12423
|
+
join7(deps.homeDir, "Library", "Application Support", "Claude"),
|
|
12424
|
+
join7(deps.homeDir, "Library", "Preferences", "claude-cli-nodejs")
|
|
12119
12425
|
].some((path2) => deps.fileExists(path2));
|
|
12120
12426
|
}
|
|
12121
12427
|
function readTextFileIfPresent(path2) {
|
|
@@ -12136,6 +12442,7 @@ async function startClaudeCodeSession(options) {
|
|
|
12136
12442
|
startedSessionIds: /* @__PURE__ */ new Set(),
|
|
12137
12443
|
completedTurnCount: 0
|
|
12138
12444
|
};
|
|
12445
|
+
const streamUsageTracker = createClaudeCodeStreamUsageTracker();
|
|
12139
12446
|
for await (const message of runner(options)) {
|
|
12140
12447
|
state.sessionId = state.sessionId ?? extractClaudeSessionId(message);
|
|
12141
12448
|
const sessionId = extractClaudeSessionId(message) ?? state.sessionId;
|
|
@@ -12143,7 +12450,11 @@ async function startClaudeCodeSession(options) {
|
|
|
12143
12450
|
state.startedSessionIds.add(sessionId);
|
|
12144
12451
|
await options.onTranscriptEvent?.({ type: "session_started", sessionId });
|
|
12145
12452
|
}
|
|
12146
|
-
for (const event of transcriptEventsForClaudeMessage(
|
|
12453
|
+
for (const event of transcriptEventsForClaudeMessage(
|
|
12454
|
+
message,
|
|
12455
|
+
sessionId,
|
|
12456
|
+
streamUsageTracker
|
|
12457
|
+
)) {
|
|
12147
12458
|
if (event.type === "assistant_message") {
|
|
12148
12459
|
recordClaudeAssistantAggregate(state, event);
|
|
12149
12460
|
}
|
|
@@ -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.84-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
|
}
|
|
@@ -19730,8 +20131,8 @@ var init_runnerConsoleReporter = __esm({
|
|
|
19730
20131
|
});
|
|
19731
20132
|
|
|
19732
20133
|
// src/telemetry.ts
|
|
19733
|
-
import { mkdirSync as
|
|
19734
|
-
import { dirname as dirname10, basename as basename7, join as
|
|
20134
|
+
import { mkdirSync as mkdirSync10, readFileSync as readFileSync13, writeFileSync as writeFileSync8 } from "node:fs";
|
|
20135
|
+
import { dirname as dirname10, basename as basename7, join as join17 } from "node:path";
|
|
19735
20136
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
19736
20137
|
function peekFlagValue(args, flags) {
|
|
19737
20138
|
for (let index = 0; index < args.length; index += 1) {
|
|
@@ -19770,12 +20171,12 @@ function telemetryBaseUrl(apiUrl, env = process.env) {
|
|
|
19770
20171
|
}
|
|
19771
20172
|
}
|
|
19772
20173
|
function telemetryInstallIdPath(env = process.env) {
|
|
19773
|
-
return
|
|
20174
|
+
return join17(dirname10(localConfigPath(env)), "install-id");
|
|
19774
20175
|
}
|
|
19775
20176
|
function ensureTelemetryInstallId(env = process.env) {
|
|
19776
20177
|
const path2 = telemetryInstallIdPath(env);
|
|
19777
20178
|
try {
|
|
19778
|
-
const existing =
|
|
20179
|
+
const existing = readFileSync13(path2, "utf8").trim();
|
|
19779
20180
|
if (existing !== "" && existing.length <= 128) {
|
|
19780
20181
|
return existing;
|
|
19781
20182
|
}
|
|
@@ -19783,8 +20184,8 @@ function ensureTelemetryInstallId(env = process.env) {
|
|
|
19783
20184
|
}
|
|
19784
20185
|
const installId = randomUUID3();
|
|
19785
20186
|
try {
|
|
19786
|
-
|
|
19787
|
-
|
|
20187
|
+
mkdirSync10(dirname10(path2), { recursive: true });
|
|
20188
|
+
writeFileSync8(path2, `${installId}
|
|
19788
20189
|
`, { mode: 384 });
|
|
19789
20190
|
} catch {
|
|
19790
20191
|
}
|
|
@@ -19971,17 +20372,17 @@ var init_linzumiApiClient = __esm({
|
|
|
19971
20372
|
});
|
|
19972
20373
|
|
|
19973
20374
|
// src/authCache.ts
|
|
19974
|
-
import { existsSync as existsSync11, mkdirSync as
|
|
19975
|
-
import { homedir as
|
|
19976
|
-
import { dirname as dirname11, join as
|
|
20375
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync11, readFileSync as readFileSync14, writeFileSync as writeFileSync9 } from "node:fs";
|
|
20376
|
+
import { homedir as homedir12 } from "node:os";
|
|
20377
|
+
import { dirname as dirname11, join as join18 } from "node:path";
|
|
19977
20378
|
function defaultAuthFilePath() {
|
|
19978
|
-
return
|
|
20379
|
+
return join18(homedir12(), ".linzumi", "auth.json");
|
|
19979
20380
|
}
|
|
19980
20381
|
function readCachedLocalRunnerToken(kandanUrl, authFilePath = defaultAuthFilePath()) {
|
|
19981
20382
|
if (!existsSync11(authFilePath)) {
|
|
19982
20383
|
return void 0;
|
|
19983
20384
|
}
|
|
19984
|
-
const authFile = parseAuthFile(
|
|
20385
|
+
const authFile = parseAuthFile(readFileSync14(authFilePath, "utf8"));
|
|
19985
20386
|
const kandanBaseUrl = kandanHttpBaseUrl(kandanUrl);
|
|
19986
20387
|
const entry = authFile.local_codex_runner?.[kandanBaseUrl];
|
|
19987
20388
|
if (entry === void 0 || entry.access_token.trim() === "") {
|
|
@@ -20003,7 +20404,7 @@ function readPersonalAgentDelegationToken(authFilePath) {
|
|
|
20003
20404
|
`missing personal-agent delegation auth file: ${authFilePath}`
|
|
20004
20405
|
);
|
|
20005
20406
|
}
|
|
20006
|
-
const authFile = parseAuthFile(
|
|
20407
|
+
const authFile = parseAuthFile(readFileSync14(authFilePath, "utf8"));
|
|
20007
20408
|
const entry = authFile.personal_agent_delegation;
|
|
20008
20409
|
if (entry === void 0 || entry.access_token.trim() === "") {
|
|
20009
20410
|
throw new Error(
|
|
@@ -20021,7 +20422,7 @@ function readPersonalAgentDelegationToken(authFilePath) {
|
|
|
20021
20422
|
}
|
|
20022
20423
|
function writeCachedLocalRunnerToken(args) {
|
|
20023
20424
|
const authFilePath = args.authFilePath ?? defaultAuthFilePath();
|
|
20024
|
-
const existing = existsSync11(authFilePath) ? parseAuthFile(
|
|
20425
|
+
const existing = existsSync11(authFilePath) ? parseAuthFile(readFileSync14(authFilePath, "utf8")) : { version: 1 };
|
|
20025
20426
|
const kandanBaseUrl = kandanHttpBaseUrl(args.kandanUrl);
|
|
20026
20427
|
const issuedAt = /* @__PURE__ */ new Date();
|
|
20027
20428
|
const expiresAt = args.expiresInSeconds === void 0 ? void 0 : new Date(
|
|
@@ -20039,8 +20440,8 @@ function writeCachedLocalRunnerToken(args) {
|
|
|
20039
20440
|
}
|
|
20040
20441
|
}
|
|
20041
20442
|
};
|
|
20042
|
-
|
|
20043
|
-
|
|
20443
|
+
mkdirSync11(dirname11(authFilePath), { recursive: true });
|
|
20444
|
+
writeFileSync9(authFilePath, `${JSON.stringify(next, null, 2)}
|
|
20044
20445
|
`, "utf8");
|
|
20045
20446
|
return {
|
|
20046
20447
|
accessToken: args.accessToken,
|
|
@@ -20485,9 +20886,9 @@ var init_threadCodexWorkerIpc = __esm({
|
|
|
20485
20886
|
|
|
20486
20887
|
// src/signupTaskSuggestions.ts
|
|
20487
20888
|
import { spawn as spawn7 } from "node:child_process";
|
|
20488
|
-
import { mkdtempSync as mkdtempSync3, readFileSync as
|
|
20889
|
+
import { mkdtempSync as mkdtempSync3, readFileSync as readFileSync15, rmSync as rmSync4, writeFileSync as writeFileSync10 } from "node:fs";
|
|
20489
20890
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
20490
|
-
import { join as
|
|
20891
|
+
import { join as join19 } from "node:path";
|
|
20491
20892
|
async function suggestSignupTasksWithCodex(args) {
|
|
20492
20893
|
const attempts = 2;
|
|
20493
20894
|
let previousResponse;
|
|
@@ -20509,11 +20910,11 @@ async function suggestSignupTasksWithCodex(args) {
|
|
|
20509
20910
|
);
|
|
20510
20911
|
}
|
|
20511
20912
|
async function runCodexTaskSuggestion(args) {
|
|
20512
|
-
const tempRoot = mkdtempSync3(
|
|
20513
|
-
const schemaPath =
|
|
20514
|
-
const outputPath =
|
|
20913
|
+
const tempRoot = mkdtempSync3(join19(tmpdir2(), "linzumi-signup-codex-tasks-"));
|
|
20914
|
+
const schemaPath = join19(tempRoot, "task-suggestions.schema.json");
|
|
20915
|
+
const outputPath = join19(tempRoot, "task-suggestions.json");
|
|
20515
20916
|
const prompt = taskSuggestionPrompt(args.previousResponse);
|
|
20516
|
-
|
|
20917
|
+
writeFileSync10(
|
|
20517
20918
|
schemaPath,
|
|
20518
20919
|
`${JSON.stringify(taskSuggestionJsonSchema(), null, 2)}
|
|
20519
20920
|
`,
|
|
@@ -20530,9 +20931,9 @@ async function runCodexTaskSuggestion(args) {
|
|
|
20530
20931
|
prompt
|
|
20531
20932
|
})
|
|
20532
20933
|
);
|
|
20533
|
-
return
|
|
20934
|
+
return readFileSync15(outputPath, "utf8");
|
|
20534
20935
|
} finally {
|
|
20535
|
-
|
|
20936
|
+
rmSync4(tempRoot, { recursive: true, force: true });
|
|
20536
20937
|
}
|
|
20537
20938
|
}
|
|
20538
20939
|
function codexTaskSuggestionProcess(args) {
|
|
@@ -20979,25 +21380,25 @@ import { createHash as createHash5, randomUUID as randomUUID4 } from "node:crypt
|
|
|
20979
21380
|
import {
|
|
20980
21381
|
chmodSync as chmodSync2,
|
|
20981
21382
|
lstatSync,
|
|
20982
|
-
mkdirSync as
|
|
21383
|
+
mkdirSync as mkdirSync12,
|
|
20983
21384
|
mkdtempSync as mkdtempSync4,
|
|
20984
21385
|
readdirSync as readdirSync4,
|
|
20985
|
-
readFileSync as
|
|
21386
|
+
readFileSync as readFileSync16,
|
|
20986
21387
|
realpathSync as realpathSync6,
|
|
20987
21388
|
renameSync as renameSync3,
|
|
20988
|
-
rmSync as
|
|
21389
|
+
rmSync as rmSync5,
|
|
20989
21390
|
statSync as statSync3,
|
|
20990
|
-
writeFileSync as
|
|
21391
|
+
writeFileSync as writeFileSync11
|
|
20991
21392
|
} from "node:fs";
|
|
20992
21393
|
import { readFile as readFile2 } from "node:fs/promises";
|
|
20993
21394
|
import { createServer as createServer3 } from "node:http";
|
|
20994
|
-
import { homedir as
|
|
21395
|
+
import { homedir as homedir13, hostname as hostname2, tmpdir as tmpdir3 } from "node:os";
|
|
20995
21396
|
import {
|
|
20996
21397
|
basename as basename8,
|
|
20997
21398
|
dirname as dirname13,
|
|
20998
21399
|
extname as extname2,
|
|
20999
21400
|
isAbsolute as isAbsolute5,
|
|
21000
|
-
join as
|
|
21401
|
+
join as join20,
|
|
21001
21402
|
resolve as resolve8
|
|
21002
21403
|
} from "node:path";
|
|
21003
21404
|
async function runLocalCodexRunner(options) {
|
|
@@ -21243,6 +21644,9 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
|
|
|
21243
21644
|
defaultAgentProvider: "codex",
|
|
21244
21645
|
startInstance: allowedCwds.value.length > 0,
|
|
21245
21646
|
durableClaudeSessionStore: true,
|
|
21647
|
+
// Honest capability: no faithful Claude Code rewind exists yet; the
|
|
21648
|
+
// rewind_thread control responds with a clean rejection (spec:
|
|
21649
|
+
// plans/2026-06-12-claude-steer-rewind-parity-note.md item B).
|
|
21246
21650
|
claudeCodeCheckpointRewind: false,
|
|
21247
21651
|
allowedCwds: allowedCwds.value,
|
|
21248
21652
|
missingAllowedCwds: missingAllowedCwds.value,
|
|
@@ -22333,13 +22737,14 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
|
|
|
22333
22737
|
if (workspaceSlug === void 0 || channelSlug === void 0 || kandanThreadId === void 0) {
|
|
22334
22738
|
return void 0;
|
|
22335
22739
|
}
|
|
22336
|
-
const
|
|
22337
|
-
|
|
22740
|
+
const providerResolution = resolveControlCodexModelProvider(control);
|
|
22741
|
+
const providerResolutionError = codexModelProviderResolutionError(providerResolution);
|
|
22742
|
+
if (providerResolutionError !== void 0) {
|
|
22338
22743
|
return {
|
|
22339
22744
|
instanceId,
|
|
22340
22745
|
controlType: control.type,
|
|
22341
22746
|
ok: false,
|
|
22342
|
-
error:
|
|
22747
|
+
error: providerResolutionError,
|
|
22343
22748
|
kandanThreadId,
|
|
22344
22749
|
cwd
|
|
22345
22750
|
};
|
|
@@ -22954,14 +23359,14 @@ function commanderOutboxPersistDir() {
|
|
|
22954
23359
|
if (override !== void 0 && override !== "") {
|
|
22955
23360
|
return override;
|
|
22956
23361
|
}
|
|
22957
|
-
return
|
|
23362
|
+
return join20(homedir13(), ".linzumi", "commander-outbox");
|
|
22958
23363
|
}
|
|
22959
23364
|
function controlCursorStorePath(runnerId) {
|
|
22960
23365
|
const sanitized = runnerId.replace(/[^A-Za-z0-9._-]+/g, "-").replace(/^[-.]+|[-.]+$/g, "").slice(0, 80);
|
|
22961
23366
|
const digest = createHash5("sha256").update(runnerId).digest("hex").slice(0, 8);
|
|
22962
23367
|
const stem = sanitized === "" ? "runner" : sanitized;
|
|
22963
|
-
return
|
|
22964
|
-
|
|
23368
|
+
return join20(
|
|
23369
|
+
homedir13(),
|
|
22965
23370
|
".linzumi",
|
|
22966
23371
|
"control-cursors",
|
|
22967
23372
|
`${stem}.${digest}.json`
|
|
@@ -22971,8 +23376,8 @@ function appliedStartTurnStorePath(runnerId) {
|
|
|
22971
23376
|
const sanitized = runnerId.replace(/[^A-Za-z0-9._-]+/g, "-").replace(/^[-.]+|[-.]+$/g, "").slice(0, 80);
|
|
22972
23377
|
const digest = createHash5("sha256").update(runnerId).digest("hex").slice(0, 8);
|
|
22973
23378
|
const stem = sanitized === "" ? "runner" : sanitized;
|
|
22974
|
-
return
|
|
22975
|
-
|
|
23379
|
+
return join20(
|
|
23380
|
+
homedir13(),
|
|
22976
23381
|
".linzumi",
|
|
22977
23382
|
"control-cursors",
|
|
22978
23383
|
`${stem}.${digest}.start-turn.json`
|
|
@@ -23094,9 +23499,9 @@ function createControlCursorFileStore(path2, log2, options) {
|
|
|
23094
23499
|
}
|
|
23095
23500
|
dirty = false;
|
|
23096
23501
|
try {
|
|
23097
|
-
|
|
23502
|
+
mkdirSync12(dirname13(path2), { recursive: true });
|
|
23098
23503
|
const tmpPath = `${path2}.tmp`;
|
|
23099
|
-
|
|
23504
|
+
writeFileSync11(
|
|
23100
23505
|
tmpPath,
|
|
23101
23506
|
`${JSON.stringify({
|
|
23102
23507
|
...epoch === void 0 ? {} : { [controlCursorEpochKey]: epoch },
|
|
@@ -23204,7 +23609,7 @@ function readControlCursorFile(path2, log2) {
|
|
|
23204
23609
|
const cursors = /* @__PURE__ */ new Map();
|
|
23205
23610
|
let raw;
|
|
23206
23611
|
try {
|
|
23207
|
-
raw =
|
|
23612
|
+
raw = readFileSync16(path2, "utf8");
|
|
23208
23613
|
} catch (error) {
|
|
23209
23614
|
if (!isErrnoCode2(error, "ENOENT")) {
|
|
23210
23615
|
log2("control_cursor_store.read_failed", {
|
|
@@ -23798,18 +24203,18 @@ async function applyControl(codex, kandan, topic, instanceId, options, agentProv
|
|
|
23798
24203
|
return delegated;
|
|
23799
24204
|
}
|
|
23800
24205
|
if (agentProvider === "codex") {
|
|
23801
|
-
const
|
|
24206
|
+
const providerControlError = codexModelProviderControlError(
|
|
23802
24207
|
options,
|
|
23803
24208
|
control
|
|
23804
24209
|
);
|
|
23805
|
-
if (
|
|
24210
|
+
if (providerControlError !== void 0) {
|
|
23806
24211
|
try {
|
|
23807
24212
|
await publishStartInstanceMessageState(
|
|
23808
24213
|
kandan,
|
|
23809
24214
|
topic,
|
|
23810
24215
|
control,
|
|
23811
24216
|
"failed",
|
|
23812
|
-
|
|
24217
|
+
providerControlError,
|
|
23813
24218
|
{ instanceId }
|
|
23814
24219
|
);
|
|
23815
24220
|
} catch (error) {
|
|
@@ -23821,7 +24226,7 @@ async function applyControl(codex, kandan, topic, instanceId, options, agentProv
|
|
|
23821
24226
|
instanceId,
|
|
23822
24227
|
controlType: control.type,
|
|
23823
24228
|
ok: false,
|
|
23824
|
-
error:
|
|
24229
|
+
error: providerControlError
|
|
23825
24230
|
};
|
|
23826
24231
|
}
|
|
23827
24232
|
}
|
|
@@ -23969,16 +24374,16 @@ async function applyControl(codex, kandan, topic, instanceId, options, agentProv
|
|
|
23969
24374
|
return delegated;
|
|
23970
24375
|
}
|
|
23971
24376
|
if (agentProvider === "codex") {
|
|
23972
|
-
const
|
|
24377
|
+
const providerControlError = codexModelProviderControlError(
|
|
23973
24378
|
options,
|
|
23974
24379
|
control
|
|
23975
24380
|
);
|
|
23976
|
-
if (
|
|
24381
|
+
if (providerControlError !== void 0) {
|
|
23977
24382
|
return {
|
|
23978
24383
|
instanceId,
|
|
23979
24384
|
controlType: control.type,
|
|
23980
24385
|
ok: false,
|
|
23981
|
-
error:
|
|
24386
|
+
error: providerControlError
|
|
23982
24387
|
};
|
|
23983
24388
|
}
|
|
23984
24389
|
}
|
|
@@ -24299,18 +24704,30 @@ async function applyControl(codex, kandan, topic, instanceId, options, agentProv
|
|
|
24299
24704
|
error: "claude_code_steer_requires_text_input"
|
|
24300
24705
|
};
|
|
24301
24706
|
}
|
|
24302
|
-
|
|
24303
|
-
|
|
24304
|
-
|
|
24305
|
-
|
|
24306
|
-
|
|
24307
|
-
|
|
24308
|
-
|
|
24707
|
+
let steered;
|
|
24708
|
+
try {
|
|
24709
|
+
steered = claudeSession.steerTurn(steerText);
|
|
24710
|
+
} catch (steerError) {
|
|
24711
|
+
const message = steerError instanceof Error ? steerError.message : String(steerError);
|
|
24712
|
+
log2("claude_code.steer_failed", {
|
|
24713
|
+
thread_id: control.threadId,
|
|
24714
|
+
message
|
|
24715
|
+
});
|
|
24716
|
+
return {
|
|
24717
|
+
instanceId,
|
|
24718
|
+
controlType: control.type,
|
|
24719
|
+
agentProvider: "claude-code",
|
|
24720
|
+
ok: false,
|
|
24721
|
+
error: "claude_code_steer_failed",
|
|
24722
|
+
message,
|
|
24723
|
+
threadId: control.threadId
|
|
24724
|
+
};
|
|
24725
|
+
}
|
|
24309
24726
|
return {
|
|
24310
24727
|
instanceId,
|
|
24311
24728
|
controlType: control.type,
|
|
24312
24729
|
agentProvider: "claude-code",
|
|
24313
|
-
steered
|
|
24730
|
+
steered,
|
|
24314
24731
|
threadId: control.threadId
|
|
24315
24732
|
};
|
|
24316
24733
|
}
|
|
@@ -24349,6 +24766,30 @@ ${steerText}`,
|
|
|
24349
24766
|
response
|
|
24350
24767
|
};
|
|
24351
24768
|
}
|
|
24769
|
+
case "rewind_thread": {
|
|
24770
|
+
const claudeSession = activeClaudeCodeSessions.get(control.threadId);
|
|
24771
|
+
if (claudeSession !== void 0 || control.agentProvider === "claude-code") {
|
|
24772
|
+
return {
|
|
24773
|
+
instanceId,
|
|
24774
|
+
controlType: control.type,
|
|
24775
|
+
agentProvider: "claude-code",
|
|
24776
|
+
requestId: stringValue(control.requestId) ?? null,
|
|
24777
|
+
threadId: control.threadId,
|
|
24778
|
+
ok: false,
|
|
24779
|
+
error: "claude_code_rewind_unsupported",
|
|
24780
|
+
message: "Claude Code does not support rewind yet"
|
|
24781
|
+
};
|
|
24782
|
+
}
|
|
24783
|
+
return {
|
|
24784
|
+
instanceId,
|
|
24785
|
+
controlType: control.type,
|
|
24786
|
+
requestId: stringValue(control.requestId) ?? null,
|
|
24787
|
+
threadId: control.threadId,
|
|
24788
|
+
ok: false,
|
|
24789
|
+
error: "rewind_not_supported",
|
|
24790
|
+
message: "This runner does not support rewinding threads yet"
|
|
24791
|
+
};
|
|
24792
|
+
}
|
|
24352
24793
|
case "interrupt_queued_messages": {
|
|
24353
24794
|
const agentProvider = stringValue(control.agentProvider)?.trim();
|
|
24354
24795
|
if (agentProvider !== "claude-code") {
|
|
@@ -24816,10 +25257,24 @@ function startInstanceAgentLabel(provider) {
|
|
|
24816
25257
|
return "Claude Code";
|
|
24817
25258
|
}
|
|
24818
25259
|
}
|
|
24819
|
-
function
|
|
25260
|
+
function resolveControlCodexModelProvider(control) {
|
|
24820
25261
|
const modelProvider = stringValue(control.modelProvider)?.trim();
|
|
25262
|
+
const llmProxy = objectValue(control.llmProxy);
|
|
25263
|
+
const baseUrl = stringValue(llmProxy?.baseUrl)?.trim();
|
|
25264
|
+
const token = stringValue(llmProxy?.token)?.trim();
|
|
25265
|
+
const binding = baseUrl !== void 0 && baseUrl !== "" && token !== void 0 && token !== "" ? { baseUrl, token } : void 0;
|
|
24821
25266
|
if (modelProvider === void 0 || modelProvider === "") {
|
|
24822
|
-
|
|
25267
|
+
if (binding === void 0) {
|
|
25268
|
+
return { type: "none" };
|
|
25269
|
+
}
|
|
25270
|
+
return {
|
|
25271
|
+
type: "provider",
|
|
25272
|
+
runtime: {
|
|
25273
|
+
provider: "openai-proxy",
|
|
25274
|
+
llmProxyBaseUrl: binding.baseUrl,
|
|
25275
|
+
llmProxyToken: binding.token
|
|
25276
|
+
}
|
|
25277
|
+
};
|
|
24823
25278
|
}
|
|
24824
25279
|
if (modelProvider !== "wafer") {
|
|
24825
25280
|
return {
|
|
@@ -24827,40 +25282,84 @@ function resolveControlWaferModelProvider(control) {
|
|
|
24827
25282
|
error: `model_provider_unsupported:${modelProvider}`
|
|
24828
25283
|
};
|
|
24829
25284
|
}
|
|
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 === "") {
|
|
25285
|
+
if (binding === void 0) {
|
|
24834
25286
|
return { type: "error", error: "wafer_model_provider_missing_llm_proxy" };
|
|
24835
25287
|
}
|
|
24836
25288
|
return {
|
|
24837
|
-
type: "
|
|
25289
|
+
type: "provider",
|
|
24838
25290
|
runtime: {
|
|
24839
25291
|
provider: "wafer",
|
|
24840
|
-
llmProxyBaseUrl: baseUrl,
|
|
24841
|
-
llmProxyToken: token
|
|
25292
|
+
llmProxyBaseUrl: binding.baseUrl,
|
|
25293
|
+
llmProxyToken: binding.token
|
|
24842
25294
|
}
|
|
24843
25295
|
};
|
|
24844
25296
|
}
|
|
24845
|
-
function
|
|
24846
|
-
|
|
25297
|
+
function codexModelProviderResolutionError(resolution) {
|
|
25298
|
+
if (resolution.type === "error") {
|
|
25299
|
+
return resolution.error;
|
|
25300
|
+
}
|
|
25301
|
+
if (resolution.type === "provider" && resolution.runtime.provider === "openai-proxy" && resolveForwardableOpenAiApiKey() === void 0) {
|
|
25302
|
+
return "codex_llm_proxy_requires_openai_api_key";
|
|
25303
|
+
}
|
|
25304
|
+
return void 0;
|
|
25305
|
+
}
|
|
25306
|
+
function codexModelProviderControlError(options, control) {
|
|
25307
|
+
const resolution = resolveControlCodexModelProvider(control);
|
|
24847
25308
|
switch (resolution.type) {
|
|
24848
25309
|
case "none":
|
|
24849
25310
|
return void 0;
|
|
24850
25311
|
case "error":
|
|
24851
25312
|
return resolution.error;
|
|
24852
|
-
case "
|
|
24853
|
-
|
|
25313
|
+
case "provider": {
|
|
25314
|
+
const gateError = codexModelProviderResolutionError(resolution);
|
|
25315
|
+
if (gateError !== void 0) {
|
|
25316
|
+
return gateError;
|
|
25317
|
+
}
|
|
25318
|
+
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";
|
|
25319
|
+
}
|
|
24854
25320
|
}
|
|
24855
25321
|
}
|
|
24856
25322
|
function linzumiCodexModelProviderConfig(runtime) {
|
|
24857
|
-
|
|
24858
|
-
|
|
24859
|
-
|
|
24860
|
-
|
|
24861
|
-
|
|
24862
|
-
|
|
24863
|
-
|
|
25323
|
+
const baseUrl = `${runtime.llmProxyBaseUrl.replace(/\/+$/, "")}/v1`;
|
|
25324
|
+
switch (runtime.provider) {
|
|
25325
|
+
case "wafer":
|
|
25326
|
+
return {
|
|
25327
|
+
id: "linzumi",
|
|
25328
|
+
name: "Linzumi Proxy",
|
|
25329
|
+
baseUrl,
|
|
25330
|
+
envKey: "LINZUMI_LLM_PROXY_TOKEN",
|
|
25331
|
+
wireApi: "responses"
|
|
25332
|
+
};
|
|
25333
|
+
case "openai-proxy":
|
|
25334
|
+
return {
|
|
25335
|
+
id: "linzumi",
|
|
25336
|
+
name: "Linzumi Proxy",
|
|
25337
|
+
baseUrl,
|
|
25338
|
+
envKey: "OPENAI_API_KEY",
|
|
25339
|
+
wireApi: "responses",
|
|
25340
|
+
envHttpHeaders: {
|
|
25341
|
+
"x-linzumi-llm-proxy-token": "LINZUMI_LLM_PROXY_TOKEN"
|
|
25342
|
+
}
|
|
25343
|
+
};
|
|
25344
|
+
}
|
|
25345
|
+
}
|
|
25346
|
+
function codexModelProviderAppServerEnv(runtime) {
|
|
25347
|
+
switch (runtime.provider) {
|
|
25348
|
+
case "wafer":
|
|
25349
|
+
return { LINZUMI_LLM_PROXY_TOKEN: runtime.llmProxyToken };
|
|
25350
|
+
case "openai-proxy": {
|
|
25351
|
+
const openAiApiKey = resolveForwardableOpenAiApiKey();
|
|
25352
|
+
if (openAiApiKey === void 0) {
|
|
25353
|
+
throw new Error(
|
|
25354
|
+
"codex llm proxy requires API-key auth (OPENAI_API_KEY in the environment or $CODEX_HOME/auth.json); ChatGPT OAuth credentials cannot be forwarded"
|
|
25355
|
+
);
|
|
25356
|
+
}
|
|
25357
|
+
return {
|
|
25358
|
+
LINZUMI_LLM_PROXY_TOKEN: runtime.llmProxyToken,
|
|
25359
|
+
OPENAI_API_KEY: openAiApiKey
|
|
25360
|
+
};
|
|
25361
|
+
}
|
|
25362
|
+
}
|
|
24864
25363
|
}
|
|
24865
25364
|
async function startCodexProviderInstance(args) {
|
|
24866
25365
|
if (args.options.codexUrl === void 0) {
|
|
@@ -24985,6 +25484,23 @@ function createClaudeCodeInputQueue(input) {
|
|
|
24985
25484
|
}
|
|
24986
25485
|
waiter({ done: false, value: message });
|
|
24987
25486
|
};
|
|
25487
|
+
const enqueueSteer = (content) => {
|
|
25488
|
+
if (state.closed) {
|
|
25489
|
+
throw new Error("Claude Code streaming input is closed");
|
|
25490
|
+
}
|
|
25491
|
+
if (pendingSourceSeqs.length === 0) {
|
|
25492
|
+
enqueue({ content, sourceSeq: void 0 });
|
|
25493
|
+
return "steered_queued";
|
|
25494
|
+
}
|
|
25495
|
+
const message = claudeCodeUserInputMessage(content);
|
|
25496
|
+
const waiter = waiters.shift();
|
|
25497
|
+
if (waiter === void 0) {
|
|
25498
|
+
pendingMessages.push(message);
|
|
25499
|
+
} else {
|
|
25500
|
+
waiter({ done: false, value: message });
|
|
25501
|
+
}
|
|
25502
|
+
return "steered_live";
|
|
25503
|
+
};
|
|
24988
25504
|
return {
|
|
24989
25505
|
messages: {
|
|
24990
25506
|
[Symbol.asyncIterator]() {
|
|
@@ -25010,6 +25526,7 @@ function createClaudeCodeInputQueue(input) {
|
|
|
25010
25526
|
drainClosedWaiters();
|
|
25011
25527
|
},
|
|
25012
25528
|
enqueue,
|
|
25529
|
+
enqueueSteer,
|
|
25013
25530
|
completeTurn: () => pendingSourceSeqs.shift(),
|
|
25014
25531
|
currentSourceSeq: () => pendingSourceSeqs[0]
|
|
25015
25532
|
};
|
|
@@ -25331,6 +25848,24 @@ async function startClaudeCodeProviderInstance(args) {
|
|
|
25331
25848
|
onTodoWriteCompleted: planMirror.handleTodoWrite,
|
|
25332
25849
|
log: args.log
|
|
25333
25850
|
});
|
|
25851
|
+
const liveBashCapture = args.options.claudeCodeRunner === void 0 && claudeLiveBashCaptureEnabled(process.env) ? createClaudeCodeLiveBashCapture({
|
|
25852
|
+
captureDir: join20(
|
|
25853
|
+
tmpdir3(),
|
|
25854
|
+
`linzumi-claude-live-bash-${args.instanceId}`
|
|
25855
|
+
),
|
|
25856
|
+
onOutputDelta: (toolUseId, delta) => {
|
|
25857
|
+
if (activeSessionId === void 0) {
|
|
25858
|
+
return;
|
|
25859
|
+
}
|
|
25860
|
+
adapter.handleTranscriptEvent({
|
|
25861
|
+
type: "command_output_delta",
|
|
25862
|
+
sessionId: activeSessionId,
|
|
25863
|
+
itemKey: toolUseId,
|
|
25864
|
+
delta
|
|
25865
|
+
});
|
|
25866
|
+
},
|
|
25867
|
+
log: (event, fields) => args.log(event, fields)
|
|
25868
|
+
}) : void 0;
|
|
25334
25869
|
let mcpAuthCleanup;
|
|
25335
25870
|
let mcpServers;
|
|
25336
25871
|
try {
|
|
@@ -25435,6 +25970,7 @@ async function startClaudeCodeProviderInstance(args) {
|
|
|
25435
25970
|
threadId,
|
|
25436
25971
|
currentSourceSeq: inputQueue.currentSourceSeq,
|
|
25437
25972
|
enqueueInput: inputQueue.enqueue,
|
|
25973
|
+
steerTurn: inputQueue.enqueueSteer,
|
|
25438
25974
|
interruptTurn: async (reason) => {
|
|
25439
25975
|
const aborted = adapter.interruptActiveTurn(reason);
|
|
25440
25976
|
await sessionControls?.interrupt();
|
|
@@ -25493,6 +26029,22 @@ async function startClaudeCodeProviderInstance(args) {
|
|
|
25493
26029
|
if (event.type === "rate_limit") {
|
|
25494
26030
|
await reportClaudeCodeRateLimit(event);
|
|
25495
26031
|
}
|
|
26032
|
+
if (event.type === "tool_result") {
|
|
26033
|
+
liveBashCapture?.settleTool(event.itemKey);
|
|
26034
|
+
}
|
|
26035
|
+
if (event.type === "turn_interrupted" || event.type === "session_failed") {
|
|
26036
|
+
liveBashCapture?.settleAll();
|
|
26037
|
+
}
|
|
26038
|
+
if (event.type === "usage") {
|
|
26039
|
+
const summary = claudeCodeTokenUsageSummaryText(event.usage);
|
|
26040
|
+
if (summary !== void 0) {
|
|
26041
|
+
args.log("claude_code.token_usage", {
|
|
26042
|
+
linzumi_thread_id: threadId,
|
|
26043
|
+
claude_session_id: event.sessionId,
|
|
26044
|
+
token_usage_summary: summary
|
|
26045
|
+
});
|
|
26046
|
+
}
|
|
26047
|
+
}
|
|
25496
26048
|
adapter.handleTranscriptEvent(event);
|
|
25497
26049
|
};
|
|
25498
26050
|
const llmProxy = objectValue(args.control.llmProxy);
|
|
@@ -25539,6 +26091,10 @@ async function startClaudeCodeProviderInstance(args) {
|
|
|
25539
26091
|
runner: args.options.claudeCodeRunner,
|
|
25540
26092
|
canUseTool,
|
|
25541
26093
|
...mcpServers === void 0 ? {} : { mcpServers },
|
|
26094
|
+
...liveBashCapture === void 0 ? {} : {
|
|
26095
|
+
preToolUseHookMatchers: liveBashCapture.hookMatchers,
|
|
26096
|
+
wrapApprovedToolInput: (toolUseId, toolName2, input) => toolName2 === "Bash" ? liveBashCapture.wrapApprovedTool(toolUseId, input) : void 0
|
|
26097
|
+
},
|
|
25542
26098
|
env: sessionEnv,
|
|
25543
26099
|
// The built-in Linzumi MCP is trusted like the codex side: its tools
|
|
25544
26100
|
// run without an approval round-trip. SDK allowedTools matches MCP
|
|
@@ -25555,6 +26111,7 @@ async function startClaudeCodeProviderInstance(args) {
|
|
|
25555
26111
|
} finally {
|
|
25556
26112
|
inputQueue.close();
|
|
25557
26113
|
mcpAuthCleanup?.();
|
|
26114
|
+
liveBashCapture?.close();
|
|
25558
26115
|
if (activeSessionId !== void 0) {
|
|
25559
26116
|
args.activeClaudeCodeSessions.delete(activeSessionId);
|
|
25560
26117
|
await args.disposeClaudeCodeForwardPortSession?.(activeSessionId);
|
|
@@ -25710,6 +26267,8 @@ function claudeSessionStoreEntryPayload(args, event) {
|
|
|
25710
26267
|
itemKey: event.itemKey,
|
|
25711
26268
|
body: event.content
|
|
25712
26269
|
};
|
|
26270
|
+
case "command_output_delta":
|
|
26271
|
+
return void 0;
|
|
25713
26272
|
case "usage":
|
|
25714
26273
|
return { usage: event.usage };
|
|
25715
26274
|
case "rate_limit":
|
|
@@ -26128,7 +26687,7 @@ function threadRunnerOptions(args) {
|
|
|
26128
26687
|
args.options,
|
|
26129
26688
|
args.control
|
|
26130
26689
|
);
|
|
26131
|
-
const
|
|
26690
|
+
const providerResolution = resolveControlCodexModelProvider(args.control);
|
|
26132
26691
|
return {
|
|
26133
26692
|
...args.options,
|
|
26134
26693
|
clientId: void 0,
|
|
@@ -26145,7 +26704,7 @@ function threadRunnerOptions(args) {
|
|
|
26145
26704
|
role: "thread",
|
|
26146
26705
|
kandanThreadId: args.kandanThreadId
|
|
26147
26706
|
},
|
|
26148
|
-
codexModelProvider:
|
|
26707
|
+
codexModelProvider: providerResolution.type === "provider" ? providerResolution.runtime : void 0,
|
|
26149
26708
|
spawnThreadRunner: void 0,
|
|
26150
26709
|
threadRunnerReadyTimeoutMs: args.options.threadRunnerReadyTimeoutMs,
|
|
26151
26710
|
runtimeDefaults: {
|
|
@@ -26182,6 +26741,7 @@ async function spawnLocalThreadRunnerProcess(options) {
|
|
|
26182
26741
|
scriptPath,
|
|
26183
26742
|
redactedThreadRunnerCliArgs(args)
|
|
26184
26743
|
);
|
|
26744
|
+
const forwardableOpenAiApiKey = options.codexModelProvider?.provider === "openai-proxy" ? resolveForwardableOpenAiApiKey() : void 0;
|
|
26185
26745
|
const env = {
|
|
26186
26746
|
...process.env,
|
|
26187
26747
|
LINZUMI_THREAD_RUNNER_ROLE: "thread",
|
|
@@ -26189,7 +26749,8 @@ async function spawnLocalThreadRunnerProcess(options) {
|
|
|
26189
26749
|
LINZUMI_THREAD_RUNNER_TOKEN: options.token,
|
|
26190
26750
|
// The LLM proxy credential travels via env (like the runner token), not
|
|
26191
26751
|
// argv, so the spawned worker's command line never carries it.
|
|
26192
|
-
...options.codexModelProvider === void 0 ? {} : { LINZUMI_LLM_PROXY_TOKEN: options.codexModelProvider.llmProxyToken }
|
|
26752
|
+
...options.codexModelProvider === void 0 ? {} : { LINZUMI_LLM_PROXY_TOKEN: options.codexModelProvider.llmProxyToken },
|
|
26753
|
+
...forwardableOpenAiApiKey === void 0 ? {} : { OPENAI_API_KEY: forwardableOpenAiApiKey }
|
|
26193
26754
|
};
|
|
26194
26755
|
writeCliAuditEvent("process.spawn", {
|
|
26195
26756
|
command: process.execPath,
|
|
@@ -27395,16 +27956,16 @@ async function startOwnedCodexAppServer(options, args = { linzumiMcp: true }) {
|
|
|
27395
27956
|
model: defaults.model,
|
|
27396
27957
|
reasoningEffort: defaults.reasoningEffort,
|
|
27397
27958
|
fast: options.fast,
|
|
27398
|
-
//
|
|
27399
|
-
// Kandan LLM proxy via a custom Linzumi model provider
|
|
27400
|
-
//
|
|
27959
|
+
// Proxy-routed thread workers point their owned app-server at the
|
|
27960
|
+
// Kandan LLM proxy via a custom Linzumi model provider. Wafer routes
|
|
27961
|
+
// ride the session token as the bearer; openai-proxy routes (parity
|
|
27962
|
+
// backlog item 50) additionally materialize the user's own
|
|
27963
|
+
// OPENAI_API_KEY as the passthrough upstream credential.
|
|
27401
27964
|
...options.codexModelProvider === void 0 ? {} : {
|
|
27402
27965
|
modelProvider: linzumiCodexModelProviderConfig(
|
|
27403
27966
|
options.codexModelProvider
|
|
27404
27967
|
),
|
|
27405
|
-
env:
|
|
27406
|
-
LINZUMI_LLM_PROXY_TOKEN: options.codexModelProvider.llmProxyToken
|
|
27407
|
-
}
|
|
27968
|
+
env: codexModelProviderAppServerEnv(options.codexModelProvider)
|
|
27408
27969
|
},
|
|
27409
27970
|
mcpServers: mcpAuth === void 0 ? [] : [
|
|
27410
27971
|
linzumiMcpServerConfig({
|
|
@@ -27452,9 +28013,9 @@ function mcpOwnerUsername(options) {
|
|
|
27452
28013
|
return options.channelSession?.listenUser ?? identityFromAccessToken(options.token).actorUsername;
|
|
27453
28014
|
}
|
|
27454
28015
|
function writeEphemeralMcpAuthFile(options) {
|
|
27455
|
-
const directory = mkdtempSync4(
|
|
28016
|
+
const directory = mkdtempSync4(join20(tmpdir3(), "linzumi-mcp-auth-"));
|
|
27456
28017
|
chmodSync2(directory, 448);
|
|
27457
|
-
const path2 =
|
|
28018
|
+
const path2 = join20(directory, "auth.json");
|
|
27458
28019
|
writeCachedLocalRunnerToken({
|
|
27459
28020
|
kandanUrl: options.kandanUrl,
|
|
27460
28021
|
accessToken: options.token,
|
|
@@ -27463,7 +28024,7 @@ function writeEphemeralMcpAuthFile(options) {
|
|
|
27463
28024
|
chmodSync2(path2, 384);
|
|
27464
28025
|
return {
|
|
27465
28026
|
path: path2,
|
|
27466
|
-
cleanup: () =>
|
|
28027
|
+
cleanup: () => rmSync5(directory, { recursive: true, force: true })
|
|
27467
28028
|
};
|
|
27468
28029
|
}
|
|
27469
28030
|
function once(action) {
|
|
@@ -27530,7 +28091,7 @@ function configuredAllowedCwds(values, options = {}) {
|
|
|
27530
28091
|
const absolutePath = resolve8(expandUserPath(value));
|
|
27531
28092
|
try {
|
|
27532
28093
|
if (options.createMissing === true) {
|
|
27533
|
-
|
|
28094
|
+
mkdirSync12(absolutePath, { recursive: true });
|
|
27534
28095
|
}
|
|
27535
28096
|
const realPath = realpathSync6(absolutePath);
|
|
27536
28097
|
allowedCwds.push(
|
|
@@ -27567,7 +28128,7 @@ function allowedCwdProjects(allowedCwds) {
|
|
|
27567
28128
|
});
|
|
27568
28129
|
}
|
|
27569
28130
|
function isGitProjectDirectory(cwd) {
|
|
27570
|
-
const gitPath =
|
|
28131
|
+
const gitPath = join20(cwd, ".git");
|
|
27571
28132
|
try {
|
|
27572
28133
|
const gitPathStats = statSync3(gitPath);
|
|
27573
28134
|
return gitPathStats.isDirectory() || gitPathStats.isFile();
|
|
@@ -27592,7 +28153,7 @@ function browseRunnerDirectory(control, options) {
|
|
|
27592
28153
|
}
|
|
27593
28154
|
const parent = dirname13(currentPath);
|
|
27594
28155
|
const entries = readdirSync4(currentPath, { withFileTypes: true }).filter((entry) => entry.isDirectory()).filter((entry) => visibleRunnerDirectoryEntryName(entry.name)).map((entry) => {
|
|
27595
|
-
const path2 =
|
|
28156
|
+
const path2 = join20(currentPath, entry.name);
|
|
27596
28157
|
return {
|
|
27597
28158
|
name: entry.name,
|
|
27598
28159
|
path: path2,
|
|
@@ -27633,7 +28194,7 @@ function projectDirectoryName(name) {
|
|
|
27633
28194
|
function availableProjectDirectoryName(projectsRoot, baseName, suffix = 0) {
|
|
27634
28195
|
for (let nextSuffix = suffix; ; nextSuffix += 1) {
|
|
27635
28196
|
const candidate = nextSuffix === 0 ? baseName : `${baseName}-${nextSuffix}`;
|
|
27636
|
-
if (!projectPathExists(
|
|
28197
|
+
if (!projectPathExists(join20(projectsRoot, candidate))) {
|
|
27637
28198
|
return candidate;
|
|
27638
28199
|
}
|
|
27639
28200
|
}
|
|
@@ -27661,9 +28222,9 @@ function createRunnerProject(control, options, allowedCwds) {
|
|
|
27661
28222
|
error: "invalid_project_template"
|
|
27662
28223
|
};
|
|
27663
28224
|
}
|
|
27664
|
-
const projectsRoot =
|
|
28225
|
+
const projectsRoot = join20(currentHomeDirectory(), "linzumi");
|
|
27665
28226
|
const resolvedProjectDirName = template === "hello_linzumi_demo" ? availableProjectDirectoryName(projectsRoot, projectDirName) : projectDirName;
|
|
27666
|
-
const projectPath =
|
|
28227
|
+
const projectPath = join20(projectsRoot, resolvedProjectDirName);
|
|
27667
28228
|
let createdProjectPath = false;
|
|
27668
28229
|
try {
|
|
27669
28230
|
if (template !== "hello_linzumi_demo" && projectPathExists(projectPath)) {
|
|
@@ -27675,7 +28236,7 @@ function createRunnerProject(control, options, allowedCwds) {
|
|
|
27675
28236
|
error: "project_directory_exists"
|
|
27676
28237
|
};
|
|
27677
28238
|
}
|
|
27678
|
-
|
|
28239
|
+
mkdirSync12(projectsRoot, { recursive: true });
|
|
27679
28240
|
if (template === "hello_linzumi_demo") {
|
|
27680
28241
|
createdProjectPath = true;
|
|
27681
28242
|
createHelloLinzumiProject({
|
|
@@ -27683,7 +28244,7 @@ function createRunnerProject(control, options, allowedCwds) {
|
|
|
27683
28244
|
name: resolvedProjectDirName
|
|
27684
28245
|
});
|
|
27685
28246
|
} else {
|
|
27686
|
-
|
|
28247
|
+
mkdirSync12(projectPath, { recursive: false });
|
|
27687
28248
|
createdProjectPath = true;
|
|
27688
28249
|
}
|
|
27689
28250
|
const git = spawnSync5("git", ["init"], {
|
|
@@ -27741,7 +28302,7 @@ function createRunnerProject(control, options, allowedCwds) {
|
|
|
27741
28302
|
}
|
|
27742
28303
|
function removeCreatedProjectDirectory(projectPath) {
|
|
27743
28304
|
try {
|
|
27744
|
-
|
|
28305
|
+
rmSync5(projectPath, { recursive: true, force: true });
|
|
27745
28306
|
return void 0;
|
|
27746
28307
|
} catch (error) {
|
|
27747
28308
|
return error instanceof Error ? error.message : "cleanup_failed";
|
|
@@ -27805,6 +28366,7 @@ var init_runner = __esm({
|
|
|
27805
28366
|
init_commanderAttachments();
|
|
27806
28367
|
init_claudeCodePipeline();
|
|
27807
28368
|
init_claudeCodePlanMirror();
|
|
28369
|
+
init_claudeCodeLiveBashOutput();
|
|
27808
28370
|
init_claudeCodeSession();
|
|
27809
28371
|
init_codexAppServer();
|
|
27810
28372
|
init_codexProjectTrust();
|
|
@@ -27866,7 +28428,7 @@ var init_runner = __esm({
|
|
|
27866
28428
|
});
|
|
27867
28429
|
|
|
27868
28430
|
// src/kandanTls.ts
|
|
27869
|
-
import { existsSync as existsSync13, readFileSync as
|
|
28431
|
+
import { existsSync as existsSync13, readFileSync as readFileSync17 } from "node:fs";
|
|
27870
28432
|
import { Agent } from "undici";
|
|
27871
28433
|
import WsWebSocket from "ws";
|
|
27872
28434
|
function kandanTlsTrustFromEnv() {
|
|
@@ -27880,7 +28442,7 @@ function kandanTlsTrustFromCaFile(caFile) {
|
|
|
27880
28442
|
if (!existsSync13(trimmed)) {
|
|
27881
28443
|
throw new Error(`KANDAN_TLS_CA_FILE does not exist: ${trimmed}`);
|
|
27882
28444
|
}
|
|
27883
|
-
const ca =
|
|
28445
|
+
const ca = readFileSync17(trimmed, "utf8");
|
|
27884
28446
|
return {
|
|
27885
28447
|
caFile: trimmed,
|
|
27886
28448
|
ca,
|
|
@@ -42989,9 +43551,9 @@ var require_internal = __commonJS({
|
|
|
42989
43551
|
}
|
|
42990
43552
|
InternalCodec.prototype.encoder = InternalEncoder;
|
|
42991
43553
|
InternalCodec.prototype.decoder = InternalDecoder;
|
|
42992
|
-
var
|
|
43554
|
+
var StringDecoder2 = __require("string_decoder").StringDecoder;
|
|
42993
43555
|
function InternalDecoder(options, codec) {
|
|
42994
|
-
this.decoder = new
|
|
43556
|
+
this.decoder = new StringDecoder2(codec.enc);
|
|
42995
43557
|
}
|
|
42996
43558
|
InternalDecoder.prototype.write = function(buf) {
|
|
42997
43559
|
if (!Buffer4.isBuffer(buf)) {
|
|
@@ -46664,7 +47226,7 @@ var init_RemoveFileError = __esm({
|
|
|
46664
47226
|
|
|
46665
47227
|
// ../../node_modules/@inquirer/external-editor/dist/esm/index.js
|
|
46666
47228
|
import { spawn as spawn11, spawnSync as spawnSync6 } from "child_process";
|
|
46667
|
-
import { readFileSync as
|
|
47229
|
+
import { readFileSync as readFileSync20, unlinkSync as unlinkSync3, writeFileSync as writeFileSync14 } from "fs";
|
|
46668
47230
|
import path from "node:path";
|
|
46669
47231
|
import os from "node:os";
|
|
46670
47232
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
@@ -46781,14 +47343,14 @@ var init_esm5 = __esm({
|
|
|
46781
47343
|
if (Object.prototype.hasOwnProperty.call(this.fileOptions, "mode")) {
|
|
46782
47344
|
opt.mode = this.fileOptions.mode;
|
|
46783
47345
|
}
|
|
46784
|
-
|
|
47346
|
+
writeFileSync14(this.tempFile, this.text, opt);
|
|
46785
47347
|
} catch (createFileError) {
|
|
46786
47348
|
throw new CreateFileError(createFileError);
|
|
46787
47349
|
}
|
|
46788
47350
|
}
|
|
46789
47351
|
readTemporaryFile() {
|
|
46790
47352
|
try {
|
|
46791
|
-
const tempFileBuffer =
|
|
47353
|
+
const tempFileBuffer = readFileSync20(this.tempFile);
|
|
46792
47354
|
if (tempFileBuffer.length === 0) {
|
|
46793
47355
|
this.text = "";
|
|
46794
47356
|
} else {
|
|
@@ -48157,17 +48719,17 @@ import { spawn as spawn12, spawnSync as spawnSync7 } from "node:child_process";
|
|
|
48157
48719
|
import {
|
|
48158
48720
|
existsSync as existsSync16,
|
|
48159
48721
|
constants as fsConstants,
|
|
48160
|
-
mkdirSync as
|
|
48722
|
+
mkdirSync as mkdirSync15,
|
|
48161
48723
|
mkdtempSync as mkdtempSync5,
|
|
48162
|
-
readFileSync as
|
|
48724
|
+
readFileSync as readFileSync21,
|
|
48163
48725
|
readdirSync as readdirSync5,
|
|
48164
|
-
rmSync as
|
|
48726
|
+
rmSync as rmSync6,
|
|
48165
48727
|
statSync as statSync4,
|
|
48166
|
-
writeFileSync as
|
|
48728
|
+
writeFileSync as writeFileSync15
|
|
48167
48729
|
} from "node:fs";
|
|
48168
48730
|
import { access } from "node:fs/promises";
|
|
48169
|
-
import { homedir as
|
|
48170
|
-
import { delimiter as delimiter3, dirname as dirname16, join as
|
|
48731
|
+
import { homedir as homedir16, tmpdir as tmpdir4 } from "node:os";
|
|
48732
|
+
import { delimiter as delimiter3, dirname as dirname16, join as join23, resolve as resolve10 } from "node:path";
|
|
48171
48733
|
import { stdin as defaultStdin, stdout as defaultStdout } from "node:process";
|
|
48172
48734
|
import { emitKeypressEvents } from "node:readline";
|
|
48173
48735
|
function signupHelpText() {
|
|
@@ -48288,7 +48850,7 @@ function defaultSignupDraftStore(serviceUrl) {
|
|
|
48288
48850
|
}
|
|
48289
48851
|
let parsed;
|
|
48290
48852
|
try {
|
|
48291
|
-
parsed = JSON.parse(
|
|
48853
|
+
parsed = JSON.parse(readFileSync21(path2, "utf8"));
|
|
48292
48854
|
} catch (_error) {
|
|
48293
48855
|
return void 0;
|
|
48294
48856
|
}
|
|
@@ -48298,20 +48860,20 @@ function defaultSignupDraftStore(serviceUrl) {
|
|
|
48298
48860
|
return comparableServiceUrl(parsed.serviceUrl) === comparableServiceUrl(serviceUrl) ? parsed : void 0;
|
|
48299
48861
|
},
|
|
48300
48862
|
write: (draft) => {
|
|
48301
|
-
|
|
48302
|
-
|
|
48863
|
+
mkdirSync15(dirname16(path2), { recursive: true });
|
|
48864
|
+
writeFileSync15(path2, `${JSON.stringify(draft, null, 2)}
|
|
48303
48865
|
`, {
|
|
48304
48866
|
encoding: "utf8",
|
|
48305
48867
|
mode: 384
|
|
48306
48868
|
});
|
|
48307
48869
|
},
|
|
48308
48870
|
clear: () => {
|
|
48309
|
-
|
|
48871
|
+
rmSync6(path2, { force: true });
|
|
48310
48872
|
}
|
|
48311
48873
|
};
|
|
48312
48874
|
}
|
|
48313
48875
|
function defaultSignupDraftPath(serviceUrl) {
|
|
48314
|
-
return
|
|
48876
|
+
return join23(
|
|
48315
48877
|
dirname16(localConfigPath()),
|
|
48316
48878
|
`signup-draft.${localConfigScopeFileStem(serviceUrl)}.json`
|
|
48317
48879
|
);
|
|
@@ -48346,8 +48908,8 @@ function defaultSignupTaskCacheStore(serviceUrl) {
|
|
|
48346
48908
|
}
|
|
48347
48909
|
}
|
|
48348
48910
|
};
|
|
48349
|
-
|
|
48350
|
-
|
|
48911
|
+
mkdirSync15(dirname16(path2), { recursive: true });
|
|
48912
|
+
writeFileSync15(path2, `${JSON.stringify(next, null, 2)}
|
|
48351
48913
|
`, {
|
|
48352
48914
|
encoding: "utf8",
|
|
48353
48915
|
mode: 384
|
|
@@ -48356,7 +48918,7 @@ function defaultSignupTaskCacheStore(serviceUrl) {
|
|
|
48356
48918
|
};
|
|
48357
48919
|
}
|
|
48358
48920
|
function defaultSignupTaskCachePath(serviceUrl) {
|
|
48359
|
-
return
|
|
48921
|
+
return join23(
|
|
48360
48922
|
dirname16(localConfigPath()),
|
|
48361
48923
|
`signup-task-cache.${localConfigScopeFileStem(serviceUrl)}.json`
|
|
48362
48924
|
);
|
|
@@ -48367,7 +48929,7 @@ function readSignupTaskCache(path2) {
|
|
|
48367
48929
|
}
|
|
48368
48930
|
let parsed;
|
|
48369
48931
|
try {
|
|
48370
|
-
parsed = JSON.parse(
|
|
48932
|
+
parsed = JSON.parse(readFileSync21(path2, "utf8"));
|
|
48371
48933
|
} catch (_error) {
|
|
48372
48934
|
return { version: 1, entries: {} };
|
|
48373
48935
|
}
|
|
@@ -50252,7 +50814,7 @@ function autocompletePathSuggestions(pathInput) {
|
|
|
50252
50814
|
try {
|
|
50253
50815
|
const showHidden = prefix.startsWith(".");
|
|
50254
50816
|
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) =>
|
|
50817
|
+
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
50818
|
path: path2,
|
|
50257
50819
|
score: fuzzyPathSegmentScore(path2.split("/").at(-1) ?? path2, prefix)
|
|
50258
50820
|
})).filter((candidate) => candidate.score !== void 0).sort((left, right) => {
|
|
@@ -50498,7 +51060,7 @@ async function runSignupPreflights(runtime) {
|
|
|
50498
51060
|
function defaultPreflightRuntime() {
|
|
50499
51061
|
return {
|
|
50500
51062
|
cwd: process.cwd(),
|
|
50501
|
-
homeDir:
|
|
51063
|
+
homeDir: homedir16(),
|
|
50502
51064
|
probeTool,
|
|
50503
51065
|
readGitEmail,
|
|
50504
51066
|
discoverCodeRoots,
|
|
@@ -50643,13 +51205,13 @@ async function suggestTasksWithCodex(projectPath, retryPolicy) {
|
|
|
50643
51205
|
);
|
|
50644
51206
|
}
|
|
50645
51207
|
async function runCodexTaskSuggestion2(projectPath, previousResponse, retryPolicy) {
|
|
50646
|
-
const tempRoot = mkdtempSync5(
|
|
50647
|
-
const schemaPath =
|
|
50648
|
-
const outputPath =
|
|
51208
|
+
const tempRoot = mkdtempSync5(join23(tmpdir4(), "linzumi-signup-codex-tasks-"));
|
|
51209
|
+
const schemaPath = join23(tempRoot, "task-suggestions.schema.json");
|
|
51210
|
+
const outputPath = join23(tempRoot, "task-suggestions.json");
|
|
50649
51211
|
const model = process.env.LINZUMI_SIGNUP_TASK_MODEL ?? "gpt-5.4-mini";
|
|
50650
51212
|
const prompt = taskSuggestionPrompt2(previousResponse);
|
|
50651
51213
|
const codexCommand = await resolveSignupCodexCommand();
|
|
50652
|
-
|
|
51214
|
+
writeFileSync15(
|
|
50653
51215
|
schemaPath,
|
|
50654
51216
|
`${JSON.stringify(taskSuggestionJsonSchema2(), null, 2)}
|
|
50655
51217
|
`,
|
|
@@ -50670,9 +51232,9 @@ async function runCodexTaskSuggestion2(projectPath, previousResponse, retryPolic
|
|
|
50670
51232
|
),
|
|
50671
51233
|
retryPolicy
|
|
50672
51234
|
);
|
|
50673
|
-
return
|
|
51235
|
+
return readFileSync21(outputPath, "utf8");
|
|
50674
51236
|
} finally {
|
|
50675
|
-
|
|
51237
|
+
rmSync6(tempRoot, { recursive: true, force: true });
|
|
50676
51238
|
}
|
|
50677
51239
|
}
|
|
50678
51240
|
function codexTaskSuggestionProcess2(args) {
|
|
@@ -50707,7 +51269,7 @@ function codexTaskSuggestionProcess2(args) {
|
|
|
50707
51269
|
function signupCodexTaskSuggestionProcessForTest(args) {
|
|
50708
51270
|
return codexTaskSuggestionProcess2(args);
|
|
50709
51271
|
}
|
|
50710
|
-
async function resolveSignupCodexCommand(env = process.env, homeDir =
|
|
51272
|
+
async function resolveSignupCodexCommand(env = process.env, homeDir = homedir16(), executableExists = fileIsExecutable) {
|
|
50711
51273
|
const override = firstConfiguredValue([
|
|
50712
51274
|
env.LINZUMI_SIGNUP_CODEX_BIN,
|
|
50713
51275
|
env.LINZUMI_CODEX_BIN
|
|
@@ -50762,7 +51324,7 @@ function resolveHomePath(path2, homeDir) {
|
|
|
50762
51324
|
return homeDir;
|
|
50763
51325
|
}
|
|
50764
51326
|
if (path2.startsWith("~/")) {
|
|
50765
|
-
return
|
|
51327
|
+
return join23(homeDir, path2.slice(2));
|
|
50766
51328
|
}
|
|
50767
51329
|
return resolve10(path2);
|
|
50768
51330
|
}
|
|
@@ -50775,9 +51337,9 @@ function commandLooksPathLike(command) {
|
|
|
50775
51337
|
}
|
|
50776
51338
|
function homeManagedCodexCandidates(homeDir) {
|
|
50777
51339
|
return [
|
|
50778
|
-
|
|
50779
|
-
|
|
50780
|
-
|
|
51340
|
+
join23(homeDir, ".volta", "bin", "codex"),
|
|
51341
|
+
join23(homeDir, ".local", "bin", "codex"),
|
|
51342
|
+
join23(homeDir, "bin", "codex")
|
|
50781
51343
|
];
|
|
50782
51344
|
}
|
|
50783
51345
|
async function firstExecutablePath(paths, executableExists) {
|
|
@@ -50792,7 +51354,7 @@ function commandPathCandidates(path2) {
|
|
|
50792
51354
|
if (path2 === void 0 || path2.trim() === "") {
|
|
50793
51355
|
return [];
|
|
50794
51356
|
}
|
|
50795
|
-
return path2.split(delimiter3).filter((entry) => entry.trim() !== "").map((entry) =>
|
|
51357
|
+
return path2.split(delimiter3).filter((entry) => entry.trim() !== "").map((entry) => join23(entry, "codex"));
|
|
50796
51358
|
}
|
|
50797
51359
|
async function fileIsExecutable(path2) {
|
|
50798
51360
|
try {
|
|
@@ -51025,11 +51587,11 @@ function codexPreflightLocation(command, homeDir) {
|
|
|
51025
51587
|
switch (command) {
|
|
51026
51588
|
case "codex":
|
|
51027
51589
|
return "on PATH";
|
|
51028
|
-
case
|
|
51590
|
+
case join23(homeDir, ".volta", "bin", "codex"):
|
|
51029
51591
|
return "via Volta";
|
|
51030
|
-
case
|
|
51592
|
+
case join23(homeDir, ".local", "bin", "codex"):
|
|
51031
51593
|
return "via ~/.local/bin";
|
|
51032
|
-
case
|
|
51594
|
+
case join23(homeDir, "bin", "codex"):
|
|
51033
51595
|
return "via ~/bin";
|
|
51034
51596
|
default:
|
|
51035
51597
|
return "from configured path";
|
|
@@ -51188,7 +51750,7 @@ function probeToolWithArgs(command, args, cwd) {
|
|
|
51188
51750
|
}
|
|
51189
51751
|
async function discoverCodeRoots(homeDir) {
|
|
51190
51752
|
const candidates = ["src", "code", "projects"].map(
|
|
51191
|
-
(name) =>
|
|
51753
|
+
(name) => join23(homeDir, name)
|
|
51192
51754
|
);
|
|
51193
51755
|
return candidates.filter((path2) => existsSync16(path2)).flatMap((path2) => discoveredProjectNames(path2));
|
|
51194
51756
|
}
|
|
@@ -51242,7 +51804,7 @@ function discoverProjectsFromCurrentDirectory(cwd) {
|
|
|
51242
51804
|
}
|
|
51243
51805
|
function discoverProjectsFromGuessedRoots(homeDir) {
|
|
51244
51806
|
const guessedRoots = ["src", "code", "projects"].map(
|
|
51245
|
-
(name) =>
|
|
51807
|
+
(name) => join23(homeDir, name)
|
|
51246
51808
|
);
|
|
51247
51809
|
const projects = guessedRoots.flatMap(
|
|
51248
51810
|
(root) => discoverProjectsUnderRoot(root)
|
|
@@ -51294,25 +51856,25 @@ function looksLikeProject(path2) {
|
|
|
51294
51856
|
"pnpm-lock.yaml",
|
|
51295
51857
|
"yarn.lock",
|
|
51296
51858
|
"package-lock.json"
|
|
51297
|
-
].some((name) => existsSync16(
|
|
51859
|
+
].some((name) => existsSync16(join23(path2, name)));
|
|
51298
51860
|
}
|
|
51299
51861
|
function detectProjectLanguage(path2) {
|
|
51300
|
-
if (existsSync16(
|
|
51862
|
+
if (existsSync16(join23(path2, "pyproject.toml")) || existsSync16(join23(path2, "requirements.txt"))) {
|
|
51301
51863
|
return "Python";
|
|
51302
51864
|
}
|
|
51303
|
-
if (existsSync16(
|
|
51865
|
+
if (existsSync16(join23(path2, "Cargo.toml"))) {
|
|
51304
51866
|
return "Rust";
|
|
51305
51867
|
}
|
|
51306
|
-
if (existsSync16(
|
|
51868
|
+
if (existsSync16(join23(path2, "go.mod"))) {
|
|
51307
51869
|
return "Go";
|
|
51308
51870
|
}
|
|
51309
|
-
if (existsSync16(
|
|
51871
|
+
if (existsSync16(join23(path2, "mix.exs"))) {
|
|
51310
51872
|
return "Elixir";
|
|
51311
51873
|
}
|
|
51312
|
-
if (existsSync16(
|
|
51874
|
+
if (existsSync16(join23(path2, "tsconfig.json")) || packageJsonMentionsTypeScript(path2)) {
|
|
51313
51875
|
return "TypeScript";
|
|
51314
51876
|
}
|
|
51315
|
-
if (existsSync16(
|
|
51877
|
+
if (existsSync16(join23(path2, "package.json"))) {
|
|
51316
51878
|
return "JavaScript";
|
|
51317
51879
|
}
|
|
51318
51880
|
return "Project";
|
|
@@ -51320,7 +51882,7 @@ function detectProjectLanguage(path2) {
|
|
|
51320
51882
|
function packageJsonMentionsTypeScript(path2) {
|
|
51321
51883
|
try {
|
|
51322
51884
|
const packageJson2 = JSON.parse(
|
|
51323
|
-
|
|
51885
|
+
readFileSync21(join23(path2, "package.json"), "utf8")
|
|
51324
51886
|
);
|
|
51325
51887
|
return packageJson2.dependencies?.typescript !== void 0 || packageJson2.devDependencies?.typescript !== void 0;
|
|
51326
51888
|
} catch {
|
|
@@ -51328,11 +51890,11 @@ function packageJsonMentionsTypeScript(path2) {
|
|
|
51328
51890
|
}
|
|
51329
51891
|
}
|
|
51330
51892
|
function hasGitMetadata(path2) {
|
|
51331
|
-
return existsSync16(
|
|
51893
|
+
return existsSync16(join23(path2, ".git"));
|
|
51332
51894
|
}
|
|
51333
51895
|
function childDirectories(root) {
|
|
51334
51896
|
try {
|
|
51335
|
-
return readdirSync5(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) =>
|
|
51897
|
+
return readdirSync5(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join23(root, entry.name));
|
|
51336
51898
|
} catch {
|
|
51337
51899
|
return [];
|
|
51338
51900
|
}
|
|
@@ -51358,10 +51920,10 @@ function directoryExists(path2) {
|
|
|
51358
51920
|
}
|
|
51359
51921
|
function expandHomePath(path2) {
|
|
51360
51922
|
if (path2 === "~") {
|
|
51361
|
-
return
|
|
51923
|
+
return homedir16();
|
|
51362
51924
|
}
|
|
51363
51925
|
if (path2.startsWith("~/")) {
|
|
51364
|
-
return
|
|
51926
|
+
return join23(homedir16(), path2.slice(2));
|
|
51365
51927
|
}
|
|
51366
51928
|
return resolve10(path2);
|
|
51367
51929
|
}
|
|
@@ -51451,8 +52013,8 @@ init_onboardingDiscoveryChildProcess();
|
|
|
51451
52013
|
init_runner();
|
|
51452
52014
|
init_claudeCodeSession();
|
|
51453
52015
|
init_authCache();
|
|
51454
|
-
import { existsSync as existsSync17, readFileSync as
|
|
51455
|
-
import { homedir as
|
|
52016
|
+
import { existsSync as existsSync17, readFileSync as readFileSync22, realpathSync as realpathSync7 } from "node:fs";
|
|
52017
|
+
import { homedir as homedir17 } from "node:os";
|
|
51456
52018
|
import { resolve as resolve11 } from "node:path";
|
|
51457
52019
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
51458
52020
|
|
|
@@ -51547,9 +52109,9 @@ init_kandanTls();
|
|
|
51547
52109
|
init_protocol();
|
|
51548
52110
|
init_json();
|
|
51549
52111
|
init_defaultUrls();
|
|
51550
|
-
import { existsSync as existsSync14, mkdirSync as
|
|
51551
|
-
import { dirname as dirname14, join as
|
|
51552
|
-
import { homedir as
|
|
52112
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync13, readFileSync as readFileSync18, writeFileSync as writeFileSync12 } from "node:fs";
|
|
52113
|
+
import { dirname as dirname14, join as join21 } from "node:path";
|
|
52114
|
+
import { homedir as homedir14 } from "node:os";
|
|
51553
52115
|
async function runAgentCliCommand(args, deps = {
|
|
51554
52116
|
fetchImpl: fetch,
|
|
51555
52117
|
stdout: process.stdout,
|
|
@@ -52257,7 +52819,7 @@ function agentTokenFile(flags) {
|
|
|
52257
52819
|
return flags.get("agent-token-file") ?? defaultAgentTokenFilePath();
|
|
52258
52820
|
}
|
|
52259
52821
|
function defaultAgentTokenFilePath() {
|
|
52260
|
-
return
|
|
52822
|
+
return join21(homedir14(), ".linzumi", "agent-token.json");
|
|
52261
52823
|
}
|
|
52262
52824
|
function normalizedApiUrl(apiUrl) {
|
|
52263
52825
|
return apiUrl.endsWith("/") ? apiUrl : `${apiUrl}/`;
|
|
@@ -52266,11 +52828,11 @@ function authorizationHeaders(token) {
|
|
|
52266
52828
|
return { authorization: `Bearer ${token}` };
|
|
52267
52829
|
}
|
|
52268
52830
|
function readOptionalTextFile(path2) {
|
|
52269
|
-
return existsSync14(path2) ?
|
|
52831
|
+
return existsSync14(path2) ? readFileSync18(path2, "utf8") : void 0;
|
|
52270
52832
|
}
|
|
52271
52833
|
function writeTextFile(path2, content) {
|
|
52272
|
-
|
|
52273
|
-
|
|
52834
|
+
mkdirSync13(dirname14(path2), { recursive: true });
|
|
52835
|
+
writeFileSync12(path2, content);
|
|
52274
52836
|
}
|
|
52275
52837
|
function readStoredAgentTokenFile(path2, readTextFile = readOptionalTextFile) {
|
|
52276
52838
|
const content = readTextFile(path2);
|
|
@@ -52359,25 +52921,25 @@ init_runnerLogger();
|
|
|
52359
52921
|
import {
|
|
52360
52922
|
existsSync as existsSync15,
|
|
52361
52923
|
closeSync as closeSync3,
|
|
52362
|
-
mkdirSync as
|
|
52924
|
+
mkdirSync as mkdirSync14,
|
|
52363
52925
|
openSync as openSync4,
|
|
52364
|
-
readFileSync as
|
|
52926
|
+
readFileSync as readFileSync19,
|
|
52365
52927
|
watch,
|
|
52366
|
-
writeFileSync as
|
|
52928
|
+
writeFileSync as writeFileSync13
|
|
52367
52929
|
} from "node:fs";
|
|
52368
|
-
import { homedir as
|
|
52369
|
-
import { dirname as dirname15, join as
|
|
52930
|
+
import { homedir as homedir15 } from "node:os";
|
|
52931
|
+
import { dirname as dirname15, join as join22, resolve as resolve9 } from "node:path";
|
|
52370
52932
|
import { execFileSync, spawn as spawn10 } from "node:child_process";
|
|
52371
52933
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
52372
52934
|
var connectedMarkers = ["Connected to Linzumi", "Runner connected:"];
|
|
52373
52935
|
function commanderStatusDir() {
|
|
52374
|
-
return
|
|
52936
|
+
return join22(homedir15(), ".linzumi", "commanders");
|
|
52375
52937
|
}
|
|
52376
52938
|
function commanderStatusFile(runnerId, statusDir = commanderStatusDir()) {
|
|
52377
|
-
return
|
|
52939
|
+
return join22(statusDir, `${safeRunnerId(runnerId)}.json`);
|
|
52378
52940
|
}
|
|
52379
52941
|
function defaultCommanderLogFile(runnerId) {
|
|
52380
|
-
return
|
|
52942
|
+
return join22(homedir15(), ".linzumi", "logs", `${safeRunnerId(runnerId)}.log`);
|
|
52381
52943
|
}
|
|
52382
52944
|
function commanderLogIsConnected(log2) {
|
|
52383
52945
|
return connectedMarkers.some((marker) => log2.includes(marker));
|
|
@@ -52398,8 +52960,8 @@ function startCommanderDaemon(options) {
|
|
|
52398
52960
|
"--log-file",
|
|
52399
52961
|
logFile
|
|
52400
52962
|
];
|
|
52401
|
-
|
|
52402
|
-
|
|
52963
|
+
mkdirSync14(statusDir, { recursive: true });
|
|
52964
|
+
mkdirSync14(dirname15(logFile), { recursive: true });
|
|
52403
52965
|
const out = openSync4(logFile, "a");
|
|
52404
52966
|
const err = openSync4(logFile, "a");
|
|
52405
52967
|
writeCliAuditEvent(
|
|
@@ -52445,7 +53007,7 @@ function startCommanderDaemon(options) {
|
|
|
52445
53007
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
52446
53008
|
command: [nodeBin, ...command]
|
|
52447
53009
|
};
|
|
52448
|
-
|
|
53010
|
+
writeFileSync13(statusFile, `${JSON.stringify(record, null, 2)}
|
|
52449
53011
|
`);
|
|
52450
53012
|
return record;
|
|
52451
53013
|
}
|
|
@@ -52454,12 +53016,12 @@ function commanderDaemonStatus(runnerId, statusDir = commanderStatusDir(), proce
|
|
|
52454
53016
|
if (!existsSync15(statusFile)) {
|
|
52455
53017
|
return { status: "missing", runnerId, statusFile };
|
|
52456
53018
|
}
|
|
52457
|
-
const record = parseRecord(
|
|
53019
|
+
const record = parseRecord(readFileSync19(statusFile, "utf8"));
|
|
52458
53020
|
return processIsRunning(record.pid) && processMatchesRecord(record, processIdentityReader) ? { status: "running", record } : { status: "stopped", record };
|
|
52459
53021
|
}
|
|
52460
53022
|
async function waitForCommanderDaemon(options) {
|
|
52461
53023
|
const now = options.now ?? (() => Date.now());
|
|
52462
|
-
const readTextFile = options.readTextFile ?? ((path2) => existsSync15(path2) ?
|
|
53024
|
+
const readTextFile = options.readTextFile ?? ((path2) => existsSync15(path2) ? readFileSync19(path2, "utf8") : void 0);
|
|
52463
53025
|
const statusImpl = options.statusImpl ?? commanderDaemonStatus;
|
|
52464
53026
|
const deadline = now() + options.timeoutMs;
|
|
52465
53027
|
while (now() <= deadline) {
|
|
@@ -66401,7 +66963,7 @@ async function parseAgentRunnerArgs(args, deps = {
|
|
|
66401
66963
|
};
|
|
66402
66964
|
}
|
|
66403
66965
|
function readAgentTokenTextFile(path2) {
|
|
66404
|
-
return existsSync17(path2) ?
|
|
66966
|
+
return existsSync17(path2) ? readFileSync22(path2, "utf8") : void 0;
|
|
66405
66967
|
}
|
|
66406
66968
|
function rejectAgentRunnerTargetingFlags(values) {
|
|
66407
66969
|
const unsupportedFlags = [
|
|
@@ -66711,10 +67273,10 @@ function rejectStartTargetingFlags(values) {
|
|
|
66711
67273
|
}
|
|
66712
67274
|
function resolveUserPath(pathValue) {
|
|
66713
67275
|
if (pathValue === "~") {
|
|
66714
|
-
return
|
|
67276
|
+
return homedir17();
|
|
66715
67277
|
}
|
|
66716
67278
|
if (pathValue.startsWith("~/")) {
|
|
66717
|
-
return resolve11(
|
|
67279
|
+
return resolve11(homedir17(), pathValue.slice(2));
|
|
66718
67280
|
}
|
|
66719
67281
|
return resolve11(pathValue);
|
|
66720
67282
|
}
|
|
@@ -66817,21 +67379,23 @@ function threadRunnerCodexModelProvider(values) {
|
|
|
66817
67379
|
if (modelProvider === void 0) {
|
|
66818
67380
|
return void 0;
|
|
66819
67381
|
}
|
|
66820
|
-
if (modelProvider !== "wafer") {
|
|
67382
|
+
if (modelProvider !== "wafer" && modelProvider !== "openai-proxy") {
|
|
66821
67383
|
throw new Error(`unsupported --model-provider: ${modelProvider}`);
|
|
66822
67384
|
}
|
|
66823
67385
|
const llmProxyBaseUrl = stringValue8(values, "llm-proxy-base-url");
|
|
66824
67386
|
const llmProxyToken = process.env.LINZUMI_LLM_PROXY_TOKEN?.trim();
|
|
66825
67387
|
if (llmProxyBaseUrl === void 0) {
|
|
66826
|
-
throw new Error(
|
|
67388
|
+
throw new Error(
|
|
67389
|
+
`--model-provider ${modelProvider} requires --llm-proxy-base-url`
|
|
67390
|
+
);
|
|
66827
67391
|
}
|
|
66828
67392
|
if (llmProxyToken === void 0 || llmProxyToken === "") {
|
|
66829
67393
|
throw new Error(
|
|
66830
|
-
|
|
67394
|
+
`--model-provider ${modelProvider} requires the LINZUMI_LLM_PROXY_TOKEN env credential`
|
|
66831
67395
|
);
|
|
66832
67396
|
}
|
|
66833
67397
|
return {
|
|
66834
|
-
provider:
|
|
67398
|
+
provider: modelProvider,
|
|
66835
67399
|
llmProxyBaseUrl,
|
|
66836
67400
|
llmProxyToken
|
|
66837
67401
|
};
|