nolo-cli 0.7.0 → 0.8.0-alpha.5
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/index.js +1134 -436
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1209,8 +1209,29 @@ var init_levelLockError = __esm({
|
|
|
1209
1209
|
}
|
|
1210
1210
|
});
|
|
1211
1211
|
|
|
1212
|
+
// packages/cli/levelLazyShim.mjs
|
|
1213
|
+
import { createRequire } from "node:module";
|
|
1214
|
+
function ensureLevel() {
|
|
1215
|
+
if (!_RealLevel) {
|
|
1216
|
+
_RealLevel = _require("level").Level;
|
|
1217
|
+
}
|
|
1218
|
+
return _RealLevel;
|
|
1219
|
+
}
|
|
1220
|
+
var _require, _RealLevel, Level;
|
|
1221
|
+
var init_levelLazyShim = __esm({
|
|
1222
|
+
"packages/cli/levelLazyShim.mjs"() {
|
|
1223
|
+
"use strict";
|
|
1224
|
+
_require = createRequire(import.meta.url);
|
|
1225
|
+
Level = class {
|
|
1226
|
+
constructor(...args2) {
|
|
1227
|
+
const RealLevel = ensureLevel();
|
|
1228
|
+
return new RealLevel(...args2);
|
|
1229
|
+
}
|
|
1230
|
+
};
|
|
1231
|
+
}
|
|
1232
|
+
});
|
|
1233
|
+
|
|
1212
1234
|
// packages/database-engine/levelAuthorityStore.ts
|
|
1213
|
-
import { Level } from "level";
|
|
1214
1235
|
function createLevelAuthorityStore(source) {
|
|
1215
1236
|
const levelDb = typeof source === "string" ? new Level(source, { valueEncoding: safeJsonEncoding }) : source;
|
|
1216
1237
|
const writeBatchOps = async (ops) => {
|
|
@@ -1281,6 +1302,7 @@ var safeJsonEncoding;
|
|
|
1281
1302
|
var init_levelAuthorityStore = __esm({
|
|
1282
1303
|
"packages/database-engine/levelAuthorityStore.ts"() {
|
|
1283
1304
|
"use strict";
|
|
1305
|
+
init_levelLazyShim();
|
|
1284
1306
|
safeJsonEncoding = {
|
|
1285
1307
|
name: "safe-json",
|
|
1286
1308
|
format: "utf8",
|
|
@@ -16077,12 +16099,14 @@ function buildLocalToolExecutors(args2) {
|
|
|
16077
16099
|
})();
|
|
16078
16100
|
const question = String(parsedArgs.question ?? "").trim();
|
|
16079
16101
|
const choices = Array.isArray(parsedArgs.choices) ? parsedArgs.choices : [];
|
|
16102
|
+
const questions = Array.isArray(parsedArgs.questions) ? parsedArgs.questions : void 0;
|
|
16080
16103
|
const blocking = parsedArgs.blocking !== false;
|
|
16081
|
-
|
|
16104
|
+
const hasQuestions = questions && questions.length > 0;
|
|
16105
|
+
if (!hasQuestions && (!question || choices.length === 0)) {
|
|
16082
16106
|
return {
|
|
16083
16107
|
content: JSON.stringify({
|
|
16084
16108
|
error: "ui_ask_choice",
|
|
16085
|
-
detail: "ui_ask_choice \u9700\u8981 question \
|
|
16109
|
+
detail: "ui_ask_choice \u9700\u8981 question+choices \u6216 questions\u3002"
|
|
16086
16110
|
}),
|
|
16087
16111
|
metadata: { uiAskChoice: true, error: true }
|
|
16088
16112
|
};
|
|
@@ -16090,10 +16114,28 @@ function buildLocalToolExecutors(args2) {
|
|
|
16090
16114
|
if (args2.requestUserChoice) {
|
|
16091
16115
|
try {
|
|
16092
16116
|
const result = await args2.requestUserChoice({
|
|
16093
|
-
question,
|
|
16094
|
-
choices,
|
|
16095
|
-
blocking
|
|
16117
|
+
question: hasQuestions ? questions[0].question : question,
|
|
16118
|
+
choices: hasQuestions ? questions[0].choices : choices,
|
|
16119
|
+
blocking,
|
|
16120
|
+
...hasQuestions ? { questions } : {}
|
|
16096
16121
|
});
|
|
16122
|
+
if (result.kind === "multi-submitted") {
|
|
16123
|
+
return {
|
|
16124
|
+
content: JSON.stringify({
|
|
16125
|
+
type: "ui_ask_choice",
|
|
16126
|
+
question,
|
|
16127
|
+
choices,
|
|
16128
|
+
blocking,
|
|
16129
|
+
...hasQuestions ? { questions } : {},
|
|
16130
|
+
answers: result.answers,
|
|
16131
|
+
selected: {
|
|
16132
|
+
label: result.answers.map((a) => a.userMessage).join(", "),
|
|
16133
|
+
userMessage: result.userMessage
|
|
16134
|
+
}
|
|
16135
|
+
}),
|
|
16136
|
+
metadata: { uiAskChoice: true, resolved: true }
|
|
16137
|
+
};
|
|
16138
|
+
}
|
|
16097
16139
|
if (result.kind === "selected") {
|
|
16098
16140
|
return {
|
|
16099
16141
|
content: JSON.stringify({
|
|
@@ -16101,6 +16143,7 @@ function buildLocalToolExecutors(args2) {
|
|
|
16101
16143
|
question,
|
|
16102
16144
|
choices,
|
|
16103
16145
|
blocking,
|
|
16146
|
+
...hasQuestions ? { questions } : {},
|
|
16104
16147
|
selected: {
|
|
16105
16148
|
label: result.label,
|
|
16106
16149
|
userMessage: result.userMessage
|
|
@@ -16115,6 +16158,7 @@ function buildLocalToolExecutors(args2) {
|
|
|
16115
16158
|
question,
|
|
16116
16159
|
choices,
|
|
16117
16160
|
blocking,
|
|
16161
|
+
...hasQuestions ? { questions } : {},
|
|
16118
16162
|
selected: { label: "", userMessage: "" },
|
|
16119
16163
|
cancelled: true
|
|
16120
16164
|
}),
|
|
@@ -16128,7 +16172,8 @@ function buildLocalToolExecutors(args2) {
|
|
|
16128
16172
|
type: "ui_ask_choice",
|
|
16129
16173
|
question,
|
|
16130
16174
|
choices,
|
|
16131
|
-
blocking
|
|
16175
|
+
blocking,
|
|
16176
|
+
...hasQuestions ? { questions } : {}
|
|
16132
16177
|
}),
|
|
16133
16178
|
metadata: { uiAskChoice: true }
|
|
16134
16179
|
};
|
|
@@ -37355,11 +37400,24 @@ var init_dialogUrl = __esm({
|
|
|
37355
37400
|
|
|
37356
37401
|
// packages/ai/tools/uiAskChoiceTool.ts
|
|
37357
37402
|
async function uiAskChoiceFunc(args2, _thunkApi) {
|
|
37403
|
+
const blocking = args2?.blocking !== false;
|
|
37404
|
+
if (Array.isArray(args2?.questions) && args2.questions.length > 0) {
|
|
37405
|
+
const firstQ = args2.questions[0];
|
|
37406
|
+
return {
|
|
37407
|
+
rawData: {
|
|
37408
|
+
type: "ui_ask_choice",
|
|
37409
|
+
question: firstQ?.question ?? "",
|
|
37410
|
+
choices: firstQ?.choices ?? [],
|
|
37411
|
+
blocking,
|
|
37412
|
+
questions: args2.questions
|
|
37413
|
+
},
|
|
37414
|
+
displayData: args2.questions.map((q) => q.question).join(" / ")
|
|
37415
|
+
};
|
|
37416
|
+
}
|
|
37358
37417
|
const question = String(args2?.question ?? "").trim();
|
|
37359
37418
|
const choices = Array.isArray(args2?.choices) ? args2.choices : [];
|
|
37360
|
-
const blocking = args2?.blocking !== false;
|
|
37361
37419
|
if (!question || choices.length === 0) {
|
|
37362
|
-
throw new Error("ui_ask_choice \u9700\u8981 question \
|
|
37420
|
+
throw new Error("ui_ask_choice \u9700\u8981 question+choices \u6216 questions\u3002");
|
|
37363
37421
|
}
|
|
37364
37422
|
return {
|
|
37365
37423
|
rawData: {
|
|
@@ -37408,14 +37466,20 @@ var init_uiAskChoiceTool = __esm({
|
|
|
37408
37466
|
"\u5728\u4EE3\u7801\u534F\u4F5C\u573A\u666F\u4E0B\u7684\u63A8\u8350\u7528\u6CD5\uFF1A",
|
|
37409
37467
|
"- \u5982\u679C\u4F60\u5DF2\u7ECF\u5728\u672C\u8F6E assistant \u7684 content \u4E2D\u7ED9\u51FA\u4E86\u5206\u6790\u3001\u8BF4\u660E\u6216\u591A\u4E2A\u5907\u9009\u65B9\u6848\uFF0C\u53EF\u4EE5\u5728\u540C\u4E00\u8F6E\u6D88\u606F\u7684\u7ED3\u5C3E\u8C03\u7528\u672C\u5DE5\u5177\uFF0C\u8BF7\u7528\u6237\u9009\u62E9\u201C\u662F\u5426\u6839\u636E\u4E0A\u8FF0\u65B9\u6848\u5F00\u59CB\u5B9E\u9645\u4FEE\u6539\u4EE3\u7801\u201D\u6216\u201C\u4F18\u5148\u6267\u884C\u54EA\u4E00\u4E2A\u65B9\u6848/\u6B65\u9AA4\u201D\u3002",
|
|
37410
37468
|
"- \u5728\u8FD9\u79CD\u60C5\u51B5\u4E0B\uFF0Cquestion \u5B57\u6BB5\u901A\u5E38\u662F\u4E00\u4E2A\u7B80\u77ED\u7684\u95EE\u9898\uFF08\u4F8B\u5982\uFF1A\u201C\u63A5\u4E0B\u6765\u4F60\u5E0C\u671B\u6211\u6309\u54EA\u4E2A\u65B9\u6848\u6765\u5177\u4F53\u4FEE\u6539\u4EE3\u7801\uFF1F\u201D\uFF09\uFF0C\u800C\u8BE6\u7EC6\u7684\u89E3\u91CA\u548C\u65B9\u6848\u63CF\u8FF0\u653E\u5728 content \u4E2D\u3002",
|
|
37411
|
-
"- \u5982\u679C\u5F53\u524D\u5BF9\u8BDD\u53EA\u9700\u8981\u4E00\u4E2A\u7B80\u5355\u7684\u9009\u62E9\uFF0C\u800C\u4E0D\u9700\u8981\u989D\u5916\u89E3\u91CA\uFF0C\u4F60\u4E5F\u53EF\u4EE5\u4E0D\u8F93\u51FA\u989D\u5916\u7684 content\uFF0C\u800C\u53EA\u8C03\u7528\u672C\u5DE5\u5177\uFF0C\u7531 question \u5B57\u6BB5\u76F4\u63A5\u5411\u7528\u6237\u63D0\u95EE\u3002"
|
|
37469
|
+
"- \u5982\u679C\u5F53\u524D\u5BF9\u8BDD\u53EA\u9700\u8981\u4E00\u4E2A\u7B80\u5355\u7684\u9009\u62E9\uFF0C\u800C\u4E0D\u9700\u8981\u989D\u5916\u89E3\u91CA\uFF0C\u4F60\u4E5F\u53EF\u4EE5\u4E0D\u8F93\u51FA\u989D\u5916\u7684 content\uFF0C\u800C\u53EA\u8C03\u7528\u672C\u5DE5\u5177\uFF0C\u7531 question \u5B57\u6BB5\u76F4\u63A5\u5411\u7528\u6237\u63D0\u95EE\u3002",
|
|
37470
|
+
"",
|
|
37471
|
+
"\u591A\u95EE\u9898 & \u591A\u9009\u652F\u6301\uFF1A",
|
|
37472
|
+
"- \u5F53\u4F60\u9700\u8981\u4E00\u6B21\u95EE\u591A\u4E2A\u95EE\u9898\u65F6\uFF0C\u4F7F\u7528 questions \u6570\u7EC4\u4EE3\u66FF question+choices\u3002",
|
|
37473
|
+
"- \u6BCF\u4E2A question \u53EF\u4EE5\u8BBE\u7F6E multiSelect: true \u5141\u8BB8\u591A\u9009\u3002",
|
|
37474
|
+
"- \u6BCF\u4E2A question \u53EF\u4EE5\u8BBE\u7F6E allowOther: false \u9690\u85CF\u201C\u5176\u4ED6\u201D\u8F93\u5165\u6846\u3002",
|
|
37475
|
+
"- \u6BCF\u4E2A choice \u53EF\u4EE5\u52A0 detail \u5B57\u6BB5\u63D0\u4F9B\u66F4\u957F\u7684\u63CF\u8FF0\u3002"
|
|
37412
37476
|
].join("\n"),
|
|
37413
37477
|
parameters: {
|
|
37414
37478
|
type: "object",
|
|
37415
37479
|
properties: {
|
|
37416
37480
|
question: {
|
|
37417
37481
|
type: "string",
|
|
37418
|
-
description: "\u5C55\u793A\u7ED9\u7528\u6237\u7684\u95EE\u9898\u6587\u6848\
|
|
37482
|
+
description: "\u5C55\u793A\u7ED9\u7528\u6237\u7684\u95EE\u9898\u6587\u6848\uFF08\u5355\u95EE\u9898\u6A21\u5F0F\uFF09\u3002\u4E0E questions \u4E8C\u9009\u4E00\u3002"
|
|
37419
37483
|
},
|
|
37420
37484
|
choices: {
|
|
37421
37485
|
type: "array",
|
|
@@ -37431,6 +37495,10 @@ var init_uiAskChoiceTool = __esm({
|
|
|
37431
37495
|
type: "string",
|
|
37432
37496
|
description: "\u663E\u793A\u7ED9\u7528\u6237\u770B\u7684\u6309\u94AE\u6587\u5B57\u3002\u4F8B\u5982\uFF1A\u201C\u751F\u6210\u672C\u5468\u5468\u62A5\u201D\u3002"
|
|
37433
37497
|
},
|
|
37498
|
+
detail: {
|
|
37499
|
+
type: "string",
|
|
37500
|
+
description: "\u9009\u9879\u7684\u8865\u5145\u63CF\u8FF0\uFF0C\u663E\u793A\u5728 label \u4E0B\u65B9\u3002\u53EF\u9009\u3002"
|
|
37501
|
+
},
|
|
37434
37502
|
userMessage: {
|
|
37435
37503
|
type: "string",
|
|
37436
37504
|
description: [
|
|
@@ -37443,6 +37511,56 @@ var init_uiAskChoiceTool = __esm({
|
|
|
37443
37511
|
required: ["id", "label"]
|
|
37444
37512
|
}
|
|
37445
37513
|
},
|
|
37514
|
+
questions: {
|
|
37515
|
+
type: "array",
|
|
37516
|
+
description: "\u591A\u95EE\u9898\u6A21\u5F0F\uFF1A\u4E00\u6B21\u95EE\u591A\u4E2A\u95EE\u9898\uFF0C\u6BCF\u4E2A\u95EE\u9898\u72EC\u7ACB\u6E32\u67D3\u4E3A\u4E00\u4E2A tab\u3002\u4E0E question+choices \u4E8C\u9009\u4E00\u3002",
|
|
37517
|
+
items: {
|
|
37518
|
+
type: "object",
|
|
37519
|
+
properties: {
|
|
37520
|
+
id: {
|
|
37521
|
+
type: "string",
|
|
37522
|
+
description: "\u95EE\u9898\u6807\u8BC6\uFF0C\u7528\u4E8E\u7ED3\u679C\u5BF9\u5E94\u3002"
|
|
37523
|
+
},
|
|
37524
|
+
question: {
|
|
37525
|
+
type: "string",
|
|
37526
|
+
description: "\u95EE\u9898\u6587\u6848\u3002"
|
|
37527
|
+
},
|
|
37528
|
+
choices: {
|
|
37529
|
+
type: "array",
|
|
37530
|
+
description: "\u8BE5\u95EE\u9898\u7684\u5907\u9009\u9879\u3002",
|
|
37531
|
+
items: {
|
|
37532
|
+
type: "object",
|
|
37533
|
+
properties: {
|
|
37534
|
+
id: { type: "string" },
|
|
37535
|
+
label: { type: "string" },
|
|
37536
|
+
detail: {
|
|
37537
|
+
type: "string",
|
|
37538
|
+
description: "\u8865\u5145\u63CF\u8FF0\u3002"
|
|
37539
|
+
},
|
|
37540
|
+
userMessage: { type: "string" }
|
|
37541
|
+
},
|
|
37542
|
+
required: ["id", "label"]
|
|
37543
|
+
}
|
|
37544
|
+
},
|
|
37545
|
+
multiSelect: {
|
|
37546
|
+
type: "boolean",
|
|
37547
|
+
description: "\u5141\u8BB8\u591A\u9009\u3002\u9ED8\u8BA4 false\u3002",
|
|
37548
|
+
default: false
|
|
37549
|
+
},
|
|
37550
|
+
allowOther: {
|
|
37551
|
+
type: "boolean",
|
|
37552
|
+
description: "\u663E\u793A\u201C\u5176\u4ED6\u201D\u81EA\u7531\u8F93\u5165\u884C\u3002\u9ED8\u8BA4 true\u3002",
|
|
37553
|
+
default: true
|
|
37554
|
+
},
|
|
37555
|
+
required: {
|
|
37556
|
+
type: "boolean",
|
|
37557
|
+
description: "\u662F\u5426\u5FC5\u987B\u56DE\u7B54\u624D\u80FD\u63D0\u4EA4\u3002\u9ED8\u8BA4 true\u3002",
|
|
37558
|
+
default: true
|
|
37559
|
+
}
|
|
37560
|
+
},
|
|
37561
|
+
required: ["id", "question", "choices"]
|
|
37562
|
+
}
|
|
37563
|
+
},
|
|
37446
37564
|
blocking: {
|
|
37447
37565
|
type: "boolean",
|
|
37448
37566
|
description: [
|
|
@@ -37452,7 +37570,7 @@ var init_uiAskChoiceTool = __esm({
|
|
|
37452
37570
|
default: true
|
|
37453
37571
|
}
|
|
37454
37572
|
},
|
|
37455
|
-
required: [
|
|
37573
|
+
required: []
|
|
37456
37574
|
}
|
|
37457
37575
|
};
|
|
37458
37576
|
}
|
|
@@ -93696,7 +93814,7 @@ function formatCompactToolLine(event, pending, colorEnabled) {
|
|
|
93696
93814
|
const label = rawArgs ? `${rawLabel} ${rawArgs}` : rawLabel;
|
|
93697
93815
|
if (event.type === "tool-error") {
|
|
93698
93816
|
const message = clip5(event.message ?? t("toolFailed"), 96);
|
|
93699
|
-
return formatToolTraceLine(
|
|
93817
|
+
return formatToolTraceLine(`\u25B8 ${label} \u2717 ${message}`, colorEnabled, "error");
|
|
93700
93818
|
}
|
|
93701
93819
|
if (event.type === "tool-result" && (event.toolName === "ui_ask_choice" || event.metadata?.uiAskChoice)) {
|
|
93702
93820
|
const block = formatUiAskChoiceBlock(event, colorEnabled);
|
|
@@ -93708,7 +93826,7 @@ function formatCompactToolLine(event, pending, colorEnabled) {
|
|
|
93708
93826
|
const marker = failed ? "\u2717" : isNeedsActionToolResult(event) ? "!" : "\u2713";
|
|
93709
93827
|
let mainLine;
|
|
93710
93828
|
if (!colorEnabled) {
|
|
93711
|
-
mainLine =
|
|
93829
|
+
mainLine = `\u25B8 ${label} ${marker}${suffix}
|
|
93712
93830
|
`;
|
|
93713
93831
|
} else {
|
|
93714
93832
|
const chromePointer = themeText("\u25B8", "chrome", true);
|
|
@@ -93716,7 +93834,7 @@ function formatCompactToolLine(event, pending, colorEnabled) {
|
|
|
93716
93834
|
const argsPart = rawArgs ? ` ${dimCliText(rawArgs, true)}` : "";
|
|
93717
93835
|
const statusToken = failed ? themeText("\u2717", "danger", true) : isNeedsActionToolResult(event) ? themeText("!", "warning", true) : themeText("\u2713", "success", true);
|
|
93718
93836
|
const suffixPart = hint.inline ? ` ${dimCliText(hint.inline, true)}` : "";
|
|
93719
|
-
mainLine =
|
|
93837
|
+
mainLine = `${chromePointer} ${mutedLabel}${argsPart} ${statusToken}${suffixPart}
|
|
93720
93838
|
`;
|
|
93721
93839
|
}
|
|
93722
93840
|
if (!hint.detail) return mainLine;
|
|
@@ -93726,28 +93844,28 @@ function formatCompactToolLine(event, pending, colorEnabled) {
|
|
|
93726
93844
|
function formatEditDetailLine(line, colorEnabled) {
|
|
93727
93845
|
const marker = line.slice(0, 2);
|
|
93728
93846
|
const rest = line.slice(2);
|
|
93729
|
-
if (!colorEnabled) return `
|
|
93847
|
+
if (!colorEnabled) return ` ${line}
|
|
93730
93848
|
`;
|
|
93731
93849
|
const diff = diffLineSequences();
|
|
93732
93850
|
if (!diff) {
|
|
93733
93851
|
const color = marker === "- " ? "red" : marker === "+ " ? "green" : void 0;
|
|
93734
93852
|
if (color) {
|
|
93735
|
-
return `
|
|
93853
|
+
return ` ${styleCliText(marker, color, true)}${dimCliText(rest, true)}
|
|
93736
93854
|
`;
|
|
93737
93855
|
}
|
|
93738
|
-
return `
|
|
93856
|
+
return ` ${dimCliText(line, true)}
|
|
93739
93857
|
`;
|
|
93740
93858
|
}
|
|
93741
93859
|
const RESET2 = "\x1B[0m";
|
|
93742
93860
|
if (marker === "- ") {
|
|
93743
|
-
return `
|
|
93861
|
+
return ` ${diff.removed.bg}${diff.removed.fg}- ${rest}${RESET2}
|
|
93744
93862
|
`;
|
|
93745
93863
|
}
|
|
93746
93864
|
if (marker === "+ ") {
|
|
93747
|
-
return `
|
|
93865
|
+
return ` ${diff.added.bg}${diff.added.fg}+ ${rest}${RESET2}
|
|
93748
93866
|
`;
|
|
93749
93867
|
}
|
|
93750
|
-
return `
|
|
93868
|
+
return ` ${dimCliText(line, true)}
|
|
93751
93869
|
`;
|
|
93752
93870
|
}
|
|
93753
93871
|
function createToolEventFormatter(mode, colorEnabled = resolveCliColorEnabled()) {
|
|
@@ -97769,7 +97887,6 @@ var init_offlineMarxistsAgentCommand = __esm({
|
|
|
97769
97887
|
import fs3 from "node:fs";
|
|
97770
97888
|
import path6 from "node:path";
|
|
97771
97889
|
import os from "node:os";
|
|
97772
|
-
import { Level as Level2 } from "level";
|
|
97773
97890
|
async function clearAgentKeysFromLocalLevelDbs(args2) {
|
|
97774
97891
|
const home = os.homedir();
|
|
97775
97892
|
const noloHome = process.env.NOLO_HOME?.trim() || path6.join(home, ".nolo");
|
|
@@ -97783,7 +97900,7 @@ async function clearAgentKeysFromLocalLevelDbs(args2) {
|
|
|
97783
97900
|
const cleaned = [];
|
|
97784
97901
|
for (const dbPath of dbPaths) {
|
|
97785
97902
|
try {
|
|
97786
|
-
const db = new
|
|
97903
|
+
const db = new Level(dbPath, { valueEncoding: "json" });
|
|
97787
97904
|
await db.open();
|
|
97788
97905
|
try {
|
|
97789
97906
|
for (const key of args2.keys) {
|
|
@@ -97804,6 +97921,7 @@ async function clearAgentKeysFromLocalLevelDbs(args2) {
|
|
|
97804
97921
|
var init_localLevelDbCleanup = __esm({
|
|
97805
97922
|
"packages/cli/localLevelDbCleanup.ts"() {
|
|
97806
97923
|
"use strict";
|
|
97924
|
+
init_levelLazyShim();
|
|
97807
97925
|
}
|
|
97808
97926
|
});
|
|
97809
97927
|
|
|
@@ -99870,7 +99988,6 @@ var init_memoryAuthorityStore = __esm({
|
|
|
99870
99988
|
// packages/database-engine/serverStoreFactory.ts
|
|
99871
99989
|
import fs4 from "fs";
|
|
99872
99990
|
import path7 from "path";
|
|
99873
|
-
import { Level as Level3 } from "level";
|
|
99874
99991
|
function ensureServerDbDirectory(dbPath) {
|
|
99875
99992
|
const dir = path7.dirname(dbPath);
|
|
99876
99993
|
if (!fs4.existsSync(dir)) {
|
|
@@ -99878,7 +99995,7 @@ function ensureServerDbDirectory(dbPath) {
|
|
|
99878
99995
|
}
|
|
99879
99996
|
}
|
|
99880
99997
|
function createLevelBackedAuthorityStore(dbPath) {
|
|
99881
|
-
const levelDb = new
|
|
99998
|
+
const levelDb = new Level(dbPath, {
|
|
99882
99999
|
valueEncoding: safeJsonEncoding2
|
|
99883
100000
|
});
|
|
99884
100001
|
return createLevelAuthorityStore(levelDb);
|
|
@@ -99930,6 +100047,7 @@ var safeJsonEncoding2;
|
|
|
99930
100047
|
var init_serverStoreFactory = __esm({
|
|
99931
100048
|
"packages/database-engine/serverStoreFactory.ts"() {
|
|
99932
100049
|
"use strict";
|
|
100050
|
+
init_levelLazyShim();
|
|
99933
100051
|
init_trimmedLowercaseString();
|
|
99934
100052
|
init_legacyServerDb();
|
|
99935
100053
|
init_levelAuthorityStore();
|
|
@@ -106909,13 +107027,73 @@ function renderDialogOverflow(text, colorEnabled = resolveCliColorEnabled()) {
|
|
|
106909
107027
|
function renderDialogCommand(text, colorEnabled = resolveCliColorEnabled()) {
|
|
106910
107028
|
return themeText(` ${text}`, "danger", colorEnabled);
|
|
106911
107029
|
}
|
|
106912
|
-
var DIALOG_CURSOR;
|
|
107030
|
+
var DIALOG_CURSOR, DIALOG_CHECKED, DIALOG_UNCHECKED;
|
|
106913
107031
|
var init_dialogFrame = __esm({
|
|
106914
107032
|
"packages/cli/tui/dialogFrame.ts"() {
|
|
106915
107033
|
"use strict";
|
|
106916
107034
|
init_terminalStyles();
|
|
106917
107035
|
init_theme();
|
|
106918
107036
|
DIALOG_CURSOR = "\u276F";
|
|
107037
|
+
DIALOG_CHECKED = "\u25C9";
|
|
107038
|
+
DIALOG_UNCHECKED = "\u25CB";
|
|
107039
|
+
}
|
|
107040
|
+
});
|
|
107041
|
+
|
|
107042
|
+
// packages/cli/tui/tuiScrollbar.ts
|
|
107043
|
+
function parseScrollAction(sequence) {
|
|
107044
|
+
const mouse = SGR_MOUSE_REGEX.exec(sequence);
|
|
107045
|
+
if (mouse) {
|
|
107046
|
+
const button = Number(mouse[1]);
|
|
107047
|
+
if ((button & 64) === 0) return null;
|
|
107048
|
+
if ((button & 2) !== 0) return null;
|
|
107049
|
+
return (button & 1) !== 0 ? "wheel-down" : "wheel-up";
|
|
107050
|
+
}
|
|
107051
|
+
switch (sequence) {
|
|
107052
|
+
case "\x1B[5~":
|
|
107053
|
+
return "page-up";
|
|
107054
|
+
case "\x1B[6~":
|
|
107055
|
+
return "page-down";
|
|
107056
|
+
case "\x1B[5;2~":
|
|
107057
|
+
case "\x1B[5;5~":
|
|
107058
|
+
return "half-page-up";
|
|
107059
|
+
case "\x1B[6;2~":
|
|
107060
|
+
case "\x1B[6;5~":
|
|
107061
|
+
return "half-page-down";
|
|
107062
|
+
case "\x1B[H":
|
|
107063
|
+
case "\x1B[1~":
|
|
107064
|
+
case "\x1B[7~":
|
|
107065
|
+
return "top";
|
|
107066
|
+
case "\x1B[F":
|
|
107067
|
+
case "\x1B[4~":
|
|
107068
|
+
case "\x1B[8~":
|
|
107069
|
+
return "bottom";
|
|
107070
|
+
default:
|
|
107071
|
+
return null;
|
|
107072
|
+
}
|
|
107073
|
+
}
|
|
107074
|
+
function renderScrollbarRow(rowIndex, visibleHeight, totalLines, scrollTop) {
|
|
107075
|
+
if (totalLines <= visibleHeight) return " ";
|
|
107076
|
+
const trackHeight = visibleHeight;
|
|
107077
|
+
const thumbSize = Math.max(
|
|
107078
|
+
1,
|
|
107079
|
+
Math.floor(visibleHeight * visibleHeight / totalLines)
|
|
107080
|
+
);
|
|
107081
|
+
const maxScrollTop = totalLines - visibleHeight;
|
|
107082
|
+
const thumbTop = Math.floor(
|
|
107083
|
+
scrollTop / maxScrollTop * (trackHeight - thumbSize)
|
|
107084
|
+
);
|
|
107085
|
+
const thumbBottom = thumbTop + thumbSize;
|
|
107086
|
+
if (rowIndex >= thumbTop && rowIndex < thumbBottom) {
|
|
107087
|
+
return "\u2588";
|
|
107088
|
+
}
|
|
107089
|
+
return "\u2502";
|
|
107090
|
+
}
|
|
107091
|
+
var SGR_MOUSE_REGEX, WHEEL_SCROLL_LINES;
|
|
107092
|
+
var init_tuiScrollbar = __esm({
|
|
107093
|
+
"packages/cli/tui/tuiScrollbar.ts"() {
|
|
107094
|
+
"use strict";
|
|
107095
|
+
SGR_MOUSE_REGEX = /^\x1b\[<(\d+);\d+;\d+[Mm]$/;
|
|
107096
|
+
WHEEL_SCROLL_LINES = 3;
|
|
106919
107097
|
}
|
|
106920
107098
|
});
|
|
106921
107099
|
|
|
@@ -107064,6 +107242,7 @@ async function runSelectDialog(args2) {
|
|
|
107064
107242
|
const output2 = args2.output ?? process.stdout;
|
|
107065
107243
|
const input2 = args2.input ?? process.stdin;
|
|
107066
107244
|
const readKey = args2.readKey ?? createRawKeyReader(input2);
|
|
107245
|
+
output2.write("\x1B[?1006h\x1B[?1000h");
|
|
107067
107246
|
const wasRaw = Boolean(input2.isTTY && input2.isRaw);
|
|
107068
107247
|
let renderedLineCount = 0;
|
|
107069
107248
|
const bottomAnchored = Boolean(args2.bottomAnchored && args2.bottomRow);
|
|
@@ -107127,6 +107306,18 @@ async function runSelectDialog(args2) {
|
|
|
107127
107306
|
if (sequence == null) {
|
|
107128
107307
|
return { kind: "cancelled" };
|
|
107129
107308
|
}
|
|
107309
|
+
const scrollAction = parseScrollAction(sequence);
|
|
107310
|
+
if (scrollAction === "wheel-up" || scrollAction === "wheel-down") {
|
|
107311
|
+
selectedIndex = Math.min(
|
|
107312
|
+
Math.max(
|
|
107313
|
+
selectedIndex + (scrollAction === "wheel-up" ? -1 : 1),
|
|
107314
|
+
0
|
|
107315
|
+
),
|
|
107316
|
+
items.length - 1
|
|
107317
|
+
);
|
|
107318
|
+
paint();
|
|
107319
|
+
continue;
|
|
107320
|
+
}
|
|
107130
107321
|
if (isCancel(sequence)) {
|
|
107131
107322
|
return { kind: "cancelled" };
|
|
107132
107323
|
}
|
|
@@ -107145,6 +107336,7 @@ async function runSelectDialog(args2) {
|
|
|
107145
107336
|
}
|
|
107146
107337
|
}
|
|
107147
107338
|
} finally {
|
|
107339
|
+
output2.write("\x1B[?1000l\x1B[?1006l");
|
|
107148
107340
|
resizeTarget.off?.("resize", onOutputResize);
|
|
107149
107341
|
readKey.dispose?.();
|
|
107150
107342
|
if (input2.isTTY) {
|
|
@@ -107169,6 +107361,7 @@ var init_selectDialog = __esm({
|
|
|
107169
107361
|
"use strict";
|
|
107170
107362
|
init_dialogFrame();
|
|
107171
107363
|
init_i18n2();
|
|
107364
|
+
init_tuiScrollbar();
|
|
107172
107365
|
CSI_ARROW_UP = "\x1B[A";
|
|
107173
107366
|
CSI_ARROW_DOWN = "\x1B[B";
|
|
107174
107367
|
CSI_ARROW_UP_APP = "\x1BOA";
|
|
@@ -107257,6 +107450,509 @@ var init_confirmDialog = __esm({
|
|
|
107257
107450
|
}
|
|
107258
107451
|
});
|
|
107259
107452
|
|
|
107453
|
+
// packages/ai/tools/askChoiceState.ts
|
|
107454
|
+
function normalizeAskChoiceArgs(args2) {
|
|
107455
|
+
const blocking = args2.blocking !== false;
|
|
107456
|
+
if (Array.isArray(args2.questions) && args2.questions.length > 0) {
|
|
107457
|
+
return {
|
|
107458
|
+
questions: args2.questions.map(
|
|
107459
|
+
(q, i) => normalizeQuestion(q, i)
|
|
107460
|
+
),
|
|
107461
|
+
blocking
|
|
107462
|
+
};
|
|
107463
|
+
}
|
|
107464
|
+
const question = String(args2.question ?? "").trim();
|
|
107465
|
+
const choices = Array.isArray(args2.choices) ? args2.choices : [];
|
|
107466
|
+
if (!question || choices.length === 0) {
|
|
107467
|
+
return { questions: [], blocking };
|
|
107468
|
+
}
|
|
107469
|
+
return {
|
|
107470
|
+
questions: [
|
|
107471
|
+
normalizeQuestion(
|
|
107472
|
+
{ question, choices, multiSelect: false, allowOther: true, required: true },
|
|
107473
|
+
0
|
|
107474
|
+
)
|
|
107475
|
+
],
|
|
107476
|
+
blocking
|
|
107477
|
+
};
|
|
107478
|
+
}
|
|
107479
|
+
function normalizeQuestion(raw, index) {
|
|
107480
|
+
return {
|
|
107481
|
+
id: String(raw?.id ?? `q${index}`),
|
|
107482
|
+
question: String(raw?.question ?? "").trim(),
|
|
107483
|
+
choices: (Array.isArray(raw?.choices) ? raw.choices : []).map(
|
|
107484
|
+
(c, ci) => ({
|
|
107485
|
+
id: String(c?.id ?? `c${ci}`),
|
|
107486
|
+
label: String(c?.label ?? "").trim(),
|
|
107487
|
+
...typeof c?.detail === "string" && c.detail.trim() ? { detail: c.detail.trim() } : {},
|
|
107488
|
+
...typeof c?.userMessage === "string" && c.userMessage.trim() ? { userMessage: c.userMessage.trim() } : {}
|
|
107489
|
+
})
|
|
107490
|
+
),
|
|
107491
|
+
multiSelect: raw?.multiSelect === true,
|
|
107492
|
+
allowOther: raw?.allowOther !== false,
|
|
107493
|
+
required: raw?.required !== false
|
|
107494
|
+
};
|
|
107495
|
+
}
|
|
107496
|
+
function createInitialAskChoiceState(questions) {
|
|
107497
|
+
return {
|
|
107498
|
+
questions,
|
|
107499
|
+
activeIndex: 0,
|
|
107500
|
+
questionStates: questions.map(() => ({
|
|
107501
|
+
cursorIndex: 0,
|
|
107502
|
+
selectedIds: [],
|
|
107503
|
+
pickedId: null,
|
|
107504
|
+
otherText: "",
|
|
107505
|
+
otherFocused: false
|
|
107506
|
+
})),
|
|
107507
|
+
phase: "active"
|
|
107508
|
+
};
|
|
107509
|
+
}
|
|
107510
|
+
function askChoiceReducer(state4, action3) {
|
|
107511
|
+
if (state4.phase !== "active") return state4;
|
|
107512
|
+
switch (action3.type) {
|
|
107513
|
+
case "CANCEL":
|
|
107514
|
+
return { ...state4, phase: "cancelled" };
|
|
107515
|
+
case "SUBMIT": {
|
|
107516
|
+
if (!canSubmit(state4)) return state4;
|
|
107517
|
+
return { ...state4, phase: "submitted" };
|
|
107518
|
+
}
|
|
107519
|
+
case "SWITCH_TAB": {
|
|
107520
|
+
const idx = clamp3(action3.index, 0, state4.questions.length - 1);
|
|
107521
|
+
return { ...state4, activeIndex: idx };
|
|
107522
|
+
}
|
|
107523
|
+
case "NEXT_TAB": {
|
|
107524
|
+
const idx = Math.min(state4.activeIndex + 1, state4.questions.length - 1);
|
|
107525
|
+
return { ...state4, activeIndex: idx };
|
|
107526
|
+
}
|
|
107527
|
+
case "PREV_TAB": {
|
|
107528
|
+
const idx = Math.max(state4.activeIndex - 1, 0);
|
|
107529
|
+
return { ...state4, activeIndex: idx };
|
|
107530
|
+
}
|
|
107531
|
+
case "MOVE_CURSOR": {
|
|
107532
|
+
const qs = state4.questionStates[state4.activeIndex];
|
|
107533
|
+
const q = state4.questions[state4.activeIndex];
|
|
107534
|
+
const maxIndex = q.allowOther ? q.choices.length : q.choices.length - 1;
|
|
107535
|
+
const next = clamp3(qs.cursorIndex + action3.delta, 0, maxIndex);
|
|
107536
|
+
const newQs = [...state4.questionStates];
|
|
107537
|
+
newQs[state4.activeIndex] = {
|
|
107538
|
+
...qs,
|
|
107539
|
+
cursorIndex: next,
|
|
107540
|
+
otherFocused: false
|
|
107541
|
+
};
|
|
107542
|
+
return { ...state4, questionStates: newQs };
|
|
107543
|
+
}
|
|
107544
|
+
case "TOGGLE_AT_CURSOR": {
|
|
107545
|
+
const qs = state4.questionStates[state4.activeIndex];
|
|
107546
|
+
const q = state4.questions[state4.activeIndex];
|
|
107547
|
+
if (!q.multiSelect) return state4;
|
|
107548
|
+
const isOtherRow = qs.cursorIndex >= q.choices.length;
|
|
107549
|
+
if (isOtherRow) {
|
|
107550
|
+
const newQs2 = [...state4.questionStates];
|
|
107551
|
+
newQs2[state4.activeIndex] = { ...qs, otherFocused: !qs.otherFocused };
|
|
107552
|
+
return { ...state4, questionStates: newQs2 };
|
|
107553
|
+
}
|
|
107554
|
+
const choiceId = q.choices[qs.cursorIndex]?.id;
|
|
107555
|
+
if (!choiceId) return state4;
|
|
107556
|
+
const has = qs.selectedIds.includes(choiceId);
|
|
107557
|
+
const newSelected = has ? qs.selectedIds.filter((id) => id !== choiceId) : [...qs.selectedIds, choiceId];
|
|
107558
|
+
const newQs = [...state4.questionStates];
|
|
107559
|
+
newQs[state4.activeIndex] = { ...qs, selectedIds: newSelected };
|
|
107560
|
+
return { ...state4, questionStates: newQs };
|
|
107561
|
+
}
|
|
107562
|
+
case "SELECT_AT_CURSOR": {
|
|
107563
|
+
const qs = state4.questionStates[state4.activeIndex];
|
|
107564
|
+
const q = state4.questions[state4.activeIndex];
|
|
107565
|
+
const isOtherRow = qs.cursorIndex >= q.choices.length;
|
|
107566
|
+
if (isOtherRow) {
|
|
107567
|
+
const newQs2 = [...state4.questionStates];
|
|
107568
|
+
newQs2[state4.activeIndex] = { ...qs, otherFocused: true };
|
|
107569
|
+
return { ...state4, questionStates: newQs2 };
|
|
107570
|
+
}
|
|
107571
|
+
const choiceId = q.choices[qs.cursorIndex]?.id;
|
|
107572
|
+
if (!choiceId) return state4;
|
|
107573
|
+
if (q.multiSelect) {
|
|
107574
|
+
const has = qs.selectedIds.includes(choiceId);
|
|
107575
|
+
const newSelected = has ? qs.selectedIds.filter((id) => id !== choiceId) : [...qs.selectedIds, choiceId];
|
|
107576
|
+
const newQs2 = [...state4.questionStates];
|
|
107577
|
+
newQs2[state4.activeIndex] = { ...qs, selectedIds: newSelected };
|
|
107578
|
+
return { ...state4, questionStates: newQs2 };
|
|
107579
|
+
}
|
|
107580
|
+
const newQs = [...state4.questionStates];
|
|
107581
|
+
newQs[state4.activeIndex] = { ...qs, pickedId: choiceId, otherFocused: false };
|
|
107582
|
+
if (state4.questions.length === 1) {
|
|
107583
|
+
return {
|
|
107584
|
+
...state4,
|
|
107585
|
+
questionStates: newQs,
|
|
107586
|
+
phase: "submitted"
|
|
107587
|
+
};
|
|
107588
|
+
}
|
|
107589
|
+
const nextState = { ...state4, questionStates: newQs };
|
|
107590
|
+
const isLastTab = state4.activeIndex >= state4.questions.length - 1;
|
|
107591
|
+
if (isLastTab && canSubmit(nextState)) {
|
|
107592
|
+
return { ...nextState, phase: "submitted" };
|
|
107593
|
+
}
|
|
107594
|
+
const nextTab = Math.min(
|
|
107595
|
+
state4.activeIndex + 1,
|
|
107596
|
+
state4.questions.length - 1
|
|
107597
|
+
);
|
|
107598
|
+
return { ...nextState, activeIndex: nextTab };
|
|
107599
|
+
}
|
|
107600
|
+
case "FOCUS_OTHER": {
|
|
107601
|
+
const qs = state4.questionStates[state4.activeIndex];
|
|
107602
|
+
const newQs = [...state4.questionStates];
|
|
107603
|
+
newQs[state4.activeIndex] = { ...qs, otherFocused: true };
|
|
107604
|
+
return { ...state4, questionStates: newQs };
|
|
107605
|
+
}
|
|
107606
|
+
case "BLUR_OTHER": {
|
|
107607
|
+
const qs = state4.questionStates[state4.activeIndex];
|
|
107608
|
+
const newQs = [...state4.questionStates];
|
|
107609
|
+
newQs[state4.activeIndex] = { ...qs, otherFocused: false };
|
|
107610
|
+
return { ...state4, questionStates: newQs };
|
|
107611
|
+
}
|
|
107612
|
+
case "SET_OTHER_TEXT": {
|
|
107613
|
+
const qs = state4.questionStates[state4.activeIndex];
|
|
107614
|
+
const newQs = [...state4.questionStates];
|
|
107615
|
+
newQs[state4.activeIndex] = { ...qs, otherText: action3.text };
|
|
107616
|
+
return { ...state4, questionStates: newQs };
|
|
107617
|
+
}
|
|
107618
|
+
default:
|
|
107619
|
+
return state4;
|
|
107620
|
+
}
|
|
107621
|
+
}
|
|
107622
|
+
function isQuestionAnswered(q, qs) {
|
|
107623
|
+
if (!q.required) return true;
|
|
107624
|
+
const hasSelection = q.multiSelect ? qs.selectedIds.length > 0 : qs.pickedId !== null;
|
|
107625
|
+
const hasOther = q.allowOther && qs.otherText.trim().length > 0;
|
|
107626
|
+
return hasSelection || hasOther;
|
|
107627
|
+
}
|
|
107628
|
+
function canSubmit(state4) {
|
|
107629
|
+
return state4.questions.every(
|
|
107630
|
+
(q, i) => isQuestionAnswered(q, state4.questionStates[i])
|
|
107631
|
+
);
|
|
107632
|
+
}
|
|
107633
|
+
function buildAskChoiceResult(state4) {
|
|
107634
|
+
if (state4.phase === "cancelled") return { kind: "cancelled" };
|
|
107635
|
+
if (state4.phase !== "submitted") return { kind: "cancelled" };
|
|
107636
|
+
const answers = state4.questions.map((q, i) => {
|
|
107637
|
+
const qs = state4.questionStates[i];
|
|
107638
|
+
const selectedIds = q.multiSelect ? qs.selectedIds : qs.pickedId ? [qs.pickedId] : [];
|
|
107639
|
+
const otherText = qs.otherText.trim();
|
|
107640
|
+
const parts = [];
|
|
107641
|
+
for (const id of selectedIds) {
|
|
107642
|
+
const choice = q.choices.find((c) => c.id === id);
|
|
107643
|
+
if (choice) {
|
|
107644
|
+
parts.push(choice.userMessage || choice.label);
|
|
107645
|
+
}
|
|
107646
|
+
}
|
|
107647
|
+
if (otherText) {
|
|
107648
|
+
parts.push(otherText);
|
|
107649
|
+
}
|
|
107650
|
+
return {
|
|
107651
|
+
questionId: q.id,
|
|
107652
|
+
selectedIds,
|
|
107653
|
+
otherText,
|
|
107654
|
+
userMessage: parts.join("\n")
|
|
107655
|
+
};
|
|
107656
|
+
});
|
|
107657
|
+
return { kind: "submitted", answers };
|
|
107658
|
+
}
|
|
107659
|
+
function clamp3(value, min, max) {
|
|
107660
|
+
return Math.max(min, Math.min(max, value));
|
|
107661
|
+
}
|
|
107662
|
+
var init_askChoiceState = __esm({
|
|
107663
|
+
"packages/ai/tools/askChoiceState.ts"() {
|
|
107664
|
+
"use strict";
|
|
107665
|
+
}
|
|
107666
|
+
});
|
|
107667
|
+
|
|
107668
|
+
// packages/cli/tui/askChoiceDialog.ts
|
|
107669
|
+
function renderTabBar(questions, activeIndex, colorEnabled) {
|
|
107670
|
+
const tabs = questions.map((q, i) => {
|
|
107671
|
+
const label = `Q${i + 1}`;
|
|
107672
|
+
if (i === activeIndex) {
|
|
107673
|
+
return colorEnabled ? `${themeColorSequence("accent")}\x1B[1m ${label} \x1B[0m` : `[${label}]`;
|
|
107674
|
+
}
|
|
107675
|
+
return colorEnabled ? themeText(` ${label} `, "muted", colorEnabled) : ` ${label} `;
|
|
107676
|
+
});
|
|
107677
|
+
const submitLabel = "Submit";
|
|
107678
|
+
return tabs.join(" ") + " " + (colorEnabled ? themeText(submitLabel, "chrome", colorEnabled) : submitLabel);
|
|
107679
|
+
}
|
|
107680
|
+
function renderFooter(colorEnabled) {
|
|
107681
|
+
const hints = "\u21B5 pick/submit \xB7 space toggle \xB7 tab switch \xB7 esc cancel";
|
|
107682
|
+
return colorEnabled ? themeText(` ${hints}`, "chrome", colorEnabled) : ` ${hints}`;
|
|
107683
|
+
}
|
|
107684
|
+
function renderAskChoiceFrame(state4) {
|
|
107685
|
+
const colorEnabled = resolveCliColorEnabled();
|
|
107686
|
+
const q = state4.questions[state4.activeIndex];
|
|
107687
|
+
const qs = state4.questionStates[state4.activeIndex];
|
|
107688
|
+
const lines = [];
|
|
107689
|
+
lines.push(renderDialogTitle("question"));
|
|
107690
|
+
lines.push("");
|
|
107691
|
+
if (state4.questions.length > 1) {
|
|
107692
|
+
lines.push(renderTabBar(state4.questions, state4.activeIndex, colorEnabled));
|
|
107693
|
+
lines.push("");
|
|
107694
|
+
}
|
|
107695
|
+
lines.push(
|
|
107696
|
+
colorEnabled ? `${themeColorSequence("accent")}? ${q.question}\x1B[0m` : `? ${q.question}`
|
|
107697
|
+
);
|
|
107698
|
+
if (q.multiSelect) {
|
|
107699
|
+
lines.push(
|
|
107700
|
+
colorEnabled ? themeText(" Space to toggle, Enter to confirm selection.", "muted", colorEnabled) : " Space to toggle, Enter to confirm selection."
|
|
107701
|
+
);
|
|
107702
|
+
} else {
|
|
107703
|
+
lines.push(
|
|
107704
|
+
colorEnabled ? themeText(" Type your answer, then press Enter to save.", "muted", colorEnabled) : " Type your answer, then press Enter to save."
|
|
107705
|
+
);
|
|
107706
|
+
}
|
|
107707
|
+
lines.push("");
|
|
107708
|
+
const totalRows = q.choices.length + (q.allowOther ? 1 : 0);
|
|
107709
|
+
const window2 = computeVisibleWindow({
|
|
107710
|
+
selectedIndex: qs.cursorIndex,
|
|
107711
|
+
total: totalRows
|
|
107712
|
+
});
|
|
107713
|
+
if (window2.start > 0) {
|
|
107714
|
+
lines.push(
|
|
107715
|
+
colorEnabled ? themeText(` \u2191 ${window2.start} more`, "chrome", colorEnabled) : ` \u2191 ${window2.start} more`
|
|
107716
|
+
);
|
|
107717
|
+
}
|
|
107718
|
+
for (let i = window2.start; i < window2.end; i++) {
|
|
107719
|
+
if (i < q.choices.length) {
|
|
107720
|
+
const choice = q.choices[i];
|
|
107721
|
+
const focused = qs.cursorIndex === i;
|
|
107722
|
+
const checkbox = q.multiSelect ? qs.selectedIds.includes(choice.id) ? DIALOG_CHECKED : DIALOG_UNCHECKED : qs.pickedId === choice.id ? DIALOG_CHECKED : void 0;
|
|
107723
|
+
lines.push(
|
|
107724
|
+
renderDialogRow({
|
|
107725
|
+
label: `[${i + 1}] ${choice.label}`,
|
|
107726
|
+
...choice.detail ? { detail: choice.detail } : {},
|
|
107727
|
+
focused,
|
|
107728
|
+
...checkbox ? { checkbox } : {}
|
|
107729
|
+
})
|
|
107730
|
+
);
|
|
107731
|
+
} else {
|
|
107732
|
+
const focused = qs.cursorIndex === i;
|
|
107733
|
+
const marker = focused ? DIALOG_CURSOR : " ";
|
|
107734
|
+
const otherContent = qs.otherFocused ? `${qs.otherText}\u2588` : qs.otherText || "";
|
|
107735
|
+
const row = `${marker} [${i + 1}] Other: ${otherContent}`;
|
|
107736
|
+
if (focused && colorEnabled) {
|
|
107737
|
+
lines.push(
|
|
107738
|
+
`\x1B[1m${themeColorSequence("accent")}${row}\x1B[0m`
|
|
107739
|
+
);
|
|
107740
|
+
} else {
|
|
107741
|
+
lines.push(row);
|
|
107742
|
+
}
|
|
107743
|
+
}
|
|
107744
|
+
}
|
|
107745
|
+
if (window2.end < totalRows) {
|
|
107746
|
+
lines.push(
|
|
107747
|
+
colorEnabled ? themeText(` \u2193 ${totalRows - window2.end} more`, "chrome", colorEnabled) : ` \u2193 ${totalRows - window2.end} more`
|
|
107748
|
+
);
|
|
107749
|
+
}
|
|
107750
|
+
lines.push("");
|
|
107751
|
+
lines.push(renderFooter(colorEnabled));
|
|
107752
|
+
return lines.join("\n");
|
|
107753
|
+
}
|
|
107754
|
+
async function runAskChoiceDialog(args2) {
|
|
107755
|
+
const { request } = args2;
|
|
107756
|
+
const normalized = normalizeAskChoiceArgs({
|
|
107757
|
+
question: request.question,
|
|
107758
|
+
choices: request.choices,
|
|
107759
|
+
questions: request.questions,
|
|
107760
|
+
blocking: request.blocking
|
|
107761
|
+
});
|
|
107762
|
+
if (normalized.questions.length === 0) {
|
|
107763
|
+
return { kind: "cancelled" };
|
|
107764
|
+
}
|
|
107765
|
+
const q0 = normalized.questions[0];
|
|
107766
|
+
if (normalized.questions.length === 1 && !q0.multiSelect && !q0.allowOther) {
|
|
107767
|
+
}
|
|
107768
|
+
let state4 = createInitialAskChoiceState(normalized.questions);
|
|
107769
|
+
const output2 = args2.output ?? process.stdout;
|
|
107770
|
+
const input2 = args2.input ?? process.stdin;
|
|
107771
|
+
const readKey = args2.readKey ?? createRawKeyReader(input2);
|
|
107772
|
+
output2.write("\x1B[?1006h\x1B[?1000h");
|
|
107773
|
+
const wasRaw = Boolean(input2.isTTY && input2.isRaw);
|
|
107774
|
+
let renderedLineCount = 0;
|
|
107775
|
+
const bottomAnchored = Boolean(args2.bottomAnchored && args2.bottomRow);
|
|
107776
|
+
const resolveBottomRow = () => Math.max(
|
|
107777
|
+
1,
|
|
107778
|
+
typeof args2.bottomRow === "function" ? args2.bottomRow() : args2.bottomRow ?? 0
|
|
107779
|
+
);
|
|
107780
|
+
let lastBottomRow = 0;
|
|
107781
|
+
const paint = () => {
|
|
107782
|
+
const frame = renderAskChoiceFrame(state4);
|
|
107783
|
+
const lines = frame.split("\n");
|
|
107784
|
+
const lineCount = lines.length;
|
|
107785
|
+
const canPosition = outputIsTty(output2) && typeof output2.write === "function";
|
|
107786
|
+
if (bottomAnchored && canPosition) {
|
|
107787
|
+
const anchorRow = resolveBottomRow();
|
|
107788
|
+
clearAnchoredLines(
|
|
107789
|
+
output2,
|
|
107790
|
+
lastBottomRow > 0 ? lastBottomRow : anchorRow,
|
|
107791
|
+
renderedLineCount
|
|
107792
|
+
);
|
|
107793
|
+
for (let i = 0; i < lines.length; i++) {
|
|
107794
|
+
const row = anchorRow - (lines.length - 1 - i);
|
|
107795
|
+
if (row < 1) break;
|
|
107796
|
+
output2.write(`\x1B[${row};1H\x1B[2K${lines[i]}`);
|
|
107797
|
+
}
|
|
107798
|
+
lastBottomRow = anchorRow;
|
|
107799
|
+
renderedLineCount = lineCount;
|
|
107800
|
+
return;
|
|
107801
|
+
}
|
|
107802
|
+
if (canPosition) {
|
|
107803
|
+
for (let i = 0; i < renderedLineCount; i++) {
|
|
107804
|
+
output2.write("\x1B[1A\x1B[2K");
|
|
107805
|
+
}
|
|
107806
|
+
output2.write(`${frame}
|
|
107807
|
+
`);
|
|
107808
|
+
renderedLineCount = lineCount;
|
|
107809
|
+
return;
|
|
107810
|
+
}
|
|
107811
|
+
if (typeof output2.write === "function") {
|
|
107812
|
+
output2.write(`${frame}
|
|
107813
|
+
`);
|
|
107814
|
+
}
|
|
107815
|
+
renderedLineCount = lineCount;
|
|
107816
|
+
};
|
|
107817
|
+
const resizeTarget = output2;
|
|
107818
|
+
const onOutputResize = () => paint();
|
|
107819
|
+
if (input2.isTTY && !wasRaw) {
|
|
107820
|
+
input2.setRawMode?.(true);
|
|
107821
|
+
}
|
|
107822
|
+
if (bottomAnchored && outputIsTty(output2)) {
|
|
107823
|
+
resizeTarget.on?.("resize", onOutputResize);
|
|
107824
|
+
}
|
|
107825
|
+
paint();
|
|
107826
|
+
try {
|
|
107827
|
+
while (state4.phase === "active") {
|
|
107828
|
+
const sequence = await readKey();
|
|
107829
|
+
if (sequence == null) {
|
|
107830
|
+
state4 = askChoiceReducer(state4, { type: "CANCEL" });
|
|
107831
|
+
break;
|
|
107832
|
+
}
|
|
107833
|
+
const scrollAction = parseScrollAction(sequence);
|
|
107834
|
+
if (scrollAction === "wheel-up" || scrollAction === "wheel-down") {
|
|
107835
|
+
state4 = askChoiceReducer(state4, {
|
|
107836
|
+
type: "MOVE_CURSOR",
|
|
107837
|
+
delta: scrollAction === "wheel-up" ? -1 : 1
|
|
107838
|
+
});
|
|
107839
|
+
paint();
|
|
107840
|
+
continue;
|
|
107841
|
+
}
|
|
107842
|
+
let action3 = null;
|
|
107843
|
+
if (isCancel(sequence)) {
|
|
107844
|
+
action3 = { type: "CANCEL" };
|
|
107845
|
+
} else if (sequence === CSI_TAB) {
|
|
107846
|
+
action3 = { type: "NEXT_TAB" };
|
|
107847
|
+
} else if (sequence === CSI_SHIFT_TAB) {
|
|
107848
|
+
action3 = { type: "PREV_TAB" };
|
|
107849
|
+
} else if (isArrowUp(sequence)) {
|
|
107850
|
+
action3 = { type: "MOVE_CURSOR", delta: -1 };
|
|
107851
|
+
} else if (isArrowDown(sequence)) {
|
|
107852
|
+
action3 = { type: "MOVE_CURSOR", delta: 1 };
|
|
107853
|
+
} else if (sequence === CSI_SPACE) {
|
|
107854
|
+
action3 = { type: "TOGGLE_AT_CURSOR" };
|
|
107855
|
+
} else if (isSubmit(sequence)) {
|
|
107856
|
+
const qs = state4.questionStates[state4.activeIndex];
|
|
107857
|
+
const q = state4.questions[state4.activeIndex];
|
|
107858
|
+
const isOtherRow = qs.cursorIndex >= q.choices.length;
|
|
107859
|
+
if (qs.otherFocused) {
|
|
107860
|
+
action3 = { type: "BLUR_OTHER" };
|
|
107861
|
+
} else if (isOtherRow && !qs.otherFocused) {
|
|
107862
|
+
action3 = { type: "FOCUS_OTHER" };
|
|
107863
|
+
} else if (q.multiSelect) {
|
|
107864
|
+
action3 = { type: "SUBMIT" };
|
|
107865
|
+
} else {
|
|
107866
|
+
action3 = { type: "SELECT_AT_CURSOR" };
|
|
107867
|
+
}
|
|
107868
|
+
} else if (sequence === CSI_BACKSPACE || sequence === CSI_BACKSPACE_ALT) {
|
|
107869
|
+
const qs = state4.questionStates[state4.activeIndex];
|
|
107870
|
+
if (qs.otherFocused && qs.otherText.length > 0) {
|
|
107871
|
+
action3 = {
|
|
107872
|
+
type: "SET_OTHER_TEXT",
|
|
107873
|
+
text: qs.otherText.slice(0, -1)
|
|
107874
|
+
};
|
|
107875
|
+
}
|
|
107876
|
+
} else if (sequence.length === 1 && sequence.charCodeAt(0) >= 32) {
|
|
107877
|
+
const qs = state4.questionStates[state4.activeIndex];
|
|
107878
|
+
if (qs.otherFocused) {
|
|
107879
|
+
action3 = {
|
|
107880
|
+
type: "SET_OTHER_TEXT",
|
|
107881
|
+
text: qs.otherText + sequence
|
|
107882
|
+
};
|
|
107883
|
+
}
|
|
107884
|
+
}
|
|
107885
|
+
if (action3) {
|
|
107886
|
+
const prev = state4;
|
|
107887
|
+
state4 = askChoiceReducer(state4, action3);
|
|
107888
|
+
if (state4.phase !== "active") break;
|
|
107889
|
+
if (action3.type === "BLUR_OTHER" && state4.activeIndex >= state4.questions.length - 1 && canSubmit(state4)) {
|
|
107890
|
+
state4 = askChoiceReducer(state4, { type: "SUBMIT" });
|
|
107891
|
+
break;
|
|
107892
|
+
}
|
|
107893
|
+
paint();
|
|
107894
|
+
}
|
|
107895
|
+
}
|
|
107896
|
+
} finally {
|
|
107897
|
+
output2.write("\x1B[?1000l\x1B[?1006l");
|
|
107898
|
+
resizeTarget.off?.("resize", onOutputResize);
|
|
107899
|
+
readKey.dispose?.();
|
|
107900
|
+
if (input2.isTTY) {
|
|
107901
|
+
drainInputBuffer(input2);
|
|
107902
|
+
if (!wasRaw) input2.setRawMode?.(false);
|
|
107903
|
+
if (bottomAnchored) {
|
|
107904
|
+
clearAnchoredLines(
|
|
107905
|
+
output2,
|
|
107906
|
+
lastBottomRow > 0 ? lastBottomRow : resolveBottomRow(),
|
|
107907
|
+
renderedLineCount
|
|
107908
|
+
);
|
|
107909
|
+
} else {
|
|
107910
|
+
for (let i = 0; i < renderedLineCount; i++) {
|
|
107911
|
+
output2.write("\x1B[1A\x1B[2K");
|
|
107912
|
+
}
|
|
107913
|
+
}
|
|
107914
|
+
renderedLineCount = 0;
|
|
107915
|
+
}
|
|
107916
|
+
}
|
|
107917
|
+
const result = buildAskChoiceResult(state4);
|
|
107918
|
+
if (result.kind === "cancelled") {
|
|
107919
|
+
return { kind: "cancelled" };
|
|
107920
|
+
}
|
|
107921
|
+
if (result.answers.length === 1) {
|
|
107922
|
+
const a = result.answers[0];
|
|
107923
|
+
return {
|
|
107924
|
+
kind: "selected",
|
|
107925
|
+
userMessage: a.userMessage,
|
|
107926
|
+
label: a.selectedIds.map((id) => {
|
|
107927
|
+
const q = normalized.questions[0];
|
|
107928
|
+
return q.choices.find((c) => c.id === id)?.label ?? "";
|
|
107929
|
+
}).join(", ") || a.otherText || ""
|
|
107930
|
+
};
|
|
107931
|
+
}
|
|
107932
|
+
return {
|
|
107933
|
+
kind: "multi-submitted",
|
|
107934
|
+
answers: result.answers,
|
|
107935
|
+
userMessage: result.answers.map((a) => a.userMessage).filter(Boolean).join("\n\n")
|
|
107936
|
+
};
|
|
107937
|
+
}
|
|
107938
|
+
var CSI_TAB, CSI_SHIFT_TAB, CSI_BACKSPACE, CSI_BACKSPACE_ALT, CSI_SPACE;
|
|
107939
|
+
var init_askChoiceDialog = __esm({
|
|
107940
|
+
"packages/cli/tui/askChoiceDialog.ts"() {
|
|
107941
|
+
"use strict";
|
|
107942
|
+
init_askChoiceState();
|
|
107943
|
+
init_dialogFrame();
|
|
107944
|
+
init_selectDialog();
|
|
107945
|
+
init_terminalStyles();
|
|
107946
|
+
init_theme();
|
|
107947
|
+
init_tuiScrollbar();
|
|
107948
|
+
CSI_TAB = " ";
|
|
107949
|
+
CSI_SHIFT_TAB = "\x1B[Z";
|
|
107950
|
+
CSI_BACKSPACE = "\x7F";
|
|
107951
|
+
CSI_BACKSPACE_ALT = "\b";
|
|
107952
|
+
CSI_SPACE = " ";
|
|
107953
|
+
}
|
|
107954
|
+
});
|
|
107955
|
+
|
|
107260
107956
|
// packages/cli/tui/dialogHost.ts
|
|
107261
107957
|
function resolveTtyRows(output2) {
|
|
107262
107958
|
if (typeof output2 === "object" && output2 !== null && "rows" in output2 && typeof output2.rows === "number") {
|
|
@@ -107294,6 +107990,92 @@ var init_dialogHost = __esm({
|
|
|
107294
107990
|
}
|
|
107295
107991
|
});
|
|
107296
107992
|
|
|
107993
|
+
// packages/cli/tui/activityIndicator.ts
|
|
107994
|
+
function createActivityIndicator(deps) {
|
|
107995
|
+
const now = deps.now ?? (() => Date.now());
|
|
107996
|
+
const frameIntervalMs = deps.frameIntervalMs ?? ACTIVITY_FRAME_INTERVAL_MS;
|
|
107997
|
+
const fallbackDelayMs = deps.fallbackDelayMs ?? ACTIVITY_FALLBACK_DELAY_MS;
|
|
107998
|
+
const setIntervalFn = deps.setIntervalFn ?? ((cb, ms) => setInterval(cb, ms));
|
|
107999
|
+
const clearIntervalFn = deps.clearIntervalFn ?? ((handle) => clearInterval(handle));
|
|
108000
|
+
let explicitLabel = null;
|
|
108001
|
+
let explicitStartedAt = 0;
|
|
108002
|
+
let fallbackActive = false;
|
|
108003
|
+
let fallbackStartedAt = 0;
|
|
108004
|
+
let lastActivityAt = 0;
|
|
108005
|
+
let frameIndex = 0;
|
|
108006
|
+
let timer = null;
|
|
108007
|
+
const elapsedSecFrom = (startedAt) => startedAt > 0 ? Math.max(0, Math.floor((now() - startedAt) / 1e3)) : 0;
|
|
108008
|
+
const tick = () => {
|
|
108009
|
+
frameIndex += 1;
|
|
108010
|
+
if (explicitLabel === null && !fallbackActive && deps.isTurnActive() && lastActivityAt > 0 && now() - lastActivityAt >= fallbackDelayMs) {
|
|
108011
|
+
fallbackActive = true;
|
|
108012
|
+
fallbackStartedAt = now();
|
|
108013
|
+
}
|
|
108014
|
+
deps.onRepaint();
|
|
108015
|
+
};
|
|
108016
|
+
const ensureTimer = () => {
|
|
108017
|
+
if (timer === null) {
|
|
108018
|
+
timer = setIntervalFn(tick, frameIntervalMs);
|
|
108019
|
+
}
|
|
108020
|
+
};
|
|
108021
|
+
const report = (label) => {
|
|
108022
|
+
lastActivityAt = now();
|
|
108023
|
+
if (label !== null) {
|
|
108024
|
+
explicitLabel = label;
|
|
108025
|
+
if (explicitStartedAt === 0) explicitStartedAt = lastActivityAt;
|
|
108026
|
+
fallbackActive = false;
|
|
108027
|
+
fallbackStartedAt = 0;
|
|
108028
|
+
} else {
|
|
108029
|
+
explicitLabel = null;
|
|
108030
|
+
explicitStartedAt = 0;
|
|
108031
|
+
fallbackActive = false;
|
|
108032
|
+
fallbackStartedAt = 0;
|
|
108033
|
+
}
|
|
108034
|
+
ensureTimer();
|
|
108035
|
+
deps.onRepaint();
|
|
108036
|
+
};
|
|
108037
|
+
const getView = () => {
|
|
108038
|
+
if (!deps.isTurnActive()) return null;
|
|
108039
|
+
const frame = ACTIVITY_FRAMES[frameIndex % ACTIVITY_FRAMES.length];
|
|
108040
|
+
if (explicitLabel !== null) {
|
|
108041
|
+
return {
|
|
108042
|
+
frame,
|
|
108043
|
+
label: explicitLabel,
|
|
108044
|
+
elapsedSec: elapsedSecFrom(explicitStartedAt)
|
|
108045
|
+
};
|
|
108046
|
+
}
|
|
108047
|
+
if (fallbackActive) {
|
|
108048
|
+
return {
|
|
108049
|
+
frame,
|
|
108050
|
+
label: deps.fallbackLabel(),
|
|
108051
|
+
elapsedSec: elapsedSecFrom(fallbackStartedAt)
|
|
108052
|
+
};
|
|
108053
|
+
}
|
|
108054
|
+
return null;
|
|
108055
|
+
};
|
|
108056
|
+
const stop = () => {
|
|
108057
|
+
if (timer !== null) {
|
|
108058
|
+
clearIntervalFn(timer);
|
|
108059
|
+
timer = null;
|
|
108060
|
+
}
|
|
108061
|
+
explicitLabel = null;
|
|
108062
|
+
explicitStartedAt = 0;
|
|
108063
|
+
fallbackActive = false;
|
|
108064
|
+
fallbackStartedAt = 0;
|
|
108065
|
+
lastActivityAt = 0;
|
|
108066
|
+
};
|
|
108067
|
+
return { report, getView, stop };
|
|
108068
|
+
}
|
|
108069
|
+
var ACTIVITY_FRAMES, ACTIVITY_FRAME_INTERVAL_MS, ACTIVITY_FALLBACK_DELAY_MS;
|
|
108070
|
+
var init_activityIndicator = __esm({
|
|
108071
|
+
"packages/cli/tui/activityIndicator.ts"() {
|
|
108072
|
+
"use strict";
|
|
108073
|
+
ACTIVITY_FRAMES = ["\xB7", "~", "\u2248", "\u223F", "\u2248", "~"];
|
|
108074
|
+
ACTIVITY_FRAME_INTERVAL_MS = 150;
|
|
108075
|
+
ACTIVITY_FALLBACK_DELAY_MS = 1200;
|
|
108076
|
+
}
|
|
108077
|
+
});
|
|
108078
|
+
|
|
107297
108079
|
// packages/ai/agent/utils/sortUtils.ts
|
|
107298
108080
|
function sortAgentsFavoriteOwnedPublic(items) {
|
|
107299
108081
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -108051,6 +108833,278 @@ var init_gitStatus = __esm({
|
|
|
108051
108833
|
}
|
|
108052
108834
|
});
|
|
108053
108835
|
|
|
108836
|
+
// packages/cli/tui/tuiAnsi.ts
|
|
108837
|
+
function stripAnsi(text) {
|
|
108838
|
+
return text.replace(OSC_HYPERLINK_REGEX, "").replace(ANSI_ESCAPE_REGEX, "");
|
|
108839
|
+
}
|
|
108840
|
+
function applyTerminalOutputToText(existing, chunk) {
|
|
108841
|
+
if (!chunk) return existing;
|
|
108842
|
+
let text = existing;
|
|
108843
|
+
let index = 0;
|
|
108844
|
+
while (index < chunk.length) {
|
|
108845
|
+
if (chunk[index] === "\x1B") {
|
|
108846
|
+
const sgr = SGR_SEQUENCE_REGEX.exec(chunk.slice(index));
|
|
108847
|
+
if (sgr) {
|
|
108848
|
+
text += sgr[0];
|
|
108849
|
+
index += sgr[0].length;
|
|
108850
|
+
continue;
|
|
108851
|
+
}
|
|
108852
|
+
const osc = chunk.slice(index).match(/^\x1b\]8;;[^\x07\x1b]*(?:\x07|\x1b\\)/);
|
|
108853
|
+
if (osc) {
|
|
108854
|
+
index += osc[0].length;
|
|
108855
|
+
continue;
|
|
108856
|
+
}
|
|
108857
|
+
const csi = chunk.slice(index).match(/^\x1b\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]/);
|
|
108858
|
+
if (csi) {
|
|
108859
|
+
index += csi[0].length;
|
|
108860
|
+
continue;
|
|
108861
|
+
}
|
|
108862
|
+
index += 1;
|
|
108863
|
+
continue;
|
|
108864
|
+
}
|
|
108865
|
+
const ch = chunk[index];
|
|
108866
|
+
if (ch === "\r") {
|
|
108867
|
+
const lastNl = text.lastIndexOf("\n");
|
|
108868
|
+
text = lastNl === -1 ? "" : text.slice(0, lastNl + 1);
|
|
108869
|
+
index += 1;
|
|
108870
|
+
continue;
|
|
108871
|
+
}
|
|
108872
|
+
if (ch === "\n") {
|
|
108873
|
+
text += "\n";
|
|
108874
|
+
index += 1;
|
|
108875
|
+
continue;
|
|
108876
|
+
}
|
|
108877
|
+
if (ch === "\b") {
|
|
108878
|
+
const trailing = TRAILING_SGR_REGEX.exec(text);
|
|
108879
|
+
const sgrTail = trailing ? trailing[0] : "";
|
|
108880
|
+
const head = sgrTail ? text.slice(0, -sgrTail.length) : text;
|
|
108881
|
+
if (head.length > 0 && head[head.length - 1] !== "\n") {
|
|
108882
|
+
text = head.slice(0, -1) + sgrTail;
|
|
108883
|
+
}
|
|
108884
|
+
index += 1;
|
|
108885
|
+
continue;
|
|
108886
|
+
}
|
|
108887
|
+
const code = ch.charCodeAt(0);
|
|
108888
|
+
if (code < 32 && ch !== " " || code === 127) {
|
|
108889
|
+
index += 1;
|
|
108890
|
+
continue;
|
|
108891
|
+
}
|
|
108892
|
+
text += ch;
|
|
108893
|
+
index += 1;
|
|
108894
|
+
}
|
|
108895
|
+
return text;
|
|
108896
|
+
}
|
|
108897
|
+
function displayWidth2(str) {
|
|
108898
|
+
let width = 0;
|
|
108899
|
+
for (const char of str) {
|
|
108900
|
+
const code = char.codePointAt(0) ?? 0;
|
|
108901
|
+
if (code < 32 || code === 127) continue;
|
|
108902
|
+
if (code >= 4352 && code <= 4447 || // 0x2768-0x2775 (ornamental brackets, incl. the ❯ prompt at U+276F)
|
|
108903
|
+
// render narrow in terminals; counting them wide drifts the cursor.
|
|
108904
|
+
code >= 9728 && code <= 10175 && !(code >= 10088 && code <= 10101) || // 0x2B00-0x2BFF (Misc Symbols and Arrows, incl. ⬢ U+2B22 used as the
|
|
108905
|
+
// status-line agent icon) render double-wide in common monospace fonts;
|
|
108906
|
+
// counting ⬢ as width 1 drifts the whole status line right of the icon.
|
|
108907
|
+
code >= 11008 && code <= 11263 || code >= 11904 && code <= 12350 || code >= 12352 && code <= 13247 || code >= 13312 && code <= 19903 || code >= 19968 && code <= 42191 || code >= 44032 && code <= 55203 || code >= 63744 && code <= 64255 || code >= 65072 && code <= 65135 || code >= 65281 && code <= 65376 || code >= 65504 && code <= 65510 || code >= 127744 && code <= 129791 || code >= 131072 && code <= 196605 || code >= 196608 && code <= 262141 || // East Asian Ambiguous CJK quotation marks (U+201C/D “ ”, U+2018/9 ‘ ’).
|
|
108908
|
+
// In CJK locale + CJK fonts these render double-wide like 全角 punctuation;
|
|
108909
|
+
// in English fonts they stay width 1. Follow the active locale so Chinese
|
|
108910
|
+
// replies align correctly without breaking English terminal output.
|
|
108911
|
+
getCliLocale() === "zh" && (code === 8220 || code === 8221 || code === 8216 || code === 8217)) {
|
|
108912
|
+
width += 2;
|
|
108913
|
+
} else {
|
|
108914
|
+
width += 1;
|
|
108915
|
+
}
|
|
108916
|
+
}
|
|
108917
|
+
return width;
|
|
108918
|
+
}
|
|
108919
|
+
function visibleWidth(str) {
|
|
108920
|
+
return displayWidth2(stripAnsi(str));
|
|
108921
|
+
}
|
|
108922
|
+
function truncateAnsi(text, maxWidth) {
|
|
108923
|
+
if (maxWidth <= 0) return "";
|
|
108924
|
+
if (visibleWidth(text) <= maxWidth) return text;
|
|
108925
|
+
let width = 0;
|
|
108926
|
+
let out = "";
|
|
108927
|
+
let i = 0;
|
|
108928
|
+
let sawAnsi = false;
|
|
108929
|
+
while (i < text.length) {
|
|
108930
|
+
if (text[i] === "\x1B" && text[i + 1] === "[") {
|
|
108931
|
+
sawAnsi = true;
|
|
108932
|
+
let j = i + 2;
|
|
108933
|
+
while (j < text.length) {
|
|
108934
|
+
const code = text.charCodeAt(j);
|
|
108935
|
+
j += 1;
|
|
108936
|
+
if (code >= 64 && code <= 126) break;
|
|
108937
|
+
}
|
|
108938
|
+
out += text.slice(i, j);
|
|
108939
|
+
i = j;
|
|
108940
|
+
continue;
|
|
108941
|
+
}
|
|
108942
|
+
const codePoint = text.codePointAt(i) ?? 0;
|
|
108943
|
+
const char = String.fromCodePoint(codePoint);
|
|
108944
|
+
const charWidth = displayWidth2(char);
|
|
108945
|
+
if (width + charWidth > maxWidth) break;
|
|
108946
|
+
out += char;
|
|
108947
|
+
width += charWidth;
|
|
108948
|
+
i += char.length;
|
|
108949
|
+
}
|
|
108950
|
+
return sawAnsi ? `${out}\x1B[0m` : out;
|
|
108951
|
+
}
|
|
108952
|
+
function fitAnsiLine(text, width, ellipsis = "\u2026") {
|
|
108953
|
+
if (width <= 0) return "";
|
|
108954
|
+
if (visibleWidth(text) <= width) return text;
|
|
108955
|
+
const ellipsisWidth = displayWidth2(ellipsis);
|
|
108956
|
+
if (width < ellipsisWidth) return truncateAnsi(text, width);
|
|
108957
|
+
if (width === ellipsisWidth) return truncateAnsi(ellipsis, width) || truncateAnsi(text, width);
|
|
108958
|
+
return `${truncateAnsi(text, width - ellipsisWidth)}${ellipsis}`;
|
|
108959
|
+
}
|
|
108960
|
+
function countPhysicalLines(text, columns) {
|
|
108961
|
+
const lines = text.split("\n");
|
|
108962
|
+
let total = 0;
|
|
108963
|
+
for (const line of lines) {
|
|
108964
|
+
const width = displayWidth2(line);
|
|
108965
|
+
total += Math.max(1, Math.ceil(width / columns));
|
|
108966
|
+
}
|
|
108967
|
+
return Math.max(total, 1);
|
|
108968
|
+
}
|
|
108969
|
+
function takeDisplayWidth(text, width) {
|
|
108970
|
+
let used = 0;
|
|
108971
|
+
let index = 0;
|
|
108972
|
+
for (const char of text) {
|
|
108973
|
+
const charWidth = displayWidth2(char);
|
|
108974
|
+
if (used + charWidth > width && used > 0) break;
|
|
108975
|
+
used += charWidth;
|
|
108976
|
+
index += char.length;
|
|
108977
|
+
}
|
|
108978
|
+
return { prefix: text.slice(0, index), rest: text.slice(index) };
|
|
108979
|
+
}
|
|
108980
|
+
function padOrTruncateToWidth(text, width) {
|
|
108981
|
+
const textWidth = visibleWidth(text);
|
|
108982
|
+
if (textWidth > width) {
|
|
108983
|
+
return truncateAnsi(text, width);
|
|
108984
|
+
}
|
|
108985
|
+
return `${text}${" ".repeat(width - textWidth)}`;
|
|
108986
|
+
}
|
|
108987
|
+
function tokenizeAnsiLine(line) {
|
|
108988
|
+
const tokens = [];
|
|
108989
|
+
let index = 0;
|
|
108990
|
+
while (index < line.length) {
|
|
108991
|
+
if (line[index] === "\x1B") {
|
|
108992
|
+
const osc = line.slice(index).match(/^\x1b\]8;;[^\x07\x1b]*(?:\x07|\x1b\\)/);
|
|
108993
|
+
if (osc) {
|
|
108994
|
+
tokens.push({ kind: "sgr", value: osc[0], width: 0 });
|
|
108995
|
+
index += osc[0].length;
|
|
108996
|
+
continue;
|
|
108997
|
+
}
|
|
108998
|
+
const sgr = SGR_SEQUENCE_REGEX.exec(line.slice(index));
|
|
108999
|
+
if (sgr) {
|
|
109000
|
+
tokens.push({ kind: "sgr", value: sgr[0], width: 0 });
|
|
109001
|
+
index += sgr[0].length;
|
|
109002
|
+
continue;
|
|
109003
|
+
}
|
|
109004
|
+
}
|
|
109005
|
+
const codePoint = line.codePointAt(index) ?? 0;
|
|
109006
|
+
const value = String.fromCodePoint(codePoint);
|
|
109007
|
+
tokens.push({ kind: "char", value, width: displayWidth2(value) });
|
|
109008
|
+
index += value.length;
|
|
109009
|
+
}
|
|
109010
|
+
return tokens;
|
|
109011
|
+
}
|
|
109012
|
+
function wrapTranscriptLine(line, columns) {
|
|
109013
|
+
if (line === "") return [""];
|
|
109014
|
+
const tokens = tokenizeAnsiLine(line);
|
|
109015
|
+
const result = [];
|
|
109016
|
+
let activeStyles = [];
|
|
109017
|
+
const applyStyleToken = (value) => {
|
|
109018
|
+
if (SGR_RESET_REGEX.test(value)) {
|
|
109019
|
+
activeStyles = [];
|
|
109020
|
+
} else {
|
|
109021
|
+
activeStyles.push(value);
|
|
109022
|
+
}
|
|
109023
|
+
};
|
|
109024
|
+
let start = 0;
|
|
109025
|
+
while (start < tokens.length) {
|
|
109026
|
+
if (tokens.slice(start).every((token) => token.kind === "sgr")) {
|
|
109027
|
+
if (result.length > 0) break;
|
|
109028
|
+
}
|
|
109029
|
+
const openingStyles = [...activeStyles];
|
|
109030
|
+
let width = 0;
|
|
109031
|
+
let end = start;
|
|
109032
|
+
let lastBreak = -1;
|
|
109033
|
+
while (end < tokens.length) {
|
|
109034
|
+
const token = tokens[end];
|
|
109035
|
+
if (token.kind === "sgr") {
|
|
109036
|
+
end += 1;
|
|
109037
|
+
continue;
|
|
109038
|
+
}
|
|
109039
|
+
if (width + token.width > columns && width > 0) break;
|
|
109040
|
+
width += token.width;
|
|
109041
|
+
end += 1;
|
|
109042
|
+
if (token.value === " " || token.value === " ") {
|
|
109043
|
+
lastBreak = end;
|
|
109044
|
+
}
|
|
109045
|
+
}
|
|
109046
|
+
let segmentEnd = end;
|
|
109047
|
+
if (end < tokens.length && lastBreak > start) {
|
|
109048
|
+
const overflowToken = tokens[end];
|
|
109049
|
+
if (overflowToken.kind === "char" && overflowToken.value !== " " && overflowToken.width === 1) {
|
|
109050
|
+
segmentEnd = lastBreak;
|
|
109051
|
+
}
|
|
109052
|
+
}
|
|
109053
|
+
if (segmentEnd === start) segmentEnd = start + 1;
|
|
109054
|
+
let segment = "";
|
|
109055
|
+
let sawStyle = openingStyles.length > 0;
|
|
109056
|
+
for (let i = start; i < segmentEnd; i += 1) {
|
|
109057
|
+
const token = tokens[i];
|
|
109058
|
+
segment += token.value;
|
|
109059
|
+
if (token.kind === "sgr") {
|
|
109060
|
+
sawStyle = true;
|
|
109061
|
+
applyStyleToken(token.value);
|
|
109062
|
+
}
|
|
109063
|
+
}
|
|
109064
|
+
const prefix = openingStyles.join("");
|
|
109065
|
+
const needsReset = (sawStyle || activeStyles.length > 0) && !segment.endsWith("\x1B[0m");
|
|
109066
|
+
result.push(`${prefix}${segment}${needsReset ? "\x1B[0m" : ""}`);
|
|
109067
|
+
start = segmentEnd;
|
|
109068
|
+
while (start < tokens.length) {
|
|
109069
|
+
const token = tokens[start];
|
|
109070
|
+
if (token.kind === "char" && token.value === " ") {
|
|
109071
|
+
start += 1;
|
|
109072
|
+
continue;
|
|
109073
|
+
}
|
|
109074
|
+
break;
|
|
109075
|
+
}
|
|
109076
|
+
}
|
|
109077
|
+
return result.length > 0 ? result : [""];
|
|
109078
|
+
}
|
|
109079
|
+
function wrapTextToLines(text, columns) {
|
|
109080
|
+
const result = [];
|
|
109081
|
+
for (const logicalLine of text.split("\n")) {
|
|
109082
|
+
if (logicalLine === "") {
|
|
109083
|
+
result.push("");
|
|
109084
|
+
continue;
|
|
109085
|
+
}
|
|
109086
|
+
let remaining = logicalLine;
|
|
109087
|
+
while (remaining.length > 0) {
|
|
109088
|
+
const { prefix, rest } = takeDisplayWidth(remaining, columns);
|
|
109089
|
+
result.push(prefix);
|
|
109090
|
+
remaining = rest;
|
|
109091
|
+
}
|
|
109092
|
+
}
|
|
109093
|
+
return result;
|
|
109094
|
+
}
|
|
109095
|
+
var ANSI_ESCAPE_REGEX, OSC_HYPERLINK_REGEX, SGR_SEQUENCE_REGEX, TRAILING_SGR_REGEX, SGR_RESET_REGEX;
|
|
109096
|
+
var init_tuiAnsi = __esm({
|
|
109097
|
+
"packages/cli/tui/tuiAnsi.ts"() {
|
|
109098
|
+
"use strict";
|
|
109099
|
+
init_i18n2();
|
|
109100
|
+
ANSI_ESCAPE_REGEX = /\x1b\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]/g;
|
|
109101
|
+
OSC_HYPERLINK_REGEX = /\x1b\]8;;[^\x07\x1b]*(?:\x07|\x1b\\)\x1b\]8;;(?:\x07|\x1b\\)|\x1b\]8;;[^\x07\x1b]*(?:\x07|\x1b\\)/g;
|
|
109102
|
+
SGR_SEQUENCE_REGEX = /^\x1b\[[0-9;]*m/;
|
|
109103
|
+
TRAILING_SGR_REGEX = /(?:\x1b\[[0-9;]*m)+$/;
|
|
109104
|
+
SGR_RESET_REGEX = /^\x1b\[0?m$/;
|
|
109105
|
+
}
|
|
109106
|
+
});
|
|
109107
|
+
|
|
108054
109108
|
// packages/cli/tui/sessionRender.ts
|
|
108055
109109
|
function formatCwd(cwd) {
|
|
108056
109110
|
const parts = cwd.split(/[/\\]/);
|
|
@@ -108080,7 +109134,7 @@ function renderStatusLine(state4) {
|
|
|
108080
109134
|
const sep3 = themeText(" \xB7 ", "chrome", colorEnabled);
|
|
108081
109135
|
const autoRouteActive = state4.agentKey === DEFAULT_TUI_AGENT_KEY && (typeof process === "undefined" || process.env?.NOLO_AUTO_ROUTE !== "0");
|
|
108082
109136
|
const agentDisplayName = autoRouteActive ? "auto" : state4.agentName;
|
|
108083
|
-
const modeSuffix = state4.modeLabel &&
|
|
109137
|
+
const modeSuffix = state4.modeLabel && state4.modeLabel !== "auto" ? ` \xB7 ${state4.modeLabel}` : "";
|
|
108084
109138
|
const agentLabel = `\u{1F3D4} ${agentDisplayName}${modeSuffix}`;
|
|
108085
109139
|
const agentSegment = themeText(agentLabel, "accent", colorEnabled);
|
|
108086
109140
|
const cwdSegment = themeText(`\u{1F4C1} ${formatCwd(state4.cwd)}`, "info", colorEnabled);
|
|
@@ -108168,18 +109222,18 @@ function buildColoredScene(isDark, frame = 0, maxFrames = 0) {
|
|
|
108168
109222
|
` ${pk}\u2581\u2581\u2581\u2581\u2581\u2581\u2571${r} ${tr}\u2660${r} ${tr}\u2660${r} ${pk}\u2572\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581${r}`
|
|
108169
109223
|
].join("\n");
|
|
108170
109224
|
}
|
|
108171
|
-
function renderWelcome(state4, frame = 0, maxFrames = 0) {
|
|
109225
|
+
function renderWelcome(state4, frame = 0, maxFrames = 0, columns) {
|
|
108172
109226
|
const colorEnabled = resolveCliColorEnabled();
|
|
108173
109227
|
const brightness = resolveTuiBrightness();
|
|
108174
109228
|
const isDark = brightness === "dark";
|
|
108175
|
-
|
|
109229
|
+
let sceneArt = colorEnabled ? buildColoredScene(isDark, frame, maxFrames) : buildPlainScene(isDark, frame, maxFrames);
|
|
109230
|
+
if (typeof columns === "number" && columns > 0) {
|
|
109231
|
+
const widestSceneCol = sceneArt.split("\n").reduce((max, line) => Math.max(max, displayWidth2(stripAnsi(line))), 0);
|
|
109232
|
+
if (columns < widestSceneCol) sceneArt = "";
|
|
109233
|
+
}
|
|
108176
109234
|
const versionLine = colorEnabled ? `\x1B[1m${themeColorSequence("accent")}nolo\x1B[0m ${state4.cliVersion ?? ""} | server ${state4.serverUrl}`.replace(" |", " |") : `nolo ${state4.cliVersion ?? ""} | server ${state4.serverUrl}`.replace(" |", " |");
|
|
108177
|
-
|
|
108178
|
-
|
|
108179
|
-
versionLine,
|
|
108180
|
-
t("welcomeHint"),
|
|
108181
|
-
""
|
|
108182
|
-
].join("\n");
|
|
109235
|
+
const body = sceneArt ? [sceneArt, versionLine, t("welcomeHint"), ""] : [versionLine, t("welcomeHint"), ""];
|
|
109236
|
+
return body.join("\n");
|
|
108183
109237
|
}
|
|
108184
109238
|
function renderPrompt(_state) {
|
|
108185
109239
|
return t("promptLabel");
|
|
@@ -108287,6 +109341,7 @@ var init_sessionRender = __esm({
|
|
|
108287
109341
|
init_dialogFrame();
|
|
108288
109342
|
init_i18n2();
|
|
108289
109343
|
init_readlineWorkspace();
|
|
109344
|
+
init_tuiAnsi();
|
|
108290
109345
|
init_theme();
|
|
108291
109346
|
init_processRegistry();
|
|
108292
109347
|
}
|
|
@@ -109422,336 +110477,6 @@ var init_chatQueueTuiBinding = __esm({
|
|
|
109422
110477
|
}
|
|
109423
110478
|
});
|
|
109424
110479
|
|
|
109425
|
-
// packages/cli/tui/tuiAnsi.ts
|
|
109426
|
-
function stripAnsi(text) {
|
|
109427
|
-
return text.replace(OSC_HYPERLINK_REGEX, "").replace(ANSI_ESCAPE_REGEX, "");
|
|
109428
|
-
}
|
|
109429
|
-
function applyTerminalOutputToText(existing, chunk) {
|
|
109430
|
-
if (!chunk) return existing;
|
|
109431
|
-
let text = existing;
|
|
109432
|
-
let index = 0;
|
|
109433
|
-
while (index < chunk.length) {
|
|
109434
|
-
if (chunk[index] === "\x1B") {
|
|
109435
|
-
const sgr = SGR_SEQUENCE_REGEX.exec(chunk.slice(index));
|
|
109436
|
-
if (sgr) {
|
|
109437
|
-
text += sgr[0];
|
|
109438
|
-
index += sgr[0].length;
|
|
109439
|
-
continue;
|
|
109440
|
-
}
|
|
109441
|
-
const osc = chunk.slice(index).match(/^\x1b\]8;;[^\x07\x1b]*(?:\x07|\x1b\\)/);
|
|
109442
|
-
if (osc) {
|
|
109443
|
-
index += osc[0].length;
|
|
109444
|
-
continue;
|
|
109445
|
-
}
|
|
109446
|
-
const csi = chunk.slice(index).match(/^\x1b\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]/);
|
|
109447
|
-
if (csi) {
|
|
109448
|
-
index += csi[0].length;
|
|
109449
|
-
continue;
|
|
109450
|
-
}
|
|
109451
|
-
index += 1;
|
|
109452
|
-
continue;
|
|
109453
|
-
}
|
|
109454
|
-
const ch = chunk[index];
|
|
109455
|
-
if (ch === "\r") {
|
|
109456
|
-
const lastNl = text.lastIndexOf("\n");
|
|
109457
|
-
text = lastNl === -1 ? "" : text.slice(0, lastNl + 1);
|
|
109458
|
-
index += 1;
|
|
109459
|
-
continue;
|
|
109460
|
-
}
|
|
109461
|
-
if (ch === "\n") {
|
|
109462
|
-
text += "\n";
|
|
109463
|
-
index += 1;
|
|
109464
|
-
continue;
|
|
109465
|
-
}
|
|
109466
|
-
if (ch === "\b") {
|
|
109467
|
-
const trailing = TRAILING_SGR_REGEX.exec(text);
|
|
109468
|
-
const sgrTail = trailing ? trailing[0] : "";
|
|
109469
|
-
const head = sgrTail ? text.slice(0, -sgrTail.length) : text;
|
|
109470
|
-
if (head.length > 0 && head[head.length - 1] !== "\n") {
|
|
109471
|
-
text = head.slice(0, -1) + sgrTail;
|
|
109472
|
-
}
|
|
109473
|
-
index += 1;
|
|
109474
|
-
continue;
|
|
109475
|
-
}
|
|
109476
|
-
const code = ch.charCodeAt(0);
|
|
109477
|
-
if (code < 32 && ch !== " " || code === 127) {
|
|
109478
|
-
index += 1;
|
|
109479
|
-
continue;
|
|
109480
|
-
}
|
|
109481
|
-
text += ch;
|
|
109482
|
-
index += 1;
|
|
109483
|
-
}
|
|
109484
|
-
return text;
|
|
109485
|
-
}
|
|
109486
|
-
function displayWidth2(str) {
|
|
109487
|
-
let width = 0;
|
|
109488
|
-
for (const char of str) {
|
|
109489
|
-
const code = char.codePointAt(0) ?? 0;
|
|
109490
|
-
if (code < 32 || code === 127) continue;
|
|
109491
|
-
if (code >= 4352 && code <= 4447 || // 0x2768-0x2775 (ornamental brackets, incl. the ❯ prompt at U+276F)
|
|
109492
|
-
// render narrow in terminals; counting them wide drifts the cursor.
|
|
109493
|
-
code >= 9728 && code <= 10175 && !(code >= 10088 && code <= 10101) || // 0x2B00-0x2BFF (Misc Symbols and Arrows, incl. ⬢ U+2B22 used as the
|
|
109494
|
-
// status-line agent icon) render double-wide in common monospace fonts;
|
|
109495
|
-
// counting ⬢ as width 1 drifts the whole status line right of the icon.
|
|
109496
|
-
code >= 11008 && code <= 11263 || code >= 11904 && code <= 12350 || code >= 12352 && code <= 13247 || code >= 13312 && code <= 19903 || code >= 19968 && code <= 42191 || code >= 44032 && code <= 55203 || code >= 63744 && code <= 64255 || code >= 65072 && code <= 65135 || code >= 65281 && code <= 65376 || code >= 65504 && code <= 65510 || code >= 127744 && code <= 129791 || code >= 131072 && code <= 196605 || code >= 196608 && code <= 262141 || // East Asian Ambiguous CJK quotation marks (U+201C/D “ ”, U+2018/9 ‘ ’).
|
|
109497
|
-
// In CJK locale + CJK fonts these render double-wide like 全角 punctuation;
|
|
109498
|
-
// in English fonts they stay width 1. Follow the active locale so Chinese
|
|
109499
|
-
// replies align correctly without breaking English terminal output.
|
|
109500
|
-
getCliLocale() === "zh" && (code === 8220 || code === 8221 || code === 8216 || code === 8217)) {
|
|
109501
|
-
width += 2;
|
|
109502
|
-
} else {
|
|
109503
|
-
width += 1;
|
|
109504
|
-
}
|
|
109505
|
-
}
|
|
109506
|
-
return width;
|
|
109507
|
-
}
|
|
109508
|
-
function visibleWidth(str) {
|
|
109509
|
-
return displayWidth2(stripAnsi(str));
|
|
109510
|
-
}
|
|
109511
|
-
function truncateAnsi(text, maxWidth) {
|
|
109512
|
-
if (maxWidth <= 0) return "";
|
|
109513
|
-
if (visibleWidth(text) <= maxWidth) return text;
|
|
109514
|
-
let width = 0;
|
|
109515
|
-
let out = "";
|
|
109516
|
-
let i = 0;
|
|
109517
|
-
let sawAnsi = false;
|
|
109518
|
-
while (i < text.length) {
|
|
109519
|
-
if (text[i] === "\x1B" && text[i + 1] === "[") {
|
|
109520
|
-
sawAnsi = true;
|
|
109521
|
-
let j = i + 2;
|
|
109522
|
-
while (j < text.length) {
|
|
109523
|
-
const code = text.charCodeAt(j);
|
|
109524
|
-
j += 1;
|
|
109525
|
-
if (code >= 64 && code <= 126) break;
|
|
109526
|
-
}
|
|
109527
|
-
out += text.slice(i, j);
|
|
109528
|
-
i = j;
|
|
109529
|
-
continue;
|
|
109530
|
-
}
|
|
109531
|
-
const codePoint = text.codePointAt(i) ?? 0;
|
|
109532
|
-
const char = String.fromCodePoint(codePoint);
|
|
109533
|
-
const charWidth = displayWidth2(char);
|
|
109534
|
-
if (width + charWidth > maxWidth) break;
|
|
109535
|
-
out += char;
|
|
109536
|
-
width += charWidth;
|
|
109537
|
-
i += char.length;
|
|
109538
|
-
}
|
|
109539
|
-
return sawAnsi ? `${out}\x1B[0m` : out;
|
|
109540
|
-
}
|
|
109541
|
-
function fitAnsiLine(text, width, ellipsis = "\u2026") {
|
|
109542
|
-
if (width <= 0) return "";
|
|
109543
|
-
if (visibleWidth(text) <= width) return text;
|
|
109544
|
-
const ellipsisWidth = displayWidth2(ellipsis);
|
|
109545
|
-
if (width < ellipsisWidth) return truncateAnsi(text, width);
|
|
109546
|
-
if (width === ellipsisWidth) return truncateAnsi(ellipsis, width) || truncateAnsi(text, width);
|
|
109547
|
-
return `${truncateAnsi(text, width - ellipsisWidth)}${ellipsis}`;
|
|
109548
|
-
}
|
|
109549
|
-
function countPhysicalLines(text, columns) {
|
|
109550
|
-
const lines = text.split("\n");
|
|
109551
|
-
let total = 0;
|
|
109552
|
-
for (const line of lines) {
|
|
109553
|
-
const width = displayWidth2(line);
|
|
109554
|
-
total += Math.max(1, Math.ceil(width / columns));
|
|
109555
|
-
}
|
|
109556
|
-
return Math.max(total, 1);
|
|
109557
|
-
}
|
|
109558
|
-
function takeDisplayWidth(text, width) {
|
|
109559
|
-
let used = 0;
|
|
109560
|
-
let index = 0;
|
|
109561
|
-
for (const char of text) {
|
|
109562
|
-
const charWidth = displayWidth2(char);
|
|
109563
|
-
if (used + charWidth > width && used > 0) break;
|
|
109564
|
-
used += charWidth;
|
|
109565
|
-
index += char.length;
|
|
109566
|
-
}
|
|
109567
|
-
return { prefix: text.slice(0, index), rest: text.slice(index) };
|
|
109568
|
-
}
|
|
109569
|
-
function padOrTruncateToWidth(text, width) {
|
|
109570
|
-
const textWidth = visibleWidth(text);
|
|
109571
|
-
if (textWidth > width) {
|
|
109572
|
-
return truncateAnsi(text, width);
|
|
109573
|
-
}
|
|
109574
|
-
return `${text}${" ".repeat(width - textWidth)}`;
|
|
109575
|
-
}
|
|
109576
|
-
function tokenizeAnsiLine(line) {
|
|
109577
|
-
const tokens = [];
|
|
109578
|
-
let index = 0;
|
|
109579
|
-
while (index < line.length) {
|
|
109580
|
-
if (line[index] === "\x1B") {
|
|
109581
|
-
const osc = line.slice(index).match(/^\x1b\]8;;[^\x07\x1b]*(?:\x07|\x1b\\)/);
|
|
109582
|
-
if (osc) {
|
|
109583
|
-
tokens.push({ kind: "sgr", value: osc[0], width: 0 });
|
|
109584
|
-
index += osc[0].length;
|
|
109585
|
-
continue;
|
|
109586
|
-
}
|
|
109587
|
-
const sgr = SGR_SEQUENCE_REGEX.exec(line.slice(index));
|
|
109588
|
-
if (sgr) {
|
|
109589
|
-
tokens.push({ kind: "sgr", value: sgr[0], width: 0 });
|
|
109590
|
-
index += sgr[0].length;
|
|
109591
|
-
continue;
|
|
109592
|
-
}
|
|
109593
|
-
}
|
|
109594
|
-
const codePoint = line.codePointAt(index) ?? 0;
|
|
109595
|
-
const value = String.fromCodePoint(codePoint);
|
|
109596
|
-
tokens.push({ kind: "char", value, width: displayWidth2(value) });
|
|
109597
|
-
index += value.length;
|
|
109598
|
-
}
|
|
109599
|
-
return tokens;
|
|
109600
|
-
}
|
|
109601
|
-
function wrapTranscriptLine(line, columns) {
|
|
109602
|
-
if (line === "") return [""];
|
|
109603
|
-
const tokens = tokenizeAnsiLine(line);
|
|
109604
|
-
const result = [];
|
|
109605
|
-
let activeStyles = [];
|
|
109606
|
-
const applyStyleToken = (value) => {
|
|
109607
|
-
if (SGR_RESET_REGEX.test(value)) {
|
|
109608
|
-
activeStyles = [];
|
|
109609
|
-
} else {
|
|
109610
|
-
activeStyles.push(value);
|
|
109611
|
-
}
|
|
109612
|
-
};
|
|
109613
|
-
let start = 0;
|
|
109614
|
-
while (start < tokens.length) {
|
|
109615
|
-
if (tokens.slice(start).every((token) => token.kind === "sgr")) {
|
|
109616
|
-
if (result.length > 0) break;
|
|
109617
|
-
}
|
|
109618
|
-
const openingStyles = [...activeStyles];
|
|
109619
|
-
let width = 0;
|
|
109620
|
-
let end = start;
|
|
109621
|
-
let lastBreak = -1;
|
|
109622
|
-
while (end < tokens.length) {
|
|
109623
|
-
const token = tokens[end];
|
|
109624
|
-
if (token.kind === "sgr") {
|
|
109625
|
-
end += 1;
|
|
109626
|
-
continue;
|
|
109627
|
-
}
|
|
109628
|
-
if (width + token.width > columns && width > 0) break;
|
|
109629
|
-
width += token.width;
|
|
109630
|
-
end += 1;
|
|
109631
|
-
if (token.value === " " || token.value === " ") {
|
|
109632
|
-
lastBreak = end;
|
|
109633
|
-
}
|
|
109634
|
-
}
|
|
109635
|
-
let segmentEnd = end;
|
|
109636
|
-
if (end < tokens.length && lastBreak > start) {
|
|
109637
|
-
const overflowToken = tokens[end];
|
|
109638
|
-
if (overflowToken.kind === "char" && overflowToken.value !== " " && overflowToken.width === 1) {
|
|
109639
|
-
segmentEnd = lastBreak;
|
|
109640
|
-
}
|
|
109641
|
-
}
|
|
109642
|
-
if (segmentEnd === start) segmentEnd = start + 1;
|
|
109643
|
-
let segment = "";
|
|
109644
|
-
let sawStyle = openingStyles.length > 0;
|
|
109645
|
-
for (let i = start; i < segmentEnd; i += 1) {
|
|
109646
|
-
const token = tokens[i];
|
|
109647
|
-
segment += token.value;
|
|
109648
|
-
if (token.kind === "sgr") {
|
|
109649
|
-
sawStyle = true;
|
|
109650
|
-
applyStyleToken(token.value);
|
|
109651
|
-
}
|
|
109652
|
-
}
|
|
109653
|
-
const prefix = openingStyles.join("");
|
|
109654
|
-
const needsReset = (sawStyle || activeStyles.length > 0) && !segment.endsWith("\x1B[0m");
|
|
109655
|
-
result.push(`${prefix}${segment}${needsReset ? "\x1B[0m" : ""}`);
|
|
109656
|
-
start = segmentEnd;
|
|
109657
|
-
while (start < tokens.length) {
|
|
109658
|
-
const token = tokens[start];
|
|
109659
|
-
if (token.kind === "char" && token.value === " ") {
|
|
109660
|
-
start += 1;
|
|
109661
|
-
continue;
|
|
109662
|
-
}
|
|
109663
|
-
break;
|
|
109664
|
-
}
|
|
109665
|
-
}
|
|
109666
|
-
return result.length > 0 ? result : [""];
|
|
109667
|
-
}
|
|
109668
|
-
function wrapTextToLines(text, columns) {
|
|
109669
|
-
const result = [];
|
|
109670
|
-
for (const logicalLine of text.split("\n")) {
|
|
109671
|
-
if (logicalLine === "") {
|
|
109672
|
-
result.push("");
|
|
109673
|
-
continue;
|
|
109674
|
-
}
|
|
109675
|
-
let remaining = logicalLine;
|
|
109676
|
-
while (remaining.length > 0) {
|
|
109677
|
-
const { prefix, rest } = takeDisplayWidth(remaining, columns);
|
|
109678
|
-
result.push(prefix);
|
|
109679
|
-
remaining = rest;
|
|
109680
|
-
}
|
|
109681
|
-
}
|
|
109682
|
-
return result;
|
|
109683
|
-
}
|
|
109684
|
-
var ANSI_ESCAPE_REGEX, OSC_HYPERLINK_REGEX, SGR_SEQUENCE_REGEX, TRAILING_SGR_REGEX, SGR_RESET_REGEX;
|
|
109685
|
-
var init_tuiAnsi = __esm({
|
|
109686
|
-
"packages/cli/tui/tuiAnsi.ts"() {
|
|
109687
|
-
"use strict";
|
|
109688
|
-
init_i18n2();
|
|
109689
|
-
ANSI_ESCAPE_REGEX = /\x1b\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]/g;
|
|
109690
|
-
OSC_HYPERLINK_REGEX = /\x1b\]8;;[^\x07\x1b]*(?:\x07|\x1b\\)\x1b\]8;;(?:\x07|\x1b\\)|\x1b\]8;;[^\x07\x1b]*(?:\x07|\x1b\\)/g;
|
|
109691
|
-
SGR_SEQUENCE_REGEX = /^\x1b\[[0-9;]*m/;
|
|
109692
|
-
TRAILING_SGR_REGEX = /(?:\x1b\[[0-9;]*m)+$/;
|
|
109693
|
-
SGR_RESET_REGEX = /^\x1b\[0?m$/;
|
|
109694
|
-
}
|
|
109695
|
-
});
|
|
109696
|
-
|
|
109697
|
-
// packages/cli/tui/tuiScrollbar.ts
|
|
109698
|
-
function parseScrollAction(sequence) {
|
|
109699
|
-
const mouse = SGR_MOUSE_REGEX.exec(sequence);
|
|
109700
|
-
if (mouse) {
|
|
109701
|
-
const button = Number(mouse[1]);
|
|
109702
|
-
if ((button & 64) === 0) return null;
|
|
109703
|
-
if ((button & 2) !== 0) return null;
|
|
109704
|
-
return (button & 1) !== 0 ? "wheel-down" : "wheel-up";
|
|
109705
|
-
}
|
|
109706
|
-
switch (sequence) {
|
|
109707
|
-
case "\x1B[5~":
|
|
109708
|
-
return "page-up";
|
|
109709
|
-
case "\x1B[6~":
|
|
109710
|
-
return "page-down";
|
|
109711
|
-
case "\x1B[5;2~":
|
|
109712
|
-
case "\x1B[5;5~":
|
|
109713
|
-
return "half-page-up";
|
|
109714
|
-
case "\x1B[6;2~":
|
|
109715
|
-
case "\x1B[6;5~":
|
|
109716
|
-
return "half-page-down";
|
|
109717
|
-
case "\x1B[H":
|
|
109718
|
-
case "\x1B[1~":
|
|
109719
|
-
case "\x1B[7~":
|
|
109720
|
-
return "top";
|
|
109721
|
-
case "\x1B[F":
|
|
109722
|
-
case "\x1B[4~":
|
|
109723
|
-
case "\x1B[8~":
|
|
109724
|
-
return "bottom";
|
|
109725
|
-
default:
|
|
109726
|
-
return null;
|
|
109727
|
-
}
|
|
109728
|
-
}
|
|
109729
|
-
function renderScrollbarRow(rowIndex, visibleHeight, totalLines, scrollTop) {
|
|
109730
|
-
if (totalLines <= visibleHeight) return " ";
|
|
109731
|
-
const trackHeight = visibleHeight;
|
|
109732
|
-
const thumbSize = Math.max(
|
|
109733
|
-
1,
|
|
109734
|
-
Math.floor(visibleHeight * visibleHeight / totalLines)
|
|
109735
|
-
);
|
|
109736
|
-
const maxScrollTop = totalLines - visibleHeight;
|
|
109737
|
-
const thumbTop = Math.floor(
|
|
109738
|
-
scrollTop / maxScrollTop * (trackHeight - thumbSize)
|
|
109739
|
-
);
|
|
109740
|
-
const thumbBottom = thumbTop + thumbSize;
|
|
109741
|
-
if (rowIndex >= thumbTop && rowIndex < thumbBottom) {
|
|
109742
|
-
return "\u2588";
|
|
109743
|
-
}
|
|
109744
|
-
return "\u2502";
|
|
109745
|
-
}
|
|
109746
|
-
var SGR_MOUSE_REGEX, WHEEL_SCROLL_LINES;
|
|
109747
|
-
var init_tuiScrollbar = __esm({
|
|
109748
|
-
"packages/cli/tui/tuiScrollbar.ts"() {
|
|
109749
|
-
"use strict";
|
|
109750
|
-
SGR_MOUSE_REGEX = /^\x1b\[<(\d+);\d+;\d+[Mm]$/;
|
|
109751
|
-
WHEEL_SCROLL_LINES = 3;
|
|
109752
|
-
}
|
|
109753
|
-
});
|
|
109754
|
-
|
|
109755
110480
|
// packages/cli/tui/tuiHistory.ts
|
|
109756
110481
|
function createTurnHistory() {
|
|
109757
110482
|
return {
|
|
@@ -110664,58 +111389,27 @@ async function startTuiWorkspace(options) {
|
|
|
110664
111389
|
stdout: output2
|
|
110665
111390
|
});
|
|
110666
111391
|
if (detected) setActiveBrightness(detected);
|
|
110667
|
-
const
|
|
110668
|
-
output2.write(
|
|
110669
|
-
for (let i = 0; i < frames; i++) {
|
|
110670
|
-
output2.write(renderWelcome(state4, i, frames));
|
|
110671
|
-
if (i < frames - 1) {
|
|
110672
|
-
await new Promise((resolve9) => setTimeout(resolve9, 100));
|
|
110673
|
-
output2.write("\r\x1B[8A\x1B[0J");
|
|
110674
|
-
}
|
|
110675
|
-
}
|
|
110676
|
-
output2.write("\x1B[?25h");
|
|
111392
|
+
const bannerColumns = output2.columns;
|
|
111393
|
+
output2.write(renderWelcome(state4, 0, 0, bannerColumns));
|
|
110677
111394
|
let fixedInput = createNoopFixedInput();
|
|
110678
111395
|
let buffer = "";
|
|
110679
111396
|
let cursorPos = 0;
|
|
110680
111397
|
let activeTurnAbort = null;
|
|
110681
|
-
|
|
110682
|
-
|
|
110683
|
-
|
|
110684
|
-
|
|
110685
|
-
const stopActivity = () => {
|
|
110686
|
-
if (activityTimer !== null) {
|
|
110687
|
-
clearInterval(activityTimer);
|
|
110688
|
-
activityTimer = null;
|
|
110689
|
-
}
|
|
110690
|
-
activityLabel = null;
|
|
110691
|
-
activityStartedAt = 0;
|
|
110692
|
-
};
|
|
110693
|
-
const activityReporter = (label) => {
|
|
110694
|
-
if (label !== null) {
|
|
110695
|
-
activityLabel = label;
|
|
110696
|
-
if (activityStartedAt === 0) {
|
|
110697
|
-
activityStartedAt = Date.now();
|
|
110698
|
-
}
|
|
110699
|
-
if (activityTimer === null) {
|
|
110700
|
-
activityTimer = setInterval(() => {
|
|
110701
|
-
activityFrameIndex += 1;
|
|
110702
|
-
if (fixedInput.active && !fixedInput.isPaused()) {
|
|
110703
|
-
output2.write("\x1B[?2026h\x1B[?25l");
|
|
110704
|
-
try {
|
|
110705
|
-
fixedInput.repaint(buffer);
|
|
110706
|
-
} finally {
|
|
110707
|
-
output2.write("\x1B[?25h\x1B[?2026l");
|
|
110708
|
-
}
|
|
110709
|
-
}
|
|
110710
|
-
}, 150);
|
|
110711
|
-
}
|
|
110712
|
-
} else {
|
|
110713
|
-
stopActivity();
|
|
111398
|
+
const activityIndicator = createActivityIndicator({
|
|
111399
|
+
isTurnActive: () => activeTurnAbort !== null,
|
|
111400
|
+
fallbackLabel: () => `${state4.agentName} -> working`,
|
|
111401
|
+
onRepaint: () => {
|
|
110714
111402
|
if (fixedInput.active && !fixedInput.isPaused()) {
|
|
110715
|
-
|
|
111403
|
+
output2.write("\x1B[?2026h\x1B[?25l");
|
|
111404
|
+
try {
|
|
111405
|
+
fixedInput.repaint(buffer);
|
|
111406
|
+
} finally {
|
|
111407
|
+
output2.write("\x1B[?25h\x1B[?2026l");
|
|
111408
|
+
}
|
|
110716
111409
|
}
|
|
110717
111410
|
}
|
|
110718
|
-
};
|
|
111411
|
+
});
|
|
111412
|
+
const activityReporter = (label) => activityIndicator.report(label);
|
|
110719
111413
|
let explicitAgentSwitch = false;
|
|
110720
111414
|
let copyViewExitResolver = null;
|
|
110721
111415
|
const history = createTurnHistory();
|
|
@@ -110814,25 +111508,15 @@ ${t("copyViewHint")}
|
|
|
110814
111508
|
scheduleRender();
|
|
110815
111509
|
}) : output2;
|
|
110816
111510
|
const requestUserChoice = isInteractiveInput(input2) && dialogHost ? async (req) => {
|
|
110817
|
-
const items = req.choices.map((c) => ({
|
|
110818
|
-
label: c.label
|
|
110819
|
-
}));
|
|
110820
111511
|
try {
|
|
110821
|
-
|
|
110822
|
-
(anchor) =>
|
|
110823
|
-
|
|
110824
|
-
title: req.question,
|
|
111512
|
+
return await dialogHost.run(
|
|
111513
|
+
(anchor) => runAskChoiceDialog({
|
|
111514
|
+
request: req,
|
|
110825
111515
|
input: input2,
|
|
110826
111516
|
output: output2,
|
|
110827
111517
|
...anchor
|
|
110828
111518
|
})
|
|
110829
111519
|
);
|
|
110830
|
-
if (pickResult.kind === "selected") {
|
|
110831
|
-
const choice = req.choices[pickResult.index];
|
|
110832
|
-
const userMessage = choice?.userMessage?.trim() || choice?.label || "";
|
|
110833
|
-
return { kind: "selected", userMessage, label: choice?.label ?? "" };
|
|
110834
|
-
}
|
|
110835
|
-
return { kind: "cancelled" };
|
|
110836
111520
|
} catch {
|
|
110837
111521
|
return { kind: "cancelled" };
|
|
110838
111522
|
}
|
|
@@ -110885,7 +111569,7 @@ ${t("copyViewHint")}
|
|
|
110885
111569
|
}
|
|
110886
111570
|
return { ok: !wasAborted, aborted: wasAborted };
|
|
110887
111571
|
} finally {
|
|
110888
|
-
|
|
111572
|
+
activityIndicator.stop();
|
|
110889
111573
|
activeTurnAbort = null;
|
|
110890
111574
|
explicitAgentSwitch = false;
|
|
110891
111575
|
}
|
|
@@ -111244,17 +111928,15 @@ ${err.message}` : ""}`
|
|
|
111244
111928
|
return base;
|
|
111245
111929
|
},
|
|
111246
111930
|
getActivityLine: () => {
|
|
111247
|
-
|
|
111931
|
+
const view = activityIndicator.getView();
|
|
111932
|
+
if (view === null) return null;
|
|
111248
111933
|
const colorEnabled = resolveCliColorEnabled();
|
|
111249
|
-
const
|
|
111250
|
-
const frame = FRAMES[activityFrameIndex % FRAMES.length];
|
|
111251
|
-
const elapsedSec = activityStartedAt > 0 ? Math.max(0, Math.floor((Date.now() - activityStartedAt) / 1e3)) : 0;
|
|
111252
|
-
const elapsed = formatElapsedSeconds(elapsedSec);
|
|
111934
|
+
const elapsed = formatElapsedSeconds(view.elapsedSec);
|
|
111253
111935
|
const stopHint = t("stopHint");
|
|
111254
111936
|
if (!colorEnabled) {
|
|
111255
|
-
return `${frame} ${
|
|
111937
|
+
return `${view.frame} ${view.label} (${elapsed}) \xB7 ${stopHint}`;
|
|
111256
111938
|
}
|
|
111257
|
-
return themeText(frame, "accent") + " " + themeText(
|
|
111939
|
+
return themeText(view.frame, "accent") + " " + themeText(view.label, "muted") + themeText(` (${elapsed})`, "chrome") + themeText(` \xB7 ${stopHint}`, "chrome");
|
|
111258
111940
|
},
|
|
111259
111941
|
getQueueLines: () => {
|
|
111260
111942
|
if (!chatQueueBinding || chatQueueBinding.queueLength() === 0) return [];
|
|
@@ -111343,12 +112025,27 @@ ${err.message}` : ""}`
|
|
|
111343
112025
|
if (busyLock) {
|
|
111344
112026
|
const submittedText2 = result.submit;
|
|
111345
112027
|
const trimmedText = submittedText2.trim();
|
|
111346
|
-
|
|
112028
|
+
const busySlashCommand = trimmedText.split(/\s+/)[0]?.toLowerCase();
|
|
112029
|
+
const isBusyLocalSlash = busySlashCommand === "/context" || busySlashCommand === "/ctx" || busySlashCommand === "/switch";
|
|
112030
|
+
if (isBusyLocalSlash) {
|
|
112031
|
+
const beforeAgentKey = state4.agentKey;
|
|
111347
112032
|
const res = handleTuiInput(submittedText2, state4);
|
|
111348
|
-
|
|
111349
|
-
|
|
111350
|
-
|
|
112033
|
+
if (res.action) {
|
|
112034
|
+
output2.write(
|
|
112035
|
+
"Model picker isn't available while a reply is running. Use `/switch <name>` to switch now (takes effect on the next turn), or wait for the reply to finish.\n"
|
|
112036
|
+
);
|
|
112037
|
+
} else {
|
|
112038
|
+
state4 = res.nextState;
|
|
112039
|
+
let msg = res.output;
|
|
112040
|
+
if (busySlashCommand === "/switch" && res.nextState.agentKey !== beforeAgentKey) {
|
|
112041
|
+
const hint = "Note: the new model takes effect on the next turn. Switching models may consume more tokens because the conversation context is re-sent to the new model.";
|
|
112042
|
+
msg = msg ? `${msg}
|
|
112043
|
+
${hint}` : hint;
|
|
112044
|
+
}
|
|
112045
|
+
if (msg) {
|
|
112046
|
+
output2.write(`${msg}
|
|
111351
112047
|
`);
|
|
112048
|
+
}
|
|
111352
112049
|
}
|
|
111353
112050
|
buffer = "";
|
|
111354
112051
|
cursorPos2 = 0;
|
|
@@ -111571,8 +112268,9 @@ var init_readlineWorkspace = __esm({
|
|
|
111571
112268
|
init_updateCommands();
|
|
111572
112269
|
init_processSpawn();
|
|
111573
112270
|
init_confirmDialog();
|
|
111574
|
-
|
|
112271
|
+
init_askChoiceDialog();
|
|
111575
112272
|
init_dialogHost();
|
|
112273
|
+
init_activityIndicator();
|
|
111576
112274
|
init_agentPicker();
|
|
111577
112275
|
init_agentCatalog();
|
|
111578
112276
|
init_dialogPicker();
|