@linzumi/cli 0.0.59-beta → 0.0.60-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 +339 -110
- package/package.json +1 -1
package/README.md
CHANGED
package/dist/index.js
CHANGED
|
@@ -28294,7 +28294,7 @@ function realpathOrResolved(pathValue) {
|
|
|
28294
28294
|
}
|
|
28295
28295
|
|
|
28296
28296
|
// src/version.ts
|
|
28297
|
-
var linzumiCliVersion = "0.0.
|
|
28297
|
+
var linzumiCliVersion = "0.0.60-beta";
|
|
28298
28298
|
var linzumiCliVersionText = `linzumi ${linzumiCliVersion}`;
|
|
28299
28299
|
|
|
28300
28300
|
// src/runnerLock.ts
|
|
@@ -28780,6 +28780,7 @@ function normalizeLocalRunnerCache(value) {
|
|
|
28780
28780
|
}
|
|
28781
28781
|
|
|
28782
28782
|
// src/runner.ts
|
|
28783
|
+
var THREAD_RUNNER_READY_TIMEOUT_MS = 3e4;
|
|
28783
28784
|
async function runLocalCodexRunner(options) {
|
|
28784
28785
|
const log = makeRunnerLogger(options);
|
|
28785
28786
|
const cleanup = {
|
|
@@ -28817,6 +28818,29 @@ async function runLocalCodexRunner(options) {
|
|
|
28817
28818
|
throw error51;
|
|
28818
28819
|
}
|
|
28819
28820
|
}
|
|
28821
|
+
async function runThreadCodexWorker(options) {
|
|
28822
|
+
if (options.threadProcess?.role !== "thread") {
|
|
28823
|
+
throw new Error("thread Codex worker requires thread process options");
|
|
28824
|
+
}
|
|
28825
|
+
if (process.send === void 0) {
|
|
28826
|
+
throw new Error("thread Codex worker requires an IPC channel");
|
|
28827
|
+
}
|
|
28828
|
+
const log = makeRunnerLogger(options);
|
|
28829
|
+
const started = await startOwnedCodexAppServer(options, {
|
|
28830
|
+
linzumiMcp: false
|
|
28831
|
+
});
|
|
28832
|
+
const stop = once(() => {
|
|
28833
|
+
started.stop();
|
|
28834
|
+
log.close();
|
|
28835
|
+
});
|
|
28836
|
+
process.send({
|
|
28837
|
+
type: "linzumi_thread_codex_worker_ready",
|
|
28838
|
+
kandanThreadId: options.threadProcess.kandanThreadId,
|
|
28839
|
+
codexUrl: started.url
|
|
28840
|
+
});
|
|
28841
|
+
await waitForThreadCodexWorkerStop(started.process);
|
|
28842
|
+
stop();
|
|
28843
|
+
}
|
|
28820
28844
|
async function openLocalCodexRunner(options, log, cleanup, close) {
|
|
28821
28845
|
const agentProviders = availableRunnerAgentProviders(options);
|
|
28822
28846
|
const allowedForwardPorts = options.allowedForwardPorts ?? [];
|
|
@@ -29711,7 +29735,10 @@ async function openLocalCodexRunner(options, log, cleanup, close) {
|
|
|
29711
29735
|
launchTui: options.launchTui,
|
|
29712
29736
|
enablePortForwardWatch: true,
|
|
29713
29737
|
initialForwardPorts: allowedForwardPorts,
|
|
29714
|
-
portForwardWatcher:
|
|
29738
|
+
portForwardWatcher: channelSessionPortForwardWatcherOptions({
|
|
29739
|
+
rootPid: started?.process.pid,
|
|
29740
|
+
start: options.portForwardWatcher
|
|
29741
|
+
}),
|
|
29715
29742
|
suppressedForwardPorts,
|
|
29716
29743
|
onForwardPortApproved: (port, attribution) => {
|
|
29717
29744
|
liveForwardPorts.add(port);
|
|
@@ -29771,7 +29798,9 @@ async function openLocalCodexRunner(options, log, cleanup, close) {
|
|
|
29771
29798
|
);
|
|
29772
29799
|
threadRunnerProcesses.clear();
|
|
29773
29800
|
});
|
|
29774
|
-
const
|
|
29801
|
+
const attachThreadSessionWithCodex = async (args) => {
|
|
29802
|
+
const { control, cwd, codexThreadId, sessionCodex } = args;
|
|
29803
|
+
const portForwardWatcherRootPid = args.portForwardWatcherRootPid;
|
|
29775
29804
|
const workspaceSlug = optionalThreadControlField(control, "workspace");
|
|
29776
29805
|
const channelSlug = optionalThreadControlField(control, "channel");
|
|
29777
29806
|
const kandanThreadId = optionalThreadControlField(control, "threadId");
|
|
@@ -29791,7 +29820,7 @@ async function openLocalCodexRunner(options, log, cleanup, close) {
|
|
|
29791
29820
|
const runtimeSettings = startInstanceRuntimeSettings(options, control);
|
|
29792
29821
|
const session = await attachChannelSession({
|
|
29793
29822
|
kandan,
|
|
29794
|
-
codex,
|
|
29823
|
+
codex: sessionCodex,
|
|
29795
29824
|
topic,
|
|
29796
29825
|
instanceId,
|
|
29797
29826
|
options: {
|
|
@@ -29805,7 +29834,10 @@ async function openLocalCodexRunner(options, log, cleanup, close) {
|
|
|
29805
29834
|
launchTui: false,
|
|
29806
29835
|
enablePortForwardWatch: true,
|
|
29807
29836
|
initialForwardPorts: allowedForwardPorts,
|
|
29808
|
-
portForwardWatcher:
|
|
29837
|
+
portForwardWatcher: channelSessionPortForwardWatcherOptions({
|
|
29838
|
+
rootPid: portForwardWatcherRootPid,
|
|
29839
|
+
start: options.portForwardWatcher
|
|
29840
|
+
}),
|
|
29809
29841
|
suppressedForwardPorts,
|
|
29810
29842
|
onForwardPortApproved: (port, attribution) => {
|
|
29811
29843
|
liveForwardPorts.add(port);
|
|
@@ -29840,10 +29872,23 @@ async function openLocalCodexRunner(options, log, cleanup, close) {
|
|
|
29840
29872
|
dynamicChannelSessions.set(kandanThreadId, session);
|
|
29841
29873
|
return session;
|
|
29842
29874
|
};
|
|
29875
|
+
const attachThreadSession = async (control, cwd, codexThreadId) => {
|
|
29876
|
+
return await attachThreadSessionWithCodex({
|
|
29877
|
+
control,
|
|
29878
|
+
cwd,
|
|
29879
|
+
codexThreadId,
|
|
29880
|
+
sessionCodex: codex,
|
|
29881
|
+
portForwardWatcherRootPid: started?.process.pid
|
|
29882
|
+
});
|
|
29883
|
+
};
|
|
29843
29884
|
const startThreadRunnerProcess = async (control, cwd) => {
|
|
29844
29885
|
if (options.threadProcess?.role === "thread") {
|
|
29845
29886
|
return void 0;
|
|
29846
29887
|
}
|
|
29888
|
+
const agentProviderResult = startInstanceAgentProvider(control);
|
|
29889
|
+
if (agentProviderResult.type !== "ok" || agentProviderResult.provider !== "codex") {
|
|
29890
|
+
return void 0;
|
|
29891
|
+
}
|
|
29847
29892
|
const workspaceSlug = optionalThreadControlField(control, "workspace");
|
|
29848
29893
|
const channelSlug = optionalThreadControlField(control, "channel");
|
|
29849
29894
|
const kandanThreadId = optionalThreadControlField(control, "threadId");
|
|
@@ -29863,17 +29908,24 @@ async function openLocalCodexRunner(options, log, cleanup, close) {
|
|
|
29863
29908
|
};
|
|
29864
29909
|
}
|
|
29865
29910
|
const spawnThreadRunner = options.spawnThreadRunner ?? spawnLocalThreadRunnerProcess;
|
|
29911
|
+
const readyTimeoutMs = threadRunnerReadyTimeoutMs(options);
|
|
29866
29912
|
const startingEntry = {
|
|
29867
29913
|
kind: "starting",
|
|
29868
|
-
promise:
|
|
29869
|
-
|
|
29870
|
-
|
|
29871
|
-
|
|
29872
|
-
|
|
29873
|
-
|
|
29874
|
-
|
|
29875
|
-
|
|
29876
|
-
|
|
29914
|
+
promise: withThreadRunnerReadyTimeout(
|
|
29915
|
+
spawnThreadRunner(
|
|
29916
|
+
threadRunnerOptions({
|
|
29917
|
+
options,
|
|
29918
|
+
control,
|
|
29919
|
+
cwd,
|
|
29920
|
+
workspaceSlug,
|
|
29921
|
+
channelSlug,
|
|
29922
|
+
kandanThreadId
|
|
29923
|
+
})
|
|
29924
|
+
),
|
|
29925
|
+
{
|
|
29926
|
+
kandanThreadId,
|
|
29927
|
+
timeoutMs: readyTimeoutMs
|
|
29928
|
+
}
|
|
29877
29929
|
)
|
|
29878
29930
|
};
|
|
29879
29931
|
threadRunnerProcesses.set(kandanThreadId, startingEntry);
|
|
@@ -29886,31 +29938,84 @@ async function openLocalCodexRunner(options, log, cleanup, close) {
|
|
|
29886
29938
|
}
|
|
29887
29939
|
throw error51;
|
|
29888
29940
|
}
|
|
29889
|
-
|
|
29890
|
-
|
|
29891
|
-
|
|
29892
|
-
|
|
29893
|
-
|
|
29894
|
-
|
|
29895
|
-
|
|
29896
|
-
|
|
29897
|
-
|
|
29941
|
+
try {
|
|
29942
|
+
const threadCodex = await connectCodexAppServer(handle.codexUrl);
|
|
29943
|
+
const closeThreadCodex = once(() => threadCodex.close());
|
|
29944
|
+
handle.onExit?.(closeThreadCodex);
|
|
29945
|
+
const runtimeHandle = {
|
|
29946
|
+
...handle,
|
|
29947
|
+
close: async () => {
|
|
29948
|
+
closeThreadCodex();
|
|
29949
|
+
await handle.close();
|
|
29950
|
+
}
|
|
29951
|
+
};
|
|
29952
|
+
const runningEntry = {
|
|
29953
|
+
kind: "running",
|
|
29954
|
+
handle: runtimeHandle
|
|
29955
|
+
};
|
|
29956
|
+
if (threadRunnerProcesses.get(kandanThreadId) === startingEntry) {
|
|
29957
|
+
threadRunnerProcesses.set(kandanThreadId, runningEntry);
|
|
29958
|
+
}
|
|
29959
|
+
handle.onExit?.(() => {
|
|
29960
|
+
if (threadRunnerProcesses.get(kandanThreadId) === runningEntry) {
|
|
29961
|
+
threadRunnerProcesses.delete(kandanThreadId);
|
|
29962
|
+
}
|
|
29963
|
+
});
|
|
29964
|
+
log("runner.thread_process_started", {
|
|
29965
|
+
kandanThreadId,
|
|
29966
|
+
cwd
|
|
29967
|
+
});
|
|
29968
|
+
const onStartedThread = (startedControl, startedCwd, codexThreadId) => attachThreadSessionWithCodex({
|
|
29969
|
+
control: startedControl,
|
|
29970
|
+
cwd: startedCwd,
|
|
29971
|
+
codexThreadId,
|
|
29972
|
+
sessionCodex: threadCodex,
|
|
29973
|
+
portForwardWatcherRootPid: handle.processPid
|
|
29974
|
+
});
|
|
29975
|
+
switch (control.type) {
|
|
29976
|
+
case "start_instance": {
|
|
29977
|
+
const result = await startCodexProviderInstance({
|
|
29978
|
+
codex: threadCodex,
|
|
29979
|
+
kandan,
|
|
29980
|
+
topic,
|
|
29981
|
+
control,
|
|
29982
|
+
options,
|
|
29983
|
+
instanceId,
|
|
29984
|
+
cwd,
|
|
29985
|
+
matchedRoot: cwd,
|
|
29986
|
+
onStartedThread,
|
|
29987
|
+
setStartupStage: () => void 0,
|
|
29988
|
+
setStartedCodexThreadId: () => void 0
|
|
29989
|
+
});
|
|
29990
|
+
return result.controlResponse;
|
|
29991
|
+
}
|
|
29992
|
+
case "reconnect_thread":
|
|
29993
|
+
return await applyControl(
|
|
29994
|
+
threadCodex,
|
|
29995
|
+
kandan,
|
|
29996
|
+
topic,
|
|
29997
|
+
instanceId,
|
|
29998
|
+
options,
|
|
29999
|
+
agentProviders,
|
|
30000
|
+
allowedCwds.value,
|
|
30001
|
+
activeClaudeCodeSessions,
|
|
30002
|
+
pendingClaudeCodeApprovals,
|
|
30003
|
+
ensureClaudeCodeForwardPortSession,
|
|
30004
|
+
disposeClaudeCodeForwardPortSession,
|
|
30005
|
+
control,
|
|
30006
|
+
log,
|
|
30007
|
+
onStartedThread,
|
|
30008
|
+
void 0
|
|
30009
|
+
);
|
|
30010
|
+
}
|
|
30011
|
+
} catch (error51) {
|
|
30012
|
+
const entry = threadRunnerProcesses.get(kandanThreadId);
|
|
30013
|
+
if (entry === startingEntry || entry?.kind === "running") {
|
|
29898
30014
|
threadRunnerProcesses.delete(kandanThreadId);
|
|
29899
30015
|
}
|
|
29900
|
-
|
|
29901
|
-
|
|
29902
|
-
|
|
29903
|
-
cwd
|
|
29904
|
-
});
|
|
29905
|
-
return {
|
|
29906
|
-
instanceId,
|
|
29907
|
-
controlType: control.type,
|
|
29908
|
-
ok: true,
|
|
29909
|
-
delegated: true,
|
|
29910
|
-
threadProcess: "started",
|
|
29911
|
-
kandanThreadId,
|
|
29912
|
-
cwd
|
|
29913
|
-
};
|
|
30016
|
+
await (entry?.kind === "running" ? entry.handle.close() : handle.close()).catch(() => void 0);
|
|
30017
|
+
throw error51;
|
|
30018
|
+
}
|
|
29914
30019
|
};
|
|
29915
30020
|
const heartbeatPayload = () => ({
|
|
29916
30021
|
instanceId,
|
|
@@ -30228,12 +30333,6 @@ async function openLocalCodexRunner(options, log, cleanup, close) {
|
|
|
30228
30333
|
};
|
|
30229
30334
|
controlDispatcher.value = handleControl;
|
|
30230
30335
|
pendingControls.splice(0).forEach(handleControl);
|
|
30231
|
-
if (options.threadProcess?.role === "thread") {
|
|
30232
|
-
const initialControl = options.threadProcess.initialControl;
|
|
30233
|
-
if (initialControl !== void 0) {
|
|
30234
|
-
handleControl(initialControl);
|
|
30235
|
-
}
|
|
30236
|
-
}
|
|
30237
30336
|
return { instanceId, codexUrl, close };
|
|
30238
30337
|
}
|
|
30239
30338
|
function controlTargetsInstance(control, instanceId) {
|
|
@@ -32551,6 +32650,15 @@ function startInstanceRuntimeSettings(options, control) {
|
|
|
32551
32650
|
allowPortForwardingByDefault: control.allowPortForwardingByDefault ?? defaults.allowPortForwardingByDefault
|
|
32552
32651
|
};
|
|
32553
32652
|
}
|
|
32653
|
+
function channelSessionPortForwardWatcherOptions(args) {
|
|
32654
|
+
if (args.rootPid === void 0 && args.start === void 0) {
|
|
32655
|
+
return void 0;
|
|
32656
|
+
}
|
|
32657
|
+
return {
|
|
32658
|
+
...args.rootPid === void 0 ? {} : { rootPid: args.rootPid },
|
|
32659
|
+
...args.start === void 0 ? {} : { start: args.start }
|
|
32660
|
+
};
|
|
32661
|
+
}
|
|
32554
32662
|
function threadRunnerOptions(args) {
|
|
32555
32663
|
const runtimeSettings = startInstanceRuntimeSettings(
|
|
32556
32664
|
args.options,
|
|
@@ -32558,7 +32666,7 @@ function threadRunnerOptions(args) {
|
|
|
32558
32666
|
);
|
|
32559
32667
|
return {
|
|
32560
32668
|
...args.options,
|
|
32561
|
-
clientId:
|
|
32669
|
+
clientId: void 0,
|
|
32562
32670
|
machineId: void 0,
|
|
32563
32671
|
runnerLockConfigPath: void 0,
|
|
32564
32672
|
workspaceSlug: args.workspaceSlug,
|
|
@@ -32570,10 +32678,10 @@ function threadRunnerOptions(args) {
|
|
|
32570
32678
|
editorRuntime: void 0,
|
|
32571
32679
|
threadProcess: {
|
|
32572
32680
|
role: "thread",
|
|
32573
|
-
kandanThreadId: args.kandanThreadId
|
|
32574
|
-
initialControl: args.control
|
|
32681
|
+
kandanThreadId: args.kandanThreadId
|
|
32575
32682
|
},
|
|
32576
32683
|
spawnThreadRunner: void 0,
|
|
32684
|
+
threadRunnerReadyTimeoutMs: args.options.threadRunnerReadyTimeoutMs,
|
|
32577
32685
|
runtimeDefaults: {
|
|
32578
32686
|
model: runtimeSettings.model,
|
|
32579
32687
|
reasoningEffort: runtimeSettings.reasoningEffort,
|
|
@@ -32601,6 +32709,7 @@ async function closeThreadRunnerEntry(entry) {
|
|
|
32601
32709
|
}
|
|
32602
32710
|
async function spawnLocalThreadRunnerProcess(options) {
|
|
32603
32711
|
const scriptPath = process.argv[1];
|
|
32712
|
+
const kandanThreadId = options.threadProcess?.kandanThreadId ?? "";
|
|
32604
32713
|
if (scriptPath === void 0 || scriptPath.trim() === "") {
|
|
32605
32714
|
throw new Error(
|
|
32606
32715
|
"cannot fork thread runner without current CLI script path"
|
|
@@ -32610,14 +32719,7 @@ async function spawnLocalThreadRunnerProcess(options) {
|
|
|
32610
32719
|
const env = {
|
|
32611
32720
|
...process.env,
|
|
32612
32721
|
LINZUMI_THREAD_RUNNER_ROLE: "thread",
|
|
32613
|
-
|
|
32614
|
-
LINZUMI_THREAD_RUNNER_CLIENT_ID: options.clientId ?? `${options.runnerId}:thread`,
|
|
32615
|
-
LINZUMI_THREAD_RUNNER_KANDAN_THREAD_ID: options.threadProcess?.kandanThreadId ?? "",
|
|
32616
|
-
...options.threadProcess?.initialControl === void 0 ? {} : {
|
|
32617
|
-
LINZUMI_THREAD_RUNNER_INITIAL_CONTROL: JSON.stringify(
|
|
32618
|
-
options.threadProcess.initialControl
|
|
32619
|
-
)
|
|
32620
|
-
}
|
|
32722
|
+
LINZUMI_THREAD_RUNNER_KANDAN_THREAD_ID: kandanThreadId
|
|
32621
32723
|
};
|
|
32622
32724
|
writeCliAuditEvent("process.spawn", {
|
|
32623
32725
|
command: process.execPath,
|
|
@@ -32628,7 +32730,7 @@ async function spawnLocalThreadRunnerProcess(options) {
|
|
|
32628
32730
|
const child = spawn6(process.execPath, [scriptPath, ...args], {
|
|
32629
32731
|
cwd: options.cwd,
|
|
32630
32732
|
env,
|
|
32631
|
-
stdio: "inherit"
|
|
32733
|
+
stdio: ["inherit", "inherit", "inherit", "ipc"]
|
|
32632
32734
|
});
|
|
32633
32735
|
writeCliAuditEvent("process.spawned", {
|
|
32634
32736
|
command: process.execPath,
|
|
@@ -32655,8 +32757,64 @@ async function spawnLocalThreadRunnerProcess(options) {
|
|
|
32655
32757
|
}
|
|
32656
32758
|
exitListeners.clear();
|
|
32657
32759
|
});
|
|
32760
|
+
const ready2 = await new Promise((resolve11, reject) => {
|
|
32761
|
+
let settled = false;
|
|
32762
|
+
let timeout;
|
|
32763
|
+
const cleanupReadyListeners = () => {
|
|
32764
|
+
if (timeout !== void 0) {
|
|
32765
|
+
clearTimeout(timeout);
|
|
32766
|
+
}
|
|
32767
|
+
child.off("message", onMessage);
|
|
32768
|
+
child.off("exit", onExitBeforeReady);
|
|
32769
|
+
};
|
|
32770
|
+
const settle = (action) => {
|
|
32771
|
+
if (settled) {
|
|
32772
|
+
return;
|
|
32773
|
+
}
|
|
32774
|
+
settled = true;
|
|
32775
|
+
cleanupReadyListeners();
|
|
32776
|
+
action();
|
|
32777
|
+
};
|
|
32778
|
+
const onMessage = (message) => {
|
|
32779
|
+
const parsed = (() => {
|
|
32780
|
+
try {
|
|
32781
|
+
return threadRunnerReadyMessage(message, kandanThreadId);
|
|
32782
|
+
} catch (error51) {
|
|
32783
|
+
settle(
|
|
32784
|
+
() => reject(error51 instanceof Error ? error51 : new Error(String(error51)))
|
|
32785
|
+
);
|
|
32786
|
+
return void 0;
|
|
32787
|
+
}
|
|
32788
|
+
})();
|
|
32789
|
+
if (parsed === void 0) {
|
|
32790
|
+
return;
|
|
32791
|
+
}
|
|
32792
|
+
settle(() => resolve11(parsed));
|
|
32793
|
+
};
|
|
32794
|
+
const onExitBeforeReady = (code, signal) => {
|
|
32795
|
+
settle(
|
|
32796
|
+
() => reject(
|
|
32797
|
+
new Error(
|
|
32798
|
+
`thread Codex worker exited before ready: code=${code ?? "null"} signal=${signal ?? "null"}`
|
|
32799
|
+
)
|
|
32800
|
+
)
|
|
32801
|
+
);
|
|
32802
|
+
};
|
|
32803
|
+
const onReadyTimeout = () => {
|
|
32804
|
+
settle(() => {
|
|
32805
|
+
child.kill("SIGINT");
|
|
32806
|
+
reject(threadRunnerReadyTimeoutError(kandanThreadId, readyTimeoutMs));
|
|
32807
|
+
});
|
|
32808
|
+
};
|
|
32809
|
+
child.on("message", onMessage);
|
|
32810
|
+
child.once("exit", onExitBeforeReady);
|
|
32811
|
+
const readyTimeoutMs = threadRunnerReadyTimeoutMs(options);
|
|
32812
|
+
timeout = setTimeout(onReadyTimeout, readyTimeoutMs);
|
|
32813
|
+
});
|
|
32658
32814
|
return {
|
|
32659
|
-
kandanThreadId:
|
|
32815
|
+
kandanThreadId: ready2.kandanThreadId,
|
|
32816
|
+
codexUrl: ready2.codexUrl,
|
|
32817
|
+
processPid: child.pid,
|
|
32660
32818
|
onExit: (listener) => {
|
|
32661
32819
|
if (exitState.exited) {
|
|
32662
32820
|
queueMicrotask(listener);
|
|
@@ -32674,6 +32832,79 @@ async function spawnLocalThreadRunnerProcess(options) {
|
|
|
32674
32832
|
})
|
|
32675
32833
|
};
|
|
32676
32834
|
}
|
|
32835
|
+
function threadRunnerReadyMessage(message, expectedKandanThreadId) {
|
|
32836
|
+
if (!isJsonObject(message)) {
|
|
32837
|
+
return void 0;
|
|
32838
|
+
}
|
|
32839
|
+
if (message.type !== "linzumi_thread_codex_worker_ready") {
|
|
32840
|
+
return void 0;
|
|
32841
|
+
}
|
|
32842
|
+
const kandanThreadId = stringValue(message.kandanThreadId);
|
|
32843
|
+
const codexUrl = stringValue(message.codexUrl);
|
|
32844
|
+
if (kandanThreadId !== expectedKandanThreadId || codexUrl === void 0) {
|
|
32845
|
+
throw new Error("thread Codex worker reported invalid ready payload");
|
|
32846
|
+
}
|
|
32847
|
+
return { kandanThreadId, codexUrl };
|
|
32848
|
+
}
|
|
32849
|
+
function waitForThreadCodexWorkerStop(codexProcess) {
|
|
32850
|
+
return new Promise((resolve11) => {
|
|
32851
|
+
const stop = once(() => {
|
|
32852
|
+
process.off("disconnect", stop);
|
|
32853
|
+
process.off("SIGINT", stop);
|
|
32854
|
+
process.off("SIGTERM", stop);
|
|
32855
|
+
codexProcess.off("exit", stop);
|
|
32856
|
+
resolve11();
|
|
32857
|
+
});
|
|
32858
|
+
process.once("disconnect", stop);
|
|
32859
|
+
process.once("SIGINT", stop);
|
|
32860
|
+
process.once("SIGTERM", stop);
|
|
32861
|
+
codexProcess.once("exit", stop);
|
|
32862
|
+
});
|
|
32863
|
+
}
|
|
32864
|
+
function withThreadRunnerReadyTimeout(promise2, args) {
|
|
32865
|
+
return new Promise((resolve11, reject) => {
|
|
32866
|
+
let settled = false;
|
|
32867
|
+
const timeout = setTimeout(() => {
|
|
32868
|
+
if (settled) {
|
|
32869
|
+
return;
|
|
32870
|
+
}
|
|
32871
|
+
settled = true;
|
|
32872
|
+
reject(
|
|
32873
|
+
threadRunnerReadyTimeoutError(args.kandanThreadId, args.timeoutMs)
|
|
32874
|
+
);
|
|
32875
|
+
}, args.timeoutMs);
|
|
32876
|
+
promise2.then(
|
|
32877
|
+
(handle) => {
|
|
32878
|
+
if (settled) {
|
|
32879
|
+
return;
|
|
32880
|
+
}
|
|
32881
|
+
settled = true;
|
|
32882
|
+
clearTimeout(timeout);
|
|
32883
|
+
resolve11(handle);
|
|
32884
|
+
},
|
|
32885
|
+
(error51) => {
|
|
32886
|
+
if (settled) {
|
|
32887
|
+
return;
|
|
32888
|
+
}
|
|
32889
|
+
settled = true;
|
|
32890
|
+
clearTimeout(timeout);
|
|
32891
|
+
reject(error51);
|
|
32892
|
+
}
|
|
32893
|
+
);
|
|
32894
|
+
});
|
|
32895
|
+
}
|
|
32896
|
+
function threadRunnerReadyTimeoutError(kandanThreadId, timeoutMs) {
|
|
32897
|
+
return new Error(
|
|
32898
|
+
`thread Codex worker did not report ready within ${timeoutMs}ms for Kandan thread ${kandanThreadId}`
|
|
32899
|
+
);
|
|
32900
|
+
}
|
|
32901
|
+
function threadRunnerReadyTimeoutMs(options) {
|
|
32902
|
+
const timeoutMs = options.threadRunnerReadyTimeoutMs ?? THREAD_RUNNER_READY_TIMEOUT_MS;
|
|
32903
|
+
if (Number.isFinite(timeoutMs) && timeoutMs >= 0) {
|
|
32904
|
+
return timeoutMs;
|
|
32905
|
+
}
|
|
32906
|
+
throw new Error("thread runner ready timeout must be a non-negative number");
|
|
32907
|
+
}
|
|
32677
32908
|
function threadRunnerCliArgs(options) {
|
|
32678
32909
|
return [
|
|
32679
32910
|
"--api-url",
|
|
@@ -32722,17 +32953,17 @@ function redactedThreadRunnerCliArgs(args) {
|
|
|
32722
32953
|
function optionalCliValue(flag, value) {
|
|
32723
32954
|
return value === void 0 || value === "" ? [] : [flag, value];
|
|
32724
32955
|
}
|
|
32725
|
-
async function startOwnedCodexAppServer(options) {
|
|
32956
|
+
async function startOwnedCodexAppServer(options, args = { linzumiMcp: true }) {
|
|
32726
32957
|
ensureCodexProjectTrusted(options.cwd);
|
|
32727
32958
|
const defaults = runnerRuntimeDefaults(options);
|
|
32728
|
-
const mcpAuth = writeEphemeralMcpAuthFile(options);
|
|
32959
|
+
const mcpAuth = args.linzumiMcp === true ? writeEphemeralMcpAuthFile(options) : void 0;
|
|
32729
32960
|
const mcpCommand = currentLinzumiCommand();
|
|
32730
32961
|
try {
|
|
32731
32962
|
const started = await startCodexAppServer(options.codexBin, options.cwd, {
|
|
32732
32963
|
model: defaults.model,
|
|
32733
32964
|
reasoningEffort: defaults.reasoningEffort,
|
|
32734
32965
|
fast: options.fast,
|
|
32735
|
-
mcpServers: [
|
|
32966
|
+
mcpServers: mcpAuth === void 0 ? [] : [
|
|
32736
32967
|
linzumiMcpServerConfig({
|
|
32737
32968
|
command: mcpCommand.command,
|
|
32738
32969
|
argsPrefix: mcpCommand.argsPrefix,
|
|
@@ -32742,7 +32973,7 @@ async function startOwnedCodexAppServer(options) {
|
|
|
32742
32973
|
})
|
|
32743
32974
|
]
|
|
32744
32975
|
});
|
|
32745
|
-
const cleanup = once(mcpAuth
|
|
32976
|
+
const cleanup = once(() => mcpAuth?.cleanup());
|
|
32746
32977
|
started.process.once("exit", cleanup);
|
|
32747
32978
|
return {
|
|
32748
32979
|
...started,
|
|
@@ -32752,7 +32983,7 @@ async function startOwnedCodexAppServer(options) {
|
|
|
32752
32983
|
}
|
|
32753
32984
|
};
|
|
32754
32985
|
} catch (error51) {
|
|
32755
|
-
mcpAuth
|
|
32986
|
+
mcpAuth?.cleanup();
|
|
32756
32987
|
throw error51;
|
|
32757
32988
|
}
|
|
32758
32989
|
}
|
|
@@ -63133,24 +63364,22 @@ async function main(args) {
|
|
|
63133
63364
|
return;
|
|
63134
63365
|
case "agentRunner": {
|
|
63135
63366
|
const options = await parseAgentRunnerArgs(parsed.args);
|
|
63136
|
-
await runLocalCodexRunner(
|
|
63137
|
-
withLocalMachineId(withThreadRunnerEnv(options))
|
|
63138
|
-
);
|
|
63367
|
+
await runLocalCodexRunner(withLocalMachineId(options));
|
|
63139
63368
|
return;
|
|
63140
63369
|
}
|
|
63141
63370
|
case "start": {
|
|
63142
63371
|
const options = await parseStartRunnerArgs(parsed.args);
|
|
63143
63372
|
addAllowedCwdForLinzumiUrl(options.cwd, options.kandanUrl);
|
|
63144
|
-
await runLocalCodexRunner(
|
|
63145
|
-
withLocalMachineId(withThreadRunnerEnv(options))
|
|
63146
|
-
);
|
|
63373
|
+
await runLocalCodexRunner(withLocalMachineId(options));
|
|
63147
63374
|
return;
|
|
63148
63375
|
}
|
|
63149
63376
|
case "run": {
|
|
63377
|
+
if (process.env.LINZUMI_THREAD_RUNNER_ROLE === "thread") {
|
|
63378
|
+
await runThreadCodexWorker(parseThreadCodexWorkerArgs(parsed.args));
|
|
63379
|
+
return;
|
|
63380
|
+
}
|
|
63150
63381
|
const options = await parseRunnerArgs(parsed.args);
|
|
63151
|
-
await runLocalCodexRunner(
|
|
63152
|
-
withLocalMachineId(withThreadRunnerEnv(options))
|
|
63153
|
-
);
|
|
63382
|
+
await runLocalCodexRunner(withLocalMachineId(options));
|
|
63154
63383
|
return;
|
|
63155
63384
|
}
|
|
63156
63385
|
}
|
|
@@ -63779,7 +64008,13 @@ async function parseRunnerArgs(args, deps = {
|
|
|
63779
64008
|
) : [...localConfiguredAllowedCwds.allowedCwds];
|
|
63780
64009
|
const codexBin = stringValue5(values, "codex-bin") ?? "codex";
|
|
63781
64010
|
const customCodeServerBin = stringValue5(values, "code-server-bin");
|
|
63782
|
-
const
|
|
64011
|
+
const initialDependencyStatus = await deps.buildDependencyStatus({
|
|
64012
|
+
cwd,
|
|
64013
|
+
codexBin,
|
|
64014
|
+
codeServerBin: customCodeServerBin
|
|
64015
|
+
});
|
|
64016
|
+
assertStartDependencies(initialDependencyStatus);
|
|
64017
|
+
const explicitToken = stringValue5(values, "token");
|
|
63783
64018
|
const token = await deps.resolveToken({
|
|
63784
64019
|
kandanUrl,
|
|
63785
64020
|
explicitToken,
|
|
@@ -64023,57 +64258,51 @@ function withLocalMachineId(options) {
|
|
|
64023
64258
|
machineId: localConfigScopeKey(options.kandanUrl) === localConfigScopeKey(defaultLinzumiWebSocketUrl) ? ensureLocalMachineId() : ensureLocalMachineIdForLinzumiUrl(options.kandanUrl)
|
|
64024
64259
|
};
|
|
64025
64260
|
}
|
|
64026
|
-
function
|
|
64027
|
-
|
|
64028
|
-
|
|
64029
|
-
|
|
64030
|
-
const
|
|
64031
|
-
|
|
64032
|
-
|
|
64033
|
-
|
|
64034
|
-
);
|
|
64035
|
-
}
|
|
64261
|
+
function parseThreadCodexWorkerArgs(args) {
|
|
64262
|
+
const values = strictFlagValues2(args);
|
|
64263
|
+
const kandanUrl = kandanUrlValue(values) ?? defaultLinzumiWebSocketUrl;
|
|
64264
|
+
const cwd = stringValue5(values, "cwd") ?? process.cwd();
|
|
64265
|
+
const configuredAllowedCwds2 = values.has("allowed-cwd") ? assertConfiguredAllowedCwds(
|
|
64266
|
+
parseAllowedCwdList(stringValue5(values, "allowed-cwd"))
|
|
64267
|
+
) : assertConfiguredAllowedCwds([cwd]);
|
|
64268
|
+
const kandanThreadId = requiredThreadRunnerKandanThreadId();
|
|
64036
64269
|
return {
|
|
64037
|
-
|
|
64038
|
-
|
|
64270
|
+
kandanUrl,
|
|
64271
|
+
token: "",
|
|
64272
|
+
runnerId: `thread-codex-worker:${kandanThreadId}`,
|
|
64039
64273
|
machineId: void 0,
|
|
64040
64274
|
runnerLockConfigPath: void 0,
|
|
64275
|
+
workspaceSlug: stringValue5(values, "workspace"),
|
|
64276
|
+
cwd,
|
|
64277
|
+
codexBin: stringValue5(values, "codex-bin") ?? "codex",
|
|
64041
64278
|
codexUrl: void 0,
|
|
64042
64279
|
launchTui: false,
|
|
64280
|
+
fast: values.get("fast") === true ? true : void 0,
|
|
64281
|
+
logFile: stringValue5(values, "log-file"),
|
|
64282
|
+
allowedCwds: configuredAllowedCwds2.allowedCwds,
|
|
64283
|
+
missingAllowedCwds: configuredAllowedCwds2.missingAllowedCwds,
|
|
64284
|
+
allowedForwardPorts: parseAllowedPortList(
|
|
64285
|
+
stringValue5(values, "forward-port")
|
|
64286
|
+
),
|
|
64287
|
+
codeServerBin: void 0,
|
|
64288
|
+
editorRuntime: void 0,
|
|
64289
|
+
socketFactory: void 0,
|
|
64290
|
+
runtimeDefaults: runnerRuntimeDefaultsFromValues(values),
|
|
64043
64291
|
threadProcess: {
|
|
64044
64292
|
role: "thread",
|
|
64045
|
-
kandanThreadId
|
|
64046
|
-
initialControl: initialThreadControlFromEnv()
|
|
64293
|
+
kandanThreadId
|
|
64047
64294
|
},
|
|
64048
64295
|
channelSession: void 0
|
|
64049
64296
|
};
|
|
64050
64297
|
}
|
|
64051
|
-
function
|
|
64052
|
-
|
|
64053
|
-
|
|
64054
|
-
|
|
64055
|
-
|
|
64056
|
-
|
|
64057
|
-
throw new Error("thread runner is missing LINZUMI_THREAD_RUNNER_TOKEN");
|
|
64058
|
-
}
|
|
64059
|
-
return token;
|
|
64060
|
-
}
|
|
64061
|
-
function initialThreadControlFromEnv() {
|
|
64062
|
-
const raw = process.env.LINZUMI_THREAD_RUNNER_INITIAL_CONTROL;
|
|
64063
|
-
if (raw === void 0 || raw.trim() === "") {
|
|
64064
|
-
return void 0;
|
|
64065
|
-
}
|
|
64066
|
-
const parsed = JSON.parse(raw);
|
|
64067
|
-
if (parsed === null || typeof parsed !== "object" || !("type" in parsed)) {
|
|
64068
|
-
throw new Error("thread runner initial control is invalid");
|
|
64069
|
-
}
|
|
64070
|
-
switch (parsed.type) {
|
|
64071
|
-
case "start_instance":
|
|
64072
|
-
case "reconnect_thread":
|
|
64073
|
-
return parsed;
|
|
64074
|
-
default:
|
|
64075
|
-
throw new Error("thread runner initial control type is invalid");
|
|
64298
|
+
function requiredThreadRunnerKandanThreadId() {
|
|
64299
|
+
const kandanThreadId = process.env.LINZUMI_THREAD_RUNNER_KANDAN_THREAD_ID;
|
|
64300
|
+
if (kandanThreadId === void 0 || kandanThreadId.trim() === "") {
|
|
64301
|
+
throw new Error(
|
|
64302
|
+
"thread runner is missing LINZUMI_THREAD_RUNNER_KANDAN_THREAD_ID"
|
|
64303
|
+
);
|
|
64076
64304
|
}
|
|
64305
|
+
return kandanThreadId;
|
|
64077
64306
|
}
|
|
64078
64307
|
function required3(values, key) {
|
|
64079
64308
|
const value = stringValue5(values, key);
|
package/package.json
CHANGED