@bastani/atomic 0.9.13-alpha.3 → 0.9.13
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/CHANGELOG.md +97 -0
- package/dist/builtin/i-have-adhd/CHANGELOG.md +13 -0
- package/dist/builtin/i-have-adhd/package.json +1 -1
- package/dist/builtin/intercom/CHANGELOG.md +26 -0
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/mcp/CHANGELOG.md +15 -0
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/CHANGELOG.md +41 -0
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/web-access/CHANGELOG.md +14 -0
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +57 -0
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +70 -16
- package/dist/builtin/workflows/src/extension/ui-surface.ts +2 -0
- package/dist/builtin/workflows/src/tui/keybindings-adapter.ts +1 -0
- package/dist/builtin/workflows/src/tui/overlay-adapter.ts +1 -0
- package/dist/builtin/workflows/src/tui/stage-chat-view-archive-history.ts +27 -8
- package/dist/builtin/workflows/src/tui/stage-chat-view-input.ts +17 -1
- package/dist/builtin/workflows/src/tui/stage-chat-view.ts +20 -3
- package/dist/builtin/workflows/src/tui/workflow-attach-pane.ts +10 -1
- package/dist/core/agent-session-events.d.ts.map +1 -1
- package/dist/core/agent-session-events.js +6 -0
- package/dist/core/agent-session-events.js.map +1 -1
- package/dist/core/agent-session-methods.d.ts +2 -0
- package/dist/core/agent-session-methods.d.ts.map +1 -1
- package/dist/core/agent-session-methods.js.map +1 -1
- package/dist/core/agent-session-prompt.d.ts.map +1 -1
- package/dist/core/agent-session-prompt.js +63 -0
- package/dist/core/agent-session-prompt.js.map +1 -1
- package/dist/core/agent-session-queue-pause.d.ts.map +1 -1
- package/dist/core/agent-session-queue-pause.js +6 -0
- package/dist/core/agent-session-queue-pause.js.map +1 -1
- package/dist/core/agent-session.d.ts +14 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +14 -0
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/extensions/ui-types.d.ts +2 -0
- package/dist/core/extensions/ui-types.d.ts.map +1 -1
- package/dist/core/extensions/ui-types.js.map +1 -1
- package/dist/core/keybindings.d.ts +0 -5
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +0 -2
- package/dist/core/keybindings.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +1 -0
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +1 -0
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/transcript-follow-indicator.d.ts +14 -0
- package/dist/modes/interactive/components/transcript-follow-indicator.d.ts.map +1 -0
- package/dist/modes/interactive/components/transcript-follow-indicator.js +36 -0
- package/dist/modes/interactive/components/transcript-follow-indicator.js.map +1 -0
- package/dist/modes/interactive/interactive-extension-custom-ui.js +3 -0
- package/dist/modes/interactive/interactive-extension-custom-ui.js.map +1 -1
- package/dist/modes/interactive/interactive-input-handling.js +0 -3
- package/dist/modes/interactive/interactive-input-handling.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-base.d.ts +1 -0
- package/dist/modes/interactive/interactive-mode-base.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-base.js +7 -1
- package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-surface.d.ts +3 -3
- package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +1 -0
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/interactive-slash-commands.js +2 -5
- package/dist/modes/interactive/interactive-slash-commands.js.map +1 -1
- package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-startup.js +6 -0
- package/dist/modes/interactive/interactive-startup.js.map +1 -1
- package/dist/modes/interactive/interactive-transcript-follow.d.ts +2 -0
- package/dist/modes/interactive/interactive-transcript-follow.d.ts.map +1 -0
- package/dist/modes/interactive/interactive-transcript-follow.js +6 -0
- package/dist/modes/interactive/interactive-transcript-follow.js.map +1 -0
- package/dist/modes/interactive/interactive-tui.d.ts +13 -1
- package/dist/modes/interactive/interactive-tui.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-tui.js +59 -1
- package/dist/modes/interactive/interactive-tui.js.map +1 -1
- package/dist/modes/interactive-engine/engine-custom-ui.d.ts +2 -0
- package/dist/modes/interactive-engine/engine-custom-ui.d.ts.map +1 -1
- package/dist/modes/interactive-engine/engine-custom-ui.js +1 -0
- package/dist/modes/interactive-engine/engine-custom-ui.js.map +1 -1
- package/dist/modes/interactive-engine/protocol.d.ts +1 -0
- package/dist/modes/interactive-engine/protocol.d.ts.map +1 -1
- package/dist/modes/interactive-engine/protocol.js +1 -0
- package/dist/modes/interactive-engine/protocol.js.map +1 -1
- package/dist/modes/interactive-engine/remote-component.d.ts.map +1 -1
- package/dist/modes/interactive-engine/remote-component.js +21 -9
- package/dist/modes/interactive-engine/remote-component.js.map +1 -1
- package/docs/keybindings.md +2 -5
- package/docs/usage.md +2 -0
- package/npm-shrinkwrap.json +29 -29
- package/package.json +2 -2
|
@@ -38951,6 +38951,7 @@ var APP_ACTION = {
|
|
|
38951
38951
|
thinkingToggle: "app.thinking.toggle"
|
|
38952
38952
|
};
|
|
38953
38953
|
var TUI_ACTION = {
|
|
38954
|
+
altScreenBottom: "tui.altScreen.bottom",
|
|
38954
38955
|
editorCursorUp: "tui.editor.cursorUp",
|
|
38955
38956
|
editorCursorDown: "tui.editor.cursorDown",
|
|
38956
38957
|
editorCursorLeft: "tui.editor.cursorLeft",
|
|
@@ -40606,6 +40607,11 @@ function remoteTerminalControlFrom(tui) {
|
|
|
40606
40607
|
return { setAutowrap: terminal.setAutowrap.bind(terminal) };
|
|
40607
40608
|
}
|
|
40608
40609
|
|
|
40610
|
+
// dist/builtin/workflows/src/tui/workflow-attach-pane.ts
|
|
40611
|
+
import {
|
|
40612
|
+
TRANSCRIPT_JUMP_TO_END_URL as TRANSCRIPT_JUMP_TO_END_URL2
|
|
40613
|
+
} from "@bastani/atomic";
|
|
40614
|
+
|
|
40609
40615
|
// dist/builtin/workflows/src/runs/foreground/stage-queued-user-messages.ts
|
|
40610
40616
|
var EMPTY_STAGE_QUEUED_USER_MESSAGES = Object.freeze({
|
|
40611
40617
|
steering: Object.freeze([]),
|
|
@@ -43796,6 +43802,9 @@ class StageChatComposerDrafts {
|
|
|
43796
43802
|
}
|
|
43797
43803
|
}
|
|
43798
43804
|
|
|
43805
|
+
// dist/builtin/workflows/src/tui/stage-chat-view.ts
|
|
43806
|
+
import { keyText as keyText2, TranscriptFollowIndicator } from "@bastani/atomic";
|
|
43807
|
+
|
|
43799
43808
|
// dist/builtin/workflows/src/tui/stage-chat-layout.ts
|
|
43800
43809
|
function resolveStageChatViewportRows(reported, fallbackRows) {
|
|
43801
43810
|
if (typeof reported !== "number" || !Number.isFinite(reported)) {
|
|
@@ -44130,7 +44139,7 @@ function postMortemUnavailableMessage(reason) {
|
|
|
44130
44139
|
return;
|
|
44131
44140
|
}
|
|
44132
44141
|
}
|
|
44133
|
-
function renderReadOnlyArchiveBody(ctx, width, budget, stage) {
|
|
44142
|
+
function renderReadOnlyArchiveBody(ctx, width, budget, stage, indicatorLines = [], renderIndicator = () => indicatorLines) {
|
|
44134
44143
|
if (stage?.promptFootprint) {
|
|
44135
44144
|
return renderReadOnlyPromptArchiveBody(ctx, width, budget, stage);
|
|
44136
44145
|
}
|
|
@@ -44141,8 +44150,13 @@ function renderReadOnlyArchiveBody(ctx, width, budget, stage) {
|
|
|
44141
44150
|
callout.push(...bannerLines(ctx, width, unavailableMessage === undefined ? "info" : "warning", unavailableMessage === undefined ? "◌" : "!", unavailableMessage === undefined ? "READ-ONLY SESSION" : "SESSION UNAVAILABLE", unavailableMessage === undefined ? stage?.sessionFile ? "archived transcript" : "no live chat session" : "post-mortem chat cannot be reopened"));
|
|
44142
44151
|
callout.push(...new Text2(paint2(unavailableMessage ?? "This node is no longer attached to a live chat session.", t.textMuted), 2, 0).render(width));
|
|
44143
44152
|
const transcriptBudget = Math.max(0, budget - callout.length);
|
|
44144
|
-
const
|
|
44145
|
-
|
|
44153
|
+
const reservedIndicatorRows = indicatorLines.length > 0 && transcriptBudget > indicatorLines.length ? indicatorLines.length : 0;
|
|
44154
|
+
const transcriptRows = transcriptBudget - reservedIndicatorRows;
|
|
44155
|
+
const lines = transcriptRows > 0 ? ctx.chatHost.renderBody(width, transcriptRows) : [];
|
|
44156
|
+
const visibleIndicatorLines = reservedIndicatorRows > 0 ? [...renderIndicator().slice(0, reservedIndicatorRows)] : [];
|
|
44157
|
+
while (visibleIndicatorLines.length < reservedIndicatorRows)
|
|
44158
|
+
visibleIndicatorLines.push(blankLine(width));
|
|
44159
|
+
lines.push(...visibleIndicatorLines, ...callout);
|
|
44146
44160
|
while (lines.length < budget)
|
|
44147
44161
|
lines.push(blankLine(width));
|
|
44148
44162
|
if (lines.length > budget)
|
|
@@ -44218,16 +44232,21 @@ function formatReadOnlyPromptAnswer(value2, kind) {
|
|
|
44218
44232
|
return String(value2);
|
|
44219
44233
|
}
|
|
44220
44234
|
}
|
|
44221
|
-
function renderPausedBody(ctx, width, budget) {
|
|
44235
|
+
function renderPausedBody(ctx, width, budget, indicatorLines = [], renderIndicator = () => indicatorLines) {
|
|
44222
44236
|
const t = ctx.theme;
|
|
44223
44237
|
const callout = [];
|
|
44224
44238
|
callout.push(blankLine(width));
|
|
44225
44239
|
callout.push(...bannerLines(ctx, width, "warning", "❚❚", "PAUSED", "enter resumes · ctrl+x return to graph"));
|
|
44226
44240
|
callout.push(...new Text2(paint2("This workflow stage is paused. Type a message below and press Enter to resume.", t.textMuted), 2, 0).render(width));
|
|
44227
|
-
const calloutRows = Math.min(callout.length, Math.max(0, budget
|
|
44228
|
-
const transcriptBudget = Math.max(
|
|
44229
|
-
const
|
|
44230
|
-
|
|
44241
|
+
const calloutRows = Math.min(callout.length, Math.max(0, budget));
|
|
44242
|
+
const transcriptBudget = Math.max(0, budget - calloutRows);
|
|
44243
|
+
const reservedIndicatorRows = indicatorLines.length > 0 && transcriptBudget > indicatorLines.length ? indicatorLines.length : 0;
|
|
44244
|
+
const transcriptRows = transcriptBudget - reservedIndicatorRows;
|
|
44245
|
+
const lines = transcriptRows > 0 ? ctx.chatHost.renderBody(width, transcriptRows) : [];
|
|
44246
|
+
const visibleIndicatorLines = reservedIndicatorRows > 0 ? [...renderIndicator().slice(0, reservedIndicatorRows)] : [];
|
|
44247
|
+
while (visibleIndicatorLines.length < reservedIndicatorRows)
|
|
44248
|
+
visibleIndicatorLines.push(blankLine(width));
|
|
44249
|
+
lines.push(...visibleIndicatorLines, ...callout.slice(0, calloutRows));
|
|
44231
44250
|
while (lines.length < budget)
|
|
44232
44251
|
lines.push(blankLine(width));
|
|
44233
44252
|
if (lines.length > budget)
|
|
@@ -44670,6 +44689,9 @@ function canSubmitPrompt(ctx, promptId) {
|
|
|
44670
44689
|
return ctx.canSubmitPrompt?.(ctx.runId, ctx.stageId, promptId) ?? true;
|
|
44671
44690
|
}
|
|
44672
44691
|
|
|
44692
|
+
// dist/builtin/workflows/src/tui/stage-chat-view-input.ts
|
|
44693
|
+
import { TRANSCRIPT_JUMP_TO_END_URL } from "@bastani/atomic";
|
|
44694
|
+
|
|
44673
44695
|
// dist/builtin/workflows/src/tui/stage-chat-view-state.ts
|
|
44674
44696
|
import { ChatSessionHost } from "@bastani/atomic";
|
|
44675
44697
|
import { Editor } from "@earendil-works/pi-tui";
|
|
@@ -45644,6 +45666,8 @@ function promptPageSize(ctx) {
|
|
|
45644
45666
|
|
|
45645
45667
|
// dist/builtin/workflows/src/tui/stage-chat-view-input.ts
|
|
45646
45668
|
function handleStageChatInput(ctx, data) {
|
|
45669
|
+
if (data === TRANSCRIPT_JUMP_TO_END_URL)
|
|
45670
|
+
return handleStageChatJumpToBottom(ctx, data);
|
|
45647
45671
|
const keybindings = isKeybindingsLike(ctx.piKeybindings) ? ctx.piKeybindings : undefined;
|
|
45648
45672
|
if (matchesKey(data, Key.ctrl("t")) && matchesAction(keybindings, data, APP_ACTION.thinkingToggle)) {
|
|
45649
45673
|
return false;
|
|
@@ -45677,6 +45701,8 @@ function handleStageChatInput(ctx, data) {
|
|
|
45677
45701
|
if (readOnlyPromptArchive && handlePromptScrollInput(ctx, data, true)) {
|
|
45678
45702
|
return true;
|
|
45679
45703
|
}
|
|
45704
|
+
if (handleStageChatJumpToBottom(ctx, data))
|
|
45705
|
+
return true;
|
|
45680
45706
|
if (ctx.chatHost.handleScrollInput(data))
|
|
45681
45707
|
return true;
|
|
45682
45708
|
if (matchesKey(data, Key.escape)) {
|
|
@@ -45707,6 +45733,13 @@ function handleStageChatInput(ctx, data) {
|
|
|
45707
45733
|
return true;
|
|
45708
45734
|
return ctx.chatHost.handleInput(data);
|
|
45709
45735
|
}
|
|
45736
|
+
function handleStageChatJumpToBottom(ctx, data) {
|
|
45737
|
+
const keybindings = isKeybindingsLike(ctx.piKeybindings) ? ctx.piKeybindings : undefined;
|
|
45738
|
+
if (data !== TRANSCRIPT_JUMP_TO_END_URL && !matchesAction(keybindings, data, TUI_ACTION.altScreenBottom))
|
|
45739
|
+
return false;
|
|
45740
|
+
ctx.chatHost.scrollToBottom();
|
|
45741
|
+
return true;
|
|
45742
|
+
}
|
|
45710
45743
|
function handleToolsExpandInput(ctx, data) {
|
|
45711
45744
|
const keybindings = isKeybindingsLike(ctx.piKeybindings) ? ctx.piKeybindings : undefined;
|
|
45712
45745
|
if (!matchesAction(keybindings, data, APP_ACTION.toolsExpand))
|
|
@@ -45730,6 +45763,10 @@ function handleMountedCustomUiInput(ctx, data) {
|
|
|
45730
45763
|
ctx.onClose();
|
|
45731
45764
|
return true;
|
|
45732
45765
|
}
|
|
45766
|
+
if (handleStageChatJumpToBottom(ctx, data)) {
|
|
45767
|
+
ctx.requestRender?.();
|
|
45768
|
+
return true;
|
|
45769
|
+
}
|
|
45733
45770
|
if (ctx.chatHost.handleScrollInput(data)) {
|
|
45734
45771
|
ctx.requestRender?.();
|
|
45735
45772
|
return true;
|
|
@@ -45904,6 +45941,12 @@ class StageChatView {
|
|
|
45904
45941
|
if (blocked)
|
|
45905
45942
|
this.chatHost.scrollToBottom();
|
|
45906
45943
|
let bodyLines;
|
|
45944
|
+
let transcriptBodyActive = false;
|
|
45945
|
+
let reservedIndicatorLines = [];
|
|
45946
|
+
const indicator = new TranscriptFollowIndicator({
|
|
45947
|
+
isFollowing: () => this.chatHost.bodyScrollFromBottom() === 0,
|
|
45948
|
+
keyLabel: () => keyText2("tui.altScreen.bottom")
|
|
45949
|
+
});
|
|
45907
45950
|
if (bodyBudget <= 0) {
|
|
45908
45951
|
bodyLines = [];
|
|
45909
45952
|
} else if (promptActive) {
|
|
@@ -45911,16 +45954,24 @@ class StageChatView {
|
|
|
45911
45954
|
} else if (blocked) {
|
|
45912
45955
|
bodyLines = renderBlockedBody(ctx, w, bodyBudget, stage);
|
|
45913
45956
|
} else if (!readOnlyArchive && isPaused(ctx, stage)) {
|
|
45914
|
-
|
|
45957
|
+
reservedIndicatorLines = bodyBudget > 1 ? indicator.render(w) : [];
|
|
45958
|
+
bodyLines = renderPausedBody(ctx, w, bodyBudget, reservedIndicatorLines, () => indicator.render(w));
|
|
45915
45959
|
} else if (readOnlyArchive) {
|
|
45916
|
-
|
|
45960
|
+
reservedIndicatorLines = bodyBudget > 1 ? indicator.render(w) : [];
|
|
45961
|
+
bodyLines = renderReadOnlyArchiveBody(ctx, w, bodyBudget, stage, reservedIndicatorLines, () => indicator.render(w));
|
|
45917
45962
|
} else {
|
|
45963
|
+
transcriptBodyActive = true;
|
|
45918
45964
|
bodyLines = this.chatHost.renderBody(w, bodyBudget);
|
|
45919
45965
|
}
|
|
45966
|
+
const indicatorLines = transcriptBodyActive && bodyBudget > 1 ? indicator.render(w) : [];
|
|
45967
|
+
const indicatorVisible = indicatorLines.length > 0;
|
|
45968
|
+
const dropBodyRow = transcriptBodyActive && indicatorVisible && bodyLines.length >= bodyBudget;
|
|
45969
|
+
const visibleBodyLines = bodyLines.slice(dropBodyRow ? 1 : 0, bodyBudget);
|
|
45920
45970
|
const lines = [
|
|
45921
45971
|
...headerLines,
|
|
45922
45972
|
...sepLines,
|
|
45923
|
-
...
|
|
45973
|
+
...visibleBodyLines,
|
|
45974
|
+
...indicatorLines,
|
|
45924
45975
|
...visiblePendingLines,
|
|
45925
45976
|
...visibleWorkingLines,
|
|
45926
45977
|
...visibleUsageLines,
|
|
@@ -46288,6 +46339,8 @@ class WorkflowAttachPane {
|
|
|
46288
46339
|
return true;
|
|
46289
46340
|
return this.chatView.handleInput(data);
|
|
46290
46341
|
}
|
|
46342
|
+
if (data === TRANSCRIPT_JUMP_TO_END_URL2)
|
|
46343
|
+
return false;
|
|
46291
46344
|
if (this._shouldQuarantineGraphEnter(data))
|
|
46292
46345
|
return true;
|
|
46293
46346
|
return this.graphView.handleInput(data);
|
|
@@ -46655,6 +46708,7 @@ function buildGraphOverlayAdapter(pi, store2, buildOpts = {}) {
|
|
|
46655
46708
|
overlay: true,
|
|
46656
46709
|
deferInlineCustomUiFocus: true,
|
|
46657
46710
|
handlesCtrlC: true,
|
|
46711
|
+
handlesInternalUiAction: true,
|
|
46658
46712
|
overlayOptions: FULLSCREEN_OVERLAY_OPTIONS,
|
|
46659
46713
|
onHandle: (handle) => {
|
|
46660
46714
|
currentHandle = handle;
|
|
@@ -73435,7 +73489,7 @@ function openInputsPicker(ui, opts) {
|
|
|
73435
73489
|
}
|
|
73436
73490
|
|
|
73437
73491
|
// dist/builtin/workflows/src/tui/session-picker.ts
|
|
73438
|
-
import { keyText as
|
|
73492
|
+
import { keyText as keyText3 } from "@bastani/atomic";
|
|
73439
73493
|
var ESCAPE_CODE = 27;
|
|
73440
73494
|
function isQuitRun3(run2) {
|
|
73441
73495
|
return run2.endedAt === undefined && run2.status === "paused" && run2.exitReason === "quit";
|
|
@@ -73528,12 +73582,12 @@ function renderHintsRow(width, theme, state2) {
|
|
|
73528
73582
|
const muted = hexToAnsi(theme.textMuted);
|
|
73529
73583
|
const sep7 = `${dim} · ${RESET}`;
|
|
73530
73584
|
const hint = (key2, label) => `${text}${key2}${RESET} ${muted}${label}${RESET}`;
|
|
73531
|
-
const parts = state2.filterFocused ? [hint(
|
|
73532
|
-
hint(`${
|
|
73533
|
-
hint(
|
|
73585
|
+
const parts = state2.filterFocused ? [hint(keyText3("tui.select.confirm"), "Submit"), hint(keyText3("tui.select.cancel"), "Exit Filter")] : [
|
|
73586
|
+
hint(`${keyText3("tui.select.up")}/${keyText3("tui.select.down")}`, "Navigate"),
|
|
73587
|
+
hint(keyText3("tui.select.confirm"), "Connect"),
|
|
73534
73588
|
hint("a", state2.includeAll ? "Active Only" : "All"),
|
|
73535
73589
|
hint("/", "Filter"),
|
|
73536
|
-
hint(
|
|
73590
|
+
hint(keyText3("tui.select.cancel"), "Close")
|
|
73537
73591
|
];
|
|
73538
73592
|
const line = ` ${parts.join(sep7)}`;
|
|
73539
73593
|
const clipped = truncateToWidth(line, width, "…");
|
|
@@ -120,6 +120,8 @@ export interface PiCustomOverlayOptions {
|
|
|
120
120
|
* surface whose hint row offers `ctrl+c Skip`, `ctrl+c Close`, or cancel.
|
|
121
121
|
*/
|
|
122
122
|
handlesCtrlC?: boolean;
|
|
123
|
+
/** Declare that this component claims internal UI actions such as jump-to-bottom. */
|
|
124
|
+
handlesInternalUiAction?: boolean;
|
|
123
125
|
/**
|
|
124
126
|
* Geometry / anchoring intended for pi-tui's `resolveOverlayLayout`.
|
|
125
127
|
* NOT forwarded by current pi interactive `custom()` — see
|
|
@@ -412,6 +412,7 @@ export function buildGraphOverlayAdapter(
|
|
|
412
412
|
// Ctrl+C (Skip / Close / cancel), so the host must forward it here
|
|
413
413
|
// instead of closing this overlay on the first press.
|
|
414
414
|
handlesCtrlC: true,
|
|
415
|
+
handlesInternalUiAction: true,
|
|
415
416
|
overlayOptions: FULLSCREEN_OVERLAY_OPTIONS,
|
|
416
417
|
onHandle: (handle) => {
|
|
417
418
|
currentHandle = handle;
|
|
@@ -38,6 +38,8 @@ export function renderReadOnlyArchiveBody(
|
|
|
38
38
|
width: number,
|
|
39
39
|
budget: number,
|
|
40
40
|
stage: StageSnapshot | undefined,
|
|
41
|
+
indicatorLines: readonly string[] = [],
|
|
42
|
+
renderIndicator: () => readonly string[] = () => indicatorLines,
|
|
41
43
|
): string[] {
|
|
42
44
|
if (stage?.promptFootprint) {
|
|
43
45
|
return renderReadOnlyPromptArchiveBody(ctx, width, budget, stage);
|
|
@@ -69,8 +71,14 @@ export function renderReadOnlyArchiveBody(
|
|
|
69
71
|
).render(width),
|
|
70
72
|
);
|
|
71
73
|
const transcriptBudget = Math.max(0, budget - callout.length);
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
+
const reservedIndicatorRows =
|
|
75
|
+
indicatorLines.length > 0 && transcriptBudget > indicatorLines.length ? indicatorLines.length : 0;
|
|
76
|
+
const transcriptRows = transcriptBudget - reservedIndicatorRows;
|
|
77
|
+
const lines = transcriptRows > 0 ? ctx.chatHost.renderBody(width, transcriptRows) : [];
|
|
78
|
+
const visibleIndicatorLines =
|
|
79
|
+
reservedIndicatorRows > 0 ? [...renderIndicator().slice(0, reservedIndicatorRows)] : [];
|
|
80
|
+
while (visibleIndicatorLines.length < reservedIndicatorRows) visibleIndicatorLines.push(blankLine(width));
|
|
81
|
+
lines.push(...visibleIndicatorLines, ...callout);
|
|
74
82
|
while (lines.length < budget) lines.push(blankLine(width));
|
|
75
83
|
if (lines.length > budget) lines.length = budget;
|
|
76
84
|
return lines;
|
|
@@ -163,7 +171,13 @@ function formatReadOnlyPromptAnswer(value: unknown, kind: PendingPrompt["kind"])
|
|
|
163
171
|
}
|
|
164
172
|
}
|
|
165
173
|
|
|
166
|
-
export function renderPausedBody(
|
|
174
|
+
export function renderPausedBody(
|
|
175
|
+
ctx: StageChatViewContext,
|
|
176
|
+
width: number,
|
|
177
|
+
budget: number,
|
|
178
|
+
indicatorLines: readonly string[] = [],
|
|
179
|
+
renderIndicator: () => readonly string[] = () => indicatorLines,
|
|
180
|
+
): string[] {
|
|
167
181
|
const t = ctx.theme;
|
|
168
182
|
const callout: string[] = [];
|
|
169
183
|
callout.push(blankLine(width));
|
|
@@ -175,11 +189,16 @@ export function renderPausedBody(ctx: StageChatViewContext, width: number, budge
|
|
|
175
189
|
0,
|
|
176
190
|
).render(width),
|
|
177
191
|
);
|
|
178
|
-
|
|
179
|
-
const
|
|
180
|
-
const
|
|
181
|
-
|
|
182
|
-
|
|
192
|
+
const calloutRows = Math.min(callout.length, Math.max(0, budget));
|
|
193
|
+
const transcriptBudget = Math.max(0, budget - calloutRows);
|
|
194
|
+
const reservedIndicatorRows =
|
|
195
|
+
indicatorLines.length > 0 && transcriptBudget > indicatorLines.length ? indicatorLines.length : 0;
|
|
196
|
+
const transcriptRows = transcriptBudget - reservedIndicatorRows;
|
|
197
|
+
const lines = transcriptRows > 0 ? ctx.chatHost.renderBody(width, transcriptRows) : [];
|
|
198
|
+
const visibleIndicatorLines =
|
|
199
|
+
reservedIndicatorRows > 0 ? [...renderIndicator().slice(0, reservedIndicatorRows)] : [];
|
|
200
|
+
while (visibleIndicatorLines.length < reservedIndicatorRows) visibleIndicatorLines.push(blankLine(width));
|
|
201
|
+
lines.push(...visibleIndicatorLines, ...callout.slice(0, calloutRows));
|
|
183
202
|
while (lines.length < budget) lines.push(blankLine(width));
|
|
184
203
|
if (lines.length > budget) lines.length = budget;
|
|
185
204
|
return lines;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TRANSCRIPT_JUMP_TO_END_URL } from "@bastani/atomic";
|
|
2
|
+
|
|
3
|
+
import { APP_ACTION, isKeybindingsLike, matchesAction, TUI_ACTION } from "./keybindings-adapter.js";
|
|
2
4
|
import { parseTerminalMouseInput, terminalMouseWheelDirection } from "./mouse-input.js";
|
|
3
5
|
import { defaultResponseFor, handlePromptCardInput, isPromptEscapeInput } from "./prompt-card.js";
|
|
4
6
|
import { releaseMountedCustomUi } from "./stage-chat-view-custom-ui.js";
|
|
@@ -18,6 +20,7 @@ import { PROMPT_SCROLL_STEP_ROWS, type StageChatViewContext } from "./stage-chat
|
|
|
18
20
|
import { Key, matchesKey } from "./text-helpers.js";
|
|
19
21
|
|
|
20
22
|
export function handleStageChatInput(ctx: StageChatViewContext, data: string): boolean {
|
|
23
|
+
if (data === TRANSCRIPT_JUMP_TO_END_URL) return handleStageChatJumpToBottom(ctx, data);
|
|
21
24
|
const keybindings = isKeybindingsLike(ctx.piKeybindings) ? ctx.piKeybindings : undefined;
|
|
22
25
|
// Only the default physical Ctrl+T belongs to the host thinking action. A
|
|
23
26
|
// user remap may reuse an editor key, so let that key reach the composer.
|
|
@@ -51,6 +54,7 @@ export function handleStageChatInput(ctx: StageChatViewContext, data: string): b
|
|
|
51
54
|
if (readOnlyPromptArchive && handlePromptScrollInput(ctx, data, true)) {
|
|
52
55
|
return true;
|
|
53
56
|
}
|
|
57
|
+
if (handleStageChatJumpToBottom(ctx, data)) return true;
|
|
54
58
|
if (ctx.chatHost.handleScrollInput(data)) return true;
|
|
55
59
|
if (matchesKey(data, Key.escape)) {
|
|
56
60
|
if (ctx.chatHost.isCompacting() || ctx.chatHost.isBashRunning() || ctx.chatHost.isEditingBashCommand()) {
|
|
@@ -79,6 +83,14 @@ export function handleStageChatInput(ctx: StageChatViewContext, data: string): b
|
|
|
79
83
|
if (blocked) return true;
|
|
80
84
|
return ctx.chatHost.handleInput(data);
|
|
81
85
|
}
|
|
86
|
+
|
|
87
|
+
function handleStageChatJumpToBottom(ctx: StageChatViewContext, data: string): boolean {
|
|
88
|
+
const keybindings = isKeybindingsLike(ctx.piKeybindings) ? ctx.piKeybindings : undefined;
|
|
89
|
+
if (data !== TRANSCRIPT_JUMP_TO_END_URL && !matchesAction(keybindings, data, TUI_ACTION.altScreenBottom))
|
|
90
|
+
return false;
|
|
91
|
+
ctx.chatHost.scrollToBottom();
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
82
94
|
function handleToolsExpandInput(ctx: StageChatViewContext, data: string): boolean {
|
|
83
95
|
const keybindings = isKeybindingsLike(ctx.piKeybindings) ? ctx.piKeybindings : undefined;
|
|
84
96
|
if (!matchesAction(keybindings, data, APP_ACTION.toolsExpand)) return false;
|
|
@@ -106,6 +118,10 @@ function handleMountedCustomUiInput(ctx: StageChatViewContext, data: string): bo
|
|
|
106
118
|
}
|
|
107
119
|
// Let scroll input reach the transcript so history stays scrollable while the
|
|
108
120
|
// question is shown, matching the standalone ask_user_question tool.
|
|
121
|
+
if (handleStageChatJumpToBottom(ctx, data)) {
|
|
122
|
+
ctx.requestRender?.();
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
109
125
|
if (ctx.chatHost.handleScrollInput(data)) {
|
|
110
126
|
ctx.requestRender?.();
|
|
111
127
|
return true;
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
* - https://pi.dev/docs/latest/tui (canonical Pi-tui component contract)
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
|
+
import { keyText, TranscriptFollowIndicator } from "@bastani/atomic";
|
|
26
27
|
import type { Component, Focusable } from "@earendil-works/pi-tui";
|
|
27
28
|
import { fitStageChatFrame, planStageChatFrame } from "./stage-chat-layout.js";
|
|
28
29
|
import {
|
|
@@ -157,6 +158,12 @@ export class StageChatView implements Component, Focusable {
|
|
|
157
158
|
if (blocked) this.chatHost.scrollToBottom();
|
|
158
159
|
|
|
159
160
|
let bodyLines: string[];
|
|
161
|
+
let transcriptBodyActive = false;
|
|
162
|
+
let reservedIndicatorLines: readonly string[] = [];
|
|
163
|
+
const indicator = new TranscriptFollowIndicator({
|
|
164
|
+
isFollowing: () => this.chatHost.bodyScrollFromBottom() === 0,
|
|
165
|
+
keyLabel: () => keyText("tui.altScreen.bottom"),
|
|
166
|
+
});
|
|
160
167
|
if (bodyBudget <= 0) {
|
|
161
168
|
bodyLines = [];
|
|
162
169
|
} else if (promptActive) {
|
|
@@ -164,17 +171,27 @@ export class StageChatView implements Component, Focusable {
|
|
|
164
171
|
} else if (blocked) {
|
|
165
172
|
bodyLines = renderBlockedBody(ctx, w, bodyBudget, stage);
|
|
166
173
|
} else if (!readOnlyArchive && isPaused(ctx, stage)) {
|
|
167
|
-
|
|
174
|
+
reservedIndicatorLines = bodyBudget > 1 ? indicator.render(w) : [];
|
|
175
|
+
bodyLines = renderPausedBody(ctx, w, bodyBudget, reservedIndicatorLines, () => indicator.render(w));
|
|
168
176
|
} else if (readOnlyArchive) {
|
|
169
|
-
|
|
177
|
+
reservedIndicatorLines = bodyBudget > 1 ? indicator.render(w) : [];
|
|
178
|
+
bodyLines = renderReadOnlyArchiveBody(ctx, w, bodyBudget, stage, reservedIndicatorLines, () =>
|
|
179
|
+
indicator.render(w),
|
|
180
|
+
);
|
|
170
181
|
} else {
|
|
182
|
+
transcriptBodyActive = true;
|
|
171
183
|
bodyLines = this.chatHost.renderBody(w, bodyBudget);
|
|
172
184
|
}
|
|
185
|
+
const indicatorLines = transcriptBodyActive && bodyBudget > 1 ? indicator.render(w) : [];
|
|
186
|
+
const indicatorVisible = indicatorLines.length > 0;
|
|
187
|
+
const dropBodyRow = transcriptBodyActive && indicatorVisible && bodyLines.length >= bodyBudget;
|
|
188
|
+
const visibleBodyLines = bodyLines.slice(dropBodyRow ? 1 : 0, bodyBudget);
|
|
173
189
|
|
|
174
190
|
const lines = [
|
|
175
191
|
...headerLines,
|
|
176
192
|
...sepLines,
|
|
177
|
-
...
|
|
193
|
+
...visibleBodyLines,
|
|
194
|
+
...indicatorLines,
|
|
178
195
|
...visiblePendingLines,
|
|
179
196
|
...visibleWorkingLines,
|
|
180
197
|
...visibleUsageLines,
|
|
@@ -8,7 +8,11 @@
|
|
|
8
8
|
* `stage-chat-view.ts`, and `stage-control-registry.ts`.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import
|
|
11
|
+
import {
|
|
12
|
+
type ChatMessageRenderOptions,
|
|
13
|
+
type ReadonlyFooterDataProvider,
|
|
14
|
+
TRANSCRIPT_JUMP_TO_END_URL,
|
|
15
|
+
} from "@bastani/atomic";
|
|
12
16
|
import type { Component, EditorComponent, EditorTheme, TUI } from "@earendil-works/pi-tui";
|
|
13
17
|
import type { StageControlRegistry } from "../runs/foreground/stage-control-registry.js";
|
|
14
18
|
import { stageQueuedUserMessageCount } from "../runs/foreground/stage-queued-user-messages.js";
|
|
@@ -340,6 +344,11 @@ export class WorkflowAttachPane implements Component {
|
|
|
340
344
|
if (this._shouldQuarantineStagePromptEnter(data)) return true;
|
|
341
345
|
return this.chatView.handleInput(data);
|
|
342
346
|
}
|
|
347
|
+
// The overlay opts into internal UI actions for the whole adapter, so the
|
|
348
|
+
// graph view is offered the jump URL too. It draws no follow indicator and
|
|
349
|
+
// has nothing to jump to: decline so the host transcript stays the fallback
|
|
350
|
+
// instead of swallowing the activation.
|
|
351
|
+
if (data === TRANSCRIPT_JUMP_TO_END_URL) return false;
|
|
343
352
|
if (this._shouldQuarantineGraphEnter(data)) return true;
|
|
344
353
|
return this.graphView.handleInput(data);
|
|
345
354
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-session-events.d.ts","sourceRoot":"","sources":["../../src/core/agent-session-events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC9E,OAAO,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAe,MAAM,8BAA8B,CAAC;AAE3F,OAAO,KAAK,EAAE,2BAA2B,IAAI,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAS9F,OAAO,EACN,KAAK,iBAAiB,EACtB,KAAK,yBAAyB,EAI9B,MAAM,0BAA0B,CAAC;AAgBlC,wBAAgB,KAAK,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAIxE;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAMzD;AAED,4EAA4E;AAE5E,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CA2B7F;AAED,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI,CA6B1F;AAED,wBAAgB,4BAA4B,CAC3C,IAAI,EAAE,YAAY,EAClB,QAAQ,EAAE,YAAY,EAAE,GACtB,gBAAgB,GAAG,SAAS,CAQ9B;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"agent-session-events.d.ts","sourceRoot":"","sources":["../../src/core/agent-session-events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC9E,OAAO,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAe,MAAM,8BAA8B,CAAC;AAE3F,OAAO,KAAK,EAAE,2BAA2B,IAAI,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAS9F,OAAO,EACN,KAAK,iBAAiB,EACtB,KAAK,yBAAyB,EAI9B,MAAM,0BAA0B,CAAC;AAgBlC,wBAAgB,KAAK,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAIxE;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAMzD;AAED,4EAA4E;AAE5E,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CA2B7F;AAED,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI,CA6B1F;AAED,wBAAgB,4BAA4B,CAC3C,IAAI,EAAE,YAAY,EAClB,QAAQ,EAAE,YAAY,EAAE,GACtB,gBAAgB,GAAG,SAAS,CAQ9B;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAsM7F;AAED,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI,CA0BvF;AAED,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI,CAQvF;AAED,wCAAwC;AAExC,wBAAgB,aAAa,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAMtD;AAED,0CAA0C;AAE1C,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CAMhF;AAED,8EAA8E;AAE9E,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,YAAY,GAAG,gBAAgB,GAAG,SAAS,CAS1F;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,GAAG,IAAI,CAchH;AAED,kDAAkD;AAElD,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAsE9F;AAED;;;;GAIG;AAEH,wBAAgB,SAAS,CAAC,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,yBAAyB,GAAG,MAAM,IAAI,CAU7F;AAED,oDAAoD;AACpD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAK7D;AAED;;;GAGG;AAEH,wBAAgB,OAAO,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAmBhD;AAMD,uBAAuB;AAEvB,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;CAiBrC,CAAC"}
|
|
@@ -89,6 +89,11 @@ export async function _processAgentEvent(event) {
|
|
|
89
89
|
const steeringIndex = this._steeringMessages.indexOf(messageText);
|
|
90
90
|
if (steeringIndex !== -1) {
|
|
91
91
|
this._steeringMessages.splice(steeringIndex, 1);
|
|
92
|
+
// The loop already polled this message out of the agent queue, so the
|
|
93
|
+
// pause hold can no longer reach it and Escape can no longer restore it
|
|
94
|
+
// to the editor. Record it so an interrupt that kills its reply before
|
|
95
|
+
// any output can still schedule that reply (issue #2362).
|
|
96
|
+
this._admittedQueuedMessageAwaitingReply = messageText;
|
|
92
97
|
this._emitQueueUpdate();
|
|
93
98
|
}
|
|
94
99
|
else {
|
|
@@ -96,6 +101,7 @@ export async function _processAgentEvent(event) {
|
|
|
96
101
|
const followUpIndex = this._followUpMessages.indexOf(messageText);
|
|
97
102
|
if (followUpIndex !== -1) {
|
|
98
103
|
this._followUpMessages.splice(followUpIndex, 1);
|
|
104
|
+
this._admittedQueuedMessageAwaitingReply = messageText;
|
|
99
105
|
this._emitQueueUpdate();
|
|
100
106
|
}
|
|
101
107
|
}
|