@linzumi/cli 0.0.93-beta → 0.0.94-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 +184 -7
- package/package.json +1 -1
package/README.md
CHANGED
package/dist/index.js
CHANGED
|
@@ -19376,7 +19376,7 @@ var linzumiCliVersion, linzumiCliVersionText;
|
|
|
19376
19376
|
var init_version = __esm({
|
|
19377
19377
|
"src/version.ts"() {
|
|
19378
19378
|
"use strict";
|
|
19379
|
-
linzumiCliVersion = "0.0.
|
|
19379
|
+
linzumiCliVersion = "0.0.94-beta";
|
|
19380
19380
|
linzumiCliVersionText = `linzumi ${linzumiCliVersion}`;
|
|
19381
19381
|
}
|
|
19382
19382
|
});
|
|
@@ -19487,6 +19487,82 @@ function assessRunnerLockHolder(record, isPidAlive, now) {
|
|
|
19487
19487
|
}
|
|
19488
19488
|
return { state: "live" };
|
|
19489
19489
|
}
|
|
19490
|
+
function shouldAutoTakeOverForUpdate(existing, myVersion, myLaunchSource, holderState) {
|
|
19491
|
+
if (myLaunchSource !== electronAutoConnectLaunchSource) {
|
|
19492
|
+
return false;
|
|
19493
|
+
}
|
|
19494
|
+
if (existing.launchSource !== electronAutoConnectLaunchSource) {
|
|
19495
|
+
return false;
|
|
19496
|
+
}
|
|
19497
|
+
if (holderState.state !== "live") {
|
|
19498
|
+
return true;
|
|
19499
|
+
}
|
|
19500
|
+
return compareCliVersions(myVersion, existing.cliVersion) > 0;
|
|
19501
|
+
}
|
|
19502
|
+
function compareCliVersions(a, b) {
|
|
19503
|
+
const pa = parseCliVersion(a);
|
|
19504
|
+
const pb = parseCliVersion(b);
|
|
19505
|
+
for (let i = 0; i < 3; i++) {
|
|
19506
|
+
if (pa.core[i] !== pb.core[i]) {
|
|
19507
|
+
return pa.core[i] > pb.core[i] ? 1 : -1;
|
|
19508
|
+
}
|
|
19509
|
+
}
|
|
19510
|
+
if (pa.prerelease.length === 0 && pb.prerelease.length === 0) {
|
|
19511
|
+
return 0;
|
|
19512
|
+
}
|
|
19513
|
+
if (pa.prerelease.length === 0) {
|
|
19514
|
+
return 1;
|
|
19515
|
+
}
|
|
19516
|
+
if (pb.prerelease.length === 0) {
|
|
19517
|
+
return -1;
|
|
19518
|
+
}
|
|
19519
|
+
return comparePrerelease(pa.prerelease, pb.prerelease);
|
|
19520
|
+
}
|
|
19521
|
+
function parseCliVersion(value) {
|
|
19522
|
+
const trimmed = value.trim().replace(/^v/i, "").split("+", 1)[0] ?? "";
|
|
19523
|
+
const hyphen = trimmed.indexOf("-");
|
|
19524
|
+
const coreText = hyphen === -1 ? trimmed : trimmed.slice(0, hyphen);
|
|
19525
|
+
const prereleaseText = hyphen === -1 ? "" : trimmed.slice(hyphen + 1);
|
|
19526
|
+
const parts = coreText.split(".");
|
|
19527
|
+
const core = [
|
|
19528
|
+
parseCoreNumber(parts[0]),
|
|
19529
|
+
parseCoreNumber(parts[1]),
|
|
19530
|
+
parseCoreNumber(parts[2])
|
|
19531
|
+
];
|
|
19532
|
+
const prerelease = prereleaseText === "" ? [] : prereleaseText.split(".").filter((id) => id !== "");
|
|
19533
|
+
return { core, prerelease };
|
|
19534
|
+
}
|
|
19535
|
+
function parseCoreNumber(value) {
|
|
19536
|
+
const parsed = Number.parseInt(value ?? "", 10);
|
|
19537
|
+
return Number.isInteger(parsed) && parsed >= 0 ? parsed : 0;
|
|
19538
|
+
}
|
|
19539
|
+
function comparePrerelease(a, b) {
|
|
19540
|
+
const length = Math.max(a.length, b.length);
|
|
19541
|
+
for (let i = 0; i < length; i++) {
|
|
19542
|
+
if (i >= a.length) {
|
|
19543
|
+
return -1;
|
|
19544
|
+
}
|
|
19545
|
+
if (i >= b.length) {
|
|
19546
|
+
return 1;
|
|
19547
|
+
}
|
|
19548
|
+
const idA = a[i];
|
|
19549
|
+
const idB = b[i];
|
|
19550
|
+
const numA = Number.parseInt(idA, 10);
|
|
19551
|
+
const numB = Number.parseInt(idB, 10);
|
|
19552
|
+
const aIsNum = numA.toString() === idA;
|
|
19553
|
+
const bIsNum = numB.toString() === idB;
|
|
19554
|
+
if (aIsNum && bIsNum) {
|
|
19555
|
+
if (numA !== numB) {
|
|
19556
|
+
return numA > numB ? 1 : -1;
|
|
19557
|
+
}
|
|
19558
|
+
} else if (aIsNum !== bIsNum) {
|
|
19559
|
+
return aIsNum ? -1 : 1;
|
|
19560
|
+
} else if (idA !== idB) {
|
|
19561
|
+
return idA > idB ? 1 : -1;
|
|
19562
|
+
}
|
|
19563
|
+
}
|
|
19564
|
+
return 0;
|
|
19565
|
+
}
|
|
19490
19566
|
function takeOverWedgedHolder(lockPath, holder, reason, killPid, onTakeover) {
|
|
19491
19567
|
try {
|
|
19492
19568
|
killPid(holder.pid);
|
|
@@ -19754,7 +19830,7 @@ function displayLinzumiUrl(linzumiUrl) {
|
|
|
19754
19830
|
function isNodeErrorCode2(error, code) {
|
|
19755
19831
|
return typeof error === "object" && error !== null && "code" in error && error.code === code;
|
|
19756
19832
|
}
|
|
19757
|
-
var runnerLockHeartbeatIntervalMs, runnerLockTakeoverAfterMs, runnerLockHeldErrorName, RunnerLockHeldError;
|
|
19833
|
+
var runnerLockHeartbeatIntervalMs, runnerLockTakeoverAfterMs, runnerLockHeldErrorName, RunnerLockHeldError, electronAutoConnectLaunchSource;
|
|
19758
19834
|
var init_runnerLock = __esm({
|
|
19759
19835
|
"src/runnerLock.ts"() {
|
|
19760
19836
|
"use strict";
|
|
@@ -19775,6 +19851,7 @@ var init_runnerLock = __esm({
|
|
|
19775
19851
|
this.heldBy = heldBy;
|
|
19776
19852
|
}
|
|
19777
19853
|
};
|
|
19854
|
+
electronAutoConnectLaunchSource = "electron_auto_connect";
|
|
19778
19855
|
}
|
|
19779
19856
|
});
|
|
19780
19857
|
|
|
@@ -25632,6 +25709,43 @@ async function acquireRunnerLockWithConflictResolution(acquire, options, log2) {
|
|
|
25632
25709
|
lockPath: error.lockPath
|
|
25633
25710
|
});
|
|
25634
25711
|
const lockTakeover = options.lockTakeover;
|
|
25712
|
+
const autoTakeoverDeps = resolveRunnerLockTakeoverDeps(
|
|
25713
|
+
error.lockPath,
|
|
25714
|
+
lockTakeover?.takeover,
|
|
25715
|
+
log2
|
|
25716
|
+
);
|
|
25717
|
+
const holderState = assessRunnerLockHolder(
|
|
25718
|
+
error.heldBy,
|
|
25719
|
+
autoTakeoverDeps.isPidAlive,
|
|
25720
|
+
() => new Date(autoTakeoverDeps.now())
|
|
25721
|
+
);
|
|
25722
|
+
if (shouldAutoTakeOverForUpdate(
|
|
25723
|
+
error.heldBy,
|
|
25724
|
+
linzumiCliVersion,
|
|
25725
|
+
options.launchSource,
|
|
25726
|
+
holderState
|
|
25727
|
+
)) {
|
|
25728
|
+
log2("runner.lock_auto_takeover_for_update", {
|
|
25729
|
+
runnerId: options.runnerId,
|
|
25730
|
+
heldByRunnerId: error.heldBy.runnerId,
|
|
25731
|
+
heldByPid: error.heldBy.pid,
|
|
25732
|
+
lockPath: error.lockPath,
|
|
25733
|
+
fromVersion: error.heldBy.cliVersion,
|
|
25734
|
+
toVersion: linzumiCliVersion,
|
|
25735
|
+
launchSource: electronAutoConnectLaunchSource,
|
|
25736
|
+
holderState: holderState.state
|
|
25737
|
+
});
|
|
25738
|
+
const autoPromptDeps = lockTakeover?.prompt ?? defaultRunnerLockTakeoverPromptDeps(lockTakeover);
|
|
25739
|
+
await resolveRunnerLockConflict({
|
|
25740
|
+
holder: error.heldBy,
|
|
25741
|
+
lockPath: error.lockPath,
|
|
25742
|
+
baseMessage: error.message,
|
|
25743
|
+
takeOverWithoutPrompt: true,
|
|
25744
|
+
prompt: autoPromptDeps,
|
|
25745
|
+
takeover: autoTakeoverDeps
|
|
25746
|
+
});
|
|
25747
|
+
return acquire();
|
|
25748
|
+
}
|
|
25635
25749
|
if (!shouldResolveRunnerLockConflict(lockTakeover)) {
|
|
25636
25750
|
throw error;
|
|
25637
25751
|
}
|
|
@@ -25848,6 +25962,32 @@ async function resumeCodexThreadForReconnect(codex, codexThreadId, resumeOverrid
|
|
|
25848
25962
|
);
|
|
25849
25963
|
}
|
|
25850
25964
|
}
|
|
25965
|
+
async function applyCodexUnavailableControl(kandan, topic, instanceId, control, log2) {
|
|
25966
|
+
const error = "agent_provider_unavailable:codex";
|
|
25967
|
+
log2("kandan.start_instance_codex_app_server_unavailable", {
|
|
25968
|
+
controlType: control.type,
|
|
25969
|
+
thread_id: controlThreadId(control) ?? null,
|
|
25970
|
+
instanceId
|
|
25971
|
+
});
|
|
25972
|
+
if (control.type === "start_instance" || control.type === "reconnect_thread") {
|
|
25973
|
+
try {
|
|
25974
|
+
await publishStartInstanceMessageState(
|
|
25975
|
+
kandan,
|
|
25976
|
+
topic,
|
|
25977
|
+
control,
|
|
25978
|
+
"failed",
|
|
25979
|
+
error,
|
|
25980
|
+
{ instanceId }
|
|
25981
|
+
);
|
|
25982
|
+
} catch (publishError) {
|
|
25983
|
+
log2("kandan.start_instance_unavailable_state_push_failed", {
|
|
25984
|
+
agent_provider: "codex",
|
|
25985
|
+
message: publishError instanceof Error ? publishError.message : String(publishError)
|
|
25986
|
+
});
|
|
25987
|
+
}
|
|
25988
|
+
}
|
|
25989
|
+
throw new Error(error);
|
|
25990
|
+
}
|
|
25851
25991
|
async function applyControl(codex, kandan, topic, instanceId, options, agentProviders, allowedCwds, remoteCodexSandboxRunner, activeRemoteCodexExecRequests, activeClaudeCodeSessions, pendingClaudeCodeApprovals, ensureClaudeCodeForwardPortSession, disposeClaudeCodeForwardPortSession, control, log2, onStartedThread, onThreadProcessStart) {
|
|
25852
25992
|
if (codex === void 0) {
|
|
25853
25993
|
switch (control.type) {
|
|
@@ -25861,6 +26001,43 @@ async function applyControl(codex, kandan, topic, instanceId, options, agentProv
|
|
|
25861
26001
|
activeRemoteCodexExecRequests,
|
|
25862
26002
|
log2
|
|
25863
26003
|
);
|
|
26004
|
+
// PROD WEDGE (coding jobs down on the shipped CLI beta): a runner whose
|
|
26005
|
+
// cached dependencyStatus.codex.available was `false` at connect (the
|
|
26006
|
+
// `codex --version` probe timed out during the blocking onboarding scan
|
|
26007
|
+
// and was never re-probed) never started its SHARED codex app-server, so
|
|
26008
|
+
// this `codex` is undefined. But a start_instance / reconnect_thread runs
|
|
26009
|
+
// in its OWN thread worker that spawns its OWN codex app-server - it does
|
|
26010
|
+
// NOT need the shared client. The old `default` arm returned
|
|
26011
|
+
// `agent_provider_unavailable:codex` HERE, before delegating, and only as
|
|
26012
|
+
// a bare codex_response: no thread-worker spawn, no
|
|
26013
|
+
// `runner.thread_process_starting` log, no message_state - a SILENT no-op
|
|
26014
|
+
// that left the user's job stuck in `coding` (prod thread 99d5808e,
|
|
26015
|
+
// control_seq 13). When a thread worker IS available (onThreadProcessStart
|
|
26016
|
+
// wired), fall through to the normal switch so the control delegates to
|
|
26017
|
+
// the worker; the worker's own start surfaces any genuine engine failure.
|
|
26018
|
+
// When NO thread worker exists, codex genuinely cannot run the job, so
|
|
26019
|
+
// fail LOUD (log + failed message_state + throw -> codex_error) instead of
|
|
26020
|
+
// leaving it silently stuck. This loud path is SCOPED to start_instance /
|
|
26021
|
+
// reconnect_thread only.
|
|
26022
|
+
case "start_instance":
|
|
26023
|
+
case "reconnect_thread":
|
|
26024
|
+
if (onThreadProcessStart !== void 0) {
|
|
26025
|
+
break;
|
|
26026
|
+
}
|
|
26027
|
+
return await applyCodexUnavailableControl(
|
|
26028
|
+
kandan,
|
|
26029
|
+
topic,
|
|
26030
|
+
instanceId,
|
|
26031
|
+
control,
|
|
26032
|
+
log2
|
|
26033
|
+
);
|
|
26034
|
+
// Every OTHER control type that reaches here is a request/response control
|
|
26035
|
+
// that does NOT need the shared codex app-server to fail gracefully
|
|
26036
|
+
// (browse_directory, create_project, suggest_tasks,
|
|
26037
|
+
// list_claude_code_sessions, interrupt, cancel_turn, ...). Preserve the
|
|
26038
|
+
// original behavior: return a bare `agent_provider_unavailable:codex`
|
|
26039
|
+
// codex_response - NO throw, NO failed message_state, NO start_instance
|
|
26040
|
+
// log - so onboarding/UI features keep working while codex is unavailable.
|
|
25864
26041
|
default:
|
|
25865
26042
|
return {
|
|
25866
26043
|
instanceId,
|
|
@@ -68863,7 +69040,7 @@ async function parseStartRunnerArgs(args, deps = {
|
|
|
68863
69040
|
cwd,
|
|
68864
69041
|
codexBin,
|
|
68865
69042
|
codexUrl: stringValue8(values, "codex-url"),
|
|
68866
|
-
launchSource:
|
|
69043
|
+
launchSource: electronAutoConnectLaunchSource2(),
|
|
68867
69044
|
launchTui: values.get("launch-tui") === true,
|
|
68868
69045
|
fast: values.get("fast") === true,
|
|
68869
69046
|
logFile: stringValue8(values, "log-file"),
|
|
@@ -68968,7 +69145,7 @@ async function parseAgentRunnerArgs(args, deps = {
|
|
|
68968
69145
|
cwd,
|
|
68969
69146
|
codexBin,
|
|
68970
69147
|
codexUrl: stringValue8(values, "codex-url"),
|
|
68971
|
-
launchSource:
|
|
69148
|
+
launchSource: electronAutoConnectLaunchSource2(),
|
|
68972
69149
|
launchTui: values.get("launch-tui") === true,
|
|
68973
69150
|
fast: values.get("fast") === true,
|
|
68974
69151
|
logFile: stringValue8(values, "log-file"),
|
|
@@ -69143,7 +69320,7 @@ async function parseRunnerArgs(args, deps = {
|
|
|
69143
69320
|
cwd,
|
|
69144
69321
|
codexBin,
|
|
69145
69322
|
codexUrl: stringValue8(values, "codex-url"),
|
|
69146
|
-
launchSource:
|
|
69323
|
+
launchSource: electronAutoConnectLaunchSource2(),
|
|
69147
69324
|
launchTui: values.get("launch-tui") === true,
|
|
69148
69325
|
fast: values.get("fast") === true,
|
|
69149
69326
|
logFile: stringValue8(values, "log-file"),
|
|
@@ -69178,11 +69355,11 @@ function runnerRuntimeDefaultsFromValues(values) {
|
|
|
69178
69355
|
allowPortForwardingByDefault: true
|
|
69179
69356
|
};
|
|
69180
69357
|
}
|
|
69181
|
-
function
|
|
69358
|
+
function electronAutoConnectLaunchSource2() {
|
|
69182
69359
|
return process.env.LINZUMI_ELECTRON_AUTO_CONNECT_RUNNER === "1" ? "electron_auto_connect" : void 0;
|
|
69183
69360
|
}
|
|
69184
69361
|
function connectLaunchSourceTelemetryValue() {
|
|
69185
|
-
return
|
|
69362
|
+
return electronAutoConnectLaunchSource2() ?? "cli";
|
|
69186
69363
|
}
|
|
69187
69364
|
function workspaceTelemetryAttribute(workspace) {
|
|
69188
69365
|
return workspace === void 0 ? {} : { workspace };
|
package/package.json
CHANGED