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
@@ -20,7 +20,7 @@
20
20
  * attempt is recorded on the result, so callers can surface why a source
21
21
  * resolved the way it did.
22
22
  */
23
- import type { Suite } from '../model/types.js';
23
+ import type { DiscoveredSuite } from '../model/types.js';
24
24
  /** One filter's work context: the checkout and its identity. */
25
25
  export interface ScanContext {
26
26
  marketplacePath?: string;
@@ -40,7 +40,7 @@ export type ScanAbstentionReason = string;
40
40
  /** The outcome of one filter (or the whole chain) for one checkout. */
41
41
  export type ScanResolution = {
42
42
  kind: 'resolved';
43
- suites: Suite[];
43
+ suites: DiscoveredSuite[];
44
44
  } | {
45
45
  kind: 'abstain';
46
46
  reason: ScanAbstentionReason;
@@ -69,7 +69,7 @@ export interface ScanAttempt {
69
69
  /** The full outcome of scanning one checkout. */
70
70
  export interface ScanResult {
71
71
  marketplacePath?: string;
72
- suites: Suite[];
72
+ suites: DiscoveredSuite[];
73
73
  attempts: ScanAttempt[];
74
74
  /** Human-readable diagnostics: dropped entries, broken manifests, fallbacks taken. */
75
75
  notes: string[];
@@ -1,9 +1,6 @@
1
- import type { Suite, SuiteComponents, SuiteDimension } from '../model/types.js';
1
+ import type { DiscoveredSuite, SuiteComponents, SuiteDimension } from '../model/types.js';
2
2
  import { type MarketplaceEntry } from './manifests.js';
3
3
  import type { ScanChain, ScanContext, ScanFilter, ScanResolution, ScanResult } from './scan-pipeline.js';
4
- export { repoName } from './manifests.js';
5
- export { listMdFiles, discoverLspEntries, type LspEntry } from './surfaces.js';
6
- export type { MarketplaceEntry } from './manifests.js';
7
4
  export interface SuiteHint extends SuiteComponents {
8
5
  layout?: import('../model/layouts.js').ManifestKind;
9
6
  name?: string;
@@ -70,13 +67,10 @@ export declare class FlatCollectionsStrategy implements ScanFilter {
70
67
  }
71
68
  /** The default chain, most specific first with a terminal fallback. */
72
69
  export declare function defaultScanFilters(): readonly ScanFilter[];
73
- /** Discover every suite under one source checkout. */
74
- export declare function discoverSuitesInSource(checkoutDir: string, sourceId: string, dimension: SuiteDimension, sourceUrl?: string): Promise<Suite[]>;
75
70
  /** Scan one checkout through the filter chain with full diagnostics. */
76
71
  export declare function scanSource(checkoutDir: string, sourceId: string, dimension: SuiteDimension, sourceUrl?: string): Promise<ScanResult>;
77
- /** Whether a directory carries any known suite manifest. */
78
- export declare function hasSuiteManifest(dir: string): Promise<boolean>;
79
72
  /** Whether a directory carries skill files in the flat or bundled shape. */
80
73
  export declare function hasSkillFiles(dir: string): Promise<boolean>;
81
74
  /** Read one suite root into the normalized shape, or undefined when no manifest parses. */
82
- export declare function readSuite(root: string, sourceId: string, dimension: SuiteDimension, hint: SuiteHint | undefined, notes?: string[]): Promise<Suite | undefined>;
75
+ export declare function readSuite(root: string, sourceId: string, dimension: SuiteDimension, hint: SuiteHint | undefined, notes?: string[]): Promise<DiscoveredSuite | undefined>;
76
+ export {};
@@ -5,18 +5,24 @@ export interface ParsedSkillFrontmatter {
5
5
  whenToUse?: string;
6
6
  invocation: SkillInvocationPolicy;
7
7
  }
8
- /** Kebab-case skill names only, matching the shipped provider's rule. */
9
- export declare function isSkillName(name: string): boolean;
10
- /**
11
- * Normalize a display-style skill name into kebab-case (e.g. "Presentations"
12
- * → "presentations"), or `undefined` when nothing usable remains.
13
- */
14
- export declare function normalizeSkillName(name: string): string | undefined;
15
8
  /**
16
9
  * Parse skill frontmatter with the shipped provider's fail-closed semantics.
17
10
  * @returns the parsed frontmatter, or a rejection string explaining why the
18
11
  * skill must be dropped from discovery.
19
12
  */
20
13
  export declare function parseSkillFrontmatter(text: string, expectedName: string | undefined): ParsedSkillFrontmatter | string;
14
+ /**
15
+ * Rejection for a user skill document the harness's own `dsh-skill-filesystem`
16
+ * reader would drop from `~/.agents/skills`, or `undefined` when that reader
17
+ * accepts it.
18
+ *
19
+ * The two readers share the directory, so the panel publishes only documents
20
+ * both accept: a listed entry never becomes a skill that loads in a
21
+ * market-equipped session alone. The checks mirror the shipped reader rather
22
+ * than the lenient suite scan — strict YAML, no display-name normalization,
23
+ * and a `name` the reader compares only against its kebab grammar.
24
+ * @returns the drop reason, phrased as the reader's own diagnostic.
25
+ */
26
+ export declare function skillEntryRejection(text: string): string | undefined;
21
27
  /** Strip the frontmatter block, returning the instruction body. */
22
28
  export declare function stripFrontmatter(text: string): string;
@@ -1,8 +1,13 @@
1
- import type { SourceRef, Suite, SuiteDimension } from '../model/types.js';
1
+ import type { DiscoveredSuite, SourceRef, SuiteDimension } from '../model/types.js';
2
2
  /** Discover suites from the selected configured or project checkouts. */
3
- export declare function discoverSourceList(sources: SourceRef[], dimension: SuiteDimension, dimensionRoot: string): Promise<Suite[]>;
4
- /** Discover suites plus per-source scan diagnostics for one dimension. */
5
- export declare function discoverSourceListWithNotes(sources: SourceRef[], dimension: SuiteDimension, dimensionRoot: string, scanProjectLayouts?: boolean): Promise<{
6
- suites: Suite[];
3
+ export declare function discoverSourceList(sources: SourceRef[], dimension: SuiteDimension, dimensionRoot: string): Promise<DiscoveredSuite[]>;
4
+ /**
5
+ * Discover suites plus per-source scan diagnostics for one dimension.
6
+ * @param scanProjectLayouts - whether the project's own native Agent directories
7
+ * join the scan. Required on purpose: the switch has one owner (the host
8
+ * settings document), so a default here would be a second copy of it.
9
+ */
10
+ export declare function discoverSourceListWithNotes(sources: SourceRef[], dimension: SuiteDimension, dimensionRoot: string, scanProjectLayouts: boolean): Promise<{
11
+ suites: DiscoveredSuite[];
7
12
  scanNotes: Record<string, string[]>;
8
13
  }>;
@@ -4,13 +4,15 @@
4
4
  * The actual discovery lives in the strategy chain (`scan-pipeline.ts` +
5
5
  * `scan-resolvers.ts`); this module is the compatibility facade that keeps
6
6
  * the historical imports (`discoverSuitesInSource`, `repoName`,
7
- * `listMdFiles`, `LspEntry`) stable for callers and tests.
7
+ * `listMdFiles`) stable for callers and tests.
8
8
  */
9
- import type { Suite, SuiteDimension } from '../model/types.js';
10
- export { repoName, listMdFiles, discoverLspEntries, scanSource, canonicalGitUrl, resolveMarketplaceEntry, defaultScanFilters, MarketplaceStrategy, RootedStrategy, FlatCollectionsStrategy } from './scan-resolvers.js';
11
- export type { MarketplaceEntry, EntryResolution, EntryHandler, SuiteHint } from './scan-resolvers.js';
12
- export type { LspEntry } from './surfaces.js';
9
+ import type { DiscoveredSuite, SuiteDimension } from '../model/types.js';
10
+ export { repoName } from './manifests.js';
11
+ export { listMdFiles, discoverLspEntries } from './surfaces.js';
12
+ export { scanSource, canonicalGitUrl, resolveMarketplaceEntry, defaultScanFilters, MarketplaceStrategy, RootedStrategy, FlatCollectionsStrategy } from './scan-resolvers.js';
13
+ export type { MarketplaceEntry } from './manifests.js';
14
+ export type { EntryResolution, EntryHandler, SuiteHint } from './scan-resolvers.js';
13
15
  export { runScanChain } from './scan-pipeline.js';
14
16
  export type { ScanContext, ScanFilter, ScanChain, ScanResolution, ScanAttempt, ScanResult } from './scan-pipeline.js';
15
17
  /** Discover every suite under one source checkout. */
16
- export declare function discoverSuitesInSource(checkoutDir: string, sourceId: string, dimension: SuiteDimension, sourceUrl?: string): Promise<Suite[]>;
18
+ export declare function discoverSuitesInSource(checkoutDir: string, sourceId: string, dimension: SuiteDimension, sourceUrl?: string): Promise<DiscoveredSuite[]>;
@@ -32,5 +32,3 @@ export declare function validateMcpJson(pluginRoot: string, raw: unknown, option
32
32
  export declare function expandPlaceholders(value: string, pluginRoot: string, pluginData: string, env?: NodeJS.ProcessEnv): string;
33
33
  /** Resolve an expanded plugin-relative cwd to an absolute path. */
34
34
  export declare function resolveCwd(value: string, pluginRoot: string, pluginData: string): string;
35
- /** Whether one absolute path equals or lies under another absolute path. */
36
- export declare function isWithin(root: string, candidate: string): boolean;
@@ -50,4 +50,39 @@ export interface LspStatusPayload {
50
50
  };
51
51
  /** True when the host lacks the LSP packages, so every declaration is blocked. */
52
52
  hostMissing: boolean;
53
+ /**
54
+ * A profile layer that still registers the seam this plugin owns, present
55
+ * only while a `seam-conflict` is actually being reported. Releases before
56
+ * the plugin provisioned LSP itself told users to add such a layer by hand,
57
+ * so an upgrade can land here and the panel offers to remove it.
58
+ */
59
+ legacySeam?: LspLegacySeam;
60
+ }
61
+ /** One profile layer that must be removed before this plugin can own the LSP seam. */
62
+ export interface LspLegacySeam {
63
+ /** Profile name, as passed to `dsh --profile`. */
64
+ profile: string;
65
+ /** Absolute path of the profile's patch file. */
66
+ patchPath: string;
67
+ /** The conflicting `insert` rows, as `id` plus package name. */
68
+ rows: Array<{
69
+ id: string;
70
+ name: string;
71
+ }>;
72
+ /** Other profiles carrying a legacy layer, which this action does not touch. */
73
+ otherProfiles: string[];
74
+ /** Whether the host must restart before the removal takes effect. */
75
+ restartRequired: boolean;
76
+ /** Human-readable summary of the layer, used in the panel copy. */
77
+ summary: string;
78
+ }
79
+ /** The outcome of removing one profile's legacy LSP layer. */
80
+ export interface LspLegacySeamMigration {
81
+ profile: string;
82
+ /** Absolute path of the patch file that was edited. */
83
+ patchPath: string;
84
+ /** Where the pre-edit content was kept. */
85
+ backupPath: string;
86
+ /** True when the host must restart before the removal takes effect. */
87
+ restartRequired: boolean;
53
88
  }
@@ -9,6 +9,7 @@ export declare const MARKET_ROUTES: {
9
9
  readonly lspStatus: "/api/agent-plugins/lsp-status";
10
10
  readonly lspServers: "/api/agent-plugins/lsp-servers";
11
11
  readonly addLspServer: "/api/agent-plugins/lsp-servers/add";
12
+ readonly migrateLspSeam: "/api/agent-plugins/lsp-servers/migrate-seam";
12
13
  readonly serverConfig: "/api/agent-plugins/server-config";
13
14
  readonly saveServerConfig: "/api/agent-plugins/server-config/save";
14
15
  readonly progress: "/api/agent-plugins/progress";
@@ -27,6 +28,7 @@ export declare const MARKET_ROUTES: {
27
28
  readonly setSurface: "/api/agent-plugins/set-surface";
28
29
  readonly mcpOverrides: "/api/agent-plugins/mcp-overrides";
29
30
  readonly setMcpOverride: "/api/agent-plugins/set-mcp-override";
31
+ readonly setMcpServerEnabled: "/api/agent-plugins/set-mcp-server-enabled";
30
32
  readonly mcpRetry: "/api/agent-plugins/mcp-retry";
31
33
  readonly mcpReauthorize: "/api/agent-plugins/mcp-reauthorize";
32
34
  readonly mcpBackend: "/api/agent-plugins/mcp-backend";
@@ -71,7 +73,7 @@ export declare function userPanelRoute(kind: UserPanelKind): string;
71
73
  /** Build one user-panel mutation route URL (all POSTs). */
72
74
  export declare function userPanelMutationRoute(kind: UserPanelKind, mutation: UserPanelMutation, name?: string): string;
73
75
  /** The MCP mount backend state reported to the settings page. */
74
- export interface McpBackendPayload {
76
+ export type McpBackendInfo = {
75
77
  backend: 'builtin' | 'host';
76
78
  /** Whether the host `dsh-mcp-client` resolves from the plugin context. */
77
79
  hostClient: {
@@ -83,7 +85,7 @@ export interface McpBackendPayload {
83
85
  setting: 'auto' | 'global' | 'china';
84
86
  effective: 'global' | 'china';
85
87
  };
86
- }
88
+ };
87
89
  /** One unmanaged `.sources/` checkout the user can adopt as a source. */
88
90
  export interface UnmanagedSource {
89
91
  id: string;
@@ -242,6 +244,8 @@ export interface SuiteDetail {
242
244
  description: string | null;
243
245
  author: string | null;
244
246
  keywords: string[];
247
+ /** Last modification of the suite checkout, as an ISO timestamp; null when it cannot be read. */
248
+ updatedAt: string | null;
245
249
  layout: string;
246
250
  dimension: string;
247
251
  root: string;
@@ -272,6 +276,7 @@ export interface SkillContent {
272
276
  }
273
277
  /** A user panel entry (skills / commands / agent personas) over HTTP. */
274
278
  export interface UserPanelEntryWire {
279
+ /** Entry name: the name its document declares, else the file's base name. */
275
280
  name: string;
276
281
  description: string;
277
282
  disabled: boolean;
@@ -283,7 +288,13 @@ export interface UserPanelEntryWire {
283
288
  suiteName?: string;
284
289
  metadata: Record<string, unknown>;
285
290
  path: string;
291
+ /** The entry file's last modification, as an ISO timestamp. */
292
+ updatedAt?: string | null;
286
293
  content: string;
294
+ /** Suite checkout root of a plugin-provided file; runtime consumers resolve `${PLUGIN_ROOT}` against it. */
295
+ suiteRoot?: string;
296
+ /** The suite's `${PLUGIN_DATA}` directory, for the same runtime resolution. */
297
+ suiteData?: string;
287
298
  }
288
299
  /** The user panel surface the market exposes. */
289
300
  export type UserPanelKind = 'skills' | 'commands' | 'agents';
@@ -35,6 +35,10 @@ export interface McpStatusEntry {
35
35
  advertisedTools?: boolean;
36
36
  /** Whether a failed server will be retried automatically. */
37
37
  retryable?: boolean;
38
+ /** A remote server whose suite declares no `auth` block: the bridge still
39
+ * runs the OAuth flow when the server answers 401, which the redacted
40
+ * configuration alone cannot show. */
41
+ oauthDefault?: boolean;
38
42
  }
39
43
  /** The MCP status response returned by the host. */
40
44
  export interface McpStatusPayload {
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Browser-safe settings contract of the market's host settings namespace: the
3
+ * namespace key, the fields with their defaults, and the one reader that turns
4
+ * a stored section into resolved values.
5
+ *
6
+ * The defaults live here and nowhere else. The namespace schema declares them
7
+ * to the host, the node half reads them back through {@link resolveMarketSettings},
8
+ * and the browser half — which cannot import `src/runtime` — reads the same
9
+ * resolved values off the settings snapshot it is handed. Changing a default is
10
+ * therefore a one-line edit in this module.
11
+ *
12
+ * @module contracts/settings
13
+ */
14
+ /** Settings namespace this plugin registers; the key the plugin-config tab pairs our card by. */
15
+ export declare const MARKET_SETTINGS_NAMESPACE = "dsh-agent-plugins-market";
16
+ /** The persisted download-region setting: `auto` follows the interface language. */
17
+ export type DownloadRegionSetting = 'auto' | 'global' | 'china';
18
+ /** Every market setting with the value it resolves to when the document says nothing. */
19
+ export interface MarketSettings {
20
+ /** ON = the built-in MCP bridge with OAuth and SSE; OFF = host client compat mode. */
21
+ mcpEnhanced: boolean;
22
+ /** ON = native project Agent layouts (`.claude/`, `.agents/`) take part in discovery. */
23
+ scanProjectLayouts: boolean;
24
+ /** Download region for GitHub acquisition. */
25
+ downloadRegion: DownloadRegionSetting;
26
+ /** ON = the `report_market_issue` model tool is registered. */
27
+ feedbackEnabled: boolean;
28
+ /** ON = every configured source refreshes in the background. */
29
+ autoUpdateSources: boolean;
30
+ }
31
+ /**
32
+ * The default of every market setting — the single place one is written.
33
+ *
34
+ * These are user-visible behavior: a flip here is a behavior change that ships
35
+ * with its documentation, not a private implementation detail.
36
+ */
37
+ export declare const MARKET_SETTINGS_DEFAULTS: MarketSettings;
38
+ /** Every field name the market's settings section carries. */
39
+ export type MarketSettingKey = keyof MarketSettings;
40
+ /**
41
+ * Narrow an untrusted stored region to a setting; anything else reads as the
42
+ * declared default.
43
+ * @param value - the stored `downloadRegion` value.
44
+ * @param fallback - the value an unrecognized input reads as.
45
+ */
46
+ export declare function narrowDownloadRegion(value: unknown, fallback?: DownloadRegionSetting): DownloadRegionSetting;
47
+ /**
48
+ * Resolve a stored settings section the way the host resolves it: each field
49
+ * takes its stored value when it is one this field accepts, and its declared
50
+ * default otherwise.
51
+ *
52
+ * The host hands the resolved section back on its own, but not every caller has
53
+ * one — the plugin's own halves read a section they may not have received yet,
54
+ * and a test hands in a bare literal. Funnelling all of them through this
55
+ * function is what keeps a second reading of "what does missing mean" from
56
+ * growing somewhere else.
57
+ * @param section - the stored (or absent) namespace section, untrusted.
58
+ */
59
+ export declare function resolveMarketSettings(section: unknown): MarketSettings;
@@ -42,6 +42,10 @@ export declare const MANIFEST_ALIASES: Partial<Record<ManifestKind, readonly str
42
42
  /** Equivalent plugin-owned path variables; these never resolve as credentials. */
43
43
  export declare const PLUGIN_ROOT_VARIABLES: ReadonlySet<string>;
44
44
  export declare const PLUGIN_DATA_VARIABLES: ReadonlySet<string>;
45
+ /** Equivalent session project-directory variables; only a calling session supplies the directory. */
46
+ export declare const PROJECT_DIR_VARIABLES: ReadonlySet<string>;
47
+ /** Claude Code names the directory holding the skill's own file; no dialect alias exists. */
48
+ export declare const SKILL_DIR_VARIABLE = "CLAUDE_SKILL_DIR";
45
49
  /** Explicit project document formats and portable surfaces; execution stays in the runtime adapters. */
46
50
  export type ProjectMcpFormat = 'mcpServers' | 'zcode' | 'codex';
47
51
  export type ProjectHookFormat = 'claude' | 'zcode';
@@ -50,6 +54,11 @@ export interface ProjectLayout {
50
54
  label: string;
51
55
  subdirs: readonly string[];
52
56
  mcpFiles?: readonly string[];
57
+ /**
58
+ * Project-root-relative hook documents, read in order. A `settings.json`
59
+ * layer carries a `hooks` key; a standalone `hooks.json` may instead be the
60
+ * bare event table, the same file shape a suite ships under `hooks/`.
61
+ */
53
62
  hookFiles?: readonly string[];
54
63
  mcpFormat?: ProjectMcpFormat;
55
64
  hookFormat?: ProjectHookFormat;
@@ -64,6 +73,7 @@ export declare const PROJECT_LAYOUTS: readonly [{
64
73
  readonly dirName: ".agents";
65
74
  readonly label: "agents";
66
75
  readonly subdirs: readonly ["skills", "agents", "commands"];
76
+ readonly hookFiles: readonly [".agents/hooks/hooks.json", ".agents/hooks.json"];
67
77
  }, {
68
78
  readonly dirName: ".codex";
69
79
  readonly label: "Codex";
@@ -26,8 +26,20 @@ export interface SourceRef {
26
26
  /** The checkout pre-existed (manually cloned or adopted); never deleted on source removal. */
27
27
  adopted?: boolean;
28
28
  }
29
+ /**
30
+ * Archive URL suffixes with the payload kind each names, longest suffix first
31
+ * so `.tar.gz` wins over `.tar`. Source-kind inference, source-id derivation,
32
+ * and archive extraction all read this one table.
33
+ */
34
+ export declare const ARCHIVE_SUFFIXES: readonly [readonly [".tar.gz", "targz"], readonly [".tgz", "targz"], readonly [".zip", "zip"], readonly [".tar", "tar"]];
35
+ /** Payload kind of an archive source. */
36
+ export type ArchiveFormat = (typeof ARCHIVE_SUFFIXES)[number][1];
37
+ /** Classify an archive URL by extension; undefined when unsupported. */
38
+ export declare function archiveFormatOf(url: string): ArchiveFormat | undefined;
29
39
  /** Whether a URL points at a downloadable archive. */
30
40
  export declare function isArchiveUrl(url: string): boolean;
41
+ /** Drop a trailing archive suffix (`plugin-0.1.zip` → `plugin-0.1`); other values pass through. */
42
+ export declare function stripArchiveSuffix(value: string): string;
31
43
  /**
32
44
  * Effective acquisition kind of a source: the explicit `kind` wins, the
33
45
  * legacy `local` flag maps to `'local'`, archive-shaped URLs infer
@@ -163,8 +175,13 @@ export interface LspSuiteConfig {
163
175
  }
164
176
  /** Install dimension of a suite. */
165
177
  export type SuiteDimension = 'user' | 'project';
166
- /** One discovered suite with runtime-relevant fields resolved. */
167
- export interface Suite {
178
+ /**
179
+ * One suite as scanning produced it, with runtime-relevant fields resolved:
180
+ * no install entry has been merged in, so there is no lock commit, install
181
+ * timestamp, or effective surface set — except where the layout describes the
182
+ * set itself (project-native). Runtime consumers take {@link Suite}.
183
+ */
184
+ export interface DiscoveredSuite {
168
185
  resources?: {
169
186
  commands: SuiteMarkdownResource[];
170
187
  agents: SuiteMarkdownResource[];
@@ -184,7 +201,7 @@ export interface Suite {
184
201
  surfaces: SuiteSurfaceCounts;
185
202
  dimension: SuiteDimension;
186
203
  enabled: boolean;
187
- /** Effective per-surface enablement (overrides merged over enabled defaults). */
204
+ /** Effective per-surface enablement, declared only by a self-describing layout. */
188
205
  activeSurfaces?: Record<SuiteSurfaceKey, boolean>;
189
206
  lockCommit?: string;
190
207
  installedAt?: string;
@@ -196,6 +213,15 @@ export interface Suite {
196
213
  /** Surface diagnostics on a surviving suite; invalid declared manifests are rejected before discovery returns a suite. */
197
214
  errors: string[];
198
215
  }
216
+ /**
217
+ * A suite with its install state applied: the shape `CatalogContext.project()`
218
+ * returns and every runtime consumer takes. The effective surface set is
219
+ * always present, so no consumer has to interpret its absence.
220
+ */
221
+ export interface Suite extends DiscoveredSuite {
222
+ /** Effective per-surface enablement (overrides merged over enabled defaults). */
223
+ activeSurfaces: Record<SuiteSurfaceKey, boolean>;
224
+ }
199
225
  export interface ProjectHooks {
200
226
  projectRoot: string;
201
227
  events: Record<string, Array<{
@@ -229,5 +255,3 @@ export interface SuiteState {
229
255
  sources: SourceRef[];
230
256
  installed: Record<string, InstalledEntry>;
231
257
  }
232
- /** Browser-safe market records are shared from the transport contracts. */
233
- export type { OverviewPayload, SourceOverview, SuiteOverviewCard } from '../contracts/market.js';
@@ -0,0 +1,6 @@
1
+ /** Internal IDs stay opaque to callers; only colliding resource names need qualification. */
2
+ export declare function namedAgentRoles<T extends {
3
+ name: string;
4
+ }>(entries: readonly T[]): Array<T & {
5
+ callName: string;
6
+ }>;
@@ -1,10 +1,7 @@
1
1
  import type { Context } from '@deepseek-ai/cordis';
2
2
  import { type SubagentCatalogEntry } from './subagent-catalog.js';
3
3
  import { type HostTranslate } from './host-locale.js';
4
- type JsonValue = string | number | boolean | null | JsonValue[] | {
5
- [key: string]: JsonValue;
6
- };
7
- export declare const AGENT_ROLE_TOOL_NAME = "subagents_run";
4
+ export declare const AGENT_ROLE_TOOL_NAME = "subagent_run";
8
5
  /** Panel identity is preserved so identically named cards from different suites remain addressable. */
9
6
  export interface AgentRoleEntry {
10
7
  name: string;
@@ -13,7 +10,15 @@ export interface AgentRoleEntry {
13
10
  disabled: boolean;
14
11
  title?: string;
15
12
  rawText?: string;
13
+ /** Suite checkout root the card's `${PLUGIN_ROOT}` variables resolve to; absent for project-native files. */
14
+ suiteRoot?: string;
15
+ /** The suite's `${PLUGIN_DATA}` directory; absent for project-native files. */
16
+ suiteData?: string;
16
17
  }
18
+ /**
19
+ * The executable part of one card. `tools` / `disallowedTools` stay in the file
20
+ * and are preserved by the editors, but they are not applied.
21
+ */
17
22
  export interface AgentRolePolicy {
18
23
  content: string;
19
24
  model?: string;
@@ -21,75 +26,77 @@ export interface AgentRolePolicy {
21
26
  reasoningEffort?: string;
22
27
  title?: string;
23
28
  description?: string;
24
- tools?: string[];
25
- disallowedTools?: string[];
26
29
  disabled: boolean;
27
30
  }
28
- /** Strict YAML parsing prevents malformed routing/restriction metadata from silently inheriting wider privileges. */
29
- export declare function parseAgentRole(text: string): AgentRolePolicy;
30
- interface ModelCatalog {
31
- listProviders(): {
32
- id: string;
33
- }[];
34
- listModels(provider: string): Promise<{
35
- id: string;
36
- }[]>;
37
- resolveCallConfig(config: {
38
- provider: string;
39
- model: string;
40
- reasoningEffort?: string;
41
- }, signal?: AbortSignal): Promise<unknown>;
42
- }
43
- /** Bare ids must resolve uniquely; Claude aliases are accepted only if actually advertised by a DSH provider. */
44
- export declare function resolveAgentModel(policy: AgentRolePolicy, catalog: ModelCatalog): Promise<{
31
+ /** Child LLM options this plugin sends; never carries inherited parent values. */
32
+ export interface AgentRoleOptions {
45
33
  provider?: string;
46
34
  model?: string;
47
- }>;
48
- export interface AgentRoleRequest {
49
- label: string;
35
+ reasoningEffort?: string;
36
+ }
37
+ /** What the host `ctx.subagents` seam receives for one role delegation. */
38
+ export interface AgentRoleDelegation {
50
39
  prompt: {
51
40
  type: 'text';
52
41
  text: string;
53
42
  }[];
54
43
  parent: unknown;
55
- signal: AbortSignal;
56
44
  maxDepth: number;
57
- agentOptions: {
58
- provider?: string;
59
- model?: string;
60
- reasoningEffort?: string;
61
- };
62
45
  persona: string;
63
- toolFilter?: {
64
- allow?: string[];
65
- deny?: string[];
66
- };
46
+ agentOptions?: AgentRoleOptions;
67
47
  }
68
48
  export interface AgentRoleHost {
69
49
  tools: {
70
50
  register(definition: unknown): () => void;
71
51
  };
72
- llm: ModelCatalog;
52
+ llm: {
53
+ resolveCallConfig(config: {
54
+ provider: string;
55
+ model: string;
56
+ reasoningEffort?: string;
57
+ }, signal?: AbortSignal): Promise<unknown>;
58
+ };
73
59
  subagents: {
74
- start(provider: string, request: AgentRoleRequest): Promise<{
75
- id: string;
76
- result: Promise<{
77
- stopReason: string;
78
- output: JsonValue[];
79
- }>;
80
- dispose(): void | Promise<void>;
60
+ startContinuable(spec: {
61
+ provider: string;
62
+ label: string;
63
+ request: AgentRoleDelegation;
64
+ signal: AbortSignal;
65
+ }): Promise<{
66
+ childId: string;
67
+ messageId: string;
81
68
  }>;
82
69
  };
83
70
  }
84
- /** Read the same declaration for catalog summaries and execution, including inline resources. */
85
- export declare function readAgentRole(entry: AgentRoleEntry): Promise<AgentRolePolicy>;
71
+ /** Strict YAML parsing prevents malformed routing metadata from silently inheriting wider privileges. */
72
+ export declare function parseAgentRole(text: string): AgentRolePolicy;
73
+ /**
74
+ * Resolve the child LLM options one card may contribute.
75
+ *
76
+ * A card route is advisory. Only an exact `provider` plus `model` pair is
77
+ * applied, and only when the live LLM runtime accepts it; every other
78
+ * declaration — a bare id, a Claude alias, a lone `provider`, an unsupported
79
+ * effort — degrades to inheriting the parent route and reports a diagnostic.
80
+ * @param policy - the card's parsed routing metadata.
81
+ * @param parent - the calling Agent whose route an unusable declaration falls back to.
82
+ * @param llm - live LLM runtime owning provider, model and effort validation.
83
+ * @param signal - tool-call cancellation signal.
84
+ * @param subject - role name used in diagnostics.
85
+ * @param diagnose - diagnostic sink; degradation is reported, never silent.
86
+ * @returns the options to send, or undefined for pure inheritance.
87
+ */
88
+ export declare function resolveAgentOptions(policy: AgentRolePolicy, parent: unknown, llm: AgentRoleHost['llm'], signal: AbortSignal, subject: string, diagnose: (message: string) => void): Promise<AgentRoleOptions | undefined>;
86
89
  /** Stable summaries; invalid declarations are excluded and transient read failures abort publication. */
87
- export declare function agentRoleCatalog(entries: AgentRoleEntry[], signal: AbortSignal, diagnose?: (message: string) => void): Promise<SubagentCatalogEntry[]>;
88
- /** Resolve fresh panel state and raw Markdown on every call, including after edits, disabling and uninstall. */
89
- export declare function executeAgentRole(host: AgentRoleHost, listRoles: (parent?: unknown) => Promise<AgentRoleEntry[]>, name: string, prompt: string, parent: unknown, signal: AbortSignal): Promise<{
90
- runId: string;
91
- output: JsonValue[];
90
+ export declare function agentRoleCatalog(entries: AgentRoleEntry[], signal: AbortSignal, diagnose?: (message: string) => void, projectDir?: string): Promise<SubagentCatalogEntry[]>;
91
+ /** Read the same declaration for catalog summaries and execution, including inline resources. */
92
+ export declare function readAgentRole(entry: AgentRoleEntry, projectDir?: string): Promise<AgentRolePolicy>;
93
+ /**
94
+ * Start one role child and return its durable id without waiting for the result.
95
+ * Resume state, steering, and the settlement notice belong to the host's
96
+ * continuation manager; this executor owns only role resolution.
97
+ */
98
+ export declare function executeAgentRole(host: AgentRoleHost, listRoles: (parent?: unknown) => Promise<AgentRoleEntry[]>, agentName: string, prompt: string, parent: unknown, signal: AbortSignal, diagnose?: (message: string) => void): Promise<{
99
+ subagentId: string;
92
100
  }>;
93
101
  /** Mount once after tools, llm and subagents are available; the returned disposer belongs to the plugin lifecycle. */
94
102
  export declare function mountAgentRoleTool(ctx: Context, listRoles: (parent?: unknown) => Promise<AgentRoleEntry[]>, t?: HostTranslate): () => void;
95
- export {};
@@ -3,12 +3,13 @@
3
3
  * register as dsh slash commands.
4
4
  *
5
5
  * A CC command is a prompt template the model executes (its body carries
6
- * `$ARGUMENTS` and execution rules), so the handler maps it onto the
7
- * harness's follow-up mechanism: the template with `$ARGUMENTS` substituted
8
- * becomes one durable user-role follow-up message on the receiving agent.
9
- * Registrations reconcile on every enable/disable/install/uninstall; a
10
- * broken command file or an unavailable `ctx.commands` is contained per
11
- * command and reported as a diagnostic.
6
+ * `$ARGUMENTS`, path variables and `` !`cmd` `` dynamic-context placeholders),
7
+ * so the handler maps it onto the harness's follow-up mechanism: the template
8
+ * with those placeholders resolved becomes one durable user-role follow-up
9
+ * message on the receiving agent. Registrations reconcile on every
10
+ * enable/disable/install/uninstall; a broken command file, a failed injected
11
+ * command, or an unavailable `ctx.commands` is contained per command and
12
+ * reported as a diagnostic.
12
13
  */
13
14
  import type { Context } from '@deepseek-ai/cordis';
14
15
  import type { Suite, SuiteMarkdownResource } from '../model/types.js';
@@ -23,13 +24,20 @@ interface CommandSpec {
23
24
  description: string;
24
25
  body: string;
25
26
  hint?: string;
27
+ /** Set when the command file belongs to a suite with a plugin root; absent for project-native files. */
28
+ suiteRoot?: string;
29
+ /** The suite's `${PLUGIN_DATA}` directory; absent for project-native files. */
30
+ suiteData?: string;
26
31
  }
27
32
  export declare class CommandMountRegistry {
28
33
  private readonly ctx;
29
34
  private readonly t;
35
+ private readonly dataRoot?;
30
36
  private readonly fingerprints;
31
37
  private readonly live;
32
- constructor(ctx: Context, t?: HostTranslate);
38
+ constructor(ctx: Context, t?: HostTranslate, dataRoot?: string | undefined);
39
+ /** The live shell seam, when the profile has one; dynamic context stays literal without it. */
40
+ private shell;
33
41
  /** Register/unregister suite commands to match the enabled suites exactly. */
34
42
  reconcile(enabledSuites: Suite[]): Promise<CommandMountDiagnostic[]>;
35
43
  /** Dispose every registered command; used at plugin teardown. */
@@ -0,0 +1,17 @@
1
+ /** Identifies this plugin's bounded waits inside a timeout reason. */
2
+ export declare const MARKET_DEADLINE_CODE = "MARKET_DEADLINE";
3
+ /**
4
+ * Resolve `true` once `work` settles, or `false` when `deadlineMs` elapses.
5
+ *
6
+ * A rejection counts as settled: this helper only reports timing, so callers
7
+ * that need the failure attach their own handler to `work`.
8
+ *
9
+ * A non-positive wait means "do not wait": the answer is simply whether the
10
+ * work had already settled. That is deliberately not the host primitive's own
11
+ * reading of a non-positive timeout, which is "arm no timer at all" — the floor
12
+ * below keeps the two from collapsing into opposite behaviors.
13
+ * @param work - the work to wait for; it is never cancelled, only stopped being awaited.
14
+ * @param deadlineMs - how long to wait, in milliseconds.
15
+ * @returns whether the work settled before the deadline.
16
+ */
17
+ export declare function settlesWithin(work: Promise<unknown>, deadlineMs: number): Promise<boolean>;