From 991385def827211065547e1544f6a85b33c5e87c Mon Sep 17 00:00:00 2001 From: womeimingzi11 Date: Thu, 1 Oct 2026 22:51:16 +0800 Subject: [PATCH 1/2] fix(client): register the browser half with the module loader `lib/client.js` shipped as verbatim `tsc` ESM output: top-level `import` / `export` bindings and no `window.__ModuleLoader__.load({ id, factory })` call. The host's client module system (`@deepseek-ai/dsh-client-modules`) is a lazy CJS table whose only acceptance test is that registration, so the bundle executed, registered nothing, and the Plugins page reported client-modules: could not load "@perrylink/dsh-github": ... : loaded without registering "@perrylink/dsh-github" via __ModuleLoader__.load The host half was unaffected and kept its tools registered throughout. - `scripts/build-client.mjs` rewrites the compiled bundle into the loader's factory: `import ... from 'm'` becomes `require('m')`, each top-level `export` declaration loses its keyword and gains an `exports.` line, and the body is wrapped. It fails loud on any shape it cannot transform and is a no-op on an already-wrapped bundle, so both `build` and `prepare` call it. Original line order is preserved and the shipped source map is shifted by the wrapper's line count, so it stays aligned. - `dsh.client.inject` gains the two modules the bundle actually requires (`react`, `@deepseek-ai/dsh-client-ui-primitives`), neither of which was declared. - `scripts/verify-artifacts.mjs` executed only the host face; it now also runs the shipped client bundle against a stub `__ModuleLoader__` and asserts registration, materialization and the absence of top-level ESM. - `test/client-bundle-contract.test.ts` asserts the same contract as a unit test. Declares and tests the DSH 0.2 host line in the same change, because this fix is what makes the browser half work there: the `@deepseek-ai/dsh-*` peer union and `engines.dsh` gain `|| >=0.2.0-rc.1 <0.3.0-0`, `dshWorkshop.compatibility. dshVersions` records `0.2.0-rc.2`, the five READMEs follow, and the Compat workflow's profile job now runs both ends of the band instead of one pin. Verified on `0.2.0-rc.2`: the batch bundle the Plugins page requests (`/plugins/??...,@perrylink/dsh-github/client.js,...`) serves and executes to seven registered modules with this row among them, the single-row fallback URL registers the same row, and `pnpm test` reports 189 passed / 3 skipped. --- .github/workflows/compat.yml | 12 +- CHANGELOG.md | 25 ++ README-es.md | 2 +- README-hi.md | 2 +- README-pt.md | 2 +- README-zh.md | 2 +- README.md | 2 +- lib/client.js | 601 ++++++++++++++-------------- lib/client.js.map | 2 +- package.json | 36 +- scripts/build-client.mjs | 196 +++++++++ scripts/prepare.mjs | 18 +- scripts/verify-artifacts.mjs | 40 +- test/client-bundle-contract.test.ts | 105 +++++ 14 files changed, 726 insertions(+), 319 deletions(-) create mode 100644 scripts/build-client.mjs create mode 100644 test/client-bundle-contract.test.ts diff --git a/.github/workflows/compat.yml b/.github/workflows/compat.yml index d5d275f..d1a1587 100644 --- a/.github/workflows/compat.yml +++ b/.github/workflows/compat.yml @@ -63,6 +63,14 @@ jobs: profile: runs-on: ubuntu-latest timeout-minutes: 25 + strategy: + fail-fast: false + matrix: + # Both ends of the declared band: the oldest line still supported and + # the current one. A range is what the manifest accepts, not what CI + # has exercised, so both are run. + dsh: ['0.1.7-rc.2', '0.2.0-rc.2'] + name: profile (${{ matrix.dsh }}) steps: - uses: actions/checkout@v5 @@ -83,7 +91,7 @@ jobs: pnpm run build pnpm pack --pack-destination "$RUNNER_TEMP" - name: Install dsh CLI - run: npm install -g @deepseek-ai/dsh@0.1.7-rc.2 + run: npm install -g @deepseek-ai/dsh@${{ matrix.dsh }} - name: Install into a scratch profile (builds allowlisted) run: | @@ -104,7 +112,7 @@ jobs: protobufjs: true '@google/genai': true YAML - dsh plugin --profile compat add '@deepseek-ai/dsh-base@0.1.7-rc.2' '@deepseek-ai/dsh-headless@0.1.7-rc.2' "$TARBALL" + dsh plugin --profile compat add "@deepseek-ai/dsh-base@${{ matrix.dsh }}" "@deepseek-ai/dsh-headless@${{ matrix.dsh }}" "$TARBALL" - name: Row-mount assertion run: | diff --git a/CHANGELOG.md b/CHANGELOG.md index 011cd63..03cb78c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,31 @@ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +## [0.8.0] - 2026-10-01 + +### Added + +- **DeepSeek Harness `0.2` support.** The declared host ranges (`engines.dsh` and the `@deepseek-ai/dsh-*` `peerDependencies` union) gain `|| >=0.2.0-rc.1 <0.3.0-0`, `dshWorkshop.compatibility.dshVersions` records `0.2.0-rc.2`, and the Compat workflow's profile job now runs both ends of the range (`0.1.7-rc.2` and `0.2.0-rc.2`) instead of a single pin. + +### Fixed + +- **The browser half never registered with the client module loader, so the Plugins page reported the plugin as failed to sync.** `lib/client.js` shipped as verbatim `tsc` ESM output — top-level `import`/`export` bindings and no `window.__ModuleLoader__.load({ id, factory })` call. The host's client module system (`@deepseek-ai/dsh-client-modules`) is a lazy CJS table whose only acceptance test is that registration, so the bundle executed, registered nothing, and the page surfaced + + ``` + client-modules: could not load "@perrylink/dsh-github": … : + loaded without registering "@perrylink/dsh-github" via __ModuleLoader__.load + ``` + + The host half was unaffected and kept its tools registered throughout. `scripts/build-client.mjs` now rewrites the compiled bundle in place: `import … from 'm'` becomes `require('m')`, each top-level `export` declaration loses its keyword and gains an `exports. = ` line, and the body is wrapped in the loader's factory. It is wired into both `build` and `prepare`, fails loud on any shape it cannot transform, and is a no-op on an already-wrapped bundle. Original line order is preserved and the shipped `lib/client.js.map` is shifted by the wrapper's line count, so it stays aligned. + + The same acceptance test and the same message are present in `@deepseek-ai/dsh-client-modules@0.1.7-rc.2`, so this is a defect in how the artifact is built rather than a `0.2`-only regression; worth confirming whether the committed bundle ever registered on the older line. + +- **`dsh.client.inject` omitted two modules the browser half requires.** `src/client.ts` imports `react` and `@deepseek-ai/dsh-client-ui-primitives`, and neither was declared, so the module graph did not guarantee they arrive before this row materializes. Both are now listed. + +### Changed + +- **The client bundle is now covered by the gates that were missing it.** `scripts/verify-artifacts.mjs` executed only the host face; it now also runs the shipped client bundle against a stub `__ModuleLoader__`, asserts it registers exactly once under the package name, materializes its factory, and rejects top-level ESM. `test/client-bundle-contract.test.ts` asserts the same contract as a unit test — the 0.7.14 lesson ("`lib/client.js` is a build artifact of `src/client.ts`, and nothing in the test suite renders it") applied to the half that had no gate at all. + ## [0.7.15] - 2026-09-25 ### Changed diff --git a/README-es.md b/README-es.md index d733642..2c2e446 100644 --- a/README-es.md +++ b/README-es.md @@ -48,7 +48,7 @@ | Superficie | Estado | |---|---| -| Harness | DeepSeek Harness `dsh-v0.1.7-rc.2` (compatibilidad declarada para `>=0.1.2-rc.1 <0.2.0 \|\| >=0.1.5-alpha.1 <0.2.0 \|\| >=0.1.6-0 <0.2.0 \|\| >=0.1.7-0 <0.2.0`; 0.1.2-rc.1 adaptado el 2026-09-09): el job de revisión pasa a ser propiedad de un `SessionId` desnudo y la fuente de aviso usa el kind propio del plugin `dsh-github` (la unión `Agent \| SessionId` del host y su `kind: 'plugin'` comodín ya no existen); la tarjeta de configuración se registra en la **página Plugins** (grupo Official, slot `plugins.item`) y se renderiza desde el form que entrega `dsh-client-ui-plugin-manager`, en lugar de enlazar el eliminado `ctx.settingsScope`; el controlador de CI autoaprueba mediante la costura oficial `ctx.approval.setPolicy`; el bot de revisión sondea como tarea en segundo plano `ctx.jobs` con respaldo por temporizador. Actualizado el 2026-09-24 a `0.1.7-rc.2` (typecheck + typecheck:ci + 185 pruebas unitarias en verde). | +| Harness | DeepSeek Harness `dsh-v0.1.7-rc.2` (compatibilidad declarada para `>=0.1.2-rc.1 <0.2.0 \|\| >=0.1.5-alpha.1 <0.2.0 \|\| >=0.1.6-0 <0.2.0 \|\| >=0.1.7-0 <0.2.0 \|\| >=0.2.0-rc.1 <0.3.0-0`; la línea `0.2` (`0.2.0-rc.1` / `0.2.0-rc.2`) queda declarada y soportada desde `0.8.0`, donde la mitad de navegador se registra mediante el contrato `__ModuleLoader__` del host en lugar de terminar en enlaces ESM de nivel superior; 0.1.2-rc.1 adaptado el 2026-09-09): el job de revisión pasa a ser propiedad de un `SessionId` desnudo y la fuente de aviso usa el kind propio del plugin `dsh-github` (la unión `Agent \| SessionId` del host y su `kind: 'plugin'` comodín ya no existen); la tarjeta de configuración se registra en la **página Plugins** (grupo Official, slot `plugins.item`) y se renderiza desde el form que entrega `dsh-client-ui-plugin-manager`, en lugar de enlazar el eliminado `ctx.settingsScope`; el controlador de CI autoaprueba mediante la costura oficial `ctx.approval.setPolicy`; el bot de revisión sondea como tarea en segundo plano `ctx.jobs` con respaldo por temporizador. Actualizado el 2026-09-24 a `0.1.7-rc.2` (typecheck + typecheck:ci + 185 pruebas unitarias en verde). | | Node | `^22.19.0 \|\| >=24.0.0` | | Plataformas | Todas (plugin host; red saliente a GitHub) | | Modelo | Cualquiera (la revisión estática es determinista; `reviewMode: "model"` es opcional) | diff --git a/README-hi.md b/README-hi.md index da53d8b..8ab8485 100644 --- a/README-hi.md +++ b/README-hi.md @@ -48,7 +48,7 @@ | सतह | स्थिति | |---|---| -| Harness | DeepSeek Harness `dsh-v0.1.7-rc.2` (`>=0.1.2-rc.1 <0.2.0 \|\| >=0.1.5-alpha.1 <0.2.0 \|\| >=0.1.6-0 <0.2.0 \|\| >=0.1.7-0 <0.2.0` के लिए compat घोषित; 0.1.2-rc.1 2026-09-09 को अनुकूलित): review job अब नंगे `SessionId` का है और notice source plugin का अपना kind `dsh-github` है (host का `Agent \| SessionId` union और उसका catch-all `kind: 'plugin'` दोनों हट गए); settings card **Plugins पेज** (Official समूह, `plugins.item` slot) पर पंजीकृत होता है और `dsh-client-ui-plugin-manager` द्वारा दिए गए owner form से render होता है, हटाए गए `ctx.settingsScope` को bind करने की जगह; CI driver आधिकारिक `ctx.approval.setPolicy` नीति सीम से ऑटो-अनुमोदन करता है; review bot `ctx.jobs` पृष्ठभूमि job के रूप में टाइमर फ़ॉलबैक के साथ पोल करता है। 2026-09-24 को `0.1.7-rc.2` पर अपग्रेड (typecheck + typecheck:ci + 185 यूनिट टेस्ट हरे)। | +| Harness | DeepSeek Harness `dsh-v0.1.7-rc.2` (`>=0.1.2-rc.1 <0.2.0 \|\| >=0.1.5-alpha.1 <0.2.0 \|\| >=0.1.6-0 <0.2.0 \|\| >=0.1.7-0 <0.2.0 \|\| >=0.2.0-rc.1 <0.3.0-0` के लिए compat घोषित; `0.2` लाइन (`0.2.0-rc.1` / `0.2.0-rc.2`) `0.8.0` से घोषित और समर्थित है, जहाँ browser half top-level ESM bindings छोड़ने के बजाय host के `__ModuleLoader__` contract से रजिस्टर होता है; 0.1.2-rc.1 2026-09-09 को अनुकूलित): review job अब नंगे `SessionId` का है और notice source plugin का अपना kind `dsh-github` है (host का `Agent \| SessionId` union और उसका catch-all `kind: 'plugin'` दोनों हट गए); settings card **Plugins पेज** (Official समूह, `plugins.item` slot) पर पंजीकृत होता है और `dsh-client-ui-plugin-manager` द्वारा दिए गए owner form से render होता है, हटाए गए `ctx.settingsScope` को bind करने की जगह; CI driver आधिकारिक `ctx.approval.setPolicy` नीति सीम से ऑटो-अनुमोदन करता है; review bot `ctx.jobs` पृष्ठभूमि job के रूप में टाइमर फ़ॉलबैक के साथ पोल करता है। 2026-09-24 को `0.1.7-rc.2` पर अपग्रेड (typecheck + typecheck:ci + 185 यूनिट टेस्ट हरे)। | | Node | `^22.19.0 \|\| >=24.0.0` | | Platforms | सभी (host plugin; GitHub की ओर outbound network) | | Model | कोई भी (static review deterministic है; `reviewMode: "model"` वैकल्पिक है) | diff --git a/README-pt.md b/README-pt.md index 1348fc2..e783ab2 100644 --- a/README-pt.md +++ b/README-pt.md @@ -48,7 +48,7 @@ | Superfície | Status | |---|---| -| Harness | DeepSeek Harness `dsh-v0.1.7-rc.2` (compatibilidade declarada para `>=0.1.2-rc.1 <0.2.0 \|\| >=0.1.5-alpha.1 <0.2.0 \|\| >=0.1.6-0 <0.2.0 \|\| >=0.1.7-0 <0.2.0`; 0.1.2-rc.1 adaptado em 2026-09-09): o job de revisão passa a pertencer a um `SessionId` puro e a fonte dos avisos usa o kind próprio do plugin `dsh-github` (a união `Agent \| SessionId` do host e o `kind: 'plugin'` genérico deixaram de existir); o cartão de configurações se registra na **página Plugins** (grupo Official, slot `plugins.item`) e renderiza a partir do form entregue por `dsh-client-ui-plugin-manager`, em vez de vincular o removido `ctx.settingsScope`; o driver de CI autoaprova pela costura oficial `ctx.approval.setPolicy`; o bot de revisão pesquisa como job em segundo plano `ctx.jobs` com fallback por temporizador. Atualizado em 2026-09-24 para `0.1.7-rc.2` (typecheck + typecheck:ci + 185 testes unitários verdes). | +| Harness | DeepSeek Harness `dsh-v0.1.7-rc.2` (compatibilidade declarada para `>=0.1.2-rc.1 <0.2.0 \|\| >=0.1.5-alpha.1 <0.2.0 \|\| >=0.1.6-0 <0.2.0 \|\| >=0.1.7-0 <0.2.0 \|\| >=0.2.0-rc.1 <0.3.0-0`; a linha `0.2` (`0.2.0-rc.1` / `0.2.0-rc.2`) passa a ser declarada e suportada a partir de `0.8.0`, em que a metade de navegador se registra pelo contrato `__ModuleLoader__` do host em vez de terminar em vínculos ESM de nível superior; 0.1.2-rc.1 adaptado em 2026-09-09): o job de revisão passa a pertencer a um `SessionId` puro e a fonte dos avisos usa o kind próprio do plugin `dsh-github` (a união `Agent \| SessionId` do host e o `kind: 'plugin'` genérico deixaram de existir); o cartão de configurações se registra na **página Plugins** (grupo Official, slot `plugins.item`) e renderiza a partir do form entregue por `dsh-client-ui-plugin-manager`, em vez de vincular o removido `ctx.settingsScope`; o driver de CI autoaprova pela costura oficial `ctx.approval.setPolicy`; o bot de revisão pesquisa como job em segundo plano `ctx.jobs` com fallback por temporizador. Atualizado em 2026-09-24 para `0.1.7-rc.2` (typecheck + typecheck:ci + 185 testes unitários verdes). | | Node | `^22.19.0 \|\| >=24.0.0` | | Plataformas | Todas (plugin host; rede de saída para o GitHub) | | Modelo | Qualquer (a revisão estática é determinística; `reviewMode: "model"` é opcional) | diff --git a/README-zh.md b/README-zh.md index 2e4769b..a5e6973 100644 --- a/README-zh.md +++ b/README-zh.md @@ -50,7 +50,7 @@ | 界面 | 状态 | |---|---| -| Harness | DeepSeek Harness `dsh-v0.1.7-rc.2`(兼容声明覆盖 `>=0.1.2-rc.1 <0.2.0 \|\| >=0.1.5-alpha.1 <0.2.0 \|\| >=0.1.6-0 <0.2.0 \|\| >=0.1.7-0 <0.2.0`;0.1.2-rc.1 于 2026-09-09 已适配):评审任务改由裸 `SessionId` 归属、通知来源改为插件自有的 `dsh-github` kind(宿主的 `Agent \| SessionId` 联合与兜底 `kind: 'plugin'` 均已移除);设置卡注册在 **Plugins 页**(Official 组,`plugins.item` 槽),并从 `dsh-client-ui-plugin-manager` 提供的 owner form 渲染,不再绑定已删除的 `ctx.settingsScope`;CI 驱动器通过官方 `ctx.approval.setPolicy` 策略缝自动放行;评审机器人以 `ctx.jobs` 后台任务轮询,并带定时器降级。2026-09-24 升级至 `0.1.7-rc.2`(typecheck + typecheck:ci + 185 项单元测试全绿)。 | +| Harness | DeepSeek Harness `dsh-v0.1.7-rc.2`(兼容声明覆盖 `>=0.1.2-rc.1 <0.2.0 \|\| >=0.1.5-alpha.1 <0.2.0 \|\| >=0.1.6-0 <0.2.0 \|\| >=0.1.7-0 <0.2.0 \|\| >=0.2.0-rc.1 <0.3.0-0`;`0.2` 线(`0.2.0-rc.1` / `0.2.0-rc.2`)自 `0.8.0` 起纳入声明并提供支持——浏览器半边改为通过宿主的 `__ModuleLoader__` 契约注册,不再以顶层 ESM 绑定收尾;0.1.2-rc.1 于 2026-09-09 已适配):评审任务改由裸 `SessionId` 归属、通知来源改为插件自有的 `dsh-github` kind(宿主的 `Agent \| SessionId` 联合与兜底 `kind: 'plugin'` 均已移除);设置卡注册在 **Plugins 页**(Official 组,`plugins.item` 槽),并从 `dsh-client-ui-plugin-manager` 提供的 owner form 渲染,不再绑定已删除的 `ctx.settingsScope`;CI 驱动器通过官方 `ctx.approval.setPolicy` 策略缝自动放行;评审机器人以 `ctx.jobs` 后台任务轮询,并带定时器降级。2026-09-24 升级至 `0.1.7-rc.2`(typecheck + typecheck:ci + 185 项单元测试全绿)。 | | Node | `^22.19.0 \|\| >=24.0.0` | | Platforms | 全部(host 插件;出站网络访问 GitHub) | | Model | 任意(静态审查是确定性的;`reviewMode: "model"` 为可选) | diff --git a/README.md b/README.md index 9bbad3e..8195491 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ | Surface | Status | |---|---| -| Harness | DeepSeek Harness `dsh-v0.1.7-rc.2` (compat declared for `>=0.1.2-rc.1 <0.2.0 \|\| >=0.1.5-alpha.1 <0.2.0 \|\| >=0.1.6-0 <0.2.0 \|\| >=0.1.7-0 <0.2.0`; 0.1.2-rc.1 adapted 2026-09-09): the review job is owned by a bare `SessionId` and a notice source is the plugin-owned kind `dsh-github` (the host's `Agent \| SessionId` union and its catch-all `kind: 'plugin'` are both gone); the settings card registers on the **Plugins page** (Official group, `plugins.item` slot) and renders from the owner form `dsh-client-ui-plugin-manager` supplies, instead of binding the removed `ctx.settingsScope`; the CI driver auto-approves through the official `ctx.approval.setPolicy` policy seam; the review bot polls as a `ctx.jobs` background job with a timer fallback. Upgraded 2026-09-24 to `0.1.7-rc.2` (typecheck + typecheck:ci + 185 unit tests green). | +| Harness | DeepSeek Harness `dsh-v0.1.7-rc.2` (compat declared for `>=0.1.2-rc.1 <0.2.0 \|\| >=0.1.5-alpha.1 <0.2.0 \|\| >=0.1.6-0 <0.2.0 \|\| >=0.1.7-0 <0.2.0 \|\| >=0.2.0-rc.1 <0.3.0-0`; the `0.2` line (`0.2.0-rc.1` / `0.2.0-rc.2`) is declared and supported from `0.8.0`, where the browser half registers through the host's `__ModuleLoader__` contract instead of leaving top-level ESM bindings; 0.1.2-rc.1 adapted 2026-09-09): the review job is owned by a bare `SessionId` and a notice source is the plugin-owned kind `dsh-github` (the host's `Agent \| SessionId` union and its catch-all `kind: 'plugin'` are both gone); the settings card registers on the **Plugins page** (Official group, `plugins.item` slot) and renders from the owner form `dsh-client-ui-plugin-manager` supplies, instead of binding the removed `ctx.settingsScope`; the CI driver auto-approves through the official `ctx.approval.setPolicy` policy seam; the review bot polls as a `ctx.jobs` background job with a timer fallback. Upgraded 2026-09-24 to `0.1.7-rc.2` (typecheck + typecheck:ci + 185 unit tests green). | | Node | `^22.19.0 \|\| >=24.0.0` | | Platforms | All (host plugin; outbound network to GitHub) | | Model | Any (static review is deterministic; `reviewMode: "model"` is optional) | diff --git a/lib/client.js b/lib/client.js index 8a2425e..194e5e8 100644 --- a/lib/client.js +++ b/lib/client.js @@ -1,291 +1,310 @@ -/** - * dsh-github browser half — one card in the Plugins page's Official group. - * - * The card reports and edits the GitHub token. The token literal never rides - * the settings document: it is written through the credentials domain, - * addressed by the reference the plugin's cordis.yml `Config.tokenRef` names - * (default `GITHUB_TOKEN`), which is exactly where the host half resolves it — - * per operation, no restart needed. - * - * Since host 0.1.7-alpha.1 the page owns configuration: the card renders the - * `summary` one-liner and the `page` body from the `plugins.item` owner props - * (`view`, and the `form` the Plugins page supplies), instead of binding a - * `settingsScope` itself — that service, `settings.plugin.item`'s old shape, - * and the `dsh-settings-file` package behind them were all removed. The card - * therefore reads `tokenRef` from `form.state.value` and never writes the - * settings document; the credential is written through the credentials - * domain, which is a different seam and stayed. - * - * The shipped `lib/client.js` is the built bundle of this module. The browser - * module loader executes that bundle, not this file. - * @module @perrylink/dsh-github/client - */ -import { createElement, useState } from 'react'; -import { Button, IconLoadingOutlineRegular, } from '@deepseek-ai/dsh-client-ui-primitives'; -/** - * Create the minimal card store. - * @param init - initial state. - * @returns the store. - */ -export function createSnapshotStore(init) { - let state = init; - const listeners = new Set(); - return { - getSnapshot: () => state, - subscribe: (listener) => { - listeners.add(listener); - return () => { listeners.delete(listener); }; - }, - set: (next) => { - state = next; - for (const listener of [...listeners]) - listener(); - }, - }; -} -/** Namespace of the GitHub capability. Spelled here rather than imported: a client package must not depend on a Host package. */ -export const GITHUB_NS = 'dsh-github'; -/** Credential reference the provider resolves when the configuration names none. */ -export const DEFAULT_TOKEN_REF = 'GITHUB_TOKEN'; -/** English copy. */ -export const en = { - githubTitle: 'GitHub', - githubDescription: 'GitHub pull requests, issues, and CI through the agent.', - tokenLabel: 'GitHub token', - tokenHint: 'Stored in the credentials file, not here. Applied immediately; leave blank to keep the current token.', - tokenSet: 'A token is configured.', - tokenUnset: 'No token is configured; GitHub tools are unavailable until one is.', - unsaved: 'Unsaved', - readOnly: 'This deployment stores settings read-only.', - save: 'Save', - saving: 'Saving…', - discard: 'Discard', - saveFailed: 'The deployment did not accept this value; it was left for you to correct.', -}; -/** Simplified Chinese copy. */ -export const zh = { - githubTitle: 'GitHub', - githubDescription: '通过 agent 操作 GitHub 的 PR、issue 与 CI。', - tokenLabel: 'GitHub Token', - tokenHint: '写入凭证文件而非设置文件;保存后立即生效。留空表示保持现有令牌。', - tokenSet: '已配置令牌。', - tokenUnset: '未配置令牌;配置之前 GitHub 工具不可用。', - unsaved: '未保存', - readOnly: '本部署的设置为只读。', - save: '保存', - saving: '保存中…', - discard: '放弃修改', - saveFailed: '本部署没有接受该值,已保留供你修改。', -}; -/** - * Bridges the page-supplied configuration form and the credentials domain onto - * the card. The token is the one control that does not live in the - * configuration: its literal never rides a response, so the card learns only - * whether one is configured and writes it through the credentials domain, - * addressed by the reference `Config.tokenRef` names. - */ -export class GithubCardController { - form; - api; - store; - saving = false; - failed = false; - credential = { ref: '', configured: false, writable: true }; - /** - * @param form - the configuration form the Plugins page hands this entry, or - * `undefined` when the page supplied none (the card then reads the default - * reference and offers the credential control alone). - * @param api - the credentials Remote namespace. - */ - constructor(form, api) { - this.form = form; - this.api = api; - this.store = createSnapshotStore(this.projection()); - form?.subscribe(() => { - void this.readCredential(); - this.publish(); - }); - void this.readCredential(); - } - /** Whether the Host configuration document accepts writes. */ - writable() { - return this.form?.getSnapshot().writable ?? true; - } - /** The configuration form this controller reads (identity-compared by the caller). */ - formOf() { - return this.form; - } - /** Project the card's full state for its snapshot store. */ - projection() { - return { - writable: this.writable(), - configured: this.credential.configured, - credentialWritable: this.credential.writable, - saving: this.saving, - failed: this.failed, - ref: this.credential.ref, - }; - } - /** The credential reference the configuration names, or the provider default. */ - refOf() { - const declared = this.form?.getSnapshot().value?.tokenRef; - return declared !== undefined && declared.length > 0 ? declared : DEFAULT_TOKEN_REF; - } - /** - * Ask the credentials domain about the reference the section names. A - * response is published only while it still answers for the reference in - * force, so two reads settling out of order cannot clobber each other. - */ - async readCredential() { - const ref = this.refOf(); - if (ref !== this.credential.ref) { - this.credential = { ref, configured: false, writable: true }; - this.publish(); - } - let response; - try { - response = await this.api.describe([ref]); - } - catch { - return; - } - if (!response.ok || ref !== this.refOf()) - return; - const view = response.value[ref]; - const next = { ref, configured: view?.configured ?? false, writable: view?.writable ?? true }; - if (next.configured === this.credential.configured && next.writable === this.credential.writable) - return; - this.credential = next; - this.publish(); - } - /** - * Re-read after the Host reports a change to the reference this card - * watches — a token can be written from elsewhere, and the section does not - * change when it is. - * @param ref - the reference the Host reports as changed. - */ - refreshCredential(ref) { - if (ref !== this.credential.ref) - return; - void this.readCredential(); - } - /** - * Write the staged token, then re-read whether the Host now holds one. A - * blank value writes nothing, which keeps the stored key. - * @param value - the staged credential literal. - * @returns whether the Host reports a configured credential afterwards. - */ - async save(value) { - const text = (value ?? '').trim(); - if (text === '' || this.saving) - return false; - this.saving = true; - this.failed = false; - this.publish(); - try { - await this.api.set(this.refOf(), text); - } - catch { - // handled below by re-reading the configured state - } - await this.readCredential(); - const landed = this.credential.configured; - this.saving = false; - this.failed = !landed; - this.publish(); - return landed; - } - /** Build the face the card's slot registration injects. */ - inject() { - return { - hooks: { githubCard: this.store }, - submit: (value) => this.save(value), - }; - } - publish() { - this.store.set(this.projection()); - } -} -/** - * Render the GitHub card. `summary` renders the one-liner the Plugins page - * places under the card's title (the description plus the token state badge); - * `page` renders the token control and the save/discard row on the plugin's - * own page. The page supplies the configuration form, so the card never - * depends on a served namespace to render. - */ -export function GithubCard(props) { - const { t } = props; - const state = props.useGithubCard((snapshot) => snapshot); - const [draft, setDraft] = useState(''); - if (props.view === 'summary') { - return createElement('span', { className: 'ghc-summary' }, createElement('span', null, t('githubDescription')), createElement('span', { className: state.configured ? 'ghc-badge' : 'ghc-badgeMuted' }, state.configured ? t('tokenSet') : t('tokenUnset'))); - } - const dirty = draft.trim() !== ''; - const saveLabel = state.saving ? t('saving') : t('save'); - return createElement('div', { className: 'ghc-card ghc-cardPage' }, !state.writable - ? createElement('p', { className: 'ghc-readOnly', role: 'status' }, t('readOnly')) - : null, createElement('div', { className: 'ghc-field' }, createElement('div', { className: 'ghc-head' }, createElement('label', { className: 'ghc-label', htmlFor: 'plugin-config-github-token' }, t('tokenLabel')), createElement('span', { className: 'ghc-badges' }, createElement('span', { className: state.configured ? 'ghc-badge' : 'ghc-badgeMuted' }, state.configured ? t('tokenSet') : t('tokenUnset')))), createElement('input', { - id: 'plugin-config-github-token', - className: 'ghc-input', - type: 'password', - autoComplete: 'off', - value: draft, - disabled: !state.credentialWritable, - onChange: (event) => setDraft(event.target.value), - }), createElement('p', { className: 'ghc-hint' }, t('tokenHint'))), createElement('div', { className: 'ghc-actions' }, state.failed ? createElement('p', { className: 'ghc-failed', role: 'status' }, t('saveFailed')) : null, createElement(Button, { - variant: 'ghost', - size: 'sm', - disabled: !dirty || state.saving, - onClick: () => setDraft(''), - }, t('discard')), createElement(Button, { - variant: 'primary', - size: 'sm', - disabled: !state.writable || !dirty || state.saving, - icon: state.saving - ? createElement('span', { className: 'ghc-spin' }, createElement(IconLoadingOutlineRegular, { size: 16 })) - : undefined, - onClick: async () => { - const landed = await props.submit(draft); - if (landed) - setDraft(''); - }, - }, saveLabel))); -} -/** Dictionary namespace owned by this plugin. */ -export const NS = 'dsh-github'; -/** - * Required services (cordis fiber inject). `settingsScope` is gone: host - * 0.1.7-alpha.1 removed it, and the Plugins page now hands the configuration - * form to the `plugins.item` entry instead. `@deepseek-ai/dsh-client-ui-plugin-manager` - * owns that slot, so it must be composed for the card to mount at all. - */ -export const inject = ['slots', 'locale', 'connection', 'remote', 'remote.credentials']; -/** - * Mount the GitHub configuration card into the Plugins page's Official group. - * - * The form arrives per render, so the controller is rebuilt whenever the page - * supplies a different one — the page's own form owner stays authoritative and - * the card keeps no second copy of the accepted values. - * @param ctx - the browser plugin context. - */ -export function apply(ctx) { - const t = ctx.locale.bind(NS); - ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'dsh-github: card dictionaries'); - let github; - const controllerFor = (form) => { - if (github === undefined || github.formOf() !== form) { - github = new GithubCardController(form, ctx.remote.credentials); - } - return github; - }; - ctx.effect(() => ctx.remote.$on('credentials/reference-updated', (ref) => github?.refreshCredential(ref)), 'dsh-github: credential invalidations'); - ctx.slots.inject('plugins.item', () => ctx.slots.register({ - name: 'plugins.item', - id: NS, - order: 100, - label: () => t('githubTitle'), - locale: NS, - inject: () => controllerFor(github?.formOf()).inject(), - }, GithubCard)); -} -//# sourceMappingURL=client.js.map \ No newline at end of file +window.__ModuleLoader__.load({ + id: "@perrylink/dsh-github", + factory: (require) => { + var module = { exports: {} }; + var exports = module.exports; + Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); + /** + * dsh-github browser half — one card in the Plugins page's Official group. + * + * The card reports and edits the GitHub token. The token literal never rides + * the settings document: it is written through the credentials domain, + * addressed by the reference the plugin's cordis.yml `Config.tokenRef` names + * (default `GITHUB_TOKEN`), which is exactly where the host half resolves it — + * per operation, no restart needed. + * + * Since host 0.1.7-alpha.1 the page owns configuration: the card renders the + * `summary` one-liner and the `page` body from the `plugins.item` owner props + * (`view`, and the `form` the Plugins page supplies), instead of binding a + * `settingsScope` itself — that service, `settings.plugin.item`'s old shape, + * and the `dsh-settings-file` package behind them were all removed. The card + * therefore reads `tokenRef` from `form.state.value` and never writes the + * settings document; the credential is written through the credentials + * domain, which is a different seam and stayed. + * + * The shipped `lib/client.js` is the built bundle of this module. The browser + * module loader executes that bundle, not this file. + * @module @perrylink/dsh-github/client + */ + const { createElement, useState } = require("react"); + const { Button, IconLoadingOutlineRegular } = require("@deepseek-ai/dsh-client-ui-primitives"); + /** + * Create the minimal card store. + * @param init - initial state. + * @returns the store. + */ + function createSnapshotStore(init) { + let state = init; + const listeners = new Set(); + return { + getSnapshot: () => state, + subscribe: (listener) => { + listeners.add(listener); + return () => { listeners.delete(listener); }; + }, + set: (next) => { + state = next; + for (const listener of [...listeners]) + listener(); + }, + }; + } + /** Namespace of the GitHub capability. Spelled here rather than imported: a client package must not depend on a Host package. */ + const GITHUB_NS = 'dsh-github'; + /** Credential reference the provider resolves when the configuration names none. */ + const DEFAULT_TOKEN_REF = 'GITHUB_TOKEN'; + /** English copy. */ + const en = { + githubTitle: 'GitHub', + githubDescription: 'GitHub pull requests, issues, and CI through the agent.', + tokenLabel: 'GitHub token', + tokenHint: 'Stored in the credentials file, not here. Applied immediately; leave blank to keep the current token.', + tokenSet: 'A token is configured.', + tokenUnset: 'No token is configured; GitHub tools are unavailable until one is.', + unsaved: 'Unsaved', + readOnly: 'This deployment stores settings read-only.', + save: 'Save', + saving: 'Saving…', + discard: 'Discard', + saveFailed: 'The deployment did not accept this value; it was left for you to correct.', + }; + /** Simplified Chinese copy. */ + const zh = { + githubTitle: 'GitHub', + githubDescription: '通过 agent 操作 GitHub 的 PR、issue 与 CI。', + tokenLabel: 'GitHub Token', + tokenHint: '写入凭证文件而非设置文件;保存后立即生效。留空表示保持现有令牌。', + tokenSet: '已配置令牌。', + tokenUnset: '未配置令牌;配置之前 GitHub 工具不可用。', + unsaved: '未保存', + readOnly: '本部署的设置为只读。', + save: '保存', + saving: '保存中…', + discard: '放弃修改', + saveFailed: '本部署没有接受该值,已保留供你修改。', + }; + /** + * Bridges the page-supplied configuration form and the credentials domain onto + * the card. The token is the one control that does not live in the + * configuration: its literal never rides a response, so the card learns only + * whether one is configured and writes it through the credentials domain, + * addressed by the reference `Config.tokenRef` names. + */ + class GithubCardController { + form; + api; + store; + saving = false; + failed = false; + credential = { ref: '', configured: false, writable: true }; + /** + * @param form - the configuration form the Plugins page hands this entry, or + * `undefined` when the page supplied none (the card then reads the default + * reference and offers the credential control alone). + * @param api - the credentials Remote namespace. + */ + constructor(form, api) { + this.form = form; + this.api = api; + this.store = createSnapshotStore(this.projection()); + form?.subscribe(() => { + void this.readCredential(); + this.publish(); + }); + void this.readCredential(); + } + /** Whether the Host configuration document accepts writes. */ + writable() { + return this.form?.getSnapshot().writable ?? true; + } + /** The configuration form this controller reads (identity-compared by the caller). */ + formOf() { + return this.form; + } + /** Project the card's full state for its snapshot store. */ + projection() { + return { + writable: this.writable(), + configured: this.credential.configured, + credentialWritable: this.credential.writable, + saving: this.saving, + failed: this.failed, + ref: this.credential.ref, + }; + } + /** The credential reference the configuration names, or the provider default. */ + refOf() { + const declared = this.form?.getSnapshot().value?.tokenRef; + return declared !== undefined && declared.length > 0 ? declared : DEFAULT_TOKEN_REF; + } + /** + * Ask the credentials domain about the reference the section names. A + * response is published only while it still answers for the reference in + * force, so two reads settling out of order cannot clobber each other. + */ + async readCredential() { + const ref = this.refOf(); + if (ref !== this.credential.ref) { + this.credential = { ref, configured: false, writable: true }; + this.publish(); + } + let response; + try { + response = await this.api.describe([ref]); + } + catch { + return; + } + if (!response.ok || ref !== this.refOf()) + return; + const view = response.value[ref]; + const next = { ref, configured: view?.configured ?? false, writable: view?.writable ?? true }; + if (next.configured === this.credential.configured && next.writable === this.credential.writable) + return; + this.credential = next; + this.publish(); + } + /** + * Re-read after the Host reports a change to the reference this card + * watches — a token can be written from elsewhere, and the section does not + * change when it is. + * @param ref - the reference the Host reports as changed. + */ + refreshCredential(ref) { + if (ref !== this.credential.ref) + return; + void this.readCredential(); + } + /** + * Write the staged token, then re-read whether the Host now holds one. A + * blank value writes nothing, which keeps the stored key. + * @param value - the staged credential literal. + * @returns whether the Host reports a configured credential afterwards. + */ + async save(value) { + const text = (value ?? '').trim(); + if (text === '' || this.saving) + return false; + this.saving = true; + this.failed = false; + this.publish(); + try { + await this.api.set(this.refOf(), text); + } + catch { + // handled below by re-reading the configured state + } + await this.readCredential(); + const landed = this.credential.configured; + this.saving = false; + this.failed = !landed; + this.publish(); + return landed; + } + /** Build the face the card's slot registration injects. */ + inject() { + return { + hooks: { githubCard: this.store }, + submit: (value) => this.save(value), + }; + } + publish() { + this.store.set(this.projection()); + } + } + /** + * Render the GitHub card. `summary` renders the one-liner the Plugins page + * places under the card's title (the description plus the token state badge); + * `page` renders the token control and the save/discard row on the plugin's + * own page. The page supplies the configuration form, so the card never + * depends on a served namespace to render. + */ + function GithubCard(props) { + const { t } = props; + const state = props.useGithubCard((snapshot) => snapshot); + const [draft, setDraft] = useState(''); + if (props.view === 'summary') { + return createElement('span', { className: 'ghc-summary' }, createElement('span', null, t('githubDescription')), createElement('span', { className: state.configured ? 'ghc-badge' : 'ghc-badgeMuted' }, state.configured ? t('tokenSet') : t('tokenUnset'))); + } + const dirty = draft.trim() !== ''; + const saveLabel = state.saving ? t('saving') : t('save'); + return createElement('div', { className: 'ghc-card ghc-cardPage' }, !state.writable + ? createElement('p', { className: 'ghc-readOnly', role: 'status' }, t('readOnly')) + : null, createElement('div', { className: 'ghc-field' }, createElement('div', { className: 'ghc-head' }, createElement('label', { className: 'ghc-label', htmlFor: 'plugin-config-github-token' }, t('tokenLabel')), createElement('span', { className: 'ghc-badges' }, createElement('span', { className: state.configured ? 'ghc-badge' : 'ghc-badgeMuted' }, state.configured ? t('tokenSet') : t('tokenUnset')))), createElement('input', { + id: 'plugin-config-github-token', + className: 'ghc-input', + type: 'password', + autoComplete: 'off', + value: draft, + disabled: !state.credentialWritable, + onChange: (event) => setDraft(event.target.value), + }), createElement('p', { className: 'ghc-hint' }, t('tokenHint'))), createElement('div', { className: 'ghc-actions' }, state.failed ? createElement('p', { className: 'ghc-failed', role: 'status' }, t('saveFailed')) : null, createElement(Button, { + variant: 'ghost', + size: 'sm', + disabled: !dirty || state.saving, + onClick: () => setDraft(''), + }, t('discard')), createElement(Button, { + variant: 'primary', + size: 'sm', + disabled: !state.writable || !dirty || state.saving, + icon: state.saving + ? createElement('span', { className: 'ghc-spin' }, createElement(IconLoadingOutlineRegular, { size: 16 })) + : undefined, + onClick: async () => { + const landed = await props.submit(draft); + if (landed) + setDraft(''); + }, + }, saveLabel))); + } + /** Dictionary namespace owned by this plugin. */ + const NS = 'dsh-github'; + /** + * Required services (cordis fiber inject). `settingsScope` is gone: host + * 0.1.7-alpha.1 removed it, and the Plugins page now hands the configuration + * form to the `plugins.item` entry instead. `@deepseek-ai/dsh-client-ui-plugin-manager` + * owns that slot, so it must be composed for the card to mount at all. + */ + const inject = ['slots', 'locale', 'connection', 'remote', 'remote.credentials']; + /** + * Mount the GitHub configuration card into the Plugins page's Official group. + * + * The form arrives per render, so the controller is rebuilt whenever the page + * supplies a different one — the page's own form owner stays authoritative and + * the card keeps no second copy of the accepted values. + * @param ctx - the browser plugin context. + */ + function apply(ctx) { + const t = ctx.locale.bind(NS); + ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'dsh-github: card dictionaries'); + let github; + const controllerFor = (form) => { + if (github === undefined || github.formOf() !== form) { + github = new GithubCardController(form, ctx.remote.credentials); + } + return github; + }; + ctx.effect(() => ctx.remote.$on('credentials/reference-updated', (ref) => github?.refreshCredential(ref)), 'dsh-github: credential invalidations'); + ctx.slots.inject('plugins.item', () => ctx.slots.register({ + name: 'plugins.item', + id: NS, + order: 100, + label: () => t('githubTitle'), + locale: NS, + inject: () => controllerFor(github?.formOf()).inject(), + }, GithubCard)); + } + exports.createSnapshotStore = createSnapshotStore; + exports.GITHUB_NS = GITHUB_NS; + exports.DEFAULT_TOKEN_REF = DEFAULT_TOKEN_REF; + exports.en = en; + exports.zh = zh; + exports.GithubCardController = GithubCardController; + exports.GithubCard = GithubCard; + exports.NS = NS; + exports.inject = inject; + exports.apply = apply; + return module.exports; + } +}); +//# sourceMappingURL=client.js.map diff --git a/lib/client.js.map b/lib/client.js.map index e8bb1fc..636b4c2 100644 --- a/lib/client.js.map +++ b/lib/client.js.map @@ -1 +1 @@ -{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"} diff --git a/package.json b/package.json index 5c50935..b3bc839 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@perrylink/dsh-github", - "version": "0.7.15", + "version": "0.8.0", "description": "Official-grade GitHub CI for DeepSeek Harness: composite action (review PRs / fix CI / report), polling PR review bot with idempotent inline comments, a status-check gate, and approval-gated PR/issue/repo/file tools", "type": "module", "main": "lib/index.js", @@ -29,7 +29,7 @@ "LICENSE" ], "scripts": { - "build": "tsc --noEmitOnError && node scripts/fix-dts.mjs", + "build": "tsc --noEmitOnError && node scripts/fix-dts.mjs && node scripts/build-client.mjs", "prepare": "node scripts/prepare.mjs", "prepublishOnly": "npm run build && npm test", "test": "vitest run", @@ -62,7 +62,7 @@ }, "engines": { "node": "^22.19.0 || >=24.0.0", - "dsh": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0" + "dsh": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0 || >=0.2.0-rc.1 <0.3.0-0" }, "packageManager": "pnpm@11.7.0", "dsh": { @@ -72,6 +72,8 @@ }, "client": { "inject": [ + "react", + "@deepseek-ai/dsh-client-ui-primitives", "@deepseek-ai/dsh-client-connection", "@deepseek-ai/dsh-client-locale", "@deepseek-ai/dsh-client-ui-plugin-manager", @@ -103,7 +105,7 @@ "filesystem:write" ], "compatibility": { - "dshVersions": ["0.1.2-rc.1","0.1.5-rc.2","0.1.7-rc.1", "0.1.7-rc.2"] + "dshVersions": ["0.1.2-rc.1","0.1.5-rc.2","0.1.7-rc.1", "0.1.7-rc.2", "0.2.0-rc.2"] }, "capability": { "id": "gh-ci", @@ -123,19 +125,19 @@ }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.4", - "@deepseek-ai/dsh-agent": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0", - "@deepseek-ai/dsh-client-ui-plugin-manager": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0", - "@deepseek-ai/dsh-client-ui-primitives": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0", - "@deepseek-ai/dsh-client-ui-settings": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0", - "@deepseek-ai/dsh-credentials": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0", - "@deepseek-ai/dsh-jobs": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0", - "@deepseek-ai/dsh-llm": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0", - "@deepseek-ai/dsh-session": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0", - "@deepseek-ai/dsh-settings": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0", - "@deepseek-ai/dsh-subagent": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0", - "@deepseek-ai/dsh-tool-jobs": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0", - "@deepseek-ai/dsh-tools": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0", - "@deepseek-ai/dsh-user-approval": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0", + "@deepseek-ai/dsh-agent": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0 || >=0.2.0-rc.1 <0.3.0-0", + "@deepseek-ai/dsh-client-ui-plugin-manager": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0 || >=0.2.0-rc.1 <0.3.0-0", + "@deepseek-ai/dsh-client-ui-primitives": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0 || >=0.2.0-rc.1 <0.3.0-0", + "@deepseek-ai/dsh-client-ui-settings": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0 || >=0.2.0-rc.1 <0.3.0-0", + "@deepseek-ai/dsh-credentials": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0 || >=0.2.0-rc.1 <0.3.0-0", + "@deepseek-ai/dsh-jobs": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0 || >=0.2.0-rc.1 <0.3.0-0", + "@deepseek-ai/dsh-llm": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0 || >=0.2.0-rc.1 <0.3.0-0", + "@deepseek-ai/dsh-session": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0 || >=0.2.0-rc.1 <0.3.0-0", + "@deepseek-ai/dsh-settings": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0 || >=0.2.0-rc.1 <0.3.0-0", + "@deepseek-ai/dsh-subagent": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0 || >=0.2.0-rc.1 <0.3.0-0", + "@deepseek-ai/dsh-tool-jobs": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0 || >=0.2.0-rc.1 <0.3.0-0", + "@deepseek-ai/dsh-tools": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0 || >=0.2.0-rc.1 <0.3.0-0", + "@deepseek-ai/dsh-user-approval": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0 || >=0.2.0-rc.1 <0.3.0-0", "react": "^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { diff --git a/scripts/build-client.mjs b/scripts/build-client.mjs new file mode 100644 index 0000000..b70ec71 --- /dev/null +++ b/scripts/build-client.mjs @@ -0,0 +1,196 @@ +// Wrap the tsc-compiled ESM client bundle into the DeepSeek Harness browser +// module-loader contract. +// +// The host's client module system (`@deepseek-ai/dsh-client-modules`) is a lazy +// CJS table: executing a client bundle must REGISTER a factory through +// `window.__ModuleLoader__.load({ id, factory })`; every module body side effect +// lives inside that factory and runs at materialization, not at script +// execution. A bundle that ends in top-level `export` bindings registers +// nothing, and the host reports +// +// client-modules: could not load "": : +// loaded without registering "" via __ModuleLoader__.load +// +// `tsc` emits ESM, so this step rewrites the compiled file in place: +// +// import { a, b } from 'm' -> const { a, b } = require('m') +// export function f() {} -> function f() {} (+ exports.f = f) +// export const x = 1 -> const x = 1 (+ exports.x = x) +// export class C {} -> class C {} (+ exports.C = C) +// export { a, b as c } -> (removed) (+ exports.a = a; exports.c = b) +// +// Original line order is preserved: only a fixed prefix is added before the +// module body and a fixed suffix after it, so `lib/client.js.map` stays valid +// after the same line offset is applied to it (an empty leading run of `;` +// segments means "these generated lines carry no mapping"). That keeps the map +// shipped with the wrapped bundle usable while debugging in the browser. +// +// It fails loud on any shape it does not recognize, rather than ship a bundle +// that cannot register. Re-running it on an already-wrapped bundle is a no-op, +// so both `build` and `prepare` can call it. +import { readFileSync, writeFileSync } from 'node:fs' +import { fileURLToPath } from 'node:url' +import { dirname, join } from 'node:path' + +const root = dirname(dirname(fileURLToPath(import.meta.url))) +const libDir = join(root, 'lib') +const clientPath = join(libDir, 'client.js') +const mapPath = join(libDir, 'client.js.map') +const manifest = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8')) +const pkgName = manifest.name + +const MARKER = 'window.__ModuleLoader__.load(' +const source = readFileSync(clientPath, 'utf8') + +if (source.includes(MARKER)) { + console.log('build-client: lib/client.js is already wrapped; nothing to do') + process.exit(0) +} + +const SOURCE_MAP_COMMENT = /^\/\/# sourceMappingURL=(\S+)\s*$/ + +// Top-level statements only: tsc emits them at column 0 and nested code is +// always indented, so a column-0 anchor cannot reach into a function body. +const isTopLevel = (line) => !/^[ \t]/.test(line) + +const exported = [] // [ exportName, localName ] +const body = [] +let sourceMapTarget + +const fail = (line, why) => { + throw new Error( + `build-client: unsupported top-level statement (${why}); ` + + `teach scripts/build-client.mjs this shape before shipping:\n ${line}`, + ) +} + +for (const line of source.split('\n')) { + if (isTopLevel(line) && line.startsWith('import ')) { + const named = line.match(/^import\s*\{([^}]*)\}\s*from\s*(['"])([^'"]+)\2\s*;?$/) + const bare = line.match(/^import\s+(['"])([^'"]+)\1\s*;?$/) + const star = line.match(/^import\s*\*\s*as\s+([A-Za-z_$][\w$]*)\s*from\s*(['"])([^'"]+)\2\s*;?$/) + const def = line.match(/^import\s+([A-Za-z_$][\w$]*)\s*from\s*(['"])([^'"]+)\2\s*;?$/) + + if (bare) { + body.push(`require(${JSON.stringify(bare[2])});`) + } else if (named) { + const spec = named[1] + .split(',') + .map((s) => s.trim()) + .filter(Boolean) + for (const binding of spec) { + if (!/^[A-Za-z_$][\w$]*$/.test(binding)) fail(line, 'aliased or namespaced named import') + } + body.push(`const { ${spec.join(', ')} } = require(${JSON.stringify(named[3])});`) + } else if (star) { + body.push(`const ${star[1]} = require(${JSON.stringify(star[3])});`) + } else if (def) { + body.push(`const ${def[1]} = require(${JSON.stringify(def[3])}).default;`) + } else { + fail(line, 'unrecognized import form') + } + continue + } + + if (isTopLevel(line) && line.startsWith('export ')) { + if (/^export\s+default\b/.test(line)) fail(line, 'default export') + if (/^export\s*\*/.test(line)) fail(line, 'star re-export') + + const list = line.match(/^export\s*\{([^}]*)\}\s*(?:from\s*(['"])([^'"]+)\2)?\s*;?$/) + if (list) { + if (list[2] !== undefined) fail(line, 're-export from another module') + for (const entry of list[1].split(',').map((s) => s.trim()).filter(Boolean)) { + const parts = entry.split(/\s+as\s+/).map((s) => s.trim()) + const exportedName = parts.length === 2 ? parts[1] : parts[0] + if (!/^[A-Za-z_$][\w$]*$/.test(exportedName)) fail(line, 'unrecognized export alias') + exported.push([exportedName, parts[0]]) + } + continue // the declaration itself stays in the body untouched + } + + const decl = line.match( + /^export\s+(?:async\s+)?(function\*?|class|const|let|var)\s+([A-Za-z_$][\w$]*)/, + ) + if (!decl) fail(line, 'unrecognized export form') + if (decl[1] === 'const' || decl[1] === 'let' || decl[1] === 'var') { + // Only a simple `name = …` binding is supported; destructuring would need + // per-binding names this script cannot infer from a single line. + if (!/^export\s+(?:const|let|var)\s+[A-Za-z_$][\w$]*\s*=/.test(line)) { + fail(line, 'destructuring or uninitialized export binding') + } + } + exported.push([decl[2], decl[2]]) + body.push(line.slice('export '.length)) + continue + } + + // The trailing source map comment is re-emitted after the wrapper so the map + // reference stays the last line of the shipped file. + const mapComment = line.match(SOURCE_MAP_COMMENT) + if (mapComment && isTopLevel(line)) { + sourceMapTarget = mapComment[1] + continue + } + + body.push(line) +} + +const indent = (line) => (line.length === 0 ? '' : `\t${line}`) + +const prefix = [ + 'window.__ModuleLoader__.load({', + `\tid: ${JSON.stringify(pkgName)},`, + '\tfactory: (require) => {', + '\t\tvar module = { exports: {} };', + '\t\tvar exports = module.exports;', + '\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: "Module" });', +] +const suffix = [ + ...exported.map(([name, local]) => `\t\texports.${name} = ${local};`), + '\t\treturn module.exports;', + '\t}', + '});', +] + +const wrapped = [ + ...prefix, + ...body.map(indent), + ...suffix, + ...(sourceMapTarget === undefined ? [] : [`//# sourceMappingURL=${sourceMapTarget}`]), + '', +].join('\n') + +// Guard the contract itself: the host accepts a bundle only when it registers +// under the package name, so a regression here must fail the build, not the +// browser. +const leftover = wrapped + .split('\n') + .filter((line) => isTopLevel(line) && /^(?:import|export)\s/.test(line)) +if (leftover.length > 0) { + throw new Error(`build-client: ESM syntax survived the wrap:\n${leftover.join('\n')}`) +} +if (!wrapped.includes(MARKER) || !wrapped.includes(`id: ${JSON.stringify(pkgName)}`)) { + throw new Error('build-client: wrapped bundle does not register under the package name') +} + +writeFileSync(clientPath, wrapped) + +// Shift the source map by the wrapper prefix so mappings stay aligned. A run of +// empty generated segments is exactly "these lines have no mapping", which is +// true for the wrapper lines themselves. +let mapShifted = false +try { + const map = JSON.parse(readFileSync(mapPath, 'utf8')) + if (typeof map.mappings === 'string') { + map.mappings = `${';'.repeat(prefix.length)}${map.mappings}` + writeFileSync(mapPath, `${JSON.stringify(map)}\n`) + mapShifted = true + } +} catch { + // A missing source map is not fatal: the bundle contract does not need it. +} + +console.log( + `build-client: wrapped lib/client.js for __ModuleLoader__ ` + + `(${exported.length} exports, id ${pkgName}${mapShifted ? ', source map shifted' : ''})`, +) diff --git a/scripts/prepare.mjs b/scripts/prepare.mjs index 7494bb2..11e943e 100644 --- a/scripts/prepare.mjs +++ b/scripts/prepare.mjs @@ -14,6 +14,19 @@ const root = dirname(dirname(fileURLToPath(import.meta.url))) const lib = join(root, 'lib') const tsc = join(root, 'node_modules', 'typescript', 'bin', 'tsc') +// The client bundle must satisfy the browser module-loader contract, and `tsc` +// alone emits ESM that cannot register. Runs after either branch below; it is a +// no-op when the committed artifact is already wrapped. +const wrapClient = () => { + const wrap = spawnSync(process.execPath, [join(root, 'scripts', 'build-client.mjs')], { + cwd: root, + stdio: 'inherit', + }) + if (wrap.status !== 0) { + process.exit(typeof wrap.status === 'number' ? wrap.status : 1) + } +} + if (existsSync(tsc)) { const result = spawnSync(process.execPath, [tsc, '-p', 'tsconfig.json', '--noEmitOnError'], { cwd: root, @@ -31,11 +44,14 @@ if (existsSync(tsc)) { if (fix.status !== 0) { process.exit(typeof fix.status === 'number' ? fix.status : 1) } + wrapClient() process.exit(0) } if (existsSync(join(lib, 'index.js'))) { - // Committed build artifacts: usable without a compiler. + // Committed build artifacts: usable without a compiler. The wrap step still + // runs so a stale committed client bundle is repaired rather than shipped. + wrapClient() process.exit(0) } diff --git a/scripts/verify-artifacts.mjs b/scripts/verify-artifacts.mjs index 93face6..f44ff9e 100644 --- a/scripts/verify-artifacts.mjs +++ b/scripts/verify-artifacts.mjs @@ -5,8 +5,9 @@ // syntax leaking into shipped output and against a tarball missing the // bundle patch or the Action contract. import { execFileSync } from 'node:child_process' -import { existsSync } from 'node:fs' +import { existsSync, readFileSync } from 'node:fs' import path from 'node:path' +import { createContext, runInContext } from 'node:vm' import { fileURLToPath, pathToFileURL } from 'node:url' const root = path.dirname(path.dirname(fileURLToPath(import.meta.url))) @@ -14,6 +15,7 @@ const root = path.dirname(path.dirname(fileURLToPath(import.meta.url))) const required = [ 'lib/index.js', 'lib/index.d.ts', + 'lib/client.js', 'action.yml', 'cordis.patch.yml', ] @@ -22,6 +24,7 @@ for (const rel of required) { } execFileSync(process.execPath, ['--check', path.join(root, 'lib/index.js')], { stdio: 'inherit' }) +execFileSync(process.execPath, ['--check', path.join(root, 'lib/client.js')], { stdio: 'inherit' }) const index = await import(pathToFileURL(path.join(root, 'lib/index.js')).href) if ('default' in index) throw new Error('lib/index.js must not carry a default export') @@ -29,4 +32,37 @@ if (index.name !== 'dsh-github' || typeof index.apply !== 'function') { throw new Error('lib/index.js exports an unexpected plugin face') } -console.log('artifacts OK: syntax + ESM import + bundle patch and action contract present') +// The browser half must satisfy the host's lazy CJS module-loader contract: +// executing the bundle only REGISTERS a factory via window.__ModuleLoader__.load. +// A bundle that keeps top-level ESM bindings registers nothing and the browser +// reports `loaded without registering "" via __ModuleLoader__.load`, so the +// shipped client is executed here the way the loader executes it. +const manifest = JSON.parse(readFileSync(path.join(root, 'package.json'), 'utf8')) +const client = readFileSync(path.join(root, 'lib/client.js'), 'utf8') +for (const line of client.split('\n')) { + if (/^(?:import|export)\s/.test(line)) { + throw new Error(`lib/client.js carries top-level ESM that cannot register: ${line}`) + } +} + +const registrations = [] +runInContext(client, createContext({ + window: { __ModuleLoader__: { load: (entry) => registrations.push(entry) } }, +})) +if (registrations.length !== 1) { + throw new Error(`lib/client.js registered ${registrations.length} factories; expected exactly the package row`) +} +const [entry] = registrations +if (entry.id !== manifest.name) { + throw new Error(`lib/client.js registered "${entry.id}" but the package is "${manifest.name}"`) +} +const clientFace = entry.factory((specifier) => { + if (specifier === 'react') return { createElement: () => null, useState: (init) => [init, () => {}] } + if (specifier === '@deepseek-ai/dsh-client-ui-primitives') return { Button: () => null, IconLoadingOutlineRegular: () => null } + throw new Error(`lib/client.js requires undeclared module "${specifier}"`) +}) +if (typeof clientFace.apply !== 'function' || !Array.isArray(clientFace.inject)) { + throw new Error('lib/client.js exports an unexpected plugin face') +} + +console.log('artifacts OK: syntax + ESM import + module-loader registration + bundle patch and action contract present') diff --git a/test/client-bundle-contract.test.ts b/test/client-bundle-contract.test.ts new file mode 100644 index 0000000..ab672f6 --- /dev/null +++ b/test/client-bundle-contract.test.ts @@ -0,0 +1,105 @@ +/** + * Client bundle module-loader contract (pure static + one sandboxed run). + * + * The host's browser module system (`@deepseek-ai/dsh-client-modules`) is a lazy + * CJS table: executing a client bundle must only REGISTER a factory through + * `window.__ModuleLoader__.load({ id, factory })`, and every module body side + * effect lives inside that factory, which the loader materializes with a + * `require` of its own. A bundle that keeps its top-level `export` bindings + * registers nothing and the browser reports + * + * client-modules: could not load "": : + * loaded without registering "" via __ModuleLoader__.load + * + * `tsc` emits ESM, so `scripts/build-client.mjs` rewrites the compiled file. + * This test executes the SHIPPED artifact the way the loader does — run the + * bundle against a stub `__ModuleLoader__`, then materialize the captured + * factory with stub requires — so a regression in that rewrite fails here + * instead of in a browser. + * @module dsh-github/test/client-bundle-contract + */ + +import { readFileSync } from 'node:fs' +import { join } from 'node:path' +import { fileURLToPath } from 'node:url' +import { createContext, runInContext } from 'node:vm' +import { describe, expect, it } from 'vitest' + +const root = fileURLToPath(new URL('..', import.meta.url)) +const manifest = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8')) as { + name: string + dsh: { client: { inject?: string[] } } +} +const bundle = readFileSync(join(root, 'lib', 'client.js'), 'utf8') + +interface Registered { + id: string + factory: (require: (specifier: string) => unknown) => Record +} + +/** Run the bundle exactly as the browser loader does and return what it registered. */ +function loadBundle(): Registered { + const registrations: Registered[] = [] + const context = createContext({ + window: { + __ModuleLoader__: { + load: (entry: Registered) => { + registrations.push(entry) + }, + }, + }, + }) + runInContext(bundle, context) + expect(registrations, 'the bundle registered no factory').toHaveLength(1) + return registrations[0] +} + +/** The bundle's own two dependencies; anything else is an undeclared import. */ +function requireStub(specifier: string): unknown { + switch (specifier) { + case 'react': + return { createElement: () => null, useState: (initial: unknown) => [initial, () => {}] } + case '@deepseek-ai/dsh-client-ui-primitives': + return { Button: () => null, IconLoadingOutlineRegular: () => null } + default: + throw new Error( + `bundle required "${specifier}", which this test does not stub — ` + + 'declare it in dsh.client.inject and add it here', + ) + } +} + +describe('lib/client.js module-loader contract', () => { + it('carries no top-level ESM syntax', () => { + const offending = bundle + .split('\n') + .filter((line) => /^(?:import|export)\s/.test(line)) + expect(offending, 'top-level ESM survived the wrap').toEqual([]) + }) + + it('registers a factory under the package name', () => { + const entry = loadBundle() + expect(entry.id).toBe(manifest.name) + expect(typeof entry.factory).toBe('function') + }) + + it('materializes the plugin face the loader consumes', () => { + const exports = loadBundle().factory(requireStub) + expect(typeof exports.apply).toBe('function') + expect(exports.inject).toEqual(['slots', 'locale', 'connection', 'remote', 'remote.credentials']) + expect(exports.NS).toBe('dsh-github') + }) + + it('declares every module the bundle requires in dsh.client.inject', () => { + const inject = manifest.dsh.client.inject ?? [] + const required = [...bundle.matchAll(/require\((['"])([^'"]+)\1\)/g)].map((match) => match[2]) + expect(required.length, 'the bundle requires nothing — did the wrap drop its imports?').toBeGreaterThan(0) + for (const specifier of required) { + // A subpath such as `react/jsx-runtime` is answered by its package row. + const packageRow = specifier.startsWith('@') + ? specifier.split('/').slice(0, 2).join('/') + : specifier.split('/')[0] + expect(inject, `"${specifier}" is not declared in dsh.client.inject`).toContain(packageRow) + } + }) +}) From 5f588ec23fe7201632c62ffc34c4834e868418d1 Mon Sep 17 00:00:00 2001 From: womeimingzi11 Date: Fri, 2 Oct 2026 00:05:31 +0800 Subject: [PATCH 2/2] fix(client): mount the card on the bundle row, not the official list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The browser half took the page's `plugins.item` seat. That list is what the Plugins page renders through `renderGroup("official", …)` — the Official group, where the host's own settings plugins (agent-loop, shell, subagent, web-search) mount their cards — so this community bundle was presented as an official plugin instead of an installed one, while its bundle row sat in the Installed group with no configuration of its own. The card now takes this bundle row's seat, `plugins.row.config`, keyed `#` — the key the page's own `rowConfigKey` helper defines. Both seats hand the card the same props (`{ view, form }`; `submit` and the snapshot hook come from the card's own `inject`), so the component is unchanged. `plugins.bundle.config` is not the alternative: that seat is rendered with `{ view }` only — no `form` — and this card reads `tokenRef` from the form. - `PACKAGE_NAME` / `ROW_ID` / `ROW_CONFIG_KEY` are stated once so the seat key and `cordis.patch.yml` cannot drift apart. - `test/client-card-seat.test.ts` runs `apply` against a recording stub context and asserts the bundle registers `plugins.row.config` under the key derived from the patch, and never touches `plugins.item`. Verified against the real host on `0.2.0-rc.2`: the bundle the server returns for this row registers exactly `["plugins.row.config"]` with key `@perrylink/dsh-github#dsh-github`, and carries no `plugins.item` at all. --- CHANGELOG.md | 2 + lib/client.d.ts | 51 +++++++++++----- lib/client.d.ts.map | 2 +- lib/client.js | 60 +++++++++++++------ lib/client.js.map | 2 +- pnpm-lock.yaml | 2 +- src/client.ts | 59 +++++++++++++------ test/client-card-seat.test.ts | 108 ++++++++++++++++++++++++++++++++++ 8 files changed, 234 insertions(+), 52 deletions(-) create mode 100644 test/client-card-seat.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 03cb78c..845597a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,8 @@ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - **`dsh.client.inject` omitted two modules the browser half requires.** `src/client.ts` imports `react` and `@deepseek-ai/dsh-client-ui-primitives`, and neither was declared, so the module graph did not guarantee they arrive before this row materializes. Both are now listed. +- **The configuration card mounted in the Plugins page's Official group.** The browser half took the `plugins.item` seat, which the page renders through `renderGroup("official", …)` beside the host's own settings plugins (agent-loop, shell, subagent, web-search) — so this community bundle was presented as an official plugin rather than an installed one. The card now takes this bundle row's own seat, `plugins.row.config`, keyed `#`; both seats hand the card the same `{ view, form }` props, so the card itself is unchanged. `test/client-card-seat.test.ts` pins the seat and derives the key from `cordis.patch.yml` rather than restating it. + ### Changed - **The client bundle is now covered by the gates that were missing it.** `scripts/verify-artifacts.mjs` executed only the host face; it now also runs the shipped client bundle against a stub `__ModuleLoader__`, asserts it registers exactly once under the package name, materializes its factory, and rejects top-level ESM. `test/client-bundle-contract.test.ts` asserts the same contract as a unit test — the 0.7.14 lesson ("`lib/client.js` is a build artifact of `src/client.ts`, and nothing in the test suite renders it") applied to the half that had no gate at all. diff --git a/lib/client.d.ts b/lib/client.d.ts index e4da811..1e048d7 100644 --- a/lib/client.d.ts +++ b/lib/client.d.ts @@ -1,5 +1,6 @@ /** - * dsh-github browser half — one card in the Plugins page's Official group. + * dsh-github browser half — one card on this plugin's own row in the Plugins + * page's Installed group. * * The card reports and edits the GitHub token. The token literal never rides * the settings document: it is written through the credentials domain, @@ -8,13 +9,20 @@ * per operation, no restart needed. * * Since host 0.1.7-alpha.1 the page owns configuration: the card renders the - * `summary` one-liner and the `page` body from the `plugins.item` owner props - * (`view`, and the `form` the Plugins page supplies), instead of binding a - * `settingsScope` itself — that service, `settings.plugin.item`'s old shape, - * and the `dsh-settings-file` package behind them were all removed. The card - * therefore reads `tokenRef` from `form.state.value` and never writes the - * settings document; the credential is written through the credentials - * domain, which is a different seam and stayed. + * `summary` one-liner and the `page` body from the seat's props (`view`, and + * the `form` the Plugins page supplies for the row's own configuration entry), + * instead of binding a `settingsScope` itself — that service, + * `settings.plugin.item`'s old shape, and the `dsh-settings-file` package + * behind them were all removed. The card therefore reads `tokenRef` from + * `form.state.value` and never writes the settings document; the credential is + * written through the credentials domain, which is a different seam and stayed. + * + * The seat is this bundle's own row (`plugins.row.config`, keyed + * `#`) rather than the page's `plugins.item` list. That list is + * the page's **Official** group, where the host's own settings plugins mount, so + * a community bundle registering there is presented as an official plugin + * instead of an installed one. The row seat carries the same `{ view, form }` + * props, so the card itself is unchanged. * * The shipped `lib/client.js` is the built bundle of this module. The browser * module loader executes that bundle, not this file. @@ -236,11 +244,23 @@ export interface GithubCardProps { export declare function GithubCard(props: GithubCardProps): ReactNode; /** Dictionary namespace owned by this plugin. */ export declare const NS = "dsh-github"; +/** + * Package name the bundle patch installs this plugin under. The row + * configuration seat is keyed `#`, so this and {@link ROW_ID} + * must agree with the package name and row `id` that `cordis.patch.yml` + * declares. + */ +export declare const PACKAGE_NAME = "@perrylink/dsh-github"; +/** Row id the bundle patch declares for this plugin's configuration entry. */ +export declare const ROW_ID = "dsh-github"; +/** The `plugins.row.config` key this bundle's row mounts its card under. */ +export declare const ROW_CONFIG_KEY = "@perrylink/dsh-github#dsh-github"; /** * Required services (cordis fiber inject). `settingsScope` is gone: host * 0.1.7-alpha.1 removed it, and the Plugins page now hands the configuration - * form to the `plugins.item` entry instead. `@deepseek-ai/dsh-client-ui-plugin-manager` - * owns that slot, so it must be composed for the card to mount at all. + * form to the bundle row's `plugins.row.config` seat instead. + * `@deepseek-ai/dsh-client-ui-plugin-manager` owns that slot, so it must be + * composed for the card to mount at all. */ export declare const inject: string[]; export interface ClientContextLike { @@ -260,11 +280,14 @@ export interface ClientContextLike { }; } /** - * Mount the GitHub configuration card into the Plugins page's Official group. + * Mount the GitHub configuration card on this bundle's own row. * - * The form arrives per render, so the controller is rebuilt whenever the page - * supplies a different one — the page's own form owner stays authoritative and - * the card keeps no second copy of the accepted values. + * The card takes the row configuration seat (`plugins.row.config`), so it + * renders inside this plugin's row in the Plugins page's Installed group rather + * than in the page's Official list. The form arrives per render, so the + * controller is rebuilt whenever the page supplies a different one — the page's + * own form owner stays authoritative and the card keeps no second copy of the + * accepted values. * @param ctx - the browser plugin context. */ export declare function apply(ctx: ClientContextLike): void; diff --git a/lib/client.d.ts.map b/lib/client.d.ts.map index 45fa86c..b820eb1 100644 --- a/lib/client.d.ts.map +++ b/lib/client.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/lib/client.js b/lib/client.js index 194e5e8..5af3cfc 100644 --- a/lib/client.js +++ b/lib/client.js @@ -5,7 +5,8 @@ window.__ModuleLoader__.load({ var exports = module.exports; Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); /** - * dsh-github browser half — one card in the Plugins page's Official group. + * dsh-github browser half — one card on this plugin's own row in the Plugins + * page's Installed group. * * The card reports and edits the GitHub token. The token literal never rides * the settings document: it is written through the credentials domain, @@ -14,13 +15,20 @@ window.__ModuleLoader__.load({ * per operation, no restart needed. * * Since host 0.1.7-alpha.1 the page owns configuration: the card renders the - * `summary` one-liner and the `page` body from the `plugins.item` owner props - * (`view`, and the `form` the Plugins page supplies), instead of binding a - * `settingsScope` itself — that service, `settings.plugin.item`'s old shape, - * and the `dsh-settings-file` package behind them were all removed. The card - * therefore reads `tokenRef` from `form.state.value` and never writes the - * settings document; the credential is written through the credentials - * domain, which is a different seam and stayed. + * `summary` one-liner and the `page` body from the seat's props (`view`, and + * the `form` the Plugins page supplies for the row's own configuration entry), + * instead of binding a `settingsScope` itself — that service, + * `settings.plugin.item`'s old shape, and the `dsh-settings-file` package + * behind them were all removed. The card therefore reads `tokenRef` from + * `form.state.value` and never writes the settings document; the credential is + * written through the credentials domain, which is a different seam and stayed. + * + * The seat is this bundle's own row (`plugins.row.config`, keyed + * `#`) rather than the page's `plugins.item` list. That list is + * the page's **Official** group, where the host's own settings plugins mount, so + * a community bundle registering there is presented as an official plugin + * instead of an installed one. The row seat carries the same `{ view, form }` + * props, so the card itself is unchanged. * * The shipped `lib/client.js` is the built bundle of this module. The browser * module loader executes that bundle, not this file. @@ -259,19 +267,34 @@ window.__ModuleLoader__.load({ } /** Dictionary namespace owned by this plugin. */ const NS = 'dsh-github'; + /** + * Package name the bundle patch installs this plugin under. The row + * configuration seat is keyed `#`, so this and {@link ROW_ID} + * must agree with the package name and row `id` that `cordis.patch.yml` + * declares. + */ + const PACKAGE_NAME = '@perrylink/dsh-github'; + /** Row id the bundle patch declares for this plugin's configuration entry. */ + const ROW_ID = 'dsh-github'; + /** The `plugins.row.config` key this bundle's row mounts its card under. */ + const ROW_CONFIG_KEY = `${PACKAGE_NAME}#${ROW_ID}`; /** * Required services (cordis fiber inject). `settingsScope` is gone: host * 0.1.7-alpha.1 removed it, and the Plugins page now hands the configuration - * form to the `plugins.item` entry instead. `@deepseek-ai/dsh-client-ui-plugin-manager` - * owns that slot, so it must be composed for the card to mount at all. + * form to the bundle row's `plugins.row.config` seat instead. + * `@deepseek-ai/dsh-client-ui-plugin-manager` owns that slot, so it must be + * composed for the card to mount at all. */ const inject = ['slots', 'locale', 'connection', 'remote', 'remote.credentials']; /** - * Mount the GitHub configuration card into the Plugins page's Official group. + * Mount the GitHub configuration card on this bundle's own row. * - * The form arrives per render, so the controller is rebuilt whenever the page - * supplies a different one — the page's own form owner stays authoritative and - * the card keeps no second copy of the accepted values. + * The card takes the row configuration seat (`plugins.row.config`), so it + * renders inside this plugin's row in the Plugins page's Installed group rather + * than in the page's Official list. The form arrives per render, so the + * controller is rebuilt whenever the page supplies a different one — the page's + * own form owner stays authoritative and the card keeps no second copy of the + * accepted values. * @param ctx - the browser plugin context. */ function apply(ctx) { @@ -285,9 +308,9 @@ window.__ModuleLoader__.load({ return github; }; ctx.effect(() => ctx.remote.$on('credentials/reference-updated', (ref) => github?.refreshCredential(ref)), 'dsh-github: credential invalidations'); - ctx.slots.inject('plugins.item', () => ctx.slots.register({ - name: 'plugins.item', - id: NS, + ctx.slots.inject('plugins.row.config', () => ctx.slots.register({ + name: 'plugins.row.config', + key: ROW_CONFIG_KEY, order: 100, label: () => t('githubTitle'), locale: NS, @@ -302,6 +325,9 @@ window.__ModuleLoader__.load({ exports.GithubCardController = GithubCardController; exports.GithubCard = GithubCard; exports.NS = NS; + exports.PACKAGE_NAME = PACKAGE_NAME; + exports.ROW_ID = ROW_ID; + exports.ROW_CONFIG_KEY = ROW_CONFIG_KEY; exports.inject = inject; exports.apply = apply; return module.exports; diff --git a/lib/client.js.map b/lib/client.js.map index 636b4c2..4cca12a 100644 --- a/lib/client.js.map +++ b/lib/client.js.map @@ -1 +1 @@ -{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"} +{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":";;;;;;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAoC,MAAM,OAAO,CAAA;AACjF,OAAO,EACL,MAAM,EAAE,yBAAyB,GAClC,MAAM,uCAAuC,CAAA;AA+D9C;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAI,IAAO;IAC5C,IAAI,KAAK,GAAG,IAAI,CAAA;IAChB,MAAM,SAAS,GAAG,IAAI,GAAG,EAAc,CAAA;IACvC,OAAO;QACL,WAAW,EAAE,GAAG,EAAE,CAAC,KAAK;QACxB,SAAS,EAAE,CAAC,QAAQ,EAAE,EAAE;YACtB,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;YACvB,OAAO,GAAG,EAAE,GAAG,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA,CAAC,CAAC,CAAA;QAC7C,CAAC;QACD,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE;YACZ,KAAK,GAAG,IAAI,CAAA;YACZ,KAAK,MAAM,QAAQ,IAAI,CAAC,GAAG,SAAS,CAAC;gBAAE,QAAQ,EAAE,CAAA;QACnD,CAAC;KACF,CAAA;AACH,CAAC;AAED,iIAAiI;AACjI,MAAM,CAAC,MAAM,SAAS,GAAG,YAAY,CAAA;AACrC,oFAAoF;AACpF,MAAM,CAAC,MAAM,iBAAiB,GAAG,cAAc,CAAA;AAkB/C,oBAAoB;AACpB,MAAM,CAAC,MAAM,EAAE,GAAqB;IAClC,WAAW,EAAE,QAAQ;IACrB,iBAAiB,EAAE,yDAAyD;IAC5E,UAAU,EAAE,cAAc;IAC1B,SAAS,EAAE,uGAAuG;IAClH,QAAQ,EAAE,wBAAwB;IAClC,UAAU,EAAE,oEAAoE;IAChF,OAAO,EAAE,SAAS;IAClB,QAAQ,EAAE,4CAA4C;IACtD,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,SAAS;IACjB,OAAO,EAAE,SAAS;IAClB,UAAU,EAAE,2EAA2E;CACxF,CAAA;AAED,+BAA+B;AAC/B,MAAM,CAAC,MAAM,EAAE,GAAqB;IAClC,WAAW,EAAE,QAAQ;IACrB,iBAAiB,EAAE,qCAAqC;IACxD,UAAU,EAAE,cAAc;IAC1B,SAAS,EAAE,kCAAkC;IAC7C,QAAQ,EAAE,QAAQ;IAClB,UAAU,EAAE,0BAA0B;IACtC,OAAO,EAAE,KAAK;IACd,QAAQ,EAAE,YAAY;IACtB,IAAI,EAAE,IAAI;IACV,MAAM,EAAE,MAAM;IACd,OAAO,EAAE,MAAM;IACf,UAAU,EAAE,oBAAoB;CACjC,CAAA;AAqDD;;;;;;GAMG;AACH,MAAM,OAAO,oBAAoB;IACd,IAAI,CAA0C;IAC9C,GAAG,CAAgB;IACnB,KAAK,CAAgC;IAC9C,MAAM,GAAG,KAAK,CAAA;IACd,MAAM,GAAG,KAAK,CAAA;IACd,UAAU,GAA4D,EAAE,GAAG,EAAE,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAA;IAE5H;;;;;OAKG;IACH,YAAY,IAA8C,EAAE,GAAmB;QAC7E,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAA;QACd,IAAI,CAAC,KAAK,GAAG,mBAAmB,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAA;QACnD,IAAI,EAAE,SAAS,CAAC,GAAG,EAAE;YACnB,KAAK,IAAI,CAAC,cAAc,EAAE,CAAA;YAC1B,IAAI,CAAC,OAAO,EAAE,CAAA;QAChB,CAAC,CAAC,CAAA;QACF,KAAK,IAAI,CAAC,cAAc,EAAE,CAAA;IAC5B,CAAC;IAED,8DAA8D;IAC9D,QAAQ;QACN,OAAO,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,CAAC,QAAQ,IAAI,IAAI,CAAA;IAClD,CAAC;IAED,sFAAsF;IACtF,MAAM;QACJ,OAAO,IAAI,CAAC,IAAI,CAAA;IAClB,CAAC;IAED,4DAA4D;IAC5D,UAAU;QACR,OAAO;YACL,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE;YACzB,UAAU,EAAE,IAAI,CAAC,UAAU,CAAC,UAAU;YACtC,kBAAkB,EAAE,IAAI,CAAC,UAAU,CAAC,QAAQ;YAC5C,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,GAAG,EAAE,IAAI,CAAC,UAAU,CAAC,GAAG;SACzB,CAAA;IACH,CAAC;IAED,iFAAiF;IACjF,KAAK;QACH,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAA;QACzD,OAAO,QAAQ,KAAK,SAAS,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,iBAAiB,CAAA;IACrF,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,cAAc;QAClB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,EAAE,CAAA;QACxB,IAAI,GAAG,KAAK,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC;YAChC,IAAI,CAAC,UAAU,GAAG,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAA;YAC5D,IAAI,CAAC,OAAO,EAAE,CAAA;QAChB,CAAC;QACD,IAAI,QAAQ,CAAA;QACZ,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;QAC3C,CAAC;QAAC,MAAM,CAAC;YACP,OAAM;QACR,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,GAAG,KAAK,IAAI,CAAC,KAAK,EAAE;YAAE,OAAM;QAChD,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QAChC,MAAM,IAAI,GAAG,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,IAAI,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,IAAI,IAAI,EAAE,CAAA;QAC7F,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI,CAAC,UAAU,CAAC,UAAU,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,UAAU,CAAC,QAAQ;YAAE,OAAM;QACxG,IAAI,CAAC,UAAU,GAAG,IAAI,CAAA;QACtB,IAAI,CAAC,OAAO,EAAE,CAAA;IAChB,CAAC;IAED;;;;;OAKG;IACH,iBAAiB,CAAC,GAAW;QAC3B,IAAI,GAAG,KAAK,IAAI,CAAC,UAAU,CAAC,GAAG;YAAE,OAAM;QACvC,KAAK,IAAI,CAAC,cAAc,EAAE,CAAA;IAC5B,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,IAAI,CAAC,KAAa;QACtB,MAAM,IAAI,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;QACjC,IAAI,IAAI,KAAK,EAAE,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO,KAAK,CAAA;QAC5C,IAAI,CAAC,MAAM,GAAG,IAAI,CAAA;QAClB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;QACnB,IAAI,CAAC,OAAO,EAAE,CAAA;QACd,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,CAAA;QACxC,CAAC;QAAC,MAAM,CAAC;YACP,mDAAmD;QACrD,CAAC;QACD,MAAM,IAAI,CAAC,cAAc,EAAE,CAAA;QAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,UAAU,CAAA;QACzC,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;QACnB,IAAI,CAAC,MAAM,GAAG,CAAC,MAAM,CAAA;QACrB,IAAI,CAAC,OAAO,EAAE,CAAA;QACd,OAAO,MAAM,CAAA;IACf,CAAC;IAED,2DAA2D;IAC3D,MAAM;QACJ,OAAO;YACL,KAAK,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,KAAK,EAAE;YACjC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;SACpC,CAAA;IACH,CAAC;IAEO,OAAO;QACb,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAA;IACnC,CAAC;CACF;AAWD;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,KAAsB;IAC/C,MAAM,EAAE,CAAC,EAAE,GAAG,KAAK,CAAA;IACnB,MAAM,KAAK,GAAG,KAAK,CAAC,aAAa,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAA;IACzD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAA;IACtC,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO,aAAa,CAClB,MAAM,EACN,EAAE,SAAS,EAAE,aAAa,EAAE,EAC5B,aAAa,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,mBAAmB,CAAC,CAAC,EACnD,aAAa,CACX,MAAM,EACN,EAAE,SAAS,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,gBAAgB,EAAE,EAChE,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CACnD,CACF,CAAA;IACH,CAAC;IACD,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,CAAA;IACjC,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;IACxD,OAAO,aAAa,CAClB,KAAK,EACL,EAAE,SAAS,EAAE,uBAAuB,EAAE,EACtC,CAAC,KAAK,CAAC,QAAQ;QACb,CAAC,CAAC,aAAa,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,cAAc,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC;QAClF,CAAC,CAAC,IAAI,EACR,aAAa,CACX,KAAK,EACL,EAAE,SAAS,EAAE,WAAW,EAAE,EAC1B,aAAa,CACX,KAAK,EACL,EAAE,SAAS,EAAE,UAAU,EAAE,EACzB,aAAa,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,WAAW,EAAE,OAAO,EAAE,4BAA4B,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,EAC1G,aAAa,CACX,MAAM,EACN,EAAE,SAAS,EAAE,YAAY,EAAE,EAC3B,aAAa,CACX,MAAM,EACN,EAAE,SAAS,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,gBAAgB,EAAE,EAChE,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CACnD,CACF,CACF,EACD,aAAa,CAAC,OAAO,EAAE;QACrB,EAAE,EAAE,4BAA4B;QAChC,SAAS,EAAE,WAAW;QACtB,IAAI,EAAE,UAAU;QAChB,YAAY,EAAE,KAAK;QACnB,KAAK,EAAE,KAAK;QACZ,QAAQ,EAAE,CAAC,KAAK,CAAC,kBAAkB;QACnC,QAAQ,EAAE,CAAC,KAAoC,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC;KACjF,CAAC,EACF,aAAa,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAC9D,EACD,aAAa,CACX,KAAK,EACL,EAAE,SAAS,EAAE,aAAa,EAAE,EAC5B,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EACtG,aAAa,CACX,MAAM,EACN;QACE,OAAO,EAAE,OAAO;QAChB,IAAI,EAAE,IAAI;QACV,QAAQ,EAAE,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM;QAChC,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC;KAC5B,EACD,CAAC,CAAC,SAAS,CAAC,CACb,EACD,aAAa,CACX,MAAM,EACN;QACE,OAAO,EAAE,SAAS;QAClB,IAAI,EAAE,IAAI;QACV,QAAQ,EAAE,CAAC,KAAK,CAAC,QAAQ,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM;QACnD,IAAI,EAAE,KAAK,CAAC,MAAM;YAChB,CAAC,CAAC,aAAa,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,EAAE,aAAa,CAAC,yBAAyB,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;YAC1G,CAAC,CAAC,SAAS;QACb,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;YACxC,IAAI,MAAM;gBAAE,QAAQ,CAAC,EAAE,CAAC,CAAA;QAC1B,CAAC;KACF,EACD,SAAS,CACV,CACF,CACF,CAAA;AACH,CAAC;AAED,iDAAiD;AACjD,MAAM,CAAC,MAAM,EAAE,GAAG,YAAY,CAAA;AAC9B;;;;;GAKG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,uBAAuB,CAAA;AACnD,8EAA8E;AAC9E,MAAM,CAAC,MAAM,MAAM,GAAG,YAAY,CAAA;AAClC,4EAA4E;AAC5E,MAAM,CAAC,MAAM,cAAc,GAAG,GAAG,YAAY,IAAI,MAAM,EAAE,CAAA;AACzD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,oBAAoB,CAAC,CAAA;AAyBvF;;;;;;;;;;GAUG;AACH,MAAM,UAAU,KAAK,CAAC,GAAsB;IAC1C,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAC7B,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,+BAA+B,CAAC,CAAA;IACtF,IAAI,MAAwC,CAAA;IAC5C,MAAM,aAAa,GAAG,CAAC,IAAmC,EAAwB,EAAE;QAClF,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC;YACrD,MAAM,GAAG,IAAI,oBAAoB,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;QACjE,CAAC;QACD,OAAO,MAAM,CAAA;IACf,CAAC,CAAA;IACD,GAAG,CAAC,MAAM,CACR,GAAG,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,+BAA+B,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,EAAE,iBAAiB,CAAC,GAAG,CAAC,CAAC,EAC9F,sCAAsC,CACvC,CAAA;IACD,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,oBAAoB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAC7D;QACE,IAAI,EAAE,oBAAoB;QAC1B,GAAG,EAAE,cAAc;QACnB,KAAK,EAAE,GAAG;QACV,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC;QAC7B,MAAM,EAAE,EAAE;QACV,MAAM,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;KACvD,EACD,UAAU,CACX,CAAC,CAAA;AACJ,CAAC"} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 250ea3e..6b4612c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -514,7 +514,7 @@ importers: .: dependencies: '@deepseek-ai/dsh-client-ui-plugin-manager': - specifier: '>=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0' + specifier: '>=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0 || >=0.2.0-rc.1 <0.3.0-0' version: 0.1.6-alpha.2(@deepseek-ai/cordis@4.0.4) '@deepseek-ai/dsh-client-ui-primitives': specifier: 0.1.7-rc.2 diff --git a/src/client.ts b/src/client.ts index 32ae7b3..c54709b 100644 --- a/src/client.ts +++ b/src/client.ts @@ -1,5 +1,6 @@ /** - * dsh-github browser half — one card in the Plugins page's Official group. + * dsh-github browser half — one card on this plugin's own row in the Plugins + * page's Installed group. * * The card reports and edits the GitHub token. The token literal never rides * the settings document: it is written through the credentials domain, @@ -8,13 +9,20 @@ * per operation, no restart needed. * * Since host 0.1.7-alpha.1 the page owns configuration: the card renders the - * `summary` one-liner and the `page` body from the `plugins.item` owner props - * (`view`, and the `form` the Plugins page supplies), instead of binding a - * `settingsScope` itself — that service, `settings.plugin.item`'s old shape, - * and the `dsh-settings-file` package behind them were all removed. The card - * therefore reads `tokenRef` from `form.state.value` and never writes the - * settings document; the credential is written through the credentials - * domain, which is a different seam and stayed. + * `summary` one-liner and the `page` body from the seat's props (`view`, and + * the `form` the Plugins page supplies for the row's own configuration entry), + * instead of binding a `settingsScope` itself — that service, + * `settings.plugin.item`'s old shape, and the `dsh-settings-file` package + * behind them were all removed. The card therefore reads `tokenRef` from + * `form.state.value` and never writes the settings document; the credential is + * written through the credentials domain, which is a different seam and stayed. + * + * The seat is this bundle's own row (`plugins.row.config`, keyed + * `#`) rather than the page's `plugins.item` list. That list is + * the page's **Official** group, where the host's own settings plugins mount, so + * a community bundle registering there is presented as an official plugin + * instead of an installed one. The row seat carries the same `{ view, form }` + * props, so the card itself is unchanged. * * The shipped `lib/client.js` is the built bundle of this module. The browser * module loader executes that bundle, not this file. @@ -449,11 +457,23 @@ export function GithubCard(props: GithubCardProps): ReactNode { /** Dictionary namespace owned by this plugin. */ export const NS = 'dsh-github' +/** + * Package name the bundle patch installs this plugin under. The row + * configuration seat is keyed `#`, so this and {@link ROW_ID} + * must agree with the package name and row `id` that `cordis.patch.yml` + * declares. + */ +export const PACKAGE_NAME = '@perrylink/dsh-github' +/** Row id the bundle patch declares for this plugin's configuration entry. */ +export const ROW_ID = 'dsh-github' +/** The `plugins.row.config` key this bundle's row mounts its card under. */ +export const ROW_CONFIG_KEY = `${PACKAGE_NAME}#${ROW_ID}` /** * Required services (cordis fiber inject). `settingsScope` is gone: host * 0.1.7-alpha.1 removed it, and the Plugins page now hands the configuration - * form to the `plugins.item` entry instead. `@deepseek-ai/dsh-client-ui-plugin-manager` - * owns that slot, so it must be composed for the card to mount at all. + * form to the bundle row's `plugins.row.config` seat instead. + * `@deepseek-ai/dsh-client-ui-plugin-manager` owns that slot, so it must be + * composed for the card to mount at all. */ export const inject = ['slots', 'locale', 'connection', 'remote', 'remote.credentials'] @@ -474,18 +494,21 @@ export interface ClientContextLike { } } -/** The `form` member the Plugins page hands a `plugins.item` entry. */ +/** The `form` member the Plugins page hands a `plugins.row.config` entry. */ interface PluginConfigViewProps { readonly view: 'summary' | 'page' readonly form?: ConfigForm | undefined } /** - * Mount the GitHub configuration card into the Plugins page's Official group. + * Mount the GitHub configuration card on this bundle's own row. * - * The form arrives per render, so the controller is rebuilt whenever the page - * supplies a different one — the page's own form owner stays authoritative and - * the card keeps no second copy of the accepted values. + * The card takes the row configuration seat (`plugins.row.config`), so it + * renders inside this plugin's row in the Plugins page's Installed group rather + * than in the page's Official list. The form arrives per render, so the + * controller is rebuilt whenever the page supplies a different one — the page's + * own form owner stays authoritative and the card keeps no second copy of the + * accepted values. * @param ctx - the browser plugin context. */ export function apply(ctx: ClientContextLike): void { @@ -502,10 +525,10 @@ export function apply(ctx: ClientContextLike): void { () => ctx.remote.$on('credentials/reference-updated', (ref) => github?.refreshCredential(ref)), 'dsh-github: credential invalidations', ) - ctx.slots.inject('plugins.item', () => ctx.slots.register( + ctx.slots.inject('plugins.row.config', () => ctx.slots.register( { - name: 'plugins.item', - id: NS, + name: 'plugins.row.config', + key: ROW_CONFIG_KEY, order: 100, label: () => t('githubTitle'), locale: NS, diff --git a/test/client-card-seat.test.ts b/test/client-card-seat.test.ts new file mode 100644 index 0000000..7d5cdc4 --- /dev/null +++ b/test/client-card-seat.test.ts @@ -0,0 +1,108 @@ +/** + * Where the browser half mounts its card (pure static + one sandboxed run). + * + * The Plugins page declares three configuration seats and groups them apart: + * `plugins.item` is rendered by `renderGroup("official", …)` — the Official + * group, where the host's own settings plugins (agent-loop, shell, subagent, + * web-search) mount their cards — while `plugins.row.config` renders inside one + * bundle row's own detail view, in the Installed group. A community bundle that + * takes the `plugins.item` seat is therefore presented as an official plugin + * instead of an installed one. + * + * Both seats hand the card the same `{ view, form }` props, so the deployment + * that keeps the official list clean is a change of seat, not of card. This test + * pins that: the bundle must register `plugins.row.config` under this package's + * own row key, and must not touch `plugins.item`. + * @module dsh-github/test/client-card-seat + */ + +import { readFileSync } from 'node:fs' +import { join } from 'node:path' +import { fileURLToPath } from 'node:url' +import { createContext, runInContext } from 'node:vm' +import { describe, expect, it } from 'vitest' + +const root = fileURLToPath(new URL('..', import.meta.url)) +const manifest = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8')) as { name: string } +const patch = readFileSync(join(root, 'cordis.patch.yml'), 'utf8') +const bundle = readFileSync(join(root, 'lib', 'client.js'), 'utf8') + +/** The row id the bundle patch declares, read from the patch rather than restated. */ +function declaredRowIds(): string[] { + return [...patch.matchAll(/^\s*-\s*id:\s*(\S+)\s*$/gm)].map((match) => match[1]) +} + +interface Registration { + options: Record +} + +/** Materialize the bundle and run its `apply` against a recording stub context. */ +function applyCard(): { injected: string[]; registrations: Registration[] } { + const registrations: Registration[] = [] + const injected: string[] = [] + const registered: Array<{ + id: string + factory: (require: (specifier: string) => unknown) => Record + }> = [] + const context = createContext({ + window: { + __ModuleLoader__: { + load: (entry: (typeof registered)[number]) => { + registered.push(entry) + }, + }, + }, + }) + runInContext(bundle, context) + const face = registered[0].factory((specifier: string) => { + if (specifier === 'react') return { createElement: () => null, useState: (init: unknown) => [init, () => {}] } + if (specifier === '@deepseek-ai/dsh-client-ui-primitives') { + return { Button: () => null, IconLoadingOutlineRegular: () => null } + } + throw new Error(`undeclared require: ${specifier}`) + }) + + const ctx = { + get: () => undefined, + effect: () => {}, + locale: { bind: () => (key: string) => key, register: () => {} }, + remote: { + $on: () => ({}), + credentials: { + describe: async () => ({ ok: true, value: {} }), + set: async () => ({ ok: true }), + }, + }, + slots: { + inject: (slot: string, factory: () => unknown) => { + injected.push(slot) + factory() + }, + register: (options: Record) => { + registrations.push({ options }) + }, + }, + } + ;(face.apply as (context: unknown) => void)(ctx) + return { injected, registrations } +} + +describe('client card seat', () => { + it('mounts on the bundle row, not in the official plugins list', () => { + const { injected } = applyCard() + expect(injected).toContain('plugins.row.config') + expect(injected, 'the official list is for the host’s own settings plugins').not.toContain('plugins.item') + }) + + it('keys the row seat to the package and the row the patch declares', () => { + const { registrations } = applyCard() + expect(registrations).toHaveLength(1) + const [registration] = registrations + expect(registration.options.name).toBe('plugins.row.config') + expect(registration.options.key).toBe(`${manifest.name}#${declaredRowIds()[0]}`) + }) + + it('declares a single constant row so the key stays derivable', () => { + expect(declaredRowIds()).toEqual(['dsh-github']) + }) +})