@senpi/runtime 1.1.0-dev.runtime-phase-2.20260513122539 → 1.1.0-dev.runtime-phase-2.20260514134437

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.
Files changed (42) hide show
  1. package/dist/cli/senpi-cli-config.d.ts +15 -1
  2. package/dist/cli/senpi-cli-config.d.ts.map +1 -1
  3. package/dist/cli/senpi-cli-config.js +19 -2
  4. package/dist/cli/senpi-cli-config.js.map +1 -1
  5. package/dist/cli/senpi-commands.d.ts.map +1 -1
  6. package/dist/cli/senpi-commands.js +4 -1
  7. package/dist/cli/senpi-commands.js.map +1 -1
  8. package/dist/index.d.ts +17 -3
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +32 -10
  11. package/dist/index.js.map +1 -1
  12. package/dist/runtime/auto-update/coordinator.d.ts +13 -0
  13. package/dist/runtime/auto-update/coordinator.d.ts.map +1 -1
  14. package/dist/runtime/auto-update/coordinator.js +14 -0
  15. package/dist/runtime/auto-update/coordinator.js.map +1 -1
  16. package/dist/skills-manager/bootstrap.d.ts.map +1 -1
  17. package/dist/skills-manager/bootstrap.js +34 -16
  18. package/dist/skills-manager/bootstrap.js.map +1 -1
  19. package/dist/skills-manager/constants.d.ts +20 -1
  20. package/dist/skills-manager/constants.d.ts.map +1 -1
  21. package/dist/skills-manager/constants.js +26 -1
  22. package/dist/skills-manager/constants.js.map +1 -1
  23. package/dist/skills-manager/coordinator.d.ts +147 -20
  24. package/dist/skills-manager/coordinator.d.ts.map +1 -1
  25. package/dist/skills-manager/coordinator.js +260 -86
  26. package/dist/skills-manager/coordinator.js.map +1 -1
  27. package/dist/skills-manager/state-store.d.ts +27 -4
  28. package/dist/skills-manager/state-store.d.ts.map +1 -1
  29. package/dist/skills-manager/state-store.js +42 -16
  30. package/dist/skills-manager/state-store.js.map +1 -1
  31. package/dist/skills-manager/types.d.ts +46 -8
  32. package/dist/skills-manager/types.d.ts.map +1 -1
  33. package/dist/skills-manager/utils.d.ts +17 -0
  34. package/dist/skills-manager/utils.d.ts.map +1 -1
  35. package/dist/skills-manager/utils.js +43 -11
  36. package/dist/skills-manager/utils.js.map +1 -1
  37. package/dist/skills-manager/version-manager.d.ts +93 -8
  38. package/dist/skills-manager/version-manager.d.ts.map +1 -1
  39. package/dist/skills-manager/version-manager.js +185 -28
  40. package/dist/skills-manager/version-manager.js.map +1 -1
  41. package/openclaw.plugin.json +7 -9
  42. package/package.json +1 -1
@@ -1,20 +1,29 @@
1
1
  /**
2
2
  * Central lifecycle manager for Senpi skills auto-update.
3
3
  *
4
- * Mirrors AutoUpdateCoordinator from src/runtime/auto-update/coordinator.ts:
5
- * same runToken + stopped + running triple for thread-safety, same
6
- * self-managed setTimeout loop, same injectable-dependency pattern for
7
- * testability.
4
+ * Mirrors AutoUpdateCoordinator from src/runtime/auto-update/coordinator.ts
5
+ * for thread-safety (runToken + stopped + running triple) and uses the same
6
+ * injectable-dependency pattern for testability.
8
7
  *
9
- * On start(): bootstrap missing skills then schedule the first poll.
10
- * Each tick(): resolve skill names, check remote versions in parallel,
11
- * auto-apply patch/minor, notify on major (deduped), skip on none/unknown.
8
+ * Scheduling: this coordinator does not own a timer. Ticks fire from
9
+ * outside — currently from auto-update's `onTickComplete` hook in
10
+ * `src/index.ts`, which calls {@link SkillsUpdateCoordinator.runTickOnce}
11
+ * after every auto-update cycle. Skills-manager therefore inherits the
12
+ * `autoUpdate.pollIntervalMinutes` cadence and the same failure-backoff
13
+ * cadence.
14
+ *
15
+ * On start(): load persisted state, bootstrap any missing skills, mark
16
+ * health as healthy. The first tick fires on the next external invocation
17
+ * of `runTickOnce()`.
18
+ *
19
+ * Each tick: resolve skill names (configured list or discovery), check
20
+ * remote versions in parallel, auto-apply patch/minor, notify on major
21
+ * (deduped by version), skip on none/unknown.
12
22
  */
13
23
  import type { SkillsManagerSnapshot, SkillsUpdateCoordinatorOptions } from "./types.js";
14
24
  export declare class SkillsUpdateCoordinator {
15
25
  private readonly options;
16
26
  private readonly store;
17
- private timer;
18
27
  private operationChain;
19
28
  private stopped;
20
29
  private runToken;
@@ -22,17 +31,81 @@ export declare class SkillsUpdateCoordinator {
22
31
  private snapshot;
23
32
  /** Latest remote version per skill name — populated during ticks. */
24
33
  private latestVersions;
34
+ /**
35
+ * Local (pre-install) version per skill name — populated during ticks
36
+ * and manual RPC paths from `SkillVersionInfo.localVersion`. Used by the
37
+ * update-summary and major-available notifications to render the
38
+ * `prev → new` transition. Captured *before* the install runs so the
39
+ * value still reflects the on-disk version at the time the user chose to
40
+ * update; reading `state.skills[name].installedVersion` instead would
41
+ * surface the *post-install* version (recorded by `recordSuccess`) and
42
+ * collapse the transition to `vX -> vX`.
43
+ */
44
+ private previousVersions;
45
+ /**
46
+ * Cached short descriptions parsed from each skill's **remote** SKILL.md
47
+ * frontmatter — i.e. the description for the upcoming/current remote
48
+ * version, not whatever's installed locally. Used to enrich
49
+ * update-summary and major-available notifications with a one-line
50
+ * "About:" so the user gets context for the version the message is
51
+ * actually announcing.
52
+ *
53
+ * Populated during tick / updateSkill / updateAll alongside
54
+ * `latestVersions`; absent / null entries simply omit the line from the
55
+ * notification.
56
+ *
57
+ * Using the remote description (rather than the local one) keeps the
58
+ * notification description in sync with the version number it sits next
59
+ * to — e.g. when notifying about a major bump v1 → v2, the "About:" line
60
+ * reflects the v2 description, even if the v1 local copy on disk is
61
+ * stale or worded differently.
62
+ */
63
+ private skillDescriptions;
25
64
  constructor(options: SkillsUpdateCoordinatorOptions);
26
- /** Load persisted state, bootstrap missing skills, and schedule the first poll. */
65
+ /**
66
+ * Load persisted state and bootstrap missing skills. Does **not** schedule
67
+ * a poll loop — skills-manager runs off the auto-update coordinator's
68
+ * `onTickComplete` hook (see `src/index.ts`), which invokes
69
+ * {@link runTickOnce} on whatever cadence auto-update is configured with.
70
+ *
71
+ * Calling `start()` is still required even in the externally-scheduled
72
+ * mode so bootstrap, state load, and the "ready" snapshot all happen
73
+ * before the first external tick fires.
74
+ */
27
75
  start(): Promise<void>;
28
76
  /**
29
- * Cancel the next scheduled poll, prevent in-flight ticks from rescheduling,
30
- * and wait for any currently-executing tick or manual RPC to finish so the
31
- * caller can rely on no async work still touching state after `stop()`
32
- * resolves. Without this drain, a caller `await coordinator.stop()` could
33
- * proceed to e.g. delete the state dir while a tick mid-write fires.
77
+ * Stop the coordinator: prevent any new ticks from being processed, and
78
+ * wait for any in-flight tick or manual RPC to finish so the caller can
79
+ * rely on no async work still touching state after `stop()` resolves.
80
+ *
81
+ * Since scheduling is now external (auto-update's `onTickComplete` hook),
82
+ * there's no internal timer to cancel — `stop()` just flips the `stopped`
83
+ * flag (which `runTickOnce` checks) and drains the serialised operation
84
+ * queue. The auto-update hook itself becomes a no-op for stopped
85
+ * coordinators since `runTickOnce` returns early.
34
86
  */
35
87
  stop(): Promise<void>;
88
+ /**
89
+ * Public one-shot tick entry point. Called externally on whatever cadence
90
+ * the host wires up — currently from the auto-update coordinator's
91
+ * `onTickComplete` hook in `src/index.ts`, which fires after each
92
+ * auto-update version check completes (success or failure).
93
+ *
94
+ * Replaces the previous internal `tick()` + `scheduleNext()` pair: the
95
+ * coordinator no longer owns a timer of its own. Manual RPCs
96
+ * (`senpi.skills.update`, `senpi.skills.updateAll`) remain independent of
97
+ * this path.
98
+ *
99
+ * Returns early as a no-op when:
100
+ * - The coordinator has been stopped (e.g. plugin teardown).
101
+ * - The runToken has rolled (e.g. a stop/start cycle invalidated this call).
102
+ * - The coordinator was disabled at start time (config.enabled === false).
103
+ *
104
+ * Tick errors are logged + recorded on the snapshot but never thrown —
105
+ * the caller (auto-update) must not have its own scheduling disturbed by
106
+ * a transient skills-manager failure.
107
+ */
108
+ runTickOnce(): Promise<void>;
36
109
  /** Return the latest point-in-time snapshot for gateway RPCs. */
37
110
  getSnapshot(): SkillsManagerSnapshot;
38
111
  /**
@@ -66,8 +139,6 @@ export declare class SkillsUpdateCoordinator {
66
139
  version: string | null;
67
140
  error?: string;
68
141
  }>>;
69
- private scheduleNext;
70
- private tick;
71
142
  /**
72
143
  * Run coordinator work in a global critical section so periodic ticks and
73
144
  * manual RPC updates never interleave at await points.
@@ -148,6 +219,39 @@ export declare class SkillsUpdateCoordinator {
148
219
  * caller via a rejected promise (batch path captures it instead).
149
220
  */
150
221
  private applyUpdate;
222
+ /**
223
+ * Format the per-skill nested-bullet block used in both notification
224
+ * shapes. Renders the structure suggested in PR #78 review feedback:
225
+ *
226
+ * **skill-name**
227
+ * • v1.0.0 → v2.0.0 (or "v1.0.0 (install failed)" when failed)
228
+ * • description: … (omitted when no remote description)
229
+ * • error: … (only on failure, replaces the description)
230
+ *
231
+ * **Why markdown, not HTML?**
232
+ * Openclaw's Telegram channel (`src/telegram/send.ts:sendMessageTelegram`)
233
+ * pipes outbound text through `renderTelegramHtmlText`, which defaults
234
+ * `textMode` to `"markdown"` — i.e. it expects the source to be markdown
235
+ * and runs `markdownToTelegramHtml` over it before handing the converted
236
+ * HTML to the Bot API with `parse_mode: "HTML"`. The `message` tool
237
+ * (which is what this coordinator's `notify` callback ultimately hits via
238
+ * `/tools/invoke`) does not expose `textMode`, so HTML written by us is
239
+ * treated as literal characters by the markdown step and rendered as
240
+ * visible `<b>` text in the chat (the actual production bug this docstring
241
+ * fixes — confirmed against a live notification screenshot).
242
+ *
243
+ * Using markdown source (`**bold**`, backticks) instead means the channel's
244
+ * markdown→HTML converter produces the correct `<b>` / `<code>` HTML
245
+ * payload and Telegram renders the formatting properly.
246
+ *
247
+ * @param skillName Skill identifier (rendered bold via `**name**`).
248
+ * @param toVersion Resolved upgraded-to version. `null` for failure rows
249
+ * where no install completed; renders as
250
+ * "vPREV (install failed)".
251
+ * @param errorReason Optional failure reason. When provided, replaces
252
+ * the description line with `error: …`.
253
+ */
254
+ private formatSkillBlock;
151
255
  /**
152
256
  * Send a one-way Telegram notification for a pending major update, deduped
153
257
  * by version.
@@ -164,6 +268,27 @@ export declare class SkillsUpdateCoordinator {
164
268
  * so the user can tell which skills still need attention. Sections with no
165
269
  * entries are omitted. If neither section has entries, no notification is
166
270
  * sent.
271
+ *
272
+ * Format (markdown source — see `formatSkillBlock` for why markdown
273
+ * rather than HTML):
274
+ *
275
+ * Senpi skills update:
276
+ *
277
+ * Updated:
278
+ *
279
+ * **skill-a**
280
+ * • v1.0.0 → v1.0.1
281
+ * • description: …
282
+ *
283
+ * **skill-b**
284
+ * • v2.0.0 → v2.0.1
285
+ * • description: …
286
+ *
287
+ * Failed to update:
288
+ *
289
+ * **skill-c**
290
+ * • v1.0.0 (install failed)
291
+ * • error: clone failed: …
167
292
  */
168
293
  private sendUpdateSummary;
169
294
  /**
@@ -179,7 +304,12 @@ export declare class SkillsUpdateCoordinator {
179
304
  /**
180
305
  * Resolve the list of skill names to check this tick.
181
306
  * Uses `config.skills` when non-empty; otherwise discovers all immediate
182
- * subdirectories of `skillsDir`.
307
+ * subdirectories across every dir in the `skillsDir` search path,
308
+ * deduped by name and sorted.
309
+ *
310
+ * Per-dir read errors (other than ENOENT) are logged but do not abort the
311
+ * scan — a misconfigured secondary dir cannot mask skills present in the
312
+ * primary.
183
313
  */
184
314
  private resolveSkillNames;
185
315
  /**
@@ -195,9 +325,6 @@ export declare class SkillsUpdateCoordinator {
195
325
  * 3. Caller-supplied lifecycle metadata — `health`, `lastAction`,
196
326
  * `lastError` describing the most recent tick / manual RPC outcome.
197
327
  *
198
- * `nextCheckAt` is preserved from the previous snapshot so callers always
199
- * see a valid ETA even on transient rebuilds (e.g. mid-tick error paths).
200
- *
201
328
  * This is called at every state-mutating boundary (start, tick complete,
202
329
  * tick error, manual update complete, manual update skipped, manual update
203
330
  * clone failed, stop/disable) so the next RPC response reflects the latest
@@ -1 +1 @@
1
- {"version":3,"file":"coordinator.d.ts","sourceRoot":"","sources":["../../src/skills-manager/coordinator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAQH,OAAO,KAAK,EAMV,qBAAqB,EAGrB,8BAA8B,EAC/B,MAAM,YAAY,CAAC;AAIpB,qBAAa,uBAAuB;IAWtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAVpC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA0B;IAChD,OAAO,CAAC,KAAK,CAA+B;IAC5C,OAAO,CAAC,cAAc,CAAoC;IAC1D,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,KAAK,CAAyD;IACtE,OAAO,CAAC,QAAQ,CAAwB;IACxC,qEAAqE;IACrE,OAAO,CAAC,cAAc,CAAoC;gBAE7B,OAAO,EAAE,8BAA8B;IAKpE,mFAAmF;IAC7E,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA8B5B;;;;;;OAMG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAe3B,iEAAiE;IACjE,WAAW,IAAI,qBAAqB;IAMpC;;;;;;;;;;OAUG;IACG,WAAW,CACf,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IAwFxD;;;;;;;;;OASG;IACG,SAAS,IAAI,OAAO,CACxB,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAClF;IAuID,OAAO,CAAC,YAAY;YAWN,IAAI;IAoBlB;;;OAGG;YACW,aAAa;IAwB3B;;;OAGG;YACW,OAAO;IAoFrB;;;;;;;;;;OAUG;YACW,YAAY;IAsC1B;;;;;;;;;;;OAWG;YACW,mBAAmB;IAyDjC;;;;;;;;;;;;;;;;;;;OAmBG;IACH,OAAO,CAAC,aAAa;IAQrB;;;;;;;OAOG;IACH,OAAO,CAAC,kBAAkB;IAU1B;;;OAGG;IACH,OAAO,CAAC,qBAAqB;IAmB7B;;;;;;;;OAQG;YACW,WAAW;IAmDzB;;;;;;;;OAQG;YACW,oBAAoB;IA6BlC;;;;;;OAMG;YACW,iBAAiB;IA+B/B;;;;;;;;OAQG;IACH,OAAO,CAAC,cAAc;IAQtB;;;;OAIG;YACW,iBAAiB;IAqB/B;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,OAAO,CAAC,aAAa;YAyBP,YAAY;CAS3B"}
1
+ {"version":3,"file":"coordinator.d.ts","sourceRoot":"","sources":["../../src/skills-manager/coordinator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAQH,OAAO,KAAK,EAMV,qBAAqB,EAGrB,8BAA8B,EAC/B,MAAM,YAAY,CAAC;AAIpB,qBAAa,uBAAuB;IAwCtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAvCpC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA0B;IAChD,OAAO,CAAC,cAAc,CAAoC;IAC1D,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,KAAK,CAAyD;IACtE,OAAO,CAAC,QAAQ,CAAwB;IACxC,qEAAqE;IACrE,OAAO,CAAC,cAAc,CAAoC;IAC1D;;;;;;;;;OASG;IACH,OAAO,CAAC,gBAAgB,CAAoC;IAC5D;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,CAAC,iBAAiB,CAAoC;gBAEhC,OAAO,EAAE,8BAA8B;IAKpE;;;;;;;;;OASG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA4B5B;;;;;;;;;;OAUG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAW3B;;;;;;;;;;;;;;;;;;;OAmBG;IACG,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAmBlC,iEAAiE;IACjE,WAAW,IAAI,qBAAqB;IAMpC;;;;;;;;;;OAUG;IACG,WAAW,CACf,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IA2FxD;;;;;;;;;OASG;IACG,SAAS,IAAI,OAAO,CACxB,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAClF;IAuID;;;OAGG;YACW,aAAa;IAwB3B;;;OAGG;YACW,OAAO;IAsFrB;;;;;;;;;;OAUG;YACW,YAAY;IAsC1B;;;;;;;;;;;OAWG;YACW,mBAAmB;IA4DjC;;;;;;;;;;;;;;;;;;;OAmBG;IACH,OAAO,CAAC,aAAa;IAQrB;;;;;;;OAOG;IACH,OAAO,CAAC,kBAAkB;IAU1B;;;OAGG;IACH,OAAO,CAAC,qBAAqB;IAmB7B;;;;;;;;OAQG;YACW,WAAW;IAmDzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+BG;IACH,OAAO,CAAC,gBAAgB;IAwBxB;;;;;;;;OAQG;YACW,oBAAoB;IAuClC;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;YACW,iBAAiB;IAgC/B;;;;;;;;OAQG;IACH,OAAO,CAAC,cAAc;IAYtB;;;;;;;;;OASG;YACW,iBAAiB;IAqC/B;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,CAAC,aAAa;YA2BP,YAAY;CAS3B"}