@timurproko/a1 0.2.7-dev.1270 → 0.2.7-dev.1275
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 +61 -0
- package/dist/app/session-shell/dialog-coordinator.d.ts +8 -0
- package/dist/app/session-shell/dialog-coordinator.js +72 -3
- package/dist/app/session-shell/session-selectors.d.ts +1 -1
- package/dist/app/session-shell/session-selectors.js +1 -1
- package/dist/app/session-shell/session-shell.js +9 -3
- 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/workflow-output.js +12 -0
- package/dist/app/session-shell/workflow-router.d.ts +1 -1
- package/dist/composition/owned-ui.js +17 -13
- 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 +2 -0
- package/dist/contracts/presentation/progress-palette.generated.d.ts +1 -1
- package/dist/contracts/presentation/progress-palette.generated.js +1 -1
- package/dist/contracts/presentation/terminal.d.ts +4 -0
- package/dist/contracts/presentation/theme.d.ts +2 -0
- 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/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 +2 -1
- package/dist/integrations/pi/components/shell-selectors-dialogs.js +2 -8
- package/dist/integrations/pi/components/theme.d.ts +2 -0
- package/dist/integrations/pi/components/theme.js +5 -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/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.js +9 -2
- 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/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 +9 -14
- 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.js +1 -1
- 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/presentation.js +2 -1
- package/dist/integrations/pi/session-presenters/presenters.js +22 -10
- 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/spans.d.ts +7 -0
- package/dist/ui/components/spans.js +63 -1
- 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
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { lstat, mkdir, open, unlink } from "node:fs/promises";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
5
|
+
import { PRODUCT_IDENTITY } from "../../product-identity.js";
|
|
6
|
+
/** Persistent user-owned exports; development data/config overrides never relocate user files. */
|
|
7
|
+
function resolveUserExportsDirectory(home = process.env[PRODUCT_IDENTITY.environment.profileHome] ?? homedir()) {
|
|
8
|
+
if (!isAbsolute(home) || home.includes("\0"))
|
|
9
|
+
throw new TypeError("User export home must be absolute");
|
|
10
|
+
return resolve(home, dirname(PRODUCT_IDENTITY.state.piAgentProfile), "exports");
|
|
11
|
+
}
|
|
12
|
+
/** Exclusively reserve a default export; failure cleanup may remove only this same regular file. */
|
|
13
|
+
export async function reserveUserExport(sessionId, format, home) {
|
|
14
|
+
const directory = resolveUserExportsDirectory(home);
|
|
15
|
+
const parent = dirname(directory);
|
|
16
|
+
await mkdir(parent, { recursive: true });
|
|
17
|
+
if (!(await lstat(parent)).isDirectory())
|
|
18
|
+
throw new Error("User export directory must not traverse a link");
|
|
19
|
+
await mkdir(directory, { recursive: true });
|
|
20
|
+
if (!(await lstat(directory)).isDirectory())
|
|
21
|
+
throw new Error("User export directory must not traverse a link");
|
|
22
|
+
const id = sessionId.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 80) || "session";
|
|
23
|
+
const stamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
24
|
+
const path = join(directory, `${PRODUCT_IDENTITY.filesystem.slug}-session-${stamp}-${id}-${randomUUID()}.${format}`);
|
|
25
|
+
const file = await open(path, "wx", 0o600);
|
|
26
|
+
const identity = await file.stat();
|
|
27
|
+
await file.close();
|
|
28
|
+
return {
|
|
29
|
+
path,
|
|
30
|
+
async failed() {
|
|
31
|
+
const current = await lstat(path).catch(error => { if (error.code !== "ENOENT")
|
|
32
|
+
throw error; });
|
|
33
|
+
if (current?.isFile() && current.dev === identity.dev && current.ino === identity.ino)
|
|
34
|
+
await unlink(path);
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
@@ -10,7 +10,7 @@ export const STARTUP_DESCRIPTOR = Object.freeze({
|
|
|
10
10
|
],
|
|
11
11
|
"generatedArtifact": {
|
|
12
12
|
"path": "dist/integrations/pi/startup-public.js",
|
|
13
|
-
"sha256": "
|
|
13
|
+
"sha256": "e6a12f0ec3c5f2ada12bb29f8a02584f0724b37d107c29608b6629a4196cca13"
|
|
14
14
|
},
|
|
15
15
|
"dependencyLayerIdentity": {
|
|
16
16
|
"source": "A1_RELEASE_LAYERS",
|
|
@@ -19,7 +19,7 @@ export const STARTUP_DESCRIPTOR = Object.freeze({
|
|
|
19
19
|
"compileCacheNamespace": {
|
|
20
20
|
"strategy": "node-abi-version-and-ordered-layer-sha256-v1"
|
|
21
21
|
},
|
|
22
|
-
"identity": "
|
|
22
|
+
"identity": "1823698969cb8a551539b6351a7ba7b0756121369e6f9bf898347080d7892ece"
|
|
23
23
|
});
|
|
24
24
|
|
|
25
25
|
export function loadDeclaredStartupGraph() {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { OwnedUiShellComponentPort } from "../../../contracts/owned-ui/index.js";
|
|
2
|
+
import type { ModelsDialogConfig, ModelsDialogCallbacks, ModelsDialogModel } from "./models-dialog.js";
|
|
3
|
+
interface DeferredModelsDialogPort extends OwnedUiShellComponentPort {
|
|
4
|
+
readonly ready: Promise<void>;
|
|
5
|
+
updateModels(models: readonly ModelsDialogModel[]): void;
|
|
6
|
+
setRefreshStatus(message: string, kind: "muted" | "success" | "warning"): void;
|
|
7
|
+
dirty(): boolean;
|
|
8
|
+
}
|
|
9
|
+
/** Captures input immediately while keeping the optional Models controller outside the startup graph. */
|
|
10
|
+
export declare function createDeferredModelsDialog(options: ModelsDialogConfig & ModelsDialogCallbacks): DeferredModelsDialogPort;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/** Captures input immediately while keeping the optional Models controller outside the startup graph. */
|
|
2
|
+
export function createDeferredModelsDialog(options) {
|
|
3
|
+
let dialog;
|
|
4
|
+
let closed = false;
|
|
5
|
+
let focused = false;
|
|
6
|
+
let models = options.models;
|
|
7
|
+
let status;
|
|
8
|
+
let failure;
|
|
9
|
+
const pending = [];
|
|
10
|
+
const ready = import("./models-dialog.js").then(({ ModelsDialogComponent }) => {
|
|
11
|
+
if (closed)
|
|
12
|
+
return;
|
|
13
|
+
dialog = new ModelsDialogComponent({ ...options, models }, options);
|
|
14
|
+
dialog.focused = focused;
|
|
15
|
+
if (status !== undefined)
|
|
16
|
+
dialog.setRefreshStatus(...status);
|
|
17
|
+
for (const data of pending.splice(0)) {
|
|
18
|
+
if (!closed)
|
|
19
|
+
dialog.handleInput(data);
|
|
20
|
+
}
|
|
21
|
+
options.requestRender();
|
|
22
|
+
}).catch(() => { if (!closed) {
|
|
23
|
+
failure = "Models unavailable — Esc close";
|
|
24
|
+
options.requestRender();
|
|
25
|
+
} });
|
|
26
|
+
return {
|
|
27
|
+
ready,
|
|
28
|
+
render: width => dialog?.render(width) ?? (failure === undefined ? [] : [failure.slice(0, width)]),
|
|
29
|
+
handleInput: data => {
|
|
30
|
+
if (dialog !== undefined)
|
|
31
|
+
dialog.handleInput(data);
|
|
32
|
+
else if (data === "\u001b" || data === "\u0003")
|
|
33
|
+
options.onCancel();
|
|
34
|
+
else if (pending.length < 32)
|
|
35
|
+
pending.push(data);
|
|
36
|
+
},
|
|
37
|
+
invalidate: () => dialog?.invalidate(),
|
|
38
|
+
setFocused: value => { focused = value; if (dialog !== undefined)
|
|
39
|
+
dialog.focused = value; },
|
|
40
|
+
dispose: () => { closed = true; pending.length = 0; dialog?.dispose(); },
|
|
41
|
+
updateModels: next => { models = next; dialog?.updateModels(next); },
|
|
42
|
+
setRefreshStatus: (message, kind) => { status = [message, kind]; dialog?.setRefreshStatus(message, kind); },
|
|
43
|
+
dirty: () => dialog?.dirty ?? false,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
@@ -19,6 +19,8 @@ export interface ModelsDialogConfig {
|
|
|
19
19
|
readonly refreshStatus?: string;
|
|
20
20
|
}
|
|
21
21
|
export interface ModelsDialogCallbacks {
|
|
22
|
+
/** Live terminal height; omitted component consumers retain the ordinary 24-row budget. */
|
|
23
|
+
viewportHeight?(): number;
|
|
22
24
|
/** Enter on a row: the shell switches through its workflow and closes the dialog on success. */
|
|
23
25
|
onSelect(modelId: string): void;
|
|
24
26
|
/** Every scope or order edit, session-only. */
|
|
@@ -208,20 +208,25 @@ export class ModelsDialogComponent {
|
|
|
208
208
|
const push = (line = "") => { lines.push(truncateToWidth(line, width)); };
|
|
209
209
|
const rows = this.#rows();
|
|
210
210
|
this.#clampSelection(rows);
|
|
211
|
+
const height = this.#callbacks.viewportHeight?.() ?? 24;
|
|
212
|
+
const compact = height < 13;
|
|
213
|
+
const capacity = Math.max(1, Math.min(MAX_VISIBLE_ROWS, height - (compact ? 7 : 13)));
|
|
211
214
|
push(theme.fg("dim", "Filter: ")
|
|
212
215
|
+ theme.fg(this.#filter === "all" ? "mdHeading" : "dim", "all")
|
|
213
216
|
+ theme.fg("dim", " | ")
|
|
214
217
|
+ theme.fg(this.#filter === "scoped" ? "mdHeading" : "dim", "scoped"));
|
|
215
|
-
|
|
218
|
+
if (!compact)
|
|
219
|
+
push();
|
|
216
220
|
for (const line of renderPiModalSearchInput(this.#input, width))
|
|
217
221
|
push(line);
|
|
218
|
-
|
|
222
|
+
if (!compact)
|
|
223
|
+
push();
|
|
219
224
|
if (rows.length === 0) {
|
|
220
225
|
push(theme.fg("muted", ` ${this.#emptyText()}`));
|
|
221
226
|
}
|
|
222
227
|
else {
|
|
223
|
-
const startIndex = Math.max(0, Math.min(this.#selectedIndex - Math.floor(
|
|
224
|
-
const endIndex = Math.min(startIndex +
|
|
228
|
+
const startIndex = Math.max(0, Math.min(this.#selectedIndex - Math.floor(capacity / 2), rows.length - capacity));
|
|
229
|
+
const endIndex = Math.min(startIndex + capacity, rows.length);
|
|
225
230
|
for (let index = startIndex; index < endIndex; index += 1) {
|
|
226
231
|
const row = rows[index];
|
|
227
232
|
const selected = index === this.#selectedIndex;
|
|
@@ -234,15 +239,16 @@ export class ModelsDialogComponent {
|
|
|
234
239
|
const active = row.fullId === this.#activeModelId ? ` ${theme.fg("success", "✓")}` : "";
|
|
235
240
|
push(renderPiModalListRow(`${prefix}${marker} ${label} ${provider}${active}`, width, selected));
|
|
236
241
|
}
|
|
237
|
-
if (startIndex > 0 || endIndex < rows.length)
|
|
242
|
+
if (!compact && (startIndex > 0 || endIndex < rows.length))
|
|
238
243
|
push(theme.fg("muted", ` (${this.#selectedIndex + 1}/${rows.length})`));
|
|
239
244
|
const selectedRow = rows[this.#selectedIndex];
|
|
240
|
-
if (selectedRow) {
|
|
245
|
+
if (selectedRow && !compact) {
|
|
241
246
|
push();
|
|
242
247
|
push(theme.fg("muted", ` Model Name: ${selectedRow.model.name}`));
|
|
243
248
|
}
|
|
244
249
|
}
|
|
245
|
-
|
|
250
|
+
if (!compact)
|
|
251
|
+
push();
|
|
246
252
|
if (this.#refreshStatus !== undefined)
|
|
247
253
|
push(theme.fg(this.#refreshStatus.kind, ` ${this.#refreshStatus.message}`));
|
|
248
254
|
push(renderHintsWithClose(this.#hints(), width));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Attributed owned theme resources adapted from @earendil-works/pi-coding-agent 1.5.
|
|
3
|
-
* commit
|
|
2
|
+
* Attributed owned theme resources adapted from @earendil-works/pi-coding-agent 1.5.1 (MIT),
|
|
3
|
+
* commit dd30101cfc5b0609411dd80b6f93adbc14db14cf.
|
|
4
4
|
* Upstream dark.json SHA-256: e1f96982f8cb7d2a48eca7db03c9cb282cb1e14a243680cd855638ecd6a251b6
|
|
5
5
|
* Upstream light.json SHA-256: 2dee6a4be7f765e7fd7728166b7ebf8c29e4ce313f8ec6b38ae50699e3abc2f3
|
|
6
6
|
* Modifications: removed upstream schema/export metadata; runtime color data is unchanged.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Attributed owned theme resources adapted from @earendil-works/pi-coding-agent 1.5.
|
|
3
|
-
* commit
|
|
2
|
+
* Attributed owned theme resources adapted from @earendil-works/pi-coding-agent 1.5.1 (MIT),
|
|
3
|
+
* commit dd30101cfc5b0609411dd80b6f93adbc14db14cf.
|
|
4
4
|
* Upstream dark.json SHA-256: e1f96982f8cb7d2a48eca7db03c9cb282cb1e14a243680cd855638ecd6a251b6
|
|
5
5
|
* Upstream light.json SHA-256: 2dee6a4be7f765e7fd7728166b7ebf8c29e4ce313f8ec6b38ae50699e3abc2f3
|
|
6
6
|
* Modifications: removed upstream schema/export metadata; runtime color data is unchanged.
|
|
@@ -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,6 +1,6 @@
|
|
|
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 {
|
|
3
|
+
import type { ModelsDialogCallbacks, ModelsDialogConfig } from "./models-dialog.js";
|
|
4
4
|
import { type TrustDecision, type TrustOption, type TrustUpdate } from "./upstream/components/trust-selector.js";
|
|
5
5
|
import { type PiShellComponentPort, type PiShellEditorOptions, type PiShellSelectorOption, type PiShellSelectorOptions } from "./shell-shared-facade.js";
|
|
6
6
|
export { createPiShellSkillsSelector, type PiShellSkillsSelectorOptions } from "./skills-dialog.js";
|
|
@@ -50,6 +50,7 @@ export declare function createPiShellScopedModelsSelector(options: PiShellScoped
|
|
|
50
50
|
export interface PiShellModelsDialogOptions extends ModelsDialogConfig, ModelsDialogCallbacks {
|
|
51
51
|
}
|
|
52
52
|
export interface PiShellModelsDialogPort extends PiShellComponentPort {
|
|
53
|
+
readonly ready?: Promise<void>;
|
|
53
54
|
updateModels(models: readonly PiShellScopedModelDescriptor[]): void;
|
|
54
55
|
setRefreshStatus(message: string, kind: "muted" | "success" | "warning"): void;
|
|
55
56
|
readonly dirty: () => boolean;
|
|
@@ -4,7 +4,7 @@ import { ExtensionSelectorComponent } from "./upstream/components/extension-sele
|
|
|
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
6
|
import { addPiModalSelectFooter, adoptPiModalFrame, adoptPiModalHeader, adoptPiModalSearchInput } from "./modal-frame.js";
|
|
7
|
-
import {
|
|
7
|
+
import { createDeferredModelsDialog } from "./models-dialog-loader.js";
|
|
8
8
|
import { TrustSelectorComponent } from "./upstream/components/trust-selector.js";
|
|
9
9
|
import { canonicalizePiSettingsHint, DIALOG_CLOSE_SHORTCUT_HINT, PINNED_PI_LAYOUT, getPiSelectListTheme, paintPiBorder, piTheme, renderPiModalShortcutHints, } from "./theme.js";
|
|
10
10
|
import { componentFromPort, componentPort, createTuiFacade, ensureTheme, isRecord, } from "./shell-shared-facade.js";
|
|
@@ -133,13 +133,7 @@ export function createPiShellScopedModelsSelector(options) {
|
|
|
133
133
|
/** The bare-A1 unified Models dialog behind the owned component boundary; the pinned selectors above stay for `a1 pi`. */
|
|
134
134
|
export function createPiShellModelsDialog(options) {
|
|
135
135
|
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
|
-
};
|
|
136
|
+
return createDeferredModelsDialog(options);
|
|
143
137
|
}
|
|
144
138
|
export function createPiShellTrustSelector(options) {
|
|
145
139
|
ensureTheme();
|
|
@@ -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;
|
|
@@ -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 {
|
|
@@ -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": {
|
|
@@ -1,12 +1,12 @@
|
|
|
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 { Key, matchesKey, TUI_KEYBINDINGS, KeybindingsManager as TuiKeybindingsManager, } from "@earendil-works/pi-tui";
|
|
@@ -85,7 +85,7 @@ export const KEYBINDINGS = {
|
|
|
85
85
|
description: "Restore queued messages",
|
|
86
86
|
},
|
|
87
87
|
"app.clipboard.pasteImage": {
|
|
88
|
-
defaultKeys: windowsKeybindings ? "alt+v" : "ctrl+v",
|
|
88
|
+
defaultKeys: windowsKeybindings ? ["alt+v", "ctrl+v"] : "ctrl+v",
|
|
89
89
|
description: "Paste files on macOS, images, or text from clipboard",
|
|
90
90
|
},
|
|
91
91
|
"app.session.new": { defaultKeys: [], description: "Start a new session" },
|
|
@@ -186,6 +186,8 @@ const OWNED_INPUT_KEYBINDINGS = {
|
|
|
186
186
|
...KEYBINDINGS,
|
|
187
187
|
"app.thinking.cycle": { ...KEYBINDINGS["app.thinking.cycle"], defaultKeys: "ctrl+l" },
|
|
188
188
|
"app.model.select": { ...KEYBINDINGS["app.model.select"], defaultKeys: [] },
|
|
189
|
+
"app.model.cycleForward": { ...KEYBINDINGS["app.model.cycleForward"], defaultKeys: "ctrl+m" },
|
|
190
|
+
"owned.apps.open": { defaultKeys: "ctrl+p", description: "Open Launcher" },
|
|
189
191
|
"app.message.dequeue": { ...KEYBINDINGS["app.message.dequeue"], defaultKeys: "alt+up" },
|
|
190
192
|
"app.tree.filter.cycleForward": { ...KEYBINDINGS["app.tree.filter.cycleForward"], defaultKeys: "tab" },
|
|
191
193
|
"tui.editor.deleteWordBackward": {
|
|
@@ -369,6 +371,10 @@ export class KeybindingsManager extends TuiKeybindingsManager {
|
|
|
369
371
|
}
|
|
370
372
|
// Protocol: Ctrl+C is a conventional dialog escape hatch, not advertised keybinding chrome.
|
|
371
373
|
matches(data, keybinding) {
|
|
374
|
+
// Compatibility: legacy Ctrl+M is indistinguishable from Enter; never steal ordinary submission.
|
|
375
|
+
if (data === "\r" && this.getKeys(keybinding).includes("ctrl+m")) {
|
|
376
|
+
return this.getKeys(keybinding).some(key => key !== "ctrl+m" && matchesKey(data, key));
|
|
377
|
+
}
|
|
372
378
|
return keybinding === "tui.select.cancel" && matchesKey(data, "ctrl+c")
|
|
373
379
|
|| super.matches(data, keybinding);
|
|
374
380
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"sourcePackage": "@earendil-works/pi-coding-agent",
|
|
3
|
-
"sourceVersion": "1.5.
|
|
3
|
+
"sourceVersion": "1.5.1",
|
|
4
4
|
"upstreamRepository": "https://github.com/earendil-works/pi.git",
|
|
5
|
-
"upstreamCommit": "
|
|
5
|
+
"upstreamCommit": "dd30101cfc5b0609411dd80b6f93adbc14db14cf",
|
|
6
6
|
"sourcePath": "dist/modes/interactive/assets/clankolas.png",
|
|
7
7
|
"sourceSha256": "169acd0dfe6fbb8d8742ed24a3fc654fd0b2e2d4223c733249c5493723f1b72d",
|
|
8
8
|
"license": "MIT",
|
|
@@ -1,5 +1,5 @@
|
|
|
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/modes/interactive/components/countdown-timer.ts.
|
|
4
4
|
* Modifications: Mechanical source port with ECMAScript private fields; imports remain on the public
|
|
5
5
|
* Pi TUI package root.
|
|
@@ -1,5 +1,5 @@
|
|
|
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/modes/interactive/components/earendil-announcement.ts.
|
|
4
4
|
* Modifications: Mechanical pinned source port with private imports remapped to public package-root
|
|
5
5
|
* types/APIs and A1-owned theme boundaries. The unchanged image is loaded lazily from its attributed,
|
|
@@ -1,5 +1,5 @@
|
|
|
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/modes/interactive/components/extension-editor.ts.
|
|
4
4
|
* Modifications: Mechanical port: remap pi-tui to the root public singleton, use owned
|
|
5
5
|
* keybindings/theme and external-editor seams, preserve editor layout, hints, focus, submission,
|
|
@@ -1,5 +1,5 @@
|
|
|
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/modes/interactive/components/extension-editor.ts.
|
|
4
4
|
* Modifications: Mechanical port: remap pi-tui to the root public singleton, use owned
|
|
5
5
|
* keybindings/theme and external-editor seams, preserve editor layout, hints, focus, submission,
|
|
@@ -1,5 +1,5 @@
|
|
|
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/modes/interactive/components/extension-input.ts.
|
|
4
4
|
* Modifications: Mechanical port: remap public imports, use ECMAScript private fields, and route the
|
|
5
5
|
* bare-A1 instruction row and chrome through the shared semantic shortcut and compact padded
|
|
@@ -1,5 +1,5 @@
|
|
|
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/modes/interactive/components/extension-selector.ts.
|
|
4
4
|
* Modifications: Mechanical port: remap public imports, use ECMAScript private fields, and route the
|
|
5
5
|
* bare-A1 instruction row and chrome through the shared semantic shortcut and compact padded
|
|
@@ -59,12 +59,19 @@ export class ExtensionSelectorComponent extends Container {
|
|
|
59
59
|
#updateList() {
|
|
60
60
|
this.#listContainer.clear();
|
|
61
61
|
const theme = piTheme();
|
|
62
|
-
|
|
62
|
+
const maxVisible = 10;
|
|
63
|
+
// Center the window on the selection, then clamp it to the list boundaries.
|
|
64
|
+
const startIndex = Math.max(0, Math.min(this.#selectedIndex - Math.floor(maxVisible / 2), this.#options.length - maxVisible));
|
|
65
|
+
const endIndex = Math.min(startIndex + maxVisible, this.#options.length);
|
|
66
|
+
for (let index = startIndex; index < endIndex; index += 1) {
|
|
63
67
|
const option = this.#options[index];
|
|
64
68
|
this.#listContainer.addChild(new Text(index === this.#selectedIndex
|
|
65
69
|
? theme.fg("accent", "→ ") + theme.fg("accent", option)
|
|
66
70
|
: ` ${theme.fg("text", option)}`, 0, 0));
|
|
67
71
|
}
|
|
72
|
+
if (startIndex > 0 || endIndex < this.#options.length) {
|
|
73
|
+
this.#listContainer.addChild(new Text(theme.fg("muted", ` (${this.#selectedIndex + 1}/${this.#options.length})`), 0, 0));
|
|
74
|
+
}
|
|
68
75
|
}
|
|
69
76
|
handleInput(keyData) {
|
|
70
77
|
const keys = getKeybindings();
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { MarkdownTransformer, Theme } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
export type MermaidRenderingMode = "off" | "final" | "streaming";
|
|
3
|
+
type MermaidTheme = Pick<Theme, "fg" | "getFgAnsi">;
|
|
3
4
|
interface MermaidTransformerOptions {
|
|
4
5
|
getMode: () => MermaidRenderingMode;
|
|
5
|
-
theme?:
|
|
6
|
+
theme?: MermaidTheme;
|
|
6
7
|
}
|
|
7
8
|
/** Create a transformer that replaces top-level Mermaid code blocks with Unicode terminal diagrams. */
|
|
8
9
|
export declare function createMermaidMarkdownTransformer(options: MermaidTransformerOptions): MarkdownTransformer;
|