@linzumi/cli 0.0.68-beta → 0.0.69-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 +498 -91
- package/package.json +1 -1
package/README.md
CHANGED
package/dist/index.js
CHANGED
|
@@ -286,6 +286,7 @@ var init_channelSessionSupport = __esm({
|
|
|
286
286
|
|
|
287
287
|
// src/commanderAttachments.ts
|
|
288
288
|
import { readFile, realpath, stat, writeFile, mkdir } from "node:fs/promises";
|
|
289
|
+
import { homedir } from "node:os";
|
|
289
290
|
import {
|
|
290
291
|
basename,
|
|
291
292
|
extname,
|
|
@@ -402,13 +403,14 @@ async function uploadedFileIdsForCommanderOutput(runtime, body, structured) {
|
|
|
402
403
|
return [];
|
|
403
404
|
}
|
|
404
405
|
const cwdRealPath = await realpath(runtime.cwd);
|
|
406
|
+
const uploadRoots = await commanderAttachmentUploadRoots(cwdRealPath);
|
|
405
407
|
const paths = await extractKandanAttachmentPaths(body, cwdRealPath);
|
|
406
408
|
if (paths.length === 0) {
|
|
407
409
|
return [];
|
|
408
410
|
}
|
|
409
411
|
const files = await Promise.all(
|
|
410
412
|
paths.map(async (path2) => {
|
|
411
|
-
assertCommanderAttachmentUploadAllowed(
|
|
413
|
+
assertCommanderAttachmentUploadAllowed(uploadRoots, path2);
|
|
412
414
|
const info = await stat(path2);
|
|
413
415
|
if (!info.isFile()) {
|
|
414
416
|
throw new Error(`Kandan attachment path is not a file: ${path2}`);
|
|
@@ -556,13 +558,19 @@ async function extractKandanAttachmentPaths(body, cwdRealPath) {
|
|
|
556
558
|
const paths = [];
|
|
557
559
|
for (const line of lines.slice(headingIndex + 1)) {
|
|
558
560
|
const trimmed = line.trim();
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
break;
|
|
562
|
-
}
|
|
561
|
+
const rawPath = kandanAttachmentRawPath(trimmed);
|
|
562
|
+
if (rawPath === "") {
|
|
563
563
|
continue;
|
|
564
564
|
}
|
|
565
|
-
|
|
565
|
+
if (rawPath === void 0) {
|
|
566
|
+
break;
|
|
567
|
+
}
|
|
568
|
+
if (commanderAttachmentRawPathHasHiddenSegment(rawPath)) {
|
|
569
|
+
continue;
|
|
570
|
+
}
|
|
571
|
+
if (!isCommanderAttachmentUploadPathCandidate(rawPath)) {
|
|
572
|
+
break;
|
|
573
|
+
}
|
|
566
574
|
const resolvedPath = await resolveCommanderAttachmentPath(
|
|
567
575
|
cwdRealPath,
|
|
568
576
|
rawPath
|
|
@@ -575,27 +583,34 @@ async function extractKandanAttachmentPaths(body, cwdRealPath) {
|
|
|
575
583
|
}
|
|
576
584
|
return paths;
|
|
577
585
|
}
|
|
586
|
+
function kandanAttachmentRawPath(trimmedLine) {
|
|
587
|
+
if (trimmedLine === "") {
|
|
588
|
+
return "";
|
|
589
|
+
}
|
|
590
|
+
const rawPath = trimmedLine.startsWith("- ") ? trimmedLine.slice(2).trim() : trimmedLine;
|
|
591
|
+
if (rawPath === "") {
|
|
592
|
+
return void 0;
|
|
593
|
+
}
|
|
594
|
+
return rawPath.replace(/^`|`$/g, "");
|
|
595
|
+
}
|
|
578
596
|
async function resolveCommanderAttachmentPath(cwdRealPath, rawPath) {
|
|
579
597
|
if (rawPath === "") {
|
|
580
598
|
throw new Error("Kandan attachment path must not be empty");
|
|
581
599
|
}
|
|
582
600
|
const candidatePath = isAbsolute(rawPath) ? resolve(rawPath) : resolve(cwdRealPath, rawPath);
|
|
583
|
-
|
|
584
|
-
const relativePath = relative(cwdRealPath, path2);
|
|
585
|
-
if (relativePath.startsWith("..") || isAbsolute(relativePath)) {
|
|
586
|
-
throw new Error(
|
|
587
|
-
`Kandan attachment path must resolve inside the runner cwd: ${rawPath}`
|
|
588
|
-
);
|
|
589
|
-
}
|
|
590
|
-
return path2;
|
|
601
|
+
return await realpath(candidatePath);
|
|
591
602
|
}
|
|
592
|
-
function assertCommanderAttachmentUploadAllowed(
|
|
593
|
-
const
|
|
594
|
-
|
|
603
|
+
function assertCommanderAttachmentUploadAllowed(uploadRoots, filePath) {
|
|
604
|
+
const matchedRoot = uploadRoots.find(
|
|
605
|
+
(root) => pathIsInsideRoot(root.path, filePath)
|
|
606
|
+
);
|
|
607
|
+
if (matchedRoot === void 0) {
|
|
608
|
+
const rootLabels = uploadRoots.map((root) => root.label).join(", ");
|
|
595
609
|
throw new Error(
|
|
596
|
-
`Kandan attachment path must resolve inside
|
|
610
|
+
`Kandan attachment path must resolve inside an allowed upload root (${rootLabels}): ${filePath}`
|
|
597
611
|
);
|
|
598
612
|
}
|
|
613
|
+
const relativePath = relative(matchedRoot.path, filePath);
|
|
599
614
|
const hiddenSegment = relativePath.split(/[\\/]+/).find((segment) => segment.startsWith("."));
|
|
600
615
|
if (hiddenSegment !== void 0) {
|
|
601
616
|
throw new Error(
|
|
@@ -609,6 +624,25 @@ function assertCommanderAttachmentUploadAllowed(cwdRealPath, filePath) {
|
|
|
609
624
|
);
|
|
610
625
|
}
|
|
611
626
|
}
|
|
627
|
+
async function commanderAttachmentUploadRoots(cwdRealPath) {
|
|
628
|
+
const roots = [
|
|
629
|
+
{ path: cwdRealPath, label: "runner cwd" }
|
|
630
|
+
];
|
|
631
|
+
const downloadsPath = resolve(homedir(), "Downloads");
|
|
632
|
+
try {
|
|
633
|
+
const downloadsRealPath = await realpath(downloadsPath);
|
|
634
|
+
if (!roots.some((root) => root.path === downloadsRealPath)) {
|
|
635
|
+
roots.push({ path: downloadsRealPath, label: "~/Downloads" });
|
|
636
|
+
}
|
|
637
|
+
} catch (_error) {
|
|
638
|
+
return roots;
|
|
639
|
+
}
|
|
640
|
+
return roots;
|
|
641
|
+
}
|
|
642
|
+
function pathIsInsideRoot(rootPath, filePath) {
|
|
643
|
+
const relativePath = relative(rootPath, filePath);
|
|
644
|
+
return relativePath === "" || !relativePath.startsWith("..") && !isAbsolute(relativePath);
|
|
645
|
+
}
|
|
612
646
|
function contentTypeForFileName(fileName) {
|
|
613
647
|
const lower = fileName.toLowerCase();
|
|
614
648
|
if (lower.endsWith(".png")) {
|
|
@@ -634,6 +668,69 @@ function contentTypeForFileName(fileName) {
|
|
|
634
668
|
}
|
|
635
669
|
return "application/octet-stream";
|
|
636
670
|
}
|
|
671
|
+
function bodyWithoutKandanAttachmentFooter(body) {
|
|
672
|
+
const lines = body.split(/\r?\n/);
|
|
673
|
+
const headingIndex = lines.findIndex(
|
|
674
|
+
(line) => line.trim().toLowerCase() === "kandan attachments:"
|
|
675
|
+
);
|
|
676
|
+
if (headingIndex === -1) {
|
|
677
|
+
return body;
|
|
678
|
+
}
|
|
679
|
+
const visibleAfterLines = [];
|
|
680
|
+
let sawVisibleAfterLine = false;
|
|
681
|
+
for (const line of lines.slice(headingIndex + 1)) {
|
|
682
|
+
if (line.trim() === "") {
|
|
683
|
+
switch (sawVisibleAfterLine) {
|
|
684
|
+
case true:
|
|
685
|
+
visibleAfterLines.push(line);
|
|
686
|
+
break;
|
|
687
|
+
case false:
|
|
688
|
+
break;
|
|
689
|
+
}
|
|
690
|
+
continue;
|
|
691
|
+
}
|
|
692
|
+
if (isKandanAttachmentDisplayDirectiveLine(line)) {
|
|
693
|
+
continue;
|
|
694
|
+
}
|
|
695
|
+
visibleAfterLines.push(line);
|
|
696
|
+
sawVisibleAfterLine = true;
|
|
697
|
+
}
|
|
698
|
+
const visibleLines = [...lines.slice(0, headingIndex), ...visibleAfterLines];
|
|
699
|
+
while (visibleLines.length > 0 && visibleLines[visibleLines.length - 1]?.trim() === "") {
|
|
700
|
+
visibleLines.pop();
|
|
701
|
+
}
|
|
702
|
+
return visibleLines.join("\n");
|
|
703
|
+
}
|
|
704
|
+
function displayBodyForCommanderOutput(body, uploadedFileIds) {
|
|
705
|
+
const displayBody = bodyWithoutKandanAttachmentFooter(body);
|
|
706
|
+
switch (displayBody.trim() === "" && uploadedFileIds.length > 0) {
|
|
707
|
+
case true:
|
|
708
|
+
return "Attached file.";
|
|
709
|
+
case false:
|
|
710
|
+
return displayBody;
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
function structuredWithAssistantContent(structured, content) {
|
|
714
|
+
return stringValue(structured.kind) === "codex_assistant_message" ? { ...structured, content } : structured;
|
|
715
|
+
}
|
|
716
|
+
function isKandanAttachmentDisplayDirectiveLine(line) {
|
|
717
|
+
const rawPath = kandanAttachmentRawPath(line.trim());
|
|
718
|
+
if (rawPath === "") {
|
|
719
|
+
return true;
|
|
720
|
+
}
|
|
721
|
+
if (rawPath === void 0) {
|
|
722
|
+
return false;
|
|
723
|
+
}
|
|
724
|
+
return !commanderAttachmentRawPathHasHiddenSegment(rawPath) && commanderAttachmentUploadExtensions.has(extname(rawPath).toLowerCase());
|
|
725
|
+
}
|
|
726
|
+
function isCommanderAttachmentUploadPathCandidate(rawPath) {
|
|
727
|
+
return commanderAttachmentUploadExtensions.has(
|
|
728
|
+
extname(rawPath).toLowerCase()
|
|
729
|
+
);
|
|
730
|
+
}
|
|
731
|
+
function commanderAttachmentRawPathHasHiddenSegment(rawPath) {
|
|
732
|
+
return rawPath.split(/[\\/]+/).some((segment) => segment.startsWith("."));
|
|
733
|
+
}
|
|
637
734
|
async function pushOk(kandan, topic, event, payload) {
|
|
638
735
|
const reply = await kandan.push(topic, event, payload);
|
|
639
736
|
if (isJsonObject(reply) && reply.status === "ok" && isJsonObject(reply.response)) {
|
|
@@ -754,6 +851,7 @@ var init_codexRuntimeOptions = __esm({
|
|
|
754
851
|
|
|
755
852
|
// src/codexOutput.ts
|
|
756
853
|
import { Buffer as Buffer2 } from "node:buffer";
|
|
854
|
+
import { fileURLToPath } from "node:url";
|
|
757
855
|
function codexOutputMessagesForTurn(response, turnId) {
|
|
758
856
|
if ("error" in response) {
|
|
759
857
|
return [];
|
|
@@ -803,19 +901,10 @@ function codexOutputMessagesForItem(item, index) {
|
|
|
803
901
|
}
|
|
804
902
|
];
|
|
805
903
|
}
|
|
806
|
-
case "agentMessage":
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
itemKey,
|
|
811
|
-
body: text2,
|
|
812
|
-
structured: baseStructured("codex_assistant_message", {
|
|
813
|
-
content: text2,
|
|
814
|
-
phase: stringValue(item.phase) ?? "final_answer"
|
|
815
|
-
})
|
|
816
|
-
}
|
|
817
|
-
];
|
|
818
|
-
}
|
|
904
|
+
case "agentMessage":
|
|
905
|
+
return codexAssistantMessageForItem(item, itemKey, baseStructured);
|
|
906
|
+
case "message":
|
|
907
|
+
return stringValue(item.role) === "assistant" ? codexAssistantMessageForItem(item, itemKey, baseStructured) : [];
|
|
819
908
|
case "commandExecution": {
|
|
820
909
|
const command = stringValue(item.command) ?? "command";
|
|
821
910
|
const output = nonBlankStringValue(item.aggregatedOutput) ?? "";
|
|
@@ -1121,7 +1210,26 @@ function codexUserInputMessageForItem(item, index) {
|
|
|
1121
1210
|
const body = textParts.length > 0 ? textParts.join("\n\n") : nonBlankStringValue(item.text) ?? nonBlankStringValue(item.message) ?? "";
|
|
1122
1211
|
return [{ itemKey, body }];
|
|
1123
1212
|
}
|
|
1213
|
+
function codexAssistantMessageForItem(item, itemKey, baseStructured) {
|
|
1214
|
+
const text2 = assistantVisibleText(item);
|
|
1215
|
+
const attachmentPaths = assistantImageAttachmentPaths(item);
|
|
1216
|
+
const body = assistantBodyWithAttachmentPaths(text2, attachmentPaths);
|
|
1217
|
+
return [
|
|
1218
|
+
{
|
|
1219
|
+
itemKey,
|
|
1220
|
+
body,
|
|
1221
|
+
structured: baseStructured("codex_assistant_message", {
|
|
1222
|
+
content: text2,
|
|
1223
|
+
phase: stringValue(item.phase) ?? "final_answer"
|
|
1224
|
+
})
|
|
1225
|
+
}
|
|
1226
|
+
];
|
|
1227
|
+
}
|
|
1124
1228
|
function assistantVisibleText(item) {
|
|
1229
|
+
const contentText = assistantContentText(item);
|
|
1230
|
+
if (contentText !== "") {
|
|
1231
|
+
return contentText;
|
|
1232
|
+
}
|
|
1125
1233
|
const direct = stringValue(item.reply) ?? stringValue(item.summary) ?? stringValue(item.content) ?? stringValue(item.text) ?? "";
|
|
1126
1234
|
const parsed = parseJsonObjectOrUndefined(direct);
|
|
1127
1235
|
if (parsed === void 0) {
|
|
@@ -1129,6 +1237,52 @@ function assistantVisibleText(item) {
|
|
|
1129
1237
|
}
|
|
1130
1238
|
return stringValue(parsed.reply) ?? stringValue(parsed.summary) ?? stringValue(parsed.content) ?? stringValue(parsed.message) ?? stringValue(parsed.output_text) ?? direct;
|
|
1131
1239
|
}
|
|
1240
|
+
function assistantContentText(item) {
|
|
1241
|
+
return (arrayValue(item.content) ?? []).filter(isJsonObject).flatMap((part) => {
|
|
1242
|
+
const type = stringValue(part.type);
|
|
1243
|
+
if (type !== "text" && type !== "output_text" && type !== "input_text") {
|
|
1244
|
+
return [];
|
|
1245
|
+
}
|
|
1246
|
+
const text2 = nonBlankStringValue(part.text) ?? nonBlankStringValue(part.content) ?? nonBlankStringValue(part.output_text);
|
|
1247
|
+
return text2 === void 0 ? [] : [text2];
|
|
1248
|
+
}).join("\n\n");
|
|
1249
|
+
}
|
|
1250
|
+
function assistantBodyWithAttachmentPaths(text2, attachmentPaths) {
|
|
1251
|
+
const uniqueAttachmentPaths = [...new Set(attachmentPaths)];
|
|
1252
|
+
if (uniqueAttachmentPaths.length === 0) {
|
|
1253
|
+
return text2;
|
|
1254
|
+
}
|
|
1255
|
+
const attachmentFooter = [
|
|
1256
|
+
"Kandan attachments:",
|
|
1257
|
+
...uniqueAttachmentPaths.map((path2) => `- ${path2}`)
|
|
1258
|
+
].join("\n");
|
|
1259
|
+
const normalizedText = text2.trim();
|
|
1260
|
+
return normalizedText === "" ? attachmentFooter : [text2, "", attachmentFooter].join("\n");
|
|
1261
|
+
}
|
|
1262
|
+
function assistantImageAttachmentPaths(item) {
|
|
1263
|
+
return (arrayValue(item.content) ?? []).filter(isJsonObject).flatMap((part) => {
|
|
1264
|
+
const type = stringValue(part.type)?.toLowerCase();
|
|
1265
|
+
if (type !== "image" && type !== "output_image" && type !== "input_image") {
|
|
1266
|
+
return [];
|
|
1267
|
+
}
|
|
1268
|
+
const rawPath = stringValue(part.path) ?? stringValue(part.file_path) ?? stringValue(part.filePath) ?? stringValue(part.image_url) ?? stringValue(part.imageUrl) ?? stringValue(part.url);
|
|
1269
|
+
const localPath = rawPath === void 0 ? void 0 : localAttachmentPath(rawPath);
|
|
1270
|
+
return localPath === void 0 ? [] : [localPath];
|
|
1271
|
+
});
|
|
1272
|
+
}
|
|
1273
|
+
function localAttachmentPath(rawPath) {
|
|
1274
|
+
if (/^https?:\/\//i.test(rawPath) || /^data:/i.test(rawPath)) {
|
|
1275
|
+
return void 0;
|
|
1276
|
+
}
|
|
1277
|
+
if (/^file:\/\//i.test(rawPath)) {
|
|
1278
|
+
try {
|
|
1279
|
+
return fileURLToPath(rawPath);
|
|
1280
|
+
} catch (_error) {
|
|
1281
|
+
return void 0;
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
return rawPath;
|
|
1285
|
+
}
|
|
1132
1286
|
function assistantDeltaText(params) {
|
|
1133
1287
|
return textDeltaFromParams(params);
|
|
1134
1288
|
}
|
|
@@ -3333,6 +3487,32 @@ async function attachChannelSession(args) {
|
|
|
3333
3487
|
case "item/completed":
|
|
3334
3488
|
enqueueWebSearchProgress(args, state, params, payloadContext);
|
|
3335
3489
|
enqueueCompletedFileChange(args, state, params, payloadContext);
|
|
3490
|
+
const completedAssistantItemForward = forwardCompletedAssistantItem(
|
|
3491
|
+
args,
|
|
3492
|
+
state,
|
|
3493
|
+
params,
|
|
3494
|
+
payloadContext
|
|
3495
|
+
);
|
|
3496
|
+
if (turnId !== void 0) {
|
|
3497
|
+
rememberPendingCompletedAssistantItemForward(
|
|
3498
|
+
state,
|
|
3499
|
+
turnId,
|
|
3500
|
+
completedAssistantItemForward
|
|
3501
|
+
);
|
|
3502
|
+
}
|
|
3503
|
+
void completedAssistantItemForward.catch((error) => {
|
|
3504
|
+
args.log("codex.completed_assistant_item_forward_failed", {
|
|
3505
|
+
message: error instanceof Error ? error.message : String(error)
|
|
3506
|
+
});
|
|
3507
|
+
}).finally(() => {
|
|
3508
|
+
if (turnId !== void 0) {
|
|
3509
|
+
forgetPendingCompletedAssistantItemForward(
|
|
3510
|
+
state,
|
|
3511
|
+
turnId,
|
|
3512
|
+
completedAssistantItemForward
|
|
3513
|
+
);
|
|
3514
|
+
}
|
|
3515
|
+
});
|
|
3336
3516
|
if (turnId !== void 0) {
|
|
3337
3517
|
const promise = mirrorLocalTuiInputFromNotification(
|
|
3338
3518
|
args,
|
|
@@ -3426,6 +3606,8 @@ function initialChannelSessionState(cursor, rootSeq, kandanThreadId, codexThread
|
|
|
3426
3606
|
forwardedTurnIds: /* @__PURE__ */ new Set(),
|
|
3427
3607
|
forwardingTurnIds: /* @__PURE__ */ new Set(),
|
|
3428
3608
|
retryableTurnIds: /* @__PURE__ */ new Set(),
|
|
3609
|
+
completedAssistantItemKeys: /* @__PURE__ */ new Set(),
|
|
3610
|
+
pendingCompletedAssistantItemForwards: /* @__PURE__ */ new Map(),
|
|
3429
3611
|
claimedKandanMessageKeys: /* @__PURE__ */ new Set(),
|
|
3430
3612
|
localTuiTurnIds: /* @__PURE__ */ new Set(),
|
|
3431
3613
|
mirroredTuiInputProjections: createBoundedCache(maxForwardedTurnIds),
|
|
@@ -5014,6 +5196,7 @@ async function forwardCompletedCodexTurn(args, state, turnId, payloadContext) {
|
|
|
5014
5196
|
};
|
|
5015
5197
|
}
|
|
5016
5198
|
await waitForPendingTuiInputMirror(state, turnId);
|
|
5199
|
+
await waitForPendingCompletedAssistantItemForwards(state, turnId);
|
|
5017
5200
|
await waitForStreamingForwardChains(args, state, payloadContext);
|
|
5018
5201
|
rememberForwardingTurnId(state, turnId);
|
|
5019
5202
|
forgetRetryableTurnId(state, turnId);
|
|
@@ -5124,9 +5307,17 @@ async function forwardCompletedCodexTurn(args, state, turnId, payloadContext) {
|
|
|
5124
5307
|
}
|
|
5125
5308
|
}
|
|
5126
5309
|
function completedOutputProjectionsForTurn(state, turnId, messages) {
|
|
5127
|
-
const snapshotOutputs = messages.flatMap(
|
|
5128
|
-
|
|
5129
|
-
|
|
5310
|
+
const snapshotOutputs = messages.flatMap((message, snapshotIndex) => {
|
|
5311
|
+
if (completedAssistantItemForwarded(state, message.itemKey)) {
|
|
5312
|
+
return [];
|
|
5313
|
+
}
|
|
5314
|
+
return completedSnapshotOutputProjection(
|
|
5315
|
+
state,
|
|
5316
|
+
turnId,
|
|
5317
|
+
message,
|
|
5318
|
+
snapshotIndex
|
|
5319
|
+
);
|
|
5320
|
+
});
|
|
5130
5321
|
const matchedStructuredKeys = new Set(
|
|
5131
5322
|
snapshotOutputs.flatMap((output) => {
|
|
5132
5323
|
switch (output.match.kind) {
|
|
@@ -5395,6 +5586,97 @@ function logCompletedCodexOutput(args, turnId, message) {
|
|
|
5395
5586
|
file_paths: fileChangePaths(message.structured)
|
|
5396
5587
|
});
|
|
5397
5588
|
}
|
|
5589
|
+
async function forwardCompletedAssistantItem(args, state, params, payloadContext) {
|
|
5590
|
+
if (state.kandanThreadId === void 0 || state.codexThreadId === void 0) {
|
|
5591
|
+
return;
|
|
5592
|
+
}
|
|
5593
|
+
const turnId = stringValue(params.turnId) ?? stringValue(params.turn_id) ?? stringValue(objectValue(params.turn)?.id);
|
|
5594
|
+
const item = objectValue(params.item) ?? params;
|
|
5595
|
+
const completedItemKey = stringValue(params.itemId) ?? stringValue(params.item_id) ?? stringValue(objectValue(params.item)?.id);
|
|
5596
|
+
if (turnId !== void 0) {
|
|
5597
|
+
await waitForPendingTuiInputMirror(state, turnId);
|
|
5598
|
+
await waitForStreamingForwardChains(args, state, payloadContext);
|
|
5599
|
+
}
|
|
5600
|
+
const parsedMessage = codexOutputMessagesForItem(item, 0).find(
|
|
5601
|
+
(candidate) => stringValue(candidate.structured.kind) === "codex_assistant_message"
|
|
5602
|
+
);
|
|
5603
|
+
const fallbackStream = parsedMessage === void 0 ? resolveStreamingAssistantOutputForCompletedSignal(
|
|
5604
|
+
state,
|
|
5605
|
+
turnId,
|
|
5606
|
+
completedItemKey
|
|
5607
|
+
) : { status: "none" };
|
|
5608
|
+
if (fallbackStream.status === "ambiguous") {
|
|
5609
|
+
throw new LogicalProjectionError(
|
|
5610
|
+
`Cannot reconcile completed assistant item signal from item notification; ${fallbackStream.candidateCount} active streamed assistant outputs exist`
|
|
5611
|
+
);
|
|
5612
|
+
}
|
|
5613
|
+
const message = parsedMessage ?? (fallbackStream.status === "matched" ? {
|
|
5614
|
+
itemKey: fallbackStream.output.itemKey,
|
|
5615
|
+
body: fallbackStream.output.content,
|
|
5616
|
+
structured: codexAssistantStructuredMessage(
|
|
5617
|
+
fallbackStream.output.itemKey,
|
|
5618
|
+
fallbackStream.output.content,
|
|
5619
|
+
"completed"
|
|
5620
|
+
)
|
|
5621
|
+
} : void 0);
|
|
5622
|
+
const messageTurnId = turnId ?? (fallbackStream.status === "matched" ? fallbackStream.output.turnId : void 0);
|
|
5623
|
+
if (message === void 0 || completedAssistantItemForwarded(state, message.itemKey)) {
|
|
5624
|
+
return;
|
|
5625
|
+
}
|
|
5626
|
+
const sourceMessageSeq = messageTurnId === void 0 ? void 0 : sourceMessageSeqForTurn(state, messageTurnId);
|
|
5627
|
+
if (messageTurnId !== void 0 && sourceMessageSeq === void 0) {
|
|
5628
|
+
args.log("codex.completed_assistant_item_without_source_message", {
|
|
5629
|
+
turn_id: messageTurnId,
|
|
5630
|
+
item_key: message.itemKey
|
|
5631
|
+
});
|
|
5632
|
+
return;
|
|
5633
|
+
}
|
|
5634
|
+
const structured = codexAssistantStructuredMessage(
|
|
5635
|
+
message.itemKey,
|
|
5636
|
+
message.body,
|
|
5637
|
+
"completed"
|
|
5638
|
+
);
|
|
5639
|
+
const streamed = resolveStreamingAssistantOutputForCompletedMessage(
|
|
5640
|
+
state,
|
|
5641
|
+
messageTurnId ?? `item:${message.itemKey}`,
|
|
5642
|
+
message.itemKey,
|
|
5643
|
+
message.body,
|
|
5644
|
+
structured
|
|
5645
|
+
);
|
|
5646
|
+
switch (streamed.status) {
|
|
5647
|
+
case "none":
|
|
5648
|
+
await streamCompletedCodexOutput(args, state, payloadContext, {
|
|
5649
|
+
turnId: turnId ?? `item:${message.itemKey}`,
|
|
5650
|
+
sourceMessageSeq,
|
|
5651
|
+
rootSeq: state.rootSeq,
|
|
5652
|
+
message: {
|
|
5653
|
+
...message,
|
|
5654
|
+
structured
|
|
5655
|
+
}
|
|
5656
|
+
});
|
|
5657
|
+
break;
|
|
5658
|
+
case "matched":
|
|
5659
|
+
await editStreamedCodexOutput(
|
|
5660
|
+
args,
|
|
5661
|
+
state,
|
|
5662
|
+
streamed.output.seq,
|
|
5663
|
+
message.itemKey,
|
|
5664
|
+
message.body,
|
|
5665
|
+
"completed"
|
|
5666
|
+
);
|
|
5667
|
+
forgetStreamingAssistantOutput(state, streamed.output.itemKey);
|
|
5668
|
+
break;
|
|
5669
|
+
case "ambiguous":
|
|
5670
|
+
throw new LogicalProjectionError(
|
|
5671
|
+
`Cannot reconcile completed assistant item ${message.itemKey} from item notification; ${streamed.candidateCount} active streamed assistant outputs exist`
|
|
5672
|
+
);
|
|
5673
|
+
}
|
|
5674
|
+
rememberCompletedAssistantItemKey(state, message.itemKey);
|
|
5675
|
+
logCompletedCodexOutput(args, messageTurnId ?? `item:${message.itemKey}`, {
|
|
5676
|
+
...message,
|
|
5677
|
+
structured
|
|
5678
|
+
});
|
|
5679
|
+
}
|
|
5398
5680
|
function compareCompletedOutputProjection(left, right) {
|
|
5399
5681
|
if (left.kind === "snapshot" && right.kind === "snapshot" && left.match.kind !== right.match.kind && (left.match.kind === "none" || right.match.kind === "none")) {
|
|
5400
5682
|
return left.snapshotIndex - right.snapshotIndex;
|
|
@@ -6271,12 +6553,20 @@ async function streamCompletedCodexOutput(args, state, payloadContext, params) {
|
|
|
6271
6553
|
params.message.body,
|
|
6272
6554
|
structured
|
|
6273
6555
|
);
|
|
6556
|
+
const displayBody = displayBodyForCommanderOutput(
|
|
6557
|
+
params.message.body,
|
|
6558
|
+
uploadedFileIds
|
|
6559
|
+
);
|
|
6560
|
+
const displayStructured = structuredWithAssistantContent(
|
|
6561
|
+
structured,
|
|
6562
|
+
displayBody
|
|
6563
|
+
);
|
|
6274
6564
|
await pushOk2(args.kandan, args.topic, "session:stream_thread_message", {
|
|
6275
6565
|
workspace: session.workspaceSlug,
|
|
6276
6566
|
channel: session.channelSlug,
|
|
6277
6567
|
thread_id: state.kandanThreadId,
|
|
6278
6568
|
stream_key: streamKey,
|
|
6279
|
-
body:
|
|
6569
|
+
body: displayBody,
|
|
6280
6570
|
payload: {
|
|
6281
6571
|
...localRunnerPayload(
|
|
6282
6572
|
args.options,
|
|
@@ -6290,7 +6580,7 @@ async function streamCompletedCodexOutput(args, state, payloadContext, params) {
|
|
|
6290
6580
|
...params.rootSeq === void 0 ? {} : { reply_to_seq: params.rootSeq },
|
|
6291
6581
|
...params.sourceMessageSeq === void 0 ? {} : { source_message_seq: params.sourceMessageSeq },
|
|
6292
6582
|
...streamMetadata,
|
|
6293
|
-
structured
|
|
6583
|
+
structured: displayStructured
|
|
6294
6584
|
},
|
|
6295
6585
|
...uploadedFileIds.length === 0 ? {} : { uploaded_file_ids: uploadedFileIds },
|
|
6296
6586
|
client_message_id: streamKey
|
|
@@ -6313,13 +6603,36 @@ async function editCodexStructuredOutput(args, state, targetSeq, content, struct
|
|
|
6313
6603
|
return;
|
|
6314
6604
|
}
|
|
6315
6605
|
const session = args.options.channelSession;
|
|
6606
|
+
const uploadedFileIds = stringValue(structured.stream_state) === "completed" ? await uploadedFileIdsForCommanderOutput(
|
|
6607
|
+
{
|
|
6608
|
+
kandan: args.kandan,
|
|
6609
|
+
topic: args.topic,
|
|
6610
|
+
workspace: session.workspaceSlug,
|
|
6611
|
+
channel: session.channelSlug,
|
|
6612
|
+
cwd: args.options.cwd,
|
|
6613
|
+
kandanUrl: args.options.kandanUrl,
|
|
6614
|
+
token: args.options.token,
|
|
6615
|
+
fetch: args.options.fetch
|
|
6616
|
+
},
|
|
6617
|
+
content,
|
|
6618
|
+
structured
|
|
6619
|
+
) : [];
|
|
6620
|
+
const displayContent = displayBodyForCommanderOutput(
|
|
6621
|
+
content,
|
|
6622
|
+
uploadedFileIds
|
|
6623
|
+
);
|
|
6624
|
+
const displayStructured = structuredWithAssistantContent(
|
|
6625
|
+
structured,
|
|
6626
|
+
displayContent
|
|
6627
|
+
);
|
|
6316
6628
|
await pushOk2(args.kandan, args.topic, "session:edit_thread_message", {
|
|
6317
6629
|
workspace: session.workspaceSlug,
|
|
6318
6630
|
channel: session.channelSlug,
|
|
6319
6631
|
thread_id: state.kandanThreadId,
|
|
6320
6632
|
target_seq: targetSeq,
|
|
6321
|
-
body:
|
|
6322
|
-
structured
|
|
6633
|
+
body: displayContent,
|
|
6634
|
+
structured: displayStructured,
|
|
6635
|
+
...uploadedFileIds.length === 0 ? {} : { uploaded_file_ids: uploadedFileIds }
|
|
6323
6636
|
});
|
|
6324
6637
|
}
|
|
6325
6638
|
async function mirrorLocalTuiInputFromNotification(args, state, turnId, params, payloadContext) {
|
|
@@ -6495,6 +6808,30 @@ function resolveStreamingAssistantOutputForCompletedMessage(state, turnId, itemK
|
|
|
6495
6808
|
}
|
|
6496
6809
|
}
|
|
6497
6810
|
}
|
|
6811
|
+
function resolveStreamingAssistantOutputForCompletedSignal(state, turnId, itemKey) {
|
|
6812
|
+
if (itemKey !== void 0) {
|
|
6813
|
+
const exact = findStreamingAssistantOutput(state, itemKey);
|
|
6814
|
+
if (exact !== void 0) {
|
|
6815
|
+
return { status: "matched", output: exact };
|
|
6816
|
+
}
|
|
6817
|
+
}
|
|
6818
|
+
if (turnId === void 0) {
|
|
6819
|
+
return { status: "none" };
|
|
6820
|
+
}
|
|
6821
|
+
const candidates = boundedCacheValues(state.streamingAssistantOutputs).filter(
|
|
6822
|
+
(output) => output.turnId === turnId
|
|
6823
|
+
);
|
|
6824
|
+
switch (candidates.length) {
|
|
6825
|
+
case 0:
|
|
6826
|
+
return { status: "none" };
|
|
6827
|
+
case 1: {
|
|
6828
|
+
const [output] = candidates;
|
|
6829
|
+
return output === void 0 ? { status: "none" } : { status: "matched", output };
|
|
6830
|
+
}
|
|
6831
|
+
default:
|
|
6832
|
+
return { status: "ambiguous", candidateCount: candidates.length };
|
|
6833
|
+
}
|
|
6834
|
+
}
|
|
6498
6835
|
function normalizedTranscriptText(value) {
|
|
6499
6836
|
return value.trim().replace(/\s+/g, " ");
|
|
6500
6837
|
}
|
|
@@ -6511,6 +6848,16 @@ function rememberStreamingAssistantOutput(state, output) {
|
|
|
6511
6848
|
function forgetStreamingAssistantOutput(state, itemKey) {
|
|
6512
6849
|
forgetBoundedCacheValue(state.streamingAssistantOutputs, itemKey);
|
|
6513
6850
|
}
|
|
6851
|
+
function completedAssistantItemForwarded(state, itemKey) {
|
|
6852
|
+
return state.completedAssistantItemKeys.has(itemKey);
|
|
6853
|
+
}
|
|
6854
|
+
function rememberCompletedAssistantItemKey(state, itemKey) {
|
|
6855
|
+
rememberBoundedStringSet(
|
|
6856
|
+
state.completedAssistantItemKeys,
|
|
6857
|
+
itemKey,
|
|
6858
|
+
maxForwardedTurnIds
|
|
6859
|
+
);
|
|
6860
|
+
}
|
|
6514
6861
|
function rememberStreamingReasoningOutput(state, output) {
|
|
6515
6862
|
rememberBoundedCacheValue(
|
|
6516
6863
|
state.streamingReasoningOutputs,
|
|
@@ -6662,6 +7009,32 @@ async function waitForPendingTuiInputMirror(state, turnId) {
|
|
|
6662
7009
|
await pending;
|
|
6663
7010
|
}
|
|
6664
7011
|
}
|
|
7012
|
+
function rememberPendingCompletedAssistantItemForward(state, turnId, promise) {
|
|
7013
|
+
const existing = state.pendingCompletedAssistantItemForwards.get(turnId);
|
|
7014
|
+
const pending = existing ?? /* @__PURE__ */ new Set();
|
|
7015
|
+
pending.add(promise);
|
|
7016
|
+
state.pendingCompletedAssistantItemForwards.set(turnId, pending);
|
|
7017
|
+
trimBoundedMap(
|
|
7018
|
+
state.pendingCompletedAssistantItemForwards,
|
|
7019
|
+
maxForwardedTurnIds
|
|
7020
|
+
);
|
|
7021
|
+
}
|
|
7022
|
+
function forgetPendingCompletedAssistantItemForward(state, turnId, promise) {
|
|
7023
|
+
const pending = state.pendingCompletedAssistantItemForwards.get(turnId);
|
|
7024
|
+
if (pending === void 0) {
|
|
7025
|
+
return;
|
|
7026
|
+
}
|
|
7027
|
+
pending.delete(promise);
|
|
7028
|
+
if (pending.size === 0) {
|
|
7029
|
+
state.pendingCompletedAssistantItemForwards.delete(turnId);
|
|
7030
|
+
}
|
|
7031
|
+
}
|
|
7032
|
+
async function waitForPendingCompletedAssistantItemForwards(state, turnId) {
|
|
7033
|
+
const pending = state.pendingCompletedAssistantItemForwards.get(turnId);
|
|
7034
|
+
if (pending !== void 0) {
|
|
7035
|
+
await Promise.allSettled([...pending]);
|
|
7036
|
+
}
|
|
7037
|
+
}
|
|
6665
7038
|
async function waitForStreamingForwardChains(args, state, payloadContext) {
|
|
6666
7039
|
flushPendingStreamingDeltas(args, state, payloadContext);
|
|
6667
7040
|
await Promise.all([
|
|
@@ -7175,7 +7548,7 @@ var init_channelSession = __esm({
|
|
|
7175
7548
|
|
|
7176
7549
|
// src/claudeCodeSession.ts
|
|
7177
7550
|
import { existsSync, readFileSync } from "node:fs";
|
|
7178
|
-
import { homedir } from "node:os";
|
|
7551
|
+
import { homedir as homedir2 } from "node:os";
|
|
7179
7552
|
import { join as join2 } from "node:path";
|
|
7180
7553
|
function claudeCodeSettingSources() {
|
|
7181
7554
|
return ["user", "project", "local"];
|
|
@@ -7183,7 +7556,7 @@ function claudeCodeSettingSources() {
|
|
|
7183
7556
|
async function probeClaudeCodeAvailability(args) {
|
|
7184
7557
|
if (!hasClaudeCodeAuthHint(process.env, {
|
|
7185
7558
|
cwd: args.cwd,
|
|
7186
|
-
homeDir:
|
|
7559
|
+
homeDir: homedir2(),
|
|
7187
7560
|
platform: process.platform,
|
|
7188
7561
|
fileExists: existsSync,
|
|
7189
7562
|
readTextFile: readTextFileIfPresent
|
|
@@ -7848,7 +8221,7 @@ var init_claudeCodeSession = __esm({
|
|
|
7848
8221
|
// src/runnerLogger.ts
|
|
7849
8222
|
import { appendFileSync, openSync } from "node:fs";
|
|
7850
8223
|
import { createWriteStream } from "node:fs";
|
|
7851
|
-
import { homedir as
|
|
8224
|
+
import { homedir as homedir3 } from "node:os";
|
|
7852
8225
|
import { dirname, join as join3 } from "node:path";
|
|
7853
8226
|
import { mkdirSync } from "node:fs";
|
|
7854
8227
|
function createRunnerLogger(logFile, consoleReporter) {
|
|
@@ -7890,10 +8263,10 @@ function writeCliAuditEvent(event, payload, options = {}) {
|
|
|
7890
8263
|
}
|
|
7891
8264
|
function defaultCliAuditLogFile() {
|
|
7892
8265
|
const override = process.env.LINZUMI_CLI_AUDIT_LOG?.trim();
|
|
7893
|
-
return override === void 0 || override === "" ? join3(
|
|
8266
|
+
return override === void 0 || override === "" ? join3(homedir3(), ".linzumi", "logs", "command-events.jsonl") : override;
|
|
7894
8267
|
}
|
|
7895
8268
|
function defaultRunnerLogFile() {
|
|
7896
|
-
return join3(
|
|
8269
|
+
return join3(homedir3(), ".linzumi", "logs", "runner-events.jsonl");
|
|
7897
8270
|
}
|
|
7898
8271
|
function redactForCliLog(value) {
|
|
7899
8272
|
return redactObject(value);
|
|
@@ -8553,11 +8926,11 @@ import {
|
|
|
8553
8926
|
realpathSync,
|
|
8554
8927
|
writeFileSync
|
|
8555
8928
|
} from "node:fs";
|
|
8556
|
-
import { homedir as
|
|
8929
|
+
import { homedir as homedir4 } from "node:os";
|
|
8557
8930
|
import { join as join4, resolve as resolve2 } from "node:path";
|
|
8558
8931
|
function ensureCodexProjectTrusted(projectPath, options = {}) {
|
|
8559
8932
|
const trustedPath = realpathSync(resolve2(projectPath));
|
|
8560
|
-
const configHome = options.configHome ?? process.env.CODEX_HOME ?? join4(
|
|
8933
|
+
const configHome = options.configHome ?? process.env.CODEX_HOME ?? join4(homedir4(), ".codex");
|
|
8561
8934
|
const configPath = join4(configHome, "config.toml");
|
|
8562
8935
|
const currentConfig = existsSync2(configPath) ? readFileSync2(configPath, "utf8") : "";
|
|
8563
8936
|
const nextConfig = codexConfigWithTrustedProject(currentConfig, trustedPath);
|
|
@@ -8612,7 +8985,7 @@ var init_codexProjectTrust = __esm({
|
|
|
8612
8985
|
|
|
8613
8986
|
// src/localCapabilities.ts
|
|
8614
8987
|
import { realpathSync as realpathSync2 } from "node:fs";
|
|
8615
|
-
import { homedir as
|
|
8988
|
+
import { homedir as homedir5 } from "node:os";
|
|
8616
8989
|
import { isAbsolute as isAbsolute2, relative as relative2, resolve as resolve3 } from "node:path";
|
|
8617
8990
|
function parseAllowedCwdList(value) {
|
|
8618
8991
|
if (value === void 0) {
|
|
@@ -8652,10 +9025,10 @@ function assertConfiguredAllowedCwds(paths) {
|
|
|
8652
9025
|
}
|
|
8653
9026
|
function expandUserPath(pathValue) {
|
|
8654
9027
|
if (pathValue === "~") {
|
|
8655
|
-
return
|
|
9028
|
+
return homedir5();
|
|
8656
9029
|
}
|
|
8657
9030
|
if (pathValue.startsWith("~/")) {
|
|
8658
|
-
return resolve3(
|
|
9031
|
+
return resolve3(homedir5(), pathValue.slice(2));
|
|
8659
9032
|
}
|
|
8660
9033
|
return pathValue;
|
|
8661
9034
|
}
|
|
@@ -9041,11 +9414,11 @@ import {
|
|
|
9041
9414
|
unlinkSync,
|
|
9042
9415
|
writeFileSync as writeFileSync2
|
|
9043
9416
|
} from "node:fs";
|
|
9044
|
-
import { homedir as
|
|
9417
|
+
import { homedir as homedir6 } from "node:os";
|
|
9045
9418
|
import { basename as basename3, dirname as dirname2, join as join5, resolve as resolve4 } from "node:path";
|
|
9046
9419
|
function localConfigPath(env = process.env) {
|
|
9047
9420
|
const override = env.LINZUMI_CONFIG_FILE;
|
|
9048
|
-
return override !== void 0 && override.trim() !== "" ? resolve4(expandUserPath(override)) : resolve4(
|
|
9421
|
+
return override !== void 0 && override.trim() !== "" ? resolve4(expandUserPath(override)) : resolve4(homedir6(), ".linzumi", "config.json");
|
|
9049
9422
|
}
|
|
9050
9423
|
function localConfigScopeKey(linzumiUrl) {
|
|
9051
9424
|
const normalizedUrl = kandanHttpBaseUrl(linzumiUrl);
|
|
@@ -10741,7 +11114,7 @@ import {
|
|
|
10741
11114
|
rmSync,
|
|
10742
11115
|
writeFileSync as writeFileSync4
|
|
10743
11116
|
} from "node:fs";
|
|
10744
|
-
import { homedir as
|
|
11117
|
+
import { homedir as homedir7 } from "node:os";
|
|
10745
11118
|
import { dirname as dirname4, join as join7, resolve as resolve5 } from "node:path";
|
|
10746
11119
|
import { Readable } from "node:stream";
|
|
10747
11120
|
import { pipeline } from "node:stream/promises";
|
|
@@ -11227,7 +11600,7 @@ function fileSha256Sync(path2) {
|
|
|
11227
11600
|
return createHash2("sha256").update(readFileSync5(path2)).digest("hex");
|
|
11228
11601
|
}
|
|
11229
11602
|
function defaultEditorRuntimeCacheRoot() {
|
|
11230
|
-
return join7(
|
|
11603
|
+
return join7(homedir7(), ".linzumi", "editor-runtimes");
|
|
11231
11604
|
}
|
|
11232
11605
|
function nonEmptyString(value) {
|
|
11233
11606
|
return typeof value === "string" && value.trim() !== "" ? value.trim() : void 0;
|
|
@@ -11750,7 +12123,7 @@ var linzumiCliVersion, linzumiCliVersionText;
|
|
|
11750
12123
|
var init_version = __esm({
|
|
11751
12124
|
"src/version.ts"() {
|
|
11752
12125
|
"use strict";
|
|
11753
|
-
linzumiCliVersion = "0.0.
|
|
12126
|
+
linzumiCliVersion = "0.0.69-beta";
|
|
11754
12127
|
linzumiCliVersionText = `linzumi ${linzumiCliVersion}`;
|
|
11755
12128
|
}
|
|
11756
12129
|
});
|
|
@@ -12179,10 +12552,10 @@ var init_runnerConsoleReporter = __esm({
|
|
|
12179
12552
|
|
|
12180
12553
|
// src/authCache.ts
|
|
12181
12554
|
import { existsSync as existsSync7, mkdirSync as mkdirSync7, readFileSync as readFileSync7, writeFileSync as writeFileSync5 } from "node:fs";
|
|
12182
|
-
import { homedir as
|
|
12555
|
+
import { homedir as homedir8 } from "node:os";
|
|
12183
12556
|
import { dirname as dirname6, join as join9 } from "node:path";
|
|
12184
12557
|
function defaultAuthFilePath() {
|
|
12185
|
-
const base = process.env.KANDAN_HOME ?? join9(
|
|
12558
|
+
const base = process.env.KANDAN_HOME ?? join9(homedir8(), ".kandan");
|
|
12186
12559
|
return join9(base, "auth.json");
|
|
12187
12560
|
}
|
|
12188
12561
|
function readCachedLocalRunnerToken(kandanUrl, authFilePath = defaultAuthFilePath()) {
|
|
@@ -12885,7 +13258,7 @@ import {
|
|
|
12885
13258
|
statSync
|
|
12886
13259
|
} from "node:fs";
|
|
12887
13260
|
import { createServer as createServer3 } from "node:http";
|
|
12888
|
-
import { homedir as
|
|
13261
|
+
import { homedir as homedir9, hostname as hostname2, tmpdir as tmpdir3 } from "node:os";
|
|
12889
13262
|
import { dirname as dirname7, join as join11, resolve as resolve6 } from "node:path";
|
|
12890
13263
|
async function runLocalCodexRunner(options) {
|
|
12891
13264
|
const log = makeRunnerLogger(options);
|
|
@@ -16556,16 +16929,24 @@ async function streamClaudeCodeStructuredMessage(args, sessionId, message) {
|
|
|
16556
16929
|
message.body,
|
|
16557
16930
|
message.structured
|
|
16558
16931
|
) : [];
|
|
16932
|
+
const displayBody = displayBodyForCommanderOutput(
|
|
16933
|
+
message.body,
|
|
16934
|
+
uploadedFileIds
|
|
16935
|
+
);
|
|
16936
|
+
const displayStructured = structuredWithAssistantContent(
|
|
16937
|
+
message.structured,
|
|
16938
|
+
displayBody
|
|
16939
|
+
);
|
|
16559
16940
|
await args.kandan.push(args.topic, "session:stream_thread_message", {
|
|
16560
16941
|
workspace: args.workspace,
|
|
16561
16942
|
channel: args.channel,
|
|
16562
16943
|
thread_id: args.threadId,
|
|
16563
16944
|
stream_key: streamKey,
|
|
16564
|
-
body:
|
|
16945
|
+
body: displayBody,
|
|
16565
16946
|
payload: claudeCodePayload(
|
|
16566
16947
|
{ ...args, sourceSeq: args.sourceSeq() },
|
|
16567
16948
|
sessionId,
|
|
16568
|
-
|
|
16949
|
+
displayStructured
|
|
16569
16950
|
),
|
|
16570
16951
|
...uploadedFileIds.length === 0 ? {} : { uploaded_file_ids: uploadedFileIds },
|
|
16571
16952
|
client_message_id: streamKey
|
|
@@ -16590,15 +16971,23 @@ async function postClaudeCodeStructuredMessage(args, sessionId, message) {
|
|
|
16590
16971
|
message.body,
|
|
16591
16972
|
message.structured
|
|
16592
16973
|
);
|
|
16974
|
+
const displayBody = displayBodyForCommanderOutput(
|
|
16975
|
+
message.body,
|
|
16976
|
+
uploadedFileIds
|
|
16977
|
+
);
|
|
16978
|
+
const displayStructured = structuredWithAssistantContent(
|
|
16979
|
+
message.structured,
|
|
16980
|
+
displayBody
|
|
16981
|
+
);
|
|
16593
16982
|
await args.kandan.push(args.topic, "session:post_thread_message", {
|
|
16594
16983
|
workspace: args.workspace,
|
|
16595
16984
|
channel: args.channel,
|
|
16596
16985
|
thread_id: args.threadId,
|
|
16597
|
-
body:
|
|
16986
|
+
body: displayBody,
|
|
16598
16987
|
payload: claudeCodePayload(
|
|
16599
16988
|
{ ...args, sourceSeq: args.sourceSeq() },
|
|
16600
16989
|
sessionId,
|
|
16601
|
-
|
|
16990
|
+
displayStructured
|
|
16602
16991
|
),
|
|
16603
16992
|
...uploadedFileIds.length === 0 ? {} : { uploaded_file_ids: uploadedFileIds },
|
|
16604
16993
|
client_message_id: claudeCodeMessageClientId(
|
|
@@ -17523,7 +17912,7 @@ function isGitProjectDirectory(cwd) {
|
|
|
17523
17912
|
}
|
|
17524
17913
|
function browseRunnerDirectory(control, options) {
|
|
17525
17914
|
const requestId = stringValue(control.requestId) ?? null;
|
|
17526
|
-
const requestedPath = stringValue(control.path) ??
|
|
17915
|
+
const requestedPath = stringValue(control.path) ?? homedir9();
|
|
17527
17916
|
try {
|
|
17528
17917
|
const currentPath = realpathSync5(resolve6(expandUserPath(requestedPath)));
|
|
17529
17918
|
const stats = statSync(currentPath);
|
|
@@ -17554,7 +17943,7 @@ function browseRunnerDirectory(control, options) {
|
|
|
17554
17943
|
ok: true,
|
|
17555
17944
|
currentPath,
|
|
17556
17945
|
parentPath: parent === currentPath ? null : parent,
|
|
17557
|
-
homePath:
|
|
17946
|
+
homePath: homedir9(),
|
|
17558
17947
|
runnerCwd: resolve6(options.cwd),
|
|
17559
17948
|
entries,
|
|
17560
17949
|
isGit: isGitProjectDirectory(currentPath)
|
|
@@ -17589,7 +17978,7 @@ function createRunnerProject(control, options, allowedCwds) {
|
|
|
17589
17978
|
error: "invalid_project_name"
|
|
17590
17979
|
};
|
|
17591
17980
|
}
|
|
17592
|
-
const projectsRoot = join11(
|
|
17981
|
+
const projectsRoot = join11(homedir9(), "linzumi");
|
|
17593
17982
|
const projectPath = join11(projectsRoot, projectDirName);
|
|
17594
17983
|
let createdProjectPath = false;
|
|
17595
17984
|
try {
|
|
@@ -17806,7 +18195,7 @@ var init_kandanTls = __esm({
|
|
|
17806
18195
|
// src/helloLinzumiProject.ts
|
|
17807
18196
|
import { existsSync as existsSync10, mkdirSync as mkdirSync10, readFileSync as readFileSync11, rmSync as rmSync4, writeFileSync as writeFileSync8 } from "node:fs";
|
|
17808
18197
|
import { dirname as dirname9, join as join13, resolve as resolve7 } from "node:path";
|
|
17809
|
-
import { fileURLToPath } from "node:url";
|
|
18198
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
17810
18199
|
function createHelloLinzumiProject(input = {}) {
|
|
17811
18200
|
const options = typeof input === "string" ? { rootPath: input } : input;
|
|
17812
18201
|
const root = resolveHelloProjectRoot(options);
|
|
@@ -17895,7 +18284,7 @@ var init_helloLinzumiProject = __esm({
|
|
|
17895
18284
|
defaultHelloLinzumiPort = 8787;
|
|
17896
18285
|
defaultHelloLinzumiHost = "0.0.0.0";
|
|
17897
18286
|
markerFile = ".linzumi-demo-project";
|
|
17898
|
-
moduleDir = dirname9(
|
|
18287
|
+
moduleDir = dirname9(fileURLToPath2(import.meta.url));
|
|
17899
18288
|
linzumiLogoSvg = readFileSync11(join13(moduleDir, "assets", "linzumi-logo.svg"), "utf8");
|
|
17900
18289
|
packageJson = `${JSON.stringify(
|
|
17901
18290
|
{
|
|
@@ -38626,7 +39015,7 @@ import {
|
|
|
38626
39015
|
writeFileSync as writeFileSync11
|
|
38627
39016
|
} from "node:fs";
|
|
38628
39017
|
import { access } from "node:fs/promises";
|
|
38629
|
-
import { homedir as
|
|
39018
|
+
import { homedir as homedir12, tmpdir as tmpdir4 } from "node:os";
|
|
38630
39019
|
import { delimiter as delimiter2, dirname as dirname11, join as join15, resolve as resolve9 } from "node:path";
|
|
38631
39020
|
import { stdin as defaultStdin, stdout as defaultStdout } from "node:process";
|
|
38632
39021
|
import { emitKeypressEvents } from "node:readline";
|
|
@@ -40929,7 +41318,7 @@ async function runSignupPreflights(runtime) {
|
|
|
40929
41318
|
function defaultPreflightRuntime() {
|
|
40930
41319
|
return {
|
|
40931
41320
|
cwd: process.cwd(),
|
|
40932
|
-
homeDir:
|
|
41321
|
+
homeDir: homedir12(),
|
|
40933
41322
|
probeTool,
|
|
40934
41323
|
readGitEmail,
|
|
40935
41324
|
discoverCodeRoots,
|
|
@@ -41138,7 +41527,7 @@ function codexTaskSuggestionProcess2(args) {
|
|
|
41138
41527
|
function signupCodexTaskSuggestionProcessForTest(args) {
|
|
41139
41528
|
return codexTaskSuggestionProcess2(args);
|
|
41140
41529
|
}
|
|
41141
|
-
async function resolveSignupCodexCommand(env = process.env, homeDir =
|
|
41530
|
+
async function resolveSignupCodexCommand(env = process.env, homeDir = homedir12(), executableExists = fileIsExecutable) {
|
|
41142
41531
|
const override = firstConfiguredValue([
|
|
41143
41532
|
env.LINZUMI_SIGNUP_CODEX_BIN,
|
|
41144
41533
|
env.LINZUMI_CODEX_BIN
|
|
@@ -41777,10 +42166,10 @@ function directoryExists(path2) {
|
|
|
41777
42166
|
}
|
|
41778
42167
|
function expandHomePath(path2) {
|
|
41779
42168
|
if (path2 === "~") {
|
|
41780
|
-
return
|
|
42169
|
+
return homedir12();
|
|
41781
42170
|
}
|
|
41782
42171
|
if (path2.startsWith("~/")) {
|
|
41783
|
-
return join15(
|
|
42172
|
+
return join15(homedir12(), path2.slice(2));
|
|
41784
42173
|
}
|
|
41785
42174
|
return resolve9(path2);
|
|
41786
42175
|
}
|
|
@@ -41868,9 +42257,9 @@ init_runner();
|
|
|
41868
42257
|
init_claudeCodeSession();
|
|
41869
42258
|
init_authCache();
|
|
41870
42259
|
import { existsSync as existsSync13, readFileSync as readFileSync15, realpathSync as realpathSync6 } from "node:fs";
|
|
41871
|
-
import { homedir as
|
|
42260
|
+
import { homedir as homedir13 } from "node:os";
|
|
41872
42261
|
import { resolve as resolve10 } from "node:path";
|
|
41873
|
-
import { fileURLToPath as
|
|
42262
|
+
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
41874
42263
|
|
|
41875
42264
|
// src/authResolution.ts
|
|
41876
42265
|
init_authCache();
|
|
@@ -41931,7 +42320,7 @@ init_json();
|
|
|
41931
42320
|
init_defaultUrls();
|
|
41932
42321
|
import { existsSync as existsSync9, mkdirSync as mkdirSync9, readFileSync as readFileSync10, writeFileSync as writeFileSync7 } from "node:fs";
|
|
41933
42322
|
import { dirname as dirname8, join as join12 } from "node:path";
|
|
41934
|
-
import { homedir as
|
|
42323
|
+
import { homedir as homedir10 } from "node:os";
|
|
41935
42324
|
async function runAgentCliCommand(args, deps = {
|
|
41936
42325
|
fetchImpl: fetch,
|
|
41937
42326
|
stdout: process.stdout,
|
|
@@ -42639,7 +43028,7 @@ function agentTokenFile(flags) {
|
|
|
42639
43028
|
return flags.get("agent-token-file") ?? defaultAgentTokenFilePath();
|
|
42640
43029
|
}
|
|
42641
43030
|
function defaultAgentTokenFilePath() {
|
|
42642
|
-
return join12(
|
|
43031
|
+
return join12(homedir10(), ".linzumi", "agent-token.json");
|
|
42643
43032
|
}
|
|
42644
43033
|
function normalizedApiUrl(apiUrl) {
|
|
42645
43034
|
return apiUrl.endsWith("/") ? apiUrl : `${apiUrl}/`;
|
|
@@ -42747,13 +43136,13 @@ import {
|
|
|
42747
43136
|
watch,
|
|
42748
43137
|
writeFileSync as writeFileSync9
|
|
42749
43138
|
} from "node:fs";
|
|
42750
|
-
import { homedir as
|
|
43139
|
+
import { homedir as homedir11 } from "node:os";
|
|
42751
43140
|
import { dirname as dirname10, join as join14, resolve as resolve8 } from "node:path";
|
|
42752
43141
|
import { execFileSync, spawn as spawn8 } from "node:child_process";
|
|
42753
|
-
import { fileURLToPath as
|
|
43142
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
42754
43143
|
var connectedMarkers = ["Connected to Linzumi", "Runner connected:"];
|
|
42755
43144
|
function commanderStatusDir() {
|
|
42756
|
-
return join14(
|
|
43145
|
+
return join14(homedir11(), ".linzumi", "commanders");
|
|
42757
43146
|
}
|
|
42758
43147
|
function commanderStatusFile(runnerId, statusDir = commanderStatusDir()) {
|
|
42759
43148
|
return join14(statusDir, `${safeRunnerId(runnerId)}.json`);
|
|
@@ -42859,7 +43248,7 @@ async function waitForCommanderDaemon(options) {
|
|
|
42859
43248
|
if (commanderLogIsConnected(log)) {
|
|
42860
43249
|
return { ok: true, record: status.record };
|
|
42861
43250
|
}
|
|
42862
|
-
await waitForFileChangeOrTimeout(
|
|
43251
|
+
const readyAfterWait = await waitForFileChangeOrTimeout(
|
|
42863
43252
|
status.record.logFile,
|
|
42864
43253
|
deadline,
|
|
42865
43254
|
now,
|
|
@@ -42868,6 +43257,24 @@ async function waitForCommanderDaemon(options) {
|
|
|
42868
43257
|
return updatedLog !== void 0 && commanderLogIsConnected(updatedLog);
|
|
42869
43258
|
}
|
|
42870
43259
|
);
|
|
43260
|
+
if (readyAfterWait) {
|
|
43261
|
+
const refreshedStatus = statusImpl(
|
|
43262
|
+
options.runnerId,
|
|
43263
|
+
options.statusDir
|
|
43264
|
+
);
|
|
43265
|
+
switch (refreshedStatus.status) {
|
|
43266
|
+
case "missing":
|
|
43267
|
+
return { ok: false, reason: "missing" };
|
|
43268
|
+
case "stopped":
|
|
43269
|
+
return { ok: false, reason: "stopped" };
|
|
43270
|
+
case "running": {
|
|
43271
|
+
const refreshedLog = readTextFile(refreshedStatus.record.logFile);
|
|
43272
|
+
if (refreshedLog !== void 0 && commanderLogIsConnected(refreshedLog)) {
|
|
43273
|
+
return { ok: true, record: refreshedStatus.record };
|
|
43274
|
+
}
|
|
43275
|
+
}
|
|
43276
|
+
}
|
|
43277
|
+
}
|
|
42871
43278
|
}
|
|
42872
43279
|
}
|
|
42873
43280
|
}
|
|
@@ -42885,7 +43292,7 @@ function currentEntrypoint() {
|
|
|
42885
43292
|
if (scriptPath !== void 0) {
|
|
42886
43293
|
return scriptPath;
|
|
42887
43294
|
}
|
|
42888
|
-
return
|
|
43295
|
+
return fileURLToPath3(import.meta.url);
|
|
42889
43296
|
}
|
|
42890
43297
|
function parseRecord(content) {
|
|
42891
43298
|
const parsed = JSON.parse(content);
|
|
@@ -42991,31 +43398,31 @@ function safeRunnerId(runnerId) {
|
|
|
42991
43398
|
}
|
|
42992
43399
|
async function waitForFileChangeOrTimeout(path2, deadline, now, ready2 = () => false) {
|
|
42993
43400
|
const remaining = Math.max(0, deadline - now());
|
|
42994
|
-
|
|
43401
|
+
return new Promise((resolve11) => {
|
|
42995
43402
|
let resolved = false;
|
|
42996
43403
|
let watcher;
|
|
42997
|
-
const finish = () => {
|
|
43404
|
+
const finish = (connected) => {
|
|
42998
43405
|
if (resolved) {
|
|
42999
43406
|
return;
|
|
43000
43407
|
}
|
|
43001
43408
|
resolved = true;
|
|
43002
43409
|
watcher?.close();
|
|
43003
43410
|
clearTimeout(timer);
|
|
43004
|
-
resolve11();
|
|
43411
|
+
resolve11(connected);
|
|
43005
43412
|
};
|
|
43006
|
-
const timer = setTimeout(finish, remaining);
|
|
43413
|
+
const timer = setTimeout(() => finish(false), remaining);
|
|
43007
43414
|
try {
|
|
43008
|
-
watcher = watch(path2, finish);
|
|
43009
|
-
watcher.on("error", finish);
|
|
43415
|
+
watcher = watch(path2, () => finish(ready2()));
|
|
43416
|
+
watcher.on("error", () => finish(ready2()));
|
|
43010
43417
|
if (ready2()) {
|
|
43011
|
-
finish();
|
|
43418
|
+
finish(true);
|
|
43012
43419
|
}
|
|
43013
43420
|
} catch (_error) {
|
|
43014
43421
|
if (ready2()) {
|
|
43015
|
-
finish();
|
|
43422
|
+
finish(true);
|
|
43016
43423
|
return;
|
|
43017
43424
|
}
|
|
43018
|
-
finish();
|
|
43425
|
+
finish(false);
|
|
43019
43426
|
}
|
|
43020
43427
|
});
|
|
43021
43428
|
}
|
|
@@ -55197,7 +55604,7 @@ function isMainModule() {
|
|
|
55197
55604
|
if (scriptPath === void 0) {
|
|
55198
55605
|
return false;
|
|
55199
55606
|
}
|
|
55200
|
-
return
|
|
55607
|
+
return fileURLToPath4(import.meta.url) === resolve10(scriptPath);
|
|
55201
55608
|
}
|
|
55202
55609
|
async function main(args) {
|
|
55203
55610
|
const parsed = parseCommand(args);
|
|
@@ -56088,10 +56495,10 @@ function rejectStartTargetingFlags(values) {
|
|
|
56088
56495
|
}
|
|
56089
56496
|
function resolveUserPath(pathValue) {
|
|
56090
56497
|
if (pathValue === "~") {
|
|
56091
|
-
return
|
|
56498
|
+
return homedir13();
|
|
56092
56499
|
}
|
|
56093
56500
|
if (pathValue.startsWith("~/")) {
|
|
56094
|
-
return resolve10(
|
|
56501
|
+
return resolve10(homedir13(), pathValue.slice(2));
|
|
56095
56502
|
}
|
|
56096
56503
|
return resolve10(pathValue);
|
|
56097
56504
|
}
|
package/package.json
CHANGED