@pi-unipi/unipi 2.19.3 → 2.20.0
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 +15 -0
- package/README.md +9 -1
- package/package.json +24 -24
- package/packages/ask-user/package.json +2 -2
- package/packages/ask-user/tools.ts +30 -0
- 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/footer/package.json +3 -3
- package/packages/fusion/README.md +9 -4
- package/packages/fusion/package.json +3 -3
- package/packages/fusion/src/index.ts +87 -94
- package/packages/fusion/src/tools.ts +77 -10
- package/packages/fusion/src/transcript.ts +13 -11
- 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 +1377 -3330
- 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/packages/fusion/src/sidekick-widget.ts +0 -3
|
@@ -2,7 +2,7 @@ import { Text, type Component } from "@earendil-works/pi-tui";
|
|
|
2
2
|
import { type ExtensionAPI, type ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
3
3
|
import { Type } from "typebox";
|
|
4
4
|
import type { SidekickRuntime, HandoffProgress, HandoffReport } from "./sidekick-runtime.js";
|
|
5
|
-
import { duration, markdownText, renderSidekickTranscript, sidekickWorkingHeader } from "./transcript.js";
|
|
5
|
+
import { duration, frameSidekick, markdownText, renderSidekickTranscript, sidekickWorkingHeader } from "./transcript.js";
|
|
6
6
|
|
|
7
7
|
const SidekickParams = Type.Object({
|
|
8
8
|
message: Type.String({ description: "A concrete implementation or verification brief for the sidekick" }),
|
|
@@ -22,6 +22,46 @@ export interface FusionToolDeps {
|
|
|
22
22
|
onDetach?: (ctx: ExtensionContext) => void;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Exactly-once completion delivery for handoffs nobody is waiting on.
|
|
27
|
+
*
|
|
28
|
+
* `attach`/`detach` bracket every waiting period. The completion is sent only
|
|
29
|
+
* if the report lands (or has already landed) while no waiter is attached, and
|
|
30
|
+
* only once per handoff id.
|
|
31
|
+
*/
|
|
32
|
+
export function createCompletionDelivery(send: (report: HandoffReport) => void): {
|
|
33
|
+
attach(id: string): void;
|
|
34
|
+
detach(id: string, done: Promise<HandoffReport>): void;
|
|
35
|
+
consume(id: string): void;
|
|
36
|
+
} {
|
|
37
|
+
const waiting = new Set<string>();
|
|
38
|
+
const armed = new Set<string>();
|
|
39
|
+
const delivered = new Set<string>();
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
attach(id) {
|
|
43
|
+
waiting.add(id);
|
|
44
|
+
},
|
|
45
|
+
detach(id, done) {
|
|
46
|
+
waiting.delete(id);
|
|
47
|
+
// One continuation per handoff, however many times a waiter gives up.
|
|
48
|
+
if (armed.has(id)) return;
|
|
49
|
+
armed.add(id);
|
|
50
|
+
void done
|
|
51
|
+
.then((report) => {
|
|
52
|
+
if (waiting.has(id) || delivered.has(id)) return;
|
|
53
|
+
delivered.add(id);
|
|
54
|
+
send(report);
|
|
55
|
+
})
|
|
56
|
+
.catch(() => undefined);
|
|
57
|
+
},
|
|
58
|
+
consume(id) {
|
|
59
|
+
waiting.delete(id);
|
|
60
|
+
delivered.add(id);
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
25
65
|
function firstLine(value: string): string {
|
|
26
66
|
return value.split("\n", 1)[0] ?? "";
|
|
27
67
|
}
|
|
@@ -101,6 +141,21 @@ type ThemeLike = {
|
|
|
101
141
|
bold: (text: string) => string;
|
|
102
142
|
};
|
|
103
143
|
|
|
144
|
+
type FramedTheme = ThemeLike & { bg: (color: string, text: string) => string };
|
|
145
|
+
|
|
146
|
+
function transcriptStatus(partial: boolean, report: HandoffReport | undefined): "working" | "completed" | "error" {
|
|
147
|
+
if (partial) return "working";
|
|
148
|
+
return report?.status === "completed" ? "completed" : "error";
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Sidekick output on the main surface: the same markdown/tool format the lead
|
|
153
|
+
* uses, marked as sidekick-origin by the existing `▍` rail.
|
|
154
|
+
*/
|
|
155
|
+
function frameTranscript(theme: ThemeLike, status: "working" | "completed" | "error", content: Component): Component {
|
|
156
|
+
return frameSidekick(theme as FramedTheme, status, content);
|
|
157
|
+
}
|
|
158
|
+
|
|
104
159
|
// Model-facing result text carries handoff ids and protocol instructions the
|
|
105
160
|
// lead needs; none of it may reach the terminal. Anything rendered as plain
|
|
106
161
|
// content goes through this first.
|
|
@@ -147,7 +202,7 @@ function renderToolTranscript(result: { content?: unknown; details?: unknown; is
|
|
|
147
202
|
const partial = progress !== undefined;
|
|
148
203
|
if (!events) return new Text(displayText(contentText(result.content)), 0, 0);
|
|
149
204
|
const header = partial ? sidekickWorkingHeader(theme, progress, label) : reportHeader(theme, label, report);
|
|
150
|
-
return renderSidekickTranscript(theme, {
|
|
205
|
+
return frameTranscript(theme, transcriptStatus(partial, report), renderSidekickTranscript(theme, {
|
|
151
206
|
events,
|
|
152
207
|
droppedEvents: progress?.droppedEvents,
|
|
153
208
|
header,
|
|
@@ -155,24 +210,29 @@ function renderToolTranscript(result: { content?: unknown; details?: unknown; is
|
|
|
155
210
|
isPartial: partial,
|
|
156
211
|
report,
|
|
157
212
|
renderText: markdownText,
|
|
158
|
-
});
|
|
213
|
+
}));
|
|
159
214
|
}
|
|
160
215
|
|
|
161
216
|
function renderCompletionCard(theme: ThemeLike, report: HandoffReport | undefined): Component {
|
|
162
217
|
if (!report) return new Text(`${theme.fg("accent", "◆")} ${theme.fg("accent", theme.bold("sidekick done"))}`, 0, 0);
|
|
163
|
-
return renderSidekickTranscript(theme, {
|
|
218
|
+
return frameTranscript(theme, transcriptStatus(false, report), renderSidekickTranscript(theme, {
|
|
164
219
|
events: report.events ?? [],
|
|
165
220
|
header: reportHeader(theme, "sidekick", report),
|
|
166
221
|
expanded: false,
|
|
167
222
|
isPartial: false,
|
|
168
223
|
report,
|
|
169
224
|
renderText: markdownText,
|
|
170
|
-
});
|
|
225
|
+
}));
|
|
171
226
|
}
|
|
172
227
|
|
|
173
228
|
export function registerFusionTools(pi: ExtensionAPI, deps: FusionToolDeps): void {
|
|
174
229
|
pi.registerMessageRenderer("sidekick-completion", (message: { details?: HandoffReport }, _options, theme) => renderCompletionCard(theme as unknown as ThemeLike, message.details));
|
|
175
230
|
|
|
231
|
+
// One delivery mechanism for every handoff nobody is waiting on.
|
|
232
|
+
const completion = createCompletionDelivery((report) => {
|
|
233
|
+
pi.sendMessage(completionMessage(report) as never, { deliverAs: "followUp", triggerTurn: true } as never);
|
|
234
|
+
});
|
|
235
|
+
|
|
176
236
|
pi.registerTool({
|
|
177
237
|
name: "sidekick",
|
|
178
238
|
label: "Sidekick",
|
|
@@ -187,19 +247,20 @@ export function registerFusionTools(pi: ExtensionAPI, deps: FusionToolDeps): voi
|
|
|
187
247
|
const handoff = runtime.handoff(params.message);
|
|
188
248
|
if (!wasBusy) deps.onHandoffStart?.(ctx);
|
|
189
249
|
if (params.block === false) {
|
|
190
|
-
void handoff.done.then((report) =>
|
|
191
|
-
|
|
192
|
-
pi.sendMessage(completionMessage(report) as never, { deliverAs: "followUp", triggerTurn: true } as never);
|
|
193
|
-
}).catch(() => undefined);
|
|
250
|
+
void handoff.done.then((report) => deps.onReport?.(ctx, report)).catch(() => undefined);
|
|
251
|
+
completion.detach(handoff.id, handoff.done);
|
|
194
252
|
deps.onDetach?.(ctx);
|
|
195
253
|
return result(`Handoff ${handoff.id} started in the background. You will receive a <subagent_completion_notification agent_id="${handoff.id}"> when it finishes; use read_subagent to wait.`, { background: true, id: handoff.id });
|
|
196
254
|
}
|
|
197
255
|
deps.onAttach?.(ctx);
|
|
256
|
+
completion.attach(handoff.id);
|
|
198
257
|
const waited = await waitForReport(runtime, handoff.id, handoff.done, signal, ctx, onUpdate ? (update) => onUpdate(update as never) : undefined);
|
|
199
258
|
if (waited.report) {
|
|
259
|
+
completion.consume(handoff.id);
|
|
200
260
|
deps.onReport?.(ctx, waited.report);
|
|
201
261
|
return result(reportText(waited.report), waited.report, waited.report.status !== "completed");
|
|
202
262
|
}
|
|
263
|
+
completion.detach(handoff.id, handoff.done);
|
|
203
264
|
deps.onDetach?.(ctx);
|
|
204
265
|
if (waited.error) return result(`Handoff ${handoff.id} failed: ${waited.error}`, undefined, true);
|
|
205
266
|
if (waited.aborted) return result(`${progressText(runtime, handoff.id)}\nHandoff ${handoff.id} aborted.`, undefined, true);
|
|
@@ -222,16 +283,22 @@ export function registerFusionTools(pi: ExtensionAPI, deps: FusionToolDeps): voi
|
|
|
222
283
|
if (!latest) return result("No sidekick handoff has run yet.", undefined, true);
|
|
223
284
|
const id = params.agent_id ?? latest.id;
|
|
224
285
|
const selected = runtime.reports.get(id);
|
|
225
|
-
if (selected)
|
|
286
|
+
if (selected) {
|
|
287
|
+
completion.consume(id);
|
|
288
|
+
return result(reportText(selected), selected, selected.status !== "completed");
|
|
289
|
+
}
|
|
226
290
|
if (id !== latest.id) return result(`No sidekick handoff found for ${id}.`, undefined, true);
|
|
227
291
|
if (params.block !== true) return result(`Handoff ${id} is still running.\n${progressText(runtime, id)}`, { progress: runtime.progress(id), id });
|
|
228
292
|
deps.onAttach?.(ctx);
|
|
293
|
+
completion.attach(id);
|
|
229
294
|
const timeoutMs = (params.timeout ?? 2700) * 1000;
|
|
230
295
|
const waited = await waitForReport(runtime, id, latest.done, signal, ctx, onUpdate ? (update) => onUpdate(update as never) : undefined, timeoutMs);
|
|
231
296
|
if (waited.report) {
|
|
297
|
+
completion.consume(id);
|
|
232
298
|
deps.onReport?.(ctx, waited.report);
|
|
233
299
|
return result(reportText(waited.report), waited.report, waited.report.status !== "completed");
|
|
234
300
|
}
|
|
301
|
+
completion.detach(id, latest.done);
|
|
235
302
|
deps.onDetach?.(ctx);
|
|
236
303
|
if (waited.error) return result(`Handoff ${id} failed: ${waited.error}`, undefined, true);
|
|
237
304
|
if (waited.aborted) return result(`Handoff ${id} aborted.`, undefined, true);
|
|
@@ -53,6 +53,13 @@ export interface TranscriptOptions {
|
|
|
53
53
|
renderText: (markdown: string) => Component;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
/**
|
|
57
|
+
* Non-expanded transcripts show this many most recent events. Windowing is the
|
|
58
|
+
* only cap: a completed handoff renders its events, it is never collapsed into
|
|
59
|
+
* a "N steps" stub.
|
|
60
|
+
*/
|
|
61
|
+
export const TRANSCRIPT_WINDOW = 8;
|
|
62
|
+
|
|
56
63
|
function firstLine(value: string): string {
|
|
57
64
|
return value.split("\n", 1)[0] ?? "";
|
|
58
65
|
}
|
|
@@ -91,14 +98,8 @@ export function renderSidekickTranscript(theme: ThemeLike, opts: TranscriptOptio
|
|
|
91
98
|
const box = new Container();
|
|
92
99
|
box.addChild(new Text(opts.header, 0, 0));
|
|
93
100
|
|
|
94
|
-
if (!opts.isPartial && !opts.expanded) {
|
|
95
|
-
if (opts.report?.text) box.addChild(opts.renderText(opts.report.text));
|
|
96
|
-
box.addChild(new Text(theme.fg("dim", `${String(opts.events.length)} steps · expand to see the transcript`), 0, 0));
|
|
97
|
-
return box;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
101
|
const dropped = opts.droppedEvents ?? 0;
|
|
101
|
-
const start = opts.expanded ? 0 : Math.max(0, opts.events.length -
|
|
102
|
+
const start = opts.expanded ? 0 : Math.max(0, opts.events.length - TRANSCRIPT_WINDOW);
|
|
102
103
|
if (opts.expanded && dropped > 0) {
|
|
103
104
|
box.addChild(new Text(theme.fg("dim", `… ${String(dropped)} earliest steps dropped`), 0, 0));
|
|
104
105
|
} else if (start > 0) {
|
|
@@ -110,12 +111,13 @@ export function renderSidekickTranscript(theme: ThemeLike, opts: TranscriptOptio
|
|
|
110
111
|
else if (event.text.trim()) box.addChild(opts.renderText(event.text.trim()));
|
|
111
112
|
}
|
|
112
113
|
|
|
113
|
-
if (!opts.isPartial && opts.
|
|
114
|
+
if (!opts.isPartial && opts.report?.text) {
|
|
114
115
|
// The final assistant message usually IS the report; don't print it twice.
|
|
115
116
|
const last = opts.events.at(-1);
|
|
116
|
-
if (last?.kind === "text" && last.text.trim() === opts.report.text.trim())
|
|
117
|
-
|
|
118
|
-
|
|
117
|
+
if (!(last?.kind === "text" && last.text.trim() === opts.report.text.trim())) {
|
|
118
|
+
box.addChild(new Text(theme.fg("dim", "── report ──"), 0, 0));
|
|
119
|
+
box.addChild(opts.renderText(opts.report.text));
|
|
120
|
+
}
|
|
119
121
|
}
|
|
120
122
|
return box;
|
|
121
123
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/image",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.20.0",
|
|
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.
|
|
37
|
+
"@pi-unipi/core": "2.20.0"
|
|
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.
|
|
3
|
+
"version": "2.20.0",
|
|
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.
|
|
36
|
+
"@pi-unipi/core": "2.20.0"
|
|
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.
|
|
3
|
+
"version": "2.20.0",
|
|
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.
|
|
36
|
+
"@pi-unipi/core": "2.20.0"
|
|
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.
|
|
3
|
+
"version": "2.20.0",
|
|
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.
|
|
42
|
+
"@pi-unipi/core": "2.20.0"
|
|
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.
|
|
3
|
+
"version": "2.20.0",
|
|
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.
|
|
33
|
+
"@pi-unipi/core": "2.20.0"
|
|
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.
|
|
3
|
+
"version": "2.20.0",
|
|
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.
|
|
43
|
-
"@pi-unipi/info-screen": "2.
|
|
42
|
+
"@pi-unipi/core": "2.20.0",
|
|
43
|
+
"@pi-unipi/info-screen": "2.20.0",
|
|
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.
|
|
3
|
+
"version": "2.20.0",
|
|
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.
|
|
35
|
+
"@pi-unipi/core": "2.20.0"
|
|
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.
|
|
3
|
+
"version": "2.20.0",
|
|
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.
|
|
37
|
+
"@pi-unipi/core": "2.20.0",
|
|
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.
|
|
3
|
+
"version": "2.20.0",
|
|
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.
|
|
35
|
-
"@pi-unipi/info-screen": "2.
|
|
34
|
+
"@pi-unipi/core": "2.20.0",
|
|
35
|
+
"@pi-unipi/info-screen": "2.20.0"
|
|
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.
|
|
3
|
+
"version": "2.20.0",
|
|
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.
|
|
12
|
+
"@pi-unipi/core": "2.20.0",
|
|
13
13
|
"@earendil-works/pi-agent-core": "^0.84.0",
|
|
14
14
|
"acorn": "8.18.0"
|
|
15
15
|
},
|