@oh-my-pi/pi-coding-agent 15.10.0 → 15.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +142 -1
- package/dist/types/cli/dry-balance-cli.d.ts +15 -1
- package/dist/types/cli/startup-cwd.d.ts +2 -0
- package/dist/types/commands/launch.d.ts +3 -0
- package/dist/types/commit/analysis/conventional.d.ts +2 -2
- package/dist/types/commit/analysis/summary.d.ts +2 -2
- package/dist/types/commit/changelog/generate.d.ts +2 -2
- package/dist/types/commit/changelog/index.d.ts +2 -2
- package/dist/types/commit/map-reduce/index.d.ts +3 -3
- package/dist/types/commit/map-reduce/map-phase.d.ts +2 -2
- package/dist/types/commit/map-reduce/reduce-phase.d.ts +2 -2
- package/dist/types/commit/model-selection.d.ts +10 -4
- package/dist/types/config/api-key-resolver.d.ts +34 -0
- package/dist/types/config/keybindings.d.ts +2 -2
- package/dist/types/config/model-provider-priority.d.ts +1 -0
- package/dist/types/config/model-registry.d.ts +17 -1
- package/dist/types/config/model-resolver.d.ts +4 -1
- package/dist/types/config/settings-schema.d.ts +9 -0
- package/dist/types/config/settings.d.ts +7 -2
- package/dist/types/dap/config.d.ts +14 -1
- package/dist/types/dap/types.d.ts +10 -0
- package/dist/types/debug/report-bundle.d.ts +3 -0
- package/dist/types/edit/file-snapshot-store.d.ts +18 -10
- package/dist/types/eval/py/__tests__/prelude.test.d.ts +1 -0
- package/dist/types/extensibility/extensions/types.d.ts +4 -1
- package/dist/types/lsp/client.d.ts +10 -0
- package/dist/types/lsp/utils.d.ts +3 -2
- package/dist/types/main.d.ts +3 -9
- package/dist/types/mcp/tool-bridge.d.ts +2 -0
- package/dist/types/modes/components/chat-block.d.ts +64 -0
- package/dist/types/modes/components/custom-editor.d.ts +4 -1
- package/dist/types/modes/components/overlay-box.d.ts +17 -0
- package/dist/types/modes/components/plan-review-overlay.d.ts +59 -0
- package/dist/types/modes/components/plan-toc.d.ts +41 -0
- package/dist/types/modes/components/read-tool-group.d.ts +2 -0
- package/dist/types/modes/components/status-line.d.ts +2 -0
- package/dist/types/modes/components/transcript-container.d.ts +11 -0
- package/dist/types/modes/controllers/command-controller.d.ts +1 -0
- package/dist/types/modes/controllers/event-controller.d.ts +17 -1
- package/dist/types/modes/controllers/extension-ui-controller.d.ts +0 -1
- package/dist/types/modes/controllers/input-controller.d.ts +1 -1
- package/dist/types/modes/controllers/streaming-reveal.d.ts +22 -0
- package/dist/types/modes/controllers/tan-command-controller.d.ts +6 -0
- package/dist/types/modes/interactive-mode.d.ts +16 -5
- package/dist/types/modes/magic-keywords.d.ts +1 -1
- package/dist/types/modes/markdown-prose.d.ts +1 -1
- package/dist/types/modes/theme/theme.d.ts +1 -1
- package/dist/types/modes/types.d.ts +21 -5
- package/dist/types/modes/utils/copy-targets.d.ts +21 -1
- package/dist/types/modes/workflow.d.ts +3 -3
- package/dist/types/plan-mode/approved-plan.d.ts +27 -8
- package/dist/types/plan-mode/plan-protection.d.ts +4 -4
- package/dist/types/sdk.d.ts +2 -0
- package/dist/types/session/agent-session.d.ts +21 -0
- package/dist/types/session/auth-storage.d.ts +1 -1
- package/dist/types/session/messages.d.ts +12 -0
- package/dist/types/session/session-manager.d.ts +8 -3
- package/dist/types/slash-commands/types.d.ts +4 -6
- package/dist/types/task/executor.d.ts +17 -0
- package/dist/types/task/index.d.ts +1 -0
- package/dist/types/task/render.d.ts +3 -2
- package/dist/types/tools/archive-reader.d.ts +5 -0
- package/dist/types/tools/ast-edit.d.ts +3 -0
- package/dist/types/tools/ast-grep.d.ts +3 -0
- package/dist/types/tools/bash.d.ts +1 -0
- package/dist/types/tools/eval.d.ts +8 -0
- package/dist/types/tools/find.d.ts +8 -4
- package/dist/types/tools/gh-cache-invalidation.d.ts +6 -0
- package/dist/types/tools/github-cache.d.ts +12 -0
- package/dist/types/tools/grouped-file-output.d.ts +95 -12
- package/dist/types/tools/memory-render.d.ts +4 -1
- package/dist/types/tools/path-utils.d.ts +8 -0
- package/dist/types/tools/plan-mode-guard.d.ts +8 -9
- package/dist/types/tools/render-utils.d.ts +5 -9
- package/dist/types/tools/search.d.ts +6 -2
- package/dist/types/tools/sqlite-reader.d.ts +1 -0
- package/dist/types/tools/todo.d.ts +3 -2
- package/dist/types/tools/write.d.ts +3 -0
- package/dist/types/tools/yield.d.ts +8 -0
- package/dist/types/tui/output-block.d.ts +16 -4
- package/dist/types/tui/status-line.d.ts +3 -0
- package/dist/types/utils/enhanced-paste.d.ts +20 -0
- package/dist/types/web/search/providers/kimi.d.ts +1 -1
- package/package.json +9 -9
- package/src/auto-thinking/classifier.ts +5 -1
- package/src/cli/args.ts +3 -1
- package/src/cli/dry-balance-cli.ts +54 -21
- package/src/cli/gallery-cli.ts +4 -1
- package/src/cli/gallery-fixtures/misc.ts +29 -0
- package/src/cli/startup-cwd.ts +68 -0
- package/src/commands/launch.ts +3 -0
- package/src/commit/analysis/conventional.ts +2 -2
- package/src/commit/analysis/summary.ts +2 -2
- package/src/commit/changelog/generate.ts +2 -2
- package/src/commit/changelog/index.ts +2 -2
- package/src/commit/map-reduce/index.ts +3 -3
- package/src/commit/map-reduce/map-phase.ts +2 -2
- package/src/commit/map-reduce/reduce-phase.ts +2 -2
- package/src/commit/model-selection.ts +36 -11
- package/src/commit/pipeline.ts +4 -4
- package/src/config/api-key-resolver.ts +58 -0
- package/src/config/model-provider-priority.ts +55 -0
- package/src/config/model-registry.ts +29 -24
- package/src/config/model-resolver.ts +39 -7
- package/src/config/settings-schema.ts +10 -0
- package/src/config/settings.ts +106 -43
- package/src/dap/config.ts +41 -2
- package/src/dap/defaults.json +1 -0
- package/src/dap/session.ts +1 -0
- package/src/dap/types.ts +10 -0
- package/src/debug/index.ts +47 -53
- package/src/debug/raw-sse-buffer.ts +7 -4
- package/src/debug/report-bundle.ts +9 -0
- package/src/edit/file-snapshot-store.ts +33 -1
- package/src/edit/hashline/filesystem.ts +2 -1
- package/src/edit/renderer.ts +82 -78
- package/src/eval/__tests__/llm-bridge.test.ts +110 -31
- package/src/eval/js/context-manager.ts +32 -15
- package/src/eval/llm-bridge.ts +22 -6
- package/src/eval/py/__tests__/prelude.test.ts +19 -0
- package/src/eval/py/executor.ts +23 -11
- package/src/eval/py/prelude.py +1 -1
- package/src/extensibility/extensions/types.ts +10 -1
- package/src/goals/tools/goal-tool.ts +36 -26
- package/src/internal-urls/docs-index.generated.ts +8 -8
- package/src/lsp/client.ts +23 -11
- package/src/lsp/config.ts +11 -1
- package/src/lsp/index.ts +61 -9
- package/src/lsp/utils.ts +3 -2
- package/src/main.ts +100 -72
- package/src/mcp/tool-bridge.ts +2 -0
- package/src/memories/index.ts +14 -7
- package/src/mnemopi/backend.ts +5 -1
- package/src/modes/acp/acp-agent.ts +33 -26
- package/src/modes/components/assistant-message.ts +2 -9
- package/src/modes/components/chat-block.ts +111 -0
- package/src/modes/components/copy-selector.ts +1 -44
- package/src/modes/components/custom-editor.ts +164 -109
- package/src/modes/components/custom-message.ts +1 -3
- package/src/modes/components/execution-shared.ts +1 -2
- package/src/modes/components/hook-message.ts +1 -3
- package/src/modes/components/model-selector.ts +59 -13
- package/src/modes/components/oauth-selector.ts +33 -7
- package/src/modes/components/overlay-box.ts +108 -0
- package/src/modes/components/plan-review-overlay.ts +799 -0
- package/src/modes/components/plan-toc.ts +138 -0
- package/src/modes/components/read-tool-group.ts +20 -4
- package/src/modes/components/skill-message.ts +0 -1
- package/src/modes/components/status-line.ts +19 -4
- package/src/modes/components/tips.txt +2 -1
- package/src/modes/components/todo-reminder.ts +0 -2
- package/src/modes/components/tool-execution.ts +68 -88
- package/src/modes/components/transcript-container.ts +84 -24
- package/src/modes/components/user-message.ts +2 -3
- package/src/modes/controllers/command-controller-shared.ts +7 -6
- package/src/modes/controllers/command-controller.ts +57 -55
- package/src/modes/controllers/event-controller.ts +67 -40
- package/src/modes/controllers/extension-ui-controller.ts +10 -73
- package/src/modes/controllers/input-controller.ts +170 -126
- package/src/modes/controllers/mcp-command-controller.ts +69 -60
- package/src/modes/controllers/selector-controller.ts +23 -25
- package/src/modes/controllers/streaming-reveal.ts +212 -0
- package/src/modes/controllers/tan-command-controller.ts +173 -0
- package/src/modes/interactive-mode.ts +274 -112
- package/src/modes/magic-keywords.ts +1 -1
- package/src/modes/markdown-prose.ts +1 -1
- package/src/modes/setup-wizard/wizard-overlay.ts +1 -1
- package/src/modes/theme/shimmer.ts +20 -9
- package/src/modes/theme/theme-schema.json +1 -1
- package/src/modes/theme/theme.ts +8 -4
- package/src/modes/types.ts +21 -7
- package/src/modes/utils/copy-targets.ts +133 -27
- package/src/modes/utils/ui-helpers.ts +44 -46
- package/src/modes/workflow.ts +10 -10
- package/src/plan-mode/approved-plan.ts +66 -43
- package/src/plan-mode/plan-protection.ts +4 -4
- package/src/prompts/system/background-tan-dispatch.md +8 -0
- package/src/prompts/system/plan-mode-active.md +67 -58
- package/src/prompts/system/plan-mode-approved.md +1 -1
- package/src/prompts/system/workflow-notice.md +1 -1
- package/src/prompts/tools/bash.md +9 -0
- package/src/prompts/tools/browser.md +1 -1
- package/src/prompts/tools/eval.md +2 -1
- package/src/prompts/tools/read.md +2 -2
- package/src/sdk.ts +37 -46
- package/src/session/agent-session.ts +119 -18
- package/src/session/auth-storage.ts +2 -0
- package/src/session/messages.ts +26 -0
- package/src/session/session-manager.ts +109 -28
- package/src/slash-commands/builtin-registry.ts +36 -9
- package/src/slash-commands/types.ts +4 -6
- package/src/task/executor.ts +76 -38
- package/src/task/index.ts +4 -0
- package/src/task/render.ts +211 -147
- package/src/tools/archive-reader.ts +64 -0
- package/src/tools/ask.ts +119 -164
- package/src/tools/ast-edit.ts +98 -71
- package/src/tools/ast-grep.ts +37 -43
- package/src/tools/bash.ts +57 -6
- package/src/tools/browser/tab-supervisor.ts +13 -1
- package/src/tools/browser/tab-worker.ts +33 -4
- package/src/tools/debug.ts +20 -8
- package/src/tools/eval.ts +13 -2
- package/src/tools/fetch.ts +297 -7
- package/src/tools/find.ts +51 -30
- package/src/tools/gh-cache-invalidation.ts +200 -0
- package/src/tools/gh-renderer.ts +81 -42
- package/src/tools/github-cache.ts +25 -0
- package/src/tools/grouped-file-output.ts +272 -48
- package/src/tools/image-gen.ts +150 -103
- package/src/tools/inspect-image-renderer.ts +63 -41
- package/src/tools/inspect-image.ts +10 -3
- package/src/tools/job.ts +3 -4
- package/src/tools/memory-render.ts +4 -1
- package/src/tools/path-utils.ts +28 -2
- package/src/tools/plan-mode-guard.ts +66 -39
- package/src/tools/read.ts +48 -28
- package/src/tools/render-utils.ts +21 -37
- package/src/tools/resolve.ts +14 -0
- package/src/tools/search-tool-bm25.ts +36 -23
- package/src/tools/search.ts +118 -81
- package/src/tools/sqlite-reader.ts +9 -12
- package/src/tools/todo.ts +118 -52
- package/src/tools/write.ts +83 -64
- package/src/tools/yield.ts +10 -1
- package/src/tui/output-block.ts +60 -13
- package/src/tui/status-line.ts +5 -1
- package/src/utils/commit-message-generator.ts +11 -3
- package/src/utils/enhanced-paste.ts +230 -0
- package/src/utils/title-generator.ts +2 -1
- package/src/web/search/providers/anthropic.ts +25 -19
- package/src/web/search/providers/codex.ts +37 -8
- package/src/web/search/providers/exa.ts +11 -3
- package/src/web/search/providers/kimi.ts +28 -17
- package/src/web/search/providers/parallel.ts +35 -24
- package/src/web/search/providers/synthetic.ts +8 -6
- package/src/web/search/providers/tavily.ts +9 -8
- package/src/web/search/providers/zai.ts +8 -6
|
@@ -39,6 +39,26 @@ function isBlockAppendOnly(child: Component): boolean {
|
|
|
39
39
|
return fn ? fn.call(child) : false;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
// A "plain blank" row is empty or whitespace-only with no ANSI bytes. It marks
|
|
43
|
+
// separation padding (a `Spacer`, or a no-background `paddingY` row) as opposed
|
|
44
|
+
// to a background-colored padding row, whose escape sequences contain `\S` and
|
|
45
|
+
// are therefore preserved as part of a block's visual design.
|
|
46
|
+
const NON_WHITESPACE = /\S/;
|
|
47
|
+
function isPlainBlank(line: string): boolean {
|
|
48
|
+
return !NON_WHITESPACE.test(line);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Strip leading/trailing plain-blank rows so each block contributes only its
|
|
52
|
+
// visible body; the container owns the gaps between blocks. Returns the input
|
|
53
|
+
// array unchanged when there is nothing to trim (no allocation on the hot path).
|
|
54
|
+
function stripPlainBlankEdges(lines: string[]): string[] {
|
|
55
|
+
let start = 0;
|
|
56
|
+
let end = lines.length;
|
|
57
|
+
while (start < end && isPlainBlank(lines[start]!)) start++;
|
|
58
|
+
while (end > start && isPlainBlank(lines[end - 1]!)) end--;
|
|
59
|
+
return start === 0 && end === lines.length ? lines : lines.slice(start, end);
|
|
60
|
+
}
|
|
61
|
+
|
|
42
62
|
/**
|
|
43
63
|
* Transcript container that freezes the rendered output of every block except
|
|
44
64
|
* the bottom-most (live) one on terminals where committed native scrollback is
|
|
@@ -118,9 +138,13 @@ export class TranscriptContainer extends Container implements NativeScrollbackLi
|
|
|
118
138
|
width = Math.max(1, width);
|
|
119
139
|
this.#nativeScrollbackLiveRegionStart = undefined;
|
|
120
140
|
this.#nativeScrollbackCommitSafeEnd = undefined;
|
|
121
|
-
if (!TERMINAL.eagerEraseScrollbackRisk) return super.render(width);
|
|
122
141
|
|
|
142
|
+
// Freezing/snapshotting only applies on ED3-risk terminals; elsewhere every
|
|
143
|
+
// block renders live. Inter-block spacing applies on BOTH paths so the gap
|
|
144
|
+
// between blocks is identical regardless of terminal.
|
|
145
|
+
const risk = TERMINAL.eagerEraseScrollbackRisk;
|
|
123
146
|
const count = this.children.length;
|
|
147
|
+
|
|
124
148
|
// The live region spans from the earliest still-mutating block through the
|
|
125
149
|
// bottom. A block that has not finalized must stay repaintable: out-of-band
|
|
126
150
|
// inserts (TTSR/todo cards) can append a finalized block *below* a tool that
|
|
@@ -137,45 +161,81 @@ export class TranscriptContainer extends Container implements NativeScrollbackLi
|
|
|
137
161
|
// recompute them so they freeze at their final content. Everything below
|
|
138
162
|
// the lower of the two cutoffs was already frozen last frame and replays.
|
|
139
163
|
const replayCutoff = Math.min(liveStartIndex, this.#prevLiveStartIndex);
|
|
140
|
-
this.#prevLiveStartIndex = liveStartIndex;
|
|
164
|
+
if (risk) this.#prevLiveStartIndex = liveStartIndex;
|
|
141
165
|
|
|
142
166
|
const lines: string[] = [];
|
|
143
167
|
// Tracks whether we are still inside the leading run of append-only live
|
|
144
|
-
// blocks. The first non-append-only live block
|
|
145
|
-
// the live region's start, which cannot happen for a leading run) closes it.
|
|
168
|
+
// blocks. The first non-append-only live block closes it.
|
|
146
169
|
let commitSafeOpen = true;
|
|
170
|
+
// The live-region start is recorded at the first visible row at/after the
|
|
171
|
+
// cutoff; empty leading blocks (or a separator) must not claim it early.
|
|
172
|
+
let liveRecorded = false;
|
|
147
173
|
for (let i = 0; i < count; i++) {
|
|
148
174
|
const child = this.children[i]! as Component & SnapshotCarrier;
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
175
|
+
|
|
176
|
+
// Resolve this child's contribution — its visible body with plain-blank
|
|
177
|
+
// top/bottom edges stripped (the container owns inter-block gaps). On
|
|
178
|
+
// ED3-risk terminals a frozen, scrolled-off block replays its snapshot
|
|
179
|
+
// instead of recomputing; a stale generation (post-thaw) or width
|
|
180
|
+
// mismatch (resize) recomputes, as does a block still live last frame.
|
|
181
|
+
let contribution: string[] | undefined;
|
|
182
|
+
if (risk && i < liveStartIndex && i < replayCutoff) {
|
|
152
183
|
const snapshot = child[kSnapshot];
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
// instead, as does a block that was still live last frame (i >= cutoff).
|
|
156
|
-
if (i < replayCutoff && snapshot && snapshot.generation === this.#generation && snapshot.width === width) {
|
|
157
|
-
lines.push(...snapshot.lines);
|
|
158
|
-
continue;
|
|
184
|
+
if (snapshot && snapshot.generation === this.#generation && snapshot.width === width) {
|
|
185
|
+
contribution = snapshot.lines;
|
|
159
186
|
}
|
|
160
187
|
}
|
|
161
|
-
|
|
188
|
+
if (contribution === undefined) {
|
|
189
|
+
const rendered = child.render(width);
|
|
190
|
+
contribution = stripPlainBlankEdges(rendered);
|
|
191
|
+
// Cache every block's latest contribution. While a block is in the
|
|
192
|
+
// live region this keeps its snapshot current; on the frame it crosses
|
|
193
|
+
// out, the recompute above refreshes it before it freezes.
|
|
194
|
+
if (risk) child[kSnapshot] = { width, lines: contribution, generation: this.#generation };
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Empty (or stripped-to-nothing) children contribute nothing and never
|
|
198
|
+
// affect spacing or the live-region offsets.
|
|
199
|
+
if (contribution.length === 0) continue;
|
|
200
|
+
|
|
201
|
+
// Every block is separated from preceding visible content by exactly one
|
|
202
|
+
// blank row — skipped when it opens the transcript or the prior row is
|
|
203
|
+
// already a plain blank (a fragment's own trailing pad), never doubling.
|
|
204
|
+
const sep = lines.length > 0 && !isPlainBlank(lines[lines.length - 1]!) ? 1 : 0;
|
|
205
|
+
|
|
206
|
+
// The separator before the first live block stays in the committed prefix
|
|
207
|
+
// (it is deterministic and never changes once the prior block is frozen),
|
|
208
|
+
// so the live region begins at the block's first content row.
|
|
209
|
+
if (risk && !liveRecorded && i >= liveStartIndex) {
|
|
210
|
+
this.#nativeScrollbackLiveRegionStart = lines.length + sep;
|
|
211
|
+
liveRecorded = true;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (sep) lines.push("");
|
|
215
|
+
for (let j = 0; j < contribution.length; j++) lines.push(contribution[j]!);
|
|
216
|
+
|
|
162
217
|
// Extend the commit-safe boundary through each leading append-only live
|
|
163
|
-
// block.
|
|
164
|
-
//
|
|
165
|
-
|
|
166
|
-
if (i >= liveStartIndex && commitSafeOpen) {
|
|
218
|
+
// block. The first volatile live block closes the run so its mutable
|
|
219
|
+
// rows stay deferred.
|
|
220
|
+
if (risk && i >= liveStartIndex && commitSafeOpen) {
|
|
167
221
|
if (isBlockAppendOnly(child)) {
|
|
168
|
-
this.#nativeScrollbackCommitSafeEnd = lines.length
|
|
222
|
+
this.#nativeScrollbackCommitSafeEnd = lines.length;
|
|
169
223
|
} else {
|
|
170
224
|
commitSafeOpen = false;
|
|
171
225
|
}
|
|
172
226
|
}
|
|
173
|
-
// Cache every block's latest render. While a block is in the live region
|
|
174
|
-
// this keeps its snapshot current; on the frame it crosses out, the
|
|
175
|
-
// recompute above refreshes it to the final state before it freezes.
|
|
176
|
-
child[kSnapshot] = { width, lines: rendered, generation: this.#generation };
|
|
177
|
-
lines.push(...rendered);
|
|
178
227
|
}
|
|
179
228
|
return lines;
|
|
180
229
|
}
|
|
181
230
|
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Groups a run of sibling rows (an IRC card's header + body, a file-mention
|
|
234
|
+
* list, a bordered command/version panel) into a single transcript child so the
|
|
235
|
+
* container spaces it as one block — one blank line above, none injected between
|
|
236
|
+
* its rows. Without this wrapper the rows would be top-level children and the
|
|
237
|
+
* container would put a blank line between each (and inside any border box).
|
|
238
|
+
* It is a plain {@link Container}; the named subclass documents intent and makes
|
|
239
|
+
* every manual block grouping greppable.
|
|
240
|
+
*/
|
|
241
|
+
export class TranscriptBlock extends Container {}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Container, Markdown
|
|
1
|
+
import { Container, Markdown } from "@oh-my-pi/pi-tui";
|
|
2
2
|
import { getMarkdownTheme, theme } from "../../modes/theme/theme";
|
|
3
3
|
import { imageReferenceHyperlink, renderImageReferences } from "../image-references";
|
|
4
4
|
import { highlightMagicKeywords } from "../magic-keywords";
|
|
@@ -15,7 +15,7 @@ export class UserMessageComponent extends Container {
|
|
|
15
15
|
constructor(text: string, synthetic = false, imageLinks?: readonly (string | undefined)[]) {
|
|
16
16
|
super();
|
|
17
17
|
const bgColor = (value: string) => theme.bg("userMessageBg", value);
|
|
18
|
-
// Paint the magic keywords ("ultrathink"/"orchestrate"/"
|
|
18
|
+
// Paint the magic keywords ("ultrathink"/"orchestrate"/"workflowz") inside the rendered
|
|
19
19
|
// bubble too — matching the live editor glow. The Markdown component routes code spans and
|
|
20
20
|
// fenced blocks through its own code styling (never `color`), so those are already excluded;
|
|
21
21
|
// `highlightMagicKeywords` additionally restores the bubble's own foreground after each
|
|
@@ -30,7 +30,6 @@ export class UserMessageComponent extends Container {
|
|
|
30
30
|
renderText: baseText,
|
|
31
31
|
renderReference: (label, index) => imageReferenceHyperlink(label, index, imageLinks, imageLabel),
|
|
32
32
|
});
|
|
33
|
-
this.addChild(new Spacer(1));
|
|
34
33
|
this.addChild(
|
|
35
34
|
new Markdown(text, 1, 1, getMarkdownTheme(), {
|
|
36
35
|
bgColor,
|
|
@@ -7,10 +7,11 @@
|
|
|
7
7
|
* wording, and add-flow logic stay in the per-controller files because they
|
|
8
8
|
* diverge in workflow.
|
|
9
9
|
*/
|
|
10
|
-
import {
|
|
10
|
+
import { Text } from "@oh-my-pi/pi-tui";
|
|
11
11
|
import type { SourceMeta } from "../../capability/types";
|
|
12
12
|
import { shortenPath } from "../../tools/render-utils";
|
|
13
13
|
import { DynamicBorder } from "../components/dynamic-border";
|
|
14
|
+
import { TranscriptBlock } from "../components/transcript-container";
|
|
14
15
|
import { parseCommandArgs } from "../shared";
|
|
15
16
|
import type { InteractiveModeContext } from "../types";
|
|
16
17
|
|
|
@@ -100,9 +101,9 @@ export function* groupBySource<T>(
|
|
|
100
101
|
* container and request a render.
|
|
101
102
|
*/
|
|
102
103
|
export function showCommandMessage(ctx: InteractiveModeContext, text: string): void {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
ctx.
|
|
104
|
+
const block = new TranscriptBlock();
|
|
105
|
+
block.addChild(new DynamicBorder());
|
|
106
|
+
block.addChild(new Text(text, 1, 1));
|
|
107
|
+
block.addChild(new DynamicBorder());
|
|
108
|
+
ctx.present(block);
|
|
108
109
|
}
|
|
@@ -28,6 +28,7 @@ import { BashExecutionComponent } from "../../modes/components/bash-execution";
|
|
|
28
28
|
import { BorderedLoader } from "../../modes/components/bordered-loader";
|
|
29
29
|
import { DynamicBorder } from "../../modes/components/dynamic-border";
|
|
30
30
|
import { EvalExecutionComponent } from "../../modes/components/eval-execution";
|
|
31
|
+
import { TranscriptBlock } from "../../modes/components/transcript-container";
|
|
31
32
|
import { getMarkdownTheme, getSymbolTheme, theme } from "../../modes/theme/theme";
|
|
32
33
|
import type { InteractiveModeContext } from "../../modes/types";
|
|
33
34
|
import { computeContextBreakdown, renderContextUsage } from "../../modes/utils/context-usage";
|
|
@@ -46,13 +47,13 @@ import { openPath } from "../../utils/open";
|
|
|
46
47
|
import { setSessionTerminalTitle } from "../../utils/title-generator";
|
|
47
48
|
|
|
48
49
|
function showMarkdownPanel(ctx: InteractiveModeContext, title: string, markdown: string): void {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
ctx.
|
|
50
|
+
const block = new TranscriptBlock();
|
|
51
|
+
block.addChild(new DynamicBorder());
|
|
52
|
+
block.addChild(new Text(theme.bold(theme.fg("accent", title)), 1, 0));
|
|
53
|
+
block.addChild(new Spacer(1));
|
|
54
|
+
block.addChild(new Markdown(markdown.trim(), 1, 1, getMarkdownTheme()));
|
|
55
|
+
block.addChild(new DynamicBorder());
|
|
56
|
+
ctx.present(block);
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
export class CommandController {
|
|
@@ -334,9 +335,7 @@ export class CommandController {
|
|
|
334
335
|
}
|
|
335
336
|
}
|
|
336
337
|
|
|
337
|
-
this.ctx.
|
|
338
|
-
this.ctx.chatContainer.addChild(new Text(info, 1, 0));
|
|
339
|
-
this.ctx.ui.requestRender();
|
|
338
|
+
this.ctx.present([new Spacer(1), new Text(info, 1, 0)]);
|
|
340
339
|
}
|
|
341
340
|
|
|
342
341
|
async handleJobsCommand(): Promise<void> {
|
|
@@ -353,9 +352,7 @@ export class CommandController {
|
|
|
353
352
|
|
|
354
353
|
if (snapshot.running.length === 0 && snapshot.recent.length === 0) {
|
|
355
354
|
info += `\n${theme.fg("dim", "No async jobs yet.")}\n`;
|
|
356
|
-
this.ctx.
|
|
357
|
-
this.ctx.chatContainer.addChild(new Text(info, 1, 0));
|
|
358
|
-
this.ctx.ui.requestRender();
|
|
355
|
+
this.ctx.present([new Spacer(1), new Text(info, 1, 0)]);
|
|
359
356
|
return;
|
|
360
357
|
}
|
|
361
358
|
|
|
@@ -375,9 +372,7 @@ export class CommandController {
|
|
|
375
372
|
}
|
|
376
373
|
}
|
|
377
374
|
|
|
378
|
-
this.ctx.
|
|
379
|
-
this.ctx.chatContainer.addChild(new Text(info.trimEnd(), 1, 0));
|
|
380
|
-
this.ctx.ui.requestRender();
|
|
375
|
+
this.ctx.present([new Spacer(1), new Text(info.trimEnd(), 1, 0)]);
|
|
381
376
|
}
|
|
382
377
|
|
|
383
378
|
async handleUsageCommand(reports?: UsageReport[] | null): Promise<void> {
|
|
@@ -403,9 +398,7 @@ export class CommandController {
|
|
|
403
398
|
|
|
404
399
|
const availableWidth = Math.max(40, (this.ctx.ui.terminal.columns ?? 100) - 2);
|
|
405
400
|
const output = renderUsageReports(usageReports, theme, Date.now(), availableWidth);
|
|
406
|
-
this.ctx.
|
|
407
|
-
this.ctx.chatContainer.addChild(new Text(output, 1, 0));
|
|
408
|
-
this.ctx.ui.requestRender();
|
|
401
|
+
this.ctx.present([new Spacer(1), new Text(output, 1, 0)]);
|
|
409
402
|
}
|
|
410
403
|
|
|
411
404
|
async handleChangelogCommand(showFull = false): Promise<void> {
|
|
@@ -426,13 +419,13 @@ export class CommandController {
|
|
|
426
419
|
? ""
|
|
427
420
|
: `\n\n${theme.fg("dim", "Use")} ${theme.bold("/changelog full")} ${theme.fg("dim", "to view the complete changelog.")}`;
|
|
428
421
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
this.ctx.
|
|
422
|
+
const block = new TranscriptBlock();
|
|
423
|
+
block.addChild(new DynamicBorder());
|
|
424
|
+
block.addChild(new Text(theme.bold(theme.fg("accent", title)), 1, 0));
|
|
425
|
+
block.addChild(new Spacer(1));
|
|
426
|
+
block.addChild(new Markdown(changelogMarkdown + hint, 1, 1, getMarkdownTheme()));
|
|
427
|
+
block.addChild(new DynamicBorder());
|
|
428
|
+
this.ctx.present(block);
|
|
436
429
|
}
|
|
437
430
|
|
|
438
431
|
handleHotkeysCommand(): void {
|
|
@@ -452,13 +445,13 @@ export class CommandController {
|
|
|
452
445
|
return;
|
|
453
446
|
}
|
|
454
447
|
const output = renderContextUsage(breakdown, theme);
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
this.ctx.
|
|
448
|
+
const block = new TranscriptBlock();
|
|
449
|
+
block.addChild(new DynamicBorder());
|
|
450
|
+
block.addChild(new Text(theme.bold(theme.fg("accent", "Context Usage")), 1, 0));
|
|
451
|
+
block.addChild(new Spacer(1));
|
|
452
|
+
block.addChild(new Text(output, 1, 0));
|
|
453
|
+
block.addChild(new DynamicBorder());
|
|
454
|
+
this.ctx.present(block);
|
|
462
455
|
}
|
|
463
456
|
|
|
464
457
|
async handleMemoryCommand(text: string): Promise<void> {
|
|
@@ -473,13 +466,13 @@ export class CommandController {
|
|
|
473
466
|
this.ctx.showWarning("Memory payload is empty (memory backend off, disabled, or no memory available).");
|
|
474
467
|
return;
|
|
475
468
|
}
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
this.ctx.
|
|
469
|
+
const block = new TranscriptBlock();
|
|
470
|
+
block.addChild(new DynamicBorder());
|
|
471
|
+
block.addChild(new Text(theme.bold(theme.fg("accent", "Memory Injection Payload")), 1, 0));
|
|
472
|
+
block.addChild(new Spacer(1));
|
|
473
|
+
block.addChild(new Markdown(payload, 1, 1, getMarkdownTheme()));
|
|
474
|
+
block.addChild(new DynamicBorder());
|
|
475
|
+
this.ctx.present(block);
|
|
483
476
|
return;
|
|
484
477
|
}
|
|
485
478
|
|
|
@@ -800,8 +793,7 @@ export class CommandController {
|
|
|
800
793
|
this.ctx.streamingMessage = undefined;
|
|
801
794
|
this.ctx.pendingTools.clear();
|
|
802
795
|
|
|
803
|
-
this.ctx.
|
|
804
|
-
this.ctx.chatContainer.addChild(new Text(`${theme.fg("accent", `${theme.status.success} ${label}`)}`, 1, 1));
|
|
796
|
+
this.ctx.present([new Spacer(1), new Text(`${theme.fg("accent", `${theme.status.success} ${label}`)}`, 1, 1)]);
|
|
805
797
|
await this.ctx.reloadTodos();
|
|
806
798
|
this.ctx.ui.requestRender(true, { clearScrollback: true });
|
|
807
799
|
}
|
|
@@ -810,6 +802,18 @@ export class CommandController {
|
|
|
810
802
|
await this.#runNewSessionFlow();
|
|
811
803
|
}
|
|
812
804
|
|
|
805
|
+
async handleFreshCommand(): Promise<void> {
|
|
806
|
+
const result = this.ctx.session.freshSession();
|
|
807
|
+
if (!result) {
|
|
808
|
+
this.ctx.showWarning("Wait for the current response to finish or abort it before refreshing provider state.");
|
|
809
|
+
return;
|
|
810
|
+
}
|
|
811
|
+
const stateLabel = result.closedProviderSessions === 1 ? "provider state" : "provider states";
|
|
812
|
+
this.ctx.statusLine.invalidate();
|
|
813
|
+
this.ctx.updateEditorTopBorder();
|
|
814
|
+
this.ctx.showStatus(`Fresh provider session started (${result.closedProviderSessions} ${stateLabel} pruned).`);
|
|
815
|
+
}
|
|
816
|
+
|
|
813
817
|
async handleDropCommand(): Promise<void> {
|
|
814
818
|
if (!this.ctx.sessionManager.getSessionFile()) {
|
|
815
819
|
this.ctx.showError("Nothing to drop (in-memory session)");
|
|
@@ -840,11 +844,10 @@ export class CommandController {
|
|
|
840
844
|
|
|
841
845
|
const sessionFile = this.ctx.session.sessionFile;
|
|
842
846
|
const shortPath = sessionFile ? sessionFile.split("/").pop() : "new session";
|
|
843
|
-
this.ctx.
|
|
844
|
-
|
|
847
|
+
this.ctx.present([
|
|
848
|
+
new Spacer(1),
|
|
845
849
|
new Text(`${theme.fg("accent", `${theme.status.success} Session forked to ${shortPath}`)}`, 1, 1),
|
|
846
|
-
);
|
|
847
|
-
this.ctx.ui.requestRender();
|
|
850
|
+
]);
|
|
848
851
|
}
|
|
849
852
|
|
|
850
853
|
async handleMoveCommand(targetPath: string): Promise<void> {
|
|
@@ -878,11 +881,10 @@ export class CommandController {
|
|
|
878
881
|
await this.ctx.sessionManager.moveTo(resolvedPath);
|
|
879
882
|
await this.ctx.applyCwdChange(resolvedPath);
|
|
880
883
|
|
|
881
|
-
this.ctx.
|
|
882
|
-
|
|
884
|
+
this.ctx.present([
|
|
885
|
+
new Spacer(1),
|
|
883
886
|
new Text(`${theme.fg("accent", `${theme.status.success} Session moved to ${resolvedPath}`)}`, 1, 1),
|
|
884
|
-
);
|
|
885
|
-
this.ctx.ui.requestRender();
|
|
887
|
+
]);
|
|
886
888
|
} catch (err) {
|
|
887
889
|
this.ctx.showError(`Move failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
888
890
|
}
|
|
@@ -913,7 +915,7 @@ export class CommandController {
|
|
|
913
915
|
this.ctx.pendingMessagesContainer.addChild(this.ctx.bashComponent);
|
|
914
916
|
this.ctx.pendingBashComponents.push(this.ctx.bashComponent);
|
|
915
917
|
} else {
|
|
916
|
-
this.ctx.
|
|
918
|
+
this.ctx.present(this.ctx.bashComponent);
|
|
917
919
|
}
|
|
918
920
|
this.ctx.ui.requestRender();
|
|
919
921
|
|
|
@@ -954,7 +956,7 @@ export class CommandController {
|
|
|
954
956
|
this.ctx.pendingMessagesContainer.addChild(this.ctx.pythonComponent);
|
|
955
957
|
this.ctx.pendingPythonComponents.push(this.ctx.pythonComponent);
|
|
956
958
|
} else {
|
|
957
|
-
this.ctx.
|
|
959
|
+
this.ctx.present(this.ctx.pythonComponent);
|
|
958
960
|
}
|
|
959
961
|
this.ctx.ui.requestRender();
|
|
960
962
|
|
|
@@ -1143,10 +1145,10 @@ export class CommandController {
|
|
|
1143
1145
|
this.ctx.updateEditorBorderColor();
|
|
1144
1146
|
await this.ctx.reloadTodos();
|
|
1145
1147
|
|
|
1146
|
-
this.ctx.
|
|
1147
|
-
|
|
1148
|
+
this.ctx.present([
|
|
1149
|
+
new Spacer(1),
|
|
1148
1150
|
new Text(`${theme.fg("accent", `${theme.status.success} New session started with handoff context`)}`, 1, 1),
|
|
1149
|
-
);
|
|
1151
|
+
]);
|
|
1150
1152
|
if (result.savedPath) {
|
|
1151
1153
|
this.ctx.showStatus(`Handoff document saved to: ${result.savedPath}`);
|
|
1152
1154
|
}
|