@timurproko/a1 0.1.8-dev.544 → 0.1.8-dev.558
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/bin/cli.js +4 -0
- package/dist/app/session-shell/session-shell-root.js +15 -5
- package/dist/cli/dispatch.d.ts +5 -0
- package/dist/cli/dispatch.js +26 -0
- package/dist/cli/session-context.d.ts +9 -0
- package/dist/cli/session-context.js +29 -0
- package/dist/composition/owned-ui.js +6 -2
- package/dist/contracts/owned-ui/model.d.ts +5 -0
- package/dist/contracts/owned-ui/validation.js +6 -0
- package/dist/contracts/presentation/index.d.ts +13 -0
- package/dist/contracts/presentation/index.js +30 -0
- package/dist/features/launch/index.d.ts +2 -0
- package/dist/features/launch/index.js +1 -0
- package/dist/features/launch/session-context.d.ts +8 -0
- package/dist/features/launch/session-context.js +8 -0
- package/dist/features/owned-ui/project-trust-prompt.js +1 -1
- package/dist/features/owned-ui/reference-screen-app.js +7 -8
- package/dist/features/owned-ui/settings-app.js +9 -5
- package/dist/foundation/lifecycle/index.d.ts +2 -0
- package/dist/foundation/lifecycle/index.js +1 -0
- package/dist/foundation/lifecycle/session-repository-context.d.ts +18 -0
- package/dist/foundation/lifecycle/session-repository-context.js +173 -0
- package/dist/foundation/release/index.d.ts +2 -2
- package/dist/foundation/release/index.js +1 -1
- package/dist/foundation/release/update.d.ts +22 -1
- package/dist/foundation/release/update.js +61 -12
- package/dist/integrations/pi/components/models-dialog.js +9 -9
- package/dist/integrations/pi/components/shell-editor-autocomplete.d.ts +0 -6
- package/dist/integrations/pi/components/shell-editor-autocomplete.js +41 -8
- package/dist/integrations/pi/components/shell-extension-ui.js +4 -2
- package/dist/integrations/pi/components/shell-footer-status.js +1 -1
- package/dist/integrations/pi/components/shell-presenters-transcript.js +4 -2
- package/dist/integrations/pi/components/skills-command.d.ts +2 -0
- package/dist/integrations/pi/components/skills-command.js +11 -10
- package/dist/integrations/pi/components/skills-dialog.js +8 -3
- package/dist/integrations/pi/components/theme.d.ts +4 -0
- package/dist/integrations/pi/components/theme.js +10 -0
- package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.d.ts +4 -4
- package/dist/integrations/pi/components/upstream/components/extension-editor.d.ts +2 -2
- package/dist/integrations/pi/components/upstream/components/extension-editor.js +9 -10
- package/dist/integrations/pi/components/upstream/components/extension-input.d.ts +17 -0
- package/dist/integrations/pi/components/upstream/components/extension-input.js +72 -0
- package/dist/integrations/pi/components/upstream/components/extension-selector.d.ts +15 -0
- package/dist/integrations/pi/components/upstream/components/extension-selector.js +92 -0
- package/dist/integrations/pi/components/upstream/components/scoped-models-selector.d.ts +3 -2
- package/dist/integrations/pi/components/upstream/components/scoped-models-selector.js +16 -15
- package/dist/integrations/pi/components/upstream/components/session-footer.js +25 -9
- package/dist/integrations/pi/components/upstream/components/session-selector.js +25 -16
- package/dist/integrations/pi/components/upstream/components/thinking-selector.d.ts +6 -4
- package/dist/integrations/pi/components/upstream/components/thinking-selector.js +22 -12
- package/dist/integrations/pi/components/upstream/components/tree-selector.d.ts +3 -2
- package/dist/integrations/pi/components/upstream/components/tree-selector.js +16 -13
- package/dist/integrations/pi/components/upstream/components/trust-selector.js +11 -5
- package/dist/integrations/pi/engine/adapter.d.ts +2 -1
- package/dist/integrations/pi/engine/adapter.js +2 -0
- package/dist/integrations/pi/engine/message-values.js +1 -0
- package/dist/integrations/pi/engine/resource-catalog.js +1 -1
- package/dist/integrations/pi/engine/session-runtime.d.ts +11 -2
- package/dist/integrations/pi/engine/session-runtime.js +136 -33
- package/dist/integrations/pi/engine/transcript-projection.js +35 -0
- package/dist/integrations/pi/startup-public.manifest.json +2 -0
- package/dist/native/darwin-arm64/manifest.json +1 -1
- package/dist/native/linux-x64/manifest.json +1 -1
- package/dist/native/win32-x64/manifest.json +2 -2
- package/dist/native/win32-x64/process-guardian.exe +0 -0
- package/dist/product-identity.d.ts +1 -1
- package/dist/product-identity.js +1 -1
- package/dist/product-identity.json +2 -1
- package/dist/ui/components/dialog-panel.d.ts +2 -1
- package/dist/ui/components/dialog-panel.js +6 -1
- package/dist/ui/components/index.d.ts +2 -0
- package/dist/ui/components/index.js +1 -0
- package/dist/ui/components/shortcut-hints.d.ts +7 -0
- package/dist/ui/components/shortcut-hints.js +12 -0
- package/dist/ui/components/shortcuts.d.ts +2 -0
- package/dist/ui/components/shortcuts.js +5 -2
- package/dist/ui/components/transcript-viewport.d.ts +1 -1
- package/docs/architecture/project-structure.md +6 -3
- package/docs/ci-release-runbook.md +9 -7
- package/docs/openspec-archive-automation.md +6 -0
- package/docs/validation.md +5 -2
- package/package.json +1 -1
|
@@ -139,7 +139,7 @@ export declare const KEYBINDINGS: {
|
|
|
139
139
|
readonly description: "Copy selection or last assistant message";
|
|
140
140
|
};
|
|
141
141
|
readonly "app.message.followUp": {
|
|
142
|
-
readonly defaultKeys: "
|
|
142
|
+
readonly defaultKeys: "alt+enter" | "ctrl+q";
|
|
143
143
|
readonly description: "Queue follow-up message";
|
|
144
144
|
};
|
|
145
145
|
readonly "app.message.dequeue": {
|
|
@@ -147,7 +147,7 @@ export declare const KEYBINDINGS: {
|
|
|
147
147
|
readonly description: "Restore queued messages";
|
|
148
148
|
};
|
|
149
149
|
readonly "app.clipboard.pasteImage": {
|
|
150
|
-
readonly defaultKeys: "
|
|
150
|
+
readonly defaultKeys: "alt+v" | "ctrl+v";
|
|
151
151
|
readonly description: "Paste image from clipboard (text fallback)";
|
|
152
152
|
};
|
|
153
153
|
readonly "app.session.new": {
|
|
@@ -167,11 +167,11 @@ export declare const KEYBINDINGS: {
|
|
|
167
167
|
readonly description: "Resume a session";
|
|
168
168
|
};
|
|
169
169
|
readonly "app.tree.foldOrUp": {
|
|
170
|
-
readonly defaultKeys: ("
|
|
170
|
+
readonly defaultKeys: ("alt+left" | "ctrl+left")[];
|
|
171
171
|
readonly description: "Fold tree branch or move up";
|
|
172
172
|
};
|
|
173
173
|
readonly "app.tree.unfoldOrDown": {
|
|
174
|
-
readonly defaultKeys: ("
|
|
174
|
+
readonly defaultKeys: ("alt+right" | "ctrl+right")[];
|
|
175
175
|
readonly description: "Unfold tree branch or move down";
|
|
176
176
|
};
|
|
177
177
|
readonly "app.tree.editLabel": {
|
|
@@ -3,8 +3,8 @@
|
|
|
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,
|
|
6
|
-
* cancellation, and external-editor lifecycle.
|
|
7
|
-
* Deviations:
|
|
6
|
+
* cancellation, and external-editor lifecycle; bare A1 uses the shared semantic modal shortcut row.
|
|
7
|
+
* Deviations: owned-modal-shortcut-hints.
|
|
8
8
|
*/
|
|
9
9
|
import { Container, type TUI } from "@earendil-works/pi-tui";
|
|
10
10
|
import type { KeybindingsManager } from "../adjacent/core/keybindings.js";
|
|
@@ -3,16 +3,13 @@
|
|
|
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,
|
|
6
|
-
* cancellation, and external-editor lifecycle.
|
|
7
|
-
* Deviations:
|
|
6
|
+
* cancellation, and external-editor lifecycle; bare A1 uses the shared semantic modal shortcut row.
|
|
7
|
+
* Deviations: owned-modal-shortcut-hints.
|
|
8
8
|
*/
|
|
9
9
|
import { Container, Editor, Spacer, Text, } from "@earendil-works/pi-tui";
|
|
10
10
|
import { DynamicBorder, getSelectListTheme } from "../../../startup-public.js";
|
|
11
11
|
import { editInExternalEditor } from "../external-editor.js";
|
|
12
|
-
import { piTheme } from "../../theme.js";
|
|
13
|
-
function keyHint(keybindings, keybinding, description) {
|
|
14
|
-
return piTheme().fg("dim", keybindings.getKeys(keybinding).join("/")) + piTheme().fg("muted", ` ${description}`);
|
|
15
|
-
}
|
|
12
|
+
import { piTheme, renderPiModalShortcutHints } from "../../theme.js";
|
|
16
13
|
export class ExtensionEditorComponent extends Container {
|
|
17
14
|
#editor;
|
|
18
15
|
#tui;
|
|
@@ -54,10 +51,12 @@ export class ExtensionEditorComponent extends Container {
|
|
|
54
51
|
this.#editor.onSubmit = onSubmit;
|
|
55
52
|
this.addChild(this.#editor);
|
|
56
53
|
this.addChild(new Spacer(1));
|
|
57
|
-
const hint =
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
54
|
+
const hint = renderPiModalShortcutHints([
|
|
55
|
+
{ key: this.#keybindings.getKeys("tui.select.confirm").join("/"), action: "submit" },
|
|
56
|
+
{ key: this.#keybindings.getKeys("tui.input.newLine").join("/"), action: "newline" },
|
|
57
|
+
{ key: this.#keybindings.getKeys("tui.select.cancel").join("/"), action: "cancel" },
|
|
58
|
+
{ key: this.#keybindings.getKeys("app.editor.external").join("/"), action: "external editor" },
|
|
59
|
+
]);
|
|
61
60
|
this.addChild(new Text(hint, 1, 0));
|
|
62
61
|
this.addChild(new Spacer(1));
|
|
63
62
|
this.addChild(new DynamicBorder());
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Container, type TUI } from "@earendil-works/pi-tui";
|
|
2
|
+
interface ExtensionInputOptions {
|
|
3
|
+
readonly tui?: TUI;
|
|
4
|
+
readonly timeout?: number;
|
|
5
|
+
readonly description?: string;
|
|
6
|
+
readonly initialValue?: string;
|
|
7
|
+
}
|
|
8
|
+
/** Bare-A1 extension text input using the common modal shortcut row. */
|
|
9
|
+
export declare class ExtensionInputComponent extends Container {
|
|
10
|
+
#private;
|
|
11
|
+
get focused(): boolean;
|
|
12
|
+
set focused(value: boolean);
|
|
13
|
+
constructor(title: string, _placeholder: string | undefined, onSubmit: (value: string) => void, onCancel: () => void, opts?: ExtensionInputOptions);
|
|
14
|
+
handleInput(keyData: string): void;
|
|
15
|
+
dispose(): void;
|
|
16
|
+
}
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provenance: @earendil-works/pi-coding-agent 0.87.0 (MIT), commit 16787ad5b2dc748047f314ca1bfe7708f30f54f3,
|
|
3
|
+
* packages/coding-agent/src/modes/interactive/components/extension-input.ts.
|
|
4
|
+
* Modifications: Mechanical port: remap public imports, use ECMAScript private fields, and route the
|
|
5
|
+
* bare-A1 instruction row through the shared semantic shortcut renderer while preserving input,
|
|
6
|
+
* timeout, focus, submission, cancellation, and disposal behavior.
|
|
7
|
+
* Deviations: owned-modal-shortcut-hints.
|
|
8
|
+
*/
|
|
9
|
+
import { DynamicBorder } from "../../../startup-public.js";
|
|
10
|
+
import { Container, getKeybindings, Input, Spacer, Text } from "@earendil-works/pi-tui";
|
|
11
|
+
import { piTheme, renderPiModalShortcutHints } from "../../theme.js";
|
|
12
|
+
import { CountdownTimer } from "./countdown-timer.js";
|
|
13
|
+
/** Bare-A1 extension text input using the common modal shortcut row. */
|
|
14
|
+
export class ExtensionInputComponent extends Container {
|
|
15
|
+
#input = new Input();
|
|
16
|
+
#onSubmit;
|
|
17
|
+
#onCancel;
|
|
18
|
+
#titleText;
|
|
19
|
+
#baseTitle;
|
|
20
|
+
#countdown;
|
|
21
|
+
#focused = false;
|
|
22
|
+
get focused() { return this.#focused; }
|
|
23
|
+
set focused(value) {
|
|
24
|
+
this.#focused = value;
|
|
25
|
+
this.#input.focused = value;
|
|
26
|
+
}
|
|
27
|
+
constructor(title, _placeholder, onSubmit, onCancel, opts) {
|
|
28
|
+
super();
|
|
29
|
+
this.#onSubmit = onSubmit;
|
|
30
|
+
this.#onCancel = onCancel;
|
|
31
|
+
this.#baseTitle = title;
|
|
32
|
+
const theme = piTheme();
|
|
33
|
+
this.addChild(new DynamicBorder());
|
|
34
|
+
this.addChild(new Spacer(1));
|
|
35
|
+
this.#titleText = new Text(theme.fg("accent", title), 1, 0);
|
|
36
|
+
this.addChild(this.#titleText);
|
|
37
|
+
if (opts?.description) {
|
|
38
|
+
this.addChild(new Spacer(1));
|
|
39
|
+
this.addChild(new Text(theme.fg("text", opts.description), 1, 0));
|
|
40
|
+
}
|
|
41
|
+
this.addChild(new Spacer(1));
|
|
42
|
+
this.#countdown = opts?.timeout !== undefined && opts.timeout > 0 && opts.tui !== undefined
|
|
43
|
+
? new CountdownTimer(opts.timeout, opts.tui, seconds => {
|
|
44
|
+
const current = piTheme();
|
|
45
|
+
this.#titleText.setText(current.fg("accent", `${this.#baseTitle} (${seconds}s)`));
|
|
46
|
+
}, () => this.#onCancel())
|
|
47
|
+
: undefined;
|
|
48
|
+
if (opts?.initialValue !== undefined)
|
|
49
|
+
this.#input.setValue(opts.initialValue);
|
|
50
|
+
this.addChild(this.#input);
|
|
51
|
+
this.addChild(new Spacer(1));
|
|
52
|
+
const keys = getKeybindings();
|
|
53
|
+
this.addChild(new Text(renderPiModalShortcutHints([
|
|
54
|
+
{ key: keys.getKeys("tui.select.confirm").join("/"), action: "submit" },
|
|
55
|
+
{ key: keys.getKeys("tui.select.cancel").join("/"), action: "cancel" },
|
|
56
|
+
]), 1, 0));
|
|
57
|
+
this.addChild(new Spacer(1));
|
|
58
|
+
this.addChild(new DynamicBorder());
|
|
59
|
+
}
|
|
60
|
+
handleInput(keyData) {
|
|
61
|
+
const keys = getKeybindings();
|
|
62
|
+
if (keys.matches(keyData, "tui.select.confirm") || keyData === "\n")
|
|
63
|
+
this.#onSubmit(this.#input.getValue());
|
|
64
|
+
else if (keys.matches(keyData, "tui.select.cancel"))
|
|
65
|
+
this.#onCancel();
|
|
66
|
+
else
|
|
67
|
+
this.#input.handleInput(keyData);
|
|
68
|
+
}
|
|
69
|
+
dispose() {
|
|
70
|
+
this.#countdown?.dispose();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Container, type TUI } from "@earendil-works/pi-tui";
|
|
2
|
+
interface ExtensionSelectorOptions {
|
|
3
|
+
readonly tui?: TUI;
|
|
4
|
+
readonly timeout?: number;
|
|
5
|
+
readonly description?: string;
|
|
6
|
+
readonly onToggleToolsExpanded?: () => void;
|
|
7
|
+
}
|
|
8
|
+
/** Bare-A1 extension selector using the common modal shortcut row. */
|
|
9
|
+
export declare class ExtensionSelectorComponent extends Container {
|
|
10
|
+
#private;
|
|
11
|
+
constructor(title: string, options: readonly string[], onSelect: (value: string) => void, onCancel: () => void, opts?: ExtensionSelectorOptions);
|
|
12
|
+
handleInput(keyData: string): void;
|
|
13
|
+
dispose(): void;
|
|
14
|
+
}
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provenance: @earendil-works/pi-coding-agent 0.87.0 (MIT), commit 16787ad5b2dc748047f314ca1bfe7708f30f54f3,
|
|
3
|
+
* packages/coding-agent/src/modes/interactive/components/extension-selector.ts.
|
|
4
|
+
* Modifications: Mechanical port: remap public imports, use ECMAScript private fields, and route the
|
|
5
|
+
* bare-A1 instruction row through the shared semantic shortcut renderer while preserving options,
|
|
6
|
+
* timeout, navigation, selection, cancellation, and disposal behavior.
|
|
7
|
+
* Deviations: owned-modal-shortcut-hints.
|
|
8
|
+
*/
|
|
9
|
+
import { DynamicBorder } from "../../../startup-public.js";
|
|
10
|
+
import { Container, getKeybindings, Spacer, Text } from "@earendil-works/pi-tui";
|
|
11
|
+
import { piTheme, renderPiModalShortcutHints } from "../../theme.js";
|
|
12
|
+
import { CountdownTimer } from "./countdown-timer.js";
|
|
13
|
+
/** Bare-A1 extension selector using the common modal shortcut row. */
|
|
14
|
+
export class ExtensionSelectorComponent extends Container {
|
|
15
|
+
#options;
|
|
16
|
+
#selectedIndex = 0;
|
|
17
|
+
#listContainer = new Container();
|
|
18
|
+
#onSelect;
|
|
19
|
+
#onCancel;
|
|
20
|
+
#titleText;
|
|
21
|
+
#baseTitle;
|
|
22
|
+
#countdown;
|
|
23
|
+
#onToggleToolsExpanded;
|
|
24
|
+
constructor(title, options, onSelect, onCancel, opts) {
|
|
25
|
+
super();
|
|
26
|
+
this.#options = options;
|
|
27
|
+
this.#onSelect = onSelect;
|
|
28
|
+
this.#onCancel = onCancel;
|
|
29
|
+
this.#baseTitle = title;
|
|
30
|
+
this.#onToggleToolsExpanded = opts?.onToggleToolsExpanded;
|
|
31
|
+
const theme = piTheme();
|
|
32
|
+
this.addChild(new DynamicBorder());
|
|
33
|
+
this.addChild(new Spacer(1));
|
|
34
|
+
this.#titleText = new Text(theme.fg("accent", theme.bold(title)), 1, 0);
|
|
35
|
+
this.addChild(this.#titleText);
|
|
36
|
+
if (opts?.description) {
|
|
37
|
+
this.addChild(new Spacer(1));
|
|
38
|
+
this.addChild(new Text(theme.fg("text", opts.description), 1, 0));
|
|
39
|
+
}
|
|
40
|
+
this.addChild(new Spacer(1));
|
|
41
|
+
this.#countdown = opts?.timeout !== undefined && opts.timeout > 0 && opts.tui !== undefined
|
|
42
|
+
? new CountdownTimer(opts.timeout, opts.tui, seconds => {
|
|
43
|
+
const current = piTheme();
|
|
44
|
+
this.#titleText.setText(current.fg("accent", current.bold(`${this.#baseTitle} (${seconds}s)`)));
|
|
45
|
+
}, () => this.#onCancel())
|
|
46
|
+
: undefined;
|
|
47
|
+
this.addChild(this.#listContainer);
|
|
48
|
+
this.addChild(new Spacer(1));
|
|
49
|
+
const keys = getKeybindings();
|
|
50
|
+
this.addChild(new Text(renderPiModalShortcutHints([
|
|
51
|
+
{ key: "↑↓", action: "navigate" },
|
|
52
|
+
{ key: keys.getKeys("tui.select.confirm").join("/"), action: "select" },
|
|
53
|
+
{ key: keys.getKeys("tui.select.cancel").join("/"), action: "cancel" },
|
|
54
|
+
]), 1, 0));
|
|
55
|
+
this.addChild(new Spacer(1));
|
|
56
|
+
this.addChild(new DynamicBorder());
|
|
57
|
+
this.#updateList();
|
|
58
|
+
}
|
|
59
|
+
#updateList() {
|
|
60
|
+
this.#listContainer.clear();
|
|
61
|
+
const theme = piTheme();
|
|
62
|
+
for (let index = 0; index < this.#options.length; index += 1) {
|
|
63
|
+
const option = this.#options[index];
|
|
64
|
+
this.#listContainer.addChild(new Text(index === this.#selectedIndex
|
|
65
|
+
? theme.fg("accent", "→ ") + theme.fg("accent", option)
|
|
66
|
+
: ` ${theme.fg("text", option)}`, 1, 0));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
handleInput(keyData) {
|
|
70
|
+
const keys = getKeybindings();
|
|
71
|
+
if (keys.matches(keyData, "app.tools.expand"))
|
|
72
|
+
this.#onToggleToolsExpanded?.();
|
|
73
|
+
else if (keys.matches(keyData, "tui.select.up") || keyData === "k") {
|
|
74
|
+
this.#selectedIndex = Math.max(0, this.#selectedIndex - 1);
|
|
75
|
+
this.#updateList();
|
|
76
|
+
}
|
|
77
|
+
else if (keys.matches(keyData, "tui.select.down") || keyData === "j") {
|
|
78
|
+
this.#selectedIndex = Math.min(this.#options.length - 1, this.#selectedIndex + 1);
|
|
79
|
+
this.#updateList();
|
|
80
|
+
}
|
|
81
|
+
else if (keys.matches(keyData, "tui.select.confirm") || keyData === "\n") {
|
|
82
|
+
const selected = this.#options[this.#selectedIndex];
|
|
83
|
+
if (selected !== undefined)
|
|
84
|
+
this.#onSelect(selected);
|
|
85
|
+
}
|
|
86
|
+
else if (keys.matches(keyData, "tui.select.cancel"))
|
|
87
|
+
this.#onCancel();
|
|
88
|
+
}
|
|
89
|
+
dispose() {
|
|
90
|
+
this.#countdown?.dispose();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
* Modifications: Source-synchronized scoped-model selector port: preserve session-only toggles,
|
|
5
5
|
* search, bulk/provider/reorder actions, dirty state, Ctrl+S persistence, refresh status,
|
|
6
6
|
* cancellation, and focus while remapping theme and public helper imports; local key labels preserve
|
|
7
|
-
* pinned platform formatting before layout without changing binding identities
|
|
8
|
-
*
|
|
7
|
+
* pinned platform formatting before layout without changing binding identities, and bare A1 uses the
|
|
8
|
+
* shared semantic modal shortcut row.
|
|
9
|
+
* Deviations: owned-modal-shortcut-hints.
|
|
9
10
|
*/
|
|
10
11
|
interface ScopedModel {
|
|
11
12
|
readonly provider: string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Container, fuzzyFilter, getKeybindings, Input, Key, matchesKey, Spacer, Text, } from "@earendil-works/pi-tui";
|
|
2
2
|
import { DynamicBorder } from "../../../startup-public.js";
|
|
3
3
|
import { getModelSearchText } from "../model-search.js";
|
|
4
|
-
import { piTheme } from "
|
|
4
|
+
import { piTheme, renderPiModalShortcutHints } from "../../theme.js";
|
|
5
5
|
// Rationale: upstream's capitalized hint formatter is private to the package; the same mapping lives here.
|
|
6
6
|
function keyDisplayText(keybinding) {
|
|
7
7
|
return getKeybindings().getKeys(keybinding)
|
|
@@ -113,7 +113,9 @@ export class ScopedModelsSelectorComponent extends Container {
|
|
|
113
113
|
this.addChild(new DynamicBorder());
|
|
114
114
|
this.addChild(new Spacer(1));
|
|
115
115
|
this.addChild(new Text(theme.fg("accent", theme.bold("Model Configuration")), 0, 0));
|
|
116
|
-
|
|
116
|
+
const saveKey = keyDisplayText("app.models.save");
|
|
117
|
+
this.addChild(new Text(theme.fg("muted", "Session-only.")
|
|
118
|
+
+ (saveKey ? ` ${renderPiModalShortcutHints([{ key: saveKey, action: "to save to settings." }])}` : ""), 0, 0));
|
|
117
119
|
this.addChild(new Spacer(1));
|
|
118
120
|
// Search input
|
|
119
121
|
this.searchInput = new Input();
|
|
@@ -167,19 +169,18 @@ export class ScopedModelsSelectorComponent extends Container {
|
|
|
167
169
|
const allEnabled = this.enabledIds === null;
|
|
168
170
|
const countText = allEnabled
|
|
169
171
|
? "all enabled"
|
|
170
|
-
: `${enabledCount}/${this.allIds.length} enabled${unavailableCount ?
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
: theme.fg("dim", ` ${parts.join(" · ")}`);
|
|
172
|
+
: `${enabledCount}/${this.allIds.length} enabled${unavailableCount ? `, ${unavailableCount} unavailable` : ""}`;
|
|
173
|
+
const reorderKeys = [keyDisplayText("app.models.reorderUp"), keyDisplayText("app.models.reorderDown")].filter(Boolean).join("/");
|
|
174
|
+
const hint = renderPiModalShortcutHints([
|
|
175
|
+
{ key: keyDisplayText("tui.select.confirm"), action: "toggle" },
|
|
176
|
+
{ key: keyDisplayText("app.models.enableAll"), action: "all" },
|
|
177
|
+
{ key: keyDisplayText("app.models.clearAll"), action: "clear" },
|
|
178
|
+
{ key: keyDisplayText("app.models.toggleProvider"), action: "provider" },
|
|
179
|
+
{ key: reorderKeys, action: "reorder" },
|
|
180
|
+
{ key: keyDisplayText("app.models.save"), action: "save" },
|
|
181
|
+
{ action: countText },
|
|
182
|
+
]);
|
|
183
|
+
return this.isDirty ? `${hint} ${theme.fg("warning", "(unsaved)")}` : hint;
|
|
183
184
|
}
|
|
184
185
|
refresh() {
|
|
185
186
|
const query = this.searchInput.getValue();
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* Provenance: @earendil-works/pi-coding-agent 0.87.0 (MIT), commit 16787ad5b2dc748047f314ca1bfe7708f30f54f3,
|
|
3
3
|
* packages/coding-agent/src/modes/interactive/components/footer.ts.
|
|
4
4
|
* Modifications: Consumes neutral owned-UI view data instead of a fabricated concrete AgentSession; an
|
|
5
|
-
* explicit bare-A1 profile colors the thinking-level name
|
|
6
|
-
*
|
|
7
|
-
* thinking level they already present.
|
|
5
|
+
* explicit bare-A1 profile colors the thinking-level name, renders its repository-context path, and
|
|
6
|
+
* reserves its linked pull-request badge before path truncation while preserving the remaining footer
|
|
7
|
+
* layout and formatting; replacement surfaces may suppress a thinking level they already present.
|
|
8
8
|
* Deviations: owned-status-level-color, owned-pull-request-badge.
|
|
9
9
|
*/
|
|
10
10
|
import { isAbsolute, relative, resolve, sep } from "node:path";
|
|
@@ -36,17 +36,33 @@ export class SessionFooter {
|
|
|
36
36
|
const contextPercentValue = usage?.contextPercent ?? 0;
|
|
37
37
|
const contextPercentSource = usage?.contextAvailable === false ? undefined : usage?.contextPercent;
|
|
38
38
|
const contextPercent = contextPercentSource !== null ? contextPercentValue.toFixed(1) : "?";
|
|
39
|
-
|
|
39
|
+
const repositoryPath = this.profile === "a1" ? view.status.footer?.repositoryPath ?? this.cwd : this.cwd;
|
|
40
|
+
let pwd = formatCwd(repositoryPath, process.env.HOME || process.env.USERPROFILE);
|
|
40
41
|
const branch = view.status.footer?.branch;
|
|
41
42
|
if (branch)
|
|
42
43
|
pwd = `${pwd} (${branch})`;
|
|
43
44
|
const sessionName = view.status.footer?.sessionName;
|
|
44
45
|
const pullRequest = this.profile === "a1" ? view.status.footer?.pullRequest : null;
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
let pathRow;
|
|
47
|
+
if (pullRequest === undefined || pullRequest === null) {
|
|
48
|
+
pathRow = theme.fg("dim", sessionName ? `${pwd} • ${sessionName}` : pwd);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
const badge = theme.fg("dim", " ")
|
|
52
|
+
+ hyperlink(theme.fg("mdLink", `#${pullRequest.number}`), pullRequest.url);
|
|
53
|
+
const sessionSuffix = sessionName ? theme.fg("dim", ` • ${sessionName}`) : "";
|
|
54
|
+
const full = theme.fg("dim", pwd) + badge + sessionSuffix;
|
|
55
|
+
if (visibleWidth(full) <= width)
|
|
56
|
+
pathRow = full;
|
|
57
|
+
else if (visibleWidth(badge) <= width) {
|
|
58
|
+
const pathWidth = Math.max(0, width - visibleWidth(badge));
|
|
59
|
+
const path = pathWidth === 0 ? "" : truncateToWidth(theme.fg("dim", pwd), pathWidth, theme.fg("dim", "..."));
|
|
60
|
+
pathRow = path + badge;
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
pathRow = truncateToWidth(badge, width, theme.fg("dim", "..."));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
50
66
|
const parts = [];
|
|
51
67
|
if (input)
|
|
52
68
|
parts.push(`↑${formatTokens(input)}`);
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* Modifications: Source-synchronized session selector port: preserve threaded/current/all scope,
|
|
5
5
|
* search, sort, named/path filters, rename, delete confirmation, active-session protection, loading
|
|
6
6
|
* progress, cancellation, focus, and disposal while remapping public helpers, owned keybindings/theme,
|
|
7
|
-
*
|
|
8
|
-
* Deviations:
|
|
7
|
+
* canonical path handling, and the shared bare-A1 modal shortcut row.
|
|
8
|
+
* Deviations: owned-modal-shortcut-hints.
|
|
9
9
|
*/
|
|
10
10
|
import { spawnSync } from "node:child_process";
|
|
11
11
|
import { existsSync, realpathSync } from "node:fs";
|
|
@@ -14,7 +14,7 @@ import * as os from "node:os";
|
|
|
14
14
|
import { Container, getKeybindings, Input, Spacer, Text, truncateToWidth, visibleWidth, } from "@earendil-works/pi-tui";
|
|
15
15
|
import { KeybindingsManager } from "../adjacent/core/keybindings.js";
|
|
16
16
|
import { DynamicBorder } from "../../../startup-public.js";
|
|
17
|
-
import { piTheme } from "
|
|
17
|
+
import { piTheme, renderPiModalShortcutHints } from "../../theme.js";
|
|
18
18
|
const theme = new Proxy({}, {
|
|
19
19
|
get(_target, property) {
|
|
20
20
|
const active = piTheme();
|
|
@@ -25,8 +25,8 @@ const theme = new Proxy({}, {
|
|
|
25
25
|
function keyText(keybinding, keybindings) {
|
|
26
26
|
return keybindings.getKeys(keybinding).join("/");
|
|
27
27
|
}
|
|
28
|
-
function
|
|
29
|
-
return
|
|
28
|
+
function shortcutHint(keybinding, action, keybindings) {
|
|
29
|
+
return { key: keyText(keybinding, keybindings), action };
|
|
30
30
|
}
|
|
31
31
|
import { filterAndSortSessions, hasSessionName } from "./session-selector-search.js";
|
|
32
32
|
function shortenPath(path) {
|
|
@@ -158,8 +158,11 @@ class SessionSelectorHeader {
|
|
|
158
158
|
let hintLine1;
|
|
159
159
|
let hintLine2;
|
|
160
160
|
if (this.confirmingDeletePath !== null) {
|
|
161
|
-
const confirmHint =
|
|
162
|
-
|
|
161
|
+
const confirmHint = theme.fg("error", "Delete session? ") + renderPiModalShortcutHints([
|
|
162
|
+
shortcutHint("tui.select.confirm", "confirm", this.keybindings),
|
|
163
|
+
shortcutHint("tui.select.cancel", "cancel", this.keybindings),
|
|
164
|
+
]);
|
|
165
|
+
hintLine1 = truncateToWidth(confirmHint, width, "…");
|
|
163
166
|
hintLine2 = "";
|
|
164
167
|
}
|
|
165
168
|
else if (this.statusMessage) {
|
|
@@ -169,18 +172,21 @@ class SessionSelectorHeader {
|
|
|
169
172
|
}
|
|
170
173
|
else {
|
|
171
174
|
const pathState = this.showPath ? "(on)" : "(off)";
|
|
172
|
-
const
|
|
173
|
-
|
|
175
|
+
const hint1 = renderPiModalShortcutHints([
|
|
176
|
+
shortcutHint("tui.input.tab", "scope", this.keybindings),
|
|
177
|
+
{ action: "re:<pattern> regex" },
|
|
178
|
+
{ action: '"phrase" exact' },
|
|
179
|
+
]);
|
|
174
180
|
const hint2Parts = [
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
181
|
+
shortcutHint("app.session.toggleSort", "sort", this.keybindings),
|
|
182
|
+
shortcutHint("app.session.toggleNamedFilter", "named", this.keybindings),
|
|
183
|
+
shortcutHint("app.session.delete", "delete", this.keybindings),
|
|
184
|
+
shortcutHint("app.session.togglePath", `path ${pathState}`, this.keybindings),
|
|
179
185
|
];
|
|
180
186
|
if (this.showRenameHint) {
|
|
181
|
-
hint2Parts.push(
|
|
187
|
+
hint2Parts.push(shortcutHint("app.session.rename", "rename", this.keybindings));
|
|
182
188
|
}
|
|
183
|
-
const hint2 = hint2Parts
|
|
189
|
+
const hint2 = renderPiModalShortcutHints(hint2Parts);
|
|
184
190
|
hintLine1 = truncateToWidth(hint1, width, "…");
|
|
185
191
|
hintLine2 = truncateToWidth(hint2, width, "…");
|
|
186
192
|
}
|
|
@@ -776,7 +782,10 @@ export class SessionSelectorComponent extends Container {
|
|
|
776
782
|
panel.addChild(new Spacer(1));
|
|
777
783
|
panel.addChild(this.renameInput);
|
|
778
784
|
panel.addChild(new Spacer(1));
|
|
779
|
-
panel.addChild(new Text(
|
|
785
|
+
panel.addChild(new Text(renderPiModalShortcutHints([
|
|
786
|
+
shortcutHint("tui.select.confirm", "to save", this.keybindings),
|
|
787
|
+
shortcutHint("tui.select.cancel", "to cancel", this.keybindings),
|
|
788
|
+
]), 1, 0));
|
|
780
789
|
this.buildBaseLayout(panel, { showHeader: false });
|
|
781
790
|
this.requestRender();
|
|
782
791
|
}
|
|
@@ -4,10 +4,11 @@
|
|
|
4
4
|
* Modifications: Preserve the searchable thinking-level selector, current/default semantics,
|
|
5
5
|
* selection, save, cancellation, and focus while accepting the active bare-A1 cycle-key label from the
|
|
6
6
|
* shell, styling the title with the established bold semantic accent treatment, placing its muted hint
|
|
7
|
-
* directly below it, deduplicating levels, and rendering aligned muted descriptions after
|
|
8
|
-
*
|
|
9
|
-
* mode
|
|
10
|
-
*
|
|
7
|
+
* directly below it, deduplicating levels, and rendering aligned muted descriptions after adjacent
|
|
8
|
+
* active and bracketed default markers. All list and border colors use the owned theme and its
|
|
9
|
+
* explicit color mode, and the footer uses the shared bare-A1 modal shortcut row. The comparison
|
|
10
|
+
* profile retains the public pinned component.
|
|
11
|
+
* Deviations: owned-modal-shortcut-hints, owned-level-cycle-shortcut, owned-thinking-selector-heading.
|
|
11
12
|
*/
|
|
12
13
|
import { Container, type Focusable, SelectList } from "@earendil-works/pi-tui";
|
|
13
14
|
export type ThinkingSelectorLevel = "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max";
|
|
@@ -21,6 +22,7 @@ export declare class OwnedThinkingSelectorComponent extends Container implements
|
|
|
21
22
|
private onCancel;
|
|
22
23
|
private onSelectAsDefault;
|
|
23
24
|
private currentLevel;
|
|
25
|
+
private defaultThinkingLevel;
|
|
24
26
|
private _focused;
|
|
25
27
|
get focused(): boolean;
|
|
26
28
|
set focused(value: boolean);
|
|
@@ -4,14 +4,15 @@
|
|
|
4
4
|
* Modifications: Preserve the searchable thinking-level selector, current/default semantics,
|
|
5
5
|
* selection, save, cancellation, and focus while accepting the active bare-A1 cycle-key label from the
|
|
6
6
|
* shell, styling the title with the established bold semantic accent treatment, placing its muted hint
|
|
7
|
-
* directly below it, deduplicating levels, and rendering aligned muted descriptions after
|
|
8
|
-
*
|
|
9
|
-
* mode
|
|
10
|
-
*
|
|
7
|
+
* directly below it, deduplicating levels, and rendering aligned muted descriptions after adjacent
|
|
8
|
+
* active and bracketed default markers. All list and border colors use the owned theme and its
|
|
9
|
+
* explicit color mode, and the footer uses the shared bare-A1 modal shortcut row. The comparison
|
|
10
|
+
* profile retains the public pinned component.
|
|
11
|
+
* Deviations: owned-modal-shortcut-hints, owned-level-cycle-shortcut, owned-thinking-selector-heading.
|
|
11
12
|
*/
|
|
12
13
|
import { Container, fuzzyFilter, getKeybindings, Input, SelectList, Spacer, Text, } from "@earendil-works/pi-tui";
|
|
13
14
|
import { DynamicBorder } from "../../../startup-public.js";
|
|
14
|
-
import { piTheme } from "
|
|
15
|
+
import { piTheme, renderPiModalShortcutHints } from "../../theme.js";
|
|
15
16
|
const THINKING_SELECT_LIST_LAYOUT = {
|
|
16
17
|
minPrimaryColumnWidth: 12,
|
|
17
18
|
maxPrimaryColumnWidth: 32,
|
|
@@ -35,6 +36,7 @@ export class OwnedThinkingSelectorComponent extends Container {
|
|
|
35
36
|
onCancel;
|
|
36
37
|
onSelectAsDefault;
|
|
37
38
|
currentLevel;
|
|
39
|
+
defaultThinkingLevel;
|
|
38
40
|
_focused = false;
|
|
39
41
|
get focused() {
|
|
40
42
|
return this._focused;
|
|
@@ -49,10 +51,11 @@ export class OwnedThinkingSelectorComponent extends Container {
|
|
|
49
51
|
this.onCancel = onCancel;
|
|
50
52
|
this.onSelectAsDefault = onSelectAsDefault;
|
|
51
53
|
this.currentLevel = currentLevel;
|
|
54
|
+
this.defaultThinkingLevel = defaultThinkingLevel;
|
|
52
55
|
this.allItems = [...new Set(availableLevels)].map((level) => ({
|
|
53
56
|
value: level,
|
|
54
57
|
label: level,
|
|
55
|
-
description:
|
|
58
|
+
description: LEVEL_DESCRIPTIONS[level],
|
|
56
59
|
}));
|
|
57
60
|
this.addChild(new DynamicBorder((text) => piTheme().fg("border", text)));
|
|
58
61
|
this.addChild(new Spacer(1));
|
|
@@ -67,7 +70,11 @@ export class OwnedThinkingSelectorComponent extends Container {
|
|
|
67
70
|
this.selectListChildIndex = this.children.length;
|
|
68
71
|
this.addChild(this.selectList);
|
|
69
72
|
this.addChild(new Spacer(1));
|
|
70
|
-
this.addChild(new Text(
|
|
73
|
+
this.addChild(new Text(renderPiModalShortcutHints([
|
|
74
|
+
{ key: this.keyDisplayText("tui.select.confirm"), action: "to select" },
|
|
75
|
+
{ key: this.keyDisplayText("app.thinking.save"), action: "to set as default" },
|
|
76
|
+
{ key: this.keyDisplayText("tui.select.cancel"), action: "to cancel" },
|
|
77
|
+
]), 0, 0));
|
|
71
78
|
this.addChild(new DynamicBorder((text) => piTheme().fg("border", text)));
|
|
72
79
|
}
|
|
73
80
|
keyDisplayText(keybinding) {
|
|
@@ -79,17 +86,20 @@ export class OwnedThinkingSelectorComponent extends Container {
|
|
|
79
86
|
.join("/");
|
|
80
87
|
}
|
|
81
88
|
buildSelectList(items, preselect) {
|
|
89
|
+
const markerWidth = (item) => (item.value === this.currentLevel ? 2 : 0) + (item.value === this.defaultThinkingLevel ? 10 : 0);
|
|
82
90
|
const primaryWidth = this.allItems.reduce((widest, item) => {
|
|
83
91
|
const level = item.label ?? item.value;
|
|
84
|
-
return Math.max(widest, level.length + (item
|
|
92
|
+
return Math.max(widest, level.length + markerWidth(item));
|
|
85
93
|
}, 0);
|
|
86
94
|
const themedItems = items.map((item) => {
|
|
87
95
|
const level = item.label ?? item.value;
|
|
88
|
-
const
|
|
89
|
-
const
|
|
90
|
-
|
|
96
|
+
const currentMarker = item.value === this.currentLevel ? ` ${piTheme().fg("success", "✓")}` : "";
|
|
97
|
+
const defaultMarker = item.value === this.defaultThinkingLevel
|
|
98
|
+
? ` ${piTheme().fg("muted", "[default]")}`
|
|
99
|
+
: "";
|
|
100
|
+
const separator = " ".repeat(Math.max(1, primaryWidth - level.length - markerWidth(item) + 1));
|
|
91
101
|
const description = item.description ? piTheme().fg("muted", item.description) : "";
|
|
92
|
-
return { value: item.value, label: `${level}${currentMarker}${separator}${description}` };
|
|
102
|
+
return { value: item.value, label: `${level}${currentMarker}${defaultMarker}${separator}${description}` };
|
|
93
103
|
});
|
|
94
104
|
// Invariant: the bare selector uses the owned theme's explicit color mode, not upstream's host detection.
|
|
95
105
|
const list = new SelectList(themedItems, Math.max(1, themedItems.length), {
|
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
* packages/coding-agent/src/modes/interactive/components/tree-selector.ts.
|
|
4
4
|
* Modifications: Source-synchronized tree selector port: preserve filtering, folding, labels, copying,
|
|
5
5
|
* tree navigation, key hints, focus, and viewport behavior while remapping public types/components
|
|
6
|
-
* plus owned keybindings/theme helpers required to avoid the pinned package nested pi-tui singleton
|
|
7
|
-
*
|
|
6
|
+
* plus owned keybindings/theme helpers required to avoid the pinned package nested pi-tui singleton;
|
|
7
|
+
* bare A1 uses the shared semantic modal shortcut row.
|
|
8
|
+
* Deviations: owned-modal-shortcut-hints.
|
|
8
9
|
*/
|
|
9
10
|
import { type Component, Container, type Focusable } from "@earendil-works/pi-tui";
|
|
10
11
|
import { type SessionTreeNode } from "@earendil-works/pi-coding-agent";
|