dsh-agent-plugins-market 0.6.2 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. package/README.md +117 -111
  2. package/README.zh.md +112 -98
  3. package/client/client.js +28533 -1511
  4. package/client/client.js.map +1 -1
  5. package/lib/application/catalog-context.js +188 -0
  6. package/lib/application/catalog.js +229 -1109
  7. package/lib/application/details.js +19 -8
  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 +263 -0
  11. package/lib/application/panel-resources.js +43 -14
  12. package/lib/application/ports.js +21 -0
  13. package/lib/application/project-agent-roles.js +8 -2
  14. package/lib/application/snapshot-cache.js +160 -0
  15. package/lib/application/source-store.js +521 -0
  16. package/lib/catalog/archive.js +35 -30
  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 +74 -55
  22. package/lib/catalog/plugin-variables.js +38 -0
  23. package/lib/catalog/project-config.js +2 -1
  24. package/lib/catalog/project-hooks.js +23 -2
  25. package/lib/catalog/scan-resolvers.js +29 -45
  26. package/lib/catalog/skills-parse.js +61 -10
  27. package/lib/catalog/source-catalog.js +10 -4
  28. package/lib/catalog/suite-components.js +7 -7
  29. package/lib/catalog/suite-scanner.js +3 -1
  30. package/lib/catalog/surfaces.js +5 -26
  31. package/lib/catalog/validate.js +7 -11
  32. package/lib/contracts/market.js +2 -0
  33. package/lib/contracts/settings.js +63 -0
  34. package/lib/index.js +115 -217
  35. package/lib/model/layouts.js +10 -1
  36. package/lib/model/types.js +26 -3
  37. package/lib/routes.js +57 -15
  38. package/lib/runtime/agent-role-names.js +70 -0
  39. package/lib/runtime/agent-role-router.js +142 -106
  40. package/lib/runtime/commands-mounts.js +55 -11
  41. package/lib/runtime/deadline.js +54 -0
  42. package/lib/runtime/dynamic-context.js +140 -0
  43. package/lib/runtime/feedback-tool.js +101 -46
  44. package/lib/runtime/hooks-mounts.js +9 -11
  45. package/lib/runtime/host-locale.js +49 -24
  46. package/lib/runtime/lsp-direct-config.js +19 -19
  47. package/lib/runtime/lsp-mounts.js +182 -70
  48. package/lib/runtime/lsp-server-state.js +4 -4
  49. package/lib/runtime/lsp-status.js +1 -1
  50. package/lib/runtime/mcp-auth-record.js +42 -0
  51. package/lib/runtime/mcp-backend.js +14 -14
  52. package/lib/runtime/mcp-client/config.js +8 -1
  53. package/lib/runtime/mcp-client/connection.js +38 -43
  54. package/lib/runtime/mcp-client/host-contract.js +10 -0
  55. package/lib/runtime/mcp-client/host-seams.js +8 -88
  56. package/lib/runtime/mcp-client/oauth.js +5 -7
  57. package/lib/runtime/mcp-client/plugin-identity.js +28 -0
  58. package/lib/runtime/mcp-client/projection.js +202 -0
  59. package/lib/runtime/mcp-client/tools.js +4 -189
  60. package/lib/runtime/mcp-config.js +36 -14
  61. package/lib/runtime/mcp-direct-config.js +33 -16
  62. package/lib/runtime/mcp-mounts.js +35 -75
  63. package/lib/runtime/mcp-overrides.js +5 -5
  64. package/lib/runtime/mcp-redaction.js +3 -2
  65. package/lib/runtime/mcp-status.js +7 -8
  66. package/lib/runtime/mount-lifecycle.js +73 -0
  67. package/lib/runtime/profile-seam.js +321 -0
  68. package/lib/runtime/project-runtime.js +34 -17
  69. package/lib/runtime/reconcile-scheduler.js +97 -0
  70. package/lib/runtime/reconciler.js +6 -1
  71. package/lib/runtime/regions.js +0 -19
  72. package/lib/runtime/server-config.js +6 -4
  73. package/lib/runtime/settings-namespace.js +144 -0
  74. package/lib/runtime/skills-provider.js +38 -14
  75. package/lib/runtime/source-auto-update.js +66 -0
  76. package/lib/{model/state.js → runtime/state-store.js} +9 -11
  77. package/lib/runtime/storage-migration.js +35 -18
  78. package/lib/runtime/subagent-catalog.js +5 -4
  79. package/lib/runtime/timer-seat.js +80 -0
  80. package/lib/runtime/tool-registry-observer.js +20 -20
  81. package/lib/runtime/user-commands.js +7 -3
  82. package/lib/runtime/user-panels.js +125 -46
  83. package/lib/runtime/user-store.js +124 -69
  84. package/lib/types/application/catalog-context.d.ts +124 -0
  85. package/lib/types/application/catalog.d.ts +108 -304
  86. package/lib/types/application/install-store.d.ts +21 -0
  87. package/lib/types/application/lsp-service.d.ts +36 -0
  88. package/lib/types/application/mcp-service.d.ts +77 -0
  89. package/lib/types/application/panel-resources.d.ts +8 -0
  90. package/lib/types/application/ports.d.ts +72 -0
  91. package/lib/types/application/queries.d.ts +15 -26
  92. package/lib/types/application/snapshot-cache.d.ts +51 -0
  93. package/lib/types/application/source-store.d.ts +100 -0
  94. package/lib/types/catalog/archive.d.ts +3 -11
  95. package/lib/types/catalog/component-files.d.ts +4 -0
  96. package/lib/types/catalog/fs-probes.d.ts +10 -0
  97. package/lib/types/catalog/manifests.d.ts +17 -16
  98. package/lib/types/catalog/native-project.d.ts +2 -2
  99. package/lib/types/catalog/paths.d.ts +53 -15
  100. package/lib/types/catalog/plugin-variables.d.ts +16 -0
  101. package/lib/types/catalog/scan-pipeline.d.ts +3 -3
  102. package/lib/types/catalog/scan-resolvers.d.ts +3 -9
  103. package/lib/types/catalog/skills-parse.d.ts +13 -7
  104. package/lib/types/catalog/source-catalog.d.ts +10 -5
  105. package/lib/types/catalog/suite-scanner.d.ts +8 -6
  106. package/lib/types/catalog/validate.d.ts +0 -2
  107. package/lib/types/contracts/lsp-status.d.ts +35 -0
  108. package/lib/types/contracts/market.d.ts +13 -2
  109. package/lib/types/contracts/mcp-status.d.ts +4 -0
  110. package/lib/types/contracts/settings.d.ts +59 -0
  111. package/lib/types/model/layouts.d.ts +10 -0
  112. package/lib/types/model/types.d.ts +29 -5
  113. package/lib/types/runtime/agent-role-names.d.ts +6 -0
  114. package/lib/types/runtime/agent-role-router.d.ts +59 -52
  115. package/lib/types/runtime/commands-mounts.d.ts +15 -7
  116. package/lib/types/runtime/deadline.d.ts +17 -0
  117. package/lib/types/runtime/dynamic-context.d.ts +81 -0
  118. package/lib/types/runtime/feedback-tool.d.ts +33 -11
  119. package/lib/types/runtime/hooks-mounts.d.ts +1 -1
  120. package/lib/types/runtime/host-locale.d.ts +20 -2
  121. package/lib/types/runtime/lsp-direct-config.d.ts +3 -3
  122. package/lib/types/runtime/lsp-mounts.d.ts +69 -19
  123. package/lib/types/runtime/lsp-status.d.ts +2 -1
  124. package/lib/types/runtime/mcp-auth-record.d.ts +29 -0
  125. package/lib/types/runtime/mcp-backend.d.ts +10 -14
  126. package/lib/types/runtime/mcp-client/config.d.ts +8 -2
  127. package/lib/types/runtime/mcp-client/host-contract.d.ts +78 -0
  128. package/lib/types/runtime/mcp-client/host-seams.d.ts +20 -64
  129. package/lib/types/runtime/mcp-client/oauth.d.ts +1 -1
  130. package/lib/types/runtime/mcp-client/plugin-identity.d.ts +16 -0
  131. package/lib/types/runtime/mcp-client/projection.d.ts +45 -0
  132. package/lib/types/runtime/mcp-client/tools.d.ts +5 -72
  133. package/lib/types/runtime/mcp-config.d.ts +25 -4
  134. package/lib/types/runtime/mcp-direct-config.d.ts +18 -4
  135. package/lib/types/runtime/mcp-mounts.d.ts +10 -15
  136. package/lib/types/runtime/mcp-overrides.d.ts +1 -1
  137. package/lib/types/runtime/mcp-status.d.ts +1 -1
  138. package/lib/types/runtime/mount-lifecycle.d.ts +53 -0
  139. package/lib/types/runtime/profile-seam.d.ts +64 -0
  140. package/lib/types/runtime/project-runtime.d.ts +10 -3
  141. package/lib/types/runtime/reconcile-scheduler.d.ts +45 -0
  142. package/lib/types/runtime/reconciler.d.ts +2 -0
  143. package/lib/types/runtime/regions.d.ts +1 -4
  144. package/lib/types/runtime/settings-namespace.d.ts +76 -0
  145. package/lib/types/runtime/skills-provider.d.ts +11 -2
  146. package/lib/types/runtime/source-auto-update.d.ts +32 -0
  147. package/lib/types/{model/state.d.ts → runtime/state-store.d.ts} +2 -2
  148. package/lib/types/runtime/storage-migration.d.ts +5 -3
  149. package/lib/types/runtime/subagent-catalog.d.ts +2 -0
  150. package/lib/types/runtime/timer-seat.d.ts +51 -0
  151. package/lib/types/runtime/tool-registry-observer.d.ts +12 -6
  152. package/lib/types/runtime/user-panels.d.ts +69 -19
  153. package/lib/types/runtime/user-store.d.ts +67 -20
  154. package/package.json +68 -24
  155. package/schemas/README.md +1 -1
@@ -0,0 +1,124 @@
1
+ import type { GitOptions } from '../catalog/git.js';
2
+ import { type DiscoveredSuite, type InstalledEntry, type Suite, type SuiteDimension, type SuiteState } from '../model/types.js';
3
+ import type { CatalogPortsOverride } from './ports.js';
4
+ import { SnapshotCache, type SnapshotHost } from './snapshot-cache.js';
5
+ /**
6
+ * Git network tuning, plumbed from the host config to every remote-touching
7
+ * invocation (proxy, `insteadOf` mirrors, timeout, retry). `fallbackTarball`
8
+ * additionally lets a failed GitHub clone fall back to a codeload tarball
9
+ * download through the archive pipeline.
10
+ */
11
+ export interface CatalogGitOptions extends GitOptions {
12
+ /** Retry a failed GitHub clone as a codeload tarball download; default false. */
13
+ fallbackTarball?: boolean;
14
+ /** Allow plain-http archive downloads (intranet mirrors); default false. */
15
+ allowHttpArchives?: boolean;
16
+ }
17
+ /** Dependencies and host callback used by the catalog application module. */
18
+ export interface CatalogOptions {
19
+ userRoot: string;
20
+ dataRoot: string;
21
+ /** Shared Agent layout root holding the user's hand-authored resources and service declarations. */
22
+ agentsRoot: string;
23
+ onChanged: () => void | Promise<void>;
24
+ /** Git/archive acquisition tuning. */
25
+ git?: CatalogGitOptions;
26
+ /** Host seams; unwired members fall back to the defaults in `ports.ts`. */
27
+ ports?: CatalogPortsOverride;
28
+ /**
29
+ * Freshness window for cached project-dimension snapshots. The project
30
+ * catalog sits on the skill-list hot path (every provider `list()` call),
31
+ * and its inputs — the project's own files — change only through editor
32
+ * saves; a short window keeps listing cheap without going stale. Defaults
33
+ * to 5 seconds; 0 disables caching.
34
+ */
35
+ projectSnapshotTtlMs?: number;
36
+ /**
37
+ * Freshness window for the cached user-dimension snapshot (defaults to the
38
+ * scan-cache TTL). It bounds how long out-of-band edits to local sources
39
+ * stay invisible; 0 disables snapshot caching. Tests pass a small value so
40
+ * staleness regressions need no real sleeps.
41
+ */
42
+ userSnapshotTtlMs?: number;
43
+ }
44
+ /** Key of one install entry in the persisted `installed` record. */
45
+ export declare function installKey(sourceId: string, suiteId: string): string;
46
+ /**
47
+ * How long an explicit caller waits for the derived refresh before answering
48
+ * anyway. The refresh keeps running; only the wait ends.
49
+ */
50
+ export declare const DERIVED_REFRESH_WAIT_MS = 10000;
51
+ export declare class CatalogContext implements SnapshotHost {
52
+ private currentState;
53
+ private mutationQueue;
54
+ private currentRevision;
55
+ private currentScanGeneration;
56
+ /**
57
+ * The project-layout switch in effect. The host settings document owns the
58
+ * value and pushes it here on registration and on every change; the initial
59
+ * value is the contract's declared default, which is what the catalog would
60
+ * read from the document before the settings service resolves.
61
+ */
62
+ private scanProjectLayoutsEnabled;
63
+ /** The derived refresh in flight, shared by every change that lands while it runs. */
64
+ private refreshPass;
65
+ /** Whether a change landed after the running pass started; it earns one more pass. */
66
+ private refreshQueued;
67
+ readonly statePath: string;
68
+ readonly userRoot: string;
69
+ readonly dataRoot: string;
70
+ readonly agentsRoot: string;
71
+ readonly git: CatalogGitOptions;
72
+ /** Discovery scans and dimension snapshots derived from {@link state}. */
73
+ readonly snapshots: SnapshotCache;
74
+ private readonly onChanged;
75
+ constructor(options: CatalogOptions);
76
+ get state(): SuiteState;
77
+ /** Bumped by every mutation: a snapshot built at an older revision is never published. */
78
+ get revision(): number;
79
+ /** Bumped by every content-changing mutation: a scan started earlier never repopulates its cache. */
80
+ get scanGeneration(): number;
81
+ /** Whether native project layouts (`.claude/`, `.agents/`) take part in discovery. */
82
+ get scanProjectLayouts(): boolean;
83
+ /** One install entry, or undefined when the suite is not installed. */
84
+ installed(sourceId: string, suiteId: string): InstalledEntry | undefined;
85
+ /** Load persisted user state once at plugin activation. */
86
+ load(): Promise<void>;
87
+ /** Replace the persisted state and write it out. */
88
+ commit(next: SuiteState): Promise<void>;
89
+ /** Apply the host's project-layout switch and invalidate every project snapshot. */
90
+ setScanProjectLayouts(enabled: boolean): Promise<void>;
91
+ /**
92
+ * Apply the install state to freshly discovered suites: enablement, the
93
+ * effective surface toggles, and the lock/install timestamps the market
94
+ * cards report.
95
+ */
96
+ project(discovered: readonly DiscoveredSuite[], state: SuiteState, dimension: SuiteDimension): Suite[];
97
+ /**
98
+ * Invalidate snapshots and schedule the change pipeline. `keepScanCache`
99
+ * marks state-only mutations (install, enable, surface toggles, MCP
100
+ * overrides) whose inputs leave every checkout untouched, so the next
101
+ * snapshot re-derives from cached discovery instead of rescanning the
102
+ * filesystem.
103
+ *
104
+ * The invalidation is synchronous and the refresh is coalesced in the
105
+ * background: resolving here means the state is durable, never that every
106
+ * mount has finished. Callers that must observe the refreshed surfaces await
107
+ * {@link refreshSettled}, whose wait is bounded so one stuck mount cannot
108
+ * hold a request — or the next mutation behind it — open.
109
+ */
110
+ notifyChanged(keepScanCache?: boolean): Promise<void>;
111
+ /**
112
+ * Resolve once the queued derived refresh finishes, `false` when the deadline
113
+ * elapses first. The refresh itself is never cancelled.
114
+ */
115
+ refreshSettled(deadlineMs?: number): Promise<boolean>;
116
+ /** Queue one derived refresh; a pass already in flight absorbs it. */
117
+ private scheduleRefresh;
118
+ /** Drop every cached dimension snapshot; `increment` advances the revision. */
119
+ invalidateSnapshot(increment: boolean): void;
120
+ /** Drop cached discovery and advance the generation a scan is validated against. */
121
+ invalidateScans(): void;
122
+ /** Serialize one mutation behind every mutation queued before it. */
123
+ enqueue<T>(operation: () => Promise<T>): Promise<T>;
124
+ }
@@ -1,251 +1,66 @@
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
+ /** The plugin storage root holding per-suite `${PLUGIN_DATA}` directories and overrides. */
28
+ get dataRoot(): string;
29
+ get sources(): SourceRef[];
30
+ /** Whether one suite currently carries an install entry. */
31
+ isInstalled(sourceId: string, suiteId: string): boolean;
112
32
  /** Apply the host's project-layout switch and invalidate every project snapshot. */
113
33
  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>;
34
+ /** Load persisted user state once at plugin activation. */
35
+ load(): Promise<void>;
36
+ /** Append config-seeded sources missing from user state and persist them. */
37
+ mergeSources(sources: SourceRef[]): Promise<void>;
175
38
  /**
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.
39
+ * Panel changed hook: the HTTP layer notifies after a user-panel mutation
40
+ * (skills / commands / agent personas). Catalog state is untouched — this
41
+ * only runs the change pipeline so the runtime remounts commands and the
42
+ * skill providers re-read their catalogs.
179
43
  */
180
- mcpBackendInfo(): Promise<{
181
- backend: McpBackend;
182
- hostClient: HostMcpClientProbe;
183
- downloadRegion: {
184
- setting: DownloadRegionSetting;
185
- effective: EffectiveRegion;
186
- };
187
- }>;
44
+ notifyPanelsChanged(): Promise<void>;
188
45
  /**
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.
46
+ * Wait for the derived refresh triggered by the latest change, bounded so a
47
+ * stuck mount reports back instead of holding an explicit retry open.
192
48
  */
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;
49
+ refreshSettled(deadlineMs?: number): Promise<boolean>;
207
50
  /** Read one coherent user-dimension snapshot, reusing in-flight discovery. */
208
51
  readUserCatalog(): Promise<CatalogSnapshot>;
209
52
  /** Read one coherent project-dimension snapshot for a workspace cwd. */
210
53
  readProjectCatalog(cwd: string): Promise<CatalogSnapshot>;
211
- private buildProjectSnapshot;
54
+ /** Runtime discovery scans only sources containing an enabled install. No acquisition or network access. */
55
+ enabledUserSuites(): Promise<Suite[]>;
56
+ /** The full market overview from one user snapshot. */
57
+ overview(): Promise<OverviewPayload>;
212
58
  /** One suite's full detail for the market detail modal. */
213
59
  suiteDetail(sourceId: string, suiteId: string): Promise<SuiteDetail>;
214
60
  /** One skill's full SKILL.md text for the market detail modal. */
215
61
  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;
62
+ /** Add a source and acquire it immediately (clone, download, or in-place). */
63
+ addSource(input: SourceInput): Promise<SourceRef>;
249
64
  /** Register one unmanaged `.sources/` checkout as a source without touching its files. */
250
65
  adoptSource(id: string): Promise<SourceRef>;
251
66
  /** Unmanaged `.sources/` checkouts: present on disk, absent from state. */
@@ -253,53 +68,21 @@ export declare class Catalog {
253
68
  id: string;
254
69
  url?: string;
255
70
  }>>;
256
- /** Progress snapshot of the source mutation currently in flight. */
257
- private currentSourceState;
71
+ /** Update one source's URL, branch, kind, or archive digest. */
72
+ updateSource(sourceId: string, patch: SourcePatch): Promise<void>;
73
+ /** Remove a source and its install entries; `deleteCheckout` also deletes the managed checkout. */
74
+ removeSource(sourceId: string, deleteCheckout?: boolean): Promise<void>;
75
+ /** Refresh one source checkout, or every source when sourceId is omitted. */
76
+ refreshSource(sourceId?: string): Promise<void>;
77
+ /** Progress snapshot for the progress route. */
78
+ sourceProgress(): SourceProgress;
258
79
  /** Begin reporting progress for a source mutation. */
259
80
  beginSourceState(sourceId: string, step: string, cloned: boolean): void;
260
81
  /** Advance the in-flight source mutation step. */
261
82
  updateSourceStep(step: string): void;
262
83
  /** Stop reporting source mutation progress. */
263
84
  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. */
85
+ /** Install a suite from a source and enable it. */
303
86
  install(sourceId: string, suiteId: string): Promise<void>;
304
87
  /** Uninstall a suite while retaining the source checkout. */
305
88
  uninstall(sourceId: string, suiteId: string): Promise<void>;
@@ -307,42 +90,63 @@ export declare class Catalog {
307
90
  setEnabled(sourceId: string, suiteId: string, enabled: boolean): Promise<void>;
308
91
  /** Enable or disable one runtime surface of an installed suite. */
309
92
  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>;
93
+ /** Build the flat MCP service inventory for the status surface. */
94
+ mcpStatus(): Promise<McpStatusPayload>;
95
+ /** Persist a user-owned MCP service and reconcile its bridge mount. */
96
+ addMcpServer(name: string, server: unknown): Promise<void>;
97
+ /** Read effective service configuration without exposing credential literals. */
98
+ serverConfig(kind: 'mcp' | 'lsp', id: string): Promise<ServerConfigPayload>;
99
+ /** Validate a complete replacement before writing; plugin checkouts remain untouched. */
100
+ saveServerConfig(kind: 'mcp' | 'lsp', id: string, config: unknown): Promise<void>;
101
+ /** One suite's persisted MCP overrides, addressed by qualified suite id. */
102
+ mcpOverrides(sourceId: string, suiteId: string): Promise<McpSuiteOverrides>;
103
+ /** Set or clear one server's MCP override and remount it. */
104
+ setMcpOverride(sourceId: string, suiteId: string, serverKey: string, override: McpServerOverride | null): Promise<void>;
312
105
  /**
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.
106
+ * Enable or disable one declared MCP server, addressed by the same
107
+ * source-qualified suite id its status row carries. Disabling writes an
108
+ * override rather than editing the suite's `mcp.json`, so a refresh cannot
109
+ * clobber the user's choice.
317
110
  */
318
- notifyPanelsChanged(): Promise<void>;
319
- private setInstalled;
111
+ setMcpServerEnabled(suiteKey: string, serverKey: string, enabled: boolean): Promise<void>;
112
+ /** Re-run the MCP reconcile pass without changing any catalog state. */
113
+ retryMounts(): Promise<void>;
114
+ /** The persisted MCP backend choice without the host-client probe. */
115
+ mcpBackend(): Promise<McpBackend>;
320
116
  /**
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.
117
+ * The active MCP mount backend plus a live probe of the host client, and
118
+ * the download-region setting with its locale-resolved effective route.
325
119
  */
326
- private acquire;
327
- /** The filesystem location of one source. */
328
- private sourceCheckoutPath;
329
- private buildSnapshot;
330
- private invalidateSnapshot;
331
- private invalidateScans;
120
+ mcpBackendInfo(): Promise<McpBackendInfo>;
121
+ /** Switch the MCP mount backend and remount every suite server through it. */
122
+ setMcpBackend(backend: McpBackend): Promise<void>;
123
+ /**
124
+ * Drop one MCP server's OAuth grant record so the next mount re-runs the
125
+ * browser authorization.
126
+ * @throws when the credentials service is not mounted.
127
+ */
128
+ reauthorizeMcpServer(serverName: string): Promise<void>;
129
+ /** Whether the re-authorize action can run in this composition. */
130
+ mcpReauthorizeAvailable(): boolean;
131
+ /** MCP overrides for a supplied runtime selection, or the full market catalog when omitted. */
132
+ allMcpOverrides(suites?: readonly Suite[]): Promise<Map<string, McpSuiteOverrides>>;
133
+ /** The LSP status surface: declared servers merged with mount diagnostics. */
134
+ lspStatus(): Promise<LspStatusPayload>;
135
+ /** The user's direct LSP server table (normalized specs). */
136
+ lspServers(): Promise<LspServerTable>;
137
+ /** Create one direct LSP declaration without replacing other user servers. */
138
+ addLspServer(name: string, config: unknown): Promise<void>;
139
+ /** Validate and persist the user's direct LSP server table. */
140
+ setLspServers(raw: unknown): Promise<LspServerTable>;
141
+ /** Enable or disable one declared language server by row id. */
142
+ setLspServerEnabled(id: string, enabled: boolean): Promise<void>;
332
143
  /**
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.
144
+ * Remove one profile's legacy LSP layer — the hand-written
145
+ * `cordis.patch.yml` rows an older release told users to add, which now
146
+ * register a seam this plugin owns.
337
147
  */
338
- private notifyChanged;
339
- private enqueue;
148
+ migrateLegacyLspSeam(profile: string): Promise<LspLegacySeamMigration>;
340
149
  }
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;
150
+ export type { CatalogGitOptions, CatalogOptions };
151
+ export type { CatalogSnapshot };
152
+ 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
+ }