@aiwayds/dsh-tui-pi 2.26.0 → 2.27.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -3
- package/README.zh-CN.md +5 -3
- package/cordis.patch.yml +14 -0
- package/lib/btw-overlay.d.ts +6 -4
- package/lib/btw-overlay.js +29 -26
- package/lib/btw-overlay.js.map +1 -1
- package/lib/custom-provider.d.ts +12 -13
- package/lib/custom-provider.js +23 -10
- package/lib/custom-provider.js.map +1 -1
- package/lib/hotkeys.js +2 -1
- package/lib/hotkeys.js.map +1 -1
- package/lib/index.js +106 -37
- package/lib/index.js.map +1 -1
- package/lib/keymap.d.ts +13 -0
- package/lib/keymap.js +8 -0
- package/lib/keymap.js.map +1 -1
- package/lib/model-list.d.ts +6 -1
- package/lib/model-list.js +10 -6
- package/lib/model-list.js.map +1 -1
- package/lib/plugins.d.ts +108 -0
- package/lib/plugins.js +367 -0
- package/lib/plugins.js.map +1 -0
- package/lib/provider-catalog.d.ts +30 -0
- package/lib/provider-catalog.js +38 -0
- package/lib/provider-catalog.js.map +1 -1
- package/lib/search.d.ts +125 -0
- package/lib/search.js +308 -0
- package/lib/search.js.map +1 -0
- package/lib/selectors.d.ts +4 -2
- package/lib/selectors.js +19 -12
- package/lib/selectors.js.map +1 -1
- package/lib/settings.d.ts +16 -1
- package/lib/settings.js +181 -17
- package/lib/settings.js.map +1 -1
- package/locales/en.json +64 -1
- package/locales/ja.json +64 -1
- package/locales/ko.json +64 -1
- package/locales/zh-CN.json +64 -1
- package/package.json +1 -1
package/lib/model-list.d.ts
CHANGED
|
@@ -30,7 +30,12 @@ export type ModelRow = {
|
|
|
30
30
|
kind: 'hiddenHeader';
|
|
31
31
|
count: number;
|
|
32
32
|
};
|
|
33
|
-
/**
|
|
33
|
+
/**
|
|
34
|
+
* Keyword match of `query` against name/id/provider: whitespace-separated
|
|
35
|
+
* tokens, case-insensitive, AND across tokens (each token substring-matches
|
|
36
|
+
* at least one field). A single token degrades to the plain substring match;
|
|
37
|
+
* an empty/whitespace-only query matches everything.
|
|
38
|
+
*/
|
|
34
39
|
export declare function matchesModelFilter(model: ListedModel, query: string): boolean;
|
|
35
40
|
/**
|
|
36
41
|
* Display order of every picker section: providers aggregate alphabetically,
|
package/lib/model-list.js
CHANGED
|
@@ -11,14 +11,18 @@
|
|
|
11
11
|
export function modelKey(model) {
|
|
12
12
|
return `${model.provider}/${model.id}`;
|
|
13
13
|
}
|
|
14
|
-
/**
|
|
14
|
+
/**
|
|
15
|
+
* Keyword match of `query` against name/id/provider: whitespace-separated
|
|
16
|
+
* tokens, case-insensitive, AND across tokens (each token substring-matches
|
|
17
|
+
* at least one field). A single token degrades to the plain substring match;
|
|
18
|
+
* an empty/whitespace-only query matches everything.
|
|
19
|
+
*/
|
|
15
20
|
export function matchesModelFilter(model, query) {
|
|
16
|
-
const
|
|
17
|
-
if (
|
|
21
|
+
const tokens = query.trim().toLowerCase().split(/\s+/).filter(token => token !== '');
|
|
22
|
+
if (tokens.length === 0)
|
|
18
23
|
return true;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|| model.provider.toLowerCase().includes(needle));
|
|
24
|
+
const fields = [model.name, model.id, model.provider].map(field => field.toLowerCase());
|
|
25
|
+
return tokens.every(token => fields.some(field => field.includes(token)));
|
|
22
26
|
}
|
|
23
27
|
/**
|
|
24
28
|
* Display order of every picker section: providers aggregate alphabetically,
|
package/lib/model-list.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-list.js","sourceRoot":"","sources":["../src/model-list.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AASH,8DAA8D;AAC9D,MAAM,UAAU,QAAQ,CAAC,KAA2C;IAClE,OAAO,GAAG,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,EAAE,EAAE,CAAA;AACxC,CAAC;AAYD
|
|
1
|
+
{"version":3,"file":"model-list.js","sourceRoot":"","sources":["../src/model-list.ts"],"names":[],"mappings":"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"}
|
package/lib/plugins.d.ts
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The /plugins manager — the terminal counterpart of the web profile's
|
|
3
|
+
* plugin-management page, over the SAME base service (`ctx.pluginManager`,
|
|
4
|
+
* dsh-plugin-manager): bundles from `listBundles()`, Enter toggles
|
|
5
|
+
* `setBundleEnabled`, `d` uninstalls through `removeBundle` behind a
|
|
6
|
+
* confirm, `i` installs a spec (`inspect` preview → `installBundle`).
|
|
7
|
+
* `/` engages the shared TablePanel filter; every mutation reloads the
|
|
8
|
+
* list and the ChangeResult surfaces on the in-panel status line
|
|
9
|
+
* (`applied` / `restart-required` / `overridden` / `failed`…).
|
|
10
|
+
*
|
|
11
|
+
* Pure row/notice builders live at the top (unit-testable); the panel is
|
|
12
|
+
* the PanelHost glue, exercised on a terminal (same split as btw-overlay).
|
|
13
|
+
*/
|
|
14
|
+
import { type TUI } from '@earendil-works/pi-tui';
|
|
15
|
+
import { type TuiTheme } from './theme/index.ts';
|
|
16
|
+
/**
|
|
17
|
+
* Structural face of one bundle from `pluginManager.listBundles()` — the
|
|
18
|
+
* fields this panel renders. Kept local so the plugin never hard-depends on
|
|
19
|
+
* the `@deepseek-ai/dsh-plugin-manager` package at typecheck time.
|
|
20
|
+
*/
|
|
21
|
+
export interface PluginBundleInfo {
|
|
22
|
+
name: string;
|
|
23
|
+
version?: string;
|
|
24
|
+
description?: string;
|
|
25
|
+
enabled: boolean;
|
|
26
|
+
/** Profile-owned dependency (`true`) vs installation-supplied optional. */
|
|
27
|
+
installed: boolean;
|
|
28
|
+
optional: boolean;
|
|
29
|
+
removable: boolean;
|
|
30
|
+
readOnlyReason?: 'management-required' | 'unaddressable';
|
|
31
|
+
error?: {
|
|
32
|
+
message?: string;
|
|
33
|
+
} & Record<string, unknown>;
|
|
34
|
+
}
|
|
35
|
+
/** Structural face of `pluginManager`'s ChangeResult. */
|
|
36
|
+
export interface PluginChangeResult {
|
|
37
|
+
changed: boolean;
|
|
38
|
+
application: 'applied' | 'restart-required' | 'overridden' | 'failed' | 'cancelled';
|
|
39
|
+
target: string;
|
|
40
|
+
error?: {
|
|
41
|
+
message?: string;
|
|
42
|
+
} & Record<string, unknown>;
|
|
43
|
+
}
|
|
44
|
+
/** Structural face of `pluginManager.inspect()`'s answer. */
|
|
45
|
+
export type PluginInspection = {
|
|
46
|
+
status: 'accepted';
|
|
47
|
+
name?: string;
|
|
48
|
+
version?: string;
|
|
49
|
+
description?: string;
|
|
50
|
+
bundle: boolean | null;
|
|
51
|
+
} | {
|
|
52
|
+
status: 'refused';
|
|
53
|
+
problem: string;
|
|
54
|
+
reason: string;
|
|
55
|
+
};
|
|
56
|
+
/** The service surface the panel drives (base bundle, keyed `pluginManager`). */
|
|
57
|
+
export interface PluginManagerSeam {
|
|
58
|
+
listBundles(): Promise<readonly PluginBundleInfo[]>;
|
|
59
|
+
setBundleEnabled(name: string, enabled: boolean): Promise<PluginChangeResult>;
|
|
60
|
+
removeBundle(name: string): Promise<PluginChangeResult>;
|
|
61
|
+
installBundle(spec: string, options?: {
|
|
62
|
+
enabled?: boolean;
|
|
63
|
+
}): Promise<PluginChangeResult>;
|
|
64
|
+
inspect(spec: string): Promise<PluginInspection>;
|
|
65
|
+
}
|
|
66
|
+
/** One rendered row of the plugin table. */
|
|
67
|
+
export interface PluginRowView {
|
|
68
|
+
name: string;
|
|
69
|
+
/** Name + @version (the PLUGIN column). */
|
|
70
|
+
label: string;
|
|
71
|
+
/** STATE column text (on/off/not installed + badges). */
|
|
72
|
+
state: string;
|
|
73
|
+
/** Enter may toggle (not read-only, no load error). */
|
|
74
|
+
toggleable: boolean;
|
|
75
|
+
removable: boolean;
|
|
76
|
+
}
|
|
77
|
+
/** STATE text of one bundle: on/off/not-installed plus error/readonly badges. */
|
|
78
|
+
export declare function bundleStateText(bundle: PluginBundleInfo): string;
|
|
79
|
+
/**
|
|
80
|
+
* Bundle rows for the table: alphabetical by name (the web page groups
|
|
81
|
+
* Official/Installed cards; a flat sorted table reads better in a terminal
|
|
82
|
+
* and the `/` filter narrows it anyway).
|
|
83
|
+
*/
|
|
84
|
+
export declare function pluginRowViews(bundles: readonly PluginBundleInfo[]): PluginRowView[];
|
|
85
|
+
/**
|
|
86
|
+
* Status-line wording of one ChangeResult — the application outcome the
|
|
87
|
+
* web page toasts, phrased for the TUI status row.
|
|
88
|
+
*/
|
|
89
|
+
export declare function pluginChangeNotice(result: PluginChangeResult): string;
|
|
90
|
+
/** Options for the /plugins manager entry point. */
|
|
91
|
+
export interface OpenPluginsPanelOptions {
|
|
92
|
+
tui: TUI;
|
|
93
|
+
theme: TuiTheme;
|
|
94
|
+
/** The pluginManager service (already narrowed to the seam); undefined = unavailable. */
|
|
95
|
+
manager?: PluginManagerSeam;
|
|
96
|
+
restoreFocus: () => void;
|
|
97
|
+
/** Esc exit — closes the hosting overlay (wired by openPluginsPanel). */
|
|
98
|
+
onExit?: () => void;
|
|
99
|
+
/** Error sink for failures that outlive the panel (transcript). */
|
|
100
|
+
onError: (message: string) => void;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Open the /plugins manager. Returns `undefined` once the panel closed
|
|
104
|
+
* normally, or an error string when plugin management is unavailable in
|
|
105
|
+
* this profile (no pluginManager service) or the first listing failed —
|
|
106
|
+
* the caller turns that into the command's error reply.
|
|
107
|
+
*/
|
|
108
|
+
export declare function openPluginsPanel(options: OpenPluginsPanelOptions): Promise<string | undefined>;
|
package/lib/plugins.js
ADDED
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The /plugins manager — the terminal counterpart of the web profile's
|
|
3
|
+
* plugin-management page, over the SAME base service (`ctx.pluginManager`,
|
|
4
|
+
* dsh-plugin-manager): bundles from `listBundles()`, Enter toggles
|
|
5
|
+
* `setBundleEnabled`, `d` uninstalls through `removeBundle` behind a
|
|
6
|
+
* confirm, `i` installs a spec (`inspect` preview → `installBundle`).
|
|
7
|
+
* `/` engages the shared TablePanel filter; every mutation reloads the
|
|
8
|
+
* list and the ChangeResult surfaces on the in-panel status line
|
|
9
|
+
* (`applied` / `restart-required` / `overridden` / `failed`…).
|
|
10
|
+
*
|
|
11
|
+
* Pure row/notice builders live at the top (unit-testable); the panel is
|
|
12
|
+
* the PanelHost glue, exercised on a terminal (same split as btw-overlay).
|
|
13
|
+
*/
|
|
14
|
+
import { getKeybindings } from '@earendil-works/pi-tui';
|
|
15
|
+
import { t } from "./i18n/index.js";
|
|
16
|
+
import { EditField } from "./settings.js";
|
|
17
|
+
import { autoColumns, panelThemeFns, PanelHost, TablePanel } from "./panels.js";
|
|
18
|
+
import { BOLD, RESET } from "./theme/index.js";
|
|
19
|
+
import { clipToWidth } from "./text.js";
|
|
20
|
+
/** STATE text of one bundle: on/off/not-installed plus error/readonly badges. */
|
|
21
|
+
export function bundleStateText(bundle) {
|
|
22
|
+
const base = !bundle.installed && bundle.optional
|
|
23
|
+
? t('plugins.state.available')
|
|
24
|
+
: bundle.enabled
|
|
25
|
+
? t('plugins.state.on')
|
|
26
|
+
: t('plugins.state.off');
|
|
27
|
+
if (bundle.error !== undefined)
|
|
28
|
+
return `${base} ${t('plugins.state.error')}`;
|
|
29
|
+
if (bundle.readOnlyReason !== undefined)
|
|
30
|
+
return `${base} ${t('plugins.state.readOnly')}`;
|
|
31
|
+
return base;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Bundle rows for the table: alphabetical by name (the web page groups
|
|
35
|
+
* Official/Installed cards; a flat sorted table reads better in a terminal
|
|
36
|
+
* and the `/` filter narrows it anyway).
|
|
37
|
+
*/
|
|
38
|
+
export function pluginRowViews(bundles) {
|
|
39
|
+
return [...bundles]
|
|
40
|
+
.sort((a, b) => a.name.localeCompare(b.name))
|
|
41
|
+
.map(bundle => ({
|
|
42
|
+
name: bundle.name,
|
|
43
|
+
label: bundle.version !== undefined && bundle.version !== '' ? `${bundle.name}@${bundle.version}` : bundle.name,
|
|
44
|
+
state: bundleStateText(bundle),
|
|
45
|
+
toggleable: bundle.readOnlyReason === undefined && bundle.error === undefined,
|
|
46
|
+
removable: bundle.removable,
|
|
47
|
+
}));
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Status-line wording of one ChangeResult — the application outcome the
|
|
51
|
+
* web page toasts, phrased for the TUI status row.
|
|
52
|
+
*/
|
|
53
|
+
export function pluginChangeNotice(result) {
|
|
54
|
+
const suffix = result.error?.message !== undefined && result.error.message !== ''
|
|
55
|
+
? `: ${result.error.message}`
|
|
56
|
+
: '';
|
|
57
|
+
switch (result.application) {
|
|
58
|
+
case 'applied': return t('plugins.notice.applied', { target: result.target });
|
|
59
|
+
case 'restart-required': return t('plugins.notice.restartRequired', { target: result.target });
|
|
60
|
+
case 'overridden': return t('plugins.notice.overridden', { target: result.target });
|
|
61
|
+
case 'failed': return t('plugins.notice.failed', { target: result.target }) + suffix;
|
|
62
|
+
case 'cancelled': return t('plugins.notice.cancelled');
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* One-line confirm (Enter/Esc) for destructive plugin actions — the
|
|
67
|
+
* ConfirmReset shape with plugin copy.
|
|
68
|
+
*/
|
|
69
|
+
class PluginConfirm {
|
|
70
|
+
theme;
|
|
71
|
+
label;
|
|
72
|
+
body;
|
|
73
|
+
onConfirm;
|
|
74
|
+
onCancel;
|
|
75
|
+
constructor(theme, label, body, onConfirm, onCancel) {
|
|
76
|
+
this.theme = theme;
|
|
77
|
+
this.label = label;
|
|
78
|
+
this.body = body;
|
|
79
|
+
this.onConfirm = onConfirm;
|
|
80
|
+
this.onCancel = onCancel;
|
|
81
|
+
}
|
|
82
|
+
invalidate() { }
|
|
83
|
+
render(width) {
|
|
84
|
+
const fns = panelThemeFns(this.theme);
|
|
85
|
+
const lines = [fns.accent(BOLD + clipToWidth(this.label, width) + RESET)];
|
|
86
|
+
lines.push('');
|
|
87
|
+
for (const line of this.body)
|
|
88
|
+
lines.push(fns.muted(clipToWidth(` ${line}`, width)));
|
|
89
|
+
lines.push('');
|
|
90
|
+
lines.push(fns.subtle(clipToWidth(t('plugins.confirm.hints'), width)));
|
|
91
|
+
return lines;
|
|
92
|
+
}
|
|
93
|
+
handleInput(data) {
|
|
94
|
+
const kb = getKeybindings();
|
|
95
|
+
if (kb.matches(data, 'tui.select.confirm'))
|
|
96
|
+
this.onConfirm();
|
|
97
|
+
else if (kb.matches(data, 'tui.select.cancel'))
|
|
98
|
+
this.onCancel();
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* The manager panel: a filterable bundle table plus in-place swap modes
|
|
103
|
+
* (install editor, install preview, uninstall confirm) and a status line
|
|
104
|
+
* carrying busy state and ChangeResult notices.
|
|
105
|
+
*/
|
|
106
|
+
class PluginsPanel {
|
|
107
|
+
tui;
|
|
108
|
+
theme;
|
|
109
|
+
manager;
|
|
110
|
+
onExit;
|
|
111
|
+
onError;
|
|
112
|
+
bundles = [];
|
|
113
|
+
query = '';
|
|
114
|
+
/** The active table; rebuilt on every reload/keep-focus path. */
|
|
115
|
+
table;
|
|
116
|
+
tableOptions;
|
|
117
|
+
/** In-place swap mode (install editor / preview / uninstall confirm). */
|
|
118
|
+
mode;
|
|
119
|
+
/** Status line: busy text or a change notice (auto-clearing). */
|
|
120
|
+
status;
|
|
121
|
+
statusTimer;
|
|
122
|
+
busy = false;
|
|
123
|
+
rerender = () => { this.tui.requestRender(); };
|
|
124
|
+
constructor(options) {
|
|
125
|
+
if (options.manager === undefined)
|
|
126
|
+
throw new Error('pluginManager service is required');
|
|
127
|
+
this.tui = options.tui;
|
|
128
|
+
this.theme = options.theme;
|
|
129
|
+
this.manager = options.manager;
|
|
130
|
+
this.onExit = options.onExit ?? (() => { });
|
|
131
|
+
this.onError = options.onError;
|
|
132
|
+
this.tableOptions = {
|
|
133
|
+
title: t('plugins.title'),
|
|
134
|
+
columns: [],
|
|
135
|
+
rows: [],
|
|
136
|
+
renderCell: (row, column) => (column.key === 'state' ? row.state : row.label),
|
|
137
|
+
isSelectable: () => true,
|
|
138
|
+
onSelect: row => { void this.toggle(row); },
|
|
139
|
+
onCancel: () => this.onExit(),
|
|
140
|
+
footer: t('plugins.footer'),
|
|
141
|
+
status: () => this.status,
|
|
142
|
+
emptyHint: t('plugins.empty'),
|
|
143
|
+
filter: {
|
|
144
|
+
getQuery: () => this.query,
|
|
145
|
+
onQueryChange: next => {
|
|
146
|
+
this.query = next;
|
|
147
|
+
this.rebuild();
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
shortcuts: {
|
|
151
|
+
i: () => { void this.beginInstall(); },
|
|
152
|
+
d: () => { void this.confirmRemove(this.table.selectedRow()); },
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
this.table = new TablePanel(this.theme, this.tableOptions);
|
|
156
|
+
}
|
|
157
|
+
invalidate() {
|
|
158
|
+
this.mode?.invalidate();
|
|
159
|
+
this.table.invalidate();
|
|
160
|
+
}
|
|
161
|
+
/** PanelHost teardown hook: drop any pending status-clear timer. */
|
|
162
|
+
dispose() {
|
|
163
|
+
clearTimeout(this.statusTimer);
|
|
164
|
+
}
|
|
165
|
+
render(width) {
|
|
166
|
+
return (this.mode ?? this.table).render(width);
|
|
167
|
+
}
|
|
168
|
+
handleInput(data) {
|
|
169
|
+
// A running mutation already holds the write path — extra keys must not
|
|
170
|
+
// stack a second one (the notice would lie about the first).
|
|
171
|
+
if (this.busy)
|
|
172
|
+
return;
|
|
173
|
+
const target = this.mode ?? this.table;
|
|
174
|
+
target.handleInput?.(data);
|
|
175
|
+
}
|
|
176
|
+
/** Initial load; returns an error string when the listing fails. */
|
|
177
|
+
async load() {
|
|
178
|
+
try {
|
|
179
|
+
this.bundles = await this.manager.listBundles();
|
|
180
|
+
}
|
|
181
|
+
catch (cause) {
|
|
182
|
+
return t('plugins.listFailed', { message: cause instanceof Error ? cause.message : String(cause) });
|
|
183
|
+
}
|
|
184
|
+
this.rebuild();
|
|
185
|
+
return undefined;
|
|
186
|
+
}
|
|
187
|
+
/** Rebuild the table rows from the current bundles + filter. */
|
|
188
|
+
rebuild(keepName) {
|
|
189
|
+
const rows = pluginRowViews(this.bundles).filter(row => row.label.toLowerCase().includes(this.query.trim().toLowerCase())
|
|
190
|
+
|| row.name.toLowerCase().includes(this.query.trim().toLowerCase()));
|
|
191
|
+
this.tableOptions.columns = autoColumns([
|
|
192
|
+
{ key: 'plugin', title: t('plugins.col.plugin'), cap: 36 },
|
|
193
|
+
{ key: 'state', title: t('plugins.col.state') },
|
|
194
|
+
], rows, (row, key) => (key === 'state' ? row.state : row.label));
|
|
195
|
+
this.tableOptions.rows = rows;
|
|
196
|
+
const followed = keepName !== undefined && this.table.focusRow(row => row.name === keepName);
|
|
197
|
+
if (!followed && this.query.trim() !== '')
|
|
198
|
+
this.table.focusRow(() => true);
|
|
199
|
+
else if (!followed)
|
|
200
|
+
this.table.resyncCursor();
|
|
201
|
+
}
|
|
202
|
+
/** Show one status line; busy text persists, notices auto-clear. */
|
|
203
|
+
flash(message, autoClearMs) {
|
|
204
|
+
this.status = message;
|
|
205
|
+
clearTimeout(this.statusTimer);
|
|
206
|
+
if (autoClearMs !== undefined) {
|
|
207
|
+
this.statusTimer = setTimeout(() => {
|
|
208
|
+
this.status = undefined;
|
|
209
|
+
this.rerender();
|
|
210
|
+
}, autoClearMs);
|
|
211
|
+
}
|
|
212
|
+
this.rerender();
|
|
213
|
+
}
|
|
214
|
+
/** Reload the bundle list, keeping the cursor on `keepName` when present. */
|
|
215
|
+
async reload(keepName) {
|
|
216
|
+
try {
|
|
217
|
+
this.bundles = await this.manager.listBundles();
|
|
218
|
+
}
|
|
219
|
+
catch (cause) {
|
|
220
|
+
this.onError(t('plugins.listFailed', { message: cause instanceof Error ? cause.message : String(cause) }));
|
|
221
|
+
}
|
|
222
|
+
this.rebuild(keepName);
|
|
223
|
+
this.rerender();
|
|
224
|
+
}
|
|
225
|
+
/** Enter: toggle the bundle on/off (guarded), then reload + notice. */
|
|
226
|
+
async toggle(row) {
|
|
227
|
+
if (row === undefined || !row.toggleable) {
|
|
228
|
+
if (row !== undefined)
|
|
229
|
+
this.flash(t('plugins.notice.readOnly', { name: row.name }), 4000);
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
const bundle = this.bundles.find(entry => entry.name === row.name);
|
|
233
|
+
if (bundle === undefined)
|
|
234
|
+
return;
|
|
235
|
+
this.busy = true;
|
|
236
|
+
this.flash(t('plugins.busy.toggling', { name: row.name }));
|
|
237
|
+
try {
|
|
238
|
+
const result = await this.manager.setBundleEnabled(row.name, !bundle.enabled);
|
|
239
|
+
this.flash(pluginChangeNotice(result), 6000);
|
|
240
|
+
}
|
|
241
|
+
catch (cause) {
|
|
242
|
+
this.flash(t('plugins.notice.failed', {
|
|
243
|
+
target: row.name,
|
|
244
|
+
}) + `: ${cause instanceof Error ? cause.message : String(cause)}`, 6000);
|
|
245
|
+
}
|
|
246
|
+
this.busy = false;
|
|
247
|
+
await this.reload(row.name);
|
|
248
|
+
}
|
|
249
|
+
/** `d`: uninstall behind a one-line confirm. */
|
|
250
|
+
async confirmRemove(row) {
|
|
251
|
+
if (row === undefined)
|
|
252
|
+
return;
|
|
253
|
+
if (!row.removable) {
|
|
254
|
+
this.flash(t('plugins.notice.notRemovable', { name: row.name }), 4000);
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
const name = row.name;
|
|
258
|
+
this.mode = new PluginConfirm(this.theme, t('plugins.confirm.removeTitle', { name }), [t('plugins.confirm.removeBody')], () => { void this.remove(name); }, () => { this.mode = undefined; this.rerender(); });
|
|
259
|
+
this.rerender();
|
|
260
|
+
}
|
|
261
|
+
async remove(name) {
|
|
262
|
+
this.mode = undefined;
|
|
263
|
+
this.busy = true;
|
|
264
|
+
this.flash(t('plugins.busy.removing', { name }));
|
|
265
|
+
try {
|
|
266
|
+
const result = await this.manager.removeBundle(name);
|
|
267
|
+
this.flash(pluginChangeNotice(result), 6000);
|
|
268
|
+
}
|
|
269
|
+
catch (cause) {
|
|
270
|
+
this.flash(t('plugins.notice.failed', { target: name }) + `: ${cause instanceof Error ? cause.message : String(cause)}`, 6000);
|
|
271
|
+
}
|
|
272
|
+
this.busy = false;
|
|
273
|
+
await this.reload();
|
|
274
|
+
}
|
|
275
|
+
/** `i`: spec editor → inspect preview → confirm → install. */
|
|
276
|
+
async beginInstall() {
|
|
277
|
+
this.mode = new EditField(this.tui, {
|
|
278
|
+
title: t('plugins.install.title'),
|
|
279
|
+
subtitle: t('plugins.install.hint'),
|
|
280
|
+
initial: '',
|
|
281
|
+
parse: text => (text.trim() === ''
|
|
282
|
+
? { kind: 'error', error: t('plugins.install.empty') }
|
|
283
|
+
: { kind: 'value', value: text.trim() }),
|
|
284
|
+
onCommit: async (outcome) => {
|
|
285
|
+
if (outcome.kind !== 'value')
|
|
286
|
+
return undefined;
|
|
287
|
+
// Fire-and-forget: closing the editor immediately hands the screen
|
|
288
|
+
// back to the table, whose status line carries the install phases.
|
|
289
|
+
void this.runInstall(String(outcome.value));
|
|
290
|
+
return undefined;
|
|
291
|
+
},
|
|
292
|
+
// Enter and Esc both return to the table; the install (when started)
|
|
293
|
+
// continues on the status line.
|
|
294
|
+
onDone: () => { this.mode = undefined; this.rerender(); },
|
|
295
|
+
onError: message => this.onError(message),
|
|
296
|
+
}, this.theme);
|
|
297
|
+
this.rerender();
|
|
298
|
+
}
|
|
299
|
+
async runInstall(spec) {
|
|
300
|
+
this.mode = undefined;
|
|
301
|
+
this.busy = true;
|
|
302
|
+
this.flash(t('plugins.busy.inspecting', { spec }));
|
|
303
|
+
let inspection;
|
|
304
|
+
try {
|
|
305
|
+
inspection = await this.manager.inspect(spec);
|
|
306
|
+
}
|
|
307
|
+
catch (cause) {
|
|
308
|
+
this.busy = false;
|
|
309
|
+
this.flash(t('plugins.install.inspectFailed', {
|
|
310
|
+
message: cause instanceof Error ? cause.message : String(cause),
|
|
311
|
+
}), 6000);
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
if (inspection.status === 'refused') {
|
|
315
|
+
this.busy = false;
|
|
316
|
+
this.flash(t('plugins.install.refused', {
|
|
317
|
+
problem: inspection.problem,
|
|
318
|
+
reason: inspection.reason,
|
|
319
|
+
}), 8000);
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
this.flash(t('plugins.busy.installing', { spec }));
|
|
323
|
+
try {
|
|
324
|
+
const result = await this.manager.installBundle(spec, { enabled: true });
|
|
325
|
+
this.flash(pluginChangeNotice(result), 8000);
|
|
326
|
+
}
|
|
327
|
+
catch (cause) {
|
|
328
|
+
this.flash(t('plugins.notice.failed', { target: spec }) + `: ${cause instanceof Error ? cause.message : String(cause)}`, 8000);
|
|
329
|
+
}
|
|
330
|
+
this.busy = false;
|
|
331
|
+
await this.reload();
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Open the /plugins manager. Returns `undefined` once the panel closed
|
|
336
|
+
* normally, or an error string when plugin management is unavailable in
|
|
337
|
+
* this profile (no pluginManager service) or the first listing failed —
|
|
338
|
+
* the caller turns that into the command's error reply.
|
|
339
|
+
*/
|
|
340
|
+
export async function openPluginsPanel(options) {
|
|
341
|
+
if (options.manager === undefined)
|
|
342
|
+
return t('plugins.unavailable');
|
|
343
|
+
const restoreFocus = options.restoreFocus;
|
|
344
|
+
// The panel's Esc exit closes the host BEFORE refocusing — the shared
|
|
345
|
+
// overlay contract (a half-torn-down overlay must not strand focus).
|
|
346
|
+
const exit = () => {
|
|
347
|
+
host.close();
|
|
348
|
+
restoreFocus();
|
|
349
|
+
};
|
|
350
|
+
// A half-mounted overlay must not strand the keyboard (PanelHost calls
|
|
351
|
+
// onError first, then we settle through the same exit path).
|
|
352
|
+
const host = new PanelHost(options.tui, options.theme, () => {
|
|
353
|
+
restoreFocus();
|
|
354
|
+
});
|
|
355
|
+
const panel = new PluginsPanel({
|
|
356
|
+
...options,
|
|
357
|
+
onExit: exit,
|
|
358
|
+
});
|
|
359
|
+
const loadError = await panel.load();
|
|
360
|
+
if (loadError !== undefined) {
|
|
361
|
+
restoreFocus();
|
|
362
|
+
return loadError;
|
|
363
|
+
}
|
|
364
|
+
host.open(panel, '75%', '80%');
|
|
365
|
+
return undefined;
|
|
366
|
+
}
|
|
367
|
+
//# sourceMappingURL=plugins.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugins.js","sourceRoot":"","sources":["../src/plugins.ts"],"names":[],"mappings":"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"}
|
|
@@ -91,6 +91,36 @@ export declare function resolveCatalogHint(hint: string): string;
|
|
|
91
91
|
* @returns the derived reference (e.g. `ANTHROPIC_API_KEY`, `OPENCODE_GO_API_KEY`).
|
|
92
92
|
*/
|
|
93
93
|
export declare function deriveKeyRef(provider: string): string;
|
|
94
|
+
/**
|
|
95
|
+
* The editable form state of a hand-declared route — the shape the
|
|
96
|
+
* custom-provider form works on, in both create and edit mode. Lives here
|
|
97
|
+
* (not in custom-provider.ts) so settings.ts can read a live profile into
|
|
98
|
+
* one without touching the custom-provider ↔ settings import cycle.
|
|
99
|
+
*/
|
|
100
|
+
export interface CustomProviderDraft {
|
|
101
|
+
id: string;
|
|
102
|
+
/** Empty string = no display name (the route id shows instead). */
|
|
103
|
+
displayName: string;
|
|
104
|
+
api: string;
|
|
105
|
+
baseURL: string;
|
|
106
|
+
/** Comma-joined model ids (parsed form of the models field). */
|
|
107
|
+
models: string;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Read a live `providers.<id>` profile into an editable draft: unknown or
|
|
111
|
+
* malformed fields fall back to their form defaults rather than failing —
|
|
112
|
+
* an edit must always be openable, even for a route the web page wrote
|
|
113
|
+
* with fields this form does not know.
|
|
114
|
+
*/
|
|
115
|
+
export declare function customDraftFromProfile(id: string, profile: unknown): CustomProviderDraft;
|
|
116
|
+
/**
|
|
117
|
+
* Whether a live profile row is a hand-declared route (editable in full)
|
|
118
|
+
* rather than a catalog-served one (only its key is editable — endpoint,
|
|
119
|
+
* protocol and models come from the installed pi-ai catalog). A profile
|
|
120
|
+
* that carries its own `api`/`baseURL`/`models` overrides the catalog, so
|
|
121
|
+
* it reads as hand-declared even when the directory disagrees.
|
|
122
|
+
*/
|
|
123
|
+
export declare function isHandDeclaredProfile(profile: unknown): boolean;
|
|
94
124
|
/**
|
|
95
125
|
* The llm-pi-ai providers.<id> value an entry writes as: a catalog route
|
|
96
126
|
* stores only the derived credential reference (endpoint, protocol, and
|
package/lib/provider-catalog.js
CHANGED
|
@@ -113,6 +113,44 @@ export function resolveCatalogHint(hint) {
|
|
|
113
113
|
export function deriveKeyRef(provider) {
|
|
114
114
|
return `${provider.toUpperCase().replace(/[^A-Z0-9]+/g, '_')}_API_KEY`;
|
|
115
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* Read a live `providers.<id>` profile into an editable draft: unknown or
|
|
118
|
+
* malformed fields fall back to their form defaults rather than failing —
|
|
119
|
+
* an edit must always be openable, even for a route the web page wrote
|
|
120
|
+
* with fields this form does not know.
|
|
121
|
+
*/
|
|
122
|
+
export function customDraftFromProfile(id, profile) {
|
|
123
|
+
const p = (typeof profile === 'object' && profile !== null ? profile : {});
|
|
124
|
+
const models = Array.isArray(p.models)
|
|
125
|
+
? p.models
|
|
126
|
+
.map(model => (typeof model === 'object' && model !== null
|
|
127
|
+
? model.id
|
|
128
|
+
: undefined))
|
|
129
|
+
.filter((modelId) => typeof modelId === 'string' && modelId !== '')
|
|
130
|
+
: [];
|
|
131
|
+
return {
|
|
132
|
+
id,
|
|
133
|
+
displayName: typeof p.displayName === 'string' ? p.displayName : '',
|
|
134
|
+
api: typeof p.api === 'string' ? p.api : '',
|
|
135
|
+
baseURL: typeof p.baseURL === 'string' ? p.baseURL : '',
|
|
136
|
+
models: models.join(','),
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Whether a live profile row is a hand-declared route (editable in full)
|
|
141
|
+
* rather than a catalog-served one (only its key is editable — endpoint,
|
|
142
|
+
* protocol and models come from the installed pi-ai catalog). A profile
|
|
143
|
+
* that carries its own `api`/`baseURL`/`models` overrides the catalog, so
|
|
144
|
+
* it reads as hand-declared even when the directory disagrees.
|
|
145
|
+
*/
|
|
146
|
+
export function isHandDeclaredProfile(profile) {
|
|
147
|
+
if (typeof profile !== 'object' || profile === null)
|
|
148
|
+
return false;
|
|
149
|
+
const p = profile;
|
|
150
|
+
return typeof p.api === 'string'
|
|
151
|
+
|| typeof p.baseURL === 'string'
|
|
152
|
+
|| Array.isArray(p.models);
|
|
153
|
+
}
|
|
116
154
|
/**
|
|
117
155
|
* The llm-pi-ai providers.<id> value an entry writes as: a catalog route
|
|
118
156
|
* stores only the derived credential reference (endpoint, protocol, and
|