@astralyn/pi 0.85.1 → 0.85.3
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 +43 -0
- package/dist/bundle/chunks/anthropic-messages-IHRRITCV.js +6 -0
- package/dist/bundle/chunks/anthropic.js +75 -0
- package/dist/bundle/chunks/azure-openai-responses-QXBIDYXO.js +2 -0
- package/dist/bundle/chunks/bedrock-converse-stream.js +78 -0
- package/dist/bundle/chunks/chunk-37ATLPRE.js +2 -0
- package/dist/bundle/chunks/chunk-4L3WN2XY.js +2 -0
- package/dist/bundle/chunks/chunk-5B3S5DVL.js +4 -0
- package/dist/bundle/chunks/chunk-5FDOJRDS.js +2 -0
- package/dist/bundle/chunks/chunk-6CYCI3EJ.js +12 -0
- package/dist/bundle/chunks/chunk-7LO5Z4WE.js +2 -0
- package/dist/bundle/chunks/chunk-APKJ4JGA.js +2 -0
- package/dist/bundle/chunks/chunk-EDBLK2JQ.js +2 -0
- package/dist/bundle/chunks/chunk-FEZ5RM2B.js +2 -0
- package/dist/bundle/chunks/chunk-JEIV47WR.js +2 -0
- package/dist/bundle/chunks/chunk-JSJPY26N.js +2 -0
- package/dist/bundle/chunks/chunk-KI6LC764.js +42 -0
- package/dist/bundle/chunks/chunk-LB4P77SH.js +1688 -0
- package/dist/bundle/chunks/chunk-NUHFSC37.js +25 -0
- package/dist/bundle/chunks/chunk-O36ZMA3U.js +2 -0
- package/dist/bundle/chunks/chunk-OWESLY5T.js +11 -0
- package/dist/bundle/chunks/chunk-RRBI7OUG.js +50 -0
- package/dist/bundle/chunks/chunk-S2DJQQI2.js +2 -0
- package/dist/bundle/chunks/chunk-UP6RLTHQ.js +2 -0
- package/dist/bundle/chunks/chunk-UUSTLCVC.js +2 -0
- package/dist/bundle/chunks/chunk-WWBSZG5V.js +2 -0
- package/dist/bundle/chunks/chunk-YZJWMPUI.js +2 -0
- package/dist/bundle/chunks/github-copilot.js +2 -0
- package/dist/bundle/chunks/google-generative-ai-NBOR3IQR.js +2 -0
- package/dist/bundle/chunks/google-vertex-VTHX3SUB.js +2 -0
- package/dist/bundle/chunks/https-proxy-agent-2VXB7436.js +13 -0
- package/dist/bundle/chunks/image-resize-worker.js +2 -0
- package/dist/bundle/chunks/kimi-coding.js +2 -0
- package/dist/bundle/chunks/mistral-conversations-NO4ANAA5.js +5 -0
- package/dist/bundle/chunks/multipart-parser-SQ6GDJL7.js +3 -0
- package/dist/bundle/chunks/node-7L5OTM6S.js +2 -0
- package/dist/bundle/chunks/node-G4XOIDPH.js +16 -0
- package/dist/bundle/chunks/openai-codex-responses-5S3T3HMA.js +10 -0
- package/dist/bundle/chunks/openai-codex.js +75 -0
- package/dist/bundle/chunks/openai-completions-CXRRTRWE.js +7 -0
- package/dist/bundle/chunks/openai-responses-CV3MH6VP.js +2 -0
- package/dist/bundle/chunks/openrouter-images-6XDE2CEW.js +2 -0
- package/dist/bundle/chunks/openrouter.js +75 -0
- package/dist/bundle/chunks/pi-messages-PE6B42TG.js +8 -0
- package/dist/bundle/chunks/radius.js +75 -0
- package/dist/bundle/chunks/src-UK77SYZE.js +4 -0
- package/dist/bundle/chunks/xai.js +2 -0
- package/dist/bundle/cli.js +3 -0
- package/dist/bundle/index.js +2 -0
- package/dist/bundle/rpc-entry.js +3 -0
- package/dist/cli.js +5 -2469
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +2 -6
- 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/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +0 -1
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +0 -6
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +0 -11
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- 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.d.ts +3 -9
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +3 -8
- 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/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.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 +10 -2469
- 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/development.md +1 -1
- package/docs/docs.json +2 -2
- package/docs/extensions.md +0 -13
- package/docs/keybindings.md +3 -0
- package/docs/settings.md +11 -7
- package/npm-shrinkwrap.json +4 -4
- package/package.json +6 -5
- 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/dist/image-resize-worker.js +0 -2
- package/docs/bundled/extensions/router.md +0 -197
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
/** Extension-owned dialog host that keeps every /router TUI page in one modal lifecycle. */
|
|
2
|
-
import { Container, isFocusable, Spacer, Text } from "@earendil-works/pi-tui";
|
|
3
|
-
import { DynamicBorder } from "../../modes/interactive/components/dynamic-border.js";
|
|
4
|
-
import { ExtensionInputComponent } from "../../modes/interactive/components/extension-input.js";
|
|
5
|
-
import { ExtensionSelectorComponent } from "../../modes/interactive/components/extension-selector.js";
|
|
6
|
-
import { keyLabel } from "../../modes/interactive/components/keybinding-hints.js";
|
|
7
|
-
export class RouterTuiSessionClosedError extends Error {
|
|
8
|
-
constructor() {
|
|
9
|
-
super("Router TUI session is closed.");
|
|
10
|
-
this.name = "RouterTuiSessionClosedError";
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
export function createNativeRouterDialogs(ctx) {
|
|
14
|
-
return {
|
|
15
|
-
kind: "native",
|
|
16
|
-
select: (title, options) => ctx.ui.select(title, options),
|
|
17
|
-
input: (title, placeholder) => ctx.ui.input(title, placeholder),
|
|
18
|
-
confirm: (title, message) => ctx.ui.confirm(title, message),
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Persistent root mounted by one ctx.ui.custom() call. Child dialogs resolve
|
|
23
|
-
* without closing this root, so async flow continuations can replace them
|
|
24
|
-
* without exposing the main editor between pages.
|
|
25
|
-
*/
|
|
26
|
-
export class RouterTuiSession extends Container {
|
|
27
|
-
constructor(tui, theme, keybindings, onTransitionClose) {
|
|
28
|
-
super();
|
|
29
|
-
this.kind = "tui";
|
|
30
|
-
this.acceptsInput = false;
|
|
31
|
-
this.closeRequested = false;
|
|
32
|
-
this.disposed = false;
|
|
33
|
-
this._focused = false;
|
|
34
|
-
this.tui = tui;
|
|
35
|
-
this.theme = theme;
|
|
36
|
-
this.keybindings = keybindings;
|
|
37
|
-
this.onTransitionClose = onTransitionClose;
|
|
38
|
-
const loading = new Container();
|
|
39
|
-
loading.addChild(new DynamicBorder((text) => theme.fg("border", text)));
|
|
40
|
-
loading.addChild(new Spacer(1));
|
|
41
|
-
loading.addChild(new Text(theme.fg("muted", "Loading router…"), 1, 0));
|
|
42
|
-
loading.addChild(new Spacer(1));
|
|
43
|
-
loading.addChild(new DynamicBorder((text) => theme.fg("border", text)));
|
|
44
|
-
this.activeScreen = loading;
|
|
45
|
-
this.addChild(loading);
|
|
46
|
-
}
|
|
47
|
-
get focused() {
|
|
48
|
-
return this._focused;
|
|
49
|
-
}
|
|
50
|
-
set focused(value) {
|
|
51
|
-
this._focused = value;
|
|
52
|
-
if (this.activeScreen && isFocusable(this.activeScreen)) {
|
|
53
|
-
this.activeScreen.focused = value && this.acceptsInput;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
show(factory) {
|
|
57
|
-
this.clearTransitionTimer();
|
|
58
|
-
if (this.disposed || this.closeRequested)
|
|
59
|
-
return Promise.reject(new RouterTuiSessionClosedError());
|
|
60
|
-
if (this.pendingReject)
|
|
61
|
-
return Promise.reject(new Error("Router TUI session already has an active dialog."));
|
|
62
|
-
return new Promise((resolve, reject) => {
|
|
63
|
-
let settled = false;
|
|
64
|
-
const fail = (error) => {
|
|
65
|
-
if (settled || this.disposed)
|
|
66
|
-
return;
|
|
67
|
-
settled = true;
|
|
68
|
-
this.acceptsInput = false;
|
|
69
|
-
if (this.pendingReject === reject)
|
|
70
|
-
this.pendingReject = undefined;
|
|
71
|
-
reject(error instanceof Error ? error : new Error(String(error)));
|
|
72
|
-
};
|
|
73
|
-
const done = (result) => {
|
|
74
|
-
if (settled || this.disposed)
|
|
75
|
-
return;
|
|
76
|
-
settled = true;
|
|
77
|
-
this.acceptsInput = false;
|
|
78
|
-
if (this.activeScreen && isFocusable(this.activeScreen))
|
|
79
|
-
this.activeScreen.focused = false;
|
|
80
|
-
if (this.pendingReject === reject)
|
|
81
|
-
this.pendingReject = undefined;
|
|
82
|
-
this.tui.setFocus(this);
|
|
83
|
-
this.beginTransition();
|
|
84
|
-
resolve(result);
|
|
85
|
-
};
|
|
86
|
-
this.pendingReject = reject;
|
|
87
|
-
let pending;
|
|
88
|
-
try {
|
|
89
|
-
pending = factory(this.tui, this.theme, this.keybindings, done);
|
|
90
|
-
}
|
|
91
|
-
catch (error) {
|
|
92
|
-
fail(error);
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
void Promise.resolve(pending).then((component) => {
|
|
96
|
-
if (settled || this.disposed) {
|
|
97
|
-
this.disposeScreen(component);
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
try {
|
|
101
|
-
this.setActiveScreen(component);
|
|
102
|
-
}
|
|
103
|
-
catch (error) {
|
|
104
|
-
this.disposeScreen(component);
|
|
105
|
-
fail(error);
|
|
106
|
-
}
|
|
107
|
-
}, fail);
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
input(title, placeholder) {
|
|
111
|
-
return this.show((tui, _theme, _keybindings, done) => new ExtensionInputComponent(title, placeholder, done, () => done(undefined), { tui }));
|
|
112
|
-
}
|
|
113
|
-
async confirm(title, message) {
|
|
114
|
-
const selected = await this.show((tui, _theme, _keybindings, done) => new ExtensionSelectorComponent(title, ["Yes", "No"], done, () => done(undefined), {
|
|
115
|
-
tui,
|
|
116
|
-
subtitle: message,
|
|
117
|
-
}));
|
|
118
|
-
return selected === "Yes";
|
|
119
|
-
}
|
|
120
|
-
handleInput(data) {
|
|
121
|
-
if (this.acceptsInput) {
|
|
122
|
-
this.activeScreen?.handleInput?.(data);
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
if (this.closeRequested || !this.keybindings.matches(data, "tui.select.cancel"))
|
|
126
|
-
return;
|
|
127
|
-
this.closeRequested = true;
|
|
128
|
-
this.onTransitionClose();
|
|
129
|
-
}
|
|
130
|
-
dispose() {
|
|
131
|
-
if (this.disposed)
|
|
132
|
-
return;
|
|
133
|
-
this.disposed = true;
|
|
134
|
-
this.acceptsInput = false;
|
|
135
|
-
this.clearTransitionTimer();
|
|
136
|
-
const reject = this.pendingReject;
|
|
137
|
-
this.pendingReject = undefined;
|
|
138
|
-
this.disposeActiveScreen();
|
|
139
|
-
this.clear();
|
|
140
|
-
reject?.(new RouterTuiSessionClosedError());
|
|
141
|
-
}
|
|
142
|
-
beginTransition() {
|
|
143
|
-
this.clearTransitionTimer();
|
|
144
|
-
this.transitionTimer = setTimeout(() => {
|
|
145
|
-
this.transitionTimer = undefined;
|
|
146
|
-
if (this.disposed || this.closeRequested || this.acceptsInput)
|
|
147
|
-
return;
|
|
148
|
-
const working = new Container();
|
|
149
|
-
working.addChild(new DynamicBorder((text) => this.theme.fg("border", text)));
|
|
150
|
-
working.addChild(new Spacer(1));
|
|
151
|
-
const cancelKey = keyLabel("tui.select.cancel", { keybindings: this.keybindings });
|
|
152
|
-
const closeHint = cancelKey ? `${cancelKey} closes /router` : "Close /router to continue";
|
|
153
|
-
working.addChild(new Text(this.theme.fg("muted", `Working… ${closeHint}`), 1, 0));
|
|
154
|
-
working.addChild(new Spacer(1));
|
|
155
|
-
working.addChild(new DynamicBorder((text) => this.theme.fg("border", text)));
|
|
156
|
-
this.disposeActiveScreen();
|
|
157
|
-
this.clear();
|
|
158
|
-
this.activeScreen = working;
|
|
159
|
-
this.addChild(working);
|
|
160
|
-
this.tui.requestRender();
|
|
161
|
-
}, 150);
|
|
162
|
-
}
|
|
163
|
-
clearTransitionTimer() {
|
|
164
|
-
if (this.transitionTimer === undefined)
|
|
165
|
-
return;
|
|
166
|
-
clearTimeout(this.transitionTimer);
|
|
167
|
-
this.transitionTimer = undefined;
|
|
168
|
-
}
|
|
169
|
-
setActiveScreen(component) {
|
|
170
|
-
this.disposeActiveScreen();
|
|
171
|
-
this.clear();
|
|
172
|
-
this.activeScreen = component;
|
|
173
|
-
this.addChild(component);
|
|
174
|
-
this.acceptsInput = true;
|
|
175
|
-
this.tui.setFocus(component);
|
|
176
|
-
this.tui.requestRender();
|
|
177
|
-
}
|
|
178
|
-
disposeActiveScreen() {
|
|
179
|
-
const screen = this.activeScreen;
|
|
180
|
-
this.activeScreen = undefined;
|
|
181
|
-
if (screen)
|
|
182
|
-
this.disposeScreen(screen);
|
|
183
|
-
}
|
|
184
|
-
disposeScreen(screen) {
|
|
185
|
-
const dispose = screen.dispose;
|
|
186
|
-
if (isFocusable(screen))
|
|
187
|
-
screen.focused = false;
|
|
188
|
-
try {
|
|
189
|
-
dispose?.call(screen);
|
|
190
|
-
}
|
|
191
|
-
catch {
|
|
192
|
-
// A child cleanup failure must not strand the outer custom lifecycle.
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
//# sourceMappingURL=dialog-host.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dialog-host.js","sourceRoot":"","sources":["../../../src/extensions/router/dialog-host.ts"],"names":[],"mappings":"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","sourcesContent":["/** Extension-owned dialog host that keeps every /router TUI page in one modal lifecycle. */\n\nimport { type Component, Container, type Focusable, isFocusable, Spacer, Text, type TUI } from \"@earendil-works/pi-tui\";\nimport type { ExtensionCommandContext } from \"../../core/extensions/types.ts\";\nimport type { KeybindingsManager } from \"../../core/keybindings.ts\";\nimport { DynamicBorder } from \"../../modes/interactive/components/dynamic-border.ts\";\nimport { ExtensionInputComponent } from \"../../modes/interactive/components/extension-input.ts\";\nimport { ExtensionSelectorComponent } from \"../../modes/interactive/components/extension-selector.ts\";\nimport { keyLabel } from \"../../modes/interactive/components/keybinding-hints.ts\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\n\nexport type RouterComponent = Component & { dispose?(): void };\n\nexport type RouterComponentFactory<T> = (\n\ttui: TUI,\n\ttheme: Theme,\n\tkeybindings: KeybindingsManager,\n\tdone: (result: T) => void,\n) => RouterComponent | Promise<RouterComponent>;\n\ninterface RouterDialogBase {\n\tinput(title: string, placeholder?: string): Promise<string | undefined>;\n\tconfirm(title: string, message: string): Promise<boolean>;\n}\n\nexport interface RouterNativeDialogs extends RouterDialogBase {\n\treadonly kind: \"native\";\n\tselect(title: string, options: string[]): Promise<string | undefined>;\n}\n\nexport interface RouterTuiDialogs extends RouterDialogBase {\n\treadonly kind: \"tui\";\n\tshow<T>(factory: RouterComponentFactory<T>): Promise<T>;\n}\n\nexport type RouterDialogs = RouterNativeDialogs | RouterTuiDialogs;\n\nexport class RouterTuiSessionClosedError extends Error {\n\tconstructor() {\n\t\tsuper(\"Router TUI session is closed.\");\n\t\tthis.name = \"RouterTuiSessionClosedError\";\n\t}\n}\n\nexport function createNativeRouterDialogs(ctx: ExtensionCommandContext): RouterNativeDialogs {\n\treturn {\n\t\tkind: \"native\",\n\t\tselect: (title, options) => ctx.ui.select(title, options),\n\t\tinput: (title, placeholder) => ctx.ui.input(title, placeholder),\n\t\tconfirm: (title, message) => ctx.ui.confirm(title, message),\n\t};\n}\n\n/**\n * Persistent root mounted by one ctx.ui.custom() call. Child dialogs resolve\n * without closing this root, so async flow continuations can replace them\n * without exposing the main editor between pages.\n */\nexport class RouterTuiSession extends Container implements Focusable, RouterTuiDialogs {\n\treadonly kind = \"tui\" as const;\n\n\tprivate readonly tui: TUI;\n\tprivate readonly theme: Theme;\n\tprivate readonly keybindings: KeybindingsManager;\n\tprivate readonly onTransitionClose: () => void;\n\tprivate activeScreen: RouterComponent | undefined;\n\tprivate pendingReject: ((error: Error) => void) | undefined;\n\tprivate transitionTimer: ReturnType<typeof setTimeout> | undefined;\n\tprivate acceptsInput = false;\n\tprivate closeRequested = false;\n\tprivate disposed = false;\n\tprivate _focused = false;\n\n\tconstructor(tui: TUI, theme: Theme, keybindings: KeybindingsManager, onTransitionClose: () => void) {\n\t\tsuper();\n\t\tthis.tui = tui;\n\t\tthis.theme = theme;\n\t\tthis.keybindings = keybindings;\n\t\tthis.onTransitionClose = onTransitionClose;\n\n\t\tconst loading = new Container();\n\t\tloading.addChild(new DynamicBorder((text) => theme.fg(\"border\", text)));\n\t\tloading.addChild(new Spacer(1));\n\t\tloading.addChild(new Text(theme.fg(\"muted\", \"Loading router…\"), 1, 0));\n\t\tloading.addChild(new Spacer(1));\n\t\tloading.addChild(new DynamicBorder((text) => theme.fg(\"border\", text)));\n\t\tthis.activeScreen = loading;\n\t\tthis.addChild(loading);\n\t}\n\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t\tif (this.activeScreen && isFocusable(this.activeScreen)) {\n\t\t\tthis.activeScreen.focused = value && this.acceptsInput;\n\t\t}\n\t}\n\n\tshow<T>(factory: RouterComponentFactory<T>): Promise<T> {\n\t\tthis.clearTransitionTimer();\n\t\tif (this.disposed || this.closeRequested) return Promise.reject(new RouterTuiSessionClosedError());\n\t\tif (this.pendingReject) return Promise.reject(new Error(\"Router TUI session already has an active dialog.\"));\n\t\treturn new Promise<T>((resolve, reject) => {\n\t\t\tlet settled = false;\n\t\t\tconst fail = (error: unknown) => {\n\t\t\t\tif (settled || this.disposed) return;\n\t\t\t\tsettled = true;\n\t\t\t\tthis.acceptsInput = false;\n\t\t\t\tif (this.pendingReject === reject) this.pendingReject = undefined;\n\t\t\t\treject(error instanceof Error ? error : new Error(String(error)));\n\t\t\t};\n\t\t\tconst done = (result: T) => {\n\t\t\t\tif (settled || this.disposed) return;\n\t\t\t\tsettled = true;\n\t\t\t\tthis.acceptsInput = false;\n\t\t\t\tif (this.activeScreen && isFocusable(this.activeScreen)) this.activeScreen.focused = false;\n\t\t\t\tif (this.pendingReject === reject) this.pendingReject = undefined;\n\t\t\t\tthis.tui.setFocus(this);\n\t\t\t\tthis.beginTransition();\n\t\t\t\tresolve(result);\n\t\t\t};\n\t\t\tthis.pendingReject = reject;\n\t\t\tlet pending: RouterComponent | Promise<RouterComponent>;\n\t\t\ttry {\n\t\t\t\tpending = factory(this.tui, this.theme, this.keybindings, done);\n\t\t\t} catch (error) {\n\t\t\t\tfail(error);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvoid Promise.resolve(pending).then((component) => {\n\t\t\t\tif (settled || this.disposed) {\n\t\t\t\t\tthis.disposeScreen(component);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tthis.setActiveScreen(component);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.disposeScreen(component);\n\t\t\t\t\tfail(error);\n\t\t\t\t}\n\t\t\t}, fail);\n\t\t});\n\t}\n\n\tinput(title: string, placeholder?: string): Promise<string | undefined> {\n\t\treturn this.show<string | undefined>(\n\t\t\t(tui, _theme, _keybindings, done) =>\n\t\t\t\tnew ExtensionInputComponent(title, placeholder, done, () => done(undefined), { tui }),\n\t\t);\n\t}\n\n\tasync confirm(title: string, message: string): Promise<boolean> {\n\t\tconst selected = await this.show<string | undefined>(\n\t\t\t(tui, _theme, _keybindings, done) =>\n\t\t\t\tnew ExtensionSelectorComponent(title, [\"Yes\", \"No\"], done, () => done(undefined), {\n\t\t\t\t\ttui,\n\t\t\t\t\tsubtitle: message,\n\t\t\t\t}),\n\t\t);\n\t\treturn selected === \"Yes\";\n\t}\n\n\thandleInput(data: string): void {\n\t\tif (this.acceptsInput) {\n\t\t\tthis.activeScreen?.handleInput?.(data);\n\t\t\treturn;\n\t\t}\n\t\tif (this.closeRequested || !this.keybindings.matches(data, \"tui.select.cancel\")) return;\n\t\tthis.closeRequested = true;\n\t\tthis.onTransitionClose();\n\t}\n\n\tdispose(): void {\n\t\tif (this.disposed) return;\n\t\tthis.disposed = true;\n\t\tthis.acceptsInput = false;\n\t\tthis.clearTransitionTimer();\n\t\tconst reject = this.pendingReject;\n\t\tthis.pendingReject = undefined;\n\t\tthis.disposeActiveScreen();\n\t\tthis.clear();\n\t\treject?.(new RouterTuiSessionClosedError());\n\t}\n\n\tprivate beginTransition(): void {\n\t\tthis.clearTransitionTimer();\n\t\tthis.transitionTimer = setTimeout(() => {\n\t\t\tthis.transitionTimer = undefined;\n\t\t\tif (this.disposed || this.closeRequested || this.acceptsInput) return;\n\t\t\tconst working = new Container();\n\t\t\tworking.addChild(new DynamicBorder((text) => this.theme.fg(\"border\", text)));\n\t\t\tworking.addChild(new Spacer(1));\n\t\t\tconst cancelKey = keyLabel(\"tui.select.cancel\", { keybindings: this.keybindings });\n\t\t\tconst closeHint = cancelKey ? `${cancelKey} closes /router` : \"Close /router to continue\";\n\t\t\tworking.addChild(new Text(this.theme.fg(\"muted\", `Working… ${closeHint}`), 1, 0));\n\t\t\tworking.addChild(new Spacer(1));\n\t\t\tworking.addChild(new DynamicBorder((text) => this.theme.fg(\"border\", text)));\n\t\t\tthis.disposeActiveScreen();\n\t\t\tthis.clear();\n\t\t\tthis.activeScreen = working;\n\t\t\tthis.addChild(working);\n\t\t\tthis.tui.requestRender();\n\t\t}, 150);\n\t}\n\n\tprivate clearTransitionTimer(): void {\n\t\tif (this.transitionTimer === undefined) return;\n\t\tclearTimeout(this.transitionTimer);\n\t\tthis.transitionTimer = undefined;\n\t}\n\n\tprivate setActiveScreen(component: RouterComponent): void {\n\t\tthis.disposeActiveScreen();\n\t\tthis.clear();\n\t\tthis.activeScreen = component;\n\t\tthis.addChild(component);\n\t\tthis.acceptsInput = true;\n\t\tthis.tui.setFocus(component);\n\t\tthis.tui.requestRender();\n\t}\n\n\tprivate disposeActiveScreen(): void {\n\t\tconst screen = this.activeScreen;\n\t\tthis.activeScreen = undefined;\n\t\tif (screen) this.disposeScreen(screen);\n\t}\n\n\tprivate disposeScreen(screen: RouterComponent): void {\n\t\tconst dispose = screen.dispose;\n\t\tif (isFocusable(screen)) screen.focused = false;\n\t\ttry {\n\t\t\tdispose?.call(screen);\n\t\t} catch {\n\t\t\t// A child cleanup failure must not strand the outer custom lifecycle.\n\t\t}\n\t}\n}\n"]}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
/** Private TUI primitives for /router. */
|
|
2
|
-
import { Container, type KeybindingsManager, type TUI } from "@earendil-works/pi-tui";
|
|
3
|
-
import type { Theme } from "../../modes/interactive/theme/theme.ts";
|
|
4
|
-
import { type ThinkingLevel } from "./constants.ts";
|
|
5
|
-
import type { ThinkingLevelMap } from "./types.ts";
|
|
6
|
-
export interface SelectItem<T extends string = string> {
|
|
7
|
-
value: T;
|
|
8
|
-
label: string;
|
|
9
|
-
description?: string;
|
|
10
|
-
searchText?: string;
|
|
11
|
-
}
|
|
12
|
-
export declare function createSearchableSelector<T extends string>(opts: {
|
|
13
|
-
title: string;
|
|
14
|
-
subtitle?: string;
|
|
15
|
-
items: ReadonlyArray<SelectItem<T>>;
|
|
16
|
-
initialValue?: T;
|
|
17
|
-
initialQuery?: string;
|
|
18
|
-
maxVisible?: number;
|
|
19
|
-
emptyMessage?: string;
|
|
20
|
-
}): (tui: TUI, theme: Theme, keybindings: KeybindingsManager, done: (result: T | undefined) => void) => Container;
|
|
21
|
-
export interface ModelChecklistItem {
|
|
22
|
-
id: string;
|
|
23
|
-
name?: string;
|
|
24
|
-
unavailable?: boolean;
|
|
25
|
-
}
|
|
26
|
-
export declare function createModelChecklist(opts: {
|
|
27
|
-
title: string;
|
|
28
|
-
subtitle?: string;
|
|
29
|
-
models: ReadonlyArray<ModelChecklistItem>;
|
|
30
|
-
initiallySelected?: ReadonlySet<string>;
|
|
31
|
-
/** Models that must remain selected while the checklist is open. */
|
|
32
|
-
protectedIds?: ReadonlySet<string>;
|
|
33
|
-
onChange?: (selectedIds: string[]) => void;
|
|
34
|
-
onProtectedToggle?: (id: string) => void;
|
|
35
|
-
}): (tui: TUI, theme: Theme, keybindings: KeybindingsManager, done: (result: {
|
|
36
|
-
kind: "close";
|
|
37
|
-
selectedIds: string[];
|
|
38
|
-
}) => void) => Container;
|
|
39
|
-
export declare function createThinkingMapEditor(opts: {
|
|
40
|
-
title: string;
|
|
41
|
-
map: ThinkingLevelMap;
|
|
42
|
-
levels?: ReadonlyArray<ThinkingLevel>;
|
|
43
|
-
onChange?: (map: ThinkingLevelMap) => void;
|
|
44
|
-
}): (tui: TUI, theme: Theme, keybindings: KeybindingsManager, done: (result: ThinkingLevelMap | undefined) => void) => Container;
|
|
45
|
-
//# sourceMappingURL=dialog.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../../../src/extensions/router/dialog.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAE1C,OAAO,EACN,SAAS,EAGT,KAAK,kBAAkB,EAIvB,KAAK,GAAG,EACR,MAAM,wBAAwB,CAAC;AAGhC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wCAAwC,CAAC;AACpE,OAAO,EAA0B,KAAK,aAAa,EAAY,MAAM,gBAAgB,CAAC;AAEtF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,MAAM,WAAW,UAAU,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IACpD,KAAK,EAAE,CAAC,CAAC;IACT,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,wBAAwB,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,EAAE;IAChE,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IACpC,YAAY,CAAC,EAAE,CAAC,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC,GAAG,SAAS,KAAK,IAAI,KAAK,SAAS,CAsHhH;AAED,MAAM,WAAW,kBAAkB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,aAAa,CAAC,kBAAkB,CAAC,CAAC;IAC1C,iBAAiB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACxC,oEAAoE;IACpE,YAAY,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACnC,QAAQ,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAC3C,iBAAiB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC,GAAG,CACH,GAAG,EAAE,GAAG,EACR,KAAK,EAAE,KAAK,EACZ,WAAW,EAAE,kBAAkB,EAC/B,IAAI,EAAE,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,WAAW,EAAE,MAAM,EAAE,CAAA;CAAE,KAAK,IAAI,KAC5D,SAAS,CA8Jb;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,gBAAgB,CAAC;IACtB,MAAM,CAAC,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;IACtC,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,IAAI,CAAC;CAC3C,GAAG,CACH,GAAG,EAAE,GAAG,EACR,KAAK,EAAE,KAAK,EACZ,WAAW,EAAE,kBAAkB,EAC/B,IAAI,EAAE,CAAC,MAAM,EAAE,gBAAgB,GAAG,SAAS,KAAK,IAAI,KAChD,SAAS,CAiHb"}
|
|
@@ -1,378 +0,0 @@
|
|
|
1
|
-
/** Private TUI primitives for /router. */
|
|
2
|
-
import { Container, fuzzyFilter, Input, Spacer, Text, TruncatedText, } from "@earendil-works/pi-tui";
|
|
3
|
-
import { DynamicBorder } from "../../modes/interactive/components/dynamic-border.js";
|
|
4
|
-
import { keyHint, rawKeyHint } from "../../modes/interactive/components/keybinding-hints.js";
|
|
5
|
-
import { ROUTER_THINKING_LEVELS, truncate } from "./constants.js";
|
|
6
|
-
import { resolveRouterThinkingMap } from "./presets.js";
|
|
7
|
-
export function createSearchableSelector(opts) {
|
|
8
|
-
return (tui, theme, keybindings, done) => {
|
|
9
|
-
const allItems = [...opts.items];
|
|
10
|
-
let filteredItems = allItems;
|
|
11
|
-
let selectedIndex = Math.max(0, allItems.findIndex((item) => item.value === opts.initialValue));
|
|
12
|
-
const maxVisible = Math.max(1, opts.maxVisible ?? 10);
|
|
13
|
-
const input = new Input();
|
|
14
|
-
if (opts.initialQuery)
|
|
15
|
-
input.setValue(opts.initialQuery);
|
|
16
|
-
const list = new Container();
|
|
17
|
-
const footer = new Text("", 1, 0);
|
|
18
|
-
const container = new Container();
|
|
19
|
-
const refresh = () => {
|
|
20
|
-
list.clear();
|
|
21
|
-
const start = Math.max(0, Math.min(selectedIndex - Math.floor(maxVisible / 2), Math.max(0, filteredItems.length - maxVisible)));
|
|
22
|
-
const end = Math.min(start + maxVisible, filteredItems.length);
|
|
23
|
-
for (let index = start; index < end; index++) {
|
|
24
|
-
const item = filteredItems[index];
|
|
25
|
-
if (!item)
|
|
26
|
-
continue;
|
|
27
|
-
const active = index === selectedIndex;
|
|
28
|
-
const prefix = active ? theme.fg("accent", "→ ") : " ";
|
|
29
|
-
const label = theme.fg(active ? "accent" : "text", item.label);
|
|
30
|
-
const description = item.description ? theme.fg("muted", ` ${truncate(item.description, 48)}`) : "";
|
|
31
|
-
list.addChild(new TruncatedText(prefix + label + description, 1, 0));
|
|
32
|
-
}
|
|
33
|
-
if (filteredItems.length === 0) {
|
|
34
|
-
list.addChild(new Text(theme.fg("muted", ` ${opts.emptyMessage ?? "No matching items"}`), 1, 0));
|
|
35
|
-
}
|
|
36
|
-
else if (start > 0 || end < filteredItems.length) {
|
|
37
|
-
list.addChild(new Text(theme.fg("muted", ` (${selectedIndex + 1}/${filteredItems.length})`), 1, 0));
|
|
38
|
-
}
|
|
39
|
-
const hints = [
|
|
40
|
-
rawKeyHint("type", "filter"),
|
|
41
|
-
rawKeyHint("↑↓", "navigate"),
|
|
42
|
-
keyHint("tui.select.confirm", "select"),
|
|
43
|
-
keyHint("tui.select.cancel", "back"),
|
|
44
|
-
];
|
|
45
|
-
footer.setText(hints.join(" "));
|
|
46
|
-
container.invalidate();
|
|
47
|
-
tui.requestRender();
|
|
48
|
-
};
|
|
49
|
-
const applyFilter = (query, preferred) => {
|
|
50
|
-
filteredItems = query
|
|
51
|
-
? fuzzyFilter(allItems, query, (item) => item.searchText ?? `${item.label} ${item.description ?? ""} ${item.value}`)
|
|
52
|
-
: allItems;
|
|
53
|
-
const preferredIndex = preferred ? filteredItems.findIndex((item) => item.value === preferred) : -1;
|
|
54
|
-
selectedIndex = preferredIndex >= 0 ? preferredIndex : 0;
|
|
55
|
-
refresh();
|
|
56
|
-
};
|
|
57
|
-
container.addChild(new DynamicBorder((text) => theme.fg("border", text)));
|
|
58
|
-
container.addChild(new Spacer(1));
|
|
59
|
-
container.addChild(new TruncatedText(theme.fg("accent", theme.bold(opts.title)), 1, 0));
|
|
60
|
-
if (opts.subtitle)
|
|
61
|
-
container.addChild(new TruncatedText(theme.fg("muted", opts.subtitle), 1, 0));
|
|
62
|
-
container.addChild(new Spacer(1));
|
|
63
|
-
// Keep the search row mounted even when empty, matching /model and
|
|
64
|
-
// preventing the list from jumping when the first character is typed.
|
|
65
|
-
container.addChild(input);
|
|
66
|
-
container.addChild(new Spacer(1));
|
|
67
|
-
container.addChild(list);
|
|
68
|
-
container.addChild(new Spacer(1));
|
|
69
|
-
container.addChild(footer);
|
|
70
|
-
container.addChild(new Spacer(1));
|
|
71
|
-
container.addChild(new DynamicBorder((text) => theme.fg("border", text)));
|
|
72
|
-
Object.defineProperty(container, "focused", {
|
|
73
|
-
get: () => input.focused,
|
|
74
|
-
set: (focused) => {
|
|
75
|
-
input.focused = focused;
|
|
76
|
-
},
|
|
77
|
-
});
|
|
78
|
-
container.handleInput = (data) => {
|
|
79
|
-
if (keybindings.matches(data, "tui.select.up")) {
|
|
80
|
-
if (filteredItems.length > 0) {
|
|
81
|
-
selectedIndex = selectedIndex === 0 ? filteredItems.length - 1 : selectedIndex - 1;
|
|
82
|
-
refresh();
|
|
83
|
-
}
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
if (keybindings.matches(data, "tui.select.down")) {
|
|
87
|
-
if (filteredItems.length > 0) {
|
|
88
|
-
selectedIndex = selectedIndex === filteredItems.length - 1 ? 0 : selectedIndex + 1;
|
|
89
|
-
refresh();
|
|
90
|
-
}
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
if (keybindings.matches(data, "tui.select.confirm")) {
|
|
94
|
-
const item = filteredItems[selectedIndex];
|
|
95
|
-
if (item)
|
|
96
|
-
done(item.value);
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
if (keybindings.matches(data, "tui.select.cancel")) {
|
|
100
|
-
done(undefined);
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
const before = input.getValue();
|
|
104
|
-
input.handleInput(data);
|
|
105
|
-
const after = input.getValue();
|
|
106
|
-
if (after !== before)
|
|
107
|
-
applyFilter(after);
|
|
108
|
-
};
|
|
109
|
-
applyFilter(opts.initialQuery ?? "", opts.initialValue);
|
|
110
|
-
return container;
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
export function createModelChecklist(opts) {
|
|
114
|
-
return (tui, theme, keybindings, done) => {
|
|
115
|
-
const items = opts.models.map((model) => ({
|
|
116
|
-
id: model.id,
|
|
117
|
-
label: model.name && model.name !== model.id ? `${model.id} · ${model.name}` : model.id,
|
|
118
|
-
unavailable: model.unavailable ?? false,
|
|
119
|
-
protected: opts.protectedIds?.has(model.id) ?? false,
|
|
120
|
-
searchText: `${model.id} ${model.name ?? ""} ${model.unavailable ? "not returned unavailable" : ""}`,
|
|
121
|
-
}));
|
|
122
|
-
const selected = new Set(opts.initiallySelected ?? []);
|
|
123
|
-
let filter = "";
|
|
124
|
-
let selectedIndex = 0;
|
|
125
|
-
const maxVisible = 10;
|
|
126
|
-
const input = new Input();
|
|
127
|
-
const list = new Container();
|
|
128
|
-
const footer = new Text("", 1, 0);
|
|
129
|
-
const container = new Container();
|
|
130
|
-
const filtered = () => {
|
|
131
|
-
const query = filter.trim();
|
|
132
|
-
return query ? fuzzyFilter(items, query, (item) => item.searchText) : items;
|
|
133
|
-
};
|
|
134
|
-
const notifyChange = () => opts.onChange?.([...selected]);
|
|
135
|
-
const selectionChanged = (before) => before.size !== selected.size || [...before].some((id) => !selected.has(id));
|
|
136
|
-
const refresh = () => {
|
|
137
|
-
const rows = filtered();
|
|
138
|
-
if (selectedIndex >= rows.length)
|
|
139
|
-
selectedIndex = Math.max(0, rows.length - 1);
|
|
140
|
-
list.clear();
|
|
141
|
-
const start = Math.max(0, Math.min(selectedIndex - Math.floor(maxVisible / 2), Math.max(0, rows.length - maxVisible)));
|
|
142
|
-
const end = Math.min(start + maxVisible, rows.length);
|
|
143
|
-
for (let index = start; index < end; index++) {
|
|
144
|
-
const item = rows[index];
|
|
145
|
-
const active = index === selectedIndex;
|
|
146
|
-
const mark = selected.has(item.id) ? theme.fg("success", "[x]") : theme.fg("muted", "[ ]");
|
|
147
|
-
const prefix = active ? theme.fg("accent", "→ ") : " ";
|
|
148
|
-
const label = theme.fg(active ? "accent" : "text", item.label);
|
|
149
|
-
const availability = item.unavailable ? theme.fg("warning", " (not returned)") : "";
|
|
150
|
-
const current = item.protected ? theme.fg("success", " (current)") : "";
|
|
151
|
-
list.addChild(new TruncatedText(`${prefix}${mark} ${label}${availability}${current}`, 1, 0));
|
|
152
|
-
}
|
|
153
|
-
if (rows.length === 0) {
|
|
154
|
-
list.addChild(new Text(theme.fg("muted", " No matching models"), 1, 0));
|
|
155
|
-
}
|
|
156
|
-
else if (start > 0 || end < rows.length) {
|
|
157
|
-
list.addChild(new Text(theme.fg("muted", ` (${selectedIndex + 1}/${rows.length})`), 1, 0));
|
|
158
|
-
}
|
|
159
|
-
const statusLine = theme.fg("muted", `${selected.size} selected · ${rows.length} shown`);
|
|
160
|
-
const hints = [
|
|
161
|
-
keyHint("app.list.toggle", "toggle"),
|
|
162
|
-
keyHint("app.models.enableAll", "all"),
|
|
163
|
-
keyHint("app.models.clearAll", "none"),
|
|
164
|
-
rawKeyHint("type", "filter"),
|
|
165
|
-
keyHint("tui.select.confirm", "done"),
|
|
166
|
-
keyHint("tui.select.cancel", "back"),
|
|
167
|
-
];
|
|
168
|
-
footer.setText(`${statusLine}\n${hints.join(" ")}`);
|
|
169
|
-
container.invalidate();
|
|
170
|
-
tui.requestRender();
|
|
171
|
-
};
|
|
172
|
-
container.addChild(new DynamicBorder((text) => theme.fg("border", text)));
|
|
173
|
-
container.addChild(new Spacer(1));
|
|
174
|
-
container.addChild(new TruncatedText(theme.fg("accent", theme.bold(opts.title)), 1, 0));
|
|
175
|
-
if (opts.subtitle)
|
|
176
|
-
container.addChild(new TruncatedText(theme.fg("muted", opts.subtitle), 1, 0));
|
|
177
|
-
container.addChild(new Spacer(1));
|
|
178
|
-
container.addChild(input);
|
|
179
|
-
container.addChild(new Spacer(1));
|
|
180
|
-
container.addChild(list);
|
|
181
|
-
container.addChild(new Spacer(1));
|
|
182
|
-
container.addChild(footer);
|
|
183
|
-
container.addChild(new Spacer(1));
|
|
184
|
-
container.addChild(new DynamicBorder((text) => theme.fg("border", text)));
|
|
185
|
-
Object.defineProperty(container, "focused", {
|
|
186
|
-
get: () => input.focused,
|
|
187
|
-
set: (focused) => {
|
|
188
|
-
input.focused = focused;
|
|
189
|
-
},
|
|
190
|
-
});
|
|
191
|
-
container.handleInput = (data) => {
|
|
192
|
-
const rows = filtered();
|
|
193
|
-
if (keybindings.matches(data, "app.list.toggle")) {
|
|
194
|
-
const item = rows[selectedIndex];
|
|
195
|
-
if (item) {
|
|
196
|
-
if (item.protected) {
|
|
197
|
-
opts.onProtectedToggle?.(item.id);
|
|
198
|
-
return;
|
|
199
|
-
}
|
|
200
|
-
if (selected.has(item.id))
|
|
201
|
-
selected.delete(item.id);
|
|
202
|
-
else
|
|
203
|
-
selected.add(item.id);
|
|
204
|
-
notifyChange();
|
|
205
|
-
refresh();
|
|
206
|
-
}
|
|
207
|
-
return;
|
|
208
|
-
}
|
|
209
|
-
if (keybindings.matches(data, "app.models.enableAll")) {
|
|
210
|
-
const before = new Set(selected);
|
|
211
|
-
for (const item of rows)
|
|
212
|
-
selected.add(item.id);
|
|
213
|
-
if (selectionChanged(before))
|
|
214
|
-
notifyChange();
|
|
215
|
-
refresh();
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
if (keybindings.matches(data, "app.models.clearAll")) {
|
|
219
|
-
const before = new Set(selected);
|
|
220
|
-
let protectedId;
|
|
221
|
-
for (const item of rows) {
|
|
222
|
-
if (item.protected) {
|
|
223
|
-
protectedId ??= item.id;
|
|
224
|
-
continue;
|
|
225
|
-
}
|
|
226
|
-
selected.delete(item.id);
|
|
227
|
-
}
|
|
228
|
-
if (protectedId)
|
|
229
|
-
opts.onProtectedToggle?.(protectedId);
|
|
230
|
-
if (selectionChanged(before))
|
|
231
|
-
notifyChange();
|
|
232
|
-
refresh();
|
|
233
|
-
return;
|
|
234
|
-
}
|
|
235
|
-
if (keybindings.matches(data, "tui.select.up")) {
|
|
236
|
-
if (rows.length > 0) {
|
|
237
|
-
selectedIndex = selectedIndex === 0 ? rows.length - 1 : selectedIndex - 1;
|
|
238
|
-
refresh();
|
|
239
|
-
}
|
|
240
|
-
return;
|
|
241
|
-
}
|
|
242
|
-
if (keybindings.matches(data, "tui.select.down")) {
|
|
243
|
-
if (rows.length > 0) {
|
|
244
|
-
selectedIndex = selectedIndex === rows.length - 1 ? 0 : selectedIndex + 1;
|
|
245
|
-
refresh();
|
|
246
|
-
}
|
|
247
|
-
return;
|
|
248
|
-
}
|
|
249
|
-
if (keybindings.matches(data, "tui.select.confirm") || keybindings.matches(data, "tui.select.cancel")) {
|
|
250
|
-
done({ kind: "close", selectedIds: [...selected] });
|
|
251
|
-
return;
|
|
252
|
-
}
|
|
253
|
-
const before = input.getValue();
|
|
254
|
-
input.handleInput(data);
|
|
255
|
-
const after = input.getValue();
|
|
256
|
-
if (after !== before) {
|
|
257
|
-
filter = after;
|
|
258
|
-
selectedIndex = 0;
|
|
259
|
-
refresh();
|
|
260
|
-
}
|
|
261
|
-
};
|
|
262
|
-
refresh();
|
|
263
|
-
return container;
|
|
264
|
-
};
|
|
265
|
-
}
|
|
266
|
-
export function createThinkingMapEditor(opts) {
|
|
267
|
-
return (tui, theme, keybindings, done) => {
|
|
268
|
-
const levels = [...(opts.levels ?? ROUTER_THINKING_LEVELS)];
|
|
269
|
-
const working = resolveRouterThinkingMap(opts.map);
|
|
270
|
-
let index = 0;
|
|
271
|
-
let mode = "levels";
|
|
272
|
-
let choice = 0;
|
|
273
|
-
const input = new Input();
|
|
274
|
-
const container = new Container();
|
|
275
|
-
let focused = false;
|
|
276
|
-
const refresh = () => {
|
|
277
|
-
container.clear();
|
|
278
|
-
container.addChild(new DynamicBorder((text) => theme.fg("border", text)));
|
|
279
|
-
container.addChild(new Text(theme.fg("accent", opts.title), 1, 1));
|
|
280
|
-
if (mode === "levels") {
|
|
281
|
-
for (const [i, level] of levels.entries()) {
|
|
282
|
-
const value = working[level];
|
|
283
|
-
const status = value === undefined ? "Inherit" : value === null ? "Hidden" : `→ ${value}`;
|
|
284
|
-
container.addChild(new TruncatedText(theme.fg(i === index ? "accent" : "text", `${i === index ? "→" : " "} ${level} · ${status}`), 1, 0));
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
else if (mode === "choice") {
|
|
288
|
-
container.addChild(new Text(theme.fg("muted", `${levels[index]} · mapping`), 1, 0));
|
|
289
|
-
for (const [i, label] of [
|
|
290
|
-
"Inherit (Pi default)",
|
|
291
|
-
"String target (provider effort)",
|
|
292
|
-
"Hidden (null)",
|
|
293
|
-
].entries()) {
|
|
294
|
-
container.addChild(new Text(theme.fg(i === choice ? "accent" : "text", `${i === choice ? "→" : " "} ${label}`), 1, 0));
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
else {
|
|
298
|
-
container.addChild(new Text(theme.fg("muted", `${levels[index]} · non-empty provider effort`), 1, 0));
|
|
299
|
-
container.addChild(input);
|
|
300
|
-
}
|
|
301
|
-
input.focused = focused && mode === "target";
|
|
302
|
-
container.addChild(new Text(`${keyHint("tui.select.confirm", mode === "target" ? "save" : "edit")} ${keyHint("tui.select.cancel", "back")}`, 1, 1));
|
|
303
|
-
container.addChild(new DynamicBorder((text) => theme.fg("border", text)));
|
|
304
|
-
container.invalidate();
|
|
305
|
-
tui.requestRender();
|
|
306
|
-
};
|
|
307
|
-
const save = (value) => {
|
|
308
|
-
const level = levels[index];
|
|
309
|
-
if (value === undefined)
|
|
310
|
-
delete working[level];
|
|
311
|
-
else
|
|
312
|
-
working[level] = value;
|
|
313
|
-
opts.onChange?.({ ...working });
|
|
314
|
-
mode = "levels";
|
|
315
|
-
refresh();
|
|
316
|
-
};
|
|
317
|
-
Object.defineProperty(container, "focused", {
|
|
318
|
-
get: () => focused,
|
|
319
|
-
set: (value) => {
|
|
320
|
-
focused = value;
|
|
321
|
-
input.focused = value && mode === "target";
|
|
322
|
-
},
|
|
323
|
-
});
|
|
324
|
-
container.handleInput = (data) => {
|
|
325
|
-
if (keybindings.matches(data, "tui.select.cancel")) {
|
|
326
|
-
if (mode === "levels")
|
|
327
|
-
done(undefined);
|
|
328
|
-
else {
|
|
329
|
-
mode = mode === "target" ? "choice" : "levels";
|
|
330
|
-
refresh();
|
|
331
|
-
}
|
|
332
|
-
return;
|
|
333
|
-
}
|
|
334
|
-
if (keybindings.matches(data, "tui.select.confirm")) {
|
|
335
|
-
if (mode === "levels") {
|
|
336
|
-
mode = "choice";
|
|
337
|
-
choice = 0;
|
|
338
|
-
}
|
|
339
|
-
else if (mode === "choice") {
|
|
340
|
-
if (choice === 0)
|
|
341
|
-
return save(undefined);
|
|
342
|
-
if (choice === 2)
|
|
343
|
-
return save(null);
|
|
344
|
-
mode = "target";
|
|
345
|
-
input.setValue(working[levels[index]] ?? "");
|
|
346
|
-
}
|
|
347
|
-
else {
|
|
348
|
-
const value = input.getValue().trim();
|
|
349
|
-
if (value)
|
|
350
|
-
save(value);
|
|
351
|
-
return;
|
|
352
|
-
}
|
|
353
|
-
refresh();
|
|
354
|
-
return;
|
|
355
|
-
}
|
|
356
|
-
if (mode === "target") {
|
|
357
|
-
input.handleInput(data);
|
|
358
|
-
tui.requestRender();
|
|
359
|
-
return;
|
|
360
|
-
}
|
|
361
|
-
const delta = keybindings.matches(data, "tui.select.up")
|
|
362
|
-
? -1
|
|
363
|
-
: keybindings.matches(data, "tui.select.down")
|
|
364
|
-
? 1
|
|
365
|
-
: 0;
|
|
366
|
-
if (delta) {
|
|
367
|
-
if (mode === "levels")
|
|
368
|
-
index = (index + delta + levels.length) % levels.length;
|
|
369
|
-
else
|
|
370
|
-
choice = (choice + delta + 3) % 3;
|
|
371
|
-
refresh();
|
|
372
|
-
}
|
|
373
|
-
};
|
|
374
|
-
refresh();
|
|
375
|
-
return container;
|
|
376
|
-
};
|
|
377
|
-
}
|
|
378
|
-
//# sourceMappingURL=dialog.js.map
|