@linzumi/cli 0.0.35-beta → 0.0.37-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 +3 -2
- package/dist/index.js +119 -42
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -63,7 +63,7 @@ Install the CLI or run it with `npx`:
|
|
|
63
63
|
|
|
64
64
|
```bash
|
|
65
65
|
npm install -g @linzumi/cli@latest
|
|
66
|
-
npx -y @linzumi/cli@0.0.
|
|
66
|
+
npx -y @linzumi/cli@0.0.37-beta --version
|
|
67
67
|
linzumi --version
|
|
68
68
|
```
|
|
69
69
|
|
|
@@ -114,7 +114,8 @@ linzumi paths add ~/code/my-app
|
|
|
114
114
|
```
|
|
115
115
|
|
|
116
116
|
The trust list lives at `~/.linzumi/config.json`. The bootstrap agent
|
|
117
|
-
adds `/tmp/hello_linzumi` for you on first run.
|
|
117
|
+
adds `/tmp/hello_linzumi` for you on first run. For `linzumi connect`, the
|
|
118
|
+
selected `--cwd` is also trusted for that runner process.
|
|
118
119
|
|
|
119
120
|
## When something looks wrong
|
|
120
121
|
|
package/dist/index.js
CHANGED
|
@@ -1481,7 +1481,7 @@ var maxForwardedTurnIds = 64;
|
|
|
1481
1481
|
async function attachChannelSession(args) {
|
|
1482
1482
|
const session = args.options.channelSession;
|
|
1483
1483
|
const chatTopic = `chat:${session.workspaceSlug}:${session.channelSlug}`;
|
|
1484
|
-
const state = initialChannelSessionState(0, session.kandanThreadId, args.options);
|
|
1484
|
+
const state = initialChannelSessionState(0, session.rootSeq, session.kandanThreadId, session.codexThreadId, args.options);
|
|
1485
1485
|
const joined = await args.kandan.join(chatTopic, { last_seq: 0 }, {
|
|
1486
1486
|
rejoinPayload: () => ({ last_seq: state.minSeq })
|
|
1487
1487
|
});
|
|
@@ -1599,6 +1599,7 @@ async function attachChannelSession(args) {
|
|
|
1599
1599
|
}
|
|
1600
1600
|
},
|
|
1601
1601
|
handleControl: (control) => handleChannelSessionControl(args, state, payloadContext, control),
|
|
1602
|
+
startThreadMessageTurn: (message) => startThreadMessageTurn(args, state, payloadContext, message),
|
|
1602
1603
|
currentRuntimeSettings: () => state.runtimeSettings,
|
|
1603
1604
|
currentCodexThreadId: () => state.codexThreadId,
|
|
1604
1605
|
currentKandanThreadId: () => state.kandanThreadId,
|
|
@@ -1641,11 +1642,11 @@ async function bindCurrentCodexThread(args, state) {
|
|
|
1641
1642
|
instance_id: args.instanceId
|
|
1642
1643
|
});
|
|
1643
1644
|
}
|
|
1644
|
-
function initialChannelSessionState(cursor, kandanThreadId, options) {
|
|
1645
|
+
function initialChannelSessionState(cursor, rootSeq, kandanThreadId, codexThreadId, options) {
|
|
1645
1646
|
return {
|
|
1646
|
-
rootSeq
|
|
1647
|
+
rootSeq,
|
|
1647
1648
|
kandanThreadId,
|
|
1648
|
-
codexThreadId
|
|
1649
|
+
codexThreadId,
|
|
1649
1650
|
turn: { status: "idle" },
|
|
1650
1651
|
closed: false,
|
|
1651
1652
|
minSeq: cursor,
|
|
@@ -1712,6 +1713,15 @@ async function bindChannelSession(args, state, payloadContext) {
|
|
|
1712
1713
|
if (state.rootSeq !== undefined) {
|
|
1713
1714
|
state.minSeq = Math.max(state.minSeq, state.rootSeq);
|
|
1714
1715
|
}
|
|
1716
|
+
} else if (state.codexThreadId !== undefined) {
|
|
1717
|
+
await bindCurrentCodexThread(args, state);
|
|
1718
|
+
switch (state.rootSeq) {
|
|
1719
|
+
case undefined:
|
|
1720
|
+
await postBoundThreadAvailability(args, state, payloadContext, codexVersion);
|
|
1721
|
+
break;
|
|
1722
|
+
default:
|
|
1723
|
+
break;
|
|
1724
|
+
}
|
|
1715
1725
|
} else {
|
|
1716
1726
|
const resolved = await pushOk(args.kandan, args.topic, "session:resolve_thread_session", {
|
|
1717
1727
|
workspace: session.workspaceSlug,
|
|
@@ -1723,15 +1733,22 @@ async function bindChannelSession(args, state, payloadContext) {
|
|
|
1723
1733
|
if (state.codexThreadId === undefined) {
|
|
1724
1734
|
throw new Error("Kandan thread root metadata did not include a Codex thread id");
|
|
1725
1735
|
}
|
|
1726
|
-
await
|
|
1727
|
-
workspace: session.workspaceSlug,
|
|
1728
|
-
channel: session.channelSlug,
|
|
1729
|
-
thread_id: state.kandanThreadId,
|
|
1730
|
-
body: availabilityMessage(args.options, codexVersion, state.codexThreadId),
|
|
1731
|
-
payload: localRunnerPayload(args.options, args.instanceId, "availability", state.codexThreadId, payloadContext)
|
|
1732
|
-
});
|
|
1736
|
+
await postBoundThreadAvailability(args, state, payloadContext, codexVersion);
|
|
1733
1737
|
}
|
|
1734
1738
|
}
|
|
1739
|
+
async function postBoundThreadAvailability(args, state, payloadContext, codexVersion) {
|
|
1740
|
+
if (state.kandanThreadId === undefined || state.codexThreadId === undefined) {
|
|
1741
|
+
throw new Error("cannot post local Codex availability before thread binding");
|
|
1742
|
+
}
|
|
1743
|
+
const session = args.options.channelSession;
|
|
1744
|
+
await pushOk(args.kandan, args.topic, "session:post_thread_message", {
|
|
1745
|
+
workspace: session.workspaceSlug,
|
|
1746
|
+
channel: session.channelSlug,
|
|
1747
|
+
thread_id: state.kandanThreadId,
|
|
1748
|
+
body: availabilityMessage(args.options, codexVersion, state.codexThreadId),
|
|
1749
|
+
payload: localRunnerPayload(args.options, args.instanceId, "availability", state.codexThreadId, payloadContext)
|
|
1750
|
+
});
|
|
1751
|
+
}
|
|
1735
1752
|
async function handleChannelSessionControl(args, state, payloadContext, control) {
|
|
1736
1753
|
if (control.type === "update_session_settings") {
|
|
1737
1754
|
return updateSessionSettings(args, state, control);
|
|
@@ -1745,7 +1762,10 @@ async function handleChannelSessionControl(args, state, payloadContext, control)
|
|
|
1745
1762
|
if (control.type !== "interrupt_queued_messages") {
|
|
1746
1763
|
return;
|
|
1747
1764
|
}
|
|
1748
|
-
if (state.codexThreadId
|
|
1765
|
+
if (state.codexThreadId !== control.threadId) {
|
|
1766
|
+
return;
|
|
1767
|
+
}
|
|
1768
|
+
if (state.codexThreadId === undefined || state.kandanThreadId === undefined) {
|
|
1749
1769
|
return { instanceId: args.instanceId, ok: false, error: "thread_not_bound" };
|
|
1750
1770
|
}
|
|
1751
1771
|
const interrupted = interruptPendingKandanMessages(state.queue, control.throughSeq);
|
|
@@ -1795,7 +1815,10 @@ async function handleChannelSessionControl(args, state, payloadContext, control)
|
|
|
1795
1815
|
};
|
|
1796
1816
|
}
|
|
1797
1817
|
function updateSessionSettings(args, state, control) {
|
|
1798
|
-
if (state.codexThreadId
|
|
1818
|
+
if (state.codexThreadId !== control.threadId) {
|
|
1819
|
+
return;
|
|
1820
|
+
}
|
|
1821
|
+
if (state.codexThreadId === undefined) {
|
|
1799
1822
|
return { instanceId: args.instanceId, ok: false, error: "thread_not_bound" };
|
|
1800
1823
|
}
|
|
1801
1824
|
state.runtimeSettings = mergeRuntimeSettings(state.runtimeSettings, control);
|
|
@@ -1822,7 +1845,10 @@ function updateSessionSettings(args, state, control) {
|
|
|
1822
1845
|
};
|
|
1823
1846
|
}
|
|
1824
1847
|
async function resolvePendingCodexApprovalRequest(args, state, control) {
|
|
1825
|
-
if (state.codexThreadId
|
|
1848
|
+
if (state.codexThreadId !== control.threadId) {
|
|
1849
|
+
return;
|
|
1850
|
+
}
|
|
1851
|
+
if (state.codexThreadId === undefined || state.kandanThreadId === undefined) {
|
|
1826
1852
|
return { instanceId: args.instanceId, ok: false, error: "thread_not_bound" };
|
|
1827
1853
|
}
|
|
1828
1854
|
const approval = state.pendingApprovalRequests.get(approvalRequestKey(control.requestId, control.sourceSeq));
|
|
@@ -1836,7 +1862,7 @@ async function resolvePendingCodexApprovalRequest(args, state, control) {
|
|
|
1836
1862
|
await publishMessageState(args, state.kandanThreadId, approval.sourceSeq, {
|
|
1837
1863
|
status: "processing",
|
|
1838
1864
|
reason: "streaming response"
|
|
1839
|
-
});
|
|
1865
|
+
}, undefined, undefined, state.codexThreadId);
|
|
1840
1866
|
args.log("codex.approval_request_resolved", {
|
|
1841
1867
|
request_id: control.requestId,
|
|
1842
1868
|
source_seq: control.sourceSeq,
|
|
@@ -1846,6 +1872,10 @@ async function resolvePendingCodexApprovalRequest(args, state, control) {
|
|
|
1846
1872
|
return { instanceId: args.instanceId, ok: true };
|
|
1847
1873
|
}
|
|
1848
1874
|
async function resolvePendingPortForwardRequest(args, state, payloadContext, control) {
|
|
1875
|
+
const request = state.pendingPortForwardRequests.get(control.requestId);
|
|
1876
|
+
if (request === undefined) {
|
|
1877
|
+
return;
|
|
1878
|
+
}
|
|
1849
1879
|
if (!portForwardControlSenderAllowed(args, payloadContext, control)) {
|
|
1850
1880
|
args.log("port_forward.request_resolution_ignored", {
|
|
1851
1881
|
request_id: control.requestId,
|
|
@@ -1855,10 +1885,6 @@ async function resolvePendingPortForwardRequest(args, state, payloadContext, con
|
|
|
1855
1885
|
});
|
|
1856
1886
|
return { instanceId: args.instanceId, ok: false, error: "sender_not_allowed" };
|
|
1857
1887
|
}
|
|
1858
|
-
const request = state.pendingPortForwardRequests.get(control.requestId);
|
|
1859
|
-
if (request === undefined) {
|
|
1860
|
-
return { instanceId: args.instanceId, ok: false, error: "port_forward_request_not_found" };
|
|
1861
|
-
}
|
|
1862
1888
|
state.pendingPortForwardRequests.delete(control.requestId);
|
|
1863
1889
|
if (control.decision === "deny") {
|
|
1864
1890
|
state.dismissedForwardTargets.set(request.port, approvedTargetFromRequest(request));
|
|
@@ -2204,6 +2230,27 @@ async function handleKandanChatEvent(args, state, runnerIdentity, payloadContext
|
|
|
2204
2230
|
await publishKandanMessageState(args, event, { status: "queued" });
|
|
2205
2231
|
await drainKandanMessageQueue(args, state, payloadContext);
|
|
2206
2232
|
}
|
|
2233
|
+
async function startThreadMessageTurn(args, state, payloadContext, message) {
|
|
2234
|
+
if (state.kandanThreadId === undefined || state.codexThreadId === undefined) {
|
|
2235
|
+
throw new Error("cannot start a local Codex turn before thread binding");
|
|
2236
|
+
}
|
|
2237
|
+
const queued = {
|
|
2238
|
+
seq: message.seq,
|
|
2239
|
+
actorSlug: message.actorSlug,
|
|
2240
|
+
actorUserId: message.actorUserId,
|
|
2241
|
+
body: message.body,
|
|
2242
|
+
attachments: []
|
|
2243
|
+
};
|
|
2244
|
+
enqueuePendingKandanMessage(state.queue, queued);
|
|
2245
|
+
args.log("kandan.message_queued", {
|
|
2246
|
+
seq: queued.seq,
|
|
2247
|
+
actor_slug: queued.actorSlug ?? null,
|
|
2248
|
+
actor_user_id: queued.actorUserId ?? null,
|
|
2249
|
+
queue_depth: pendingKandanMessageQueueLength(state.queue)
|
|
2250
|
+
});
|
|
2251
|
+
await publishQueuedMessageState(args, state, queued, { status: "queued" });
|
|
2252
|
+
await drainKandanMessageQueue(args, state, payloadContext);
|
|
2253
|
+
}
|
|
2207
2254
|
async function bindUnboundHistoricalThread(args, state, event) {
|
|
2208
2255
|
if (event.threadId === undefined || event.replyToSeq === undefined) {
|
|
2209
2256
|
return false;
|
|
@@ -2362,7 +2409,11 @@ async function drainKandanMessageQueue(args, state, payloadContext) {
|
|
|
2362
2409
|
}
|
|
2363
2410
|
async function handleCodexServerRequest(args, state, payloadContext, request) {
|
|
2364
2411
|
const params = objectValue(request.params) ?? {};
|
|
2365
|
-
const turnId =
|
|
2412
|
+
const turnId = codexNotificationTurnId(params);
|
|
2413
|
+
const threadId = codexNotificationThreadId(params);
|
|
2414
|
+
if (state.closed || !codexNotificationBelongsToSession(state, threadId, turnId)) {
|
|
2415
|
+
return;
|
|
2416
|
+
}
|
|
2366
2417
|
if (codexApprovalRequestCanAutoAccept(state.runtimeSettings, request.method)) {
|
|
2367
2418
|
args.log("codex.server_request_auto_accepted", {
|
|
2368
2419
|
method: request.method,
|
|
@@ -2405,7 +2456,7 @@ async function requestKandanApproval(args, state, request, turnId, payloadContex
|
|
|
2405
2456
|
status: "processing",
|
|
2406
2457
|
reason: "awaiting approval",
|
|
2407
2458
|
approval
|
|
2408
|
-
});
|
|
2459
|
+
}, undefined, undefined, state.codexThreadId);
|
|
2409
2460
|
args.log("codex.approval_request_pending", {
|
|
2410
2461
|
request_id: approval.requestId,
|
|
2411
2462
|
source_seq: sourceSeq,
|
|
@@ -3576,12 +3627,13 @@ async function publishQueuedMessageState(args, state, message, messageState) {
|
|
|
3576
3627
|
}
|
|
3577
3628
|
await publishMessageState(args, state.kandanThreadId, message.seq, messageState, message.actorSlug, message.actorUserId);
|
|
3578
3629
|
}
|
|
3579
|
-
async function publishMessageState(args, threadId, seq, state, actorSlug, actorUserId) {
|
|
3630
|
+
async function publishMessageState(args, threadId, seq, state, actorSlug, actorUserId, codexThreadId) {
|
|
3580
3631
|
const session = args.options.channelSession;
|
|
3581
3632
|
const payload = {
|
|
3582
3633
|
workspace: session.workspaceSlug,
|
|
3583
3634
|
channel: session.channelSlug,
|
|
3584
3635
|
thread_id: threadId,
|
|
3636
|
+
...codexThreadId === undefined ? {} : { codex_thread_id: codexThreadId },
|
|
3585
3637
|
seq,
|
|
3586
3638
|
status: state.status,
|
|
3587
3639
|
..."reason" in state ? { reason: state.reason } : {},
|
|
@@ -3639,7 +3691,7 @@ async function refreshActiveProcessingHeartbeat(args, state) {
|
|
|
3639
3691
|
if (activeProcessingState === undefined || state.kandanThreadId === undefined) {
|
|
3640
3692
|
return;
|
|
3641
3693
|
}
|
|
3642
|
-
await publishMessageState(args, state.kandanThreadId, activeProcessingState.seq, processingMessageStateFromActive(activeProcessingState));
|
|
3694
|
+
await publishMessageState(args, state.kandanThreadId, activeProcessingState.seq, processingMessageStateFromActive(activeProcessingState), undefined, undefined, state.codexThreadId);
|
|
3643
3695
|
}
|
|
3644
3696
|
function clearActiveProcessingState(state, seq) {
|
|
3645
3697
|
if (state.activeProcessingState?.seq === seq) {
|
|
@@ -4305,12 +4357,21 @@ async function respondToServerRequest(websocket, request, callbacks) {
|
|
|
4305
4357
|
}));
|
|
4306
4358
|
return;
|
|
4307
4359
|
}
|
|
4308
|
-
const callback
|
|
4309
|
-
|
|
4310
|
-
|
|
4360
|
+
for (const callback of callbacks) {
|
|
4361
|
+
const result = await callback(request);
|
|
4362
|
+
if (result !== undefined) {
|
|
4363
|
+
websocket.send(JSON.stringify({ jsonrpc: "2.0", id: request.id, result }));
|
|
4364
|
+
return;
|
|
4365
|
+
}
|
|
4311
4366
|
}
|
|
4312
|
-
|
|
4313
|
-
|
|
4367
|
+
websocket.send(JSON.stringify({
|
|
4368
|
+
jsonrpc: "2.0",
|
|
4369
|
+
id: request.id,
|
|
4370
|
+
error: {
|
|
4371
|
+
code: -32601,
|
|
4372
|
+
message: `unhandled Codex app-server request: ${request.method}`
|
|
4373
|
+
}
|
|
4374
|
+
}));
|
|
4314
4375
|
} catch (error) {
|
|
4315
4376
|
websocket.send(JSON.stringify({
|
|
4316
4377
|
jsonrpc: "2.0",
|
|
@@ -6981,7 +7042,7 @@ async function openLocalCodexRunner(options, log, cleanup, close) {
|
|
|
6981
7042
|
await Promise.all(Array.from(dynamicChannelSessions.values(), (session) => session.close()));
|
|
6982
7043
|
dynamicChannelSessions.clear();
|
|
6983
7044
|
});
|
|
6984
|
-
const attachStartedThreadSession = async (control, cwd) => {
|
|
7045
|
+
const attachStartedThreadSession = async (control, cwd, codexThreadId) => {
|
|
6985
7046
|
const workspaceSlug = normalizedWorkDescription(control.workspace);
|
|
6986
7047
|
const channelSlug = normalizedWorkDescription(control.channel);
|
|
6987
7048
|
const kandanThreadId = normalizedWorkDescription(control.threadId);
|
|
@@ -7021,6 +7082,8 @@ async function openLocalCodexRunner(options, log, cleanup, close) {
|
|
|
7021
7082
|
workspaceSlug,
|
|
7022
7083
|
channelSlug,
|
|
7023
7084
|
kandanThreadId,
|
|
7085
|
+
rootSeq: integerValue(control.rootSeq),
|
|
7086
|
+
codexThreadId,
|
|
7024
7087
|
listenUser,
|
|
7025
7088
|
model: control.model,
|
|
7026
7089
|
reasoningEffort: control.reasoningEffort,
|
|
@@ -7031,6 +7094,7 @@ async function openLocalCodexRunner(options, log, cleanup, close) {
|
|
|
7031
7094
|
log
|
|
7032
7095
|
});
|
|
7033
7096
|
dynamicChannelSessions.set(kandanThreadId, session);
|
|
7097
|
+
return session;
|
|
7034
7098
|
};
|
|
7035
7099
|
const heartbeatPayload = () => ({
|
|
7036
7100
|
instanceId,
|
|
@@ -7420,14 +7484,23 @@ async function applyControl(codex, kandan, topic, instanceId, options, allowedCw
|
|
|
7420
7484
|
if (codexThreadId !== undefined && developerPrompt !== undefined) {
|
|
7421
7485
|
await postVisibleDeveloperPrompt(kandan, topic, control, developerPrompt, codexThreadId);
|
|
7422
7486
|
}
|
|
7423
|
-
|
|
7424
|
-
await onStartedThread(control, cwd.cwd);
|
|
7425
|
-
}
|
|
7487
|
+
const startedThreadSession = codexThreadId !== undefined && onStartedThread !== undefined ? await onStartedThread(control, cwd.cwd, codexThreadId) : undefined;
|
|
7426
7488
|
if (codexThreadId !== undefined && workDescription !== undefined) {
|
|
7427
|
-
|
|
7428
|
-
|
|
7429
|
-
|
|
7430
|
-
|
|
7489
|
+
const rootSeq = integerValue(control.rootSeq);
|
|
7490
|
+
if (startedThreadSession !== undefined && rootSeq !== undefined) {
|
|
7491
|
+
const identity = identityFromAccessToken(options.token);
|
|
7492
|
+
await startedThreadSession.startThreadMessageTurn({
|
|
7493
|
+
seq: rootSeq,
|
|
7494
|
+
body: workDescription,
|
|
7495
|
+
actorSlug: identity.actorUsername,
|
|
7496
|
+
actorUserId: identity.actorUserId
|
|
7497
|
+
});
|
|
7498
|
+
} else {
|
|
7499
|
+
await codex.request("turn/start", {
|
|
7500
|
+
threadId: codexThreadId,
|
|
7501
|
+
input: [{ type: "text", text: workDescription }]
|
|
7502
|
+
});
|
|
7503
|
+
}
|
|
7431
7504
|
}
|
|
7432
7505
|
return {
|
|
7433
7506
|
instanceId,
|
|
@@ -7486,6 +7559,7 @@ async function applyControl(codex, kandan, topic, instanceId, options, allowedCw
|
|
|
7486
7559
|
case "kill_instance":
|
|
7487
7560
|
case "interrupt_queued_messages":
|
|
7488
7561
|
case "resolve_codex_approval_request":
|
|
7562
|
+
case "resolve_port_forward_request":
|
|
7489
7563
|
case "forward_http_request":
|
|
7490
7564
|
case "forward_websocket_open":
|
|
7491
7565
|
case "forward_websocket_send":
|
|
@@ -9421,7 +9495,7 @@ async function main(args) {
|
|
|
9421
9495
|
process.stdout.write(connectGuideText());
|
|
9422
9496
|
return;
|
|
9423
9497
|
case "version":
|
|
9424
|
-
process.stdout.write(`linzumi 0.0.
|
|
9498
|
+
process.stdout.write(`linzumi 0.0.37-beta
|
|
9425
9499
|
`);
|
|
9426
9500
|
return;
|
|
9427
9501
|
case "auth":
|
|
@@ -9935,13 +10009,15 @@ async function parseRunnerArgs(args, deps = {
|
|
|
9935
10009
|
process.exit(0);
|
|
9936
10010
|
}
|
|
9937
10011
|
if (values.get("version") === true) {
|
|
9938
|
-
process.stdout.write(`linzumi 0.0.
|
|
10012
|
+
process.stdout.write(`linzumi 0.0.37-beta
|
|
9939
10013
|
`);
|
|
9940
10014
|
process.exit(0);
|
|
9941
10015
|
}
|
|
9942
10016
|
const channelTarget = parseChannelSessionTarget(values);
|
|
9943
10017
|
const kandanUrl = required(values, "linzumi-url");
|
|
9944
10018
|
const cwd = stringValue3(values, "cwd") ?? process.cwd();
|
|
10019
|
+
const cwdAllowedCwds = assertConfiguredAllowedCwds([cwd]);
|
|
10020
|
+
const configuredAllowedCwds = values.has("allowed-cwd") ? assertConfiguredAllowedCwds(parseAllowedCwdList(stringValue3(values, "allowed-cwd"))) : readConfiguredAllowedCwds();
|
|
9945
10021
|
const codexBin = stringValue3(values, "codex-bin") ?? "codex";
|
|
9946
10022
|
const customCodeServerBin = stringValue3(values, "code-server-bin");
|
|
9947
10023
|
const explicitToken = stringValue3(values, "token");
|
|
@@ -9981,7 +10057,7 @@ async function parseRunnerArgs(args, deps = {
|
|
|
9981
10057
|
launchTui: values.get("launch-tui") === true,
|
|
9982
10058
|
fast: values.get("fast") === true,
|
|
9983
10059
|
logFile: stringValue3(values, "log-file"),
|
|
9984
|
-
allowedCwds:
|
|
10060
|
+
allowedCwds: Array.from(new Set([...cwdAllowedCwds, ...configuredAllowedCwds])),
|
|
9985
10061
|
allowedForwardPorts: parseAllowedPortList(stringValue3(values, "forward-port")),
|
|
9986
10062
|
codeServerBin: editorRuntime.codeServerBin,
|
|
9987
10063
|
editorRuntime: editorRuntime.runtime,
|
|
@@ -10221,7 +10297,7 @@ Codex:
|
|
|
10221
10297
|
--stream-flush-ms <ms> Batch live Codex deltas before Linzumi persistence, default 150
|
|
10222
10298
|
--fast Mark this runner as low-latency/fast in the availability message
|
|
10223
10299
|
--log-file <path> JSONL event log path, default <cwd>/.linzumi-runner.log
|
|
10224
|
-
--allowed-cwd <paths>
|
|
10300
|
+
--allowed-cwd <paths> Extra comma-separated roots where Linzumi may start local Codex sessions
|
|
10225
10301
|
--forward-port <ports> Comma-separated local TCP ports Linzumi may expose as authenticated previews
|
|
10226
10302
|
--code-server-bin <path> Custom development code-server executable. The default editor runtime is downloaded from Linzumi.
|
|
10227
10303
|
|
|
@@ -10318,8 +10394,9 @@ Usage:
|
|
|
10318
10394
|
linzumi paths add <path>
|
|
10319
10395
|
linzumi paths remove <path>
|
|
10320
10396
|
|
|
10321
|
-
Trusted paths are stored in ~/.linzumi/config.json. linzumi connect
|
|
10322
|
-
|
|
10397
|
+
Trusted paths are stored in ~/.linzumi/config.json. linzumi connect always
|
|
10398
|
+
trusts its selected cwd for that runner process and also uses configured paths
|
|
10399
|
+
unless --allowed-cwd is passed with explicit extra roots.
|
|
10323
10400
|
`;
|
|
10324
10401
|
}
|
|
10325
10402
|
function startHelpText() {
|
package/package.json
CHANGED