@mjasnikovs/pi-task 0.13.1 → 0.13.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.
package/dist/remote/bridge.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { broadcast as wsBroadcast } from './broadcast.js';
|
|
1
|
+
import { broadcast as wsBroadcast, hasConnectedClients } from './broadcast.js';
|
|
2
2
|
import { pushNotify } from './push.js';
|
|
3
3
|
import { setPrompt, clearPrompt } from './session-state.js';
|
|
4
4
|
const g = globalThis;
|
|
@@ -56,7 +56,8 @@ export class SessionUI {
|
|
|
56
56
|
};
|
|
57
57
|
setPrompt(prompt);
|
|
58
58
|
// Reaches a backgrounded/suspended phone, which the in-page UI can't.
|
|
59
|
-
|
|
59
|
+
if (!hasConnectedClients())
|
|
60
|
+
void pushNotify('pi needs your input', spec.question, 'pi-prompt').catch(() => { });
|
|
60
61
|
// Local: resolves to a value/undefined, or undefined on abort. Swallow
|
|
61
62
|
// the rejection some implementations throw on abort so it never leaks.
|
|
62
63
|
const local = this.ctx.hasUI ?
|
|
@@ -3,3 +3,4 @@ export declare function addClient(ws: WebSocket): void;
|
|
|
3
3
|
export declare function removeClient(ws: WebSocket): void;
|
|
4
4
|
export declare function broadcast(msg: unknown): void;
|
|
5
5
|
export declare function sendTo(ws: WebSocket, msg: unknown): void;
|
|
6
|
+
export declare function hasConnectedClients(): boolean;
|
package/dist/remote/broadcast.js
CHANGED
package/dist/remote/events.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { setAgentIdle } from './state.js';
|
|
2
2
|
import { pushNotify } from './push.js';
|
|
3
3
|
import { publishNotify } from './bridge.js';
|
|
4
|
+
import { hasConnectedClients } from './broadcast.js';
|
|
4
5
|
import { agentStart, appendText, textEnd, startTool, updateTool, endTool, agentEnd, addUserTurn, addError, addSystemNote } from './session-state.js';
|
|
5
6
|
/** Mirror pi agent events into the authoritative SessionState. Each handler
|
|
6
7
|
* drives a mutator, which updates the snapshot AND broadcasts the live delta. */
|
|
@@ -22,7 +23,8 @@ export function setupEvents(pi) {
|
|
|
22
23
|
if (errorMessage || ae.reason === 'error') {
|
|
23
24
|
const message = errorMessage || 'Request failed';
|
|
24
25
|
addError(message);
|
|
25
|
-
|
|
26
|
+
if (!hasConnectedClients())
|
|
27
|
+
void pushNotify('Agent error', message, 'pi-error').catch(() => { });
|
|
26
28
|
}
|
|
27
29
|
}
|
|
28
30
|
});
|
|
@@ -41,7 +43,8 @@ export function setupEvents(pi) {
|
|
|
41
43
|
pi.on('agent_end', (_event, ctx) => {
|
|
42
44
|
setAgentIdle(true);
|
|
43
45
|
agentEnd(ctx.getContextUsage());
|
|
44
|
-
|
|
46
|
+
if (!hasConnectedClients())
|
|
47
|
+
void pushNotify('Task finished', '', 'pi-end').catch(() => { });
|
|
45
48
|
});
|
|
46
49
|
pi.on('input', (event, _ctx) => {
|
|
47
50
|
if (event.source === 'interactive' && typeof event.text === 'string') {
|
package/dist/remote/server.js
CHANGED
|
@@ -121,6 +121,21 @@ export async function startServer(onMessage, getHtml) {
|
|
|
121
121
|
handle.onFirstConnect = null;
|
|
122
122
|
// One authoritative snapshot — the client replaces its whole view with it.
|
|
123
123
|
sendTo(ws, snapshot());
|
|
124
|
+
// Heartbeat: ping every 30 s; terminate if the client doesn't respond.
|
|
125
|
+
// This catches phones that close/sleep without sending a TCP FIN, so the
|
|
126
|
+
// server's client-set stays accurate and push notifications fire correctly.
|
|
127
|
+
let alive = true;
|
|
128
|
+
const heartbeat = setInterval(() => {
|
|
129
|
+
if (!alive) {
|
|
130
|
+
ws.terminate();
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
alive = false;
|
|
134
|
+
ws.ping();
|
|
135
|
+
}, 10_000);
|
|
136
|
+
ws.on('pong', () => {
|
|
137
|
+
alive = true;
|
|
138
|
+
});
|
|
124
139
|
ws.on('message', data => {
|
|
125
140
|
let msg;
|
|
126
141
|
try {
|
|
@@ -142,6 +157,7 @@ export async function startServer(onMessage, getHtml) {
|
|
|
142
157
|
onMessage(msg.text);
|
|
143
158
|
});
|
|
144
159
|
ws.on('close', () => {
|
|
160
|
+
clearInterval(heartbeat);
|
|
145
161
|
removeClient(ws);
|
|
146
162
|
});
|
|
147
163
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mjasnikovs/pi-task",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.2",
|
|
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",
|