nolo-cli 0.7.0 → 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 +728 -73
- 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();
|
|
@@ -110678,44 +111352,21 @@ async function startTuiWorkspace(options) {
|
|
|
110678
111352
|
let buffer = "";
|
|
110679
111353
|
let cursorPos = 0;
|
|
110680
111354
|
let activeTurnAbort = null;
|
|
110681
|
-
|
|
110682
|
-
|
|
110683
|
-
|
|
110684
|
-
|
|
110685
|
-
const stopActivity = () => {
|
|
110686
|
-
if (activityTimer !== null) {
|
|
110687
|
-
clearInterval(activityTimer);
|
|
110688
|
-
activityTimer = null;
|
|
110689
|
-
}
|
|
110690
|
-
activityLabel = null;
|
|
110691
|
-
activityStartedAt = 0;
|
|
110692
|
-
};
|
|
110693
|
-
const activityReporter = (label) => {
|
|
110694
|
-
if (label !== null) {
|
|
110695
|
-
activityLabel = label;
|
|
110696
|
-
if (activityStartedAt === 0) {
|
|
110697
|
-
activityStartedAt = Date.now();
|
|
110698
|
-
}
|
|
110699
|
-
if (activityTimer === null) {
|
|
110700
|
-
activityTimer = setInterval(() => {
|
|
110701
|
-
activityFrameIndex += 1;
|
|
110702
|
-
if (fixedInput.active && !fixedInput.isPaused()) {
|
|
110703
|
-
output2.write("\x1B[?2026h\x1B[?25l");
|
|
110704
|
-
try {
|
|
110705
|
-
fixedInput.repaint(buffer);
|
|
110706
|
-
} finally {
|
|
110707
|
-
output2.write("\x1B[?25h\x1B[?2026l");
|
|
110708
|
-
}
|
|
110709
|
-
}
|
|
110710
|
-
}, 150);
|
|
110711
|
-
}
|
|
110712
|
-
} else {
|
|
110713
|
-
stopActivity();
|
|
111355
|
+
const activityIndicator = createActivityIndicator({
|
|
111356
|
+
isTurnActive: () => activeTurnAbort !== null,
|
|
111357
|
+
fallbackLabel: () => `${state4.agentName} -> working`,
|
|
111358
|
+
onRepaint: () => {
|
|
110714
111359
|
if (fixedInput.active && !fixedInput.isPaused()) {
|
|
110715
|
-
|
|
111360
|
+
output2.write("\x1B[?2026h\x1B[?25l");
|
|
111361
|
+
try {
|
|
111362
|
+
fixedInput.repaint(buffer);
|
|
111363
|
+
} finally {
|
|
111364
|
+
output2.write("\x1B[?25h\x1B[?2026l");
|
|
111365
|
+
}
|
|
110716
111366
|
}
|
|
110717
111367
|
}
|
|
110718
|
-
};
|
|
111368
|
+
});
|
|
111369
|
+
const activityReporter = (label) => activityIndicator.report(label);
|
|
110719
111370
|
let explicitAgentSwitch = false;
|
|
110720
111371
|
let copyViewExitResolver = null;
|
|
110721
111372
|
const history = createTurnHistory();
|
|
@@ -110814,25 +111465,15 @@ ${t("copyViewHint")}
|
|
|
110814
111465
|
scheduleRender();
|
|
110815
111466
|
}) : output2;
|
|
110816
111467
|
const requestUserChoice = isInteractiveInput(input2) && dialogHost ? async (req) => {
|
|
110817
|
-
const items = req.choices.map((c) => ({
|
|
110818
|
-
label: c.label
|
|
110819
|
-
}));
|
|
110820
111468
|
try {
|
|
110821
|
-
|
|
110822
|
-
(anchor) =>
|
|
110823
|
-
|
|
110824
|
-
title: req.question,
|
|
111469
|
+
return await dialogHost.run(
|
|
111470
|
+
(anchor) => runAskChoiceDialog({
|
|
111471
|
+
request: req,
|
|
110825
111472
|
input: input2,
|
|
110826
111473
|
output: output2,
|
|
110827
111474
|
...anchor
|
|
110828
111475
|
})
|
|
110829
111476
|
);
|
|
110830
|
-
if (pickResult.kind === "selected") {
|
|
110831
|
-
const choice = req.choices[pickResult.index];
|
|
110832
|
-
const userMessage = choice?.userMessage?.trim() || choice?.label || "";
|
|
110833
|
-
return { kind: "selected", userMessage, label: choice?.label ?? "" };
|
|
110834
|
-
}
|
|
110835
|
-
return { kind: "cancelled" };
|
|
110836
111477
|
} catch {
|
|
110837
111478
|
return { kind: "cancelled" };
|
|
110838
111479
|
}
|
|
@@ -110885,7 +111526,7 @@ ${t("copyViewHint")}
|
|
|
110885
111526
|
}
|
|
110886
111527
|
return { ok: !wasAborted, aborted: wasAborted };
|
|
110887
111528
|
} finally {
|
|
110888
|
-
|
|
111529
|
+
activityIndicator.stop();
|
|
110889
111530
|
activeTurnAbort = null;
|
|
110890
111531
|
explicitAgentSwitch = false;
|
|
110891
111532
|
}
|
|
@@ -111244,17 +111885,15 @@ ${err.message}` : ""}`
|
|
|
111244
111885
|
return base;
|
|
111245
111886
|
},
|
|
111246
111887
|
getActivityLine: () => {
|
|
111247
|
-
|
|
111888
|
+
const view = activityIndicator.getView();
|
|
111889
|
+
if (view === null) return null;
|
|
111248
111890
|
const colorEnabled = resolveCliColorEnabled();
|
|
111249
|
-
const
|
|
111250
|
-
const frame = FRAMES[activityFrameIndex % FRAMES.length];
|
|
111251
|
-
const elapsedSec = activityStartedAt > 0 ? Math.max(0, Math.floor((Date.now() - activityStartedAt) / 1e3)) : 0;
|
|
111252
|
-
const elapsed = formatElapsedSeconds(elapsedSec);
|
|
111891
|
+
const elapsed = formatElapsedSeconds(view.elapsedSec);
|
|
111253
111892
|
const stopHint = t("stopHint");
|
|
111254
111893
|
if (!colorEnabled) {
|
|
111255
|
-
return `${frame} ${
|
|
111894
|
+
return `${view.frame} ${view.label} (${elapsed}) \xB7 ${stopHint}`;
|
|
111256
111895
|
}
|
|
111257
|
-
return themeText(frame, "accent") + " " + themeText(
|
|
111896
|
+
return themeText(view.frame, "accent") + " " + themeText(view.label, "muted") + themeText(` (${elapsed})`, "chrome") + themeText(` \xB7 ${stopHint}`, "chrome");
|
|
111258
111897
|
},
|
|
111259
111898
|
getQueueLines: () => {
|
|
111260
111899
|
if (!chatQueueBinding || chatQueueBinding.queueLength() === 0) return [];
|
|
@@ -111343,12 +111982,27 @@ ${err.message}` : ""}`
|
|
|
111343
111982
|
if (busyLock) {
|
|
111344
111983
|
const submittedText2 = result.submit;
|
|
111345
111984
|
const trimmedText = submittedText2.trim();
|
|
111346
|
-
|
|
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;
|
|
111347
111989
|
const res = handleTuiInput(submittedText2, state4);
|
|
111348
|
-
|
|
111349
|
-
|
|
111350
|
-
|
|
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}
|
|
111351
112004
|
`);
|
|
112005
|
+
}
|
|
111352
112006
|
}
|
|
111353
112007
|
buffer = "";
|
|
111354
112008
|
cursorPos2 = 0;
|
|
@@ -111571,8 +112225,9 @@ var init_readlineWorkspace = __esm({
|
|
|
111571
112225
|
init_updateCommands();
|
|
111572
112226
|
init_processSpawn();
|
|
111573
112227
|
init_confirmDialog();
|
|
111574
|
-
|
|
112228
|
+
init_askChoiceDialog();
|
|
111575
112229
|
init_dialogHost();
|
|
112230
|
+
init_activityIndicator();
|
|
111576
112231
|
init_agentPicker();
|
|
111577
112232
|
init_agentCatalog();
|
|
111578
112233
|
init_dialogPicker();
|