@linzumi/cli 0.0.97-beta → 0.0.99-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 +115 -22
- package/package.json +1 -1
package/README.md
CHANGED
package/dist/index.js
CHANGED
|
@@ -14705,7 +14705,16 @@ function linzumiMcpServerConfig(options) {
|
|
|
14705
14705
|
...options.toolScope === void 0 || options.toolScope === "all" ? [] : ["--tool-scope", options.toolScope]
|
|
14706
14706
|
],
|
|
14707
14707
|
env: {
|
|
14708
|
-
...options.accessToken === void 0 ? {} : { LINZUMI_MCP_ACCESS_TOKEN: options.accessToken }
|
|
14708
|
+
...options.accessToken === void 0 ? {} : { LINZUMI_MCP_ACCESS_TOKEN: options.accessToken },
|
|
14709
|
+
// The Linzumi metadata MCP is launched by codex as a STDIO child whose
|
|
14710
|
+
// `command` may be the Electron app binary. That binary only behaves as a
|
|
14711
|
+
// plain Node process (and thus boots the MCP server instead of a GUI
|
|
14712
|
+
// shell) when ELECTRON_RUN_AS_NODE=1 is present in its env. Newer codex
|
|
14713
|
+
// sanitizes MCP-child env to an allowlist that drops ELECTRON_RUN_AS_NODE,
|
|
14714
|
+
// so we both (a) pin it here and (b) explicitly forward it via
|
|
14715
|
+
// codexMcpConfigArgs / codexMcpConfigToml below. For a real Node `command`
|
|
14716
|
+
// this flag is a harmless no-op, so we always include it.
|
|
14717
|
+
ELECTRON_RUN_AS_NODE: "1"
|
|
14709
14718
|
}
|
|
14710
14719
|
};
|
|
14711
14720
|
}
|
|
@@ -14714,7 +14723,16 @@ function codexMcpConfigArgs(config) {
|
|
|
14714
14723
|
"-c",
|
|
14715
14724
|
`mcp_servers.${config.name}.command=${JSON.stringify(config.command)}`,
|
|
14716
14725
|
"-c",
|
|
14717
|
-
`mcp_servers.${config.name}.args=${tomlStringArray(config.args)}
|
|
14726
|
+
`mcp_servers.${config.name}.args=${tomlStringArray(config.args)}`,
|
|
14727
|
+
// Explicitly forward the server env (ELECTRON_RUN_AS_NODE,
|
|
14728
|
+
// LINZUMI_MCP_ACCESS_TOKEN, …) so codex passes it to the stdio child
|
|
14729
|
+
// regardless of its env-forwarding/sanitization allowlist. Without this,
|
|
14730
|
+
// newer codex strips ELECTRON_RUN_AS_NODE and the Electron-binary `command`
|
|
14731
|
+
// boots a GUI shell that pollutes the MCP stdout JSON-RPC framing.
|
|
14732
|
+
...Object.entries(config.env).flatMap(([key, value]) => [
|
|
14733
|
+
"-c",
|
|
14734
|
+
`mcp_servers.${config.name}.env.${key}=${JSON.stringify(value)}`
|
|
14735
|
+
])
|
|
14718
14736
|
];
|
|
14719
14737
|
}
|
|
14720
14738
|
function linzumiMcpCommandForProcess(processExecPath, scriptPath, execArgv = []) {
|
|
@@ -19785,7 +19803,7 @@ var linzumiCliVersion, linzumiCliVersionText;
|
|
|
19785
19803
|
var init_version = __esm({
|
|
19786
19804
|
"src/version.ts"() {
|
|
19787
19805
|
"use strict";
|
|
19788
|
-
linzumiCliVersion = "0.0.
|
|
19806
|
+
linzumiCliVersion = "0.0.99-beta";
|
|
19789
19807
|
linzumiCliVersionText = `linzumi ${linzumiCliVersion}`;
|
|
19790
19808
|
}
|
|
19791
19809
|
});
|
|
@@ -24561,6 +24579,17 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
|
|
|
24561
24579
|
}
|
|
24562
24580
|
const dynamicChannelSessions = /* @__PURE__ */ new Map();
|
|
24563
24581
|
const dynamicChannelSessionAttachInFlight = /* @__PURE__ */ new Map();
|
|
24582
|
+
const dynamicChannelSessionAttachWaiters = /* @__PURE__ */ new Map();
|
|
24583
|
+
const resolveDynamicChannelSessionAttachWaiters = (codexThreadId, session) => {
|
|
24584
|
+
const waiters = dynamicChannelSessionAttachWaiters.get(codexThreadId);
|
|
24585
|
+
if (waiters === void 0) {
|
|
24586
|
+
return;
|
|
24587
|
+
}
|
|
24588
|
+
dynamicChannelSessionAttachWaiters.delete(codexThreadId);
|
|
24589
|
+
for (const waiter of waiters) {
|
|
24590
|
+
waiter(session);
|
|
24591
|
+
}
|
|
24592
|
+
};
|
|
24564
24593
|
const dynamicChannelSessionCodexClients = /* @__PURE__ */ new Map();
|
|
24565
24594
|
const codexTurnFailureGuards = /* @__PURE__ */ new Map();
|
|
24566
24595
|
const lossReportPushes = [];
|
|
@@ -24622,6 +24651,7 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
|
|
|
24622
24651
|
);
|
|
24623
24652
|
dynamicChannelSessions.clear();
|
|
24624
24653
|
dynamicChannelSessionCodexClients.clear();
|
|
24654
|
+
dynamicChannelSessionAttachWaiters.clear();
|
|
24625
24655
|
const claudeSessions = [...activeClaudeCodeSessions.values()];
|
|
24626
24656
|
for (const session of claudeSessions) {
|
|
24627
24657
|
try {
|
|
@@ -24698,6 +24728,28 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
|
|
|
24698
24728
|
}
|
|
24699
24729
|
return true;
|
|
24700
24730
|
};
|
|
24731
|
+
const resolveLiveDynamicChannelSession = async (codexThreadId, options2 = {}) => {
|
|
24732
|
+
const existing = dynamicChannelSessions.get(codexThreadId);
|
|
24733
|
+
if (existing !== void 0) {
|
|
24734
|
+
return existing;
|
|
24735
|
+
}
|
|
24736
|
+
const inFlight = dynamicChannelSessionAttachInFlight.get(codexThreadId);
|
|
24737
|
+
if (inFlight !== void 0) {
|
|
24738
|
+
const attached = await inFlight;
|
|
24739
|
+
if (attached !== void 0) {
|
|
24740
|
+
return attached;
|
|
24741
|
+
}
|
|
24742
|
+
}
|
|
24743
|
+
const settled = dynamicChannelSessions.get(codexThreadId);
|
|
24744
|
+
if (settled !== void 0 || options2.waitForSiblingSpawn !== true) {
|
|
24745
|
+
return settled;
|
|
24746
|
+
}
|
|
24747
|
+
return await new Promise((resolve12) => {
|
|
24748
|
+
const waiters = dynamicChannelSessionAttachWaiters.get(codexThreadId) ?? [];
|
|
24749
|
+
waiters.push(resolve12);
|
|
24750
|
+
dynamicChannelSessionAttachWaiters.set(codexThreadId, waiters);
|
|
24751
|
+
});
|
|
24752
|
+
};
|
|
24701
24753
|
const attachThreadSessionWithCodex = async (args) => {
|
|
24702
24754
|
const { control, cwd, codexThreadId, sessionCodex } = args;
|
|
24703
24755
|
const portForwardWatcherRootPid = args.portForwardWatcherRootPid;
|
|
@@ -24737,6 +24789,11 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
|
|
|
24737
24789
|
threadId: rebuildArgs.kandanThreadId,
|
|
24738
24790
|
codexThreadId: rebuildArgs.codexThreadId,
|
|
24739
24791
|
cwd,
|
|
24792
|
+
// Carry the conversation context through the rebuild-replay so
|
|
24793
|
+
// the respawned worker's developer instructions match what the
|
|
24794
|
+
// server would have replayed (parity with the live reconnect
|
|
24795
|
+
// control built above at channelSession.linzumiContext).
|
|
24796
|
+
...control.linzumiContext === void 0 ? {} : { linzumiContext: control.linzumiContext },
|
|
24740
24797
|
...integerValue(control.rootSeq) === void 0 ? {} : { rootSeq: integerValue(control.rootSeq) },
|
|
24741
24798
|
sourceSeq: message.seq,
|
|
24742
24799
|
workDescription: message.body,
|
|
@@ -24746,19 +24803,42 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
|
|
|
24746
24803
|
...runtimeSettings.approvalPolicy === void 0 ? {} : { approvalPolicy: runtimeSettings.approvalPolicy },
|
|
24747
24804
|
...runtimeSettings.fast === void 0 ? {} : { fast: runtimeSettings.fast }
|
|
24748
24805
|
};
|
|
24749
|
-
const
|
|
24750
|
-
|
|
24751
|
-
|
|
24806
|
+
const replayOntoLiveSession = async (options2) => {
|
|
24807
|
+
const liveSession = await withCodexStartRequestTimeout(
|
|
24808
|
+
"thread/attach",
|
|
24809
|
+
resolveLiveDynamicChannelSession(rebuildArgs.codexThreadId, {
|
|
24810
|
+
waitForSiblingSpawn: options2.waitForSiblingSpawn
|
|
24811
|
+
})
|
|
24812
|
+
);
|
|
24813
|
+
if (liveSession === void 0) {
|
|
24814
|
+
throw new Error(
|
|
24815
|
+
`dead-worker rebuild could not resolve a live session for codex thread ${rebuildArgs.codexThreadId}`
|
|
24816
|
+
);
|
|
24817
|
+
}
|
|
24818
|
+
await liveSession.startThreadMessageTurn({
|
|
24819
|
+
seq: message.seq,
|
|
24820
|
+
body: message.body,
|
|
24821
|
+
actorSlug: message.actorSlug,
|
|
24822
|
+
actorUserId: message.actorUserId,
|
|
24823
|
+
boundStartTimeout: true
|
|
24824
|
+
});
|
|
24825
|
+
};
|
|
24752
24826
|
try {
|
|
24753
|
-
if (
|
|
24754
|
-
await
|
|
24755
|
-
seq: message.seq,
|
|
24756
|
-
body: message.body,
|
|
24757
|
-
actorSlug: message.actorSlug,
|
|
24758
|
-
actorUserId: message.actorUserId
|
|
24759
|
-
});
|
|
24827
|
+
if (rebuilt) {
|
|
24828
|
+
await replayOntoLiveSession({ waitForSiblingSpawn: false });
|
|
24760
24829
|
} else {
|
|
24761
|
-
await startThreadRunnerProcess(
|
|
24830
|
+
const startResult = await startThreadRunnerProcess(
|
|
24831
|
+
reconnectControl,
|
|
24832
|
+
cwd
|
|
24833
|
+
);
|
|
24834
|
+
if (threadStartDelegatedToSibling(startResult)) {
|
|
24835
|
+
log2("runner.thread_dead_worker_rebuild_replay_on_sibling", {
|
|
24836
|
+
codex_thread_id: rebuildArgs.codexThreadId,
|
|
24837
|
+
kandan_thread_id: rebuildArgs.kandanThreadId,
|
|
24838
|
+
seq: message.seq
|
|
24839
|
+
});
|
|
24840
|
+
await replayOntoLiveSession({ waitForSiblingSpawn: true });
|
|
24841
|
+
}
|
|
24762
24842
|
}
|
|
24763
24843
|
rebuilt = true;
|
|
24764
24844
|
} catch (error) {
|
|
@@ -24830,6 +24910,7 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
|
|
|
24830
24910
|
});
|
|
24831
24911
|
dynamicChannelSessions.set(codexThreadId, session);
|
|
24832
24912
|
dynamicChannelSessionCodexClients.set(codexThreadId, sessionCodex);
|
|
24913
|
+
resolveDynamicChannelSessionAttachWaiters(codexThreadId, session);
|
|
24833
24914
|
threadSessionRegistry.upsert({
|
|
24834
24915
|
workspace: workspaceSlug,
|
|
24835
24916
|
channel: channelSlug,
|
|
@@ -25949,6 +26030,9 @@ function controlTargetsInstance(control, instanceId) {
|
|
|
25949
26030
|
function controlInstanceId(control) {
|
|
25950
26031
|
return "instanceId" in control ? control.instanceId : void 0;
|
|
25951
26032
|
}
|
|
26033
|
+
function threadStartDelegatedToSibling(startResult) {
|
|
26034
|
+
return startResult !== void 0 && startResult.delegated === true && startResult.threadProcess === "already_started";
|
|
26035
|
+
}
|
|
25952
26036
|
function shouldUseThreadProcesses(options) {
|
|
25953
26037
|
if (options.threadProcess?.role === "thread") {
|
|
25954
26038
|
return false;
|
|
@@ -26506,7 +26590,10 @@ async function resumeCodexThreadForReconnect(codex, codexThreadId, resumeOverrid
|
|
|
26506
26590
|
threadId: codexThreadId,
|
|
26507
26591
|
...resumeOverrides
|
|
26508
26592
|
};
|
|
26509
|
-
const resumeResponse = await
|
|
26593
|
+
const resumeResponse = await withCodexStartRequestTimeout(
|
|
26594
|
+
"thread/resume",
|
|
26595
|
+
codex.request("thread/resume", resumeParams)
|
|
26596
|
+
);
|
|
26510
26597
|
if (!("error" in resumeResponse)) {
|
|
26511
26598
|
return;
|
|
26512
26599
|
}
|
|
@@ -26524,7 +26611,10 @@ async function resumeCodexThreadForReconnect(codex, codexThreadId, resumeOverrid
|
|
|
26524
26611
|
`failed to prepare Codex thread before reconnect: ${injected.error.message}`
|
|
26525
26612
|
);
|
|
26526
26613
|
}
|
|
26527
|
-
const verified = await
|
|
26614
|
+
const verified = await withCodexStartRequestTimeout(
|
|
26615
|
+
"thread/resume",
|
|
26616
|
+
codex.request("thread/resume", resumeParams)
|
|
26617
|
+
);
|
|
26528
26618
|
if ("error" in verified) {
|
|
26529
26619
|
throw new Error(
|
|
26530
26620
|
`failed to verify Codex thread before reconnect: ${verified.error.message}`
|
|
@@ -27089,7 +27179,10 @@ async function applyControl(codex, kandan, topic, instanceId, options, agentProv
|
|
|
27089
27179
|
ensureCodexProjectTrusted(cwd.cwd);
|
|
27090
27180
|
}
|
|
27091
27181
|
const runtimeSettings = startInstanceRuntimeSettings(options, control);
|
|
27092
|
-
const startedThreadSession = onStartedThread === void 0 ? void 0 : await
|
|
27182
|
+
const startedThreadSession = onStartedThread === void 0 ? void 0 : await withCodexStartRequestTimeout(
|
|
27183
|
+
"thread/attach",
|
|
27184
|
+
onStartedThread(control, cwd.cwd, codexThreadId)
|
|
27185
|
+
);
|
|
27093
27186
|
if (workDescription !== void 0) {
|
|
27094
27187
|
const rootSeq = integerValue(control.rootSeq);
|
|
27095
27188
|
const sourceSeq = integerValue(control.sourceSeq) ?? rootSeq;
|
|
@@ -27115,7 +27208,8 @@ async function applyControl(codex, kandan, topic, instanceId, options, agentProv
|
|
|
27115
27208
|
seq: sourceSeq,
|
|
27116
27209
|
body: workDescription,
|
|
27117
27210
|
actorSlug: identity.actorUsername,
|
|
27118
|
-
actorUserId: identity.actorUserId
|
|
27211
|
+
actorUserId: identity.actorUserId,
|
|
27212
|
+
boundStartTimeout: true
|
|
27119
27213
|
});
|
|
27120
27214
|
}
|
|
27121
27215
|
return {
|
|
@@ -27780,10 +27874,9 @@ async function startCodexProviderInstance(args) {
|
|
|
27780
27874
|
let startedThreadSession;
|
|
27781
27875
|
if (codexThreadId !== void 0 && args.onStartedThread !== void 0) {
|
|
27782
27876
|
args.setStartupStage("binding_kandan_thread");
|
|
27783
|
-
startedThreadSession = await
|
|
27784
|
-
|
|
27785
|
-
args.cwd,
|
|
27786
|
-
codexThreadId
|
|
27877
|
+
startedThreadSession = await withCodexStartRequestTimeout(
|
|
27878
|
+
"thread/attach",
|
|
27879
|
+
args.onStartedThread(args.control, args.cwd, codexThreadId)
|
|
27787
27880
|
);
|
|
27788
27881
|
}
|
|
27789
27882
|
if (codexThreadId !== void 0 && workDescription !== void 0) {
|
package/package.json
CHANGED