@deepseek-ai/dsh-client-ui-plugin-manager 0.1.6-alpha.2 → 0.1.7-alpha.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/README.i18n.yaml +2 -2
- package/README.md +38 -9
- package/README.zh.md +38 -9
- package/lib/client.js +1154 -382
- package/lib/index.js +140 -4
- package/lib/typert.host.d.ts +3 -0
- package/lib/typert.host.js +53 -0
- package/lib/typert.remote-client.d.ts +21 -0
- package/lib/typert.remote-client.js +28 -0
- package/lib/types/client/PluginManagerPage.d.ts +1 -1
- package/lib/types/client/index.d.ts +1 -1
- package/lib/types/client/locales.d.ts +63 -19
- package/lib/types/client/manager-store.d.ts +87 -25
- package/lib/types/client/presentation.d.ts +29 -7
- package/lib/types/client/slot-contract.d.ts +111 -11
- package/lib/types/index.d.ts +35 -3
- package/package.json +37 -16
|
@@ -6,9 +6,11 @@
|
|
|
6
6
|
* change made on another surface shows here without a manual refresh.
|
|
7
7
|
*/
|
|
8
8
|
import type { Context as ClientContext } from '@deepseek-ai/cordis';
|
|
9
|
-
import type { BundleInfo, ManagementError, PluginEntryId, PluginInfo, PluginInspectProblem, PluginInstallFailureKind, PluginInstallLogChunk, PluginInstallProgress, PluginInstallRequestId, PluginSpecInspection, ReadOnlyReason } from '@deepseek-ai/dsh-api-remotes/client';
|
|
9
|
+
import type { BundleInfo, ManagementError, PluginEntryId, PluginInfo, PluginInspectProblem, PluginInstallFailureKind, PluginInstallLogChunk, PluginInstallProgress, PluginInstallRequestId, PluginRegistries, PluginSpecInspection, ReadOnlyReason, Registry } from '@deepseek-ai/dsh-api-remotes/client';
|
|
10
10
|
import { type SnapshotStore } from '@deepseek-ai/dsh-client-store';
|
|
11
11
|
import type { HostObservable } from '@deepseek-ai/dsh-client-ui-slots';
|
|
12
|
+
import type { LocalizedText, PluginLocalizedMeta } from '@deepseek-ai/dsh-package-manifest';
|
|
13
|
+
import type { SettingsDescribeFace, ConfigForms } from '@deepseek-ai/dsh-client-ui-settings/client';
|
|
12
14
|
import type { ConfigLedger } from './config-ledger.ts';
|
|
13
15
|
/** The action a failed notice names. */
|
|
14
16
|
export type FailedAction = 'enable' | 'disable' | 'uninstall' | 'rowEnable' | 'rowDisable';
|
|
@@ -24,6 +26,10 @@ export type ManagerNotice = {
|
|
|
24
26
|
} | {
|
|
25
27
|
readonly kind: 'cancelled';
|
|
26
28
|
readonly seq: number;
|
|
29
|
+
} | {
|
|
30
|
+
readonly kind: 'install';
|
|
31
|
+
readonly outcome: 'done' | 'failed' | 'unconfirmed' | 'applying' | 'unknown';
|
|
32
|
+
readonly seq: number;
|
|
27
33
|
} | {
|
|
28
34
|
readonly kind: 'failed';
|
|
29
35
|
/** What was being done when it failed. */
|
|
@@ -43,6 +49,8 @@ export interface PackageRow {
|
|
|
43
49
|
readonly rowId: string;
|
|
44
50
|
/** The module the row names. */
|
|
45
51
|
readonly moduleName: string;
|
|
52
|
+
/** Local package display text and metadata diagnostics supplied by the Host. */
|
|
53
|
+
readonly meta?: PluginLocalizedMeta;
|
|
46
54
|
/** Whether the entry runs; false for a row without a live entry. */
|
|
47
55
|
readonly enabled: boolean;
|
|
48
56
|
/** The entry's fiber phase, null without a live fiber. */
|
|
@@ -55,6 +63,8 @@ export interface PackageView {
|
|
|
55
63
|
readonly name: string;
|
|
56
64
|
readonly version?: string;
|
|
57
65
|
readonly description?: string;
|
|
66
|
+
/** Local package display text and metadata diagnostics supplied by the Host. */
|
|
67
|
+
readonly meta?: PluginLocalizedMeta;
|
|
58
68
|
/** Whether the profile's own dependencies hold the package; false for a bundle the installation supplies. */
|
|
59
69
|
readonly installed: boolean;
|
|
60
70
|
/** Whether the installation ships the bundle for the person to switch on: official, off until selected, never removable. */
|
|
@@ -73,10 +83,26 @@ export type InstallSubject = Extract<PluginSpecInspection, {
|
|
|
73
83
|
}> & {
|
|
74
84
|
readonly spec: string;
|
|
75
85
|
};
|
|
86
|
+
/** The registry the person picked for an install: one the Host offers, or a typed URL. */
|
|
87
|
+
export type RegistryChoice = {
|
|
88
|
+
readonly kind: 'offered';
|
|
89
|
+
readonly registry: Registry;
|
|
90
|
+
} | {
|
|
91
|
+
readonly kind: 'custom';
|
|
92
|
+
readonly url: string;
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* The registries the dialog offers: the Host's first, its fallbacks, and pnpm's own, each once.
|
|
96
|
+
* @param registries - what the Host configured, or null while unread.
|
|
97
|
+
* @returns the registries in the order the dialog lists them.
|
|
98
|
+
*/
|
|
99
|
+
export declare function offeredRegistries(registries: PluginRegistries | null): Registry[];
|
|
76
100
|
/** Why the typed spec was refused before anything installed. */
|
|
77
101
|
export interface InstallInputError {
|
|
78
102
|
readonly problem: PluginInspectProblem;
|
|
79
103
|
readonly reason: string;
|
|
104
|
+
/** The registries the check asked, in order, when the refusal came from asking them. */
|
|
105
|
+
readonly registries?: readonly Registry[];
|
|
80
106
|
}
|
|
81
107
|
/** One pnpm run of an install, as the dialog's terminal draws it. */
|
|
82
108
|
export interface InstallRun {
|
|
@@ -91,18 +117,30 @@ export interface InstallRun {
|
|
|
91
117
|
readonly exitCode?: number | null;
|
|
92
118
|
}
|
|
93
119
|
/**
|
|
94
|
-
*
|
|
95
|
-
* `
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
* confirmed cancellation, and the back control return to `idle` with the spec kept.
|
|
120
|
+
* Installation input, Host progress, and the final outcome. `unconfirmed` keeps
|
|
121
|
+
* an unresolved request pending; `unknown` releases it after the Host reports
|
|
122
|
+
* no active request and its original reply is lost. Neither means cancellation.
|
|
123
|
+
* Closing any pending phase preserves its request and output for reopening.
|
|
124
|
+
* Confirmed cancellation and returning from an outcome keep the spec for editing.
|
|
100
125
|
*/
|
|
101
126
|
export interface InstallState {
|
|
102
127
|
readonly open: boolean;
|
|
103
128
|
/** The package spec as typed. */
|
|
104
129
|
readonly spec: string;
|
|
105
|
-
|
|
130
|
+
/** The registries the Host configured, read when the dialog opens; null until the Host answered. */
|
|
131
|
+
readonly registries: PluginRegistries | null;
|
|
132
|
+
/** The registry this install asks first: the one last used, else the Host's first. */
|
|
133
|
+
readonly registry: RegistryChoice;
|
|
134
|
+
/** Whether the registry options are unfolded under the spec. */
|
|
135
|
+
readonly registryOpen: boolean;
|
|
136
|
+
/** Whether the typed registry was refused for not being an http(s) URL. */
|
|
137
|
+
readonly registryError: boolean;
|
|
138
|
+
/** The registries the Host asked for this install, in order, and how many it may ask; null before the run. */
|
|
139
|
+
readonly attempts: {
|
|
140
|
+
readonly registries: readonly Registry[];
|
|
141
|
+
readonly total: number;
|
|
142
|
+
} | null;
|
|
143
|
+
readonly phase: 'idle' | 'checking' | 'starting' | 'running' | 'cancelling' | 'applying' | 'unconfirmed' | 'unknown' | 'done' | 'failed';
|
|
106
144
|
/** Identifies this dialog's installation, including log and cancellation messages. */
|
|
107
145
|
readonly requestId?: PluginInstallRequestId;
|
|
108
146
|
/** Why the spec was refused before installing; shown under the field. */
|
|
@@ -111,7 +149,7 @@ export interface InstallState {
|
|
|
111
149
|
readonly subject: InstallSubject | null;
|
|
112
150
|
/** The pnpm runs of the open install, in the order they started. */
|
|
113
151
|
readonly runs: readonly InstallRun[];
|
|
114
|
-
/** Whether the run's command and output are unfolded. */
|
|
152
|
+
/** Whether the run's command and output are unfolded, including after reopening. */
|
|
115
153
|
readonly detailsOpen: boolean;
|
|
116
154
|
/** The bundle the finished run added, left off until enabled from the installed screen. */
|
|
117
155
|
readonly installed: string | null;
|
|
@@ -122,15 +160,17 @@ export interface InstallState {
|
|
|
122
160
|
* `code` with its diagnostic as `reason`, or the transport's words alone;
|
|
123
161
|
* `kind` classifies a pnpm failure, and `pendingBuilds` names the packages
|
|
124
162
|
* whose install scripts pnpm left undecided, offered for approval.
|
|
125
|
-
* `
|
|
126
|
-
*
|
|
163
|
+
* `uncertainty` distinguishes a lost installation reply, an unconfirmed
|
|
164
|
+
* cancellation, and a cancellation awaiting the Host's acceptance of the run.
|
|
127
165
|
*/
|
|
128
166
|
readonly failure: {
|
|
129
167
|
readonly reason: string;
|
|
130
168
|
readonly code?: ManagementError['code'];
|
|
131
169
|
readonly kind?: PluginInstallFailureKind;
|
|
170
|
+
/** What the last failed run could not reach, as the Host attributed it: the registry, or the spec's own host. */
|
|
171
|
+
readonly failedAt?: 'registry' | 'spec-host';
|
|
132
172
|
readonly pendingBuilds?: readonly string[];
|
|
133
|
-
readonly
|
|
173
|
+
readonly uncertainty?: 'result' | 'cancellation' | 'acceptance';
|
|
134
174
|
} | null;
|
|
135
175
|
/** The packages whose install scripts the finished run was allowed to execute, saved for this profile. */
|
|
136
176
|
readonly approvedBuilds: readonly string[];
|
|
@@ -140,7 +180,7 @@ export interface InstallState {
|
|
|
140
180
|
/**
|
|
141
181
|
* Whether an installation is still owned by the Host.
|
|
142
182
|
* @param phase - the dialog's current installation phase.
|
|
143
|
-
* @returns true
|
|
183
|
+
* @returns true while a Host result or a check for an active request is outstanding.
|
|
144
184
|
*/
|
|
145
185
|
export declare function isInstallPending(phase: InstallState['phase']): boolean;
|
|
146
186
|
/** A destructive action waiting for the user's confirmation: a package's uninstall. */
|
|
@@ -163,7 +203,13 @@ export interface PluginManagerState {
|
|
|
163
203
|
}
|
|
164
204
|
/** The registration-side face the tab's slot entry injects. */
|
|
165
205
|
export interface PluginManagerFace {
|
|
206
|
+
/** Resolve local package text in the current Client locale at render time. */
|
|
207
|
+
resolveText: (text: LocalizedText) => string;
|
|
208
|
+
/** Resolve a configuration form by the Host entry id. */
|
|
209
|
+
configForm: ConfigForms['get'];
|
|
166
210
|
hooks: {
|
|
211
|
+
/** Shared accepted configuration values. */
|
|
212
|
+
configurations: SettingsDescribeFace;
|
|
167
213
|
/** Tab snapshot bound by the renderer as usePluginManager. */
|
|
168
214
|
pluginManager: SnapshotStore<PluginManagerState>;
|
|
169
215
|
/** The plugins carrying configuration, bound by the renderer as useConfigLedger. */
|
|
@@ -174,20 +220,23 @@ export interface PluginManagerFace {
|
|
|
174
220
|
/** Read the Host again. */
|
|
175
221
|
refresh: () => void;
|
|
176
222
|
openInstall: () => void;
|
|
177
|
-
/**
|
|
223
|
+
/** Hide immediately, abort a check, or request cancellation while retaining the Host-owned installation. */
|
|
178
224
|
closeInstall: () => void;
|
|
179
225
|
editInstallSpec: (text: string) => void;
|
|
180
226
|
/** Check the spec with the Host, then install it; from the failed screen, run it again. */
|
|
181
227
|
runInstall: () => void;
|
|
228
|
+
/** Fold or unfold the registry options under the spec. */
|
|
229
|
+
toggleRegistryOptions: () => void;
|
|
230
|
+
/** Pick the registry the install asks first, or type one. */
|
|
231
|
+
chooseRegistry: (choice: RegistryChoice) => void;
|
|
232
|
+
/** From the failed screen: back to the spec with the registry options unfolded. */
|
|
233
|
+
changeRegistry: () => void;
|
|
182
234
|
/** Allow the install scripts the failed run left pending, saved for this profile, and run the same spec again. */
|
|
183
235
|
approveBuildsAndRetry: () => void;
|
|
184
236
|
/** Leave the check or the failed screen for the spec, or ask the Host to stop the run and wait for its cleanup. */
|
|
185
237
|
cancelInstall: () => void;
|
|
186
|
-
/**
|
|
187
|
-
|
|
188
|
-
* it confirms; the dialog stays when it cannot. Otherwise nothing.
|
|
189
|
-
*/
|
|
190
|
-
cancelInstallAndClose: () => void;
|
|
238
|
+
/** Ask the Host for the result of an installation whose original reply was lost. */
|
|
239
|
+
reconcileInstall: () => void;
|
|
191
240
|
toggleInstallDetails: () => void;
|
|
192
241
|
/** Enable the bundle the finished install added, then close the dialog and mark it in the list. */
|
|
193
242
|
enableInstalled: () => void;
|
|
@@ -234,7 +283,11 @@ export declare class PluginManagerController {
|
|
|
234
283
|
private pendingConfirm;
|
|
235
284
|
/** Cancels the check the dialog has in flight. */
|
|
236
285
|
private inspectAbort;
|
|
286
|
+
private request;
|
|
237
287
|
private noticeSeq;
|
|
288
|
+
private registryRead;
|
|
289
|
+
/** The registry last used from this browser, kept across dialogs and page loads; null until one was used. */
|
|
290
|
+
private readonly registryMemory;
|
|
238
291
|
/**
|
|
239
292
|
* @param ctx - the tab plugin's context, whose `remote.pluginManager` and `remote.pluginInventory` namespaces answer.
|
|
240
293
|
*/
|
|
@@ -249,14 +302,18 @@ export declare class PluginManagerController {
|
|
|
249
302
|
/**
|
|
250
303
|
* Build the face the tab's slot registration injects.
|
|
251
304
|
* @param configLedger - the projection of the plugins carrying configuration, bound beside the tab's own state.
|
|
305
|
+
* @param resolveText - render-time package text resolution supplied by the locale service.
|
|
252
306
|
* @returns the tab's snapshot sources and its actions.
|
|
253
307
|
*/
|
|
254
|
-
inject(configLedger: HostObservable<ConfigLedger
|
|
308
|
+
inject(configLedger: HostObservable<ConfigLedger>, resolveText: PluginManagerFace['resolveText']): PluginManagerFace;
|
|
255
309
|
/**
|
|
256
310
|
* Follow the Host's cancellation window for this dialog's installation.
|
|
257
311
|
* @param progress - a request id and phase received from the Host.
|
|
258
312
|
*/
|
|
259
313
|
installProgress(progress: PluginInstallProgress): void;
|
|
314
|
+
private currentRegistryRead;
|
|
315
|
+
/** Read the registries the Host offers, for the dialog just opened; a refused read leaves pnpm's own and a typed one. */
|
|
316
|
+
private readRegistries;
|
|
260
317
|
/**
|
|
261
318
|
* Fold a chunk belonging to this installation into its pnpm command.
|
|
262
319
|
* A final chunk may arrive after the install answer and still updates an existing run.
|
|
@@ -288,6 +345,10 @@ export declare class PluginManagerController {
|
|
|
288
345
|
* the Host saves that permission for this profile before pnpm runs.
|
|
289
346
|
*/
|
|
290
347
|
private startInstall;
|
|
348
|
+
/** A recovery call shares the Host's active result; absent results are explicitly unknown. */
|
|
349
|
+
private reconcileInstall;
|
|
350
|
+
private settleInstall;
|
|
351
|
+
private installUncertain;
|
|
291
352
|
/**
|
|
292
353
|
* Allow the install scripts the failed run left pending and run the same
|
|
293
354
|
* spec again. Only the failed screen with pending names offers this.
|
|
@@ -295,15 +356,16 @@ export declare class PluginManagerController {
|
|
|
295
356
|
private approveBuildsAndRetry;
|
|
296
357
|
/**
|
|
297
358
|
* Leave the check or the failed screen for the spec at once; a Host-owned
|
|
298
|
-
* run is asked to stop and
|
|
359
|
+
* run is asked to stop and its state waits for the Host's word, since
|
|
299
360
|
* neither a dropped RPC nor a closed connection means pnpm has stopped.
|
|
300
|
-
* @param closeAfter - stop only a running install, and close the dialog once the Host confirms the stop.
|
|
301
361
|
*/
|
|
302
362
|
private cancelInstall;
|
|
363
|
+
/** A cancellation that overtakes installation is retried after the Host acknowledges that request. */
|
|
364
|
+
private sendCancellation;
|
|
365
|
+
private notifyHiddenInstall;
|
|
303
366
|
/**
|
|
304
|
-
*
|
|
305
|
-
*
|
|
306
|
-
* stopped the run.
|
|
367
|
+
* Release the tracked request and return to editing with its spec retained.
|
|
368
|
+
* A cancellation notice is supplied only after the Host confirms it stopped.
|
|
307
369
|
*/
|
|
308
370
|
private offerSpecAgain;
|
|
309
371
|
/**
|
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
/** Display labels and toast sentences for global plugin management. */
|
|
2
|
-
import type { ManagementError } from '@deepseek-ai/dsh-api-remotes/client';
|
|
2
|
+
import type { ManagementError, Registry } from '@deepseek-ai/dsh-api-remotes/client';
|
|
3
3
|
import type { PropsLocale } from '@deepseek-ai/dsh-client-ui-slots';
|
|
4
|
-
import type { ManagerNotice, PackageView } from './manager-store.ts';
|
|
4
|
+
import type { ManagerNotice, PackageRow, PackageView, PluginManagerFace } from './manager-store.ts';
|
|
5
5
|
/** The translate seat of the manager's dictionary. */
|
|
6
6
|
export type Translate = PropsLocale<'pluginManager'>['t'];
|
|
7
|
+
/**
|
|
8
|
+
* What a registry reads as: pnpm's own as the default registry, a known mirror by its name, any other registry by
|
|
9
|
+
* its host; and the host each names, for where the name alone would leave it unsaid.
|
|
10
|
+
* @param registry - the registry, null for the one pnpm's own configuration names.
|
|
11
|
+
* @param t - the manager's translate seat.
|
|
12
|
+
* @param resolved - the URL pnpm's own configuration names, null while unknown, when it reads as npm's own.
|
|
13
|
+
* @returns the name and the host.
|
|
14
|
+
*/
|
|
15
|
+
export declare function registryText(registry: Registry, t: Translate, resolved: string | null): {
|
|
16
|
+
name: string;
|
|
17
|
+
host: string;
|
|
18
|
+
};
|
|
7
19
|
/**
|
|
8
20
|
* What a management error reads as: the code's sentence, or, for an
|
|
9
21
|
* operation error, the Host's diagnostic as it is.
|
|
@@ -22,16 +34,26 @@ export declare function managementText(error: {
|
|
|
22
34
|
*/
|
|
23
35
|
export declare function shortName(name: string): string;
|
|
24
36
|
/**
|
|
25
|
-
*
|
|
26
|
-
* @param pkg -
|
|
27
|
-
* @param
|
|
28
|
-
* @returns localized copy
|
|
37
|
+
* Resolve installed package metadata without changing its technical identity.
|
|
38
|
+
* @param pkg - package identity and local metadata.
|
|
39
|
+
* @param resolveText - current-locale package text resolver.
|
|
40
|
+
* @returns localized copy with a technical-name fallback and the independent beta status.
|
|
29
41
|
*/
|
|
30
|
-
export declare function packageText(pkg: Pick<PackageView, 'name' | '
|
|
42
|
+
export declare function packageText(pkg: Pick<PackageView, 'name' | 'meta'>, resolveText: PluginManagerFace['resolveText']): {
|
|
31
43
|
title: string;
|
|
32
44
|
description: string | undefined;
|
|
33
45
|
beta: boolean;
|
|
34
46
|
};
|
|
47
|
+
/**
|
|
48
|
+
* Resolve a bundle row's plugin metadata, using its full module specifier as the final title fallback.
|
|
49
|
+
* @param row - row identity and local metadata.
|
|
50
|
+
* @param resolveText - current-locale package text resolver.
|
|
51
|
+
* @returns the row's display title and optional description.
|
|
52
|
+
*/
|
|
53
|
+
export declare function rowText(row: Pick<PackageRow, 'moduleName' | 'meta'>, resolveText: PluginManagerFace['resolveText']): {
|
|
54
|
+
title: string;
|
|
55
|
+
description: string | undefined;
|
|
56
|
+
};
|
|
35
57
|
/**
|
|
36
58
|
* The sentence one notice shows.
|
|
37
59
|
* @param notice - the last action's outcome.
|
|
@@ -1,28 +1,90 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The slots the Plugins page declares for plugins
|
|
3
|
-
* configuration: the official plugins listed beside the official
|
|
4
|
-
* bundle's configuration on its page, and one row's configuration
|
|
5
|
-
* that row.
|
|
6
|
-
*
|
|
2
|
+
* The slots the Plugins page declares for other plugins. Three carry a
|
|
3
|
+
* plugin's own configuration: the official plugins listed beside the official
|
|
4
|
+
* bundles, one bundle's configuration on its page, and one row's configuration
|
|
5
|
+
* opened from that row. Three more take contributions to any detail page —
|
|
6
|
+
* its head actions, the badges beside its title, and the sections under its
|
|
7
|
+
* own content — from a plugin that has something to say about bundles, rows,
|
|
8
|
+
* or official plugins it does not own. A registrant merges this contract with
|
|
9
|
+
* `import type` and registers through `ctx.slots`; it never imports this
|
|
10
|
+
* package at runtime.
|
|
7
11
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
12
|
+
* Entries accept `page` for the form with its own save control and `summary`
|
|
13
|
+
* for an official card's one-liner or a row's missing-description fallback.
|
|
14
|
+
* Bundle configuration renders only `page`. A detail contribution is rendered
|
|
15
|
+
* with the subject of the open page and decides from it whether to render at
|
|
16
|
+
* all. The page draws the title, icon, and crumb itself.
|
|
11
17
|
*/
|
|
18
|
+
import type { ConfigForm, ConfigFormSnapshot } from '@deepseek-ai/dsh-client-ui-settings/client';
|
|
12
19
|
/** The view the page asks a configuration entry for. */
|
|
13
20
|
export interface PluginConfigViewProps {
|
|
14
21
|
/** `summary` renders the one-liner alone, as text or inline nodes; `page` renders the form with its save control. */
|
|
15
22
|
readonly view: 'summary' | 'page';
|
|
23
|
+
/** Host-owned configuration values and write actions for this page's entry. */
|
|
24
|
+
readonly form?: ConfigPageForm | undefined;
|
|
25
|
+
}
|
|
26
|
+
/** One row of a bundle as a detail contribution sees it. */
|
|
27
|
+
export interface PluginRowRef {
|
|
28
|
+
/** The row id as the bundle's patch declares it. */
|
|
29
|
+
readonly rowId: string;
|
|
30
|
+
/** The module the row names. */
|
|
31
|
+
readonly moduleName: string;
|
|
32
|
+
/** Whether the row's entry runs. */
|
|
33
|
+
readonly enabled: boolean;
|
|
34
|
+
}
|
|
35
|
+
/** One bundle as a detail contribution sees it: the facts a contribution decides on, never the page's own state. */
|
|
36
|
+
export interface PluginPackageRef {
|
|
37
|
+
/** The package name. */
|
|
38
|
+
readonly name: string;
|
|
39
|
+
/** The installed version, when the Host reports one. */
|
|
40
|
+
readonly version?: string;
|
|
41
|
+
/** Whether the profile's own dependencies hold the package; false for a bundle the installation supplies. */
|
|
42
|
+
readonly installed: boolean;
|
|
43
|
+
/** Whether the bundle is switched on. */
|
|
44
|
+
readonly enabled: boolean;
|
|
45
|
+
/** The rows the bundle declares. */
|
|
46
|
+
readonly rows: readonly PluginRowRef[];
|
|
47
|
+
}
|
|
48
|
+
/** What a detail page is about: a bundle, one row of a bundle, or an official plugin listed by its `plugins.item` id. */
|
|
49
|
+
export type PluginsSubject = {
|
|
50
|
+
readonly kind: 'bundle';
|
|
51
|
+
readonly pkg: PluginPackageRef;
|
|
52
|
+
} | {
|
|
53
|
+
readonly kind: 'row';
|
|
54
|
+
readonly pkg: PluginPackageRef;
|
|
55
|
+
readonly row: PluginRowRef;
|
|
56
|
+
} | {
|
|
57
|
+
readonly kind: 'item';
|
|
58
|
+
readonly id: string;
|
|
59
|
+
};
|
|
60
|
+
/** The owner props every detail contribution is rendered with. */
|
|
61
|
+
export interface PluginDetailProps {
|
|
62
|
+
/** The subject of the open page; an entry renders null for a subject it has nothing for. */
|
|
63
|
+
readonly subject: PluginsSubject;
|
|
64
|
+
}
|
|
65
|
+
/** One user-requested bundle activation and navigation to its configuration page. */
|
|
66
|
+
export interface PluginActivationOwnerProps {
|
|
67
|
+
readonly packageName: string;
|
|
68
|
+
/** Dismiss guidance for this activation. */
|
|
69
|
+
readonly onDismiss: () => void;
|
|
70
|
+
/** Dismiss guidance and open this bundle's detail page. */
|
|
71
|
+
readonly onOpenDetails: () => void;
|
|
16
72
|
}
|
|
17
73
|
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
18
74
|
interface SlotMap {
|
|
75
|
+
/** Optional guidance after the user enables a bundle from the list, keyed by npm package name. */
|
|
76
|
+
'plugins.bundle.activation': {
|
|
77
|
+
kind: 'keyed';
|
|
78
|
+
scope: 'root';
|
|
79
|
+
owner: PluginActivationOwnerProps;
|
|
80
|
+
};
|
|
19
81
|
/**
|
|
20
82
|
* One official plugin the Plugins page lists in its Official group after
|
|
21
83
|
* the official bundles: `label` is the card's title and `order` its place.
|
|
22
84
|
* The page renders the entry as the card's one-liner (`view: 'summary'`)
|
|
23
85
|
* and, once the card is opened, as the body of the plugin's own page
|
|
24
|
-
* (`view: 'page'`). OCCUPIED by the
|
|
25
|
-
*
|
|
86
|
+
* (`view: 'page'`). OCCUPIED by the official settings pages, one companion
|
|
87
|
+
* package per host-plane namespace; a bundle's configuration belongs in
|
|
26
88
|
* `plugins.bundle.config` or `plugins.row.config` instead.
|
|
27
89
|
*/
|
|
28
90
|
'plugins.item': {
|
|
@@ -44,13 +106,51 @@ declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
|
44
106
|
* The configuration of one row a bundle declares, keyed by
|
|
45
107
|
* `<package name>#<row id>` with the row id as the bundle's patch declares
|
|
46
108
|
* it: the row on the bundle's page gains a configure control that opens
|
|
47
|
-
* the entry's page, headed by the
|
|
109
|
+
* the entry's page, headed by the plugin's display title and description.
|
|
110
|
+
* An absent description falls back to the entry's `view: 'summary'`.
|
|
48
111
|
*/
|
|
49
112
|
'plugins.row.config': {
|
|
50
113
|
kind: 'keyed';
|
|
51
114
|
scope: 'root';
|
|
52
115
|
owner: PluginConfigViewProps;
|
|
53
116
|
};
|
|
117
|
+
/**
|
|
118
|
+
* Controls at the head of a detail page, before the page's own switch and
|
|
119
|
+
* uninstall, rendered with the page's subject. An entry renders null for a
|
|
120
|
+
* subject it has no control for.
|
|
121
|
+
*/
|
|
122
|
+
'plugins.detail.actions': {
|
|
123
|
+
kind: 'list';
|
|
124
|
+
scope: 'root';
|
|
125
|
+
owner: PluginDetailProps;
|
|
126
|
+
};
|
|
127
|
+
/**
|
|
128
|
+
* Tags beside a detail page's title, after the version, beta, and problem
|
|
129
|
+
* tags the page draws itself, rendered with the page's subject.
|
|
130
|
+
*/
|
|
131
|
+
'plugins.detail.badge': {
|
|
132
|
+
kind: 'list';
|
|
133
|
+
scope: 'root';
|
|
134
|
+
owner: PluginDetailProps;
|
|
135
|
+
};
|
|
136
|
+
/**
|
|
137
|
+
* Sections under a detail page's own content: after the rows on a bundle's
|
|
138
|
+
* page, after the configuration on a row's or an official plugin's page.
|
|
139
|
+
* An entry draws its own section chrome and renders null for a subject it
|
|
140
|
+
* has nothing for.
|
|
141
|
+
*/
|
|
142
|
+
'plugins.detail.section': {
|
|
143
|
+
kind: 'list';
|
|
144
|
+
scope: 'root';
|
|
145
|
+
owner: PluginDetailProps;
|
|
146
|
+
};
|
|
54
147
|
}
|
|
55
148
|
}
|
|
149
|
+
/** Reactive page values and commands supplied by the configuration page owner. */
|
|
150
|
+
export interface ConfigPageForm {
|
|
151
|
+
/** Accepted Host values; refreshed by the page owner. */
|
|
152
|
+
readonly state: ConfigFormSnapshot<Record<string, unknown>>;
|
|
153
|
+
/** Submit all field edits together with the revision the editor read. */
|
|
154
|
+
readonly mutate: ConfigForm<Record<string, unknown>>['mutate'];
|
|
155
|
+
}
|
|
56
156
|
//# sourceMappingURL=slot-contract.d.ts.map
|
package/lib/types/index.d.ts
CHANGED
|
@@ -1,4 +1,36 @@
|
|
|
1
|
-
/** Host
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/** Host registry-response probing for the plugin installation dialog. */
|
|
2
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
3
|
+
import z from '@deepseek-ai/schemastery';
|
|
4
|
+
import { TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
|
|
5
|
+
declare module '@deepseek-ai/cordis' {
|
|
6
|
+
interface Context {
|
|
7
|
+
pluginRegistryProbe: PluginRegistryProbe;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
/** Registry-probe deadline and process-local cache policy. */
|
|
11
|
+
export interface Config {
|
|
12
|
+
/** Whether the dialog can compare the public npm registries. */
|
|
13
|
+
registryProbeEnabled: boolean;
|
|
14
|
+
/** Deadline for the parallel HTTPS probes, including response cleanup. */
|
|
15
|
+
registryProbeTimeoutMs: number;
|
|
16
|
+
/** Lifetime of a winning registry or unavailable result. */
|
|
17
|
+
registryProbeCacheTtlMs: number;
|
|
18
|
+
}
|
|
19
|
+
/** Compares public registry responses on the Host; the Client owns the initial selection. */
|
|
20
|
+
export default class PluginRegistryProbe extends TypertRemoteService {
|
|
21
|
+
private readonly config;
|
|
22
|
+
static Config: z<Partial<Config>, Config>;
|
|
23
|
+
private readonly lifetime;
|
|
24
|
+
private pending;
|
|
25
|
+
private cached;
|
|
26
|
+
constructor(ctx: Context, config: Config);
|
|
27
|
+
/**
|
|
28
|
+
* Race npm and npmmirror HTTPS ping responses through the Host's fetch proxy.
|
|
29
|
+
* Concurrent readers share a probe; a winner cancels and awaits the other request.
|
|
30
|
+
* @returns the first registry with a successful response, or null when disabled or neither responds successfully; results are cached.
|
|
31
|
+
* @throws rejects when the service has been unloaded.
|
|
32
|
+
*/
|
|
33
|
+
fastest(): Promise<string | null>;
|
|
34
|
+
private probe;
|
|
35
|
+
}
|
|
4
36
|
//# sourceMappingURL=index.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepseek-ai/dsh-client-ui-plugin-manager",
|
|
3
3
|
"description": "Plugin management for the dsh web client: the sidebar Plugins panel installs, enables, disables, retries, and composes installed plugin packages",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.7-alpha.2",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -23,7 +23,15 @@
|
|
|
23
23
|
"default": "./lib/client.js"
|
|
24
24
|
},
|
|
25
25
|
"./src/*": "./src/*",
|
|
26
|
-
"./package.json": "./package.json"
|
|
26
|
+
"./package.json": "./package.json",
|
|
27
|
+
"./typert": {
|
|
28
|
+
"types": "./lib/typert.host.d.ts",
|
|
29
|
+
"default": "./lib/typert.host.js"
|
|
30
|
+
},
|
|
31
|
+
"./remote": {
|
|
32
|
+
"types": "./lib/typert.remote-client.d.ts",
|
|
33
|
+
"default": "./lib/typert.remote-client.js"
|
|
34
|
+
}
|
|
27
35
|
},
|
|
28
36
|
"dsh": {
|
|
29
37
|
"client": {
|
|
@@ -38,32 +46,45 @@
|
|
|
38
46
|
},
|
|
39
47
|
"license": "MIT",
|
|
40
48
|
"peerDependencies": {
|
|
41
|
-
"@deepseek-ai/cordis": "
|
|
49
|
+
"@deepseek-ai/cordis": "~4.0.4"
|
|
42
50
|
},
|
|
43
51
|
"devDependencies": {
|
|
44
52
|
"@testing-library/react": "^16.1.0",
|
|
45
53
|
"@types/react": "~18.3.1",
|
|
54
|
+
"@types/react-dom": "~18.3.0",
|
|
46
55
|
"clsx": "^2.1.1",
|
|
47
56
|
"react": "^18.2.0",
|
|
48
57
|
"react-dom": "^18.2.0",
|
|
49
|
-
"@deepseek-ai/cordis": "
|
|
50
|
-
"@deepseek-ai/dsh-api-remotes": "
|
|
51
|
-
"@deepseek-ai/dsh-client-locale": "
|
|
52
|
-
"@deepseek-ai/dsh-client-store": "
|
|
53
|
-
"@deepseek-ai/dsh-client-test-runtime": "
|
|
54
|
-
"@deepseek-ai/dsh-client-ui-layout": "
|
|
55
|
-
"@deepseek-ai/dsh-client-ui-
|
|
56
|
-
"@deepseek-ai/dsh-client-ui-
|
|
57
|
-
"@deepseek-ai/dsh-client-ui-
|
|
58
|
-
"@deepseek-ai/dsh-
|
|
59
|
-
"@deepseek-ai/dsh-util-crypto": "
|
|
60
|
-
"@deepseek-ai/dsh-
|
|
58
|
+
"@deepseek-ai/cordis": "~4.0.4",
|
|
59
|
+
"@deepseek-ai/dsh-api-remotes": "0.1.7-alpha.2",
|
|
60
|
+
"@deepseek-ai/dsh-client-locale": "0.1.7-alpha.2",
|
|
61
|
+
"@deepseek-ai/dsh-client-store": "0.1.7-alpha.2",
|
|
62
|
+
"@deepseek-ai/dsh-client-test-runtime": "0.1.7-alpha.2",
|
|
63
|
+
"@deepseek-ai/dsh-client-ui-layout": "0.1.7-alpha.2",
|
|
64
|
+
"@deepseek-ai/dsh-client-ui-primitives": "0.1.7-alpha.2",
|
|
65
|
+
"@deepseek-ai/dsh-client-ui-renderer": "0.1.7-alpha.2",
|
|
66
|
+
"@deepseek-ai/dsh-client-ui-sidebar": "0.1.7-alpha.2",
|
|
67
|
+
"@deepseek-ai/dsh-package-manifest": "0.1.7-alpha.2",
|
|
68
|
+
"@deepseek-ai/dsh-util-crypto": "0.1.7-alpha.2",
|
|
69
|
+
"@deepseek-ai/dsh-plugin-manager": "0.1.7-alpha.2",
|
|
70
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.1.7-alpha.2",
|
|
71
|
+
"@deepseek-ai/dsh-client-ui-settings": "0.1.7-alpha.2"
|
|
61
72
|
},
|
|
62
73
|
"files": [
|
|
63
74
|
"lib/index.js",
|
|
64
75
|
"lib/client.js",
|
|
65
|
-
"lib/types/**/*.d.ts"
|
|
76
|
+
"lib/types/**/*.d.ts",
|
|
77
|
+
"lib/typert.host.js",
|
|
78
|
+
"lib/typert.host.d.ts",
|
|
79
|
+
"lib/typert.remote-client.js",
|
|
80
|
+
"lib/typert.remote-client.d.ts"
|
|
66
81
|
],
|
|
82
|
+
"dependencies": {
|
|
83
|
+
"zod": "^4.4.3",
|
|
84
|
+
"@deepseek-ai/dsh-timeout": "0.1.7-alpha.2",
|
|
85
|
+
"@deepseek-ai/schemastery": "~3.18.4",
|
|
86
|
+
"@deepseek-ai/dsh-typert-protocol": "0.1.7-alpha.2"
|
|
87
|
+
},
|
|
67
88
|
"scripts": {
|
|
68
89
|
"bundle": "tsdown",
|
|
69
90
|
"watch": "tsdown --watch"
|