@javierfrancoleal/plugin-authoring 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -131,8 +131,9 @@ Rules:
131
131
 
132
132
  | Slot | Alcance | Para qué |
133
133
  |---|---|---|
134
- | `shell.bottom` | root | **global full-width bottom bar** (empty by default) |
135
- | `shell.overlay` / `shell.leading` | root | overlay / top-left corner |
134
+ | `shell.bottom` | root | **global full-width bottom bar** (empty by default) — **single: a 2nd occupant THROWS** |
135
+ | `shell.overlay` | root | **list (additive)** — overlays/pills without conflict |
136
+ | `shell.leading` | root | top-left corner (macOS) |
136
137
  | `sidebar` / `rightbar` / `main` | root | columns / central panel |
137
138
  | `conversation.input.dock` | sesión | bar above the composer |
138
139
 
@@ -149,11 +150,78 @@ Rules:
149
150
 
150
151
  ## Install into the running app
151
152
 
153
+ **A) From npm** (another machine/profile without the local checkout):
154
+
155
+ ```bash
156
+ dsh plugin --profile <perfil> add @javierfrancoleal/mi-plugin
157
+ ```
158
+
159
+ This adds the dependency + bundle and runs pnpm for you; restart the app after.
160
+
161
+ **B) Local (`link:`) — developing in the monorepo:**
162
+
152
163
  1. `~/.dsh/profiles/<perfil>/package.json`: add `"@scope/nombre": "link:/abs/path"` to
153
164
  `dependencies` and `"@scope/nombre"` to `dsh.profile.bundles`.
154
165
  2. `cd ~/.dsh/profiles/<perfil> && pnpm install`.
155
166
  3. **Restart the app** (a new bundle needs a host recomposition).
156
167
 
168
+ ## Dynamic host→client data (Remote/Typert)
169
+
170
+ When the client needs changing data (balance, host state…), expose a **Remote** on
171
+ the host and read it from the client. Verified recipe (`jfranco-balance`,
172
+ 2026-11-04); `dsh-goal` uses a code generator that a `link:` without build cannot
173
+ use, so write everything by hand:
174
+
175
+ **Host** (`lib/index.js`):
176
+
177
+ ```js
178
+ import { TypertRemoteService } from "@deepseek-ai/dsh-typert-protocol";
179
+
180
+ class MiService extends TypertRemoteService {
181
+ constructor(ctx) { super(ctx, "miServicio"); this.ctx = ctx; }
182
+ async getSnapshot() { /* JSON-serializable object */ }
183
+ }
184
+ const MARKER = "@deepseek-ai/dsh-typert-protocol/remote-methods";
185
+ Object.defineProperty(MiService.prototype, MARKER, {
186
+ configurable: true,
187
+ value: Object.freeze({ version: 1, methods: Object.freeze([
188
+ Object.freeze({ method: "getSnapshot", invocation: Object.freeze({ kind: "direct" }) }),
189
+ ]) }),
190
+ });
191
+ export default MiService; // default export = the Cordis plugin
192
+ ```
193
+
194
+ The gateway's SRC discovery exposes endpoint `miServicio/getSnapshot` with no
195
+ generated `./typert` artifact.
196
+
197
+ **Client** (`lib/client.js`):
198
+
199
+ ```js
200
+ const inject = ["slots", "locale", "remote"];
201
+ const CONTRIBUTION = {
202
+ package: "@javierfrancoleal/mi-plugin",
203
+ descriptors: [{
204
+ id: "@javierfrancoleal/mi-plugin#miServicio/getSnapshot",
205
+ service: "miServicio", namespace: "miServicio", method: "getSnapshot",
206
+ invocation: { kind: "direct" }, parameters: [], result: { mode: "src-json" },
207
+ }],
208
+ };
209
+ async function apply(ctx) {
210
+ await ctx.remote.$mount(CONTRIBUTION);
211
+ const handle = ctx.get("remote.miServicio");
212
+ const res = await handle.getSnapshot(); // { ok: true, value } | { ok: false, error }
213
+ }
214
+ ```
215
+
216
+ **DeepSeek credentials** (authenticated APIs, e.g. `GET /user/balance`):
217
+
218
+ - API key: `ctx.get("credentials").resolve("DEEPSEEK_API_KEY")` → `{ value }`
219
+ (header `Authorization: Bearer <key>`).
220
+ - Account token (fallback, live-verified 2026-11-04):
221
+ `ctx.get("deepseekAccount").resolveToken("https://api.deepseek.com")` →
222
+ header `x-dsh-auth-token`. `/user/balance` accepts it, so the plugin works
223
+ with account sign-in.
224
+
157
225
  ## Gotchas
158
226
 
159
227
  1. The checkout lives inside `app.asar` — use `_dsh-inspect/asar-tool.mjs list|extract`.
@@ -162,6 +230,10 @@ Rules:
162
230
  3. New bundles are NOT picked up by HMR on external edits — restart the app.
163
231
  4. `dsh.bundle.patch` + `dsh.client` can coexist (dual-face).
164
232
  5. React / slots / primitives are baseline; don't list them in `dsh.client.inject`.
233
+ 6. **Bundle URLs are revisioned**: the real form is
234
+ `/plugins/??<id>/client.js&rev=<sha1(mtime:ctime:size)[0:12]>`; the bare
235
+ `/plugins/<id>/client.js` **always 404s**. Get the `rev` from the root HTML.
236
+ 7. **The app may change port after a restart** — re-read the advertised URL.
165
237
 
166
238
  ## Validation checklist
167
239
 
@@ -169,7 +241,8 @@ Rules:
169
241
  node --check lib/index.js && node --check lib/client.js
170
242
  node tools/check-client.mjs lib/client.js
171
243
  dsh --profile testprices --dump-config | grep mi-plugin # throwaway profile, not desktop
172
- curl -sS http://127.0.0.1:<puerto>/plugins/@scope/mi-plugin/client.js # 200 after restart
244
+ curl -sS http://127.0.0.1:<puerto>/ | grep -o "mi-plugin/client[^\"']*" # find your rev
245
+ curl -sS "http://127.0.0.1:<puerto>/plugins/??@scope/mi-plugin/client.js&rev=<rev>" # 200
173
246
  ```
174
247
 
175
248
  Full reference: `docs/PLUGIN-AUTHORING.md`. Template: `templates/dsh-plugin/`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@javierfrancoleal/plugin-authoring",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Plugin-authoring skill for DeepSeek Harness: the distilled anatomy, client-UI recipe, slots, locale, theme tokens, install steps, gotchas, and validation checklist for building and publishing new DSH plugins.",
5
5
  "author": "J.Franco",
6
6
  "license": "MIT",