From c795996b5db551818f85d1deb605e856cfb6a422 Mon Sep 17 00:00:00 2001 From: turtle1999 Date: Mon, 28 Sep 2026 14:06:29 +0800 Subject: [PATCH 1/6] docs(agent-preset): merge plugin UI action and theme rules into cordis-plugin-development --- .../skills/cordis-plugin-development/SKILL.md | 7 +++-- .../references/practices.md | 2 ++ .../references/user-actions.md | 28 +++++++++++++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 packages/preset/agent-preset/skills/cordis-plugin-development/references/user-actions.md diff --git a/packages/preset/agent-preset/skills/cordis-plugin-development/SKILL.md b/packages/preset/agent-preset/skills/cordis-plugin-development/SKILL.md index def5d11e19..4b26280fb0 100644 --- a/packages/preset/agent-preset/skills/cordis-plugin-development/SKILL.md +++ b/packages/preset/agent-preset/skills/cordis-plugin-development/SKILL.md @@ -1,6 +1,6 @@ --- name: cordis-plugin-development -description: Use when adding, enabling, disabling, installing, configuring, or debugging a plugin, bundle, feature, page, panel, tool, or MCP connection in the current Harness profile, including a shipped plugin that is disabled by default, and for any visual object, decoration, or widget request that names no other destination, which means an installed UI plugin rendered in the Harness Web UI. +description: Use when designing, reviewing, adding, enabling, disabling, installing, configuring, or debugging a plugin, bundle, feature, page, panel, tool, or MCP connection in the current Harness profile, including a shipped plugin that is disabled by default, and for any visual object, decoration, or widget request that names no other destination, which means an installed UI plugin rendered in the Harness Web UI. --- # Persistent Harness plugins @@ -16,9 +16,9 @@ A shipped bundle can resolve a plugin row and leave it `disabled`. The row id an ## Deliver a working plugin first 1. Resolve the requested result and destination. An unspecified visual destination is the current Harness Web UI; a standalone image or HTML file does not complete such a request. Choose reasonable visual details and implement a small first version; install it before visual refinement. -2. Discover only the APIs needed for that version: `cordis_inspect_list`, then targeted `cordis_inspect_query` calls. For UI, query Client `Slots.listSubTree` and the selected slot's registration options and props. For anything beyond a static decoration, such as tool policy, agent context, session-derived state, or Chat rows, read `references/practices.md` before choosing the extension point. Once the chosen slot and registration API are known, write the plugin. +2. Discover only the APIs needed for that version: `cordis_inspect_list`, then targeted `cordis_inspect_query` calls. For UI, query Client `Slots.listSubTree` and the selected slot's registration options and props. For anything beyond a static decoration, such as tool policy, agent context, session-derived state, or Chat rows, read `references/practices.md` before choosing the extension point; for a user action in plugin UI, also read `references/user-actions.md`. Once the chosen slot and registration API are known, write the plugin. 3. Read the matching template under `templates/` with the file-read tool and write its copies into one workspace directory, or write the installable package, patch, and required Host/Client files there yourself. Check JavaScript syntax and the manifest, then install it. Before that first installation, do not create preview HTML, mock shells, design variants, screenshot scripts, or rasterizer tooling. Use the installed plugin itself as the first preview. -4. Read the installation result: its `application` and `warnings` fields decide whether the change is live, not server logs, terminal output, process lists, or the page's boot payload. Confirm new rows with `cordis_inspect_query`, which needs no approval, rather than paging `list_plugins`. After `application: applied`, exercise the capability or inspect the live Client registration. Use the connected page for visual verification when browser control is available. For a page or panel, also verify design consistency: styles use only theme tokens, the plugin imports no Harness Client package such as `@deepseek-ai/dsh-client-ui-primitives`, the console shows no slot entry crash, and the view reads correctly in light and dark themes beside a comparable host page. State any verification limitation explicitly; installation and slot registration alone do not establish what the user can see. +4. Read the installation result: its `application` and `warnings` fields decide whether the change is live, not server logs, terminal output, process lists, or the page's boot payload. Confirm new rows with `cordis_inspect_query`, which needs no approval, rather than paging `list_plugins`. After `application: applied`, exercise the capability or inspect the live Client registration. Use the connected page for visual verification when browser control is available. For a page or panel, also verify design consistency: styles use only theme tokens, the plugin imports no Harness Client package such as `@deepseek-ai/dsh-client-ui-primitives`, the console shows no slot entry crash, and the view reads correctly in light and dark themes beside a comparable host page. For a user action, run the checks in `references/user-actions.md`. Scale verification to the change's risk and reuse existing test tooling. Restore any user setting or state changed while testing. State any verification limitation explicitly; installation and slot registration alone do not establish what the user can see. 5. Fix observed defects in the same plugin. When the requested result works, finish with its location and verification status. Do not continue speculative visual variants, optional features, or a new mock preview. Close any task list you created. ## Knowledge sources, in order @@ -43,3 +43,4 @@ The files below live in this skill's base directory, which the `skill` tool repo | MCP bundle starting point, two files | `templates/mcp/package.json`, `templates/mcp/cordis.patch.yml` | | Loader patch dialect and the list of installable plugin packages | the `cordis-composition-reference` skill | | Choosing extension points, contexts, and state mechanisms for upgrade stability and performance | `references/practices.md` | +| Pairing each UI action with an agent tool and reporting its result to the agent | `references/user-actions.md` | diff --git a/packages/preset/agent-preset/skills/cordis-plugin-development/references/practices.md b/packages/preset/agent-preset/skills/cordis-plugin-development/references/practices.md index 9d7a393457..5709df87db 100644 --- a/packages/preset/agent-preset/skills/cordis-plugin-development/references/practices.md +++ b/packages/preset/agent-preset/skills/cordis-plugin-development/references/practices.md @@ -32,6 +32,8 @@ These rules follow from Harness mechanisms. Confirm every Service method, Event - Render plugin pages as React components in a slot. Do not serve an HTML page from the Host and embed it in an iframe: an iframe document does not receive the host's theme tokens, light/dark switching, or `ctx.locale`. - Style with the theme tokens that `cordis_inspect_query` `Theme` lists (`--dsw-alias-*`); literal colors are for artwork only. Tokens are the lowest-risk way to match the host: a renamed token degrades appearance but never breaks rendering. Copy spacing, type sizes, and row patterns from an existing host page of the same kind; the Plugin Manager page is the reference for management lists. +- Show status with semantic state tokens such as `--dsw-alias-state-error-primary`, keeping text in or on state colors readable in both themes. Match background, border, and hover layers to the slot the view renders in. +- In settings and management views, lead with the items the user configures; omit decoration and repeated structure. Expand details on demand, but keep an error summary visible. - Do not `require('@deepseek-ai/dsh-client-ui-primitives')` or load any other Harness Client package as a module; `dsh.client.inject` entries only order activation and stay allowed. They change without notice, a plain-JS plugin has no type check, and a throwing component blanks your slot entry (console: `slot entry crashed in ''`). Write your own controls and match the host instead: copy markup, CSS, and behavior from the primitive into the plugin (`src/*.tsx` and `*.module.css` in a DSH source checkout, or the installed package's `lib/index.js` and `lib/**/*.css`), or inspect the rendered host control in the connected page. Rename copied classes under your plugin's prefix, keep only `--dsw-alias-*` token references, and keep the behavior that users rely on, such as Modal focus and Escape handling, `role="switch"` with `aria-checked`, and Tooltip placement. Tokens then remain the only shared styling dependency. - Contribute through slots: `ctx.slots.inject(ownerKey, () => ctx.slots.register(...))`. The callback's registrations are disposed when the owning declaration collapses and reinstalled when it returns. Read session data through the slot props' selector hooks, subscribing to the smallest slice. Do not write DOM outside your component or append to `document.body`. - Add a Chat row by registering an event definition with `ctx.uiConversation.events.register()` and its view in the `conversation.chat.node` slot under the definition's `kind`, which is the renderer key; the Conversation layer owns paging, Turn and Step placement, and incremental assembly. diff --git a/packages/preset/agent-preset/skills/cordis-plugin-development/references/user-actions.md b/packages/preset/agent-preset/skills/cordis-plugin-development/references/user-actions.md new file mode 100644 index 0000000000..8e5278def3 --- /dev/null +++ b/packages/preset/agent-preset/skills/cordis-plugin-development/references/user-actions.md @@ -0,0 +1,28 @@ +# User actions and agent tools + +A user action in plugin UI, such as a button, toggle, slider, or form submission, changes state that the agent works with. The agent must be able to perform the same action and must learn when the user performed it. Confirm the Host entry points and tools you use with `cordis_inspect_query` before relying on them. + +## One operation, two callers + +1. Implement the operation once in Host code the plugin provides. It returns the result or an explicit status, and a failure carries its reason. +2. The UI action calls it through a Client-callable Host entry point found with inspection, such as a session command that `ctx.remote.commands.execute()` runs, and shows the returned failure. +3. Register one agent tool per action. The tool takes the same parameters, has the same meaning, calls the same operation, and returns its result as the tool result. +4. When the user performed the action, the UI path reports the state change, return value, or failure to the agent with `agent.inject()`, as a user message whose source names the plugin and states that the user made the change. The tool path does not inject: its tool result already reports the change. + +An action that grants or confirms authority, such as approving a tool call, answering a question the agent asked, or loosening a policy, stays user-only; the agent receives only its reported result. Every other user action has its tool. These designs leave the agent unaware of what the user did or unable to repeat it: + +- The UI action changes only Client state. +- The UI path and the tool carry separate logic, so their results drift apart. +- The user performs the action and nothing reports it to the agent. + +## Reporting results + +- Report with `agent.inject()`; its timing and waking behavior are in `references/practices.md`. Call `agent.steer()` only when the running turn must react at its next step, and `agent.followup()` only when the result must start its own turn. +- Coalesce continuously fired actions, such as slider drags, per-keystroke input, and bulk toggles, into one injection, for example by enforcing a minimum interval since the last injection. One injection per event fills the agent's context with redundant messages. +- Resolve the agent when the action runs; it can be disposed after the view rendered. When the agent is gone or `agent.inject()` throws, return the failure to the UI instead of dropping it. + +## Verification + +- Acting as the agent, perform the action through the tool alone and compare the result with the UI action. +- After the user performs the action, wake the agent and check that its next admitted step contains the reported result. +- Trigger the action repeatedly, by dragging, clicking, or bulk changes, and check that the agent receives one coalesced injection and is not woken for each event. From 68519237ac3f13f1d91c4c50fee27b6c475f2769 Mon Sep 17 00:00:00 2001 From: turtle1999 Date: Mon, 28 Sep 2026 14:12:43 +0800 Subject: [PATCH 2/6] docs(agent-preset): avoid automatic UI action context injection --- .../skills/cordis-plugin-development/SKILL.md | 2 +- .../references/user-actions.md | 23 +++++-------------- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/packages/preset/agent-preset/skills/cordis-plugin-development/SKILL.md b/packages/preset/agent-preset/skills/cordis-plugin-development/SKILL.md index 4b26280fb0..165f56edf9 100644 --- a/packages/preset/agent-preset/skills/cordis-plugin-development/SKILL.md +++ b/packages/preset/agent-preset/skills/cordis-plugin-development/SKILL.md @@ -43,4 +43,4 @@ The files below live in this skill's base directory, which the `skill` tool repo | MCP bundle starting point, two files | `templates/mcp/package.json`, `templates/mcp/cordis.patch.yml` | | Loader patch dialect and the list of installable plugin packages | the `cordis-composition-reference` skill | | Choosing extension points, contexts, and state mechanisms for upgrade stability and performance | `references/practices.md` | -| Pairing each UI action with an agent tool and reporting its result to the agent | `references/user-actions.md` | +| Sharing operations between UI actions and agent tools without automatic context injection | `references/user-actions.md` | diff --git a/packages/preset/agent-preset/skills/cordis-plugin-development/references/user-actions.md b/packages/preset/agent-preset/skills/cordis-plugin-development/references/user-actions.md index 8e5278def3..c0500c2259 100644 --- a/packages/preset/agent-preset/skills/cordis-plugin-development/references/user-actions.md +++ b/packages/preset/agent-preset/skills/cordis-plugin-development/references/user-actions.md @@ -1,28 +1,17 @@ # User actions and agent tools -A user action in plugin UI, such as a button, toggle, slider, or form submission, changes state that the agent works with. The agent must be able to perform the same action and must learn when the user performed it. Confirm the Host entry points and tools you use with `cordis_inspect_query` before relying on them. +The agent must be able to perform the same operations as the plugin UI. Confirm the Host entry points and tools you use with `cordis_inspect_query` before relying on them. ## One operation, two callers -1. Implement the operation once in Host code the plugin provides. It returns the result or an explicit status, and a failure carries its reason. +1. Implement the operation once as a Host service method. It returns the result or an explicit status, and a failure carries its reason. 2. The UI action calls it through a Client-callable Host entry point found with inspection, such as a session command that `ctx.remote.commands.execute()` runs, and shows the returned failure. -3. Register one agent tool per action. The tool takes the same parameters, has the same meaning, calls the same operation, and returns its result as the tool result. -4. When the user performed the action, the UI path reports the state change, return value, or failure to the agent with `agent.inject()`, as a user message whose source names the plugin and states that the user made the change. The tool path does not inject: its tool result already reports the change. +3. Register one agent tool per action. The tool takes the same parameters, has the same meaning, calls the same method, and returns its result as the tool result. -An action that grants or confirms authority, such as approving a tool call, answering a question the agent asked, or loosening a policy, stays user-only; the agent receives only its reported result. Every other user action has its tool. These designs leave the agent unaware of what the user did or unable to repeat it: +An action that grants or confirms authority, such as approving a tool call, answering a question the agent asked, or loosening a policy, stays user-only. Every other user action has its tool. Do not maintain separate operation logic in the UI and tool paths. -- The UI action changes only Client state. -- The UI path and the tool carry separate logic, so their results drift apart. -- The user performs the action and nothing reports it to the agent. - -## Reporting results - -- Report with `agent.inject()`; its timing and waking behavior are in `references/practices.md`. Call `agent.steer()` only when the running turn must react at its next step, and `agent.followup()` only when the result must start its own turn. -- Coalesce continuously fired actions, such as slider drags, per-keystroke input, and bulk toggles, into one injection, for example by enforcing a minimum interval since the last injection. One injection per event fills the agent's context with redundant messages. -- Resolve the agent when the action runs; it can be disposed after the view rendered. When the agent is gone or `agent.inject()` throws, return the failure to the UI instead of dropping it. +UI actions do not automatically inject results into agent context or wake the agent. Tool calls report through their tool results. ## Verification -- Acting as the agent, perform the action through the tool alone and compare the result with the UI action. -- After the user performs the action, wake the agent and check that its next admitted step contains the reported result. -- Trigger the action repeatedly, by dragging, clicking, or bulk changes, and check that the agent receives one coalesced injection and is not woken for each event. +For actions available to both callers, perform the action through the tool alone and compare its state changes, return values, and failures with the UI action. Verify that UI operations do not automatically inject operation reports or wake the agent. For user-only actions, verify that the agent cannot execute or authorize them. From 1f847565baabf559bb779318e27887da0ca139bc Mon Sep 17 00:00:00 2001 From: turtle1999 Date: Mon, 28 Sep 2026 15:06:17 +0800 Subject: [PATCH 3/6] docs(agent-preset): clarify plugin action and review guidance --- .../skills/cordis-plugin-development/SKILL.md | 10 +++++++--- .../cordis-plugin-development/references/practices.md | 2 -- .../cordis-plugin-development/references/ui-plugin.md | 6 ++++++ .../references/user-actions.md | 10 ++++------ 4 files changed, 17 insertions(+), 11 deletions(-) diff --git a/packages/preset/agent-preset/skills/cordis-plugin-development/SKILL.md b/packages/preset/agent-preset/skills/cordis-plugin-development/SKILL.md index 165f56edf9..d0909d04a4 100644 --- a/packages/preset/agent-preset/skills/cordis-plugin-development/SKILL.md +++ b/packages/preset/agent-preset/skills/cordis-plugin-development/SKILL.md @@ -5,10 +5,14 @@ description: Use when designing, reviewing, adding, enabling, disabling, install # Persistent Harness plugins -Use ordinary workspace files to author a bundle, then `plugin_manager` with `action: install_bundle` and the absolute package directory as `target` to install it in the current profile. Changes affect every session in that profile and survive restart. Load `editing-cordis-compositions` for agent preset changes. +For implementation, use ordinary workspace files to author a bundle, then `plugin_manager` with `action: install_bundle` and the absolute package directory as `target` to install it in the current profile. Changes affect every session in that profile and survive restart. Load `editing-cordis-compositions` for agent preset changes. Do not write the profile's `package.json` or `cordis.patch.yml`, create packages under `$DSH_HOME`, or run pnpm in the profile directory: `install_bundle` performs those steps, and each hand-made write outside the workspace needs its own approval. Every `plugin_manager` action, including `list_plugins` and `list_bundles`, also needs approval without Full access, so call it only when its result decides the next step. +## Design or review + +Read the applicable references below and inspect the proposed or existing plugin against current APIs. Report design choices or findings instead of following the installation workflow. Do not write files, install bundles, or change profile state unless the user requests implementation. + ## Enable a shipped plugin A shipped bundle can resolve a plugin row and leave it `disabled`. The row id and its reason are in the shipped patch, `packages/bundle/*/cordis.patch.yml` in a source checkout. Write a workspace bundle whose patch overrides that row with `disabled: false` and inserts the Host rows it depends on; a source checkout's `apps/cli/config/examples//cordis.yml` lists them for opt-in features. Packages shipped with dsh resolve from the dsh installation, so the bundle declares no dependencies on them. Install it with `install_bundle`. @@ -18,7 +22,7 @@ A shipped bundle can resolve a plugin row and leave it `disabled`. The row id an 1. Resolve the requested result and destination. An unspecified visual destination is the current Harness Web UI; a standalone image or HTML file does not complete such a request. Choose reasonable visual details and implement a small first version; install it before visual refinement. 2. Discover only the APIs needed for that version: `cordis_inspect_list`, then targeted `cordis_inspect_query` calls. For UI, query Client `Slots.listSubTree` and the selected slot's registration options and props. For anything beyond a static decoration, such as tool policy, agent context, session-derived state, or Chat rows, read `references/practices.md` before choosing the extension point; for a user action in plugin UI, also read `references/user-actions.md`. Once the chosen slot and registration API are known, write the plugin. 3. Read the matching template under `templates/` with the file-read tool and write its copies into one workspace directory, or write the installable package, patch, and required Host/Client files there yourself. Check JavaScript syntax and the manifest, then install it. Before that first installation, do not create preview HTML, mock shells, design variants, screenshot scripts, or rasterizer tooling. Use the installed plugin itself as the first preview. -4. Read the installation result: its `application` and `warnings` fields decide whether the change is live, not server logs, terminal output, process lists, or the page's boot payload. Confirm new rows with `cordis_inspect_query`, which needs no approval, rather than paging `list_plugins`. After `application: applied`, exercise the capability or inspect the live Client registration. Use the connected page for visual verification when browser control is available. For a page or panel, also verify design consistency: styles use only theme tokens, the plugin imports no Harness Client package such as `@deepseek-ai/dsh-client-ui-primitives`, the console shows no slot entry crash, and the view reads correctly in light and dark themes beside a comparable host page. For a user action, run the checks in `references/user-actions.md`. Scale verification to the change's risk and reuse existing test tooling. Restore any user setting or state changed while testing. State any verification limitation explicitly; installation and slot registration alone do not establish what the user can see. +4. Read the installation result: its `application` and `warnings` fields decide whether the change is live, not server logs, terminal output, process lists, or the page's boot payload. Confirm new rows with `cordis_inspect_query`, which needs no approval, rather than paging `list_plugins`. After `application: applied`, exercise the capability or inspect the live Client registration. Use the connected page for visual verification when browser control is available. For a page or panel, also verify design consistency: styles use only theme tokens, the plugin imports no Harness Client package such as `@deepseek-ai/dsh-client-ui-primitives`, the console shows no slot entry crash, and the view reads correctly in light and dark themes beside a comparable host page. For a user action, run the checks in `references/user-actions.md`. Scale verification to the change's risk; follow `references/verification.md` when browser control is unavailable. Restore any user setting or state changed while testing. State any verification limitation explicitly; installation and slot registration alone do not establish what the user can see. 5. Fix observed defects in the same plugin. When the requested result works, finish with its location and verification status. Do not continue speculative visual variants, optional features, or a new mock preview. Close any task list you created. ## Knowledge sources, in order @@ -43,4 +47,4 @@ The files below live in this skill's base directory, which the `skill` tool repo | MCP bundle starting point, two files | `templates/mcp/package.json`, `templates/mcp/cordis.patch.yml` | | Loader patch dialect and the list of installable plugin packages | the `cordis-composition-reference` skill | | Choosing extension points, contexts, and state mechanisms for upgrade stability and performance | `references/practices.md` | -| Sharing operations between UI actions and agent tools without automatic context injection | `references/user-actions.md` | +| Sharing application operations between UI actions and agent tools | `references/user-actions.md` | diff --git a/packages/preset/agent-preset/skills/cordis-plugin-development/references/practices.md b/packages/preset/agent-preset/skills/cordis-plugin-development/references/practices.md index 5709df87db..9d7a393457 100644 --- a/packages/preset/agent-preset/skills/cordis-plugin-development/references/practices.md +++ b/packages/preset/agent-preset/skills/cordis-plugin-development/references/practices.md @@ -32,8 +32,6 @@ These rules follow from Harness mechanisms. Confirm every Service method, Event - Render plugin pages as React components in a slot. Do not serve an HTML page from the Host and embed it in an iframe: an iframe document does not receive the host's theme tokens, light/dark switching, or `ctx.locale`. - Style with the theme tokens that `cordis_inspect_query` `Theme` lists (`--dsw-alias-*`); literal colors are for artwork only. Tokens are the lowest-risk way to match the host: a renamed token degrades appearance but never breaks rendering. Copy spacing, type sizes, and row patterns from an existing host page of the same kind; the Plugin Manager page is the reference for management lists. -- Show status with semantic state tokens such as `--dsw-alias-state-error-primary`, keeping text in or on state colors readable in both themes. Match background, border, and hover layers to the slot the view renders in. -- In settings and management views, lead with the items the user configures; omit decoration and repeated structure. Expand details on demand, but keep an error summary visible. - Do not `require('@deepseek-ai/dsh-client-ui-primitives')` or load any other Harness Client package as a module; `dsh.client.inject` entries only order activation and stay allowed. They change without notice, a plain-JS plugin has no type check, and a throwing component blanks your slot entry (console: `slot entry crashed in ''`). Write your own controls and match the host instead: copy markup, CSS, and behavior from the primitive into the plugin (`src/*.tsx` and `*.module.css` in a DSH source checkout, or the installed package's `lib/index.js` and `lib/**/*.css`), or inspect the rendered host control in the connected page. Rename copied classes under your plugin's prefix, keep only `--dsw-alias-*` token references, and keep the behavior that users rely on, such as Modal focus and Escape handling, `role="switch"` with `aria-checked`, and Tooltip placement. Tokens then remain the only shared styling dependency. - Contribute through slots: `ctx.slots.inject(ownerKey, () => ctx.slots.register(...))`. The callback's registrations are disposed when the owning declaration collapses and reinstalled when it returns. Read session data through the slot props' selector hooks, subscribing to the smallest slice. Do not write DOM outside your component or append to `document.body`. - Add a Chat row by registering an event definition with `ctx.uiConversation.events.register()` and its view in the `conversation.chat.node` slot under the definition's `kind`, which is the renderer key; the Conversation layer owns paging, Turn and Step placement, and incremental assembly. diff --git a/packages/preset/agent-preset/skills/cordis-plugin-development/references/ui-plugin.md b/packages/preset/agent-preset/skills/cordis-plugin-development/references/ui-plugin.md index d647923d75..666dc4e5f4 100644 --- a/packages/preset/agent-preset/skills/cordis-plugin-development/references/ui-plugin.md +++ b/packages/preset/agent-preset/skills/cordis-plugin-development/references/ui-plugin.md @@ -4,6 +4,12 @@ Read `templates/decoration/` with the file-read tool and write its files into yo `index.js` exports `export function apply() {}`; the patch inserts one row named after the package. For a simple drawing, prefer a slot with allocated space, such as `conversation.composer.dock` when available. Keep the first version within that slot's flow; do not plan a motion path around host controls. Use `shell.overlay` only when the request needs an overlay and its placement is known. +## Visual design + +- Show status with semantic tokens such as `--dsw-alias-state-error-primary`. Check text contrast against its background in light and dark themes. +- Match background and border tokens to the component's container and nesting depth; choose hover tokens for the actual control rather than treating every slot as the same background. +- In settings and management views, lead with configurable items and avoid repeated structure and unnecessary decoration. Expand details on demand, but keep an error summary visible. + ## Client module The browser artifact registers a lazy factory whose id equals the package name. React comes from the browser module table; no duplicate React installation, CDN script, or UMD search is needed. For compiled sources, use the deployment's Client build tooling to emit this format; declare non-baseline runtime imports in `dsh.client.external`. diff --git a/packages/preset/agent-preset/skills/cordis-plugin-development/references/user-actions.md b/packages/preset/agent-preset/skills/cordis-plugin-development/references/user-actions.md index c0500c2259..8b0e00c986 100644 --- a/packages/preset/agent-preset/skills/cordis-plugin-development/references/user-actions.md +++ b/packages/preset/agent-preset/skills/cordis-plugin-development/references/user-actions.md @@ -1,17 +1,15 @@ # User actions and agent tools -The agent must be able to perform the same operations as the plugin UI. Confirm the Host entry points and tools you use with `cordis_inspect_query` before relying on them. +Expose the plugin UI's operations on application data and configuration to the agent. Pure view interactions, such as switching tabs or expanding details, do not need tools. Confirm the Host entry points and tools you use with `cordis_inspect_query` before relying on them. ## One operation, two callers 1. Implement the operation once as a Host service method. It returns the result or an explicit status, and a failure carries its reason. 2. The UI action calls it through a Client-callable Host entry point found with inspection, such as a session command that `ctx.remote.commands.execute()` runs, and shows the returned failure. -3. Register one agent tool per action. The tool takes the same parameters, has the same meaning, calls the same method, and returns its result as the tool result. +3. Expose the operation through an agent tool with matching parameters and meaning. Related operations may share a tool with an `action` parameter. The tool calls the same method and returns its result as the tool result. -An action that grants or confirms authority, such as approving a tool call, answering a question the agent asked, or loosening a policy, stays user-only. Every other user action has its tool. Do not maintain separate operation logic in the UI and tool paths. - -UI actions do not automatically inject results into agent context or wake the agent. Tool calls report through their tool results. +An action that grants or confirms authority, such as approving a tool call, answering a question the agent asked, or loosening a policy, stays user-only. Do not maintain separate operation logic in the UI and tool paths. ## Verification -For actions available to both callers, perform the action through the tool alone and compare its state changes, return values, and failures with the UI action. Verify that UI operations do not automatically inject operation reports or wake the agent. For user-only actions, verify that the agent cannot execute or authorize them. +For operations available to both callers, perform the operation through the tool alone and compare its state changes, return values, and failures with the UI action. For user-only actions, verify that the agent cannot execute or authorize them. From 8931fa27487716a5bd00344acd88e95465438b68 Mon Sep 17 00:00:00 2001 From: turtle1999 Date: Mon, 28 Sep 2026 14:58:50 +0800 Subject: [PATCH 4/6] feat(agent-preset): share agent experience skill with creator mode --- .agents/skills/agent-experience/SKILL.md | 22 +---------- packages/preset/agent-preset/README.i18n.yaml | 8 ++-- packages/preset/agent-preset/README.md | 5 ++- packages/preset/agent-preset/README.zh.md | 5 ++- packages/preset/agent-preset/package.json | 1 + .../skills/agent-experience/SKILL.md | 21 ++++++++++ .../preset/agent-preset/tests/skills.spec.ts | 39 +++++++++++++++++-- pnpm-lock.yaml | 3 ++ 8 files changed, 74 insertions(+), 30 deletions(-) mode change 100644 => 120000 .agents/skills/agent-experience/SKILL.md create mode 100644 packages/preset/agent-preset/skills/agent-experience/SKILL.md diff --git a/.agents/skills/agent-experience/SKILL.md b/.agents/skills/agent-experience/SKILL.md deleted file mode 100644 index 3ad20ad5cb..0000000000 --- a/.agents/skills/agent-experience/SKILL.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -name: agent-experience -description: Use when writing or changing a model-facing tool definition (name, description, parameter schema, or its system-prompt section), and when designing skills, context loading, or multi-step workflows, to make information discoverable and use context efficiently. -metadata: - date: "2026-09-11" ---- - -- **Start with minimal context:** expose purpose, available actions, and constraints first; load detailed instructions when needed. -- **Make discovery explicit:** every deferred resource needs a clear description and a reliable way to retrieve it. -- **Keep critical constraints visible:** permissions, destructive effects, and required validation should appear before the relevant action. -- **Prefer bounded outputs:** return concise results with identifiers or paths for retrieving details; avoid dumping entire logs or documents. -- **Use locality:** include a bounded amount of likely needed adjacent context with an operation’s result. For example, deliver a thread reply with a few preceding messages. Mark omissions and truncation explicitly, and provide a way to retrieve more. -- **Evaluate total work:** saving context is useful only if it does not cause more searches, repeated reads, or mistakes. - -## Tool definitions - -- **Delete obvious constraints.** Omit rules the model learns from the call result, such as a missing file failing to read or a failed send not being delivered. -- **Describe behavior, not implementation.** State what the tool does and returns; omit internal mechanisms, output markers the model sees in results, and enforcement details. -- **Put parameter rules on the parameter.** Defaults, ranges, pairing, and when-to-set rules belong in that parameter's description or schema; a description that varies with configuration usually means the varying part belongs to a parameter. -- **Say each fact once.** Do not repeat the tool definition in its system-prompt section, a parameter description in the tool description, or one tool's rules in another tool. -- **Measure the change.** Compare first-turn prompt tokens before and after a tool-definition change. diff --git a/.agents/skills/agent-experience/SKILL.md b/.agents/skills/agent-experience/SKILL.md new file mode 120000 index 0000000000..fb40f7ffce --- /dev/null +++ b/.agents/skills/agent-experience/SKILL.md @@ -0,0 +1 @@ +../../../packages/preset/agent-preset/skills/agent-experience/SKILL.md \ No newline at end of file diff --git a/packages/preset/agent-preset/README.i18n.yaml b/packages/preset/agent-preset/README.i18n.yaml index df88f455fb..8742b7ef45 100644 --- a/packages/preset/agent-preset/README.i18n.yaml +++ b/packages/preset/agent-preset/README.i18n.yaml @@ -15,8 +15,8 @@ en: d152484eb41ac6b4 zh: b3ad7867f23dad1c /deepseek-ai-dsh-agent-preset/use-this-package: - en: a403abbf4d126f04 - zh: d8d1d643e789cd1f + en: 3e243b0ee04dd23f + zh: 832841c35b57180a /deepseek-ai-dsh-agent-preset/understand-the-implementation: en: 7ac55a3a3af4fcef zh: 95fe36abba794967 @@ -30,8 +30,8 @@ en: 4644bd5f0c865667 zh: 9aedc8ac43fb8b61 /deepseek-ai-dsh-agent-preset/known-limitations-and-deferred-work: - en: d4dbce86236e8e91 - zh: 11766aef5d0ff536 + en: 4546a11627bbbca1 + zh: eaa260cdfe37e31f /deepseek-ai-dsh-agent-preset/known-limitations-and-deferred-work/dev-note: en: af1f8da6d3acb3e2 zh: e0c4f6afeefd5214 diff --git a/packages/preset/agent-preset/README.md b/packages/preset/agent-preset/README.md index 99802e2592..407200ace1 100644 --- a/packages/preset/agent-preset/README.md +++ b/packages/preset/agent-preset/README.md @@ -47,7 +47,9 @@ Define an Agent’s child plugins in ordinary Cordis YAML. Declare several prese The declaration row’s `id` addresses Loader edits; `config.id` is the preset identity saved by sessions. Child entry IDs may be omitted and assigned by Loader. -The package also ships the `skills/` directory that creator mode mounts through `skill-filesystem`: `cordis-plugin-development` (a short procedure with `references/` read on demand and copyable `templates/` bundles), `editing-cordis-compositions`, and `cordis-composition-reference`, whose `references/packages.md` is generated by `scripts/gen-plugin-packages.ts` and freshness-gated in `doc-sync`. The two procedure skills tell the agent to read inspection results first, then the package README under the `packageDir` that `Config.listConfigs` reports, then built `lib/` or checkout sources. Every shipped `SKILL.md`, rendered as a `skill` tool result, stays under the 8192-character threshold above which the standard preset's tool-result pruner trims results. +The package also ships the `skills/` directory that creator mode mounts through `skill-filesystem`: `agent-experience` (tool descriptions and efficient context loading), `cordis-plugin-development` (a short procedure with `references/` read on demand and copyable `templates/` bundles), `editing-cordis-compositions`, and `cordis-composition-reference`, whose `references/packages.md` is generated by `scripts/gen-plugin-packages.ts` and freshness-gated in `doc-sync`. The two procedure skills tell the agent to read inspection results first, then the package README under the `packageDir` that `Config.listConfigs` reports, then built `lib/` or checkout sources. Every shipped `SKILL.md`, rendered as a `skill` tool result, stays under the 8192-character threshold above which the standard preset's tool-result pruner trims results. + +Edit `agent-experience` in [skills/agent-experience/SKILL.md](skills/agent-experience/SKILL.md). The repository discovery path, `.agents/skills/agent-experience/SKILL.md`, is a relative symbolic link to this file; the published package contains the regular file. ## Understand the implementation @@ -80,6 +82,7 @@ A live Agent’s composition stays stable; new Agents can use an updated definit - Requires the `agentPresets` service. Duplicate preset IDs fail declaration loading. Declarations provide no directory, file-copy or file-delete operations. +- Repository discovery of `agent-experience` requires a checkout with symbolic links enabled. With `core.symlinks=false`, Git writes the link target as plain text, not a skill. Creator mode uses the regular file in the package and does not depend on that alias. ### Dev Note diff --git a/packages/preset/agent-preset/README.zh.md b/packages/preset/agent-preset/README.zh.md index 1130b015a8..32e3b0dbd2 100644 --- a/packages/preset/agent-preset/README.zh.md +++ b/packages/preset/agent-preset/README.zh.md @@ -47,7 +47,9 @@ kind: "package-reference" 声明行的 `id` 是 Loader 编辑地址;`config.id` 是会话保存的 preset 标识符。子插件可省略行 ID,由 Loader 分配。 -本包还随包出货创造模式通过 `skill-filesystem` 挂载的 `skills/` 目录:`cordis-plugin-development`(简短流程,配合按需读取的 `references/` 与可复制的 `templates/` 组合包)、`editing-cordis-compositions`,以及 `cordis-composition-reference`,后者的 `references/packages.md` 由 `scripts/gen-plugin-packages.ts` 生成并在 `doc-sync` 中做新鲜度门禁。两个流程 skill 让 agent 先读检查结果,再读 `Config.listConfigs` 报告的 `packageDir` 下的包 README,最后读构建后的 `lib/` 或 checkout 源码。每个出货的 `SKILL.md` 作为 `skill` 工具结果渲染后都保持在 8192 字符阈值之下,标准 preset 的工具结果修剪器超过该阈值才会裁剪。 +本包还随包出货创造模式通过 `skill-filesystem` 挂载的 `skills/` 目录:`agent-experience`(工具描述与高效上下文加载)、`cordis-plugin-development`(简短流程,配合按需读取的 `references/` 与可复制的 `templates/` 组合包)、`editing-cordis-compositions`,以及 `cordis-composition-reference`,后者的 `references/packages.md` 由 `scripts/gen-plugin-packages.ts` 生成并在 `doc-sync` 中做新鲜度门禁。两个流程 skill 让 agent 先读检查结果,再读 `Config.listConfigs` 报告的 `packageDir` 下的包 README,最后读构建后的 `lib/` 或 checkout 源码。每个出货的 `SKILL.md` 作为 `skill` 工具结果渲染后都保持在 8192 字符阈值之下,标准 preset 的工具结果修剪器超过该阈值才会裁剪。 + +在 [skills/agent-experience/SKILL.md](skills/agent-experience/SKILL.md) 编辑 `agent-experience`。仓库发现路径 `.agents/skills/agent-experience/SKILL.md` 是指向该文件的相对符号链接;发布包包含普通文件。 ## 理解实现 @@ -80,6 +82,7 @@ kind: "package-reference" - 需要 `agentPresets` 服务。重复的 preset ID 会导致声明加载失败。声明不提供目录、文件复制或文件删除操作。 +- 从仓库发现 `agent-experience` 要求 checkout 启用符号链接。设置 `core.symlinks=false` 时,Git 会将链接目标写成纯文本,而不是 skill。创造模式使用包内的普通文件,不依赖该别名。 ### 开发备注 diff --git a/packages/preset/agent-preset/package.json b/packages/preset/agent-preset/package.json index 5c6acf9fb2..3ce3697829 100644 --- a/packages/preset/agent-preset/package.json +++ b/packages/preset/agent-preset/package.json @@ -42,6 +42,7 @@ "@deepseek-ai/dsh-agent-preset-registry": "workspace:*", "@deepseek-ai/dsh-compaction-tool-result-pruner": "workspace:*", "@deepseek-ai/dsh-skill": "workspace:*", + "@deepseek-ai/dsh-skill-filesystem": "workspace:*", "@deepseek-ai/schemastery": "workspace:~", "@types/js-yaml": "^4.0.9", "js-yaml": "^4.2.0" diff --git a/packages/preset/agent-preset/skills/agent-experience/SKILL.md b/packages/preset/agent-preset/skills/agent-experience/SKILL.md new file mode 100644 index 0000000000..3ad20ad5cb --- /dev/null +++ b/packages/preset/agent-preset/skills/agent-experience/SKILL.md @@ -0,0 +1,21 @@ +--- +name: agent-experience +description: Use when writing or changing a model-facing tool definition (name, description, parameter schema, or its system-prompt section), and when designing skills, context loading, or multi-step workflows, to make information discoverable and use context efficiently. +metadata: + date: "2026-09-11" +--- + +- **Start with minimal context:** expose purpose, available actions, and constraints first; load detailed instructions when needed. +- **Make discovery explicit:** every deferred resource needs a clear description and a reliable way to retrieve it. +- **Keep critical constraints visible:** permissions, destructive effects, and required validation should appear before the relevant action. +- **Prefer bounded outputs:** return concise results with identifiers or paths for retrieving details; avoid dumping entire logs or documents. +- **Use locality:** include a bounded amount of likely needed adjacent context with an operation’s result. For example, deliver a thread reply with a few preceding messages. Mark omissions and truncation explicitly, and provide a way to retrieve more. +- **Evaluate total work:** saving context is useful only if it does not cause more searches, repeated reads, or mistakes. + +## Tool definitions + +- **Delete obvious constraints.** Omit rules the model learns from the call result, such as a missing file failing to read or a failed send not being delivered. +- **Describe behavior, not implementation.** State what the tool does and returns; omit internal mechanisms, output markers the model sees in results, and enforcement details. +- **Put parameter rules on the parameter.** Defaults, ranges, pairing, and when-to-set rules belong in that parameter's description or schema; a description that varies with configuration usually means the varying part belongs to a parameter. +- **Say each fact once.** Do not repeat the tool definition in its system-prompt section, a parameter description in the tool description, or one tool's rules in another tool. +- **Measure the change.** Compare first-turn prompt tokens before and after a tool-definition change. diff --git a/packages/preset/agent-preset/tests/skills.spec.ts b/packages/preset/agent-preset/tests/skills.spec.ts index 1e93f0b564..ff04a5a3f1 100644 --- a/packages/preset/agent-preset/tests/skills.spec.ts +++ b/packages/preset/agent-preset/tests/skills.spec.ts @@ -3,13 +3,15 @@ * files exist, templates parse, and no skill bans reading DSH sources. */ import { execFileSync } from 'node:child_process' -import { readdirSync, readFileSync, statSync } from 'node:fs' -import { join } from 'node:path' +import { lstatSync, readdirSync, readFileSync, readlinkSync, realpathSync, statSync } from 'node:fs' +import { dirname, join, resolve } from 'node:path' +import { Context } from '@deepseek-ai/cordis' import { fileURLToPath } from 'node:url' import * as yaml from 'js-yaml' import { entryListSchema } from '@deepseek-ai/cordis-plugin-include' import { codePointLength } from '@deepseek-ai/dsh-compaction-tool-result-pruner' -import { renderSkillContent } from '@deepseek-ai/dsh-skill' +import SkillRegistry, { renderSkillContent } from '@deepseek-ai/dsh-skill' +import * as SkillFileSystem from '@deepseek-ai/dsh-skill-filesystem' import { describe, expect, it } from 'vitest' const skills = fileURLToPath(new URL('../skills/', import.meta.url)) @@ -35,6 +37,37 @@ function markdownFiles(dir: string): string[] { } describe('the shipped creator skills', () => { + const repositorySkills = fileURLToPath(new URL('../../../../.agents/skills/', import.meta.url)) + const alias = join(repositorySkills, 'agent-experience/SKILL.md') + const canonical = join(skills, 'agent-experience/SKILL.md') + + it('keeps agent-experience in the package with a repository alias, not a second copy', () => { + expect(names).toContain('agent-experience') + expect(lstatSync(canonical).isFile()).toBe(true) + const linked = lstatSync(alias).isSymbolicLink() + // Git can materialize link targets as plain files on Windows with core.symlinks=false. + if (!linked) expect(process.platform).toBe('win32') + const target = linked ? readlinkSync(alias) : readFileSync(alias, 'utf8').trim() + expect(resolve(dirname(alias), target)).toBe(canonical) + }) + + it.for(['package', 'repository'] as const)('loads agent-experience from the %s skill root', async (source, test) => { + if (source === 'repository' && process.platform === 'win32' && !lstatSync(alias).isSymbolicLink()) { + test.skip(true, 'Repository discovery requires a checkout with symbolic links enabled.') + } + const ctx = new Context() + test.onTestFinished(() => ctx.fiber.dispose()) + await ctx.plugin(SkillRegistry) + await ctx.plugin(SkillFileSystem, { + includeDefaultRoots: false, watch: false, + customSkillDirs: [source === 'package' ? skills : repositorySkills], + }) + expect((await ctx.skills.list()).map(skill => skill.name)).toContain('agent-experience') + const loaded = await ctx.skills.get('agent-experience') + expect(loaded?.path).toBe(realpathSync(canonical)) + expect(loaded?.content).toBe(body('agent-experience').trim()) + }) + it('render below the pruner threshold and name only files that exist', () => { for (const name of names) { const rendered = renderSkillContent({ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c667b3b788..7e988883ad 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10025,6 +10025,9 @@ importers: '@deepseek-ai/dsh-skill': specifier: workspace:* version: link:../../skill/skill + '@deepseek-ai/dsh-skill-filesystem': + specifier: workspace:* + version: link:../../skill/skill-filesystem '@types/js-yaml': specifier: ^4.0.9 version: 4.0.9 From 3879d819104d751bba9c6d68c33d87cbb8ce9054 Mon Sep 17 00:00:00 2001 From: turtle1999 Date: Mon, 28 Sep 2026 15:25:50 +0800 Subject: [PATCH 5/6] docs(agent-experience): remove date metadata --- packages/preset/agent-preset/skills/agent-experience/SKILL.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/preset/agent-preset/skills/agent-experience/SKILL.md b/packages/preset/agent-preset/skills/agent-experience/SKILL.md index 3ad20ad5cb..0d12d9c301 100644 --- a/packages/preset/agent-preset/skills/agent-experience/SKILL.md +++ b/packages/preset/agent-preset/skills/agent-experience/SKILL.md @@ -1,8 +1,6 @@ --- name: agent-experience description: Use when writing or changing a model-facing tool definition (name, description, parameter schema, or its system-prompt section), and when designing skills, context loading, or multi-step workflows, to make information discoverable and use context efficiently. -metadata: - date: "2026-09-11" --- - **Start with minimal context:** expose purpose, available actions, and constraints first; load detailed instructions when needed. From b1f5f5c171b93ce2c891040f59f97668a212f765 Mon Sep 17 00:00:00 2001 From: turtle1999 Date: Mon, 28 Sep 2026 15:29:43 +0800 Subject: [PATCH 6/6] docs(agent-preset): remove visual design section --- .../cordis-plugin-development/references/ui-plugin.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/preset/agent-preset/skills/cordis-plugin-development/references/ui-plugin.md b/packages/preset/agent-preset/skills/cordis-plugin-development/references/ui-plugin.md index 666dc4e5f4..d647923d75 100644 --- a/packages/preset/agent-preset/skills/cordis-plugin-development/references/ui-plugin.md +++ b/packages/preset/agent-preset/skills/cordis-plugin-development/references/ui-plugin.md @@ -4,12 +4,6 @@ Read `templates/decoration/` with the file-read tool and write its files into yo `index.js` exports `export function apply() {}`; the patch inserts one row named after the package. For a simple drawing, prefer a slot with allocated space, such as `conversation.composer.dock` when available. Keep the first version within that slot's flow; do not plan a motion path around host controls. Use `shell.overlay` only when the request needs an overlay and its placement is known. -## Visual design - -- Show status with semantic tokens such as `--dsw-alias-state-error-primary`. Check text contrast against its background in light and dark themes. -- Match background and border tokens to the component's container and nesting depth; choose hover tokens for the actual control rather than treating every slot as the same background. -- In settings and management views, lead with configurable items and avoid repeated structure and unnecessary decoration. Expand details on demand, but keep an error summary visible. - ## Client module The browser artifact registers a lazy factory whose id equals the package name. React comes from the browser module table; no duplicate React installation, CDN script, or UMD search is needed. For compiled sources, use the deployment's Client build tooling to emit this format; declare non-baseline runtime imports in `dsh.client.external`.