@timurproko/a1 0.1.8-dev.512 → 0.1.8-dev.521
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/README.md +64 -20
- package/dist/app/session-shell/index.d.ts +1 -1
- package/dist/app/session-shell/prompt-suggestion-controller.d.ts +2 -0
- package/dist/app/session-shell/prompt-suggestion-controller.js +12 -0
- package/dist/app/session-shell/session-shell-root.d.ts +10 -0
- package/dist/app/session-shell/session-shell-root.js +12 -2
- package/dist/app/session-shell/session-shell.d.ts +8 -1
- package/dist/app/session-shell/session-shell.js +217 -18
- package/dist/composition/index.d.ts +1 -1
- package/dist/composition/owned-ui.js +21 -3
- package/dist/composition/settings-route-host.d.ts +17 -4
- package/dist/composition/settings-route-host.js +47 -16
- package/dist/contracts/owned-ui/index.d.ts +1 -1
- package/dist/contracts/owned-ui/model.d.ts +1 -5
- package/dist/features/owned-ui/index.d.ts +3 -0
- package/dist/features/owned-ui/index.js +2 -0
- package/dist/features/owned-ui/reference-routes.d.ts +6 -0
- package/dist/features/owned-ui/reference-routes.js +6 -0
- package/dist/features/owned-ui/reference-screen-app.d.ts +37 -0
- package/dist/features/owned-ui/reference-screen-app.js +232 -0
- package/dist/features/owned-ui/settings-app.js +2 -7
- package/dist/integrations/pi/components/index.d.ts +4 -2
- package/dist/integrations/pi/components/index.js +2 -1
- package/dist/integrations/pi/components/models-dialog.d.ts +55 -0
- package/dist/integrations/pi/components/models-dialog.js +310 -0
- package/dist/integrations/pi/components/shell-editor-autocomplete.d.ts +10 -0
- package/dist/integrations/pi/components/shell-editor-autocomplete.js +29 -5
- package/dist/integrations/pi/components/shell-footer-status.js +2 -1
- package/dist/integrations/pi/components/shell-presenters-info.d.ts +10 -0
- package/dist/integrations/pi/components/shell-presenters-info.js +31 -11
- package/dist/integrations/pi/components/shell-selectors-dialogs.d.ts +11 -1
- package/dist/integrations/pi/components/shell-selectors-dialogs.js +13 -0
- package/dist/integrations/pi/components/shell-shared-facade.d.ts +8 -0
- package/dist/integrations/pi/components/skills-command.d.ts +47 -0
- package/dist/integrations/pi/components/skills-command.js +118 -0
- package/dist/integrations/pi/components/skills-dialog.d.ts +9 -0
- package/dist/integrations/pi/components/skills-dialog.js +123 -0
- package/dist/integrations/pi/components/upstream/components/owned-editor.d.ts +8 -2
- package/dist/integrations/pi/components/upstream/components/owned-editor.js +42 -7
- package/dist/integrations/pi/engine/adapter.d.ts +5 -1
- package/dist/integrations/pi/engine/adapter.js +13 -1
- package/dist/integrations/pi/engine/index.d.ts +2 -2
- package/dist/integrations/pi/engine/index.js +1 -1
- package/dist/integrations/pi/engine/resource-catalog.d.ts +2 -1
- package/dist/integrations/pi/engine/resource-catalog.js +19 -9
- package/dist/integrations/pi/engine/workflow-contexts.d.ts +8 -1
- package/dist/integrations/pi/engine/workflow-contexts.js +52 -8
- package/dist/integrations/pi/engine/workflow-runner.js +98 -74
- package/dist/integrations/pi/engine/workflows.d.ts +26 -2
- package/dist/integrations/pi/engine/workflows.js +8 -0
- package/dist/native/darwin-arm64/manifest.json +1 -1
- package/dist/native/linux-x64/manifest.json +1 -1
- package/dist/native/win32-x64/manifest.json +2 -2
- package/dist/native/win32-x64/process-guardian.exe +0 -0
- package/dist/ui/apps/contracts.d.ts +9 -1
- package/dist/ui/apps/index.d.ts +1 -1
- package/dist/ui/settings/declarations.d.ts +15 -29
- package/dist/ui/settings/declarations.js +14 -25
- package/dist/ui/settings/index.d.ts +1 -1
- package/dist/ui/settings/index.js +1 -1
- package/dist/ui/settings/migrations.js +18 -0
- package/docs/architecture/prompt-suggestions.md +1 -1
- package/docs/architecture/ui-reference-provenance.md +1 -0
- package/docs/ci-release-runbook.md +31 -23
- package/docs/features/modal-content-interaction.md +3 -2
- package/package.json +1 -1
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const CHANGELOG_APP_ID = "changelog";
|
|
2
|
+
export declare const CHANGELOG_ROUTE = "changelog";
|
|
3
|
+
export declare const CHANGELOG_TITLE = "What's New";
|
|
4
|
+
export declare const HOTKEYS_APP_ID = "hotkeys";
|
|
5
|
+
export declare const HOTKEYS_ROUTE = "hotkeys";
|
|
6
|
+
export declare const HOTKEYS_TITLE = "Keyboard Shortcuts";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export const CHANGELOG_APP_ID = "changelog";
|
|
2
|
+
export const CHANGELOG_ROUTE = "changelog";
|
|
3
|
+
export const CHANGELOG_TITLE = "What's New";
|
|
4
|
+
export const HOTKEYS_APP_ID = "hotkeys";
|
|
5
|
+
export const HOTKEYS_ROUTE = "hotkeys";
|
|
6
|
+
export const HOTKEYS_TITLE = "Keyboard Shortcuts";
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { OwnedUiViewportSettings } from "../../contracts/owned-ui/index.js";
|
|
2
|
+
import type { AppHostServices, UiApp } from "../../ui/apps/index.js";
|
|
3
|
+
import { ShortcutRegistry, type PaneInputResult, type PaneMouseEvent, type PaneRect } from "../../ui/components/index.js";
|
|
4
|
+
type Action = "up" | "down" | "page-up" | "page-down" | "first" | "last" | "close";
|
|
5
|
+
export declare const REFERENCE_SCREEN_SHORTCUTS: ShortcutRegistry<Action>;
|
|
6
|
+
/** Rows of a document already styled and wrapped for one content width. */
|
|
7
|
+
export interface ReferenceDocumentProvider {
|
|
8
|
+
/** The rows for this width, or null while the document is not available yet. */
|
|
9
|
+
rows(width: number): readonly string[] | null;
|
|
10
|
+
/** Settles once `rows` answers; absent when the document is available at once. */
|
|
11
|
+
readonly ready?: Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
export interface ReferenceScreenOptions {
|
|
14
|
+
readonly id: string;
|
|
15
|
+
readonly title: string;
|
|
16
|
+
readonly document: ReferenceDocumentProvider;
|
|
17
|
+
/** The reader's scroll settings, read on every frame so a live change is honored. */
|
|
18
|
+
readonly scrollSettings: () => OwnedUiViewportSettings;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Presents one read-only document full screen between two accent rules: the bold
|
|
22
|
+
* title leads the scrolled rows, the shared scrollbar rail runs beside them, and
|
|
23
|
+
* the hint line closes the frame. Rows come from a provider per content width and
|
|
24
|
+
* are cached until the width changes; the screen closes on Escape and leaves the
|
|
25
|
+
* interrupt chord to its host.
|
|
26
|
+
*/
|
|
27
|
+
export declare class ReferenceScreenApp implements UiApp {
|
|
28
|
+
#private;
|
|
29
|
+
readonly id: string;
|
|
30
|
+
constructor(options: ReferenceScreenOptions);
|
|
31
|
+
onActivate(host: AppHostServices): void;
|
|
32
|
+
onClose(_host: AppHostServices): void;
|
|
33
|
+
render(rect: PaneRect, host: AppHostServices): readonly string[];
|
|
34
|
+
onInput(data: string, host: AppHostServices): PaneInputResult;
|
|
35
|
+
onMouse(event: PaneMouseEvent, _host: AppHostServices): PaneInputResult;
|
|
36
|
+
}
|
|
37
|
+
export {};
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { GLOBAL_SCOPE, PLAIN_THEME, RAIL_COLUMNS, ShortcutRegistry, ScrollbarRails, assertNoShortcutConflicts, displayWidth, padToWidth, scrollForTrackPage, scrollbarGeometry, scrollbarPresentation, scrollbarWheelRows, truncateToWidth, withScrollbarRail, } from "../../ui/components/index.js";
|
|
2
|
+
const SCOPE = "reference-screen";
|
|
3
|
+
/** Rows above the document: the top rule. */
|
|
4
|
+
const HEADER_ROWS = 1;
|
|
5
|
+
/** Rows below the document: the bottom rule and the hint line. */
|
|
6
|
+
const FOOTER_ROWS = 2;
|
|
7
|
+
// Compatibility: the transcript rail stays lit this long after a scroll, and repaints just after.
|
|
8
|
+
const SCROLL_LINGER_MS = 900;
|
|
9
|
+
const SCROLL_LINGER_REPAINT_MS = 925;
|
|
10
|
+
const LOADING_NOTICE = "Loading…";
|
|
11
|
+
export const REFERENCE_SCREEN_SHORTCUTS = new ShortcutRegistry();
|
|
12
|
+
// Compatibility: the footer reads as v2's `esc/ctrl+c close • ↑↓ scroll`, without ctrl+c, which is
|
|
13
|
+
// the A1 interrupt chord here rather than a close key.
|
|
14
|
+
REFERENCE_SCREEN_SHORTCUTS.declare({ key: "escape", scope: GLOBAL_SCOPE, description: "Close", section: "Screen", hint: { keys: "esc", does: "close" } }, "close");
|
|
15
|
+
REFERENCE_SCREEN_SHORTCUTS.declare({ key: "up", scope: SCOPE, description: "Scroll up", section: "Navigate", hint: { keys: "↑↓", does: "scroll" } }, "up");
|
|
16
|
+
REFERENCE_SCREEN_SHORTCUTS.declare({ key: "down", scope: SCOPE, description: "Scroll down", section: "Navigate", hint: { keys: "↑↓", does: "scroll" } }, "down");
|
|
17
|
+
REFERENCE_SCREEN_SHORTCUTS.declare({ key: "pageUp", scope: SCOPE, description: "Up a page", section: "Navigate" }, "page-up");
|
|
18
|
+
REFERENCE_SCREEN_SHORTCUTS.declare({ key: "pageDown", scope: SCOPE, description: "Down a page", section: "Navigate" }, "page-down");
|
|
19
|
+
REFERENCE_SCREEN_SHORTCUTS.declare({ key: "home", scope: SCOPE, description: "First row", section: "Navigate" }, "first");
|
|
20
|
+
REFERENCE_SCREEN_SHORTCUTS.declare({ key: "end", scope: SCOPE, description: "Last row", section: "Navigate" }, "last");
|
|
21
|
+
/** The separator v2's footer puts between its hints. */
|
|
22
|
+
const HINT_SEPARATOR = " • ";
|
|
23
|
+
assertNoShortcutConflicts(REFERENCE_SCREEN_SHORTCUTS.assemble());
|
|
24
|
+
const KEYS = {
|
|
25
|
+
"\u001b[A": "up",
|
|
26
|
+
"\u001b[B": "down",
|
|
27
|
+
"\u001b[5~": "pageUp",
|
|
28
|
+
"\u001b[6~": "pageDown",
|
|
29
|
+
// Protocol: xterm, VT220, and rxvt forms of the same two chords.
|
|
30
|
+
"\u001b[H": "home",
|
|
31
|
+
"\u001b[1~": "home",
|
|
32
|
+
"\u001b[7~": "home",
|
|
33
|
+
"\u001b[F": "end",
|
|
34
|
+
"\u001b[4~": "end",
|
|
35
|
+
"\u001b[8~": "end",
|
|
36
|
+
"\u001b": "escape",
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Presents one read-only document full screen between two accent rules: the bold
|
|
40
|
+
* title leads the scrolled rows, the shared scrollbar rail runs beside them, and
|
|
41
|
+
* the hint line closes the frame. Rows come from a provider per content width and
|
|
42
|
+
* are cached until the width changes; the screen closes on Escape and leaves the
|
|
43
|
+
* interrupt chord to its host.
|
|
44
|
+
*/
|
|
45
|
+
export class ReferenceScreenApp {
|
|
46
|
+
id;
|
|
47
|
+
#title;
|
|
48
|
+
#document;
|
|
49
|
+
#scrollSettings;
|
|
50
|
+
#scroll = 0;
|
|
51
|
+
#interruptArmed = false;
|
|
52
|
+
#failure = null;
|
|
53
|
+
// Performance: the provider wraps Markdown; wheel and drag frames must not repeat that work.
|
|
54
|
+
#cached = null;
|
|
55
|
+
// Invariant: rail hover and drag live in the shared keyed state, as the transcript's do.
|
|
56
|
+
#rails = new ScrollbarRails();
|
|
57
|
+
// Rationale: the rail as drawn in the last frame, or null when nothing can be pointed at.
|
|
58
|
+
#railFrame = null;
|
|
59
|
+
#bodyHeight = 0;
|
|
60
|
+
// Invariant: a scroll lights the rail until this time; the timer repaints once it has passed.
|
|
61
|
+
#activeUntil = 0;
|
|
62
|
+
#activityTimer;
|
|
63
|
+
#renderedScroll;
|
|
64
|
+
constructor(options) {
|
|
65
|
+
this.id = options.id;
|
|
66
|
+
this.#title = options.title;
|
|
67
|
+
this.#document = options.document;
|
|
68
|
+
this.#scrollSettings = options.scrollSettings;
|
|
69
|
+
}
|
|
70
|
+
onActivate(host) {
|
|
71
|
+
const ready = this.#document.ready;
|
|
72
|
+
if (ready === undefined)
|
|
73
|
+
return;
|
|
74
|
+
void ready.then(() => {
|
|
75
|
+
this.#cached = null;
|
|
76
|
+
host.requestRender();
|
|
77
|
+
}, (error) => {
|
|
78
|
+
this.#failure = `Could not load ${this.#title}: ${error instanceof Error ? error.message : String(error)}`;
|
|
79
|
+
host.requestRender();
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
onClose(_host) {
|
|
83
|
+
this.#clearActivityTimer();
|
|
84
|
+
this.#rails.clear();
|
|
85
|
+
}
|
|
86
|
+
render(rect, host) {
|
|
87
|
+
const theme = host.theme ?? PLAIN_THEME;
|
|
88
|
+
this.#interruptArmed = host.interruptArmed;
|
|
89
|
+
const settings = this.#scrollSettings();
|
|
90
|
+
const reservesRail = settings.scrollbarAppearance !== "hidden";
|
|
91
|
+
const contentWidth = reservesRail ? Math.max(0, rect.width - RAIL_COLUMNS) : rect.width;
|
|
92
|
+
const bodyHeight = Math.max(0, rect.height - HEADER_ROWS - FOOTER_ROWS);
|
|
93
|
+
this.#bodyHeight = bodyHeight;
|
|
94
|
+
const rows = this.#rows(contentWidth, theme);
|
|
95
|
+
const maxScroll = Math.max(0, rows.length - bodyHeight);
|
|
96
|
+
this.#scroll = Math.min(Math.max(0, this.#scroll), maxScroll);
|
|
97
|
+
const now = Date.now();
|
|
98
|
+
// Rationale: every way of scrolling ends in this frame, so a moved document is noticed here
|
|
99
|
+
// once rather than at each wheel, drag, and key branch.
|
|
100
|
+
if (this.#renderedScroll !== undefined && this.#renderedScroll !== this.#scroll)
|
|
101
|
+
this.#noteScrollActivity(host, now);
|
|
102
|
+
this.#renderedScroll = this.#scroll;
|
|
103
|
+
const geometry = scrollbarGeometry({ contentLength: rows.length, viewportHeight: bodyHeight, scroll: this.#scroll, trackHeight: bodyHeight });
|
|
104
|
+
const presentation = scrollbarPresentation({
|
|
105
|
+
geometry,
|
|
106
|
+
appearance: settings.scrollbarAppearance,
|
|
107
|
+
style: settings.scrollbarStyle,
|
|
108
|
+
hovered: this.#rails.isHovered(this.id),
|
|
109
|
+
dragging: this.#rails.isDragging(this.id),
|
|
110
|
+
activeUntil: this.#activeUntil,
|
|
111
|
+
now,
|
|
112
|
+
});
|
|
113
|
+
this.#railFrame = reservesRail && geometry !== null
|
|
114
|
+
? { rail: { key: this.id, column: rect.width, rowStart: HEADER_ROWS, trackHeight: geometry.trackHeight }, geometry, page: bodyHeight }
|
|
115
|
+
: null;
|
|
116
|
+
const body = [];
|
|
117
|
+
for (let index = this.#scroll; index < this.#scroll + bodyHeight; index++) {
|
|
118
|
+
const row = rows[index] ?? "";
|
|
119
|
+
body.push(displayWidth(row) > contentWidth ? truncateToWidth(row, contentWidth) : row);
|
|
120
|
+
}
|
|
121
|
+
const withRail = withScrollbarRail(body, geometry, contentWidth, theme, { presentation });
|
|
122
|
+
const hint = this.#interruptArmed ? "press ctrl+c again to exit a1" : REFERENCE_SCREEN_SHORTCUTS.hint(SCOPE, HINT_SEPARATOR);
|
|
123
|
+
// Compatibility: the v2 reference screen frames its document between two border-coloured rules.
|
|
124
|
+
const rule = theme.fg("border", "─".repeat(rect.width));
|
|
125
|
+
// Compatibility: v2 sets its footer against the left edge, unlike the settings status line.
|
|
126
|
+
const frame = [rule, ...withRail, rule, padToWidth(theme.fg("dim", hint), rect.width)];
|
|
127
|
+
// Invariant: a rectangle too small for the chrome still gets exactly its rows, top first.
|
|
128
|
+
return frame.slice(0, rect.height).concat(Array(Math.max(0, rect.height - frame.length)).fill(""));
|
|
129
|
+
}
|
|
130
|
+
onInput(data, host) {
|
|
131
|
+
const action = REFERENCE_SCREEN_SHORTCUTS.resolve(KEYS[data] ?? data, SCOPE);
|
|
132
|
+
if (action === null)
|
|
133
|
+
return { consumed: false };
|
|
134
|
+
switch (action) {
|
|
135
|
+
case "close":
|
|
136
|
+
host.close();
|
|
137
|
+
return { consumed: true };
|
|
138
|
+
case "up":
|
|
139
|
+
this.#scrollBy(-1);
|
|
140
|
+
return { consumed: true };
|
|
141
|
+
case "down":
|
|
142
|
+
this.#scrollBy(1);
|
|
143
|
+
return { consumed: true };
|
|
144
|
+
case "page-up":
|
|
145
|
+
this.#scrollBy(-Math.max(1, this.#bodyHeight));
|
|
146
|
+
return { consumed: true };
|
|
147
|
+
case "page-down":
|
|
148
|
+
this.#scrollBy(Math.max(1, this.#bodyHeight));
|
|
149
|
+
return { consumed: true };
|
|
150
|
+
case "first":
|
|
151
|
+
this.#scroll = 0;
|
|
152
|
+
return { consumed: true };
|
|
153
|
+
case "last":
|
|
154
|
+
this.#scroll = Number.MAX_SAFE_INTEGER;
|
|
155
|
+
return { consumed: true };
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
onMouse(event, _host) {
|
|
159
|
+
if (event.kind === "wheel-up" || event.kind === "wheel-down") {
|
|
160
|
+
// Invariant: the whole screen owns wheel scrolling; it must not depend on the pointer's row.
|
|
161
|
+
const distance = scrollbarWheelRows(this.#scrollSettings().scrollbarSpeed);
|
|
162
|
+
this.#scrollBy(event.kind === "wheel-down" ? distance : -distance);
|
|
163
|
+
return { consumed: true };
|
|
164
|
+
}
|
|
165
|
+
const rail = this.#railPointer(event);
|
|
166
|
+
if (rail.owned)
|
|
167
|
+
return { consumed: true };
|
|
168
|
+
return { consumed: event.kind !== "motion", render: rail.changed };
|
|
169
|
+
}
|
|
170
|
+
// Rationale: the rail takes its share of a pointer report first: hover, a thumb drag, or a
|
|
171
|
+
// track page. Owned means the document must not see the report; changed means the rail looks different.
|
|
172
|
+
#railPointer(event) {
|
|
173
|
+
const frame = this.#railFrame;
|
|
174
|
+
const wasHovered = this.#rails.isHovered(this.id);
|
|
175
|
+
if (frame === null) {
|
|
176
|
+
this.#rails.clear();
|
|
177
|
+
return { owned: false, changed: wasHovered };
|
|
178
|
+
}
|
|
179
|
+
const pointer = { column: event.column, row: event.row - 1 };
|
|
180
|
+
if (this.#rails.isDragging(this.id)) {
|
|
181
|
+
// Invariant: a drag keeps the pointer wherever it goes until the button comes up.
|
|
182
|
+
if (event.kind === "release")
|
|
183
|
+
this.#rails.endDrag();
|
|
184
|
+
else {
|
|
185
|
+
const target = this.#rails.dragTo(frame.rail, frame.geometry, pointer);
|
|
186
|
+
if (target !== null)
|
|
187
|
+
this.#scroll = target;
|
|
188
|
+
}
|
|
189
|
+
return { owned: true, changed: true };
|
|
190
|
+
}
|
|
191
|
+
const over = this.#rails.notePointer([frame.rail], pointer) !== null;
|
|
192
|
+
if (!over)
|
|
193
|
+
return { owned: false, changed: wasHovered };
|
|
194
|
+
if (event.kind === "press" && !this.#rails.beginDrag(frame.rail, frame.geometry, pointer)) {
|
|
195
|
+
this.#scroll = scrollForTrackPage(frame.geometry, pointer.row - frame.rail.rowStart, this.#scroll, frame.page);
|
|
196
|
+
}
|
|
197
|
+
return { owned: true, changed: true };
|
|
198
|
+
}
|
|
199
|
+
// Invariant: the title is the first document row, as in v2, so it scrolls with the document.
|
|
200
|
+
#rows(width, theme) {
|
|
201
|
+
// Compatibility: one leading space, so the title lines up with the padded Markdown rows as in v2.
|
|
202
|
+
const title = ` ${theme.bold(theme.fg("accent", this.#title))}`;
|
|
203
|
+
if (this.#failure !== null)
|
|
204
|
+
return [title, "", this.#failure];
|
|
205
|
+
const cached = this.#cached;
|
|
206
|
+
if (cached !== null && cached.width === width)
|
|
207
|
+
return [title, ...cached.rows];
|
|
208
|
+
const rows = this.#document.rows(width);
|
|
209
|
+
if (rows === null)
|
|
210
|
+
return [title, "", LOADING_NOTICE];
|
|
211
|
+
this.#cached = { width, rows };
|
|
212
|
+
return [title, ...rows];
|
|
213
|
+
}
|
|
214
|
+
#scrollBy(distance) {
|
|
215
|
+
// Invariant: the upper clamp happens at render, where the body height and row count are known.
|
|
216
|
+
this.#scroll = Math.max(0, this.#scroll + distance);
|
|
217
|
+
}
|
|
218
|
+
#noteScrollActivity(host, now) {
|
|
219
|
+
this.#activeUntil = Math.max(this.#activeUntil, now + SCROLL_LINGER_MS);
|
|
220
|
+
this.#clearActivityTimer();
|
|
221
|
+
this.#activityTimer = setTimeout(() => {
|
|
222
|
+
this.#activityTimer = undefined;
|
|
223
|
+
host.requestRender();
|
|
224
|
+
}, SCROLL_LINGER_REPAINT_MS);
|
|
225
|
+
this.#activityTimer.unref?.();
|
|
226
|
+
}
|
|
227
|
+
#clearActivityTimer() {
|
|
228
|
+
if (this.#activityTimer !== undefined)
|
|
229
|
+
clearTimeout(this.#activityTimer);
|
|
230
|
+
this.#activityTimer = undefined;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
@@ -74,7 +74,6 @@ export class SettingsApp {
|
|
|
74
74
|
#filter = null;
|
|
75
75
|
#menu = null;
|
|
76
76
|
#structured = null;
|
|
77
|
-
#loading = true;
|
|
78
77
|
#interruptArmed = false;
|
|
79
78
|
// Invariant: pending values remain visible until the source reflects them.
|
|
80
79
|
#pending = new Map();
|
|
@@ -98,10 +97,7 @@ export class SettingsApp {
|
|
|
98
97
|
this.#session = session;
|
|
99
98
|
}
|
|
100
99
|
onActivate(host) {
|
|
101
|
-
void this.#session.load().then(() =>
|
|
102
|
-
this.#loading = false;
|
|
103
|
-
host.requestRender();
|
|
104
|
-
});
|
|
100
|
+
void this.#session.load().then(() => host.requestRender());
|
|
105
101
|
}
|
|
106
102
|
onClose(_host) {
|
|
107
103
|
this.#clearActivityTimer();
|
|
@@ -161,8 +157,7 @@ export class SettingsApp {
|
|
|
161
157
|
const body = [];
|
|
162
158
|
this.#frameRows = [];
|
|
163
159
|
if (rows.length === 0) {
|
|
164
|
-
|
|
165
|
-
body.push(...renderEmptyState(message, "👀", bodyHeight, contentWidth, theme));
|
|
160
|
+
body.push(...renderEmptyState("No settings found.", "👀", bodyHeight, contentWidth, theme));
|
|
166
161
|
}
|
|
167
162
|
else {
|
|
168
163
|
if (layout.topPadding > 0)
|
|
@@ -2,12 +2,14 @@ export { adaptPiAssistantMessage, adaptPiToolExecution, adaptPiUserMessage } fro
|
|
|
2
2
|
export { loadHistoryEditor, type HistoryEditorConstructor } from "./history-editor-loader.js";
|
|
3
3
|
export { PiComponentConformanceError, runPiComponentConformance } from "./conformance.js";
|
|
4
4
|
export type { PiComponentConformanceReport, PiComponentConformanceResult } from "./conformance.js";
|
|
5
|
-
export { PINNED_PI_BUILTIN_SLASH_COMMANDS, componentFromPort, componentPort, createPiExtensionUiBridge, createPiQueuedInputStatus, createPiShellArmin, createPiShellAuthProviderSelector, createPiShellChangelog, createPiShellCollapsedChangelog, createPiShellDaxnuts, createPiShellDialog, createPiShellEarendilAnnouncement, createPiShellEditor, createPiShellExtensionSelector, createPiShellFooter, createPiShellHeader, createPiShellHotkeys, createPiShellLoadedResources, createPiShellLoginDialog, createPiShellModelSelector, createPiShellOperationLoader, createPiShellReloadBox, createPiShellScopedModelsSelector, createPiShellSelector, createPiShellSessionInfo, createPiShellSessionSelector, createPiShellSettingsSelector, createPiShellShowImagesSelector, createPiShellStatus, createPiShellThemeSelector, createPiShellThinkingSelector, createPiShellTranscriptComponent, createPiShellTreeSelector, createPiShellTrustSelector, createPiShellUserMessageSelector, createTuiFacade, ensureTheme, formatSessionTokens, isAutocompleteProvider, isPiPromptStyleCompaction, isRecord, paintPiSubmittedPromptTimestamp, piShellHyperlink, piShellTruncateToWidth, piShellVisibleWidth, renderPiShellCommandMessage, renderPiShellPackageUpdateNotice, renderPiShellStartupDiagnostic, renderPiShellStatusText, renderPiShellTranscriptBlock, validatedAssistantMessage, } from "./shell-components.js";
|
|
6
|
-
export type { PiExtensionUiBridge, PiExtensionUiBridgeHost, PiShellAuthProviderOption, PiShellAutocompleteCommand, PiShellClipboardContent, PiShellCommandMessagePresentation, PiShellComponentPort, PiShellEditorBodyGeometry, PiShellEditorOptions, PiShellEditorPointerEvent, PiShellEditorPort, PiShellEditorTextRange, PiShellExtensionRendererResolver, PiShellHeaderOptions, PiShellHeaderPort, PiShellImageAssetResolver, PiShellLoadedResourcesPort, PiShellLoginDialogPort, PiShellModelSelectorOptions, PiShellOperationLoaderPort, PiShellPasteReservation, PiShellQueuedInputPort, PiShellResourceEntry, PiShellResourceSection, PiShellScopedModelDescriptor, PiShellScopedModelsSelectorOptions, PiShellScopedModelsSelectorPort, PiShellSelectorOption, PiShellSelectorOptions, PiShellSessionInfoPresentation, PiShellSettingsSelectorOptions, PiShellStartupNotice, PiShellStatusPlacement, PiShellStatusPort, PiShellSubmittedPromptComposer, PiShellTranscriptComponentPort, PiShellViewComponentPort, } from "./shell-components.js";
|
|
5
|
+
export { OWNED_BUILTIN_SLASH_COMMANDS, PINNED_PI_BUILTIN_SLASH_COMMANDS, componentFromPort, componentPort, createPiExtensionUiBridge, createPiQueuedInputStatus, createPiShellArmin, createPiShellAuthProviderSelector, createPiShellChangelog, createPiShellCollapsedChangelog, createPiShellDaxnuts, createPiShellDialog, createPiShellEarendilAnnouncement, createPiShellEditor, createPiShellExtensionSelector, createPiShellFooter, createPiShellHeader, createPiShellHotkeys, createPiShellLoadedResources, createPiShellLoginDialog, createPiShellModelSelector, createPiShellModelsDialog, createPiShellOperationLoader, createPiShellReloadBox, createPiShellScopedModelsSelector, createPiShellSelector, createPiShellSessionInfo, createPiShellSessionSelector, createPiShellSettingsSelector, createPiShellShowImagesSelector, createPiShellSkillsSelector, createPiShellStatus, createPiShellThemeSelector, createPiShellThinkingSelector, createPiShellTranscriptComponent, createPiShellTreeSelector, createPiShellTrustSelector, createPiShellUserMessageSelector, createTuiFacade, ensureTheme, formatSessionTokens, isAutocompleteProvider, isPiPromptStyleCompaction, isRecord, paintPiSubmittedPromptTimestamp, piShellHyperlink, piShellTruncateToWidth, piShellVisibleWidth, renderPiShellChangelogLines, renderPiShellCommandMessage, renderPiShellHotkeysLines, renderPiShellPackageUpdateNotice, renderPiShellStartupDiagnostic, renderPiShellStatusText, renderPiShellTranscriptBlock, validatedAssistantMessage, } from "./shell-components.js";
|
|
6
|
+
export type { PiExtensionUiBridge, PiExtensionUiBridgeHost, PiShellAuthProviderOption, PiShellAutocompleteCommand, PiShellClipboardContent, PiShellCommandMessagePresentation, PiShellComponentPort, PiShellEditorBodyGeometry, PiShellEditorOptions, PiShellEditorPointerEvent, PiShellEditorPort, PiShellEditorTextRange, PiShellExtensionRendererResolver, PiShellHeaderOptions, PiShellHeaderPort, PiShellHotkeysPresentation, PiShellImageAssetResolver, PiShellLoadedResourcesPort, PiShellLoginDialogPort, PiShellModelSelectorOptions, PiShellModelsDialogOptions, PiShellModelsDialogPort, PiShellOperationLoaderPort, PiShellPasteReservation, PiShellQueuedInputPort, PiShellResourceEntry, PiShellResourceSection, PiShellScopedModelDescriptor, PiShellScopedModelsSelectorOptions, PiShellScopedModelsSelectorPort, PiShellSelectorOption, PiShellSelectorOptions, PiShellSessionInfoPresentation, PiShellSettingsSelectorOptions, PiShellStartupNotice, PiShellStatusPlacement, PiShellStatusPort, PiShellSubmittedPromptComposer, PiShellTranscriptComponentPort, PiShellViewComponentPort, } from "./shell-components.js";
|
|
7
7
|
export { PINNED_PI_LAYOUT, applyConfiguredPiTheme, applyPiTheme, applyPiThemeInstance, currentPiThemeName, detectPiTerminalBackgroundFromEnv, detectPiTerminalBackgroundTheme, detectPiTerminalThemeForAuto, ensurePiTheme, getAvailablePiThemes, loadPiTheme, onPiThemeChange, parsePiAutoThemeSetting, piTheme, resolvePiThemeSetting, stopPiThemeWatcher, } from "./theme.js";
|
|
8
8
|
export type { PiColorMode, PiTerminalTheme, PiTerminalThemeDetection, PiTerminalThemeDetector, PiThemeBackground, PiThemeResult } from "./theme.js";
|
|
9
9
|
export { OwnedPiThemeController } from "./upstream/theme/theme-controller.js";
|
|
10
10
|
export type { PiThemeRuntimePort, PiThemeSettingsPort } from "./upstream/theme/theme-controller.js";
|
|
11
|
+
export { ModelsDialogComponent } from "./models-dialog.js";
|
|
12
|
+
export type { ModelsDialogCallbacks, ModelsDialogConfig, ModelsDialogFilter, ModelsDialogModel } from "./models-dialog.js";
|
|
11
13
|
export { CountdownTimer } from "./upstream/components/countdown-timer.js";
|
|
12
14
|
export { ExtensionEditorComponent } from "./upstream/components/extension-editor.js";
|
|
13
15
|
export { SessionSelectorComponent } from "./upstream/components/session-selector.js";
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
export { adaptPiAssistantMessage, adaptPiToolExecution, adaptPiUserMessage } from "./components.js";
|
|
2
2
|
export { loadHistoryEditor } from "./history-editor-loader.js";
|
|
3
3
|
export { PiComponentConformanceError, runPiComponentConformance } from "./conformance.js";
|
|
4
|
-
export { PINNED_PI_BUILTIN_SLASH_COMMANDS, componentFromPort, componentPort, createPiExtensionUiBridge, createPiQueuedInputStatus, createPiShellArmin, createPiShellAuthProviderSelector, createPiShellChangelog, createPiShellCollapsedChangelog, createPiShellDaxnuts, createPiShellDialog, createPiShellEarendilAnnouncement, createPiShellEditor, createPiShellExtensionSelector, createPiShellFooter, createPiShellHeader, createPiShellHotkeys, createPiShellLoadedResources, createPiShellLoginDialog, createPiShellModelSelector, createPiShellOperationLoader, createPiShellReloadBox, createPiShellScopedModelsSelector, createPiShellSelector, createPiShellSessionInfo, createPiShellSessionSelector, createPiShellSettingsSelector, createPiShellShowImagesSelector, createPiShellStatus, createPiShellThemeSelector, createPiShellThinkingSelector, createPiShellTranscriptComponent, createPiShellTreeSelector, createPiShellTrustSelector, createPiShellUserMessageSelector, createTuiFacade, ensureTheme, formatSessionTokens, isAutocompleteProvider, isPiPromptStyleCompaction, isRecord, paintPiSubmittedPromptTimestamp, piShellHyperlink, piShellTruncateToWidth, piShellVisibleWidth, renderPiShellCommandMessage, renderPiShellPackageUpdateNotice, renderPiShellStartupDiagnostic, renderPiShellStatusText, renderPiShellTranscriptBlock, validatedAssistantMessage, } from "./shell-components.js";
|
|
4
|
+
export { OWNED_BUILTIN_SLASH_COMMANDS, PINNED_PI_BUILTIN_SLASH_COMMANDS, componentFromPort, componentPort, createPiExtensionUiBridge, createPiQueuedInputStatus, createPiShellArmin, createPiShellAuthProviderSelector, createPiShellChangelog, createPiShellCollapsedChangelog, createPiShellDaxnuts, createPiShellDialog, createPiShellEarendilAnnouncement, createPiShellEditor, createPiShellExtensionSelector, createPiShellFooter, createPiShellHeader, createPiShellHotkeys, createPiShellLoadedResources, createPiShellLoginDialog, createPiShellModelSelector, createPiShellModelsDialog, createPiShellOperationLoader, createPiShellReloadBox, createPiShellScopedModelsSelector, createPiShellSelector, createPiShellSessionInfo, createPiShellSessionSelector, createPiShellSettingsSelector, createPiShellShowImagesSelector, createPiShellSkillsSelector, createPiShellStatus, createPiShellThemeSelector, createPiShellThinkingSelector, createPiShellTranscriptComponent, createPiShellTreeSelector, createPiShellTrustSelector, createPiShellUserMessageSelector, createTuiFacade, ensureTheme, formatSessionTokens, isAutocompleteProvider, isPiPromptStyleCompaction, isRecord, paintPiSubmittedPromptTimestamp, piShellHyperlink, piShellTruncateToWidth, piShellVisibleWidth, renderPiShellChangelogLines, renderPiShellCommandMessage, renderPiShellHotkeysLines, renderPiShellPackageUpdateNotice, renderPiShellStartupDiagnostic, renderPiShellStatusText, renderPiShellTranscriptBlock, validatedAssistantMessage, } from "./shell-components.js";
|
|
5
5
|
export { PINNED_PI_LAYOUT, applyConfiguredPiTheme, applyPiTheme, applyPiThemeInstance, currentPiThemeName, detectPiTerminalBackgroundFromEnv, detectPiTerminalBackgroundTheme, detectPiTerminalThemeForAuto, ensurePiTheme, getAvailablePiThemes, loadPiTheme, onPiThemeChange, parsePiAutoThemeSetting, piTheme, resolvePiThemeSetting, stopPiThemeWatcher, } from "./theme.js";
|
|
6
6
|
export { OwnedPiThemeController } from "./upstream/theme/theme-controller.js";
|
|
7
|
+
export { ModelsDialogComponent } from "./models-dialog.js";
|
|
7
8
|
export { CountdownTimer } from "./upstream/components/countdown-timer.js";
|
|
8
9
|
export { ExtensionEditorComponent } from "./upstream/components/extension-editor.js";
|
|
9
10
|
export { SessionSelectorComponent } from "./upstream/components/session-selector.js";
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { type Component, type Focusable } from "@earendil-works/pi-tui";
|
|
2
|
+
export type ModelsDialogFilter = "all" | "scoped";
|
|
3
|
+
export interface ModelsDialogModel {
|
|
4
|
+
readonly provider: string;
|
|
5
|
+
readonly id: string;
|
|
6
|
+
readonly name: string;
|
|
7
|
+
}
|
|
8
|
+
export interface ModelsDialogConfig {
|
|
9
|
+
/** The authenticated catalog; rows never widen beyond it. */
|
|
10
|
+
readonly models: readonly ModelsDialogModel[];
|
|
11
|
+
/** `provider/id` of the active model, or null before one is set. */
|
|
12
|
+
readonly activeModelId: string | null;
|
|
13
|
+
/** The explicit cycling scope the session currently uses, in order. */
|
|
14
|
+
readonly scopeIds: readonly string[];
|
|
15
|
+
/** The last persisted scope, in order; the dirty comparison baseline. */
|
|
16
|
+
readonly savedScopeIds: readonly string[];
|
|
17
|
+
readonly initialQuery?: string;
|
|
18
|
+
readonly initialFilter?: ModelsDialogFilter;
|
|
19
|
+
readonly refreshStatus?: string;
|
|
20
|
+
}
|
|
21
|
+
export interface ModelsDialogCallbacks {
|
|
22
|
+
/** Enter on a row: the shell switches through its workflow and closes the dialog on success. */
|
|
23
|
+
onSelect(modelId: string): void;
|
|
24
|
+
/** Every scope or order edit, session-only. */
|
|
25
|
+
onScopeChange(scopeIds: readonly string[]): void;
|
|
26
|
+
/** Ctrl+S: a resolved promise clears the dirty state for exactly the saved snapshot; a rejection keeps it. */
|
|
27
|
+
onSave(scopeIds: readonly string[]): Promise<void> | void;
|
|
28
|
+
onCancel(): void;
|
|
29
|
+
requestRender(): void;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Bare A1's one model-management dialog: a searchable catalog with `all`/`scoped` filters where
|
|
33
|
+
* Enter switches the active model, Space edits the session's cycling scope, and Ctrl+S persists
|
|
34
|
+
* that scope. The component owns only presentation state (query, filter, selection, desired and
|
|
35
|
+
* saved scope, refresh status); every switch, scope write, and save goes through its callbacks.
|
|
36
|
+
*/
|
|
37
|
+
export declare class ModelsDialogComponent implements Component, Focusable {
|
|
38
|
+
#private;
|
|
39
|
+
constructor(config: ModelsDialogConfig, callbacks: ModelsDialogCallbacks);
|
|
40
|
+
get focused(): boolean;
|
|
41
|
+
set focused(value: boolean);
|
|
42
|
+
/** True while the desired scope or order differs from the last successful save. */
|
|
43
|
+
get dirty(): boolean;
|
|
44
|
+
get filter(): ModelsDialogFilter;
|
|
45
|
+
get query(): string;
|
|
46
|
+
get scopeIds(): readonly string[];
|
|
47
|
+
get selectedModelId(): string | undefined;
|
|
48
|
+
/** Replace the catalog after a refresh; query, filter, surviving selection, scope edits, and dirty state stay. */
|
|
49
|
+
updateModels(models: readonly ModelsDialogModel[]): void;
|
|
50
|
+
setRefreshStatus(message: string, kind: "muted" | "success" | "warning"): void;
|
|
51
|
+
dispose(): void;
|
|
52
|
+
invalidate(): void;
|
|
53
|
+
handleInput(data: string): void;
|
|
54
|
+
render(width: number): string[];
|
|
55
|
+
}
|