nolo-cli 0.6.1 → 0.8.0
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 +791 -102
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -16077,12 +16077,14 @@ function buildLocalToolExecutors(args2) {
|
|
|
16077
16077
|
})();
|
|
16078
16078
|
const question = String(parsedArgs.question ?? "").trim();
|
|
16079
16079
|
const choices = Array.isArray(parsedArgs.choices) ? parsedArgs.choices : [];
|
|
16080
|
+
const questions = Array.isArray(parsedArgs.questions) ? parsedArgs.questions : void 0;
|
|
16080
16081
|
const blocking = parsedArgs.blocking !== false;
|
|
16081
|
-
|
|
16082
|
+
const hasQuestions = questions && questions.length > 0;
|
|
16083
|
+
if (!hasQuestions && (!question || choices.length === 0)) {
|
|
16082
16084
|
return {
|
|
16083
16085
|
content: JSON.stringify({
|
|
16084
16086
|
error: "ui_ask_choice",
|
|
16085
|
-
detail: "ui_ask_choice \u9700\u8981 question \
|
|
16087
|
+
detail: "ui_ask_choice \u9700\u8981 question+choices \u6216 questions\u3002"
|
|
16086
16088
|
}),
|
|
16087
16089
|
metadata: { uiAskChoice: true, error: true }
|
|
16088
16090
|
};
|
|
@@ -16090,10 +16092,28 @@ function buildLocalToolExecutors(args2) {
|
|
|
16090
16092
|
if (args2.requestUserChoice) {
|
|
16091
16093
|
try {
|
|
16092
16094
|
const result = await args2.requestUserChoice({
|
|
16093
|
-
question,
|
|
16094
|
-
choices,
|
|
16095
|
-
blocking
|
|
16095
|
+
question: hasQuestions ? questions[0].question : question,
|
|
16096
|
+
choices: hasQuestions ? questions[0].choices : choices,
|
|
16097
|
+
blocking,
|
|
16098
|
+
...hasQuestions ? { questions } : {}
|
|
16096
16099
|
});
|
|
16100
|
+
if (result.kind === "multi-submitted") {
|
|
16101
|
+
return {
|
|
16102
|
+
content: JSON.stringify({
|
|
16103
|
+
type: "ui_ask_choice",
|
|
16104
|
+
question,
|
|
16105
|
+
choices,
|
|
16106
|
+
blocking,
|
|
16107
|
+
...hasQuestions ? { questions } : {},
|
|
16108
|
+
answers: result.answers,
|
|
16109
|
+
selected: {
|
|
16110
|
+
label: result.answers.map((a) => a.userMessage).join(", "),
|
|
16111
|
+
userMessage: result.userMessage
|
|
16112
|
+
}
|
|
16113
|
+
}),
|
|
16114
|
+
metadata: { uiAskChoice: true, resolved: true }
|
|
16115
|
+
};
|
|
16116
|
+
}
|
|
16097
16117
|
if (result.kind === "selected") {
|
|
16098
16118
|
return {
|
|
16099
16119
|
content: JSON.stringify({
|
|
@@ -16101,6 +16121,7 @@ function buildLocalToolExecutors(args2) {
|
|
|
16101
16121
|
question,
|
|
16102
16122
|
choices,
|
|
16103
16123
|
blocking,
|
|
16124
|
+
...hasQuestions ? { questions } : {},
|
|
16104
16125
|
selected: {
|
|
16105
16126
|
label: result.label,
|
|
16106
16127
|
userMessage: result.userMessage
|
|
@@ -16115,6 +16136,7 @@ function buildLocalToolExecutors(args2) {
|
|
|
16115
16136
|
question,
|
|
16116
16137
|
choices,
|
|
16117
16138
|
blocking,
|
|
16139
|
+
...hasQuestions ? { questions } : {},
|
|
16118
16140
|
selected: { label: "", userMessage: "" },
|
|
16119
16141
|
cancelled: true
|
|
16120
16142
|
}),
|
|
@@ -16128,7 +16150,8 @@ function buildLocalToolExecutors(args2) {
|
|
|
16128
16150
|
type: "ui_ask_choice",
|
|
16129
16151
|
question,
|
|
16130
16152
|
choices,
|
|
16131
|
-
blocking
|
|
16153
|
+
blocking,
|
|
16154
|
+
...hasQuestions ? { questions } : {}
|
|
16132
16155
|
}),
|
|
16133
16156
|
metadata: { uiAskChoice: true }
|
|
16134
16157
|
};
|
|
@@ -37355,11 +37378,24 @@ var init_dialogUrl = __esm({
|
|
|
37355
37378
|
|
|
37356
37379
|
// packages/ai/tools/uiAskChoiceTool.ts
|
|
37357
37380
|
async function uiAskChoiceFunc(args2, _thunkApi) {
|
|
37381
|
+
const blocking = args2?.blocking !== false;
|
|
37382
|
+
if (Array.isArray(args2?.questions) && args2.questions.length > 0) {
|
|
37383
|
+
const firstQ = args2.questions[0];
|
|
37384
|
+
return {
|
|
37385
|
+
rawData: {
|
|
37386
|
+
type: "ui_ask_choice",
|
|
37387
|
+
question: firstQ?.question ?? "",
|
|
37388
|
+
choices: firstQ?.choices ?? [],
|
|
37389
|
+
blocking,
|
|
37390
|
+
questions: args2.questions
|
|
37391
|
+
},
|
|
37392
|
+
displayData: args2.questions.map((q) => q.question).join(" / ")
|
|
37393
|
+
};
|
|
37394
|
+
}
|
|
37358
37395
|
const question = String(args2?.question ?? "").trim();
|
|
37359
37396
|
const choices = Array.isArray(args2?.choices) ? args2.choices : [];
|
|
37360
|
-
const blocking = args2?.blocking !== false;
|
|
37361
37397
|
if (!question || choices.length === 0) {
|
|
37362
|
-
throw new Error("ui_ask_choice \u9700\u8981 question \
|
|
37398
|
+
throw new Error("ui_ask_choice \u9700\u8981 question+choices \u6216 questions\u3002");
|
|
37363
37399
|
}
|
|
37364
37400
|
return {
|
|
37365
37401
|
rawData: {
|
|
@@ -37408,14 +37444,20 @@ var init_uiAskChoiceTool = __esm({
|
|
|
37408
37444
|
"\u5728\u4EE3\u7801\u534F\u4F5C\u573A\u666F\u4E0B\u7684\u63A8\u8350\u7528\u6CD5\uFF1A",
|
|
37409
37445
|
"- \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
37446
|
"- \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"
|
|
37447
|
+
"- \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",
|
|
37448
|
+
"",
|
|
37449
|
+
"\u591A\u95EE\u9898 & \u591A\u9009\u652F\u6301\uFF1A",
|
|
37450
|
+
"- \u5F53\u4F60\u9700\u8981\u4E00\u6B21\u95EE\u591A\u4E2A\u95EE\u9898\u65F6\uFF0C\u4F7F\u7528 questions \u6570\u7EC4\u4EE3\u66FF question+choices\u3002",
|
|
37451
|
+
"- \u6BCF\u4E2A question \u53EF\u4EE5\u8BBE\u7F6E multiSelect: true \u5141\u8BB8\u591A\u9009\u3002",
|
|
37452
|
+
"- \u6BCF\u4E2A question \u53EF\u4EE5\u8BBE\u7F6E allowOther: false \u9690\u85CF\u201C\u5176\u4ED6\u201D\u8F93\u5165\u6846\u3002",
|
|
37453
|
+
"- \u6BCF\u4E2A choice \u53EF\u4EE5\u52A0 detail \u5B57\u6BB5\u63D0\u4F9B\u66F4\u957F\u7684\u63CF\u8FF0\u3002"
|
|
37412
37454
|
].join("\n"),
|
|
37413
37455
|
parameters: {
|
|
37414
37456
|
type: "object",
|
|
37415
37457
|
properties: {
|
|
37416
37458
|
question: {
|
|
37417
37459
|
type: "string",
|
|
37418
|
-
description: "\u5C55\u793A\u7ED9\u7528\u6237\u7684\u95EE\u9898\u6587\u6848\
|
|
37460
|
+
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
37461
|
},
|
|
37420
37462
|
choices: {
|
|
37421
37463
|
type: "array",
|
|
@@ -37431,6 +37473,10 @@ var init_uiAskChoiceTool = __esm({
|
|
|
37431
37473
|
type: "string",
|
|
37432
37474
|
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
37475
|
},
|
|
37476
|
+
detail: {
|
|
37477
|
+
type: "string",
|
|
37478
|
+
description: "\u9009\u9879\u7684\u8865\u5145\u63CF\u8FF0\uFF0C\u663E\u793A\u5728 label \u4E0B\u65B9\u3002\u53EF\u9009\u3002"
|
|
37479
|
+
},
|
|
37434
37480
|
userMessage: {
|
|
37435
37481
|
type: "string",
|
|
37436
37482
|
description: [
|
|
@@ -37443,6 +37489,56 @@ var init_uiAskChoiceTool = __esm({
|
|
|
37443
37489
|
required: ["id", "label"]
|
|
37444
37490
|
}
|
|
37445
37491
|
},
|
|
37492
|
+
questions: {
|
|
37493
|
+
type: "array",
|
|
37494
|
+
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",
|
|
37495
|
+
items: {
|
|
37496
|
+
type: "object",
|
|
37497
|
+
properties: {
|
|
37498
|
+
id: {
|
|
37499
|
+
type: "string",
|
|
37500
|
+
description: "\u95EE\u9898\u6807\u8BC6\uFF0C\u7528\u4E8E\u7ED3\u679C\u5BF9\u5E94\u3002"
|
|
37501
|
+
},
|
|
37502
|
+
question: {
|
|
37503
|
+
type: "string",
|
|
37504
|
+
description: "\u95EE\u9898\u6587\u6848\u3002"
|
|
37505
|
+
},
|
|
37506
|
+
choices: {
|
|
37507
|
+
type: "array",
|
|
37508
|
+
description: "\u8BE5\u95EE\u9898\u7684\u5907\u9009\u9879\u3002",
|
|
37509
|
+
items: {
|
|
37510
|
+
type: "object",
|
|
37511
|
+
properties: {
|
|
37512
|
+
id: { type: "string" },
|
|
37513
|
+
label: { type: "string" },
|
|
37514
|
+
detail: {
|
|
37515
|
+
type: "string",
|
|
37516
|
+
description: "\u8865\u5145\u63CF\u8FF0\u3002"
|
|
37517
|
+
},
|
|
37518
|
+
userMessage: { type: "string" }
|
|
37519
|
+
},
|
|
37520
|
+
required: ["id", "label"]
|
|
37521
|
+
}
|
|
37522
|
+
},
|
|
37523
|
+
multiSelect: {
|
|
37524
|
+
type: "boolean",
|
|
37525
|
+
description: "\u5141\u8BB8\u591A\u9009\u3002\u9ED8\u8BA4 false\u3002",
|
|
37526
|
+
default: false
|
|
37527
|
+
},
|
|
37528
|
+
allowOther: {
|
|
37529
|
+
type: "boolean",
|
|
37530
|
+
description: "\u663E\u793A\u201C\u5176\u4ED6\u201D\u81EA\u7531\u8F93\u5165\u884C\u3002\u9ED8\u8BA4 true\u3002",
|
|
37531
|
+
default: true
|
|
37532
|
+
},
|
|
37533
|
+
required: {
|
|
37534
|
+
type: "boolean",
|
|
37535
|
+
description: "\u662F\u5426\u5FC5\u987B\u56DE\u7B54\u624D\u80FD\u63D0\u4EA4\u3002\u9ED8\u8BA4 true\u3002",
|
|
37536
|
+
default: true
|
|
37537
|
+
}
|
|
37538
|
+
},
|
|
37539
|
+
required: ["id", "question", "choices"]
|
|
37540
|
+
}
|
|
37541
|
+
},
|
|
37446
37542
|
blocking: {
|
|
37447
37543
|
type: "boolean",
|
|
37448
37544
|
description: [
|
|
@@ -37452,7 +37548,7 @@ var init_uiAskChoiceTool = __esm({
|
|
|
37452
37548
|
default: true
|
|
37453
37549
|
}
|
|
37454
37550
|
},
|
|
37455
|
-
required: [
|
|
37551
|
+
required: []
|
|
37456
37552
|
}
|
|
37457
37553
|
};
|
|
37458
37554
|
}
|
|
@@ -106909,13 +107005,15 @@ function renderDialogOverflow(text, colorEnabled = resolveCliColorEnabled()) {
|
|
|
106909
107005
|
function renderDialogCommand(text, colorEnabled = resolveCliColorEnabled()) {
|
|
106910
107006
|
return themeText(` ${text}`, "danger", colorEnabled);
|
|
106911
107007
|
}
|
|
106912
|
-
var DIALOG_CURSOR;
|
|
107008
|
+
var DIALOG_CURSOR, DIALOG_CHECKED, DIALOG_UNCHECKED;
|
|
106913
107009
|
var init_dialogFrame = __esm({
|
|
106914
107010
|
"packages/cli/tui/dialogFrame.ts"() {
|
|
106915
107011
|
"use strict";
|
|
106916
107012
|
init_terminalStyles();
|
|
106917
107013
|
init_theme();
|
|
106918
107014
|
DIALOG_CURSOR = "\u276F";
|
|
107015
|
+
DIALOG_CHECKED = "\u25C9";
|
|
107016
|
+
DIALOG_UNCHECKED = "\u25CB";
|
|
106919
107017
|
}
|
|
106920
107018
|
});
|
|
106921
107019
|
|
|
@@ -107257,6 +107355,496 @@ var init_confirmDialog = __esm({
|
|
|
107257
107355
|
}
|
|
107258
107356
|
});
|
|
107259
107357
|
|
|
107358
|
+
// packages/ai/tools/askChoiceState.ts
|
|
107359
|
+
function normalizeAskChoiceArgs(args2) {
|
|
107360
|
+
const blocking = args2.blocking !== false;
|
|
107361
|
+
if (Array.isArray(args2.questions) && args2.questions.length > 0) {
|
|
107362
|
+
return {
|
|
107363
|
+
questions: args2.questions.map(
|
|
107364
|
+
(q, i) => normalizeQuestion(q, i)
|
|
107365
|
+
),
|
|
107366
|
+
blocking
|
|
107367
|
+
};
|
|
107368
|
+
}
|
|
107369
|
+
const question = String(args2.question ?? "").trim();
|
|
107370
|
+
const choices = Array.isArray(args2.choices) ? args2.choices : [];
|
|
107371
|
+
if (!question || choices.length === 0) {
|
|
107372
|
+
return { questions: [], blocking };
|
|
107373
|
+
}
|
|
107374
|
+
return {
|
|
107375
|
+
questions: [
|
|
107376
|
+
normalizeQuestion(
|
|
107377
|
+
{ question, choices, multiSelect: false, allowOther: true, required: true },
|
|
107378
|
+
0
|
|
107379
|
+
)
|
|
107380
|
+
],
|
|
107381
|
+
blocking
|
|
107382
|
+
};
|
|
107383
|
+
}
|
|
107384
|
+
function normalizeQuestion(raw, index) {
|
|
107385
|
+
return {
|
|
107386
|
+
id: String(raw?.id ?? `q${index}`),
|
|
107387
|
+
question: String(raw?.question ?? "").trim(),
|
|
107388
|
+
choices: (Array.isArray(raw?.choices) ? raw.choices : []).map(
|
|
107389
|
+
(c, ci) => ({
|
|
107390
|
+
id: String(c?.id ?? `c${ci}`),
|
|
107391
|
+
label: String(c?.label ?? "").trim(),
|
|
107392
|
+
...typeof c?.detail === "string" && c.detail.trim() ? { detail: c.detail.trim() } : {},
|
|
107393
|
+
...typeof c?.userMessage === "string" && c.userMessage.trim() ? { userMessage: c.userMessage.trim() } : {}
|
|
107394
|
+
})
|
|
107395
|
+
),
|
|
107396
|
+
multiSelect: raw?.multiSelect === true,
|
|
107397
|
+
allowOther: raw?.allowOther !== false,
|
|
107398
|
+
required: raw?.required !== false
|
|
107399
|
+
};
|
|
107400
|
+
}
|
|
107401
|
+
function createInitialAskChoiceState(questions) {
|
|
107402
|
+
return {
|
|
107403
|
+
questions,
|
|
107404
|
+
activeIndex: 0,
|
|
107405
|
+
questionStates: questions.map(() => ({
|
|
107406
|
+
cursorIndex: 0,
|
|
107407
|
+
selectedIds: [],
|
|
107408
|
+
pickedId: null,
|
|
107409
|
+
otherText: "",
|
|
107410
|
+
otherFocused: false
|
|
107411
|
+
})),
|
|
107412
|
+
phase: "active"
|
|
107413
|
+
};
|
|
107414
|
+
}
|
|
107415
|
+
function askChoiceReducer(state4, action3) {
|
|
107416
|
+
if (state4.phase !== "active") return state4;
|
|
107417
|
+
switch (action3.type) {
|
|
107418
|
+
case "CANCEL":
|
|
107419
|
+
return { ...state4, phase: "cancelled" };
|
|
107420
|
+
case "SUBMIT": {
|
|
107421
|
+
if (!canSubmit(state4)) return state4;
|
|
107422
|
+
return { ...state4, phase: "submitted" };
|
|
107423
|
+
}
|
|
107424
|
+
case "SWITCH_TAB": {
|
|
107425
|
+
const idx = clamp3(action3.index, 0, state4.questions.length - 1);
|
|
107426
|
+
return { ...state4, activeIndex: idx };
|
|
107427
|
+
}
|
|
107428
|
+
case "NEXT_TAB": {
|
|
107429
|
+
const idx = Math.min(state4.activeIndex + 1, state4.questions.length - 1);
|
|
107430
|
+
return { ...state4, activeIndex: idx };
|
|
107431
|
+
}
|
|
107432
|
+
case "PREV_TAB": {
|
|
107433
|
+
const idx = Math.max(state4.activeIndex - 1, 0);
|
|
107434
|
+
return { ...state4, activeIndex: idx };
|
|
107435
|
+
}
|
|
107436
|
+
case "MOVE_CURSOR": {
|
|
107437
|
+
const qs = state4.questionStates[state4.activeIndex];
|
|
107438
|
+
const q = state4.questions[state4.activeIndex];
|
|
107439
|
+
const maxIndex = q.allowOther ? q.choices.length : q.choices.length - 1;
|
|
107440
|
+
const next = clamp3(qs.cursorIndex + action3.delta, 0, maxIndex);
|
|
107441
|
+
const newQs = [...state4.questionStates];
|
|
107442
|
+
newQs[state4.activeIndex] = {
|
|
107443
|
+
...qs,
|
|
107444
|
+
cursorIndex: next,
|
|
107445
|
+
otherFocused: false
|
|
107446
|
+
};
|
|
107447
|
+
return { ...state4, questionStates: newQs };
|
|
107448
|
+
}
|
|
107449
|
+
case "TOGGLE_AT_CURSOR": {
|
|
107450
|
+
const qs = state4.questionStates[state4.activeIndex];
|
|
107451
|
+
const q = state4.questions[state4.activeIndex];
|
|
107452
|
+
if (!q.multiSelect) return state4;
|
|
107453
|
+
const isOtherRow = qs.cursorIndex >= q.choices.length;
|
|
107454
|
+
if (isOtherRow) {
|
|
107455
|
+
const newQs2 = [...state4.questionStates];
|
|
107456
|
+
newQs2[state4.activeIndex] = { ...qs, otherFocused: !qs.otherFocused };
|
|
107457
|
+
return { ...state4, questionStates: newQs2 };
|
|
107458
|
+
}
|
|
107459
|
+
const choiceId = q.choices[qs.cursorIndex]?.id;
|
|
107460
|
+
if (!choiceId) return state4;
|
|
107461
|
+
const has = qs.selectedIds.includes(choiceId);
|
|
107462
|
+
const newSelected = has ? qs.selectedIds.filter((id) => id !== choiceId) : [...qs.selectedIds, choiceId];
|
|
107463
|
+
const newQs = [...state4.questionStates];
|
|
107464
|
+
newQs[state4.activeIndex] = { ...qs, selectedIds: newSelected };
|
|
107465
|
+
return { ...state4, questionStates: newQs };
|
|
107466
|
+
}
|
|
107467
|
+
case "SELECT_AT_CURSOR": {
|
|
107468
|
+
const qs = state4.questionStates[state4.activeIndex];
|
|
107469
|
+
const q = state4.questions[state4.activeIndex];
|
|
107470
|
+
const isOtherRow = qs.cursorIndex >= q.choices.length;
|
|
107471
|
+
if (isOtherRow) {
|
|
107472
|
+
const newQs2 = [...state4.questionStates];
|
|
107473
|
+
newQs2[state4.activeIndex] = { ...qs, otherFocused: true };
|
|
107474
|
+
return { ...state4, questionStates: newQs2 };
|
|
107475
|
+
}
|
|
107476
|
+
const choiceId = q.choices[qs.cursorIndex]?.id;
|
|
107477
|
+
if (!choiceId) return state4;
|
|
107478
|
+
if (q.multiSelect) {
|
|
107479
|
+
const has = qs.selectedIds.includes(choiceId);
|
|
107480
|
+
const newSelected = has ? qs.selectedIds.filter((id) => id !== choiceId) : [...qs.selectedIds, choiceId];
|
|
107481
|
+
const newQs2 = [...state4.questionStates];
|
|
107482
|
+
newQs2[state4.activeIndex] = { ...qs, selectedIds: newSelected };
|
|
107483
|
+
return { ...state4, questionStates: newQs2 };
|
|
107484
|
+
}
|
|
107485
|
+
const newQs = [...state4.questionStates];
|
|
107486
|
+
newQs[state4.activeIndex] = { ...qs, pickedId: choiceId, otherFocused: false };
|
|
107487
|
+
if (state4.questions.length === 1) {
|
|
107488
|
+
return {
|
|
107489
|
+
...state4,
|
|
107490
|
+
questionStates: newQs,
|
|
107491
|
+
phase: "submitted"
|
|
107492
|
+
};
|
|
107493
|
+
}
|
|
107494
|
+
const nextTab = Math.min(
|
|
107495
|
+
state4.activeIndex + 1,
|
|
107496
|
+
state4.questions.length - 1
|
|
107497
|
+
);
|
|
107498
|
+
return {
|
|
107499
|
+
...state4,
|
|
107500
|
+
questionStates: newQs,
|
|
107501
|
+
activeIndex: nextTab
|
|
107502
|
+
};
|
|
107503
|
+
}
|
|
107504
|
+
case "FOCUS_OTHER": {
|
|
107505
|
+
const qs = state4.questionStates[state4.activeIndex];
|
|
107506
|
+
const newQs = [...state4.questionStates];
|
|
107507
|
+
newQs[state4.activeIndex] = { ...qs, otherFocused: true };
|
|
107508
|
+
return { ...state4, questionStates: newQs };
|
|
107509
|
+
}
|
|
107510
|
+
case "BLUR_OTHER": {
|
|
107511
|
+
const qs = state4.questionStates[state4.activeIndex];
|
|
107512
|
+
const newQs = [...state4.questionStates];
|
|
107513
|
+
newQs[state4.activeIndex] = { ...qs, otherFocused: false };
|
|
107514
|
+
return { ...state4, questionStates: newQs };
|
|
107515
|
+
}
|
|
107516
|
+
case "SET_OTHER_TEXT": {
|
|
107517
|
+
const qs = state4.questionStates[state4.activeIndex];
|
|
107518
|
+
const newQs = [...state4.questionStates];
|
|
107519
|
+
newQs[state4.activeIndex] = { ...qs, otherText: action3.text };
|
|
107520
|
+
return { ...state4, questionStates: newQs };
|
|
107521
|
+
}
|
|
107522
|
+
default:
|
|
107523
|
+
return state4;
|
|
107524
|
+
}
|
|
107525
|
+
}
|
|
107526
|
+
function isQuestionAnswered(q, qs) {
|
|
107527
|
+
if (!q.required) return true;
|
|
107528
|
+
const hasSelection = q.multiSelect ? qs.selectedIds.length > 0 : qs.pickedId !== null;
|
|
107529
|
+
const hasOther = q.allowOther && qs.otherText.trim().length > 0;
|
|
107530
|
+
return hasSelection || hasOther;
|
|
107531
|
+
}
|
|
107532
|
+
function canSubmit(state4) {
|
|
107533
|
+
return state4.questions.every(
|
|
107534
|
+
(q, i) => isQuestionAnswered(q, state4.questionStates[i])
|
|
107535
|
+
);
|
|
107536
|
+
}
|
|
107537
|
+
function buildAskChoiceResult(state4) {
|
|
107538
|
+
if (state4.phase === "cancelled") return { kind: "cancelled" };
|
|
107539
|
+
if (state4.phase !== "submitted") return { kind: "cancelled" };
|
|
107540
|
+
const answers = state4.questions.map((q, i) => {
|
|
107541
|
+
const qs = state4.questionStates[i];
|
|
107542
|
+
const selectedIds = q.multiSelect ? qs.selectedIds : qs.pickedId ? [qs.pickedId] : [];
|
|
107543
|
+
const otherText = qs.otherText.trim();
|
|
107544
|
+
const parts = [];
|
|
107545
|
+
for (const id of selectedIds) {
|
|
107546
|
+
const choice = q.choices.find((c) => c.id === id);
|
|
107547
|
+
if (choice) {
|
|
107548
|
+
parts.push(choice.userMessage || choice.label);
|
|
107549
|
+
}
|
|
107550
|
+
}
|
|
107551
|
+
if (otherText) {
|
|
107552
|
+
parts.push(otherText);
|
|
107553
|
+
}
|
|
107554
|
+
return {
|
|
107555
|
+
questionId: q.id,
|
|
107556
|
+
selectedIds,
|
|
107557
|
+
otherText,
|
|
107558
|
+
userMessage: parts.join("\n")
|
|
107559
|
+
};
|
|
107560
|
+
});
|
|
107561
|
+
return { kind: "submitted", answers };
|
|
107562
|
+
}
|
|
107563
|
+
function clamp3(value, min, max) {
|
|
107564
|
+
return Math.max(min, Math.min(max, value));
|
|
107565
|
+
}
|
|
107566
|
+
var init_askChoiceState = __esm({
|
|
107567
|
+
"packages/ai/tools/askChoiceState.ts"() {
|
|
107568
|
+
"use strict";
|
|
107569
|
+
}
|
|
107570
|
+
});
|
|
107571
|
+
|
|
107572
|
+
// packages/cli/tui/askChoiceDialog.ts
|
|
107573
|
+
function renderTabBar(questions, activeIndex, colorEnabled) {
|
|
107574
|
+
const tabs = questions.map((q, i) => {
|
|
107575
|
+
const label = `Q${i + 1}`;
|
|
107576
|
+
if (i === activeIndex) {
|
|
107577
|
+
return colorEnabled ? `${themeColorSequence("accent")}\x1B[1m ${label} \x1B[0m` : `[${label}]`;
|
|
107578
|
+
}
|
|
107579
|
+
return colorEnabled ? themeText(` ${label} `, "muted", colorEnabled) : ` ${label} `;
|
|
107580
|
+
});
|
|
107581
|
+
const submitLabel = "Submit";
|
|
107582
|
+
return tabs.join(" ") + " " + (colorEnabled ? themeText(submitLabel, "chrome", colorEnabled) : submitLabel);
|
|
107583
|
+
}
|
|
107584
|
+
function renderFooter(colorEnabled) {
|
|
107585
|
+
const hints = "type answer \u21B5save tab switch s submit esc cancel";
|
|
107586
|
+
return colorEnabled ? themeText(` ${hints}`, "chrome", colorEnabled) : ` ${hints}`;
|
|
107587
|
+
}
|
|
107588
|
+
function renderAskChoiceFrame(state4) {
|
|
107589
|
+
const colorEnabled = resolveCliColorEnabled();
|
|
107590
|
+
const q = state4.questions[state4.activeIndex];
|
|
107591
|
+
const qs = state4.questionStates[state4.activeIndex];
|
|
107592
|
+
const lines = [];
|
|
107593
|
+
lines.push(renderDialogTitle("question"));
|
|
107594
|
+
lines.push("");
|
|
107595
|
+
if (state4.questions.length > 1) {
|
|
107596
|
+
lines.push(renderTabBar(state4.questions, state4.activeIndex, colorEnabled));
|
|
107597
|
+
lines.push("");
|
|
107598
|
+
}
|
|
107599
|
+
lines.push(
|
|
107600
|
+
colorEnabled ? `${themeColorSequence("accent")}? ${q.question}\x1B[0m` : `? ${q.question}`
|
|
107601
|
+
);
|
|
107602
|
+
if (q.multiSelect) {
|
|
107603
|
+
lines.push(
|
|
107604
|
+
colorEnabled ? themeText(" Space to toggle, Enter to confirm selection.", "muted", colorEnabled) : " Space to toggle, Enter to confirm selection."
|
|
107605
|
+
);
|
|
107606
|
+
} else {
|
|
107607
|
+
lines.push(
|
|
107608
|
+
colorEnabled ? themeText(" Type your answer, then press Enter to save.", "muted", colorEnabled) : " Type your answer, then press Enter to save."
|
|
107609
|
+
);
|
|
107610
|
+
}
|
|
107611
|
+
lines.push("");
|
|
107612
|
+
const totalRows = q.choices.length + (q.allowOther ? 1 : 0);
|
|
107613
|
+
const window2 = computeVisibleWindow({
|
|
107614
|
+
selectedIndex: qs.cursorIndex,
|
|
107615
|
+
total: totalRows
|
|
107616
|
+
});
|
|
107617
|
+
if (window2.start > 0) {
|
|
107618
|
+
lines.push(
|
|
107619
|
+
colorEnabled ? themeText(` \u2191 ${window2.start} more`, "chrome", colorEnabled) : ` \u2191 ${window2.start} more`
|
|
107620
|
+
);
|
|
107621
|
+
}
|
|
107622
|
+
for (let i = window2.start; i < window2.end; i++) {
|
|
107623
|
+
if (i < q.choices.length) {
|
|
107624
|
+
const choice = q.choices[i];
|
|
107625
|
+
const focused = qs.cursorIndex === i;
|
|
107626
|
+
const checkbox = q.multiSelect ? qs.selectedIds.includes(choice.id) ? DIALOG_CHECKED : DIALOG_UNCHECKED : qs.pickedId === choice.id ? DIALOG_CHECKED : void 0;
|
|
107627
|
+
lines.push(
|
|
107628
|
+
renderDialogRow({
|
|
107629
|
+
label: `[${i + 1}] ${choice.label}`,
|
|
107630
|
+
...choice.detail ? { detail: choice.detail } : {},
|
|
107631
|
+
focused,
|
|
107632
|
+
...checkbox ? { checkbox } : {}
|
|
107633
|
+
})
|
|
107634
|
+
);
|
|
107635
|
+
} else {
|
|
107636
|
+
const focused = qs.cursorIndex === i;
|
|
107637
|
+
const marker = focused ? DIALOG_CURSOR : " ";
|
|
107638
|
+
const otherContent = qs.otherFocused ? `${qs.otherText}\u2588` : qs.otherText || "";
|
|
107639
|
+
const row = `${marker} [${i + 1}] Other: ${otherContent}`;
|
|
107640
|
+
if (focused && colorEnabled) {
|
|
107641
|
+
lines.push(
|
|
107642
|
+
`\x1B[1m${themeColorSequence("accent")}${row}\x1B[0m`
|
|
107643
|
+
);
|
|
107644
|
+
} else {
|
|
107645
|
+
lines.push(row);
|
|
107646
|
+
}
|
|
107647
|
+
}
|
|
107648
|
+
}
|
|
107649
|
+
if (window2.end < totalRows) {
|
|
107650
|
+
lines.push(
|
|
107651
|
+
colorEnabled ? themeText(` \u2193 ${totalRows - window2.end} more`, "chrome", colorEnabled) : ` \u2193 ${totalRows - window2.end} more`
|
|
107652
|
+
);
|
|
107653
|
+
}
|
|
107654
|
+
lines.push("");
|
|
107655
|
+
lines.push(renderFooter(colorEnabled));
|
|
107656
|
+
return lines.join("\n");
|
|
107657
|
+
}
|
|
107658
|
+
async function runAskChoiceDialog(args2) {
|
|
107659
|
+
const { request } = args2;
|
|
107660
|
+
const normalized = normalizeAskChoiceArgs({
|
|
107661
|
+
question: request.question,
|
|
107662
|
+
choices: request.choices,
|
|
107663
|
+
questions: request.questions,
|
|
107664
|
+
blocking: request.blocking
|
|
107665
|
+
});
|
|
107666
|
+
if (normalized.questions.length === 0) {
|
|
107667
|
+
return { kind: "cancelled" };
|
|
107668
|
+
}
|
|
107669
|
+
const q0 = normalized.questions[0];
|
|
107670
|
+
if (normalized.questions.length === 1 && !q0.multiSelect && !q0.allowOther) {
|
|
107671
|
+
}
|
|
107672
|
+
let state4 = createInitialAskChoiceState(normalized.questions);
|
|
107673
|
+
const output2 = args2.output ?? process.stdout;
|
|
107674
|
+
const input2 = args2.input ?? process.stdin;
|
|
107675
|
+
const readKey = args2.readKey ?? createRawKeyReader(input2);
|
|
107676
|
+
const wasRaw = Boolean(input2.isTTY && input2.isRaw);
|
|
107677
|
+
let renderedLineCount = 0;
|
|
107678
|
+
const bottomAnchored = Boolean(args2.bottomAnchored && args2.bottomRow);
|
|
107679
|
+
const resolveBottomRow = () => Math.max(
|
|
107680
|
+
1,
|
|
107681
|
+
typeof args2.bottomRow === "function" ? args2.bottomRow() : args2.bottomRow ?? 0
|
|
107682
|
+
);
|
|
107683
|
+
let lastBottomRow = 0;
|
|
107684
|
+
const paint = () => {
|
|
107685
|
+
const frame = renderAskChoiceFrame(state4);
|
|
107686
|
+
const lines = frame.split("\n");
|
|
107687
|
+
const lineCount = lines.length;
|
|
107688
|
+
const canPosition = outputIsTty(output2) && typeof output2.write === "function";
|
|
107689
|
+
if (bottomAnchored && canPosition) {
|
|
107690
|
+
const anchorRow = resolveBottomRow();
|
|
107691
|
+
clearAnchoredLines(
|
|
107692
|
+
output2,
|
|
107693
|
+
lastBottomRow > 0 ? lastBottomRow : anchorRow,
|
|
107694
|
+
renderedLineCount
|
|
107695
|
+
);
|
|
107696
|
+
for (let i = 0; i < lines.length; i++) {
|
|
107697
|
+
const row = anchorRow - (lines.length - 1 - i);
|
|
107698
|
+
if (row < 1) break;
|
|
107699
|
+
output2.write(`\x1B[${row};1H\x1B[2K${lines[i]}`);
|
|
107700
|
+
}
|
|
107701
|
+
lastBottomRow = anchorRow;
|
|
107702
|
+
renderedLineCount = lineCount;
|
|
107703
|
+
return;
|
|
107704
|
+
}
|
|
107705
|
+
if (canPosition) {
|
|
107706
|
+
for (let i = 0; i < renderedLineCount; i++) {
|
|
107707
|
+
output2.write("\x1B[1A\x1B[2K");
|
|
107708
|
+
}
|
|
107709
|
+
output2.write(`${frame}
|
|
107710
|
+
`);
|
|
107711
|
+
renderedLineCount = lineCount;
|
|
107712
|
+
return;
|
|
107713
|
+
}
|
|
107714
|
+
if (typeof output2.write === "function") {
|
|
107715
|
+
output2.write(`${frame}
|
|
107716
|
+
`);
|
|
107717
|
+
}
|
|
107718
|
+
renderedLineCount = lineCount;
|
|
107719
|
+
};
|
|
107720
|
+
const resizeTarget = output2;
|
|
107721
|
+
const onOutputResize = () => paint();
|
|
107722
|
+
if (input2.isTTY && !wasRaw) {
|
|
107723
|
+
input2.setRawMode?.(true);
|
|
107724
|
+
}
|
|
107725
|
+
if (bottomAnchored && outputIsTty(output2)) {
|
|
107726
|
+
resizeTarget.on?.("resize", onOutputResize);
|
|
107727
|
+
}
|
|
107728
|
+
paint();
|
|
107729
|
+
try {
|
|
107730
|
+
while (state4.phase === "active") {
|
|
107731
|
+
const sequence = await readKey();
|
|
107732
|
+
if (sequence == null) {
|
|
107733
|
+
state4 = askChoiceReducer(state4, { type: "CANCEL" });
|
|
107734
|
+
break;
|
|
107735
|
+
}
|
|
107736
|
+
let action3 = null;
|
|
107737
|
+
if (isCancel(sequence)) {
|
|
107738
|
+
action3 = { type: "CANCEL" };
|
|
107739
|
+
} else if (sequence === CSI_TAB) {
|
|
107740
|
+
action3 = { type: "NEXT_TAB" };
|
|
107741
|
+
} else if (sequence === CSI_SHIFT_TAB) {
|
|
107742
|
+
action3 = { type: "PREV_TAB" };
|
|
107743
|
+
} else if (isArrowUp(sequence)) {
|
|
107744
|
+
action3 = { type: "MOVE_CURSOR", delta: -1 };
|
|
107745
|
+
} else if (isArrowDown(sequence)) {
|
|
107746
|
+
action3 = { type: "MOVE_CURSOR", delta: 1 };
|
|
107747
|
+
} else if (sequence === CSI_SPACE) {
|
|
107748
|
+
action3 = { type: "TOGGLE_AT_CURSOR" };
|
|
107749
|
+
} else if (sequence === "s" && !state4.questionStates[state4.activeIndex].otherFocused && canSubmit(state4)) {
|
|
107750
|
+
action3 = { type: "SUBMIT" };
|
|
107751
|
+
} else if (isSubmit(sequence)) {
|
|
107752
|
+
const qs = state4.questionStates[state4.activeIndex];
|
|
107753
|
+
const q = state4.questions[state4.activeIndex];
|
|
107754
|
+
const isOtherRow = qs.cursorIndex >= q.choices.length;
|
|
107755
|
+
if (qs.otherFocused) {
|
|
107756
|
+
action3 = { type: "BLUR_OTHER" };
|
|
107757
|
+
} else if (isOtherRow && !qs.otherFocused) {
|
|
107758
|
+
action3 = { type: "FOCUS_OTHER" };
|
|
107759
|
+
} else {
|
|
107760
|
+
action3 = { type: "SELECT_AT_CURSOR" };
|
|
107761
|
+
}
|
|
107762
|
+
} else if (sequence === CSI_BACKSPACE || sequence === CSI_BACKSPACE_ALT) {
|
|
107763
|
+
const qs = state4.questionStates[state4.activeIndex];
|
|
107764
|
+
if (qs.otherFocused && qs.otherText.length > 0) {
|
|
107765
|
+
action3 = {
|
|
107766
|
+
type: "SET_OTHER_TEXT",
|
|
107767
|
+
text: qs.otherText.slice(0, -1)
|
|
107768
|
+
};
|
|
107769
|
+
}
|
|
107770
|
+
} else if (sequence.length === 1 && sequence.charCodeAt(0) >= 32) {
|
|
107771
|
+
const qs = state4.questionStates[state4.activeIndex];
|
|
107772
|
+
if (qs.otherFocused) {
|
|
107773
|
+
action3 = {
|
|
107774
|
+
type: "SET_OTHER_TEXT",
|
|
107775
|
+
text: qs.otherText + sequence
|
|
107776
|
+
};
|
|
107777
|
+
}
|
|
107778
|
+
}
|
|
107779
|
+
if (action3) {
|
|
107780
|
+
const prev = state4;
|
|
107781
|
+
state4 = askChoiceReducer(state4, action3);
|
|
107782
|
+
if (state4.phase !== "active") break;
|
|
107783
|
+
if (action3.type === "BLUR_OTHER" && state4.questions.length === 1 && canSubmit(state4)) {
|
|
107784
|
+
state4 = askChoiceReducer(state4, { type: "SUBMIT" });
|
|
107785
|
+
break;
|
|
107786
|
+
}
|
|
107787
|
+
paint();
|
|
107788
|
+
}
|
|
107789
|
+
}
|
|
107790
|
+
} finally {
|
|
107791
|
+
resizeTarget.off?.("resize", onOutputResize);
|
|
107792
|
+
readKey.dispose?.();
|
|
107793
|
+
if (input2.isTTY) {
|
|
107794
|
+
drainInputBuffer(input2);
|
|
107795
|
+
if (!wasRaw) input2.setRawMode?.(false);
|
|
107796
|
+
if (bottomAnchored) {
|
|
107797
|
+
clearAnchoredLines(
|
|
107798
|
+
output2,
|
|
107799
|
+
lastBottomRow > 0 ? lastBottomRow : resolveBottomRow(),
|
|
107800
|
+
renderedLineCount
|
|
107801
|
+
);
|
|
107802
|
+
} else {
|
|
107803
|
+
for (let i = 0; i < renderedLineCount; i++) {
|
|
107804
|
+
output2.write("\x1B[1A\x1B[2K");
|
|
107805
|
+
}
|
|
107806
|
+
}
|
|
107807
|
+
renderedLineCount = 0;
|
|
107808
|
+
}
|
|
107809
|
+
}
|
|
107810
|
+
const result = buildAskChoiceResult(state4);
|
|
107811
|
+
if (result.kind === "cancelled") {
|
|
107812
|
+
return { kind: "cancelled" };
|
|
107813
|
+
}
|
|
107814
|
+
if (result.answers.length === 1) {
|
|
107815
|
+
const a = result.answers[0];
|
|
107816
|
+
return {
|
|
107817
|
+
kind: "selected",
|
|
107818
|
+
userMessage: a.userMessage,
|
|
107819
|
+
label: a.selectedIds.map((id) => {
|
|
107820
|
+
const q = normalized.questions[0];
|
|
107821
|
+
return q.choices.find((c) => c.id === id)?.label ?? "";
|
|
107822
|
+
}).join(", ") || a.otherText || ""
|
|
107823
|
+
};
|
|
107824
|
+
}
|
|
107825
|
+
return {
|
|
107826
|
+
kind: "multi-submitted",
|
|
107827
|
+
answers: result.answers,
|
|
107828
|
+
userMessage: result.answers.map((a) => a.userMessage).filter(Boolean).join("\n\n")
|
|
107829
|
+
};
|
|
107830
|
+
}
|
|
107831
|
+
var CSI_TAB, CSI_SHIFT_TAB, CSI_BACKSPACE, CSI_BACKSPACE_ALT, CSI_SPACE;
|
|
107832
|
+
var init_askChoiceDialog = __esm({
|
|
107833
|
+
"packages/cli/tui/askChoiceDialog.ts"() {
|
|
107834
|
+
"use strict";
|
|
107835
|
+
init_askChoiceState();
|
|
107836
|
+
init_dialogFrame();
|
|
107837
|
+
init_selectDialog();
|
|
107838
|
+
init_terminalStyles();
|
|
107839
|
+
init_theme();
|
|
107840
|
+
CSI_TAB = " ";
|
|
107841
|
+
CSI_SHIFT_TAB = "\x1B[Z";
|
|
107842
|
+
CSI_BACKSPACE = "\x7F";
|
|
107843
|
+
CSI_BACKSPACE_ALT = "\b";
|
|
107844
|
+
CSI_SPACE = " ";
|
|
107845
|
+
}
|
|
107846
|
+
});
|
|
107847
|
+
|
|
107260
107848
|
// packages/cli/tui/dialogHost.ts
|
|
107261
107849
|
function resolveTtyRows(output2) {
|
|
107262
107850
|
if (typeof output2 === "object" && output2 !== null && "rows" in output2 && typeof output2.rows === "number") {
|
|
@@ -107294,6 +107882,92 @@ var init_dialogHost = __esm({
|
|
|
107294
107882
|
}
|
|
107295
107883
|
});
|
|
107296
107884
|
|
|
107885
|
+
// packages/cli/tui/activityIndicator.ts
|
|
107886
|
+
function createActivityIndicator(deps) {
|
|
107887
|
+
const now = deps.now ?? (() => Date.now());
|
|
107888
|
+
const frameIntervalMs = deps.frameIntervalMs ?? ACTIVITY_FRAME_INTERVAL_MS;
|
|
107889
|
+
const fallbackDelayMs = deps.fallbackDelayMs ?? ACTIVITY_FALLBACK_DELAY_MS;
|
|
107890
|
+
const setIntervalFn = deps.setIntervalFn ?? ((cb, ms) => setInterval(cb, ms));
|
|
107891
|
+
const clearIntervalFn = deps.clearIntervalFn ?? ((handle) => clearInterval(handle));
|
|
107892
|
+
let explicitLabel = null;
|
|
107893
|
+
let explicitStartedAt = 0;
|
|
107894
|
+
let fallbackActive = false;
|
|
107895
|
+
let fallbackStartedAt = 0;
|
|
107896
|
+
let lastActivityAt = 0;
|
|
107897
|
+
let frameIndex = 0;
|
|
107898
|
+
let timer = null;
|
|
107899
|
+
const elapsedSecFrom = (startedAt) => startedAt > 0 ? Math.max(0, Math.floor((now() - startedAt) / 1e3)) : 0;
|
|
107900
|
+
const tick = () => {
|
|
107901
|
+
frameIndex += 1;
|
|
107902
|
+
if (explicitLabel === null && !fallbackActive && deps.isTurnActive() && lastActivityAt > 0 && now() - lastActivityAt >= fallbackDelayMs) {
|
|
107903
|
+
fallbackActive = true;
|
|
107904
|
+
fallbackStartedAt = now();
|
|
107905
|
+
}
|
|
107906
|
+
deps.onRepaint();
|
|
107907
|
+
};
|
|
107908
|
+
const ensureTimer = () => {
|
|
107909
|
+
if (timer === null) {
|
|
107910
|
+
timer = setIntervalFn(tick, frameIntervalMs);
|
|
107911
|
+
}
|
|
107912
|
+
};
|
|
107913
|
+
const report = (label) => {
|
|
107914
|
+
lastActivityAt = now();
|
|
107915
|
+
if (label !== null) {
|
|
107916
|
+
explicitLabel = label;
|
|
107917
|
+
if (explicitStartedAt === 0) explicitStartedAt = lastActivityAt;
|
|
107918
|
+
fallbackActive = false;
|
|
107919
|
+
fallbackStartedAt = 0;
|
|
107920
|
+
} else {
|
|
107921
|
+
explicitLabel = null;
|
|
107922
|
+
explicitStartedAt = 0;
|
|
107923
|
+
fallbackActive = false;
|
|
107924
|
+
fallbackStartedAt = 0;
|
|
107925
|
+
}
|
|
107926
|
+
ensureTimer();
|
|
107927
|
+
deps.onRepaint();
|
|
107928
|
+
};
|
|
107929
|
+
const getView = () => {
|
|
107930
|
+
if (!deps.isTurnActive()) return null;
|
|
107931
|
+
const frame = ACTIVITY_FRAMES[frameIndex % ACTIVITY_FRAMES.length];
|
|
107932
|
+
if (explicitLabel !== null) {
|
|
107933
|
+
return {
|
|
107934
|
+
frame,
|
|
107935
|
+
label: explicitLabel,
|
|
107936
|
+
elapsedSec: elapsedSecFrom(explicitStartedAt)
|
|
107937
|
+
};
|
|
107938
|
+
}
|
|
107939
|
+
if (fallbackActive) {
|
|
107940
|
+
return {
|
|
107941
|
+
frame,
|
|
107942
|
+
label: deps.fallbackLabel(),
|
|
107943
|
+
elapsedSec: elapsedSecFrom(fallbackStartedAt)
|
|
107944
|
+
};
|
|
107945
|
+
}
|
|
107946
|
+
return null;
|
|
107947
|
+
};
|
|
107948
|
+
const stop = () => {
|
|
107949
|
+
if (timer !== null) {
|
|
107950
|
+
clearIntervalFn(timer);
|
|
107951
|
+
timer = null;
|
|
107952
|
+
}
|
|
107953
|
+
explicitLabel = null;
|
|
107954
|
+
explicitStartedAt = 0;
|
|
107955
|
+
fallbackActive = false;
|
|
107956
|
+
fallbackStartedAt = 0;
|
|
107957
|
+
lastActivityAt = 0;
|
|
107958
|
+
};
|
|
107959
|
+
return { report, getView, stop };
|
|
107960
|
+
}
|
|
107961
|
+
var ACTIVITY_FRAMES, ACTIVITY_FRAME_INTERVAL_MS, ACTIVITY_FALLBACK_DELAY_MS;
|
|
107962
|
+
var init_activityIndicator = __esm({
|
|
107963
|
+
"packages/cli/tui/activityIndicator.ts"() {
|
|
107964
|
+
"use strict";
|
|
107965
|
+
ACTIVITY_FRAMES = ["\xB7", "~", "\u2248", "\u223F", "\u2248", "~"];
|
|
107966
|
+
ACTIVITY_FRAME_INTERVAL_MS = 150;
|
|
107967
|
+
ACTIVITY_FALLBACK_DELAY_MS = 1200;
|
|
107968
|
+
}
|
|
107969
|
+
});
|
|
107970
|
+
|
|
107297
107971
|
// packages/ai/agent/utils/sortUtils.ts
|
|
107298
107972
|
function sortAgentsFavoriteOwnedPublic(items) {
|
|
107299
107973
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -108103,51 +108777,76 @@ function renderStatusLine(state4) {
|
|
|
108103
108777
|
if (!surface) return body;
|
|
108104
108778
|
return `${surface} ${body} \x1B[49m`;
|
|
108105
108779
|
}
|
|
108106
|
-
function buildPlainScene(isDark) {
|
|
108107
|
-
|
|
108780
|
+
function buildPlainScene(isDark, frame = 0, maxFrames = 0) {
|
|
108781
|
+
let skyLine = ` ${isDark ? "\u{1F319}" : "\u2600"}`;
|
|
108782
|
+
if (isDark) {
|
|
108783
|
+
const star1 = frame % 6 < 3 ? "\u2726" : "\u22C6";
|
|
108784
|
+
const star2 = frame % 4 < 2 ? "\u22C6" : "\xB7";
|
|
108785
|
+
const star3 = frame % 5 < 2 ? "\xB7" : "\u2726";
|
|
108786
|
+
skyLine = ` ${star1} \u{1F319} ${star2} ${star3}`;
|
|
108787
|
+
}
|
|
108788
|
+
const wavePattern = "_.~^~.";
|
|
108789
|
+
const longWave = wavePattern.repeat(10);
|
|
108790
|
+
const offset = frame % wavePattern.length;
|
|
108791
|
+
const wave2 = longWave.slice(offset, offset + 25);
|
|
108108
108792
|
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~"
|
|
108793
|
+
skyLine,
|
|
108794
|
+
" \u2571\u2572 \u2588\u2584 \u2588 \u2584\u2580\u2580\u2584 \u2588 \u2584\u2580\u2580\u2584",
|
|
108795
|
+
" \u2571 \u2572 \u2571\u2572 \u2588 \u2580\u2588 \u2588 \u2588 \u2588 \u2588 \u2588",
|
|
108796
|
+
" \u2571 \u2572\u2571 \u2572 \u2580 \u2580 \u2580\u2580 \u2580\u2580\u2580\u2580 \u2580\u2580",
|
|
108797
|
+
` \u2571 \u2660 \u2572 ${wave2}`,
|
|
108798
|
+
" \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
108799
|
].join("\n");
|
|
108120
108800
|
}
|
|
108121
|
-
function buildColoredScene(isDark) {
|
|
108801
|
+
function buildColoredScene(isDark, frame = 0, maxFrames = 0) {
|
|
108122
108802
|
const pk = themeColorSequence("chrome");
|
|
108123
108803
|
const sk = themeColorSequence("warning");
|
|
108124
|
-
const st = themeColorSequence("muted");
|
|
108125
108804
|
const tr = themeColorSequence("success");
|
|
108126
108805
|
const wv = themeColorSequence("info");
|
|
108127
108806
|
const ac = themeColorSequence("accent");
|
|
108128
|
-
const
|
|
108807
|
+
const mu = themeColorSequence("muted");
|
|
108129
108808
|
const r = "\x1B[39m";
|
|
108130
108809
|
const b = "\x1B[1m";
|
|
108131
108810
|
const rs = "\x1B[0m";
|
|
108132
|
-
|
|
108811
|
+
let skyLine = ` ${sk}${isDark ? "\u{1F319}" : "\u2600"}${r}`;
|
|
108812
|
+
if (isDark) {
|
|
108813
|
+
const star1 = frame % 6 < 3 ? "\u2726" : "\u22C6";
|
|
108814
|
+
const star2 = frame % 4 < 2 ? "\u22C6" : "\xB7";
|
|
108815
|
+
const star3 = frame % 5 < 2 ? "\xB7" : "\u2726";
|
|
108816
|
+
skyLine = ` ${mu}${star1}${r} ${sk}\u{1F319}${r} ${mu}${star2}${r} ${mu}${star3}${r}`;
|
|
108817
|
+
}
|
|
108818
|
+
const wavePattern = "_.~^~.";
|
|
108819
|
+
const longWave = wavePattern.repeat(10);
|
|
108820
|
+
const offset = frame % wavePattern.length;
|
|
108821
|
+
const wave2 = longWave.slice(offset, offset + 25);
|
|
108822
|
+
const waveStr = `${wv}${wave2.slice(0, 20)}${r}${mu}${wave2.slice(20, 25)}${r}`;
|
|
108823
|
+
const line1 = "\u2588\u2584 \u2588 \u2584\u2580\u2580\u2584 \u2588 \u2584\u2580\u2580\u2584";
|
|
108824
|
+
const line2 = "\u2588 \u2580\u2588 \u2588 \u2588 \u2588 \u2588 \u2588";
|
|
108825
|
+
const line3 = "\u2580 \u2580 \u2580\u2580 \u2580\u2580\u2580\u2580 \u2580\u2580";
|
|
108826
|
+
const sweepEndFrame = maxFrames > 3 ? maxFrames - 3 : maxFrames;
|
|
108827
|
+
const sweepLen = maxFrames === 0 ? 21 : Math.min(21, Math.floor(frame / sweepEndFrame * 21));
|
|
108828
|
+
const colorLine = (str, bold) => {
|
|
108829
|
+
const active = str.slice(0, sweepLen);
|
|
108830
|
+
const dimmed = str.slice(sweepLen);
|
|
108831
|
+
return `${bold ? b : ""}${ac}${active}${r}${mu}${dimmed}${r}${bold ? rs : ""}`;
|
|
108832
|
+
};
|
|
108833
|
+
const nolo1 = colorLine(line1, true);
|
|
108834
|
+
const nolo2 = colorLine(line2, false);
|
|
108835
|
+
const nolo3 = colorLine(line3, false);
|
|
108133
108836
|
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}`
|
|
108837
|
+
skyLine,
|
|
108838
|
+
` ${pk}\u2571\u2572${r} ${nolo1}`,
|
|
108839
|
+
` ${pk}\u2571 \u2572 \u2571\u2572${r} ${nolo2}`,
|
|
108840
|
+
` ${pk}\u2571 \u2572\u2571 \u2572${r} ${nolo3}`,
|
|
108841
|
+
` ${pk}\u2571${r} ${tr}\u2660${r} ${pk}\u2572${r} ${waveStr}`,
|
|
108842
|
+
` ${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
108843
|
].join("\n");
|
|
108145
108844
|
}
|
|
108146
|
-
function renderWelcome(state4) {
|
|
108845
|
+
function renderWelcome(state4, frame = 0, maxFrames = 0) {
|
|
108147
108846
|
const colorEnabled = resolveCliColorEnabled();
|
|
108148
108847
|
const brightness = resolveTuiBrightness();
|
|
108149
108848
|
const isDark = brightness === "dark";
|
|
108150
|
-
const sceneArt = colorEnabled ? buildColoredScene(isDark) : buildPlainScene(isDark);
|
|
108849
|
+
const sceneArt = colorEnabled ? buildColoredScene(isDark, frame, maxFrames) : buildPlainScene(isDark, frame, maxFrames);
|
|
108151
108850
|
const versionLine = colorEnabled ? `\x1B[1m${themeColorSequence("accent")}nolo\x1B[0m ${state4.cliVersion ?? ""} | server ${state4.serverUrl}`.replace(" |", " |") : `nolo ${state4.cliVersion ?? ""} | server ${state4.serverUrl}`.replace(" |", " |");
|
|
108152
108851
|
return [
|
|
108153
108852
|
sceneArt,
|
|
@@ -110639,49 +111338,35 @@ async function startTuiWorkspace(options) {
|
|
|
110639
111338
|
stdout: output2
|
|
110640
111339
|
});
|
|
110641
111340
|
if (detected) setActiveBrightness(detected);
|
|
110642
|
-
|
|
111341
|
+
const frames = 15;
|
|
111342
|
+
output2.write("\x1B[?25l");
|
|
111343
|
+
for (let i = 0; i < frames; i++) {
|
|
111344
|
+
output2.write(renderWelcome(state4, i, frames));
|
|
111345
|
+
if (i < frames - 1) {
|
|
111346
|
+
await new Promise((resolve9) => setTimeout(resolve9, 100));
|
|
111347
|
+
output2.write("\r\x1B[8A\x1B[0J");
|
|
111348
|
+
}
|
|
111349
|
+
}
|
|
111350
|
+
output2.write("\x1B[?25h");
|
|
110643
111351
|
let fixedInput = createNoopFixedInput();
|
|
110644
111352
|
let buffer = "";
|
|
110645
111353
|
let cursorPos = 0;
|
|
110646
111354
|
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();
|
|
111355
|
+
const activityIndicator = createActivityIndicator({
|
|
111356
|
+
isTurnActive: () => activeTurnAbort !== null,
|
|
111357
|
+
fallbackLabel: () => `${state4.agentName} -> working`,
|
|
111358
|
+
onRepaint: () => {
|
|
110680
111359
|
if (fixedInput.active && !fixedInput.isPaused()) {
|
|
110681
|
-
|
|
111360
|
+
output2.write("\x1B[?2026h\x1B[?25l");
|
|
111361
|
+
try {
|
|
111362
|
+
fixedInput.repaint(buffer);
|
|
111363
|
+
} finally {
|
|
111364
|
+
output2.write("\x1B[?25h\x1B[?2026l");
|
|
111365
|
+
}
|
|
110682
111366
|
}
|
|
110683
111367
|
}
|
|
110684
|
-
};
|
|
111368
|
+
});
|
|
111369
|
+
const activityReporter = (label) => activityIndicator.report(label);
|
|
110685
111370
|
let explicitAgentSwitch = false;
|
|
110686
111371
|
let copyViewExitResolver = null;
|
|
110687
111372
|
const history = createTurnHistory();
|
|
@@ -110780,25 +111465,15 @@ ${t("copyViewHint")}
|
|
|
110780
111465
|
scheduleRender();
|
|
110781
111466
|
}) : output2;
|
|
110782
111467
|
const requestUserChoice = isInteractiveInput(input2) && dialogHost ? async (req) => {
|
|
110783
|
-
const items = req.choices.map((c) => ({
|
|
110784
|
-
label: c.label
|
|
110785
|
-
}));
|
|
110786
111468
|
try {
|
|
110787
|
-
|
|
110788
|
-
(anchor) =>
|
|
110789
|
-
|
|
110790
|
-
title: req.question,
|
|
111469
|
+
return await dialogHost.run(
|
|
111470
|
+
(anchor) => runAskChoiceDialog({
|
|
111471
|
+
request: req,
|
|
110791
111472
|
input: input2,
|
|
110792
111473
|
output: output2,
|
|
110793
111474
|
...anchor
|
|
110794
111475
|
})
|
|
110795
111476
|
);
|
|
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
111477
|
} catch {
|
|
110803
111478
|
return { kind: "cancelled" };
|
|
110804
111479
|
}
|
|
@@ -110851,7 +111526,7 @@ ${t("copyViewHint")}
|
|
|
110851
111526
|
}
|
|
110852
111527
|
return { ok: !wasAborted, aborted: wasAborted };
|
|
110853
111528
|
} finally {
|
|
110854
|
-
|
|
111529
|
+
activityIndicator.stop();
|
|
110855
111530
|
activeTurnAbort = null;
|
|
110856
111531
|
explicitAgentSwitch = false;
|
|
110857
111532
|
}
|
|
@@ -111210,17 +111885,15 @@ ${err.message}` : ""}`
|
|
|
111210
111885
|
return base;
|
|
111211
111886
|
},
|
|
111212
111887
|
getActivityLine: () => {
|
|
111213
|
-
|
|
111888
|
+
const view = activityIndicator.getView();
|
|
111889
|
+
if (view === null) return null;
|
|
111214
111890
|
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);
|
|
111891
|
+
const elapsed = formatElapsedSeconds(view.elapsedSec);
|
|
111219
111892
|
const stopHint = t("stopHint");
|
|
111220
111893
|
if (!colorEnabled) {
|
|
111221
|
-
return `${frame} ${
|
|
111894
|
+
return `${view.frame} ${view.label} (${elapsed}) \xB7 ${stopHint}`;
|
|
111222
111895
|
}
|
|
111223
|
-
return themeText(frame, "accent") + " " + themeText(
|
|
111896
|
+
return themeText(view.frame, "accent") + " " + themeText(view.label, "muted") + themeText(` (${elapsed})`, "chrome") + themeText(` \xB7 ${stopHint}`, "chrome");
|
|
111224
111897
|
},
|
|
111225
111898
|
getQueueLines: () => {
|
|
111226
111899
|
if (!chatQueueBinding || chatQueueBinding.queueLength() === 0) return [];
|
|
@@ -111309,12 +111982,27 @@ ${err.message}` : ""}`
|
|
|
111309
111982
|
if (busyLock) {
|
|
111310
111983
|
const submittedText2 = result.submit;
|
|
111311
111984
|
const trimmedText = submittedText2.trim();
|
|
111312
|
-
|
|
111985
|
+
const busySlashCommand = trimmedText.split(/\s+/)[0]?.toLowerCase();
|
|
111986
|
+
const isBusyLocalSlash = busySlashCommand === "/context" || busySlashCommand === "/ctx" || busySlashCommand === "/switch";
|
|
111987
|
+
if (isBusyLocalSlash) {
|
|
111988
|
+
const beforeAgentKey = state4.agentKey;
|
|
111313
111989
|
const res = handleTuiInput(submittedText2, state4);
|
|
111314
|
-
|
|
111315
|
-
|
|
111316
|
-
|
|
111990
|
+
if (res.action) {
|
|
111991
|
+
output2.write(
|
|
111992
|
+
"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"
|
|
111993
|
+
);
|
|
111994
|
+
} else {
|
|
111995
|
+
state4 = res.nextState;
|
|
111996
|
+
let msg = res.output;
|
|
111997
|
+
if (busySlashCommand === "/switch" && res.nextState.agentKey !== beforeAgentKey) {
|
|
111998
|
+
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.";
|
|
111999
|
+
msg = msg ? `${msg}
|
|
112000
|
+
${hint}` : hint;
|
|
112001
|
+
}
|
|
112002
|
+
if (msg) {
|
|
112003
|
+
output2.write(`${msg}
|
|
111317
112004
|
`);
|
|
112005
|
+
}
|
|
111318
112006
|
}
|
|
111319
112007
|
buffer = "";
|
|
111320
112008
|
cursorPos2 = 0;
|
|
@@ -111537,8 +112225,9 @@ var init_readlineWorkspace = __esm({
|
|
|
111537
112225
|
init_updateCommands();
|
|
111538
112226
|
init_processSpawn();
|
|
111539
112227
|
init_confirmDialog();
|
|
111540
|
-
|
|
112228
|
+
init_askChoiceDialog();
|
|
111541
112229
|
init_dialogHost();
|
|
112230
|
+
init_activityIndicator();
|
|
111542
112231
|
init_agentPicker();
|
|
111543
112232
|
init_agentCatalog();
|
|
111544
112233
|
init_dialogPicker();
|