topchester-ai 0.50.0 → 0.52.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/dist/bin.mjs +1 -1
- package/dist/{cli-BWa58EWv.mjs → cli-yf0DNAUH.mjs} +285 -26
- package/dist/cli-yf0DNAUH.mjs.map +1 -0
- package/dist/cli.mjs +1 -1
- package/package.json +1 -1
- package/dist/cli-BWa58EWv.mjs.map +0 -1
package/dist/bin.mjs
CHANGED
|
@@ -9551,12 +9551,16 @@ var BusyIndicator = class {
|
|
|
9551
9551
|
}
|
|
9552
9552
|
render() {
|
|
9553
9553
|
if (this.activityOverride) {
|
|
9554
|
-
this.app.setEphemeralLine(
|
|
9554
|
+
this.app.setEphemeralLine(this.formatActivityLine(this.activityOverride));
|
|
9555
9555
|
return;
|
|
9556
9556
|
}
|
|
9557
9557
|
const activityEveryMs = this.options.activityEveryMs ?? 1200;
|
|
9558
9558
|
const activityIndex = Math.floor(this.ticks * 80 / activityEveryMs) % this.options.activities.length;
|
|
9559
|
-
this.app.setEphemeralLine(
|
|
9559
|
+
this.app.setEphemeralLine(this.formatActivityLine(this.options.activities[activityIndex] ?? ""));
|
|
9560
|
+
}
|
|
9561
|
+
formatActivityLine(activity) {
|
|
9562
|
+
const hint = this.options.activityHint ? ` · ${this.options.activityHint}` : "";
|
|
9563
|
+
return `${this.frames[this.index]} ${activity}${hint}`;
|
|
9560
9564
|
}
|
|
9561
9565
|
};
|
|
9562
9566
|
var ReasoningTailBuffer = class {
|
|
@@ -9641,6 +9645,18 @@ const slashCommandSuggestions = [
|
|
|
9641
9645
|
value: "/skill",
|
|
9642
9646
|
description: "activate a skill"
|
|
9643
9647
|
},
|
|
9648
|
+
{
|
|
9649
|
+
value: "/queue",
|
|
9650
|
+
description: "queue a follow-up prompt"
|
|
9651
|
+
},
|
|
9652
|
+
{
|
|
9653
|
+
value: "/q",
|
|
9654
|
+
description: "queue a follow-up prompt"
|
|
9655
|
+
},
|
|
9656
|
+
{
|
|
9657
|
+
value: "/steer",
|
|
9658
|
+
description: "steer the active turn"
|
|
9659
|
+
},
|
|
9644
9660
|
{
|
|
9645
9661
|
value: "/new",
|
|
9646
9662
|
description: "start a fresh session"
|
|
@@ -9709,6 +9725,21 @@ const slashCommands = [
|
|
|
9709
9725
|
name: "restore",
|
|
9710
9726
|
description: "restore a previous interactive TUI session",
|
|
9711
9727
|
execute: executeRestoreCommand
|
|
9728
|
+
},
|
|
9729
|
+
{
|
|
9730
|
+
name: "queue",
|
|
9731
|
+
description: "queue a follow-up prompt",
|
|
9732
|
+
execute: executeInteractiveOnlyCommand("/queue")
|
|
9733
|
+
},
|
|
9734
|
+
{
|
|
9735
|
+
name: "q",
|
|
9736
|
+
description: "queue a follow-up prompt",
|
|
9737
|
+
execute: executeInteractiveOnlyCommand("/q")
|
|
9738
|
+
},
|
|
9739
|
+
{
|
|
9740
|
+
name: "steer",
|
|
9741
|
+
description: "steer the active turn",
|
|
9742
|
+
execute: executeInteractiveOnlyCommand("/steer")
|
|
9712
9743
|
}
|
|
9713
9744
|
];
|
|
9714
9745
|
function parseSlashCommand(input) {
|
|
@@ -10192,6 +10223,7 @@ var ChatLayout = class {
|
|
|
10192
10223
|
temporaryLine;
|
|
10193
10224
|
taskPlanNoticeLine;
|
|
10194
10225
|
noticeLine;
|
|
10226
|
+
queuedFollowUpCount = 0;
|
|
10195
10227
|
promptHint;
|
|
10196
10228
|
taskPlan;
|
|
10197
10229
|
cancelPending;
|
|
@@ -10277,6 +10309,9 @@ var ChatLayout = class {
|
|
|
10277
10309
|
setNoticeLine(line) {
|
|
10278
10310
|
this.noticeLine = line;
|
|
10279
10311
|
}
|
|
10312
|
+
setQueuedFollowUpCount(count) {
|
|
10313
|
+
this.queuedFollowUpCount = Math.max(0, count);
|
|
10314
|
+
}
|
|
10280
10315
|
setPromptHint(hint) {
|
|
10281
10316
|
this.promptHint = hint;
|
|
10282
10317
|
}
|
|
@@ -10332,6 +10367,7 @@ var ChatLayout = class {
|
|
|
10332
10367
|
this.temporaryLine = void 0;
|
|
10333
10368
|
this.taskPlanNoticeLine = void 0;
|
|
10334
10369
|
this.noticeLine = void 0;
|
|
10370
|
+
this.queuedFollowUpCount = 0;
|
|
10335
10371
|
this.promptHint = void 0;
|
|
10336
10372
|
this.taskPlan = void 0;
|
|
10337
10373
|
this.cancelPending = void 0;
|
|
@@ -10430,6 +10466,10 @@ var ChatLayout = class {
|
|
|
10430
10466
|
if (this.temporaryLine) lines.push(...this.renderThreadMessageLines([` ${ui.muted(this.temporaryLine)}`], innerWidth, width, false));
|
|
10431
10467
|
if (this.taskPlanNoticeLine) lines.push(...this.renderThreadMessageLines([` ${this.taskPlanNoticeLine}`], innerWidth, width, false));
|
|
10432
10468
|
if (this.noticeLine) lines.push(...this.renderThreadMessageLines([` ${this.noticeLine}`], innerWidth, width, false));
|
|
10469
|
+
if (this.queuedFollowUpCount > 0) {
|
|
10470
|
+
const suffix = this.queuedFollowUpCount === 1 ? "follow-up" : "follow-ups";
|
|
10471
|
+
lines.push(...this.renderThreadMessageLines([` ${ui.muted(`queued: ${this.queuedFollowUpCount} ${suffix}`)}`], innerWidth, width, false));
|
|
10472
|
+
}
|
|
10433
10473
|
return lines;
|
|
10434
10474
|
}
|
|
10435
10475
|
renderThreadMessageLines(lines, innerWidth, width, highlight) {
|
|
@@ -10795,12 +10835,11 @@ var ChatLayout = class {
|
|
|
10795
10835
|
submitPromptValue() {
|
|
10796
10836
|
if (this.promptValue.trim().length === 0) return;
|
|
10797
10837
|
const message = this.expandPastedContent(this.promptValue).trim();
|
|
10798
|
-
this.addMessage(userMessage(message));
|
|
10799
10838
|
this.promptValue = "";
|
|
10800
10839
|
this.promptCursor = 0;
|
|
10801
10840
|
this.pastedContent.clear();
|
|
10802
10841
|
this.pasteCounter = 0;
|
|
10803
|
-
this.submitUserInput(message);
|
|
10842
|
+
if (this.submitUserInput(message) !== "queued") this.addMessage(userMessage(message));
|
|
10804
10843
|
}
|
|
10805
10844
|
handlePromptEditInput(data) {
|
|
10806
10845
|
if (this.promptHint) return false;
|
|
@@ -10927,12 +10966,21 @@ var ChatLayout = class {
|
|
|
10927
10966
|
this.activeModalActionIndex = 0;
|
|
10928
10967
|
}
|
|
10929
10968
|
submitUserInput(message) {
|
|
10969
|
+
this.promptHistory.add(message);
|
|
10970
|
+
if (message.startsWith("/")) {
|
|
10971
|
+
const result = this.submitCommand?.(message);
|
|
10972
|
+
if (result === "queued") return result;
|
|
10973
|
+
this.setTaskPlanNotice(void 0);
|
|
10974
|
+
this.setStartupHintLine(void 0);
|
|
10975
|
+
this.setEphemeralLine(void 0);
|
|
10976
|
+
return result;
|
|
10977
|
+
}
|
|
10978
|
+
const result = this.submitMessage?.(message);
|
|
10979
|
+
if (result === "queued") return result;
|
|
10930
10980
|
this.setTaskPlanNotice(void 0);
|
|
10931
10981
|
this.setStartupHintLine(void 0);
|
|
10932
10982
|
this.setEphemeralLine(void 0);
|
|
10933
|
-
|
|
10934
|
-
if (message.startsWith("/")) this.submitCommand?.(message);
|
|
10935
|
-
else this.submitMessage?.(message);
|
|
10983
|
+
return result;
|
|
10936
10984
|
}
|
|
10937
10985
|
};
|
|
10938
10986
|
function getVisibleSuggestionWindowStart(total, activeIndex, visibleRows) {
|
|
@@ -12431,6 +12479,30 @@ function formatStartupKnowledgeGuidance(status) {
|
|
|
12431
12479
|
if ((status.nonCleanFileCount ?? 0) > 0) return "Next: run /kb sync to update project knowledge, or /kb status to inspect the files.";
|
|
12432
12480
|
}
|
|
12433
12481
|
//#endregion
|
|
12482
|
+
//#region src/agent/runtime/steering.ts
|
|
12483
|
+
var MutableRuntimeSteeringBuffer = class {
|
|
12484
|
+
prompts = [];
|
|
12485
|
+
push(prompt) {
|
|
12486
|
+
const trimmed = prompt.trim();
|
|
12487
|
+
if (trimmed.length > 0) this.prompts.push(trimmed);
|
|
12488
|
+
}
|
|
12489
|
+
drain() {
|
|
12490
|
+
if (this.prompts.length === 0) return;
|
|
12491
|
+
return this.prompts.splice(0).join("\n\n");
|
|
12492
|
+
}
|
|
12493
|
+
hasPending() {
|
|
12494
|
+
return this.prompts.length > 0;
|
|
12495
|
+
}
|
|
12496
|
+
};
|
|
12497
|
+
function formatRuntimeSteeringPrompt(steering) {
|
|
12498
|
+
return [
|
|
12499
|
+
"User steering received while this turn was running:",
|
|
12500
|
+
steering.trim(),
|
|
12501
|
+
"",
|
|
12502
|
+
"Continue the user's original request, applying this steering if it is still relevant."
|
|
12503
|
+
].join("\n");
|
|
12504
|
+
}
|
|
12505
|
+
//#endregion
|
|
12434
12506
|
//#region src/agent/runtime/model.ts
|
|
12435
12507
|
/**
|
|
12436
12508
|
* Calls the configured model gateway for a single agent step and normalizes
|
|
@@ -12809,7 +12881,7 @@ var TopchesterAgentRuntime = class TopchesterAgentRuntime {
|
|
|
12809
12881
|
}
|
|
12810
12882
|
}
|
|
12811
12883
|
afterTool = "task";
|
|
12812
|
-
nextPrompt = this.appendHookContextsToPrompt(`${nextPrompt}\n\n${taskResults.map((toolResult) => formatToolResultForPrompt(toolResult)).join("\n\n")}\n\n${formatContinuationInstruction(result.toolProtocol, taskResults.at(-1), isToolAllowed(permissions, "plan_todo"))}`, "PostToolUse", postHookContexts);
|
|
12884
|
+
nextPrompt = this.appendRuntimeSteeringToContinuationPrompt(this.appendHookContextsToPrompt(`${nextPrompt}\n\n${taskResults.map((toolResult) => formatToolResultForPrompt(toolResult)).join("\n\n")}\n\n${formatContinuationInstruction(result.toolProtocol, taskResults.at(-1), isToolAllowed(permissions, "plan_todo"))}`, "PostToolUse", postHookContexts), options.steering);
|
|
12813
12885
|
continue;
|
|
12814
12886
|
}
|
|
12815
12887
|
if (modelToolCalls.length > 1 && modelToolCalls.every((call) => toolCatalog.isParallelSafe(call.tool))) {
|
|
@@ -12872,7 +12944,7 @@ var TopchesterAgentRuntime = class TopchesterAgentRuntime {
|
|
|
12872
12944
|
}
|
|
12873
12945
|
}
|
|
12874
12946
|
afterTool = parallelCalls.at(-1)?.tool;
|
|
12875
|
-
nextPrompt = this.appendHookContextsToPrompt(`${nextPrompt}\n\n${parallelResults.map((toolResult) => formatToolResultForPrompt(toolResult)).join("\n\n")}\n\n${formatContinuationInstruction(result.toolProtocol, parallelResults.at(-1), isToolAllowed(permissions, "plan_todo"))}`, "PostToolUse", postHookContexts);
|
|
12947
|
+
nextPrompt = this.appendRuntimeSteeringToContinuationPrompt(this.appendHookContextsToPrompt(`${nextPrompt}\n\n${parallelResults.map((toolResult) => formatToolResultForPrompt(toolResult)).join("\n\n")}\n\n${formatContinuationInstruction(result.toolProtocol, parallelResults.at(-1), isToolAllowed(permissions, "plan_todo"))}`, "PostToolUse", postHookContexts), options.steering);
|
|
12876
12948
|
continue;
|
|
12877
12949
|
}
|
|
12878
12950
|
const executableToolCall = toolCall;
|
|
@@ -12940,7 +13012,7 @@ var TopchesterAgentRuntime = class TopchesterAgentRuntime {
|
|
|
12940
13012
|
return;
|
|
12941
13013
|
}
|
|
12942
13014
|
afterTool = executableToolCall.tool;
|
|
12943
|
-
nextPrompt = this.appendHookContextsToPrompt(`${nextPrompt}\n\n${formatToolResultForPrompt(toolResult)}\n\n${formatContinuationInstruction(result.toolProtocol, toolResult, isToolAllowed(permissions, "plan_todo"))}`, "PostToolUse", postHook.contexts);
|
|
13015
|
+
nextPrompt = this.appendRuntimeSteeringToContinuationPrompt(this.appendHookContextsToPrompt(`${nextPrompt}\n\n${formatToolResultForPrompt(toolResult)}\n\n${formatContinuationInstruction(result.toolProtocol, toolResult, isToolAllowed(permissions, "plan_todo"))}`, "PostToolUse", postHook.contexts), options.steering);
|
|
12944
13016
|
}
|
|
12945
13017
|
const finalMessage = "I stopped because the tool loop ended unexpectedly.";
|
|
12946
13018
|
yield agentEvent.assistantMessage(finalMessage, formatAgentMessageMeta(lastModelId, totalDurationMs, tokenUsageTotals));
|
|
@@ -13219,6 +13291,11 @@ var TopchesterAgentRuntime = class TopchesterAgentRuntime {
|
|
|
13219
13291
|
nonCleanFileCount: result.files.length
|
|
13220
13292
|
};
|
|
13221
13293
|
}
|
|
13294
|
+
appendRuntimeSteeringToContinuationPrompt(prompt, steering) {
|
|
13295
|
+
const text = steering?.drain()?.trim();
|
|
13296
|
+
if (!text) return prompt;
|
|
13297
|
+
return `${prompt}\n\n${formatRuntimeSteeringPrompt(text)}`;
|
|
13298
|
+
}
|
|
13222
13299
|
/**
|
|
13223
13300
|
* Adds relevant L1 knowledge context to the conversation prompt when the
|
|
13224
13301
|
* compiled KB is present and ready. Search failures are logged and then
|
|
@@ -13782,6 +13859,9 @@ var TopchesterTuiShell = class {
|
|
|
13782
13859
|
knowledgeStatusTimer;
|
|
13783
13860
|
skillsService;
|
|
13784
13861
|
pendingSkillActivations = [];
|
|
13862
|
+
chatRunning = false;
|
|
13863
|
+
queuedChatMessages = [];
|
|
13864
|
+
activeSteeringBuffer;
|
|
13785
13865
|
constructor(context, runtime, options = {}) {
|
|
13786
13866
|
this.context = context;
|
|
13787
13867
|
this.options = options;
|
|
@@ -13833,10 +13913,26 @@ var TopchesterTuiShell = class {
|
|
|
13833
13913
|
app.setTaskPlan(this.options.initialTaskPlan);
|
|
13834
13914
|
if (!isResumed) app.setStartupHintLine(STARTUP_PROMPT_HINT);
|
|
13835
13915
|
app.setSubmitMessage((message) => {
|
|
13916
|
+
if (this.chatRunning) {
|
|
13917
|
+
this.enqueueChatMessage(app, tui, message);
|
|
13918
|
+
return "queued";
|
|
13919
|
+
}
|
|
13836
13920
|
this.startBackgroundTask(app, tui, "Chat", () => this.submitChatMessage(app, tui, message));
|
|
13921
|
+
return "submitted";
|
|
13837
13922
|
});
|
|
13838
13923
|
app.setSubmitCommand((command) => {
|
|
13924
|
+
const queuedPrompt = parseQueueCommandPrompt(command);
|
|
13925
|
+
if (queuedPrompt !== void 0) {
|
|
13926
|
+
this.submitQueueCommand(app, tui, queuedPrompt);
|
|
13927
|
+
return "queued";
|
|
13928
|
+
}
|
|
13929
|
+
const steeringPrompt = parseSteerCommandPrompt(command);
|
|
13930
|
+
if (steeringPrompt !== void 0) {
|
|
13931
|
+
this.submitSteerCommand(app, tui, steeringPrompt);
|
|
13932
|
+
return "queued";
|
|
13933
|
+
}
|
|
13839
13934
|
this.startBackgroundTask(app, tui, "Command", () => this.submitSlashCommand(app, tui, command));
|
|
13935
|
+
return "submitted";
|
|
13840
13936
|
});
|
|
13841
13937
|
tui.addChild(app);
|
|
13842
13938
|
tui.setFocus(app);
|
|
@@ -13902,9 +13998,15 @@ var TopchesterTuiShell = class {
|
|
|
13902
13998
|
tui.requestRender();
|
|
13903
13999
|
}
|
|
13904
14000
|
async submitChatMessage(app, tui, message) {
|
|
14001
|
+
if (this.chatRunning) {
|
|
14002
|
+
this.enqueueChatMessage(app, tui, message);
|
|
14003
|
+
return;
|
|
14004
|
+
}
|
|
14005
|
+
const activeSession = this.session;
|
|
14006
|
+
const steering = new MutableRuntimeSteeringBuffer();
|
|
13905
14007
|
const busy = new BusyIndicator(app, tui, {
|
|
13906
14008
|
status: "thinking",
|
|
13907
|
-
|
|
14009
|
+
activityHint: "press Esc to stop",
|
|
13908
14010
|
activities: [
|
|
13909
14011
|
"Thinking...",
|
|
13910
14012
|
"Calling model...",
|
|
@@ -13914,10 +14016,13 @@ var TopchesterTuiShell = class {
|
|
|
13914
14016
|
const abortController = new AbortController();
|
|
13915
14017
|
const reasoningDisplay = isStreamReasoningEnabledByEnv() ? createBusyReasoningSink(busy) : void 0;
|
|
13916
14018
|
let cancelled = false;
|
|
14019
|
+
this.activeSteeringBuffer = steering;
|
|
13917
14020
|
app.setCancelPending(() => {
|
|
13918
14021
|
cancelled = true;
|
|
13919
14022
|
abortController.abort();
|
|
13920
14023
|
});
|
|
14024
|
+
this.chatRunning = true;
|
|
14025
|
+
this.refreshQueuedChatStatus(app);
|
|
13921
14026
|
busy.start();
|
|
13922
14027
|
tui.requestRender();
|
|
13923
14028
|
try {
|
|
@@ -13936,7 +14041,8 @@ var TopchesterTuiShell = class {
|
|
|
13936
14041
|
for await (const event of this.runtime.submitMessageStream(conversation, modelMessage, abortController.signal, {
|
|
13937
14042
|
onReasoning: reasoningDisplay?.sink,
|
|
13938
14043
|
session: this.session,
|
|
13939
|
-
requestBashApproval: (request) => this.requestBashApproval(app, tui, busy, request, abortController.signal)
|
|
14044
|
+
requestBashApproval: (request) => this.requestBashApproval(app, tui, busy, request, abortController.signal),
|
|
14045
|
+
steering
|
|
13940
14046
|
})) {
|
|
13941
14047
|
if (event.type === "message" && event.role === "assistant") {
|
|
13942
14048
|
reasoningDisplay?.commit(app);
|
|
@@ -13959,9 +14065,93 @@ var TopchesterTuiShell = class {
|
|
|
13959
14065
|
}
|
|
13960
14066
|
} finally {
|
|
13961
14067
|
app.setCancelPending(void 0);
|
|
14068
|
+
this.chatRunning = false;
|
|
14069
|
+
if (this.activeSteeringBuffer === steering) this.activeSteeringBuffer = void 0;
|
|
13962
14070
|
busy.stop();
|
|
13963
14071
|
tui.requestRender();
|
|
13964
14072
|
}
|
|
14073
|
+
this.handleUnconsumedSteering(app, tui, steering, cancelled);
|
|
14074
|
+
if (this.session === activeSession && app.isReady()) await this.drainQueuedChatMessages(app, tui);
|
|
14075
|
+
}
|
|
14076
|
+
enqueueChatMessage(app, tui, message) {
|
|
14077
|
+
const trimmed = message.trim();
|
|
14078
|
+
if (trimmed.length === 0) return;
|
|
14079
|
+
this.queuedChatMessages.push(trimmed);
|
|
14080
|
+
this.refreshQueuedChatStatus(app);
|
|
14081
|
+
tui.requestRender();
|
|
14082
|
+
}
|
|
14083
|
+
submitQueueCommand(app, tui, prompt) {
|
|
14084
|
+
const trimmed = prompt.trim();
|
|
14085
|
+
if (trimmed.length === 0) {
|
|
14086
|
+
app.addMessage(systemMessage("Usage: /queue <prompt>"));
|
|
14087
|
+
tui.requestRender();
|
|
14088
|
+
return;
|
|
14089
|
+
}
|
|
14090
|
+
if (this.chatRunning) {
|
|
14091
|
+
this.enqueueChatMessage(app, tui, trimmed);
|
|
14092
|
+
return;
|
|
14093
|
+
}
|
|
14094
|
+
app.addMessage(userMessage(trimmed));
|
|
14095
|
+
this.startBackgroundTask(app, tui, "Chat", () => this.submitChatMessage(app, tui, trimmed));
|
|
14096
|
+
tui.requestRender();
|
|
14097
|
+
}
|
|
14098
|
+
submitSteerCommand(app, tui, prompt) {
|
|
14099
|
+
const trimmed = prompt.trim();
|
|
14100
|
+
if (trimmed.length === 0) {
|
|
14101
|
+
app.addMessage(systemMessage("Usage: /steer <prompt>"));
|
|
14102
|
+
tui.requestRender();
|
|
14103
|
+
return;
|
|
14104
|
+
}
|
|
14105
|
+
if (!this.chatRunning) {
|
|
14106
|
+
app.addMessage(userMessage(trimmed));
|
|
14107
|
+
this.startBackgroundTask(app, tui, "Chat", () => this.submitChatMessage(app, tui, trimmed));
|
|
14108
|
+
tui.requestRender();
|
|
14109
|
+
return;
|
|
14110
|
+
}
|
|
14111
|
+
const steering = this.activeSteeringBuffer;
|
|
14112
|
+
if (!steering) {
|
|
14113
|
+
this.enqueueChatMessage(app, tui, trimmed);
|
|
14114
|
+
return;
|
|
14115
|
+
}
|
|
14116
|
+
steering.push(trimmed);
|
|
14117
|
+
app.setTemporaryLine("steering added to active turn", { expireAfterMs: 2e3 });
|
|
14118
|
+
tui.requestRender();
|
|
14119
|
+
}
|
|
14120
|
+
handleUnconsumedSteering(app, tui, steering, cancelled) {
|
|
14121
|
+
const pending = steering.drain();
|
|
14122
|
+
if (!pending) return;
|
|
14123
|
+
if (cancelled) {
|
|
14124
|
+
app.addMessage(systemMessage("Dropped pending steering after response stopped."));
|
|
14125
|
+
tui.requestRender();
|
|
14126
|
+
return;
|
|
14127
|
+
}
|
|
14128
|
+
this.enqueueChatMessage(app, tui, pending);
|
|
14129
|
+
}
|
|
14130
|
+
async drainQueuedChatMessages(app, tui) {
|
|
14131
|
+
while (!this.chatRunning && app.isReady()) {
|
|
14132
|
+
const message = this.queuedChatMessages.shift();
|
|
14133
|
+
this.refreshQueuedChatStatus(app);
|
|
14134
|
+
if (!message) {
|
|
14135
|
+
tui.requestRender();
|
|
14136
|
+
return;
|
|
14137
|
+
}
|
|
14138
|
+
app.addMessage(userMessage(message));
|
|
14139
|
+
tui.requestRender();
|
|
14140
|
+
await this.submitChatMessage(app, tui, message);
|
|
14141
|
+
}
|
|
14142
|
+
}
|
|
14143
|
+
refreshQueuedChatStatus(app) {
|
|
14144
|
+
app.setQueuedFollowUpCount(this.queuedChatMessages.length);
|
|
14145
|
+
}
|
|
14146
|
+
clearQueuedChatMessages(app) {
|
|
14147
|
+
const droppedCount = this.queuedChatMessages.length;
|
|
14148
|
+
this.queuedChatMessages = [];
|
|
14149
|
+
const droppedSteering = this.activeSteeringBuffer?.hasPending() ? this.activeSteeringBuffer.drain() : void 0;
|
|
14150
|
+
this.refreshQueuedChatStatus(app);
|
|
14151
|
+
if (droppedCount === 0 && !droppedSteering) return;
|
|
14152
|
+
const parts = droppedCount > 0 ? [`Dropped ${droppedCount} queued ${droppedCount === 1 ? "follow-up" : "follow-ups"}.`] : [];
|
|
14153
|
+
if (droppedSteering) parts.push("Dropped pending steering.");
|
|
14154
|
+
return parts.join(" ");
|
|
13965
14155
|
}
|
|
13966
14156
|
requestBashApproval(app, tui, busy, request, abortSignal) {
|
|
13967
14157
|
return new Promise((resolve) => {
|
|
@@ -14443,7 +14633,9 @@ var TopchesterTuiShell = class {
|
|
|
14443
14633
|
this.taskPlanNoticeTimer = void 0;
|
|
14444
14634
|
}
|
|
14445
14635
|
const session = await createSession(this.context.workspaceRoot);
|
|
14636
|
+
const droppedQueuedNotice = this.clearQueuedChatMessages(app);
|
|
14446
14637
|
const messages = getStartupThreadMessages(this.context);
|
|
14638
|
+
if (droppedQueuedNotice) messages.push(systemMessage(droppedQueuedNotice));
|
|
14447
14639
|
this.session = session;
|
|
14448
14640
|
this.sessionStartedAt = Date.now();
|
|
14449
14641
|
this.pendingSkillActivations = [];
|
|
@@ -14470,7 +14662,12 @@ var TopchesterTuiShell = class {
|
|
|
14470
14662
|
const rehydrated = rehydrateSession((await loadSession(this.context.workspaceRoot, fork.sessionId)).events);
|
|
14471
14663
|
const forkNoticeText = `Forked session from ${sourceSession.sessionId.slice(0, 8)}.`;
|
|
14472
14664
|
const forkNotice = systemMessage(forkNoticeText);
|
|
14473
|
-
const
|
|
14665
|
+
const droppedQueuedNotice = this.clearQueuedChatMessages(app);
|
|
14666
|
+
const resetMessages = [
|
|
14667
|
+
...rehydrated.messages,
|
|
14668
|
+
forkNotice,
|
|
14669
|
+
...droppedQueuedNotice ? [systemMessage(droppedQueuedNotice)] : []
|
|
14670
|
+
];
|
|
14474
14671
|
this.session = fork;
|
|
14475
14672
|
this.sessionStartedAt = Date.now();
|
|
14476
14673
|
this.pendingSkillActivations = [];
|
|
@@ -14528,7 +14725,12 @@ var TopchesterTuiShell = class {
|
|
|
14528
14725
|
restoredTaskPlan = rehydrated.taskPlan;
|
|
14529
14726
|
restoredStatus = rehydrated.status;
|
|
14530
14727
|
const noticeText = `Restored session ${sessionId.slice(0, 8)}.`;
|
|
14531
|
-
|
|
14728
|
+
const droppedQueuedNotice = this.clearQueuedChatMessages(app);
|
|
14729
|
+
restoredMessages = [
|
|
14730
|
+
...rehydrated.messages,
|
|
14731
|
+
systemMessage(noticeText),
|
|
14732
|
+
...droppedQueuedNotice ? [systemMessage(droppedQueuedNotice)] : []
|
|
14733
|
+
];
|
|
14532
14734
|
this.session = restoredSession;
|
|
14533
14735
|
this.sessionStartedAt = Date.now();
|
|
14534
14736
|
this.pendingSkillActivations = [];
|
|
@@ -14618,6 +14820,16 @@ var TopchesterTuiShell = class {
|
|
|
14618
14820
|
printExitBanner((this.session ?? fallbackSession).sessionId, Date.now() - this.sessionStartedAt);
|
|
14619
14821
|
}
|
|
14620
14822
|
};
|
|
14823
|
+
function parseQueueCommandPrompt(command) {
|
|
14824
|
+
const trimmed = command.trim();
|
|
14825
|
+
const match = /^\/(?:queue|q)(?:\s+([\s\S]*))?$/u.exec(trimmed);
|
|
14826
|
+
return match ? match[1] ?? "" : void 0;
|
|
14827
|
+
}
|
|
14828
|
+
function parseSteerCommandPrompt(command) {
|
|
14829
|
+
const trimmed = command.trim();
|
|
14830
|
+
const match = /^\/steer(?:\s+([\s\S]*))?$/u.exec(trimmed);
|
|
14831
|
+
return match ? match[1] ?? "" : void 0;
|
|
14832
|
+
}
|
|
14621
14833
|
//#endregion
|
|
14622
14834
|
//#region src/version.ts
|
|
14623
14835
|
const FALLBACK_VERSION = "0.0.0";
|
|
@@ -15125,8 +15337,8 @@ function createTopchesterProgram() {
|
|
|
15125
15337
|
console.log(result.lines.join("\n"));
|
|
15126
15338
|
if (!result.ok) process.exitCode = 1;
|
|
15127
15339
|
});
|
|
15128
|
-
const authCommand = program.command("auth").description("manage global provider authentication");
|
|
15129
|
-
authCommand.command("login").description("log in to a provider").argument("
|
|
15340
|
+
const authCommand = program.command("auth").description("manage global provider authentication").addHelpText("after", formatAuthCommandHelp);
|
|
15341
|
+
authCommand.command("login").usage("[options] <provider>").description("log in to a provider").argument("[provider]", "provider id").option("--device", "use device-code login").addHelpText("after", formatAuthLoginHelp).action(async (provider, options) => {
|
|
15130
15342
|
try {
|
|
15131
15343
|
await executeAuthLoginCommand(provider, options);
|
|
15132
15344
|
} catch (error) {
|
|
@@ -15259,19 +15471,66 @@ function printStartupSummary(context) {
|
|
|
15259
15471
|
}
|
|
15260
15472
|
}
|
|
15261
15473
|
}
|
|
15474
|
+
const AUTH_PROVIDERS = [{
|
|
15475
|
+
id: "codex",
|
|
15476
|
+
name: "Codex / ChatGPT",
|
|
15477
|
+
auth: "OAuth device-code login for Codex-backed model access.",
|
|
15478
|
+
example: "topchester auth login codex --device"
|
|
15479
|
+
}];
|
|
15480
|
+
function formatAuthCommandHelp() {
|
|
15481
|
+
return [
|
|
15482
|
+
"",
|
|
15483
|
+
ui.label("Supported providers:"),
|
|
15484
|
+
...AUTH_PROVIDERS.map((provider) => ` ${ui.modelInline(provider.id.padEnd(8))} ${provider.name} - ${provider.auth}`),
|
|
15485
|
+
"",
|
|
15486
|
+
ui.label("Examples:"),
|
|
15487
|
+
...AUTH_PROVIDERS.map((provider) => ` ${provider.example}`),
|
|
15488
|
+
" topchester auth status"
|
|
15489
|
+
].join("\n");
|
|
15490
|
+
}
|
|
15491
|
+
function formatAuthLoginHelp() {
|
|
15492
|
+
return [
|
|
15493
|
+
"",
|
|
15494
|
+
ui.label("Supported providers:"),
|
|
15495
|
+
...AUTH_PROVIDERS.map((provider) => ` ${ui.modelInline(provider.id.padEnd(8))} ${provider.auth}`),
|
|
15496
|
+
"",
|
|
15497
|
+
ui.label("Examples:"),
|
|
15498
|
+
...AUTH_PROVIDERS.map((provider) => ` ${provider.example}`),
|
|
15499
|
+
"",
|
|
15500
|
+
ui.label("What happens:"),
|
|
15501
|
+
" Topchester prints a browser URL and one-time code, waits for approval, then stores tokens in the global auth store."
|
|
15502
|
+
].join("\n");
|
|
15503
|
+
}
|
|
15504
|
+
function formatAuthLoginUsageError(reason) {
|
|
15505
|
+
return [
|
|
15506
|
+
ui.error(reason),
|
|
15507
|
+
"",
|
|
15508
|
+
ui.label("Usage:"),
|
|
15509
|
+
" topchester auth login <provider> --device",
|
|
15510
|
+
"",
|
|
15511
|
+
ui.label("Supported providers:"),
|
|
15512
|
+
...AUTH_PROVIDERS.map((provider) => ` ${provider.id.padEnd(8)} ${provider.name} - ${provider.auth}`),
|
|
15513
|
+
"",
|
|
15514
|
+
ui.label("Examples:"),
|
|
15515
|
+
...AUTH_PROVIDERS.map((provider) => ` ${provider.example}`),
|
|
15516
|
+
"",
|
|
15517
|
+
"Run `topchester auth login --help` for details."
|
|
15518
|
+
].join("\n");
|
|
15519
|
+
}
|
|
15262
15520
|
async function executeAuthLoginCommand(provider, options) {
|
|
15263
|
-
if (provider
|
|
15264
|
-
if (
|
|
15521
|
+
if (!provider) throw new Error(formatAuthLoginUsageError("Missing provider."));
|
|
15522
|
+
if (provider !== "codex") throw new Error(formatAuthLoginUsageError(`Unsupported auth provider "${provider}".`));
|
|
15523
|
+
if (!options.device) throw new Error(formatAuthLoginUsageError("Codex login currently requires \"--device\"."));
|
|
15265
15524
|
const deviceCode = await requestCodexDeviceCode();
|
|
15266
|
-
console.log("Codex device login");
|
|
15267
|
-
console.log(
|
|
15268
|
-
console.log(
|
|
15269
|
-
console.log(
|
|
15270
|
-
console.log("Device codes are a common phishing target. Never share this code.");
|
|
15271
|
-
console.log("Waiting for browser approval...");
|
|
15525
|
+
console.log(ui.heading("Codex device login"));
|
|
15526
|
+
console.log(`${ui.label("verification URL:")} ${deviceCode.verificationUrl}`);
|
|
15527
|
+
console.log(`${ui.label("user code:")} ${ui.inverse(deviceCode.userCode)}`);
|
|
15528
|
+
console.log(`${ui.label("expires:")} ${new Date(deviceCode.expiresAt).toISOString()}`);
|
|
15529
|
+
console.log(ui.warn("Device codes are a common phishing target. Never share this code."));
|
|
15530
|
+
console.log(ui.label("Waiting for browser approval..."));
|
|
15272
15531
|
await setAuthProvider("codex", await exchangeCodexAuthorizationCode(await pollCodexDeviceAuthorization(deviceCode), { issuer: deviceCode.issuer }));
|
|
15273
15532
|
await configureCodexGlobalProvider();
|
|
15274
|
-
console.log("Codex login saved.");
|
|
15533
|
+
console.log(ui.ok("Codex login saved."));
|
|
15275
15534
|
console.log("Configured global Codex provider and starter model choices.");
|
|
15276
15535
|
}
|
|
15277
15536
|
async function formatAuthStatus() {
|
|
@@ -15370,4 +15629,4 @@ function formatDryRunSyncStatus(status) {
|
|
|
15370
15629
|
//#endregion
|
|
15371
15630
|
export { runTopchesterCli as t };
|
|
15372
15631
|
|
|
15373
|
-
//# sourceMappingURL=cli-
|
|
15632
|
+
//# sourceMappingURL=cli-yf0DNAUH.mjs.map
|