@astralyn/pi 0.85.1 → 0.85.2
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/CHANGELOG.md +28 -0
- package/dist/cli.js +94 -91
- package/dist/core/agent-session.js +2 -2
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/background/history.d.ts.map +1 -1
- package/dist/core/background/history.js +6 -0
- package/dist/core/background/history.js.map +1 -1
- package/dist/core/background/presentation.d.ts.map +1 -1
- package/dist/core/background/presentation.js +41 -4
- package/dist/core/background/presentation.js.map +1 -1
- package/dist/core/background/service.d.ts +2 -2
- package/dist/core/background/service.d.ts.map +1 -1
- package/dist/core/background/service.js +38 -15
- package/dist/core/background/service.js.map +1 -1
- package/dist/core/background/types.d.ts +9 -0
- package/dist/core/background/types.d.ts.map +1 -1
- package/dist/core/background/types.js +4 -0
- package/dist/core/background/types.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +5 -12
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +11 -19
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/compaction/settings.d.ts +27 -0
- package/dist/core/compaction/settings.d.ts.map +1 -0
- package/dist/core/compaction/settings.js +40 -0
- package/dist/core/compaction/settings.js.map +1 -0
- package/dist/core/keybindings.d.ts +15 -0
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +12 -0
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/model-config.d.ts +32 -10
- package/dist/core/model-config.d.ts.map +1 -1
- package/dist/core/model-config.js +38 -1
- package/dist/core/model-config.js.map +1 -1
- package/dist/core/model-runtime.d.ts +2 -0
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +4 -0
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/settings-manager.d.ts +4 -7
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +7 -6
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/tools/bash.js +1 -1
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/shell-execution.d.ts.map +1 -1
- package/dist/core/tools/shell-execution.js +3 -1
- package/dist/core/tools/shell-execution.js.map +1 -1
- package/dist/extensions/background/manager.d.ts +8 -5
- package/dist/extensions/background/manager.d.ts.map +1 -1
- package/dist/extensions/background/manager.js +115 -39
- package/dist/extensions/background/manager.js.map +1 -1
- package/dist/extensions/background/task-view.d.ts +5 -0
- package/dist/extensions/background/task-view.d.ts.map +1 -1
- package/dist/extensions/background/task-view.js +4 -0
- package/dist/extensions/background/task-view.js.map +1 -1
- package/dist/extensions/btw/controller.d.ts +1 -1
- package/dist/extensions/btw/controller.d.ts.map +1 -1
- package/dist/extensions/btw/controller.js +4 -4
- package/dist/extensions/btw/controller.js.map +1 -1
- package/dist/extensions/btw/index.js +3 -3
- package/dist/extensions/btw/index.js.map +1 -1
- package/dist/extensions/index.js +2 -2
- package/dist/extensions/index.js.map +1 -1
- package/dist/extensions/provider/catalog.d.ts +57 -0
- package/dist/extensions/provider/catalog.d.ts.map +1 -0
- package/dist/extensions/provider/catalog.js +181 -0
- package/dist/extensions/provider/catalog.js.map +1 -0
- package/dist/extensions/provider/compat-fields.d.ts +25 -0
- package/dist/extensions/provider/compat-fields.d.ts.map +1 -0
- package/dist/extensions/provider/compat-fields.js +148 -0
- package/dist/extensions/provider/compat-fields.js.map +1 -0
- package/dist/extensions/provider/configuration.d.ts +8 -0
- package/dist/extensions/provider/configuration.d.ts.map +1 -0
- package/dist/extensions/provider/configuration.js +21 -0
- package/dist/extensions/provider/configuration.js.map +1 -0
- package/dist/extensions/provider/connection.d.ts +14 -0
- package/dist/extensions/provider/connection.d.ts.map +1 -0
- package/dist/extensions/provider/connection.js +86 -0
- package/dist/extensions/provider/connection.js.map +1 -0
- package/dist/extensions/provider/constants.d.ts +38 -0
- package/dist/extensions/provider/constants.d.ts.map +1 -0
- package/dist/extensions/provider/constants.js +75 -0
- package/dist/extensions/provider/constants.js.map +1 -0
- package/dist/extensions/provider/index.d.ts +4 -0
- package/dist/extensions/provider/index.d.ts.map +1 -0
- package/dist/extensions/provider/index.js +65 -0
- package/dist/extensions/provider/index.js.map +1 -0
- package/dist/extensions/provider/probe.d.ts +34 -0
- package/dist/extensions/provider/probe.d.ts.map +1 -0
- package/dist/extensions/provider/probe.js +178 -0
- package/dist/extensions/provider/probe.js.map +1 -0
- package/dist/extensions/provider/refresh.d.ts +30 -0
- package/dist/extensions/provider/refresh.d.ts.map +1 -0
- package/dist/extensions/provider/refresh.js +66 -0
- package/dist/extensions/provider/refresh.js.map +1 -0
- package/dist/extensions/provider/store.d.ts +131 -0
- package/dist/extensions/provider/store.d.ts.map +1 -0
- package/dist/extensions/provider/store.js +503 -0
- package/dist/extensions/provider/store.js.map +1 -0
- package/dist/extensions/provider/ui/app.d.ts +25 -0
- package/dist/extensions/provider/ui/app.d.ts.map +1 -0
- package/dist/extensions/provider/ui/app.js +153 -0
- package/dist/extensions/provider/ui/app.js.map +1 -0
- package/dist/extensions/provider/ui/builtin-data.d.ts +53 -0
- package/dist/extensions/provider/ui/builtin-data.d.ts.map +1 -0
- package/dist/extensions/provider/ui/builtin-data.js +315 -0
- package/dist/extensions/provider/ui/builtin-data.js.map +1 -0
- package/dist/extensions/provider/ui/compat.d.ts +57 -0
- package/dist/extensions/provider/ui/compat.d.ts.map +1 -0
- package/dist/extensions/provider/ui/compat.js +427 -0
- package/dist/extensions/provider/ui/compat.js.map +1 -0
- package/dist/extensions/provider/ui/dialogs.d.ts +30 -0
- package/dist/extensions/provider/ui/dialogs.d.ts.map +1 -0
- package/dist/extensions/provider/ui/dialogs.js +89 -0
- package/dist/extensions/provider/ui/dialogs.js.map +1 -0
- package/dist/extensions/provider/ui/dictionary.d.ts +29 -0
- package/dist/extensions/provider/ui/dictionary.d.ts.map +1 -0
- package/dist/extensions/provider/ui/dictionary.js +385 -0
- package/dist/extensions/provider/ui/dictionary.js.map +1 -0
- package/dist/extensions/provider/ui/editor.d.ts +91 -0
- package/dist/extensions/provider/ui/editor.d.ts.map +1 -0
- package/dist/extensions/provider/ui/editor.js +667 -0
- package/dist/extensions/provider/ui/editor.js.map +1 -0
- package/dist/extensions/provider/ui/fetch-models.d.ts +39 -0
- package/dist/extensions/provider/ui/fetch-models.d.ts.map +1 -0
- package/dist/extensions/provider/ui/fetch-models.js +320 -0
- package/dist/extensions/provider/ui/fetch-models.js.map +1 -0
- package/dist/extensions/provider/ui/model-fields.d.ts +43 -0
- package/dist/extensions/provider/ui/model-fields.d.ts.map +1 -0
- package/dist/extensions/provider/ui/model-fields.js +441 -0
- package/dist/extensions/provider/ui/model-fields.js.map +1 -0
- package/dist/extensions/provider/ui/model-options.d.ts +93 -0
- package/dist/extensions/provider/ui/model-options.d.ts.map +1 -0
- package/dist/extensions/provider/ui/model-options.js +529 -0
- package/dist/extensions/provider/ui/model-options.js.map +1 -0
- package/dist/extensions/provider/ui/pane.d.ts +81 -0
- package/dist/extensions/provider/ui/pane.d.ts.map +1 -0
- package/dist/extensions/provider/ui/pane.js +3 -0
- package/dist/extensions/provider/ui/pane.js.map +1 -0
- package/dist/extensions/provider/ui/provider-fields.d.ts +60 -0
- package/dist/extensions/provider/ui/provider-fields.d.ts.map +1 -0
- package/dist/extensions/provider/ui/provider-fields.js +326 -0
- package/dist/extensions/provider/ui/provider-fields.js.map +1 -0
- package/dist/extensions/provider/ui/provider-list.d.ts +34 -0
- package/dist/extensions/provider/ui/provider-list.d.ts.map +1 -0
- package/dist/extensions/provider/ui/provider-list.js +162 -0
- package/dist/extensions/provider/ui/provider-list.js.map +1 -0
- package/dist/extensions/provider/ui/session.d.ts +20 -0
- package/dist/extensions/provider/ui/session.d.ts.map +1 -0
- package/dist/extensions/provider/ui/session.js +52 -0
- package/dist/extensions/provider/ui/session.js.map +1 -0
- package/dist/extensions/provider/ui/thinking-map.d.ts +20 -0
- package/dist/extensions/provider/ui/thinking-map.d.ts.map +1 -0
- package/dist/extensions/provider/ui/thinking-map.js +166 -0
- package/dist/extensions/provider/ui/thinking-map.js.map +1 -0
- package/dist/extensions/provider/ui/value-row.d.ts +88 -0
- package/dist/extensions/provider/ui/value-row.d.ts.map +1 -0
- package/dist/extensions/provider/ui/value-row.js +158 -0
- package/dist/extensions/provider/ui/value-row.js.map +1 -0
- package/dist/extensions/statusline/index.js +2 -2
- package/dist/extensions/statusline/index.js.map +1 -1
- package/dist/extensions/subagent/index.d.ts.map +1 -1
- package/dist/extensions/subagent/index.js +4 -2
- package/dist/extensions/subagent/index.js.map +1 -1
- package/dist/extensions/subagent/resolve.d.ts +5 -0
- package/dist/extensions/subagent/resolve.d.ts.map +1 -1
- package/dist/extensions/subagent/resolve.js +15 -7
- package/dist/extensions/subagent/resolve.js.map +1 -1
- package/dist/extensions/subagent/schema.d.ts +2 -0
- package/dist/extensions/subagent/schema.d.ts.map +1 -1
- package/dist/extensions/subagent/schema.js +1 -0
- package/dist/extensions/subagent/schema.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +10 -0
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +20 -2
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +6 -1
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/rpc-entry.js +94 -91
- package/docs/bundled/README.md +1 -1
- package/docs/bundled/extensions/background.md +5 -5
- package/docs/bundled/extensions/provider.md +117 -0
- package/docs/bundled/extensions/statusline.md +1 -1
- package/docs/bundled/extensions/subagent.md +7 -3
- package/docs/compaction.md +16 -6
- package/docs/docs.json +2 -2
- package/docs/keybindings.md +3 -0
- package/docs/settings.md +11 -7
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/dist/extensions/router/constants.d.ts +0 -23
- package/dist/extensions/router/constants.d.ts.map +0 -1
- package/dist/extensions/router/constants.js +0 -30
- package/dist/extensions/router/constants.js.map +0 -1
- package/dist/extensions/router/dialog-host.d.ts +0 -60
- package/dist/extensions/router/dialog-host.d.ts.map +0 -1
- package/dist/extensions/router/dialog-host.js +0 -196
- package/dist/extensions/router/dialog-host.js.map +0 -1
- package/dist/extensions/router/dialog.d.ts +0 -45
- package/dist/extensions/router/dialog.d.ts.map +0 -1
- package/dist/extensions/router/dialog.js +0 -378
- package/dist/extensions/router/dialog.js.map +0 -1
- package/dist/extensions/router/identity.d.ts +0 -15
- package/dist/extensions/router/identity.d.ts.map +0 -1
- package/dist/extensions/router/identity.js +0 -173
- package/dist/extensions/router/identity.js.map +0 -1
- package/dist/extensions/router/index.d.ts +0 -15
- package/dist/extensions/router/index.d.ts.map +0 -1
- package/dist/extensions/router/index.js +0 -70
- package/dist/extensions/router/index.js.map +0 -1
- package/dist/extensions/router/presets.d.ts +0 -51
- package/dist/extensions/router/presets.d.ts.map +0 -1
- package/dist/extensions/router/presets.js +0 -108
- package/dist/extensions/router/presets.js.map +0 -1
- package/dist/extensions/router/probe.d.ts +0 -26
- package/dist/extensions/router/probe.d.ts.map +0 -1
- package/dist/extensions/router/probe.js +0 -216
- package/dist/extensions/router/probe.js.map +0 -1
- package/dist/extensions/router/register.d.ts +0 -12
- package/dist/extensions/router/register.d.ts.map +0 -1
- package/dist/extensions/router/register.js +0 -90
- package/dist/extensions/router/register.js.map +0 -1
- package/dist/extensions/router/state.d.ts +0 -20
- package/dist/extensions/router/state.d.ts.map +0 -1
- package/dist/extensions/router/state.js +0 -169
- package/dist/extensions/router/state.js.map +0 -1
- package/dist/extensions/router/store.d.ts +0 -12
- package/dist/extensions/router/store.d.ts.map +0 -1
- package/dist/extensions/router/store.js +0 -266
- package/dist/extensions/router/store.js.map +0 -1
- package/dist/extensions/router/stream.d.ts +0 -12
- package/dist/extensions/router/stream.d.ts.map +0 -1
- package/dist/extensions/router/stream.js +0 -233
- package/dist/extensions/router/stream.js.map +0 -1
- package/dist/extensions/router/transport.d.ts +0 -9
- package/dist/extensions/router/transport.d.ts.map +0 -1
- package/dist/extensions/router/transport.js +0 -81
- package/dist/extensions/router/transport.js.map +0 -1
- package/dist/extensions/router/types.d.ts +0 -39
- package/dist/extensions/router/types.d.ts.map +0 -1
- package/dist/extensions/router/types.js +0 -2
- package/dist/extensions/router/types.js.map +0 -1
- package/dist/extensions/router/ui.d.ts +0 -26
- package/dist/extensions/router/ui.d.ts.map +0 -1
- package/dist/extensions/router/ui.js +0 -897
- package/dist/extensions/router/ui.js.map +0 -1
- package/docs/bundled/extensions/router.md +0 -197
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/** Provider navigation and save/refresh finalization in one modal lifetime. */
|
|
2
|
+
import { Container, Text } from "@earendil-works/pi-tui";
|
|
3
|
+
import { DynamicBorder } from "../../../modes/interactive/components/dynamic-border.js";
|
|
4
|
+
import { ExtensionSelectorComponent } from "../../../modes/interactive/components/extension-selector.js";
|
|
5
|
+
import { keyHint } from "../../../modes/interactive/components/keybinding-hints.js";
|
|
6
|
+
import { formatError, truncate } from "../constants.js";
|
|
7
|
+
import { RefreshCoordinator } from "../refresh.js";
|
|
8
|
+
import { ProviderEditorScreen } from "./editor.js";
|
|
9
|
+
import { ProviderListScreen } from "./provider-list.js";
|
|
10
|
+
import { ProviderTuiSession } from "./session.js";
|
|
11
|
+
class SavingScreen extends Container {
|
|
12
|
+
constructor(theme, keybindings, onCancel) {
|
|
13
|
+
super();
|
|
14
|
+
this.keybindings = keybindings;
|
|
15
|
+
this.onCancel = onCancel;
|
|
16
|
+
this.addChild(new DynamicBorder((text) => theme.fg("border", text)));
|
|
17
|
+
this.addChild(new Text(theme.fg("muted", "Saving provider changes and updating models…"), 1, 1));
|
|
18
|
+
this.addChild(new Text(keyHint("tui.select.cancel", "return to providers"), 1, 0));
|
|
19
|
+
this.addChild(new DynamicBorder((text) => theme.fg("border", text)));
|
|
20
|
+
}
|
|
21
|
+
handleInput(data) {
|
|
22
|
+
if (this.keybindings.matches(data, "tui.select.cancel"))
|
|
23
|
+
this.onCancel();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export function createProviderErrorScreen(tui, done, error) {
|
|
27
|
+
return new ExtensionSelectorComponent("models.json cannot be edited", ["Back"], done, done, {
|
|
28
|
+
tui,
|
|
29
|
+
subtitle: `${truncate(error, 2400)}\n\nFix the file manually and open /provider again.`,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
export function createProviderApp(tui, theme, keybindings, done, options) {
|
|
33
|
+
const { store, registry, runtime } = options;
|
|
34
|
+
const session = new ProviderTuiSession(tui);
|
|
35
|
+
const refresher = new RefreshCoordinator(runtime);
|
|
36
|
+
let activeEditor;
|
|
37
|
+
let closing;
|
|
38
|
+
function notify(message, type) {
|
|
39
|
+
if (!session.signal.aborted)
|
|
40
|
+
options.notify(message, type);
|
|
41
|
+
}
|
|
42
|
+
store.onSaveResult = (result) => {
|
|
43
|
+
if (session.signal.aborted)
|
|
44
|
+
return;
|
|
45
|
+
if (result.kind === "invalid" || result.kind === "error")
|
|
46
|
+
notify(result.error, "error");
|
|
47
|
+
activeEditor?.syncFromStore();
|
|
48
|
+
tui.requestRender();
|
|
49
|
+
};
|
|
50
|
+
function showList() {
|
|
51
|
+
if (session.signal.aborted)
|
|
52
|
+
return;
|
|
53
|
+
activeEditor = undefined;
|
|
54
|
+
session.setScreen(new ProviderListScreen(tui, theme, keybindings, (result) => {
|
|
55
|
+
if (result.kind === "close")
|
|
56
|
+
requestClose();
|
|
57
|
+
else
|
|
58
|
+
openProvider(result.providerId);
|
|
59
|
+
}, store));
|
|
60
|
+
}
|
|
61
|
+
function openProvider(providerId) {
|
|
62
|
+
if (!store.getProviderIds().includes(providerId)) {
|
|
63
|
+
notify(`No provider ${JSON.stringify(providerId)} in models.json.`, "warning");
|
|
64
|
+
showList();
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
activeEditor = new ProviderEditorScreen(tui, theme, keybindings, showList, {
|
|
68
|
+
store,
|
|
69
|
+
refresher,
|
|
70
|
+
providerId,
|
|
71
|
+
registry,
|
|
72
|
+
runtime,
|
|
73
|
+
currentModel: options.getCurrentModel(),
|
|
74
|
+
notify,
|
|
75
|
+
});
|
|
76
|
+
session.setScreen(activeEditor);
|
|
77
|
+
}
|
|
78
|
+
function showUnsaved(error) {
|
|
79
|
+
const back = "Return to providers";
|
|
80
|
+
const retry = "Retry saving";
|
|
81
|
+
const discard = "Discard unsaved changes and close";
|
|
82
|
+
session.setScreen(new ExtensionSelectorComponent("Some changes are not saved", [back, retry, discard], (choice) => {
|
|
83
|
+
if (choice === back) {
|
|
84
|
+
showList();
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (choice === retry)
|
|
88
|
+
store.retrySave();
|
|
89
|
+
if (choice === discard)
|
|
90
|
+
store.discardPending();
|
|
91
|
+
requestClose();
|
|
92
|
+
}, showList, { tui, subtitle: truncate(error, 2400) }));
|
|
93
|
+
}
|
|
94
|
+
function requestClose() {
|
|
95
|
+
if (closing || session.signal.aborted)
|
|
96
|
+
return;
|
|
97
|
+
const controller = new AbortController();
|
|
98
|
+
closing = controller;
|
|
99
|
+
const signal = AbortSignal.any([session.signal, controller.signal]);
|
|
100
|
+
activeEditor = undefined;
|
|
101
|
+
session.setScreen(new SavingScreen(theme, keybindings, () => {
|
|
102
|
+
controller.abort();
|
|
103
|
+
closing = undefined;
|
|
104
|
+
showList();
|
|
105
|
+
}));
|
|
106
|
+
void finishClose(controller, signal);
|
|
107
|
+
}
|
|
108
|
+
async function finishClose(controller, signal) {
|
|
109
|
+
try {
|
|
110
|
+
await store.flush();
|
|
111
|
+
if (signal.aborted)
|
|
112
|
+
return;
|
|
113
|
+
const unsaved = store.getPendingError();
|
|
114
|
+
if (unsaved) {
|
|
115
|
+
closing = undefined;
|
|
116
|
+
showUnsaved(unsaved);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
const outcome = await refresher.flush(signal);
|
|
120
|
+
if (signal.aborted)
|
|
121
|
+
return;
|
|
122
|
+
if (!outcome.ok)
|
|
123
|
+
notify(`Changes saved, but model refresh failed: ${outcome.errors.join("; ")}`, "warning");
|
|
124
|
+
const current = options.getCurrentModel();
|
|
125
|
+
if (current && refresher.touchedProviders.includes(current.provider)) {
|
|
126
|
+
const refreshed = registry.find(current.provider, current.id);
|
|
127
|
+
if (refreshed && !(await options.setModel(refreshed))) {
|
|
128
|
+
notify("Reselect the current model with /model to apply its updated configuration.", "warning");
|
|
129
|
+
}
|
|
130
|
+
if (!refreshed)
|
|
131
|
+
notify("The current model is no longer available; select another with /model.", "warning");
|
|
132
|
+
}
|
|
133
|
+
if (!signal.aborted)
|
|
134
|
+
done();
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
if (!signal.aborted) {
|
|
138
|
+
notify(formatError(error), "error");
|
|
139
|
+
showList();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
finally {
|
|
143
|
+
if (closing === controller)
|
|
144
|
+
closing = undefined;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if (options.initialProviderId)
|
|
148
|
+
openProvider(options.initialProviderId);
|
|
149
|
+
else
|
|
150
|
+
showList();
|
|
151
|
+
return session;
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=app.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../../../../src/extensions/provider/ui/app.ts"],"names":[],"mappings":"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","sourcesContent":["/** Provider navigation and save/refresh finalization in one modal lifetime. */\n\nimport type { Api, Model } from \"@earendil-works/pi-ai\";\nimport { Container, Text, type TUI } from \"@earendil-works/pi-tui\";\nimport type { KeybindingsManager } from \"../../../core/keybindings.ts\";\nimport type { ModelRegistry } from \"../../../core/model-registry.ts\";\nimport type { ModelRuntime } from \"../../../core/model-runtime.ts\";\nimport { DynamicBorder } from \"../../../modes/interactive/components/dynamic-border.ts\";\nimport { ExtensionSelectorComponent } from \"../../../modes/interactive/components/extension-selector.ts\";\nimport { keyHint } from \"../../../modes/interactive/components/keybinding-hints.ts\";\nimport type { Theme } from \"../../../modes/interactive/theme/theme.ts\";\nimport { formatError, truncate } from \"../constants.ts\";\nimport { RefreshCoordinator } from \"../refresh.ts\";\nimport type { ModelsJsonStore } from \"../store.ts\";\nimport { ProviderEditorScreen } from \"./editor.ts\";\nimport { ProviderListScreen } from \"./provider-list.ts\";\nimport { ProviderTuiSession } from \"./session.ts\";\n\nexport interface ProviderAppOptions {\n\tstore: ModelsJsonStore;\n\truntime: Pick<ModelRuntime, \"refresh\" | \"getError\" | \"getAuth\" | \"getProviderAuthStatus\">;\n\tregistry: Pick<ModelRegistry, \"find\" | \"getProviderAuthStatus\">;\n\tgetCurrentModel(): { provider: string; id: string } | undefined;\n\tsetModel(model: Model<Api>): Promise<boolean>;\n\tnotify(message: string, type: \"info\" | \"warning\" | \"error\"): void;\n\tinitialProviderId?: string;\n}\n\nclass SavingScreen extends Container {\n\tprivate readonly keybindings: KeybindingsManager;\n\tprivate readonly onCancel: () => void;\n\n\tconstructor(theme: Theme, keybindings: KeybindingsManager, onCancel: () => void) {\n\t\tsuper();\n\t\tthis.keybindings = keybindings;\n\t\tthis.onCancel = onCancel;\n\t\tthis.addChild(new DynamicBorder((text) => theme.fg(\"border\", text)));\n\t\tthis.addChild(new Text(theme.fg(\"muted\", \"Saving provider changes and updating models…\"), 1, 1));\n\t\tthis.addChild(new Text(keyHint(\"tui.select.cancel\", \"return to providers\"), 1, 0));\n\t\tthis.addChild(new DynamicBorder((text) => theme.fg(\"border\", text)));\n\t}\n\n\thandleInput(data: string): void {\n\t\tif (this.keybindings.matches(data, \"tui.select.cancel\")) this.onCancel();\n\t}\n}\n\nexport function createProviderErrorScreen(tui: TUI, done: () => void, error: string): ExtensionSelectorComponent {\n\treturn new ExtensionSelectorComponent(\"models.json cannot be edited\", [\"Back\"], done, done, {\n\t\ttui,\n\t\tsubtitle: `${truncate(error, 2400)}\\n\\nFix the file manually and open /provider again.`,\n\t});\n}\n\nexport function createProviderApp(\n\ttui: TUI,\n\ttheme: Theme,\n\tkeybindings: KeybindingsManager,\n\tdone: () => void,\n\toptions: ProviderAppOptions,\n): ProviderTuiSession {\n\tconst { store, registry, runtime } = options;\n\tconst session = new ProviderTuiSession(tui);\n\tconst refresher = new RefreshCoordinator(runtime);\n\tlet activeEditor: ProviderEditorScreen | undefined;\n\tlet closing: AbortController | undefined;\n\n\tfunction notify(message: string, type: \"info\" | \"warning\" | \"error\"): void {\n\t\tif (!session.signal.aborted) options.notify(message, type);\n\t}\n\n\tstore.onSaveResult = (result) => {\n\t\tif (session.signal.aborted) return;\n\t\tif (result.kind === \"invalid\" || result.kind === \"error\") notify(result.error, \"error\");\n\t\tactiveEditor?.syncFromStore();\n\t\ttui.requestRender();\n\t};\n\n\tfunction showList(): void {\n\t\tif (session.signal.aborted) return;\n\t\tactiveEditor = undefined;\n\t\tsession.setScreen(\n\t\t\tnew ProviderListScreen(\n\t\t\t\ttui,\n\t\t\t\ttheme,\n\t\t\t\tkeybindings,\n\t\t\t\t(result) => {\n\t\t\t\t\tif (result.kind === \"close\") requestClose();\n\t\t\t\t\telse openProvider(result.providerId);\n\t\t\t\t},\n\t\t\t\tstore,\n\t\t\t),\n\t\t);\n\t}\n\n\tfunction openProvider(providerId: string): void {\n\t\tif (!store.getProviderIds().includes(providerId)) {\n\t\t\tnotify(`No provider ${JSON.stringify(providerId)} in models.json.`, \"warning\");\n\t\t\tshowList();\n\t\t\treturn;\n\t\t}\n\t\tactiveEditor = new ProviderEditorScreen(tui, theme, keybindings, showList, {\n\t\t\tstore,\n\t\t\trefresher,\n\t\t\tproviderId,\n\t\t\tregistry,\n\t\t\truntime,\n\t\t\tcurrentModel: options.getCurrentModel(),\n\t\t\tnotify,\n\t\t});\n\t\tsession.setScreen(activeEditor);\n\t}\n\n\tfunction showUnsaved(error: string): void {\n\t\tconst back = \"Return to providers\";\n\t\tconst retry = \"Retry saving\";\n\t\tconst discard = \"Discard unsaved changes and close\";\n\t\tsession.setScreen(\n\t\t\tnew ExtensionSelectorComponent(\n\t\t\t\t\"Some changes are not saved\",\n\t\t\t\t[back, retry, discard],\n\t\t\t\t(choice) => {\n\t\t\t\t\tif (choice === back) {\n\t\t\t\t\t\tshowList();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (choice === retry) store.retrySave();\n\t\t\t\t\tif (choice === discard) store.discardPending();\n\t\t\t\t\trequestClose();\n\t\t\t\t},\n\t\t\t\tshowList,\n\t\t\t\t{ tui, subtitle: truncate(error, 2400) },\n\t\t\t),\n\t\t);\n\t}\n\n\tfunction requestClose(): void {\n\t\tif (closing || session.signal.aborted) return;\n\t\tconst controller = new AbortController();\n\t\tclosing = controller;\n\t\tconst signal = AbortSignal.any([session.signal, controller.signal]);\n\t\tactiveEditor = undefined;\n\t\tsession.setScreen(\n\t\t\tnew SavingScreen(theme, keybindings, () => {\n\t\t\t\tcontroller.abort();\n\t\t\t\tclosing = undefined;\n\t\t\t\tshowList();\n\t\t\t}),\n\t\t);\n\t\tvoid finishClose(controller, signal);\n\t}\n\n\tasync function finishClose(controller: AbortController, signal: AbortSignal): Promise<void> {\n\t\ttry {\n\t\t\tawait store.flush();\n\t\t\tif (signal.aborted) return;\n\t\t\tconst unsaved = store.getPendingError();\n\t\t\tif (unsaved) {\n\t\t\t\tclosing = undefined;\n\t\t\t\tshowUnsaved(unsaved);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst outcome = await refresher.flush(signal);\n\t\t\tif (signal.aborted) return;\n\t\t\tif (!outcome.ok) notify(`Changes saved, but model refresh failed: ${outcome.errors.join(\"; \")}`, \"warning\");\n\t\t\tconst current = options.getCurrentModel();\n\t\t\tif (current && refresher.touchedProviders.includes(current.provider)) {\n\t\t\t\tconst refreshed = registry.find(current.provider, current.id);\n\t\t\t\tif (refreshed && !(await options.setModel(refreshed))) {\n\t\t\t\t\tnotify(\"Reselect the current model with /model to apply its updated configuration.\", \"warning\");\n\t\t\t\t}\n\t\t\t\tif (!refreshed) notify(\"The current model is no longer available; select another with /model.\", \"warning\");\n\t\t\t}\n\t\t\tif (!signal.aborted) done();\n\t\t} catch (error) {\n\t\t\tif (!signal.aborted) {\n\t\t\t\tnotify(formatError(error), \"error\");\n\t\t\t\tshowList();\n\t\t\t}\n\t\t} finally {\n\t\t\tif (closing === controller) closing = undefined;\n\t\t}\n\t}\n\n\tif (options.initialProviderId) openProvider(options.initialProviderId);\n\telse showList();\n\treturn session;\n}\n"]}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Use Built-in Data: pick a Pi builtin catalog entry as a reference for the
|
|
3
|
+
* current model, preview per-field changes ("current → reference"), check the
|
|
4
|
+
* fields to copy, and apply once. Selection and preview are temporary state;
|
|
5
|
+
* Esc applies nothing. Identity/connection fields (provider, id, api,
|
|
6
|
+
* baseUrl, keys) are never touched.
|
|
7
|
+
*/
|
|
8
|
+
import { type CatalogEntry } from "../catalog.ts";
|
|
9
|
+
import type { EditorHost, EditorPane, ModelHandle } from "./pane.ts";
|
|
10
|
+
import { type ScrollWindowInfo } from "./value-row.ts";
|
|
11
|
+
export declare class BuiltinCandidatesPane implements EditorPane {
|
|
12
|
+
readonly crumb = "Use Built-in Data";
|
|
13
|
+
private readonly search;
|
|
14
|
+
private query;
|
|
15
|
+
private index;
|
|
16
|
+
private focused;
|
|
17
|
+
private readonly host;
|
|
18
|
+
private readonly model;
|
|
19
|
+
constructor(host: EditorHost, model: ModelHandle);
|
|
20
|
+
private candidates;
|
|
21
|
+
private tiers;
|
|
22
|
+
render(width: number): string[];
|
|
23
|
+
scrollWindow(): ScrollWindowInfo;
|
|
24
|
+
private pickCurrent;
|
|
25
|
+
handleInput(data: string): void;
|
|
26
|
+
setFocused(focused: boolean): void;
|
|
27
|
+
isEditing(): boolean;
|
|
28
|
+
hints(): string;
|
|
29
|
+
}
|
|
30
|
+
export declare class BuiltinPreviewPane implements EditorPane {
|
|
31
|
+
readonly crumb = "Use Built-in Data \u00B7 preview";
|
|
32
|
+
private readonly changes;
|
|
33
|
+
private readonly checked;
|
|
34
|
+
private readonly snapshot;
|
|
35
|
+
private readonly snapshotApi;
|
|
36
|
+
private index;
|
|
37
|
+
private expanded;
|
|
38
|
+
private error;
|
|
39
|
+
private focused;
|
|
40
|
+
private readonly host;
|
|
41
|
+
private readonly model;
|
|
42
|
+
private readonly reference;
|
|
43
|
+
constructor(host: EditorHost, model: ModelHandle, reference: CatalogEntry);
|
|
44
|
+
private rowCount;
|
|
45
|
+
render(width: number): string[];
|
|
46
|
+
scrollWindow(): ScrollWindowInfo;
|
|
47
|
+
handleInput(data: string): void;
|
|
48
|
+
private apply;
|
|
49
|
+
private applyChange;
|
|
50
|
+
setFocused(focused: boolean): void;
|
|
51
|
+
hints(): string;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=builtin-data.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builtin-data.d.ts","sourceRoot":"","sources":["../../../../src/extensions/provider/ui/builtin-data.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,EAAE,KAAK,YAAY,EAA6D,MAAM,eAAe,CAAC;AAG7G,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACrE,OAAO,EAAmC,KAAK,gBAAgB,EAAe,MAAM,gBAAgB,CAAC;AAOrG,qBAAa,qBAAsB,YAAW,UAAU;IACvD,QAAQ,CAAC,KAAK,uBAAuB;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IACrC,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,OAAO,CAAS;IAExB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;IAClC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAc;gBACxB,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW;IAYhD,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,KAAK;IAIb,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IA4B/B,YAAY,IAAI,gBAAgB;IAKhC,OAAO,CAAC,WAAW;IAMnB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IA4B/B,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAKlC,SAAS,IAAI,OAAO;IAIpB,KAAK,IAAI,MAAM;CAQf;AAED,qBAAa,kBAAmB,YAAW,UAAU;IACpD,QAAQ,CAAC,KAAK,sCAAiC;IAC/C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;IACxC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAY;IACpC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA6C;IACtE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;IACjD,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,QAAQ,CAAqB;IACrC,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,OAAO,CAAS;IAExB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;IAClC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAc;IACpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;gBAC7B,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY;IAYzE,OAAO,CAAC,QAAQ;IAIhB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAsC/B,YAAY,IAAI,gBAAgB;IAahC,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IA4C/B,OAAO,CAAC,KAAK;IA8Bb,OAAO,CAAC,WAAW;IAsDnB,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAIlC,KAAK,IAAI,MAAM;CAOf"}
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Use Built-in Data: pick a Pi builtin catalog entry as a reference for the
|
|
3
|
+
* current model, preview per-field changes ("current → reference"), check the
|
|
4
|
+
* fields to copy, and apply once. Selection and preview are temporary state;
|
|
5
|
+
* Esc applies nothing. Identity/connection fields (provider, id, api,
|
|
6
|
+
* baseUrl, keys) are never touched.
|
|
7
|
+
*/
|
|
8
|
+
import { keyHint, rawKeyHint } from "../../../modes/interactive/components/keybinding-hints.js";
|
|
9
|
+
import { computeFieldChanges, matchBuiltinModels } from "../catalog.js";
|
|
10
|
+
import { truncate } from "../constants.js";
|
|
11
|
+
import { jsonEquals } from "../store.js";
|
|
12
|
+
import { renderInfoLine, renderPlainLine, ValueEditor } from "./value-row.js";
|
|
13
|
+
function formatContext(model) {
|
|
14
|
+
const ctx = model.contextWindow >= 1000 ? `${Math.round(model.contextWindow / 1024)}k` : String(model.contextWindow);
|
|
15
|
+
return `${model.api} · ${ctx} ctx${model.reasoning ? " · reasoning" : ""}`;
|
|
16
|
+
}
|
|
17
|
+
export class BuiltinCandidatesPane {
|
|
18
|
+
constructor(host, model) {
|
|
19
|
+
this.crumb = "Use Built-in Data";
|
|
20
|
+
this.index = 0;
|
|
21
|
+
this.focused = false;
|
|
22
|
+
this.host = host;
|
|
23
|
+
this.model = model;
|
|
24
|
+
this.query = this.model.read().id ?? "";
|
|
25
|
+
this.search = new ValueEditor({
|
|
26
|
+
onCommit: () => this.pickCurrent(),
|
|
27
|
+
onCancel: () => this.host.popPane(),
|
|
28
|
+
});
|
|
29
|
+
this.search.reset(this.query);
|
|
30
|
+
}
|
|
31
|
+
candidates() {
|
|
32
|
+
return matchBuiltinModels(this.query, this.host.effectiveApi(this.model.read())).map((match) => match.entry);
|
|
33
|
+
}
|
|
34
|
+
tiers() {
|
|
35
|
+
return matchBuiltinModels(this.query, this.host.effectiveApi(this.model.read()));
|
|
36
|
+
}
|
|
37
|
+
render(width) {
|
|
38
|
+
const theme = this.host.theme;
|
|
39
|
+
const lines = [this.search.renderLine(width)];
|
|
40
|
+
const matches = this.tiers();
|
|
41
|
+
if (matches.length === 0) {
|
|
42
|
+
lines.push(renderInfoLine(theme, "No builtin candidates — keep configuring manually.", width));
|
|
43
|
+
}
|
|
44
|
+
for (const [rowIndex, match] of matches.entries()) {
|
|
45
|
+
const { providerId, model } = match.entry;
|
|
46
|
+
const label = `${providerId} / ${model.id}`;
|
|
47
|
+
const note = (match.tier === "exact" ? "exact · " : "") +
|
|
48
|
+
`${model.name !== model.id ? `${model.name} · ` : ""}${formatContext(model)}`;
|
|
49
|
+
lines.push(renderPlainLine(theme, label, {
|
|
50
|
+
active: rowIndex === this.index,
|
|
51
|
+
paneFocused: this.focused,
|
|
52
|
+
note,
|
|
53
|
+
width,
|
|
54
|
+
}));
|
|
55
|
+
}
|
|
56
|
+
lines.push(renderInfoLine(theme, "Candidates are a reference only; the configured id is never rewritten.", width));
|
|
57
|
+
return lines;
|
|
58
|
+
}
|
|
59
|
+
scrollWindow() {
|
|
60
|
+
// The filter input pins above, the reference disclaimer below.
|
|
61
|
+
return { top: 1, bottom: 1, cursor: 1 + this.index };
|
|
62
|
+
}
|
|
63
|
+
pickCurrent() {
|
|
64
|
+
const entry = this.candidates()[this.index];
|
|
65
|
+
if (!entry)
|
|
66
|
+
return;
|
|
67
|
+
this.host.pushPane(new BuiltinPreviewPane(this.host, this.model, entry));
|
|
68
|
+
}
|
|
69
|
+
handleInput(data) {
|
|
70
|
+
const kb = this.host.keybindings;
|
|
71
|
+
const count = this.candidates().length;
|
|
72
|
+
if (kb.matches(data, "tui.select.up")) {
|
|
73
|
+
if (count > 0)
|
|
74
|
+
this.index = this.index === 0 ? count - 1 : this.index - 1;
|
|
75
|
+
this.host.refresh();
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
if (kb.matches(data, "tui.select.down")) {
|
|
79
|
+
if (count > 0)
|
|
80
|
+
this.index = (this.index + 1) % count;
|
|
81
|
+
this.host.refresh();
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (kb.matches(data, "tui.select.cancel")) {
|
|
85
|
+
this.host.popPane();
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
if (kb.matches(data, "tui.select.confirm")) {
|
|
89
|
+
this.pickCurrent();
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const before = this.query;
|
|
93
|
+
this.search.handleInput(data);
|
|
94
|
+
this.query = this.search.value;
|
|
95
|
+
if (this.query !== before)
|
|
96
|
+
this.index = 0;
|
|
97
|
+
this.host.refresh();
|
|
98
|
+
}
|
|
99
|
+
setFocused(focused) {
|
|
100
|
+
this.focused = focused;
|
|
101
|
+
this.search.focused = focused;
|
|
102
|
+
}
|
|
103
|
+
isEditing() {
|
|
104
|
+
return true; // the candidate filter always owns ←/→
|
|
105
|
+
}
|
|
106
|
+
hints() {
|
|
107
|
+
return [
|
|
108
|
+
rawKeyHint("type", "filter"),
|
|
109
|
+
rawKeyHint("↑↓", "move"),
|
|
110
|
+
keyHint("tui.select.confirm", "preview"),
|
|
111
|
+
keyHint("tui.select.cancel", "back"),
|
|
112
|
+
].join(" ");
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
export class BuiltinPreviewPane {
|
|
116
|
+
constructor(host, model, reference) {
|
|
117
|
+
this.crumb = "Use Built-in Data · preview";
|
|
118
|
+
this.index = 0;
|
|
119
|
+
this.focused = false;
|
|
120
|
+
this.host = host;
|
|
121
|
+
this.model = model;
|
|
122
|
+
this.reference = reference;
|
|
123
|
+
const current = model.read();
|
|
124
|
+
this.snapshot = structuredClone(current);
|
|
125
|
+
this.snapshotApi = host.effectiveApi(current);
|
|
126
|
+
this.changes = computeFieldChanges(current, reference.model, host.effectiveApi(current));
|
|
127
|
+
this.checked = this.changes.map((change) => change.checked && change.applicable);
|
|
128
|
+
}
|
|
129
|
+
rowCount() {
|
|
130
|
+
return this.changes.length + 1; // + Apply row
|
|
131
|
+
}
|
|
132
|
+
render(width) {
|
|
133
|
+
const theme = this.host.theme;
|
|
134
|
+
const lines = [
|
|
135
|
+
renderInfoLine(theme, `reference: ${this.reference.providerId} / ${this.reference.model.id}`, width),
|
|
136
|
+
];
|
|
137
|
+
for (const [rowIndex, change] of this.changes.entries()) {
|
|
138
|
+
const active = rowIndex === this.index;
|
|
139
|
+
const expandable = change.referenceDetails !== undefined;
|
|
140
|
+
const note = !change.applicable ? "· view only" : undefined;
|
|
141
|
+
lines.push(renderPlainLine(theme, `${change.field}: ${change.currentText} → ${change.referenceText}`, {
|
|
142
|
+
checked: change.applicable ? this.checked[rowIndex] : undefined,
|
|
143
|
+
active,
|
|
144
|
+
paneFocused: this.focused,
|
|
145
|
+
note,
|
|
146
|
+
width,
|
|
147
|
+
}));
|
|
148
|
+
if (this.expanded === rowIndex && expandable) {
|
|
149
|
+
for (const detail of change.referenceDetails) {
|
|
150
|
+
lines.push(renderInfoLine(theme, ` ${detail}`, width));
|
|
151
|
+
}
|
|
152
|
+
if (change.referenceHasTiers) {
|
|
153
|
+
lines.push(renderInfoLine(theme, " reference has cost tiers — tiers are never imported.", width));
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
lines.push(renderPlainLine(theme, "Apply Selected Fields", {
|
|
158
|
+
active: this.index === this.changes.length,
|
|
159
|
+
paneFocused: this.focused,
|
|
160
|
+
width,
|
|
161
|
+
}));
|
|
162
|
+
if (this.error)
|
|
163
|
+
lines.push(theme.fg("error", truncate(this.error, Math.max(10, width - 2))));
|
|
164
|
+
return lines;
|
|
165
|
+
}
|
|
166
|
+
scrollWindow() {
|
|
167
|
+
// The reference header pins above; errors pin below. Expanded detail
|
|
168
|
+
// lines shift the cursor row when they sit above it.
|
|
169
|
+
let cursor = 1 + this.index;
|
|
170
|
+
if (this.expanded !== undefined && this.expanded < this.index) {
|
|
171
|
+
const change = this.changes[this.expanded];
|
|
172
|
+
if (change.referenceDetails) {
|
|
173
|
+
cursor += change.referenceDetails.length + (change.referenceHasTiers ? 1 : 0);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return { top: 1, bottom: this.error ? 1 : 0, cursor };
|
|
177
|
+
}
|
|
178
|
+
handleInput(data) {
|
|
179
|
+
const kb = this.host.keybindings;
|
|
180
|
+
if (kb.matches(data, "tui.select.up")) {
|
|
181
|
+
this.index = this.index === 0 ? this.rowCount() - 1 : this.index - 1;
|
|
182
|
+
this.host.refresh();
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
if (kb.matches(data, "tui.select.down")) {
|
|
186
|
+
this.index = (this.index + 1) % this.rowCount();
|
|
187
|
+
this.host.refresh();
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
if (kb.matches(data, "tui.select.cancel")) {
|
|
191
|
+
this.host.popPane();
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
if (kb.matches(data, "app.list.toggle")) {
|
|
195
|
+
const change = this.changes[this.index];
|
|
196
|
+
if (!change)
|
|
197
|
+
return;
|
|
198
|
+
if (!change.applicable) {
|
|
199
|
+
this.expanded = this.expanded === this.index ? undefined : this.index;
|
|
200
|
+
this.host.refresh();
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
this.checked[this.index] = !this.checked[this.index];
|
|
204
|
+
this.host.refresh();
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
if (kb.matches(data, "tui.select.confirm")) {
|
|
208
|
+
if (this.index === this.changes.length) {
|
|
209
|
+
this.apply();
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
const change = this.changes[this.index];
|
|
213
|
+
if (change.referenceDetails) {
|
|
214
|
+
this.expanded = this.expanded === this.index ? undefined : this.index;
|
|
215
|
+
}
|
|
216
|
+
else if (change.applicable) {
|
|
217
|
+
this.checked[this.index] = !this.checked[this.index];
|
|
218
|
+
}
|
|
219
|
+
this.host.refresh();
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
apply() {
|
|
224
|
+
// Re-validate against the live model: a stale preview must not write to a changed model.
|
|
225
|
+
const current = this.model.read();
|
|
226
|
+
if (this.host.effectiveApi(current) !== this.snapshotApi) {
|
|
227
|
+
this.error = "The API changed since this preview opened; reopen to continue.";
|
|
228
|
+
this.host.refresh();
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
if (!current.id || !jsonEquals(current, this.snapshot)) {
|
|
232
|
+
this.error = "The model changed since this preview opened; reopen to continue.";
|
|
233
|
+
this.host.refresh();
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
const chosen = this.changes.filter((_, rowIndex) => this.checked[rowIndex] && this.changes[rowIndex].applicable);
|
|
237
|
+
if (chosen.length === 0) {
|
|
238
|
+
this.host.popPane();
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
this.host.store.batch(() => {
|
|
242
|
+
for (const change of chosen)
|
|
243
|
+
this.applyChange(change.field);
|
|
244
|
+
});
|
|
245
|
+
this.host.refresher.touch(this.host.providerId);
|
|
246
|
+
this.host.notify(`Applied ${chosen.length} field${chosen.length === 1 ? "" : "s"} from ${this.reference.providerId} / ${this.reference.model.id}.`, "info");
|
|
247
|
+
this.host.popPane(); // preview
|
|
248
|
+
this.host.popPane(); // candidates → back to the model fields
|
|
249
|
+
}
|
|
250
|
+
applyChange(field) {
|
|
251
|
+
const reference = this.reference.model;
|
|
252
|
+
const current = this.model.read();
|
|
253
|
+
switch (field) {
|
|
254
|
+
case "name":
|
|
255
|
+
this.model.setField(["name"], reference.name);
|
|
256
|
+
return;
|
|
257
|
+
case "reasoning":
|
|
258
|
+
this.model.setField(["reasoning"], reference.reasoning);
|
|
259
|
+
return;
|
|
260
|
+
case "input":
|
|
261
|
+
this.model.setField(["input"], [...reference.input]);
|
|
262
|
+
return;
|
|
263
|
+
case "contextWindow":
|
|
264
|
+
this.model.setField(["contextWindow"], reference.contextWindow);
|
|
265
|
+
return;
|
|
266
|
+
case "maxTokens":
|
|
267
|
+
this.model.setField(["maxTokens"], reference.maxTokens);
|
|
268
|
+
return;
|
|
269
|
+
case "thinkingLevelMap":
|
|
270
|
+
for (const [level, target] of Object.entries(reference.thinkingLevelMap ?? {})) {
|
|
271
|
+
this.model.setField(["thinkingLevelMap", level], target);
|
|
272
|
+
}
|
|
273
|
+
return;
|
|
274
|
+
case "compat":
|
|
275
|
+
for (const [key, value] of Object.entries(reference.compat ?? {})) {
|
|
276
|
+
if (["chatTemplateKwargs", "chatTemplateArgs", "openRouterRouting", "vercelGatewayRouting"].includes(key) &&
|
|
277
|
+
value !== null &&
|
|
278
|
+
typeof value === "object" &&
|
|
279
|
+
!Array.isArray(value)) {
|
|
280
|
+
for (const [entryKey, entryValue] of Object.entries(value))
|
|
281
|
+
this.model.setField(["compat", key, entryKey], structuredClone(entryValue));
|
|
282
|
+
}
|
|
283
|
+
else
|
|
284
|
+
this.model.setField(["compat", key], structuredClone(value));
|
|
285
|
+
}
|
|
286
|
+
return;
|
|
287
|
+
case "cost": {
|
|
288
|
+
const rates = {
|
|
289
|
+
input: reference.cost.input,
|
|
290
|
+
output: reference.cost.output,
|
|
291
|
+
cacheRead: reference.cost.cacheRead,
|
|
292
|
+
cacheWrite: reference.cost.cacheWrite,
|
|
293
|
+
};
|
|
294
|
+
if (current.cost) {
|
|
295
|
+
for (const [rate, value] of Object.entries(rates))
|
|
296
|
+
this.model.setField(["cost", rate], value);
|
|
297
|
+
}
|
|
298
|
+
else
|
|
299
|
+
this.model.setField(["cost"], rates);
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
setFocused(focused) {
|
|
305
|
+
this.focused = focused;
|
|
306
|
+
}
|
|
307
|
+
hints() {
|
|
308
|
+
return [
|
|
309
|
+
keyHint("app.list.toggle", "check"),
|
|
310
|
+
keyHint("tui.select.confirm", "details / apply"),
|
|
311
|
+
keyHint("tui.select.cancel", "back"),
|
|
312
|
+
].join(" ");
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
//# sourceMappingURL=builtin-data.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builtin-data.js","sourceRoot":"","sources":["../../../../src/extensions/provider/ui/builtin-data.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Use Built-in Data: pick a Pi builtin catalog entry as a reference for the\n * current model, preview per-field changes (\"current → reference\"), check the\n * fields to copy, and apply once. Selection and preview are temporary state;\n * Esc applies nothing. Identity/connection fields (provider, id, api,\n * baseUrl, keys) are never touched.\n */\n\nimport type { Api, Model } from \"@earendil-works/pi-ai\";\nimport type { ModelsJsonModel } from \"../../../core/model-config.ts\";\nimport { keyHint, rawKeyHint } from \"../../../modes/interactive/components/keybinding-hints.ts\";\nimport { type CatalogEntry, computeFieldChanges, type FieldChange, matchBuiltinModels } from \"../catalog.ts\";\nimport { truncate } from \"../constants.ts\";\nimport { jsonEquals } from \"../store.ts\";\nimport type { EditorHost, EditorPane, ModelHandle } from \"./pane.ts\";\nimport { renderInfoLine, renderPlainLine, type ScrollWindowInfo, ValueEditor } from \"./value-row.ts\";\n\nfunction formatContext(model: Model<Api>): string {\n\tconst ctx = model.contextWindow >= 1000 ? `${Math.round(model.contextWindow / 1024)}k` : String(model.contextWindow);\n\treturn `${model.api} · ${ctx} ctx${model.reasoning ? \" · reasoning\" : \"\"}`;\n}\n\nexport class BuiltinCandidatesPane implements EditorPane {\n\treadonly crumb = \"Use Built-in Data\";\n\tprivate readonly search: ValueEditor;\n\tprivate query: string;\n\tprivate index = 0;\n\tprivate focused = false;\n\n\tprivate readonly host: EditorHost;\n\tprivate readonly model: ModelHandle;\n\tconstructor(host: EditorHost, model: ModelHandle) {\n\t\tthis.host = host;\n\t\tthis.model = model;\n\n\t\tthis.query = this.model.read().id ?? \"\";\n\t\tthis.search = new ValueEditor({\n\t\t\tonCommit: () => this.pickCurrent(),\n\t\t\tonCancel: () => this.host.popPane(),\n\t\t});\n\t\tthis.search.reset(this.query);\n\t}\n\n\tprivate candidates(): CatalogEntry[] {\n\t\treturn matchBuiltinModels(this.query, this.host.effectiveApi(this.model.read())).map((match) => match.entry);\n\t}\n\n\tprivate tiers(): ReturnType<typeof matchBuiltinModels> {\n\t\treturn matchBuiltinModels(this.query, this.host.effectiveApi(this.model.read()));\n\t}\n\n\trender(width: number): string[] {\n\t\tconst theme = this.host.theme;\n\t\tconst lines: string[] = [this.search.renderLine(width)];\n\t\tconst matches = this.tiers();\n\t\tif (matches.length === 0) {\n\t\t\tlines.push(renderInfoLine(theme, \"No builtin candidates — keep configuring manually.\", width));\n\t\t}\n\t\tfor (const [rowIndex, match] of matches.entries()) {\n\t\t\tconst { providerId, model } = match.entry;\n\t\t\tconst label = `${providerId} / ${model.id}`;\n\t\t\tconst note =\n\t\t\t\t(match.tier === \"exact\" ? \"exact · \" : \"\") +\n\t\t\t\t`${model.name !== model.id ? `${model.name} · ` : \"\"}${formatContext(model)}`;\n\t\t\tlines.push(\n\t\t\t\trenderPlainLine(theme, label, {\n\t\t\t\t\tactive: rowIndex === this.index,\n\t\t\t\t\tpaneFocused: this.focused,\n\t\t\t\t\tnote,\n\t\t\t\t\twidth,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\tlines.push(\n\t\t\trenderInfoLine(theme, \"Candidates are a reference only; the configured id is never rewritten.\", width),\n\t\t);\n\t\treturn lines;\n\t}\n\n\tscrollWindow(): ScrollWindowInfo {\n\t\t// The filter input pins above, the reference disclaimer below.\n\t\treturn { top: 1, bottom: 1, cursor: 1 + this.index };\n\t}\n\n\tprivate pickCurrent(): void {\n\t\tconst entry = this.candidates()[this.index];\n\t\tif (!entry) return;\n\t\tthis.host.pushPane(new BuiltinPreviewPane(this.host, this.model, entry));\n\t}\n\n\thandleInput(data: string): void {\n\t\tconst kb = this.host.keybindings;\n\t\tconst count = this.candidates().length;\n\t\tif (kb.matches(data, \"tui.select.up\")) {\n\t\t\tif (count > 0) this.index = this.index === 0 ? count - 1 : this.index - 1;\n\t\t\tthis.host.refresh();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"tui.select.down\")) {\n\t\t\tif (count > 0) this.index = (this.index + 1) % count;\n\t\t\tthis.host.refresh();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"tui.select.cancel\")) {\n\t\t\tthis.host.popPane();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"tui.select.confirm\")) {\n\t\t\tthis.pickCurrent();\n\t\t\treturn;\n\t\t}\n\t\tconst before = this.query;\n\t\tthis.search.handleInput(data);\n\t\tthis.query = this.search.value;\n\t\tif (this.query !== before) this.index = 0;\n\t\tthis.host.refresh();\n\t}\n\n\tsetFocused(focused: boolean): void {\n\t\tthis.focused = focused;\n\t\tthis.search.focused = focused;\n\t}\n\n\tisEditing(): boolean {\n\t\treturn true; // the candidate filter always owns ←/→\n\t}\n\n\thints(): string {\n\t\treturn [\n\t\t\trawKeyHint(\"type\", \"filter\"),\n\t\t\trawKeyHint(\"↑↓\", \"move\"),\n\t\t\tkeyHint(\"tui.select.confirm\", \"preview\"),\n\t\t\tkeyHint(\"tui.select.cancel\", \"back\"),\n\t\t].join(\" \");\n\t}\n}\n\nexport class BuiltinPreviewPane implements EditorPane {\n\treadonly crumb = \"Use Built-in Data · preview\";\n\tprivate readonly changes: FieldChange[];\n\tprivate readonly checked: boolean[];\n\tprivate readonly snapshot: Partial<ModelsJsonModel> & { id?: string };\n\tprivate readonly snapshotApi: string | undefined;\n\tprivate index = 0;\n\tprivate expanded: number | undefined;\n\tprivate error: string | undefined;\n\tprivate focused = false;\n\n\tprivate readonly host: EditorHost;\n\tprivate readonly model: ModelHandle;\n\tprivate readonly reference: CatalogEntry;\n\tconstructor(host: EditorHost, model: ModelHandle, reference: CatalogEntry) {\n\t\tthis.host = host;\n\t\tthis.model = model;\n\t\tthis.reference = reference;\n\n\t\tconst current = model.read();\n\t\tthis.snapshot = structuredClone(current);\n\t\tthis.snapshotApi = host.effectiveApi(current);\n\t\tthis.changes = computeFieldChanges(current, reference.model, host.effectiveApi(current));\n\t\tthis.checked = this.changes.map((change) => change.checked && change.applicable);\n\t}\n\n\tprivate rowCount(): number {\n\t\treturn this.changes.length + 1; // + Apply row\n\t}\n\n\trender(width: number): string[] {\n\t\tconst theme = this.host.theme;\n\t\tconst lines: string[] = [\n\t\t\trenderInfoLine(theme, `reference: ${this.reference.providerId} / ${this.reference.model.id}`, width),\n\t\t];\n\t\tfor (const [rowIndex, change] of this.changes.entries()) {\n\t\t\tconst active = rowIndex === this.index;\n\t\t\tconst expandable = change.referenceDetails !== undefined;\n\t\t\tconst note = !change.applicable ? \"· view only\" : undefined;\n\t\t\tlines.push(\n\t\t\t\trenderPlainLine(theme, `${change.field}: ${change.currentText} → ${change.referenceText}`, {\n\t\t\t\t\tchecked: change.applicable ? this.checked[rowIndex] : undefined,\n\t\t\t\t\tactive,\n\t\t\t\t\tpaneFocused: this.focused,\n\t\t\t\t\tnote,\n\t\t\t\t\twidth,\n\t\t\t\t}),\n\t\t\t);\n\t\t\tif (this.expanded === rowIndex && expandable) {\n\t\t\t\tfor (const detail of change.referenceDetails!) {\n\t\t\t\t\tlines.push(renderInfoLine(theme, ` ${detail}`, width));\n\t\t\t\t}\n\t\t\t\tif (change.referenceHasTiers) {\n\t\t\t\t\tlines.push(renderInfoLine(theme, \" reference has cost tiers — tiers are never imported.\", width));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tlines.push(\n\t\t\trenderPlainLine(theme, \"Apply Selected Fields\", {\n\t\t\t\tactive: this.index === this.changes.length,\n\t\t\t\tpaneFocused: this.focused,\n\t\t\t\twidth,\n\t\t\t}),\n\t\t);\n\t\tif (this.error) lines.push(theme.fg(\"error\", truncate(this.error, Math.max(10, width - 2))));\n\t\treturn lines;\n\t}\n\n\tscrollWindow(): ScrollWindowInfo {\n\t\t// The reference header pins above; errors pin below. Expanded detail\n\t\t// lines shift the cursor row when they sit above it.\n\t\tlet cursor = 1 + this.index;\n\t\tif (this.expanded !== undefined && this.expanded < this.index) {\n\t\t\tconst change = this.changes[this.expanded]!;\n\t\t\tif (change.referenceDetails) {\n\t\t\t\tcursor += change.referenceDetails.length + (change.referenceHasTiers ? 1 : 0);\n\t\t\t}\n\t\t}\n\t\treturn { top: 1, bottom: this.error ? 1 : 0, cursor };\n\t}\n\n\thandleInput(data: string): void {\n\t\tconst kb = this.host.keybindings;\n\t\tif (kb.matches(data, \"tui.select.up\")) {\n\t\t\tthis.index = this.index === 0 ? this.rowCount() - 1 : this.index - 1;\n\t\t\tthis.host.refresh();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"tui.select.down\")) {\n\t\t\tthis.index = (this.index + 1) % this.rowCount();\n\t\t\tthis.host.refresh();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"tui.select.cancel\")) {\n\t\t\tthis.host.popPane();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"app.list.toggle\")) {\n\t\t\tconst change = this.changes[this.index];\n\t\t\tif (!change) return;\n\t\t\tif (!change.applicable) {\n\t\t\t\tthis.expanded = this.expanded === this.index ? undefined : this.index;\n\t\t\t\tthis.host.refresh();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.checked[this.index] = !this.checked[this.index];\n\t\t\tthis.host.refresh();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"tui.select.confirm\")) {\n\t\t\tif (this.index === this.changes.length) {\n\t\t\t\tthis.apply();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst change = this.changes[this.index]!;\n\t\t\tif (change.referenceDetails) {\n\t\t\t\tthis.expanded = this.expanded === this.index ? undefined : this.index;\n\t\t\t} else if (change.applicable) {\n\t\t\t\tthis.checked[this.index] = !this.checked[this.index];\n\t\t\t}\n\t\t\tthis.host.refresh();\n\t\t\treturn;\n\t\t}\n\t}\n\n\tprivate apply(): void {\n\t\t// Re-validate against the live model: a stale preview must not write to a changed model.\n\t\tconst current = this.model.read();\n\t\tif (this.host.effectiveApi(current) !== this.snapshotApi) {\n\t\t\tthis.error = \"The API changed since this preview opened; reopen to continue.\";\n\t\t\tthis.host.refresh();\n\t\t\treturn;\n\t\t}\n\t\tif (!current.id || !jsonEquals(current, this.snapshot)) {\n\t\t\tthis.error = \"The model changed since this preview opened; reopen to continue.\";\n\t\t\tthis.host.refresh();\n\t\t\treturn;\n\t\t}\n\t\tconst chosen = this.changes.filter((_, rowIndex) => this.checked[rowIndex] && this.changes[rowIndex]!.applicable);\n\t\tif (chosen.length === 0) {\n\t\t\tthis.host.popPane();\n\t\t\treturn;\n\t\t}\n\t\tthis.host.store.batch(() => {\n\t\t\tfor (const change of chosen) this.applyChange(change.field);\n\t\t});\n\t\tthis.host.refresher.touch(this.host.providerId);\n\t\tthis.host.notify(\n\t\t\t`Applied ${chosen.length} field${chosen.length === 1 ? \"\" : \"s\"} from ${this.reference.providerId} / ${this.reference.model.id}.`,\n\t\t\t\"info\",\n\t\t);\n\t\tthis.host.popPane(); // preview\n\t\tthis.host.popPane(); // candidates → back to the model fields\n\t}\n\n\tprivate applyChange(field: FieldChange[\"field\"]): void {\n\t\tconst reference = this.reference.model;\n\t\tconst current = this.model.read();\n\t\tswitch (field) {\n\t\t\tcase \"name\":\n\t\t\t\tthis.model.setField([\"name\"], reference.name);\n\t\t\t\treturn;\n\t\t\tcase \"reasoning\":\n\t\t\t\tthis.model.setField([\"reasoning\"], reference.reasoning);\n\t\t\t\treturn;\n\t\t\tcase \"input\":\n\t\t\t\tthis.model.setField([\"input\"], [...reference.input]);\n\t\t\t\treturn;\n\t\t\tcase \"contextWindow\":\n\t\t\t\tthis.model.setField([\"contextWindow\"], reference.contextWindow);\n\t\t\t\treturn;\n\t\t\tcase \"maxTokens\":\n\t\t\t\tthis.model.setField([\"maxTokens\"], reference.maxTokens);\n\t\t\t\treturn;\n\t\t\tcase \"thinkingLevelMap\":\n\t\t\t\tfor (const [level, target] of Object.entries(reference.thinkingLevelMap ?? {})) {\n\t\t\t\t\tthis.model.setField([\"thinkingLevelMap\", level], target);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\tcase \"compat\":\n\t\t\t\tfor (const [key, value] of Object.entries(reference.compat ?? {})) {\n\t\t\t\t\tif (\n\t\t\t\t\t\t[\"chatTemplateKwargs\", \"chatTemplateArgs\", \"openRouterRouting\", \"vercelGatewayRouting\"].includes(\n\t\t\t\t\t\t\tkey,\n\t\t\t\t\t\t) &&\n\t\t\t\t\t\tvalue !== null &&\n\t\t\t\t\t\ttypeof value === \"object\" &&\n\t\t\t\t\t\t!Array.isArray(value)\n\t\t\t\t\t) {\n\t\t\t\t\t\tfor (const [entryKey, entryValue] of Object.entries(value))\n\t\t\t\t\t\t\tthis.model.setField([\"compat\", key, entryKey], structuredClone(entryValue));\n\t\t\t\t\t} else this.model.setField([\"compat\", key], structuredClone(value));\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\tcase \"cost\": {\n\t\t\t\tconst rates = {\n\t\t\t\t\tinput: reference.cost.input,\n\t\t\t\t\toutput: reference.cost.output,\n\t\t\t\t\tcacheRead: reference.cost.cacheRead,\n\t\t\t\t\tcacheWrite: reference.cost.cacheWrite,\n\t\t\t\t};\n\t\t\t\tif (current.cost) {\n\t\t\t\t\tfor (const [rate, value] of Object.entries(rates)) this.model.setField([\"cost\", rate], value);\n\t\t\t\t} else this.model.setField([\"cost\"], rates);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\tsetFocused(focused: boolean): void {\n\t\tthis.focused = focused;\n\t}\n\n\thints(): string {\n\t\treturn [\n\t\t\tkeyHint(\"app.list.toggle\", \"check\"),\n\t\t\tkeyHint(\"tui.select.confirm\", \"details / apply\"),\n\t\t\tkeyHint(\"tui.select.cancel\", \"back\"),\n\t\t].join(\" \");\n\t}\n}\n"]}
|