@linzumi/cli 0.0.55-beta → 0.0.57-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 +321 -365
- package/package.json +1 -1
package/README.md
CHANGED
package/dist/index.js
CHANGED
|
@@ -11028,7 +11028,6 @@ var require_lib3 = __commonJS({
|
|
|
11028
11028
|
});
|
|
11029
11029
|
|
|
11030
11030
|
// src/index.ts
|
|
11031
|
-
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
11032
11031
|
import { existsSync as existsSync12, readFileSync as readFileSync13, realpathSync as realpathSync6 } from "node:fs";
|
|
11033
11032
|
import { homedir as homedir10 } from "node:os";
|
|
11034
11033
|
import { resolve as resolve10 } from "node:path";
|
|
@@ -18203,8 +18202,8 @@ function pathLooksAbsolute(pathValue) {
|
|
|
18203
18202
|
}
|
|
18204
18203
|
|
|
18205
18204
|
// src/localForwarding.ts
|
|
18205
|
+
import { connect as connectTcp } from "node:net";
|
|
18206
18206
|
import { gzipSync } from "node:zlib";
|
|
18207
|
-
import NodeWebSocket from "ws";
|
|
18208
18207
|
var maxForwardBodyBytes = 64 * 1024 * 1024;
|
|
18209
18208
|
var gzipForwardThresholdBytes = 32 * 1024;
|
|
18210
18209
|
async function handleForwardHttpRequest(control, allowedPorts) {
|
|
@@ -18261,21 +18260,21 @@ async function handleForwardHttpRequest(control, allowedPorts) {
|
|
|
18261
18260
|
function isForwardHttpRequestControl(control) {
|
|
18262
18261
|
return control.type === "forward_http_request";
|
|
18263
18262
|
}
|
|
18264
|
-
function
|
|
18265
|
-
return control.type === "
|
|
18263
|
+
function isForwardTcpControl(control) {
|
|
18264
|
+
return control.type === "forward_tcp_open" || control.type === "forward_tcp_send" || control.type === "forward_tcp_close";
|
|
18266
18265
|
}
|
|
18267
|
-
function
|
|
18266
|
+
function createForwardTcpManager(kandan, topic, allowedPorts, socketFactory = defaultForwardTcpFactory) {
|
|
18268
18267
|
const sockets = /* @__PURE__ */ new Map();
|
|
18269
|
-
const pushEvent = (payload) => kandan.push(topic, "forward:
|
|
18268
|
+
const pushEvent = (payload) => kandan.push(topic, "forward:tcp_event", payload).catch(() => void 0);
|
|
18270
18269
|
const closeSocket = (socketId) => {
|
|
18271
18270
|
const stream = sockets.get(socketId);
|
|
18272
18271
|
sockets.delete(socketId);
|
|
18273
|
-
stream?.socket.
|
|
18272
|
+
stream?.socket.end();
|
|
18274
18273
|
};
|
|
18275
18274
|
return {
|
|
18276
18275
|
handle: (control) => {
|
|
18277
18276
|
switch (control.type) {
|
|
18278
|
-
case "
|
|
18277
|
+
case "forward_tcp_open": {
|
|
18279
18278
|
if (!allowedPorts().includes(control.port)) {
|
|
18280
18279
|
void pushEvent({
|
|
18281
18280
|
socketId: control.socketId,
|
|
@@ -18284,32 +18283,70 @@ function createForwardWebSocketManager(kandan, topic, allowedPorts, socketFactor
|
|
|
18284
18283
|
});
|
|
18285
18284
|
return;
|
|
18286
18285
|
}
|
|
18287
|
-
|
|
18286
|
+
const previous = sockets.get(control.socketId);
|
|
18287
|
+
previous?.socket.destroy();
|
|
18288
|
+
const socket = socketFactory(control.port);
|
|
18289
|
+
sockets.set(control.socketId, { socket });
|
|
18290
|
+
socket.on("connect", () => {
|
|
18291
|
+
if (!currentTcpSocket(sockets, control.socketId, socket)) {
|
|
18292
|
+
return;
|
|
18293
|
+
}
|
|
18294
|
+
void pushEvent({ socketId: control.socketId, type: "open" });
|
|
18295
|
+
});
|
|
18296
|
+
socket.on("data", (data) => {
|
|
18297
|
+
if (!currentTcpSocket(sockets, control.socketId, socket) || !(data instanceof Uint8Array)) {
|
|
18298
|
+
return;
|
|
18299
|
+
}
|
|
18300
|
+
void pushEvent({
|
|
18301
|
+
socketId: control.socketId,
|
|
18302
|
+
type: "data",
|
|
18303
|
+
bodyBase64: Buffer.from(data).toString("base64")
|
|
18304
|
+
});
|
|
18305
|
+
});
|
|
18306
|
+
socket.on("close", () => {
|
|
18307
|
+
if (!currentTcpSocket(sockets, control.socketId, socket)) {
|
|
18308
|
+
return;
|
|
18309
|
+
}
|
|
18310
|
+
sockets.delete(control.socketId);
|
|
18311
|
+
void pushEvent({ socketId: control.socketId, type: "close" });
|
|
18312
|
+
});
|
|
18313
|
+
socket.on("error", () => {
|
|
18314
|
+
if (!currentTcpSocket(sockets, control.socketId, socket)) {
|
|
18315
|
+
return;
|
|
18316
|
+
}
|
|
18317
|
+
sockets.delete(control.socketId);
|
|
18318
|
+
void pushEvent({
|
|
18319
|
+
socketId: control.socketId,
|
|
18320
|
+
type: "error",
|
|
18321
|
+
error: "forward_target_unavailable"
|
|
18322
|
+
});
|
|
18323
|
+
socket.destroy();
|
|
18324
|
+
});
|
|
18288
18325
|
return;
|
|
18289
18326
|
}
|
|
18290
|
-
case "
|
|
18327
|
+
case "forward_tcp_send": {
|
|
18291
18328
|
const stream = sockets.get(control.socketId);
|
|
18292
|
-
|
|
18329
|
+
const body = decodeBase64Body(control.bodyBase64);
|
|
18330
|
+
if (body === void 0) {
|
|
18293
18331
|
void pushEvent({
|
|
18294
18332
|
socketId: control.socketId,
|
|
18295
18333
|
type: "error",
|
|
18296
|
-
error: "
|
|
18334
|
+
error: "invalid_forward_request"
|
|
18297
18335
|
});
|
|
18298
18336
|
return;
|
|
18299
18337
|
}
|
|
18300
|
-
|
|
18301
|
-
|
|
18302
|
-
|
|
18303
|
-
|
|
18304
|
-
|
|
18305
|
-
|
|
18306
|
-
|
|
18307
|
-
case "pong":
|
|
18308
|
-
stream.socket.send(body);
|
|
18309
|
-
return;
|
|
18338
|
+
if (stream === void 0 || stream.socket.destroyed === true || stream.socket.writable === false) {
|
|
18339
|
+
void pushEvent({
|
|
18340
|
+
socketId: control.socketId,
|
|
18341
|
+
type: "error",
|
|
18342
|
+
error: "tcp_socket_not_open"
|
|
18343
|
+
});
|
|
18344
|
+
return;
|
|
18310
18345
|
}
|
|
18346
|
+
stream.socket.write(body);
|
|
18347
|
+
return;
|
|
18311
18348
|
}
|
|
18312
|
-
case "
|
|
18349
|
+
case "forward_tcp_close":
|
|
18313
18350
|
closeSocket(control.socketId);
|
|
18314
18351
|
return;
|
|
18315
18352
|
}
|
|
@@ -18321,105 +18358,11 @@ function createForwardWebSocketManager(kandan, topic, allowedPorts, socketFactor
|
|
|
18321
18358
|
}
|
|
18322
18359
|
};
|
|
18323
18360
|
}
|
|
18324
|
-
function
|
|
18325
|
-
let opened = false;
|
|
18326
|
-
const url = localForwardWebSocketUrl(
|
|
18327
|
-
scheme,
|
|
18328
|
-
control.port,
|
|
18329
|
-
control.path,
|
|
18330
|
-
control.queryString
|
|
18331
|
-
);
|
|
18332
|
-
const protocols = webSocketProtocols(control.headers);
|
|
18333
|
-
const headers = webSocketHeaders(control.headers);
|
|
18334
|
-
const websocket = socketFactory(url, protocols, headers);
|
|
18335
|
-
websocket.binaryType = "arraybuffer";
|
|
18336
|
-
const previousStream = sockets.get(control.socketId);
|
|
18337
|
-
previousStream?.socket.close();
|
|
18338
|
-
sockets.set(control.socketId, { socket: websocket });
|
|
18339
|
-
websocket.addEventListener("open", () => {
|
|
18340
|
-
if (!currentWebSocket(sockets, control.socketId, websocket)) {
|
|
18341
|
-
return;
|
|
18342
|
-
}
|
|
18343
|
-
opened = true;
|
|
18344
|
-
void pushEvent({ socketId: control.socketId, type: "open" });
|
|
18345
|
-
});
|
|
18346
|
-
websocket.addEventListener("message", (event) => {
|
|
18347
|
-
if (!currentWebSocket(sockets, control.socketId, websocket)) {
|
|
18348
|
-
return;
|
|
18349
|
-
}
|
|
18350
|
-
const body = typeof event.data === "string" ? Buffer.from(event.data) : Buffer.from(event.data);
|
|
18351
|
-
void pushEvent({
|
|
18352
|
-
socketId: control.socketId,
|
|
18353
|
-
type: "message",
|
|
18354
|
-
opcode: typeof event.data === "string" ? "text" : "binary",
|
|
18355
|
-
bodyBase64: body.toString("base64")
|
|
18356
|
-
});
|
|
18357
|
-
});
|
|
18358
|
-
websocket.addEventListener("close", (event) => {
|
|
18359
|
-
if (!currentWebSocket(sockets, control.socketId, websocket)) {
|
|
18360
|
-
return;
|
|
18361
|
-
}
|
|
18362
|
-
sockets.delete(control.socketId);
|
|
18363
|
-
void pushEvent({
|
|
18364
|
-
socketId: control.socketId,
|
|
18365
|
-
type: "close",
|
|
18366
|
-
code: event.code,
|
|
18367
|
-
reason: event.reason
|
|
18368
|
-
});
|
|
18369
|
-
});
|
|
18370
|
-
websocket.addEventListener("error", () => {
|
|
18371
|
-
if (!currentWebSocket(sockets, control.socketId, websocket)) {
|
|
18372
|
-
return;
|
|
18373
|
-
}
|
|
18374
|
-
sockets.delete(control.socketId);
|
|
18375
|
-
if (!opened && scheme === "ws") {
|
|
18376
|
-
openLocalWebSocket(control, sockets, pushEvent, socketFactory, "wss");
|
|
18377
|
-
return;
|
|
18378
|
-
}
|
|
18379
|
-
void pushEvent({
|
|
18380
|
-
socketId: control.socketId,
|
|
18381
|
-
type: "error",
|
|
18382
|
-
error: "websocket_error",
|
|
18383
|
-
attemptedScheme: scheme
|
|
18384
|
-
});
|
|
18385
|
-
});
|
|
18386
|
-
}
|
|
18387
|
-
function defaultForwardWebSocketFactory(url, protocols, headers) {
|
|
18388
|
-
if (headers === void 0) {
|
|
18389
|
-
return protocols === void 0 ? new WebSocket(url) : new WebSocket(url, protocols);
|
|
18390
|
-
}
|
|
18391
|
-
const options = { headers };
|
|
18392
|
-
return protocols === void 0 ? new NodeWebSocket(url, options) : new NodeWebSocket(url, protocols, options);
|
|
18393
|
-
}
|
|
18394
|
-
function currentWebSocket(sockets, socketId, socket) {
|
|
18361
|
+
function currentTcpSocket(sockets, socketId, socket) {
|
|
18395
18362
|
return sockets.get(socketId)?.socket === socket;
|
|
18396
18363
|
}
|
|
18397
|
-
function
|
|
18398
|
-
|
|
18399
|
-
return void 0;
|
|
18400
|
-
}
|
|
18401
|
-
const protocols = headers.flatMap((header) => {
|
|
18402
|
-
if (!isWireHeader(header) || header.name.toLowerCase() !== "sec-websocket-protocol") {
|
|
18403
|
-
return [];
|
|
18404
|
-
}
|
|
18405
|
-
return header.value.split(",").map((protocol) => protocol.trim()).filter((protocol) => protocol !== "");
|
|
18406
|
-
});
|
|
18407
|
-
return protocols.length === 0 ? void 0 : protocols;
|
|
18408
|
-
}
|
|
18409
|
-
function webSocketHeaders(headers) {
|
|
18410
|
-
if (!Array.isArray(headers)) {
|
|
18411
|
-
return void 0;
|
|
18412
|
-
}
|
|
18413
|
-
const forwarded = headers.reduce((acc, header) => {
|
|
18414
|
-
if (isOctWebSocketHeader(header)) {
|
|
18415
|
-
acc[header.name] = header.value;
|
|
18416
|
-
}
|
|
18417
|
-
return acc;
|
|
18418
|
-
}, {});
|
|
18419
|
-
return Object.keys(forwarded).length === 0 ? void 0 : forwarded;
|
|
18420
|
-
}
|
|
18421
|
-
function isOctWebSocketHeader(value) {
|
|
18422
|
-
return isHeader(value) && value.name.toLowerCase().startsWith("x-oct-");
|
|
18364
|
+
function defaultForwardTcpFactory(port) {
|
|
18365
|
+
return connectTcp({ host: "127.0.0.1", port });
|
|
18423
18366
|
}
|
|
18424
18367
|
function localForwardUrl(scheme, port, path2, queryString) {
|
|
18425
18368
|
const normalizedPath = path2.startsWith("/") ? path2 : `/${path2}`;
|
|
@@ -18429,12 +18372,6 @@ function localForwardUrl(scheme, port, path2, queryString) {
|
|
|
18429
18372
|
}
|
|
18430
18373
|
return url.toString();
|
|
18431
18374
|
}
|
|
18432
|
-
function localForwardWebSocketUrl(scheme, port, path2, queryString) {
|
|
18433
|
-
const httpScheme = scheme === "ws" ? "http" : "https";
|
|
18434
|
-
const url = new URL(localForwardUrl(httpScheme, port, path2, queryString));
|
|
18435
|
-
url.protocol = `${scheme}:`;
|
|
18436
|
-
return url.toString();
|
|
18437
|
-
}
|
|
18438
18375
|
async function fetchWithHttpsFallback(port, path2, queryString, request) {
|
|
18439
18376
|
try {
|
|
18440
18377
|
return await fetch(
|
|
@@ -20862,6 +20799,37 @@ function ensureLocalMachineIdForLinzumiUrl(linzumiUrl, path2 = localConfigPath()
|
|
|
20862
20799
|
writeLocalConfigSection({ ...latestConfig, machineId }, path2, linzumiUrl);
|
|
20863
20800
|
return machineId;
|
|
20864
20801
|
}
|
|
20802
|
+
function ensureLocalRunnerIdForLinzumiUrl(linzumiUrl, path2 = localConfigPath(), createRunnerId = defaultLocalRunnerId) {
|
|
20803
|
+
if (localConfigScopeKey(linzumiUrl) === prodConfigScope) {
|
|
20804
|
+
return ensureLocalRunnerId(path2, createRunnerId);
|
|
20805
|
+
}
|
|
20806
|
+
const config = readLocalConfigForLinzumiUrl(linzumiUrl, path2);
|
|
20807
|
+
if (config.runnerId !== void 0) {
|
|
20808
|
+
return config.runnerId;
|
|
20809
|
+
}
|
|
20810
|
+
const runnerId = ensureLocalRunnerIdSeed(path2, createRunnerId, linzumiUrl);
|
|
20811
|
+
const latestConfig = readLocalConfigForLinzumiUrl(linzumiUrl, path2);
|
|
20812
|
+
const latestRunnerId = latestConfig.runnerId;
|
|
20813
|
+
if (latestRunnerId !== void 0) {
|
|
20814
|
+
return latestRunnerId;
|
|
20815
|
+
}
|
|
20816
|
+
writeLocalConfigSection({ ...latestConfig, runnerId }, path2, linzumiUrl);
|
|
20817
|
+
return runnerId;
|
|
20818
|
+
}
|
|
20819
|
+
function ensureLocalRunnerId(path2 = localConfigPath(), createRunnerId = defaultLocalRunnerId) {
|
|
20820
|
+
const config = readLocalConfig(path2);
|
|
20821
|
+
if (config.runnerId !== void 0) {
|
|
20822
|
+
return config.runnerId;
|
|
20823
|
+
}
|
|
20824
|
+
const runnerId = ensureLocalRunnerIdSeed(path2, createRunnerId);
|
|
20825
|
+
const latestConfig = readLocalConfig(path2);
|
|
20826
|
+
const latestRunnerId = latestConfig.runnerId;
|
|
20827
|
+
if (latestRunnerId !== void 0) {
|
|
20828
|
+
return latestRunnerId;
|
|
20829
|
+
}
|
|
20830
|
+
writeLocalConfig({ ...latestConfig, runnerId }, path2);
|
|
20831
|
+
return runnerId;
|
|
20832
|
+
}
|
|
20865
20833
|
function localMachineIdSeedPath(configPath = localConfigPath(), linzumiUrl) {
|
|
20866
20834
|
if (linzumiUrl !== void 0 && localConfigScopeKey(linzumiUrl) !== prodConfigScope) {
|
|
20867
20835
|
return join6(
|
|
@@ -20871,6 +20839,15 @@ function localMachineIdSeedPath(configPath = localConfigPath(), linzumiUrl) {
|
|
|
20871
20839
|
}
|
|
20872
20840
|
return join6(dirname4(configPath), `${basename4(configPath)}.machine-id`);
|
|
20873
20841
|
}
|
|
20842
|
+
function localRunnerIdSeedPath(configPath = localConfigPath(), linzumiUrl) {
|
|
20843
|
+
if (linzumiUrl !== void 0 && localConfigScopeKey(linzumiUrl) !== prodConfigScope) {
|
|
20844
|
+
return join6(
|
|
20845
|
+
dirname4(configPath),
|
|
20846
|
+
`${basename4(configPath)}.${localConfigScopeFileStem(linzumiUrl)}.runner-id`
|
|
20847
|
+
);
|
|
20848
|
+
}
|
|
20849
|
+
return join6(dirname4(configPath), `${basename4(configPath)}.runner-id`);
|
|
20850
|
+
}
|
|
20874
20851
|
function readConfiguredAllowedCwdDetailsForLinzumiUrl(linzumiUrl, path2 = localConfigPath()) {
|
|
20875
20852
|
return readConfiguredAllowedCwdDetailsFromConfig(
|
|
20876
20853
|
readLocalConfigForLinzumiUrl(linzumiUrl, path2)
|
|
@@ -21033,7 +21010,12 @@ function readLocalConfigSection(path2, linzumiUrl) {
|
|
|
21033
21010
|
throw new Error(`invalid Linzumi config section ${scopeKey}: ${path2}`);
|
|
21034
21011
|
}
|
|
21035
21012
|
const allowedCwds = uniqueStrings(section.allowedCwds);
|
|
21036
|
-
return
|
|
21013
|
+
return {
|
|
21014
|
+
version: 1,
|
|
21015
|
+
...section.machineId === void 0 ? {} : { machineId: section.machineId },
|
|
21016
|
+
...section.runnerId === void 0 ? {} : { runnerId: section.runnerId },
|
|
21017
|
+
allowedCwds
|
|
21018
|
+
};
|
|
21037
21019
|
}
|
|
21038
21020
|
function writeLocalConfigSection(config, path2, linzumiUrl) {
|
|
21039
21021
|
const scopeKey = linzumiUrl === void 0 ? prodConfigScope : localConfigScopeKey(linzumiUrl);
|
|
@@ -21050,7 +21032,7 @@ function isConfigPayload(value) {
|
|
|
21050
21032
|
return typeof value === "object" && value !== null && value.version === 1 && isConfigSection(value);
|
|
21051
21033
|
}
|
|
21052
21034
|
function isConfigSection(value) {
|
|
21053
|
-
return typeof value === "object" && value !== null && Array.isArray(value.allowedCwds) && machineIdValid(value.machineId) && value.allowedCwds.every(
|
|
21035
|
+
return typeof value === "object" && value !== null && Array.isArray(value.allowedCwds) && machineIdValid(value.machineId) && runnerIdValid(value.runnerId) && value.allowedCwds.every(
|
|
21054
21036
|
(cwd) => typeof cwd === "string" && cwd.trim() !== ""
|
|
21055
21037
|
);
|
|
21056
21038
|
}
|
|
@@ -21092,7 +21074,11 @@ function normalizedConfigSection(config) {
|
|
|
21092
21074
|
throw new Error("invalid Linzumi config");
|
|
21093
21075
|
}
|
|
21094
21076
|
const allowedCwds = uniqueStrings(config.allowedCwds);
|
|
21095
|
-
return
|
|
21077
|
+
return {
|
|
21078
|
+
...config.machineId === void 0 ? {} : { machineId: config.machineId },
|
|
21079
|
+
...config.runnerId === void 0 ? {} : { runnerId: config.runnerId },
|
|
21080
|
+
allowedCwds
|
|
21081
|
+
};
|
|
21096
21082
|
}
|
|
21097
21083
|
function emptySection() {
|
|
21098
21084
|
return { allowedCwds: [] };
|
|
@@ -21102,6 +21088,9 @@ function machineIdValid(value) {
|
|
|
21102
21088
|
value
|
|
21103
21089
|
);
|
|
21104
21090
|
}
|
|
21091
|
+
function runnerIdValid(value) {
|
|
21092
|
+
return value === void 0 || typeof value === "string" && /^[a-zA-Z0-9_.-]+$/.test(value);
|
|
21093
|
+
}
|
|
21105
21094
|
function ensureLocalMachineIdSeed(configPath, createMachineId, linzumiUrl) {
|
|
21106
21095
|
const seedPath = localMachineIdSeedPath(configPath, linzumiUrl);
|
|
21107
21096
|
if (existsSync4(seedPath)) {
|
|
@@ -21130,6 +21119,34 @@ function ensureLocalMachineIdSeed(configPath, createMachineId, linzumiUrl) {
|
|
|
21130
21119
|
unlinkSync(tempPath);
|
|
21131
21120
|
}
|
|
21132
21121
|
}
|
|
21122
|
+
function ensureLocalRunnerIdSeed(configPath, createRunnerId, linzumiUrl) {
|
|
21123
|
+
const seedPath = localRunnerIdSeedPath(configPath, linzumiUrl);
|
|
21124
|
+
if (existsSync4(seedPath)) {
|
|
21125
|
+
return readRunnerIdSeed(seedPath);
|
|
21126
|
+
}
|
|
21127
|
+
const runnerId = createRunnerId();
|
|
21128
|
+
if (!runnerIdValid(runnerId)) {
|
|
21129
|
+
throw new Error(`invalid generated Linzumi runner id: ${runnerId}`);
|
|
21130
|
+
}
|
|
21131
|
+
mkdirSync5(dirname4(seedPath), { recursive: true });
|
|
21132
|
+
const tempPath = join6(
|
|
21133
|
+
dirname4(seedPath),
|
|
21134
|
+
`.${basename4(seedPath)}.${process.pid}.${randomUUID2()}.tmp`
|
|
21135
|
+
);
|
|
21136
|
+
writeFileSync4(tempPath, `${runnerId}
|
|
21137
|
+
`, { encoding: "utf8", flag: "wx" });
|
|
21138
|
+
try {
|
|
21139
|
+
linkSync(tempPath, seedPath);
|
|
21140
|
+
return runnerId;
|
|
21141
|
+
} catch (error) {
|
|
21142
|
+
if (isNodeErrorCode(error, "EEXIST")) {
|
|
21143
|
+
return readRunnerIdSeed(seedPath);
|
|
21144
|
+
}
|
|
21145
|
+
throw error;
|
|
21146
|
+
} finally {
|
|
21147
|
+
unlinkSync(tempPath);
|
|
21148
|
+
}
|
|
21149
|
+
}
|
|
21133
21150
|
function readMachineIdSeed(seedPath) {
|
|
21134
21151
|
const machineId = readFileSync4(seedPath, "utf8").trim();
|
|
21135
21152
|
if (!machineIdValid(machineId)) {
|
|
@@ -21137,6 +21154,16 @@ function readMachineIdSeed(seedPath) {
|
|
|
21137
21154
|
}
|
|
21138
21155
|
return machineId;
|
|
21139
21156
|
}
|
|
21157
|
+
function readRunnerIdSeed(seedPath) {
|
|
21158
|
+
const runnerId = readFileSync4(seedPath, "utf8").trim();
|
|
21159
|
+
if (!runnerIdValid(runnerId)) {
|
|
21160
|
+
throw new Error(`invalid Linzumi runner id seed: ${seedPath}`);
|
|
21161
|
+
}
|
|
21162
|
+
return runnerId;
|
|
21163
|
+
}
|
|
21164
|
+
function defaultLocalRunnerId() {
|
|
21165
|
+
return `runner-${randomUUID2()}`;
|
|
21166
|
+
}
|
|
21140
21167
|
function uniqueStrings(values) {
|
|
21141
21168
|
return [
|
|
21142
21169
|
...new Set(
|
|
@@ -21159,7 +21186,7 @@ function realpathOrResolved(pathValue) {
|
|
|
21159
21186
|
}
|
|
21160
21187
|
|
|
21161
21188
|
// src/version.ts
|
|
21162
|
-
var linzumiCliVersion = "0.0.
|
|
21189
|
+
var linzumiCliVersion = "0.0.57-beta";
|
|
21163
21190
|
var linzumiCliVersionText = `linzumi ${linzumiCliVersion}`;
|
|
21164
21191
|
|
|
21165
21192
|
// src/runnerLock.ts
|
|
@@ -21665,6 +21692,7 @@ async function openLocalCodexRunner(options, log, cleanup, close) {
|
|
|
21665
21692
|
allowedCwds.value
|
|
21666
21693
|
),
|
|
21667
21694
|
portForwarding: liveForwardPorts.size > 0,
|
|
21695
|
+
tcpForwarding: true,
|
|
21668
21696
|
allowedPorts: Array.from(liveForwardPorts).sort(
|
|
21669
21697
|
(left, right) => left - right
|
|
21670
21698
|
),
|
|
@@ -22013,64 +22041,6 @@ async function openLocalCodexRunner(options, log, cleanup, close) {
|
|
|
22013
22041
|
cleanup.actions.push(() => codex.close());
|
|
22014
22042
|
const seq = { value: 0 };
|
|
22015
22043
|
const discoveredCodexThreads = { value: [] };
|
|
22016
|
-
const lastReportedDiscoveryFailure = { value: void 0 };
|
|
22017
|
-
const reportClientError = async (args) => {
|
|
22018
|
-
await kandan.push(topic, "client_error_report", {
|
|
22019
|
-
id: `client-error-${randomUUID3()}`,
|
|
22020
|
-
severity: args.severity ?? "error",
|
|
22021
|
-
code: args.code,
|
|
22022
|
-
operation: args.operation,
|
|
22023
|
-
message: args.message,
|
|
22024
|
-
occurredAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
22025
|
-
instanceId,
|
|
22026
|
-
clientId,
|
|
22027
|
-
runnerId: options.runnerId,
|
|
22028
|
-
hostname: runnerHost,
|
|
22029
|
-
cwd: options.cwd,
|
|
22030
|
-
codexUrl,
|
|
22031
|
-
workspace: runnerWorkspaceSlug(options) ?? null,
|
|
22032
|
-
channel: options.channelSession?.channelSlug ?? null,
|
|
22033
|
-
cliVersion: linzumiCliVersion,
|
|
22034
|
-
details: args.details ?? {}
|
|
22035
|
-
}).catch((error) => {
|
|
22036
|
-
log("kandan.client_error_report_push_failed", {
|
|
22037
|
-
code: args.code,
|
|
22038
|
-
operation: args.operation,
|
|
22039
|
-
message: error instanceof Error ? error.message : String(error)
|
|
22040
|
-
});
|
|
22041
|
-
});
|
|
22042
|
-
};
|
|
22043
|
-
const loadDiscoveredCodexThreads = async (phase) => {
|
|
22044
|
-
try {
|
|
22045
|
-
const threads = await discoverCodexThreads(codex, options.cwd);
|
|
22046
|
-
lastReportedDiscoveryFailure.value = void 0;
|
|
22047
|
-
return threads;
|
|
22048
|
-
} catch (error) {
|
|
22049
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
22050
|
-
const signature = `codex_thread_discovery_failed:${message}`;
|
|
22051
|
-
log("codex.thread_discovery_failed", {
|
|
22052
|
-
phase,
|
|
22053
|
-
message
|
|
22054
|
-
});
|
|
22055
|
-
if (lastReportedDiscoveryFailure.value !== signature) {
|
|
22056
|
-
lastReportedDiscoveryFailure.value = signature;
|
|
22057
|
-
await reportClientError({
|
|
22058
|
-
code: "codex_thread_discovery_failed",
|
|
22059
|
-
operation: "codex_thread_discovery",
|
|
22060
|
-
message,
|
|
22061
|
-
details: {
|
|
22062
|
-
phase,
|
|
22063
|
-
codexUrl,
|
|
22064
|
-
cwd: options.cwd
|
|
22065
|
-
}
|
|
22066
|
-
});
|
|
22067
|
-
}
|
|
22068
|
-
return discoveredCodexThreads.value;
|
|
22069
|
-
}
|
|
22070
|
-
};
|
|
22071
|
-
if (options.channelSession === void 0) {
|
|
22072
|
-
discoveredCodexThreads.value = await loadDiscoveredCodexThreads("initial");
|
|
22073
|
-
}
|
|
22074
22044
|
const runtimeDefaults = runnerRuntimeDefaults(options);
|
|
22075
22045
|
const instancePayload = {
|
|
22076
22046
|
instanceId,
|
|
@@ -22229,24 +22199,18 @@ async function openLocalCodexRunner(options, log, cleanup, close) {
|
|
|
22229
22199
|
message: error instanceof Error ? error.message : String(error)
|
|
22230
22200
|
});
|
|
22231
22201
|
});
|
|
22232
|
-
const refreshDiscoveredCodexThreads = async (phase) => {
|
|
22233
|
-
discoveredCodexThreads.value = await loadDiscoveredCodexThreads(phase);
|
|
22234
|
-
await pushHeartbeat();
|
|
22235
|
-
};
|
|
22236
22202
|
const heartbeatInterval = setInterval(() => {
|
|
22237
|
-
void
|
|
22203
|
+
void pushHeartbeat();
|
|
22238
22204
|
}, 15e3);
|
|
22239
22205
|
cleanup.actions.push(() => clearInterval(heartbeatInterval));
|
|
22240
|
-
kandan.onReconnect(
|
|
22241
|
-
() => channelSession === void 0 ? refreshDiscoveredCodexThreads("reconnect").then(() => void 0) : pushHeartbeat().then(() => void 0)
|
|
22242
|
-
);
|
|
22206
|
+
kandan.onReconnect(() => pushHeartbeat().then(() => void 0));
|
|
22243
22207
|
void pushHeartbeat();
|
|
22244
|
-
const
|
|
22208
|
+
const forwardTcp = createForwardTcpManager(
|
|
22245
22209
|
kandan,
|
|
22246
22210
|
topic,
|
|
22247
22211
|
() => Array.from(liveForwardPorts)
|
|
22248
22212
|
);
|
|
22249
|
-
cleanup.actions.push(() =>
|
|
22213
|
+
cleanup.actions.push(() => forwardTcp.close());
|
|
22250
22214
|
const channelCodexThreadId = channelSession?.currentCodexThreadId();
|
|
22251
22215
|
if (options.launchTui && channelCodexThreadId !== void 0) {
|
|
22252
22216
|
await prepareCodexThreadForTuiResume(codex, channelCodexThreadId);
|
|
@@ -22282,9 +22246,6 @@ async function openLocalCodexRunner(options, log, cleanup, close) {
|
|
|
22282
22246
|
});
|
|
22283
22247
|
});
|
|
22284
22248
|
}
|
|
22285
|
-
if (channelSession === void 0 && notification.method === "thread/started") {
|
|
22286
|
-
void refreshDiscoveredCodexThreads("thread_started");
|
|
22287
|
-
}
|
|
22288
22249
|
log("codex.notification", {
|
|
22289
22250
|
method: notification.method,
|
|
22290
22251
|
metadata
|
|
@@ -22343,8 +22304,8 @@ async function openLocalCodexRunner(options, log, cleanup, close) {
|
|
|
22343
22304
|
});
|
|
22344
22305
|
return;
|
|
22345
22306
|
}
|
|
22346
|
-
if (
|
|
22347
|
-
|
|
22307
|
+
if (isForwardTcpControl(control)) {
|
|
22308
|
+
forwardTcp.handle(control);
|
|
22348
22309
|
return;
|
|
22349
22310
|
}
|
|
22350
22311
|
if (isStartLocalEditorControl(control)) {
|
|
@@ -22548,99 +22509,6 @@ async function closeCleanupStack(cleanup) {
|
|
|
22548
22509
|
})();
|
|
22549
22510
|
return cleanup.closePromise;
|
|
22550
22511
|
}
|
|
22551
|
-
async function discoverCodexThreads(codex, _cwd) {
|
|
22552
|
-
const response = await codex.request("thread/list", {
|
|
22553
|
-
limit: CODEX_THREAD_DISCOVERY_LIMIT,
|
|
22554
|
-
sortKey: "updated_at",
|
|
22555
|
-
sortDirection: "desc",
|
|
22556
|
-
archived: false,
|
|
22557
|
-
useStateDbOnly: true
|
|
22558
|
-
});
|
|
22559
|
-
if ("error" in response) {
|
|
22560
|
-
throw new Error(`thread/list failed: ${response.error.message}`);
|
|
22561
|
-
}
|
|
22562
|
-
const result = objectValue(response.result);
|
|
22563
|
-
const data = arrayValue(result?.data)?.filter(isJsonObject) ?? [];
|
|
22564
|
-
const rowsById = /* @__PURE__ */ new Map();
|
|
22565
|
-
for (const thread of data.slice(0, CODEX_THREAD_DISCOVERY_LIMIT)) {
|
|
22566
|
-
const row = codexThreadHistoryRow(thread, false);
|
|
22567
|
-
const id = stringValue(objectValue(row)?.id);
|
|
22568
|
-
if (id !== void 0 && id !== "" && !rowsById.has(id)) {
|
|
22569
|
-
rowsById.set(id, row);
|
|
22570
|
-
}
|
|
22571
|
-
}
|
|
22572
|
-
return Array.from(rowsById.values()).sort(compareCodexThreadHistoryRows);
|
|
22573
|
-
}
|
|
22574
|
-
var CODEX_THREAD_DISCOVERY_LIMIT = 50;
|
|
22575
|
-
var CODEX_THREAD_TITLE_FIELD_LIMIT = 500;
|
|
22576
|
-
var CODEX_THREAD_TEXT_FIELD_LIMIT = 2e3;
|
|
22577
|
-
var CODEX_THREAD_PATH_FIELD_LIMIT = 1e3;
|
|
22578
|
-
function codexThreadHistoryRow(thread, archived) {
|
|
22579
|
-
const gitInfo = objectValue(thread.gitInfo);
|
|
22580
|
-
const preview = codexThreadText(thread.preview, CODEX_THREAD_TEXT_FIELD_LIMIT).replace(/\s+/g, " ").trim();
|
|
22581
|
-
const name = codexThreadText(thread.name, CODEX_THREAD_TITLE_FIELD_LIMIT);
|
|
22582
|
-
const directTitle = codexThreadText(
|
|
22583
|
-
thread.title,
|
|
22584
|
-
CODEX_THREAD_TITLE_FIELD_LIMIT
|
|
22585
|
-
);
|
|
22586
|
-
const title = directTitle === "" ? name === "" ? preview : name : directTitle;
|
|
22587
|
-
const description = codexThreadText(thread.description, CODEX_THREAD_TEXT_FIELD_LIMIT) || codexThreadText(thread.summary, CODEX_THREAD_TEXT_FIELD_LIMIT) || preview;
|
|
22588
|
-
return {
|
|
22589
|
-
id: codexThreadText(thread.id, CODEX_THREAD_PATH_FIELD_LIMIT),
|
|
22590
|
-
title: title ?? "",
|
|
22591
|
-
description: description ?? "",
|
|
22592
|
-
preview,
|
|
22593
|
-
cwd: codexThreadText(thread.cwd, CODEX_THREAD_PATH_FIELD_LIMIT),
|
|
22594
|
-
source: codexThreadText(thread.source, CODEX_THREAD_TITLE_FIELD_LIMIT),
|
|
22595
|
-
createdAt: codexTimestamp(thread.createdAt),
|
|
22596
|
-
updatedAt: codexTimestamp(thread.updatedAt),
|
|
22597
|
-
archived,
|
|
22598
|
-
modelProvider: codexThreadText(
|
|
22599
|
-
thread.modelProvider,
|
|
22600
|
-
CODEX_THREAD_TITLE_FIELD_LIMIT
|
|
22601
|
-
),
|
|
22602
|
-
cliVersion: codexThreadText(
|
|
22603
|
-
thread.cliVersion,
|
|
22604
|
-
CODEX_THREAD_TITLE_FIELD_LIMIT
|
|
22605
|
-
),
|
|
22606
|
-
gitBranch: codexThreadText(
|
|
22607
|
-
gitInfo?.branch,
|
|
22608
|
-
CODEX_THREAD_TITLE_FIELD_LIMIT
|
|
22609
|
-
),
|
|
22610
|
-
gitOriginUrl: codexThreadText(
|
|
22611
|
-
gitInfo?.originUrl,
|
|
22612
|
-
CODEX_THREAD_PATH_FIELD_LIMIT
|
|
22613
|
-
),
|
|
22614
|
-
path: codexThreadText(thread.path, CODEX_THREAD_PATH_FIELD_LIMIT)
|
|
22615
|
-
};
|
|
22616
|
-
}
|
|
22617
|
-
function codexThreadText(value, maxLength) {
|
|
22618
|
-
const text2 = stringValue(value) ?? "";
|
|
22619
|
-
if (text2.length <= maxLength) {
|
|
22620
|
-
return text2;
|
|
22621
|
-
}
|
|
22622
|
-
return `${text2.slice(0, Math.max(0, maxLength - 3))}...`;
|
|
22623
|
-
}
|
|
22624
|
-
function codexTimestamp(value) {
|
|
22625
|
-
if (typeof value === "number" && Number.isFinite(value)) {
|
|
22626
|
-
return new Date(value * 1e3).toISOString();
|
|
22627
|
-
}
|
|
22628
|
-
return stringValue(value) ?? "";
|
|
22629
|
-
}
|
|
22630
|
-
function compareCodexThreadHistoryRows(left, right) {
|
|
22631
|
-
const leftRow = objectValue(left);
|
|
22632
|
-
const rightRow = objectValue(right);
|
|
22633
|
-
const leftTime = Date.parse(
|
|
22634
|
-
stringValue(leftRow?.createdAt) ?? stringValue(leftRow?.updatedAt) ?? ""
|
|
22635
|
-
);
|
|
22636
|
-
const rightTime = Date.parse(
|
|
22637
|
-
stringValue(rightRow?.createdAt) ?? stringValue(rightRow?.updatedAt) ?? ""
|
|
22638
|
-
);
|
|
22639
|
-
return safeComparableTime(leftTime) - safeComparableTime(rightTime);
|
|
22640
|
-
}
|
|
22641
|
-
function safeComparableTime(value) {
|
|
22642
|
-
return Number.isFinite(value) ? value : Number.MAX_SAFE_INTEGER;
|
|
22643
|
-
}
|
|
22644
22512
|
function extractStartedThreadId(response) {
|
|
22645
22513
|
if ("error" in response) {
|
|
22646
22514
|
throw new Error(`thread/start failed: ${response.error.message}`);
|
|
@@ -23023,9 +22891,9 @@ async function applyControl(codex, kandan, topic, instanceId, options, allowedCw
|
|
|
23023
22891
|
case "update_session_settings":
|
|
23024
22892
|
case "set_port_forward_enabled":
|
|
23025
22893
|
case "forward_http_request":
|
|
23026
|
-
case "
|
|
23027
|
-
case "
|
|
23028
|
-
case "
|
|
22894
|
+
case "forward_tcp_open":
|
|
22895
|
+
case "forward_tcp_send":
|
|
22896
|
+
case "forward_tcp_close":
|
|
23029
22897
|
case "start_local_editor":
|
|
23030
22898
|
case "update_runner_config":
|
|
23031
22899
|
return { instanceId, controlType: control.type, skipped: true };
|
|
@@ -27278,6 +27146,16 @@ import { stdin as defaultStdin, stdout as defaultStdout } from "node:process";
|
|
|
27278
27146
|
import { emitKeypressEvents } from "node:readline";
|
|
27279
27147
|
|
|
27280
27148
|
// src/signupServerClient.ts
|
|
27149
|
+
var SignupServerError = class extends Error {
|
|
27150
|
+
status;
|
|
27151
|
+
code;
|
|
27152
|
+
constructor(args) {
|
|
27153
|
+
super(args.message);
|
|
27154
|
+
this.name = "SignupServerError";
|
|
27155
|
+
this.status = args.status;
|
|
27156
|
+
this.code = args.code;
|
|
27157
|
+
}
|
|
27158
|
+
};
|
|
27281
27159
|
function createSignupServerClient(args) {
|
|
27282
27160
|
const serviceUrl = args.serviceUrl ?? defaultLinzumiHttpUrl;
|
|
27283
27161
|
const fetchImpl = args.fetchImpl ?? fetch;
|
|
@@ -27368,9 +27246,7 @@ async function signupJsonRequest(args) {
|
|
|
27368
27246
|
});
|
|
27369
27247
|
const responseText = await response.text();
|
|
27370
27248
|
if (!response.ok) {
|
|
27371
|
-
throw
|
|
27372
|
-
`Linzumi signup request failed with HTTP ${response.status}${errorResponseDetail(responseText)}`
|
|
27373
|
-
);
|
|
27249
|
+
throw signupResponseError(response.status, responseText);
|
|
27374
27250
|
}
|
|
27375
27251
|
const body = parseJsonResponse(responseText, "Linzumi signup response");
|
|
27376
27252
|
return args.render(body);
|
|
@@ -27389,6 +27265,38 @@ function errorResponseDetail(text2) {
|
|
|
27389
27265
|
}
|
|
27390
27266
|
return `: ${trimmed.slice(0, 240)}`;
|
|
27391
27267
|
}
|
|
27268
|
+
function signupResponseError(status, text2) {
|
|
27269
|
+
const code = signupErrorCodeFromResponseText(text2);
|
|
27270
|
+
if (code !== void 0) {
|
|
27271
|
+
return new SignupServerError({
|
|
27272
|
+
status,
|
|
27273
|
+
code,
|
|
27274
|
+
message: code
|
|
27275
|
+
});
|
|
27276
|
+
}
|
|
27277
|
+
return new Error(
|
|
27278
|
+
`Linzumi signup request failed with HTTP ${status}${errorResponseDetail(text2)}`
|
|
27279
|
+
);
|
|
27280
|
+
}
|
|
27281
|
+
function signupErrorCodeFromResponseText(text2) {
|
|
27282
|
+
const trimmed = text2.trim();
|
|
27283
|
+
if (trimmed === "") {
|
|
27284
|
+
return void 0;
|
|
27285
|
+
}
|
|
27286
|
+
try {
|
|
27287
|
+
const value = JSON.parse(trimmed);
|
|
27288
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
27289
|
+
return void 0;
|
|
27290
|
+
}
|
|
27291
|
+
const error = value.error;
|
|
27292
|
+
if (typeof error === "string" && error.trim() !== "") {
|
|
27293
|
+
return error;
|
|
27294
|
+
}
|
|
27295
|
+
return void 0;
|
|
27296
|
+
} catch (_error) {
|
|
27297
|
+
return void 0;
|
|
27298
|
+
}
|
|
27299
|
+
}
|
|
27392
27300
|
function renderEmailCodeStart(value) {
|
|
27393
27301
|
const body = objectRecord(value, "signup email-code start response");
|
|
27394
27302
|
return {
|
|
@@ -27576,6 +27484,7 @@ function booleanValue(record, key) {
|
|
|
27576
27484
|
}
|
|
27577
27485
|
|
|
27578
27486
|
// src/signupFlow.ts
|
|
27487
|
+
var maxSignupVerificationCodeAttempts = 3;
|
|
27579
27488
|
var blue = (value) => `\x1B[38;5;75m${value}\x1B[0m`;
|
|
27580
27489
|
var green = (value) => `\x1B[38;5;114m${value}\x1B[0m`;
|
|
27581
27490
|
var red = (value) => `\x1B[38;5;203m${value}\x1B[0m`;
|
|
@@ -28108,22 +28017,19 @@ async function runSignupFlow(deps = {}) {
|
|
|
28108
28017
|
writeDebugLaunchPayload(output, state, debugLaunchPayload);
|
|
28109
28018
|
return;
|
|
28110
28019
|
}
|
|
28111
|
-
|
|
28112
|
-
|
|
28113
|
-
|
|
28114
|
-
|
|
28115
|
-
});
|
|
28116
|
-
const verifyResult = signupServerClient === void 0 ? void 0 : await verifyEmailCodeForSignup(signupServerClient, {
|
|
28020
|
+
const verificationResult = await promptForVerifiedEmailCode({
|
|
28021
|
+
prompts,
|
|
28022
|
+
output,
|
|
28023
|
+
signupServerClient,
|
|
28117
28024
|
pendingId: codeRequest.request.pendingId,
|
|
28118
|
-
|
|
28025
|
+
email: codeRequest.request.email
|
|
28119
28026
|
});
|
|
28120
|
-
if (
|
|
28027
|
+
if (verificationResult.type === "failed") {
|
|
28121
28028
|
state = updateSignupState(state, {
|
|
28122
28029
|
currentStep: "launch",
|
|
28123
|
-
verificationCode: code,
|
|
28124
|
-
launchFailure:
|
|
28030
|
+
verificationCode: verificationResult.code,
|
|
28031
|
+
launchFailure: verificationResult.message
|
|
28125
28032
|
});
|
|
28126
|
-
writeCodeEntry(output, code);
|
|
28127
28033
|
writeSignupScreen(output, state);
|
|
28128
28034
|
writePreflightSummary(output, state);
|
|
28129
28035
|
writeSelectedProjectsSummary(output, state);
|
|
@@ -28132,14 +28038,13 @@ async function runSignupFlow(deps = {}) {
|
|
|
28132
28038
|
writeDebugLaunchPayload(output, state, debugLaunchPayload);
|
|
28133
28039
|
return;
|
|
28134
28040
|
}
|
|
28135
|
-
verifiedAuth =
|
|
28041
|
+
verifiedAuth = verificationResult.verifiedAuth;
|
|
28136
28042
|
const storedSignupAuth = verifiedAuth === void 0 ? writeSignupAuth({ email }) : signupAuthFromVerification(verifiedAuth, serviceUrl);
|
|
28137
28043
|
state = updateSignupState(state, {
|
|
28138
28044
|
currentStep: "launch",
|
|
28139
28045
|
storedSignupAuth,
|
|
28140
|
-
verificationCode: code
|
|
28046
|
+
verificationCode: verificationResult.code
|
|
28141
28047
|
});
|
|
28142
|
-
writeCodeEntry(output, code);
|
|
28143
28048
|
}
|
|
28144
28049
|
if (signupServerClient !== void 0 && verifiedAuth !== void 0) {
|
|
28145
28050
|
const defaultWorkspaceName = verifiedAuth.privateWorkspaceDefault.name || defaultWorkspaceNameForEmail(
|
|
@@ -28288,7 +28193,7 @@ async function launchSignupCommanderForCompletedSignup(commanderLauncher, args)
|
|
|
28288
28193
|
} catch (error) {
|
|
28289
28194
|
return {
|
|
28290
28195
|
status: "failed",
|
|
28291
|
-
runnerId: signupCommanderRunnerId(args.
|
|
28196
|
+
runnerId: signupCommanderRunnerId(args.serviceUrl),
|
|
28292
28197
|
restartCommand: signupConnectRestartCommand(args),
|
|
28293
28198
|
error: error instanceof Error ? error.message : String(error)
|
|
28294
28199
|
};
|
|
@@ -28335,7 +28240,8 @@ async function verifyEmailCodeForSignup(signupServerClient, args) {
|
|
|
28335
28240
|
message: signupServerFailureMessage(
|
|
28336
28241
|
"We couldn't verify your Linzumi email code",
|
|
28337
28242
|
error
|
|
28338
|
-
)
|
|
28243
|
+
),
|
|
28244
|
+
code: signupServerFailureCode(error)
|
|
28339
28245
|
};
|
|
28340
28246
|
}
|
|
28341
28247
|
}
|
|
@@ -28343,6 +28249,43 @@ function signupServerFailureMessage(prefix, error) {
|
|
|
28343
28249
|
const message = error instanceof Error ? error.message : String(error);
|
|
28344
28250
|
return `${prefix}: ${message}`;
|
|
28345
28251
|
}
|
|
28252
|
+
function signupServerFailureCode(error) {
|
|
28253
|
+
if (error instanceof SignupServerError) {
|
|
28254
|
+
return error.code;
|
|
28255
|
+
}
|
|
28256
|
+
if (error instanceof Error && error.message === "invalid_signup_code") {
|
|
28257
|
+
return "invalid_signup_code";
|
|
28258
|
+
}
|
|
28259
|
+
return void 0;
|
|
28260
|
+
}
|
|
28261
|
+
async function promptForVerifiedEmailCode(args) {
|
|
28262
|
+
writeVerificationPrompt(args.output, args.email);
|
|
28263
|
+
return verifyPromptAttempt(args, 1);
|
|
28264
|
+
}
|
|
28265
|
+
async function verifyPromptAttempt(args, attempt) {
|
|
28266
|
+
const code = await args.prompts.input({
|
|
28267
|
+
message: "Enter your Linzumi verification code",
|
|
28268
|
+
defaultValue: args.signupServerClient === void 0 ? "482931" : ""
|
|
28269
|
+
});
|
|
28270
|
+
const verifyResult = args.signupServerClient === void 0 ? void 0 : await verifyEmailCodeForSignup(args.signupServerClient, {
|
|
28271
|
+
pendingId: args.pendingId,
|
|
28272
|
+
code
|
|
28273
|
+
});
|
|
28274
|
+
writeCodeEntry(args.output, code);
|
|
28275
|
+
if (verifyResult?.type === "failed") {
|
|
28276
|
+
if (verifyResult.code === "invalid_signup_code" && attempt < maxSignupVerificationCodeAttempts) {
|
|
28277
|
+
writeBoundedLine(
|
|
28278
|
+
args.output,
|
|
28279
|
+
muted(
|
|
28280
|
+
" That code was not valid. Enter the newest 6-digit code from your email."
|
|
28281
|
+
)
|
|
28282
|
+
);
|
|
28283
|
+
return verifyPromptAttempt(args, attempt + 1);
|
|
28284
|
+
}
|
|
28285
|
+
return { type: "failed", message: verifyResult.message, code };
|
|
28286
|
+
}
|
|
28287
|
+
return verifyResult === void 0 ? { type: "completed", code } : { type: "completed", code, verifiedAuth: verifyResult.auth };
|
|
28288
|
+
}
|
|
28346
28289
|
async function refreshExistingSignupAuth(prompts, output, auth, writeSignupAuth, signupServerClient, serviceUrl) {
|
|
28347
28290
|
output.write(
|
|
28348
28291
|
`${green("\u2713")} You're already logged in!
|
|
@@ -28361,25 +28304,29 @@ ${muted(
|
|
|
28361
28304
|
if (codeRequest.type === "failed") {
|
|
28362
28305
|
return codeRequest;
|
|
28363
28306
|
}
|
|
28364
|
-
|
|
28365
|
-
|
|
28366
|
-
|
|
28367
|
-
|
|
28368
|
-
});
|
|
28369
|
-
const verifyResult = signupServerClient === void 0 ? void 0 : await verifyEmailCodeForSignup(signupServerClient, {
|
|
28307
|
+
const verificationResult = await promptForVerifiedEmailCode({
|
|
28308
|
+
prompts,
|
|
28309
|
+
output,
|
|
28310
|
+
signupServerClient,
|
|
28370
28311
|
pendingId: codeRequest.request.pendingId,
|
|
28371
|
-
|
|
28312
|
+
email: codeRequest.request.email
|
|
28372
28313
|
});
|
|
28373
|
-
if (
|
|
28374
|
-
writeCodeEntry(output, code);
|
|
28314
|
+
if (verificationResult.type === "failed") {
|
|
28375
28315
|
output.write("\n");
|
|
28376
|
-
return
|
|
28316
|
+
return {
|
|
28317
|
+
type: "failed",
|
|
28318
|
+
message: verificationResult.message
|
|
28319
|
+
};
|
|
28377
28320
|
}
|
|
28378
|
-
const verifiedAuth =
|
|
28321
|
+
const verifiedAuth = verificationResult.verifiedAuth;
|
|
28379
28322
|
const refreshedAuth = verifiedAuth === void 0 ? writeSignupAuth({ email: auth.email }) : signupAuthFromVerification(verifiedAuth, serviceUrl);
|
|
28380
|
-
writeCodeEntry(output, code);
|
|
28381
28323
|
output.write("\n");
|
|
28382
|
-
return {
|
|
28324
|
+
return {
|
|
28325
|
+
type: "completed",
|
|
28326
|
+
auth: refreshedAuth,
|
|
28327
|
+
code: verificationResult.code,
|
|
28328
|
+
verifiedAuth
|
|
28329
|
+
};
|
|
28383
28330
|
}
|
|
28384
28331
|
async function validateExistingSignupAuth(signupServerClient, auth, retryPolicy) {
|
|
28385
28332
|
if (signupServerClient === void 0 || auth.accessToken === void 0) {
|
|
@@ -28855,7 +28802,7 @@ async function defaultSignupCommanderLauncher(args) {
|
|
|
28855
28802
|
accessToken: args.localRunnerAccessToken,
|
|
28856
28803
|
expiresInSeconds: args.localRunnerExpiresInSeconds
|
|
28857
28804
|
});
|
|
28858
|
-
const runnerId = signupCommanderRunnerId(args.
|
|
28805
|
+
const runnerId = signupCommanderRunnerId(args.serviceUrl);
|
|
28859
28806
|
const restartCommand = signupConnectRestartCommand(args);
|
|
28860
28807
|
try {
|
|
28861
28808
|
const handle = await runLocalCodexRunner(
|
|
@@ -28878,13 +28825,13 @@ async function defaultSignupCommanderLauncher(args) {
|
|
|
28878
28825
|
};
|
|
28879
28826
|
}
|
|
28880
28827
|
}
|
|
28881
|
-
function signupCommanderRunnerId(
|
|
28882
|
-
return
|
|
28828
|
+
function signupCommanderRunnerId(serviceUrl) {
|
|
28829
|
+
return ensureLocalRunnerIdForLinzumiUrl(serviceUrl);
|
|
28883
28830
|
}
|
|
28884
28831
|
function failedSignupCommanderLaunchForMissingCodex(args) {
|
|
28885
28832
|
return {
|
|
28886
28833
|
status: "failed",
|
|
28887
|
-
runnerId:
|
|
28834
|
+
runnerId: "commander-not-started",
|
|
28888
28835
|
restartCommand: signupConnectRestartCommand(args),
|
|
28889
28836
|
error: "Codex preflight did not resolve a verified Codex command. Install Codex or fix the Codex CLI on PATH, then rerun signup."
|
|
28890
28837
|
};
|
|
@@ -30251,7 +30198,7 @@ function runProcessCapture(args) {
|
|
|
30251
30198
|
child.on("error", () => {
|
|
30252
30199
|
finish("");
|
|
30253
30200
|
});
|
|
30254
|
-
child.on("
|
|
30201
|
+
child.on("close", (code) => {
|
|
30255
30202
|
finish(code === 0 ? stdout : "");
|
|
30256
30203
|
});
|
|
30257
30204
|
});
|
|
@@ -30714,8 +30661,6 @@ function startCommanderDaemon(options) {
|
|
|
30714
30661
|
"commander",
|
|
30715
30662
|
...options.cwd === void 0 ? [] : [options.cwd],
|
|
30716
30663
|
...options.args,
|
|
30717
|
-
"--runner-id",
|
|
30718
|
-
options.runnerId,
|
|
30719
30664
|
"--log-file",
|
|
30720
30665
|
logFile
|
|
30721
30666
|
];
|
|
@@ -30965,7 +30910,6 @@ var flagDefinitions = /* @__PURE__ */ new Map([
|
|
|
30965
30910
|
["api-url", { kind: "value" }],
|
|
30966
30911
|
["linzumi-url", { kind: "value" }],
|
|
30967
30912
|
["token", { kind: "value" }],
|
|
30968
|
-
["runner-id", { kind: "value" }],
|
|
30969
30913
|
["cwd", { kind: "value" }],
|
|
30970
30914
|
["codex-bin", { kind: "value" }],
|
|
30971
30915
|
["codex-url", { kind: "value" }],
|
|
@@ -31291,7 +31235,8 @@ async function runCommanderDaemonCommand(args) {
|
|
|
31291
31235
|
process.stdout.write(commanderDaemonHelpText());
|
|
31292
31236
|
return;
|
|
31293
31237
|
}
|
|
31294
|
-
const
|
|
31238
|
+
const kandanUrl = kandanUrlValue(values) ?? defaultLinzumiWebSocketUrl;
|
|
31239
|
+
const runnerId = ensureLocalRunnerIdForLinzumiUrl(kandanUrl);
|
|
31295
31240
|
const cwd = cwdArg === void 0 || cwdArg.trim() === "" ? void 0 : resolveUserPath(cwdArg);
|
|
31296
31241
|
const record = startCommanderDaemon({
|
|
31297
31242
|
runnerId,
|
|
@@ -31315,7 +31260,8 @@ async function runCommanderDaemonCommand(args) {
|
|
|
31315
31260
|
}
|
|
31316
31261
|
case "status": {
|
|
31317
31262
|
const values = strictFlagValues(rest);
|
|
31318
|
-
const
|
|
31263
|
+
const kandanUrl = kandanUrlValue(values) ?? defaultLinzumiWebSocketUrl;
|
|
31264
|
+
const runnerId = ensureLocalRunnerIdForLinzumiUrl(kandanUrl);
|
|
31319
31265
|
const status = commanderDaemonStatus(
|
|
31320
31266
|
runnerId,
|
|
31321
31267
|
stringValue4(values, "status-dir")
|
|
@@ -31326,7 +31272,8 @@ async function runCommanderDaemonCommand(args) {
|
|
|
31326
31272
|
}
|
|
31327
31273
|
case "wait": {
|
|
31328
31274
|
const values = strictFlagValues(rest);
|
|
31329
|
-
const
|
|
31275
|
+
const kandanUrl = kandanUrlValue(values) ?? defaultLinzumiWebSocketUrl;
|
|
31276
|
+
const runnerId = ensureLocalRunnerIdForLinzumiUrl(kandanUrl);
|
|
31330
31277
|
const timeoutMs = positiveIntegerValue2(values, "timeout-ms") ?? 3e4;
|
|
31331
31278
|
const result = await waitForCommanderDaemon({
|
|
31332
31279
|
runnerId,
|
|
@@ -31345,7 +31292,8 @@ async function runCommanderDaemonCommand(args) {
|
|
|
31345
31292
|
}
|
|
31346
31293
|
case "stop": {
|
|
31347
31294
|
const values = strictFlagValues(rest);
|
|
31348
|
-
const
|
|
31295
|
+
const kandanUrl = kandanUrlValue(values) ?? defaultLinzumiWebSocketUrl;
|
|
31296
|
+
const runnerId = ensureLocalRunnerIdForLinzumiUrl(kandanUrl);
|
|
31349
31297
|
const status = stopCommanderDaemon(
|
|
31350
31298
|
runnerId,
|
|
31351
31299
|
stringValue4(values, "status-dir")
|
|
@@ -31391,7 +31339,8 @@ async function parseStartRunnerArgs(args, deps = {
|
|
|
31391
31339
|
fetchStartTarget: fetchLocalRunnerStartTarget,
|
|
31392
31340
|
validateToken: validateLocalRunnerToken,
|
|
31393
31341
|
buildDependencyStatus: buildRunnerDependencyStatus,
|
|
31394
|
-
resolveEditorRuntime
|
|
31342
|
+
resolveEditorRuntime,
|
|
31343
|
+
ensureRunnerId: ensureLocalRunnerIdForLinzumiUrl
|
|
31395
31344
|
}) {
|
|
31396
31345
|
const { cwdArg, flagArgs } = splitStartArgs(args);
|
|
31397
31346
|
const values = strictFlagValues(flagArgs);
|
|
@@ -31463,7 +31412,9 @@ async function parseStartRunnerArgs(args, deps = {
|
|
|
31463
31412
|
return {
|
|
31464
31413
|
kandanUrl,
|
|
31465
31414
|
token: targetToken,
|
|
31466
|
-
runnerId:
|
|
31415
|
+
runnerId: (deps.ensureRunnerId ?? ensureLocalRunnerIdForLinzumiUrl)(
|
|
31416
|
+
kandanUrl
|
|
31417
|
+
),
|
|
31467
31418
|
workspaceSlug: target.workspaceSlug,
|
|
31468
31419
|
cwd,
|
|
31469
31420
|
codexBin,
|
|
@@ -31500,7 +31451,8 @@ async function parseStartRunnerArgs(args, deps = {
|
|
|
31500
31451
|
async function parseAgentRunnerArgs(args, deps = {
|
|
31501
31452
|
readTextFile: readAgentTokenTextFile,
|
|
31502
31453
|
buildDependencyStatus: buildRunnerDependencyStatus,
|
|
31503
|
-
resolveEditorRuntime
|
|
31454
|
+
resolveEditorRuntime,
|
|
31455
|
+
ensureRunnerId: ensureLocalRunnerIdForLinzumiUrl
|
|
31504
31456
|
}) {
|
|
31505
31457
|
const { cwdArg, flagArgs } = splitStartArgs(args);
|
|
31506
31458
|
const values = strictFlagValues(flagArgs);
|
|
@@ -31565,7 +31517,9 @@ async function parseAgentRunnerArgs(args, deps = {
|
|
|
31565
31517
|
return {
|
|
31566
31518
|
kandanUrl,
|
|
31567
31519
|
token: tokenFile.commanderToken,
|
|
31568
|
-
runnerId:
|
|
31520
|
+
runnerId: (deps.ensureRunnerId ?? ensureLocalRunnerIdForLinzumiUrl)(
|
|
31521
|
+
kandanUrl
|
|
31522
|
+
),
|
|
31569
31523
|
workspaceSlug: tokenFile.workspaceId,
|
|
31570
31524
|
cwd,
|
|
31571
31525
|
codexBin,
|
|
@@ -31665,7 +31619,8 @@ async function resolveStartTargetToken(args) {
|
|
|
31665
31619
|
async function parseRunnerArgs(args, deps = {
|
|
31666
31620
|
resolveToken: resolveLocalRunnerToken,
|
|
31667
31621
|
buildDependencyStatus: buildRunnerDependencyStatus,
|
|
31668
|
-
resolveEditorRuntime
|
|
31622
|
+
resolveEditorRuntime,
|
|
31623
|
+
ensureRunnerId: ensureLocalRunnerIdForLinzumiUrl
|
|
31669
31624
|
}) {
|
|
31670
31625
|
const values = strictFlagValues(args);
|
|
31671
31626
|
if (values.get("help") === true) {
|
|
@@ -31717,7 +31672,9 @@ async function parseRunnerArgs(args, deps = {
|
|
|
31717
31672
|
return {
|
|
31718
31673
|
kandanUrl,
|
|
31719
31674
|
token,
|
|
31720
|
-
runnerId:
|
|
31675
|
+
runnerId: (deps.ensureRunnerId ?? ensureLocalRunnerIdForLinzumiUrl)(
|
|
31676
|
+
kandanUrl
|
|
31677
|
+
),
|
|
31721
31678
|
cwd,
|
|
31722
31679
|
codexBin,
|
|
31723
31680
|
codexUrl: stringValue4(values, "codex-url"),
|
|
@@ -31835,7 +31792,7 @@ function stripDaemonSupervisorFlags(args) {
|
|
|
31835
31792
|
}
|
|
31836
31793
|
const key = arg.startsWith("--") ? arg.slice(2) : void 0;
|
|
31837
31794
|
const definition = key === void 0 ? void 0 : flagDefinitions.get(key);
|
|
31838
|
-
if (key === "
|
|
31795
|
+
if (key === "log-file" || key === "status-dir") {
|
|
31839
31796
|
if (definition?.kind === "value") {
|
|
31840
31797
|
index += 1;
|
|
31841
31798
|
}
|
|
@@ -31976,8 +31933,8 @@ Usage:
|
|
|
31976
31933
|
linzumi done <thread_id> --message <message>
|
|
31977
31934
|
linzumi init-hello-linzumi-demo-app
|
|
31978
31935
|
linzumi codex start-new --title <title> --runner <runner_id> --cwd <path> --work-description <text>
|
|
31979
|
-
linzumi commander daemon
|
|
31980
|
-
linzumi commander wait
|
|
31936
|
+
linzumi commander daemon
|
|
31937
|
+
linzumi commander wait
|
|
31981
31938
|
linzumi commander <folder> [options]
|
|
31982
31939
|
linzumi start <folder> [options]
|
|
31983
31940
|
linzumi paths list|add|remove [path]
|
|
@@ -32021,7 +31978,7 @@ Examples:
|
|
|
32021
31978
|
linzumi done thr_abc123 --message "Done: https://github.com/example/repo/pull/1"
|
|
32022
31979
|
linzumi init-hello-linzumi-demo-app
|
|
32023
31980
|
linzumi paths add ~/code/my-app
|
|
32024
|
-
linzumi commander daemon
|
|
31981
|
+
linzumi commander daemon
|
|
32025
31982
|
linzumi start ~/
|
|
32026
31983
|
linzumi start ~/code/my-app
|
|
32027
31984
|
linzumi connect --workspace <your-workspace> --launch-tui
|
|
@@ -32072,11 +32029,11 @@ function commanderDaemonHelpText() {
|
|
|
32072
32029
|
return `Linzumi Commander daemon
|
|
32073
32030
|
|
|
32074
32031
|
Usage:
|
|
32075
|
-
linzumi commander daemon
|
|
32076
|
-
linzumi commander daemon <folder>
|
|
32077
|
-
linzumi commander status
|
|
32078
|
-
linzumi commander wait
|
|
32079
|
-
linzumi commander stop
|
|
32032
|
+
linzumi commander daemon [options]
|
|
32033
|
+
linzumi commander daemon <folder> [options]
|
|
32034
|
+
linzumi commander status [options]
|
|
32035
|
+
linzumi commander wait [--timeout-ms <ms>] [options]
|
|
32036
|
+
linzumi commander stop [options]
|
|
32080
32037
|
|
|
32081
32038
|
What it does:
|
|
32082
32039
|
Starts the workspace Commander as a detached process, writes a status file,
|
|
@@ -32086,7 +32043,7 @@ What it does:
|
|
|
32086
32043
|
configured folder.
|
|
32087
32044
|
|
|
32088
32045
|
Options:
|
|
32089
|
-
--
|
|
32046
|
+
--api-url <url> Linzumi API URL used to select the stored scoped runner id
|
|
32090
32047
|
--status-dir <path> Status directory, default ~/.linzumi/commanders
|
|
32091
32048
|
--log-file <path> Commander log path, default in the status dir
|
|
32092
32049
|
--timeout-ms <ms> Wait timeout, default 30000
|
|
@@ -32149,9 +32106,9 @@ Usage:
|
|
|
32149
32106
|
linzumi commander <folder> [options]
|
|
32150
32107
|
linzumi commander daemon [options]
|
|
32151
32108
|
linzumi commander daemon <folder> [options]
|
|
32152
|
-
linzumi commander status
|
|
32153
|
-
linzumi commander wait
|
|
32154
|
-
linzumi commander stop
|
|
32109
|
+
linzumi commander status [options]
|
|
32110
|
+
linzumi commander wait [options]
|
|
32111
|
+
linzumi commander stop [options]
|
|
32155
32112
|
linzumi agent runner <folder> [options]
|
|
32156
32113
|
|
|
32157
32114
|
What it does:
|
|
@@ -32164,7 +32121,6 @@ What it does:
|
|
|
32164
32121
|
Options:
|
|
32165
32122
|
--agent-token-file <path> Agent token cache, default ~/.linzumi/agent-token.json
|
|
32166
32123
|
--api-url <url> Linzumi API URL. Defaults deterministically from the stored apiUrl.
|
|
32167
|
-
--runner-id <id> Stable Commander id
|
|
32168
32124
|
--codex-bin <path> Codex executable, default codex
|
|
32169
32125
|
--code-server-bin <path> Custom development code-server executable. By default Linzumi installs the approved editor runtime.
|
|
32170
32126
|
--listen-user <user> Human whose replies Codex may accept, default owner from claim
|
|
@@ -32178,8 +32134,8 @@ Options:
|
|
|
32178
32134
|
|
|
32179
32135
|
Examples:
|
|
32180
32136
|
linzumi paths add "$PWD"
|
|
32181
|
-
linzumi commander daemon
|
|
32182
|
-
linzumi commander ~/code/my-app --api-url http://127.0.0.1:4162
|
|
32137
|
+
linzumi commander daemon
|
|
32138
|
+
linzumi commander ~/code/my-app --api-url http://127.0.0.1:4162
|
|
32183
32139
|
`;
|
|
32184
32140
|
}
|
|
32185
32141
|
function connectGuideText() {
|
package/package.json
CHANGED