@maolon/pi-watcher 0.1.3 → 0.1.4
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.
- package/CHANGELOG.md +5 -0
- package/README.md +2 -1
- package/dist/engine/service.d.ts +7 -0
- package/dist/engine/service.js +29 -0
- package/dist/pi-extension.js +22 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,11 @@ All notable changes to this project are documented here. The format follows
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.1.4] - 2026-10-08
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
- `/watcher cancel [reason]` closes every active or paused watch of the current session, no watchId needed. Each close withdraws pending attentions and supersedes open episodes like a per-watch `close`; other sessions are untouched.
|
|
13
|
+
|
|
9
14
|
## [0.1.3] - 2026-10-08
|
|
10
15
|
|
|
11
16
|
### Changed
|
package/README.md
CHANGED
|
@@ -146,7 +146,8 @@ degraded; they never mark the task as failed. The command text is stored as evid
|
|
|
146
146
|
| `register` | Full spec: `run`, `group` (up to 16 members) and `obligation` targets |
|
|
147
147
|
|
|
148
148
|
`/watcher` shows the panel; `/watcher ack <episodeId> <received|investigating|defer|resolved|dismiss> [until]`
|
|
149
|
-
handles an episode locally; `/watcher
|
|
149
|
+
handles an episode locally; `/watcher cancel [reason]` closes every active or paused watch of the current session
|
|
150
|
+
(no watchId needed); `/watcher jev` manages the optional semantic review (see below).
|
|
150
151
|
|
|
151
152
|
### Exit markers for `exec_command`
|
|
152
153
|
|
package/dist/engine/service.d.ts
CHANGED
|
@@ -42,6 +42,13 @@ export declare class WatchService {
|
|
|
42
42
|
inspectionId: Id;
|
|
43
43
|
}>;
|
|
44
44
|
control(requestId: Id, watchId: Id, expectedControlRevision: number, action: 'pause' | 'close' | 'resume', reason: string, actor: ActorContext): Promise<Json>;
|
|
45
|
+
/**
|
|
46
|
+
* Local owner cancel (for the /watcher command only): close every active or paused watch of this owner
|
|
47
|
+
* session. Each close goes through control() with the watch's current controlRevision, so the scope
|
|
48
|
+
* advance, attention withdraw and episode supersede are identical to a per-watch close. A close that
|
|
49
|
+
* fails is reported per watch, never folded into success.
|
|
50
|
+
*/
|
|
51
|
+
closeAllForOwner(reason: string, actor: ActorContext): Promise<Json>;
|
|
45
52
|
/**
|
|
46
53
|
* Layered withdrawal report (design 6.5): sourceFence for the scope advance and one entry
|
|
47
54
|
* per affected route. "withdrawn" is claimed only when every route reports prevented
|
package/dist/engine/service.js
CHANGED
|
@@ -280,6 +280,35 @@ export class WatchService {
|
|
|
280
280
|
}
|
|
281
281
|
return { ...result, ...this.relayCutReport(result) };
|
|
282
282
|
}
|
|
283
|
+
/**
|
|
284
|
+
* Local owner cancel (for the /watcher command only): close every active or paused watch of this owner
|
|
285
|
+
* session. Each close goes through control() with the watch's current controlRevision, so the scope
|
|
286
|
+
* advance, attention withdraw and episode supersede are identical to a per-watch close. A close that
|
|
287
|
+
* fails is reported per watch, never folded into success.
|
|
288
|
+
*/
|
|
289
|
+
async closeAllForOwner(reason, actor) {
|
|
290
|
+
const rows = [];
|
|
291
|
+
let cursor;
|
|
292
|
+
for (;;) {
|
|
293
|
+
const page = this.store.transaction(tx => tx.listWatches(actor.owner.sessionId, cursor, 200, ['active', 'paused']));
|
|
294
|
+
rows.push(...page);
|
|
295
|
+
if (page.length < 200)
|
|
296
|
+
break;
|
|
297
|
+
cursor = page[page.length - 1].watchId;
|
|
298
|
+
}
|
|
299
|
+
const closed = [];
|
|
300
|
+
const failed = [];
|
|
301
|
+
for (const row of rows) {
|
|
302
|
+
try {
|
|
303
|
+
const r = await this.control(newId('cancel'), row.watchId, row.controlRevision, 'close', reason, actor);
|
|
304
|
+
closed.push({ watchId: row.watchId, previousLifecycle: row.lifecycle, withdrawn: Array.isArray(r.withdrawEventIds) ? r.withdrawEventIds.length : 0 });
|
|
305
|
+
}
|
|
306
|
+
catch (e) {
|
|
307
|
+
failed.push({ watchId: row.watchId, code: e.code ?? 'ERROR', message: e instanceof Error ? e.message : String(e) });
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
return { closed, failed, reason };
|
|
311
|
+
}
|
|
283
312
|
/**
|
|
284
313
|
* Layered withdrawal report (design 6.5): sourceFence for the scope advance and one entry
|
|
285
314
|
* per affected route. "withdrawn" is claimed only when every route reports prevented
|
package/dist/pi-extension.js
CHANGED
|
@@ -130,6 +130,9 @@ class SessionBackend {
|
|
|
130
130
|
async localAck(req, actor) {
|
|
131
131
|
return JSON.stringify(await toServiceResultAsync(req.requestId, () => this.rt.service.ackEpisode(req.requestId, req.episodeId, req.action, req.note, req.until, actor)));
|
|
132
132
|
}
|
|
133
|
+
async localCancelAll(reason, actor) {
|
|
134
|
+
return JSON.stringify(await toServiceResultAsync(undefined, () => this.rt.service.closeAllForOwner(reason, actor)));
|
|
135
|
+
}
|
|
133
136
|
requestWidgetRefresh() {
|
|
134
137
|
this.refreshWidget();
|
|
135
138
|
}
|
|
@@ -553,7 +556,7 @@ export default function watcherExtension(pi, options = {}) {
|
|
|
553
556
|
].join('\n');
|
|
554
557
|
};
|
|
555
558
|
pi.registerCommand('watcher', {
|
|
556
|
-
description: 'pi-watcher panel: watches, health, open issues, and why no attention was sent. /watcher ack <episodeId> <received|investigating|defer|resolved|dismiss> [until ISO] — local owner response. /watcher jev [status] | /watcher jev consent <on|off> — optional Jev semantic review',
|
|
559
|
+
description: 'pi-watcher panel: watches, health, open issues, and why no attention was sent. /watcher ack <episodeId> <received|investigating|defer|resolved|dismiss> [until ISO] — local owner response. /watcher cancel [reason...] — close every active/paused watch of this session. /watcher jev [status] | /watcher jev consent <on|off> — optional Jev semantic review',
|
|
557
560
|
handler: async (args, ctx) => {
|
|
558
561
|
await ensureBackend(ctx);
|
|
559
562
|
const be = backend;
|
|
@@ -597,6 +600,24 @@ export default function watcherExtension(pi, options = {}) {
|
|
|
597
600
|
ctx.ui?.notify?.(result, parsed.ok === false ? 'error' : 'info');
|
|
598
601
|
return;
|
|
599
602
|
}
|
|
603
|
+
if (argv[0] === 'cancel') {
|
|
604
|
+
// Local owner cancel (non-model path): close every active/paused watch of this session, no watchId needed
|
|
605
|
+
const reason = argv.slice(1).join(' ') || 'local owner cancel';
|
|
606
|
+
const result = await be.localCancelAll(reason, actorOf(ctx));
|
|
607
|
+
be.requestWidgetRefresh();
|
|
608
|
+
const parsed = JSON.parse(result);
|
|
609
|
+
if (parsed.ok === false) {
|
|
610
|
+
ctx.ui?.notify?.(result, 'error');
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
const closed = parsed.value?.closed?.length ?? 0;
|
|
614
|
+
const failed = parsed.value?.failed?.length ?? 0;
|
|
615
|
+
const head = closed === 0 && failed === 0
|
|
616
|
+
? 'pi-watcher: no active or paused watch in this session'
|
|
617
|
+
: `pi-watcher: closed ${closed} watch(es) in this session` + (failed > 0 ? `, ${failed} failed` : '');
|
|
618
|
+
ctx.ui?.notify?.(failed > 0 ? `${head}\n${result}` : head, failed > 0 ? 'warning' : 'info');
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
600
621
|
const panel = await be.panel(actorOf(ctx));
|
|
601
622
|
const text = JSON.stringify(panel, null, 2);
|
|
602
623
|
ctx.ui?.notify?.(text.length > 4000 ? `${text.slice(0, 4000)}…` : text, 'info');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@maolon/pi-watcher",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Watch long-running Pi tasks without babysitting: deterministic task monitoring, optional semantic review, and relay-delivered wakes only when something needs the host.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|