docs(agent-preset): merge plugin UI action and theme rules into cordis-plugin-development
This commit is contained in:
1 parent
5c6427bd76
commit
c795996b5d
3 files changed
+34
-3
No files matched your search
@@ -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` |
|
||||
@@ -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 '<slot>'`). 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.
|
||||
|
||||
+28
@@ -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.
|
||||
Reference in new issue
Block a user