dsh-plugin-shop 0.1.3 → 0.2.0
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 +30 -13
- package/cordis.patch.yml +4 -4
- package/lib/client.js +237 -236
- package/lib/index.js +13 -13
- package/lib/typert.host.js +63 -63
- package/lib/typert.remote-client.d.ts +13 -13
- package/lib/typert.remote-client.js +41 -41
- package/lib/types/client/{StoreTab.d.ts → ShopTab.d.ts} +11 -11
- package/lib/types/client/index.d.ts +12 -12
- package/lib/types/client/locales.d.ts +3 -3
- package/lib/types/client/present.d.ts +12 -11
- package/lib/types/client/useInstall.d.ts +3 -3
- package/lib/types/host/executor.d.ts +1 -1
- package/lib/types/host/index.d.ts +22 -22
- package/lib/types/host/types.d.ts +1 -1
- package/lib/types/index.d.ts +2 -2
- package/package.json +3 -3
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
/** The
|
|
1
|
+
/** The shop tab: browse the catalog, detail an entry, install with the
|
|
2
2
|
* acknowledgement gate, poll the install to its terminal state (§7.2).
|
|
3
3
|
* Everything the tab renders is text — summaries, capabilities, log lines,
|
|
4
4
|
* details — never markup, so hostile npm descriptions cannot inject (spec
|
|
5
5
|
* §11.3.4): no render path here may ever use dangerouslySetInnerHTML. */
|
|
6
6
|
import { type ReactNode } from 'react';
|
|
7
7
|
import type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
8
|
-
import type { InstallArgs,
|
|
8
|
+
import type { InstallArgs, ShopCatalogResult, ShopInstallResult, ShopInstallStatusResult, ShopOutdatedEntry, ShopSetEnabledResult } from '../host/index.ts';
|
|
9
9
|
/** The tab's Remote face: the Host result types, already unwrapped from the
|
|
10
10
|
* wire envelope by `index.ts`; `catalog` throws on a wire error so the tab's
|
|
11
11
|
* error state renders. */
|
|
12
|
-
export interface
|
|
12
|
+
export interface ShopTabInjected {
|
|
13
13
|
catalog: (args?: {
|
|
14
14
|
refresh?: boolean;
|
|
15
|
-
}) => Promise<
|
|
16
|
-
install: (args: InstallArgs) => Promise<
|
|
15
|
+
}) => Promise<ShopCatalogResult>;
|
|
16
|
+
install: (args: InstallArgs) => Promise<ShopInstallResult>;
|
|
17
17
|
installStatus: (args: {
|
|
18
18
|
installId: string;
|
|
19
|
-
}) => Promise<
|
|
19
|
+
}) => Promise<ShopInstallStatusResult>;
|
|
20
20
|
setEnabled: (args: {
|
|
21
21
|
name: string;
|
|
22
22
|
enabled: boolean;
|
|
23
|
-
}) => Promise<
|
|
24
|
-
outdated: () => Promise<
|
|
23
|
+
}) => Promise<ShopSetEnabledResult>;
|
|
24
|
+
outdated: () => Promise<ShopOutdatedEntry[]>;
|
|
25
25
|
}
|
|
26
26
|
/** Full component props assembled by the Settings slot renderer. */
|
|
27
|
-
export type
|
|
28
|
-
/** The
|
|
27
|
+
export type ShopTabProps = PropsRuntime<'settings.plugins.tab'> & PropsLocale<'settings.shop'> & InjectFace<ShopTabInjected>;
|
|
28
|
+
/** The shop tab root: browse, search, refresh, and render one card per
|
|
29
29
|
* entry. Data attributes on the e2e-relevant nodes follow the Task 3 list. */
|
|
30
|
-
export declare function
|
|
30
|
+
export declare function ShopTab(props: ShopTabProps): ReactNode;
|
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Shop settings surface, browser half — one tab in `settings.plugins.tab`
|
|
3
3
|
* that browses the catalog, installs with acknowledgement, toggles
|
|
4
|
-
* enablement, and lists outdated installs. Mounts the
|
|
4
|
+
* enablement, and lists outdated installs. Mounts the shop Remote itself
|
|
5
5
|
* (the assembly does not know this package) and holds no privilege beyond
|
|
6
|
-
* the five `
|
|
6
|
+
* the five `shop/*` methods (§5.3).
|
|
7
7
|
*/
|
|
8
8
|
import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client';
|
|
9
|
-
import type {
|
|
9
|
+
import type { ShopLocaleKey } from './locales.ts';
|
|
10
10
|
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
11
11
|
interface LocaleNamespaceMap {
|
|
12
|
-
/**
|
|
13
|
-
'settings.
|
|
12
|
+
/** Shop settings tab copy. */
|
|
13
|
+
'settings.shop': ShopLocaleKey;
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
/** Dictionary namespace owned by this plugin. */
|
|
17
|
-
export declare const NS = "settings.
|
|
17
|
+
export declare const NS = "settings.shop";
|
|
18
18
|
/** Services required by the tab registration and the Remote mount.
|
|
19
19
|
*
|
|
20
|
-
* `remote.
|
|
20
|
+
* `remote.shop` is deliberately ABSENT: this package both mounts its own
|
|
21
21
|
* Remote (the assembly does not know it, §7.3) and consumes it, and cordis
|
|
22
22
|
* will not let one package do both through the inject face. Declaring the
|
|
23
|
-
* face makes the boot's activation gate wait for the `remote.
|
|
23
|
+
* face makes the boot's activation gate wait for the `remote.shop` service —
|
|
24
24
|
* which only this package's own apply can register — and the real web boot
|
|
25
|
-
* deadlocked on exactly that ("waiting for service: remote.
|
|
26
|
-
* namespace is therefore read through the reflect
|
|
25
|
+
* deadlocked on exactly that ("waiting for service: remote.shop"). The
|
|
26
|
+
* namespace is therefore read through the reflect shop instead (`ctx.get`,
|
|
27
27
|
* see apply), which has no inject requirement. */
|
|
28
28
|
export declare const inject: string[];
|
|
29
|
-
/** Mount the
|
|
29
|
+
/** Mount the shop Remote and contribute the shop tab. */
|
|
30
30
|
export declare function apply(ctx: ClientContext): Promise<void>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Copy dictionaries for the
|
|
1
|
+
/** Copy dictionaries for the shop Settings tab. */
|
|
2
2
|
/** Simplified Chinese dictionary and key source of truth. */
|
|
3
3
|
export declare const zh: {
|
|
4
4
|
tab: string;
|
|
@@ -49,8 +49,8 @@ export declare const zh: {
|
|
|
49
49
|
toggleFailed: string;
|
|
50
50
|
hotApplyNote: string;
|
|
51
51
|
};
|
|
52
|
-
/**
|
|
53
|
-
export type
|
|
52
|
+
/** Shop locale key union. */
|
|
53
|
+
export type ShopLocaleKey = keyof typeof zh;
|
|
54
54
|
/** English dictionary checked against the Chinese key set. */
|
|
55
55
|
export declare const en: {
|
|
56
56
|
tab: string;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
/** Pure presentation core for the
|
|
1
|
+
/** Pure presentation core for the shop tab (§5.1 Client half). No React, no
|
|
2
2
|
* timers, no I/O: every function here maps a value to a value, so fixtures
|
|
3
3
|
* drive all of it. */
|
|
4
|
-
import type {
|
|
4
|
+
import type { ShopLocaleKey } from './locales.ts';
|
|
5
5
|
import type { CatalogEntry, InstallRejectionCode } from '../host/index.ts';
|
|
6
6
|
/** Tier → locale key, for the entry-card tier badge (§6.2). */
|
|
7
|
-
export declare function tierKey(tier: CatalogEntry['tier']):
|
|
8
|
-
/** A derived listing has no author-declared catalog section; the
|
|
7
|
+
export declare function tierKey(tier: CatalogEntry['tier']): ShopLocaleKey;
|
|
8
|
+
/** A derived listing has no author-declared catalog section; the shop
|
|
9
9
|
* presents it as unclaimed, which is the signal that prompts an author to add
|
|
10
10
|
* one (§6.1). Never present a derived entry as though the author wrote it. */
|
|
11
11
|
export declare function isUnclaimed(entry: CatalogEntry): boolean;
|
|
@@ -16,7 +16,7 @@ export declare const ACKNOWLEDGEMENT_EN = "Once installed, this plugin holds the
|
|
|
16
16
|
export declare const ACKNOWLEDGEMENT_ZH = "\u5B89\u88C5\u540E\uFF0C\u6B64\u63D2\u4EF6\u5C06\u62E5\u6709\u4E0E\u5185\u7F6E\u63D2\u4EF6\u76F8\u540C\u7684\u6743\u9650\uFF1A\u8BFB\u5199\u4F60\u7684\u6587\u4EF6\u3001\u6267\u884C shell \u547D\u4EE4\uFF0C\u4EE5\u53CA\u8BFB\u53D6\u548C\u4FEE\u6539\u53D1\u9001\u7ED9\u6A21\u578B\u7684\u8BF7\u6C42\u3002\u5B83\u672A\u7ECF\u5BA1\u6838\u3002";
|
|
17
17
|
/** Install rejection code → locale key, for the rejected-state code label
|
|
18
18
|
* (§7.2): every rejection the host can return has a human label here. */
|
|
19
|
-
export declare function rejectionCodeKey(code: InstallRejectionCode):
|
|
19
|
+
export declare function rejectionCodeKey(code: InstallRejectionCode): ShopLocaleKey;
|
|
20
20
|
/** One polled install status (§7.3 wire data), structural. */
|
|
21
21
|
export interface InstallStatusShape {
|
|
22
22
|
found: boolean;
|
|
@@ -63,16 +63,17 @@ export declare const INSTALL_POLL_MS = 1000;
|
|
|
63
63
|
* unrelated event and a no-op, like any other event it does not recognize. */
|
|
64
64
|
export declare function reduceInstall(state: InstallView, event: InstallEvent): InstallView;
|
|
65
65
|
/**
|
|
66
|
-
* Whether a package name reads as a plugin
|
|
67
|
-
* plugins, e.g. `dsh-plugin-shop`, `dsh-store`, `pluginstore`). The
|
|
66
|
+
* Whether a package name reads as a plugin shop (a marketplace for dsh
|
|
67
|
+
* plugins, e.g. `dsh-plugin-shop`, `dsh-store`, `pluginstore`). The shop
|
|
68
68
|
* tab hides these so the market does not list competing markets.
|
|
69
69
|
*
|
|
70
70
|
* Precision over recall: a name merely CONTAINING a keyword segment without
|
|
71
71
|
* a plugin qualifier or a keyword ending (`market-data-provider`,
|
|
72
|
-
* `marketplace-hub`) is NOT a
|
|
73
|
-
* match on the substring "store".
|
|
72
|
+
* `marketplace-hub`) is NOT a shop plugin, and `dsh-restore` must never
|
|
73
|
+
* match on the substring "store". The keyword list keeps "store" on purpose:
|
|
74
|
+
* it matches other people's package names, not ours.
|
|
74
75
|
*/
|
|
75
|
-
export declare function
|
|
76
|
+
export declare function isShopLike(name: string): boolean;
|
|
76
77
|
/** The locale key for one entry's category — derived entries read as `other`
|
|
77
78
|
* (§6.1: a derived listing has no declared category). */
|
|
78
|
-
export declare function categoryKey(entry: CatalogEntry):
|
|
79
|
+
export declare function categoryKey(entry: CatalogEntry): ShopLocaleKey;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Install driving hook for one entry: start, poll to terminal, reset. */
|
|
2
2
|
import { type InstallView } from './present.ts';
|
|
3
|
-
import type { InstallArgs,
|
|
3
|
+
import type { InstallArgs, ShopInstallResult, ShopInstallStatusResult } from '../host/index.ts';
|
|
4
4
|
export interface UseInstallResult {
|
|
5
5
|
view: InstallView;
|
|
6
6
|
start: (args: InstallArgs) => Promise<void>;
|
|
@@ -9,6 +9,6 @@ export interface UseInstallResult {
|
|
|
9
9
|
/** Drive one install: rejections, the polling loop at INSTALL_POLL_MS, and
|
|
10
10
|
* terminal states. The interval is cleared on unmount and whenever the view
|
|
11
11
|
* leaves `running`, so a done/failed/rejected install never polls again. */
|
|
12
|
-
export declare function useInstall(install: (args: InstallArgs) => Promise<
|
|
12
|
+
export declare function useInstall(install: (args: InstallArgs) => Promise<ShopInstallResult>, installStatus: (args: {
|
|
13
13
|
installId: string;
|
|
14
|
-
}) => Promise<
|
|
14
|
+
}) => Promise<ShopInstallStatusResult>): UseInstallResult;
|
|
@@ -14,7 +14,7 @@ interface RunningInstall {
|
|
|
14
14
|
/**
|
|
15
15
|
* Run one `dsh plugin --profile <profile> add <spec>` and track it.
|
|
16
16
|
* Never rolls back; a failure surfaces stderr verbatim plus the recovery hint
|
|
17
|
-
* (§10). The
|
|
17
|
+
* (§10). The shop never passes build-script flags: `allowBuilds` stays the
|
|
18
18
|
* user's explicit decision in the CLI (§7.2).
|
|
19
19
|
* The child inherits the current environment unless `env` is given — the
|
|
20
20
|
* real-install test pins DSH_HOME to a temporary directory this way.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/** ShopGateway: the Host half of dsh-plugin-shop (§5.1). */
|
|
2
2
|
import type { Context } from '@deepseek-ai/cordis';
|
|
3
3
|
import { TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
|
|
4
4
|
import { loadCatalog, type LoadCatalogOptions } from './catalog.ts';
|
|
@@ -7,7 +7,7 @@ import { type InstallArgs, type InstallRejectionCode } from './install.ts';
|
|
|
7
7
|
import { type InstallStatus } from './executor.ts';
|
|
8
8
|
export type { InstallArgs, InstallRejectionCode } from './install.ts';
|
|
9
9
|
export type { CatalogEntry } from './types.ts';
|
|
10
|
-
/** One Loader inventory entry, structurally — the
|
|
10
|
+
/** One Loader inventory entry, structurally — the shop never depends on
|
|
11
11
|
* cordis-plugin-loader, whose types do not reach this package's typecheck. */
|
|
12
12
|
export interface InventoryEntry {
|
|
13
13
|
entryId: string;
|
|
@@ -15,7 +15,7 @@ export interface InventoryEntry {
|
|
|
15
15
|
enabled: boolean;
|
|
16
16
|
}
|
|
17
17
|
/** Test-only injection points; production callers pass nothing. */
|
|
18
|
-
export interface
|
|
18
|
+
export interface ShopGatewayOptions {
|
|
19
19
|
catalogUrl?: string;
|
|
20
20
|
cacheDir?: string;
|
|
21
21
|
loadCatalog?: (options: LoadCatalogOptions) => ReturnType<typeof loadCatalog>;
|
|
@@ -30,9 +30,9 @@ export interface StoreGatewayOptions {
|
|
|
30
30
|
};
|
|
31
31
|
dshBin?: string;
|
|
32
32
|
}
|
|
33
|
-
/** `
|
|
33
|
+
/** `shop/installStart` result (§7.3): rejections are typed wire values with an
|
|
34
34
|
* author-readable `detail`, not thrown RPC errors. */
|
|
35
|
-
export type
|
|
35
|
+
export type ShopInstallResult = {
|
|
36
36
|
ok: true;
|
|
37
37
|
installId: string;
|
|
38
38
|
} | {
|
|
@@ -40,33 +40,33 @@ export type StoreInstallResult = {
|
|
|
40
40
|
code: InstallRejectionCode;
|
|
41
41
|
detail: string;
|
|
42
42
|
};
|
|
43
|
-
export interface
|
|
43
|
+
export interface ShopInstallStatusResult extends InstallStatus {
|
|
44
44
|
found: boolean;
|
|
45
45
|
}
|
|
46
|
-
/** `
|
|
46
|
+
/** `shop/setEnabled` result (§7.3): an unknown name is a typed wire value,
|
|
47
47
|
* not a thrown RPC error. */
|
|
48
|
-
export interface
|
|
48
|
+
export interface ShopSetEnabledResult {
|
|
49
49
|
ok: boolean;
|
|
50
50
|
detail?: string;
|
|
51
51
|
}
|
|
52
|
-
/** `
|
|
53
|
-
export interface
|
|
52
|
+
/** `shop/outdated` entry (§7.3): one installed plugin behind the catalog. */
|
|
53
|
+
export interface ShopOutdatedEntry {
|
|
54
54
|
name: string;
|
|
55
55
|
installed: string;
|
|
56
56
|
latest: string;
|
|
57
57
|
}
|
|
58
|
-
/** `
|
|
59
|
-
export interface
|
|
58
|
+
/** `shop/catalog` result (§7.3), plus the denied list for the install gate's UI. */
|
|
59
|
+
export interface ShopCatalogResult {
|
|
60
60
|
schemaVersion: number;
|
|
61
61
|
builtAt: string;
|
|
62
62
|
stale: boolean;
|
|
63
63
|
plugins: CatalogEntry[];
|
|
64
64
|
denied: DeniedEntry[];
|
|
65
65
|
}
|
|
66
|
-
/** Remote-only service exposing the
|
|
66
|
+
/** Remote-only service exposing the shop Remote methods of §7.3.
|
|
67
67
|
*
|
|
68
|
-
* @typert service
|
|
69
|
-
export declare class
|
|
68
|
+
* @typert service shop */
|
|
69
|
+
export declare class ShopGateway extends TypertRemoteService {
|
|
70
70
|
private readonly options;
|
|
71
71
|
/** The profile dsh installs into; discovered from this module's own
|
|
72
72
|
* location when the caller does not supply one. */
|
|
@@ -86,7 +86,7 @@ export declare class StoreGateway extends TypertRemoteService {
|
|
|
86
86
|
private readonly installs;
|
|
87
87
|
/** Every install id in insertion order, oldest first; finished-record eviction walks this from the front. */
|
|
88
88
|
private readonly installOrder;
|
|
89
|
-
constructor(ctx: Context, options?:
|
|
89
|
+
constructor(ctx: Context, options?: ShopGatewayOptions);
|
|
90
90
|
/** The boot's Loader root directory (the active profile's `cordis.yml`
|
|
91
91
|
* directory, carried on `ctx.baseUrl`), when present. A `link:` install
|
|
92
92
|
* keeps this package at its source location, so the walk-up from
|
|
@@ -104,18 +104,18 @@ export declare class StoreGateway extends TypertRemoteService {
|
|
|
104
104
|
setEnabled(args: {
|
|
105
105
|
name: string;
|
|
106
106
|
enabled: boolean;
|
|
107
|
-
}):
|
|
107
|
+
}): ShopSetEnabledResult;
|
|
108
108
|
private rowConfig;
|
|
109
109
|
/** Browse the catalog (§7.3): cached snapshot, refreshed on demand. */
|
|
110
110
|
catalog(args?: {
|
|
111
111
|
refresh?: boolean;
|
|
112
|
-
}): Promise<
|
|
112
|
+
}): Promise<ShopCatalogResult>;
|
|
113
113
|
/**
|
|
114
114
|
* Install one cataloged version into the profile (§7.2). The four rejection
|
|
115
115
|
* paths run against this Host's snapshot before anything is spawned; only a
|
|
116
116
|
* passing request reaches the executor.
|
|
117
117
|
*/
|
|
118
|
-
install(args: InstallArgs): Promise<
|
|
118
|
+
install(args: InstallArgs): Promise<ShopInstallResult>;
|
|
119
119
|
/** Bound retained finished records at MAX_FINISHED_INSTALLS, evicting the
|
|
120
120
|
* oldest finished ones (insertion order, oldest first). Running records
|
|
121
121
|
* are never evicted; an id absent from the map reports `found: false`. */
|
|
@@ -123,8 +123,8 @@ export declare class StoreGateway extends TypertRemoteService {
|
|
|
123
123
|
/** Poll one install's progress (§7.2); unknown ids report `found: false`. */
|
|
124
124
|
installStatus(args: {
|
|
125
125
|
installId: string;
|
|
126
|
-
}):
|
|
126
|
+
}): ShopInstallStatusResult;
|
|
127
127
|
/** Installed plugins whose installed version is older than the catalog's (§7.3). */
|
|
128
|
-
outdated(): Promise<
|
|
128
|
+
outdated(): Promise<ShopOutdatedEntry[]>;
|
|
129
129
|
}
|
|
130
|
-
export default
|
|
130
|
+
export default ShopGateway;
|
package/lib/types/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
/** Package main: the
|
|
2
|
-
export {
|
|
1
|
+
/** Package main: the shop's Host half, mounted by the bundle row. */
|
|
2
|
+
export { ShopGateway, type ShopGatewayOptions } from './host/index.ts';
|
|
3
3
|
export { default } from './host/index.ts';
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-plugin-shop",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "The DeepSeek Harness plugin
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "The DeepSeek Harness plugin shop: browse, install, enable, and update dsh plugins from a git-auditable catalog.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/LivXue/dsh-plugin-shop.git"
|
|
@@ -113,7 +113,7 @@
|
|
|
113
113
|
"vitest": "^2.1.4"
|
|
114
114
|
},
|
|
115
115
|
"scripts": {
|
|
116
|
-
"build": "tsdown && tsc && tsdown -c tsdown.client.config.ts",
|
|
116
|
+
"build": "node -e \"require('node:fs').rmSync('lib',{recursive:true,force:true})\" && tsdown && tsc && tsdown -c tsdown.client.config.ts",
|
|
117
117
|
"test": "tsdown && tsdown -c tsdown.client.config.ts && vitest run",
|
|
118
118
|
"typecheck": "tsdown && tsc --noEmit && tsc -p tsconfig.test.json"
|
|
119
119
|
}
|