@timurproko/a1 0.2.4 → 0.2.5-dev.698
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/dist/app/session-shell/prompt-suggestion-controller.d.ts +2 -0
- package/dist/app/session-shell/prompt-suggestion-controller.js +10 -0
- package/dist/app/session-shell/session-shell-root.d.ts +1 -0
- package/dist/app/session-shell/session-shell-root.js +19 -6
- package/dist/app/session-shell/session-shell.js +77 -19
- package/dist/app/session-shell/share-operation.d.ts +3 -0
- package/dist/app/session-shell/share-operation.js +11 -0
- package/dist/composition/owned-ui.js +1 -0
- package/dist/composition/session-info-reference.d.ts +4 -0
- package/dist/composition/session-info-reference.js +20 -0
- package/dist/composition/settings-route-host.d.ts +2 -5
- package/dist/composition/settings-route-host.js +8 -12
- package/dist/contracts/presentation/index.d.ts +5 -0
- package/dist/contracts/presentation/index.js +2 -0
- package/dist/features/owned-ui/project-trust-dialog.js +7 -5
- package/dist/features/owned-ui/reference-screen-app.d.ts +4 -2
- package/dist/features/owned-ui/reference-screen-app.js +17 -7
- package/dist/features/owned-ui/settings-app.js +10 -5
- package/dist/foundation/release/progress-palette.generated.d.ts +2 -2
- package/dist/foundation/release/progress-palette.generated.js +2 -2
- package/dist/foundation/startup/startup-descriptor.js +2 -2
- package/dist/integrations/pi/components/index.d.ts +3 -2
- package/dist/integrations/pi/components/index.js +2 -1
- package/dist/integrations/pi/components/modal-frame.d.ts +11 -1
- package/dist/integrations/pi/components/modal-frame.js +29 -1
- package/dist/integrations/pi/components/models-dialog.js +17 -17
- 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/share-operation-dialog.d.ts +6 -0
- package/dist/integrations/pi/components/share-operation-dialog.js +40 -0
- package/dist/integrations/pi/components/shell-editor-autocomplete.js +15 -6
- package/dist/integrations/pi/components/shell-extension-ui.d.ts +3 -0
- package/dist/integrations/pi/components/shell-extension-ui.js +8 -4
- package/dist/integrations/pi/components/shell-presenters-info.d.ts +2 -0
- package/dist/integrations/pi/components/shell-presenters-info.js +1 -1
- package/dist/integrations/pi/components/shell-selectors-dialogs.d.ts +0 -4
- package/dist/integrations/pi/components/shell-selectors-dialogs.js +56 -34
- package/dist/integrations/pi/components/shell-session-info-reference.d.ts +10 -0
- package/dist/integrations/pi/components/shell-session-info-reference.js +94 -0
- package/dist/integrations/pi/components/shell-shared-facade.d.ts +3 -1
- package/dist/integrations/pi/components/shell-shared-facade.js +13 -1
- package/dist/integrations/pi/components/skills-dialog.js +19 -6
- package/dist/integrations/pi/components/theme.d.ts +8 -1
- package/dist/integrations/pi/components/theme.js +28 -1
- package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.d.ts +15 -7
- package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.js +21 -7
- package/dist/integrations/pi/components/upstream/assets/earendil-image.json +2 -2
- 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 +3 -3
- package/dist/integrations/pi/components/upstream/components/extension-input.js +5 -6
- package/dist/integrations/pi/components/upstream/components/extension-selector.js +3 -4
- package/dist/integrations/pi/components/upstream/components/mermaid.js +1 -1
- 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 +4 -3
- package/dist/integrations/pi/components/upstream/components/scoped-models-selector.js +4 -15
- package/dist/integrations/pi/components/upstream/components/session-footer.js +1 -1
- package/dist/integrations/pi/components/upstream/components/session-selector-search.js +1 -1
- package/dist/integrations/pi/components/upstream/components/session-selector.d.ts +2 -0
- package/dist/integrations/pi/components/upstream/components/session-selector.js +137 -110
- package/dist/integrations/pi/components/upstream/components/skill-invocation-message.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/skill-invocation-message.js +1 -1
- 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 +9 -6
- package/dist/integrations/pi/components/upstream/components/thinking-selector.js +64 -27
- package/dist/integrations/pi/components/upstream/components/tool-execution.js +1 -1
- package/dist/integrations/pi/components/upstream/components/tree-selector.d.ts +30 -21
- package/dist/integrations/pi/components/upstream/components/tree-selector.js +246 -211
- package/dist/integrations/pi/components/upstream/components/trust-selector.js +14 -16
- 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 +1 -1
- 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/theme/system-theme.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/theme/system-theme.js +1 -1
- package/dist/integrations/pi/components/upstream/theme/theme-controller.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/theme/theme.js +1 -1
- package/dist/integrations/pi/engine/adapter.js +21 -2
- package/dist/integrations/pi/engine/resources/changelog.json +4 -4
- package/dist/integrations/pi/engine/workflow-runner.js +2 -1
- package/dist/integrations/pi/startup-public.js +186 -81
- package/dist/integrations/pi/startup-public.manifest.json +107 -95
- 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/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/runtime-payload-inventory.json +2717 -2630
- package/dist/ui/apps/host.d.ts +4 -3
- package/dist/ui/apps/host.js +9 -4
- package/dist/ui/components/dialog-panel.js +6 -7
- package/dist/ui/components/index.d.ts +1 -1
- package/dist/ui/components/index.js +1 -1
- package/dist/ui/components/list-view.d.ts +3 -3
- package/dist/ui/components/list-view.js +8 -9
- package/dist/ui/components/shortcut-hints.d.ts +2 -0
- package/dist/ui/components/shortcut-hints.js +17 -1
- package/dist/ui/components/theme.d.ts +1 -1
- package/docs/assets/readme/separator-dark.svg +2 -4
- package/docs/assets/readme/separator.svg +2 -4
- package/docs/releases/0.2.4.md +1 -5
- package/package.json +3 -3
|
@@ -31,6 +31,8 @@ export declare class ContextualPromptSuggestionController {
|
|
|
31
31
|
invalidate(): void;
|
|
32
32
|
/** Retires only a generating request; a prepared or available suggestion survives the draft edit. */
|
|
33
33
|
abortPending(): void;
|
|
34
|
+
/** Reasserts retained ghost text after an editor mutation makes the prompt eligible again. */
|
|
35
|
+
restoreAvailable(): void;
|
|
34
36
|
dispose(): void;
|
|
35
37
|
}
|
|
36
38
|
export declare function samePromptSuggestionIdentity(left: OwnedUiPromptSuggestionIdentity, right: OwnedUiPromptSuggestionIdentity): boolean;
|
|
@@ -100,6 +100,16 @@ export class ContextualPromptSuggestionController {
|
|
|
100
100
|
this.#finish(request, "cancelled");
|
|
101
101
|
request.abort.abort();
|
|
102
102
|
}
|
|
103
|
+
/** Reasserts retained ghost text after an editor mutation makes the prompt eligible again. */
|
|
104
|
+
restoreAvailable() {
|
|
105
|
+
if (this.#disposed || !this.#enabled || this.#state.status !== "available")
|
|
106
|
+
return;
|
|
107
|
+
const reason = this.options.surface.presentationBlockReason?.(this.#state.identity)
|
|
108
|
+
?? (this.options.surface.canPresent(this.#state.identity) ? null : "presentation-unavailable");
|
|
109
|
+
if (reason !== null || !this.options.surface.present(this.#state.text))
|
|
110
|
+
return;
|
|
111
|
+
this.options.surface.requestRender();
|
|
112
|
+
}
|
|
103
113
|
dispose() {
|
|
104
114
|
this.#disposed = true;
|
|
105
115
|
this.invalidate();
|
|
@@ -257,6 +257,7 @@ export declare class OwnedUiSessionShellRoot implements PiTuiComponentPort {
|
|
|
257
257
|
setViewportOverlaySurfaces(surfaces: readonly PiTuiPointerSurface[] | null): void;
|
|
258
258
|
viewportInputGeometryReady(width: number, height: number): boolean;
|
|
259
259
|
handleViewportPreInput(data: string, allowWheel?: boolean, now?: number, editorActive?: boolean): SessionViewportInputResult;
|
|
260
|
+
dismissNotice(): void;
|
|
260
261
|
layoutRoot(): PiTuiLayoutNode;
|
|
261
262
|
transcriptComponent(id: string): PiShellTranscriptComponentPort | undefined;
|
|
262
263
|
exitTranscript(width: number): string;
|
|
@@ -9,7 +9,7 @@ import { PINNED_PI_HIDDEN_COMMAND_NAMES, PINNED_PI_WORKFLOW_COMMAND_NAMES } from
|
|
|
9
9
|
import { createPiExtensionUiBridge } from "../../integrations/pi/components/shell-extension-ui.js";
|
|
10
10
|
import { createPiShellEditor } from "../../integrations/pi/components/shell-editor-autocomplete.js";
|
|
11
11
|
import { createPiQueuedInputStatus, createPiShellFooter, createPiShellHeader, createPiShellLoadedResources, createPiShellStatus, } from "../../integrations/pi/components/shell-footer-status.js";
|
|
12
|
-
import { createPiShellArmin, createPiShellAuthProviderSelector, createPiShellDialog, createPiShellEarendilAnnouncement, createPiShellExtensionSelector, createPiShellLoginDialog, createPiShellModelSelector,
|
|
12
|
+
import { createPiShellArmin, createPiShellAuthProviderSelector, createPiShellDialog, createPiShellEarendilAnnouncement, createPiShellExtensionSelector, createPiShellLoginDialog, createPiShellModelSelector, createPiShellScopedModelsSelector, createPiShellSelector, createPiShellSessionSelector, createPiShellSettingsSelector, createPiShellTreeSelector, createPiShellTrustSelector, createPiShellUserMessageSelector, } from "../../integrations/pi/components/shell-selectors-dialogs.js";
|
|
13
13
|
import { createPiShellChangelog, createPiShellCollapsedChangelog, createPiShellHotkeys, createPiShellSessionInfo, renderPiShellCommandMessage, renderPiShellPackageUpdateNotice, renderPiShellReleaseUpdateBanner, renderPiShellReleaseUpdateNotice, renderPiShellStatusText, } from "../../integrations/pi/components/shell-presenters-info.js";
|
|
14
14
|
import { createPiShellTranscriptComponent, isPiPromptStyleCompaction, paintPiSubmittedPromptTimestamp, renderPiShellStartupDiagnostic, renderPiShellTranscriptBlock, } from "../../integrations/pi/components/shell-presenters-transcript.js";
|
|
15
15
|
import { onPiThemeChange, PINNED_PI_LAYOUT, piTheme } from "../../integrations/pi/components/upstream/theme/theme.js";
|
|
@@ -286,7 +286,7 @@ export class OwnedUiSessionShellRoot {
|
|
|
286
286
|
reconcilePromptImageLimitNotice(text = this.editor.getText()) {
|
|
287
287
|
if (this.#dockNotice?.errorCode !== "image-count" || !this.#promptChips.imageLimitState(text).corrected)
|
|
288
288
|
return false;
|
|
289
|
-
this
|
|
289
|
+
this.dismissNotice();
|
|
290
290
|
return true;
|
|
291
291
|
}
|
|
292
292
|
hasPendingPastes(text) { return this.#promptChips.hasPending(text); }
|
|
@@ -333,6 +333,10 @@ export class OwnedUiSessionShellRoot {
|
|
|
333
333
|
}
|
|
334
334
|
const promptAccepted = this.#view.lifecycle !== "busy" && view.lifecycle === "busy";
|
|
335
335
|
this.#view = view;
|
|
336
|
+
// Invariant: the idle new-session confirmation yields to the first truthful live status;
|
|
337
|
+
// ordinary dock notices deliberately remain visible below Working during a run.
|
|
338
|
+
if (promptAccepted && this.#dockNotice?.kind === "new-session")
|
|
339
|
+
this.#dockNotice = undefined;
|
|
336
340
|
if (promptAccepted && this.#imageSubmissionsSending > 0) {
|
|
337
341
|
this.#imageSubmissionsSending = 0;
|
|
338
342
|
this.#syncWorkingOverride();
|
|
@@ -375,7 +379,7 @@ export class OwnedUiSessionShellRoot {
|
|
|
375
379
|
// Invariant: the notice answers the reader's last command, so only their next prompt or
|
|
376
380
|
// shell command retires it; assistant, tool, and compaction blocks streaming in keep it.
|
|
377
381
|
if (block.kind === "user" || block.kind === "bash")
|
|
378
|
-
this
|
|
382
|
+
this.dismissNotice();
|
|
379
383
|
const created = createPiShellTranscriptComponent(block, this.#cwd, this.#extensionRenderers, this.#submittedPromptComposer, this.#outputPad, !this.#thinkingVisible, this.#mermaidRenderingMode, this.#showImages, this.#imageWidthCells, this.#imageAssets, { ...this.#componentRuntime, changed: () => {
|
|
380
384
|
if (this.#transcript.get(block.id) !== created)
|
|
381
385
|
return;
|
|
@@ -657,9 +661,12 @@ export class OwnedUiSessionShellRoot {
|
|
|
657
661
|
// Compatibility: Pi pads its status text by one cell regardless of the output pad setting.
|
|
658
662
|
return ["", ...renderPiShellStatusText(notice.message, width, PINNED_PI_LAYOUT.outputPad)];
|
|
659
663
|
}
|
|
660
|
-
return renderPiShellCommandMessage({
|
|
664
|
+
return renderPiShellCommandMessage({
|
|
665
|
+
kind: notice.kind === "new-session" ? "accent" : notice.kind,
|
|
666
|
+
message: notice.message,
|
|
667
|
+
}, width, this.#outputPad);
|
|
661
668
|
}
|
|
662
|
-
|
|
669
|
+
dismissNotice() {
|
|
663
670
|
if (this.#dockNotice === undefined)
|
|
664
671
|
return;
|
|
665
672
|
this.#dockNotice = undefined;
|
|
@@ -960,6 +967,12 @@ export class OwnedUiSessionShellRoot {
|
|
|
960
967
|
}
|
|
961
968
|
if (result.outcome === "completed" && (result.command === "quit" || result.command === "compact"))
|
|
962
969
|
return;
|
|
970
|
+
if (result.outcome === "completed" && result.command === "new" && this.#customViewport) {
|
|
971
|
+
// Rationale: bare A1 keeps the replacement session visually empty while preserving Pi's accent notice shape.
|
|
972
|
+
this.#dockNotice = { kind: "new-session", message: result.message };
|
|
973
|
+
this.#invalidateChrome();
|
|
974
|
+
return;
|
|
975
|
+
}
|
|
963
976
|
if (result.outcome === "completed" && (result.command === "new" || result.command === "name" || result.command === "debug")) {
|
|
964
977
|
this.#lastWorkflowStatusId = undefined;
|
|
965
978
|
const presentation = { kind: result.command, message: result.message, ...(result.detail === undefined ? {} : { detail: result.detail }) };
|
|
@@ -1247,7 +1260,7 @@ export class OwnedUiSessionShellRoot {
|
|
|
1247
1260
|
}
|
|
1248
1261
|
#appendAnchoredWorkflowComponent(render, dispose) {
|
|
1249
1262
|
// Invariant: transcript-bound workflow output supersedes a pending acknowledgement.
|
|
1250
|
-
this
|
|
1263
|
+
this.dismissNotice();
|
|
1251
1264
|
this.#workflowTranscriptSequence += 1;
|
|
1252
1265
|
const id = `workflow-status-${this.#workflowTranscriptSequence}`;
|
|
1253
1266
|
const component = {
|
|
@@ -14,7 +14,7 @@ import { createPiExtensionUiBridge } from "../../integrations/pi/components/shel
|
|
|
14
14
|
import { createPiShellEditor } from "../../integrations/pi/components/shell-editor-autocomplete.js";
|
|
15
15
|
import { SKILLS_COMMAND_NAME, findSkillByArgument, rewriteSkillsTunnelSubmission, skillPrompt, skillsFromCommands, } from "../../integrations/pi/components/skills-command.js";
|
|
16
16
|
import { createPiQueuedInputStatus, createPiShellFooter, createPiShellHeader, createPiShellLoadedResources, createPiShellStatus, } from "../../integrations/pi/components/shell-footer-status.js";
|
|
17
|
-
import { createPiShellArmin, createPiShellAuthProviderSelector, createPiShellDialog, createPiShellEarendilAnnouncement, createPiShellExtensionSelector, createPiShellLoginDialog, createPiShellModelSelector, createPiShellModelsDialog,
|
|
17
|
+
import { createPiShellArmin, createPiShellAuthProviderSelector, createPiShellDialog, createPiShellEarendilAnnouncement, createPiShellExtensionSelector, createPiShellLoginDialog, createPiShellModelSelector, createPiShellModelsDialog, createPiShellReloadBox, createPiShellScopedModelsSelector, createPiShellSelector, createPiShellSessionSelector, createPiShellSettingsSelector, createPiShellSkillsSelector, createPiShellTreeSelector, createPiShellTrustSelector, createPiShellUserMessageSelector, } from "../../integrations/pi/components/shell-selectors-dialogs.js";
|
|
18
18
|
import { createPiShellChangelog, createPiShellHotkeys, createPiShellSessionInfo, renderPiShellPackageUpdateNotice, renderPiShellStatusText, } from "../../integrations/pi/components/shell-presenters-info.js";
|
|
19
19
|
import { createPiShellTranscriptComponent, renderPiShellStartupDiagnostic, renderPiShellTranscriptBlock, } from "../../integrations/pi/components/shell-presenters-transcript.js";
|
|
20
20
|
import { onPiThemeChange, piTheme } from "../../integrations/pi/components/upstream/theme/theme.js";
|
|
@@ -188,6 +188,11 @@ export class OwnedUiSessionShell {
|
|
|
188
188
|
onEditorChange: text => {
|
|
189
189
|
this.#editorRevision++;
|
|
190
190
|
promptSuggestionController?.abortPending();
|
|
191
|
+
if (text.length === 0) {
|
|
192
|
+
// Concurrency: the editor synchronizes deletion-owned autocomplete after onChange.
|
|
193
|
+
// Reassert retained ghost text in the microtask before Pi emits its scheduled frame.
|
|
194
|
+
queueMicrotask(() => promptSuggestionController?.restoreAvailable());
|
|
195
|
+
}
|
|
191
196
|
this.root.reconcilePromptImageLimitNotice(text);
|
|
192
197
|
},
|
|
193
198
|
onPromptSuggestionAccepted: () => promptSuggestionController?.accept(),
|
|
@@ -358,12 +363,20 @@ export class OwnedUiSessionShell {
|
|
|
358
363
|
? this.runtime.addPreInputListener(data => {
|
|
359
364
|
if (inputPresentation?.coordination === false)
|
|
360
365
|
this.#streamPresentation.noteImmediatePresentation();
|
|
361
|
-
// Compatibility: Pi's fullscreen
|
|
362
|
-
|
|
363
|
-
|
|
366
|
+
// Compatibility: route modal paging and boundary keys before Pi's fullscreen handlers.
|
|
367
|
+
const isDefault = this.root.usesDefaultInputSurface();
|
|
368
|
+
if (!this.runtime.hasOverlay() && !isDefault
|
|
369
|
+
&& (this.root.editor.matchesTerminalKey(data, "pageUp")
|
|
370
|
+
|| this.root.editor.matchesTerminalKey(data, "pageDown"))) {
|
|
371
|
+
this.root.handleInput(data);
|
|
372
|
+
this.runtime.requestRender();
|
|
373
|
+
return { consume: true };
|
|
374
|
+
}
|
|
364
375
|
if (!this.runtime.hasOverlay() && (this.root.editor.matchesTerminalKey(data, "home")
|
|
365
|
-
|| this.root.editor.matchesTerminalKey(data, "end")
|
|
366
|
-
|
|
376
|
+
|| this.root.editor.matchesTerminalKey(data, "end")
|
|
377
|
+
|| !isDefault && (this.root.editor.matchesTerminalKey(data, "ctrl+home")
|
|
378
|
+
|| this.root.editor.matchesTerminalKey(data, "ctrl+end")))) {
|
|
379
|
+
if (isDefault)
|
|
367
380
|
this.root.handleViewportPreInput(data, true);
|
|
368
381
|
this.root.handleInput(data);
|
|
369
382
|
this.runtime.requestRender();
|
|
@@ -1064,12 +1077,14 @@ export class OwnedUiSessionShell {
|
|
|
1064
1077
|
},
|
|
1065
1078
|
onCancel: close,
|
|
1066
1079
|
onSelect: entryId => {
|
|
1067
|
-
close();
|
|
1068
1080
|
if (entryId === context.currentLeafId) {
|
|
1081
|
+
close();
|
|
1069
1082
|
this.root.appendWorkflowStatus("Already at this point");
|
|
1070
1083
|
this.runtime.requestRender();
|
|
1071
1084
|
return;
|
|
1072
1085
|
}
|
|
1086
|
+
if (context.skipSummaryPrompt)
|
|
1087
|
+
close();
|
|
1073
1088
|
void this.#completeTreeSelection(entryId, context.skipSummaryPrompt);
|
|
1074
1089
|
},
|
|
1075
1090
|
});
|
|
@@ -1205,6 +1220,19 @@ export class OwnedUiSessionShell {
|
|
|
1205
1220
|
async runWorkflow(request) {
|
|
1206
1221
|
if (request.command === "quit")
|
|
1207
1222
|
return this.shutdown();
|
|
1223
|
+
if (this.#customViewport && request.command === "name" && request.argument.trim().length === 0) {
|
|
1224
|
+
void this.#extensionBridge.input("Session Name", "Enter name").then(value => {
|
|
1225
|
+
if (this.#disposed || value === undefined || value.trim().length === 0)
|
|
1226
|
+
return;
|
|
1227
|
+
return this.runWorkflow({ ...request, argument: value });
|
|
1228
|
+
}).catch(error => {
|
|
1229
|
+
if (this.#disposed)
|
|
1230
|
+
return;
|
|
1231
|
+
this.root.appendWorkflowResult({ command: "name", outcome: "failed", message: error instanceof Error ? error.message : String(error) });
|
|
1232
|
+
this.runtime.requestRender();
|
|
1233
|
+
});
|
|
1234
|
+
return { outcome: "completed", diagnostic: null };
|
|
1235
|
+
}
|
|
1208
1236
|
const copyGeneration = request.command === "copy" ? this.backend.sessionBindingGeneration : undefined;
|
|
1209
1237
|
if (request.command === "login" && request.selection !== undefined) {
|
|
1210
1238
|
const setup = this.backend.pinnedAmbientAuthentication(request.selection);
|
|
@@ -1280,13 +1308,15 @@ export class OwnedUiSessionShell {
|
|
|
1280
1308
|
}
|
|
1281
1309
|
this.root.resetExtensionUi();
|
|
1282
1310
|
}
|
|
1283
|
-
const
|
|
1284
|
-
?
|
|
1311
|
+
const shareDialog = request.command === "share"
|
|
1312
|
+
? await import("./share-operation.js")
|
|
1313
|
+
: undefined;
|
|
1314
|
+
const shareSurface = shareDialog === undefined ? undefined
|
|
1315
|
+
: (this.#customViewport ? shareDialog.createPiShellShareOperationDialog : shareDialog.createPiShellOperationLoader)({
|
|
1285
1316
|
getColumns: () => this.runtime.viewport().columns,
|
|
1286
1317
|
getRows: () => this.runtime.viewport().rows,
|
|
1287
1318
|
requestRender: () => this.runtime.requestRender(),
|
|
1288
|
-
}, "Creating gist
|
|
1289
|
-
: undefined;
|
|
1319
|
+
}, "Creating gist…");
|
|
1290
1320
|
const operationSurface = shareSurface ?? (request.command === "reload" ? createPiShellReloadBox() : undefined);
|
|
1291
1321
|
const now = this.#reloadPresentation?.now ?? Date.now;
|
|
1292
1322
|
const shownAt = now();
|
|
@@ -1342,7 +1372,17 @@ export class OwnedUiSessionShell {
|
|
|
1342
1372
|
this.root.editor.reloadKeybindings();
|
|
1343
1373
|
this.#installAutocompleteCommands();
|
|
1344
1374
|
}
|
|
1345
|
-
|
|
1375
|
+
if (request.command === "tree" && result.outcome === "completed") {
|
|
1376
|
+
if (result.detail && !this.root.editor.getText().trim())
|
|
1377
|
+
this.root.editor.setText(result.detail);
|
|
1378
|
+
this.root.resumeViewportFollowing();
|
|
1379
|
+
}
|
|
1380
|
+
if (shareDialog !== undefined && this.#customViewport && result.outcome === "completed" && result.detail !== undefined) {
|
|
1381
|
+
this.root.appendWorkflowStatus(shareDialog.renderPiShellShareResult(result.message, result.detail));
|
|
1382
|
+
}
|
|
1383
|
+
else {
|
|
1384
|
+
this.root.appendWorkflowResult(result);
|
|
1385
|
+
}
|
|
1346
1386
|
this.runtime.requestRender();
|
|
1347
1387
|
return workflowAdapterResult(result);
|
|
1348
1388
|
}
|
|
@@ -1768,6 +1808,7 @@ export class OwnedUiSessionShell {
|
|
|
1768
1808
|
return { outcome: "failed", diagnostic: `route is unavailable: ${route}` };
|
|
1769
1809
|
if (!this.runtime.active)
|
|
1770
1810
|
return { outcome: "failed", diagnostic: "runtime is not active" };
|
|
1811
|
+
this.root.dismissNotice();
|
|
1771
1812
|
this.#dialogHandle?.hide();
|
|
1772
1813
|
this.#dialogSource = "route";
|
|
1773
1814
|
// Protocol: any-event reporting: hover and drag are what the screen is driven by, and
|
|
@@ -1780,6 +1821,19 @@ export class OwnedUiSessionShell {
|
|
|
1780
1821
|
const removeInterruptWatch = this.runtime.addInputListener(data => {
|
|
1781
1822
|
if (!data.includes(INTERRUPT))
|
|
1782
1823
|
return undefined;
|
|
1824
|
+
// Protocol: route hosts decide whether one interrupt closes their app. Raw-input forwarding
|
|
1825
|
+
// is required because Pi handles Ctrl+C before the fullscreen overlay receives normal input.
|
|
1826
|
+
const consumedBySurface = surface.handleInput(INTERRUPT);
|
|
1827
|
+
if (surface.isClosed()) {
|
|
1828
|
+
armedAt = 0;
|
|
1829
|
+
closeSurface();
|
|
1830
|
+
return { consume: true };
|
|
1831
|
+
}
|
|
1832
|
+
if (consumedBySurface) {
|
|
1833
|
+
armedAt = 0;
|
|
1834
|
+
this.runtime.requestRender();
|
|
1835
|
+
return { consume: true };
|
|
1836
|
+
}
|
|
1783
1837
|
const now = Date.now();
|
|
1784
1838
|
if (armedAt !== 0 && now - armedAt <= INTERRUPT_CHORD_MS) {
|
|
1785
1839
|
armedAt = 0;
|
|
@@ -1968,7 +2022,7 @@ export class OwnedUiSessionShell {
|
|
|
1968
2022
|
}
|
|
1969
2023
|
return this.#submitSkillPrompt(skillPrompt(skill.name, separator < 0 ? "" : trimmed.slice(separator + 1)), text);
|
|
1970
2024
|
}
|
|
1971
|
-
// Rationale:
|
|
2025
|
+
// Rationale: engine expands skill arguments; history retains typed input for recall.
|
|
1972
2026
|
#submitSkillPrompt(prompt, typed) {
|
|
1973
2027
|
this.#rememberInput(typed, "slash");
|
|
1974
2028
|
this.root.resumeViewportFollowing();
|
|
@@ -1979,29 +2033,33 @@ export class OwnedUiSessionShell {
|
|
|
1979
2033
|
text: prompt,
|
|
1980
2034
|
});
|
|
1981
2035
|
}
|
|
2036
|
+
#treeSummary() {
|
|
2037
|
+
return new Promise(resolve => {
|
|
2038
|
+
this.root.setInputSurface(createPiShellExtensionSelector("Summarize Branch?", ["No summary", "Summarize", "Summarize with custom prompt"], resolve, () => resolve(undefined)), true, "opaque");
|
|
2039
|
+
this.runtime.requestRender();
|
|
2040
|
+
});
|
|
2041
|
+
}
|
|
1982
2042
|
async #completeTreeSelection(entryId, skipSummaryPrompt) {
|
|
1983
2043
|
let summarize = false;
|
|
1984
2044
|
let customInstructions;
|
|
1985
2045
|
if (!skipSummaryPrompt) {
|
|
1986
2046
|
while (true) {
|
|
1987
|
-
const choice = await this.#
|
|
1988
|
-
"No summary",
|
|
1989
|
-
"Summarize",
|
|
1990
|
-
"Summarize with custom prompt",
|
|
1991
|
-
]);
|
|
2047
|
+
const choice = await this.#treeSummary();
|
|
1992
2048
|
if (choice === undefined) {
|
|
1993
2049
|
await this.showTreeSelector(entryId);
|
|
1994
2050
|
return;
|
|
1995
2051
|
}
|
|
1996
2052
|
summarize = choice !== "No summary";
|
|
1997
2053
|
if (choice === "Summarize with custom prompt") {
|
|
1998
|
-
customInstructions = await this.#extensionBridge.
|
|
2054
|
+
customInstructions = await this.#extensionBridge.input("Custom Summarization Instructions", "", { retainSurfaceOnSettle: true });
|
|
1999
2055
|
if (customInstructions === undefined)
|
|
2000
2056
|
continue;
|
|
2001
2057
|
}
|
|
2002
2058
|
break;
|
|
2003
2059
|
}
|
|
2004
2060
|
}
|
|
2061
|
+
this.root.setInputSurface(null);
|
|
2062
|
+
this.runtime.requestRender();
|
|
2005
2063
|
const result = await this.runWorkflow({
|
|
2006
2064
|
command: "tree",
|
|
2007
2065
|
argument: "",
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { createPiShellOperationLoader, createPiShellShareOperationDialog } from "../../integrations/pi/components/index.js";
|
|
2
|
+
export { createPiShellOperationLoader, createPiShellShareOperationDialog };
|
|
3
|
+
export declare function renderPiShellShareResult(message: string, gistUrl: string): string;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createPiShellOperationLoader, createPiShellShareOperationDialog, piShellHyperlink, piTheme, } from "../../integrations/pi/components/index.js";
|
|
2
|
+
import { nativeHyperlinkStyle } from "../../ui/components/index.js";
|
|
3
|
+
export { createPiShellOperationLoader, createPiShellShareOperationDialog };
|
|
4
|
+
export function renderPiShellShareResult(message, gistUrl) {
|
|
5
|
+
const theme = piTheme();
|
|
6
|
+
const match = /^Share URL: (\S+)$/u.exec(message);
|
|
7
|
+
const linked = match === null
|
|
8
|
+
? theme.fg("dim", message)
|
|
9
|
+
: `${theme.fg("dim", "Share URL: ")}${piShellHyperlink(match[1])}`;
|
|
10
|
+
return nativeHyperlinkStyle(`${linked}\n${theme.fg("dim", "Gist: ")}${piShellHyperlink(gistUrl)}`, text => theme.fg("mdLink", text));
|
|
11
|
+
}
|
|
@@ -82,6 +82,7 @@ export async function composeOwnedUi(options = {}) {
|
|
|
82
82
|
const { renderPiShellHotkeySections } = await import("../integrations/pi/components/shell-hotkey-sections.js");
|
|
83
83
|
return { sections: width => renderPiShellHotkeySections(presentation, width) };
|
|
84
84
|
},
|
|
85
|
+
session: () => import("./session-info-reference.js").then(m => m.loadSessionInfoReference(adapter)),
|
|
85
86
|
};
|
|
86
87
|
const routeHost = settings === null || !ownedSurfaces ? null : createOwnedRouteHost(settings, references);
|
|
87
88
|
const viewportSettings = settings === null || !ownedSurfaces ? null : {
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ReferenceDocumentProvider } from "../features/owned-ui/reference-screen-app.js";
|
|
2
|
+
import type { PiEngineAdapter } from "../integrations/pi/engine/adapter.js";
|
|
3
|
+
/** Captures one current session snapshot and adapts it to the neutral reference document. */
|
|
4
|
+
export declare function loadSessionInfoReference(adapter: PiEngineAdapter): Promise<ReferenceDocumentProvider>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { renderPiShellSessionInfoReferenceDocument } from "../integrations/pi/components/shell-session-info-reference.js";
|
|
2
|
+
/** Captures one current session snapshot and adapts it to the neutral reference document. */
|
|
3
|
+
export async function loadSessionInfoReference(adapter) {
|
|
4
|
+
const result = await adapter.executeWorkflow({ command: "session", argument: "" });
|
|
5
|
+
if (result.outcome !== "completed")
|
|
6
|
+
throw new Error(result.message);
|
|
7
|
+
if (result.presentation?.kind !== "session-info")
|
|
8
|
+
throw new Error("Session workflow returned no structured information");
|
|
9
|
+
const presentation = result.presentation;
|
|
10
|
+
let cached = null;
|
|
11
|
+
const document = (width) => {
|
|
12
|
+
if (cached?.width !== width)
|
|
13
|
+
cached = { width, document: renderPiShellSessionInfoReferenceDocument(presentation, width) };
|
|
14
|
+
return cached.document;
|
|
15
|
+
};
|
|
16
|
+
return {
|
|
17
|
+
preamble: width => document(width).preamble,
|
|
18
|
+
sections: width => document(width).sections,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
@@ -7,10 +7,7 @@ export type OwnedReferenceRows = NonNullable<ReferenceDocumentProvider["rows"]>;
|
|
|
7
7
|
export interface OwnedReferenceProviders {
|
|
8
8
|
changelog(input?: UiRouteInput): Promise<ReferenceDocumentProvider>;
|
|
9
9
|
hotkeys(): Promise<ReferenceDocumentProvider>;
|
|
10
|
+
session(): Promise<ReferenceDocumentProvider>;
|
|
10
11
|
}
|
|
11
|
-
/**
|
|
12
|
-
* Declares the A1-owned settings route, and the changelog and hotkeys reference
|
|
13
|
-
* routes when their documents are supplied, without evaluating their presentation
|
|
14
|
-
* graphs during startup. Opening a route retains input while the optional module loads.
|
|
15
|
-
*/
|
|
12
|
+
/** Declares settings and lazy document routes. */
|
|
16
13
|
export declare function createOwnedRouteHost(settings: OwnedSettingsManager, references?: OwnedReferenceProviders): UiRouteHost;
|
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CHANGELOG_ROUTE, CHANGELOG_TITLE, HOTKEYS_ROUTE, HOTKEYS_TITLE, } from "../features/owned-ui/reference-routes.js";
|
|
2
2
|
import { SETTINGS_APP_ID, SETTINGS_ROUTE } from "../features/owned-ui/settings-route.js";
|
|
3
3
|
import { piTheme } from "../integrations/pi/components/upstream/theme/theme.js";
|
|
4
4
|
import { faint } from "../ui/components/text.js";
|
|
5
|
-
/**
|
|
6
|
-
* Declares the A1-owned settings route, and the changelog and hotkeys reference
|
|
7
|
-
* routes when their documents are supplied, without evaluating their presentation
|
|
8
|
-
* graphs during startup. Opening a route retains input while the optional module loads.
|
|
9
|
-
*/
|
|
5
|
+
/** Declares settings and lazy document routes. */
|
|
10
6
|
export function createOwnedRouteHost(settings, references) {
|
|
11
|
-
const routes = new Set([SETTINGS_ROUTE, ...(references === undefined ? [] : [CHANGELOG_ROUTE, HOTKEYS_ROUTE])]);
|
|
7
|
+
const routes = new Set([SETTINGS_ROUTE, ...(references === undefined ? [] : [CHANGELOG_ROUTE, HOTKEYS_ROUTE, "session"])]);
|
|
12
8
|
return {
|
|
13
9
|
claims: route => routes.has(route),
|
|
14
10
|
open: (route, input) => {
|
|
@@ -18,10 +14,10 @@ export function createOwnedRouteHost(settings, references) {
|
|
|
18
14
|
return deferredSurface(SETTINGS_APP_ID, "settings", () => loadSettingsSurface(settings));
|
|
19
15
|
}
|
|
20
16
|
const changelog = route === CHANGELOG_ROUTE;
|
|
21
|
-
const
|
|
22
|
-
const title = changelog ? CHANGELOG_TITLE : HOTKEYS_TITLE;
|
|
23
|
-
const document = changelog ? references.changelog(input) : references.hotkeys();
|
|
24
|
-
return deferredSurface(
|
|
17
|
+
const session = route === "session";
|
|
18
|
+
const title = session ? "Session Info" : changelog ? CHANGELOG_TITLE : HOTKEYS_TITLE;
|
|
19
|
+
const document = session ? references.session() : changelog ? references.changelog(input) : references.hotkeys();
|
|
20
|
+
return deferredSurface(route, title, () => loadReferenceSurface(settings, route, route, title, document));
|
|
25
21
|
},
|
|
26
22
|
};
|
|
27
23
|
}
|
|
@@ -135,7 +131,7 @@ function pinnedTheme() {
|
|
|
135
131
|
bold: (text) => piTheme().bold(text),
|
|
136
132
|
plain: (text) => text,
|
|
137
133
|
disabled: (text) => faint(piTheme().fg("dim", text)),
|
|
138
|
-
highlight: (text) =>
|
|
134
|
+
highlight: (text) => piTheme().bg("selectedBg", text),
|
|
139
135
|
panel: (text) => `\u001b[48;2;55;55;55m${text}\u001b[49m`,
|
|
140
136
|
};
|
|
141
137
|
}
|
|
@@ -4,6 +4,11 @@ export interface SemanticShortcutHint {
|
|
|
4
4
|
readonly action: string;
|
|
5
5
|
readonly actionFirst?: boolean;
|
|
6
6
|
}
|
|
7
|
+
/** Canonical dismissal guidance for every A1-rendered dialog surface. */
|
|
8
|
+
export declare const DIALOG_CLOSE_SHORTCUT_HINT: Readonly<{
|
|
9
|
+
key: string;
|
|
10
|
+
action: string;
|
|
11
|
+
}>;
|
|
7
12
|
export interface ShortcutHintRoles {
|
|
8
13
|
key(label: string): string;
|
|
9
14
|
action(name: string): string;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/** Canonical dismissal guidance for every A1-rendered dialog surface. */
|
|
2
|
+
export const DIALOG_CLOSE_SHORTCUT_HINT = Object.freeze({ key: "esc", action: "close" });
|
|
1
3
|
const SHORTCUT_KEY_NAMES = Object.freeze({
|
|
2
4
|
alt: "Alt", backspace: "Backspace", cmd: "Cmd", ctrl: "Ctrl", delete: "Delete", down: "Down", end: "End",
|
|
3
5
|
enter: "Enter", esc: "Esc", escape: "Escape", home: "Home", insert: "Insert", left: "Left", meta: "Meta",
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
const
|
|
3
|
-
const
|
|
4
|
-
const
|
|
1
|
+
import { DIALOG_CLOSE_SHORTCUT_HINT, displayShortcutKeyLabel } from "../../contracts/presentation/index.js";
|
|
2
|
+
const ACCENT = "\u001b[38;2;167;152;215m";
|
|
3
|
+
const BORDER = "\u001b[38;2;97;133;204m";
|
|
4
|
+
const MUTED = "\u001b[38;2;157;165;169m";
|
|
5
|
+
const DIM = "\u001b[38;2;126;136;142m";
|
|
5
6
|
const RESET_FG = "\u001b[39m";
|
|
6
7
|
const BOLD = "\u001b[1m";
|
|
7
8
|
const RESET_BOLD = "\u001b[22m";
|
|
@@ -13,7 +14,8 @@ export function renderProjectTrustDialog(cwd, options, selected, terminalWidth,
|
|
|
13
14
|
const title = ` ${BOLD}${ACCENT}Trust project folder?${RESET_FG}${RESET_BOLD}`;
|
|
14
15
|
const path = ` ${MUTED}${sanitize(cwd)}${RESET_FG}`;
|
|
15
16
|
const choices = options.map((label, index) => choice(label, selected === index));
|
|
16
|
-
const
|
|
17
|
+
const closeKey = displayShortcutKeyLabel(DIALOG_CLOSE_SHORTCUT_HINT.key);
|
|
18
|
+
const hint = ` ${DIM}↑↓${MUTED} navigate ${DIM}Enter${MUTED} select ${DIM}${closeKey}${MUTED} ${DIALOG_CLOSE_SHORTCUT_HINT.action}${RESET_FG}`;
|
|
17
19
|
const explanation = wrap(EXPLANATION, Math.max(1, width - 2)).map(line => ` ${line}`);
|
|
18
20
|
const preferred = [rule, title, path, "", ...explanation, "", ...choices, "", hint, rule];
|
|
19
21
|
if (preferred.length <= terminalRows)
|
|
@@ -11,6 +11,8 @@ export interface ReferenceDocumentSection {
|
|
|
11
11
|
export interface ReferenceDocumentProvider {
|
|
12
12
|
/** Flat rows for this width, or null while the document is not available yet. */
|
|
13
13
|
readonly rows?: (width: number) => readonly string[] | null;
|
|
14
|
+
/** Rows between the screen title and structured groups, absent for group-only documents. */
|
|
15
|
+
readonly preamble?: (width: number) => readonly string[] | null;
|
|
14
16
|
/** Structured groups opt into shared Settings-style headers and pinning. */
|
|
15
17
|
readonly sections?: (width: number) => readonly ReferenceDocumentSection[] | null;
|
|
16
18
|
/** Settles once the selected content provider answers; absent when available at once. */
|
|
@@ -27,8 +29,8 @@ export interface ReferenceScreenOptions {
|
|
|
27
29
|
* Presents one read-only document full screen between two accent rules: the bold
|
|
28
30
|
* title leads the scrolled rows, the shared scrollbar rail runs beside them, and
|
|
29
31
|
* the hint line closes the frame. Rows come from a provider per content width and
|
|
30
|
-
* are cached until the width changes;
|
|
31
|
-
*
|
|
32
|
+
* are cached until the width changes; Escape closes locally, while an opted-in
|
|
33
|
+
* host closes on Ctrl+C before dispatching it into the screen.
|
|
32
34
|
*/
|
|
33
35
|
export declare class ReferenceScreenApp implements UiApp {
|
|
34
36
|
#private;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DIALOG_CLOSE_SHORTCUT_HINT } from "../../contracts/presentation/index.js";
|
|
2
|
+
import { GLOBAL_SCOPE, PLAIN_THEME, RAIL_COLUMNS, ShortcutRegistry, ScrollbarRails, assertNoShortcutConflicts, displayWidth, layoutList, padToWidth, renderGroupHeader, renderShortcutHintsWithClose, scrollForTrackPage, scrollbarGeometry, scrollbarPresentation, scrollbarWheelRows, truncateToWidth, withScrollbarRail, } from "../../ui/components/index.js";
|
|
2
3
|
const SCOPE = "reference-screen";
|
|
3
4
|
/** Rows above the document: the top rule. */
|
|
4
5
|
const HEADER_ROWS = 1;
|
|
@@ -9,14 +10,17 @@ const SCROLL_LINGER_MS = 900;
|
|
|
9
10
|
const SCROLL_LINGER_REPAINT_MS = 925;
|
|
10
11
|
const LOADING_NOTICE = "Loading…";
|
|
11
12
|
export const REFERENCE_SCREEN_SHORTCUTS = new ShortcutRegistry();
|
|
12
|
-
// Compatibility: Ctrl+C remains the A1 interrupt chord here rather than a close key.
|
|
13
|
-
REFERENCE_SCREEN_SHORTCUTS.declare({ key: "escape", scope: GLOBAL_SCOPE, description: "Close", section: "Screen", hint: { keys: "esc", does: "close" } }, "close");
|
|
14
13
|
REFERENCE_SCREEN_SHORTCUTS.declare({ key: "up", scope: SCOPE, description: "Scroll up", section: "Navigate", hint: { keys: "↑↓", does: "scroll" } }, "up");
|
|
15
14
|
REFERENCE_SCREEN_SHORTCUTS.declare({ key: "down", scope: SCOPE, description: "Scroll down", section: "Navigate", hint: { keys: "↑↓", does: "scroll" } }, "down");
|
|
16
15
|
REFERENCE_SCREEN_SHORTCUTS.declare({ key: "pageUp", scope: SCOPE, description: "Up a page", section: "Navigate" }, "page-up");
|
|
17
16
|
REFERENCE_SCREEN_SHORTCUTS.declare({ key: "pageDown", scope: SCOPE, description: "Down a page", section: "Navigate" }, "page-down");
|
|
18
17
|
REFERENCE_SCREEN_SHORTCUTS.declare({ key: "home", scope: SCOPE, description: "First row", section: "Navigate" }, "first");
|
|
19
18
|
REFERENCE_SCREEN_SHORTCUTS.declare({ key: "end", scope: SCOPE, description: "Last row", section: "Navigate" }, "last");
|
|
19
|
+
// Compatibility: Ctrl+C remains the A1 interrupt chord here rather than a visible close key.
|
|
20
|
+
REFERENCE_SCREEN_SHORTCUTS.declare({
|
|
21
|
+
key: "escape", scope: GLOBAL_SCOPE, description: "Close", section: "Screen",
|
|
22
|
+
hint: { keys: DIALOG_CLOSE_SHORTCUT_HINT.key, does: DIALOG_CLOSE_SHORTCUT_HINT.action },
|
|
23
|
+
}, "close");
|
|
20
24
|
assertNoShortcutConflicts(REFERENCE_SCREEN_SHORTCUTS.assemble());
|
|
21
25
|
const KEYS = {
|
|
22
26
|
"\u001b[A": "up",
|
|
@@ -36,8 +40,8 @@ const KEYS = {
|
|
|
36
40
|
* Presents one read-only document full screen between two accent rules: the bold
|
|
37
41
|
* title leads the scrolled rows, the shared scrollbar rail runs beside them, and
|
|
38
42
|
* the hint line closes the frame. Rows come from a provider per content width and
|
|
39
|
-
* are cached until the width changes;
|
|
40
|
-
*
|
|
43
|
+
* are cached until the width changes; Escape closes locally, while an opted-in
|
|
44
|
+
* host closes on Ctrl+C before dispatching it into the screen.
|
|
41
45
|
*/
|
|
42
46
|
export class ReferenceScreenApp {
|
|
43
47
|
id;
|
|
@@ -135,7 +139,7 @@ export class ReferenceScreenApp {
|
|
|
135
139
|
const withRail = withScrollbarRail(body.slice(0, bodyHeight), geometry, contentWidth, theme, { presentation });
|
|
136
140
|
const hint = this.#interruptArmed
|
|
137
141
|
? theme.fg("dim", " press ctrl+c again to exit a1")
|
|
138
|
-
:
|
|
142
|
+
: renderShortcutHintsWithClose(REFERENCE_SCREEN_SHORTCUTS.hintEntries(SCOPE), theme, rect.width, 1);
|
|
139
143
|
// Compatibility: the v2 reference screen frames its document between two border-coloured rules.
|
|
140
144
|
const rule = theme.fg("border", "─".repeat(rect.width));
|
|
141
145
|
// Invariant: dialog chrome shares the title's one-cell inset; document content keeps its own layout.
|
|
@@ -222,10 +226,16 @@ export class ReferenceScreenApp {
|
|
|
222
226
|
if (cached !== null && cached.width === width)
|
|
223
227
|
return this.#withTitle(cached.content, title);
|
|
224
228
|
const sections = this.#document.sections?.(width);
|
|
225
|
-
|
|
229
|
+
const preamble = sections === undefined ? undefined : this.#document.preamble?.(width);
|
|
230
|
+
if (sections === null || preamble === null)
|
|
226
231
|
return { kind: "flat", rows: [title, "", LOADING_NOTICE] };
|
|
227
232
|
if (sections !== undefined) {
|
|
228
233
|
const rows = [];
|
|
234
|
+
if (preamble !== undefined && preamble.length > 0) {
|
|
235
|
+
for (const row of preamble)
|
|
236
|
+
rows.push({ kind: "note", group: "", text: row });
|
|
237
|
+
rows.push({ kind: "spacer" });
|
|
238
|
+
}
|
|
229
239
|
sections.forEach((section, sectionIndex) => {
|
|
230
240
|
if (sectionIndex > 0)
|
|
231
241
|
rows.push({ kind: "spacer" });
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DIALOG_CLOSE_SHORTCUT_HINT } from "../../contracts/presentation/index.js";
|
|
2
|
+
import { GLOBAL_SCOPE, LineInput, PLAIN_THEME, ShortcutRegistry, assertNoShortcutConflicts, blockJumpTarget, dialogValueColumn, numericValues, RAIL_COLUMNS, renderDialogPanel, renderEmptyState, renderGroupHeader, renderInputRow, renderListRow, renderNote, renderShortcutHintsWithClose, dialogRowAt, menuRowAt, regionAt, renderValueMenu, withScrollbarRail, stepperEnds, steppedValue, truncateToWidth, valueColumnFor, valueMenuFrame, blockRowSpan, displayWidth, handleLineInputKey, humanizeLabel, humanizeTitle, indexOfKey, isThumbRow, layoutList, moveSelection, rowKey, scrollForSelection, scrollForTrackPage, scrollbarGeometry, scrollbarPresentation, ScrollbarRails, scrollbarWheelRows, selectableIndexes, } from "../../ui/components/index.js";
|
|
2
3
|
import { SETTINGS_APP_ID, SETTINGS_ROUTE } from "./settings-route.js";
|
|
3
4
|
export { SETTINGS_APP_ID, SETTINGS_ROUTE } from "./settings-route.js";
|
|
4
5
|
const SCOPE = SETTINGS_APP_ID;
|
|
@@ -35,13 +36,16 @@ SETTINGS_SHORTCUTS.declare({ key: "enter", scope: SCOPE, description: "Change va
|
|
|
35
36
|
SETTINGS_SHORTCUTS.declare({ key: "space", scope: SCOPE, description: "Change value", section: "Change", hint: { keys: "Enter/Space", does: "to change" } }, "activate");
|
|
36
37
|
SETTINGS_SHORTCUTS.declare({ key: "left", scope: SCOPE, description: "Previous value", section: "Change", hint: { keys: "←→", does: "to adjust" } }, "previous-value");
|
|
37
38
|
SETTINGS_SHORTCUTS.declare({ key: "right", scope: SCOPE, description: "Next value", section: "Change", hint: { keys: "←→", does: "to adjust" } }, "next-value");
|
|
38
|
-
SETTINGS_SHORTCUTS.declare({ key: "escape", scope: GLOBAL_SCOPE, description: "Close", section: "Screen", hint: { keys: "Esc", does: "to cancel" } }, "close");
|
|
39
39
|
SETTINGS_SHORTCUTS.declare({ key: "enter", scope: DIALOG_SCOPE, description: "Change this part", section: "Parts", hint: { keys: "Enter/Space", does: "to change" } }, "part-change");
|
|
40
40
|
SETTINGS_SHORTCUTS.declare({ key: "space", scope: DIALOG_SCOPE, description: "Change this part", section: "Parts", hint: { keys: "Enter/Space", does: "to change" } }, "part-change");
|
|
41
41
|
SETTINGS_SHORTCUTS.declare({ key: "left", scope: DIALOG_SCOPE, description: "Change this part", section: "Parts" }, "part-change");
|
|
42
42
|
SETTINGS_SHORTCUTS.declare({ key: "right", scope: DIALOG_SCOPE, description: "Change this part", section: "Parts" }, "part-change");
|
|
43
43
|
SETTINGS_SHORTCUTS.declare({ key: "up", scope: DIALOG_SCOPE, description: "Previous part", section: "Parts" }, "part-previous");
|
|
44
44
|
SETTINGS_SHORTCUTS.declare({ key: "down", scope: DIALOG_SCOPE, description: "Next part", section: "Parts" }, "part-next");
|
|
45
|
+
SETTINGS_SHORTCUTS.declare({
|
|
46
|
+
key: "escape", scope: GLOBAL_SCOPE, description: "Close", section: "Screen",
|
|
47
|
+
hint: { keys: DIALOG_CLOSE_SHORTCUT_HINT.key, does: DIALOG_CLOSE_SHORTCUT_HINT.action },
|
|
48
|
+
}, "close");
|
|
45
49
|
assertNoShortcutConflicts(SETTINGS_SHORTCUTS.assemble());
|
|
46
50
|
const KEYS = {
|
|
47
51
|
"\u001b[A": "up",
|
|
@@ -451,8 +455,9 @@ export class SettingsApp {
|
|
|
451
455
|
return;
|
|
452
456
|
}
|
|
453
457
|
const current = shown === null ? 0 : Math.max(0, entry.choices.indexOf(shown));
|
|
454
|
-
//
|
|
455
|
-
|
|
458
|
+
// Invariant: the opening press targeted the setting value, not an option. Keep the
|
|
459
|
+
// effective value as the keyboard origin without painting it as pointer-picked.
|
|
460
|
+
this.#menu = { entry, current, anchorKey: `${entry.backend}:${entry.id}`, choices: entry.choices, index: -1 };
|
|
456
461
|
}
|
|
457
462
|
// Rationale: a structured setting opens as its own flag list rather than a value menu.
|
|
458
463
|
#openStructured(entry) {
|
|
@@ -797,7 +802,7 @@ export class SettingsApp {
|
|
|
797
802
|
? notice
|
|
798
803
|
: this.#interruptArmed ? "press ctrl+c again to exit a1" : null;
|
|
799
804
|
const status = plainStatus === null
|
|
800
|
-
?
|
|
805
|
+
? renderShortcutHintsWithClose(SETTINGS_SHORTCUTS.hintEntries(SCOPE), theme, width, width > 0 ? 1 : 0)
|
|
801
806
|
: truncateToWidth(`${width > 0 ? " " : ""}${theme.fg("dim", plainStatus)}`, width);
|
|
802
807
|
const input = this.#filter;
|
|
803
808
|
if (input === null)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Generated by scripts/pi/sync-progress-palette.ts from @earendil-works/pi-coding-agent 1.0.
|
|
3
|
-
* (MIT), commit
|
|
2
|
+
* Generated by scripts/pi/sync-progress-palette.ts from @earendil-works/pi-coding-agent 1.0.4
|
|
3
|
+
* (MIT), commit 7c10bd4337495ee613f2224843ecdf349b80d1df. Do not edit directly.
|
|
4
4
|
*/
|
|
5
5
|
export declare const SHARED_PROGRESS_ACCENT_ANSI = "\u001B[38;2;167;152;215m";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Generated by scripts/pi/sync-progress-palette.ts from @earendil-works/pi-coding-agent 1.0.
|
|
3
|
-
* (MIT), commit
|
|
2
|
+
* Generated by scripts/pi/sync-progress-palette.ts from @earendil-works/pi-coding-agent 1.0.4
|
|
3
|
+
* (MIT), commit 7c10bd4337495ee613f2224843ecdf349b80d1df. Do not edit directly.
|
|
4
4
|
*/
|
|
5
5
|
export const SHARED_PROGRESS_ACCENT_ANSI = "\u001b[38;2;167;152;215m";
|