dsh-agent-plugins-market 0.7.1 → 0.7.2

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 (61) hide show
  1. package/README.md +29 -24
  2. package/README.zh.md +29 -24
  3. package/client/client.js +1172 -159
  4. package/client/client.js.map +1 -1
  5. package/lib/application/catalog.js +14 -2
  6. package/lib/application/install-store.js +1 -1
  7. package/lib/application/mcp-service.js +185 -30
  8. package/lib/catalog/archive.js +15 -0
  9. package/lib/catalog/manifests.js +124 -13
  10. package/lib/catalog/scan-resolvers.js +117 -12
  11. package/lib/catalog/surfaces.js +73 -27
  12. package/lib/catalog/validate.js +205 -54
  13. package/lib/contracts/market.js +2 -0
  14. package/lib/index.js +6 -2
  15. package/lib/model/layouts.js +34 -0
  16. package/lib/model/preset-source.js +8 -0
  17. package/lib/routes.js +31 -2
  18. package/lib/runtime/agent-role-router.js +176 -51
  19. package/lib/runtime/host-locale.js +6 -12
  20. package/lib/runtime/mcp-client/connection.js +3 -2
  21. package/lib/runtime/mcp-client/oauth.js +82 -14
  22. package/lib/runtime/mcp-client/tools.js +2 -1
  23. package/lib/runtime/mcp-config.js +178 -34
  24. package/lib/runtime/mcp-direct-config.js +49 -6
  25. package/lib/runtime/mcp-mounts.js +15 -3
  26. package/lib/runtime/mcp-overrides.js +131 -1
  27. package/lib/runtime/mcp-redaction.js +8 -0
  28. package/lib/runtime/mcp-status.js +21 -5
  29. package/lib/runtime/server-config.js +49 -8
  30. package/lib/runtime/subagent-catalog.js +62 -22
  31. package/lib/runtime/tool-registry-observer.js +8 -4
  32. package/lib/types/application/catalog.d.ts +10 -1
  33. package/lib/types/application/install-store.d.ts +1 -1
  34. package/lib/types/application/mcp-service.d.ts +32 -3
  35. package/lib/types/application/queries.d.ts +6 -1
  36. package/lib/types/catalog/manifests.d.ts +6 -2
  37. package/lib/types/catalog/surfaces.d.ts +14 -4
  38. package/lib/types/catalog/validate.d.ts +72 -11
  39. package/lib/types/contracts/market.d.ts +67 -0
  40. package/lib/types/contracts/mcp-status.d.ts +11 -0
  41. package/lib/types/model/layouts.d.ts +20 -0
  42. package/lib/types/model/preset-source.d.ts +18 -0
  43. package/lib/types/model/types.d.ts +37 -1
  44. package/lib/types/runtime/agent-role-router.d.ts +90 -16
  45. package/lib/types/runtime/host-locale.d.ts +1 -1
  46. package/lib/types/runtime/mcp-client/oauth.d.ts +4 -0
  47. package/lib/types/runtime/mcp-config.d.ts +75 -13
  48. package/lib/types/runtime/mcp-direct-config.d.ts +22 -0
  49. package/lib/types/runtime/mcp-overrides.d.ts +44 -0
  50. package/lib/types/runtime/mcp-redaction.d.ts +6 -0
  51. package/lib/types/runtime/server-config.d.ts +26 -1
  52. package/lib/types/runtime/subagent-catalog.d.ts +14 -2
  53. package/lib/types/runtime/tool-registry-observer.d.ts +5 -3
  54. package/package.json +8 -8
  55. package/schemas/1.0.0/mcp.schema.json +0 -22
  56. package/schemas/1.1.0/mcp.schema.json +120 -0
  57. package/schemas/1.1.0/plugin.schema.json +65 -0
  58. package/schemas/README.md +25 -19
  59. package/schemas/agent-plugins/spec.md +23 -9
  60. package/schemas/com.deepseek.harness/namespace.schema.json +42 -0
  61. package/schemas/com.deepseek.harness/spec.md +52 -0
@@ -1,7 +1,32 @@
1
1
  import type { LspServerSpec, Suite } from '../model/types.js';
2
+ /** One rejected value, with the field it belongs to when the schema knows it. */
3
+ export interface McpFieldError {
4
+ /** Dotted path inside the server object; empty for a problem with the document itself. */
5
+ field: string;
6
+ message: string;
7
+ }
8
+ /**
9
+ * A rejected MCP configuration. The message keeps the flat form the API has
10
+ * always returned, and `fields` carries the same reasons keyed by field so the
11
+ * editor can put each one beside its input.
12
+ */
13
+ export declare class McpConfigError extends Error {
14
+ readonly fields: McpFieldError[];
15
+ constructor(fields: McpFieldError[]);
16
+ }
2
17
  /** Restore only unchanged redacted leaves, rejecting invented masked values. */
3
18
  export declare function restoreRedactedConfig(input: unknown, original: unknown, redacted?: unknown): unknown;
4
- export declare function validateServerMcp(root: string, key: string, config: unknown): Promise<import("../model/types.js").McpServer>;
19
+ /**
20
+ * Validate one service definition before it is stored.
21
+ *
22
+ * A service the user declared themselves is local data rather than a
23
+ * distributable package: keys this client does not know are kept as written
24
+ * instead of being rejected by the closed-set package schema, and the
25
+ * package-only rules (bare command names, plugin-relative paths) stay off.
26
+ */
27
+ export declare function validateServerMcp(root: string, key: string, config: unknown, options?: {
28
+ userOwned?: boolean;
29
+ }): Promise<import("../model/types.js").McpServer>;
5
30
  export declare function validateServerLsp(key: string, config: unknown): LspServerSpec;
6
31
  /** Public configuration excludes the parser's derived identity. */
7
32
  export declare function lspConfig(spec: LspServerSpec): Record<string, unknown>;
@@ -1,6 +1,5 @@
1
1
  import type { Context } from '@deepseek-ai/cordis';
2
2
  import { type UserMessage } from '@deepseek-ai/dsh-llm';
3
- import type { HostTranslate } from './host-locale.js';
4
3
  export interface SubagentCatalogEntry {
5
4
  /** Exact execution identity, independent of the human-readable title. */
6
5
  name: string;
@@ -51,4 +50,17 @@ export type CatalogStepListener = (payload: {
51
50
  /** Register after the exact tool definition; teardown removes guidance before execution. */
52
51
  export declare function mountSubagentCatalog(ctx: Context, tool: {
53
52
  name: string;
54
- }, snapshot: (agent: CatalogAgent, signal: AbortSignal) => Promise<SubagentCatalogEntry[]>, t: HostTranslate): () => void;
53
+ }, snapshot: (agent: CatalogAgent, signal: AbortSignal) => Promise<SubagentCatalogEntry[]>): () => void;
54
+ /**
55
+ * Model-facing catalog text: the role list followed by the same guidance on
56
+ * first publication and on every update, so a replacement never arrives without
57
+ * the rules that govern it. The guidance covers how to brief a child, how to
58
+ * work with one while it runs, and when a role child is the wrong answer; the
59
+ * per-channel arbitration between the host's delegation tools stays in the tool
60
+ * descriptions the harness owns.
61
+ *
62
+ * Role lines carry a name and a description only. The configured route stays in
63
+ * the durable entries for execution and change detection; publishing it would
64
+ * tell the model which model each role runs on without changing what it does.
65
+ */
66
+ export declare function renderCatalogText(entries: readonly SubagentCatalogEntry[], update: boolean): string;
@@ -4,14 +4,16 @@ import type { Context } from '@deepseek-ai/cordis';
4
4
  export interface McpToolSnapshot {
5
5
  name: string;
6
6
  description?: string;
7
+ /** The input schema the server advertised, when the host exposes it. */
8
+ parameters?: unknown;
7
9
  }
8
10
  /**
9
11
  * The MCP tools the host currently publishes to the model.
10
12
  *
11
13
  * Read through the tools service's own listing API rather than its internal
12
- * layer structure. `schemas()` deep-clones each tool's parameter schema, which
13
- * this snapshot has no use for, so a failure inside it degrades to an empty
14
- * observation instead of taking the status surface down.
14
+ * layer structure. `schemas()` deep-clones each tool's parameter schema, so a
15
+ * failure inside it degrades to an empty observation instead of taking the
16
+ * status surface down.
15
17
  * @param tools - the host tools service, when it is mounted.
16
18
  * @returns one entry per `mcp__`-namespaced tool.
17
19
  */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dsh-agent-plugins-market",
3
3
  "description": "The standard way to install Claude Code / Codex / Cursor / Kimi plugin marketplace suites in DeepSeek Harness (DSH) — zero conversion, zero file copying. Skills, MCP servers, hooks and slash commands are injected into your dsh sessions at runtime.",
4
- "version": "0.7.1",
4
+ "version": "0.7.2",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
7
7
  "types": "lib/types/index.d.ts",
@@ -108,15 +108,15 @@
108
108
  "fflate": "^0.8.3",
109
109
  "smol-toml": "^1.8.0",
110
110
  "yaml": "^2.7.0",
111
- "zod": "^4.4.3"
111
+ "zod": "^4.6.5"
112
112
  },
113
113
  "devDependencies": {
114
- "@codemirror/commands": "^6.11.0",
114
+ "@codemirror/commands": "^6.11.1",
115
115
  "@codemirror/lang-json": "^6.0.2",
116
116
  "@codemirror/lang-markdown": "^6.5.2",
117
117
  "@codemirror/language": "^6.12.4",
118
- "@codemirror/state": "^6.7.4",
119
- "@codemirror/view": "^6.43.11",
118
+ "@codemirror/state": "^6.7.5",
119
+ "@codemirror/view": "^6.43.12",
120
120
  "@deepseek-ai/cordis": "^4.0.2",
121
121
  "@deepseek-ai/dsh-attachment": "0.1.5-rc.2",
122
122
  "@deepseek-ai/dsh-client-store": "0.1.5-rc.2",
@@ -139,9 +139,9 @@
139
139
  "@vitest/coverage-v8": "^4.1.11",
140
140
  "anser": "^2.3.5",
141
141
  "clsx": "^2.1.1",
142
- "dependency-cruiser": "^18.2.0",
142
+ "dependency-cruiser": "^18.4.0",
143
143
  "eslint": "^10.9.1",
144
- "immer": "^10.2.0",
144
+ "immer": "^11.1.18",
145
145
  "jsdom": "^30.0.1",
146
146
  "katex": "^0.16.47",
147
147
  "mdast-util-from-markdown": "^2.0.3",
@@ -163,7 +163,7 @@
163
163
  "typescript": "^5.8.3",
164
164
  "typescript-eslint": "^8.67.0",
165
165
  "vitest": "^4.1.10",
166
- "zustand": "~4.4.7"
166
+ "zustand": "~5.0.15"
167
167
  },
168
168
  "publishConfig": {
169
169
  "registry": "https://registry.npmjs.org/"
@@ -85,9 +85,6 @@
85
85
  },
86
86
  "headers": {
87
87
  "$ref": "#/$defs/headers"
88
- },
89
- "auth": {
90
- "$ref": "#/$defs/oauth"
91
88
  }
92
89
  },
93
90
  "required": ["type", "url"],
@@ -107,30 +104,11 @@
107
104
  },
108
105
  "headers": {
109
106
  "$ref": "#/$defs/headers"
110
- },
111
- "auth": {
112
- "$ref": "#/$defs/oauth"
113
107
  }
114
108
  },
115
109
  "required": ["type", "url"],
116
110
  "additionalProperties": false
117
111
  },
118
- "oauth": {
119
- "title": "OAuth 2.1 authorization",
120
- "type": "object",
121
- "description": "OAuth 2.1 authorization for servers that answer 401 with a challenge. The flow activates by default on the server's first 401; set enabled to false to opt out.",
122
- "properties": {
123
- "enabled": {
124
- "type": "boolean",
125
- "description": "Enable the OAuth flow (default true; set false to opt out explicitly)."
126
- },
127
- "scope": {
128
- "type": "string",
129
- "description": "Space-separated scope string requested during authorization."
130
- }
131
- },
132
- "additionalProperties": false
133
- },
134
112
  "headers": {
135
113
  "title": "HTTP headers",
136
114
  "type": "object",
@@ -0,0 +1,120 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://agent-plugins.org/schemas/1.1.0/mcp.schema.json",
4
+ "title": "Agent Plugins MCP Configuration",
5
+ "description": "Machine-readable schema for mcp.json in Agent Plugins 1.1.0. The Agent Plugins specification defines additional semantic and operational requirements.",
6
+ "type": "object",
7
+ "properties": {
8
+ "$schema": {
9
+ "const": "https://agent-plugins.org/schemas/1.1.0/mcp.schema.json",
10
+ "description": "Canonical identifier of the MCP configuration schema for the Agent Plugins version targeted by this document."
11
+ },
12
+ "mcpServers": {
13
+ "type": "object",
14
+ "additionalProperties": {
15
+ "$ref": "#/$defs/server"
16
+ }
17
+ }
18
+ },
19
+ "required": ["$schema", "mcpServers"],
20
+ "additionalProperties": false,
21
+ "$defs": {
22
+ "server": {
23
+ "title": "MCP server",
24
+ "oneOf": [
25
+ {
26
+ "$ref": "#/$defs/stdioServer"
27
+ },
28
+ {
29
+ "$ref": "#/$defs/streamableHttpServer"
30
+ },
31
+ {
32
+ "$ref": "#/$defs/sseServer"
33
+ }
34
+ ]
35
+ },
36
+ "stdioServer": {
37
+ "title": "stdio MCP server",
38
+ "type": "object",
39
+ "properties": {
40
+ "type": {
41
+ "const": "stdio"
42
+ },
43
+ "command": {
44
+ "type": "string",
45
+ "minLength": 1,
46
+ "description": "Executable token. Resolution rules are defined by the Agent Plugins specification."
47
+ },
48
+ "args": {
49
+ "type": "array",
50
+ "items": {
51
+ "type": "string"
52
+ }
53
+ },
54
+ "env": {
55
+ "type": "object",
56
+ "propertyNames": {
57
+ "not": {
58
+ "enum": ["PLUGIN_ROOT", "PLUGIN_DATA"]
59
+ }
60
+ },
61
+ "additionalProperties": {
62
+ "type": "string"
63
+ }
64
+ },
65
+ "cwd": {
66
+ "type": "string",
67
+ "pattern": "^(?:\\./|\\$\\{PLUGIN_ROOT\\}(?:/|$)|\\$\\{PLUGIN_DATA\\}(?:/|$))",
68
+ "description": "Plugin-relative, PLUGIN_ROOT-rooted, or PLUGIN_DATA-rooted working directory. Filesystem containment is validated separately."
69
+ }
70
+ },
71
+ "required": ["type", "command"],
72
+ "additionalProperties": false
73
+ },
74
+ "streamableHttpServer": {
75
+ "title": "Streamable HTTP MCP server",
76
+ "type": "object",
77
+ "properties": {
78
+ "type": {
79
+ "const": "streamable-http"
80
+ },
81
+ "url": {
82
+ "type": "string",
83
+ "minLength": 1,
84
+ "description": "MCP endpoint URL. URL semantics are defined by the Agent Plugins specification."
85
+ },
86
+ "headers": {
87
+ "$ref": "#/$defs/headers"
88
+ }
89
+ },
90
+ "required": ["type", "url"],
91
+ "additionalProperties": false
92
+ },
93
+ "sseServer": {
94
+ "title": "Legacy HTTP+SSE MCP server",
95
+ "type": "object",
96
+ "properties": {
97
+ "type": {
98
+ "const": "sse"
99
+ },
100
+ "url": {
101
+ "type": "string",
102
+ "minLength": 1,
103
+ "description": "MCP endpoint URL. URL semantics are defined by the Agent Plugins specification."
104
+ },
105
+ "headers": {
106
+ "$ref": "#/$defs/headers"
107
+ }
108
+ },
109
+ "required": ["type", "url"],
110
+ "additionalProperties": false
111
+ },
112
+ "headers": {
113
+ "title": "HTTP headers",
114
+ "type": "object",
115
+ "additionalProperties": {
116
+ "type": "string"
117
+ }
118
+ }
119
+ }
120
+ }
@@ -0,0 +1,65 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://agent-plugins.org/schemas/1.1.0/plugin.schema.json",
4
+ "title": "Agent Plugins Manifest",
5
+ "description": "Machine-readable schema for plugin.json in Agent Plugins 1.1.0. The Agent Plugins specification defines additional semantic and operational requirements.",
6
+ "type": "object",
7
+ "properties": {
8
+ "$schema": {
9
+ "const": "https://agent-plugins.org/schemas/1.1.0/plugin.schema.json",
10
+ "description": "Canonical identifier of the plugin manifest schema for the Agent Plugins version targeted by this document."
11
+ },
12
+ "name": {
13
+ "type": "string",
14
+ "minLength": 1,
15
+ "maxLength": 64,
16
+ "pattern": "^(?!.*(?:--|\\.\\.))[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?$",
17
+ "description": "Human-readable plugin name."
18
+ },
19
+ "version": {
20
+ "type": "string"
21
+ },
22
+ "description": {
23
+ "type": "string"
24
+ },
25
+ "author": {
26
+ "type": "object",
27
+ "properties": {
28
+ "name": {
29
+ "type": "string"
30
+ },
31
+ "email": {
32
+ "type": "string"
33
+ },
34
+ "url": {
35
+ "type": "string"
36
+ }
37
+ },
38
+ "additionalProperties": false
39
+ },
40
+ "homepage": {
41
+ "type": "string"
42
+ },
43
+ "repository": {
44
+ "type": "string"
45
+ },
46
+ "license": {
47
+ "type": "string"
48
+ },
49
+ "keywords": {
50
+ "type": "array",
51
+ "items": {
52
+ "type": "string"
53
+ }
54
+ },
55
+ "extensions": {
56
+ "type": "object",
57
+ "description": "Client-specific manifest data keyed by reverse-domain extension namespace. Agent Plugins assigns no semantics to namespace object contents.",
58
+ "additionalProperties": {
59
+ "type": "object"
60
+ }
61
+ }
62
+ },
63
+ "required": ["$schema", "name"],
64
+ "additionalProperties": false
65
+ }
package/schemas/README.md CHANGED
@@ -1,9 +1,10 @@
1
1
  # Plugin manifest and marketplace specifications
2
2
 
3
- This directory is the specification library for the plugin layouts this manager reads. It holds two kinds of files:
3
+ This directory is the specification library for the plugin layouts this manager reads. It holds three kinds of files:
4
4
 
5
- 1. **Vendored upstream schemas** in [`1.0.0/`](1.0.0/) — pinned copies of the official agent-plugins.org v1.0.0 schemas. These are bundled into the published package and loaded at runtime by [`src/catalog/validate.ts`](../src/catalog/validate.ts), because the specification requires clients to validate plugin packages without retrieving schemas at load time (§7.2.1: "Clients MUST NOT retrieve a schema while loading a plugin").
5
+ 1. **Vendored upstream schemas** in [`1.0.0/`](1.0.0/) and [`1.1.0/`](1.1.0/) — pinned copies of the official agent-plugins.org schemas (1.0.0 published, 1.1.0 the working draft this manager explicitly recognizes as compatible; the two releases' schemas differ only in the version string). These are bundled into the published package and loaded at runtime by [`src/catalog/validate.ts`](../src/catalog/validate.ts), because the specification requires clients to validate plugin packages without retrieving schemas at load time (§7.2.1: "Clients MUST NOT retrieve a schema while loading a plugin").
6
6
  2. **Reference contracts** in `<dialect>/` — an authored JSON Schema pair plus a `spec.md` for each layout the manager recognizes. **These are documentation, not runtime validators**: the scanner still applies the strategy-chain rules in `src/catalog/`. They exist so a dialect's field set, file locations, and evidence are pinned in one place.
7
+ 3. **The client extension namespace contract** in [`com.deepseek.harness/`](com.deepseek.harness/) — the authored schema and rules for this manager's own §8 namespace: manifest data under `extensions["com.deepseek.harness"]` and the top-level `com.deepseek.harness/` extension directory.
7
8
 
8
9
  Every authored schema records its provenance in a `$comment`, and every dialect's `spec.md` records the sources, the verification date, and the unresolved gaps.
9
10
 
@@ -14,7 +15,11 @@ schemas/
14
15
  ├── 1.0.0/ # vendored agent-plugins.org v1.0.0 (runtime-loaded)
15
16
  │ ├── plugin.schema.json
16
17
  │ └── mcp.schema.json
17
- ├── agent-plugins/spec.md # the published cross-vendor standard (schemas live in 1.0.0/)
18
+ ├── 1.1.0/ # vendored agent-plugins.org v1.1.0 working draft (runtime-loaded)
19
+ ├── agent-plugins/spec.md # the published cross-vendor standard (schemas live in 1.0.0/ and 1.1.0/)
20
+ ├── com.deepseek.harness/ # this manager's §8 client extension namespace
21
+ │ ├── namespace.schema.json
22
+ │ └── spec.md
18
23
  ├── skill-collection/spec.md # manifest-less layout; nothing to validate
19
24
  └── <dialect>/
20
25
  ├── plugin.schema.json
@@ -34,7 +39,7 @@ This table records **upstream client conventions**, including their own fallback
34
39
  | [Kimi (kimi-code)](kimi/spec.md) | `kimi.plugin.json` → `.kimi-plugin/plugin.json` | `KIMI_CODE_PLUGIN_MARKETPLACE_URL`, default `https://code.kimi.com/kimi-code/plugins/marketplace.json` | None reachable; the declared URI serves HTML |
35
40
  | [Kimi (kimi-cli, legacy)](kimi/spec.md#kimi-cli-legacy-a-different-format) | `plugin.json` with a `tools` array | None | None |
36
41
  | [Universal `.plugin/`](universal/spec.md) | `.plugin/plugin.json` | `.plugin/marketplace.json` | None — an observed convention, not a specification |
37
- | [agent-plugins.org v1](agent-plugins/spec.md) | `plugin.json` (required) | Vendor-specific; not part of the standard | **Vendored 1.0.0** |
42
+ | [agent-plugins.org v1](agent-plugins/spec.md) | `plugin.json` (required) | Vendor-specific; not part of the standard. This manager reads `.claude-plugin/marketplace.json`, root `marketplace.json`, or rooted discovery with no catalog | **Vendored 1.0.0 and 1.1.0** |
38
43
  | [Skill collection](skill-collection/spec.md) | None | None | n/a |
39
44
  | [ZCode](zcode/spec.md) | `.zcode-plugin/plugin.json` → `.claude-plugin/` → `.codex-plugin/` | `.claude-plugin/marketplace.json` → `marketplace.json` | None |
40
45
  | [Qoder CLI](qoder/spec.md) | `.qoder-plugin/plugin.json` → `.claude-plugin/plugin.json` | `.qoder-plugin/marketplace.json` → `.claude-plugin/` → `marketplace.json` | None |
@@ -44,19 +49,19 @@ This table records **upstream client conventions**, including their own fallback
44
49
 
45
50
  These are the points where the layouts actually differ; they cause the most silent failures.
46
51
 
47
- | Dialect | MCP configuration | Hooks |
48
- | -------------------- | ------------------------------------------------------------------------------------- | ---------------------------------- |
49
- | Claude Code | `.mcp.json`; inline `mcpServers` is additive | `hooks/hooks.json` or inline |
50
- | Codex | legacy: `.mcp.json` (validator rejects `mcp.json`); agent-plugins dialect: `mcp.json` | manifest `hooks` or `hooks/` |
51
- | Cursor | `mcp.json` (dot-file only via an explicit `mcpServers` field) | `hooks/hooks.json` or inline |
52
- | Kimi (kimi-code) | inline `mcpServers` only | inline `hooks` array |
53
- | Universal `.plugin/` | `.mcp.json`, `.github/mcp.json` | `hooks.json` or `hooks/hooks.json` |
54
- | agent-plugins.org v1 | `mcp.json`, required and closed; inline is forbidden | Not defined |
55
- | ZCode | `.mcp.json` only | `hooks/hooks.json` |
56
- | Qoder CLI | `.mcp.json` → `mcp.json` (never merged) | `hooks/hooks.json` |
57
- | GitHub Copilot CLI | `.mcp.json`, `.github/mcp.json` | `hooks.json` or `hooks/hooks.json` |
52
+ | Dialect | MCP configuration | Hooks |
53
+ | -------------------- | -------------------------------------------------------------------------------------- | ------------------------------------------------------------ |
54
+ | Claude Code | `.mcp.json`; inline `mcpServers` is additive | `hooks/hooks.json` or inline |
55
+ | Codex | legacy: `.mcp.json` (validator rejects `mcp.json`); agent-plugins dialect: `mcp.json` | manifest `hooks` or `hooks/` |
56
+ | Cursor | `mcp.json` (dot-file only via an explicit `mcpServers` field) | `hooks/hooks.json` or inline |
57
+ | Kimi (kimi-code) | inline `mcpServers` only | inline `hooks` array |
58
+ | Universal `.plugin/` | `.mcp.json`, `.github/mcp.json` | `hooks.json` or `hooks/hooks.json` |
59
+ | agent-plugins.org v1 | `mcp.json` (optional — a skills-only suite is conformant), closed; inline is forbidden | `com.deepseek.harness/hooks/hooks.json` (namespace contract) |
60
+ | ZCode | `.mcp.json` only | `hooks/hooks.json` |
61
+ | Qoder CLI | `.mcp.json` → `mcp.json` (never merged) | `hooks/hooks.json` |
62
+ | GitHub Copilot CLI | `.mcp.json`, `.github/mcp.json` | `hooks.json` or `hooks/hooks.json` |
58
63
 
59
- Claude Code and Copilot (including the Universal convention) define usable LSP declarations. Qoder/ZCode record the field without native execution. Cursor, Codex, Kimi and agent-plugins do not define a native LSP surface; this manager's shared LSP extension must not be confused with an upstream feature.
64
+ Claude Code and Copilot (including the Universal convention) define usable LSP declarations. Qoder/ZCode record the field without native execution. Cursor, Codex, Kimi and agent-plugins do not define a native LSP surface; this manager reads agent-plugins LSP declarations from the [`com.deepseek.harness` namespace](com.deepseek.harness/spec.md), its own §8 extension rather than an upstream feature.
60
65
 
61
66
  ## Executable coverage
62
67
 
@@ -64,10 +69,11 @@ All ten active layouts are covered by [offline README repository tests](../tests
64
69
 
65
70
  ## Provenance and update policy
66
71
 
67
- - `1.0.0/*.schema.json` are vendored. Replace both files from [`agentplugins/agent-plugins-spec`](https://github.com/agentplugins/agent-plugins-spec) at the pinned spec version and bump the spec-version references in `src/catalog/validate.ts`. Never edit them by hand.
72
+ - `1.0.0/*.schema.json` and `1.1.0/*.schema.json` are vendored. Replace the files from [`agentplugins/agent-plugins-spec`](https://github.com/agentplugins/agent-plugins-spec) at the pinned spec versions and bump the spec-version references in `src/catalog/validate.ts`. Never edit them by hand.
68
73
  - `<dialect>/*.schema.json` and `spec.md` are authored here. They are **not** upstream copies and carry no upstream compatibility guarantee. When a cited source changes, re-verify and update the schema, the `spec.md`, and the `$comment` provenance line together.
69
- - `agent-plugins/spec.md` documents the published standard but deliberately keeps its schemas in `1.0.0/` so there is exactly one copy in the tree.
74
+ - `agent-plugins/spec.md` documents the published standard but deliberately keeps its schemas in `1.0.0/` and `1.1.0/` so there is exactly one copy of each release in the tree.
75
+ - `com.deepseek.harness/` is authored here and owned here: it defines this manager's own §8 namespace, so its evolution is governed by the namespace `schemaVersion`, not by upstream releases.
70
76
 
71
77
  ## Validation
72
78
 
73
- `tests/schemas.test.ts` compiles every schema with Ajv 2020-12, asserts `$id` uniqueness, pins the vendored ids to the runtime constants in `src/catalog/validate.ts`, and requires each dialect to keep a `spec.md` and a paired marketplace schema. Run `pnpm run test` after touching this directory; run `pnpm run format:check` for formatting.
79
+ `tests/schemas.test.ts` compiles every schema with Ajv 2020-12, asserts `$id` uniqueness, pins the vendored ids to the runtime constants in `src/catalog/validate.ts`, and requires each dialect to keep a `spec.md` and a paired marketplace schema (the vendored release directories and the namespace contract keep their own documented shape instead). Run `pnpm run test` after touching this directory; run `pnpm run format:check` for formatting.
@@ -2,11 +2,11 @@
2
2
 
3
3
  The only published cross-vendor plugin format in this directory. Unlike the other dialects, its schemas are **vendored upstream** and loaded at runtime by this plugin.
4
4
 
5
- - **Schemas:** [../1.0.0/plugin.schema.json](../1.0.0/plugin.schema.json), [../1.0.0/mcp.schema.json](../1.0.0/mcp.schema.json)
5
+ - **Schemas:** [`../1.0.0/plugin.schema.json`](../1.0.0/plugin.schema.json), [`../1.0.0/mcp.schema.json`](../1.0.0/mcp.schema.json), [`../1.1.0/plugin.schema.json`](../1.1.0/plugin.schema.json), [`../1.1.0/mcp.schema.json`](../1.1.0/mcp.schema.json)
6
6
  - **Specification:** https://agent-plugins.org/specification
7
- - **Repository:** [`agentplugins/agent-plugins-spec`](https://github.com/agentplugins/agent-plugins-spec) (`spec/1.0.0.md`, `schemas/1.0.0/`)
8
- - **Status:** 1.0.0 published; 1.1.0 is a working draft whose plugin schema is currently byte-identical to 1.0.0.
9
- - **Runtime use:** `src/catalog/validate.ts` loads both 1.0.0 schemas through Ajv, and `src/catalog/manifests.ts` selects this dialect only when a root `plugin.json` declares a recognized `$schema`.
7
+ - **Repository:** [`agentplugins/agent-plugins-spec`](https://github.com/agentplugins/agent-plugins-spec) (`spec/1.0.0.md`, `spec/1.1.0.md`, `schemas/1.0.0/`, `schemas/1.1.0/`)
8
+ - **Status:** 1.0.0 published; 1.1.0 is a working draft whose schemas differ from 1.0.0 only in the version string (verified 2026-09-17 at upstream `ff8ab5e`); the spec text additionally renames two phrasings ("claiming conformance to Agent Plugins v1" → "claiming conformance", "Agent Plugins v1 defines no OAuth" → "This specification defines no OAuth"). This manager explicitly recognizes 1.1.0 as compatible (§5.2) and validates each version against its own vendored schemas.
9
+ - **Runtime use:** `src/catalog/validate.ts` loads all four vendored schemas through Ajv and selects the validator by the manifest's declared `$schema`; `src/catalog/manifests.ts` selects this dialect only when a root `plugin.json` declares a recognized `$schema`. Client-specific behavior beyond the portable core lives in the [`com.deepseek.harness` namespace](../com.deepseek.harness/spec.md).
10
10
 
11
11
  ## Manifest location
12
12
 
@@ -14,11 +14,11 @@ Normative (§5.1): clients MUST check for a manifest at `plugin.json` in the plu
14
14
 
15
15
  ## Plugin manifest fields
16
16
 
17
- Closed schema: `additionalProperties: false`, `required: ["$schema", "name"]`, and no `default` keyword anywhere.
17
+ Closed schema: `additionalProperties: false`, `required: ["$schema", "name"]`, and no `default` keyword anywhere. Per §5.2 an unknown top-level field is reported and ignored while the plugin keeps loading; any other schema violation is fatal.
18
18
 
19
19
  | Field | Type | Required | Constraints |
20
20
  | --- | --- | --- | --- |
21
- | `$schema` | string | yes | `const: https://agent-plugins.org/schemas/1.0.0/plugin.schema.json` |
21
+ | `$schema` | string | yes | `const`: the canonical id of one supported release (`1.0.0`, `1.1.0`) |
22
22
  | `name` | string | yes | 1–64 chars, `^(?!.*(?:--\|\.\.))[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?$` |
23
23
  | `version` | string | no | SemVer recommended, not enforced. |
24
24
  | `description` | string | no | |
@@ -26,7 +26,7 @@ Closed schema: `additionalProperties: false`, `required: ["$schema", "name"]`, a
26
26
  | `homepage`, `repository` | string | no | Not URL-validated. |
27
27
  | `license` | string | no | SPDX recommended, not enforced. |
28
28
  | `keywords` | string[] | no | No `minItems`/`uniqueItems`. |
29
- | `extensions` | object of object | no | Client-specific data keyed by reverse-domain namespace; the specification assigns no semantics to namespace contents. |
29
+ | `extensions` | object of object | no | Client-specific data keyed by reverse-domain namespace; the specification assigns no semantics to namespace contents. Violations inside this subtree are reported and ignored (§8.1). |
30
30
 
31
31
  ## Fixed component locations
32
32
 
@@ -37,7 +37,21 @@ Clients MUST discover each supported component type from its fixed location, and
37
37
  | Skills | `skills/` | Immediate subdirectories containing `SKILL.md` |
38
38
  | MCP servers | `mcp.json` | JSON configuration |
39
39
 
40
- v1 defines exactly these two component types. Commands, hooks, agents, rules, and LSP servers are explicitly outside the format "until their formats converge". MCP configuration MUST NOT be declared inline in `plugin.json`. The `mcp.json` schema is closed and requires `$schema` and `mcpServers` with no other top-level fields; every server requires `type` and must match exactly one closed variant.
40
+ v1 defines exactly these two component types. Commands, hooks, agents, rules, and LSP servers are explicitly outside the format "until their formats converge". MCP configuration MUST NOT be declared inline in `plugin.json`. The `mcp.json` schema is closed and requires `$schema` and `mcpServers` with no other top-level fields; every server requires `type` and must match exactly one closed variant (§7.2.2 rule 3: a per-server violation skips that server only). `mcp.json` `$schema` MUST name the same release as `plugin.json` (§10.1). Skills discovery covers one level of `skills/` subdirectories and MUST NOT search deeper descendants (§7.1). `mcp.json` fixes a location, not a presence requirement: a suite carrying skills only is conformant, and an absent `mcp.json` contributes zero servers.
41
+
42
+ ## Marketplace catalogs
43
+
44
+ The specification defines no marketplace format — catalogs of v1 suites are a vendor-side convention, and the standard assigns them no schema. This manager reads three catalog shapes over v1 suite roots, in the shared scan order:
45
+
46
+ 1. `.claude-plugin/marketplace.json` (Claude Code shape).
47
+ 2. Root `marketplace.json` — the fallback catalog for layouts without a dedicated one.
48
+ 3. No catalog at all — rooted discovery walks the checkout (up to four levels deep) and reads every directory carrying a v1 manifest, so a bare collection is scannable without any catalog file. The first-party collection [dsh-agent-plugins](https://github.com/Sivan757/dsh-agent-plugins) ships this shape: suites under `plugins/`, no catalog manifest.
49
+
50
+ A catalog entry's `name`/`version`/`description` are fallbacks: a conformant suite's own `plugin.json` wins for every field it declares. Entries may add display metadata the portable manifest cannot express (`category`, `keywords`). Entry sources resolve relative to the catalog's checkout; with no `source`, each entry resolves against the catalog checkout's own containers.
51
+
52
+ ## Client extensions
53
+
54
+ §8 gives every client a reverse-domain namespace: manifest data under `extensions`, files under a top-level directory of the same name. Other clients MUST ignore unimplemented namespaces without validating their contents. This manager's namespace is [`com.deepseek.harness`](../com.deepseek.harness/spec.md) — it carries the component types the portable format leaves out and the per-server client policy the closed `mcp.json` schema cannot hold.
41
55
 
42
56
  ## Governance and adoption
43
57
 
@@ -45,4 +59,4 @@ The technical steering committee is Amazon, Cursor, Microsoft, OpenAI, and Verce
45
59
 
46
60
  ## Update procedure
47
61
 
48
- Replace both files from the upstream repository at the pinned spec version and bump the spec-version references in `src/catalog/validate.ts`. Do not edit the vendored files by hand.
62
+ Replace the vendored files from the upstream repository at the pinned spec versions and bump the spec-version references in `src/catalog/validate.ts`. Do not edit the vendored files by hand.
@@ -0,0 +1,42 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://deepseek.com/schemas/dsh-agent-plugins-market/namespace.schema.json",
4
+ "$comment": "Authored contract for the com.deepseek.harness client extension namespace (Agent Plugins §8.1). Documentation-grade: the runtime applies the strategy-chain rules in src/catalog, not this file. The extension namespace is client-defined by specification; this schema records what this manager reads.",
5
+ "title": "com.deepseek.harness namespace extension data",
6
+ "type": "object",
7
+ "required": ["schemaVersion"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "schemaVersion": {
11
+ "type": "string",
12
+ "const": "1.0.0",
13
+ "description": "Namespace contract version the suite was written against. Only 1.0.0 is implemented; any other value skips both namespace seats and keeps the portable core."
14
+ },
15
+ "mcpServers": {
16
+ "type": "object",
17
+ "description": "Per-server client policy keyed by the server's own name in the suite's portable mcp.json. Names without a matching server are reported and ignored.",
18
+ "additionalProperties": { "$ref": "#/$defs/serverPolicy" }
19
+ }
20
+ },
21
+ "$defs": {
22
+ "serverPolicy": {
23
+ "type": "object",
24
+ "additionalProperties": false,
25
+ "properties": {
26
+ "auth": {
27
+ "type": "object",
28
+ "description": "OAuth 2.1 authorization for Streamable HTTP / SSE servers that answer 401 with a challenge; the flow activates on the server's first 401.",
29
+ "additionalProperties": false,
30
+ "properties": {
31
+ "enabled": { "type": "boolean", "default": true, "description": "Enable the OAuth flow (default true; false opts out explicitly)." },
32
+ "scope": { "type": "string", "description": "Space-separated scope string requested during authorization." }
33
+ }
34
+ },
35
+ "enabledTools": { "type": "array", "items": { "type": "string" }, "description": "Allow-list of model-facing tool names; absent means all tools." },
36
+ "disabledTools": { "type": "array", "items": { "type": "string" }, "description": "Deny-list of model-facing tool names applied after the allow-list." },
37
+ "startupTimeoutMs": { "type": "number", "exclusiveMinimum": 0, "description": "Milliseconds allowed between spawn and a completed MCP handshake before the mount fails." },
38
+ "toolCallTimeoutMs": { "type": "number", "exclusiveMinimum": 0, "description": "Milliseconds allowed for one tool call before it is cancelled." }
39
+ }
40
+ }
41
+ }
42
+ }
@@ -0,0 +1,52 @@
1
+ # com.deepseek.harness namespace contract
2
+
3
+ The client extension namespace of this manager under the [Agent Plugins specification](https://agent-plugins.org/specification) §8. The namespace has two seats, which the specification leaves entirely to the owning client:
4
+
5
+ 1. **Manifest data** — `plugin.json` → `extensions["com.deepseek.harness"]`, validated against [`namespace.schema.json`](namespace.schema.json).
6
+ 2. **Extension directory** — the top-level `com.deepseek.harness/` directory.
7
+
8
+ Both seats open only when the manifest data declares `"schemaVersion": "1.0.0"`. A suite that ships the directory without the declaration, or with an unsupported version, contributes its portable core only (`skills/`, `mcp.json`) and the directory is ignored with a scan note.
9
+
10
+ ## Extension directory layout
11
+
12
+ | Path | Surface |
13
+ | --------------------------------------- | ----------------------------------------------------------------- |
14
+ | `com.deepseek.harness/commands/*.md` | Slash commands |
15
+ | `com.deepseek.harness/agents/*.md` | Agent roles |
16
+ | `com.deepseek.harness/hooks/hooks.json` | Command hooks (Claude Code event-table shape) |
17
+ | `com.deepseek.harness/lsp.json` | LSP server declarations (`lspServers` table or a bare server map) |
18
+
19
+ ## What the namespace carries
20
+
21
+ Everything a portable suite cannot express because the v1 format fixes its component set to Agent Skills and MCP, and closes the manifest:
22
+
23
+ - **Commands, agent roles, hooks, LSP declarations.** The specification records these component types as outside the format "until their formats converge"; the namespace is where they live for this client.
24
+ - **Per-server client policy** (`extensions["com.deepseek.harness"].mcpServers`): OAuth authorization, tool allow/deny lists, and timeout policies for servers declared in the portable `mcp.json`. The portable file stays schema-clean; client-specific fields ride the namespace, keyed by the server's own name.
25
+
26
+ Namespace values are the suite's defaults rather than a ceiling the user cannot reach. A stored user override may set either timeout, and that value wins over the declaration; a user may add tool names to the deny list, while the allow-list and the suite's own deny entries stay in force. Tool filtering only ever tightens. The override record lives outside the suite checkout, so a package refresh never clobbers it and the namespace file stays source-owned. The host compatibility client (`@deepseek-ai/dsh-mcp-client`) enforces neither the tool lists nor a startup timeout, so a server mounted through it carries no such value; the built-in bridge is where those take effect.
27
+
28
+ ## User-owned declarations
29
+
30
+ `~/.agents/mcp.json` is local data rather than a distributable package. Keys this client does not know are stored back exactly as written, and the package-only rules — a closed server shape, bare command names, plugin-relative paths — do not apply to it. A suite's packaged `mcp.json` keeps every one of them, because a package carrying fields this client cannot honour is one it cannot promise to mount.
31
+
32
+ The editor reads the same two seats a suite declares, for one server at a time: the portable definition under `mcpServers` and this client's policy under `com.deepseek.harness`. The form writes only the half it owns, so a field it has no control for — a key another client introduced, a policy entry the form does not show — survives both a form edit and a JSON edit. Only the policy entries the user changed are sent on save; an entry the document drops asks for inheritance.
33
+
34
+ ## Failure behavior
35
+
36
+ | Situation | Behavior |
37
+ | ------------------------------------------------------- | ----------------------------------------------------------- |
38
+ | Namespace value is not an object | Reported, ignored; plugin keeps loading |
39
+ | `schemaVersion` missing or unsupported | Reported; both namespace seats skipped; portable core loads |
40
+ | Directory exists but the manifest declares no namespace | Directory not read; scan note records it |
41
+ | One command / agent / hook / LSP entry invalid | That entry skipped with a diagnostic; the rest load |
42
+ | Namespace path resolves outside the plugin root | That path rejected (§4.1) |
43
+
44
+ ## Placeholder rules
45
+
46
+ Values inside the namespace seats expand `${PLUGIN_ROOT}`, `${PLUGIN_DATA}`, and `${NAME}` credential references — the namespace is client-owned data, so the credential seam the portable `mcp.json` forbids (§9.2) is available here. Missing credential references fail that surface closed with a diagnostic.
47
+
48
+ ## Provenance
49
+
50
+ - Sources: [Agent Plugins specification](https://agent-plugins.org/specification) §8 (client extensions), §9.2 (placeholder expansion), and the runtime behavior of `src/catalog/manifests.ts` (manifest seat) and `src/catalog/scan-resolvers.ts` (directory seat).
51
+ - Verified: 2026-09-17 against `agentplugins/agent-plugins-spec` `ff8ab5e` (1.0.0 published, 1.1.0 working draft).
52
+ - Unresolved: none. The specification assigns no semantics to namespace contents, so every rule above is this client's own contract and can evolve by bumping `schemaVersion`.