@mjasnikovs/pi-task 0.7.3 → 0.7.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/dist/remote/broadcast.d.ts +0 -1
- package/dist/remote/broadcast.js +0 -3
- package/dist/remote/protocol.d.ts +1 -1
- package/dist/remote/server.js +1 -3
- package/dist/remote/ui.js +3 -19
- package/dist/workers/html-clean.js +12 -7
- package/package.json +11 -12
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { WebSocket } from 'ws';
|
|
2
2
|
export declare function addClient(ws: WebSocket): void;
|
|
3
3
|
export declare function removeClient(ws: WebSocket): void;
|
|
4
|
-
export declare function clientCount(): number;
|
|
5
4
|
export declare function broadcast(msg: unknown): void;
|
|
6
5
|
export declare function sendTo(ws: WebSocket, msg: unknown): void;
|
package/dist/remote/broadcast.js
CHANGED
|
@@ -9,9 +9,6 @@ export function addClient(ws) {
|
|
|
9
9
|
export function removeClient(ws) {
|
|
10
10
|
clients.delete(ws);
|
|
11
11
|
}
|
|
12
|
-
export function clientCount() {
|
|
13
|
-
return clients.size;
|
|
14
|
-
}
|
|
15
12
|
export function broadcast(msg) {
|
|
16
13
|
const json = JSON.stringify(msg);
|
|
17
14
|
for (const ws of clients) {
|
|
@@ -44,7 +44,7 @@ export interface ResetMessage {
|
|
|
44
44
|
* session-state.ts (its serializer); re-exported here as part of the wire type. */
|
|
45
45
|
export type { SnapshotMessage } from './session-state.js';
|
|
46
46
|
/** Server → browser messages. The live text_delta / tool_* / agent_* /
|
|
47
|
-
*
|
|
47
|
+
* user_message deltas are emitted by the SessionState mutators
|
|
48
48
|
* and not all enumerated here; the snapshot below carries the full state. */
|
|
49
49
|
export type ServerMessage = PromptMessage | PromptResolvedMessage | WidgetMessage | NotifyMessage | ViewerMessage | ContextMessage | ResetMessage | import('./session-state.js').SnapshotMessage;
|
|
50
50
|
/** Browser → server messages. */
|
package/dist/remote/server.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createServer } from 'node:http';
|
|
2
2
|
import { networkInterfaces } from 'node:os';
|
|
3
3
|
import { WebSocketServer } from 'ws';
|
|
4
|
-
import { addClient, removeClient,
|
|
4
|
+
import { addClient, removeClient, sendTo } from './broadcast.js';
|
|
5
5
|
import { answerPrompt } from './bridge.js';
|
|
6
6
|
import { getState, snapshot } from './session-state.js';
|
|
7
7
|
import { isClientMessage } from './protocol.js';
|
|
@@ -121,7 +121,6 @@ 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
|
-
broadcast({ type: 'client_count', count: clientCount() });
|
|
125
124
|
ws.on('message', data => {
|
|
126
125
|
let msg;
|
|
127
126
|
try {
|
|
@@ -144,7 +143,6 @@ export async function startServer(onMessage, getHtml) {
|
|
|
144
143
|
});
|
|
145
144
|
ws.on('close', () => {
|
|
146
145
|
removeClient(ws);
|
|
147
|
-
broadcast({ type: 'client_count', count: clientCount() });
|
|
148
146
|
});
|
|
149
147
|
});
|
|
150
148
|
await new Promise(resolve => httpServer.listen(port, '0.0.0.0', resolve));
|
package/dist/remote/ui.js
CHANGED
|
@@ -57,10 +57,6 @@ export function html(wsUrl) {
|
|
|
57
57
|
96% { text-shadow: 1px 0 var(--teal), -1px 0 var(--red); transform: translate(-1px, 0); }
|
|
58
58
|
}
|
|
59
59
|
@media (prefers-reduced-motion: reduce) { #header .title { animation: none; } }
|
|
60
|
-
#header .status { color: var(--subtext0); font-size: 11px; display: inline-flex; align-items: center; gap: 5px; }
|
|
61
|
-
#header .cdot { color: var(--yellow); }
|
|
62
|
-
#header .cdot.up { color: var(--green); }
|
|
63
|
-
#header .cdot.down { color: var(--red); }
|
|
64
60
|
#header .hgroup { display: flex; align-items: center; gap: 10px; }
|
|
65
61
|
#bell {
|
|
66
62
|
background: none; border: none; color: var(--subtext1); cursor: pointer;
|
|
@@ -233,7 +229,6 @@ export function html(wsUrl) {
|
|
|
233
229
|
<div id="header">
|
|
234
230
|
<span class="title">pi-task remote</span>
|
|
235
231
|
<div class="hgroup">
|
|
236
|
-
<span class="status" id="client-status"><span class="cdot" id="conn-dot">○</span></span>
|
|
237
232
|
<button id="bell" aria-label="Toggle notifications" title="Notifications">◯</button>
|
|
238
233
|
</div>
|
|
239
234
|
</div>
|
|
@@ -272,12 +267,6 @@ export function html(wsUrl) {
|
|
|
272
267
|
function setContextBar(usage) {
|
|
273
268
|
if (usage && usage.percent != null) contextFill.style.width = usage.percent + '%';
|
|
274
269
|
}
|
|
275
|
-
const connDot = document.getElementById('conn-dot');
|
|
276
|
-
// state: 'connecting' (○ yellow) | 'up' (● green) | 'down' (● red)
|
|
277
|
-
function setConn(state) {
|
|
278
|
-
connDot.textContent = state === 'connecting' ? '\\u25CB' : '\\u25CF';
|
|
279
|
-
connDot.className = 'cdot' + (state === 'up' ? ' up' : state === 'down' ? ' down' : '');
|
|
280
|
-
}
|
|
281
270
|
const reconnectOverlay = document.getElementById('reconnect-overlay');
|
|
282
271
|
const reconnectMsg = document.getElementById('reconnect-msg');
|
|
283
272
|
const cmdSuggestions = document.getElementById('cmd-suggestions');
|
|
@@ -941,9 +930,6 @@ export function html(wsUrl) {
|
|
|
941
930
|
// Seeds the bar for a client that joined mid-session.
|
|
942
931
|
setContextBar(msg.contextUsage);
|
|
943
932
|
break;
|
|
944
|
-
case 'client_count':
|
|
945
|
-
setConn('up');
|
|
946
|
-
break;
|
|
947
933
|
case 'prompt':
|
|
948
934
|
showPrompt(msg);
|
|
949
935
|
break;
|
|
@@ -983,9 +969,9 @@ export function html(wsUrl) {
|
|
|
983
969
|
cmdActive = []; cmdIndex = -1; renderSuggestions();
|
|
984
970
|
// Slash commands are handled server-side and produce no chat turn.
|
|
985
971
|
if (text.startsWith('/')) return;
|
|
986
|
-
//
|
|
987
|
-
//
|
|
988
|
-
|
|
972
|
+
// The server records the message via addUserTurn and broadcasts a
|
|
973
|
+
// user_message back to every client (us included), which renders the
|
|
974
|
+
// bubble. Don't render it here too, or the sender sees it twice.
|
|
989
975
|
setEnabled(false);
|
|
990
976
|
showThinking();
|
|
991
977
|
}
|
|
@@ -1013,7 +999,6 @@ export function html(wsUrl) {
|
|
|
1013
999
|
if (reconnectAnim) { clearInterval(reconnectAnim); reconnectAnim = null; }
|
|
1014
1000
|
reconnectOverlay.classList.remove('visible');
|
|
1015
1001
|
reconnectDelay = 1000;
|
|
1016
|
-
setConn('up');
|
|
1017
1002
|
setEnabled(true);
|
|
1018
1003
|
});
|
|
1019
1004
|
ws.addEventListener('message', (e) => {
|
|
@@ -1021,7 +1006,6 @@ export function html(wsUrl) {
|
|
|
1021
1006
|
});
|
|
1022
1007
|
ws.addEventListener('close', () => {
|
|
1023
1008
|
setEnabled(false);
|
|
1024
|
-
setConn('down');
|
|
1025
1009
|
reconnectOverlay.classList.add('visible');
|
|
1026
1010
|
// Animate the same braille spinner used elsewhere, with a live countdown.
|
|
1027
1011
|
const until = Date.now() + reconnectDelay;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readFileSync } from 'node:fs';
|
|
2
2
|
import { fileURLToPath } from 'node:url';
|
|
3
3
|
import { dirname, join } from 'node:path';
|
|
4
|
-
import {
|
|
4
|
+
import { parseHTML } from 'linkedom';
|
|
5
5
|
import { Readability } from '@mozilla/readability';
|
|
6
6
|
import TurndownService from 'turndown';
|
|
7
7
|
const turndown = new TurndownService({
|
|
@@ -10,22 +10,22 @@ const turndown = new TurndownService({
|
|
|
10
10
|
bulletListMarker: '-'
|
|
11
11
|
});
|
|
12
12
|
export function cleanHtml(html, baseUrl) {
|
|
13
|
-
const
|
|
14
|
-
const reader = new Readability(
|
|
13
|
+
const { document } = parseHTML(html);
|
|
14
|
+
const reader = new Readability(document);
|
|
15
15
|
const parsed = reader.parse();
|
|
16
16
|
if (parsed && parsed.content) {
|
|
17
17
|
return {
|
|
18
|
-
title: parsed.title ||
|
|
18
|
+
title: parsed.title || document.title || new URL(baseUrl).hostname,
|
|
19
19
|
markdown: turndown.turndown(parsed.content).trim(),
|
|
20
20
|
finalUrl: baseUrl
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
23
|
// Fallback: turndown the body
|
|
24
|
-
const body =
|
|
24
|
+
const body = document.body;
|
|
25
25
|
const bodyHtml = body ? body.innerHTML : '';
|
|
26
26
|
const markdown = turndown.turndown(bodyHtml).trim();
|
|
27
27
|
return {
|
|
28
|
-
title:
|
|
28
|
+
title: document.title || new URL(baseUrl).hostname,
|
|
29
29
|
markdown,
|
|
30
30
|
finalUrl: baseUrl
|
|
31
31
|
};
|
|
@@ -75,7 +75,12 @@ function decoderFor(contentType) {
|
|
|
75
75
|
const charset = match?.[1]?.trim().replace(/^["']|["']$/g, '');
|
|
76
76
|
if (charset) {
|
|
77
77
|
try {
|
|
78
|
-
|
|
78
|
+
// The runtime accepts any charset label string; the type is narrowed
|
|
79
|
+
// to a known-encoding union by Bun/Node's lib (DOM's looser signature
|
|
80
|
+
// is no longer pulled in transitively). Cast to the actual param type.
|
|
81
|
+
return new TextDecoder(charset, {
|
|
82
|
+
fatal: false
|
|
83
|
+
});
|
|
79
84
|
}
|
|
80
85
|
catch {
|
|
81
86
|
// Unknown/unsupported label — fall through to UTF-8.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mjasnikovs/pi-task",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.4",
|
|
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",
|
|
@@ -23,13 +23,13 @@
|
|
|
23
23
|
"@earendil-works/pi-tui": "0.78.1"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@mozilla/readability": "
|
|
26
|
+
"@mozilla/readability": "0.6.0",
|
|
27
27
|
"@sinclair/typebox": "0.34.49",
|
|
28
|
-
"
|
|
29
|
-
"qrcode": "
|
|
30
|
-
"turndown": "
|
|
31
|
-
"web-push": "
|
|
32
|
-
"ws": "
|
|
28
|
+
"linkedom": "0.18.12",
|
|
29
|
+
"qrcode": "1.5.4",
|
|
30
|
+
"turndown": "7.2.4",
|
|
31
|
+
"web-push": "3.6.7",
|
|
32
|
+
"ws": "8.21.0"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@earendil-works/pi-agent-core": "0.78.1",
|
|
@@ -38,11 +38,10 @@
|
|
|
38
38
|
"@eslint/js": "10.0.1",
|
|
39
39
|
"@sinclair/typebox": "0.34.49",
|
|
40
40
|
"@types/bun": "1.3.12",
|
|
41
|
-
"@types/
|
|
42
|
-
"@types/
|
|
43
|
-
"@types/
|
|
44
|
-
"@types/
|
|
45
|
-
"@types/ws": "^8.5.14",
|
|
41
|
+
"@types/qrcode": "1.5.6",
|
|
42
|
+
"@types/turndown": "5.0.6",
|
|
43
|
+
"@types/web-push": "3.6.4",
|
|
44
|
+
"@types/ws": "8.18.1",
|
|
46
45
|
"eslint": "10.2.1",
|
|
47
46
|
"globals": "17.5.0",
|
|
48
47
|
"prettier": "3.8.3",
|