@oh-my-pi/pi-coding-agent 15.9.67 → 15.10.1
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 +136 -0
- package/dist/types/cli/args.d.ts +1 -1
- package/dist/types/cli/dry-balance-cli.d.ts +15 -1
- package/dist/types/cli/gallery-cli.d.ts +43 -0
- package/dist/types/cli/gallery-fixtures/agentic.d.ts +2 -0
- package/dist/types/cli/gallery-fixtures/codeintel.d.ts +3 -0
- package/dist/types/cli/gallery-fixtures/edit.d.ts +3 -0
- package/dist/types/cli/gallery-fixtures/fs.d.ts +2 -0
- package/dist/types/cli/gallery-fixtures/index.d.ts +4 -0
- package/dist/types/cli/gallery-fixtures/interaction.d.ts +3 -0
- package/dist/types/cli/gallery-fixtures/memory.d.ts +2 -0
- package/dist/types/cli/gallery-fixtures/misc.d.ts +3 -0
- package/dist/types/cli/gallery-fixtures/search.d.ts +3 -0
- package/dist/types/cli/gallery-fixtures/shell.d.ts +3 -0
- package/dist/types/cli/gallery-fixtures/types.d.ts +44 -0
- package/dist/types/cli/gallery-fixtures/web.d.ts +2 -0
- package/dist/types/cli/gallery-screenshot.d.ts +35 -0
- package/dist/types/commands/gallery.d.ts +47 -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 +6 -1
- package/dist/types/config/model-id-affixes.d.ts +2 -0
- package/dist/types/config/model-registry.d.ts +25 -2
- package/dist/types/config/settings-schema.d.ts +41 -6
- package/dist/types/dap/config.d.ts +14 -1
- package/dist/types/dap/types.d.ts +10 -0
- package/dist/types/extensibility/plugins/marketplace-auto-update.d.ts +8 -0
- package/dist/types/lsp/types.d.ts +10 -0
- package/dist/types/lsp/utils.d.ts +3 -2
- package/dist/types/main.d.ts +3 -2
- package/dist/types/memory-backend/index.d.ts +2 -1
- package/dist/types/memory-backend/resolve.d.ts +1 -1
- package/dist/types/memory-backend/types.d.ts +1 -1
- package/dist/types/modes/components/chat-block.d.ts +64 -0
- package/dist/types/modes/components/custom-editor.d.ts +5 -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/tool-execution.d.ts +18 -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 +0 -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/selector-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/index.d.ts +5 -4
- package/dist/types/modes/interactive-mode.d.ts +16 -6
- package/dist/types/modes/setup-version.d.ts +11 -0
- package/dist/types/modes/setup-wizard/index.d.ts +2 -1
- package/dist/types/modes/setup-wizard/scenes/web-search.d.ts +2 -1
- package/dist/types/modes/theme/theme.d.ts +1 -1
- package/dist/types/modes/types.d.ts +19 -6
- package/dist/types/modes/utils/copy-targets.d.ts +21 -1
- 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 +3 -1
- package/dist/types/session/agent-session.d.ts +21 -0
- package/dist/types/session/messages.d.ts +12 -0
- package/dist/types/session/session-manager.d.ts +3 -1
- package/dist/types/slash-commands/types.d.ts +4 -6
- package/dist/types/task/executor.d.ts +14 -0
- package/dist/types/task/index.d.ts +1 -0
- package/dist/types/task/render.d.ts +3 -2
- package/dist/types/telemetry-export.d.ts +1 -1
- 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-render.d.ts +1 -8
- package/dist/types/tools/fetch.d.ts +15 -7
- package/dist/types/tools/find.d.ts +8 -4
- 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/plan-mode-guard.d.ts +8 -9
- package/dist/types/tools/render-utils.d.ts +13 -9
- package/dist/types/tools/renderers.d.ts +16 -2
- package/dist/types/tools/search.d.ts +5 -1
- 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 +5 -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/scrapers/github.d.ts +22 -0
- package/dist/types/web/search/providers/kimi.d.ts +1 -1
- package/dist/types/web/search/providers/perplexity.d.ts +8 -1
- package/dist/types/web/search/types.d.ts +1 -1
- package/package.json +9 -9
- package/scripts/dev-launch +42 -0
- package/scripts/dev-launch-preload.ts +19 -0
- package/src/auto-thinking/classifier.ts +5 -1
- package/src/cli/args.ts +2 -2
- package/src/cli/dry-balance-cli.ts +52 -17
- package/src/cli/gallery-cli.ts +226 -0
- package/src/cli/gallery-fixtures/agentic.ts +292 -0
- package/src/cli/gallery-fixtures/codeintel.ts +188 -0
- package/src/cli/gallery-fixtures/edit.ts +194 -0
- package/src/cli/gallery-fixtures/fs.ts +153 -0
- package/src/cli/gallery-fixtures/index.ts +40 -0
- package/src/cli/gallery-fixtures/interaction.ts +49 -0
- package/src/cli/gallery-fixtures/memory.ts +81 -0
- package/src/cli/gallery-fixtures/misc.ts +250 -0
- package/src/cli/gallery-fixtures/search.ts +213 -0
- package/src/cli/gallery-fixtures/shell.ts +167 -0
- package/src/cli/gallery-fixtures/types.ts +41 -0
- package/src/cli/gallery-fixtures/web.ts +158 -0
- package/src/cli/gallery-screenshot.ts +279 -0
- package/src/cli-commands.ts +1 -0
- package/src/commands/gallery.ts +52 -0
- package/src/commands/launch.ts +1 -1
- 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 +33 -9
- package/src/commit/pipeline.ts +4 -4
- package/src/config/api-key-resolver.ts +58 -0
- package/src/config/keybindings.ts +15 -6
- package/src/config/model-equivalence.ts +35 -12
- package/src/config/model-id-affixes.ts +39 -22
- package/src/config/model-registry.ts +41 -18
- package/src/config/settings-schema.ts +28 -5
- package/src/config/settings.ts +31 -2
- package/src/dap/client.ts +14 -16
- 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 +40 -54
- package/src/edit/renderer.ts +111 -119
- package/src/eval/__tests__/agent-bridge.test.ts +75 -32
- package/src/eval/__tests__/llm-bridge.test.ts +90 -31
- package/src/eval/agent-bridge.ts +34 -7
- package/src/eval/llm-bridge.ts +8 -3
- package/src/extensibility/extensions/runner.ts +1 -0
- package/src/extensibility/plugins/doctor.ts +0 -1
- package/src/extensibility/plugins/marketplace-auto-update.ts +49 -0
- package/src/goals/tools/goal-tool.ts +37 -27
- package/src/internal-urls/docs-index.generated.ts +10 -10
- package/src/lsp/client.ts +104 -55
- package/src/lsp/types.ts +10 -0
- package/src/lsp/utils.ts +3 -2
- package/src/main.ts +53 -56
- package/src/memories/index.ts +12 -5
- package/src/memory-backend/index.ts +13 -1
- package/src/memory-backend/resolve.ts +3 -5
- package/src/memory-backend/types.ts +1 -1
- 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 +33 -1
- 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/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 +3 -5
- package/src/modes/components/tips.txt +1 -0
- package/src/modes/components/todo-reminder.ts +0 -2
- package/src/modes/components/tool-execution.ts +115 -90
- package/src/modes/components/transcript-container.ts +84 -24
- package/src/modes/components/user-message.ts +1 -2
- package/src/modes/controllers/command-controller-shared.ts +7 -6
- package/src/modes/controllers/command-controller.ts +70 -57
- package/src/modes/controllers/event-controller.ts +41 -40
- package/src/modes/controllers/extension-ui-controller.ts +10 -73
- package/src/modes/controllers/input-controller.ts +135 -122
- package/src/modes/controllers/mcp-command-controller.ts +69 -60
- package/src/modes/controllers/selector-controller.ts +25 -27
- package/src/modes/controllers/streaming-reveal.ts +212 -0
- package/src/modes/controllers/tan-command-controller.ts +173 -0
- package/src/modes/index.ts +5 -4
- package/src/modes/interactive-mode.ts +171 -82
- package/src/modes/setup-version.ts +11 -0
- package/src/modes/setup-wizard/index.ts +3 -2
- package/src/modes/setup-wizard/scenes/web-search.ts +3 -2
- package/src/modes/setup-wizard/wizard-overlay.ts +1 -1
- package/src/modes/theme/theme-schema.json +1 -1
- package/src/modes/theme/theme.ts +8 -4
- package/src/modes/types.ts +19 -8
- package/src/modes/utils/context-usage.ts +10 -6
- package/src/modes/utils/copy-targets.ts +133 -27
- package/src/modes/utils/hotkeys-markdown.ts +1 -0
- package/src/modes/utils/ui-helpers.ts +44 -46
- 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/sdk.ts +32 -60
- package/src/session/agent-session.ts +89 -13
- package/src/session/messages.ts +26 -0
- package/src/session/session-manager.ts +13 -5
- package/src/slash-commands/builtin-registry.ts +37 -10
- package/src/slash-commands/helpers/usage-report.ts +2 -0
- package/src/slash-commands/types.ts +4 -6
- package/src/task/executor.ts +25 -4
- package/src/task/index.ts +4 -0
- package/src/task/render.ts +212 -148
- package/src/telemetry-export.ts +25 -7
- 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 +50 -6
- package/src/tools/debug.ts +20 -8
- package/src/tools/eval-backends.ts +6 -17
- package/src/tools/eval-render.ts +21 -18
- package/src/tools/eval.ts +5 -4
- package/src/tools/fetch.ts +391 -91
- package/src/tools/find.ts +44 -30
- package/src/tools/gh-renderer.ts +81 -42
- 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 +8 -1
- package/src/tools/job.ts +3 -4
- package/src/tools/memory-render.ts +4 -1
- package/src/tools/plan-mode-guard.ts +21 -39
- package/src/tools/read.ts +23 -16
- package/src/tools/render-utils.ts +38 -40
- package/src/tools/renderers.ts +16 -1
- package/src/tools/report-tool-issue.ts +1 -1
- package/src/tools/resolve.ts +14 -0
- package/src/tools/search-tool-bm25.ts +36 -23
- package/src/tools/search.ts +189 -95
- package/src/tools/sqlite-reader.ts +9 -12
- package/src/tools/todo.ts +138 -59
- package/src/tools/write.ts +100 -60
- package/src/tui/output-block.ts +60 -13
- package/src/tui/status-line.ts +5 -1
- package/src/utils/commit-message-generator.ts +9 -1
- package/src/utils/enhanced-paste.ts +202 -0
- package/src/utils/title-generator.ts +2 -1
- package/src/web/scrapers/github.ts +255 -3
- package/src/web/scrapers/youtube.ts +3 -2
- package/src/web/search/providers/anthropic.ts +25 -19
- 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/perplexity.ts +199 -51
- 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
- package/src/web/search/render.ts +39 -54
- package/src/web/search/types.ts +5 -1
- package/dist/types/eval/__tests__/shared-executors.test.d.ts +0 -1
- package/src/eval/__tests__/shared-executors.test.ts +0 -609
|
@@ -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";
|
|
@@ -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
|
}
|
|
@@ -13,7 +13,6 @@ import { Loader, Markdown, padding, Spacer, Text, visibleWidth } from "@oh-my-pi
|
|
|
13
13
|
import { formatDuration, Snowflake } from "@oh-my-pi/pi-utils";
|
|
14
14
|
import { $ } from "bun";
|
|
15
15
|
import { shouldEnableAppendOnlyContext } from "../../config/append-only-context-mode";
|
|
16
|
-
import { loadCustomShare } from "../../export/custom-share";
|
|
17
16
|
import type { CompactOptions } from "../../extensibility/extensions/types";
|
|
18
17
|
import {
|
|
19
18
|
diffMentalModelContent,
|
|
@@ -29,6 +28,7 @@ import { BashExecutionComponent } from "../../modes/components/bash-execution";
|
|
|
29
28
|
import { BorderedLoader } from "../../modes/components/bordered-loader";
|
|
30
29
|
import { DynamicBorder } from "../../modes/components/dynamic-border";
|
|
31
30
|
import { EvalExecutionComponent } from "../../modes/components/eval-execution";
|
|
31
|
+
import { TranscriptBlock } from "../../modes/components/transcript-container";
|
|
32
32
|
import { getMarkdownTheme, getSymbolTheme, theme } from "../../modes/theme/theme";
|
|
33
33
|
import type { InteractiveModeContext } from "../../modes/types";
|
|
34
34
|
import { computeContextBreakdown, renderContextUsage } from "../../modes/utils/context-usage";
|
|
@@ -47,13 +47,13 @@ import { openPath } from "../../utils/open";
|
|
|
47
47
|
import { setSessionTerminalTitle } from "../../utils/title-generator";
|
|
48
48
|
|
|
49
49
|
function showMarkdownPanel(ctx: InteractiveModeContext, title: string, markdown: string): void {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
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);
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
export class CommandController {
|
|
@@ -131,6 +131,7 @@ export class CommandController {
|
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
try {
|
|
134
|
+
const { loadCustomShare } = await import("../../export/custom-share");
|
|
134
135
|
const customShare = await loadCustomShare();
|
|
135
136
|
if (customShare) {
|
|
136
137
|
const loader = new BorderedLoader(this.ctx.ui, theme, "Sharing...");
|
|
@@ -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,20 +445,20 @@ 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> {
|
|
465
458
|
const argumentText = text.slice(7).trim();
|
|
466
459
|
const action = argumentText.split(/\s+/, 1)[0]?.toLowerCase() || "view";
|
|
467
460
|
const agentDir = this.ctx.settings.getAgentDir();
|
|
468
|
-
const backend = resolveMemoryBackend(this.ctx.settings);
|
|
461
|
+
const backend = await resolveMemoryBackend(this.ctx.settings);
|
|
469
462
|
|
|
470
463
|
if (action === "view") {
|
|
471
464
|
const payload = await backend.buildDeveloperInstructions(agentDir, this.ctx.settings, this.ctx.session);
|
|
@@ -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
|
}
|
|
@@ -1272,6 +1274,8 @@ function formatAccountLabel(limit: UsageLimit, report: UsageReport, index: numbe
|
|
|
1272
1274
|
if (email) return email;
|
|
1273
1275
|
const accountId = (report.metadata?.accountId as string | undefined) ?? limit.scope.accountId;
|
|
1274
1276
|
if (accountId) return accountId;
|
|
1277
|
+
const projectId = (report.metadata?.projectId as string | undefined) ?? limit.scope.projectId;
|
|
1278
|
+
if (projectId) return projectId;
|
|
1275
1279
|
return `account ${index + 1}`;
|
|
1276
1280
|
}
|
|
1277
1281
|
|
|
@@ -1280,6 +1284,8 @@ function formatUnlimitedReportLabel(report: UsageReport, index: number): string
|
|
|
1280
1284
|
if (email) return email;
|
|
1281
1285
|
const accountId = report.metadata?.accountId as string | undefined;
|
|
1282
1286
|
if (accountId) return accountId;
|
|
1287
|
+
const projectId = report.metadata?.projectId as string | undefined;
|
|
1288
|
+
if (projectId) return projectId;
|
|
1283
1289
|
return `account ${index + 1}`;
|
|
1284
1290
|
}
|
|
1285
1291
|
|
|
@@ -1365,6 +1371,13 @@ function formatAggregateAmount(limits: UsageLimit[]): string {
|
|
|
1365
1371
|
return `${formatNumber(remainingPct)}% free`;
|
|
1366
1372
|
}
|
|
1367
1373
|
|
|
1374
|
+
// Count unique accounts from limit scopes — not limits.length.
|
|
1375
|
+
const uniqueAccountIds = new Set(
|
|
1376
|
+
limits.map(limit => limit.scope.accountId).filter((id): id is string => typeof id === "string" && id.length > 0),
|
|
1377
|
+
);
|
|
1378
|
+
if (uniqueAccountIds.size > 0) return `${uniqueAccountIds.size} ${uniqueAccountIds.size === 1 ? "acct" : "accts"}`;
|
|
1379
|
+
// No account IDs available — keep the pre-existing fallback so providers
|
|
1380
|
+
// that don't populate scope.accountId still show a summary.
|
|
1368
1381
|
return `${limits.length} accts`;
|
|
1369
1382
|
}
|
|
1370
1383
|
|