@linxiraos/pi-tui 1.1.27 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +47 -463
- package/README.md +7 -5
- package/dist/types/app-keybindings.d.ts +1 -1
- package/dist/types/apps/cleanse-board.d.ts +1 -1
- package/dist/types/apps/debug/log-viewer.d.ts +4 -0
- package/dist/types/apps/debug/raw-sse-buffer.d.ts +2 -0
- package/dist/types/apps/git/git-tui.d.ts +2 -2
- package/dist/types/apps/git/help.d.ts +3 -1
- package/dist/types/apps/if-bench-board.d.ts +2 -2
- package/dist/types/apps/setup-model-picker.d.ts +1 -1
- package/dist/types/autocomplete.d.ts +5 -2
- package/dist/types/charts/chart-plan.d.ts +674 -0
- package/dist/types/charts/chart-svg.d.ts +59 -0
- package/dist/types/charts/table-data.d.ts +175 -0
- package/dist/types/chat/assistant-message.d.ts +5 -0
- package/dist/types/chat/chat-transcript-builder.d.ts +2 -0
- package/dist/types/chat/compaction-summary-message.d.ts +1 -0
- package/dist/types/chat/execution-shared.d.ts +6 -5
- package/dist/types/chat/fence-figure.d.ts +42 -0
- package/dist/types/chat/figure-markdown.d.ts +42 -0
- package/dist/types/chat/messages.d.ts +1 -1
- package/dist/types/chat/svg-figure.d.ts +33 -0
- package/dist/types/chat/svg-source.d.ts +49 -0
- package/dist/types/chat/table-chart.d.ts +89 -0
- package/dist/types/chat/tool-execution.d.ts +2 -0
- package/dist/types/chat/user-message.d.ts +15 -2
- package/dist/types/chrome/shared.d.ts +9 -0
- package/dist/types/chrome/transcript-container.d.ts +6 -0
- package/dist/types/components/box.d.ts +1 -0
- package/dist/types/components/disclosure.d.ts +1 -0
- package/dist/types/components/editor.d.ts +15 -4
- package/dist/types/components/form.d.ts +1 -0
- package/dist/types/components/image.d.ts +12 -44
- package/dist/types/components/key-value-list.d.ts +1 -0
- package/dist/types/components/layout/row.d.ts +1 -0
- package/dist/types/components/layout/stack.d.ts +1 -0
- package/dist/types/components/markdown.d.ts +36 -3
- package/dist/types/components/scroll-view.d.ts +1 -0
- package/dist/types/components/section.d.ts +1 -0
- package/dist/types/components/table.d.ts +1 -0
- package/dist/types/components/text.d.ts +1 -0
- package/dist/types/components/tree-view.d.ts +7 -0
- package/dist/types/components/truncated-text.d.ts +1 -0
- package/dist/types/fuzzy.d.ts +29 -1
- package/dist/types/key-hint-format.d.ts +1 -1
- package/dist/types/keybinding-matchers.d.ts +3 -0
- package/dist/types/keybindings.d.ts +1 -1
- package/dist/types/kitty-graphics.d.ts +2 -2
- package/dist/types/loop-watchdog.d.ts +8 -7
- package/dist/types/multiplexers/cmux.d.ts +16 -0
- package/dist/types/multiplexers/herdr.d.ts +26 -0
- package/dist/types/multiplexers/notify.d.ts +13 -0
- package/dist/types/multiplexers/orca.d.ts +12 -0
- package/dist/types/multiplexers/screen.d.ts +9 -0
- package/dist/types/multiplexers/tmux.d.ts +29 -0
- package/dist/types/multiplexers/types.d.ts +100 -0
- package/dist/types/multiplexers/wmux.d.ts +12 -0
- package/dist/types/multiplexers/zellij.d.ts +12 -0
- package/dist/types/native/backend.d.ts +3 -2
- package/dist/types/native/blobs.d.ts +7 -3
- package/dist/types/native/encode.d.ts +3 -4
- package/dist/types/native/overlay.d.ts +5 -0
- package/dist/types/overlays/agent-hub-projection.d.ts +6 -5
- package/dist/types/overlays/agent-hub-types.d.ts +9 -0
- package/dist/types/overlays/agent-hub.d.ts +2 -0
- package/dist/types/overlays/agent-transcript-viewer.d.ts +11 -2
- package/dist/types/overlays/agents-hub.d.ts +9 -0
- package/dist/types/overlays/annotation-overlay.d.ts +19 -2
- package/dist/types/overlays/annotation-types.d.ts +2 -0
- package/dist/types/overlays/ask-dialog.d.ts +5 -2
- package/dist/types/overlays/history-search.d.ts +10 -0
- package/dist/types/overlays/hook-selector.d.ts +9 -4
- package/dist/types/overlays/jobs-panel.d.ts +1 -7
- package/dist/types/overlays/model-browser.d.ts +54 -7
- package/dist/types/overlays/model-hub.d.ts +23 -0
- package/dist/types/overlays/oauth-selector.d.ts +0 -1
- package/dist/types/overlays/plan-review-overlay.d.ts +3 -2
- package/dist/types/overlays/session-observer-registry.d.ts +2 -0
- package/dist/types/overlays/session-selector.d.ts +6 -2
- package/dist/types/overlays/settings-defs.d.ts +1 -0
- package/dist/types/overlays/usage-dashboard.d.ts +8 -4
- package/dist/types/overlays/usage-display.d.ts +3 -1
- package/dist/types/prompt/composer.d.ts +1 -1
- package/dist/types/prompt/custom-editor.d.ts +11 -8
- package/dist/types/prompt/image-source.d.ts +2 -1
- package/dist/types/prompt/interactive-context-helpers.d.ts +4 -1
- package/dist/types/prompt/model-mention-autocomplete.d.ts +1 -1
- package/dist/types/prompt/welcome.d.ts +6 -1
- package/dist/types/render/composite.d.ts +2 -0
- package/dist/types/render/output-pane.d.ts +1 -0
- package/dist/types/render/render-utils.d.ts +1 -0
- package/dist/types/render/tool-card.d.ts +6 -0
- package/dist/types/render/width-aware-text.d.ts +2 -0
- package/dist/types/setup/scenes/types.d.ts +1 -0
- package/dist/types/status-line/component.d.ts +3 -0
- package/dist/types/status-line/host.d.ts +4 -1
- package/dist/types/status-line/segments.d.ts +2 -0
- package/dist/types/status-line/types.d.ts +14 -3
- package/dist/types/terminal-capabilities.d.ts +27 -35
- package/dist/types/terminal-multiplexer.d.ts +127 -14
- package/dist/types/terminal.d.ts +22 -6
- package/dist/types/theme/active-symbols.d.ts +1 -1
- package/dist/types/theme/schema.d.ts +11 -2
- package/dist/types/theme/symbols.d.ts +1 -1
- package/dist/types/theme/theme-class.d.ts +7 -0
- package/dist/types/theme/theme.d.ts +1 -1
- package/dist/types/theme/tui-adapters.d.ts +3 -0
- package/dist/types/tmux.d.ts +11 -4
- package/dist/types/tools/daemon.d.ts +1 -1
- package/dist/types/tools/eval.d.ts +22 -3
- package/dist/types/tools/glob.d.ts +4 -0
- package/dist/types/tools/native-view.d.ts +47 -0
- package/dist/types/tools/output-meta.d.ts +11 -1
- package/dist/types/tools/renderer.d.ts +37 -2
- package/dist/types/tools/streaming-output.d.ts +20 -1
- package/dist/types/tools/task.d.ts +0 -4
- package/dist/types/tools/write.d.ts +9 -2
- package/dist/types/tools/yield.d.ts +22 -0
- package/dist/types/tui.d.ts +31 -0
- package/dist/types/utils.d.ts +6 -0
- package/dist/types/vim.d.ts +19 -5
- package/package.json +13 -9
- package/src/app-keybindings.d.ts +1 -1
- package/src/app-keybindings.ts +1 -1
- package/src/apps/autoresearch-dashboard.ts +7 -3
- package/src/apps/cleanse-board.ts +2 -2
- package/src/apps/cleanse-picker.ts +1 -1
- package/src/apps/debug/log-viewer.ts +188 -72
- package/src/apps/debug/raw-sse-buffer.ts +8 -0
- package/src/apps/debug/raw-sse.ts +39 -5
- package/src/apps/git/diff-pane.ts +26 -5
- package/src/apps/git/git-tui.ts +2 -2
- package/src/apps/git/help.ts +29 -20
- package/src/apps/if-bench-board.ts +2 -2
- package/src/apps/ps-top.ts +2 -2
- package/src/apps/setup-model-picker.ts +1 -1
- package/src/autocomplete.d.ts +5 -2
- package/src/autocomplete.ts +67 -43
- package/src/charts/chart-plan.d.ts +674 -0
- package/src/charts/chart-plan.ts +5081 -0
- package/src/charts/chart-svg.d.ts +59 -0
- package/src/charts/chart-svg.ts +4657 -0
- package/src/charts/table-data.d.ts +175 -0
- package/src/charts/table-data.ts +1478 -0
- package/src/chat/advisor-message.ts +11 -0
- package/src/chat/assistant-message.d.ts +5 -0
- package/src/chat/assistant-message.ts +219 -50
- package/src/chat/chat-transcript-builder.d.ts +2 -0
- package/src/chat/chat-transcript-builder.ts +5 -3
- package/src/chat/compaction-summary-message.d.ts +1 -0
- package/src/chat/compaction-summary-message.ts +8 -0
- package/src/chat/execution-shared.d.ts +6 -5
- package/src/chat/execution-shared.ts +42 -25
- package/src/chat/fence-figure.d.ts +42 -0
- package/src/chat/fence-figure.ts +80 -0
- package/src/chat/figure-markdown.d.ts +42 -0
- package/src/chat/figure-markdown.ts +174 -0
- package/src/chat/messages.d.ts +1 -1
- package/src/chat/messages.ts +1 -1
- package/src/chat/read-tool-group.ts +6 -4
- package/src/chat/skill-message.ts +6 -0
- package/src/chat/svg-figure.d.ts +33 -0
- package/src/chat/svg-figure.ts +399 -0
- package/src/chat/svg-source.d.ts +49 -0
- package/src/chat/svg-source.ts +188 -0
- package/src/chat/table-chart.d.ts +89 -0
- package/src/chat/table-chart.ts +294 -0
- package/src/chat/tool-execution.d.ts +2 -0
- package/src/chat/tool-execution.ts +80 -6
- package/src/chat/user-message.d.ts +15 -2
- package/src/chat/user-message.ts +55 -3
- package/src/chrome/shared.ts +53 -0
- package/src/chrome/transcript-container.d.ts +6 -0
- package/src/chrome/transcript-container.ts +93 -13
- package/src/components/box.d.ts +1 -0
- package/src/components/box.ts +5 -0
- package/src/components/disclosure.d.ts +1 -0
- package/src/components/disclosure.ts +8 -0
- package/src/components/editor.d.ts +15 -4
- package/src/components/editor.ts +294 -46
- package/src/components/form.d.ts +1 -0
- package/src/components/form.ts +8 -0
- package/src/components/image.d.ts +12 -44
- package/src/components/image.ts +47 -151
- package/src/components/key-value-list.d.ts +1 -0
- package/src/components/key-value-list.ts +4 -0
- package/src/components/layout/row.d.ts +1 -0
- package/src/components/layout/row.ts +7 -0
- package/src/components/layout/stack.d.ts +1 -0
- package/src/components/layout/stack.ts +7 -0
- package/src/components/markdown.d.ts +36 -3
- package/src/components/markdown.ts +433 -318
- package/src/components/scroll-view.d.ts +1 -0
- package/src/components/scroll-view.ts +5 -0
- package/src/components/section.d.ts +1 -0
- package/src/components/section.ts +5 -0
- package/src/components/settings-list.ts +2 -0
- package/src/components/table.d.ts +1 -0
- package/src/components/table.ts +4 -0
- package/src/components/text.d.ts +1 -0
- package/src/components/text.ts +7 -0
- package/src/components/tree-view.d.ts +7 -0
- package/src/components/tree-view.ts +38 -8
- package/src/components/truncated-text.d.ts +1 -0
- package/src/components/truncated-text.ts +5 -0
- package/src/desktop-notify.ts +1 -1
- package/src/fuzzy.d.ts +29 -1
- package/src/fuzzy.ts +115 -30
- package/src/key-hint-format.d.ts +1 -1
- package/src/key-hint-format.ts +1 -1
- package/src/keybinding-matchers.d.ts +3 -0
- package/src/keybinding-matchers.ts +6 -2
- package/src/keybindings.d.ts +1 -1
- package/src/keybindings.ts +1 -1
- package/src/kitty-graphics.d.ts +2 -2
- package/src/kitty-graphics.ts +4 -4
- package/src/loop-watchdog.d.ts +8 -7
- package/src/loop-watchdog.ts +18 -13
- package/src/multiplexers/cmux.d.ts +16 -0
- package/src/multiplexers/cmux.ts +29 -0
- package/src/multiplexers/herdr.d.ts +26 -0
- package/src/multiplexers/herdr.ts +64 -0
- package/src/multiplexers/notify.d.ts +13 -0
- package/src/multiplexers/notify.ts +24 -0
- package/src/multiplexers/orca.d.ts +12 -0
- package/src/multiplexers/orca.ts +16 -0
- package/src/multiplexers/screen.d.ts +9 -0
- package/src/multiplexers/screen.ts +15 -0
- package/src/multiplexers/tmux.d.ts +29 -0
- package/src/multiplexers/tmux.ts +40 -0
- package/src/multiplexers/types.d.ts +100 -0
- package/src/multiplexers/types.ts +110 -0
- package/src/multiplexers/wmux.d.ts +12 -0
- package/src/multiplexers/wmux.ts +16 -0
- package/src/multiplexers/zellij.d.ts +12 -0
- package/src/multiplexers/zellij.ts +24 -0
- package/src/native/backend.d.ts +3 -2
- package/src/native/backend.ts +174 -18
- package/src/native/blobs.d.ts +7 -3
- package/src/native/blobs.ts +47 -12
- package/src/native/encode.d.ts +3 -4
- package/src/native/encode.ts +58 -31
- package/src/native/overlay.d.ts +5 -0
- package/src/native/overlay.ts +13 -0
- package/src/native/reconcile.ts +4 -0
- package/src/overlays/agent-hub-projection.d.ts +6 -5
- package/src/overlays/agent-hub-projection.ts +124 -13
- package/src/overlays/agent-hub-types.d.ts +9 -0
- package/src/overlays/agent-hub-types.ts +6 -0
- package/src/overlays/agent-hub.ts +44 -29
- package/src/overlays/agent-transcript-viewer.ts +91 -23
- package/src/overlays/agents-hub.ts +28 -8
- package/src/overlays/annotation-overlay.ts +293 -90
- package/src/overlays/annotation-types.ts +2 -0
- package/src/overlays/ask-dialog.ts +7 -10
- package/src/overlays/btw-history-panel.ts +12 -1
- package/src/overlays/copy-selector.ts +30 -8
- package/src/overlays/extensions/state-manager.ts +52 -12
- package/src/overlays/history-search.ts +100 -7
- package/src/overlays/hook-selector.ts +12 -5
- package/src/overlays/jobs-panel.ts +28 -46
- package/src/overlays/model-browser.ts +341 -110
- package/src/overlays/model-hub.ts +300 -49
- package/src/overlays/move-overlay.ts +28 -14
- package/src/overlays/oauth-selector.ts +54 -70
- package/src/overlays/plan-review-overlay.ts +194 -70
- package/src/overlays/plugin-settings.ts +3 -3
- package/src/overlays/report-panel.ts +2 -2
- package/src/overlays/rewind-selector.ts +86 -17
- package/src/overlays/session-observer-registry.d.ts +2 -0
- package/src/overlays/session-observer-registry.ts +10 -2
- package/src/overlays/session-selector.ts +64 -26
- package/src/overlays/settings-defs.ts +4 -3
- package/src/overlays/settings-selector.ts +33 -8
- package/src/overlays/snapcompact-shape-preview.ts +2 -3
- package/src/overlays/stats-notice.ts +1 -1
- package/src/overlays/tree-selector.ts +41 -20
- package/src/overlays/usage-dashboard.ts +100 -50
- package/src/overlays/usage-display.ts +10 -4
- package/src/prompt/attachment-chips.ts +15 -11
- package/src/prompt/composer-attachments.ts +6 -4
- package/src/prompt/composer.ts +4 -15
- package/src/prompt/custom-editor.ts +54 -26
- package/src/prompt/image-source.ts +2 -1
- package/src/prompt/interactive-context-helpers.ts +30 -18
- package/src/prompt/macos-spelling.ts +7 -0
- package/src/prompt/magic-keywords.ts +11 -2
- package/src/prompt/model-mention-autocomplete.ts +14 -14
- package/src/prompt/tips.txt +6 -5
- package/src/prompt/welcome.ts +55 -12
- package/src/prompt/word-completion.ts +38 -5
- package/src/render/composite.d.ts +2 -0
- package/src/render/composite.ts +64 -0
- package/src/render/output-pane.d.ts +1 -0
- package/src/render/output-pane.ts +6 -0
- package/src/render/render-utils.d.ts +1 -0
- package/src/render/render-utils.ts +11 -0
- package/src/render/tool-card.d.ts +6 -0
- package/src/render/tool-card.ts +15 -0
- package/src/render/width-aware-text.d.ts +2 -0
- package/src/render/width-aware-text.ts +5 -0
- package/src/setup/scenes/model.ts +2 -1
- package/src/setup/scenes/types.ts +1 -0
- package/src/status-line/component.ts +292 -78
- package/src/status-line/host.ts +4 -1
- package/src/status-line/segments.ts +40 -22
- package/src/status-line/types.ts +15 -3
- package/src/terminal-capabilities.d.ts +27 -35
- package/src/terminal-capabilities.ts +75 -189
- package/src/terminal-multiplexer.d.ts +127 -14
- package/src/terminal-multiplexer.ts +112 -33
- package/src/terminal.d.ts +22 -6
- package/src/terminal.ts +139 -37
- package/src/theme/active-symbols.d.ts +1 -1
- package/src/theme/active-symbols.ts +1 -1
- package/src/theme/schema-validation.ts +1 -0
- package/src/theme/schema.d.ts +11 -2
- package/src/theme/schema.ts +14 -1
- package/src/theme/session-color.ts +1 -7
- package/src/theme/symbols.d.ts +1 -1
- package/src/theme/symbols.ts +6 -1
- package/src/theme/theme-class.d.ts +7 -0
- package/src/theme/theme-class.ts +26 -1
- package/src/theme/theme-schema.json +5 -1
- package/src/theme/theme.d.ts +1 -1
- package/src/theme/theme.ts +8 -4
- package/src/theme/tui-adapters.d.ts +3 -0
- package/src/theme/tui-adapters.ts +68 -0
- package/src/tmux.d.ts +11 -4
- package/src/tmux.ts +47 -11
- package/src/tools/ast-edit.ts +59 -35
- package/src/tools/ast-grep.ts +35 -16
- package/src/tools/bash.ts +92 -42
- package/src/tools/daemon.d.ts +1 -1
- package/src/tools/daemon.ts +1 -1
- package/src/tools/default-renderer.ts +35 -19
- package/src/tools/edit.ts +142 -120
- package/src/tools/eval-format/index.ts +28 -2
- package/src/tools/eval-format/javascript.ts +7 -5
- package/src/tools/eval.d.ts +22 -3
- package/src/tools/eval.ts +364 -208
- package/src/tools/fetch.ts +5 -6
- package/src/tools/glob.d.ts +4 -0
- package/src/tools/glob.ts +33 -65
- package/src/tools/grep.ts +81 -48
- package/src/tools/index.ts +2 -0
- package/src/tools/lsp.ts +81 -59
- package/src/tools/mcp.ts +111 -68
- package/src/tools/native-view.d.ts +47 -0
- package/src/tools/native-view.ts +102 -1
- package/src/tools/output-meta.d.ts +11 -1
- package/src/tools/output-meta.ts +23 -3
- package/src/tools/read.ts +7 -5
- package/src/tools/renderer.d.ts +37 -2
- package/src/tools/renderer.ts +42 -2
- package/src/tools/streaming-output.d.ts +20 -1
- package/src/tools/streaming-output.ts +149 -50
- package/src/tools/task.d.ts +0 -4
- package/src/tools/task.ts +112 -59
- package/src/tools/todo.ts +119 -30
- package/src/tools/wait.ts +34 -24
- package/src/tools/web-search.ts +1 -1
- package/src/tools/write.d.ts +9 -2
- package/src/tools/write.ts +147 -95
- package/src/tools/yield.d.ts +22 -0
- package/src/tools/yield.ts +225 -0
- package/src/tui.d.ts +31 -0
- package/src/tui.ts +309 -160
- package/src/utils.d.ts +6 -0
- package/src/utils.ts +19 -0
- package/src/vim.d.ts +19 -5
- package/src/vim.ts +333 -18
- package/src/windows-input-mode.ts +8 -0
|
@@ -9,7 +9,7 @@ import { actionBar, actionButton } from "../../native/overlay";
|
|
|
9
9
|
import { routeSgrMouseInput, type SgrMouseEvent } from "../../mouse";
|
|
10
10
|
import { truncateToWidth } from "../../utils";
|
|
11
11
|
import { sanitizeDisplayText } from "../../overlays/extensions/display-text";
|
|
12
|
-
import { theme } from "../../theme/theme";
|
|
12
|
+
import { getThemeEpoch, theme } from "../../theme/theme";
|
|
13
13
|
import { DebugViewerFrame } from "./viewer-frame";
|
|
14
14
|
import {
|
|
15
15
|
formatRawSseIsoTime,
|
|
@@ -106,6 +106,14 @@ export class RawSseViewerComponent implements Component {
|
|
|
106
106
|
// Sequences are monotonic; we prune entries below the oldest live record
|
|
107
107
|
// after each render so the cache tracks the buffer's eviction window.
|
|
108
108
|
readonly #prettyLinesCache = new Map<number, string[]>();
|
|
109
|
+
/** Buffer snapshot for {@link #snapshotRevision}; the buffer's revision bumps on every change. */
|
|
110
|
+
#snapshot: RawSseDebugSnapshot | undefined;
|
|
111
|
+
#snapshotRevision = -1;
|
|
112
|
+
/** Rendered body for (buffer revision, width, theme epoch). */
|
|
113
|
+
#bodyLines: string[] = [];
|
|
114
|
+
#bodyRevision = -1;
|
|
115
|
+
#bodyWidth = -1;
|
|
116
|
+
#bodyThemeEpoch = -1;
|
|
109
117
|
|
|
110
118
|
constructor(options: RawSseViewerOptions) {
|
|
111
119
|
this.#deps = options.deps;
|
|
@@ -227,6 +235,7 @@ export class RawSseViewerComponent implements Component {
|
|
|
227
235
|
this.#native.clear();
|
|
228
236
|
this.#nativeHead.clear();
|
|
229
237
|
this.#nativeBody.clear();
|
|
238
|
+
this.#bodyRevision = -1;
|
|
230
239
|
}
|
|
231
240
|
|
|
232
241
|
render(width: number): readonly string[] {
|
|
@@ -249,7 +258,7 @@ export class RawSseViewerComponent implements Component {
|
|
|
249
258
|
* so they never scroll away.
|
|
250
259
|
*/
|
|
251
260
|
describeScreen(): NativeScreen {
|
|
252
|
-
const snapshot = this.#
|
|
261
|
+
const snapshot = this.#currentSnapshot();
|
|
253
262
|
const stream = this.#feedNative(snapshot);
|
|
254
263
|
const head = this.#nativeHead.get(
|
|
255
264
|
[snapshot.totalEvents, snapshot.records.length, snapshot.droppedRecords, snapshot.lastUpdatedAt],
|
|
@@ -372,15 +381,40 @@ export class RawSseViewerComponent implements Component {
|
|
|
372
381
|
this.#onExit();
|
|
373
382
|
}
|
|
374
383
|
|
|
384
|
+
/** The buffer's snapshot, re-taken only when its revision moved. */
|
|
385
|
+
#currentSnapshot(): RawSseDebugSnapshot {
|
|
386
|
+
const revision = this.#buffer.revision;
|
|
387
|
+
if (!this.#snapshot || this.#snapshotRevision !== revision) {
|
|
388
|
+
this.#snapshot = this.#buffer.snapshot();
|
|
389
|
+
this.#snapshotRevision = revision;
|
|
390
|
+
}
|
|
391
|
+
return this.#snapshot;
|
|
392
|
+
}
|
|
393
|
+
|
|
375
394
|
#renderRawLines(innerWidth: number): string[] {
|
|
376
|
-
const snapshot = this.#
|
|
395
|
+
const snapshot = this.#currentSnapshot();
|
|
396
|
+
const themeEpoch = getThemeEpoch();
|
|
397
|
+
if (
|
|
398
|
+
this.#bodyRevision === this.#snapshotRevision &&
|
|
399
|
+
this.#bodyWidth === innerWidth &&
|
|
400
|
+
this.#bodyThemeEpoch === themeEpoch
|
|
401
|
+
) {
|
|
402
|
+
return this.#bodyLines;
|
|
403
|
+
}
|
|
404
|
+
this.#bodyRevision = this.#snapshotRevision;
|
|
405
|
+
this.#bodyWidth = innerWidth;
|
|
406
|
+
this.#bodyThemeEpoch = themeEpoch;
|
|
407
|
+
this.#bodyLines = this.#formatRawLines(snapshot, innerWidth);
|
|
408
|
+
return this.#bodyLines;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
#formatRawLines(snapshot: RawSseDebugSnapshot, innerWidth: number): string[] {
|
|
377
412
|
if (snapshot.records.length === 0) {
|
|
378
413
|
return [
|
|
379
414
|
theme.fg("muted", "No raw SSE frames captured yet."),
|
|
380
415
|
theme.fg("muted", "HTTP SSE providers populate this view while a model response is streaming."),
|
|
381
416
|
];
|
|
382
417
|
}
|
|
383
|
-
|
|
384
418
|
const lines: string[] = [];
|
|
385
419
|
if (snapshot.droppedRecords > 0) {
|
|
386
420
|
lines.push(
|
|
@@ -421,7 +455,7 @@ export class RawSseViewerComponent implements Component {
|
|
|
421
455
|
}
|
|
422
456
|
}
|
|
423
457
|
#summaryText(): string {
|
|
424
|
-
const snapshot = this.#
|
|
458
|
+
const snapshot = this.#currentSnapshot();
|
|
425
459
|
const last = snapshot.lastUpdatedAt
|
|
426
460
|
? `${theme.fg("muted", "last")} ${theme.fg("accent", formatRawSseIsoTime(snapshot.lastUpdatedAt))}`
|
|
427
461
|
: theme.fg("muted", "waiting for first frame");
|
|
@@ -19,7 +19,7 @@ import { centerLine, sliceWithWidth, truncateToWidth, visibleWidth } from "../..
|
|
|
19
19
|
import { formatBytes } from "@linxiraos/pi-utils";
|
|
20
20
|
import { sanitizeDisplayText } from "../../overlays/extensions/display-text";
|
|
21
21
|
import { getLanguageFromPath } from "../../lang-from-path";
|
|
22
|
-
import { createHighlightStream, theme } from "../../theme/theme";
|
|
22
|
+
import { createHighlightStream, getThemeEpoch, theme } from "../../theme/theme";
|
|
23
23
|
import { bgAnsiHex, canvasHex, fgAnsiHex, mixHex, pill, selectionBgAnsi, textHex, withBg } from "./colors";
|
|
24
24
|
import { DIFF_CONTEXT_LINES, type FileAssetSide, type FileStreamUpdate } from "./state";
|
|
25
25
|
import { tuiText } from "../../i18n";
|
|
@@ -502,9 +502,12 @@ interface DiffPalette {
|
|
|
502
502
|
gutterDel: string;
|
|
503
503
|
}
|
|
504
504
|
|
|
505
|
-
let paletteCache: {
|
|
505
|
+
let paletteCache: { epoch: number; theme: object; palette: DiffPalette } | undefined;
|
|
506
506
|
|
|
507
|
+
/** Diff colors for the active theme, rebuilt only when the theme instance or epoch changes. */
|
|
507
508
|
function palette(): DiffPalette {
|
|
509
|
+
const epoch = getThemeEpoch();
|
|
510
|
+
if (paletteCache?.epoch === epoch && paletteCache.theme === theme) return paletteCache.palette;
|
|
508
511
|
const added = theme.getColorHex("toolDiffAdded");
|
|
509
512
|
const removed = theme.getColorHex("toolDiffRemoved");
|
|
510
513
|
const accent = theme.getColorHex("accent");
|
|
@@ -512,8 +515,6 @@ function palette(): DiffPalette {
|
|
|
512
515
|
const dark = luminance === undefined || luminance <= 0.5;
|
|
513
516
|
const canvas = canvasHex();
|
|
514
517
|
const text = textHex();
|
|
515
|
-
const key = `${added}\u0000${removed}\u0000${accent}\u0000${dark}\u0000${canvas}\u0000${text}`;
|
|
516
|
-
if (paletteCache?.key === key) return paletteCache.palette;
|
|
517
518
|
const built: DiffPalette = {
|
|
518
519
|
addSoft: bgAnsiHex(mixHex(canvas, added, dark ? 0.18 : 0.24)),
|
|
519
520
|
addStrong: bgAnsiHex(mixHex(canvas, added, dark ? 0.42 : 0.48)),
|
|
@@ -529,7 +530,7 @@ function palette(): DiffPalette {
|
|
|
529
530
|
gutterAdd: added,
|
|
530
531
|
gutterDel: removed,
|
|
531
532
|
};
|
|
532
|
-
paletteCache = {
|
|
533
|
+
paletteCache = { epoch, theme, palette: built };
|
|
533
534
|
return built;
|
|
534
535
|
}
|
|
535
536
|
|
|
@@ -599,6 +600,10 @@ export class DiffPane {
|
|
|
599
600
|
#lastHeight = 1;
|
|
600
601
|
#lastWidth = 0;
|
|
601
602
|
#layoutCache: { key: string; visuals: Visual[] } | undefined;
|
|
603
|
+
/** Minimap column for (layout, height, scroll offset, palette). */
|
|
604
|
+
#minimapCache:
|
|
605
|
+
| { visuals: Visual[]; height: number; scrollTop: number; colors: DiffPalette; lines: string[] }
|
|
606
|
+
| undefined;
|
|
602
607
|
/** Per visible row: clickable hunk-button ranges recorded during render. */
|
|
603
608
|
#hits: ({ hunk: number; primary?: [number, number]; discard?: [number, number] } | undefined)[] = [];
|
|
604
609
|
/**
|
|
@@ -1500,6 +1505,22 @@ export class DiffPane {
|
|
|
1500
1505
|
}
|
|
1501
1506
|
|
|
1502
1507
|
#renderMinimap(visuals: Visual[], height: number, colors: DiffPalette): string[] {
|
|
1508
|
+
const cached = this.#minimapCache;
|
|
1509
|
+
if (
|
|
1510
|
+
cached &&
|
|
1511
|
+
cached.visuals === visuals &&
|
|
1512
|
+
cached.height === height &&
|
|
1513
|
+
cached.scrollTop === this.scrollTop &&
|
|
1514
|
+
cached.colors === colors
|
|
1515
|
+
) {
|
|
1516
|
+
return cached.lines;
|
|
1517
|
+
}
|
|
1518
|
+
const lines = this.#buildMinimap(visuals, height, colors);
|
|
1519
|
+
this.#minimapCache = { visuals, height, scrollTop: this.scrollTop, colors, lines };
|
|
1520
|
+
return lines;
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1523
|
+
#buildMinimap(visuals: Visual[], height: number, colors: DiffPalette): string[] {
|
|
1503
1524
|
const total = visuals.length;
|
|
1504
1525
|
const lines: string[] = [];
|
|
1505
1526
|
const bandKind = (band: number): RowKind | "hunk" | null => {
|
package/src/apps/git/git-tui.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `
|
|
2
|
+
* `zetacode git` — fullscreen repository TUI.
|
|
3
3
|
*
|
|
4
4
|
* Layout: header (file path, encoding, stage-file button, close), toolbar
|
|
5
5
|
* (scope chip, file/diff toggle, hunk navigation, hunk/inline/split view
|
|
@@ -1235,7 +1235,7 @@ export async function showGitOverlay(ui: TUI, host: GitTuiHost): Promise<void> {
|
|
|
1235
1235
|
}
|
|
1236
1236
|
}
|
|
1237
1237
|
|
|
1238
|
-
/** Run the fullscreen git TUI standalone (`
|
|
1238
|
+
/** Run the fullscreen git TUI standalone (`zetacode git`) until the user quits. */
|
|
1239
1239
|
export async function runGitTui(host: GitTuiHost): Promise<void> {
|
|
1240
1240
|
const ui = new TUI(new ProcessTerminal());
|
|
1241
1241
|
ui.start();
|
package/src/apps/git/help.ts
CHANGED
|
@@ -11,7 +11,8 @@ import { formatKeyHint } from "../../app-keybindings";
|
|
|
11
11
|
import type { KeyName } from "../../key-hint-format";
|
|
12
12
|
import { matchesKey } from "../../keys";
|
|
13
13
|
import { col, node, span } from "../../native/describe";
|
|
14
|
-
import type { NativeNode } from "../../native/node";
|
|
14
|
+
import type { NativeNode, NativeUiEvent } from "../../native/node";
|
|
15
|
+
import { actionBar, actionButton } from "../../native/overlay";
|
|
15
16
|
import { theme } from "../../theme/theme";
|
|
16
17
|
import type { Component } from "../../tui";
|
|
17
18
|
import { truncateToWidth, visibleWidth } from "../../utils";
|
|
@@ -79,28 +80,36 @@ export class GitHelpSheet implements Component {
|
|
|
79
80
|
if (data === "?" || data === "q" || matchesKey(data, "escape") || matchesKey(data, "ctrl+c")) this.#close();
|
|
80
81
|
}
|
|
81
82
|
|
|
83
|
+
/** Close runs what Esc runs. */
|
|
84
|
+
handleNativeEvent(event: NativeUiEvent): void {
|
|
85
|
+
if (event.type === "action" && event.act === "close") this.#close();
|
|
86
|
+
}
|
|
87
|
+
|
|
82
88
|
describe(): NativeNode {
|
|
83
89
|
this.#native ??= col(
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
90
|
+
[
|
|
91
|
+
...GROUPS.map(group =>
|
|
92
|
+
node(
|
|
93
|
+
"section",
|
|
94
|
+
{ head: group.title, role: "zeta.hotkeys.group" },
|
|
95
|
+
[
|
|
96
|
+
node("table", {
|
|
97
|
+
role: "zeta.hotkeys.table",
|
|
98
|
+
cols: [
|
|
99
|
+
{ id: "keys", head: "Keys" },
|
|
100
|
+
{ id: "does", head: "Action", grow: 1 },
|
|
101
|
+
],
|
|
102
|
+
rows: group.rows.map((row, index) => ({
|
|
103
|
+
id: String(index),
|
|
104
|
+
cells: { keys: row.keys.map(key => span(formatKeyHint(key), "key")), does: row.label },
|
|
105
|
+
})),
|
|
106
|
+
}),
|
|
107
|
+
],
|
|
108
|
+
group.title,
|
|
109
|
+
),
|
|
102
110
|
),
|
|
103
|
-
|
|
111
|
+
actionBar([null, actionButton("Close", "close", { keys: "escape" })]),
|
|
112
|
+
],
|
|
104
113
|
{ gap: "lg", role: "zeta.app.git.help" },
|
|
105
114
|
);
|
|
106
115
|
return this.#native;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Live board and scoreboard for `
|
|
2
|
+
* Live board and scoreboard for `zetacode if-bench`.
|
|
3
3
|
*
|
|
4
4
|
* Interactive terminals get one repainted row per model — a turn ladder that
|
|
5
5
|
* fills as turns pass, the in-flight turn as a spinner cell, and the live
|
|
@@ -71,7 +71,7 @@ const FAILURE_TEXT: Record<IfBenchFailure, string> = {
|
|
|
71
71
|
provider: "provider error",
|
|
72
72
|
};
|
|
73
73
|
|
|
74
|
-
/** Rendering surface for one `
|
|
74
|
+
/** Rendering surface for one `zetacode if-bench` run. */
|
|
75
75
|
export interface IfBenchBoard extends IfBenchObserver {
|
|
76
76
|
readonly interactive: boolean;
|
|
77
77
|
/** Print a permanent line above the live rows (plain write when non-TTY). */
|
package/src/apps/ps-top.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Interactive alt-screen monitor for `
|
|
2
|
+
* Interactive alt-screen monitor for `zetacode ps` (btop idiom): a live process
|
|
3
3
|
* table over every selected broker scope with in-place actions.
|
|
4
4
|
*
|
|
5
5
|
* Keys — table: `↑/↓`/`j/k` select, `enter`/`i` info, `l` logs, `s` stop,
|
|
@@ -631,7 +631,7 @@ export class PsTopComponent implements Component {
|
|
|
631
631
|
|
|
632
632
|
#header(width: number, title: string): string {
|
|
633
633
|
const age = this.#lastRefresh ? `updated ${formatDuration(Date.now() - this.#lastRefresh)} ago` : "updating…";
|
|
634
|
-
const left = ` ${chalk.bold("
|
|
634
|
+
const left = ` ${chalk.bold("zetacode ps")} ${chalk.dim("·")} ${title}`;
|
|
635
635
|
const right = chalk.dim(age);
|
|
636
636
|
const pad = Math.max(1, width - Bun.stringWidth(left) - Bun.stringWidth(right) - 1);
|
|
637
637
|
return truncateToWidth(`${left}${" ".repeat(pad)}${right}`, width);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Standalone TUI model picker used by `
|
|
2
|
+
* Standalone TUI model picker used by `zetacode setup speech`.
|
|
3
3
|
*
|
|
4
4
|
* One-shot {@link selectStandaloneItem} prompt: resolve on select/cancel and
|
|
5
5
|
* let the adapter tear the UI down. The standalone TUI auto-renders on input,
|
package/src/autocomplete.d.ts
CHANGED
|
@@ -77,8 +77,11 @@ export interface AutocompleteProvider {
|
|
|
77
77
|
};
|
|
78
78
|
/** Get inline hint text to show as dim ghost text after the cursor */
|
|
79
79
|
getInlineHint?(lines: string[], cursorLine: number, cursorCol: number): string | null;
|
|
80
|
-
/**
|
|
81
|
-
|
|
80
|
+
/**
|
|
81
|
+
* Synchronously list slash command-name completions for a leading slash token (no async I/O).
|
|
82
|
+
* Mirrors the command-name branch of {@link getSuggestions}, including the bare `/` listing and
|
|
83
|
+
* the collapsed `/skill:` namespace row. Returns null outside a command-name token or with no match.
|
|
84
|
+
*/
|
|
82
85
|
trySyncSlashCompletion?(textBeforeCursor: string): {
|
|
83
86
|
items: AutocompleteItem[];
|
|
84
87
|
prefix: string;
|
package/src/autocomplete.ts
CHANGED
|
@@ -263,8 +263,11 @@ export interface AutocompleteProvider {
|
|
|
263
263
|
|
|
264
264
|
/** Get inline hint text to show as dim ghost text after the cursor */
|
|
265
265
|
getInlineHint?(lines: string[], cursorLine: number, cursorCol: number): string | null;
|
|
266
|
-
/**
|
|
267
|
-
|
|
266
|
+
/**
|
|
267
|
+
* Synchronously list slash command-name completions for a leading slash token (no async I/O).
|
|
268
|
+
* Mirrors the command-name branch of {@link getSuggestions}, including the bare `/` listing and
|
|
269
|
+
* the collapsed `/skill:` namespace row. Returns null outside a command-name token or with no match.
|
|
270
|
+
*/
|
|
268
271
|
trySyncSlashCompletion?(textBeforeCursor: string): { items: AutocompleteItem[]; prefix: string } | null;
|
|
269
272
|
/**
|
|
270
273
|
* Synchronously try to expand text immediately before the cursor (no async I/O).
|
|
@@ -589,6 +592,22 @@ function buildMidPromptSkillCompletions(commands: CommandEntry[], lowerPrefix: s
|
|
|
589
592
|
);
|
|
590
593
|
}
|
|
591
594
|
|
|
595
|
+
const DIR_CACHE_MAX = 100;
|
|
596
|
+
const DIR_CACHE_EVICT = 50;
|
|
597
|
+
|
|
598
|
+
/**
|
|
599
|
+
* Drops the `count` oldest entries once `map` exceeds `max`. Callers delete a
|
|
600
|
+
* key before re-setting it, so Map insertion order is refresh order.
|
|
601
|
+
*/
|
|
602
|
+
function evictOldest(map: Map<string, unknown>, max: number, count: number): void {
|
|
603
|
+
if (map.size <= max) return;
|
|
604
|
+
let remaining = count;
|
|
605
|
+
for (const key of map.keys()) {
|
|
606
|
+
if (remaining-- === 0) break;
|
|
607
|
+
map.delete(key);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
|
|
592
611
|
// Combined provider that handles both slash commands and file paths.
|
|
593
612
|
export class CombinedAutocompleteProvider implements AutocompleteProvider {
|
|
594
613
|
#commands: CommandEntry[];
|
|
@@ -598,6 +617,9 @@ export class CombinedAutocompleteProvider implements AutocompleteProvider {
|
|
|
598
617
|
// per-directory readdir fast-path for prefix completions. Global fuzzy
|
|
599
618
|
// discovery continues to use native fuzzyFind + shared scan cache.
|
|
600
619
|
#dirCache: Map<string, { entries: fs.Dirent[]; timestamp: number }> = new Map();
|
|
620
|
+
// Whether a scoped fuzzy query's base (`src/` in `@src/foo`) is a directory;
|
|
621
|
+
// stat'ing it on every keystroke is redundant while the base is unchanged.
|
|
622
|
+
#scopedBaseCache: Map<string, { isDirectory: boolean; timestamp: number }> = new Map();
|
|
601
623
|
readonly #DIR_CACHE_TTL = 2000; // 2 seconds
|
|
602
624
|
|
|
603
625
|
constructor(
|
|
@@ -806,7 +828,7 @@ export class CombinedAutocompleteProvider implements AutocompleteProvider {
|
|
|
806
828
|
};
|
|
807
829
|
}
|
|
808
830
|
|
|
809
|
-
// Slash command suggestions can be accepted before
|
|
831
|
+
// Slash command suggestions can be accepted before an async refresh
|
|
810
832
|
// catches up to newly typed characters. Replace the live command token,
|
|
811
833
|
// not only the prefix captured when the suggestion list was rendered.
|
|
812
834
|
// Absolute-path completions share the leading-slash prefix shape but
|
|
@@ -976,11 +998,21 @@ export class CombinedAutocompleteProvider implements AutocompleteProvider {
|
|
|
976
998
|
baseDir = path.join(this.#basePath, displayBase);
|
|
977
999
|
}
|
|
978
1000
|
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
1001
|
+
const now = Date.now();
|
|
1002
|
+
let cachedBase = this.#scopedBaseCache.get(baseDir);
|
|
1003
|
+
if (!cachedBase || now - cachedBase.timestamp >= this.#DIR_CACHE_TTL) {
|
|
1004
|
+
let isDirectory = false;
|
|
1005
|
+
try {
|
|
1006
|
+
isDirectory = (await fs.promises.stat(baseDir)).isDirectory();
|
|
1007
|
+
} catch {
|
|
1008
|
+
// Missing or inaccessible base: not a scope.
|
|
982
1009
|
}
|
|
983
|
-
|
|
1010
|
+
cachedBase = { isDirectory, timestamp: now };
|
|
1011
|
+
this.#scopedBaseCache.delete(baseDir);
|
|
1012
|
+
this.#scopedBaseCache.set(baseDir, cachedBase);
|
|
1013
|
+
evictOldest(this.#scopedBaseCache, DIR_CACHE_MAX, DIR_CACHE_EVICT);
|
|
1014
|
+
}
|
|
1015
|
+
if (!cachedBase.isDirectory) {
|
|
984
1016
|
return null;
|
|
985
1017
|
}
|
|
986
1018
|
|
|
@@ -1003,17 +1035,9 @@ export class CombinedAutocompleteProvider implements AutocompleteProvider {
|
|
|
1003
1035
|
}
|
|
1004
1036
|
|
|
1005
1037
|
const entries = await fs.promises.readdir(searchDir, { withFileTypes: true });
|
|
1038
|
+
this.#dirCache.delete(searchDir);
|
|
1006
1039
|
this.#dirCache.set(searchDir, { entries, timestamp: now });
|
|
1007
|
-
|
|
1008
|
-
if (this.#dirCache.size > 100) {
|
|
1009
|
-
const sortedKeys = [...this.#dirCache.entries()]
|
|
1010
|
-
.sort((a, b) => a[1].timestamp - b[1].timestamp)
|
|
1011
|
-
.slice(0, 50)
|
|
1012
|
-
.map(([key]) => key);
|
|
1013
|
-
for (const key of sortedKeys) {
|
|
1014
|
-
this.#dirCache.delete(key);
|
|
1015
|
-
}
|
|
1016
|
-
}
|
|
1040
|
+
evictOldest(this.#dirCache, DIR_CACHE_MAX, DIR_CACHE_EVICT);
|
|
1017
1041
|
|
|
1018
1042
|
return entries;
|
|
1019
1043
|
}
|
|
@@ -1021,8 +1045,10 @@ export class CombinedAutocompleteProvider implements AutocompleteProvider {
|
|
|
1021
1045
|
invalidateDirCache(dir?: string): void {
|
|
1022
1046
|
if (dir) {
|
|
1023
1047
|
this.#dirCache.delete(dir);
|
|
1048
|
+
this.#scopedBaseCache.delete(dir);
|
|
1024
1049
|
} else {
|
|
1025
1050
|
this.#dirCache.clear();
|
|
1051
|
+
this.#scopedBaseCache.clear();
|
|
1026
1052
|
}
|
|
1027
1053
|
}
|
|
1028
1054
|
|
|
@@ -1087,26 +1113,29 @@ export class CombinedAutocompleteProvider implements AutocompleteProvider {
|
|
|
1087
1113
|
const entries = await this.#getCachedDirEntries(searchDir);
|
|
1088
1114
|
const suggestions: AutocompleteItem[] = [];
|
|
1089
1115
|
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1116
|
+
const lowerSearchPrefix = searchPrefix.toLowerCase();
|
|
1117
|
+
// Skip .git directory
|
|
1118
|
+
const matched = entries.filter(
|
|
1119
|
+
entry => entry.name !== ".git" && entry.name.toLowerCase().startsWith(lowerSearchPrefix),
|
|
1120
|
+
);
|
|
1121
|
+
// Directory flag per match; symlinks are stat'ed concurrently to learn whether
|
|
1122
|
+
// they point at a directory. `null` drops a broken symlink, a file deleted
|
|
1123
|
+
// between readdir and stat, or a permission error.
|
|
1124
|
+
const directoryFlags = await Promise.all(
|
|
1125
|
+
matched.map(entry =>
|
|
1126
|
+
!entry.isDirectory() && entry.isSymbolicLink()
|
|
1127
|
+
? fs.promises.stat(path.join(searchDir, entry.name)).then(
|
|
1128
|
+
stats => stats.isDirectory(),
|
|
1129
|
+
() => null,
|
|
1130
|
+
)
|
|
1131
|
+
: entry.isDirectory(),
|
|
1132
|
+
),
|
|
1133
|
+
);
|
|
1098
1134
|
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
if (
|
|
1102
|
-
|
|
1103
|
-
const fullPath = path.join(searchDir, entry.name);
|
|
1104
|
-
isDirectory = (await fs.promises.stat(fullPath)).isDirectory();
|
|
1105
|
-
} catch {
|
|
1106
|
-
// Broken symlink, file deleted between readdir and stat, or permission error
|
|
1107
|
-
continue;
|
|
1108
|
-
}
|
|
1109
|
-
}
|
|
1135
|
+
for (let index = 0; index < matched.length; index++) {
|
|
1136
|
+
const isDirectory = directoryFlags[index];
|
|
1137
|
+
if (typeof isDirectory !== "boolean") continue;
|
|
1138
|
+
const entry = matched[index]!;
|
|
1110
1139
|
|
|
1111
1140
|
let relativePath: string;
|
|
1112
1141
|
const name = entry.name;
|
|
@@ -1300,19 +1329,14 @@ export class CombinedAutocompleteProvider implements AutocompleteProvider {
|
|
|
1300
1329
|
const slashStart = findLeadingSlashCommandStart(textBeforeCursor);
|
|
1301
1330
|
if (slashStart === null) return null;
|
|
1302
1331
|
const commandText = textBeforeCursor.slice(slashStart);
|
|
1303
|
-
if (commandText.length <= 1) return null; // Bare "/" alone, don't auto-complete
|
|
1304
1332
|
if (commandText.includes(" ")) return null; // Only complete command name, not args
|
|
1305
1333
|
|
|
1306
|
-
const
|
|
1307
|
-
const lowerPrefix = prefix.toLowerCase();
|
|
1308
|
-
|
|
1309
|
-
// The `/skill:` namespace row is excluded here: the sync path submits
|
|
1310
|
-
// immediately after applying, and the bare namespace is not a command.
|
|
1334
|
+
const lowerPrefix = commandText.slice(1).toLowerCase();
|
|
1311
1335
|
const matches = buildSlashCommandCompletions(
|
|
1312
1336
|
collapseSkillNamespace(this.#commands, lowerPrefix),
|
|
1313
1337
|
lowerPrefix,
|
|
1314
1338
|
this.#commandUsage,
|
|
1315
|
-
)
|
|
1339
|
+
);
|
|
1316
1340
|
|
|
1317
1341
|
if (matches.length === 0) return null;
|
|
1318
1342
|
// Mirror `getSuggestions`: preserve leading whitespace so the editor's
|