dsh-agent-plugins-market 0.6.2 → 0.7.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.
Files changed (136) hide show
  1. package/README.md +117 -111
  2. package/README.zh.md +112 -98
  3. package/client/client.js +547 -540
  4. package/client/client.js.map +1 -1
  5. package/lib/application/catalog-context.js +181 -0
  6. package/lib/application/catalog.js +217 -1110
  7. package/lib/application/details.js +6 -6
  8. package/lib/application/install-store.js +95 -0
  9. package/lib/application/lsp-service.js +97 -0
  10. package/lib/application/mcp-service.js +246 -0
  11. package/lib/application/panel-resources.js +29 -12
  12. package/lib/application/ports.js +21 -0
  13. package/lib/application/project-agent-roles.js +1 -1
  14. package/lib/application/snapshot-cache.js +160 -0
  15. package/lib/application/source-store.js +521 -0
  16. package/lib/catalog/archive.js +34 -29
  17. package/lib/catalog/component-files.js +14 -6
  18. package/lib/catalog/fs-probes.js +43 -0
  19. package/lib/catalog/manifests.js +53 -92
  20. package/lib/catalog/native-project.js +2 -2
  21. package/lib/catalog/paths.js +66 -55
  22. package/lib/catalog/project-config.js +2 -1
  23. package/lib/catalog/project-hooks.js +9 -1
  24. package/lib/catalog/scan-resolvers.js +29 -45
  25. package/lib/catalog/skills-parse.js +14 -10
  26. package/lib/catalog/source-catalog.js +3 -2
  27. package/lib/catalog/suite-components.js +5 -5
  28. package/lib/catalog/suite-scanner.js +3 -1
  29. package/lib/catalog/surfaces.js +5 -26
  30. package/lib/catalog/validate.js +7 -11
  31. package/lib/contracts/market.js +1 -0
  32. package/lib/index.js +91 -208
  33. package/lib/model/types.js +26 -3
  34. package/lib/routes.js +45 -15
  35. package/lib/runtime/agent-role-names.js +70 -0
  36. package/lib/runtime/agent-role-router.js +116 -102
  37. package/lib/runtime/commands-mounts.js +9 -6
  38. package/lib/runtime/deadline.js +28 -0
  39. package/lib/runtime/feedback-tool.js +94 -43
  40. package/lib/runtime/hooks-mounts.js +9 -11
  41. package/lib/runtime/host-locale.js +10 -21
  42. package/lib/runtime/lsp-direct-config.js +19 -19
  43. package/lib/runtime/lsp-mounts.js +159 -68
  44. package/lib/runtime/lsp-server-state.js +4 -4
  45. package/lib/runtime/lsp-status.js +1 -1
  46. package/lib/runtime/mcp-auth-record.js +42 -0
  47. package/lib/runtime/mcp-backend.js +6 -5
  48. package/lib/runtime/mcp-client/config.js +0 -1
  49. package/lib/runtime/mcp-client/connection.js +32 -37
  50. package/lib/runtime/mcp-client/host-contract.js +10 -0
  51. package/lib/runtime/mcp-client/oauth.js +5 -7
  52. package/lib/runtime/mcp-client/plugin-identity.js +28 -0
  53. package/lib/runtime/mcp-client/projection.js +202 -0
  54. package/lib/runtime/mcp-client/tools.js +4 -189
  55. package/lib/runtime/mcp-config.js +29 -10
  56. package/lib/runtime/mcp-direct-config.js +33 -16
  57. package/lib/runtime/mcp-mounts.js +35 -75
  58. package/lib/runtime/mcp-overrides.js +5 -5
  59. package/lib/runtime/mcp-redaction.js +3 -2
  60. package/lib/runtime/mcp-status.js +7 -8
  61. package/lib/runtime/mount-lifecycle.js +73 -0
  62. package/lib/runtime/profile-seam.js +321 -0
  63. package/lib/runtime/project-runtime.js +11 -8
  64. package/lib/runtime/reconcile-scheduler.js +99 -0
  65. package/lib/runtime/reconciler.js +4 -0
  66. package/lib/runtime/server-config.js +6 -4
  67. package/lib/runtime/settings-namespace.js +136 -0
  68. package/lib/runtime/skills-provider.js +5 -3
  69. package/lib/runtime/source-auto-update.js +70 -0
  70. package/lib/{model/state.js → runtime/state-store.js} +9 -11
  71. package/lib/runtime/storage-migration.js +35 -18
  72. package/lib/runtime/subagent-catalog.js +5 -4
  73. package/lib/runtime/user-commands.js +2 -2
  74. package/lib/runtime/user-panels.js +31 -21
  75. package/lib/runtime/user-store.js +12 -13
  76. package/lib/types/application/catalog-context.d.ts +118 -0
  77. package/lib/types/application/catalog.d.ts +99 -304
  78. package/lib/types/application/install-store.d.ts +21 -0
  79. package/lib/types/application/lsp-service.d.ts +36 -0
  80. package/lib/types/application/mcp-service.d.ts +71 -0
  81. package/lib/types/application/panel-resources.d.ts +8 -0
  82. package/lib/types/application/ports.d.ts +72 -0
  83. package/lib/types/application/queries.d.ts +13 -26
  84. package/lib/types/application/snapshot-cache.d.ts +51 -0
  85. package/lib/types/application/source-store.d.ts +100 -0
  86. package/lib/types/catalog/archive.d.ts +3 -11
  87. package/lib/types/catalog/component-files.d.ts +4 -0
  88. package/lib/types/catalog/fs-probes.d.ts +10 -0
  89. package/lib/types/catalog/manifests.d.ts +17 -16
  90. package/lib/types/catalog/native-project.d.ts +2 -2
  91. package/lib/types/catalog/paths.d.ts +47 -15
  92. package/lib/types/catalog/scan-pipeline.d.ts +3 -3
  93. package/lib/types/catalog/scan-resolvers.d.ts +3 -9
  94. package/lib/types/catalog/skills-parse.d.ts +0 -7
  95. package/lib/types/catalog/source-catalog.d.ts +3 -3
  96. package/lib/types/catalog/suite-scanner.d.ts +8 -6
  97. package/lib/types/catalog/validate.d.ts +0 -2
  98. package/lib/types/contracts/lsp-status.d.ts +35 -0
  99. package/lib/types/contracts/market.d.ts +3 -2
  100. package/lib/types/contracts/mcp-status.d.ts +4 -0
  101. package/lib/types/model/types.d.ts +29 -5
  102. package/lib/types/runtime/agent-role-names.d.ts +6 -0
  103. package/lib/types/runtime/agent-role-router.d.ts +54 -51
  104. package/lib/types/runtime/deadline.d.ts +18 -0
  105. package/lib/types/runtime/feedback-tool.d.ts +33 -11
  106. package/lib/types/runtime/hooks-mounts.d.ts +1 -1
  107. package/lib/types/runtime/host-locale.d.ts +1 -1
  108. package/lib/types/runtime/lsp-direct-config.d.ts +3 -3
  109. package/lib/types/runtime/lsp-mounts.d.ts +62 -19
  110. package/lib/types/runtime/lsp-status.d.ts +2 -1
  111. package/lib/types/runtime/mcp-auth-record.d.ts +29 -0
  112. package/lib/types/runtime/mcp-backend.d.ts +7 -4
  113. package/lib/types/runtime/mcp-client/config.d.ts +0 -2
  114. package/lib/types/runtime/mcp-client/host-contract.d.ts +78 -0
  115. package/lib/types/runtime/mcp-client/oauth.d.ts +1 -1
  116. package/lib/types/runtime/mcp-client/plugin-identity.d.ts +16 -0
  117. package/lib/types/runtime/mcp-client/projection.d.ts +45 -0
  118. package/lib/types/runtime/mcp-client/tools.d.ts +5 -72
  119. package/lib/types/runtime/mcp-config.d.ts +25 -4
  120. package/lib/types/runtime/mcp-direct-config.d.ts +18 -4
  121. package/lib/types/runtime/mcp-mounts.d.ts +10 -15
  122. package/lib/types/runtime/mcp-overrides.d.ts +1 -1
  123. package/lib/types/runtime/mcp-status.d.ts +1 -1
  124. package/lib/types/runtime/mount-lifecycle.d.ts +53 -0
  125. package/lib/types/runtime/profile-seam.d.ts +64 -0
  126. package/lib/types/runtime/reconcile-scheduler.d.ts +45 -0
  127. package/lib/types/runtime/reconciler.d.ts +2 -0
  128. package/lib/types/runtime/settings-namespace.d.ts +76 -0
  129. package/lib/types/runtime/source-auto-update.d.ts +33 -0
  130. package/lib/types/{model/state.d.ts → runtime/state-store.d.ts} +2 -2
  131. package/lib/types/runtime/storage-migration.d.ts +5 -3
  132. package/lib/types/runtime/subagent-catalog.d.ts +2 -0
  133. package/lib/types/runtime/user-panels.d.ts +8 -11
  134. package/lib/types/runtime/user-store.d.ts +2 -4
  135. package/package.json +48 -21
  136. package/schemas/README.md +1 -1
@@ -1,251 +1,64 @@
1
- import { type GitOptions } from '../catalog/git.js';
2
- import { type McpToolSnapshot } from '../runtime/mcp-status.js';
1
+ import type { LspLegacySeamMigration, LspStatusPayload } from '../contracts/lsp-status.js';
2
+ import type { OverviewPayload, ServerConfigPayload, SkillContent, SourceProgress, SuiteDetail } from '../contracts/market.js';
3
+ import type { McpStatusPayload } from '../contracts/mcp-status.js';
4
+ import type { SourceRef, Suite, SuiteSurfaceKey } from '../model/types.js';
5
+ import type { McpBackend } from '../runtime/mcp-backend.js';
3
6
  import type { McpMountDiagnostic } from '../runtime/mcp-mounts.js';
4
- import { type LspMountStatusSource } from '../runtime/lsp-status.js';
5
7
  import { type McpServerOverride, type McpSuiteOverrides } from '../runtime/mcp-overrides.js';
6
- import { type HostMcpClientProbe, type McpBackend } from '../runtime/mcp-backend.js';
7
- import { type DownloadRegionSetting, type EffectiveRegion } from '../runtime/regions.js';
8
- import type { McpStatusPayload } from '../contracts/mcp-status.js';
9
- import type { LspStatusPayload } from '../contracts/lsp-status.js';
10
- import type { OverviewPayload, ServerConfigPayload, SkillContent, SuiteDetail } from '../contracts/market.js';
11
- import { type SourceKind, type SourceRef, type Suite, type SuiteDimension, type SuiteSurfaceKey } from '../model/types.js';
12
- /**
13
- * Git network tuning, plumbed from the host config to every remote-touching
14
- * invocation (proxy, `insteadOf` mirrors, timeout, retry). `fallbackTarball`
15
- * additionally lets a failed GitHub clone fall back to a codeload tarball
16
- * download through the archive pipeline.
17
- */
18
- export interface CatalogGitOptions extends GitOptions {
19
- /** Retry a failed GitHub clone as a codeload tarball download; default false. */
20
- fallbackTarball?: boolean;
21
- /** Allow plain-http archive downloads (intranet mirrors); default false. */
22
- allowHttpArchives?: boolean;
23
- }
24
- /** Dependencies and host callback used by the catalog application module. */
25
- export interface CatalogOptions {
26
- userRoot: string;
27
- dataRoot: string;
28
- onChanged: () => void | Promise<void>;
29
- /** Git/archive acquisition tuning. */
30
- git?: CatalogGitOptions;
31
- /**
32
- * Freshness window for cached project-dimension snapshots. The project
33
- * catalog sits on the skill-list hot path (every provider `list()` call),
34
- * and its inputs — the project's own files — change only through editor
35
- * saves; a short window keeps listing cheap without going stale. Defaults
36
- * to 5 seconds; 0 disables caching.
37
- */
38
- projectSnapshotTtlMs?: number;
39
- /**
40
- * Freshness window for the cached user-dimension snapshot (defaults to the
41
- * scan-cache TTL). It bounds how long out-of-band edits to local sources
42
- * stay invisible; 0 disables snapshot caching. Tests pass a small value so
43
- * staleness regressions need no real sleeps.
44
- */
45
- userSnapshotTtlMs?: number;
46
- }
47
- /** A coherent discovered-and-installed view for one catalog dimension. */
48
- export interface CatalogSnapshot {
49
- revision: number;
50
- sources: SourceRef[];
51
- suites: Suite[];
52
- enabledSuites: Suite[];
53
- /** Per-source scan diagnostics (sourceId → notes), absent when clean. */
54
- scanNotes?: Record<string, string[]>;
55
- }
56
- export declare class Catalog {
57
- private readonly options;
58
- private state;
59
- private mutationQueue;
60
- private readonly statePath;
61
- private readonly headCache;
62
- private readonly listeners;
63
- private revision;
64
- private userSnapshot;
65
- private userSnapshotExpiresAt;
66
- private userSnapshotPromise;
67
- /**
68
- * Discovery scan cache: per-sources-fingerprint scan results with a TTL.
69
- * Install / enable / surface toggles re-derive the snapshot from cached
70
- * discovery (cheap mapping) instead of re-walking every checkout — a full
71
- * rescan of a 2,500-suite catalog costs ~1s and UI mutations happen in
72
- * bursts. Content-changing mutations (add / update / remove / adopt /
73
- * refresh / acquire) clear every cached discovery generation; the TTL
74
- * bounds staleness for in-place working-tree
75
- * edits of local sources.
76
- */
77
- private readonly scanCache;
78
- private scanGeneration;
79
- private readonly scanPromises;
80
- private static readonly SCAN_CACHE_TTL_MS;
81
- private static readonly SCAN_CACHE_MAX_ENTRIES;
82
- /**
83
- * User-dimension snapshot TTL: bounded staleness for edits made outside the
84
- * plugin (a new skill dropped into a local source's working tree, a hand
85
- * edit in a project layout) becomes visible on the next read past the TTL
86
- * instead of living until the next mutation. Configurable; a 0 value
87
- * disables snapshot caching entirely.
88
- */
89
- private readonly userSnapshotTtlMs;
90
- /** Project-dimension snapshots keyed by project root, with TTL freshness. */
91
- private readonly projectSnapshots;
92
- private readonly projectSnapshotPromises;
93
- private readonly projectSnapshotTtlMs;
8
+ import { type CatalogGitOptions, type CatalogOptions } from './catalog-context.js';
9
+ import { type LspServerTable, type McpBackendInfo, type SourceInput, type SourcePatch } from './ports.js';
10
+ import { type CatalogSnapshot } from './snapshot-cache.js';
11
+ import { codeloadTarballUrl } from './source-store.js';
12
+ import type { MarketService } from './queries.js';
13
+ export declare class Catalog implements MarketService {
14
+ private readonly context;
15
+ private readonly ports;
16
+ private readonly snapshots;
17
+ private readonly sourceStore;
18
+ private readonly installs;
19
+ private readonly mcp;
20
+ private readonly lsp;
21
+ constructor(options: CatalogOptions);
94
22
  /** Latest MCP mount diagnostics (suiteId -> reasons), fed by host reconcile. */
95
- mcpDiagnostics: McpMountDiagnostic[];
96
- /** Latest LSP mount diagnostics source, wired by the host entry. */
97
- private lspStatusSource;
98
- /** Credential-store seam for dropping a grant record (MCP re-authorize). */
99
- private credentialsStore;
100
- private toolSnapshotProvider;
101
- /** Mount-registry seam: flags a mount key for an explicit rebuild (re-authorize). */
102
- private mcpRemount;
103
- /** Resolves the mount key owning one derived serverName; absent when the server is not mounted. */
104
- private mcpServerOwner;
105
- /** Backend source (the host settings namespace scope); default is the built-in client. */
106
- private mcpBackendProvider;
107
- /** Backend writer (a scope update); absent until the settings service resolves. */
108
- private mcpBackendWriter;
109
- /** Download-region source (the host settings namespace scope). */
110
- private downloadRegionProvider;
111
- private scanProjectLayouts;
23
+ get mcpDiagnostics(): McpMountDiagnostic[];
24
+ set mcpDiagnostics(value: McpMountDiagnostic[]);
25
+ /** The user-dimension suite root this catalog operates. */
26
+ get userRoot(): string;
27
+ get sources(): SourceRef[];
28
+ /** Whether one suite currently carries an install entry. */
29
+ isInstalled(sourceId: string, suiteId: string): boolean;
112
30
  /** Apply the host's project-layout switch and invalidate every project snapshot. */
113
31
  setScanProjectLayouts(enabled: boolean): Promise<void>;
114
- constructor(options: CatalogOptions);
115
- /** Install the host tool snapshot provider used by the MCP status surface. */
116
- setMcpToolSnapshotProvider(provider: () => readonly McpToolSnapshot[]): void;
117
- /** Install the credential-store seam backing the MCP re-authorize action. */
118
- setCredentialsStore(store: {
119
- deleteGrantRecord(serverName: string): Promise<void>;
120
- }): void;
121
- /**
122
- * Drop one MCP server's OAuth grant record so the next mount re-runs the
123
- * browser authorization — the path for "I picked too narrow a scope".
124
- * @param serverName - the derived serverName whose folded form keys the record.
125
- * @throws when the credentials service is not mounted.
126
- */
127
- reauthorizeMcpServer(serverName: string): Promise<void>;
128
- /**
129
- * Install the MCP remount seam used by re-authorize: the registry flags the
130
- * mount so the next reconcile tears the live bridge down and rebuilds it.
131
- */
132
- setMcpRemountHook(hook: (suiteId: string, serverKey: string) => void, serverOwner: (serverName: string) => {
133
- suiteId: string;
134
- serverKey: string;
135
- } | undefined): void;
136
- /** Whether the re-authorize action can run in this composition. */
137
- mcpReauthorizeAvailable(): boolean;
138
- /** Install the LSP mount status source used by the LSP status surface. */
139
- setLspStatusSource(source: LspMountStatusSource): void;
140
- /** Subscribe to completed catalog mutations; returns an unsubscribe function. */
141
- subscribe(listener: () => void): () => void;
142
- /** Build the flat MCP service inventory for the status surface. */
143
- mcpStatus(): Promise<McpStatusPayload>;
144
- /** Persist a user-owned MCP service and reconcile its bridge mount. */
145
- addMcpServer(name: string, server: unknown): Promise<void>;
146
- /** Read effective service configuration without exposing credential literals. */
147
- serverConfig(kind: 'mcp' | 'lsp', id: string): Promise<ServerConfigPayload>;
148
- private resolveServerConfig;
149
- /** Validate a complete replacement before writing; plugin checkouts remain untouched. */
150
- saveServerConfig(kind: 'mcp' | 'lsp', id: string, config: unknown): Promise<void>;
151
- /** The LSP status surface: declared servers merged with mount diagnostics. */
152
- lspStatus(): Promise<LspStatusPayload>;
153
- /** The user's direct LSP server table (normalized specs). */
154
- lspServers(): Promise<Record<string, import('../model/types.js').LspServerSpec>>;
155
- /** Create one direct LSP declaration without replacing other user servers. */
156
- addLspServer(name: string, config: unknown): Promise<void>;
157
- /** Validate and persist the user's direct LSP server table. */
158
- setLspServers(raw: unknown): Promise<Record<string, import('../model/types.js').LspServerSpec>>;
159
- setLspServerEnabled(id: string, enabled: boolean): Promise<void>;
160
- /** One suite's persisted MCP overrides, addressed by qualified suite id. */
161
- mcpOverrides(sourceId: string, suiteId: string): Promise<McpSuiteOverrides>;
162
- /**
163
- * Set or clear one server's MCP override and remount it. `override === null`
164
- * clears the override (back to the source config). The serverKey must exist
165
- * in the suite's parsed mcp.json.
166
- */
167
- setMcpOverride(sourceId: string, suiteId: string, serverKey: string, override: McpServerOverride | null): Promise<void>;
168
- /**
169
- * Re-run the MCP reconcile pass: retries failed mounts and clears residual
170
- * tools, without changing any catalog state.
171
- */
172
- retryMounts(): Promise<void>;
173
- /** The persisted backend choice without the host-client probe (mount-time provider). */
174
- mcpBackend(): Promise<McpBackend>;
32
+ /** Load persisted user state once at plugin activation. */
33
+ load(): Promise<void>;
34
+ /** Append config-seeded sources missing from user state and persist them. */
35
+ mergeSources(sources: SourceRef[]): Promise<void>;
175
36
  /**
176
- * The active MCP mount backend plus a live probe of the host client, and
177
- * the download-region setting with its locale-resolved effective route —
178
- * everything the plugin-config card renders.
37
+ * Panel changed hook: the HTTP layer notifies after a user-panel mutation
38
+ * (skills / commands / agent personas). Catalog state is untouched — this
39
+ * only runs the change pipeline so the runtime remounts commands and the
40
+ * skill providers re-read their catalogs.
179
41
  */
180
- mcpBackendInfo(): Promise<{
181
- backend: McpBackend;
182
- hostClient: HostMcpClientProbe;
183
- downloadRegion: {
184
- setting: DownloadRegionSetting;
185
- effective: EffectiveRegion;
186
- };
187
- }>;
42
+ notifyPanelsChanged(): Promise<void>;
188
43
  /**
189
- * Switch the MCP mount backend and remount every suite server through it.
190
- * A host-client switch takes effect only where the host package resolves;
191
- * unresolvable or unsupported transports surface as per-server diagnostics.
44
+ * Wait for the derived refresh triggered by the latest change, bounded so a
45
+ * stuck mount reports back instead of holding an explicit retry open.
192
46
  */
193
- setMcpBackend(backend: McpBackend): Promise<void>;
194
- /** Install the backend source (the host settings namespace's scope). */
195
- setMcpBackendProvider(provider: () => Promise<McpBackend>): void;
196
- /** Install the backend writer (a scope update on the same namespace). */
197
- setMcpBackendWriter(writer: (backend: McpBackend) => Promise<void>): void;
198
- /** Install the download-region source (the host settings namespace scope). */
199
- setDownloadRegionProvider(provider: () => Promise<DownloadRegionSetting>): void;
200
- /** MCP overrides for a supplied runtime selection, or the full market catalog when omitted. */
201
- allMcpOverrides(suites?: readonly Suite[]): Promise<Map<string, McpSuiteOverrides>>;
202
- /** Load persisted user state once at plugin activation. */
203
- load(): Promise<void>;
204
- get sources(): SourceRef[];
205
- /** The user-dimension suite root this catalog operates. */
206
- get userRoot(): string;
47
+ refreshSettled(deadlineMs?: number): Promise<boolean>;
207
48
  /** Read one coherent user-dimension snapshot, reusing in-flight discovery. */
208
49
  readUserCatalog(): Promise<CatalogSnapshot>;
209
50
  /** Read one coherent project-dimension snapshot for a workspace cwd. */
210
51
  readProjectCatalog(cwd: string): Promise<CatalogSnapshot>;
211
- private buildProjectSnapshot;
52
+ /** Runtime discovery scans only sources containing an enabled install. No acquisition or network access. */
53
+ enabledUserSuites(): Promise<Suite[]>;
54
+ /** The full market overview from one user snapshot. */
55
+ overview(): Promise<OverviewPayload>;
212
56
  /** One suite's full detail for the market detail modal. */
213
57
  suiteDetail(sourceId: string, suiteId: string): Promise<SuiteDetail>;
214
58
  /** One skill's full SKILL.md text for the market detail modal. */
215
59
  skillContent(sourceId: string, suiteId: string, skillName: string): Promise<SkillContent>;
216
- /** The full market overview from one user snapshot. */
217
- overview(): Promise<OverviewPayload>;
218
- /** Runtime discovery scans only sources containing an enabled install. No acquisition or network access. */
219
- enabledUserSuites(): Promise<Suite[]>;
220
- /** Enabled user- and project-dimension suites for a workspace cwd. */
221
- enabledSuitesForCwd(cwd: string): Promise<{
222
- user: Suite[];
223
- project: Suite[];
224
- }>;
225
- /** All suites of one dimension. */
226
- suitesForDimension(dimension: SuiteDimension, dimensionRoot: string): Promise<Suite[]>;
227
- /**
228
- * Add a source and acquire it immediately (clone, download, or in-place).
229
- *
230
- * Git sources with an already-present checkout whose `origin` matches the
231
- * input URL are adopted in place — the manual-clone repair path — so no
232
- * second clone is made and no `-2` suffixed id is invented. Adopted
233
- * checkouts are never deleted on source removal.
234
- */
235
- addSource(input: {
236
- url: string;
237
- branch?: string;
238
- local?: boolean;
239
- kind?: SourceKind;
240
- sha256?: string;
241
- }): Promise<SourceRef>;
242
- /**
243
- * First candidate id whose `.sources/` checkout already exists and whose
244
- * `origin` remote matches the input URL (canonical-form equality) — the
245
- * signature of a manual clone of the very same repository. Registered ids
246
- * and checkouts of differently-origined directories never adopt.
247
- */
248
- private findAdoptableCheckout;
60
+ /** Add a source and acquire it immediately (clone, download, or in-place). */
61
+ addSource(input: SourceInput): Promise<SourceRef>;
249
62
  /** Register one unmanaged `.sources/` checkout as a source without touching its files. */
250
63
  adoptSource(id: string): Promise<SourceRef>;
251
64
  /** Unmanaged `.sources/` checkouts: present on disk, absent from state. */
@@ -253,53 +66,21 @@ export declare class Catalog {
253
66
  id: string;
254
67
  url?: string;
255
68
  }>>;
256
- /** Progress snapshot of the source mutation currently in flight. */
257
- private currentSourceState;
69
+ /** Update one source's URL, branch, kind, or archive digest. */
70
+ updateSource(sourceId: string, patch: SourcePatch): Promise<void>;
71
+ /** Remove a source and its install entries; `deleteCheckout` also deletes the managed checkout. */
72
+ removeSource(sourceId: string, deleteCheckout?: boolean): Promise<void>;
73
+ /** Refresh one source checkout, or every source when sourceId is omitted. */
74
+ refreshSource(sourceId?: string): Promise<void>;
75
+ /** Progress snapshot for the progress route. */
76
+ sourceProgress(): SourceProgress;
258
77
  /** Begin reporting progress for a source mutation. */
259
78
  beginSourceState(sourceId: string, step: string, cloned: boolean): void;
260
79
  /** Advance the in-flight source mutation step. */
261
80
  updateSourceStep(step: string): void;
262
81
  /** Stop reporting source mutation progress. */
263
82
  endSourceState(): void;
264
- /** Progress snapshot for the progress route. */
265
- sourceProgress(): {
266
- active: boolean;
267
- sourceId: string;
268
- step: string;
269
- };
270
- /**
271
- * First candidate id not claimed by a registered source; for git candidates
272
- * the checkout directory must also be free, so a stale or foreign directory
273
- * under `.sources/` is never cloned over (it would fail `git clone` with a
274
- * confusing "destination exists" error). `ownedCheckout` marks the directory
275
- * the in-flight mutation already controls, keeping a rename onto it legal.
276
- * Local sources skip the disk check: they read their own path in place and
277
- * never occupy `.sources/`.
278
- */
279
- private pickSourceId;
280
- /** Update one source's URL, branch, kind, or archive digest. */
281
- updateSource(sourceId: string, patch: {
282
- url?: string;
283
- branch?: string;
284
- local?: boolean;
285
- kind?: SourceKind;
286
- sha256?: string;
287
- }): Promise<void>;
288
- /**
289
- * Remove a source and its install entries. `deleteCheckout` (the UI's
290
- * "also delete the managed market directory" option) physically removes the
291
- * `.sources/<id>` checkout — including an adopted one, since a directory
292
- * under `.sources` is manager-owned storage. A `local` source whose URL
293
- * points outside `.sources` is registration-only: its directory is never
294
- * touched. Deleting the checkout is what keeps a removed source from
295
- * reappearing as an unmanaged entry.
296
- */
297
- removeSource(sourceId: string, deleteCheckout?: boolean): Promise<void>;
298
- /** Refresh one source checkout, or every source when sourceId is omitted. */
299
- refreshSource(sourceId?: string): Promise<void>;
300
- /** Install a suite from a source and enable it. The client confirms the
301
- * injected surfaces (skills / MCP / hooks / commands) in a pre-install
302
- * dialog before this runs; disabling afterwards is always available. */
83
+ /** Install a suite from a source and enable it. */
303
84
  install(sourceId: string, suiteId: string): Promise<void>;
304
85
  /** Uninstall a suite while retaining the source checkout. */
305
86
  uninstall(sourceId: string, suiteId: string): Promise<void>;
@@ -307,42 +88,56 @@ export declare class Catalog {
307
88
  setEnabled(sourceId: string, suiteId: string, enabled: boolean): Promise<void>;
308
89
  /** Enable or disable one runtime surface of an installed suite. */
309
90
  setSurface(sourceId: string, suiteId: string, surface: SuiteSurfaceKey, enabled: boolean): Promise<void>;
310
- /** Append config-seeded sources missing from user state and persist them. */
311
- mergeSources(sources: SourceRef[]): Promise<void>;
91
+ /** Build the flat MCP service inventory for the status surface. */
92
+ mcpStatus(): Promise<McpStatusPayload>;
93
+ /** Persist a user-owned MCP service and reconcile its bridge mount. */
94
+ addMcpServer(name: string, server: unknown): Promise<void>;
95
+ /** Read effective service configuration without exposing credential literals. */
96
+ serverConfig(kind: 'mcp' | 'lsp', id: string): Promise<ServerConfigPayload>;
97
+ /** Validate a complete replacement before writing; plugin checkouts remain untouched. */
98
+ saveServerConfig(kind: 'mcp' | 'lsp', id: string, config: unknown): Promise<void>;
99
+ /** One suite's persisted MCP overrides, addressed by qualified suite id. */
100
+ mcpOverrides(sourceId: string, suiteId: string): Promise<McpSuiteOverrides>;
101
+ /** Set or clear one server's MCP override and remount it. */
102
+ setMcpOverride(sourceId: string, suiteId: string, serverKey: string, override: McpServerOverride | null): Promise<void>;
103
+ /** Re-run the MCP reconcile pass without changing any catalog state. */
104
+ retryMounts(): Promise<void>;
105
+ /** The persisted MCP backend choice without the host-client probe. */
106
+ mcpBackend(): Promise<McpBackend>;
312
107
  /**
313
- * Panel changed hook: the HTTP layer notifies after a user-panel mutation
314
- * (skills / commands / agent personas). Catalog state is untouched — this
315
- * only runs the change pipeline so the runtime remounts commands and the
316
- * skill providers re-read their catalogs.
108
+ * The active MCP mount backend plus a live probe of the host client, and
109
+ * the download-region setting with its locale-resolved effective route.
317
110
  */
318
- notifyPanelsChanged(): Promise<void>;
319
- private setInstalled;
111
+ mcpBackendInfo(): Promise<McpBackendInfo>;
112
+ /** Switch the MCP mount backend and remount every suite server through it. */
113
+ setMcpBackend(backend: McpBackend): Promise<void>;
320
114
  /**
321
- * Acquire one source's content by kind: clone (git), download+extract
322
- * (archive), or an in-place existence check (local). Returns a lock value
323
- * when the acquisition yields one (archive SHA-256, tarball fallback
324
- * digest); git HEAD is read separately by the callers.
115
+ * Drop one MCP server's OAuth grant record so the next mount re-runs the
116
+ * browser authorization.
117
+ * @throws when the credentials service is not mounted.
325
118
  */
326
- private acquire;
327
- /** The filesystem location of one source. */
328
- private sourceCheckoutPath;
329
- private buildSnapshot;
330
- private invalidateSnapshot;
331
- private invalidateScans;
119
+ reauthorizeMcpServer(serverName: string): Promise<void>;
120
+ /** Whether the re-authorize action can run in this composition. */
121
+ mcpReauthorizeAvailable(): boolean;
122
+ /** MCP overrides for a supplied runtime selection, or the full market catalog when omitted. */
123
+ allMcpOverrides(suites?: readonly Suite[]): Promise<Map<string, McpSuiteOverrides>>;
124
+ /** The LSP status surface: declared servers merged with mount diagnostics. */
125
+ lspStatus(): Promise<LspStatusPayload>;
126
+ /** The user's direct LSP server table (normalized specs). */
127
+ lspServers(): Promise<LspServerTable>;
128
+ /** Create one direct LSP declaration without replacing other user servers. */
129
+ addLspServer(name: string, config: unknown): Promise<void>;
130
+ /** Validate and persist the user's direct LSP server table. */
131
+ setLspServers(raw: unknown): Promise<LspServerTable>;
132
+ /** Enable or disable one declared language server by row id. */
133
+ setLspServerEnabled(id: string, enabled: boolean): Promise<void>;
332
134
  /**
333
- * Invalidate snapshots and run the change pipeline. `keepScanCache` marks
334
- * state-only mutations (install, enable, surface toggles, MCP overrides)
335
- * whose inputs leave every checkout untouched, so the next snapshot
336
- * re-derives from cached discovery instead of rescanning the filesystem.
135
+ * Remove one profile's legacy LSP layer — the hand-written
136
+ * `cordis.patch.yml` rows an older release told users to add, which now
137
+ * register a seam this plugin owns.
337
138
  */
338
- private notifyChanged;
339
- private enqueue;
139
+ migrateLegacyLspSeam(profile: string): Promise<LspLegacySeamMigration>;
340
140
  }
341
- /**
342
- * The codeload tarball URL of a GitHub repository, or undefined for any
343
- * other host. `https://github.com/<owner>/<repo>` maps to
344
- * `https://codeload.github.com/<owner>/<repo>/tar.gz/refs/heads/<branch>`
345
- * (or `/tar.gz/HEAD` for the default branch) — the git-protocol fallback
346
- * when a clone cannot get through but plain HTTPS file download can.
347
- */
348
- export declare function codeloadTarballUrl(url: string, branch: string | undefined): string | undefined;
141
+ export type { CatalogGitOptions, CatalogOptions };
142
+ export type { CatalogSnapshot };
143
+ export { codeloadTarballUrl };
@@ -0,0 +1,21 @@
1
+ import { type SourceRef, type SuiteSurfaceKey } from '../model/types.js';
2
+ import { type CatalogContext } from './catalog-context.js';
3
+ import { type SourceStore } from './source-store.js';
4
+ export declare class InstallStore {
5
+ private readonly context;
6
+ private readonly sources;
7
+ constructor(context: CatalogContext, sources: SourceStore);
8
+ /** Install a suite from a source and enable it. The client confirms the
9
+ * injected surfaces (skills / MCP / hooks / commands) in a pre-install
10
+ * dialog before this runs; disabling afterwards is always available. */
11
+ install(sourceId: string, suiteId: string): Promise<void>;
12
+ /** Uninstall a suite while retaining the source checkout. */
13
+ uninstall(sourceId: string, suiteId: string): Promise<void>;
14
+ /** Enable or disable an installed suite. */
15
+ setEnabled(sourceId: string, suiteId: string, enabled: boolean): Promise<void>;
16
+ /** Enable or disable one runtime surface of an installed suite. */
17
+ setSurface(sourceId: string, suiteId: string, surface: SuiteSurfaceKey, enabled: boolean): Promise<void>;
18
+ /** Append config-seeded sources missing from user state and persist them. */
19
+ mergeSources(sources: SourceRef[]): Promise<void>;
20
+ private setInstalled;
21
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * LSP use cases: the status surface, the user's direct server table, and the
3
+ * per-server enable switch.
4
+ *
5
+ * Direct servers live in the shared Agent layout root (`~/.agents/lsp.json`)
6
+ * and are merged with the suites' inline declarations at mount time; a
7
+ * suite's own declaration stays source-owned and is never rewritten. The
8
+ * per-server enable switch stays plugin state under the data root.
9
+ */
10
+ import type { LspLegacySeamMigration, LspStatusPayload } from '../contracts/lsp-status.js';
11
+ import type { CatalogContext } from './catalog-context.js';
12
+ import type { CatalogPorts, LspServerTable } from './ports.js';
13
+ export declare class LspService {
14
+ private readonly context;
15
+ private readonly ports;
16
+ constructor(context: CatalogContext, ports: CatalogPorts);
17
+ /** The LSP status surface: declared servers merged with mount diagnostics. */
18
+ status(): Promise<LspStatusPayload>;
19
+ /** The profile layer behind a reported seam conflict, when one can be found. */
20
+ private legacySeam;
21
+ /**
22
+ * Remove one profile's legacy LSP layer, then re-reconcile.
23
+ *
24
+ * The removal edits a file the user owns, so the profile is matched against
25
+ * what was actually found on disk instead of trusting the request.
26
+ */
27
+ migrateLegacySeam(profile: string): Promise<LspLegacySeamMigration>;
28
+ /** The user's direct LSP server table (normalized specs). */
29
+ servers(): Promise<LspServerTable>;
30
+ /** Create one direct LSP declaration without replacing other user servers. */
31
+ addServer(name: string, config: unknown): Promise<void>;
32
+ /** Validate and persist the user's direct LSP server table. */
33
+ setServers(raw: unknown): Promise<LspServerTable>;
34
+ /** Enable or disable one declared language server by row id. */
35
+ setEnabled(id: string, enabled: boolean): Promise<void>;
36
+ }
@@ -0,0 +1,71 @@
1
+ import type { McpStatusPayload } from '../contracts/mcp-status.js';
2
+ import type { ServerConfigPayload } from '../contracts/market.js';
3
+ import type { Suite } from '../model/types.js';
4
+ import { type McpBackend } from '../runtime/mcp-backend.js';
5
+ import type { McpMountDiagnostic } from '../runtime/mcp-mounts.js';
6
+ import { type McpServerOverride, type McpSuiteOverrides } from '../runtime/mcp-overrides.js';
7
+ import type { CatalogContext } from './catalog-context.js';
8
+ import type { CatalogPorts, McpBackendInfo } from './ports.js';
9
+ import type { SourceStore } from './source-store.js';
10
+ export declare class McpService {
11
+ private readonly context;
12
+ private readonly ports;
13
+ private readonly sources;
14
+ /** Latest MCP mount diagnostics (suiteId -> reasons), fed by host reconcile. */
15
+ diagnostics: McpMountDiagnostic[];
16
+ constructor(context: CatalogContext, ports: CatalogPorts, sources: SourceStore);
17
+ /** Build the flat MCP service inventory for the status surface. */
18
+ status(): Promise<McpStatusPayload>;
19
+ /** Persist a user-owned MCP service and reconcile its bridge mount. */
20
+ addServer(name: string, server: unknown): Promise<void>;
21
+ /** Read effective service configuration without exposing credential literals. */
22
+ serverConfig(kind: 'mcp' | 'lsp', id: string): Promise<ServerConfigPayload>;
23
+ /** Validate a complete replacement before writing; plugin checkouts remain untouched. */
24
+ saveServerConfig(kind: 'mcp' | 'lsp', id: string, config: unknown): Promise<void>;
25
+ /** One suite's persisted MCP overrides, addressed by qualified suite id. */
26
+ overrides(sourceId: string, suiteId: string): Promise<McpSuiteOverrides>;
27
+ /**
28
+ * Set or clear one server's MCP override and remount it. `override === null`
29
+ * clears the override (back to the source config). The serverKey must exist
30
+ * in the suite's parsed mcp.json.
31
+ */
32
+ setOverride(sourceId: string, suiteId: string, serverKey: string, override: McpServerOverride | null): Promise<void>;
33
+ /**
34
+ * Re-run the MCP reconcile pass: retries failed mounts and clears residual
35
+ * tools, without changing any catalog state.
36
+ *
37
+ * Every live mount is rebuilt rather than fingerprinted: a bridge whose
38
+ * server died underneath it keeps matching its own resolved config, so a
39
+ * retry is the only path that re-verifies a mount that looks connected. The
40
+ * wait is bounded — the pass keeps running, so a slow server reports its
41
+ * outcome to the status surface instead of holding the request open.
42
+ */
43
+ retryMounts(): Promise<void>;
44
+ /** The persisted backend choice without the host-client probe (mount-time provider). */
45
+ backend(): Promise<McpBackend>;
46
+ /**
47
+ * The active MCP mount backend plus a live probe of the host client, and
48
+ * the download-region setting with its locale-resolved effective route —
49
+ * everything the plugin-config card renders.
50
+ */
51
+ backendInfo(): Promise<McpBackendInfo>;
52
+ /**
53
+ * Switch the MCP mount backend and remount every suite server through it.
54
+ * A host-client switch takes effect only where the host package resolves;
55
+ * unresolvable or unsupported transports surface as per-server diagnostics.
56
+ */
57
+ setBackend(backend: McpBackend): Promise<void>;
58
+ /**
59
+ * Drop one MCP server's OAuth grant record so the next mount re-runs the
60
+ * browser authorization — the path for "I picked too narrow a scope".
61
+ * @param serverName - the derived serverName whose folded form keys the record.
62
+ * @throws when the credentials service is not mounted.
63
+ */
64
+ reauthorize(serverName: string): Promise<void>;
65
+ /** Whether the re-authorize action can run in this composition. */
66
+ reauthorizeAvailable(): boolean;
67
+ /** MCP overrides for a supplied runtime selection, or the full market catalog when omitted. */
68
+ allOverrides(suites?: readonly Suite[]): Promise<Map<string, McpSuiteOverrides>>;
69
+ /** Resolve one editable server: its key, owning suite, root, and effective config. */
70
+ private resolveServerConfig;
71
+ }
@@ -10,4 +10,12 @@ export interface PanelResourceStore {
10
10
  update(id: string, text: string): Promise<void>;
11
11
  remove(id: string): Promise<void>;
12
12
  }
13
+ /**
14
+ * Id of one panel entry backed by a file inside an installed suite's checkout.
15
+ * The leading `[` is what distinguishes a plugin entry from a user-authored
16
+ * one; `update`/`remove` use {@link isPluginResourceId} to tell them apart.
17
+ */
18
+ export declare function pluginResourceId(sourceId: string, suiteId: string, kind: UserPanelKind, name: string): string;
19
+ /** Whether a panel entry id addresses a file inside an installed suite. */
20
+ export declare function isPluginResourceId(id: string): boolean;
13
21
  export declare function createPanelResources(catalog: Catalog, users: Record<UserPanelKind, UserPanelStore>): Record<UserPanelKind, PanelResourceStore>;