@timurproko/a1 0.2.7-dev.1270 → 0.2.7-dev.1276
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 +6 -0
- package/dist/app/session-shell/apps-dialog.d.ts +33 -0
- package/dist/app/session-shell/apps-dialog.js +62 -0
- package/dist/app/session-shell/dialog-coordinator.d.ts +12 -5
- package/dist/app/session-shell/dialog-coordinator.js +113 -15
- package/dist/app/session-shell/input-route.d.ts +23 -0
- package/dist/app/session-shell/input-route.js +59 -0
- package/dist/app/session-shell/session-selectors.d.ts +4 -4
- package/dist/app/session-shell/session-selectors.js +8 -3
- package/dist/app/session-shell/session-shell-root.js +6 -2
- package/dist/app/session-shell/session-shell.js +13 -5
- package/dist/app/session-shell/shell-host.d.ts +1 -0
- package/dist/app/session-shell/shell-host.js +22 -11
- package/dist/app/session-shell/viewport-pointer.js +5 -1
- package/dist/app/session-shell/workflow-output.js +12 -0
- package/dist/app/session-shell/workflow-router.d.ts +2 -2
- package/dist/composition/owned-ui.js +17 -13
- package/dist/composition/settings-route-host.js +1 -0
- package/dist/contracts/owned-ui/session-presenters.d.ts +1 -1
- package/dist/contracts/owned-ui/session-workflows.d.ts +3 -1
- package/dist/contracts/owned-ui/shell-components.d.ts +12 -0
- package/dist/contracts/presentation/component.d.ts +7 -0
- package/dist/contracts/presentation/index.d.ts +2 -0
- package/dist/contracts/presentation/index.js +4 -0
- package/dist/contracts/presentation/progress-palette.generated.d.ts +25 -1
- package/dist/contracts/presentation/progress-palette.generated.js +2 -135
- package/dist/contracts/presentation/terminal.d.ts +4 -0
- package/dist/contracts/presentation/theme.d.ts +2 -0
- package/dist/features/owned-ui/project-trust-dialog.d.ts +1 -1
- package/dist/features/owned-ui/project-trust-dialog.js +5 -5
- package/dist/features/owned-ui/project-trust-prompt.js +2 -2
- package/dist/features/owned-ui/reference-screen-app.d.ts +2 -0
- package/dist/features/owned-ui/reference-screen-app.js +4 -1
- package/dist/features/owned-ui/settings-app.js +6 -6
- package/dist/features/owned-ui/settings-model-dialog.js +3 -3
- package/dist/foundation/lifecycle/user-exports.d.ts +5 -0
- package/dist/foundation/lifecycle/user-exports.js +37 -0
- package/dist/foundation/startup/startup-descriptor.js +2 -2
- package/dist/integrations/pi/components/deferred-selector.d.ts +6 -0
- package/dist/integrations/pi/components/deferred-selector.js +40 -0
- package/dist/integrations/pi/components/login-dialog-loader.d.ts +3 -0
- package/dist/integrations/pi/components/login-dialog-loader.js +57 -0
- package/dist/integrations/pi/components/login-links.d.ts +6 -0
- package/dist/integrations/pi/components/login-links.js +31 -0
- package/dist/integrations/pi/components/login-text.d.ts +7 -0
- package/dist/integrations/pi/components/login-text.js +17 -0
- package/dist/integrations/pi/components/modal-frame.d.ts +5 -0
- package/dist/integrations/pi/components/modal-frame.js +30 -2
- package/dist/integrations/pi/components/models-dialog-loader.d.ts +11 -0
- package/dist/integrations/pi/components/models-dialog-loader.js +45 -0
- package/dist/integrations/pi/components/models-dialog.d.ts +2 -0
- package/dist/integrations/pi/components/models-dialog.js +13 -7
- package/dist/integrations/pi/components/resources/builtin-themes.d.ts +2 -2
- package/dist/integrations/pi/components/resources/builtin-themes.js +2 -2
- package/dist/integrations/pi/components/shell-editor-autocomplete.js +21 -15
- package/dist/integrations/pi/components/shell-footer-status.js +3 -2
- package/dist/integrations/pi/components/shell-presenters-info.js +1 -1
- package/dist/integrations/pi/components/shell-presenters-transcript.js +3 -1
- package/dist/integrations/pi/components/shell-selectors-dialogs.d.ts +13 -9
- package/dist/integrations/pi/components/shell-selectors-dialogs.js +38 -43
- package/dist/integrations/pi/components/shell-session-info-reference.d.ts +1 -1
- package/dist/integrations/pi/components/shell-session-info-reference.js +49 -46
- package/dist/integrations/pi/components/theme.d.ts +4 -0
- package/dist/integrations/pi/components/theme.js +9 -0
- package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.d.ts +8 -7
- package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.js +13 -7
- package/dist/integrations/pi/components/upstream/assets/earendil-image.json +2 -2
- package/dist/integrations/pi/components/upstream/components/auth-url.d.ts +16 -0
- package/dist/integrations/pi/components/upstream/components/auth-url.js +49 -0
- package/dist/integrations/pi/components/upstream/components/countdown-timer.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/earendil-announcement.js +1 -1
- package/dist/integrations/pi/components/upstream/components/extension-editor.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/extension-editor.js +1 -1
- package/dist/integrations/pi/components/upstream/components/extension-input.js +1 -1
- package/dist/integrations/pi/components/upstream/components/extension-selector.d.ts +1 -0
- package/dist/integrations/pi/components/upstream/components/extension-selector.js +30 -12
- package/dist/integrations/pi/components/upstream/components/login-dialog.d.ts +3 -0
- package/dist/integrations/pi/components/upstream/components/login-dialog.js +216 -0
- package/dist/integrations/pi/components/upstream/components/mermaid.d.ts +2 -1
- package/dist/integrations/pi/components/upstream/components/mermaid.js +26 -21
- package/dist/integrations/pi/components/upstream/components/oauth-selector.d.ts +19 -0
- package/dist/integrations/pi/components/upstream/components/oauth-selector.js +123 -0
- package/dist/integrations/pi/components/upstream/components/owned-editor.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/owned-editor.js +1 -1
- package/dist/integrations/pi/components/upstream/components/pi-logo.js +1 -1
- package/dist/integrations/pi/components/upstream/components/scoped-models-selector.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/session-footer.js +17 -19
- package/dist/integrations/pi/components/upstream/components/session-selector-search.js +1 -1
- package/dist/integrations/pi/components/upstream/components/session-selector.js +1 -1
- package/dist/integrations/pi/components/upstream/components/skill-invocation-message.d.ts +6 -2
- package/dist/integrations/pi/components/upstream/components/skill-invocation-message.js +27 -3
- package/dist/integrations/pi/components/upstream/components/status-indicator.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/status-indicator.js +1 -1
- package/dist/integrations/pi/components/upstream/components/themed-text.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/themed-text.js +1 -1
- package/dist/integrations/pi/components/upstream/components/thinking-selector.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/thinking-selector.js +1 -1
- package/dist/integrations/pi/components/upstream/components/tool-execution.js +1 -1
- package/dist/integrations/pi/components/upstream/components/tree-selector.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/tree-selector.js +7 -6
- package/dist/integrations/pi/components/upstream/components/trust-selector.d.ts +2 -0
- package/dist/integrations/pi/components/upstream/components/trust-selector.js +30 -13
- package/dist/integrations/pi/components/upstream/external-editor.js +1 -1
- package/dist/integrations/pi/components/upstream/history/editor-core.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/history/editor-core.js +2 -2
- package/dist/integrations/pi/components/upstream/history/kill-ring.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/history/kill-ring.js +1 -1
- package/dist/integrations/pi/components/upstream/history/printable-key.js +1 -1
- package/dist/integrations/pi/components/upstream/history/text-helpers.js +1 -1
- package/dist/integrations/pi/components/upstream/history/undo-stack.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/history/undo-stack.js +1 -1
- package/dist/integrations/pi/components/upstream/history/word-navigation.js +1 -1
- package/dist/integrations/pi/components/upstream/model-search.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/program-status-reporter.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/theme/theme.js +1 -1
- package/dist/integrations/pi/engine/adapter.d.ts +1 -1
- package/dist/integrations/pi/engine/adapter.js +3 -3
- package/dist/integrations/pi/engine/host.d.ts +1 -1
- package/dist/integrations/pi/engine/resources/changelog.json +4 -4
- package/dist/integrations/pi/engine/workflow-export.d.ts +4 -0
- package/dist/integrations/pi/engine/workflow-export.js +25 -0
- package/dist/integrations/pi/engine/workflow-runner.d.ts +1 -0
- package/dist/integrations/pi/engine/workflow-runner.js +6 -10
- package/dist/integrations/pi/engine/workflow-support.d.ts +2 -1
- package/dist/integrations/pi/engine/workflow-support.js +28 -25
- package/dist/integrations/pi/engine/workflows.d.ts +6 -1
- package/dist/integrations/pi/engine/workflows.js +1 -1
- package/dist/integrations/pi/session-presenters/components.d.ts +1 -1
- package/dist/integrations/pi/session-presenters/components.js +8 -8
- package/dist/integrations/pi/session-presenters/presentation.js +2 -1
- package/dist/integrations/pi/session-presenters/presenters.js +24 -12
- package/dist/integrations/pi/startup-public.js +289 -240
- package/dist/integrations/pi/startup-public.manifest.json +579 -363
- package/dist/integrations/pi/tui-runtime/adapter.js +3 -1
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +1 -1
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +1 -1
- package/dist/integrations/pi/tui-runtime/overlay-geometry.d.ts +5 -2
- package/dist/integrations/pi/tui-runtime/overlay-geometry.js +12 -2
- package/dist/runtime-payload-inventory.json +8044 -6930
- package/dist/ui/components/dialog-panel.d.ts +4 -3
- package/dist/ui/components/dialog-panel.js +9 -13
- package/dist/ui/components/index.d.ts +1 -1
- package/dist/ui/components/index.js +1 -1
- package/dist/ui/components/list-block.d.ts +2 -2
- package/dist/ui/components/list-block.js +4 -3
- package/dist/ui/components/spans.d.ts +7 -0
- package/dist/ui/components/spans.js +63 -1
- package/dist/ui/settings/early-accent.d.ts +24 -0
- package/docs/architecture/prompt-suggestions.md +1 -1
- package/docs/architecture/ui-reference-provenance.md +2 -1
- package/docs/features/prompt-history.md +1 -1
- package/docs/features/session-exports.md +15 -0
- package/docs/local-worktree-cleanup.md +24 -0
- package/package.json +6 -6
|
@@ -19,6 +19,17 @@ function renderOwnedAutocompleteSelection(text) {
|
|
|
19
19
|
const description = row === null ? "" : theme.fg("muted", row[2]);
|
|
20
20
|
return renderPiListSelection(arrow + label + description);
|
|
21
21
|
}
|
|
22
|
+
/** Models and thinking share the active declarations, independent of input presentation. */
|
|
23
|
+
function bindModelActions(editor, options) {
|
|
24
|
+
if (options.onModelSelect !== undefined)
|
|
25
|
+
editor.onAction("app.model.select", options.onModelSelect);
|
|
26
|
+
if (options.onModelCycle !== undefined) {
|
|
27
|
+
editor.onAction("app.model.cycleForward", () => options.onModelCycle?.("forward"));
|
|
28
|
+
editor.onAction("app.model.cycleBackward", () => options.onModelCycle?.("backward"));
|
|
29
|
+
}
|
|
30
|
+
if (options.onThinkingCycle !== undefined)
|
|
31
|
+
editor.onAction("app.thinking.cycle", options.onThinkingCycle);
|
|
32
|
+
}
|
|
22
33
|
const PINNED_THINKING_SLASH_COMMAND = { name: "thinking", description: "Set thinking level", argumentHint: "<level>" };
|
|
23
34
|
const OWNED_THINKING_SLASH_COMMAND = { name: "thinking", description: "Set thinking level" };
|
|
24
35
|
const OWNED_LOGIN_SLASH_COMMAND = { name: "login", description: "Configure provider authentication" };
|
|
@@ -52,8 +63,10 @@ export const OWNED_BUILTIN_SLASH_COMMANDS = PINNED_PI_BUILTIN_SLASH_COMMANDS.fla
|
|
|
52
63
|
if (command.name === "model") {
|
|
53
64
|
return [{ name: "models", description: "Switch models and manage scoped model cycling" }, OWNED_THINKING_SLASH_COMMAND];
|
|
54
65
|
}
|
|
55
|
-
if (command.name === "thinking" || command.name === "scoped-models")
|
|
66
|
+
if (command.name === "thinking" || command.name === "scoped-models" || command.name === "settings" || command.name === "changelog" || command.name === "hotkeys")
|
|
56
67
|
return [];
|
|
68
|
+
if (command.name === "export")
|
|
69
|
+
return [{ ...command, description: "Export session to user storage (--jsonl or an explicit path)" }];
|
|
57
70
|
if (command.name === "login")
|
|
58
71
|
return [OWNED_LOGIN_SLASH_COMMAND];
|
|
59
72
|
return [command];
|
|
@@ -179,14 +192,7 @@ export function createPiShellEditor(options) {
|
|
|
179
192
|
}
|
|
180
193
|
if (options.onExtensionShortcut !== undefined)
|
|
181
194
|
editor.onExtensionShortcut = options.onExtensionShortcut;
|
|
182
|
-
|
|
183
|
-
editor.onAction("app.model.select", options.onModelSelect);
|
|
184
|
-
if (options.onModelCycle !== undefined) {
|
|
185
|
-
editor.onAction("app.model.cycleForward", () => options.onModelCycle?.("forward"));
|
|
186
|
-
editor.onAction("app.model.cycleBackward", () => options.onModelCycle?.("backward"));
|
|
187
|
-
}
|
|
188
|
-
if (options.onThinkingCycle !== undefined)
|
|
189
|
-
editor.onAction("app.thinking.cycle", options.onThinkingCycle);
|
|
195
|
+
bindModelActions(editor, options);
|
|
190
196
|
if (options.onThinkingToggle !== undefined)
|
|
191
197
|
editor.onAction("app.thinking.toggle", options.onThinkingToggle);
|
|
192
198
|
if (options.onToolsExpand !== undefined)
|
|
@@ -230,6 +236,7 @@ export function createPiShellEditor(options) {
|
|
|
230
236
|
},
|
|
231
237
|
activateKeybindings: () => host.ensureActive(),
|
|
232
238
|
keybindingConfig: () => keybindings.getEffectiveConfig(),
|
|
239
|
+
matchesAction: (data, action) => keybindings.matches(data, action),
|
|
233
240
|
reloadKeybindings: () => host.reload(),
|
|
234
241
|
matchesTerminalKey: (data, key) => matchesKey(data, key),
|
|
235
242
|
handleInput: data => {
|
|
@@ -348,12 +355,11 @@ function autocompleteCommandSetter(options, editor, state, enabled) {
|
|
|
348
355
|
state.skills = collapsed.skills;
|
|
349
356
|
const additions = new Map(collapsed.commands.map(command => [command.name, command]));
|
|
350
357
|
const builtInNames = new Set(builtInCatalog.map(command => command.name));
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
...(command
|
|
355
|
-
|
|
356
|
-
]);
|
|
358
|
+
// Rationale: Skills is a primary command, independent of retired application commands.
|
|
359
|
+
const builtIns = [
|
|
360
|
+
...(collapsed.collapsedCommand === undefined ? [] : [autocompleteCommand(collapsed.collapsedCommand)]),
|
|
361
|
+
...builtInCatalog.map(command => autocompleteCommand(command, additions.get(command.name))),
|
|
362
|
+
];
|
|
357
363
|
const resources = collapsed.commands
|
|
358
364
|
.filter(command => command.name !== collapsed.collapsedCommand?.name && command.source !== "builtin" && !builtInNames.has(command.name))
|
|
359
365
|
.map(command => autocompleteCommand(command));
|
|
@@ -301,8 +301,9 @@ function expandedHeaderText(bindings) {
|
|
|
301
301
|
rawKeyHint(process.platform === "win32" ? "" : "ctrl+z", "to suspend"),
|
|
302
302
|
rawKeyHint("ctrl+k", "to delete to end"),
|
|
303
303
|
rawKeyHint(keys?.getKeys("app.thinking.cycle").join("/") ?? "shift+tab", "to cycle thinking level"),
|
|
304
|
-
rawKeyHint("ctrl+p/shift+ctrl+p", "to cycle models"),
|
|
305
|
-
|
|
304
|
+
rawKeyHint(keys === undefined ? "ctrl+p/shift+ctrl+p" : [...keys.getKeys("app.model.cycleForward"), ...keys.getKeys("app.model.cycleBackward")].join("/") || "unbound", "to cycle models"),
|
|
305
|
+
...(keys === undefined ? [] : [rawKeyHint(keys.getKeys("owned.apps.open").join("/") || "unbound", "to open Launcher")]),
|
|
306
|
+
// Invariant: only bare A1 supplies live bindings; unbound selection remains reachable through `/models`.
|
|
306
307
|
rawKeyHint(keys === undefined ? "ctrl+l" : keys.getKeys("app.model.select").join("/") || "/models", "to select model"),
|
|
307
308
|
rawKeyHint("ctrl+o", "to expand tools"),
|
|
308
309
|
rawKeyHint("ctrl+t", "to expand thinking"),
|
|
@@ -180,7 +180,7 @@ export function hotkeysMarkdown(bindings, getShortcuts, profile) {
|
|
|
180
180
|
? action === "app.model.select" ? "Unbound (`/models`)" : "Unbound"
|
|
181
181
|
: `\`${label}\``;
|
|
182
182
|
}).join(" / ")} | ${description} |`;
|
|
183
|
-
let markdown = ["**Navigation**", "| Key | Action |", "|-----|--------|", row(["tui.editor.cursorUp", "tui.editor.cursorDown", "tui.editor.cursorLeft", "tui.editor.cursorRight"], "Move cursor / browse history"), row(["tui.editor.cursorWordLeft", "tui.editor.cursorWordRight"], "Move by word"), row(["tui.editor.cursorLineStart"], profile === "a1" ? "Start of prompt line" : "Start of line"), row(["tui.editor.cursorLineEnd"], profile === "a1" ? "End of prompt line" : "End of line"), ...(profile === "a1" ? ["| `Ctrl+Home` | Start of content |", "| `Ctrl+End` | End of content / follow output |"] : []), row(["tui.editor.jumpForward"], "Jump forward to character"), row(["tui.editor.jumpBackward"], "Jump backward to character"), row(["tui.editor.pageUp", "tui.editor.pageDown"], "Scroll by page"), "", "**Editing**", "| Key | Action |", "|-----|--------|", row(["tui.input.submit"], "Send message"), row(["tui.input.newLine"], `New line${process.platform === "win32" ? " (Ctrl+Enter on Windows Terminal)" : ""}`), row(["tui.editor.deleteWordBackward"], "Delete word backwards"), row(["tui.editor.deleteWordForward"], "Delete word forwards"), row(["tui.editor.deleteToLineStart"], "Delete to start of line"), row(["tui.editor.deleteToLineEnd"], "Delete to end of line"), row(["tui.editor.yank"], "Paste the most-recently-deleted text"), row(["tui.editor.yankPop"], "Cycle through the deleted text after pasting"), row(["tui.editor.undo"], "Undo"), "", "**Other**", "| Key | Action |", "|-----|--------|", row(["tui.input.tab"], "Path completion / accept autocomplete"), row(["app.interrupt"], "Cancel autocomplete / abort streaming"), row(["app.clear"], "Clear editor (first) / exit (second)"), row(["app.exit"], "Exit (when editor is empty)"), row(["app.suspend"], "Suspend to background"), row(["app.thinking.cycle"], "Cycle thinking level"), row(["app.model.cycleForward", "app.model.cycleBackward"], "Cycle models"), row(["app.model.select"], profile === "a1" ? "Open the Models
|
|
183
|
+
let markdown = ["**Navigation**", "| Key | Action |", "|-----|--------|", row(["tui.editor.cursorUp", "tui.editor.cursorDown", "tui.editor.cursorLeft", "tui.editor.cursorRight"], "Move cursor / browse history"), row(["tui.editor.cursorWordLeft", "tui.editor.cursorWordRight"], "Move by word"), row(["tui.editor.cursorLineStart"], profile === "a1" ? "Start of prompt line" : "Start of line"), row(["tui.editor.cursorLineEnd"], profile === "a1" ? "End of prompt line" : "End of line"), ...(profile === "a1" ? ["| `Ctrl+Home` | Start of content |", "| `Ctrl+End` | End of content / follow output |"] : []), row(["tui.editor.jumpForward"], "Jump forward to character"), row(["tui.editor.jumpBackward"], "Jump backward to character"), row(["tui.editor.pageUp", "tui.editor.pageDown"], "Scroll by page"), "", "**Editing**", "| Key | Action |", "|-----|--------|", row(["tui.input.submit"], "Send message"), row(["tui.input.newLine"], `New line${process.platform === "win32" ? " (Ctrl+Enter on Windows Terminal)" : ""}`), row(["tui.editor.deleteWordBackward"], "Delete word backwards"), row(["tui.editor.deleteWordForward"], "Delete word forwards"), row(["tui.editor.deleteToLineStart"], "Delete to start of line"), row(["tui.editor.deleteToLineEnd"], "Delete to end of line"), row(["tui.editor.yank"], "Paste the most-recently-deleted text"), row(["tui.editor.yankPop"], "Cycle through the deleted text after pasting"), row(["tui.editor.undo"], "Undo"), "", "**Other**", "| Key | Action |", "|-----|--------|", row(["tui.input.tab"], "Path completion / accept autocomplete"), row(["app.interrupt"], "Cancel autocomplete / abort streaming"), row(["app.clear"], "Clear editor (first) / exit (second)"), row(["app.exit"], "Exit (when editor is empty)"), row(["app.suspend"], "Suspend to background"), row(["app.thinking.cycle"], "Cycle thinking level"), row(["app.model.cycleForward", "app.model.cycleBackward"], "Cycle models"), row(["app.model.select"], profile === "a1" ? "Open the in-place Models selector (`/models`)" : "Open model selector"), ...(profile === "a1" ? [row(["owned.apps.open"], "Open Launcher (Agent, Settings, Changelog, Hotkeys)")] : []), row(["app.tools.expand"], "Toggle tool output expansion"), row(["app.thinking.toggle"], "Toggle thinking block visibility"), row(["app.editor.external"], "Edit message in external editor"), row(["app.message.copy"], "Copy selection or last assistant message"), row(["app.message.followUp"], "Queue follow-up message"), row(["app.message.dequeue"], "Restore queued messages"), row(["app.clipboard.pasteImage"], profile === "a1" ? "Paste image or text from clipboard" : "Paste files on macOS, images, or text from clipboard"), "| `/` | Slash commands |", "| `!` | Run bash command |", "| `!!` | Run bash command (excluded from context) |", ...(profile === "a1" ? ["", "Legacy Ctrl+M that is indistinguishable from Enter keeps Enter behavior; use `/models` to select a model.", "", "**Models dialog**", "| Key | Action |", "|-----|--------|", "| `Space` | Toggle the selected model in the cycling scope |", "| `Tab` | Switch the all/scoped filter |", row(["app.models.save"], "Save the scope to settings"), row(["app.models.enableAll"], "Scope every listed model"), row(["app.models.clearAll"], "Clear the listed models from the scope"), row(["app.models.toggleProvider"], "Toggle the selected model's provider"), row(["app.models.reorderUp", "app.models.reorderDown"], "Reorder the cycling scope")] : [])].join("\n");
|
|
184
184
|
const shortcuts = getShortcuts(bindings ?? keys.getEffectiveConfig());
|
|
185
185
|
if (shortcuts.length > 0) {
|
|
186
186
|
markdown += "\n\n**Extensions**\n| Key | Action |\n|-----|--------|\n";
|
|
@@ -206,7 +206,9 @@ function transcriptComponent(block, cwd, expanded, extensions, submittedPrompt,
|
|
|
206
206
|
summary: block.text,
|
|
207
207
|
tokensBefore: numericPayload(block, "tokensBefore"),
|
|
208
208
|
timestamp: numericPayload(block, "timestamp") || 0,
|
|
209
|
-
}, getPiMarkdownTheme()
|
|
209
|
+
}, getPiMarkdownTheme(), outputPad, [
|
|
210
|
+
createMermaidMarkdownTransformer({ getMode: () => mermaidRenderingMode, theme: piTheme() }),
|
|
211
|
+
], block.id);
|
|
210
212
|
component.setExpanded(expanded);
|
|
211
213
|
return component;
|
|
212
214
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { ModelSelectorComponent, type SessionInfo, type SettingsCallbacks, type SettingsConfig } from "../startup-public.js";
|
|
2
2
|
import type { OwnedUiDialog } from "../../../contracts/owned-ui/index.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import type { ModelsDialogCallbacks, ModelsDialogConfig } from "./models-dialog.js";
|
|
4
|
+
import type { TrustDecision, TrustOption, TrustUpdate } from "./upstream/components/trust-selector.js";
|
|
5
5
|
import { type PiShellComponentPort, type PiShellEditorOptions, type PiShellSelectorOption, type PiShellSelectorOptions } from "./shell-shared-facade.js";
|
|
6
|
-
export { createPiShellSkillsSelector
|
|
7
|
-
export
|
|
6
|
+
export { createPiShellSkillsSelector } from "./deferred-selector.js";
|
|
7
|
+
export type { PiShellSkillsSelectorOptions } from "./skills-dialog.js";
|
|
8
|
+
export declare function createPiShellSelector(options: PiShellSelectorOptions, standard?: boolean): PiShellComponentPort;
|
|
8
9
|
export interface PiShellSettingsSelectorOptions {
|
|
9
10
|
readonly config: SettingsConfig;
|
|
10
11
|
readonly onChange: (callback: keyof SettingsCallbacks, value: unknown) => void;
|
|
@@ -13,6 +14,7 @@ export interface PiShellSettingsSelectorOptions {
|
|
|
13
14
|
export declare function createPiShellSettingsSelector(options: PiShellSettingsSelectorOptions): PiShellComponentPort;
|
|
14
15
|
type PiModelSelectorArguments = ConstructorParameters<typeof ModelSelectorComponent>;
|
|
15
16
|
export interface PiShellModelSelectorOptions {
|
|
17
|
+
readonly standardStyle?: boolean;
|
|
16
18
|
readonly currentModel: unknown;
|
|
17
19
|
readonly modelRuntime: unknown;
|
|
18
20
|
readonly scopedModels: readonly unknown[];
|
|
@@ -50,6 +52,7 @@ export declare function createPiShellScopedModelsSelector(options: PiShellScoped
|
|
|
50
52
|
export interface PiShellModelsDialogOptions extends ModelsDialogConfig, ModelsDialogCallbacks {
|
|
51
53
|
}
|
|
52
54
|
export interface PiShellModelsDialogPort extends PiShellComponentPort {
|
|
55
|
+
readonly ready?: Promise<void>;
|
|
53
56
|
updateModels(models: readonly PiShellScopedModelDescriptor[]): void;
|
|
54
57
|
setRefreshStatus(message: string, kind: "muted" | "success" | "warning"): void;
|
|
55
58
|
readonly dirty: () => boolean;
|
|
@@ -57,6 +60,7 @@ export interface PiShellModelsDialogPort extends PiShellComponentPort {
|
|
|
57
60
|
/** The bare-A1 unified Models dialog behind the owned component boundary; the pinned selectors above stay for `a1 pi`. */
|
|
58
61
|
export declare function createPiShellModelsDialog(options: PiShellModelsDialogOptions): PiShellModelsDialogPort;
|
|
59
62
|
export declare function createPiShellTrustSelector(options: {
|
|
63
|
+
readonly standardStyle?: boolean;
|
|
60
64
|
readonly cwd: string;
|
|
61
65
|
readonly savedDecision: TrustDecision | null;
|
|
62
66
|
readonly projectTrusted: boolean;
|
|
@@ -90,7 +94,7 @@ export declare function createPiShellTreeSelector(options: {
|
|
|
90
94
|
readonly initialSelectedId?: string;
|
|
91
95
|
readonly initialFilterMode?: "default" | "no-tools" | "user-only" | "labeled-only" | "all";
|
|
92
96
|
}): Promise<PiShellComponentPort>;
|
|
93
|
-
export declare function createPiShellUserMessageSelector(messages: readonly PiShellSelectorOption[], onSelect: (id: string) => void, onCancel: () => void, initialSelectedId?: string): PiShellComponentPort;
|
|
97
|
+
export declare function createPiShellUserMessageSelector(messages: readonly PiShellSelectorOption[], onSelect: (id: string) => void, onCancel: () => void, initialSelectedId?: string, standard?: boolean): PiShellComponentPort;
|
|
94
98
|
export interface PiShellLoginDialogPort extends PiShellComponentPort {
|
|
95
99
|
showAuth(url: string, instructions?: string): void;
|
|
96
100
|
showDeviceCode(info: {
|
|
@@ -107,7 +111,7 @@ export interface PiShellLoginDialogPort extends PiShellComponentPort {
|
|
|
107
111
|
showWaiting(message: string): void;
|
|
108
112
|
showProgress(message: string): void;
|
|
109
113
|
}
|
|
110
|
-
export declare function createPiShellLoginDialog(runtime: Pick<PiShellEditorOptions, "getColumns" | "getRows" | "requestRender">, providerId: string, onComplete: (success: boolean, message?: string) => void, providerName?: string, title?: string): PiShellLoginDialogPort;
|
|
114
|
+
export declare function createPiShellLoginDialog(runtime: Pick<PiShellEditorOptions, "getColumns" | "getRows" | "requestRender">, providerId: string, onComplete: (success: boolean, message?: string) => void, providerName?: string, title?: string, standard?: boolean): PiShellLoginDialogPort;
|
|
111
115
|
export declare function createPiShellArmin(runtime: Pick<PiShellEditorOptions, "getColumns" | "getRows" | "requestRender">): PiShellComponentPort;
|
|
112
116
|
export declare function createPiShellEarendilAnnouncement(): PiShellComponentPort;
|
|
113
117
|
export declare function createPiShellReloadBox(): PiShellComponentPort;
|
|
@@ -119,11 +123,11 @@ export interface PiShellAuthProviderOption extends PiShellSelectorOption {
|
|
|
119
123
|
readonly source?: string;
|
|
120
124
|
};
|
|
121
125
|
}
|
|
122
|
-
export declare function createPiShellAuthProviderSelector(mode: "login" | "logout", providers: readonly PiShellAuthProviderOption[], onSelect: (id: string) => void, onCancel: () => void, initialSearchInput?: string): PiShellComponentPort;
|
|
123
|
-
export declare function createPiShellExtensionSelector(title: string, options: readonly string[], onSelect: (value: string) => void, onCancel: () => void): PiShellComponentPort;
|
|
126
|
+
export declare function createPiShellAuthProviderSelector(mode: "login" | "logout", providers: readonly PiShellAuthProviderOption[], onSelect: (id: string) => void, onCancel: () => void, initialSearchInput?: string, standardStyle?: boolean): PiShellComponentPort;
|
|
127
|
+
export declare function createPiShellExtensionSelector(title: string, options: readonly string[], onSelect: (value: string) => void, onCancel: () => void, standardSelection?: boolean): PiShellComponentPort;
|
|
124
128
|
export declare function createPiShellThemeSelector(currentTheme: string, onSelect: (theme: string) => void, onCancel: () => void, onPreview: (theme: string) => void): PiShellComponentPort;
|
|
125
129
|
export declare function createPiShellShowImagesSelector(currentValue: boolean, onSelect: (show: boolean) => void, onCancel: () => void): PiShellComponentPort;
|
|
126
130
|
export declare function createPiShellDialog(dialog: OwnedUiDialog, handlers?: {
|
|
127
131
|
readonly onSelect?: (id: string) => void;
|
|
128
132
|
readonly onCancel?: () => void;
|
|
129
|
-
}): PiShellComponentPort;
|
|
133
|
+
}, standard?: boolean): PiShellComponentPort;
|
|
@@ -3,13 +3,14 @@ import { EarendilAnnouncementComponent } from "./upstream/components/earendil-an
|
|
|
3
3
|
import { ExtensionSelectorComponent } from "./upstream/components/extension-selector.js";
|
|
4
4
|
import { Box, Container, SelectList, Spacer, Text, } from "@earendil-works/pi-tui";
|
|
5
5
|
import { ScopedModelsSelectorComponent } from "./upstream/components/scoped-models-selector.js";
|
|
6
|
-
import { addPiModalSelectFooter, adoptPiModalFrame, adoptPiModalHeader, adoptPiModalSearchInput } from "./modal-frame.js";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
6
|
+
import { addPiModalSelectFooter, adoptPiModalFrame, adoptPiModalHeader, adoptPiModalSearchInput, renderPiModalSelectedPrimary, standardInternalChoicePort } from "./modal-frame.js";
|
|
7
|
+
import { deferredLoginDialog } from "./login-dialog-loader.js";
|
|
8
|
+
import { deferredSelector } from "./deferred-selector.js";
|
|
9
|
+
import { createDeferredModelsDialog } from "./models-dialog-loader.js";
|
|
10
|
+
import { canonicalizePiSettingsHint, DIALOG_CLOSE_SHORTCUT_HINT, PINNED_PI_LAYOUT, getPiSelectListTheme, paintPiBorder, piTheme, renderPiModalShortcutHints, internalDialogTitle, } from "./theme.js";
|
|
10
11
|
import { componentFromPort, componentPort, createTuiFacade, ensureTheme, isRecord, } from "./shell-shared-facade.js";
|
|
11
|
-
export { createPiShellSkillsSelector } from "./
|
|
12
|
-
export function createPiShellSelector(options) {
|
|
12
|
+
export { createPiShellSkillsSelector } from "./deferred-selector.js";
|
|
13
|
+
export function createPiShellSelector(options, standard = false) {
|
|
13
14
|
ensureTheme();
|
|
14
15
|
const items = options.options.map(toSelectItem);
|
|
15
16
|
const list = new SelectList(items, options.maxVisible ?? Math.min(PINNED_PI_LAYOUT.selectorMaxVisible, Math.max(1, items.length)), getPiSelectListTheme());
|
|
@@ -17,11 +18,11 @@ export function createPiShellSelector(options) {
|
|
|
17
18
|
list.onSelect = item => options.onSelect?.(item.value);
|
|
18
19
|
if (options.onCancel !== undefined)
|
|
19
20
|
list.onCancel = options.onCancel;
|
|
20
|
-
if (!options.title && options.onCancel === undefined)
|
|
21
|
+
if (!options.title && options.onCancel === undefined && !standard)
|
|
21
22
|
return componentPort(list);
|
|
22
23
|
const container = new Container();
|
|
23
24
|
if (options.title)
|
|
24
|
-
container.addChild(new Text(piTheme().fg("accent", piTheme().bold(options.title)), PINNED_PI_LAYOUT.contentPaddingX, 0));
|
|
25
|
+
container.addChild(new Text(piTheme().fg("accent", piTheme().bold(standard ? internalDialogTitle(options.title) : options.title)), PINNED_PI_LAYOUT.contentPaddingX, 0));
|
|
25
26
|
container.addChild(list);
|
|
26
27
|
if (options.onCancel !== undefined) {
|
|
27
28
|
container.addChild(new Spacer(1));
|
|
@@ -31,7 +32,8 @@ export function createPiShellSelector(options) {
|
|
|
31
32
|
DIALOG_CLOSE_SHORTCUT_HINT,
|
|
32
33
|
]), 0, 0));
|
|
33
34
|
}
|
|
34
|
-
|
|
35
|
+
const port = componentPort(container, data => list.handleInput(data));
|
|
36
|
+
return standard ? { ...port, render: width => port.render(width).map(row => renderPiModalSelectedPrimary(` ${row}`, width + 1, options.options.map(option => option.label)).slice(1)) } : port;
|
|
35
37
|
}
|
|
36
38
|
export function createPiShellSettingsSelector(options) {
|
|
37
39
|
ensureTheme();
|
|
@@ -98,7 +100,8 @@ export function createPiShellModelSelector(options) {
|
|
|
98
100
|
const selector = new ModelSelectorComponent(createTuiFacade(options.runtime), options.currentModel, options.modelRuntime, options.scopedModels, options.onSelect, options.onCancel, options.initialSearchInput, options.onSelectAsDefault, options.defaultModel);
|
|
99
101
|
adoptPiModalSearchInput(selector, selector.getSearchInput());
|
|
100
102
|
adoptPiModalFrame(selector, { topIndex: 0, bottomIndex: selector.children.length - 1 });
|
|
101
|
-
|
|
103
|
+
const port = componentPort(selector);
|
|
104
|
+
return options.standardStyle ? standardInternalChoicePort(port, true) : port;
|
|
102
105
|
}
|
|
103
106
|
function toPiScopedModel(model) {
|
|
104
107
|
const candidate = { provider: model.provider, id: model.id, name: model.name };
|
|
@@ -133,17 +136,12 @@ export function createPiShellScopedModelsSelector(options) {
|
|
|
133
136
|
/** The bare-A1 unified Models dialog behind the owned component boundary; the pinned selectors above stay for `a1 pi`. */
|
|
134
137
|
export function createPiShellModelsDialog(options) {
|
|
135
138
|
ensureTheme();
|
|
136
|
-
|
|
137
|
-
return {
|
|
138
|
-
...componentPort(dialog),
|
|
139
|
-
updateModels: models => dialog.updateModels(models),
|
|
140
|
-
setRefreshStatus: (message, kind) => dialog.setRefreshStatus(message, kind),
|
|
141
|
-
dirty: () => dialog.dirty,
|
|
142
|
-
};
|
|
139
|
+
return createDeferredModelsDialog(options);
|
|
143
140
|
}
|
|
144
141
|
export function createPiShellTrustSelector(options) {
|
|
145
142
|
ensureTheme();
|
|
146
|
-
return
|
|
143
|
+
return deferredSelector(() => import("./upstream/components/trust-selector.js")
|
|
144
|
+
.then(({ TrustSelectorComponent }) => componentPort(new TrustSelectorComponent(options))), options.onCancel);
|
|
147
145
|
}
|
|
148
146
|
export async function createPiShellSessionSelector(options) {
|
|
149
147
|
ensureTheme();
|
|
@@ -159,21 +157,26 @@ export async function createPiShellTreeSelector(options) {
|
|
|
159
157
|
selector.onCopy = options.onCopy;
|
|
160
158
|
return componentPort(selector);
|
|
161
159
|
}
|
|
162
|
-
export function createPiShellUserMessageSelector(messages, onSelect, onCancel, initialSelectedId) {
|
|
160
|
+
export function createPiShellUserMessageSelector(messages, onSelect, onCancel, initialSelectedId, standard = false) {
|
|
163
161
|
ensureTheme();
|
|
164
162
|
const selector = new UserMessageSelectorComponent(messages.map(message => ({ id: message.id, text: message.label })), onSelect, onCancel, initialSelectedId);
|
|
165
163
|
const list = selector.getMessageList();
|
|
164
|
+
if (standard)
|
|
165
|
+
selector.children[1] = new Text(piTheme().fg("accent", piTheme().bold("Fork from Message")), 1, 0);
|
|
166
166
|
addPiModalSelectFooter(selector);
|
|
167
167
|
adoptPiModalFrame(selector, { topIndex: 4, bottomIndex: selector.children.length - 1 });
|
|
168
|
-
|
|
168
|
+
const port = componentPort(selector, data => list.handleInput(data));
|
|
169
|
+
return standard ? standardInternalChoicePort(port) : port;
|
|
169
170
|
}
|
|
170
|
-
export function createPiShellLoginDialog(runtime, providerId, onComplete, providerName, title) {
|
|
171
|
+
export function createPiShellLoginDialog(runtime, providerId, onComplete, providerName, title, standard = false) {
|
|
171
172
|
ensureTheme();
|
|
173
|
+
if (standard)
|
|
174
|
+
return deferredLoginDialog(runtime, providerId, onComplete, providerName, title);
|
|
172
175
|
const dialog = new LoginDialogComponent(createTuiFacade(runtime), providerId, onComplete, providerName, title);
|
|
173
176
|
const preInsetTitle = dialog.children[1];
|
|
174
177
|
const content = dialog.children[2];
|
|
175
178
|
dialog.children.splice(dialog.children.length - 1, 0, new Spacer(1), new Text(renderPiModalShortcutHints([DIALOG_CLOSE_SHORTCUT_HINT]), 0, 0));
|
|
176
|
-
const
|
|
179
|
+
const stripHint = (result) => { content.children.pop(); return result; };
|
|
177
180
|
const header = adoptPiModalHeader(dialog, 0, 1);
|
|
178
181
|
adoptPiModalFrame(dialog, {
|
|
179
182
|
topIndex: 0,
|
|
@@ -185,23 +188,12 @@ export function createPiShellLoginDialog(runtime, providerId, onComplete, provid
|
|
|
185
188
|
...componentPort(dialog),
|
|
186
189
|
showAuth: (url, instructions) => dialog.showAuth(url, instructions),
|
|
187
190
|
showDeviceCode: info => dialog.showDeviceCode(info),
|
|
188
|
-
showManualInput(message)
|
|
189
|
-
|
|
190
|
-
removeDependencyHint();
|
|
191
|
-
return result;
|
|
192
|
-
},
|
|
193
|
-
showPrompt(message, placeholder) {
|
|
194
|
-
const result = dialog.showPrompt(message, placeholder);
|
|
195
|
-
removeDependencyHint();
|
|
196
|
-
return result;
|
|
197
|
-
},
|
|
191
|
+
showManualInput: message => stripHint(dialog.showManualInput(message)),
|
|
192
|
+
showPrompt: (message, placeholder) => stripHint(dialog.showPrompt(message, placeholder)),
|
|
198
193
|
showDetails: lines => dialog.showDetails([...lines]),
|
|
199
|
-
// Rationale:
|
|
194
|
+
// Rationale: one footer replaces optional hints.
|
|
200
195
|
showInfo: (message, links = []) => dialog.showInfo(message, [...links], false),
|
|
201
|
-
showWaiting(message)
|
|
202
|
-
dialog.showWaiting(message);
|
|
203
|
-
removeDependencyHint();
|
|
204
|
-
},
|
|
196
|
+
showWaiting: message => stripHint(dialog.showWaiting(message)),
|
|
205
197
|
showProgress: message => dialog.showProgress(message),
|
|
206
198
|
};
|
|
207
199
|
}
|
|
@@ -224,8 +216,11 @@ export function createPiShellReloadBox() {
|
|
|
224
216
|
adoptPiModalFrame(container, { topIndex: 0, bottomIndex: container.children.length - 1 });
|
|
225
217
|
return componentPort(container);
|
|
226
218
|
}
|
|
227
|
-
export function createPiShellAuthProviderSelector(mode, providers, onSelect, onCancel, initialSearchInput) {
|
|
219
|
+
export function createPiShellAuthProviderSelector(mode, providers, onSelect, onCancel, initialSearchInput, standardStyle = false) {
|
|
228
220
|
ensureTheme();
|
|
221
|
+
if (standardStyle)
|
|
222
|
+
return deferredSelector(() => import("./upstream/components/oauth-selector.js")
|
|
223
|
+
.then(({ AuthProviderSelector }) => componentPort(new AuthProviderSelector(mode, providers, onSelect, onCancel, initialSearchInput))), onCancel);
|
|
229
224
|
const selector = new OAuthSelectorComponent(mode, providers.map(provider => ({
|
|
230
225
|
id: provider.providerId,
|
|
231
226
|
name: provider.label,
|
|
@@ -236,7 +231,7 @@ export function createPiShellAuthProviderSelector(mode, providers, onSelect, onC
|
|
|
236
231
|
if (selected)
|
|
237
232
|
onSelect(selected.id);
|
|
238
233
|
}, onCancel, initialSearchInput);
|
|
239
|
-
// Provenance:
|
|
234
|
+
// Provenance: public search slot 4.
|
|
240
235
|
adoptPiModalSearchInput(selector, selector.children[4]);
|
|
241
236
|
addPiModalSelectFooter(selector);
|
|
242
237
|
const preInsetContent = [selector.children[2], selector.children[6]];
|
|
@@ -249,9 +244,9 @@ export function createPiShellAuthProviderSelector(mode, providers, onSelect, onC
|
|
|
249
244
|
});
|
|
250
245
|
return componentPort(selector);
|
|
251
246
|
}
|
|
252
|
-
export function createPiShellExtensionSelector(title, options, onSelect, onCancel) {
|
|
247
|
+
export function createPiShellExtensionSelector(title, options, onSelect, onCancel, standardSelection = false) {
|
|
253
248
|
ensureTheme();
|
|
254
|
-
return componentPort(new ExtensionSelectorComponent(title, [...options], onSelect, onCancel));
|
|
249
|
+
return componentPort(new ExtensionSelectorComponent(standardSelection ? internalDialogTitle(title) : title, [...options], onSelect, onCancel, { standardSelection }));
|
|
255
250
|
}
|
|
256
251
|
export function createPiShellThemeSelector(currentTheme, onSelect, onCancel, onPreview) {
|
|
257
252
|
ensureTheme();
|
|
@@ -269,7 +264,7 @@ export function createPiShellShowImagesSelector(currentValue, onSelect, onCancel
|
|
|
269
264
|
adoptPiModalFrame(selector, { topIndex: 0, bottomIndex: selector.children.length - 1 });
|
|
270
265
|
return componentPort(selector, data => list.handleInput(data));
|
|
271
266
|
}
|
|
272
|
-
export function createPiShellDialog(dialog, handlers = {}) {
|
|
267
|
+
export function createPiShellDialog(dialog, handlers = {}, standard = false) {
|
|
273
268
|
ensureTheme();
|
|
274
269
|
const selector = createPiShellSelector({
|
|
275
270
|
title: dialog.title,
|
|
@@ -277,7 +272,7 @@ export function createPiShellDialog(dialog, handlers = {}) {
|
|
|
277
272
|
maxVisible: 8,
|
|
278
273
|
...(handlers.onSelect === undefined ? {} : { onSelect: handlers.onSelect }),
|
|
279
274
|
...(handlers.onCancel === undefined ? {} : { onCancel: handlers.onCancel }),
|
|
280
|
-
});
|
|
275
|
+
}, standard);
|
|
281
276
|
const box = new Box(1, 1);
|
|
282
277
|
box.addChild(componentFromPort(selector));
|
|
283
278
|
return componentPort(box, data => selector.handleInput?.(data));
|
|
@@ -6,6 +6,6 @@ interface PiShellSessionInfoReferenceDocument {
|
|
|
6
6
|
readonly rows: readonly string[];
|
|
7
7
|
}[];
|
|
8
8
|
}
|
|
9
|
-
/** Renders
|
|
9
|
+
/** Renders complete report data in semantic rows sharing a left-aligned value column. */
|
|
10
10
|
export declare function renderPiShellSessionInfoReferenceDocument(presentation: PiShellSessionInfoPresentation, width: number): PiShellSessionInfoReferenceDocument;
|
|
11
11
|
export {};
|
|
@@ -14,7 +14,7 @@ function splitSessionFile(sessionFile, firstWidth, continuationWidth) {
|
|
|
14
14
|
rowWidth = continuationWidth;
|
|
15
15
|
continue;
|
|
16
16
|
}
|
|
17
|
-
// Compatibility:
|
|
17
|
+
// Compatibility: preserve a wide grapheme even when the outer frame cannot fit it.
|
|
18
18
|
if (!row)
|
|
19
19
|
row = sliceByColumn(remaining, 0, rowWidth);
|
|
20
20
|
rows.push(row);
|
|
@@ -23,72 +23,75 @@ function splitSessionFile(sessionFile, firstWidth, continuationWidth) {
|
|
|
23
23
|
}
|
|
24
24
|
return rows.length > 0 ? rows : [""];
|
|
25
25
|
}
|
|
26
|
-
/**
|
|
27
|
-
function sessionFileRows(sessionFile, width) {
|
|
28
|
-
// Compatibility: match Text's reduced-padding rule so these explicit breaks survive its renderer.
|
|
29
|
-
const paddingX = Math.min(1, Math.max(0, Math.floor((width - 1) / 2)));
|
|
30
|
-
const contentWidth = Math.max(1, width - paddingX * 2);
|
|
31
|
-
const label = piTheme().fg("dim", "File:");
|
|
32
|
-
const firstValueWidth = Math.max(0, contentWidth - visibleWidth("File: "));
|
|
33
|
-
const [first = "", ...continuation] = splitSessionFile(sessionFile, firstValueWidth, contentWidth);
|
|
34
|
-
return firstValueWidth > 0
|
|
35
|
-
? [`${label} ${first}`, ...continuation]
|
|
36
|
-
: [label, ...continuation];
|
|
37
|
-
}
|
|
38
|
-
/** Renders the pinned report values while leaving group names semantic for the owned screen. */
|
|
26
|
+
/** Renders complete report data in semantic rows sharing a left-aligned value column. */
|
|
39
27
|
export function renderPiShellSessionInfoReferenceDocument(presentation, width) {
|
|
40
28
|
ensureTheme();
|
|
41
29
|
const { stats, sessionName, cacheWaste, usageBreakdown, cacheWarming } = presentation;
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
`${piTheme().fg("dim", "ID:")} ${stats.sessionId}`,
|
|
30
|
+
const identity = [
|
|
31
|
+
...(sessionName ? [{ label: "Name:", value: sessionName }] : []),
|
|
32
|
+
{ label: "File:", value: stats.sessionFile ?? "In-memory" },
|
|
33
|
+
{ label: "ID:", value: stats.sessionId },
|
|
47
34
|
];
|
|
48
35
|
const messages = [
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
36
|
+
{ label: "Total:", value: String(stats.totalMessages) },
|
|
37
|
+
{ label: "User:", value: String(stats.userMessages) },
|
|
38
|
+
{ label: "Assistant:", value: String(stats.assistantMessages) },
|
|
39
|
+
{ label: "Tools:", value: `${stats.toolCalls} calls, ${stats.toolResults} results` },
|
|
53
40
|
];
|
|
54
41
|
const { input, cacheRead, cacheWrite } = stats.tokens;
|
|
55
42
|
const promptTokens = input + cacheRead + cacheWrite;
|
|
56
|
-
const tokens = [
|
|
43
|
+
const tokens = [{ label: "Input:", value: promptTokens.toLocaleString() }];
|
|
57
44
|
if (promptTokens > 0 && (cacheRead > 0 || cacheWrite > 0)) {
|
|
58
|
-
tokens.push(
|
|
45
|
+
tokens.push({ label: "Cached:", indent: 2, value: `${cacheRead.toLocaleString()} ${piTheme().fg("dim", `(${((cacheRead / promptTokens) * 100).toFixed(1)}%)`)}` });
|
|
59
46
|
const written = cacheWrite > 0 ? ` ${piTheme().fg("dim", `(${cacheWrite.toLocaleString()} written to cache)`)}` : "";
|
|
60
|
-
tokens.push(
|
|
47
|
+
tokens.push({ label: "Uncached:", indent: 2, value: `${(input + cacheWrite).toLocaleString()}${written}` });
|
|
61
48
|
}
|
|
62
|
-
tokens.push(
|
|
63
|
-
tokens.push(
|
|
49
|
+
tokens.push({ label: "Output:", value: stats.tokens.output.toLocaleString() });
|
|
50
|
+
tokens.push({ label: "Total:", value: stats.tokens.total.toLocaleString() });
|
|
64
51
|
const warmingStatus = cacheWarming.status;
|
|
65
52
|
const warming = [
|
|
66
|
-
|
|
67
|
-
|
|
53
|
+
{ label: "Mode:", value: cacheWarming.mode },
|
|
54
|
+
{ label: "Status:", value: warmingStatus ? formatCacheWarmingStatus(warmingStatus) : "Inactive (cache warming unavailable)" },
|
|
68
55
|
];
|
|
69
|
-
const
|
|
70
|
-
if (
|
|
71
|
-
warming.push(
|
|
72
|
-
warming.push(
|
|
56
|
+
const decision = warmingStatus?.decision;
|
|
57
|
+
if (decision?.economicsAvailable) {
|
|
58
|
+
warming.push({ label: "Cache miss penalty:", value: `$${decision.missCost.toFixed(3)}` });
|
|
59
|
+
warming.push({ label: "Refresh cost:", value: `$${decision.warmCost.toFixed(3)}` });
|
|
73
60
|
}
|
|
74
|
-
const
|
|
75
|
-
{ title: "Messages", rows: render(messages) },
|
|
76
|
-
{ title: "Tokens", rows: render(tokens) },
|
|
77
|
-
{ title: "Cache Warming", rows: render(warming) },
|
|
78
|
-
];
|
|
61
|
+
const groups = [{ title: "Messages", rows: messages }, { title: "Tokens", rows: tokens }, { title: "Cache Warming", rows: warming }];
|
|
79
62
|
if (stats.cost > 0 || cacheWaste.missedTokens > 0) {
|
|
80
|
-
const cost = [
|
|
63
|
+
const cost = [{ label: "Total:", value: `$${stats.cost.toFixed(3)}` }];
|
|
81
64
|
if (usageBreakdown.length > 1)
|
|
82
65
|
for (const entry of usageBreakdown) {
|
|
83
|
-
cost.push(
|
|
66
|
+
cost.push({ label: `${entry.key}:`, indent: 2, value: `$${entry.cost.toFixed(3)} ${piTheme().fg("dim", `(${formatSessionTokens(entry.tokens)} tokens)`)}` });
|
|
84
67
|
}
|
|
85
68
|
if (cacheWaste.missedTokens > 0) {
|
|
86
69
|
const detail = `${cacheWaste.missedTokens.toLocaleString()} tokens, ${cacheWaste.missCount === 1 ? "1 miss" : `${cacheWaste.missCount} misses`}`;
|
|
87
|
-
cost.push(cacheWaste.missedCost >= 0.0001
|
|
88
|
-
|
|
89
|
-
|
|
70
|
+
cost.push({ label: "Cache Re-billed:", value: cacheWaste.missedCost >= 0.0001
|
|
71
|
+
? `$${cacheWaste.missedCost.toFixed(3)} ${piTheme().fg("dim", `(${detail})`)}` : detail });
|
|
72
|
+
}
|
|
73
|
+
groups.push({ title: "Cost", rows: cost });
|
|
74
|
+
}
|
|
75
|
+
// Compatibility: match Text's reduced-padding rule so explicit path breaks survive rendering.
|
|
76
|
+
const padding = Math.min(1, Math.max(0, Math.floor((width - 1) / 2)));
|
|
77
|
+
const contentWidth = Math.max(1, width - padding * 2);
|
|
78
|
+
const allRows = [...identity, ...groups.flatMap(group => group.rows)];
|
|
79
|
+
const column = Math.min(Math.max(...allRows.map(row => (row.indent ?? 0) + visibleWidth(row.label))) + 1, contentWidth - 1);
|
|
80
|
+
const prefix = (row) => `${" ".repeat(row.indent ?? 0)}${piTheme().fg("dim", row.label)}${" ".repeat(Math.max(1, column - (row.indent ?? 0) - visibleWidth(row.label)))}`;
|
|
81
|
+
const render = (rows) => new Text(rows.map(row => `${prefix(row)}${row.value}`).join("\n"), 1, 0).render(width);
|
|
82
|
+
const preamble = [];
|
|
83
|
+
for (const row of identity) {
|
|
84
|
+
if (row.label !== "File:") {
|
|
85
|
+
preamble.push(`${prefix(row)}${row.value}`);
|
|
86
|
+
continue;
|
|
90
87
|
}
|
|
91
|
-
|
|
88
|
+
const label = prefix(row);
|
|
89
|
+
const firstWidth = Math.max(0, contentWidth - visibleWidth(label));
|
|
90
|
+
const [first = "", ...continuation] = splitSessionFile(row.value, firstWidth, contentWidth);
|
|
91
|
+
preamble.push(firstWidth > 0 ? `${label}${first}` : piTheme().fg("dim", row.label), ...continuation);
|
|
92
92
|
}
|
|
93
|
-
return {
|
|
93
|
+
return {
|
|
94
|
+
preamble: new Text(preamble.join("\n"), 1, 0).render(width),
|
|
95
|
+
sections: groups.map(group => ({ title: group.title, rows: render(group.rows) })),
|
|
96
|
+
};
|
|
94
97
|
}
|
|
@@ -2,6 +2,8 @@ import { DIALOG_CLOSE_SHORTCUT_HINT, displayShortcutKeyLabel, type SemanticShort
|
|
|
2
2
|
import { type MarkdownTheme, type SelectListTheme } from "@earendil-works/pi-tui";
|
|
3
3
|
export { PINNED_PI_LAYOUT, applyPiTheme, applyPiThemeInstance, currentPiThemeName, ensurePiTheme, getAvailablePiThemes, loadPiTheme, piCanvasBackgroundAnsi, piTheme, setPiAccentColor, setPiPackageBorderProjectionEnabled, } from "./upstream/theme/theme.js";
|
|
4
4
|
type Paint = (text: string) => string;
|
|
5
|
+
/** The owned floating-panel background in the live terminal color capability. */
|
|
6
|
+
export declare function paintPiFloatingDialog(text: string): string;
|
|
5
7
|
/** The live Pi theme in neutral roles; `panel` and `disabled` default to plain and dim. */
|
|
6
8
|
export declare function piUiTheme(options?: {
|
|
7
9
|
readonly panel?: Paint;
|
|
@@ -18,6 +20,8 @@ export declare function getPiMarkdownTheme(): MarkdownTheme;
|
|
|
18
20
|
export declare function getPiHotkeysMarkdownTheme(): MarkdownTheme;
|
|
19
21
|
/** Select-list roles resolved through A1's active theme rather than Pi's package-global base theme. */
|
|
20
22
|
export declare function getPiSelectListTheme(): SelectListTheme;
|
|
23
|
+
/** Display casing for internal headings, preserving provider spelling and acronyms. */
|
|
24
|
+
export declare function internalDialogTitle(title: string): string;
|
|
21
25
|
/** Paint one selected bare-A1 list item with the standard blue selection surface. */
|
|
22
26
|
export declare function renderPiListSelection(content: string): string;
|
|
23
27
|
/** One standard bare-A1 modal row, clipped before its item-bounded selection is painted. */
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { DIALOG_CLOSE_SHORTCUT_HINT, displayShortcutKeyLabel, renderSemanticShortcutHints, } from "../../../contracts/presentation/index.js";
|
|
2
|
+
import { renderFloatingDialogSurface } from "../../../ui/components/spans.js";
|
|
2
3
|
import { stripTerminalSequences, truncateToWidth } from "@earendil-works/pi-tui";
|
|
3
4
|
import { getMarkdownTheme } from "../startup-public.js";
|
|
4
5
|
import { onPiThemeChange, piTheme, renderPiAccentPreview } from "./upstream/theme/theme.js";
|
|
5
6
|
export { PINNED_PI_LAYOUT, applyPiTheme, applyPiThemeInstance, currentPiThemeName, ensurePiTheme, getAvailablePiThemes, loadPiTheme, piCanvasBackgroundAnsi, piTheme, setPiAccentColor, setPiPackageBorderProjectionEnabled, } from "./upstream/theme/theme.js";
|
|
7
|
+
/** The owned floating-panel background in the live terminal color capability. */
|
|
8
|
+
export function paintPiFloatingDialog(text) {
|
|
9
|
+
return renderFloatingDialogSurface(text, piTheme().getColorMode());
|
|
10
|
+
}
|
|
6
11
|
/** The live Pi theme in neutral roles; `panel` and `disabled` default to plain and dim. */
|
|
7
12
|
export function piUiTheme(options = {}) {
|
|
8
13
|
return {
|
|
@@ -48,6 +53,10 @@ export function getPiSelectListTheme() {
|
|
|
48
53
|
noMatch: text => piTheme().fg("muted", text),
|
|
49
54
|
};
|
|
50
55
|
}
|
|
56
|
+
/** Display casing for internal headings, preserving provider spelling and acronyms. */
|
|
57
|
+
export function internalDialogTitle(title) {
|
|
58
|
+
return title.replace(/:\s*$/u, "").replace(/\b[a-z][a-z]*/gu, (word, offset) => offset > 0 && /^(a|an|and|for|in|of|on|or|the|to|with)$/u.test(word) ? word : word[0].toUpperCase() + word.slice(1));
|
|
59
|
+
}
|
|
51
60
|
/** Paint one selected bare-A1 list item with the standard blue selection surface. */
|
|
52
61
|
export function renderPiListSelection(content) {
|
|
53
62
|
return piTheme().bg("selectedBg", content);
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Provenance: @earendil-works/pi-coding-agent 1.5.
|
|
2
|
+
* Provenance: @earendil-works/pi-coding-agent 1.5.1 (MIT), commit dd30101cfc5b0609411dd80b6f93adbc14db14cf,
|
|
3
3
|
* packages/coding-agent/src/core/keybindings.ts.
|
|
4
4
|
* Modifications: Mechanical source port with Node import prefixes, public package-root agent-directory
|
|
5
|
-
* resolution, and an opt-in bare-A1 input profile including Ctrl+L level cycling,
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* labels.
|
|
9
|
-
* Deviations: keybindings-public-config-boundary, owned-level-cycle-shortcut,
|
|
5
|
+
* resolution, and an opt-in bare-A1 input profile including Ctrl+L level cycling, Ctrl+M model cycling
|
|
6
|
+
* with ordinary Enter preserved, Ctrl+P Launcher, command-only model selection, Tab tree-filter
|
|
7
|
+
* cycling, tree-local navigation aliases, cross-platform Alt+Up queued-message restoration, and an
|
|
8
|
+
* implicit Ctrl+C selection-cancel alias omitted from shortcut labels.
|
|
9
|
+
* Deviations: keybindings-public-config-boundary, owned-level-cycle-shortcut, owned-apps-shortcuts,
|
|
10
10
|
* owned-input-keybinding-aliases, owned-session-tree-dialog, owned-dialog-ctrl-c-cancel.
|
|
11
11
|
*/
|
|
12
12
|
import { type Keybinding, type KeybindingDefinitions, type KeybindingsConfig, type KeyId, KeybindingsManager as TuiKeybindingsManager } from "@earendil-works/pi-tui";
|
|
13
13
|
export interface AppKeybindings {
|
|
14
|
+
"owned.apps.open": true;
|
|
14
15
|
"app.interrupt": true;
|
|
15
16
|
"app.clear": true;
|
|
16
17
|
"app.exit": true;
|
|
@@ -153,7 +154,7 @@ export declare const KEYBINDINGS: {
|
|
|
153
154
|
readonly description: "Restore queued messages";
|
|
154
155
|
};
|
|
155
156
|
readonly "app.clipboard.pasteImage": {
|
|
156
|
-
readonly defaultKeys: "ctrl+v" | "alt+v";
|
|
157
|
+
readonly defaultKeys: "ctrl+v" | ("ctrl+v" | "alt+v")[];
|
|
157
158
|
readonly description: "Paste files on macOS, images, or text from clipboard";
|
|
158
159
|
};
|
|
159
160
|
readonly "app.session.new": {
|