dsh-agent-plugins-market 0.9.1 → 0.9.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.
- package/README.md +59 -161
- package/README.zh.md +71 -173
- package/lib/packages/market-bundle/src/session-extension.js +10 -3
- package/lib/packages/market-runtime/src/application/fs-probe.js +43 -0
- package/lib/packages/market-runtime/src/application/panel-resources.js +3 -2
- package/lib/packages/market-runtime/src/application/panels/user-store.js +52 -12
- package/lib/packages/market-runtime/src/application/project-agent-roles.js +5 -2
- package/lib/packages/market-runtime/src/runtime/agents/agent-role-router.js +17 -11
- package/lib/packages/market-runtime/src/runtime/agents/subagent-catalog.js +19 -3
- package/lib/packages/market-runtime/src/runtime/agents/teammate-role-tool.js +13 -6
- package/lib/types/packages/market-bundle/src/session-extension.d.ts +4 -1
- package/lib/types/packages/market-runtime/src/application/fs-probe.d.ts +12 -0
- package/lib/types/packages/market-runtime/src/runtime/agents/agent-role-router.d.ts +18 -1
- package/lib/types/packages/market-runtime/src/runtime/agents/subagent-catalog.d.ts +23 -2
- package/lib/types/packages/market-runtime/src/runtime/agents/teammate-role-tool.d.ts +2 -2
- package/package.json +1 -1
- package/schemas/README.md +1 -1
package/README.md
CHANGED
|
@@ -1,242 +1,140 @@
|
|
|
1
|
-
<img src="assets/dsh-agent-plugins.png" alt="Agent Plugins" width="64" height="64" />
|
|
1
|
+
<img src="https://raw.githubusercontent.com/Sivan757/dsh-agent-plugins-market/main/assets/dsh-agent-plugins.png" alt="Agent Plugins" width="64" height="64" />
|
|
2
2
|
|
|
3
3
|
# Agent Plugins
|
|
4
4
|
|
|
5
5
|
`dsh-agent-plugins-market`
|
|
6
6
|
|
|
7
|
-
**A one-stop skills, subagent, MCP and LSP manager inside [DeepSeek Harness (DSH)](https://github.com/deepseek-ai/deepseek-harness)
|
|
7
|
+
**A one-stop skills, subagent, MCP and LSP manager inside [DeepSeek Harness (DSH)](https://github.com/deepseek-ai/deepseek-harness).**
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Run Claude Code, Codex, Cursor, Kimi and agent-plugins suites inside DSH. The plugin reads each layout in place, so you convert no manifest and copy no file. Install it from the DSH Web GUI, then manage skills, commands, agent personas, MCP services and LSP servers in one workspace.
|
|
10
10
|
|
|
11
11
|
If this plugin is useful to you, a ⭐ on [GitHub](https://github.com/Sivan757/dsh-agent-plugins-market) is appreciated.
|
|
12
12
|
|
|
13
13
|
English | [简体中文](README.zh.md) | [Documentation](https://sivan757.github.io/dsh-agent-plugins-market/) | [npm](https://www.npmjs.com/package/dsh-agent-plugins-market)
|
|
14
14
|
|
|
15
|
-
[](https://www.npmjs.com/package/dsh-agent-plugins-market) [](LICENSE)
|
|
15
|
+
[](https://www.npmjs.com/package/dsh-agent-plugins-market) [](https://github.com/Sivan757/dsh-agent-plugins-market/blob/main/LICENSE)
|
|
16
16
|
|
|
17
|
-
[Quick start](#quick-start) · [Everyday use](#everyday-use) · [Compatibility](#compatibility
|
|
17
|
+
[Quick start](#quick-start) · [Highlights](#highlights) · [Everyday use](#everyday-use) · [Compatibility](#compatibility) · [FAQ](#faq)
|
|
18
18
|
|
|
19
19
|
## Pages
|
|
20
20
|
|
|
21
21
|
<table>
|
|
22
22
|
<tr>
|
|
23
23
|
<td align="center" width="33%">
|
|
24
|
-
<img src="docs/screenshots/market.png" alt="Market" width="100%" /><br />
|
|
24
|
+
<img src="https://raw.githubusercontent.com/Sivan757/dsh-agent-plugins-market/main/docs/screenshots/market.png" alt="Market" width="100%" /><br />
|
|
25
25
|
<b>Market</b><br />Add sources, preview suites, install and enable.
|
|
26
26
|
</td>
|
|
27
27
|
<td align="center" width="33%">
|
|
28
|
-
<img src="docs/screenshots/skills.png" alt="Skills" width="100%" /><br />
|
|
28
|
+
<img src="https://raw.githubusercontent.com/Sivan757/dsh-agent-plugins-market/main/docs/screenshots/skills.png" alt="Skills" width="100%" /><br />
|
|
29
29
|
<b>Skills</b><br />Browse skills and author your own.
|
|
30
30
|
</td>
|
|
31
31
|
<td align="center" width="33%">
|
|
32
|
-
<img src="docs/screenshots/commands.png" alt="Commands" width="100%" /><br />
|
|
32
|
+
<img src="https://raw.githubusercontent.com/Sivan757/dsh-agent-plugins-market/main/docs/screenshots/commands.png" alt="Commands" width="100%" /><br />
|
|
33
33
|
<b>Commands</b><br />Manage prompt templates invoked as /name.
|
|
34
34
|
</td>
|
|
35
35
|
</tr>
|
|
36
36
|
<tr>
|
|
37
37
|
<td align="center" width="33%">
|
|
38
|
-
<img src="docs/screenshots/personas.png" alt="Agent personas" width="100%" /><br />
|
|
38
|
+
<img src="https://raw.githubusercontent.com/Sivan757/dsh-agent-plugins-market/main/docs/screenshots/personas.png" alt="Agent personas" width="100%" /><br />
|
|
39
39
|
<b>Agent personas</b><br />Roles with an exact provider, model and effort.
|
|
40
40
|
</td>
|
|
41
41
|
<td align="center" width="33%">
|
|
42
|
-
<img src="docs/screenshots/mcp.png" alt="MCP services" width="100%" /><br />
|
|
42
|
+
<img src="https://raw.githubusercontent.com/Sivan757/dsh-agent-plugins-market/main/docs/screenshots/mcp.png" alt="MCP services" width="100%" /><br />
|
|
43
43
|
<b>MCP services</b><br />Credentials, authorization and connection status.
|
|
44
44
|
</td>
|
|
45
45
|
<td align="center" width="33%">
|
|
46
|
-
<img src="docs/screenshots/lsp.png" alt="LSP servers" width="100%" /><br />
|
|
46
|
+
<img src="https://raw.githubusercontent.com/Sivan757/dsh-agent-plugins-market/main/docs/screenshots/lsp.png" alt="LSP servers" width="100%" /><br />
|
|
47
47
|
<b>LSP servers</b><br />Language server configuration and runtime status.
|
|
48
48
|
</td>
|
|
49
49
|
</tr>
|
|
50
50
|
</table>
|
|
51
51
|
|
|
52
|
-
##
|
|
52
|
+
## Quick start
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
1. In the DSH Web GUI, open **Plugins** in the sidebar.
|
|
55
|
+
2. Press **Add plugin**, type `dsh-agent-plugins-market`, then install it. The same dialog accepts a repository URL or a local directory.
|
|
56
|
+
3. Restart DSH, then open **Settings → Agent Plugins**.
|
|
57
|
+
4. The market already lists one first-party source. Press **Refresh** to fetch its suites. To bring in more, add a source such as `https://github.com/anthropics/claude-plugins-official`.
|
|
58
|
+
5. Open a suite, review its contents, then install it and keep it enabled. Skills appear in the **Skills** tab and in the `/` menu. Answer any credential notice on **MCP services** before you use that suite's tools.
|
|
55
59
|
|
|
56
|
-
|
|
57
|
-
- **Sources.** Add a Git repository, a local directory or an archive (`.zip` / `.tar.gz` / `.tgz` / `.tar`); adopt a checkout you cloned yourself; refresh on demand; delete a managed checkout when you remove its source.
|
|
58
|
-
- **First-party source.** The plugin presets one source record pointing at its own suite collection, so the market lists that repository on first run with no URL to paste. It is an ordinary Git source from there on — refresh it to fetch, then install and toggle its suites like any other.
|
|
59
|
-
- **Downloads that fit your network.** Pick a download region — default `auto` follows the interface language, or choose global / China mainland — and the plugin routes `github.com` clones through the matching mirror. A proxy and per-invocation tuning live in the host config.
|
|
60
|
-
- **Runtime surfaces.** Enabled suites inject into sessions: skills into the catalog and slash menu, commands as `/name`, agent personas into the subagent catalog, MCP tools with an `mcp__` prefix, hooks onto host lifecycle events, and language servers through the `lsp` tool.
|
|
61
|
-
- **MCP.** A built-in bridge runs stdio, Streamable HTTP with OAuth and legacy SSE without a host MCP client. `${VAR}` references resolve from the host credential store or the launch environment; per-server overrides disable or patch a declaration without editing the source, set the tool-call and startup timeouts, and switch individual tools off; creation and editing share the same service form, including advanced timeout settings and a JSON view; an optional host-client compatibility mode is available. A suite's tools register as `mcp__<suite>__<server>__<tool>`; a server you declare yourself in `~/.agents/mcp.json` mounts under its own key, `mcp__<server>__<tool>`.
|
|
62
|
-
- **LSP.** Self-provisioned: installing the plugin is the whole setup, and the `lsp` tool mounts only while a language server is wanted. The server executable itself must be on `PATH`. Upgrading from a release that asked you to expose LSP from your profile? A profile that still carries that hand-added layer reports a seam conflict; the LSP panel names the file and removes the layer for you, keeping a backup.
|
|
63
|
-
- **Agent personas and delegation.** Role cards keep their instructions and exact provider/model/effort settings. Without Agent Teams, use `subagent_role`; with Agent Teams, use `spawn_teammate_role` to create a real Team member and manage it through native Team tools.
|
|
64
|
-
- **Project dimension.** Skills, agents, commands, MCP servers and hooks are read from the project's own directories with no install step.
|
|
65
|
-
- **Your own resources.** Author skills, commands and agent personas as Markdown under `~/.agents/`, then edit them or disable them without deleting the files.
|
|
66
|
-
- **Background source updates.** Optionally refresh every configured source on a timer; off by default.
|
|
67
|
-
- **Web workspace.** Seven tabs: Market, Skills, Commands, Agent personas, MCP services, LSP servers and Hooks, each with search, filters and a grid/list toggle, plus status panels with diagnostics, credential editing, and an install confirmation that warns before executable third-party content is enabled. The settings page is the canonical layout. Every surface shares one tab row of equal columns that never scrolls sideways, and a label that does not fit ellipsizes. Every surface also shares one card and detail anatomy, and the preset manager follows it.
|
|
68
|
-
- **Bilingual interface and feedback.** Workspace strings and injected prompts follow the host language. With feedback enabled, the model can file a `report_market_issue` report through the `gh` CLI or a GitHub token; with neither, it opens a prefilled GitHub issue page and hands you the complete issue text.
|
|
69
|
-
- **Translation.** Descriptions and expanded documents can follow the Chinese or English interface. Names stay unchanged. Chinese defaults to on and English to off, but your saved choice takes priority. Documents offer original, translated, and paragraph-by-paragraph bilingual views, with bilingual selected by default. Translation starts on demand, tries Google Translate, Microsoft Translator, then your default model, and keeps the original when none answers. Results stay cached locally until cleared. Turning translation off keeps that cache. See [translation](docs/user/usage.md#translation).
|
|
60
|
+
Terminal alternative: `dsh plugin --profile <name> add dsh-agent-plugins-market`. Requirements, profile configuration and other install options live in the [usage guide](https://github.com/Sivan757/dsh-agent-plugins-market/blob/main/docs/user/usage.md#installation-options).
|
|
70
61
|
|
|
71
|
-
##
|
|
62
|
+
## Highlights
|
|
72
63
|
|
|
73
|
-
|
|
64
|
+
### Core
|
|
74
65
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
66
|
+
- **Any skill repository works.** Add a Git URL whose repository holds `skills/<name>/SKILL.md` and the market discovers it as a suite. No manifest, no conversion, no file copying.
|
|
67
|
+
- **Ten suite layouts.** Claude Code, Codex, Cursor, Kimi Code, ZCode, Qoder CLI, GitHub Copilot CLI, Universal `.plugin/`, [agent-plugins](https://agent-plugins.org) and manifest-less skill collections.
|
|
68
|
+
- **Sources and downloads.** Add a Git repository, a local directory or an archive, adopt a checkout you cloned yourself, and refresh on demand. Pick a global or China mainland mirror, and refresh every source on a 6-hour timer if you want.
|
|
69
|
+
- **Runtime injection.** Enabled suites add skills to the catalog and slash menu, commands as `/name`, agent personas to the subagent catalog, MCP tools as `mcp__*`, hooks to lifecycle events, and language servers to the `lsp` tool. Installing the plugin is the whole LSP setup.
|
|
70
|
+
- **One workspace.** Seven tabs cover the market, the resources you author, and the services that run. Every tab has search, filters and a grid or list view.
|
|
78
71
|
|
|
79
|
-
|
|
80
|
-
2. The market already lists the first-party source; press **Refresh** to fetch its suites. To pull in more, add a source, for example `https://github.com/anthropics/claude-plugins-official`.
|
|
81
|
-
3. Open a suite, review its contents, then install it and ensure it is enabled.
|
|
82
|
-
4. For a suite with skills, check the **Skills** tab and type `/` in chat to find its user-invocable skills. For an MCP suite, check **MCP services** and resolve any credential or connection notice before using its tools.
|
|
72
|
+
### Advanced
|
|
83
73
|
|
|
84
|
-
|
|
74
|
+
- **MCP OAuth with nothing to declare.** A remote MCP server that answers `401` starts RFC 9728 discovery, dynamic client registration and PKCE authorization in your browser, and the granted token persists. OAuth is on by default, so a suite needs no declaration for it.
|
|
75
|
+
- **Per-server MCP control.** Override a declaration without editing its source, switch one tool off, and set the tool-call and startup timeouts.
|
|
76
|
+
- **Project and personal resources.** Turn on **Scan project Agent layouts** to read skills, commands, roles, MCP servers and hooks from the project's own directories. Author your own under `~/.agents/` as Markdown, and disable a resource without deleting its file.
|
|
77
|
+
- **Per-workspace control.** Each workspace switches the six mounted surfaces off or on, keeps its own resource filters, and saves a resource-window setup as a favorite that works across projects.
|
|
78
|
+
- **Hooks you can read and try.** A hook row opens a declaration card with its event, matcher and timeout, plus a dry run in your home directory.
|
|
79
|
+
- **Bilingual by default.** The interface and the injected prompts follow the host language. Descriptions and documents show the original, a translation or both, and stay cached until you clear them.
|
|
85
80
|
|
|
86
81
|
## Everyday use
|
|
87
82
|
|
|
88
83
|
The workspace has seven tabs:
|
|
89
84
|
|
|
90
|
-
| Tab
|
|
91
|
-
|
|
|
92
|
-
| Market
|
|
93
|
-
| Skills
|
|
94
|
-
| Commands
|
|
95
|
-
| Agent personas | Save role instructions and model settings
|
|
96
|
-
| MCP services
|
|
97
|
-
| LSP servers
|
|
98
|
-
| Hooks
|
|
99
|
-
|
|
100
|
-
A **source** is where content comes from; a **suite** is an installable unit discovered there. Adding a source discovers its suites. Installing and enabling a suite controls its runtime capabilities.
|
|
101
|
-
|
|
102
|
-
Everything you author yourself lives in the shared Agent layout root: skills, commands and personas as Markdown under `~/.agents/`, command hooks in `~/.agents/hooks.json` (or `~/.agents/hooks/hooks.json`), and the MCP and LSP services you add in the workspace in `~/.agents/mcp.json` and `~/.agents/lsp.json`. Commands and personas are read at any subdirectory depth, so a file another tool wrote at `~/.agents/commands/git/commit.md` is callable as `/git-commit`. Project-native resources stay in the project. See [storage and discovery](docs/user/usage.md#storage-and-discovery) for paths and precedence.
|
|
103
|
-
|
|
104
|
-
All seven tabs share a saved grid/list preference. Add and refresh actions sit at the top right; resource state rails are green when active. A hook row opens its own read-only declaration. The declaration shows the full command, the declared matcher, the declared timeout and the host support verdict, never the whole suite behind it.
|
|
105
|
-
|
|
106
|
-
## Compatibility and boundaries
|
|
107
|
-
|
|
108
|
-
Supported **layout dialects** describe how files are organized. The [shared priority table](#layout-detection-precedence) lists suite manifests and Marketplace catalogs together. All ten layout contracts in [`schemas/`](schemas/README.md) have independent reader tests; [the layout audit](docs/user/layout-coverage.md) maps them to pinned repository fixtures.
|
|
109
|
-
|
|
110
|
-
Supported **runtime surfaces** describe what DSH can use:
|
|
111
|
-
|
|
112
|
-
| Surface | Runtime support and conditions |
|
|
113
|
-
| --- | --- |
|
|
114
|
-
| Skills | Host skill catalog and user-invocable slash entries; supported root placeholders are expanded. |
|
|
115
|
-
| Commands | Slash commands through the host command service. |
|
|
116
|
-
| Agents | Dynamic role catalog; `subagent_role` without Agent Teams, `spawn_teammate_role` with it. Team mode also requires session query and system-prompt services. |
|
|
117
|
-
| MCP | Built-in bridge by default: stdio, Streamable HTTP with OAuth, and legacy SSE. Optional host-client compatibility mode is also available; it enforces the tool-call timeout but not tool filters or a startup timeout. |
|
|
118
|
-
| Hooks | The command-hook subset mapped by `dsh-hooks-claude-code`. |
|
|
119
|
-
| LSP | Self-provisioned: installing the plugin is the whole setup, and `lsp` mounts only while a language server is wanted; the server executable must be on `PATH`. |
|
|
120
|
-
|
|
121
|
-
Role discovery remains available in either mode. `spawn_teammate_role(agent, name, description, prompt)` applies role instructions and model settings from the first request, returns a native Team `target`, and retains the creation snapshot for resume. Only the Lead creates members, after the user explicitly requests Team work. Native `spawn_teammate` stays available; roles do not add a second management API. A separate Team coordination briefing keeps the Lead on user intent and integration while guiding members through scoped execution and reporting, even without a role catalog. `tools` and `disallowedTools` are preserved but not enforced. See [agent roles](docs/user/agent-roles.md) for routing, prerequisites and limits.
|
|
122
|
-
|
|
123
|
-
### Layout detection precedence
|
|
124
|
-
|
|
125
|
-
When multiple manifests exist in the **same suite directory**, the first existing file in this order selects the layout:
|
|
126
|
-
|
|
127
|
-
| Priority | Layout | Suite manifest | Marketplace catalog |
|
|
128
|
-
| --- | --- | --- | --- |
|
|
129
|
-
| 1 | [agent-plugins](https://agent-plugins.org) / root compatibility | `plugin.json` | No dedicated catalog |
|
|
130
|
-
| 2 | Universal compatibility | `.plugin/plugin.json` | `.plugin/marketplace.json` |
|
|
131
|
-
| 3 | Claude Code | `.claude-plugin/plugin.json` | `.claude-plugin/marketplace.json` |
|
|
132
|
-
| 4 | Cursor | `.cursor-plugin/plugin.json` | `.cursor-plugin/marketplace.json` |
|
|
133
|
-
| 5 | Kimi Code | `kimi.plugin.json`, then `.kimi-plugin/plugin.json` | `.kimi-plugin/marketplace.json` |
|
|
134
|
-
| 6 | Codex | `.codex-plugin/plugin.json` | `.agents/plugins/marketplace.json`, then `.agents/plugins/api_marketplace.json` |
|
|
135
|
-
| 7 | ZCode | `.zcode-plugin/plugin.json` | No dedicated catalog |
|
|
136
|
-
| 8 | Qoder CLI | `.qoder-plugin/plugin.json` | `.qoder-plugin/marketplace.json` |
|
|
137
|
-
| 9 | GitHub Copilot CLI | `.github/plugin/plugin.json` | `.github/plugin/marketplace.json` |
|
|
138
|
-
| Fallback | Skill collection / shared catalog | Discover skills when no recognized manifest exists | Root `marketplace.json` |
|
|
139
|
-
|
|
140
|
-
- **Manifests are tried in order:** a manifest that cannot be read or validated is reported and the next one is tried, down to the fallback. If every candidate fails, the suite is diagnosed instead of loading half of it.
|
|
141
|
-
- **Component fallback:** for a root `plugin.json` that does not declare a recognized agent-plugins `$schema`, missing component declarations can come from `.claude-plugin/plugin.json`; explicit root declarations win, and marketplace entry declarations fill remaining gaps.
|
|
142
|
-
- Marketplace catalogs follow the same order: the first catalog that produces suites wins, and invalid or empty catalogs allow the next candidate to be tried.
|
|
143
|
-
|
|
144
|
-
The order is defined in [`packages/market-contracts/src/model/layouts.ts`](packages/market-contracts/src/model/layouts.ts); selection and root-manifest fallback are implemented in [`packages/market-catalog/src/scanning/manifests.ts`](packages/market-catalog/src/scanning/manifests.ts).
|
|
85
|
+
| Tab | Use it to |
|
|
86
|
+
| -------------- | ----------------------------------------------------------------------------------- |
|
|
87
|
+
| Market | Add sources, preview suites, install or remove them, and switch them on or off. |
|
|
88
|
+
| Skills | Browse skills and create or edit your own reusable instructions. |
|
|
89
|
+
| Commands | Manage prompt templates invoked as `/name`. |
|
|
90
|
+
| Agent personas | Save role instructions and model settings, then delegate to them. |
|
|
91
|
+
| MCP services | Add a service or configure an installed one, its credentials and its authorization. |
|
|
92
|
+
| LSP servers | Add and configure language servers, and read their runtime status. |
|
|
93
|
+
| Hooks | Read each configured hook with its event, matcher and timeout. |
|
|
145
94
|
|
|
146
|
-
|
|
95
|
+
A **source** is where content comes from. A **suite** is an installable unit discovered there. Adding a source discovers its suites. Enabling a suite turns its runtime capabilities on.
|
|
147
96
|
|
|
148
|
-
|
|
97
|
+
Your own content lives under `~/.agents/`: skills, commands and personas as Markdown, hooks in `hooks.json`, and the MCP and LSP services you add in `mcp.json` and `lsp.json`. Project-native resources stay in the project. See [storage and discovery](https://github.com/Sivan757/dsh-agent-plugins-market/blob/main/docs/user/usage.md#storage-and-discovery).
|
|
149
98
|
|
|
150
|
-
|
|
151
|
-
| ------------------------------------------------------------------------------------------------------------- | ------ | ------- | -------- | ------- | ------- | ------- |
|
|
152
|
-
| [Claude Code](https://code.claude.com/docs/en/plugins-reference) | Yes | Yes | Yes | Yes | Partial | Yes |
|
|
153
|
-
| [Codex](https://developers.openai.com/plugins/build/plugins) | Yes | Yes | Yes | Partial | Partial | Yes |
|
|
154
|
-
| [Cursor](https://cursor.com/docs/reference/plugins) | Yes | Partial | Partial | Partial | No | Yes |
|
|
155
|
-
| Kimi Code | Yes | Yes | Yes | Yes | Partial | Partial |
|
|
156
|
-
| [ZCode](https://zcode.z.ai/en/docs/plugin) `.zcode-plugin/` | Yes | Yes | Yes | Yes | Partial | Partial |
|
|
157
|
-
| [Qoder CLI](https://docs.qoder.com/cli/plugins-reference) `.qoder-plugin/` | Yes | Yes | Yes | Partial | Partial | Partial |
|
|
158
|
-
| [GitHub Copilot CLI](https://docs.github.com/en/copilot/reference/copilot-cli-reference/cli-plugin-reference) | Yes | Yes | Yes | Yes | Partial | Yes |
|
|
159
|
-
| Universal compatibility layout `.plugin/` | Yes | Yes | Yes | Yes | Partial | Yes |
|
|
160
|
-
| [agent-plugins](https://agent-plugins.org) | Yes | Yes | Yes | Yes | Yes | Yes |
|
|
161
|
-
| Manifest-less skill collection | Yes | Yes | Yes | Yes | Partial | Partial |
|
|
162
|
-
| Project-native directories | Yes | Yes | Yes | Yes | Partial | No |
|
|
99
|
+
## Compatibility
|
|
163
100
|
|
|
164
|
-
|
|
165
|
-
- **Agents and commands** are read as Markdown (`agents/*.md`, `commands/*.md`). Cursor plugin commands accept `.md`, `.mdc`, `.markdown` and `.txt`. Codex and Kimi native agent/command formats (TOML, YAML) have no adapter yet.
|
|
166
|
-
- **MCP** covers declared files, inline tables and arrays. Cursor's schema-less `mcp.json` and agent-plugins' strict `mcp.json` both work; Kimi Code is inline-only. Codex app connectors stay outside this adapter.
|
|
167
|
-
- **Hooks** map the command-style events DSH has an equivalent for; events without one (for example `afterFileEdit`) are reported instead of simulated. Cursor's native events are not read.
|
|
168
|
-
- **LSP** accepts declared files, arrays and inline tables plus the conventional `.lsp.json` / `lsp.json` locations. Declarations inside a project are reported but not mounted: the host LSP registry is global. Some layouts only expose LSP directories for preview.
|
|
169
|
-
- **agent-plugins** suites read the portable core (`skills/`, `mcp.json`) per the specification, plus this plugin's [`com.deepseek.harness`](schemas/com.deepseek.harness/spec.md) extension namespace for commands, agents, hooks, LSP and per-server MCP policy (OAuth, tool lists, timeouts). Root-level `commands/`, `agents/`, `hooks/` and `.mcp.json` files belong to other layouts and are reported as unread for this dialect; inline manifest component keys are reported and ignored per §5.2. Both recognized releases (1.0.0, 1.1.0) validate against their own vendored schemas.
|
|
170
|
-
- **Universal** is a compatibility-layout label used by this plugin; the [OpenHands SDK](https://docs.openhands.dev/sdk/guides/plugins) documents the same `.plugin/plugin.json` location and a [Vercel repository](https://github.com/vercel/vercel-plugin/blob/main/.plugin/plugin.json) uses it, but no cross-vendor specification exists.
|
|
101
|
+
The plugin reads ten layout dialects and maps six runtime surfaces. Per-layout support and the manifest priority order are on the [compatible plugins page](https://sivan757.github.io/dsh-agent-plugins-market/compatible-plugins/). Evidence: the [layout audit](https://github.com/Sivan757/dsh-agent-plugins-market/blob/main/docs/user/layout-coverage.md) and the [compatibility report](https://github.com/Sivan757/dsh-agent-plugins-market/blob/main/docs/reference/compat-report.md).
|
|
171
102
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
Reading a layout does not guarantee every behavior of its original platform. Invalid declarations are diagnosed and skipped.
|
|
175
|
-
|
|
176
|
-
### Project layout switch
|
|
177
|
-
|
|
178
|
-
The plugin settings card has **Scan project Agent layouts** (`dsh-agent-plugins-market.scanProjectLayouts`, default off). It controls one thing: whether the project you are working in contributes skills, commands, agent roles, MCP servers and hooks from its own directories (`.claude`, `.agents`, `.codex`, `.cursor`, `.kimi`, `.zcode`, `.qoder`, `.github`). Turning it on adds those candidates; turning it off removes them on the next discovery pass. The card applies a switch when you save it, and each setting offers Use default while it carries your own value. Configured sources and installed suites are unaffected.
|
|
179
|
-
|
|
180
|
-
[Project layouts](docs/user/usage.md#project-layouts) lists the directories and files read per layout and how they are mounted.
|
|
181
|
-
|
|
182
|
-
### Verified samples
|
|
183
|
-
|
|
184
|
-
The README repositories have offline snapshots in [`tests/fixtures/real-layouts/`](tests/fixtures/real-layouts/) with commit IDs, hashes and licenses, and each layout has an isolated reader test. The [compatibility report](docs/reference/compat-report.md) records the sampled repositories, their schema verdicts and the scanner output; [the audit](docs/user/layout-coverage.md) records independent resource checks. These are documentation, source and sample checks — not end-to-end certification for every platform.
|
|
185
|
-
|
|
186
|
-
Review third-party suites before enabling them: enabled services and hooks can execute programs. See the [runtime and security details](docs/user/usage.md#runtime-and-security).
|
|
103
|
+
Reading a layout does not guarantee every behavior of its original platform. Invalid declarations are diagnosed and skipped, never half-mounted.
|
|
187
104
|
|
|
188
105
|
## FAQ
|
|
189
106
|
|
|
190
107
|
**Why is an installed skill or tool missing?**
|
|
191
108
|
|
|
192
|
-
Check that the suite and the relevant capability are enabled.
|
|
109
|
+
Check that the suite and the relevant capability are enabled. The MCP and LSP panels report failures and missing credentials. Project resources also need the project-scan switch.
|
|
193
110
|
|
|
194
111
|
**Where do I configure MCP tokens?**
|
|
195
112
|
|
|
196
|
-
Open the service in **MCP services**. Missing environment references show `needs-credentials`. Host-managed credentials are write-only
|
|
197
|
-
|
|
198
|
-
**How do I add a service that no suite declares?**
|
|
199
|
-
|
|
200
|
-
Use **Add** in **MCP services** or **LSP servers**. The declaration is validated, stored in `~/.agents/mcp.json` or `~/.agents/lsp.json`, and mounted through the same lifecycle as suite services. Host-observed services remain read-only.
|
|
113
|
+
Open the service in **MCP services**. Missing environment references show `needs-credentials`. Host-managed credentials are write-only.
|
|
201
114
|
|
|
202
115
|
**Do sources refresh automatically?**
|
|
203
116
|
|
|
204
|
-
Only
|
|
205
|
-
|
|
206
|
-
**Where do the suites that appear without adding a source come from?**
|
|
207
|
-
|
|
208
|
-
The plugin presets one source record pointing at its own suite collection, so the market lists that repository on first run; press **Refresh** to fetch its suites. From there it behaves like any other source — including removal, which the next activation undoes just as it does for a source seeded through configuration.
|
|
209
|
-
|
|
210
|
-
**What if a source download fails?**
|
|
211
|
-
|
|
212
|
-
Use a local directory, adopt a manual checkout, or configure a proxy / mirror. See [source configuration](docs/user/usage.md#configure-marketplace-sources).
|
|
213
|
-
|
|
214
|
-
**When do local edits become visible?**
|
|
215
|
-
|
|
216
|
-
There is no file watcher. Local-source discovery caches results for up to 30 seconds; refresh the source to invalidate them immediately. Project discovery has a separate five-second cache. A refresh does not happen automatically on an already-open page.
|
|
117
|
+
Only with **Background source updates** on. It refreshes every configured source every 6 hours, starting one interval after you enable it. The refresh button always works.
|
|
217
118
|
|
|
218
119
|
**Does removing a source delete its files?**
|
|
219
120
|
|
|
220
|
-
Only when you tick **also delete the managed market directory** in the confirmation.
|
|
221
|
-
|
|
222
|
-
## Repository layout
|
|
121
|
+
Only when you tick **also delete the managed market directory** in the confirmation. A local-directory source outside `.sources/` is never deleted.
|
|
223
122
|
|
|
224
|
-
|
|
123
|
+
More questions: [FAQ](https://sivan757.github.io/dsh-agent-plugins-market/faq/).
|
|
225
124
|
|
|
226
|
-
##
|
|
125
|
+
## Documentation
|
|
227
126
|
|
|
228
|
-
- [
|
|
229
|
-
- [
|
|
230
|
-
- [
|
|
231
|
-
- [
|
|
232
|
-
- [Security
|
|
233
|
-
- [Domain glossary](CONTEXT.md) · [
|
|
234
|
-
- [Agent roles and storage](docs/user/agent-roles.md): installed-resource switching, model routing and migration.
|
|
127
|
+
- [Install guide](https://sivan757.github.io/dsh-agent-plugins-market/install/): prerequisites and the first suite, step by step.
|
|
128
|
+
- [Usage guide](https://github.com/Sivan757/dsh-agent-plugins-market/blob/main/docs/user/usage.md): source configuration, storage, project layouts, MCP, LSP and settings.
|
|
129
|
+
- [Compatible plugins](https://sivan757.github.io/dsh-agent-plugins-market/compatible-plugins/): layouts, precedence and verified samples.
|
|
130
|
+
- [Plugin specifications](https://github.com/Sivan757/dsh-agent-plugins-market/blob/main/schemas/README.md): per-dialect reference schemas and the [`com.deepseek.harness`](https://github.com/Sivan757/dsh-agent-plugins-market/blob/main/schemas/com.deepseek.harness/spec.md) namespace.
|
|
131
|
+
- [Contributing](https://github.com/Sivan757/dsh-agent-plugins-market/blob/main/CONTRIBUTING.md) · [Security](https://github.com/Sivan757/dsh-agent-plugins-market/blob/main/SECURITY.md) · [Changelog](https://github.com/Sivan757/dsh-agent-plugins-market/blob/main/CHANGELOG.md) · [License](https://github.com/Sivan757/dsh-agent-plugins-market/blob/main/LICENSE).
|
|
132
|
+
- [Domain glossary](https://github.com/Sivan757/dsh-agent-plugins-market/blob/main/CONTEXT.md) · [Agent roles](https://github.com/Sivan757/dsh-agent-plugins-market/blob/main/docs/user/agent-roles.md) · [Release process](https://github.com/Sivan757/dsh-agent-plugins-market/blob/main/docs/developer/release/release-process.md).
|
|
235
133
|
|
|
236
134
|
## Community
|
|
237
135
|
|
|
238
136
|
Scan the QR code to join the **dsh-agent-plugins-market** WeChat group, where we answer questions and take feature requests.
|
|
239
137
|
|
|
240
138
|
<div align="center">
|
|
241
|
-
<img src="docs/screenshots/wechat-group.webp" alt="WeChat group QR code for dsh-agent-plugins-market" width="240" />
|
|
139
|
+
<img src="https://raw.githubusercontent.com/Sivan757/dsh-agent-plugins-market/main/docs/screenshots/wechat-group.webp" alt="WeChat group QR code for dsh-agent-plugins-market" width="240" />
|
|
242
140
|
</div>
|
package/README.zh.md
CHANGED
|
@@ -1,242 +1,140 @@
|
|
|
1
|
-
<img src="assets/dsh-agent-plugins.png" alt="Agent 扩展" width="64" height="64" />
|
|
1
|
+
<img src="https://raw.githubusercontent.com/Sivan757/dsh-agent-plugins-market/main/assets/dsh-agent-plugins.png" alt="Agent 扩展" width="64" height="64" />
|
|
2
2
|
|
|
3
3
|
# Agent 扩展
|
|
4
4
|
|
|
5
5
|
`dsh-agent-plugins-market`
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
**DeepSeek Harness(DSH)里一站式的技能、子代理、MCP 与 LSP 管理器。**
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
在 DSH 中直接运行 Claude Code、Codex、Cursor、Kimi 与 agent-plugins 套件。插件就地读取各种布局,你不必转换清单,也不必复制文件。在 DSH 图形界面里安装本插件,之后在一个工作区里管理技能、命令、代理角色、MCP 服务与 LSP 服务。
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
如果这个插件对你有用,欢迎在 [GitHub](https://github.com/Sivan757/dsh-agent-plugins-market) 点一个 ⭐。
|
|
12
12
|
|
|
13
|
-
[English](README.md) | 简体中文 | [
|
|
13
|
+
[English](README.md) | 简体中文 | [在线文档](https://sivan757.github.io/dsh-agent-plugins-market/) | [npm](https://www.npmjs.com/package/dsh-agent-plugins-market)
|
|
14
14
|
|
|
15
|
-
[](https://www.npmjs.com/package/dsh-agent-plugins-market) [](LICENSE)
|
|
15
|
+
[](https://www.npmjs.com/package/dsh-agent-plugins-market) [](https://github.com/Sivan757/dsh-agent-plugins-market/blob/main/LICENSE)
|
|
16
16
|
|
|
17
|
-
[快速开始](#快速开始) · [日常使用](#日常使用) · [兼容性](
|
|
17
|
+
[快速开始](#快速开始) · [功能亮点](#功能亮点) · [日常使用](#日常使用) · [兼容性](#兼容性) · [常见问题](#常见问题)
|
|
18
18
|
|
|
19
19
|
## 页面
|
|
20
20
|
|
|
21
21
|
<table>
|
|
22
22
|
<tr>
|
|
23
23
|
<td align="center" width="33%">
|
|
24
|
-
<img src="docs/screenshots/market.png" alt="插件市场" width="100%" /><br />
|
|
25
|
-
<b>插件市场</b><br
|
|
24
|
+
<img src="https://raw.githubusercontent.com/Sivan757/dsh-agent-plugins-market/main/docs/screenshots/market.png" alt="插件市场" width="100%" /><br />
|
|
25
|
+
<b>插件市场</b><br />添加来源、预览套件、安装并启用。
|
|
26
26
|
</td>
|
|
27
27
|
<td align="center" width="33%">
|
|
28
|
-
<img src="docs/screenshots/skills.png" alt="技能" width="100%" /><br />
|
|
29
|
-
<b>技能</b><br
|
|
28
|
+
<img src="https://raw.githubusercontent.com/Sivan757/dsh-agent-plugins-market/main/docs/screenshots/skills.png" alt="技能" width="100%" /><br />
|
|
29
|
+
<b>技能</b><br />浏览技能,也可以自己编写。
|
|
30
30
|
</td>
|
|
31
31
|
<td align="center" width="33%">
|
|
32
|
-
<img src="docs/screenshots/commands.png" alt="命令" width="100%" /><br />
|
|
33
|
-
<b>命令</b><br
|
|
32
|
+
<img src="https://raw.githubusercontent.com/Sivan757/dsh-agent-plugins-market/main/docs/screenshots/commands.png" alt="命令" width="100%" /><br />
|
|
33
|
+
<b>命令</b><br />管理通过 /名称 调用的提示词模板。
|
|
34
34
|
</td>
|
|
35
35
|
</tr>
|
|
36
36
|
<tr>
|
|
37
37
|
<td align="center" width="33%">
|
|
38
|
-
<img src="docs/screenshots/personas.png" alt="代理角色" width="100%" /><br />
|
|
39
|
-
<b>代理角色</b><br
|
|
38
|
+
<img src="https://raw.githubusercontent.com/Sivan757/dsh-agent-plugins-market/main/docs/screenshots/personas.png" alt="代理角色" width="100%" /><br />
|
|
39
|
+
<b>代理角色</b><br />为角色指定精确的提供方、模型与推理强度。
|
|
40
40
|
</td>
|
|
41
41
|
<td align="center" width="33%">
|
|
42
|
-
<img src="docs/screenshots/mcp.png" alt="MCP 服务" width="100%" /><br />
|
|
42
|
+
<img src="https://raw.githubusercontent.com/Sivan757/dsh-agent-plugins-market/main/docs/screenshots/mcp.png" alt="MCP 服务" width="100%" /><br />
|
|
43
43
|
<b>MCP 服务</b><br />凭据、授权与连接状态。
|
|
44
44
|
</td>
|
|
45
45
|
<td align="center" width="33%">
|
|
46
|
-
<img src="docs/screenshots/lsp.png" alt="LSP 服务" width="100%" /><br />
|
|
46
|
+
<img src="https://raw.githubusercontent.com/Sivan757/dsh-agent-plugins-market/main/docs/screenshots/lsp.png" alt="LSP 服务" width="100%" /><br />
|
|
47
47
|
<b>LSP 服务</b><br />语言服务器配置与运行状态。
|
|
48
48
|
</td>
|
|
49
49
|
</tr>
|
|
50
50
|
</table>
|
|
51
51
|
|
|
52
|
-
## 你可以用它做什么
|
|
53
|
-
|
|
54
|
-
- 在插件设置中开启实验性的 Agent 预设管理器后,输入框才显示入口。该开关默认关闭,只控制入口显示,不停用会话运行时。会话扩展预设通过「权限」右侧的Agent 扩展图标按钮选择技能、命令、角色、MCP 与 LSP 能力。每个工作区拥有自己的预设库和新会话默认值。会话运行时处于活动状态时选择预设,将在该会话的下一次用户请求生效。进行中的中途引导(steer)与工具调用不受影响。选择提交后,已打开的斜杠技能菜单自动刷新,无需再次输入或刷新页面。在当前会话中编辑已选或待选预设会更新该会话,其他会话各自保留独立副本。复制、粘贴预设到另一个工作区会生成独立副本。全局管理的资源显示真实状态,不提供会话开关。预设详情不会修改共享凭据或配置。会话选择失败后,显式恢复会还原就绪状态并继续排队的用户输入,无需再次发送。
|
|
55
|
-
|
|
56
|
-
- **十种套件布局。** Claude Code、Codex、Cursor、Kimi Code、ZCode、Qoder CLI、GitHub Copilot CLI、Universal `.plugin/`、[agent-plugins](https://agent-plugins.org) 与无清单技能集合。
|
|
57
|
-
- **来源。** 添加 Git 仓库、本地目录或压缩包(`.zip` / `.tar.gz` / `.tgz` / `.tar`);收编自己克隆的目录;按需刷新;删除来源时可一并删除受管目录。
|
|
58
|
-
- **第一方来源。** 插件预置一条指向自身套件集合的仓库源记录,所以首次运行市场里就列出该仓库,不需要粘贴任何地址。此后它就是普通 Git 来源——刷新以拉取,再像其他来源一样安装与启停其中的套件。
|
|
59
|
-
- **适合你网络的下载方式。** 下载区域设置(默认 `auto` 跟随界面语言,也可显式选择全球或中国大陆)决定 `github.com` 克隆走的镜像前缀;代理与单次调用调优在宿主配置里。
|
|
60
|
-
- **运行时能力。** 启用套件会注入会话:技能进入目录与斜杠菜单,命令以 `/名称` 调用,代理角色进入子代理目录,MCP 工具以 `mcp__` 前缀注册,hooks 挂到宿主生命周期事件,语言服务器通过 `lsp` 工具使用。
|
|
61
|
-
- **MCP。** 内置桥接无需宿主 MCP 客户端,支持 stdio、带 OAuth 的 Streamable HTTP 和旧式 SSE。`${VAR}` 引用从宿主凭据服务或启动环境解析;按服务覆盖可禁用或修补声明,不必修改源文件,可设置工具调用超时与启动超时,也可逐个关闭工具;新建与编辑共用同一服务表单,均提供高级超时设置与 JSON 视图;还可选用宿主客户端兼容模式。套件的工具名为 `mcp__<套件>__<服务>__<工具>`;你在 `~/.agents/mcp.json` 自建的服务以自己的键挂载,即 `mcp__<服务>__<工具>`。
|
|
62
|
-
- **LSP。** 随插件自带:安装插件即完成全部设置,`lsp` 工具只在确有语言服务器需求时挂载;语言服务器可执行文件本身需在 `PATH` 中。从「需要你自己在 profile 里暴露 LSP」的版本升级上来时,若 profile 里还留着那层手工配置,会报接缝冲突;LSP 面板会指出该文件并代为移除这一层,且保留备份。
|
|
63
|
-
- **代理角色与委派。** 角色卡保留专业指令及精确的供应商、模型、思考强度配置。未启用 Agent Teams 时使用 `subagent_role`;启用后使用 `spawn_teammate_role` 创建真正的 Team 成员,并通过原生 Team 工具管理。
|
|
64
|
-
- **项目维度。** 项目自身的技能、代理、命令、MCP 服务与 hooks 无需安装即被发现。
|
|
65
|
-
- **自建资源。** 技能、命令和代理角色以 Markdown 保存在 `~/.agents/` 下,可随时编辑或禁用而不删除文件。
|
|
66
|
-
- **后台自动更新来源。** 可选:按定时器刷新全部已配置来源;默认关闭。
|
|
67
|
-
- **Web 工作区。** 七个页签:插件市场、技能、命令、代理角色、MCP 服务、LSP 服务和 Hooks。每个页签都有搜索、过滤与网格/列表切换,并提供带诊断的状态面板、凭据编辑,以及可在启用可执行第三方内容前提示风险的安装确认。设置页是版式的准绳:所有页面共用同一条页签行(等宽列、绝不横向滚动,标签过长则省略号截断),并共用同一套卡片与详情结构,预设管理器同样如此。
|
|
68
|
-
- **双语界面与反馈。** 工作区文案与注入提示跟随宿主语言;启用反馈后,模型可通过 `gh` 命令或 GitHub token 提交 `report_market_issue` 报告;两者都没有时,会打开预填好的 GitHub 新建 issue 页面并把完整 issue 文本交给你。
|
|
69
|
-
- **翻译。** 描述与已展开的文档可翻译成界面所用的中文或英文,名称保持不变。中文默认开启、英文默认关闭,但你保存的选择优先。正文提供原文、译文和逐段双语三种视图,默认双语。翻译按需开始,依次尝试 Google Translate、Microsoft Translator、你的默认模型,都未应答时保留原文。结果缓存在本地直到清空;关闭翻译会保留缓存。详见[翻译](docs/user/usage.zh.md#翻译)。
|
|
70
|
-
|
|
71
52
|
## 快速开始
|
|
72
53
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
1. 重启 DSH,打开 **设置 → Agent 扩展**。
|
|
80
|
-
2. 市场里已经列出第一方来源;点**刷新**即可拉取其中的套件。想补充更多内容时再添加来源,例如 `https://github.com/anthropics/claude-plugins-official`。
|
|
81
|
-
3. 打开套件查看内容,确认后安装,并确保套件已启用。
|
|
82
|
-
4. 如果套件提供技能,先在**技能**页签查看,再在聊天中输入 `/` 查找允许手动调用的技能。如果提供 MCP,前往 **MCP 服务**检查状态,处理凭据或连接提示后再使用工具。
|
|
83
|
-
|
|
84
|
-
环境要求、profile 配置与其他安装方式见[使用指南](docs/user/usage.zh.md#其他安装方式)。
|
|
85
|
-
|
|
86
|
-
## 日常使用
|
|
87
|
-
|
|
88
|
-
工作区包含七个页签:
|
|
89
|
-
|
|
90
|
-
| 页签 | 可以做什么 |
|
|
91
|
-
| -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
92
|
-
| 插件市场 | 添加来源、预览套件、安装 / 卸载、启用 / 禁用和刷新。 |
|
|
93
|
-
| 技能 | 浏览技能,创建或编辑自己的可复用指令。 |
|
|
94
|
-
| 命令 | 管理通过 `/名称` 调用的提示词模板。 |
|
|
95
|
-
| 代理角色 | 保存角色指令与模型配置;通过 `subagent_role` 委派,或通过 `spawn_teammate_role` 创建带角色的 Team 成员。 |
|
|
96
|
-
| MCP 服务 | 自行新增服务或配置已安装的服务及其凭据与授权,查看连接状态并重试失败的服务。 |
|
|
97
|
-
| LSP 服务 | 新增并配置语言服务器,查看运行状态。 |
|
|
98
|
-
| Hooks | 查看已配置的命令 hooks 及其支持情况。每行可打开声明卡:支持情况、事件、匹配条件与超时,并可在用户根目录试运行;已安装套件的 hook 只读列出,跟随套件。 |
|
|
99
|
-
|
|
100
|
-
**来源(source)**表示内容来自哪里,**套件(suite)**是从中发现的可安装单元。添加来源用于发现套件;安装并启用套件决定其运行时能力是否生效。
|
|
101
|
-
|
|
102
|
-
你自己创作的内容都放在共用的 Agent 布局根目录:技能、命令和角色是 `~/.agents/` 下的 Markdown 文件,命令 hooks 放在 `~/.agents/hooks.json`(或 `~/.agents/hooks/hooks.json`),工作区里新增的 MCP 与 LSP 服务分别保存在 `~/.agents/mcp.json` 与 `~/.agents/lsp.json`。命令与角色按任意子目录深度读取,因此其它工具写在 `~/.agents/commands/git/commit.md` 的文件可用 `/git-commit` 调用。项目原生资源继续保留在项目中。路径和优先级见[存储与发现](docs/user/usage.zh.md#存储与发现)。
|
|
103
|
-
|
|
104
|
-
七个页签共用持久化的卡片/列表偏好。新增、刷新统一位于页头;资源状态条为绿色时表示生效中。hook 行打开的是它自己的只读声明,包含完整命令、声明的匹配条件、声明的超时与宿主支持情况,而不是它所属的整个套件。
|
|
105
|
-
|
|
106
|
-
## 兼容性与运行边界
|
|
107
|
-
|
|
108
|
-
支持的**布局方言(layout dialect)**描述文件如何组织。[统一优先级表](#布局识别优先级)并列列出套件清单与 Marketplace 目录索引。[`schemas/`](schemas/README.md) 中十种布局契约均有独立读取测试;[布局审计](docs/user/layout-coverage.zh.md)把它们对应到固定提交号的仓库快照。
|
|
109
|
-
|
|
110
|
-
支持的**运行时能力(runtime surface)**描述 DSH 能使用什么:
|
|
111
|
-
|
|
112
|
-
| 能力 | 支持情况与条件 |
|
|
113
|
-
| ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
114
|
-
| 技能 | 接入宿主技能目录,允许手动调用的技能出现在斜杠菜单;展开支持的根路径占位符。 |
|
|
115
|
-
| 命令 | 通过宿主命令服务注册斜杠命令。 |
|
|
116
|
-
| 代理 | 动态角色目录;无 Agent Teams 时用 `subagent_role`,启用后用 `spawn_teammate_role`。Team 模式还需要会话查询和系统提示词服务。 |
|
|
117
|
-
| MCP | 默认使用内置桥接,支持 stdio、带 OAuth 的 Streamable HTTP 和旧式 SSE;也可切换宿主客户端兼容模式,该模式执行工具调用超时,但不执行工具过滤与启动超时。 |
|
|
118
|
-
| Hooks | 运行 `dsh-hooks-claude-code` 桥接映射支持的 command-hook 子集。 |
|
|
119
|
-
| LSP | 随插件自带:安装插件即安装 LSP 支持包,`lsp` 工具只在确有语言服务器需求时挂载;语言服务器可执行文件本身需在 `PATH` 中。 |
|
|
54
|
+
1. 在 DSH 图形界面中打开侧边栏的**插件**页。
|
|
55
|
+
2. 点**添加插件**,填入 `dsh-agent-plugins-market`,然后安装。同一个对话框也接受仓库地址或本地目录。
|
|
56
|
+
3. 重启 DSH,然后打开**设置 → Agent 扩展**。
|
|
57
|
+
4. 市场里已经列出一个第一方来源。点**刷新**即可拉取其中的套件。想补充更多内容时再添加来源,例如 `https://github.com/anthropics/claude-plugins-official`。
|
|
58
|
+
5. 打开套件查看内容,确认后安装并保持启用。技能会出现在**技能**页签和聊天中的 `/` 菜单里;如果套件提供 MCP,先在 **MCP 服务**处理凭据提示,再使用它的工具。
|
|
120
59
|
|
|
121
|
-
|
|
60
|
+
命令行替代方式:`dsh plugin --profile <name> add dsh-agent-plugins-market`。环境要求、profile 配置与其他安装方式见[使用指南](https://github.com/Sivan757/dsh-agent-plugins-market/blob/main/docs/user/usage.zh.md#其他安装方式)。
|
|
122
61
|
|
|
123
|
-
|
|
62
|
+
## 功能亮点
|
|
124
63
|
|
|
125
|
-
|
|
64
|
+
### 核心能力
|
|
126
65
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
| 4 | Cursor | `.cursor-plugin/plugin.json` | `.cursor-plugin/marketplace.json` |
|
|
133
|
-
| 5 | Kimi Code | `kimi.plugin.json`,其次 `.kimi-plugin/plugin.json` | `.kimi-plugin/marketplace.json` |
|
|
134
|
-
| 6 | Codex | `.codex-plugin/plugin.json` | `.agents/plugins/marketplace.json`,其次 `.agents/plugins/api_marketplace.json` |
|
|
135
|
-
| 7 | ZCode | `.zcode-plugin/plugin.json` | 无专属索引 |
|
|
136
|
-
| 8 | Qoder CLI | `.qoder-plugin/plugin.json` | `.qoder-plugin/marketplace.json` |
|
|
137
|
-
| 9 | GitHub Copilot CLI | `.github/plugin/plugin.json` | `.github/plugin/marketplace.json` |
|
|
138
|
-
| 回退 | 技能集合 / 共享索引 | 无已知清单时按技能集合约定发现 | 根 `marketplace.json` |
|
|
66
|
+
- **任何技能仓库都能用。** 仓库里只要有 `skills/<名称>/SKILL.md`,把地址加为来源就能发现套件。不需要清单,不需要转换,不需要复制文件。
|
|
67
|
+
- **十种套件布局。** Claude Code、Codex、Cursor、Kimi Code、ZCode、Qoder CLI、GitHub Copilot CLI、通用 `.plugin/`、[agent-plugins](https://agent-plugins.org) 以及无清单的技能集合。
|
|
68
|
+
- **来源与下载。** 添加 Git 仓库、本地目录或压缩包,也可以接管你自己克隆的检出目录并随时刷新。镜像线路可选全球或中国大陆;需要时还可以每 6 小时自动刷新全部来源。
|
|
69
|
+
- **运行时注入。** 启用套件后,技能进入技能目录与斜杠菜单,命令成为 `/名称`,代理角色进入子代理目录,MCP 工具以 `mcp__*` 前缀出现,hooks 挂到宿主生命周期事件,语言服务器接入 `lsp` 工具;LSP 装上插件即完成配置。
|
|
70
|
+
- **一个工作区。** 七个页签覆盖市场、你自己创作的内容与正在运行的服务,都支持搜索、筛选和卡片或列表视图。
|
|
139
71
|
|
|
140
|
-
|
|
141
|
-
- **组件补充:** 根 `plugin.json` 未声明受识别的 agent-plugins `$schema` 时,缺失的组件声明可以从 `.claude-plugin/plugin.json` 补齐;根清单中的显式声明优先,marketplace 条目声明补充剩余缺项。
|
|
142
|
-
- Marketplace 索引遵循同一顺序:第一个能产出套件的索引胜出,无效或空索引允许继续尝试后续候选。
|
|
72
|
+
### 进阶能力
|
|
143
73
|
|
|
144
|
-
|
|
74
|
+
- **MCP OAuth,无需声明。** 远端 MCP 服务返回 `401` 时,自动完成 RFC 9728 发现、动态客户端注册与 PKCE 授权,浏览器授权后令牌持久保存。OAuth 默认开启,套件不需要为此写任何声明。
|
|
75
|
+
- **逐个 MCP 服务精调。** 不改动来源就能覆盖某条声明,单独关闭某个工具,并设置工具调用与启动超时。
|
|
76
|
+
- **项目资源与自己创作的内容。** 打开**扫描项目 Agent 布局**后,无需安装即可读取项目自身目录中的技能、命令、角色、MCP 服务与 hooks。自己的内容放在 `~/.agents/` 下,以 Markdown 编写;停用资源不必删除文件。
|
|
77
|
+
- **按工作区生效的控制。** 每个工作区可以单独开关六类挂载能力,保留自己的资源筛选条件,并把资源窗口配置存为可跨项目使用的收藏。
|
|
78
|
+
- **可读可试的 Hooks。** 每个 hook 行都能打开声明卡,查看事件、匹配条件与超时,并在用户根目录试运行一次。
|
|
79
|
+
- **默认双语。** 界面与注入的提示词跟随宿主语言。描述与文档可显示原文、译文或双语,结果缓存在本地直到你清空缓存。
|
|
145
80
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
表中说明本插件是否读取该布局的对应能力。**支持**表示读取该布局自己的文件并注入;**部分**表示只理解其中一部分格式,或上游布局本身没有对应定义——具体见下表说明。依据见[兼容性报告](docs/reference/compat-report.md)与[布局审计](docs/user/layout-coverage.zh.md)。
|
|
149
|
-
|
|
150
|
-
| 布局 | 技能 | 代理 | 命令 | MCP | Hooks | LSP |
|
|
151
|
-
| ------------------------------------------------------------------------------------------------------------- | ---- | ---- | ---- | ---- | ------ | ------ |
|
|
152
|
-
| [Claude Code](https://code.claude.com/docs/en/plugins-reference) | 支持 | 支持 | 支持 | 支持 | 部分 | 支持 |
|
|
153
|
-
| [Codex](https://developers.openai.com/plugins/build/plugins) | 支持 | 支持 | 支持 | 部分 | 部分 | 支持 |
|
|
154
|
-
| [Cursor](https://cursor.com/docs/reference/plugins) | 支持 | 部分 | 部分 | 部分 | 不支持 | 支持 |
|
|
155
|
-
| Kimi Code | 支持 | 支持 | 支持 | 支持 | 部分 | 部分 |
|
|
156
|
-
| [ZCode](https://zcode.z.ai/en/docs/plugin) `.zcode-plugin/` | 支持 | 支持 | 支持 | 支持 | 部分 | 部分 |
|
|
157
|
-
| [Qoder CLI](https://docs.qoder.com/cli/plugins-reference) `.qoder-plugin/` | 支持 | 支持 | 支持 | 部分 | 部分 | 部分 |
|
|
158
|
-
| [GitHub Copilot CLI](https://docs.github.com/en/copilot/reference/copilot-cli-reference/cli-plugin-reference) | 支持 | 支持 | 支持 | 支持 | 部分 | 支持 |
|
|
159
|
-
| Universal 兼容布局 `.plugin/` | 支持 | 支持 | 支持 | 支持 | 部分 | 支持 |
|
|
160
|
-
| [agent-plugins](https://agent-plugins.org) | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
|
|
161
|
-
| 无清单技能集合 | 支持 | 支持 | 支持 | 支持 | 部分 | 部分 |
|
|
162
|
-
| 项目原生目录 | 支持 | 支持 | 支持 | 支持 | 部分 | 不支持 |
|
|
163
|
-
|
|
164
|
-
- **技能**读取清单声明的路径与约定的 `skills/` 目录,也支持平铺的 `<name>.md` 文件。自带 `SKILL.md` 的路径就是一个技能:与它并列的文档属于该技能,不作为技能读取。合规的 agent-plugins 套件是例外:技能只来自 `skills/` 一层子目录,与其规范一致。
|
|
165
|
-
- **代理与命令**按 Markdown 读取(`agents/*.md`、`commands/*.md`)。Cursor 插件命令接受 `.md`、`.mdc`、`.markdown`、`.txt`;Codex 与 Kimi 的原生代理/命令格式(TOML、YAML)尚未适配。
|
|
166
|
-
- **MCP** 支持声明的文件、内联表与数组。Cursor 的无 schema `mcp.json` 与 agent-plugins 的严格 `mcp.json` 都能读取;Kimi Code 只读内联声明。Codex 的 app 连接器不在适配范围内。
|
|
167
|
-
- **Hooks** 只映射 DSH 有对应点的命令类事件;没有对应点的事件(例如 `afterFileEdit`)给出诊断而不伪造执行。Cursor 的原生事件不读取。
|
|
168
|
-
- **LSP** 支持声明的文件、数组、内联表,以及约定的 `.lsp.json` / `lsp.json` 位置。项目内的 LSP 声明只给诊断、不挂载:宿主 LSP 注册表是全局的。部分布局只提供目录预览。
|
|
169
|
-
- **agent-plugins** 套件按规范读取可移植核心(`skills/`、`mcp.json`),另通过本插件的 [`com.deepseek.harness`](schemas/com.deepseek.harness/spec.md) 扩展命名空间承载命令、代理、hooks、LSP 与逐服务器 MCP 策略(OAuth、工具清单、超时)。该布局下根目录的 `commands/`、`agents/`、`hooks/` 与 `.mcp.json` 属于其它布局,给出「未读取」诊断;清单内联组件键按 §5.2 报告后忽略。两个受支持的版本(1.0.0、1.1.0)各自按内置 schema 校验。
|
|
170
|
-
- **Universal** 是本插件使用的兼容布局名称:[OpenHands SDK](https://docs.openhands.dev/sdk/guides/plugins)文档同样使用 `.plugin/plugin.json`,[Vercel 仓库](https://github.com/vercel/vercel-plugin/blob/main/.plugin/plugin.json)也在使用,但不存在跨厂商规范。
|
|
171
|
-
|
|
172
|
-
[jeecgboot/skills](https://github.com/jeecgboot/skills) 这类源中,未声明插件且只包含技能的目录会聚合为一张插件卡片。市场条目、自带插件清单或其它运行面的目录仍保留独立身份。聚合插件需要单独安装,不继承单个技能的安装状态。详见[技能集合规则](schemas/skill-collection/spec.md)。
|
|
81
|
+
## 日常使用
|
|
173
82
|
|
|
174
|
-
|
|
83
|
+
工作区包含七个页签:
|
|
175
84
|
|
|
176
|
-
|
|
85
|
+
| 页签 | 可以做什么 |
|
|
86
|
+
| -------- | ------------------------------------------------ |
|
|
87
|
+
| 插件市场 | 添加来源、预览套件、安装或卸载,以及启用或停用。 |
|
|
88
|
+
| 技能 | 浏览技能,创建或编辑自己的可复用指令。 |
|
|
89
|
+
| 命令 | 管理通过 `/名称` 调用的提示词模板。 |
|
|
90
|
+
| 代理角色 | 保存角色指令与模型配置,然后委派给它们。 |
|
|
91
|
+
| MCP 服务 | 新增服务,或配置已安装的服务及其凭据与授权。 |
|
|
92
|
+
| LSP 服务 | 新增并配置语言服务器,查看运行状态。 |
|
|
93
|
+
| Hooks | 查看已配置的 hook 及其事件、匹配条件与超时。 |
|
|
177
94
|
|
|
178
|
-
|
|
95
|
+
**来源(source)**表示内容来自哪里,**套件(suite)**是从中发现的可安装单元。添加来源用于发现套件,启用套件决定其运行时能力是否生效。
|
|
179
96
|
|
|
180
|
-
|
|
97
|
+
你自己创作的内容都放在 `~/.agents/` 下:技能、命令和角色是 Markdown 文件,hooks 放在 `hooks.json`,工作区里新增的 MCP 与 LSP 服务分别保存在 `mcp.json` 与 `lsp.json`。项目原生资源继续保留在项目中。路径与优先级见[存储与发现](https://github.com/Sivan757/dsh-agent-plugins-market/blob/main/docs/user/usage.zh.md#存储与发现)。
|
|
181
98
|
|
|
182
|
-
|
|
99
|
+
## 兼容性
|
|
183
100
|
|
|
184
|
-
|
|
101
|
+
插件读取十种布局方言,映射六类运行时能力。逐布局的支持情况与清单优先级见[兼容的插件市场](https://sivan757.github.io/dsh-agent-plugins-market/compatible-plugins/)。证据是[布局审计](https://github.com/Sivan757/dsh-agent-plugins-market/blob/main/docs/user/layout-coverage.zh.md)与[兼容性报告](https://github.com/Sivan757/dsh-agent-plugins-market/blob/main/docs/reference/compat-report.md)。
|
|
185
102
|
|
|
186
|
-
|
|
103
|
+
能读取某种布局,不等于它的每个行为都与原平台一致。无效声明会被诊断并跳过,不会只挂载一半。
|
|
187
104
|
|
|
188
105
|
## 常见问题
|
|
189
106
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
检查套件及对应能力是否启用。技能可能限制手动调用;MCP / LSP 面板显示用户服务故障。项目资源还需要开启项目扫描;不支持的原生字段与项目 LSP 声明进入扫描诊断。
|
|
193
|
-
|
|
194
|
-
**在哪里配置 MCP token?**
|
|
195
|
-
|
|
196
|
-
在 **MCP 服务**中打开对应服务。缺失环境变量引用时显示 `needs-credentials`。宿主管理的凭据只写不读;启动环境中的凭据需要修改环境后重启 DSH。
|
|
197
|
-
|
|
198
|
-
**套件没有声明的服务怎么添加?**
|
|
199
|
-
|
|
200
|
-
在 **MCP 服务**或 **LSP 服务**中点击新增并填入声明。声明会先校验,保存到 `~/.agents/mcp.json` 或 `~/.agents/lsp.json`,并与套件服务走同一套挂载生命周期。从宿主配置观察到的服务保持只读。
|
|
201
|
-
|
|
202
|
-
**来源会自动更新吗?**
|
|
203
|
-
|
|
204
|
-
只有开启**后台自动更新来源**后才会:开启后每 6 小时刷新一次全部已配置来源,第一次刷新在开启满一个周期之后。该开关默认关闭,刷新按钮始终可用。
|
|
205
|
-
|
|
206
|
-
**没有添加任何来源,市场里的套件是从哪来的?**
|
|
207
|
-
|
|
208
|
-
插件预置一条指向自身套件集合的仓库源记录,所以首次运行市场里就列出该仓库;点**刷新**即可拉取其中的套件。此后它与其他来源完全一致——包括删除:和通过配置预置的来源一样,下次激活会重新登记。
|
|
107
|
+
**已安装的技能或工具为什么不见了?**
|
|
209
108
|
|
|
210
|
-
|
|
109
|
+
先确认套件与对应能力都已启用。MCP 与 LSP 面板会报告失败和缺失的凭据。项目资源还需要打开项目扫描开关。
|
|
211
110
|
|
|
212
|
-
|
|
111
|
+
**MCP 的令牌在哪里配置?**
|
|
213
112
|
|
|
214
|
-
|
|
113
|
+
在 **MCP 服务**中打开该服务。缺失的环境引用会显示 `needs-credentials`。宿主托管的凭据是只写的。
|
|
215
114
|
|
|
216
|
-
|
|
115
|
+
**来源会自动刷新吗?**
|
|
217
116
|
|
|
218
|
-
|
|
117
|
+
只有打开**后台更新来源**时才会。它每 6 小时刷新一次全部已配置来源,并在启用后一个周期开始。刷新按钮始终可用。
|
|
219
118
|
|
|
220
|
-
|
|
119
|
+
**删除来源会删掉文件吗?**
|
|
221
120
|
|
|
222
|
-
|
|
121
|
+
只有你在确认框中勾选**同时删除托管的市场目录**时才会。位于 `.sources/` 之外的本地目录来源永远不会被删除。
|
|
223
122
|
|
|
224
|
-
|
|
123
|
+
更多问题见[常见问题](https://sivan757.github.io/dsh-agent-plugins-market/faq/)。
|
|
225
124
|
|
|
226
|
-
##
|
|
125
|
+
## 文档
|
|
227
126
|
|
|
228
|
-
- [
|
|
229
|
-
- [
|
|
230
|
-
- [
|
|
231
|
-
- [
|
|
232
|
-
- [
|
|
233
|
-
- [
|
|
234
|
-
- [代理角色与存储](docs/user/agent-roles.zh.md):已安装资源切换、角色模型路由与目录迁移。
|
|
127
|
+
- [安装指南](https://sivan757.github.io/dsh-agent-plugins-market/install/):从环境要求到第一个套件,逐步说明。
|
|
128
|
+
- [使用指南](https://github.com/Sivan757/dsh-agent-plugins-market/blob/main/docs/user/usage.zh.md):来源配置、存储、项目布局、MCP、LSP 与各项设置。
|
|
129
|
+
- [兼容的插件市场](https://sivan757.github.io/dsh-agent-plugins-market/compatible-plugins/):布局、优先级与抽样验证。
|
|
130
|
+
- [插件规范](https://github.com/Sivan757/dsh-agent-plugins-market/blob/main/schemas/README.md):各布局的参考 schema,以及 [`com.deepseek.harness`](https://github.com/Sivan757/dsh-agent-plugins-market/blob/main/schemas/com.deepseek.harness/spec.md) 扩展命名空间。
|
|
131
|
+
- [贡献指南](https://github.com/Sivan757/dsh-agent-plugins-market/blob/main/CONTRIBUTING.md) · [安全策略](https://github.com/Sivan757/dsh-agent-plugins-market/blob/main/SECURITY.md) · [更新日志](https://github.com/Sivan757/dsh-agent-plugins-market/blob/main/CHANGELOG.md) · [MIT 许可](https://github.com/Sivan757/dsh-agent-plugins-market/blob/main/LICENSE)。
|
|
132
|
+
- [领域词汇表](https://github.com/Sivan757/dsh-agent-plugins-market/blob/main/CONTEXT.md) · [代理角色](https://github.com/Sivan757/dsh-agent-plugins-market/blob/main/docs/user/agent-roles.zh.md) · [发布流程](https://github.com/Sivan757/dsh-agent-plugins-market/blob/main/docs/developer/release/release-process.md)。
|
|
235
133
|
|
|
236
134
|
## 交流群
|
|
237
135
|
|
|
238
|
-
|
|
136
|
+
扫描二维码加入 **dsh-agent-plugins-market** 微信群,我们在这里答疑并收集功能建议。
|
|
239
137
|
|
|
240
138
|
<div align="center">
|
|
241
|
-
<img src="docs/screenshots/wechat-group.webp" alt="dsh-agent-plugins-market 微信群二维码" width="240" />
|
|
139
|
+
<img src="https://raw.githubusercontent.com/Sivan757/dsh-agent-plugins-market/main/docs/screenshots/wechat-group.webp" alt="dsh-agent-plugins-market 微信群二维码" width="240" />
|
|
242
140
|
</div>
|
|
@@ -69,7 +69,10 @@ export function createSessionExtensions({ ctx, dataRoot, runtime, hostLocale })
|
|
|
69
69
|
let scopedContributors;
|
|
70
70
|
let selectedRoleSuites;
|
|
71
71
|
let suiteSession;
|
|
72
|
-
let listRoles = async () =>
|
|
72
|
+
let listRoles = async () => ({
|
|
73
|
+
entries: [],
|
|
74
|
+
complete: false
|
|
75
|
+
});
|
|
73
76
|
const mount = ({ catalog, panels, resources, readUserDeclarations }) => {
|
|
74
77
|
ctx.inject(['agents', 'sessions', 'sessionQuery', 'tools'], hostCtx => {
|
|
75
78
|
const eligible = (agent) => {
|
|
@@ -302,8 +305,12 @@ export function createSessionExtensions({ ctx, dataRoot, runtime, hostLocale })
|
|
|
302
305
|
});
|
|
303
306
|
listRoles = async (parent) => {
|
|
304
307
|
const agent = parent;
|
|
308
|
+
// "Not ready" is not "no roles": the extension runtime may still be
|
|
309
|
+
// initializing or recovering, so an empty answer must not replace the
|
|
310
|
+
// published catalog. A read failure propagates for the same reason, and
|
|
311
|
+
// the catalog publisher turns both into "no new information".
|
|
305
312
|
if (!agent || !extensionPresets?.ready(agent))
|
|
306
|
-
return [];
|
|
313
|
+
return { entries: [], complete: false };
|
|
307
314
|
const user = (await resources.agents.list(true))
|
|
308
315
|
.filter(entry => entry.origin === 'user' && extensionPresets?.allows(agent, 'agents:' + (entry.id ?? entry.name)))
|
|
309
316
|
.map(entry => ({ ...entry, title: entry.name, name: entry.id ?? entry.name, selectionEnabled: true }));
|
|
@@ -311,7 +318,7 @@ export function createSessionExtensions({ ctx, dataRoot, runtime, hostLocale })
|
|
|
311
318
|
suites: () => selectedRoleSuites?.(agent) ?? Promise.resolve([]),
|
|
312
319
|
selected: role => extensionPresets?.allows(agent, 'agents:' + role.name) === true
|
|
313
320
|
});
|
|
314
|
-
return [...user, ...project];
|
|
321
|
+
return { entries: [...user, ...project], complete: true };
|
|
315
322
|
};
|
|
316
323
|
};
|
|
317
324
|
return {
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structural filesystem questions, answered without trusting an error code.
|
|
3
|
+
*
|
|
4
|
+
* Operating systems disagree about which code a failed read carries: Windows
|
|
5
|
+
* can report `ENOENT` for a child of a path that exists as a file, which a
|
|
6
|
+
* code-only guard mistakes for a removed entry. A caller that tolerates "not
|
|
7
|
+
* there yet" asks this module instead, so the decision comes from the path
|
|
8
|
+
* shape rather than from the platform error vocabulary.
|
|
9
|
+
*/
|
|
10
|
+
import { stat } from 'node:fs/promises';
|
|
11
|
+
import { dirname } from 'node:path';
|
|
12
|
+
/** One path's stat, or `undefined` when the path cannot be read. */
|
|
13
|
+
async function statOf(path) {
|
|
14
|
+
try {
|
|
15
|
+
return await stat(path);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Whether a path is confirmed absent rather than unreadable.
|
|
23
|
+
*
|
|
24
|
+
* An error code alone cannot separate a removed entry from an unreadable
|
|
25
|
+
* source, because a platform can report `ENOENT` for a child of a file. The
|
|
26
|
+
* path ancestors answer the question instead: when the nearest existing
|
|
27
|
+
* ancestor is a directory, the entry is genuinely gone, and when it is not a
|
|
28
|
+
* directory, the source cannot be read and the caller must fail closed.
|
|
29
|
+
* @param path - the path to classify.
|
|
30
|
+
* @returns `true` only when the path is confirmed absent.
|
|
31
|
+
*/
|
|
32
|
+
export async function isAbsentPath(path) {
|
|
33
|
+
let current = path;
|
|
34
|
+
for (;;) {
|
|
35
|
+
const info = await statOf(current);
|
|
36
|
+
if (info !== undefined)
|
|
37
|
+
return current !== path && info.isDirectory();
|
|
38
|
+
const parent = dirname(current);
|
|
39
|
+
if (parent === current)
|
|
40
|
+
return true;
|
|
41
|
+
current = parent;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -7,6 +7,7 @@ import { pluginRootOf } from '../../../market-catalog/src/index.js';
|
|
|
7
7
|
import { isWithin, suiteDataDir } from '../../../market-catalog/src/index.js';
|
|
8
8
|
import { parseSkillFrontmatter, stripFrontmatter } from '../../../market-catalog/src/index.js';
|
|
9
9
|
import { parseFrontmatterRecord } from './panels/user-store.js';
|
|
10
|
+
import { isAbsentPath } from './fs-probe.js';
|
|
10
11
|
/**
|
|
11
12
|
* Id of one suite-owned document, whichever surface addresses it. The leading
|
|
12
13
|
* `[` is what distinguishes a plugin entry from a user-authored one;
|
|
@@ -334,8 +335,8 @@ class PanelResources {
|
|
|
334
335
|
: (suite.resources?.[this.kind] ?? (await defaultMarkdownResources(suite.root, this.kind)));
|
|
335
336
|
for (const resource of files) {
|
|
336
337
|
const { name, file } = resource;
|
|
337
|
-
const rawText = await resourceText(resource).catch(error => {
|
|
338
|
-
if (strict &&
|
|
338
|
+
const rawText = await resourceText(resource).catch(async (error) => {
|
|
339
|
+
if (strict && !(await isAbsentPath(file)))
|
|
339
340
|
throw error;
|
|
340
341
|
return undefined;
|
|
341
342
|
});
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* @module application/user-store
|
|
15
15
|
*/
|
|
16
16
|
import { readdir, readFile, rmdir, rm, stat } from 'node:fs/promises';
|
|
17
|
+
import { isAbsentPath } from '../fs-probe.js';
|
|
17
18
|
import { dirname, join } from 'node:path';
|
|
18
19
|
import { writeFileAtomic } from '@deepseek-ai/dsh-atomic-write';
|
|
19
20
|
import { parseDocument, stringify } from 'yaml';
|
|
@@ -44,15 +45,48 @@ export const SKILL_ENTRY_SHAPES = ['skill-directory', 'file'];
|
|
|
44
45
|
export function entryDocumentPath(dir, name, shape) {
|
|
45
46
|
return shape === 'skill-directory' ? join(dir, name, SKILL_ENTRY_FILE) : join(dir, `${name}.md`);
|
|
46
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* Whether one panel directory may be listed, answered structurally rather than
|
|
50
|
+
* from a listing failure.
|
|
51
|
+
*
|
|
52
|
+
* A path is either an existing directory, absent (a user who authored nothing
|
|
53
|
+
* has not broken anything), or something that can never hold entries. Only the
|
|
54
|
+
* first is listed; the second is a valid empty panel; the third is a broken
|
|
55
|
+
* configuration. Confirming the shape before listing keeps that decision
|
|
56
|
+
* independent of the code a `readdir` failure happens to carry.
|
|
57
|
+
* @param dir - the panel directory.
|
|
58
|
+
* @param strict - whether a broken configuration is an error or an empty read.
|
|
59
|
+
* @returns `true` when the directory is confirmed and may be listed.
|
|
60
|
+
*/
|
|
61
|
+
async function confirmDirectory(dir, strict) {
|
|
62
|
+
let info;
|
|
63
|
+
try {
|
|
64
|
+
info = await stat(dir);
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
// A directory is absent only when its ancestors stay searchable: a platform
|
|
68
|
+
// can report ENOENT for a child of a file, which is an unreadable panel.
|
|
69
|
+
if (await isAbsentPath(dir))
|
|
70
|
+
return false;
|
|
71
|
+
if (strict)
|
|
72
|
+
throw error;
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
if (info.isDirectory())
|
|
76
|
+
return true;
|
|
77
|
+
if (strict)
|
|
78
|
+
throw Object.assign(new Error(`ENOTDIR: not a directory, scandir '${dir}'`), { code: 'ENOTDIR' });
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
47
81
|
/** Whether a path is a regular file; strict runtime snapshots propagate real I/O failures. */
|
|
48
82
|
async function isFile(file, strict) {
|
|
49
83
|
try {
|
|
50
84
|
return (await stat(file)).isFile();
|
|
51
85
|
}
|
|
52
86
|
catch (error) {
|
|
53
|
-
if (strict
|
|
54
|
-
|
|
55
|
-
|
|
87
|
+
if (!strict || (await isAbsentPath(file)))
|
|
88
|
+
return false;
|
|
89
|
+
throw error;
|
|
56
90
|
}
|
|
57
91
|
}
|
|
58
92
|
/**
|
|
@@ -83,14 +117,18 @@ export async function listEntryDocuments(dir, strict = false, shapes = ['file'],
|
|
|
83
117
|
await collectNestedEntryDocuments(dir, '', shapes, strict, found);
|
|
84
118
|
return [...found.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
85
119
|
}
|
|
120
|
+
if (!(await confirmDirectory(dir, strict)))
|
|
121
|
+
return [];
|
|
86
122
|
let entries;
|
|
87
123
|
try {
|
|
88
124
|
entries = await readdir(dir);
|
|
89
125
|
}
|
|
90
126
|
catch (error) {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
127
|
+
// Only a structurally confirmed absence is tolerated: the directory can be
|
|
128
|
+
// removed between the confirmation and the listing.
|
|
129
|
+
if (!strict || (await isAbsentPath(dir)))
|
|
130
|
+
return [];
|
|
131
|
+
throw error;
|
|
94
132
|
}
|
|
95
133
|
for (const entry of entries.sort()) {
|
|
96
134
|
const name = entry.endsWith('.md') ? entry.slice(0, -3) : shapes.includes('skill-directory') ? entry : undefined;
|
|
@@ -114,14 +152,16 @@ export async function listEntryDocuments(dir, strict = false, shapes = ['file'],
|
|
|
114
152
|
* `/` separators and no trailing slash.
|
|
115
153
|
*/
|
|
116
154
|
async function collectNestedEntryDocuments(dir, prefix, shapes, strict, found) {
|
|
155
|
+
if (!(await confirmDirectory(dir, strict)))
|
|
156
|
+
return;
|
|
117
157
|
let entries;
|
|
118
158
|
try {
|
|
119
159
|
entries = await readdir(dir, { withFileTypes: true });
|
|
120
160
|
}
|
|
121
161
|
catch (error) {
|
|
122
|
-
if (strict
|
|
123
|
-
|
|
124
|
-
|
|
162
|
+
if (!strict || (await isAbsentPath(dir)))
|
|
163
|
+
return;
|
|
164
|
+
throw error;
|
|
125
165
|
}
|
|
126
166
|
for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
127
167
|
if (entry.isSymbolicLink() || entry.name.startsWith('.') || entry.name === 'node_modules')
|
|
@@ -171,9 +211,9 @@ export async function readEntryDocument(document, strict = false) {
|
|
|
171
211
|
text = await readFile(document.file, 'utf8');
|
|
172
212
|
}
|
|
173
213
|
catch (error) {
|
|
174
|
-
if (strict
|
|
175
|
-
|
|
176
|
-
|
|
214
|
+
if (!strict || (await isAbsentPath(document.file)))
|
|
215
|
+
return undefined;
|
|
216
|
+
throw error;
|
|
177
217
|
}
|
|
178
218
|
let meta;
|
|
179
219
|
try {
|
|
@@ -3,6 +3,7 @@ import { defaultMarkdownResources, resourceText } from '../../../market-catalog/
|
|
|
3
3
|
import { pluginRootOf } from '../../../market-catalog/src/index.js';
|
|
4
4
|
import { suiteDataDir } from '../../../market-catalog/src/index.js';
|
|
5
5
|
import { parseAgentRole } from './agent-roles.js';
|
|
6
|
+
import { isAbsentPath } from './fs-probe.js';
|
|
6
7
|
export async function projectAgentRoles(catalog, parent, options = {}) {
|
|
7
8
|
const cwd = parent?.session?.header?.cwd;
|
|
8
9
|
if (typeof cwd !== 'string' || cwd === '')
|
|
@@ -16,8 +17,10 @@ export async function projectAgentRoles(catalog, parent, options = {}) {
|
|
|
16
17
|
const suiteData = suiteRoot === undefined ? undefined : suiteDataDir(catalog.dataRoot, suite.sourceId, suite.id);
|
|
17
18
|
for (const resource of suite.resources?.agents ?? (options.suites ? [] : await defaultMarkdownResources(suite.root, 'agents'))) {
|
|
18
19
|
const path = resource.file;
|
|
19
|
-
const rawText = await resourceText(options.suites && resource.file !== suite.manifest.path ? { name: resource.name, file: resource.file } : resource).catch(error => {
|
|
20
|
-
|
|
20
|
+
const rawText = await resourceText(options.suites && resource.file !== suite.manifest.path ? { name: resource.name, file: resource.file } : resource).catch(async (error) => {
|
|
21
|
+
// A vanished document is an ordinary removal; any other failure must not
|
|
22
|
+
// silently drop a project role from the catalog.
|
|
23
|
+
if (!(await isAbsentPath(path)))
|
|
21
24
|
throw error;
|
|
22
25
|
return undefined;
|
|
23
26
|
});
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { readFile } from 'node:fs/promises';
|
|
3
3
|
import { defineTool } from '@deepseek-ai/dsh-tools';
|
|
4
4
|
import { mountSubagentCatalog } from './subagent-catalog.js';
|
|
5
|
+
import { isAbsentPath } from '../../application/fs-probe.js';
|
|
5
6
|
import { namedAgentRoles } from './agent-role-names.js';
|
|
6
7
|
import { expandPluginPaths } from '../../../../market-catalog/src/index.js';
|
|
7
8
|
import { parseAgentRole } from '../../application/agent-roles.js';
|
|
@@ -98,7 +99,9 @@ export async function agentRoleCatalog(entries, signal, diagnose = () => { }, pr
|
|
|
98
99
|
text = entry.rawText ?? (await readFile(entry.path, 'utf8'));
|
|
99
100
|
}
|
|
100
101
|
catch (error) {
|
|
101
|
-
|
|
102
|
+
// Only a confirmed disappearance is a normal removal; any other failure
|
|
103
|
+
// aborts the publication instead of publishing a smaller catalog.
|
|
104
|
+
if (!(await isAbsentPath(entry.path)))
|
|
102
105
|
throw error;
|
|
103
106
|
continue;
|
|
104
107
|
}
|
|
@@ -232,16 +235,13 @@ export async function executeAgentRole(host, listRoles, agentName, prompt, paren
|
|
|
232
235
|
await run.dispose();
|
|
233
236
|
}
|
|
234
237
|
}
|
|
235
|
-
/**
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
* description is present in every request, while the catalog message is
|
|
240
|
-
* re-published whenever roles change, so guidance kept out of the catalog is
|
|
241
|
-
* sent once and stays readable through compaction.
|
|
242
|
-
*/
|
|
238
|
+
/** Normalize one observation; a bare list means the read completed. */
|
|
239
|
+
export function roleSnapshot(observation) {
|
|
240
|
+
return Array.isArray(observation) ? { entries: observation, complete: true } : observation;
|
|
241
|
+
}
|
|
243
242
|
export function mountAgentRoleTool(ctx, listRoles) {
|
|
244
243
|
const host = ctx;
|
|
244
|
+
const entries = async (parent) => roleSnapshot(await listRoles(parent)).entries;
|
|
245
245
|
const tool = defineTool({
|
|
246
246
|
name: AGENT_ROLE_TOOL_NAME,
|
|
247
247
|
description: "Delegate a task to a named role child from the session's subagent-catalog: the role's own instructions and its configured model apply, and the child starts without this conversation. Use it proactively for self-contained work — codebase exploration whose raw reads would fill this context, a scoped implementation, a review, or an analysis you can brief in one prompt — and start independent children together in one message. The child runs in " +
|
|
@@ -307,7 +307,7 @@ export function mountAgentRoleTool(ctx, listRoles) {
|
|
|
307
307
|
// The parameter keeps the host tool's name, shape and semantics: only an
|
|
308
308
|
// explicit `false` leaves the durable-child default for a foreground run.
|
|
309
309
|
const mode = args.run_in_background === false ? 'foreground' : 'continuable';
|
|
310
|
-
return executeAgentRole(host,
|
|
310
|
+
return executeAgentRole(host, entries, args.agent, args.prompt, exec.agent, {
|
|
311
311
|
...(args.provider === undefined ? {} : { provider: args.provider }),
|
|
312
312
|
...(args.model === undefined ? {} : { model: args.model }),
|
|
313
313
|
...(args.reasoning_effort === undefined ? {} : { reasoningEffort: args.reasoning_effort })
|
|
@@ -317,7 +317,13 @@ export function mountAgentRoleTool(ctx, listRoles) {
|
|
|
317
317
|
const disposeTool = host.tools.register(tool);
|
|
318
318
|
let disposeCatalog;
|
|
319
319
|
try {
|
|
320
|
-
disposeCatalog = mountSubagentCatalog(ctx, tool, async (agent, signal) =>
|
|
320
|
+
disposeCatalog = mountSubagentCatalog(ctx, tool, async (agent, signal) => {
|
|
321
|
+
const observation = roleSnapshot(await listRoles(agent));
|
|
322
|
+
return {
|
|
323
|
+
entries: await agentRoleCatalog(observation.entries, signal, message => ctx.logger?.warn(message), sessionCwd(agent)),
|
|
324
|
+
complete: observation.complete
|
|
325
|
+
};
|
|
326
|
+
});
|
|
321
327
|
}
|
|
322
328
|
catch (error) {
|
|
323
329
|
disposeTool();
|
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
/** Durable role catalogs follow DSH tool-skill's pre-step publication and session-surface recovery. */
|
|
2
2
|
import { createHash } from 'node:crypto';
|
|
3
3
|
import { createUserMessage } from '@deepseek-ai/dsh-llm';
|
|
4
|
-
/**
|
|
4
|
+
/** Normalize the two accepted provider shapes; a bare list means it read everything. */
|
|
5
|
+
function normalizeSnapshot(observation) {
|
|
6
|
+
return Array.isArray(observation) ? { entries: observation, complete: true } : observation;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Register after the exact tool definition; teardown removes guidance before execution.
|
|
10
|
+
*
|
|
11
|
+
* The snapshot callback follows the host skill registry's provider protocol: it may
|
|
12
|
+
* return the entries directly (meaning a complete read) or an explicit snapshot
|
|
13
|
+
* whose `complete` flag reports whether every source answered.
|
|
14
|
+
*/
|
|
5
15
|
export function mountSubagentCatalog(ctx, tool, snapshot, mode = 'subagent_role') {
|
|
6
16
|
const host = ctx;
|
|
7
17
|
let disposed = false;
|
|
@@ -10,9 +20,9 @@ export function mountSubagentCatalog(ctx, tool, snapshot, mode = 'subagent_role'
|
|
|
10
20
|
if (decision.kind === 'reject' || disposed)
|
|
11
21
|
return decision;
|
|
12
22
|
signal.throwIfAborted();
|
|
13
|
-
let
|
|
23
|
+
let observed;
|
|
14
24
|
try {
|
|
15
|
-
|
|
25
|
+
observed = normalizeSnapshot(host.tools.get(tool.name, agent) === tool ? await snapshot(agent, signal) : { entries: [], complete: true });
|
|
16
26
|
}
|
|
17
27
|
catch (error) {
|
|
18
28
|
signal.throwIfAborted();
|
|
@@ -22,6 +32,12 @@ export function mountSubagentCatalog(ctx, tool, snapshot, mode = 'subagent_role'
|
|
|
22
32
|
signal.throwIfAborted();
|
|
23
33
|
if (disposed)
|
|
24
34
|
return decision;
|
|
35
|
+
// A reader that could not enumerate every source publishes nothing: the
|
|
36
|
+
// previous catalog stays the model's authority until a complete read says
|
|
37
|
+
// otherwise, so a temporarily unreadable directory cannot shrink the list.
|
|
38
|
+
if (!observed.complete)
|
|
39
|
+
return decision;
|
|
40
|
+
let entries = [...observed.entries];
|
|
25
41
|
if (host.tools.get(tool.name, agent) !== tool)
|
|
26
42
|
entries = [];
|
|
27
43
|
const digest = digestEntries(entries);
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { resolveChildAgentOptions } from '@deepseek-ai/dsh-subagent';
|
|
2
2
|
import { defineTool } from '@deepseek-ai/dsh-tools';
|
|
3
|
-
import { agentRoleCatalog, requireCurrentRole, resolveAgentOptions, resolveRolePolicy, sessionCwd } from './agent-role-router.js';
|
|
3
|
+
import { agentRoleCatalog, requireCurrentRole, resolveAgentOptions, resolveRolePolicy, roleSnapshot, sessionCwd } from './agent-role-router.js';
|
|
4
4
|
import { mountSubagentCatalog } from './subagent-catalog.js';
|
|
5
5
|
import { TeammateRoleRuntime } from './teammate-role-runtime.js';
|
|
6
6
|
export const TEAMMATE_ROLE_TOOL_NAME = 'spawn_teammate_role';
|
|
7
7
|
/** Install the enhanced tool after its replay listener is ready; teardown drains owned role creations. */
|
|
8
8
|
export async function mountTeammateRoleTool(ctx, listRoles) {
|
|
9
9
|
const runtime = new TeammateRoleRuntime(ctx);
|
|
10
|
+
const entries = async (parent) => roleSnapshot(await listRoles(parent)).entries;
|
|
10
11
|
const cleanups = [];
|
|
11
12
|
try {
|
|
12
13
|
await runtime.restore();
|
|
@@ -48,7 +49,7 @@ export async function mountTeammateRoleTool(ctx, listRoles) {
|
|
|
48
49
|
exec.signal.throwIfAborted();
|
|
49
50
|
if (ctx.agentTeams.membership(parent).role !== 'lead')
|
|
50
51
|
throw new Error('only the Team Lead can create role teammates');
|
|
51
|
-
const { entry, policy } = await resolveRolePolicy(
|
|
52
|
+
const { entry, policy } = await resolveRolePolicy(entries, args.agent, parent);
|
|
52
53
|
const options = await resolveAgentOptions(policy, {
|
|
53
54
|
...(args.provider === undefined ? {} : { provider: args.provider }),
|
|
54
55
|
...(args.model === undefined ? {} : { model: args.model }),
|
|
@@ -60,7 +61,7 @@ export async function mountTeammateRoleTool(ctx, listRoles) {
|
|
|
60
61
|
throw new Error('role teammate requires an effective provider and model');
|
|
61
62
|
// The route lookup awaited the live LLM runtime; a role revoked during
|
|
62
63
|
// it must not become a Team member.
|
|
63
|
-
await requireCurrentRole(
|
|
64
|
+
await requireCurrentRole(entries, entry, parent);
|
|
64
65
|
exec.signal.throwIfAborted();
|
|
65
66
|
return runtime.spawn(parent, args, {
|
|
66
67
|
roleId: entry.name,
|
|
@@ -105,9 +106,15 @@ export async function mountTeammateRoleTool(ctx, listRoles) {
|
|
|
105
106
|
});
|
|
106
107
|
for (const agent of ctx.agents.list())
|
|
107
108
|
denyFor(agent);
|
|
108
|
-
cleanups.push(mountSubagentCatalog(ctx, tool, async (agent, signal) =>
|
|
109
|
-
|
|
110
|
-
|
|
109
|
+
cleanups.push(mountSubagentCatalog(ctx, tool, async (agent, signal) => {
|
|
110
|
+
if (ctx.agentTeams.tryMembership(agent)?.role !== 'lead')
|
|
111
|
+
return { entries: [], complete: true };
|
|
112
|
+
const observation = roleSnapshot(await listRoles(agent));
|
|
113
|
+
return {
|
|
114
|
+
entries: await agentRoleCatalog(observation.entries, signal, message => ctx.logger.warn(message), sessionCwd(agent)),
|
|
115
|
+
complete: observation.complete
|
|
116
|
+
};
|
|
117
|
+
}, 'spawn_teammate_role'));
|
|
111
118
|
return async () => {
|
|
112
119
|
for (const off of cleanups.splice(0).reverse())
|
|
113
120
|
off();
|
|
@@ -24,7 +24,10 @@ interface SessionExtensions {
|
|
|
24
24
|
invalidate(invalidateDefaultSkills: () => void): void;
|
|
25
25
|
refresh(): Promise<void> | undefined;
|
|
26
26
|
commandRegistrations(): ReturnType<ScopedExtensionContributors['registrations']>;
|
|
27
|
-
roles: (parent?: unknown) =>
|
|
27
|
+
roles: (parent?: unknown) => Promise<{
|
|
28
|
+
entries: Awaited<ReturnType<typeof projectAgentRoles>>;
|
|
29
|
+
complete: boolean;
|
|
30
|
+
}>;
|
|
28
31
|
session(): SuiteRouteSessionResolver | undefined;
|
|
29
32
|
}
|
|
30
33
|
/** The catalog reads the settings Hooks page needs. */
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a path is confirmed absent rather than unreadable.
|
|
3
|
+
*
|
|
4
|
+
* An error code alone cannot separate a removed entry from an unreadable
|
|
5
|
+
* source, because a platform can report `ENOENT` for a child of a file. The
|
|
6
|
+
* path ancestors answer the question instead: when the nearest existing
|
|
7
|
+
* ancestor is a directory, the entry is genuinely gone, and when it is not a
|
|
8
|
+
* directory, the source cannot be read and the caller must fail closed.
|
|
9
|
+
* @param path - the path to classify.
|
|
10
|
+
* @returns `true` only when the path is confirmed absent.
|
|
11
|
+
*/
|
|
12
|
+
export declare function isAbsentPath(path: string): Promise<boolean>;
|
|
@@ -166,4 +166,21 @@ export declare function executeAgentRole(host: AgentRoleHost, listRoles: (parent
|
|
|
166
166
|
* re-published whenever roles change, so guidance kept out of the catalog is
|
|
167
167
|
* sent once and stays readable through compaction.
|
|
168
168
|
*/
|
|
169
|
-
|
|
169
|
+
/**
|
|
170
|
+
* One observation of the parent-scoped role source.
|
|
171
|
+
*
|
|
172
|
+
* The complete flag is the discovery contract the host skill registry uses: a
|
|
173
|
+
* reader that could not enumerate every source reports an incomplete
|
|
174
|
+
* observation, and the catalog publisher never replaces a published list from
|
|
175
|
+
* one, because a failed read is not evidence that its roles were removed. A
|
|
176
|
+
* bare entry list is the older protocol and means the read completed.
|
|
177
|
+
*/
|
|
178
|
+
export interface AgentRoleSnapshot {
|
|
179
|
+
entries: AgentRoleEntry[];
|
|
180
|
+
complete: boolean;
|
|
181
|
+
}
|
|
182
|
+
/** A role reader answers with entries directly or with an explicit snapshot. */
|
|
183
|
+
export type AgentRoleObservation = AgentRoleEntry[] | AgentRoleSnapshot;
|
|
184
|
+
/** Normalize one observation; a bare list means the read completed. */
|
|
185
|
+
export declare function roleSnapshot(observation: AgentRoleObservation): AgentRoleSnapshot;
|
|
186
|
+
export declare function mountAgentRoleTool(ctx: Context, listRoles: (parent?: unknown) => Promise<AgentRoleObservation>): () => void;
|
|
@@ -51,10 +51,31 @@ export type CatalogStepListener = (payload: {
|
|
|
51
51
|
agent: CatalogAgent;
|
|
52
52
|
signal: AbortSignal;
|
|
53
53
|
}, next: () => Promise<CatalogStepDecision>) => Promise<CatalogStepDecision>;
|
|
54
|
-
/**
|
|
54
|
+
/**
|
|
55
|
+
* One observation of the roles a session can delegate to.
|
|
56
|
+
*
|
|
57
|
+
* The complete flag is the discovery contract the host skill registry already
|
|
58
|
+
* uses: an observation that could not read every source carries no authority to
|
|
59
|
+
* replace the published list, because a failed read is not evidence that its
|
|
60
|
+
* roles were removed. Only a complete observation may publish, including a
|
|
61
|
+
* complete observation that is genuinely empty.
|
|
62
|
+
*/
|
|
63
|
+
export interface SubagentCatalogSnapshot {
|
|
64
|
+
entries: readonly SubagentCatalogEntry[];
|
|
65
|
+
complete: boolean;
|
|
66
|
+
}
|
|
67
|
+
/** A snapshot, or a bare entry list, which the protocol treats as complete. */
|
|
68
|
+
export type SubagentCatalogObservation = SubagentCatalogEntry[] | SubagentCatalogSnapshot;
|
|
69
|
+
/**
|
|
70
|
+
* Register after the exact tool definition; teardown removes guidance before execution.
|
|
71
|
+
*
|
|
72
|
+
* The snapshot callback follows the host skill registry's provider protocol: it may
|
|
73
|
+
* return the entries directly (meaning a complete read) or an explicit snapshot
|
|
74
|
+
* whose `complete` flag reports whether every source answered.
|
|
75
|
+
*/
|
|
55
76
|
export declare function mountSubagentCatalog(ctx: Context, tool: {
|
|
56
77
|
name: string;
|
|
57
|
-
}, snapshot: (agent: CatalogAgent, signal: AbortSignal) => Promise<
|
|
78
|
+
}, snapshot: (agent: CatalogAgent, signal: AbortSignal) => Promise<SubagentCatalogObservation>, mode?: 'subagent_role' | 'spawn_teammate_role'): () => void;
|
|
58
79
|
/**
|
|
59
80
|
* Model-facing catalog text: the delegation triggers, then the role list, then
|
|
60
81
|
* the same guidance on first publication and on every update, so a replacement
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Role-aware creation is an additional Team entry point, not another member manager. */
|
|
2
2
|
import type { Context } from '@deepseek-ai/cordis';
|
|
3
|
-
import { type
|
|
3
|
+
import { type AgentRoleObservation } from './agent-role-router.js';
|
|
4
4
|
export declare const TEAMMATE_ROLE_TOOL_NAME = "spawn_teammate_role";
|
|
5
5
|
/** Install the enhanced tool after its replay listener is ready; teardown drains owned role creations. */
|
|
6
|
-
export declare function mountTeammateRoleTool(ctx: Context, listRoles: (parent?: unknown) => Promise<
|
|
6
|
+
export declare function mountTeammateRoleTool(ctx: Context, listRoles: (parent?: unknown) => Promise<AgentRoleObservation>): Promise<() => Promise<void>>;
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "dsh-agent-plugins-market",
|
|
3
3
|
"icon": "./assets/dsh-agent-plugins.png",
|
|
4
4
|
"description": "One-stop skills, subagent, MCP and LSP manager inside DeepSeek Harness (DSH), compatible with Claude Code, Codex, Cursor, Kimi and other agent plugin layouts.",
|
|
5
|
-
"version": "0.9.
|
|
5
|
+
"version": "0.9.2",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "lib/index.js",
|
|
8
8
|
"types": "lib/types/index.d.ts",
|
package/schemas/README.md
CHANGED
|
@@ -29,7 +29,7 @@ schemas/
|
|
|
29
29
|
|
|
30
30
|
## Dialect index
|
|
31
31
|
|
|
32
|
-
This table records **upstream client conventions**, including their own fallback orders; it does not define this plugin's discovery priority. DSH uses one shared layout order for suite manifests and Marketplace catalogs, shown
|
|
32
|
+
This table records **upstream client conventions**, including their own fallback orders; it does not define this plugin's discovery priority. DSH uses one shared layout order for suite manifests and Marketplace catalogs, shown on the [compatible plugins page](https://sivan757.github.io/dsh-agent-plugins-market/compatible-plugins/#shared-layout-precedence). Catalogs without a dedicated layout use root `marketplace.json` as the final fallback.
|
|
33
33
|
|
|
34
34
|
| Dialect | Upstream plugin manifest conventions | Upstream marketplace conventions | Upstream schema |
|
|
35
35
|
| --- | --- | --- | --- |
|