@lingxi-ai-cn/dsh-plugin-hub 0.1.0-rc.8

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 DeepSeek
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,26 @@
1
+ # @lingxi-ai-cn/dsh-plugin-hub
2
+
3
+ English | [中文](README.zh.md)
4
+
5
+ Provider-neutral human Plugin Hub capability exposed as `ctx.pluginHub`. The service owns stable catalog, installed-state, detached-plan, staging, and activation-handoff DTOs plus provider registration, transient progress events, the error taxonomy, and an explicit `supportsProfileMutations()` capability. HTTP, cache, signatures, profile mutation, package-manager work, journals, and maintenance processes belong to providers. A catalog-only provider reports `false`, so a consumer can keep discovery and installed truth active without presenting an in-process mutation action.
6
+
7
+ Catalog detail DTOs preserve repository archive state, declared and verified operating systems, bounded curation notes, and structured advisories with severity and recommended action. These are discovery and risk-display facts; none can establish installability or replace signed descriptor verification.
8
+
9
+ Catalog rows may also carry Registry-owned categories, package kind, metadata source, and repository primary language. These fields are presentation and optional search filters only; clients do not infer them from README text, descriptions, repository names, or popularity.
10
+
11
+ Catalog search accepts provider-neutral `relevance`, `stars`, `updated`, and `newest` ordering. Providers keep continuation cursors opaque and bind them to the complete request, including ordering; catalog ordering remains human discovery state and does not affect installability or verification.
12
+
13
+ Install planning accepts only opaque `PluginId` and `PluginVersionId` values. Plans expose exact confirmation facts but never artifact URLs, local paths, executables, package-manager arguments, or a signature bypass. Staging and activation accept only provider-issued branded ids, and `markMaintenanceReady()` is a no-op outside an authenticated relaunch handoff.
14
+
15
+ ## Model Experience
16
+
17
+ None, as the service exposes catalog rows, README text, and progress only to human UI consumers and never writes them to the Session log.
18
+
19
+ #### KV Cache effect
20
+
21
+ No effect; the service does not add, replace, or retain model-request content.
22
+
23
+ ## Known Limitations and Deferred Work
24
+
25
+ - **Provider implementation required** - the Service Definition performs no Registry verification or profile mutation by itself; the mounted Host provider owns every trust and transaction decision.
26
+ - **No rollback contract** - retained generations, history, rollback planning, and advisory remediation remain outside the initial install lifecycle.
package/README.zh.md ADDED
@@ -0,0 +1,26 @@
1
+ # @lingxi-ai-cn/dsh-plugin-hub
2
+
3
+ 中文 | [English](README.md)
4
+
5
+ 这是通过 `ctx.pluginHub` 提供的 provider-neutral 人工 Plugin Hub 能力。服务拥有稳定的目录、installed state、detached plan、staging 和 activation handoff DTO,以及 provider 注册、临时 progress event、错误分类和显式 `supportsProfileMutations()` capability;HTTP、cache、signature、profile 修改、包管理器、journal 和 maintenance process 都属于 provider。只提供目录的 provider 会报告 `false`,因此 consumer 可以继续提供发现与已安装事实,而不呈现进程内修改操作。
6
+
7
+ 目录详情 DTO 会保留 repository archive 状态、声明与验证过的 operating system、有界 curation note,以及带 severity 与 recommended action 的结构化 advisory。这些只是发现和风险展示事实;任何一项都不能确立 installability,也不能替代 signed descriptor 校验。
8
+
9
+ 目录 row 还可以携带由 Registry 提供的 category、package kind、metadata source 和 repository primary language。这些字段只用于展示和可选搜索筛选;client 不会从 README text、description、repository name 或 popularity 推断它们。
10
+
11
+ 目录 search 接受 provider-neutral 的 `relevance`、`stars`、`updated` 和 `newest` ordering。provider 会保持 continuation cursor opaque,并将其绑定到包含 ordering 在内的完整 request;目录 ordering 只属于人工发现 state,不会影响 installability 或 verification。
12
+
13
+ 安装计划只接受 opaque `PluginId` 和 `PluginVersionId`。plan 公开精确确认事实,但绝不公开 artifact URL、本地路径、executable、包管理器参数或 signature bypass。staging 和 activation 只接受 provider 签发的 branded id;`markMaintenanceReady()` 在 authenticated relaunch handoff 之外是 no-op。
14
+
15
+ ## Model Experience
16
+
17
+ 无,因为该服务只向人工 UI consumer 提供目录、README 和进度,并且绝不会将它们写入 Session log。
18
+
19
+ #### KV Cache effect
20
+
21
+ 无影响;该服务不会添加、替换或保留模型请求内容。
22
+
23
+ ## Known Limitations and Deferred Work
24
+
25
+ - **需要 provider 实现** — Service Definition 自身不执行 Registry 校验或 profile 修改;挂载的 Host provider 拥有全部 trust 和 transaction decision。
26
+ - **无 rollback contract** — generation 保留、history、rollback plan 和 advisory remediation 不属于首个安装 lifecycle。
package/lib/index.js ADDED
@@ -0,0 +1,197 @@
1
+ import { Service } from "@deepseek-ai/cordis";
2
+ //#region lib/types/types.js
3
+ /** Provider-neutral Plugin Hub catalog vocabulary. */
4
+ /**
5
+ * Brand a catalog plugin id received from a provider.
6
+ * @param value - provider-issued opaque id.
7
+ * @returns the same string with the PluginId brand.
8
+ */
9
+ function PluginId(value) {
10
+ return value;
11
+ }
12
+ /**
13
+ * Brand a catalog version id received from a provider.
14
+ * @param value - provider-issued opaque id.
15
+ * @returns the same string with the PluginVersionId brand.
16
+ */
17
+ function PluginVersionId(value) {
18
+ return value;
19
+ }
20
+ /**
21
+ * Brand a provider-issued detached plan id.
22
+ * @param value - provider-issued opaque id.
23
+ * @returns the same string with the PluginChangePlanId brand.
24
+ */
25
+ function PluginChangePlanId(value) {
26
+ return value;
27
+ }
28
+ /**
29
+ * Brand a provider-issued transaction id.
30
+ * @param value - provider-issued opaque id.
31
+ * @returns the same string with the PluginTransactionId brand.
32
+ */
33
+ function PluginTransactionId(value) {
34
+ return value;
35
+ }
36
+ /** Stable wire/API version currently understood by the local consumer. */
37
+ const PLUGIN_HUB_API_VERSION = "dsh.plugin-hub/v1";
38
+ /** Typed failure that callers can branch on without parsing a message. */
39
+ var PluginHubError = class extends Error {
40
+ /** Stable category consumed by UI and retry policy. */
41
+ code;
42
+ /**
43
+ * @param message - bounded public diagnostic.
44
+ * @param code - stable machine-readable category.
45
+ * @param options - optional underlying cause.
46
+ */
47
+ constructor(message, code, options) {
48
+ super(message, options);
49
+ this.name = "PluginHubError";
50
+ this.code = code;
51
+ }
52
+ };
53
+ //#endregion
54
+ //#region lib/types/index.js
55
+ /** Plugin Hub Service Definition for read-only catalog consumers. */
56
+ /** Read-only provider registry and facade consumed by native TUI. */
57
+ var PluginHubRuntime = class extends Service {
58
+ providers = /* @__PURE__ */ new Map();
59
+ constructor(ctx) {
60
+ super(ctx, "pluginHub");
61
+ }
62
+ /**
63
+ * Register one provider; the effect owns removal on unload.
64
+ * @param provider - provider implementation for this fiber.
65
+ * @returns disposer that removes the exact registration.
66
+ */
67
+ registerProvider(provider) {
68
+ if (this.providers.size > 0) throw new Error("a plugin hub provider is already registered");
69
+ const dispose = this.ctx.effect(function* () {
70
+ this.providers.set(provider.id, provider);
71
+ yield () => {
72
+ this.providers.delete(provider.id);
73
+ };
74
+ }.bind(this), "pluginHub.registerProvider()");
75
+ return () => {
76
+ dispose();
77
+ };
78
+ }
79
+ /**
80
+ * Inspect provider availability without starting I/O.
81
+ * @returns whether at least one provider is mounted for optional consumers.
82
+ */
83
+ hasProvider() {
84
+ return this.providers.size > 0;
85
+ }
86
+ /**
87
+ * Inspect whether the mounted provider may mutate the active profile.
88
+ * Missing providers and catalog-only providers both return false.
89
+ * @returns provider-declared profile mutation capability.
90
+ */
91
+ supportsProfileMutations() {
92
+ const [provider] = this.providers.values();
93
+ return provider?.profileMutations === true;
94
+ }
95
+ /** Return the one configured provider or a stable unavailable error. */
96
+ provider() {
97
+ const [provider] = this.providers.values();
98
+ if (provider === void 0) throw new PluginHubError("No Plugin Hub provider is configured.", "REGISTRY_UNAVAILABLE");
99
+ return provider;
100
+ }
101
+ /**
102
+ * Read provider health and catalog freshness.
103
+ * @param signal - optional caller cancellation signal.
104
+ * @returns provider status.
105
+ */
106
+ async status(signal) {
107
+ return this.provider().status(signal);
108
+ }
109
+ /**
110
+ * Search the bounded catalog.
111
+ * @param request - literal search and filter request.
112
+ * @param signal - optional caller cancellation signal.
113
+ * @returns one provider page.
114
+ */
115
+ async search(request, signal) {
116
+ return this.provider().search(request, signal);
117
+ }
118
+ /**
119
+ * Load one complete read-only plugin description.
120
+ * @param pluginId - opaque catalog plugin id.
121
+ * @param signal - optional caller cancellation signal.
122
+ * @returns one provider detail record.
123
+ */
124
+ async plugin(pluginId, signal) {
125
+ return this.provider().plugin(pluginId, signal);
126
+ }
127
+ /**
128
+ * Inspect profile-local installed truth.
129
+ * @param signal - optional caller cancellation signal.
130
+ * @returns exact active-profile revision, bundle order, and third-party dependencies.
131
+ */
132
+ async installed(signal) {
133
+ return this.provider().installed(signal);
134
+ }
135
+ /**
136
+ * Verify one selected Registry version and create a detached install or update plan.
137
+ * @param pluginId - opaque selected plugin id.
138
+ * @param versionId - opaque selected version id.
139
+ * @param signal - optional caller cancellation signal.
140
+ * @returns expiring plan containing only user-confirmation facts.
141
+ */
142
+ async planInstall(pluginId, versionId, signal) {
143
+ return this.provider().planInstall(pluginId, versionId, signal);
144
+ }
145
+ /**
146
+ * Create a detached removal plan from local installed truth.
147
+ * @param packageName - exact installed dependency name.
148
+ * @param signal - optional caller cancellation signal.
149
+ * @returns expiring local removal plan.
150
+ */
151
+ async planRemove(packageName, signal) {
152
+ return this.provider().planRemove(packageName, signal);
153
+ }
154
+ /**
155
+ * Prepare a still-current plan in an inactive staging generation.
156
+ * @param planId - provider-issued detached plan id.
157
+ * @param signal - optional caller cancellation signal.
158
+ * @returns durable staged transaction; the active profile is unchanged.
159
+ */
160
+ async stage(planId, signal) {
161
+ return this.provider().stage(planId, signal);
162
+ }
163
+ /**
164
+ * Discard one pre-activation transaction.
165
+ * @param transactionId - provider-issued transaction id.
166
+ * @param signal - optional caller cancellation signal.
167
+ */
168
+ async discard(transactionId, signal) {
169
+ await this.provider().discard(transactionId, signal);
170
+ }
171
+ /**
172
+ * Transfer a staged transaction to the maintenance process.
173
+ * @param transactionId - provider-issued staged transaction id.
174
+ * @param signal - optional caller cancellation signal.
175
+ * @returns handoff state after the maintenance process starts waiting.
176
+ */
177
+ async createMaintenanceHandoff(transactionId, signal) {
178
+ return this.provider().createMaintenanceHandoff(transactionId, signal);
179
+ }
180
+ /**
181
+ * Publish the exact maintenance ready marker after the relaunched TUI mounts.
182
+ * A normal boot without a handoff is a no-op.
183
+ * @param signal - optional caller cancellation signal.
184
+ */
185
+ async markMaintenanceReady(signal) {
186
+ await this.provider().markMaintenanceReady(signal);
187
+ }
188
+ /**
189
+ * Publish transient provider progress to in-process UI listeners.
190
+ * @param progress - bounded public progress update.
191
+ */
192
+ publishProgress(progress) {
193
+ this.ctx.emit("plugin-hub/progress", progress);
194
+ }
195
+ };
196
+ //#endregion
197
+ export { PLUGIN_HUB_API_VERSION, PluginChangePlanId, PluginHubError, PluginHubRuntime, PluginHubRuntime as default, PluginId, PluginTransactionId, PluginVersionId };
@@ -0,0 +1,11 @@
1
+ //#region lib/types/invariant.js
2
+ /** Package-owned invariant companion for the Plugin Hub Service Definition. */
3
+ const PACKAGE_NAME = "@lingxi-ai-cn/dsh-plugin-hub";
4
+ const name = "plugin-hub-invariant";
5
+ const inject = ["invariants"];
6
+ /** No runtime invariant: provider registrations are private and effects own their disposal. */
7
+ const install = () => {};
8
+ /** Register this package's invariant companion. */
9
+ const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
10
+ //#endregion
11
+ export { apply, inject, name };
@@ -0,0 +1,115 @@
1
+ /** Plugin Hub Service Definition for read-only catalog consumers. */
2
+ import { Context, Service } from '@deepseek-ai/cordis';
3
+ import type { InstalledPluginSnapshot, PluginChangePlan, PluginChangePlanId, PluginDetail, PluginHubProgress, PluginHubProvider, PluginHubStatus, PluginId, PluginMaintenanceHandoff, PluginSearchPage, PluginSearchRequest, PluginTransactionId, PluginVersionId, StagedPluginTransaction } from './types.ts';
4
+ export * from './types.ts';
5
+ declare module '@deepseek-ai/cordis' {
6
+ interface Context {
7
+ pluginHub: PluginHubRuntime;
8
+ }
9
+ interface Events {
10
+ /**
11
+ * Provider progress is transient UI state and is never durable.
12
+ * @param progress - bounded public progress.
13
+ * @mode emit
14
+ */
15
+ 'plugin-hub/progress'(progress: PluginHubProgress): void;
16
+ }
17
+ }
18
+ /** Read-only provider registry and facade consumed by native TUI. */
19
+ export declare class PluginHubRuntime extends Service {
20
+ private readonly providers;
21
+ constructor(ctx: Context);
22
+ /**
23
+ * Register one provider; the effect owns removal on unload.
24
+ * @param provider - provider implementation for this fiber.
25
+ * @returns disposer that removes the exact registration.
26
+ */
27
+ registerProvider(provider: PluginHubProvider): () => void;
28
+ /**
29
+ * Inspect provider availability without starting I/O.
30
+ * @returns whether at least one provider is mounted for optional consumers.
31
+ */
32
+ hasProvider(): boolean;
33
+ /**
34
+ * Inspect whether the mounted provider may mutate the active profile.
35
+ * Missing providers and catalog-only providers both return false.
36
+ * @returns provider-declared profile mutation capability.
37
+ */
38
+ supportsProfileMutations(): boolean;
39
+ /** Return the one configured provider or a stable unavailable error. */
40
+ private provider;
41
+ /**
42
+ * Read provider health and catalog freshness.
43
+ * @param signal - optional caller cancellation signal.
44
+ * @returns provider status.
45
+ */
46
+ status(signal?: AbortSignal): Promise<PluginHubStatus>;
47
+ /**
48
+ * Search the bounded catalog.
49
+ * @param request - literal search and filter request.
50
+ * @param signal - optional caller cancellation signal.
51
+ * @returns one provider page.
52
+ */
53
+ search(request: PluginSearchRequest, signal?: AbortSignal): Promise<PluginSearchPage>;
54
+ /**
55
+ * Load one complete read-only plugin description.
56
+ * @param pluginId - opaque catalog plugin id.
57
+ * @param signal - optional caller cancellation signal.
58
+ * @returns one provider detail record.
59
+ */
60
+ plugin(pluginId: PluginId, signal?: AbortSignal): Promise<PluginDetail>;
61
+ /**
62
+ * Inspect profile-local installed truth.
63
+ * @param signal - optional caller cancellation signal.
64
+ * @returns exact active-profile revision, bundle order, and third-party dependencies.
65
+ */
66
+ installed(signal?: AbortSignal): Promise<InstalledPluginSnapshot>;
67
+ /**
68
+ * Verify one selected Registry version and create a detached install or update plan.
69
+ * @param pluginId - opaque selected plugin id.
70
+ * @param versionId - opaque selected version id.
71
+ * @param signal - optional caller cancellation signal.
72
+ * @returns expiring plan containing only user-confirmation facts.
73
+ */
74
+ planInstall(pluginId: PluginId, versionId: PluginVersionId, signal?: AbortSignal): Promise<PluginChangePlan>;
75
+ /**
76
+ * Create a detached removal plan from local installed truth.
77
+ * @param packageName - exact installed dependency name.
78
+ * @param signal - optional caller cancellation signal.
79
+ * @returns expiring local removal plan.
80
+ */
81
+ planRemove(packageName: string, signal?: AbortSignal): Promise<PluginChangePlan>;
82
+ /**
83
+ * Prepare a still-current plan in an inactive staging generation.
84
+ * @param planId - provider-issued detached plan id.
85
+ * @param signal - optional caller cancellation signal.
86
+ * @returns durable staged transaction; the active profile is unchanged.
87
+ */
88
+ stage(planId: PluginChangePlanId, signal?: AbortSignal): Promise<StagedPluginTransaction>;
89
+ /**
90
+ * Discard one pre-activation transaction.
91
+ * @param transactionId - provider-issued transaction id.
92
+ * @param signal - optional caller cancellation signal.
93
+ */
94
+ discard(transactionId: PluginTransactionId, signal?: AbortSignal): Promise<void>;
95
+ /**
96
+ * Transfer a staged transaction to the maintenance process.
97
+ * @param transactionId - provider-issued staged transaction id.
98
+ * @param signal - optional caller cancellation signal.
99
+ * @returns handoff state after the maintenance process starts waiting.
100
+ */
101
+ createMaintenanceHandoff(transactionId: PluginTransactionId, signal?: AbortSignal): Promise<PluginMaintenanceHandoff>;
102
+ /**
103
+ * Publish the exact maintenance ready marker after the relaunched TUI mounts.
104
+ * A normal boot without a handoff is a no-op.
105
+ * @param signal - optional caller cancellation signal.
106
+ */
107
+ markMaintenanceReady(signal?: AbortSignal): Promise<void>;
108
+ /**
109
+ * Publish transient provider progress to in-process UI listeners.
110
+ * @param progress - bounded public progress update.
111
+ */
112
+ publishProgress(progress: PluginHubProgress): void;
113
+ }
114
+ export default PluginHubRuntime;
115
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,7 @@
1
+ /** Package-owned invariant companion for the Plugin Hub Service Definition. */
2
+ import type { Context } from '@deepseek-ai/cordis';
3
+ export declare const name = "plugin-hub-invariant";
4
+ export declare const inject: string[];
5
+ /** Register this package's invariant companion. */
6
+ export declare const apply: (ctx: Context) => Promise<() => void>;
7
+ //# sourceMappingURL=invariant.d.ts.map
@@ -0,0 +1,257 @@
1
+ /** Provider-neutral Plugin Hub catalog vocabulary. */
2
+ import type { Branded } from '@deepseek-ai/dsh-brand';
3
+ /** Exact opaque identifier assigned to one catalog plugin. */
4
+ export type PluginId = Branded<'PluginId'>;
5
+ /**
6
+ * Brand a catalog plugin id received from a provider.
7
+ * @param value - provider-issued opaque id.
8
+ * @returns the same string with the PluginId brand.
9
+ */
10
+ export declare function PluginId(value: string): PluginId;
11
+ /** Exact opaque identifier assigned to one published plugin version. */
12
+ export type PluginVersionId = Branded<'PluginVersionId'>;
13
+ /**
14
+ * Brand a catalog version id received from a provider.
15
+ * @param value - provider-issued opaque id.
16
+ * @returns the same string with the PluginVersionId brand.
17
+ */
18
+ export declare function PluginVersionId(value: string): PluginVersionId;
19
+ /** Opaque identifier for one detached local profile change plan. */
20
+ export type PluginChangePlanId = Branded<'PluginChangePlanId'>;
21
+ /**
22
+ * Brand a provider-issued detached plan id.
23
+ * @param value - provider-issued opaque id.
24
+ * @returns the same string with the PluginChangePlanId brand.
25
+ */
26
+ export declare function PluginChangePlanId(value: string): PluginChangePlanId;
27
+ /** Opaque identifier for one durable local profile transaction. */
28
+ export type PluginTransactionId = Branded<'PluginTransactionId'>;
29
+ /**
30
+ * Brand a provider-issued transaction id.
31
+ * @param value - provider-issued opaque id.
32
+ * @returns the same string with the PluginTransactionId brand.
33
+ */
34
+ export declare function PluginTransactionId(value: string): PluginTransactionId;
35
+ /** Stable wire/API version currently understood by the local consumer. */
36
+ export declare const PLUGIN_HUB_API_VERSION: "dsh.plugin-hub/v1";
37
+ /** Public error taxonomy shared by providers and TUI consumers. */
38
+ export type PluginHubErrorCode = 'REGISTRY_UNAVAILABLE' | 'CATALOG_STALE' | 'CONTRACT_UNSUPPORTED' | 'SIGNATURE_INVALID' | 'DESCRIPTOR_EXPIRED' | 'PLUGIN_NOT_FOUND' | 'VERSION_NOT_INSTALLABLE' | 'DSH_INCOMPATIBLE' | 'SURFACE_INCOMPATIBLE' | 'PLUGIN_QUARANTINED' | 'ARTIFACT_TOO_LARGE' | 'ARTIFACT_DIGEST_MISMATCH' | 'PROFILE_BUSY' | 'PROFILE_CHANGED' | 'PNPM_UNAVAILABLE' | 'PNPM_FAILED' | 'BUILD_NOT_ALLOWED' | 'PROFILE_INVALID' | 'PLAN_EXPIRED' | 'STAGE_FAILED' | 'HANDOFF_FAILED' | 'INVALID_CURSOR' | 'OPERATION_ABORTED';
39
+ /** Typed failure that callers can branch on without parsing a message. */
40
+ export declare class PluginHubError extends Error {
41
+ /** Stable category consumed by UI and retry policy. */
42
+ readonly code: PluginHubErrorCode;
43
+ /**
44
+ * @param message - bounded public diagnostic.
45
+ * @param code - stable machine-readable category.
46
+ * @param options - optional underlying cause.
47
+ */
48
+ constructor(message: string, code: PluginHubErrorCode, options?: ErrorOptions);
49
+ }
50
+ /** Provider health and last-good catalog state. */
51
+ export interface PluginHubStatus {
52
+ readonly apiVersion: typeof PLUGIN_HUB_API_VERSION;
53
+ readonly catalogRevision?: number | undefined;
54
+ readonly generatedAt?: string | undefined;
55
+ readonly stale: boolean;
56
+ readonly source: 'registry' | 'cache' | 'fixture';
57
+ }
58
+ /** Provider-neutral catalog ordering applied by Registry providers. */
59
+ export type PluginCatalogSort = 'relevance' | 'stars' | 'updated' | 'newest';
60
+ /** Registry-owned discovery category; this is presentation metadata, not trust state. */
61
+ export type PluginCategory = 'communication' | 'vision' | 'browser' | 'interface' | 'agent' | 'development' | 'data' | 'automation' | 'integration' | 'theme' | 'other';
62
+ /** Registry-owned package classification used for discovery display. */
63
+ export type PluginPackageKind = 'plugin' | 'bundle' | 'skill' | 'tool' | 'integration';
64
+ /** Authority that supplied one discovery metadata value. */
65
+ export type PluginDiscoveryMetadataSource = 'author' | 'curator' | 'automatic';
66
+ /** Bounded literal catalog search request. */
67
+ export interface PluginSearchRequest {
68
+ readonly query?: string | undefined;
69
+ readonly surface?: 'tui' | 'web' | 'headless' | 'unknown' | undefined;
70
+ readonly dshVersion?: string | undefined;
71
+ readonly verification?: 'discovered' | 'manifest-valid' | 'install-verified' | 'tui-boot-verified' | 'curated' | undefined;
72
+ readonly installable?: boolean | undefined;
73
+ readonly category?: PluginCategory | undefined;
74
+ readonly kind?: PluginPackageKind | undefined;
75
+ readonly language?: string | undefined;
76
+ readonly sort?: PluginCatalogSort | undefined;
77
+ readonly cursor?: string | undefined;
78
+ readonly limit?: number | undefined;
79
+ }
80
+ /** Compatibility result returned by the Registry. */
81
+ export interface PluginCompatibility {
82
+ readonly dsh?: string | undefined;
83
+ readonly match: 'compatible' | 'incompatible' | 'unknown';
84
+ }
85
+ /** Verification state for one catalog row. */
86
+ export interface PluginVerification {
87
+ readonly level: 'discovered' | 'manifest-valid' | 'install-verified' | 'tui-boot-verified' | 'curated';
88
+ readonly status: 'passed' | 'failed' | 'unknown';
89
+ }
90
+ /** Repository identity displayed by the native TUI. */
91
+ export interface PluginRepository {
92
+ readonly provider: string;
93
+ readonly providerId?: string;
94
+ readonly fullName: string;
95
+ readonly url: string;
96
+ /** Primary language reported by the repository provider, when available. */
97
+ readonly primaryLanguage?: string | undefined;
98
+ /** Whether the source repository is archived and no longer maintained. */
99
+ readonly archived?: boolean | undefined;
100
+ }
101
+ /** Bounded curation facts supplied by the Registry for human display. */
102
+ export interface PluginCurationSummary {
103
+ readonly policyRevision: string;
104
+ readonly notes?: string | undefined;
105
+ readonly curatedAt: string;
106
+ }
107
+ /** Structured advisory facts supplied by the Registry. */
108
+ export interface PluginAdvisorySummary {
109
+ readonly id: string;
110
+ readonly severity: 'low' | 'moderate' | 'high' | 'critical';
111
+ readonly reason: string;
112
+ readonly recommendedAction?: string | undefined;
113
+ }
114
+ /** Published version summary shown in Discover and Detail. */
115
+ export interface PluginVersionSummary {
116
+ readonly id: PluginVersionId;
117
+ readonly version?: string | undefined;
118
+ readonly sourceCommit?: string | undefined;
119
+ readonly publishedAt?: string | undefined;
120
+ readonly installable: boolean;
121
+ readonly reason?: string | undefined;
122
+ }
123
+ /** One bounded plugin row in a catalog page. */
124
+ export interface PluginSummary {
125
+ readonly id: PluginId;
126
+ readonly packageName: string;
127
+ readonly displayName: string;
128
+ readonly summary: string;
129
+ readonly repository: PluginRepository;
130
+ /** Registry-owned discovery categories; never used as installation authority. */
131
+ readonly categories?: readonly PluginCategory[] | undefined;
132
+ readonly categorySource?: PluginDiscoveryMetadataSource | undefined;
133
+ readonly kind?: PluginPackageKind | undefined;
134
+ readonly kindSource?: PluginDiscoveryMetadataSource | undefined;
135
+ readonly surfaces: {
136
+ readonly declared: readonly string[];
137
+ readonly verified: readonly string[];
138
+ };
139
+ readonly compatibility: PluginCompatibility;
140
+ readonly verification: PluginVerification;
141
+ readonly latestVersion?: PluginVersionSummary | undefined;
142
+ readonly license?: string | undefined;
143
+ readonly stars?: number | undefined;
144
+ readonly updatedAt?: string | undefined;
145
+ }
146
+ /** Search response with an opaque continuation cursor. */
147
+ export interface PluginSearchPage {
148
+ readonly apiVersion: typeof PLUGIN_HUB_API_VERSION;
149
+ readonly catalogRevision: number;
150
+ readonly items: readonly PluginSummary[];
151
+ readonly nextCursor?: string | undefined;
152
+ readonly stale?: boolean | undefined;
153
+ }
154
+ /** Full read-only plugin description used by the Detail panel. */
155
+ export interface PluginDetail extends PluginSummary {
156
+ readonly packagePath?: string | undefined;
157
+ readonly readme?: string | undefined;
158
+ readonly versions: readonly PluginVersionSummary[];
159
+ readonly os?: {
160
+ readonly declared: readonly string[];
161
+ readonly verified: readonly string[];
162
+ } | undefined;
163
+ readonly curation?: PluginCurationSummary | undefined;
164
+ readonly advisories?: readonly PluginAdvisorySummary[] | undefined;
165
+ readonly quarantined?: boolean | undefined;
166
+ }
167
+ /** Health of one profile-local third-party dependency. */
168
+ export type InstalledPluginHealth = 'ok' | 'missing-package' | 'missing-entry' | 'manifest-invalid' | 'unknown';
169
+ /** One dependency derived from the active profile rather than remote Catalog state. */
170
+ export interface InstalledPlugin {
171
+ readonly packageName: string;
172
+ readonly version?: string | undefined;
173
+ readonly activeBundle: boolean;
174
+ readonly managed: boolean;
175
+ readonly pluginId?: PluginId | undefined;
176
+ readonly versionId?: PluginVersionId | undefined;
177
+ readonly sourceCommit?: string | undefined;
178
+ readonly artifactDigest?: string | undefined;
179
+ readonly health: InstalledPluginHealth;
180
+ }
181
+ /** Exact active-profile state used by installed and plan views. */
182
+ export interface InstalledPluginSnapshot {
183
+ readonly profileRevision: string;
184
+ readonly bundles: readonly string[];
185
+ readonly plugins: readonly InstalledPlugin[];
186
+ }
187
+ /** Typed profile mutation represented by a detached plan. */
188
+ export type PluginChangeOperation = 'install' | 'update' | 'remove';
189
+ /** Descriptor facts shown before a user confirms an install or update. */
190
+ export interface PluginChangeTarget {
191
+ readonly pluginId: PluginId;
192
+ readonly versionId: PluginVersionId;
193
+ readonly packageName: string;
194
+ readonly version: string;
195
+ readonly sourceCommit: string;
196
+ readonly artifactSizeBytes: number;
197
+ readonly artifactDigest: string;
198
+ readonly dshRange: string;
199
+ readonly validationLevel: string;
200
+ readonly lifecycleScripts: readonly string[];
201
+ }
202
+ /** Detached, expiring profile plan that contains no executable or local artifact path. */
203
+ export interface PluginChangePlan {
204
+ readonly id: PluginChangePlanId;
205
+ readonly operation: PluginChangeOperation;
206
+ readonly profileRevision: string;
207
+ readonly createdAt: string;
208
+ readonly expiresAt: string;
209
+ readonly packageName: string;
210
+ readonly target?: PluginChangeTarget | undefined;
211
+ readonly before: InstalledPluginSnapshot;
212
+ readonly afterBundles: readonly string[];
213
+ readonly restartRequired: true;
214
+ readonly risks: readonly string[];
215
+ }
216
+ /** Successfully prepared staging generation awaiting explicit activation handoff. */
217
+ export interface StagedPluginTransaction {
218
+ readonly id: PluginTransactionId;
219
+ readonly planId: PluginChangePlanId;
220
+ readonly operation: PluginChangeOperation;
221
+ readonly packageName: string;
222
+ readonly beforeRevision: string;
223
+ readonly afterRevision: string;
224
+ readonly createdAt: string;
225
+ readonly restartRequired: true;
226
+ }
227
+ /** Durable activation handoff that becomes owned by the maintenance process. */
228
+ export interface PluginMaintenanceHandoff {
229
+ readonly transactionId: PluginTransactionId;
230
+ readonly state: 'waiting-for-old-process';
231
+ readonly createdAt: string;
232
+ }
233
+ /** Provider-neutral catalog implementation. */
234
+ export interface PluginHubProvider {
235
+ readonly id: string;
236
+ /** Whether this provider may mutate and restart the active profile. */
237
+ readonly profileMutations: boolean;
238
+ status(signal?: AbortSignal): Promise<PluginHubStatus>;
239
+ search(request: PluginSearchRequest, signal?: AbortSignal): Promise<PluginSearchPage>;
240
+ plugin(pluginId: PluginId, signal?: AbortSignal): Promise<PluginDetail>;
241
+ installed(signal?: AbortSignal): Promise<InstalledPluginSnapshot>;
242
+ planInstall(pluginId: PluginId, versionId: PluginVersionId, signal?: AbortSignal): Promise<PluginChangePlan>;
243
+ planRemove(packageName: string, signal?: AbortSignal): Promise<PluginChangePlan>;
244
+ stage(planId: PluginChangePlanId, signal?: AbortSignal): Promise<StagedPluginTransaction>;
245
+ discard(transactionId: PluginTransactionId, signal?: AbortSignal): Promise<void>;
246
+ createMaintenanceHandoff(transactionId: PluginTransactionId, signal?: AbortSignal): Promise<PluginMaintenanceHandoff>;
247
+ markMaintenanceReady(signal?: AbortSignal): Promise<void>;
248
+ }
249
+ /** Safe in-process progress update; progress never enters a Session log. */
250
+ export interface PluginHubProgress {
251
+ readonly operationId: string;
252
+ readonly phase: 'catalog' | 'download' | 'verify' | 'materialize' | 'mutate' | 'validate' | 'handoff';
253
+ readonly message: string;
254
+ readonly completed?: number;
255
+ readonly total?: number;
256
+ }
257
+ //# sourceMappingURL=types.d.ts.map
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@lingxi-ai-cn/dsh-plugin-hub",
3
+ "description": "Provider-neutral Plugin Hub catalog and profile transaction capability for native TUI consumers",
4
+ "version": "0.1.0-rc.8",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/Lingxi-AI-cn/dsh-tui-plugin.git",
11
+ "directory": "packages/interaction/plugin-hub"
12
+ },
13
+ "type": "module",
14
+ "main": "lib/index.js",
15
+ "types": "lib/types/index.d.ts",
16
+ "exports": {
17
+ ".": {
18
+ "types": "./lib/types/index.d.ts",
19
+ "default": "./lib/index.js"
20
+ },
21
+ "./invariant": {
22
+ "types": "./lib/types/invariant.d.ts",
23
+ "default": "./lib/invariant.js"
24
+ },
25
+ "./package.json": "./package.json"
26
+ },
27
+ "files": [
28
+ "lib/index.js",
29
+ "lib/invariant.js",
30
+ "lib/types/**/*.d.ts"
31
+ ],
32
+ "license": "MIT",
33
+ "peerDependencies": {
34
+ "@deepseek-ai/dsh-brand": "0.1.0-rc.8",
35
+ "@deepseek-ai/dsh-invariants": "0.1.0-rc.8",
36
+ "@deepseek-ai/cordis": "4.0.1"
37
+ },
38
+ "devDependencies": {
39
+ "@deepseek-ai/dsh-brand": "0.1.0-rc.8",
40
+ "@deepseek-ai/dsh-invariants": "0.1.0-rc.8",
41
+ "@deepseek-ai/cordis": "4.0.1"
42
+ }
43
+ }