nolo-cli 0.6.1 → 0.8.0-alpha.2
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 +1089 -385
- 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
|
}
|
|
@@ -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,15 @@ 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";
|
|
106919
107039
|
}
|
|
106920
107040
|
});
|
|
106921
107041
|
|
|
@@ -107257,6 +107377,496 @@ var init_confirmDialog = __esm({
|
|
|
107257
107377
|
}
|
|
107258
107378
|
});
|
|
107259
107379
|
|
|
107380
|
+
// packages/ai/tools/askChoiceState.ts
|
|
107381
|
+
function normalizeAskChoiceArgs(args2) {
|
|
107382
|
+
const blocking = args2.blocking !== false;
|
|
107383
|
+
if (Array.isArray(args2.questions) && args2.questions.length > 0) {
|
|
107384
|
+
return {
|
|
107385
|
+
questions: args2.questions.map(
|
|
107386
|
+
(q, i) => normalizeQuestion(q, i)
|
|
107387
|
+
),
|
|
107388
|
+
blocking
|
|
107389
|
+
};
|
|
107390
|
+
}
|
|
107391
|
+
const question = String(args2.question ?? "").trim();
|
|
107392
|
+
const choices = Array.isArray(args2.choices) ? args2.choices : [];
|
|
107393
|
+
if (!question || choices.length === 0) {
|
|
107394
|
+
return { questions: [], blocking };
|
|
107395
|
+
}
|
|
107396
|
+
return {
|
|
107397
|
+
questions: [
|
|
107398
|
+
normalizeQuestion(
|
|
107399
|
+
{ question, choices, multiSelect: false, allowOther: true, required: true },
|
|
107400
|
+
0
|
|
107401
|
+
)
|
|
107402
|
+
],
|
|
107403
|
+
blocking
|
|
107404
|
+
};
|
|
107405
|
+
}
|
|
107406
|
+
function normalizeQuestion(raw, index) {
|
|
107407
|
+
return {
|
|
107408
|
+
id: String(raw?.id ?? `q${index}`),
|
|
107409
|
+
question: String(raw?.question ?? "").trim(),
|
|
107410
|
+
choices: (Array.isArray(raw?.choices) ? raw.choices : []).map(
|
|
107411
|
+
(c, ci) => ({
|
|
107412
|
+
id: String(c?.id ?? `c${ci}`),
|
|
107413
|
+
label: String(c?.label ?? "").trim(),
|
|
107414
|
+
...typeof c?.detail === "string" && c.detail.trim() ? { detail: c.detail.trim() } : {},
|
|
107415
|
+
...typeof c?.userMessage === "string" && c.userMessage.trim() ? { userMessage: c.userMessage.trim() } : {}
|
|
107416
|
+
})
|
|
107417
|
+
),
|
|
107418
|
+
multiSelect: raw?.multiSelect === true,
|
|
107419
|
+
allowOther: raw?.allowOther !== false,
|
|
107420
|
+
required: raw?.required !== false
|
|
107421
|
+
};
|
|
107422
|
+
}
|
|
107423
|
+
function createInitialAskChoiceState(questions) {
|
|
107424
|
+
return {
|
|
107425
|
+
questions,
|
|
107426
|
+
activeIndex: 0,
|
|
107427
|
+
questionStates: questions.map(() => ({
|
|
107428
|
+
cursorIndex: 0,
|
|
107429
|
+
selectedIds: [],
|
|
107430
|
+
pickedId: null,
|
|
107431
|
+
otherText: "",
|
|
107432
|
+
otherFocused: false
|
|
107433
|
+
})),
|
|
107434
|
+
phase: "active"
|
|
107435
|
+
};
|
|
107436
|
+
}
|
|
107437
|
+
function askChoiceReducer(state4, action3) {
|
|
107438
|
+
if (state4.phase !== "active") return state4;
|
|
107439
|
+
switch (action3.type) {
|
|
107440
|
+
case "CANCEL":
|
|
107441
|
+
return { ...state4, phase: "cancelled" };
|
|
107442
|
+
case "SUBMIT": {
|
|
107443
|
+
if (!canSubmit(state4)) return state4;
|
|
107444
|
+
return { ...state4, phase: "submitted" };
|
|
107445
|
+
}
|
|
107446
|
+
case "SWITCH_TAB": {
|
|
107447
|
+
const idx = clamp3(action3.index, 0, state4.questions.length - 1);
|
|
107448
|
+
return { ...state4, activeIndex: idx };
|
|
107449
|
+
}
|
|
107450
|
+
case "NEXT_TAB": {
|
|
107451
|
+
const idx = Math.min(state4.activeIndex + 1, state4.questions.length - 1);
|
|
107452
|
+
return { ...state4, activeIndex: idx };
|
|
107453
|
+
}
|
|
107454
|
+
case "PREV_TAB": {
|
|
107455
|
+
const idx = Math.max(state4.activeIndex - 1, 0);
|
|
107456
|
+
return { ...state4, activeIndex: idx };
|
|
107457
|
+
}
|
|
107458
|
+
case "MOVE_CURSOR": {
|
|
107459
|
+
const qs = state4.questionStates[state4.activeIndex];
|
|
107460
|
+
const q = state4.questions[state4.activeIndex];
|
|
107461
|
+
const maxIndex = q.allowOther ? q.choices.length : q.choices.length - 1;
|
|
107462
|
+
const next = clamp3(qs.cursorIndex + action3.delta, 0, maxIndex);
|
|
107463
|
+
const newQs = [...state4.questionStates];
|
|
107464
|
+
newQs[state4.activeIndex] = {
|
|
107465
|
+
...qs,
|
|
107466
|
+
cursorIndex: next,
|
|
107467
|
+
otherFocused: false
|
|
107468
|
+
};
|
|
107469
|
+
return { ...state4, questionStates: newQs };
|
|
107470
|
+
}
|
|
107471
|
+
case "TOGGLE_AT_CURSOR": {
|
|
107472
|
+
const qs = state4.questionStates[state4.activeIndex];
|
|
107473
|
+
const q = state4.questions[state4.activeIndex];
|
|
107474
|
+
if (!q.multiSelect) return state4;
|
|
107475
|
+
const isOtherRow = qs.cursorIndex >= q.choices.length;
|
|
107476
|
+
if (isOtherRow) {
|
|
107477
|
+
const newQs2 = [...state4.questionStates];
|
|
107478
|
+
newQs2[state4.activeIndex] = { ...qs, otherFocused: !qs.otherFocused };
|
|
107479
|
+
return { ...state4, questionStates: newQs2 };
|
|
107480
|
+
}
|
|
107481
|
+
const choiceId = q.choices[qs.cursorIndex]?.id;
|
|
107482
|
+
if (!choiceId) return state4;
|
|
107483
|
+
const has = qs.selectedIds.includes(choiceId);
|
|
107484
|
+
const newSelected = has ? qs.selectedIds.filter((id) => id !== choiceId) : [...qs.selectedIds, choiceId];
|
|
107485
|
+
const newQs = [...state4.questionStates];
|
|
107486
|
+
newQs[state4.activeIndex] = { ...qs, selectedIds: newSelected };
|
|
107487
|
+
return { ...state4, questionStates: newQs };
|
|
107488
|
+
}
|
|
107489
|
+
case "SELECT_AT_CURSOR": {
|
|
107490
|
+
const qs = state4.questionStates[state4.activeIndex];
|
|
107491
|
+
const q = state4.questions[state4.activeIndex];
|
|
107492
|
+
const isOtherRow = qs.cursorIndex >= q.choices.length;
|
|
107493
|
+
if (isOtherRow) {
|
|
107494
|
+
const newQs2 = [...state4.questionStates];
|
|
107495
|
+
newQs2[state4.activeIndex] = { ...qs, otherFocused: true };
|
|
107496
|
+
return { ...state4, questionStates: newQs2 };
|
|
107497
|
+
}
|
|
107498
|
+
const choiceId = q.choices[qs.cursorIndex]?.id;
|
|
107499
|
+
if (!choiceId) return state4;
|
|
107500
|
+
if (q.multiSelect) {
|
|
107501
|
+
const has = qs.selectedIds.includes(choiceId);
|
|
107502
|
+
const newSelected = has ? qs.selectedIds.filter((id) => id !== choiceId) : [...qs.selectedIds, choiceId];
|
|
107503
|
+
const newQs2 = [...state4.questionStates];
|
|
107504
|
+
newQs2[state4.activeIndex] = { ...qs, selectedIds: newSelected };
|
|
107505
|
+
return { ...state4, questionStates: newQs2 };
|
|
107506
|
+
}
|
|
107507
|
+
const newQs = [...state4.questionStates];
|
|
107508
|
+
newQs[state4.activeIndex] = { ...qs, pickedId: choiceId, otherFocused: false };
|
|
107509
|
+
if (state4.questions.length === 1) {
|
|
107510
|
+
return {
|
|
107511
|
+
...state4,
|
|
107512
|
+
questionStates: newQs,
|
|
107513
|
+
phase: "submitted"
|
|
107514
|
+
};
|
|
107515
|
+
}
|
|
107516
|
+
const nextTab = Math.min(
|
|
107517
|
+
state4.activeIndex + 1,
|
|
107518
|
+
state4.questions.length - 1
|
|
107519
|
+
);
|
|
107520
|
+
return {
|
|
107521
|
+
...state4,
|
|
107522
|
+
questionStates: newQs,
|
|
107523
|
+
activeIndex: nextTab
|
|
107524
|
+
};
|
|
107525
|
+
}
|
|
107526
|
+
case "FOCUS_OTHER": {
|
|
107527
|
+
const qs = state4.questionStates[state4.activeIndex];
|
|
107528
|
+
const newQs = [...state4.questionStates];
|
|
107529
|
+
newQs[state4.activeIndex] = { ...qs, otherFocused: true };
|
|
107530
|
+
return { ...state4, questionStates: newQs };
|
|
107531
|
+
}
|
|
107532
|
+
case "BLUR_OTHER": {
|
|
107533
|
+
const qs = state4.questionStates[state4.activeIndex];
|
|
107534
|
+
const newQs = [...state4.questionStates];
|
|
107535
|
+
newQs[state4.activeIndex] = { ...qs, otherFocused: false };
|
|
107536
|
+
return { ...state4, questionStates: newQs };
|
|
107537
|
+
}
|
|
107538
|
+
case "SET_OTHER_TEXT": {
|
|
107539
|
+
const qs = state4.questionStates[state4.activeIndex];
|
|
107540
|
+
const newQs = [...state4.questionStates];
|
|
107541
|
+
newQs[state4.activeIndex] = { ...qs, otherText: action3.text };
|
|
107542
|
+
return { ...state4, questionStates: newQs };
|
|
107543
|
+
}
|
|
107544
|
+
default:
|
|
107545
|
+
return state4;
|
|
107546
|
+
}
|
|
107547
|
+
}
|
|
107548
|
+
function isQuestionAnswered(q, qs) {
|
|
107549
|
+
if (!q.required) return true;
|
|
107550
|
+
const hasSelection = q.multiSelect ? qs.selectedIds.length > 0 : qs.pickedId !== null;
|
|
107551
|
+
const hasOther = q.allowOther && qs.otherText.trim().length > 0;
|
|
107552
|
+
return hasSelection || hasOther;
|
|
107553
|
+
}
|
|
107554
|
+
function canSubmit(state4) {
|
|
107555
|
+
return state4.questions.every(
|
|
107556
|
+
(q, i) => isQuestionAnswered(q, state4.questionStates[i])
|
|
107557
|
+
);
|
|
107558
|
+
}
|
|
107559
|
+
function buildAskChoiceResult(state4) {
|
|
107560
|
+
if (state4.phase === "cancelled") return { kind: "cancelled" };
|
|
107561
|
+
if (state4.phase !== "submitted") return { kind: "cancelled" };
|
|
107562
|
+
const answers = state4.questions.map((q, i) => {
|
|
107563
|
+
const qs = state4.questionStates[i];
|
|
107564
|
+
const selectedIds = q.multiSelect ? qs.selectedIds : qs.pickedId ? [qs.pickedId] : [];
|
|
107565
|
+
const otherText = qs.otherText.trim();
|
|
107566
|
+
const parts = [];
|
|
107567
|
+
for (const id of selectedIds) {
|
|
107568
|
+
const choice = q.choices.find((c) => c.id === id);
|
|
107569
|
+
if (choice) {
|
|
107570
|
+
parts.push(choice.userMessage || choice.label);
|
|
107571
|
+
}
|
|
107572
|
+
}
|
|
107573
|
+
if (otherText) {
|
|
107574
|
+
parts.push(otherText);
|
|
107575
|
+
}
|
|
107576
|
+
return {
|
|
107577
|
+
questionId: q.id,
|
|
107578
|
+
selectedIds,
|
|
107579
|
+
otherText,
|
|
107580
|
+
userMessage: parts.join("\n")
|
|
107581
|
+
};
|
|
107582
|
+
});
|
|
107583
|
+
return { kind: "submitted", answers };
|
|
107584
|
+
}
|
|
107585
|
+
function clamp3(value, min, max) {
|
|
107586
|
+
return Math.max(min, Math.min(max, value));
|
|
107587
|
+
}
|
|
107588
|
+
var init_askChoiceState = __esm({
|
|
107589
|
+
"packages/ai/tools/askChoiceState.ts"() {
|
|
107590
|
+
"use strict";
|
|
107591
|
+
}
|
|
107592
|
+
});
|
|
107593
|
+
|
|
107594
|
+
// packages/cli/tui/askChoiceDialog.ts
|
|
107595
|
+
function renderTabBar(questions, activeIndex, colorEnabled) {
|
|
107596
|
+
const tabs = questions.map((q, i) => {
|
|
107597
|
+
const label = `Q${i + 1}`;
|
|
107598
|
+
if (i === activeIndex) {
|
|
107599
|
+
return colorEnabled ? `${themeColorSequence("accent")}\x1B[1m ${label} \x1B[0m` : `[${label}]`;
|
|
107600
|
+
}
|
|
107601
|
+
return colorEnabled ? themeText(` ${label} `, "muted", colorEnabled) : ` ${label} `;
|
|
107602
|
+
});
|
|
107603
|
+
const submitLabel = "Submit";
|
|
107604
|
+
return tabs.join(" ") + " " + (colorEnabled ? themeText(submitLabel, "chrome", colorEnabled) : submitLabel);
|
|
107605
|
+
}
|
|
107606
|
+
function renderFooter(colorEnabled) {
|
|
107607
|
+
const hints = "type answer \u21B5save tab switch s submit esc cancel";
|
|
107608
|
+
return colorEnabled ? themeText(` ${hints}`, "chrome", colorEnabled) : ` ${hints}`;
|
|
107609
|
+
}
|
|
107610
|
+
function renderAskChoiceFrame(state4) {
|
|
107611
|
+
const colorEnabled = resolveCliColorEnabled();
|
|
107612
|
+
const q = state4.questions[state4.activeIndex];
|
|
107613
|
+
const qs = state4.questionStates[state4.activeIndex];
|
|
107614
|
+
const lines = [];
|
|
107615
|
+
lines.push(renderDialogTitle("question"));
|
|
107616
|
+
lines.push("");
|
|
107617
|
+
if (state4.questions.length > 1) {
|
|
107618
|
+
lines.push(renderTabBar(state4.questions, state4.activeIndex, colorEnabled));
|
|
107619
|
+
lines.push("");
|
|
107620
|
+
}
|
|
107621
|
+
lines.push(
|
|
107622
|
+
colorEnabled ? `${themeColorSequence("accent")}? ${q.question}\x1B[0m` : `? ${q.question}`
|
|
107623
|
+
);
|
|
107624
|
+
if (q.multiSelect) {
|
|
107625
|
+
lines.push(
|
|
107626
|
+
colorEnabled ? themeText(" Space to toggle, Enter to confirm selection.", "muted", colorEnabled) : " Space to toggle, Enter to confirm selection."
|
|
107627
|
+
);
|
|
107628
|
+
} else {
|
|
107629
|
+
lines.push(
|
|
107630
|
+
colorEnabled ? themeText(" Type your answer, then press Enter to save.", "muted", colorEnabled) : " Type your answer, then press Enter to save."
|
|
107631
|
+
);
|
|
107632
|
+
}
|
|
107633
|
+
lines.push("");
|
|
107634
|
+
const totalRows = q.choices.length + (q.allowOther ? 1 : 0);
|
|
107635
|
+
const window2 = computeVisibleWindow({
|
|
107636
|
+
selectedIndex: qs.cursorIndex,
|
|
107637
|
+
total: totalRows
|
|
107638
|
+
});
|
|
107639
|
+
if (window2.start > 0) {
|
|
107640
|
+
lines.push(
|
|
107641
|
+
colorEnabled ? themeText(` \u2191 ${window2.start} more`, "chrome", colorEnabled) : ` \u2191 ${window2.start} more`
|
|
107642
|
+
);
|
|
107643
|
+
}
|
|
107644
|
+
for (let i = window2.start; i < window2.end; i++) {
|
|
107645
|
+
if (i < q.choices.length) {
|
|
107646
|
+
const choice = q.choices[i];
|
|
107647
|
+
const focused = qs.cursorIndex === i;
|
|
107648
|
+
const checkbox = q.multiSelect ? qs.selectedIds.includes(choice.id) ? DIALOG_CHECKED : DIALOG_UNCHECKED : qs.pickedId === choice.id ? DIALOG_CHECKED : void 0;
|
|
107649
|
+
lines.push(
|
|
107650
|
+
renderDialogRow({
|
|
107651
|
+
label: `[${i + 1}] ${choice.label}`,
|
|
107652
|
+
...choice.detail ? { detail: choice.detail } : {},
|
|
107653
|
+
focused,
|
|
107654
|
+
...checkbox ? { checkbox } : {}
|
|
107655
|
+
})
|
|
107656
|
+
);
|
|
107657
|
+
} else {
|
|
107658
|
+
const focused = qs.cursorIndex === i;
|
|
107659
|
+
const marker = focused ? DIALOG_CURSOR : " ";
|
|
107660
|
+
const otherContent = qs.otherFocused ? `${qs.otherText}\u2588` : qs.otherText || "";
|
|
107661
|
+
const row = `${marker} [${i + 1}] Other: ${otherContent}`;
|
|
107662
|
+
if (focused && colorEnabled) {
|
|
107663
|
+
lines.push(
|
|
107664
|
+
`\x1B[1m${themeColorSequence("accent")}${row}\x1B[0m`
|
|
107665
|
+
);
|
|
107666
|
+
} else {
|
|
107667
|
+
lines.push(row);
|
|
107668
|
+
}
|
|
107669
|
+
}
|
|
107670
|
+
}
|
|
107671
|
+
if (window2.end < totalRows) {
|
|
107672
|
+
lines.push(
|
|
107673
|
+
colorEnabled ? themeText(` \u2193 ${totalRows - window2.end} more`, "chrome", colorEnabled) : ` \u2193 ${totalRows - window2.end} more`
|
|
107674
|
+
);
|
|
107675
|
+
}
|
|
107676
|
+
lines.push("");
|
|
107677
|
+
lines.push(renderFooter(colorEnabled));
|
|
107678
|
+
return lines.join("\n");
|
|
107679
|
+
}
|
|
107680
|
+
async function runAskChoiceDialog(args2) {
|
|
107681
|
+
const { request } = args2;
|
|
107682
|
+
const normalized = normalizeAskChoiceArgs({
|
|
107683
|
+
question: request.question,
|
|
107684
|
+
choices: request.choices,
|
|
107685
|
+
questions: request.questions,
|
|
107686
|
+
blocking: request.blocking
|
|
107687
|
+
});
|
|
107688
|
+
if (normalized.questions.length === 0) {
|
|
107689
|
+
return { kind: "cancelled" };
|
|
107690
|
+
}
|
|
107691
|
+
const q0 = normalized.questions[0];
|
|
107692
|
+
if (normalized.questions.length === 1 && !q0.multiSelect && !q0.allowOther) {
|
|
107693
|
+
}
|
|
107694
|
+
let state4 = createInitialAskChoiceState(normalized.questions);
|
|
107695
|
+
const output2 = args2.output ?? process.stdout;
|
|
107696
|
+
const input2 = args2.input ?? process.stdin;
|
|
107697
|
+
const readKey = args2.readKey ?? createRawKeyReader(input2);
|
|
107698
|
+
const wasRaw = Boolean(input2.isTTY && input2.isRaw);
|
|
107699
|
+
let renderedLineCount = 0;
|
|
107700
|
+
const bottomAnchored = Boolean(args2.bottomAnchored && args2.bottomRow);
|
|
107701
|
+
const resolveBottomRow = () => Math.max(
|
|
107702
|
+
1,
|
|
107703
|
+
typeof args2.bottomRow === "function" ? args2.bottomRow() : args2.bottomRow ?? 0
|
|
107704
|
+
);
|
|
107705
|
+
let lastBottomRow = 0;
|
|
107706
|
+
const paint = () => {
|
|
107707
|
+
const frame = renderAskChoiceFrame(state4);
|
|
107708
|
+
const lines = frame.split("\n");
|
|
107709
|
+
const lineCount = lines.length;
|
|
107710
|
+
const canPosition = outputIsTty(output2) && typeof output2.write === "function";
|
|
107711
|
+
if (bottomAnchored && canPosition) {
|
|
107712
|
+
const anchorRow = resolveBottomRow();
|
|
107713
|
+
clearAnchoredLines(
|
|
107714
|
+
output2,
|
|
107715
|
+
lastBottomRow > 0 ? lastBottomRow : anchorRow,
|
|
107716
|
+
renderedLineCount
|
|
107717
|
+
);
|
|
107718
|
+
for (let i = 0; i < lines.length; i++) {
|
|
107719
|
+
const row = anchorRow - (lines.length - 1 - i);
|
|
107720
|
+
if (row < 1) break;
|
|
107721
|
+
output2.write(`\x1B[${row};1H\x1B[2K${lines[i]}`);
|
|
107722
|
+
}
|
|
107723
|
+
lastBottomRow = anchorRow;
|
|
107724
|
+
renderedLineCount = lineCount;
|
|
107725
|
+
return;
|
|
107726
|
+
}
|
|
107727
|
+
if (canPosition) {
|
|
107728
|
+
for (let i = 0; i < renderedLineCount; i++) {
|
|
107729
|
+
output2.write("\x1B[1A\x1B[2K");
|
|
107730
|
+
}
|
|
107731
|
+
output2.write(`${frame}
|
|
107732
|
+
`);
|
|
107733
|
+
renderedLineCount = lineCount;
|
|
107734
|
+
return;
|
|
107735
|
+
}
|
|
107736
|
+
if (typeof output2.write === "function") {
|
|
107737
|
+
output2.write(`${frame}
|
|
107738
|
+
`);
|
|
107739
|
+
}
|
|
107740
|
+
renderedLineCount = lineCount;
|
|
107741
|
+
};
|
|
107742
|
+
const resizeTarget = output2;
|
|
107743
|
+
const onOutputResize = () => paint();
|
|
107744
|
+
if (input2.isTTY && !wasRaw) {
|
|
107745
|
+
input2.setRawMode?.(true);
|
|
107746
|
+
}
|
|
107747
|
+
if (bottomAnchored && outputIsTty(output2)) {
|
|
107748
|
+
resizeTarget.on?.("resize", onOutputResize);
|
|
107749
|
+
}
|
|
107750
|
+
paint();
|
|
107751
|
+
try {
|
|
107752
|
+
while (state4.phase === "active") {
|
|
107753
|
+
const sequence = await readKey();
|
|
107754
|
+
if (sequence == null) {
|
|
107755
|
+
state4 = askChoiceReducer(state4, { type: "CANCEL" });
|
|
107756
|
+
break;
|
|
107757
|
+
}
|
|
107758
|
+
let action3 = null;
|
|
107759
|
+
if (isCancel(sequence)) {
|
|
107760
|
+
action3 = { type: "CANCEL" };
|
|
107761
|
+
} else if (sequence === CSI_TAB) {
|
|
107762
|
+
action3 = { type: "NEXT_TAB" };
|
|
107763
|
+
} else if (sequence === CSI_SHIFT_TAB) {
|
|
107764
|
+
action3 = { type: "PREV_TAB" };
|
|
107765
|
+
} else if (isArrowUp(sequence)) {
|
|
107766
|
+
action3 = { type: "MOVE_CURSOR", delta: -1 };
|
|
107767
|
+
} else if (isArrowDown(sequence)) {
|
|
107768
|
+
action3 = { type: "MOVE_CURSOR", delta: 1 };
|
|
107769
|
+
} else if (sequence === CSI_SPACE) {
|
|
107770
|
+
action3 = { type: "TOGGLE_AT_CURSOR" };
|
|
107771
|
+
} else if (sequence === "s" && !state4.questionStates[state4.activeIndex].otherFocused && canSubmit(state4)) {
|
|
107772
|
+
action3 = { type: "SUBMIT" };
|
|
107773
|
+
} else if (isSubmit(sequence)) {
|
|
107774
|
+
const qs = state4.questionStates[state4.activeIndex];
|
|
107775
|
+
const q = state4.questions[state4.activeIndex];
|
|
107776
|
+
const isOtherRow = qs.cursorIndex >= q.choices.length;
|
|
107777
|
+
if (qs.otherFocused) {
|
|
107778
|
+
action3 = { type: "BLUR_OTHER" };
|
|
107779
|
+
} else if (isOtherRow && !qs.otherFocused) {
|
|
107780
|
+
action3 = { type: "FOCUS_OTHER" };
|
|
107781
|
+
} else {
|
|
107782
|
+
action3 = { type: "SELECT_AT_CURSOR" };
|
|
107783
|
+
}
|
|
107784
|
+
} else if (sequence === CSI_BACKSPACE || sequence === CSI_BACKSPACE_ALT) {
|
|
107785
|
+
const qs = state4.questionStates[state4.activeIndex];
|
|
107786
|
+
if (qs.otherFocused && qs.otherText.length > 0) {
|
|
107787
|
+
action3 = {
|
|
107788
|
+
type: "SET_OTHER_TEXT",
|
|
107789
|
+
text: qs.otherText.slice(0, -1)
|
|
107790
|
+
};
|
|
107791
|
+
}
|
|
107792
|
+
} else if (sequence.length === 1 && sequence.charCodeAt(0) >= 32) {
|
|
107793
|
+
const qs = state4.questionStates[state4.activeIndex];
|
|
107794
|
+
if (qs.otherFocused) {
|
|
107795
|
+
action3 = {
|
|
107796
|
+
type: "SET_OTHER_TEXT",
|
|
107797
|
+
text: qs.otherText + sequence
|
|
107798
|
+
};
|
|
107799
|
+
}
|
|
107800
|
+
}
|
|
107801
|
+
if (action3) {
|
|
107802
|
+
const prev = state4;
|
|
107803
|
+
state4 = askChoiceReducer(state4, action3);
|
|
107804
|
+
if (state4.phase !== "active") break;
|
|
107805
|
+
if (action3.type === "BLUR_OTHER" && state4.questions.length === 1 && canSubmit(state4)) {
|
|
107806
|
+
state4 = askChoiceReducer(state4, { type: "SUBMIT" });
|
|
107807
|
+
break;
|
|
107808
|
+
}
|
|
107809
|
+
paint();
|
|
107810
|
+
}
|
|
107811
|
+
}
|
|
107812
|
+
} finally {
|
|
107813
|
+
resizeTarget.off?.("resize", onOutputResize);
|
|
107814
|
+
readKey.dispose?.();
|
|
107815
|
+
if (input2.isTTY) {
|
|
107816
|
+
drainInputBuffer(input2);
|
|
107817
|
+
if (!wasRaw) input2.setRawMode?.(false);
|
|
107818
|
+
if (bottomAnchored) {
|
|
107819
|
+
clearAnchoredLines(
|
|
107820
|
+
output2,
|
|
107821
|
+
lastBottomRow > 0 ? lastBottomRow : resolveBottomRow(),
|
|
107822
|
+
renderedLineCount
|
|
107823
|
+
);
|
|
107824
|
+
} else {
|
|
107825
|
+
for (let i = 0; i < renderedLineCount; i++) {
|
|
107826
|
+
output2.write("\x1B[1A\x1B[2K");
|
|
107827
|
+
}
|
|
107828
|
+
}
|
|
107829
|
+
renderedLineCount = 0;
|
|
107830
|
+
}
|
|
107831
|
+
}
|
|
107832
|
+
const result = buildAskChoiceResult(state4);
|
|
107833
|
+
if (result.kind === "cancelled") {
|
|
107834
|
+
return { kind: "cancelled" };
|
|
107835
|
+
}
|
|
107836
|
+
if (result.answers.length === 1) {
|
|
107837
|
+
const a = result.answers[0];
|
|
107838
|
+
return {
|
|
107839
|
+
kind: "selected",
|
|
107840
|
+
userMessage: a.userMessage,
|
|
107841
|
+
label: a.selectedIds.map((id) => {
|
|
107842
|
+
const q = normalized.questions[0];
|
|
107843
|
+
return q.choices.find((c) => c.id === id)?.label ?? "";
|
|
107844
|
+
}).join(", ") || a.otherText || ""
|
|
107845
|
+
};
|
|
107846
|
+
}
|
|
107847
|
+
return {
|
|
107848
|
+
kind: "multi-submitted",
|
|
107849
|
+
answers: result.answers,
|
|
107850
|
+
userMessage: result.answers.map((a) => a.userMessage).filter(Boolean).join("\n\n")
|
|
107851
|
+
};
|
|
107852
|
+
}
|
|
107853
|
+
var CSI_TAB, CSI_SHIFT_TAB, CSI_BACKSPACE, CSI_BACKSPACE_ALT, CSI_SPACE;
|
|
107854
|
+
var init_askChoiceDialog = __esm({
|
|
107855
|
+
"packages/cli/tui/askChoiceDialog.ts"() {
|
|
107856
|
+
"use strict";
|
|
107857
|
+
init_askChoiceState();
|
|
107858
|
+
init_dialogFrame();
|
|
107859
|
+
init_selectDialog();
|
|
107860
|
+
init_terminalStyles();
|
|
107861
|
+
init_theme();
|
|
107862
|
+
CSI_TAB = " ";
|
|
107863
|
+
CSI_SHIFT_TAB = "\x1B[Z";
|
|
107864
|
+
CSI_BACKSPACE = "\x7F";
|
|
107865
|
+
CSI_BACKSPACE_ALT = "\b";
|
|
107866
|
+
CSI_SPACE = " ";
|
|
107867
|
+
}
|
|
107868
|
+
});
|
|
107869
|
+
|
|
107260
107870
|
// packages/cli/tui/dialogHost.ts
|
|
107261
107871
|
function resolveTtyRows(output2) {
|
|
107262
107872
|
if (typeof output2 === "object" && output2 !== null && "rows" in output2 && typeof output2.rows === "number") {
|
|
@@ -107294,6 +107904,92 @@ var init_dialogHost = __esm({
|
|
|
107294
107904
|
}
|
|
107295
107905
|
});
|
|
107296
107906
|
|
|
107907
|
+
// packages/cli/tui/activityIndicator.ts
|
|
107908
|
+
function createActivityIndicator(deps) {
|
|
107909
|
+
const now = deps.now ?? (() => Date.now());
|
|
107910
|
+
const frameIntervalMs = deps.frameIntervalMs ?? ACTIVITY_FRAME_INTERVAL_MS;
|
|
107911
|
+
const fallbackDelayMs = deps.fallbackDelayMs ?? ACTIVITY_FALLBACK_DELAY_MS;
|
|
107912
|
+
const setIntervalFn = deps.setIntervalFn ?? ((cb, ms) => setInterval(cb, ms));
|
|
107913
|
+
const clearIntervalFn = deps.clearIntervalFn ?? ((handle) => clearInterval(handle));
|
|
107914
|
+
let explicitLabel = null;
|
|
107915
|
+
let explicitStartedAt = 0;
|
|
107916
|
+
let fallbackActive = false;
|
|
107917
|
+
let fallbackStartedAt = 0;
|
|
107918
|
+
let lastActivityAt = 0;
|
|
107919
|
+
let frameIndex = 0;
|
|
107920
|
+
let timer = null;
|
|
107921
|
+
const elapsedSecFrom = (startedAt) => startedAt > 0 ? Math.max(0, Math.floor((now() - startedAt) / 1e3)) : 0;
|
|
107922
|
+
const tick = () => {
|
|
107923
|
+
frameIndex += 1;
|
|
107924
|
+
if (explicitLabel === null && !fallbackActive && deps.isTurnActive() && lastActivityAt > 0 && now() - lastActivityAt >= fallbackDelayMs) {
|
|
107925
|
+
fallbackActive = true;
|
|
107926
|
+
fallbackStartedAt = now();
|
|
107927
|
+
}
|
|
107928
|
+
deps.onRepaint();
|
|
107929
|
+
};
|
|
107930
|
+
const ensureTimer = () => {
|
|
107931
|
+
if (timer === null) {
|
|
107932
|
+
timer = setIntervalFn(tick, frameIntervalMs);
|
|
107933
|
+
}
|
|
107934
|
+
};
|
|
107935
|
+
const report = (label) => {
|
|
107936
|
+
lastActivityAt = now();
|
|
107937
|
+
if (label !== null) {
|
|
107938
|
+
explicitLabel = label;
|
|
107939
|
+
if (explicitStartedAt === 0) explicitStartedAt = lastActivityAt;
|
|
107940
|
+
fallbackActive = false;
|
|
107941
|
+
fallbackStartedAt = 0;
|
|
107942
|
+
} else {
|
|
107943
|
+
explicitLabel = null;
|
|
107944
|
+
explicitStartedAt = 0;
|
|
107945
|
+
fallbackActive = false;
|
|
107946
|
+
fallbackStartedAt = 0;
|
|
107947
|
+
}
|
|
107948
|
+
ensureTimer();
|
|
107949
|
+
deps.onRepaint();
|
|
107950
|
+
};
|
|
107951
|
+
const getView = () => {
|
|
107952
|
+
if (!deps.isTurnActive()) return null;
|
|
107953
|
+
const frame = ACTIVITY_FRAMES[frameIndex % ACTIVITY_FRAMES.length];
|
|
107954
|
+
if (explicitLabel !== null) {
|
|
107955
|
+
return {
|
|
107956
|
+
frame,
|
|
107957
|
+
label: explicitLabel,
|
|
107958
|
+
elapsedSec: elapsedSecFrom(explicitStartedAt)
|
|
107959
|
+
};
|
|
107960
|
+
}
|
|
107961
|
+
if (fallbackActive) {
|
|
107962
|
+
return {
|
|
107963
|
+
frame,
|
|
107964
|
+
label: deps.fallbackLabel(),
|
|
107965
|
+
elapsedSec: elapsedSecFrom(fallbackStartedAt)
|
|
107966
|
+
};
|
|
107967
|
+
}
|
|
107968
|
+
return null;
|
|
107969
|
+
};
|
|
107970
|
+
const stop = () => {
|
|
107971
|
+
if (timer !== null) {
|
|
107972
|
+
clearIntervalFn(timer);
|
|
107973
|
+
timer = null;
|
|
107974
|
+
}
|
|
107975
|
+
explicitLabel = null;
|
|
107976
|
+
explicitStartedAt = 0;
|
|
107977
|
+
fallbackActive = false;
|
|
107978
|
+
fallbackStartedAt = 0;
|
|
107979
|
+
lastActivityAt = 0;
|
|
107980
|
+
};
|
|
107981
|
+
return { report, getView, stop };
|
|
107982
|
+
}
|
|
107983
|
+
var ACTIVITY_FRAMES, ACTIVITY_FRAME_INTERVAL_MS, ACTIVITY_FALLBACK_DELAY_MS;
|
|
107984
|
+
var init_activityIndicator = __esm({
|
|
107985
|
+
"packages/cli/tui/activityIndicator.ts"() {
|
|
107986
|
+
"use strict";
|
|
107987
|
+
ACTIVITY_FRAMES = ["\xB7", "~", "\u2248", "\u223F", "\u2248", "~"];
|
|
107988
|
+
ACTIVITY_FRAME_INTERVAL_MS = 150;
|
|
107989
|
+
ACTIVITY_FALLBACK_DELAY_MS = 1200;
|
|
107990
|
+
}
|
|
107991
|
+
});
|
|
107992
|
+
|
|
107297
107993
|
// packages/ai/agent/utils/sortUtils.ts
|
|
107298
107994
|
function sortAgentsFavoriteOwnedPublic(items) {
|
|
107299
107995
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -108051,6 +108747,278 @@ var init_gitStatus = __esm({
|
|
|
108051
108747
|
}
|
|
108052
108748
|
});
|
|
108053
108749
|
|
|
108750
|
+
// packages/cli/tui/tuiAnsi.ts
|
|
108751
|
+
function stripAnsi(text) {
|
|
108752
|
+
return text.replace(OSC_HYPERLINK_REGEX, "").replace(ANSI_ESCAPE_REGEX, "");
|
|
108753
|
+
}
|
|
108754
|
+
function applyTerminalOutputToText(existing, chunk) {
|
|
108755
|
+
if (!chunk) return existing;
|
|
108756
|
+
let text = existing;
|
|
108757
|
+
let index = 0;
|
|
108758
|
+
while (index < chunk.length) {
|
|
108759
|
+
if (chunk[index] === "\x1B") {
|
|
108760
|
+
const sgr = SGR_SEQUENCE_REGEX.exec(chunk.slice(index));
|
|
108761
|
+
if (sgr) {
|
|
108762
|
+
text += sgr[0];
|
|
108763
|
+
index += sgr[0].length;
|
|
108764
|
+
continue;
|
|
108765
|
+
}
|
|
108766
|
+
const osc = chunk.slice(index).match(/^\x1b\]8;;[^\x07\x1b]*(?:\x07|\x1b\\)/);
|
|
108767
|
+
if (osc) {
|
|
108768
|
+
index += osc[0].length;
|
|
108769
|
+
continue;
|
|
108770
|
+
}
|
|
108771
|
+
const csi = chunk.slice(index).match(/^\x1b\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]/);
|
|
108772
|
+
if (csi) {
|
|
108773
|
+
index += csi[0].length;
|
|
108774
|
+
continue;
|
|
108775
|
+
}
|
|
108776
|
+
index += 1;
|
|
108777
|
+
continue;
|
|
108778
|
+
}
|
|
108779
|
+
const ch = chunk[index];
|
|
108780
|
+
if (ch === "\r") {
|
|
108781
|
+
const lastNl = text.lastIndexOf("\n");
|
|
108782
|
+
text = lastNl === -1 ? "" : text.slice(0, lastNl + 1);
|
|
108783
|
+
index += 1;
|
|
108784
|
+
continue;
|
|
108785
|
+
}
|
|
108786
|
+
if (ch === "\n") {
|
|
108787
|
+
text += "\n";
|
|
108788
|
+
index += 1;
|
|
108789
|
+
continue;
|
|
108790
|
+
}
|
|
108791
|
+
if (ch === "\b") {
|
|
108792
|
+
const trailing = TRAILING_SGR_REGEX.exec(text);
|
|
108793
|
+
const sgrTail = trailing ? trailing[0] : "";
|
|
108794
|
+
const head = sgrTail ? text.slice(0, -sgrTail.length) : text;
|
|
108795
|
+
if (head.length > 0 && head[head.length - 1] !== "\n") {
|
|
108796
|
+
text = head.slice(0, -1) + sgrTail;
|
|
108797
|
+
}
|
|
108798
|
+
index += 1;
|
|
108799
|
+
continue;
|
|
108800
|
+
}
|
|
108801
|
+
const code = ch.charCodeAt(0);
|
|
108802
|
+
if (code < 32 && ch !== " " || code === 127) {
|
|
108803
|
+
index += 1;
|
|
108804
|
+
continue;
|
|
108805
|
+
}
|
|
108806
|
+
text += ch;
|
|
108807
|
+
index += 1;
|
|
108808
|
+
}
|
|
108809
|
+
return text;
|
|
108810
|
+
}
|
|
108811
|
+
function displayWidth2(str) {
|
|
108812
|
+
let width = 0;
|
|
108813
|
+
for (const char of str) {
|
|
108814
|
+
const code = char.codePointAt(0) ?? 0;
|
|
108815
|
+
if (code < 32 || code === 127) continue;
|
|
108816
|
+
if (code >= 4352 && code <= 4447 || // 0x2768-0x2775 (ornamental brackets, incl. the ❯ prompt at U+276F)
|
|
108817
|
+
// render narrow in terminals; counting them wide drifts the cursor.
|
|
108818
|
+
code >= 9728 && code <= 10175 && !(code >= 10088 && code <= 10101) || // 0x2B00-0x2BFF (Misc Symbols and Arrows, incl. ⬢ U+2B22 used as the
|
|
108819
|
+
// status-line agent icon) render double-wide in common monospace fonts;
|
|
108820
|
+
// counting ⬢ as width 1 drifts the whole status line right of the icon.
|
|
108821
|
+
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 ‘ ’).
|
|
108822
|
+
// In CJK locale + CJK fonts these render double-wide like 全角 punctuation;
|
|
108823
|
+
// in English fonts they stay width 1. Follow the active locale so Chinese
|
|
108824
|
+
// replies align correctly without breaking English terminal output.
|
|
108825
|
+
getCliLocale() === "zh" && (code === 8220 || code === 8221 || code === 8216 || code === 8217)) {
|
|
108826
|
+
width += 2;
|
|
108827
|
+
} else {
|
|
108828
|
+
width += 1;
|
|
108829
|
+
}
|
|
108830
|
+
}
|
|
108831
|
+
return width;
|
|
108832
|
+
}
|
|
108833
|
+
function visibleWidth(str) {
|
|
108834
|
+
return displayWidth2(stripAnsi(str));
|
|
108835
|
+
}
|
|
108836
|
+
function truncateAnsi(text, maxWidth) {
|
|
108837
|
+
if (maxWidth <= 0) return "";
|
|
108838
|
+
if (visibleWidth(text) <= maxWidth) return text;
|
|
108839
|
+
let width = 0;
|
|
108840
|
+
let out = "";
|
|
108841
|
+
let i = 0;
|
|
108842
|
+
let sawAnsi = false;
|
|
108843
|
+
while (i < text.length) {
|
|
108844
|
+
if (text[i] === "\x1B" && text[i + 1] === "[") {
|
|
108845
|
+
sawAnsi = true;
|
|
108846
|
+
let j = i + 2;
|
|
108847
|
+
while (j < text.length) {
|
|
108848
|
+
const code = text.charCodeAt(j);
|
|
108849
|
+
j += 1;
|
|
108850
|
+
if (code >= 64 && code <= 126) break;
|
|
108851
|
+
}
|
|
108852
|
+
out += text.slice(i, j);
|
|
108853
|
+
i = j;
|
|
108854
|
+
continue;
|
|
108855
|
+
}
|
|
108856
|
+
const codePoint = text.codePointAt(i) ?? 0;
|
|
108857
|
+
const char = String.fromCodePoint(codePoint);
|
|
108858
|
+
const charWidth = displayWidth2(char);
|
|
108859
|
+
if (width + charWidth > maxWidth) break;
|
|
108860
|
+
out += char;
|
|
108861
|
+
width += charWidth;
|
|
108862
|
+
i += char.length;
|
|
108863
|
+
}
|
|
108864
|
+
return sawAnsi ? `${out}\x1B[0m` : out;
|
|
108865
|
+
}
|
|
108866
|
+
function fitAnsiLine(text, width, ellipsis = "\u2026") {
|
|
108867
|
+
if (width <= 0) return "";
|
|
108868
|
+
if (visibleWidth(text) <= width) return text;
|
|
108869
|
+
const ellipsisWidth = displayWidth2(ellipsis);
|
|
108870
|
+
if (width < ellipsisWidth) return truncateAnsi(text, width);
|
|
108871
|
+
if (width === ellipsisWidth) return truncateAnsi(ellipsis, width) || truncateAnsi(text, width);
|
|
108872
|
+
return `${truncateAnsi(text, width - ellipsisWidth)}${ellipsis}`;
|
|
108873
|
+
}
|
|
108874
|
+
function countPhysicalLines(text, columns) {
|
|
108875
|
+
const lines = text.split("\n");
|
|
108876
|
+
let total = 0;
|
|
108877
|
+
for (const line of lines) {
|
|
108878
|
+
const width = displayWidth2(line);
|
|
108879
|
+
total += Math.max(1, Math.ceil(width / columns));
|
|
108880
|
+
}
|
|
108881
|
+
return Math.max(total, 1);
|
|
108882
|
+
}
|
|
108883
|
+
function takeDisplayWidth(text, width) {
|
|
108884
|
+
let used = 0;
|
|
108885
|
+
let index = 0;
|
|
108886
|
+
for (const char of text) {
|
|
108887
|
+
const charWidth = displayWidth2(char);
|
|
108888
|
+
if (used + charWidth > width && used > 0) break;
|
|
108889
|
+
used += charWidth;
|
|
108890
|
+
index += char.length;
|
|
108891
|
+
}
|
|
108892
|
+
return { prefix: text.slice(0, index), rest: text.slice(index) };
|
|
108893
|
+
}
|
|
108894
|
+
function padOrTruncateToWidth(text, width) {
|
|
108895
|
+
const textWidth = visibleWidth(text);
|
|
108896
|
+
if (textWidth > width) {
|
|
108897
|
+
return truncateAnsi(text, width);
|
|
108898
|
+
}
|
|
108899
|
+
return `${text}${" ".repeat(width - textWidth)}`;
|
|
108900
|
+
}
|
|
108901
|
+
function tokenizeAnsiLine(line) {
|
|
108902
|
+
const tokens = [];
|
|
108903
|
+
let index = 0;
|
|
108904
|
+
while (index < line.length) {
|
|
108905
|
+
if (line[index] === "\x1B") {
|
|
108906
|
+
const osc = line.slice(index).match(/^\x1b\]8;;[^\x07\x1b]*(?:\x07|\x1b\\)/);
|
|
108907
|
+
if (osc) {
|
|
108908
|
+
tokens.push({ kind: "sgr", value: osc[0], width: 0 });
|
|
108909
|
+
index += osc[0].length;
|
|
108910
|
+
continue;
|
|
108911
|
+
}
|
|
108912
|
+
const sgr = SGR_SEQUENCE_REGEX.exec(line.slice(index));
|
|
108913
|
+
if (sgr) {
|
|
108914
|
+
tokens.push({ kind: "sgr", value: sgr[0], width: 0 });
|
|
108915
|
+
index += sgr[0].length;
|
|
108916
|
+
continue;
|
|
108917
|
+
}
|
|
108918
|
+
}
|
|
108919
|
+
const codePoint = line.codePointAt(index) ?? 0;
|
|
108920
|
+
const value = String.fromCodePoint(codePoint);
|
|
108921
|
+
tokens.push({ kind: "char", value, width: displayWidth2(value) });
|
|
108922
|
+
index += value.length;
|
|
108923
|
+
}
|
|
108924
|
+
return tokens;
|
|
108925
|
+
}
|
|
108926
|
+
function wrapTranscriptLine(line, columns) {
|
|
108927
|
+
if (line === "") return [""];
|
|
108928
|
+
const tokens = tokenizeAnsiLine(line);
|
|
108929
|
+
const result = [];
|
|
108930
|
+
let activeStyles = [];
|
|
108931
|
+
const applyStyleToken = (value) => {
|
|
108932
|
+
if (SGR_RESET_REGEX.test(value)) {
|
|
108933
|
+
activeStyles = [];
|
|
108934
|
+
} else {
|
|
108935
|
+
activeStyles.push(value);
|
|
108936
|
+
}
|
|
108937
|
+
};
|
|
108938
|
+
let start = 0;
|
|
108939
|
+
while (start < tokens.length) {
|
|
108940
|
+
if (tokens.slice(start).every((token) => token.kind === "sgr")) {
|
|
108941
|
+
if (result.length > 0) break;
|
|
108942
|
+
}
|
|
108943
|
+
const openingStyles = [...activeStyles];
|
|
108944
|
+
let width = 0;
|
|
108945
|
+
let end = start;
|
|
108946
|
+
let lastBreak = -1;
|
|
108947
|
+
while (end < tokens.length) {
|
|
108948
|
+
const token = tokens[end];
|
|
108949
|
+
if (token.kind === "sgr") {
|
|
108950
|
+
end += 1;
|
|
108951
|
+
continue;
|
|
108952
|
+
}
|
|
108953
|
+
if (width + token.width > columns && width > 0) break;
|
|
108954
|
+
width += token.width;
|
|
108955
|
+
end += 1;
|
|
108956
|
+
if (token.value === " " || token.value === " ") {
|
|
108957
|
+
lastBreak = end;
|
|
108958
|
+
}
|
|
108959
|
+
}
|
|
108960
|
+
let segmentEnd = end;
|
|
108961
|
+
if (end < tokens.length && lastBreak > start) {
|
|
108962
|
+
const overflowToken = tokens[end];
|
|
108963
|
+
if (overflowToken.kind === "char" && overflowToken.value !== " " && overflowToken.width === 1) {
|
|
108964
|
+
segmentEnd = lastBreak;
|
|
108965
|
+
}
|
|
108966
|
+
}
|
|
108967
|
+
if (segmentEnd === start) segmentEnd = start + 1;
|
|
108968
|
+
let segment = "";
|
|
108969
|
+
let sawStyle = openingStyles.length > 0;
|
|
108970
|
+
for (let i = start; i < segmentEnd; i += 1) {
|
|
108971
|
+
const token = tokens[i];
|
|
108972
|
+
segment += token.value;
|
|
108973
|
+
if (token.kind === "sgr") {
|
|
108974
|
+
sawStyle = true;
|
|
108975
|
+
applyStyleToken(token.value);
|
|
108976
|
+
}
|
|
108977
|
+
}
|
|
108978
|
+
const prefix = openingStyles.join("");
|
|
108979
|
+
const needsReset = (sawStyle || activeStyles.length > 0) && !segment.endsWith("\x1B[0m");
|
|
108980
|
+
result.push(`${prefix}${segment}${needsReset ? "\x1B[0m" : ""}`);
|
|
108981
|
+
start = segmentEnd;
|
|
108982
|
+
while (start < tokens.length) {
|
|
108983
|
+
const token = tokens[start];
|
|
108984
|
+
if (token.kind === "char" && token.value === " ") {
|
|
108985
|
+
start += 1;
|
|
108986
|
+
continue;
|
|
108987
|
+
}
|
|
108988
|
+
break;
|
|
108989
|
+
}
|
|
108990
|
+
}
|
|
108991
|
+
return result.length > 0 ? result : [""];
|
|
108992
|
+
}
|
|
108993
|
+
function wrapTextToLines(text, columns) {
|
|
108994
|
+
const result = [];
|
|
108995
|
+
for (const logicalLine of text.split("\n")) {
|
|
108996
|
+
if (logicalLine === "") {
|
|
108997
|
+
result.push("");
|
|
108998
|
+
continue;
|
|
108999
|
+
}
|
|
109000
|
+
let remaining = logicalLine;
|
|
109001
|
+
while (remaining.length > 0) {
|
|
109002
|
+
const { prefix, rest } = takeDisplayWidth(remaining, columns);
|
|
109003
|
+
result.push(prefix);
|
|
109004
|
+
remaining = rest;
|
|
109005
|
+
}
|
|
109006
|
+
}
|
|
109007
|
+
return result;
|
|
109008
|
+
}
|
|
109009
|
+
var ANSI_ESCAPE_REGEX, OSC_HYPERLINK_REGEX, SGR_SEQUENCE_REGEX, TRAILING_SGR_REGEX, SGR_RESET_REGEX;
|
|
109010
|
+
var init_tuiAnsi = __esm({
|
|
109011
|
+
"packages/cli/tui/tuiAnsi.ts"() {
|
|
109012
|
+
"use strict";
|
|
109013
|
+
init_i18n2();
|
|
109014
|
+
ANSI_ESCAPE_REGEX = /\x1b\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]/g;
|
|
109015
|
+
OSC_HYPERLINK_REGEX = /\x1b\]8;;[^\x07\x1b]*(?:\x07|\x1b\\)\x1b\]8;;(?:\x07|\x1b\\)|\x1b\]8;;[^\x07\x1b]*(?:\x07|\x1b\\)/g;
|
|
109016
|
+
SGR_SEQUENCE_REGEX = /^\x1b\[[0-9;]*m/;
|
|
109017
|
+
TRAILING_SGR_REGEX = /(?:\x1b\[[0-9;]*m)+$/;
|
|
109018
|
+
SGR_RESET_REGEX = /^\x1b\[0?m$/;
|
|
109019
|
+
}
|
|
109020
|
+
});
|
|
109021
|
+
|
|
108054
109022
|
// packages/cli/tui/sessionRender.ts
|
|
108055
109023
|
function formatCwd(cwd) {
|
|
108056
109024
|
const parts = cwd.split(/[/\\]/);
|
|
@@ -108103,58 +109071,83 @@ function renderStatusLine(state4) {
|
|
|
108103
109071
|
if (!surface) return body;
|
|
108104
109072
|
return `${surface} ${body} \x1B[49m`;
|
|
108105
109073
|
}
|
|
108106
|
-
function buildPlainScene(isDark) {
|
|
108107
|
-
|
|
109074
|
+
function buildPlainScene(isDark, frame = 0, maxFrames = 0) {
|
|
109075
|
+
let skyLine = ` ${isDark ? "\u{1F319}" : "\u2600"}`;
|
|
109076
|
+
if (isDark) {
|
|
109077
|
+
const star1 = frame % 6 < 3 ? "\u2726" : "\u22C6";
|
|
109078
|
+
const star2 = frame % 4 < 2 ? "\u22C6" : "\xB7";
|
|
109079
|
+
const star3 = frame % 5 < 2 ? "\xB7" : "\u2726";
|
|
109080
|
+
skyLine = ` ${star1} \u{1F319} ${star2} ${star3}`;
|
|
109081
|
+
}
|
|
109082
|
+
const wavePattern = "_.~^~.";
|
|
109083
|
+
const longWave = wavePattern.repeat(10);
|
|
109084
|
+
const offset = frame % wavePattern.length;
|
|
109085
|
+
const wave2 = longWave.slice(offset, offset + 25);
|
|
108108
109086
|
return [
|
|
108109
|
-
|
|
108110
|
-
|
|
108111
|
-
" \u2571 \u2572",
|
|
108112
|
-
|
|
108113
|
-
|
|
108114
|
-
" \u2581\u2581\u2581\u2581\u2581\u2581\u2571
|
|
108115
|
-
" \u2588\u2584 \u2588 \u2584\u2580\u2580\u2584 \u2588 \u2584\u2580\u2580\u2584",
|
|
108116
|
-
" \u2588 \u2580\u2588 \u2588 \u2588 \u2588 \u2588 \u2588",
|
|
108117
|
-
" \u2580 \u2580 \u2580\u2580 \u2580\u2580\u2580\u2580 \u2580\u2580",
|
|
108118
|
-
" \u2570\u256E~\u2248~~\u2248~~\u2248~~\u2248~~\u2248~~\u2248~~\u2248~~\u2248~\u2570\u256E\u2248~"
|
|
109087
|
+
skyLine,
|
|
109088
|
+
" \u2571\u2572 \u2588\u2584 \u2588 \u2584\u2580\u2580\u2584 \u2588 \u2584\u2580\u2580\u2584",
|
|
109089
|
+
" \u2571 \u2572 \u2571\u2572 \u2588 \u2580\u2588 \u2588 \u2588 \u2588 \u2588 \u2588",
|
|
109090
|
+
" \u2571 \u2572\u2571 \u2572 \u2580 \u2580 \u2580\u2580 \u2580\u2580\u2580\u2580 \u2580\u2580",
|
|
109091
|
+
` \u2571 \u2660 \u2572 ${wave2}`,
|
|
109092
|
+
" \u2581\u2581\u2581\u2581\u2581\u2581\u2571 \u2660 \u2660 \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"
|
|
108119
109093
|
].join("\n");
|
|
108120
109094
|
}
|
|
108121
|
-
function buildColoredScene(isDark) {
|
|
109095
|
+
function buildColoredScene(isDark, frame = 0, maxFrames = 0) {
|
|
108122
109096
|
const pk = themeColorSequence("chrome");
|
|
108123
109097
|
const sk = themeColorSequence("warning");
|
|
108124
|
-
const st = themeColorSequence("muted");
|
|
108125
109098
|
const tr = themeColorSequence("success");
|
|
108126
109099
|
const wv = themeColorSequence("info");
|
|
108127
109100
|
const ac = themeColorSequence("accent");
|
|
108128
|
-
const
|
|
109101
|
+
const mu = themeColorSequence("muted");
|
|
108129
109102
|
const r = "\x1B[39m";
|
|
108130
109103
|
const b = "\x1B[1m";
|
|
108131
109104
|
const rs = "\x1B[0m";
|
|
108132
|
-
|
|
109105
|
+
let skyLine = ` ${sk}${isDark ? "\u{1F319}" : "\u2600"}${r}`;
|
|
109106
|
+
if (isDark) {
|
|
109107
|
+
const star1 = frame % 6 < 3 ? "\u2726" : "\u22C6";
|
|
109108
|
+
const star2 = frame % 4 < 2 ? "\u22C6" : "\xB7";
|
|
109109
|
+
const star3 = frame % 5 < 2 ? "\xB7" : "\u2726";
|
|
109110
|
+
skyLine = ` ${mu}${star1}${r} ${sk}\u{1F319}${r} ${mu}${star2}${r} ${mu}${star3}${r}`;
|
|
109111
|
+
}
|
|
109112
|
+
const wavePattern = "_.~^~.";
|
|
109113
|
+
const longWave = wavePattern.repeat(10);
|
|
109114
|
+
const offset = frame % wavePattern.length;
|
|
109115
|
+
const wave2 = longWave.slice(offset, offset + 25);
|
|
109116
|
+
const waveStr = `${wv}${wave2.slice(0, 20)}${r}${mu}${wave2.slice(20, 25)}${r}`;
|
|
109117
|
+
const line1 = "\u2588\u2584 \u2588 \u2584\u2580\u2580\u2584 \u2588 \u2584\u2580\u2580\u2584";
|
|
109118
|
+
const line2 = "\u2588 \u2580\u2588 \u2588 \u2588 \u2588 \u2588 \u2588";
|
|
109119
|
+
const line3 = "\u2580 \u2580 \u2580\u2580 \u2580\u2580\u2580\u2580 \u2580\u2580";
|
|
109120
|
+
const sweepEndFrame = maxFrames > 3 ? maxFrames - 3 : maxFrames;
|
|
109121
|
+
const sweepLen = maxFrames === 0 ? 21 : Math.min(21, Math.floor(frame / sweepEndFrame * 21));
|
|
109122
|
+
const colorLine = (str, bold) => {
|
|
109123
|
+
const active = str.slice(0, sweepLen);
|
|
109124
|
+
const dimmed = str.slice(sweepLen);
|
|
109125
|
+
return `${bold ? b : ""}${ac}${active}${r}${mu}${dimmed}${r}${bold ? rs : ""}`;
|
|
109126
|
+
};
|
|
109127
|
+
const nolo1 = colorLine(line1, true);
|
|
109128
|
+
const nolo2 = colorLine(line2, false);
|
|
109129
|
+
const nolo3 = colorLine(line3, false);
|
|
108133
109130
|
return [
|
|
108134
|
-
|
|
108135
|
-
|
|
108136
|
-
` ${pk}\u2571 \u2572${r}`,
|
|
108137
|
-
|
|
108138
|
-
` ${pk}\u2571${r}
|
|
108139
|
-
` ${pk}\u2581\u2581\u2581\u2581\u2581\u2581\u2571${r}
|
|
108140
|
-
` ${b}${ac}\u2588\u2584 \u2588 \u2584\u2580\u2580\u2584 \u2588 \u2584\u2580\u2580\u2584${rs}`,
|
|
108141
|
-
` ${ac}\u2588 \u2580\u2588 \u2588 \u2588 \u2588 \u2588 \u2588${r}`,
|
|
108142
|
-
` ${cr}\u2580 \u2580 \u2580\u2580 \u2580\u2580\u2580\u2580 \u2580\u2580${r}`,
|
|
108143
|
-
` ${wv}\u2570\u256E~\u2248~~\u2248~~\u2248~~\u2248~~\u2248~~\u2248~~\u2248~~\u2248~\u2570\u256E\u2248~${r}`
|
|
109131
|
+
skyLine,
|
|
109132
|
+
` ${pk}\u2571\u2572${r} ${nolo1}`,
|
|
109133
|
+
` ${pk}\u2571 \u2572 \u2571\u2572${r} ${nolo2}`,
|
|
109134
|
+
` ${pk}\u2571 \u2572\u2571 \u2572${r} ${nolo3}`,
|
|
109135
|
+
` ${pk}\u2571${r} ${tr}\u2660${r} ${pk}\u2572${r} ${waveStr}`,
|
|
109136
|
+
` ${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}`
|
|
108144
109137
|
].join("\n");
|
|
108145
109138
|
}
|
|
108146
|
-
function renderWelcome(state4) {
|
|
109139
|
+
function renderWelcome(state4, frame = 0, maxFrames = 0, columns) {
|
|
108147
109140
|
const colorEnabled = resolveCliColorEnabled();
|
|
108148
109141
|
const brightness = resolveTuiBrightness();
|
|
108149
109142
|
const isDark = brightness === "dark";
|
|
108150
|
-
|
|
109143
|
+
let sceneArt = colorEnabled ? buildColoredScene(isDark, frame, maxFrames) : buildPlainScene(isDark, frame, maxFrames);
|
|
109144
|
+
if (typeof columns === "number" && columns > 0) {
|
|
109145
|
+
const widestSceneCol = sceneArt.split("\n").reduce((max, line) => Math.max(max, displayWidth2(stripAnsi(line))), 0);
|
|
109146
|
+
if (columns < widestSceneCol) sceneArt = "";
|
|
109147
|
+
}
|
|
108151
109148
|
const versionLine = colorEnabled ? `\x1B[1m${themeColorSequence("accent")}nolo\x1B[0m ${state4.cliVersion ?? ""} | server ${state4.serverUrl}`.replace(" |", " |") : `nolo ${state4.cliVersion ?? ""} | server ${state4.serverUrl}`.replace(" |", " |");
|
|
108152
|
-
|
|
108153
|
-
|
|
108154
|
-
versionLine,
|
|
108155
|
-
t("welcomeHint"),
|
|
108156
|
-
""
|
|
108157
|
-
].join("\n");
|
|
109149
|
+
const body = sceneArt ? [sceneArt, versionLine, t("welcomeHint"), ""] : [versionLine, t("welcomeHint"), ""];
|
|
109150
|
+
return body.join("\n");
|
|
108158
109151
|
}
|
|
108159
109152
|
function renderPrompt(_state) {
|
|
108160
109153
|
return t("promptLabel");
|
|
@@ -108262,6 +109255,7 @@ var init_sessionRender = __esm({
|
|
|
108262
109255
|
init_dialogFrame();
|
|
108263
109256
|
init_i18n2();
|
|
108264
109257
|
init_readlineWorkspace();
|
|
109258
|
+
init_tuiAnsi();
|
|
108265
109259
|
init_theme();
|
|
108266
109260
|
init_processRegistry();
|
|
108267
109261
|
}
|
|
@@ -109397,278 +110391,6 @@ var init_chatQueueTuiBinding = __esm({
|
|
|
109397
110391
|
}
|
|
109398
110392
|
});
|
|
109399
110393
|
|
|
109400
|
-
// packages/cli/tui/tuiAnsi.ts
|
|
109401
|
-
function stripAnsi(text) {
|
|
109402
|
-
return text.replace(OSC_HYPERLINK_REGEX, "").replace(ANSI_ESCAPE_REGEX, "");
|
|
109403
|
-
}
|
|
109404
|
-
function applyTerminalOutputToText(existing, chunk) {
|
|
109405
|
-
if (!chunk) return existing;
|
|
109406
|
-
let text = existing;
|
|
109407
|
-
let index = 0;
|
|
109408
|
-
while (index < chunk.length) {
|
|
109409
|
-
if (chunk[index] === "\x1B") {
|
|
109410
|
-
const sgr = SGR_SEQUENCE_REGEX.exec(chunk.slice(index));
|
|
109411
|
-
if (sgr) {
|
|
109412
|
-
text += sgr[0];
|
|
109413
|
-
index += sgr[0].length;
|
|
109414
|
-
continue;
|
|
109415
|
-
}
|
|
109416
|
-
const osc = chunk.slice(index).match(/^\x1b\]8;;[^\x07\x1b]*(?:\x07|\x1b\\)/);
|
|
109417
|
-
if (osc) {
|
|
109418
|
-
index += osc[0].length;
|
|
109419
|
-
continue;
|
|
109420
|
-
}
|
|
109421
|
-
const csi = chunk.slice(index).match(/^\x1b\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]/);
|
|
109422
|
-
if (csi) {
|
|
109423
|
-
index += csi[0].length;
|
|
109424
|
-
continue;
|
|
109425
|
-
}
|
|
109426
|
-
index += 1;
|
|
109427
|
-
continue;
|
|
109428
|
-
}
|
|
109429
|
-
const ch = chunk[index];
|
|
109430
|
-
if (ch === "\r") {
|
|
109431
|
-
const lastNl = text.lastIndexOf("\n");
|
|
109432
|
-
text = lastNl === -1 ? "" : text.slice(0, lastNl + 1);
|
|
109433
|
-
index += 1;
|
|
109434
|
-
continue;
|
|
109435
|
-
}
|
|
109436
|
-
if (ch === "\n") {
|
|
109437
|
-
text += "\n";
|
|
109438
|
-
index += 1;
|
|
109439
|
-
continue;
|
|
109440
|
-
}
|
|
109441
|
-
if (ch === "\b") {
|
|
109442
|
-
const trailing = TRAILING_SGR_REGEX.exec(text);
|
|
109443
|
-
const sgrTail = trailing ? trailing[0] : "";
|
|
109444
|
-
const head = sgrTail ? text.slice(0, -sgrTail.length) : text;
|
|
109445
|
-
if (head.length > 0 && head[head.length - 1] !== "\n") {
|
|
109446
|
-
text = head.slice(0, -1) + sgrTail;
|
|
109447
|
-
}
|
|
109448
|
-
index += 1;
|
|
109449
|
-
continue;
|
|
109450
|
-
}
|
|
109451
|
-
const code = ch.charCodeAt(0);
|
|
109452
|
-
if (code < 32 && ch !== " " || code === 127) {
|
|
109453
|
-
index += 1;
|
|
109454
|
-
continue;
|
|
109455
|
-
}
|
|
109456
|
-
text += ch;
|
|
109457
|
-
index += 1;
|
|
109458
|
-
}
|
|
109459
|
-
return text;
|
|
109460
|
-
}
|
|
109461
|
-
function displayWidth2(str) {
|
|
109462
|
-
let width = 0;
|
|
109463
|
-
for (const char of str) {
|
|
109464
|
-
const code = char.codePointAt(0) ?? 0;
|
|
109465
|
-
if (code < 32 || code === 127) continue;
|
|
109466
|
-
if (code >= 4352 && code <= 4447 || // 0x2768-0x2775 (ornamental brackets, incl. the ❯ prompt at U+276F)
|
|
109467
|
-
// render narrow in terminals; counting them wide drifts the cursor.
|
|
109468
|
-
code >= 9728 && code <= 10175 && !(code >= 10088 && code <= 10101) || // 0x2B00-0x2BFF (Misc Symbols and Arrows, incl. ⬢ U+2B22 used as the
|
|
109469
|
-
// status-line agent icon) render double-wide in common monospace fonts;
|
|
109470
|
-
// counting ⬢ as width 1 drifts the whole status line right of the icon.
|
|
109471
|
-
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 ‘ ’).
|
|
109472
|
-
// In CJK locale + CJK fonts these render double-wide like 全角 punctuation;
|
|
109473
|
-
// in English fonts they stay width 1. Follow the active locale so Chinese
|
|
109474
|
-
// replies align correctly without breaking English terminal output.
|
|
109475
|
-
getCliLocale() === "zh" && (code === 8220 || code === 8221 || code === 8216 || code === 8217)) {
|
|
109476
|
-
width += 2;
|
|
109477
|
-
} else {
|
|
109478
|
-
width += 1;
|
|
109479
|
-
}
|
|
109480
|
-
}
|
|
109481
|
-
return width;
|
|
109482
|
-
}
|
|
109483
|
-
function visibleWidth(str) {
|
|
109484
|
-
return displayWidth2(stripAnsi(str));
|
|
109485
|
-
}
|
|
109486
|
-
function truncateAnsi(text, maxWidth) {
|
|
109487
|
-
if (maxWidth <= 0) return "";
|
|
109488
|
-
if (visibleWidth(text) <= maxWidth) return text;
|
|
109489
|
-
let width = 0;
|
|
109490
|
-
let out = "";
|
|
109491
|
-
let i = 0;
|
|
109492
|
-
let sawAnsi = false;
|
|
109493
|
-
while (i < text.length) {
|
|
109494
|
-
if (text[i] === "\x1B" && text[i + 1] === "[") {
|
|
109495
|
-
sawAnsi = true;
|
|
109496
|
-
let j = i + 2;
|
|
109497
|
-
while (j < text.length) {
|
|
109498
|
-
const code = text.charCodeAt(j);
|
|
109499
|
-
j += 1;
|
|
109500
|
-
if (code >= 64 && code <= 126) break;
|
|
109501
|
-
}
|
|
109502
|
-
out += text.slice(i, j);
|
|
109503
|
-
i = j;
|
|
109504
|
-
continue;
|
|
109505
|
-
}
|
|
109506
|
-
const codePoint = text.codePointAt(i) ?? 0;
|
|
109507
|
-
const char = String.fromCodePoint(codePoint);
|
|
109508
|
-
const charWidth = displayWidth2(char);
|
|
109509
|
-
if (width + charWidth > maxWidth) break;
|
|
109510
|
-
out += char;
|
|
109511
|
-
width += charWidth;
|
|
109512
|
-
i += char.length;
|
|
109513
|
-
}
|
|
109514
|
-
return sawAnsi ? `${out}\x1B[0m` : out;
|
|
109515
|
-
}
|
|
109516
|
-
function fitAnsiLine(text, width, ellipsis = "\u2026") {
|
|
109517
|
-
if (width <= 0) return "";
|
|
109518
|
-
if (visibleWidth(text) <= width) return text;
|
|
109519
|
-
const ellipsisWidth = displayWidth2(ellipsis);
|
|
109520
|
-
if (width < ellipsisWidth) return truncateAnsi(text, width);
|
|
109521
|
-
if (width === ellipsisWidth) return truncateAnsi(ellipsis, width) || truncateAnsi(text, width);
|
|
109522
|
-
return `${truncateAnsi(text, width - ellipsisWidth)}${ellipsis}`;
|
|
109523
|
-
}
|
|
109524
|
-
function countPhysicalLines(text, columns) {
|
|
109525
|
-
const lines = text.split("\n");
|
|
109526
|
-
let total = 0;
|
|
109527
|
-
for (const line of lines) {
|
|
109528
|
-
const width = displayWidth2(line);
|
|
109529
|
-
total += Math.max(1, Math.ceil(width / columns));
|
|
109530
|
-
}
|
|
109531
|
-
return Math.max(total, 1);
|
|
109532
|
-
}
|
|
109533
|
-
function takeDisplayWidth(text, width) {
|
|
109534
|
-
let used = 0;
|
|
109535
|
-
let index = 0;
|
|
109536
|
-
for (const char of text) {
|
|
109537
|
-
const charWidth = displayWidth2(char);
|
|
109538
|
-
if (used + charWidth > width && used > 0) break;
|
|
109539
|
-
used += charWidth;
|
|
109540
|
-
index += char.length;
|
|
109541
|
-
}
|
|
109542
|
-
return { prefix: text.slice(0, index), rest: text.slice(index) };
|
|
109543
|
-
}
|
|
109544
|
-
function padOrTruncateToWidth(text, width) {
|
|
109545
|
-
const textWidth = visibleWidth(text);
|
|
109546
|
-
if (textWidth > width) {
|
|
109547
|
-
return truncateAnsi(text, width);
|
|
109548
|
-
}
|
|
109549
|
-
return `${text}${" ".repeat(width - textWidth)}`;
|
|
109550
|
-
}
|
|
109551
|
-
function tokenizeAnsiLine(line) {
|
|
109552
|
-
const tokens = [];
|
|
109553
|
-
let index = 0;
|
|
109554
|
-
while (index < line.length) {
|
|
109555
|
-
if (line[index] === "\x1B") {
|
|
109556
|
-
const osc = line.slice(index).match(/^\x1b\]8;;[^\x07\x1b]*(?:\x07|\x1b\\)/);
|
|
109557
|
-
if (osc) {
|
|
109558
|
-
tokens.push({ kind: "sgr", value: osc[0], width: 0 });
|
|
109559
|
-
index += osc[0].length;
|
|
109560
|
-
continue;
|
|
109561
|
-
}
|
|
109562
|
-
const sgr = SGR_SEQUENCE_REGEX.exec(line.slice(index));
|
|
109563
|
-
if (sgr) {
|
|
109564
|
-
tokens.push({ kind: "sgr", value: sgr[0], width: 0 });
|
|
109565
|
-
index += sgr[0].length;
|
|
109566
|
-
continue;
|
|
109567
|
-
}
|
|
109568
|
-
}
|
|
109569
|
-
const codePoint = line.codePointAt(index) ?? 0;
|
|
109570
|
-
const value = String.fromCodePoint(codePoint);
|
|
109571
|
-
tokens.push({ kind: "char", value, width: displayWidth2(value) });
|
|
109572
|
-
index += value.length;
|
|
109573
|
-
}
|
|
109574
|
-
return tokens;
|
|
109575
|
-
}
|
|
109576
|
-
function wrapTranscriptLine(line, columns) {
|
|
109577
|
-
if (line === "") return [""];
|
|
109578
|
-
const tokens = tokenizeAnsiLine(line);
|
|
109579
|
-
const result = [];
|
|
109580
|
-
let activeStyles = [];
|
|
109581
|
-
const applyStyleToken = (value) => {
|
|
109582
|
-
if (SGR_RESET_REGEX.test(value)) {
|
|
109583
|
-
activeStyles = [];
|
|
109584
|
-
} else {
|
|
109585
|
-
activeStyles.push(value);
|
|
109586
|
-
}
|
|
109587
|
-
};
|
|
109588
|
-
let start = 0;
|
|
109589
|
-
while (start < tokens.length) {
|
|
109590
|
-
if (tokens.slice(start).every((token) => token.kind === "sgr")) {
|
|
109591
|
-
if (result.length > 0) break;
|
|
109592
|
-
}
|
|
109593
|
-
const openingStyles = [...activeStyles];
|
|
109594
|
-
let width = 0;
|
|
109595
|
-
let end = start;
|
|
109596
|
-
let lastBreak = -1;
|
|
109597
|
-
while (end < tokens.length) {
|
|
109598
|
-
const token = tokens[end];
|
|
109599
|
-
if (token.kind === "sgr") {
|
|
109600
|
-
end += 1;
|
|
109601
|
-
continue;
|
|
109602
|
-
}
|
|
109603
|
-
if (width + token.width > columns && width > 0) break;
|
|
109604
|
-
width += token.width;
|
|
109605
|
-
end += 1;
|
|
109606
|
-
if (token.value === " " || token.value === " ") {
|
|
109607
|
-
lastBreak = end;
|
|
109608
|
-
}
|
|
109609
|
-
}
|
|
109610
|
-
let segmentEnd = end;
|
|
109611
|
-
if (end < tokens.length && lastBreak > start) {
|
|
109612
|
-
const overflowToken = tokens[end];
|
|
109613
|
-
if (overflowToken.kind === "char" && overflowToken.value !== " " && overflowToken.width === 1) {
|
|
109614
|
-
segmentEnd = lastBreak;
|
|
109615
|
-
}
|
|
109616
|
-
}
|
|
109617
|
-
if (segmentEnd === start) segmentEnd = start + 1;
|
|
109618
|
-
let segment = "";
|
|
109619
|
-
let sawStyle = openingStyles.length > 0;
|
|
109620
|
-
for (let i = start; i < segmentEnd; i += 1) {
|
|
109621
|
-
const token = tokens[i];
|
|
109622
|
-
segment += token.value;
|
|
109623
|
-
if (token.kind === "sgr") {
|
|
109624
|
-
sawStyle = true;
|
|
109625
|
-
applyStyleToken(token.value);
|
|
109626
|
-
}
|
|
109627
|
-
}
|
|
109628
|
-
const prefix = openingStyles.join("");
|
|
109629
|
-
const needsReset = (sawStyle || activeStyles.length > 0) && !segment.endsWith("\x1B[0m");
|
|
109630
|
-
result.push(`${prefix}${segment}${needsReset ? "\x1B[0m" : ""}`);
|
|
109631
|
-
start = segmentEnd;
|
|
109632
|
-
while (start < tokens.length) {
|
|
109633
|
-
const token = tokens[start];
|
|
109634
|
-
if (token.kind === "char" && token.value === " ") {
|
|
109635
|
-
start += 1;
|
|
109636
|
-
continue;
|
|
109637
|
-
}
|
|
109638
|
-
break;
|
|
109639
|
-
}
|
|
109640
|
-
}
|
|
109641
|
-
return result.length > 0 ? result : [""];
|
|
109642
|
-
}
|
|
109643
|
-
function wrapTextToLines(text, columns) {
|
|
109644
|
-
const result = [];
|
|
109645
|
-
for (const logicalLine of text.split("\n")) {
|
|
109646
|
-
if (logicalLine === "") {
|
|
109647
|
-
result.push("");
|
|
109648
|
-
continue;
|
|
109649
|
-
}
|
|
109650
|
-
let remaining = logicalLine;
|
|
109651
|
-
while (remaining.length > 0) {
|
|
109652
|
-
const { prefix, rest } = takeDisplayWidth(remaining, columns);
|
|
109653
|
-
result.push(prefix);
|
|
109654
|
-
remaining = rest;
|
|
109655
|
-
}
|
|
109656
|
-
}
|
|
109657
|
-
return result;
|
|
109658
|
-
}
|
|
109659
|
-
var ANSI_ESCAPE_REGEX, OSC_HYPERLINK_REGEX, SGR_SEQUENCE_REGEX, TRAILING_SGR_REGEX, SGR_RESET_REGEX;
|
|
109660
|
-
var init_tuiAnsi = __esm({
|
|
109661
|
-
"packages/cli/tui/tuiAnsi.ts"() {
|
|
109662
|
-
"use strict";
|
|
109663
|
-
init_i18n2();
|
|
109664
|
-
ANSI_ESCAPE_REGEX = /\x1b\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]/g;
|
|
109665
|
-
OSC_HYPERLINK_REGEX = /\x1b\]8;;[^\x07\x1b]*(?:\x07|\x1b\\)\x1b\]8;;(?:\x07|\x1b\\)|\x1b\]8;;[^\x07\x1b]*(?:\x07|\x1b\\)/g;
|
|
109666
|
-
SGR_SEQUENCE_REGEX = /^\x1b\[[0-9;]*m/;
|
|
109667
|
-
TRAILING_SGR_REGEX = /(?:\x1b\[[0-9;]*m)+$/;
|
|
109668
|
-
SGR_RESET_REGEX = /^\x1b\[0?m$/;
|
|
109669
|
-
}
|
|
109670
|
-
});
|
|
109671
|
-
|
|
109672
110394
|
// packages/cli/tui/tuiScrollbar.ts
|
|
109673
110395
|
function parseScrollAction(sequence) {
|
|
109674
110396
|
const mouse = SGR_MOUSE_REGEX.exec(sequence);
|
|
@@ -110639,49 +111361,27 @@ async function startTuiWorkspace(options) {
|
|
|
110639
111361
|
stdout: output2
|
|
110640
111362
|
});
|
|
110641
111363
|
if (detected) setActiveBrightness(detected);
|
|
110642
|
-
output2.
|
|
111364
|
+
const bannerColumns = output2.columns;
|
|
111365
|
+
output2.write(renderWelcome(state4, 0, 0, bannerColumns));
|
|
110643
111366
|
let fixedInput = createNoopFixedInput();
|
|
110644
111367
|
let buffer = "";
|
|
110645
111368
|
let cursorPos = 0;
|
|
110646
111369
|
let activeTurnAbort = null;
|
|
110647
|
-
|
|
110648
|
-
|
|
110649
|
-
|
|
110650
|
-
|
|
110651
|
-
const stopActivity = () => {
|
|
110652
|
-
if (activityTimer !== null) {
|
|
110653
|
-
clearInterval(activityTimer);
|
|
110654
|
-
activityTimer = null;
|
|
110655
|
-
}
|
|
110656
|
-
activityLabel = null;
|
|
110657
|
-
activityStartedAt = 0;
|
|
110658
|
-
};
|
|
110659
|
-
const activityReporter = (label) => {
|
|
110660
|
-
if (label !== null) {
|
|
110661
|
-
activityLabel = label;
|
|
110662
|
-
if (activityStartedAt === 0) {
|
|
110663
|
-
activityStartedAt = Date.now();
|
|
110664
|
-
}
|
|
110665
|
-
if (activityTimer === null) {
|
|
110666
|
-
activityTimer = setInterval(() => {
|
|
110667
|
-
activityFrameIndex += 1;
|
|
110668
|
-
if (fixedInput.active && !fixedInput.isPaused()) {
|
|
110669
|
-
output2.write("\x1B[?2026h\x1B[?25l");
|
|
110670
|
-
try {
|
|
110671
|
-
fixedInput.repaint(buffer);
|
|
110672
|
-
} finally {
|
|
110673
|
-
output2.write("\x1B[?25h\x1B[?2026l");
|
|
110674
|
-
}
|
|
110675
|
-
}
|
|
110676
|
-
}, 150);
|
|
110677
|
-
}
|
|
110678
|
-
} else {
|
|
110679
|
-
stopActivity();
|
|
111370
|
+
const activityIndicator = createActivityIndicator({
|
|
111371
|
+
isTurnActive: () => activeTurnAbort !== null,
|
|
111372
|
+
fallbackLabel: () => `${state4.agentName} -> working`,
|
|
111373
|
+
onRepaint: () => {
|
|
110680
111374
|
if (fixedInput.active && !fixedInput.isPaused()) {
|
|
110681
|
-
|
|
111375
|
+
output2.write("\x1B[?2026h\x1B[?25l");
|
|
111376
|
+
try {
|
|
111377
|
+
fixedInput.repaint(buffer);
|
|
111378
|
+
} finally {
|
|
111379
|
+
output2.write("\x1B[?25h\x1B[?2026l");
|
|
111380
|
+
}
|
|
110682
111381
|
}
|
|
110683
111382
|
}
|
|
110684
|
-
};
|
|
111383
|
+
});
|
|
111384
|
+
const activityReporter = (label) => activityIndicator.report(label);
|
|
110685
111385
|
let explicitAgentSwitch = false;
|
|
110686
111386
|
let copyViewExitResolver = null;
|
|
110687
111387
|
const history = createTurnHistory();
|
|
@@ -110780,25 +111480,15 @@ ${t("copyViewHint")}
|
|
|
110780
111480
|
scheduleRender();
|
|
110781
111481
|
}) : output2;
|
|
110782
111482
|
const requestUserChoice = isInteractiveInput(input2) && dialogHost ? async (req) => {
|
|
110783
|
-
const items = req.choices.map((c) => ({
|
|
110784
|
-
label: c.label
|
|
110785
|
-
}));
|
|
110786
111483
|
try {
|
|
110787
|
-
|
|
110788
|
-
(anchor) =>
|
|
110789
|
-
|
|
110790
|
-
title: req.question,
|
|
111484
|
+
return await dialogHost.run(
|
|
111485
|
+
(anchor) => runAskChoiceDialog({
|
|
111486
|
+
request: req,
|
|
110791
111487
|
input: input2,
|
|
110792
111488
|
output: output2,
|
|
110793
111489
|
...anchor
|
|
110794
111490
|
})
|
|
110795
111491
|
);
|
|
110796
|
-
if (pickResult.kind === "selected") {
|
|
110797
|
-
const choice = req.choices[pickResult.index];
|
|
110798
|
-
const userMessage = choice?.userMessage?.trim() || choice?.label || "";
|
|
110799
|
-
return { kind: "selected", userMessage, label: choice?.label ?? "" };
|
|
110800
|
-
}
|
|
110801
|
-
return { kind: "cancelled" };
|
|
110802
111492
|
} catch {
|
|
110803
111493
|
return { kind: "cancelled" };
|
|
110804
111494
|
}
|
|
@@ -110851,7 +111541,7 @@ ${t("copyViewHint")}
|
|
|
110851
111541
|
}
|
|
110852
111542
|
return { ok: !wasAborted, aborted: wasAborted };
|
|
110853
111543
|
} finally {
|
|
110854
|
-
|
|
111544
|
+
activityIndicator.stop();
|
|
110855
111545
|
activeTurnAbort = null;
|
|
110856
111546
|
explicitAgentSwitch = false;
|
|
110857
111547
|
}
|
|
@@ -111210,17 +111900,15 @@ ${err.message}` : ""}`
|
|
|
111210
111900
|
return base;
|
|
111211
111901
|
},
|
|
111212
111902
|
getActivityLine: () => {
|
|
111213
|
-
|
|
111903
|
+
const view = activityIndicator.getView();
|
|
111904
|
+
if (view === null) return null;
|
|
111214
111905
|
const colorEnabled = resolveCliColorEnabled();
|
|
111215
|
-
const
|
|
111216
|
-
const frame = FRAMES[activityFrameIndex % FRAMES.length];
|
|
111217
|
-
const elapsedSec = activityStartedAt > 0 ? Math.max(0, Math.floor((Date.now() - activityStartedAt) / 1e3)) : 0;
|
|
111218
|
-
const elapsed = formatElapsedSeconds(elapsedSec);
|
|
111906
|
+
const elapsed = formatElapsedSeconds(view.elapsedSec);
|
|
111219
111907
|
const stopHint = t("stopHint");
|
|
111220
111908
|
if (!colorEnabled) {
|
|
111221
|
-
return `${frame} ${
|
|
111909
|
+
return `${view.frame} ${view.label} (${elapsed}) \xB7 ${stopHint}`;
|
|
111222
111910
|
}
|
|
111223
|
-
return themeText(frame, "accent") + " " + themeText(
|
|
111911
|
+
return themeText(view.frame, "accent") + " " + themeText(view.label, "muted") + themeText(` (${elapsed})`, "chrome") + themeText(` \xB7 ${stopHint}`, "chrome");
|
|
111224
111912
|
},
|
|
111225
111913
|
getQueueLines: () => {
|
|
111226
111914
|
if (!chatQueueBinding || chatQueueBinding.queueLength() === 0) return [];
|
|
@@ -111309,12 +111997,27 @@ ${err.message}` : ""}`
|
|
|
111309
111997
|
if (busyLock) {
|
|
111310
111998
|
const submittedText2 = result.submit;
|
|
111311
111999
|
const trimmedText = submittedText2.trim();
|
|
111312
|
-
|
|
112000
|
+
const busySlashCommand = trimmedText.split(/\s+/)[0]?.toLowerCase();
|
|
112001
|
+
const isBusyLocalSlash = busySlashCommand === "/context" || busySlashCommand === "/ctx" || busySlashCommand === "/switch";
|
|
112002
|
+
if (isBusyLocalSlash) {
|
|
112003
|
+
const beforeAgentKey = state4.agentKey;
|
|
111313
112004
|
const res = handleTuiInput(submittedText2, state4);
|
|
111314
|
-
|
|
111315
|
-
|
|
111316
|
-
|
|
112005
|
+
if (res.action) {
|
|
112006
|
+
output2.write(
|
|
112007
|
+
"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"
|
|
112008
|
+
);
|
|
112009
|
+
} else {
|
|
112010
|
+
state4 = res.nextState;
|
|
112011
|
+
let msg = res.output;
|
|
112012
|
+
if (busySlashCommand === "/switch" && res.nextState.agentKey !== beforeAgentKey) {
|
|
112013
|
+
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.";
|
|
112014
|
+
msg = msg ? `${msg}
|
|
112015
|
+
${hint}` : hint;
|
|
112016
|
+
}
|
|
112017
|
+
if (msg) {
|
|
112018
|
+
output2.write(`${msg}
|
|
111317
112019
|
`);
|
|
112020
|
+
}
|
|
111318
112021
|
}
|
|
111319
112022
|
buffer = "";
|
|
111320
112023
|
cursorPos2 = 0;
|
|
@@ -111537,8 +112240,9 @@ var init_readlineWorkspace = __esm({
|
|
|
111537
112240
|
init_updateCommands();
|
|
111538
112241
|
init_processSpawn();
|
|
111539
112242
|
init_confirmDialog();
|
|
111540
|
-
|
|
112243
|
+
init_askChoiceDialog();
|
|
111541
112244
|
init_dialogHost();
|
|
112245
|
+
init_activityIndicator();
|
|
111542
112246
|
init_agentPicker();
|
|
111543
112247
|
init_agentCatalog();
|
|
111544
112248
|
init_dialogPicker();
|