@oh-my-pi/pi-tui 18.13.2 → 18.14.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 +40 -54
- package/README.md +34 -34
- package/dist/types/app-keybindings.d.ts +15 -0
- package/dist/types/apps/session-picker.d.ts +5 -0
- package/dist/types/charts/chart-plan.d.ts +9 -7
- package/dist/types/chat/assistant-message.d.ts +15 -3
- package/dist/types/chat/bash-execution.d.ts +2 -0
- package/dist/types/chat/display-preferences.d.ts +2 -0
- package/dist/types/chat/extension-types.d.ts +31 -0
- package/dist/types/chat/reply-write.d.ts +48 -0
- package/dist/types/chat/table-chart.d.ts +4 -3
- package/dist/types/chat/tool-execution.d.ts +1 -2
- package/dist/types/chat/transcript-outline.d.ts +7 -0
- package/dist/types/chat/transcript-render-helpers.d.ts +2 -0
- package/dist/types/chrome/index.d.ts +1 -0
- package/dist/types/chrome/transcript-notice.d.ts +35 -0
- package/dist/types/chrome/transcript-status.d.ts +20 -8
- package/dist/types/components/editor.d.ts +8 -0
- package/dist/types/components/markdown.d.ts +7 -0
- package/dist/types/native/blobs.d.ts +2 -1
- package/dist/types/native/picker.d.ts +3 -3
- package/dist/types/overlays/annotation-overlay.d.ts +7 -1
- package/dist/types/overlays/annotation-types.d.ts +28 -0
- package/dist/types/overlays/login-dialog.d.ts +5 -1
- package/dist/types/overlays/model-browser.d.ts +10 -1
- package/dist/types/overlays/oauth-selector.d.ts +23 -0
- package/dist/types/overlays/plan-review-overlay.d.ts +2 -0
- package/dist/types/overlays/rewind-selector.d.ts +1 -1
- package/dist/types/overlays/session-selector.d.ts +22 -2
- package/dist/types/prompt/composer.d.ts +41 -4
- package/dist/types/prompt/interactive-context-helpers.d.ts +10 -3
- package/dist/types/prompt/welcome.d.ts +6 -2
- package/dist/types/render/extension-links.d.ts +65 -0
- package/dist/types/render/hyperlink.d.ts +25 -7
- package/dist/types/render/index.d.ts +1 -0
- package/dist/types/setup/scenes/model.d.ts +1 -1
- package/dist/types/setup/scenes/outro.d.ts +5 -4
- package/dist/types/setup/scenes/sign-in.d.ts +13 -8
- package/dist/types/setup/scenes/splash.d.ts +4 -4
- package/dist/types/setup/scenes/types.d.ts +16 -1
- package/dist/types/setup/startup-splash.d.ts +1 -1
- package/dist/types/setup/wizard-overlay.d.ts +11 -7
- package/dist/types/setup/wizard.d.ts +5 -1
- package/dist/types/status-line/component.d.ts +1 -1
- package/dist/types/status-line/context-usage.d.ts +28 -6
- package/dist/types/status-line/host.d.ts +6 -2
- package/dist/types/theme/theme.d.ts +0 -23
- package/dist/types/tools/bash-interactive.d.ts +6 -0
- package/dist/types/tools/bash.d.ts +2 -0
- package/dist/types/tools/default-renderer.d.ts +6 -4
- package/dist/types/tools/irc.d.ts +6 -0
- package/dist/types/tools/json-tree.d.ts +23 -4
- package/dist/types/tools/lsp.d.ts +2 -0
- package/dist/types/tools/mcp.d.ts +6 -5
- package/dist/types/tools/native-view.d.ts +1 -1
- package/dist/types/tools/renderer.d.ts +2 -0
- package/dist/types/tools/streaming-output.d.ts +11 -0
- package/dist/types/tools/task.d.ts +9 -1
- package/dist/types/tools/url-scheme-host.d.ts +17 -0
- package/dist/types/tools/yield.d.ts +1 -1
- package/dist/types/tui.d.ts +7 -2
- package/package.json +10 -15
- package/src/app-keybindings.ts +15 -0
- package/src/apps/session-picker.ts +7 -0
- package/src/charts/chart-plan.ts +20 -50
- package/src/chat/advisor-message.ts +2 -0
- package/src/chat/assistant-message.ts +137 -19
- package/src/chat/background-tan-message.ts +4 -0
- package/src/chat/bash-execution.ts +6 -0
- package/src/chat/chat-transcript-builder.ts +58 -28
- package/src/chat/compaction-summary-message.ts +2 -1
- package/src/chat/display-preferences.ts +3 -0
- package/src/chat/extension-types.ts +34 -0
- package/src/chat/reply-write.ts +127 -0
- package/src/chat/table-chart.ts +10 -4
- package/src/chat/tool-execution.ts +20 -13
- package/src/chat/transcript-outline.ts +27 -0
- package/src/chat/transcript-render-helpers.ts +66 -24
- package/src/chrome/index.ts +1 -0
- package/src/chrome/transcript-notice.ts +83 -0
- package/src/chrome/transcript-status.ts +29 -29
- package/src/components/editor.ts +10 -1
- package/src/components/markdown.ts +116 -6
- package/src/hotkeys-markdown.ts +1 -0
- package/src/native/backend.ts +5 -66
- package/src/native/blobs.ts +3 -2
- package/src/native/picker.ts +3 -3
- package/src/overlays/advisor-config.ts +1 -10
- package/src/overlays/annotation-overlay.ts +125 -37
- package/src/overlays/annotation-types.ts +24 -0
- package/src/overlays/hook-selector.ts +2 -2
- package/src/overlays/login-dialog.ts +31 -5
- package/src/overlays/model-browser.ts +37 -0
- package/src/overlays/model-hub.ts +1 -7
- package/src/overlays/model-picker.ts +1 -10
- package/src/overlays/oauth-selector.ts +44 -6
- package/src/overlays/plan-review-overlay.ts +13 -2
- package/src/overlays/rewind-selector.ts +29 -12
- package/src/overlays/session-selector.ts +305 -39
- package/src/overlays/usage-dashboard.ts +5 -12
- package/src/prompt/composer.ts +213 -5
- package/src/prompt/custom-editor.ts +6 -1
- package/src/prompt/emoji-autocomplete.ts +0 -2
- package/src/prompt/interactive-context-helpers.ts +29 -4
- package/src/prompt/welcome.ts +31 -45
- package/src/render/extension-links.ts +214 -0
- package/src/render/hyperlink.ts +65 -9
- package/src/render/index.ts +1 -0
- package/src/setup/scenes/composer.ts +2 -0
- package/src/setup/scenes/glyph.ts +2 -0
- package/src/setup/scenes/model.ts +192 -29
- package/src/setup/scenes/outro.ts +30 -17
- package/src/setup/scenes/sign-in.ts +196 -400
- package/src/setup/scenes/splash.ts +25 -21
- package/src/setup/scenes/theme.ts +2 -0
- package/src/setup/scenes/types.ts +18 -1
- package/src/setup/startup-splash.ts +8 -7
- package/src/setup/wizard-overlay.ts +164 -33
- package/src/setup/wizard.ts +11 -2
- package/src/status-line/component.ts +4 -10
- package/src/status-line/context-usage.ts +72 -21
- package/src/status-line/host.ts +6 -2
- package/src/terminal.ts +24 -2
- package/src/theme/defaults.json +1 -0
- package/src/theme/loader.ts +1 -1
- package/src/theme/theme.ts +2 -75
- package/src/tools/bash-interactive.ts +6 -1
- package/src/tools/bash.ts +2 -0
- package/src/tools/default-renderer.ts +9 -6
- package/src/tools/eval.ts +14 -4
- package/src/tools/irc.ts +6 -0
- package/src/tools/job-widget.ts +13 -1
- package/src/tools/json-tree.ts +132 -42
- package/src/tools/lsp.ts +36 -15
- package/src/tools/mcp.ts +20 -12
- package/src/tools/native-view.ts +1 -1
- package/src/tools/renderer.ts +2 -0
- package/src/tools/streaming-output.ts +41 -0
- package/src/tools/task.ts +59 -17
- package/src/tools/url-scheme-host.ts +21 -0
- package/src/tools/yield.ts +18 -9
- package/src/tui.ts +43 -15
- package/THIRD-PARTY-NOTICES.txt +0 -22901
- package/dist/types/theme/defaults/index.d.ts +0 -10289
- package/src/theme/defaults/alabaster.json +0 -103
- package/src/theme/defaults/amethyst.json +0 -106
- package/src/theme/defaults/anthracite.json +0 -103
- package/src/theme/defaults/basalt.json +0 -101
- package/src/theme/defaults/birch.json +0 -105
- package/src/theme/defaults/dark-abyss.json +0 -101
- package/src/theme/defaults/dark-arctic.json +0 -114
- package/src/theme/defaults/dark-aurora.json +0 -105
- package/src/theme/defaults/dark-catppuccin.json +0 -117
- package/src/theme/defaults/dark-cavern.json +0 -101
- package/src/theme/defaults/dark-celestial.json +0 -116
- package/src/theme/defaults/dark-copper.json +0 -105
- package/src/theme/defaults/dark-cosmos.json +0 -100
- package/src/theme/defaults/dark-cyberpunk.json +0 -112
- package/src/theme/defaults/dark-dracula.json +0 -108
- package/src/theme/defaults/dark-eclipse.json +0 -101
- package/src/theme/defaults/dark-ember.json +0 -105
- package/src/theme/defaults/dark-equinox.json +0 -100
- package/src/theme/defaults/dark-forest.json +0 -106
- package/src/theme/defaults/dark-github.json +0 -115
- package/src/theme/defaults/dark-gruvbox.json +0 -122
- package/src/theme/defaults/dark-lavender.json +0 -105
- package/src/theme/defaults/dark-lunar.json +0 -99
- package/src/theme/defaults/dark-midnight.json +0 -105
- package/src/theme/defaults/dark-monochrome.json +0 -104
- package/src/theme/defaults/dark-monokai.json +0 -108
- package/src/theme/defaults/dark-nebula.json +0 -100
- package/src/theme/defaults/dark-neon-noir.json +0 -110
- package/src/theme/defaults/dark-nord.json +0 -108
- package/src/theme/defaults/dark-ocean.json +0 -111
- package/src/theme/defaults/dark-one.json +0 -110
- package/src/theme/defaults/dark-poimandres.json +0 -125
- package/src/theme/defaults/dark-rainforest.json +0 -101
- package/src/theme/defaults/dark-reef.json +0 -101
- package/src/theme/defaults/dark-retro.json +0 -102
- package/src/theme/defaults/dark-rose-pine.json +0 -106
- package/src/theme/defaults/dark-sakura.json +0 -105
- package/src/theme/defaults/dark-slate.json +0 -105
- package/src/theme/defaults/dark-solarized.json +0 -107
- package/src/theme/defaults/dark-solstice.json +0 -100
- package/src/theme/defaults/dark-starfall.json +0 -101
- package/src/theme/defaults/dark-sunset.json +0 -109
- package/src/theme/defaults/dark-swamp.json +0 -100
- package/src/theme/defaults/dark-synthwave.json +0 -113
- package/src/theme/defaults/dark-taiga.json +0 -101
- package/src/theme/defaults/dark-terminal.json +0 -105
- package/src/theme/defaults/dark-tokyo-night.json +0 -111
- package/src/theme/defaults/dark-tundra.json +0 -101
- package/src/theme/defaults/dark-twilight.json +0 -101
- package/src/theme/defaults/dark-volcanic.json +0 -101
- package/src/theme/defaults/graphite.json +0 -102
- package/src/theme/defaults/index.ts +0 -203
- package/src/theme/defaults/light-arctic.json +0 -117
- package/src/theme/defaults/light-aurora-day.json +0 -101
- package/src/theme/defaults/light-canyon.json +0 -101
- package/src/theme/defaults/light-catppuccin.json +0 -116
- package/src/theme/defaults/light-cirrus.json +0 -100
- package/src/theme/defaults/light-coral.json +0 -105
- package/src/theme/defaults/light-cyberpunk.json +0 -106
- package/src/theme/defaults/light-dawn.json +0 -100
- package/src/theme/defaults/light-dunes.json +0 -101
- package/src/theme/defaults/light-eucalyptus.json +0 -105
- package/src/theme/defaults/light-forest.json +0 -110
- package/src/theme/defaults/light-frost.json +0 -105
- package/src/theme/defaults/light-github.json +0 -125
- package/src/theme/defaults/light-glacier.json +0 -101
- package/src/theme/defaults/light-gruvbox.json +0 -118
- package/src/theme/defaults/light-haze.json +0 -100
- package/src/theme/defaults/light-honeycomb.json +0 -105
- package/src/theme/defaults/light-lagoon.json +0 -101
- package/src/theme/defaults/light-lavender.json +0 -105
- package/src/theme/defaults/light-meadow.json +0 -101
- package/src/theme/defaults/light-mint.json +0 -105
- package/src/theme/defaults/light-monochrome.json +0 -111
- package/src/theme/defaults/light-ocean.json +0 -109
- package/src/theme/defaults/light-one.json +0 -109
- package/src/theme/defaults/light-opal.json +0 -101
- package/src/theme/defaults/light-orchard.json +0 -101
- package/src/theme/defaults/light-paper.json +0 -105
- package/src/theme/defaults/light-poimandres.json +0 -125
- package/src/theme/defaults/light-prism.json +0 -100
- package/src/theme/defaults/light-retro.json +0 -108
- package/src/theme/defaults/light-sand.json +0 -105
- package/src/theme/defaults/light-savanna.json +0 -101
- package/src/theme/defaults/light-solarized.json +0 -112
- package/src/theme/defaults/light-soleil.json +0 -100
- package/src/theme/defaults/light-sunset.json +0 -109
- package/src/theme/defaults/light-synthwave.json +0 -108
- package/src/theme/defaults/light-tokyo-night.json +0 -121
- package/src/theme/defaults/light-wetland.json +0 -101
- package/src/theme/defaults/light-zenith.json +0 -99
- package/src/theme/defaults/limestone.json +0 -104
- package/src/theme/defaults/mahogany.json +0 -107
- package/src/theme/defaults/marble.json +0 -103
- package/src/theme/defaults/obsidian.json +0 -101
- package/src/theme/defaults/onyx.json +0 -101
- package/src/theme/defaults/pearl.json +0 -103
- package/src/theme/defaults/porcelain.json +0 -101
- package/src/theme/defaults/quartz.json +0 -106
- package/src/theme/defaults/sandstone.json +0 -105
- package/src/theme/defaults/titanium.json +0 -100
|
@@ -42,6 +42,7 @@ import type {
|
|
|
42
42
|
TspPickerGroup,
|
|
43
43
|
TspPickerItem,
|
|
44
44
|
TspPickerMark,
|
|
45
|
+
TspPickerProps,
|
|
45
46
|
TspSpan,
|
|
46
47
|
TspText,
|
|
47
48
|
} from "@oh-my-pi/pi-wire";
|
|
@@ -918,6 +919,22 @@ export interface ModelPickerCatalogue {
|
|
|
918
919
|
readonly itemsDel?: readonly string[];
|
|
919
920
|
}
|
|
920
921
|
|
|
922
|
+
/** The search, fact-column and row props every model `picker` sheet sends ({@link ModelBrowser.pickerRows}). */
|
|
923
|
+
export type ModelPickerRows = Pick<
|
|
924
|
+
TspPickerProps,
|
|
925
|
+
| "query"
|
|
926
|
+
| "cursor"
|
|
927
|
+
| "columns"
|
|
928
|
+
| "items"
|
|
929
|
+
| "itemsAdd"
|
|
930
|
+
| "itemsDel"
|
|
931
|
+
| "order"
|
|
932
|
+
| "hits"
|
|
933
|
+
| "selected"
|
|
934
|
+
| "current"
|
|
935
|
+
| "total"
|
|
936
|
+
>;
|
|
937
|
+
|
|
921
938
|
/** How {@link ModelBrowser.pickerOrder} heads its rows. */
|
|
922
939
|
export interface ModelPickerGrouping {
|
|
923
940
|
/** One group per provider after the Recent block (the unfiltered All models view). */
|
|
@@ -1933,6 +1950,26 @@ export class ModelBrowser implements Component {
|
|
|
1933
1950
|
return selected && !this.#isDisabled(selected) ? selected.selector : null;
|
|
1934
1951
|
}
|
|
1935
1952
|
|
|
1953
|
+
/**
|
|
1954
|
+
* A model picker's search field, fact columns and rows: `catalogue` (from
|
|
1955
|
+
* {@link pickerItems}) in `view` order (from {@link pickerOrder}), the
|
|
1956
|
+
* selection, and `current` checked. Memoize hosts on its inputs plus
|
|
1957
|
+
* {@link query}, {@link cursor} and {@link pickerSelected}.
|
|
1958
|
+
*/
|
|
1959
|
+
pickerRows(catalogue: ModelPickerCatalogue, view: ModelPickerOrder, current: string | undefined): ModelPickerRows {
|
|
1960
|
+
return {
|
|
1961
|
+
query: this.query,
|
|
1962
|
+
cursor: this.cursor,
|
|
1963
|
+
columns: MODEL_PICKER_COLUMNS,
|
|
1964
|
+
...catalogue,
|
|
1965
|
+
order: view.order,
|
|
1966
|
+
...(view.hits ? { hits: view.hits } : {}),
|
|
1967
|
+
selected: this.pickerSelected,
|
|
1968
|
+
...(current ? { current: [current] } : {}),
|
|
1969
|
+
total: this.baseCount,
|
|
1970
|
+
};
|
|
1971
|
+
}
|
|
1972
|
+
|
|
1936
1973
|
/**
|
|
1937
1974
|
* Picker rows for `catalogue`: the same object while the catalogue, roles
|
|
1938
1975
|
* and row inputs are unchanged, so typing and scope hops never resend it.
|
|
@@ -3370,13 +3370,7 @@ export class ModelHubComponent implements Component {
|
|
|
3370
3370
|
...props,
|
|
3371
3371
|
tabs: this.#pickerKindTabs(),
|
|
3372
3372
|
tab: this.#modelKindTab,
|
|
3373
|
-
|
|
3374
|
-
...catalogue,
|
|
3375
|
-
order: view.order,
|
|
3376
|
-
...(view.hits ? { hits: view.hits } : {}),
|
|
3377
|
-
selected: this.#browser.pickerSelected,
|
|
3378
|
-
...(current ? { current } : {}),
|
|
3379
|
-
total: this.#browser.baseCount,
|
|
3373
|
+
...this.#browser.pickerRows(catalogue, view, this.#currentSelector),
|
|
3380
3374
|
state,
|
|
3381
3375
|
...(state === "error" && this.#configError ? { message: this.#configError } : {}),
|
|
3382
3376
|
empty:
|
|
@@ -11,7 +11,6 @@ import type { Component, TUI } from "../tui";
|
|
|
11
11
|
import { type ThemeColor, theme } from "../theme/theme";
|
|
12
12
|
import {
|
|
13
13
|
buildSessionModelScope,
|
|
14
|
-
MODEL_PICKER_COLUMNS,
|
|
15
14
|
ModelBrowser,
|
|
16
15
|
type ModelBrowserItem,
|
|
17
16
|
type ModelPickerCatalogue,
|
|
@@ -424,17 +423,9 @@ export class ModelPickerComponent implements Component {
|
|
|
424
423
|
size: "md",
|
|
425
424
|
layout: "rows",
|
|
426
425
|
preview: "below",
|
|
427
|
-
query,
|
|
428
|
-
cursor,
|
|
429
426
|
placeholder:
|
|
430
427
|
mode === "task" || mode === "selection" ? "Search models…" : "Search models, @ for quick roles…",
|
|
431
|
-
|
|
432
|
-
...catalogue,
|
|
433
|
-
order: view.order,
|
|
434
|
-
...(view.hits ? { hits: view.hits } : {}),
|
|
435
|
-
selected,
|
|
436
|
-
...(current ? { current: [current] } : {}),
|
|
437
|
-
total: this.#browser.baseCount,
|
|
428
|
+
...this.#browser.pickerRows(catalogue, view, current),
|
|
438
429
|
empty: mode === "role" ? `No quick roles in the ${cycleKey} cycle` : "No models available",
|
|
439
430
|
actions: compact([
|
|
440
431
|
pickerAction(
|
|
@@ -17,7 +17,7 @@ import { OverlayPanel } from "../chrome/overlay-box";
|
|
|
17
17
|
import { Input } from "../components/input";
|
|
18
18
|
import { MenuSelection } from "../components/menu-selection";
|
|
19
19
|
import { centeredViewportRange } from "../components/scroll-viewport";
|
|
20
|
-
import type { TspPickerItem, TspSpan, TspTone } from "@oh-my-pi/pi-wire";
|
|
20
|
+
import type { TspPickerAction, TspPickerItem, TspSpan, TspText, TspTone } from "@oh-my-pi/pi-wire";
|
|
21
21
|
import { node, span, text } from "../native/describe";
|
|
22
22
|
import type { DescribeContext, NativeNode, NativeUiEvent } from "../native/node";
|
|
23
23
|
import { CLOSE_ACTION, dockedPicker, PICKER_KEY, pickerAction, pickerEvent, pickerQuery } from "../native/picker";
|
|
@@ -32,6 +32,21 @@ export interface OAuthSelectorAuthSource {
|
|
|
32
32
|
readonly keys: Pick<KeysApi, "source">;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
/**
|
|
36
|
+
* How a host other than `/login` presents the native provider sheet (the
|
|
37
|
+
* setup wizard): its heading, `role` and size, a status line docked above the
|
|
38
|
+
* action bar, and the Esc action that leaves in place of Close (the action's
|
|
39
|
+
* `id` cancels like Esc).
|
|
40
|
+
*/
|
|
41
|
+
export interface OAuthSelectorSheet {
|
|
42
|
+
readonly title: string;
|
|
43
|
+
readonly subtitle: TspText;
|
|
44
|
+
readonly role: string;
|
|
45
|
+
readonly size: "md" | "lg";
|
|
46
|
+
readonly status?: TspText;
|
|
47
|
+
readonly leave: { readonly id: string; readonly label: string };
|
|
48
|
+
}
|
|
49
|
+
|
|
35
50
|
/**
|
|
36
51
|
* Rendered lines before the provider rows: top border
|
|
37
52
|
* (must mirror the constructor's addChild order).
|
|
@@ -80,6 +95,7 @@ export class OAuthSelectorComponent extends OverlayPanel {
|
|
|
80
95
|
/** Picker rows for the whole catalogue; dropped when an auth state changes. */
|
|
81
96
|
#pickerItems: readonly TspPickerItem[] | undefined;
|
|
82
97
|
#pickerRoot: NativeNode | undefined;
|
|
98
|
+
#sheet: OAuthSelectorSheet | undefined;
|
|
83
99
|
constructor(
|
|
84
100
|
mode: "login" | "logout",
|
|
85
101
|
authStorage: OAuthSelectorAuthSource,
|
|
@@ -89,6 +105,7 @@ export class OAuthSelectorComponent extends OverlayPanel {
|
|
|
89
105
|
disabledProviders?: readonly string[];
|
|
90
106
|
validateAuth?: (providerId: string) => Promise<boolean>;
|
|
91
107
|
requestRender?: () => void;
|
|
108
|
+
sheet?: OAuthSelectorSheet;
|
|
92
109
|
},
|
|
93
110
|
) {
|
|
94
111
|
super(mode === "login" ? "Select provider to login" : "Select provider to logout", "omp.overlay.oauth");
|
|
@@ -98,6 +115,7 @@ export class OAuthSelectorComponent extends OverlayPanel {
|
|
|
98
115
|
this.#onCancelCallback = onCancel;
|
|
99
116
|
this.#validateAuthCallback = options?.validateAuth;
|
|
100
117
|
this.#requestRenderCallback = options?.requestRender;
|
|
118
|
+
this.#sheet = options?.sheet;
|
|
101
119
|
this.#menu = new MenuSelection<OAuthProviderInfo>([], {
|
|
102
120
|
getKey: provider => provider.id,
|
|
103
121
|
getSearchText: provider => this.#getProviderSearchText(provider),
|
|
@@ -117,6 +135,20 @@ export class OAuthSelectorComponent extends OverlayPanel {
|
|
|
117
135
|
this.#stopSpinner();
|
|
118
136
|
}
|
|
119
137
|
|
|
138
|
+
/** Replace the native sheet's presentation (a new outcome line, a relabelled leave action). */
|
|
139
|
+
setSheet(sheet: OAuthSelectorSheet): void {
|
|
140
|
+
this.#sheet = sheet;
|
|
141
|
+
this.#pickerRoot = undefined;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/** Re-read credential state after a sign-in stored one, keeping the query and selection. */
|
|
145
|
+
refreshAuth(): void {
|
|
146
|
+
this.#nativeItems = undefined;
|
|
147
|
+
this.#pickerItems = undefined;
|
|
148
|
+
this.#menu.setItems(this.#menu.items);
|
|
149
|
+
this.#updateList();
|
|
150
|
+
}
|
|
151
|
+
|
|
120
152
|
/**
|
|
121
153
|
* Fit the selector into `lines` rendered rows by shrinking the visible list
|
|
122
154
|
* window (the window is centered on the selection, so the selected row is
|
|
@@ -504,12 +536,17 @@ export class OAuthSelectorComponent extends OverlayPanel {
|
|
|
504
536
|
const query = this.#menu.query;
|
|
505
537
|
const login = this.#mode === "login";
|
|
506
538
|
const search = this.#shouldRenderSearchStatus() ? pickerQuery(this.#search) : pickerQuery(null);
|
|
539
|
+
const sheet = this.#sheet;
|
|
540
|
+
const leave: TspPickerAction = sheet
|
|
541
|
+
? pickerAction(sheet.leave.id, sheet.leave.label, "escape", { end: true })
|
|
542
|
+
: CLOSE_ACTION;
|
|
507
543
|
this.#pickerRoot = dockedPicker({
|
|
508
|
-
|
|
509
|
-
|
|
544
|
+
...(sheet ? { role: sheet.role } : {}),
|
|
545
|
+
title: sheet?.title ?? (login ? "Sign in" : "Sign out"),
|
|
546
|
+
subtitle: sheet?.subtitle ?? (login ? "Pick a provider" : "Remove stored credentials"),
|
|
510
547
|
icon: "key-round",
|
|
511
548
|
noun: "providers",
|
|
512
|
-
size: "md",
|
|
549
|
+
size: sheet?.size ?? "md",
|
|
513
550
|
layout: "cards",
|
|
514
551
|
preview: "none",
|
|
515
552
|
...search,
|
|
@@ -520,6 +557,7 @@ export class OAuthSelectorComponent extends OverlayPanel {
|
|
|
520
557
|
total: all.length,
|
|
521
558
|
empty: login ? "No OAuth providers available" : "No stored provider credentials to log out",
|
|
522
559
|
...(this.#statusMessage ? { message: this.#statusMessage } : {}),
|
|
560
|
+
...(sheet?.status ? { strip: { label: sheet.status, items: [] } } : {}),
|
|
523
561
|
actions: [
|
|
524
562
|
pickerAction(
|
|
525
563
|
"confirm",
|
|
@@ -527,7 +565,7 @@ export class OAuthSelectorComponent extends OverlayPanel {
|
|
|
527
565
|
"enter",
|
|
528
566
|
login ? { primary: true } : { primary: true, danger: true },
|
|
529
567
|
),
|
|
530
|
-
|
|
568
|
+
leave,
|
|
531
569
|
],
|
|
532
570
|
});
|
|
533
571
|
return this.#pickerRoot;
|
|
@@ -596,7 +634,7 @@ export class OAuthSelectorComponent extends OverlayPanel {
|
|
|
596
634
|
else if (ev.act === "clear") {
|
|
597
635
|
this.#search.setValue("");
|
|
598
636
|
this.#syncSearchQuery();
|
|
599
|
-
} else if (ev.act === "close" || ev.act === "cancel") {
|
|
637
|
+
} else if (ev.act === "close" || ev.act === "cancel" || ev.act === this.#sheet?.leave.id) {
|
|
600
638
|
this.stopValidation();
|
|
601
639
|
this.#onCancelCallback();
|
|
602
640
|
}
|
|
@@ -256,6 +256,8 @@ export interface PlanReviewOverlayOptions {
|
|
|
256
256
|
slider?: HookSelectorSlider;
|
|
257
257
|
/** Display label for the external-editor key, surfaced in the footer help. */
|
|
258
258
|
externalEditorLabel?: string;
|
|
259
|
+
/** The external editor's name ("Notepad", "nvim") for the native Edit button; `$EDITOR` when unset. */
|
|
260
|
+
externalEditorName?: string;
|
|
259
261
|
/** Serializable annotations restored into this overlay instance. */
|
|
260
262
|
annotationState?: PlanReviewAnnotationState;
|
|
261
263
|
}
|
|
@@ -286,6 +288,7 @@ export class PlanReviewOverlay implements Component {
|
|
|
286
288
|
#disabled: Set<number>;
|
|
287
289
|
#helpSuffix: string | undefined;
|
|
288
290
|
#externalEditorLabel: string | undefined;
|
|
291
|
+
#externalEditorName: string | undefined;
|
|
289
292
|
#promptTitle: string | undefined;
|
|
290
293
|
#selectedIndex: number;
|
|
291
294
|
#slider: HookSelectorSlider | undefined;
|
|
@@ -354,6 +357,7 @@ export class PlanReviewOverlay implements Component {
|
|
|
354
357
|
);
|
|
355
358
|
this.#helpSuffix = options.helpText;
|
|
356
359
|
this.#externalEditorLabel = options.externalEditorLabel;
|
|
360
|
+
this.#externalEditorName = options.externalEditorName;
|
|
357
361
|
this.#promptTitle = options.promptTitle;
|
|
358
362
|
this.#selectedIndex = this.#coerceIndex(options.initialIndex ?? 0);
|
|
359
363
|
if (options.slider && options.slider.segments.length > 0) {
|
|
@@ -1632,7 +1636,13 @@ export class PlanReviewOverlay implements Component {
|
|
|
1632
1636
|
// Unbound: the button still mirrors the callback, without a keycap.
|
|
1633
1637
|
const editorKeyId = getKeybindings().getKeys("app.editor.external")[0];
|
|
1634
1638
|
if (this.callbacks.onExternalEditor) {
|
|
1635
|
-
buttons.push(
|
|
1639
|
+
buttons.push(
|
|
1640
|
+
actionButton(
|
|
1641
|
+
`Edit in ${this.#externalEditorName ?? "$EDITOR"}`,
|
|
1642
|
+
"externalEditor",
|
|
1643
|
+
editorKeyId ? { keys: editorKeyId } : {},
|
|
1644
|
+
),
|
|
1645
|
+
);
|
|
1636
1646
|
}
|
|
1637
1647
|
// Cancel the review the way the cancel key does; while annotating that key
|
|
1638
1648
|
// only leaves the draft/chooser, so the button is hidden there.
|
|
@@ -1754,7 +1764,8 @@ export class PlanReviewOverlay implements Component {
|
|
|
1754
1764
|
"tabs",
|
|
1755
1765
|
);
|
|
1756
1766
|
const track: NativeChild[] = slider.caption ? [text([span(slider.caption, "dim")]), tabs] : [tabs];
|
|
1757
|
-
|
|
1767
|
+
// A role of its own: Tern's sheet lets only the role-less split row (Contents + body) shrink and scroll.
|
|
1768
|
+
const out = [keyed(rowNode(track, { role: "omp.plan.slider", gap: "sm", align: "center" }), "slider")];
|
|
1758
1769
|
const detail = slider.segments[this.#sliderIndex]?.detail;
|
|
1759
1770
|
if (detail) out.push(keyed(text([span("↳ ", "dim"), span(detail, "muted")], { wrap: "word" }), "sliderDetail"));
|
|
1760
1771
|
return out;
|
|
@@ -46,7 +46,11 @@ import { recentTranscriptEntries, type TranscriptEntryLike as TranscriptEntry }
|
|
|
46
46
|
import { theme } from "../theme/theme";
|
|
47
47
|
import { matchesAppToolsExpand, matchesSelectCancel, matchesSelectDown, matchesSelectUp } from "../keybinding-matchers";
|
|
48
48
|
import { ChatTranscriptBuilder } from "../chat/chat-transcript-builder";
|
|
49
|
-
import {
|
|
49
|
+
import {
|
|
50
|
+
nearestVisibleOutlineTarget,
|
|
51
|
+
TranscriptBrowser,
|
|
52
|
+
type TranscriptBrowserFrame,
|
|
53
|
+
} from "../chat/transcript-browser";
|
|
50
54
|
import { padToWidth } from "../render/utils";
|
|
51
55
|
import { expandKeyHint } from "../render/render-utils";
|
|
52
56
|
import { formatKeyHint, formatKeyHints } from "../app-keybindings";
|
|
@@ -55,6 +59,7 @@ import {
|
|
|
55
59
|
appendOutlineEntries,
|
|
56
60
|
type ComposedColumn,
|
|
57
61
|
composeOutlineColumn,
|
|
62
|
+
describedVisibility,
|
|
58
63
|
type OutlineTarget,
|
|
59
64
|
isUserTurnEntry,
|
|
60
65
|
outlineVisibility,
|
|
@@ -682,6 +687,21 @@ export class RewindSelectorComponent implements Component {
|
|
|
682
687
|
return this.#mainVisible?.[index] ?? true;
|
|
683
688
|
}
|
|
684
689
|
|
|
690
|
+
/**
|
|
691
|
+
* Adopt the main path's per-target visibility. A selection on a target
|
|
692
|
+
* that shows nothing (the empty turn an interrupt leaves last, a turn the
|
|
693
|
+
* expansion toggle collapsed) moves to the nearest one that shows and
|
|
694
|
+
* leaves the strip.
|
|
695
|
+
*/
|
|
696
|
+
#adoptVisibility(visible: boolean[]): void {
|
|
697
|
+
this.#mainVisible = visible;
|
|
698
|
+
const selected = nearestVisibleOutlineTarget(visible, this.#selected);
|
|
699
|
+
if (selected === this.#selected) return;
|
|
700
|
+
this.#selected = selected;
|
|
701
|
+
this.#activeVariant = 0;
|
|
702
|
+
this.#siblingSelected = 0;
|
|
703
|
+
}
|
|
704
|
+
|
|
685
705
|
// ========================================================================
|
|
686
706
|
// Native: the transcript as a page
|
|
687
707
|
// ========================================================================
|
|
@@ -694,12 +714,13 @@ export class RewindSelectorComponent implements Component {
|
|
|
694
714
|
* of branch columns, the current path first. The bar is this component's
|
|
695
715
|
* own node, docked under the page, so the filter field keeps the caret.
|
|
696
716
|
*/
|
|
697
|
-
describeScreen(
|
|
698
|
-
|
|
717
|
+
describeScreen(cx: DescribeContext): NativeScreen {
|
|
718
|
+
this.#adoptVisibility(describedVisibility(this.#builder.container.children, this.#targets, cx));
|
|
719
|
+
return { role: "omp.rewind", main: this.#page(cx), dock: [this] };
|
|
699
720
|
}
|
|
700
721
|
|
|
701
722
|
/** The page's blocks, marked for the current outline. */
|
|
702
|
-
#page(): NativeChild[] {
|
|
723
|
+
#page(cx: DescribeContext): NativeChild[] {
|
|
703
724
|
const blocks = this.#builder.container.children;
|
|
704
725
|
const page: NativeChild[] = [];
|
|
705
726
|
const filter = this.#filter;
|
|
@@ -741,6 +762,9 @@ export class RewindSelectorComponent implements Component {
|
|
|
741
762
|
for (let index = 0; index < columns.length; index++) {
|
|
742
763
|
const column = columns[index]!;
|
|
743
764
|
const active = this.#activeVariant === index + 1;
|
|
765
|
+
if (active) {
|
|
766
|
+
this.#siblingVisible = describedVisibility(column.builder.container.children, column.targets, cx);
|
|
767
|
+
}
|
|
744
768
|
const children: NativeChild[] = [this.#columnHead(index + 1, count, column.label)];
|
|
745
769
|
const picked = active ? this.#siblingSelected : -1;
|
|
746
770
|
this.#markRun(children, column.builder.container.children, 0, column.targets, picked, column.rootId);
|
|
@@ -900,15 +924,8 @@ export class RewindSelectorComponent implements Component {
|
|
|
900
924
|
// rows a matching two-column left gutter so blocks never shift while stepping.
|
|
901
925
|
const children = this.#builder.container.children;
|
|
902
926
|
const prepared = this.#browser.prepareOutline(children, this.#targets, this.#selected, contentWidth);
|
|
903
|
-
this.#mainVisible = prepared.visible;
|
|
904
927
|
this.#mainRows = prepared.childRows;
|
|
905
|
-
|
|
906
|
-
// The current target collapsed (e.g. expansion toggle): rest on the
|
|
907
|
-
// nearest visible one and leave the strip.
|
|
908
|
-
this.#selected = prepared.selected;
|
|
909
|
-
this.#activeVariant = 0;
|
|
910
|
-
this.#siblingSelected = 0;
|
|
911
|
-
}
|
|
928
|
+
this.#adoptVisibility(prepared.visible);
|
|
912
929
|
|
|
913
930
|
if (this.#filter !== undefined) return this.#filterFrame(this.#filter, prepared.childRows, contentWidth);
|
|
914
931
|
|