@pi-unipi/unipi 3.0.0-alpha.38 → 3.0.0-alpha.39
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 +6 -0
- package/package.json +23 -23
- package/packages/app-bridge/package.json +2 -2
- package/packages/app-bridge/src/bridge.ts +51 -1
- package/packages/app-bridge/src/wire.ts +27 -0
- package/packages/ask-user/package.json +2 -2
- package/packages/autocomplete/package.json +1 -1
- package/packages/background-tasks/package.json +2 -2
- package/packages/btw/package.json +2 -2
- package/packages/compactor/package.json +3 -3
- package/packages/core/package.json +1 -1
- package/packages/dream/package.json +2 -2
- package/packages/footer/package.json +3 -3
- package/packages/fusion/package.json +4 -4
- package/packages/info-screen/package.json +2 -2
- package/packages/input-shortcuts/package.json +2 -2
- package/packages/kanboard/package.json +7 -7
- package/packages/long-horizon/package.json +2 -2
- package/packages/long-horizon/src/commands.ts +57 -2
- package/packages/long-horizon/src/gate.ts +10 -0
- package/packages/mcp/package.json +2 -2
- package/packages/memory/package.json +3 -3
- package/packages/notify/package.json +2 -2
- package/packages/skill-registry/package.json +2 -2
- package/packages/subagents/package.json +3 -3
- package/packages/unipi/bundled.js +86 -1
- package/packages/updater/package.json +2 -2
- package/packages/utility/package.json +2 -2
- package/packages/watchdog/package.json +3 -3
- package/packages/web-api/package.json +2 -2
- package/packages/workflow/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [3.0.0-alpha.39] — 2026-10-11
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
- UniPi app: switch a session's working mode from the app. The app sees the current mode and changes it live (`none` returns to regular mode; another work mode is entered without a prompt). A mode switch is refused while another paused task already holds the park slot.
|
|
13
|
+
- Long-horizon: new `unipi:lh-mode` runner used for that switch.
|
|
14
|
+
|
|
9
15
|
## [3.0.0-alpha.38] — 2026-10-11
|
|
10
16
|
|
|
11
17
|
### Fixed
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/unipi",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.39",
|
|
4
4
|
"description": "All-in-one extension suite for Pi coding agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -80,28 +80,28 @@
|
|
|
80
80
|
"typebox": "^1.1.38"
|
|
81
81
|
},
|
|
82
82
|
"dependencies": {
|
|
83
|
-
"@pi-unipi/app-bridge": "3.0.0-alpha.
|
|
84
|
-
"@pi-unipi/ask-user": "3.0.0-alpha.
|
|
85
|
-
"@pi-unipi/background-tasks": "3.0.0-alpha.
|
|
86
|
-
"@pi-unipi/btw": "3.0.0-alpha.
|
|
87
|
-
"@pi-unipi/command-enchantment": "3.0.0-alpha.
|
|
88
|
-
"@pi-unipi/compactor": "3.0.0-alpha.
|
|
89
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
90
|
-
"@pi-unipi/dream": "3.0.0-alpha.
|
|
91
|
-
"@pi-unipi/footer": "3.0.0-alpha.
|
|
92
|
-
"@pi-unipi/fusion": "3.0.0-alpha.
|
|
93
|
-
"@pi-unipi/info-screen": "3.0.0-alpha.
|
|
94
|
-
"@pi-unipi/input-shortcuts": "3.0.0-alpha.
|
|
95
|
-
"@pi-unipi/kanboard": "3.0.0-alpha.
|
|
96
|
-
"@pi-unipi/mcp": "3.0.0-alpha.
|
|
97
|
-
"@pi-unipi/memory": "3.0.0-alpha.
|
|
98
|
-
"@pi-unipi/notify": "3.0.0-alpha.
|
|
99
|
-
"@pi-unipi/skill-registry": "3.0.0-alpha.
|
|
100
|
-
"@pi-unipi/subagents": "3.0.0-alpha.
|
|
101
|
-
"@pi-unipi/updater": "3.0.0-alpha.
|
|
102
|
-
"@pi-unipi/utility": "3.0.0-alpha.
|
|
103
|
-
"@pi-unipi/web-api": "3.0.0-alpha.
|
|
104
|
-
"@pi-unipi/workflow": "3.0.0-alpha.
|
|
83
|
+
"@pi-unipi/app-bridge": "3.0.0-alpha.39",
|
|
84
|
+
"@pi-unipi/ask-user": "3.0.0-alpha.39",
|
|
85
|
+
"@pi-unipi/background-tasks": "3.0.0-alpha.39",
|
|
86
|
+
"@pi-unipi/btw": "3.0.0-alpha.39",
|
|
87
|
+
"@pi-unipi/command-enchantment": "3.0.0-alpha.39",
|
|
88
|
+
"@pi-unipi/compactor": "3.0.0-alpha.39",
|
|
89
|
+
"@pi-unipi/core": "3.0.0-alpha.39",
|
|
90
|
+
"@pi-unipi/dream": "3.0.0-alpha.39",
|
|
91
|
+
"@pi-unipi/footer": "3.0.0-alpha.39",
|
|
92
|
+
"@pi-unipi/fusion": "3.0.0-alpha.39",
|
|
93
|
+
"@pi-unipi/info-screen": "3.0.0-alpha.39",
|
|
94
|
+
"@pi-unipi/input-shortcuts": "3.0.0-alpha.39",
|
|
95
|
+
"@pi-unipi/kanboard": "3.0.0-alpha.39",
|
|
96
|
+
"@pi-unipi/mcp": "3.0.0-alpha.39",
|
|
97
|
+
"@pi-unipi/memory": "3.0.0-alpha.39",
|
|
98
|
+
"@pi-unipi/notify": "3.0.0-alpha.39",
|
|
99
|
+
"@pi-unipi/skill-registry": "3.0.0-alpha.39",
|
|
100
|
+
"@pi-unipi/subagents": "3.0.0-alpha.39",
|
|
101
|
+
"@pi-unipi/updater": "3.0.0-alpha.39",
|
|
102
|
+
"@pi-unipi/utility": "3.0.0-alpha.39",
|
|
103
|
+
"@pi-unipi/web-api": "3.0.0-alpha.39",
|
|
104
|
+
"@pi-unipi/workflow": "3.0.0-alpha.39",
|
|
105
105
|
"@resvg/resvg-wasm": "^2.6.2",
|
|
106
106
|
"beautiful-mermaid": "^1.1.3"
|
|
107
107
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/app-bridge",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.39",
|
|
4
4
|
"description": "Live bridge between a pi TUI session and the UniPi phone app — streaming chat, prompts, steering and dialogs from the phone",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"access": "public"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
34
|
+
"@pi-unipi/core": "3.0.0-alpha.39"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
37
|
"@earendil-works/pi-coding-agent": "^0.87.1",
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
type FusionPresetInfo,
|
|
25
25
|
type FusionStatusInfo,
|
|
26
26
|
type LhProgressInfo,
|
|
27
|
+
type LhModeInfo,
|
|
27
28
|
type DreamDetailInfo,
|
|
28
29
|
type DreamStatusInfo,
|
|
29
30
|
type InMsg,
|
|
@@ -43,7 +44,7 @@ import { fileSuggestions } from "./files.js";
|
|
|
43
44
|
import { statPaths } from "./paths.js";
|
|
44
45
|
import { registerPath, resolveMedia } from "./media.js";
|
|
45
46
|
import { listWorkItems, stopWorkItem, backgroundWorkItem, workLogPage } from "./work.js";
|
|
46
|
-
import { bus, pendingWorkLabel, silenceCommandEcho, subscribePendingWork, UNIPI_EVENTS } from "@pi-unipi/core";
|
|
47
|
+
import { bus, callCommandRunner, pendingWorkLabel, silenceCommandEcho, subscribePendingWork, UNIPI_EVENTS } from "@pi-unipi/core";
|
|
47
48
|
import type { BtwListPage } from "./wire.js";
|
|
48
49
|
|
|
49
50
|
/** `media_chunk.data` (base64) stays well under the 900 KiB bridge line
|
|
@@ -51,6 +52,15 @@ import type { BtwListPage } from "./wire.js";
|
|
|
51
52
|
const MEDIA_CHUNK_CHARS = 700 * 1024;
|
|
52
53
|
/** UNI-222: lh_progress pushes coalesce within this window (≤ 4/s). */
|
|
53
54
|
export const LH_PROGRESS_COALESCE_MS = 250;
|
|
55
|
+
/** UNI-269: the discovery record's `lhMode`/`lhPaused` (host → chat_list → list badge). */
|
|
56
|
+
export function recordLhMode(state: LhModeInfo | undefined): { lhMode: string | null; lhPaused: string | null } {
|
|
57
|
+
const mode = typeof state?.mode === "string" && state.mode && state.mode !== "none" ? state.mode : null;
|
|
58
|
+
const paused = typeof state?.paused === "string" && state.paused && state.paused !== "none" && state.paused !== mode ? state.paused : null;
|
|
59
|
+
return { lhMode: mode, lhPaused: paused };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** UNI-269: long-horizon's command runner behind `set_lh_mode` (packages/long-horizon/src/commands.ts). */
|
|
63
|
+
export const LH_MODE_RUNNER = "unipi:lh-mode";
|
|
54
64
|
/** UNI-118: dream_status pushes coalesce within this window. */
|
|
55
65
|
export const DREAM_COALESCE_MS = 250;
|
|
56
66
|
|
|
@@ -645,6 +655,8 @@ export function createBridge(pi: ExtensionAPI, deps: BridgeDeps = defaultDeps) {
|
|
|
645
655
|
|
|
646
656
|
// UNI-222: long-horizon progress (sticky LH_PROGRESS on the core bus).
|
|
647
657
|
const lhProgress = (): LhProgressInfo | undefined => bus.get(UNIPI_EVENTS.LH_PROGRESS) as LhProgressInfo | undefined;
|
|
658
|
+
// UNI-269: the working mode (sticky LH_STATE — the footer's "Graph Mode").
|
|
659
|
+
const lhMode = (): LhModeInfo | undefined => bus.get(UNIPI_EVENTS.LH_STATE) as LhModeInfo | undefined;
|
|
648
660
|
|
|
649
661
|
const hello = (): OutMsg => {
|
|
650
662
|
const c = ctx!;
|
|
@@ -664,6 +676,7 @@ export function createBridge(pi: ExtensionAPI, deps: BridgeDeps = defaultDeps) {
|
|
|
664
676
|
fusion: fusionPreset(),
|
|
665
677
|
work: workItems(),
|
|
666
678
|
...(lhProgress() ? { lhProgress: lhProgress() } : {}),
|
|
679
|
+
...(lhMode() ? { lhMode: lhMode() } : {}),
|
|
667
680
|
...(() => {
|
|
668
681
|
const dream = dreamStatus();
|
|
669
682
|
return dream ? { dream } : {};
|
|
@@ -751,6 +764,9 @@ export function createBridge(pi: ExtensionAPI, deps: BridgeDeps = defaultDeps) {
|
|
|
751
764
|
// background subagent, a fusion handoff) — the host passes it into
|
|
752
765
|
// chat_list so lists show "Working…" instead of idle/finished.
|
|
753
766
|
pendingWork: currentPendingWork(),
|
|
767
|
+
// UNI-269: the working mode for the host's chat_list badge (null =
|
|
768
|
+
// regular / long-horizon not loaded); a parked owner's mode apart.
|
|
769
|
+
...recordLhMode(lhMode()),
|
|
754
770
|
};
|
|
755
771
|
try {
|
|
756
772
|
const file = join(dir, `${process.pid}.json`);
|
|
@@ -1516,6 +1532,23 @@ export function createBridge(pi: ExtensionAPI, deps: BridgeDeps = defaultDeps) {
|
|
|
1516
1532
|
case "lh_progress_get":
|
|
1517
1533
|
write(sock, { t: "lh_progress", progress: lhProgress(), ref: msg.ref });
|
|
1518
1534
|
return;
|
|
1535
|
+
case "set_lh_mode": {
|
|
1536
|
+
// Through long-horizon's own runner (no hard dependency on the package).
|
|
1537
|
+
try {
|
|
1538
|
+
const out = await callCommandRunner<{ ok: boolean; reason?: string }>(LH_MODE_RUNNER, ctx, { mode: msg.mode });
|
|
1539
|
+
if (!out.found) return fail("Long-horizon modes need a newer unipi on this PC.");
|
|
1540
|
+
if (!out.result?.ok) return fail(out.result?.reason ?? "Could not switch the mode.");
|
|
1541
|
+
ack();
|
|
1542
|
+
// The runner's LH_STATE emit already queued a coalesced push; send
|
|
1543
|
+
// the fresh value now too so the phone's chip settles at once.
|
|
1544
|
+
lastLhMode = JSON.stringify(lhMode() ?? null);
|
|
1545
|
+
writeRecord();
|
|
1546
|
+
send({ t: "lh_mode", mode: lhMode() });
|
|
1547
|
+
} catch (error) {
|
|
1548
|
+
fail(error instanceof Error ? error.message : String(error));
|
|
1549
|
+
}
|
|
1550
|
+
return;
|
|
1551
|
+
}
|
|
1519
1552
|
case "dream_get":
|
|
1520
1553
|
write(sock, { t: "dream_status", status: dreamStatus(), ref: msg.ref });
|
|
1521
1554
|
return;
|
|
@@ -1791,6 +1824,23 @@ export function createBridge(pi: ExtensionAPI, deps: BridgeDeps = defaultDeps) {
|
|
|
1791
1824
|
lhTimer.unref?.();
|
|
1792
1825
|
});
|
|
1793
1826
|
|
|
1827
|
+
// UNI-269: working-mode pushes, coalesced and only on a real change (the
|
|
1828
|
+
// owner lifecycle re-publishes LH_STATE with the same payload often).
|
|
1829
|
+
let lhModeTimer: ReturnType<typeof setTimeout> | undefined;
|
|
1830
|
+
let lastLhMode = JSON.stringify(lhMode() ?? null);
|
|
1831
|
+
bus.on(pi, UNIPI_EVENTS.LH_STATE, () => {
|
|
1832
|
+
if (lhModeTimer) return;
|
|
1833
|
+
lhModeTimer = setTimeout(() => {
|
|
1834
|
+
lhModeTimer = undefined;
|
|
1835
|
+
const now = JSON.stringify(lhMode() ?? null);
|
|
1836
|
+
if (now === lastLhMode) return;
|
|
1837
|
+
lastLhMode = now;
|
|
1838
|
+
writeRecord();
|
|
1839
|
+
send({ t: "lh_mode", mode: lhMode() });
|
|
1840
|
+
}, LH_PROGRESS_COALESCE_MS);
|
|
1841
|
+
lhModeTimer.unref?.();
|
|
1842
|
+
});
|
|
1843
|
+
|
|
1794
1844
|
// UNI-118: Dream status pushes (run started/finished, proposal decided…),
|
|
1795
1845
|
// coalesced. Subscribed lazily: the dream module may load after us.
|
|
1796
1846
|
let dreamTimer: ReturnType<typeof setTimeout> | undefined;
|
|
@@ -131,6 +131,20 @@ export type LhProgressInfo = {
|
|
|
131
131
|
updatedAt: number;
|
|
132
132
|
};
|
|
133
133
|
|
|
134
|
+
/** UNI-269: the session's long-horizon working mode (`@pi-unipi/core`
|
|
135
|
+
* LhStateEvent), relayed verbatim. `mode` = what the next turn runs in
|
|
136
|
+
* (`none` = regular); `paused` = a parked owner's mode. */
|
|
137
|
+
export type LhModeInfo = {
|
|
138
|
+
mode: string;
|
|
139
|
+
paused?: string;
|
|
140
|
+
owner?: { kind: string; status: "active" | "parked" };
|
|
141
|
+
lastStop?: { kind: string; at: number };
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
/** UNI-269: the modes `set_lh_mode` accepts. */
|
|
145
|
+
export const LH_MODE_IDS = ["goal", "ralph", "swarm", "graph", "none"] as const;
|
|
146
|
+
export type LhModeId = (typeof LH_MODE_IDS)[number];
|
|
147
|
+
|
|
134
148
|
/** One row of the phone's "Running" section (UNI-160 §4): a background task,
|
|
135
149
|
* a subagent, or the Fusion sidekick, in one shape. */
|
|
136
150
|
export interface WorkItemInfo {
|
|
@@ -231,6 +245,8 @@ export type OutMsg =
|
|
|
231
245
|
work: WorkItemInfo[];
|
|
232
246
|
/** UNI-222: the long-horizon progress snapshot at connect time; absent when long-horizon never published one. */
|
|
233
247
|
lhProgress?: LhProgressInfo;
|
|
248
|
+
/** UNI-269: the working mode at connect time; absent when long-horizon isn't loaded. */
|
|
249
|
+
lhMode?: LhModeInfo;
|
|
234
250
|
/** UNI-118: Dream status at connect time; absent when the dream module isn't loaded. */
|
|
235
251
|
dream?: DreamStatusInfo;
|
|
236
252
|
}
|
|
@@ -303,6 +319,8 @@ export type OutMsg =
|
|
|
303
319
|
* client, coalesced ≤ 4/s), or the reply to `lh_progress_get` (`ref`).
|
|
304
320
|
* `progress` undefined = long-horizon isn't loaded / never published. */
|
|
305
321
|
| { t: "lh_progress"; progress: LhProgressInfo | undefined; ref?: string }
|
|
322
|
+
/** UNI-269: the working mode changed (pushed to every client, coalesced). */
|
|
323
|
+
| { t: "lh_mode"; mode: LhModeInfo | undefined }
|
|
306
324
|
/** UNI-118: Dream status changed (pushed to every client, coalesced), or the
|
|
307
325
|
* reply to `dream_get` (`ref`). `status` undefined = the dream module isn't loaded. */
|
|
308
326
|
| { t: "dream_status"; status: DreamStatusInfo | undefined; ref?: string }
|
|
@@ -437,6 +455,9 @@ export type InMsg =
|
|
|
437
455
|
| { t: "work_background"; id: string; ref?: string }
|
|
438
456
|
/** UNI-222: the current long-horizon progress snapshot; replies `lh_progress{progress, ref}`. */
|
|
439
457
|
| { t: "lh_progress_get"; ref?: string }
|
|
458
|
+
/** UNI-269: switch the working mode (no prompt); `none` = /unipi:regular.
|
|
459
|
+
* Replies `ack` (then an `lh_mode` push) or `error{message}`. */
|
|
460
|
+
| { t: "set_lh_mode"; mode: LhModeId; ref?: string }
|
|
440
461
|
/** UNI-118: the current Dream status; replies `dream_status{status, ref}`. */
|
|
441
462
|
| { t: "dream_get"; ref?: string }
|
|
442
463
|
/** UNI-118: one run's report + trajectory; replies `dream_detail` (or `error`). */
|
|
@@ -480,6 +501,7 @@ const IN_TYPES = new Set([
|
|
|
480
501
|
"work_rerun",
|
|
481
502
|
"work_background",
|
|
482
503
|
"lh_progress_get",
|
|
504
|
+
"set_lh_mode",
|
|
483
505
|
"dream_get",
|
|
484
506
|
"dream_detail",
|
|
485
507
|
"dream_action",
|
|
@@ -613,6 +635,11 @@ export function parseIn(line: string): InMsg | { bad: string; ref?: string } | u
|
|
|
613
635
|
return { t: "work_background", id: m.id, ref };
|
|
614
636
|
case "lh_progress_get":
|
|
615
637
|
return { t: "lh_progress_get", ref };
|
|
638
|
+
case "set_lh_mode":
|
|
639
|
+
if (typeof m.mode !== "string" || !(LH_MODE_IDS as readonly string[]).includes(m.mode)) {
|
|
640
|
+
return { bad: "set_lh_mode.mode must be goal|ralph|swarm|graph|none", ref };
|
|
641
|
+
}
|
|
642
|
+
return { t: "set_lh_mode", mode: m.mode as LhModeId, ref };
|
|
616
643
|
case "dream_get":
|
|
617
644
|
return { t: "dream_get", ref };
|
|
618
645
|
case "dream_detail":
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/ask-user",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.39",
|
|
4
4
|
"description": "Structured user input tool for Pi coding agent — single-select, multi-select, freeform",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"access": "public"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
45
|
+
"@pi-unipi/core": "3.0.0-alpha.39"
|
|
46
46
|
},
|
|
47
47
|
"peerDependencies": {
|
|
48
48
|
"@earendil-works/pi-coding-agent": "^0.87.1",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/background-tasks",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.39",
|
|
4
4
|
"description": "Background tasks for UniPi — durable shell jobs and delegated background agents with a footer dock",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@earendil-works/pi-ai": "^0.87.1",
|
|
13
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
13
|
+
"@pi-unipi/core": "3.0.0-alpha.39",
|
|
14
14
|
"turndown": "^7.2.4"
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/btw",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.39",
|
|
4
4
|
"description": "A pi extension for parallel side conversations with /unipi:btw — part of the Unipi suite",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "extensions/btw.ts",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"@earendil-works/pi-tui": "^0.87.1"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
40
|
+
"@pi-unipi/core": "3.0.0-alpha.39"
|
|
41
41
|
},
|
|
42
42
|
"pi": {
|
|
43
43
|
"extensions": [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/compactor",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.39",
|
|
4
4
|
"description": "Compaction for Pi — lossless zero-LLM or model summaries, rebuilt from full history, with session recall",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
"access": "public"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
37
|
-
"@pi-unipi/info-screen": "3.0.0-alpha.
|
|
36
|
+
"@pi-unipi/core": "3.0.0-alpha.39",
|
|
37
|
+
"@pi-unipi/info-screen": "3.0.0-alpha.39",
|
|
38
38
|
"@earendil-works/pi-agent-core": "^0.87.1"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/dream",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.39",
|
|
4
4
|
"description": "A pi extension that dreams: reviews past session struggles in the background, turns repeated false paths into memory lessons, and crafts skills from errors — part of the Unipi suite",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "extensions/dream.ts",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"@earendil-works/pi-tui": "^0.87.1"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
42
|
+
"@pi-unipi/core": "3.0.0-alpha.39"
|
|
43
43
|
},
|
|
44
44
|
"pi": {
|
|
45
45
|
"extensions": [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/footer",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.39",
|
|
4
4
|
"description": "Persistent status bar for Unipi — subscribes to UNIPI_EVENTS and renders key stats from all unipi packages",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"access": "public"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
36
|
-
"@pi-unipi/background-tasks": "3.0.0-alpha.
|
|
35
|
+
"@pi-unipi/core": "3.0.0-alpha.39",
|
|
36
|
+
"@pi-unipi/background-tasks": "3.0.0-alpha.39"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@earendil-works/pi-coding-agent": "^0.87.1",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/fusion",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.39",
|
|
4
4
|
"description": "Devin-style model picker, fusion presets (lead + sidekick), and Local Fusion runtime for UniPi",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -32,9 +32,9 @@
|
|
|
32
32
|
"access": "public"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
36
|
-
"@pi-unipi/subagents": "3.0.0-alpha.
|
|
37
|
-
"@pi-unipi/utility": "3.0.0-alpha.
|
|
35
|
+
"@pi-unipi/core": "3.0.0-alpha.39",
|
|
36
|
+
"@pi-unipi/subagents": "3.0.0-alpha.39",
|
|
37
|
+
"@pi-unipi/utility": "3.0.0-alpha.39"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
40
|
"@earendil-works/pi-ai": "^0.87.1",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/info-screen",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.39",
|
|
4
4
|
"description": "Unicrab startup splash and the /unipi:info dashboard — this session, context, usage, compaction savings",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"access": "public"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
36
|
+
"@pi-unipi/core": "3.0.0-alpha.39"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@earendil-works/pi-coding-agent": "^0.87.1",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/input-shortcuts",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.39",
|
|
4
4
|
"description": "Keyboard shortcuts for stash/restore, undo/redo, clipboard, and thinking toggle — chord-based overlay system",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"access": "public"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
36
|
+
"@pi-unipi/core": "3.0.0-alpha.39"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@earendil-works/pi-coding-agent": "^0.87.1",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/kanboard",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.39",
|
|
4
4
|
"description": "Kanboard v3 — deferred-work board: CLI/daemon bridge, task runner and skill",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"access": "public"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
34
|
+
"@pi-unipi/core": "3.0.0-alpha.39"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
37
|
"@earendil-works/pi-coding-agent": "^0.87.1",
|
|
@@ -48,10 +48,10 @@
|
|
|
48
48
|
"themes": []
|
|
49
49
|
},
|
|
50
50
|
"optionalDependencies": {
|
|
51
|
-
"@pi-unipi/kanboard-linux-x64": "3.0.0-alpha.
|
|
52
|
-
"@pi-unipi/kanboard-linux-arm64": "3.0.0-alpha.
|
|
53
|
-
"@pi-unipi/kanboard-darwin-x64": "3.0.0-alpha.
|
|
54
|
-
"@pi-unipi/kanboard-darwin-arm64": "3.0.0-alpha.
|
|
55
|
-
"@pi-unipi/kanboard-win32-x64": "3.0.0-alpha.
|
|
51
|
+
"@pi-unipi/kanboard-linux-x64": "3.0.0-alpha.39",
|
|
52
|
+
"@pi-unipi/kanboard-linux-arm64": "3.0.0-alpha.39",
|
|
53
|
+
"@pi-unipi/kanboard-darwin-x64": "3.0.0-alpha.39",
|
|
54
|
+
"@pi-unipi/kanboard-darwin-arm64": "3.0.0-alpha.39",
|
|
55
|
+
"@pi-unipi/kanboard-win32-x64": "3.0.0-alpha.39"
|
|
56
56
|
}
|
|
57
57
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/long-horizon",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.39",
|
|
4
4
|
"description": "Long-horizon execution for Pi — mode-gated /goal /ralph /swarm /graph orchestration with a TypeSafe prompt judge",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"access": "public"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
40
|
+
"@pi-unipi/core": "3.0.0-alpha.39",
|
|
41
41
|
"@resvg/resvg-wasm": "^2.6.2",
|
|
42
42
|
"beautiful-mermaid": "^1.1.3"
|
|
43
43
|
},
|
|
@@ -16,9 +16,9 @@
|
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
import type { ExtensionAPI, ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
|
|
19
|
-
import { bus, appendProgress, sendHarnessUserMessage, UNIPI_EVENTS, type ProgressData } from "@pi-unipi/core";
|
|
19
|
+
import { bus, appendProgress, registerCommandRunner, sendHarnessUserMessage, UNIPI_EVENTS, type ProgressData } from "@pi-unipi/core";
|
|
20
20
|
import type { LhMode, OwnerKind } from "./modes.js";
|
|
21
|
-
import { MODE_REGISTRY } from "./modes.js";
|
|
21
|
+
import { isLhMode, MODE_REGISTRY, modeForOwnerKind } from "./modes.js";
|
|
22
22
|
import type { Gate } from "./gate.js";
|
|
23
23
|
import type { OwnerCoordinator } from "./owner.js";
|
|
24
24
|
import type { RalphLoop } from "./engine/ralph.js";
|
|
@@ -324,4 +324,59 @@ export function registerLongHorizonCommands(
|
|
|
324
324
|
},
|
|
325
325
|
});
|
|
326
326
|
|
|
327
|
+
// UNI-269: the app's mode chip (app-bridge `set_lh_mode`) — switch the
|
|
328
|
+
// session's working mode without sending a prompt.
|
|
329
|
+
registerCommandRunner(LH_MODE_RUNNER, async (_ctx, args) =>
|
|
330
|
+
selectSessionMode(gate, owner, String((args as { mode?: unknown } | undefined)?.mode ?? ""), stopActiveOwnerFor, machine),
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/** Runner name the app bridge calls for `set_lh_mode` (UNI-269). */
|
|
335
|
+
export const LH_MODE_RUNNER = "unipi:lh-mode";
|
|
336
|
+
|
|
337
|
+
export type SelectModeResult = { ok: true; mode: LhMode } | { ok: false; reason: string };
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* UNI-269: pick the session's working mode from outside the TUI (the app's
|
|
341
|
+
* mode chip), with no prompt. Mirrors the slash commands:
|
|
342
|
+
* - `none` = /unipi:regular: ends the active owner (terminal) and pins
|
|
343
|
+
* regular mode.
|
|
344
|
+
* - a work mode = /unipi:<mode> minus the prompt: an active owner of
|
|
345
|
+
* another mode is parked first (refused when the park slot is held),
|
|
346
|
+
* then the mode is sticky for the next turns and shows at once.
|
|
347
|
+
* - the active owner's own mode is a no-op.
|
|
348
|
+
*/
|
|
349
|
+
export function selectSessionMode(
|
|
350
|
+
gate: Gate,
|
|
351
|
+
owner: OwnerCoordinator,
|
|
352
|
+
mode: string,
|
|
353
|
+
stopActive: () => string | undefined,
|
|
354
|
+
machine?: GoalMachine,
|
|
355
|
+
): SelectModeResult {
|
|
356
|
+
if (!isLhMode(mode)) return { ok: false, reason: `unknown mode "${mode}"` };
|
|
357
|
+
if (mode === "none") {
|
|
358
|
+
stopActive();
|
|
359
|
+
gate.setSessionMode("none");
|
|
360
|
+
return { ok: true, mode };
|
|
361
|
+
}
|
|
362
|
+
const active = owner.getActive();
|
|
363
|
+
if (active && modeForOwnerKind(active.kind) === mode) return { ok: true, mode };
|
|
364
|
+
if (active) {
|
|
365
|
+
// Same as the gate's suspend-and-switch hook: a goal pauses with its owner.
|
|
366
|
+
if (active.kind === "goal") machine?.pause("paused(superseded)");
|
|
367
|
+
const reason = `paused(superseded_by:${mode})`;
|
|
368
|
+
const suspended = owner.suspend(reason);
|
|
369
|
+
if (!suspended) {
|
|
370
|
+
const parked = owner.getParked();
|
|
371
|
+
return {
|
|
372
|
+
ok: false,
|
|
373
|
+
reason: parked
|
|
374
|
+
? `A ${parked.kind === "ralph-loop" ? "ralph loop" : parked.kind} ("${parked.label}") is already parked — resume or clear it first.`
|
|
375
|
+
: "The running work could not be parked.",
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
bus.emit(UNIPI_EVENTS.LONG_HORIZON_OWNER_CHANGED, { event: "suspended", ownerId: suspended.ownerId, reason });
|
|
379
|
+
}
|
|
380
|
+
gate.selectMode(mode);
|
|
381
|
+
return { ok: true, mode };
|
|
327
382
|
}
|
|
@@ -197,6 +197,16 @@ export class Gate {
|
|
|
197
197
|
if (this.pi) syncModeTools(this.pi, mode);
|
|
198
198
|
}
|
|
199
199
|
|
|
200
|
+
/** UNI-269: the app's mode chip picked a work mode with no prompt. Same
|
|
201
|
+
* sticky override as setExplicit (the next turn resolves to it, badge and
|
|
202
|
+
* all), but the display flips NOW so the footer and the app's chip show
|
|
203
|
+
* the pick before any turn runs. */
|
|
204
|
+
selectMode(mode: LhMode): void {
|
|
205
|
+
this.setExplicit(mode);
|
|
206
|
+
this.display = mode;
|
|
207
|
+
this.deps.onDisplayChanged?.();
|
|
208
|
+
}
|
|
209
|
+
|
|
200
210
|
/** Pin the session to a mode (/unipi:regular, goal stop): every later turn resolves to it. */
|
|
201
211
|
setSessionMode(mode: LhMode): void {
|
|
202
212
|
this.sessionOverride = mode;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/mcp",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.39",
|
|
4
4
|
"description": "MCP server management extension for Pi coding agent — browse, add, configure, and use MCP servers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"test": "npx tsx --test tests/**/*.test.ts"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
33
|
+
"@pi-unipi/core": "3.0.0-alpha.39"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"@earendil-works/pi-coding-agent": "^0.87.1",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/memory",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.39",
|
|
4
4
|
"description": "Persistent cross-session memory on MemPalace (auto-installed): daemon-routed writes, shared palace with other agents, for Pi coding agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
"README.md"
|
|
45
45
|
],
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
48
|
-
"@pi-unipi/info-screen": "3.0.0-alpha.
|
|
47
|
+
"@pi-unipi/core": "3.0.0-alpha.39",
|
|
48
|
+
"@pi-unipi/info-screen": "3.0.0-alpha.39",
|
|
49
49
|
"js-yaml": "^4.1.0"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/notify",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.39",
|
|
4
4
|
"description": "Cross-platform notification extension for Pi — native OS, Gotify, and Telegram notifications for agent lifecycle events",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"access": "public"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
37
|
+
"@pi-unipi/core": "3.0.0-alpha.39",
|
|
38
38
|
"node-notifier": "^10.0.1"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/skill-registry",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.39",
|
|
4
4
|
"description": "Skill registry for pi — per-project skill on/off, a skill vault, and jev-judged skill exposure",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
},
|
|
34
34
|
"main": "index.ts",
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
36
|
+
"@pi-unipi/core": "3.0.0-alpha.39"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@earendil-works/pi-coding-agent": "^0.87.1",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/subagents",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.39",
|
|
4
4
|
"description": "Subagents for UniPi — Devin-model independent child agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
"test": "npx tsx --test src/__tests__/*.test.ts"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
13
|
-
"@pi-unipi/utility": "3.0.0-alpha.
|
|
12
|
+
"@pi-unipi/core": "3.0.0-alpha.39",
|
|
13
|
+
"@pi-unipi/utility": "3.0.0-alpha.39",
|
|
14
14
|
"@earendil-works/pi-agent-core": "^0.87.1",
|
|
15
15
|
"acorn": "8.18.0"
|
|
16
16
|
},
|
|
@@ -16863,6 +16863,15 @@ var Gate = class {
|
|
|
16863
16863
|
this.sessionOverride = mode;
|
|
16864
16864
|
if (this.pi) syncModeTools(this.pi, mode);
|
|
16865
16865
|
}
|
|
16866
|
+
/** UNI-269: the app's mode chip picked a work mode with no prompt. Same
|
|
16867
|
+
* sticky override as setExplicit (the next turn resolves to it, badge and
|
|
16868
|
+
* all), but the display flips NOW so the footer and the app's chip show
|
|
16869
|
+
* the pick before any turn runs. */
|
|
16870
|
+
selectMode(mode) {
|
|
16871
|
+
this.setExplicit(mode);
|
|
16872
|
+
this.display = mode;
|
|
16873
|
+
this.deps.onDisplayChanged?.();
|
|
16874
|
+
}
|
|
16866
16875
|
/** Pin the session to a mode (/unipi:regular, goal stop): every later turn resolves to it. */
|
|
16867
16876
|
setSessionMode(mode) {
|
|
16868
16877
|
this.sessionOverride = mode;
|
|
@@ -17264,6 +17273,36 @@ Settings: ~/.pi/agent/settings.json \u2192 unipi.longHorizon`
|
|
|
17264
17273
|
notify(ctx, "Regular mode.");
|
|
17265
17274
|
}
|
|
17266
17275
|
});
|
|
17276
|
+
registerCommandRunner(
|
|
17277
|
+
LH_MODE_RUNNER,
|
|
17278
|
+
async (_ctx, args) => selectSessionMode(gate, owner, String(args?.mode ?? ""), stopActiveOwnerFor, machine)
|
|
17279
|
+
);
|
|
17280
|
+
}
|
|
17281
|
+
var LH_MODE_RUNNER = "unipi:lh-mode";
|
|
17282
|
+
function selectSessionMode(gate, owner, mode, stopActive, machine) {
|
|
17283
|
+
if (!isLhMode(mode)) return { ok: false, reason: `unknown mode "${mode}"` };
|
|
17284
|
+
if (mode === "none") {
|
|
17285
|
+
stopActive();
|
|
17286
|
+
gate.setSessionMode("none");
|
|
17287
|
+
return { ok: true, mode };
|
|
17288
|
+
}
|
|
17289
|
+
const active = owner.getActive();
|
|
17290
|
+
if (active && modeForOwnerKind(active.kind) === mode) return { ok: true, mode };
|
|
17291
|
+
if (active) {
|
|
17292
|
+
if (active.kind === "goal") machine?.pause("paused(superseded)");
|
|
17293
|
+
const reason = `paused(superseded_by:${mode})`;
|
|
17294
|
+
const suspended = owner.suspend(reason);
|
|
17295
|
+
if (!suspended) {
|
|
17296
|
+
const parked = owner.getParked();
|
|
17297
|
+
return {
|
|
17298
|
+
ok: false,
|
|
17299
|
+
reason: parked ? `A ${parked.kind === "ralph-loop" ? "ralph loop" : parked.kind} ("${parked.label}") is already parked \u2014 resume or clear it first.` : "The running work could not be parked."
|
|
17300
|
+
};
|
|
17301
|
+
}
|
|
17302
|
+
bus.emit(UNIPI_EVENTS.LONG_HORIZON_OWNER_CHANGED, { event: "suspended", ownerId: suspended.ownerId, reason });
|
|
17303
|
+
}
|
|
17304
|
+
gate.selectMode(mode);
|
|
17305
|
+
return { ok: true, mode };
|
|
17267
17306
|
}
|
|
17268
17307
|
|
|
17269
17308
|
// packages/long-horizon/src/engine/goal-state.ts
|
|
@@ -57602,6 +57641,7 @@ function historyPage(branch, before, budget = ENTRIES_BUDGET) {
|
|
|
57602
57641
|
|
|
57603
57642
|
// packages/app-bridge/src/wire.ts
|
|
57604
57643
|
var BRIDGE_PROTOCOL = 1;
|
|
57644
|
+
var LH_MODE_IDS = ["goal", "ralph", "swarm", "graph", "none"];
|
|
57605
57645
|
var IN_TYPES = /* @__PURE__ */ new Set([
|
|
57606
57646
|
"prompt",
|
|
57607
57647
|
"abort",
|
|
@@ -57636,6 +57676,7 @@ var IN_TYPES = /* @__PURE__ */ new Set([
|
|
|
57636
57676
|
"work_rerun",
|
|
57637
57677
|
"work_background",
|
|
57638
57678
|
"lh_progress_get",
|
|
57679
|
+
"set_lh_mode",
|
|
57639
57680
|
"dream_get",
|
|
57640
57681
|
"dream_detail",
|
|
57641
57682
|
"dream_action"
|
|
@@ -57763,6 +57804,11 @@ function parseIn(line) {
|
|
|
57763
57804
|
return { t: "work_background", id: m.id, ref };
|
|
57764
57805
|
case "lh_progress_get":
|
|
57765
57806
|
return { t: "lh_progress_get", ref };
|
|
57807
|
+
case "set_lh_mode":
|
|
57808
|
+
if (typeof m.mode !== "string" || !LH_MODE_IDS.includes(m.mode)) {
|
|
57809
|
+
return { bad: "set_lh_mode.mode must be goal|ralph|swarm|graph|none", ref };
|
|
57810
|
+
}
|
|
57811
|
+
return { t: "set_lh_mode", mode: m.mode, ref };
|
|
57766
57812
|
case "dream_get":
|
|
57767
57813
|
return { t: "dream_get", ref };
|
|
57768
57814
|
case "dream_detail":
|
|
@@ -58122,6 +58168,12 @@ init_core();
|
|
|
58122
58168
|
init_core();
|
|
58123
58169
|
var MEDIA_CHUNK_CHARS = 700 * 1024;
|
|
58124
58170
|
var LH_PROGRESS_COALESCE_MS = 250;
|
|
58171
|
+
function recordLhMode(state2) {
|
|
58172
|
+
const mode = typeof state2?.mode === "string" && state2.mode && state2.mode !== "none" ? state2.mode : null;
|
|
58173
|
+
const paused = typeof state2?.paused === "string" && state2.paused && state2.paused !== "none" && state2.paused !== mode ? state2.paused : null;
|
|
58174
|
+
return { lhMode: mode, lhPaused: paused };
|
|
58175
|
+
}
|
|
58176
|
+
var LH_MODE_RUNNER2 = "unipi:lh-mode";
|
|
58125
58177
|
var DREAM_COALESCE_MS = 250;
|
|
58126
58178
|
var DREAM_API_KEY2 = /* @__PURE__ */ Symbol.for("unipi.dream.api");
|
|
58127
58179
|
var getDreamApi = () => globalThis[DREAM_API_KEY2];
|
|
@@ -58498,6 +58550,7 @@ function createBridge(pi, deps = defaultDeps2) {
|
|
|
58498
58550
|
}
|
|
58499
58551
|
};
|
|
58500
58552
|
const lhProgress = () => bus.get(UNIPI_EVENTS.LH_PROGRESS);
|
|
58553
|
+
const lhMode = () => bus.get(UNIPI_EVENTS.LH_STATE);
|
|
58501
58554
|
const hello = () => {
|
|
58502
58555
|
const c2 = ctx;
|
|
58503
58556
|
const rest = {
|
|
@@ -58516,6 +58569,7 @@ function createBridge(pi, deps = defaultDeps2) {
|
|
|
58516
58569
|
fusion: fusionPreset(),
|
|
58517
58570
|
work: workItems(),
|
|
58518
58571
|
...lhProgress() ? { lhProgress: lhProgress() } : {},
|
|
58572
|
+
...lhMode() ? { lhMode: lhMode() } : {},
|
|
58519
58573
|
...(() => {
|
|
58520
58574
|
const dream = dreamStatus();
|
|
58521
58575
|
return dream ? { dream } : {};
|
|
@@ -58591,7 +58645,10 @@ function createBridge(pi, deps = defaultDeps2) {
|
|
|
58591
58645
|
// UNI-221: wake-capable work still pending (bg task with a wake, a
|
|
58592
58646
|
// background subagent, a fusion handoff) — the host passes it into
|
|
58593
58647
|
// chat_list so lists show "Working…" instead of idle/finished.
|
|
58594
|
-
pendingWork: currentPendingWork()
|
|
58648
|
+
pendingWork: currentPendingWork(),
|
|
58649
|
+
// UNI-269: the working mode for the host's chat_list badge (null =
|
|
58650
|
+
// regular / long-horizon not loaded); a parked owner's mode apart.
|
|
58651
|
+
...recordLhMode(lhMode())
|
|
58595
58652
|
};
|
|
58596
58653
|
try {
|
|
58597
58654
|
const file = join89(dir, `${process.pid}.json`);
|
|
@@ -59208,6 +59265,20 @@ function createBridge(pi, deps = defaultDeps2) {
|
|
|
59208
59265
|
case "lh_progress_get":
|
|
59209
59266
|
write(sock, { t: "lh_progress", progress: lhProgress(), ref: msg.ref });
|
|
59210
59267
|
return;
|
|
59268
|
+
case "set_lh_mode": {
|
|
59269
|
+
try {
|
|
59270
|
+
const out = await callCommandRunner(LH_MODE_RUNNER2, ctx, { mode: msg.mode });
|
|
59271
|
+
if (!out.found) return fail("Long-horizon modes need a newer unipi on this PC.");
|
|
59272
|
+
if (!out.result?.ok) return fail(out.result?.reason ?? "Could not switch the mode.");
|
|
59273
|
+
ack();
|
|
59274
|
+
lastLhMode = JSON.stringify(lhMode() ?? null);
|
|
59275
|
+
writeRecord();
|
|
59276
|
+
send({ t: "lh_mode", mode: lhMode() });
|
|
59277
|
+
} catch (error) {
|
|
59278
|
+
fail(error instanceof Error ? error.message : String(error));
|
|
59279
|
+
}
|
|
59280
|
+
return;
|
|
59281
|
+
}
|
|
59211
59282
|
case "dream_get":
|
|
59212
59283
|
write(sock, { t: "dream_status", status: dreamStatus(), ref: msg.ref });
|
|
59213
59284
|
return;
|
|
@@ -59426,6 +59497,20 @@ function createBridge(pi, deps = defaultDeps2) {
|
|
|
59426
59497
|
}, LH_PROGRESS_COALESCE_MS);
|
|
59427
59498
|
lhTimer.unref?.();
|
|
59428
59499
|
});
|
|
59500
|
+
let lhModeTimer;
|
|
59501
|
+
let lastLhMode = JSON.stringify(lhMode() ?? null);
|
|
59502
|
+
bus.on(pi, UNIPI_EVENTS.LH_STATE, () => {
|
|
59503
|
+
if (lhModeTimer) return;
|
|
59504
|
+
lhModeTimer = setTimeout(() => {
|
|
59505
|
+
lhModeTimer = void 0;
|
|
59506
|
+
const now2 = JSON.stringify(lhMode() ?? null);
|
|
59507
|
+
if (now2 === lastLhMode) return;
|
|
59508
|
+
lastLhMode = now2;
|
|
59509
|
+
writeRecord();
|
|
59510
|
+
send({ t: "lh_mode", mode: lhMode() });
|
|
59511
|
+
}, LH_PROGRESS_COALESCE_MS);
|
|
59512
|
+
lhModeTimer.unref?.();
|
|
59513
|
+
});
|
|
59429
59514
|
let dreamTimer;
|
|
59430
59515
|
let unsubDream;
|
|
59431
59516
|
let lastDream = "";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/updater",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.39",
|
|
4
4
|
"description": "Auto-updater, changelog browser, and readme browser for Unipi — checks npm registry, renders CHANGELOG.md and README.md files in TUI overlays",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"access": "public"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
37
|
+
"@pi-unipi/core": "3.0.0-alpha.39"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
40
|
"@earendil-works/pi-coding-agent": "^0.87.1",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/utility",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.39",
|
|
4
4
|
"description": "Utility commands and tools for Pi coding agent — lifecycle, diagnostics, cache, analytics, display, batch execution",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"access": "public"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
39
|
+
"@pi-unipi/core": "3.0.0-alpha.39"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {},
|
|
42
42
|
"peerDependencies": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/watchdog",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.39",
|
|
4
4
|
"description": "Jev watchdog for long-running tool calls and background tasks — judges stuck work via TypeSafe System One and kills or warns",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"access": "public"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@pi-unipi/background-tasks": "3.0.0-alpha.
|
|
36
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
35
|
+
"@pi-unipi/background-tasks": "3.0.0-alpha.39",
|
|
36
|
+
"@pi-unipi/core": "3.0.0-alpha.39"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@earendil-works/pi-coding-agent": "^0.87.1",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/web-api",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.39",
|
|
4
4
|
"description": "Web search, read, and summarize tools with provider-based backend selection for Pi coding agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"README.md"
|
|
32
32
|
],
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
34
|
+
"@pi-unipi/core": "3.0.0-alpha.39",
|
|
35
35
|
"defuddle": "^0.18.1",
|
|
36
36
|
"linkedom": "^0.18.12",
|
|
37
37
|
"wreq-js": "^2.3.0"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/workflow",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.39",
|
|
4
4
|
"description": "Plan mode and permission modes for the Pi coding agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"access": "public"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
30
|
+
"@pi-unipi/core": "3.0.0-alpha.39"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"@earendil-works/pi-ai": "^0.87.1",
|