@pi-unipi/unipi 2.20.1 → 2.20.3
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 +12 -0
- package/package.json +24 -24
- 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/background-tasks/src/index.ts +13 -1
- package/packages/background-tasks/src/tools.ts +6 -6
- package/packages/btw/package.json +2 -2
- package/packages/compactor/package.json +3 -3
- package/packages/core/package.json +1 -1
- package/packages/core/utils.ts +36 -0
- package/packages/footer/package.json +3 -3
- package/packages/fusion/package.json +3 -3
- package/packages/fusion/src/index.ts +10 -1
- package/packages/image/package.json +2 -2
- package/packages/info-screen/package.json +2 -2
- package/packages/input-shortcuts/package.json +2 -2
- package/packages/kanboard/package.json +2 -2
- package/packages/mcp/package.json +2 -2
- package/packages/memory/package.json +3 -3
- package/packages/milestone/package.json +2 -2
- package/packages/notify/package.json +2 -2
- package/packages/ralph/package.json +3 -3
- package/packages/subagents/package.json +2 -2
- package/packages/trajectory/package.json +1 -1
- package/packages/unipi/bundled.js +38 -9
- package/packages/updater/package.json +2 -2
- package/packages/utility/package.json +2 -2
- package/packages/web-api/package.json +2 -2
- package/packages/workflow/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,18 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [2.20.3] — 2026-09-17
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- `background-tasks`: **distinguish persistent dev servers from finite jobs in `bg_run` prompt guidelines.** The prompt guidance previously grouped dev servers and test suites under the same "do not set `triggerOnCompletion:false`" rule. For persistent servers and watchers (e.g. `npm run dev`, `vite`), `triggerOnCompletion: true` caused the UI to show an indefinite "waiting on 1 bg task" spinner and caused `SidekickRuntime` in Fusion to hang waiting for `openBgTasks` to reach zero. `BgRunParams` and `promptGuidelines` in `packages/background-tasks/src/tools.ts` now explicitly instruct agents to set `triggerOnCompletion: false` for long-running servers/daemons so neither the harness nor sidekicks wait indefinitely for exit.
|
|
14
|
+
|
|
15
|
+
## [2.20.2] — 2026-09-17
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- `core`, `background-tasks`, `fusion`: **panes waiting on an auto-resume wake read `working` in herdr, not `idle`.** When the lead's turn ended while background work will re-invoke the agent — a bg task with wake-on-completion, or a Fusion sidekick handoff — herdr's sidebar flipped to `idle` the moment `agent_settled` fired, even as the session's own wake line said "agent resumes automatically when done". New key-scoped claim helper `setHerdrWorking()` in `@pi-unipi/core` emits `herdr:working {active,label}` exactly once per claim transition (the same refcounted event protocol `herdr:blocked` uses); `background-tasks` holds the claim while its bg-wake line is installed and `fusion` holds it while the sidekick wake line is up. Consumed by a one-listener patch to herdr's pi integration (held-working refcount in `desiredState()`, `blocked` still outranks it) — herdr enforces one status authority per pane and ignores second-source `pane.report_agent` reports, so the event protocol is the only channel. Until herdr upstreams the protocol, the patched integration file is local (`herdr integration install pi` reverts it; pristine v8 backup at `~/.pi/agent/herdr-agent-state.v8.orig.bak`).
|
|
20
|
+
|
|
9
21
|
## [2.20.1] — 2026-09-17
|
|
10
22
|
|
|
11
23
|
### Fixed
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/unipi",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.3",
|
|
4
4
|
"description": "All-in-one extension suite for Pi coding agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -84,29 +84,29 @@
|
|
|
84
84
|
"typebox": "^1.1.38"
|
|
85
85
|
},
|
|
86
86
|
"dependencies": {
|
|
87
|
-
"@pi-unipi/ask-user": "2.20.
|
|
88
|
-
"@pi-unipi/background-tasks": "2.20.
|
|
89
|
-
"@pi-unipi/btw": "2.20.
|
|
90
|
-
"@pi-unipi/command-enchantment": "2.20.
|
|
91
|
-
"@pi-unipi/compactor": "2.20.
|
|
92
|
-
"@pi-unipi/core": "2.20.
|
|
93
|
-
"@pi-unipi/footer": "2.20.
|
|
94
|
-
"@pi-unipi/image": "2.20.
|
|
95
|
-
"@pi-unipi/fusion": "2.20.
|
|
96
|
-
"@pi-unipi/info-screen": "2.20.
|
|
97
|
-
"@pi-unipi/input-shortcuts": "2.20.
|
|
98
|
-
"@pi-unipi/kanboard": "2.20.
|
|
99
|
-
"@pi-unipi/mcp": "2.20.
|
|
100
|
-
"@pi-unipi/memory": "2.20.
|
|
101
|
-
"@pi-unipi/milestone": "2.20.
|
|
102
|
-
"@pi-unipi/notify": "2.20.
|
|
103
|
-
"@pi-unipi/ralph": "2.20.
|
|
104
|
-
"@pi-unipi/subagents": "2.20.
|
|
105
|
-
"@pi-unipi/trajectory": "2.20.
|
|
106
|
-
"@pi-unipi/updater": "2.20.
|
|
107
|
-
"@pi-unipi/utility": "2.20.
|
|
108
|
-
"@pi-unipi/web-api": "2.20.
|
|
109
|
-
"@pi-unipi/workflow": "2.20.
|
|
87
|
+
"@pi-unipi/ask-user": "2.20.3",
|
|
88
|
+
"@pi-unipi/background-tasks": "2.20.3",
|
|
89
|
+
"@pi-unipi/btw": "2.20.3",
|
|
90
|
+
"@pi-unipi/command-enchantment": "2.20.3",
|
|
91
|
+
"@pi-unipi/compactor": "2.20.3",
|
|
92
|
+
"@pi-unipi/core": "2.20.3",
|
|
93
|
+
"@pi-unipi/footer": "2.20.3",
|
|
94
|
+
"@pi-unipi/image": "2.20.3",
|
|
95
|
+
"@pi-unipi/fusion": "2.20.3",
|
|
96
|
+
"@pi-unipi/info-screen": "2.20.3",
|
|
97
|
+
"@pi-unipi/input-shortcuts": "2.20.3",
|
|
98
|
+
"@pi-unipi/kanboard": "2.20.3",
|
|
99
|
+
"@pi-unipi/mcp": "2.20.3",
|
|
100
|
+
"@pi-unipi/memory": "2.20.3",
|
|
101
|
+
"@pi-unipi/milestone": "2.20.3",
|
|
102
|
+
"@pi-unipi/notify": "2.20.3",
|
|
103
|
+
"@pi-unipi/ralph": "2.20.3",
|
|
104
|
+
"@pi-unipi/subagents": "2.20.3",
|
|
105
|
+
"@pi-unipi/trajectory": "2.20.3",
|
|
106
|
+
"@pi-unipi/updater": "2.20.3",
|
|
107
|
+
"@pi-unipi/utility": "2.20.3",
|
|
108
|
+
"@pi-unipi/web-api": "2.20.3",
|
|
109
|
+
"@pi-unipi/workflow": "2.20.3"
|
|
110
110
|
},
|
|
111
111
|
"devDependencies": {
|
|
112
112
|
"@earendil-works/pi-agent-core": "^0.84.0",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/ask-user",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.3",
|
|
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",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"access": "public"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@pi-unipi/core": "2.20.
|
|
43
|
+
"@pi-unipi/core": "2.20.3"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
46
|
"@earendil-works/pi-coding-agent": "^0.84.0",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/background-tasks",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.3",
|
|
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.84.0",
|
|
13
|
-
"@pi-unipi/core": "2.20.
|
|
13
|
+
"@pi-unipi/core": "2.20.3",
|
|
14
14
|
"turndown": "^7.2.4"
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
13
|
-
import { createSpinnerLine } from "@pi-unipi/core";
|
|
13
|
+
import { createSpinnerLine, setHerdrWorking } from "@pi-unipi/core";
|
|
14
14
|
import { loadBackgroundTasksConfig } from "./config.js";
|
|
15
15
|
import { BackgroundTaskRegistry } from "./registry.js";
|
|
16
16
|
import {
|
|
@@ -134,9 +134,21 @@ export default function backgroundTasksExtension(pi: ExtensionAPI): void {
|
|
|
134
134
|
{ placement: "aboveEditor" },
|
|
135
135
|
);
|
|
136
136
|
wakeLineInstalled = true;
|
|
137
|
+
// The pane is not done: a running task will re-invoke the agent. Keep
|
|
138
|
+
// herdr at `working` instead of `idle` for exactly as long as the wake
|
|
139
|
+
// line is up (one claim transition per widget install, not per tick).
|
|
140
|
+
const wakeCount = registry
|
|
141
|
+
.allTasks()
|
|
142
|
+
.filter((task) => task.status === "running" && task.triggerOnCompletion).length;
|
|
143
|
+
setHerdrWorking(
|
|
144
|
+
pi,
|
|
145
|
+
"bg-wake",
|
|
146
|
+
`${wakeCount === 1 ? "1 bg task" : `${String(wakeCount)} bg tasks`} will resume agent`,
|
|
147
|
+
);
|
|
137
148
|
} else if (!wantWakeLine && wakeLineInstalled) {
|
|
138
149
|
target.ui.setWidget("background-tasks", undefined);
|
|
139
150
|
wakeLineInstalled = false;
|
|
151
|
+
setHerdrWorking(pi, "bg-wake", null);
|
|
140
152
|
}
|
|
141
153
|
if (running.length === 0 && unseenFinishedCount === 0) {
|
|
142
154
|
target.ui.setStatus("background-tasks", undefined);
|
|
@@ -52,13 +52,13 @@ export const BgRunParams = Type.Object({
|
|
|
52
52
|
notifyOnCompletion: Type.Optional(
|
|
53
53
|
Type.Boolean({
|
|
54
54
|
description:
|
|
55
|
-
"Deliver a durable terminal notification when the task finishes. Default true.
|
|
55
|
+
"Deliver a durable terminal notification when the task finishes. Default true for finite tasks. Set false or pair with triggerOnCompletion:false for persistent servers/daemons/watchers.",
|
|
56
56
|
}),
|
|
57
57
|
),
|
|
58
58
|
triggerOnCompletion: Type.Optional(
|
|
59
59
|
Type.Boolean({
|
|
60
60
|
description:
|
|
61
|
-
"Start a follow-up agent turn on terminal notification. Default true for
|
|
61
|
+
"Start a follow-up agent turn on terminal notification. Default true for finite tasks (tests, builds, exports). MUST set false for persistent background services/servers (e.g. dev servers, watchers) so the harness and subagents do not wait indefinitely for the server to finish. Requires notifyOnCompletion.",
|
|
62
62
|
}),
|
|
63
63
|
),
|
|
64
64
|
});
|
|
@@ -185,14 +185,14 @@ export function registerToolsAndCommands(options: RegisterSurfaceOptions): void
|
|
|
185
185
|
promptSnippet:
|
|
186
186
|
"Start a named long-running shell command; default terminal notification wakes a follow-up turn, so yield instead of polling",
|
|
187
187
|
promptGuidelines: [
|
|
188
|
-
"Use bg_run instead of bash for commands expected to run
|
|
188
|
+
"Use bg_run instead of bash for commands expected to run in the background (test suites, builds, dev servers, watchers).",
|
|
189
|
+
"For FINITE tasks (tests, builds, exports, scripts): leave triggerOnCompletion:true and notifyOnCompletion:true (defaults) to automatically wake the agent when finished.",
|
|
190
|
+
"For PERSISTENT servers/daemons/watchers (e.g. 'npm run dev', vite, live dev servers, background listeners): MUST set triggerOnCompletion:false (and optionally notifyOnCompletion:false) so the agent and sidekick do not wait for the server to exit.",
|
|
189
191
|
"Set isAgent:true only when the background task launches an LLM/agent process; false for scripts, tests, dev servers, sleeps.",
|
|
190
192
|
"Always set name to a concise 2-6 word human-readable label; do not use the raw command as the name.",
|
|
191
|
-
"bg_run returns immediately.
|
|
192
|
-
"After a default bg_run launch, continue only independent useful work that does not merely wait for the task; otherwise briefly acknowledge it if useful, then end the current turn. Do not call sleep, bg_status, or bg_logs merely to wait; the terminal notification will wake you.",
|
|
193
|
+
"bg_run returns immediately. For finite tasks with default wake-up, continue only independent useful work that does not merely wait for the task; otherwise end the current turn. Do not call sleep, bg_status, or bg_logs merely to wait; the terminal notification will wake you.",
|
|
193
194
|
"A running result is not an instruction to poll again.",
|
|
194
195
|
"Treat <background-task-notification> as durable terminal truth. Do not call bg_status to reconfirm it.",
|
|
195
|
-
"Do not set notifyOnCompletion:false or triggerOnCompletion:false unless intentionally opting out.",
|
|
196
196
|
],
|
|
197
197
|
parameters: BgRunParams,
|
|
198
198
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/btw",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.3",
|
|
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.84.0"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@pi-unipi/core": "2.20.
|
|
40
|
+
"@pi-unipi/core": "2.20.3"
|
|
41
41
|
},
|
|
42
42
|
"pi": {
|
|
43
43
|
"extensions": [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/compactor",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.3",
|
|
4
4
|
"description": "Context engine for Pi — zero-LLM compaction, session continuity, sandbox execution, and tool display optimization",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"access": "public"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@pi-unipi/core": "2.20.
|
|
38
|
-
"@pi-unipi/info-screen": "2.20.
|
|
37
|
+
"@pi-unipi/core": "2.20.3",
|
|
38
|
+
"@pi-unipi/info-screen": "2.20.3",
|
|
39
39
|
"@earendil-works/pi-agent-core": "^0.84.0"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
package/packages/core/utils.ts
CHANGED
|
@@ -304,6 +304,42 @@ export async function withHerdrBlocked<T>(
|
|
|
304
304
|
}
|
|
305
305
|
}
|
|
306
306
|
|
|
307
|
+
/**
|
|
308
|
+
* Claim herdr `working` state for a long-lived "the agent will auto-resume" wait
|
|
309
|
+
* (bg task wake, fusion sidekick handoff) — the states where pi has already
|
|
310
|
+
* settled but background work holds a pending wake.
|
|
311
|
+
*
|
|
312
|
+
* Key-scoped and level-based, not a wrapper: each key claims exactly once and
|
|
313
|
+
* emits `herdr:working` {active:true,label} on claim, {active:false,label} on
|
|
314
|
+
* clear — the same refcounted protocol `herdr:blocked` uses, so the herdr pi
|
|
315
|
+
* integration can keep the pane `working` after agent_settled.
|
|
316
|
+
*
|
|
317
|
+
* - label !== null && no previous claim → emit active
|
|
318
|
+
* - label !== null && same label → no emit (still claimed)
|
|
319
|
+
* - label !== null && different label → emit inactive(previous) then active
|
|
320
|
+
* - label === null && claimed → emit inactive, drop claim
|
|
321
|
+
* - label === null && not claimed → no emit
|
|
322
|
+
*/
|
|
323
|
+
const herdrWorkingClaims = new Map<string, string>();
|
|
324
|
+
|
|
325
|
+
export function setHerdrWorking(
|
|
326
|
+
pi: { events: { emit: (name: string, payload: unknown) => void } },
|
|
327
|
+
key: string,
|
|
328
|
+
label: string | null,
|
|
329
|
+
): void {
|
|
330
|
+
const previous = herdrWorkingClaims.get(key);
|
|
331
|
+
if (label === null) {
|
|
332
|
+
if (previous === undefined) return;
|
|
333
|
+
herdrWorkingClaims.delete(key);
|
|
334
|
+
emitEvent(pi, "herdr:working", { active: false, label: previous });
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
if (previous === label) return;
|
|
338
|
+
if (previous !== undefined) emitEvent(pi, "herdr:working", { active: false, label: previous });
|
|
339
|
+
herdrWorkingClaims.set(key, label);
|
|
340
|
+
emitEvent(pi, "herdr:working", { active: true, label });
|
|
341
|
+
}
|
|
342
|
+
|
|
307
343
|
/** Format a token count for display (e.g. 1234 → "1.2k", 1500000 → "1.5M"). */
|
|
308
344
|
export function formatTokens(n: number): string {
|
|
309
345
|
if (n < 1000) return String(n);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/footer",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.3",
|
|
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": "2.20.
|
|
36
|
-
"@pi-unipi/background-tasks": "2.20.
|
|
35
|
+
"@pi-unipi/core": "2.20.3",
|
|
36
|
+
"@pi-unipi/background-tasks": "2.20.3"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@earendil-works/pi-coding-agent": "^0.84.0",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/fusion",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.3",
|
|
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,8 +32,8 @@
|
|
|
32
32
|
"access": "public"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@pi-unipi/core": "2.20.
|
|
36
|
-
"@pi-unipi/subagents": "2.20.
|
|
35
|
+
"@pi-unipi/core": "2.20.3",
|
|
36
|
+
"@pi-unipi/subagents": "2.20.3"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@earendil-works/pi-ai": "^0.84.0",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
17
17
|
import type { Api, Model } from "@earendil-works/pi-ai";
|
|
18
18
|
import type { AutocompleteProvider, AutocompleteSuggestions } from "@earendil-works/pi-tui";
|
|
19
|
-
import { createSpinnerLine, setSharedFusionStatus, UNIPI_PREFIX } from "@pi-unipi/core";
|
|
19
|
+
import { createSpinnerLine, setHerdrWorking, setSharedFusionStatus, UNIPI_PREFIX } from "@pi-unipi/core";
|
|
20
20
|
import { homedir } from "node:os";
|
|
21
21
|
import { join } from "node:path";
|
|
22
22
|
import {
|
|
@@ -85,6 +85,8 @@ export interface SidekickWakeLine {
|
|
|
85
85
|
export function createSidekickWakeLine(deps: {
|
|
86
86
|
isBusy: () => boolean;
|
|
87
87
|
progress: () => { toolCalls: number; startedAt: number } | undefined;
|
|
88
|
+
/** Claim hook: called with a label when the line goes up, null when it comes down. */
|
|
89
|
+
onHeld?: (label: string | null) => void;
|
|
88
90
|
}): SidekickWakeLine {
|
|
89
91
|
let installed = false;
|
|
90
92
|
|
|
@@ -102,14 +104,17 @@ export function createSidekickWakeLine(deps: {
|
|
|
102
104
|
{ placement: "aboveEditor" },
|
|
103
105
|
);
|
|
104
106
|
installed = true;
|
|
107
|
+
deps.onHeld?.("sidekick working — resumes automatically");
|
|
105
108
|
} else if (!want && installed) {
|
|
106
109
|
ctx.ui.setWidget(SIDEKICK_WAKE_WIDGET_KEY, undefined);
|
|
107
110
|
installed = false;
|
|
111
|
+
deps.onHeld?.(null);
|
|
108
112
|
}
|
|
109
113
|
},
|
|
110
114
|
clear(ctx) {
|
|
111
115
|
if (!installed) return;
|
|
112
116
|
installed = false;
|
|
117
|
+
deps.onHeld?.(null);
|
|
113
118
|
if (!removable(ctx)) return;
|
|
114
119
|
ctx.ui.setWidget(SIDEKICK_WAKE_WIDGET_KEY, undefined);
|
|
115
120
|
},
|
|
@@ -190,6 +195,10 @@ export default function fusionExtension(pi: ExtensionAPI): void {
|
|
|
190
195
|
const wakeLine = createSidekickWakeLine({
|
|
191
196
|
isBusy: () => runtime?.isBusy() === true,
|
|
192
197
|
progress: () => runtime?.progress(),
|
|
198
|
+
// While the wake line is up the pane must read `working` in herdr (the
|
|
199
|
+
// sidekick will re-invoke the lead), not `idle` — same claim the bg-tasks
|
|
200
|
+
// wake line makes.
|
|
201
|
+
onHeld: (label) => setHerdrWorking(pi, "fusion-sidekick", label),
|
|
193
202
|
});
|
|
194
203
|
|
|
195
204
|
function identity(ctx: ExtensionContext): FusionIdentity {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/image",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.3",
|
|
4
4
|
"description": "Image generation and image recognition tools for the Pi coding agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"access": "public"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@pi-unipi/core": "2.20.
|
|
37
|
+
"@pi-unipi/core": "2.20.3"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
40
|
"@earendil-works/pi-ai": "^0.84.0",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/info-screen",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.3",
|
|
4
4
|
"description": "Dashboard and module registry for Unipi — configurable info overlay with tabbed groups",
|
|
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": "2.20.
|
|
36
|
+
"@pi-unipi/core": "2.20.3"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@earendil-works/pi-coding-agent": "^0.84.0",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/input-shortcuts",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.3",
|
|
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": "2.20.
|
|
36
|
+
"@pi-unipi/core": "2.20.3"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@earendil-works/pi-coding-agent": "^0.84.0",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/kanboard",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.3",
|
|
4
4
|
"description": "Visualization layer for unipi workflow — HTTP server with htmx/Alpine.js UI, modular parsers, TUI overlay, and kanban board",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"access": "public"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@pi-unipi/core": "2.20.
|
|
42
|
+
"@pi-unipi/core": "2.20.3"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
45
|
"@earendil-works/pi-coding-agent": "^0.84.0",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/mcp",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.3",
|
|
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": "2.20.
|
|
33
|
+
"@pi-unipi/core": "2.20.3"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"@earendil-works/pi-coding-agent": "^0.84.0",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/memory",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.3",
|
|
4
4
|
"description": "Persistent cross-session memory with MemPalace backend (auto-installed) and SQLite fallback for Pi coding agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
"README.md"
|
|
40
40
|
],
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@pi-unipi/core": "2.20.
|
|
43
|
-
"@pi-unipi/info-screen": "2.20.
|
|
42
|
+
"@pi-unipi/core": "2.20.3",
|
|
43
|
+
"@pi-unipi/info-screen": "2.20.3",
|
|
44
44
|
"js-yaml": "^4.1.0"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/milestone",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.3",
|
|
4
4
|
"description": "Lifecycle layer for project-level goals — MILESTONES.md tracking, session hooks, auto-sync",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"access": "public"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@pi-unipi/core": "2.20.
|
|
35
|
+
"@pi-unipi/core": "2.20.3"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"@earendil-works/pi-coding-agent": "^0.84.0",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/notify",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.3",
|
|
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": "2.20.
|
|
37
|
+
"@pi-unipi/core": "2.20.3",
|
|
38
38
|
"node-notifier": "^10.0.1"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/ralph",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.3",
|
|
4
4
|
"description": "Long-running iterative development loops for Pi coding agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
"test": "npx tsx --test reminder.test.ts"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@pi-unipi/core": "2.20.
|
|
35
|
-
"@pi-unipi/info-screen": "2.20.
|
|
34
|
+
"@pi-unipi/core": "2.20.3",
|
|
35
|
+
"@pi-unipi/info-screen": "2.20.3"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"@earendil-works/pi-ai": "^0.84.0",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/subagents",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.3",
|
|
4
4
|
"description": "Subagents for UniPi — parallel execution, file locking, workflow integration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"test": "npx tsx --test src/__tests__/*.test.ts"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@pi-unipi/core": "2.20.
|
|
12
|
+
"@pi-unipi/core": "2.20.3",
|
|
13
13
|
"@earendil-works/pi-agent-core": "^0.84.0",
|
|
14
14
|
"acorn": "8.18.0"
|
|
15
15
|
},
|
|
@@ -624,6 +624,19 @@ async function withHerdrBlocked(pi, label, fn) {
|
|
|
624
624
|
event(false);
|
|
625
625
|
}
|
|
626
626
|
}
|
|
627
|
+
function setHerdrWorking(pi, key, label) {
|
|
628
|
+
const previous = herdrWorkingClaims.get(key);
|
|
629
|
+
if (label === null) {
|
|
630
|
+
if (previous === void 0) return;
|
|
631
|
+
herdrWorkingClaims.delete(key);
|
|
632
|
+
emitEvent(pi, "herdr:working", { active: false, label: previous });
|
|
633
|
+
return;
|
|
634
|
+
}
|
|
635
|
+
if (previous === label) return;
|
|
636
|
+
if (previous !== void 0) emitEvent(pi, "herdr:working", { active: false, label: previous });
|
|
637
|
+
herdrWorkingClaims.set(key, label);
|
|
638
|
+
emitEvent(pi, "herdr:working", { active: true, label });
|
|
639
|
+
}
|
|
627
640
|
function formatTokens(n) {
|
|
628
641
|
if (n < 1e3) return String(n);
|
|
629
642
|
if (n < 1e4) return `${(n / 1e3).toFixed(1)}k`;
|
|
@@ -652,11 +665,12 @@ function compareVersions(a, b) {
|
|
|
652
665
|
function isNewerVersion(latest, current) {
|
|
653
666
|
return compareVersions(latest, current) > 0;
|
|
654
667
|
}
|
|
655
|
-
var cachedPiVersion;
|
|
668
|
+
var cachedPiVersion, herdrWorkingClaims;
|
|
656
669
|
var init_utils = __esm({
|
|
657
670
|
"packages/core/utils.ts"() {
|
|
658
671
|
"use strict";
|
|
659
672
|
cachedPiVersion = null;
|
|
673
|
+
herdrWorkingClaims = /* @__PURE__ */ new Map();
|
|
660
674
|
}
|
|
661
675
|
});
|
|
662
676
|
|
|
@@ -1102,6 +1116,7 @@ __export(core_exports, {
|
|
|
1102
1116
|
safeRepeat: () => safeRepeat,
|
|
1103
1117
|
safeRepeatCount: () => safeRepeatCount,
|
|
1104
1118
|
sanitize: () => sanitize,
|
|
1119
|
+
setHerdrWorking: () => setHerdrWorking,
|
|
1105
1120
|
setSharedFusionStatus: () => setSharedFusionStatus,
|
|
1106
1121
|
shouldRenderBorder: () => shouldRenderBorder,
|
|
1107
1122
|
tryDelete: () => tryDelete,
|
|
@@ -22189,12 +22204,12 @@ var BgRunParams = Type4.Object({
|
|
|
22189
22204
|
),
|
|
22190
22205
|
notifyOnCompletion: Type4.Optional(
|
|
22191
22206
|
Type4.Boolean({
|
|
22192
|
-
description: "Deliver a durable terminal notification when the task finishes. Default true.
|
|
22207
|
+
description: "Deliver a durable terminal notification when the task finishes. Default true for finite tasks. Set false or pair with triggerOnCompletion:false for persistent servers/daemons/watchers."
|
|
22193
22208
|
})
|
|
22194
22209
|
),
|
|
22195
22210
|
triggerOnCompletion: Type4.Optional(
|
|
22196
22211
|
Type4.Boolean({
|
|
22197
|
-
description: "Start a follow-up agent turn on terminal notification. Default true for
|
|
22212
|
+
description: "Start a follow-up agent turn on terminal notification. Default true for finite tasks (tests, builds, exports). MUST set false for persistent background services/servers (e.g. dev servers, watchers) so the harness and subagents do not wait indefinitely for the server to finish. Requires notifyOnCompletion."
|
|
22198
22213
|
})
|
|
22199
22214
|
)
|
|
22200
22215
|
});
|
|
@@ -22284,14 +22299,14 @@ Command: ${task.command}`,
|
|
|
22284
22299
|
description: `Start a named long-running shell command in the background and return immediately with a task ID and output path. By default, terminal state is delivered automatically as <background-task-notification> and starts a follow-up agent turn; do not sleep or poll merely to wait. Output is written under the OS temp root and model-visible logs are bounded.`,
|
|
22285
22300
|
promptSnippet: "Start a named long-running shell command; default terminal notification wakes a follow-up turn, so yield instead of polling",
|
|
22286
22301
|
promptGuidelines: [
|
|
22287
|
-
"Use bg_run instead of bash for commands expected to run
|
|
22302
|
+
"Use bg_run instead of bash for commands expected to run in the background (test suites, builds, dev servers, watchers).",
|
|
22303
|
+
"For FINITE tasks (tests, builds, exports, scripts): leave triggerOnCompletion:true and notifyOnCompletion:true (defaults) to automatically wake the agent when finished.",
|
|
22304
|
+
"For PERSISTENT servers/daemons/watchers (e.g. 'npm run dev', vite, live dev servers, background listeners): MUST set triggerOnCompletion:false (and optionally notifyOnCompletion:false) so the agent and sidekick do not wait for the server to exit.",
|
|
22288
22305
|
"Set isAgent:true only when the background task launches an LLM/agent process; false for scripts, tests, dev servers, sleeps.",
|
|
22289
22306
|
"Always set name to a concise 2-6 word human-readable label; do not use the raw command as the name.",
|
|
22290
|
-
"bg_run returns immediately.
|
|
22291
|
-
"After a default bg_run launch, continue only independent useful work that does not merely wait for the task; otherwise briefly acknowledge it if useful, then end the current turn. Do not call sleep, bg_status, or bg_logs merely to wait; the terminal notification will wake you.",
|
|
22307
|
+
"bg_run returns immediately. For finite tasks with default wake-up, continue only independent useful work that does not merely wait for the task; otherwise end the current turn. Do not call sleep, bg_status, or bg_logs merely to wait; the terminal notification will wake you.",
|
|
22292
22308
|
"A running result is not an instruction to poll again.",
|
|
22293
|
-
"Treat <background-task-notification> as durable terminal truth. Do not call bg_status to reconfirm it."
|
|
22294
|
-
"Do not set notifyOnCompletion:false or triggerOnCompletion:false unless intentionally opting out."
|
|
22309
|
+
"Treat <background-task-notification> as durable terminal truth. Do not call bg_status to reconfirm it."
|
|
22295
22310
|
],
|
|
22296
22311
|
parameters: BgRunParams,
|
|
22297
22312
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
@@ -25680,9 +25695,16 @@ function backgroundTasksExtension(pi) {
|
|
|
25680
25695
|
{ placement: "aboveEditor" }
|
|
25681
25696
|
);
|
|
25682
25697
|
wakeLineInstalled = true;
|
|
25698
|
+
const wakeCount = registry3.allTasks().filter((task) => task.status === "running" && task.triggerOnCompletion).length;
|
|
25699
|
+
setHerdrWorking(
|
|
25700
|
+
pi,
|
|
25701
|
+
"bg-wake",
|
|
25702
|
+
`${wakeCount === 1 ? "1 bg task" : `${String(wakeCount)} bg tasks`} will resume agent`
|
|
25703
|
+
);
|
|
25683
25704
|
} else if (!wantWakeLine && wakeLineInstalled) {
|
|
25684
25705
|
target.ui.setWidget("background-tasks", void 0);
|
|
25685
25706
|
wakeLineInstalled = false;
|
|
25707
|
+
setHerdrWorking(pi, "bg-wake", null);
|
|
25686
25708
|
}
|
|
25687
25709
|
if (running.length === 0 && unseenFinishedCount === 0) {
|
|
25688
25710
|
target.ui.setStatus("background-tasks", void 0);
|
|
@@ -52125,14 +52147,17 @@ function createSidekickWakeLine(deps) {
|
|
|
52125
52147
|
{ placement: "aboveEditor" }
|
|
52126
52148
|
);
|
|
52127
52149
|
installed = true;
|
|
52150
|
+
deps.onHeld?.("sidekick working \u2014 resumes automatically");
|
|
52128
52151
|
} else if (!want && installed) {
|
|
52129
52152
|
ctx.ui.setWidget(SIDEKICK_WAKE_WIDGET_KEY, void 0);
|
|
52130
52153
|
installed = false;
|
|
52154
|
+
deps.onHeld?.(null);
|
|
52131
52155
|
}
|
|
52132
52156
|
},
|
|
52133
52157
|
clear(ctx) {
|
|
52134
52158
|
if (!installed) return;
|
|
52135
52159
|
installed = false;
|
|
52160
|
+
deps.onHeld?.(null);
|
|
52136
52161
|
if (!removable(ctx)) return;
|
|
52137
52162
|
ctx.ui.setWidget(SIDEKICK_WAKE_WIDGET_KEY, void 0);
|
|
52138
52163
|
}
|
|
@@ -52198,7 +52223,11 @@ function fusionExtension(pi) {
|
|
|
52198
52223
|
let bashStreak = 0;
|
|
52199
52224
|
const wakeLine = createSidekickWakeLine({
|
|
52200
52225
|
isBusy: () => runtime?.isBusy() === true,
|
|
52201
|
-
progress: () => runtime?.progress()
|
|
52226
|
+
progress: () => runtime?.progress(),
|
|
52227
|
+
// While the wake line is up the pane must read `working` in herdr (the
|
|
52228
|
+
// sidekick will re-invoke the lead), not `idle` — same claim the bg-tasks
|
|
52229
|
+
// wake line makes.
|
|
52230
|
+
onHeld: (label) => setHerdrWorking(pi, "fusion-sidekick", label)
|
|
52202
52231
|
});
|
|
52203
52232
|
function identity(ctx) {
|
|
52204
52233
|
const reg = registryOf(ctx);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/updater",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.3",
|
|
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": "2.20.
|
|
37
|
+
"@pi-unipi/core": "2.20.3"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
40
|
"@earendil-works/pi-coding-agent": "^0.84.0",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/utility",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.3",
|
|
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": "2.20.
|
|
39
|
+
"@pi-unipi/core": "2.20.3"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {},
|
|
42
42
|
"peerDependencies": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/web-api",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.3",
|
|
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": "2.20.
|
|
34
|
+
"@pi-unipi/core": "2.20.3",
|
|
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": "2.20.
|
|
3
|
+
"version": "2.20.3",
|
|
4
4
|
"description": "Structured development workflow commands for Pi coding agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"access": "public"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@pi-unipi/core": "2.20.
|
|
33
|
+
"@pi-unipi/core": "2.20.3"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"@earendil-works/pi-ai": "^0.84.0",
|