@mjasnikovs/pi-task 0.14.21 → 0.14.22

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.
@@ -65,6 +65,18 @@ export declare class SessionUI {
65
65
  private askLocal;
66
66
  }
67
67
  export declare function publishNotify(message: string, level: 'info' | 'warning' | 'error'): void;
68
+ /**
69
+ * Mirror a task lifecycle notice (the kind pi-task shows on the terminal via
70
+ * ctx.ui.notify) to connected remote viewers. Task failures and other
71
+ * ctx.ui.notify calls bypass the host agent's event stream — the only thing
72
+ * events.ts mirrors — so without this the remote view shows nothing when a task
73
+ * fails completely even though the terminal flashes red.
74
+ *
75
+ * An 'error' becomes a PERSISTENT red bubble in the transcript (addError) so it
76
+ * survives a reconnect, matching the terminal's red text; 'warning'/'info' are a
77
+ * transient toast since they don't need to linger.
78
+ */
79
+ export declare function publishLifecycleNotice(message: string, level: 'info' | 'warning' | 'error'): void;
68
80
  export declare function publishViewer(title: string, text: string): void;
69
81
  /**
70
82
  * Wraps an event-scoped ExtensionContext so it can be used as a command ctx
@@ -1,6 +1,6 @@
1
1
  import { broadcast as wsBroadcast } from './broadcast.js';
2
2
  import { pushNotify } from './push.js';
3
- import { setPrompt, clearPrompt } from './session-state.js';
3
+ import { setPrompt, clearPrompt, addError } from './session-state.js';
4
4
  import { askQuestionBox } from '../task/question-box.js';
5
5
  const g = globalThis;
6
6
  export function getBridge() {
@@ -108,6 +108,23 @@ export class SessionUI {
108
108
  export function publishNotify(message, level) {
109
109
  getBridge().broadcast({ type: 'notify', message, level });
110
110
  }
111
+ /**
112
+ * Mirror a task lifecycle notice (the kind pi-task shows on the terminal via
113
+ * ctx.ui.notify) to connected remote viewers. Task failures and other
114
+ * ctx.ui.notify calls bypass the host agent's event stream — the only thing
115
+ * events.ts mirrors — so without this the remote view shows nothing when a task
116
+ * fails completely even though the terminal flashes red.
117
+ *
118
+ * An 'error' becomes a PERSISTENT red bubble in the transcript (addError) so it
119
+ * survives a reconnect, matching the terminal's red text; 'warning'/'info' are a
120
+ * transient toast since they don't need to linger.
121
+ */
122
+ export function publishLifecycleNotice(message, level) {
123
+ if (level === 'error')
124
+ addError(message);
125
+ else
126
+ publishNotify(message, level);
127
+ }
111
128
  export function publishViewer(title, text) {
112
129
  getBridge().broadcast({ type: 'viewer', title, text });
113
130
  }
@@ -21,7 +21,7 @@ import { researchResolution, resolutionOptions, classifyResolutionAnswer } from
21
21
  import { runWorker } from '../workers/pi-worker-core.js';
22
22
  import { findPhantomImports, rewritePhantomSpecifiers } from '../workers/phantom-imports.js';
23
23
  import { runPhaseChild, prependHint, formatLoopHint, USER_CANCELLED } from './child-runner.js';
24
- import { SessionUI, registerBridgeCommand } from '../remote/bridge.js';
24
+ import { SessionUI, registerBridgeCommand, publishLifecycleNotice } from '../remote/bridge.js';
25
25
  import { pushNotify } from '../remote/push.js';
26
26
  import { getConfig } from '../config/config.js';
27
27
  import { startAutoLoader } from './widget.js';
@@ -621,6 +621,10 @@ export function requestAutoCancel() {
621
621
  */
622
622
  function announceDone(ctx, msg, level) {
623
623
  ctx.ui.notify(msg, level);
624
+ // ctx.ui.notify is terminal-only and pushNotify is a backgrounded-device web
625
+ // push — neither shows up in a remote viewer that's watching live. Mirror it
626
+ // into the session view too (errors become a persistent red bubble).
627
+ publishLifecycleNotice(msg, level);
624
628
  void pushNotify('Task finished', msg, 'pi-end').catch(() => { });
625
629
  }
626
630
  export async function runAutoLoop(ctx, cwd, id, deps) {
@@ -4,6 +4,7 @@
4
4
  */
5
5
  import { updateTaskFrontMatter } from './task-io.js';
6
6
  import { flashTerminalWidget } from './widget.js';
7
+ import { publishLifecycleNotice } from '../remote/bridge.js';
7
8
  import { LoopExhaustedError, LeakedToolCallError, ModelError, USER_CANCELLED } from './child-runner.js';
8
9
  // ─── Classifier ──────────────────────────────────────────────────────────────
9
10
  export function classifyFailure(err, aborted) {
@@ -78,4 +79,7 @@ export async function handleFailure(err, ctx, cwd, id, aborted) {
78
79
  await updateTaskFrontMatter(cwd, id, { state: c.state, reason: c.reason });
79
80
  flashTerminalWidget(ctx, c.state, id, c.flash);
80
81
  ctx.ui.notify(`${id} ${c.notify}`, c.level);
82
+ // Mirror to remote viewers — ctx.ui.notify is terminal-only, so without this
83
+ // the remote view shows nothing when a task fails.
84
+ publishLifecycleNotice(`${id} ${c.notify}`, c.level);
81
85
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mjasnikovs/pi-task",
3
- "version": "0.14.21",
3
+ "version": "0.14.22",
4
4
  "description": "Deterministic spec-orchestration for local models, with a bundled real-time remote web view and web/docs/fetch/worker subagent tools.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",