@pi-unipi/unipi 2.17.2 → 2.18.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 +9 -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/btw/package.json +2 -2
- package/packages/compactor/package.json +3 -3
- package/packages/core/fusion-status.ts +6 -0
- package/packages/core/package.json +1 -1
- package/packages/footer/package.json +3 -3
- package/packages/footer/src/glance-editor.ts +22 -8
- package/packages/fusion/package.json +3 -3
- package/packages/fusion/src/index.ts +43 -6
- package/packages/fusion/src/nudge.ts +7 -0
- package/packages/fusion/src/prompts.ts +19 -3
- package/packages/fusion/src/sidekick-runtime.ts +83 -7
- package/packages/fusion/src/tools.ts +67 -14
- package/packages/fusion/src/transcript.ts +108 -0
- 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 +283 -45
- 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
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type
|
|
1
|
+
import { Markdown, Text, type Component } from "@earendil-works/pi-tui";
|
|
2
|
+
import { getMarkdownTheme, type ExtensionAPI, type ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
3
3
|
import { Type } from "typebox";
|
|
4
|
-
import type { SidekickRuntime, HandoffReport } from "./sidekick-runtime.js";
|
|
4
|
+
import type { SidekickRuntime, HandoffProgress, HandoffReport } from "./sidekick-runtime.js";
|
|
5
|
+
import { frameSidekick, renderSidekickTranscript, type ThemeLike as TranscriptTheme } from "./transcript.js";
|
|
5
6
|
|
|
6
7
|
const SidekickParams = Type.Object({
|
|
7
8
|
message: Type.String({ description: "A concrete implementation or verification brief for the sidekick" }),
|
|
@@ -16,12 +17,17 @@ const ReadSubagentParams = Type.Object({
|
|
|
16
17
|
export interface FusionToolDeps {
|
|
17
18
|
getRuntime: (ctx: ExtensionContext) => SidekickRuntime | undefined;
|
|
18
19
|
onReport?: (ctx: ExtensionContext, report: HandoffReport) => void;
|
|
20
|
+
onHandoffStart?: (ctx: ExtensionContext) => void;
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
function duration(ms: number): string {
|
|
22
24
|
return `${(ms / 1000).toFixed(1)}s`;
|
|
23
25
|
}
|
|
24
26
|
|
|
27
|
+
function firstLine(value: string): string {
|
|
28
|
+
return value.split("\n", 1)[0] ?? "";
|
|
29
|
+
}
|
|
30
|
+
|
|
25
31
|
function progressText(runtime: SidekickRuntime, id: string): string {
|
|
26
32
|
const progress = runtime.progress(id);
|
|
27
33
|
if (!progress) return "No active handoff progress.";
|
|
@@ -33,7 +39,9 @@ function progressText(runtime: SidekickRuntime, id: string): string {
|
|
|
33
39
|
|
|
34
40
|
function progressKey(runtime: SidekickRuntime, id: string): string {
|
|
35
41
|
const progress = runtime.progress(id);
|
|
36
|
-
|
|
42
|
+
if (!progress) return "";
|
|
43
|
+
const last = progress.events.at(-1);
|
|
44
|
+
return `${String(progress.toolCalls)}|${progress.recentTools.join("|")}|${progress.textTail}|${String(progress.events.length)}|${last?.kind === "tool" ? `${String(last.output.length)}|${String(last.done)}` : last?.kind === "text" ? `${String(last.text.length)}|${String(last.open)}` : ""}`;
|
|
37
45
|
}
|
|
38
46
|
|
|
39
47
|
function reportText(report: HandoffReport): string {
|
|
@@ -70,7 +78,7 @@ async function waitForReport(
|
|
|
70
78
|
const key = progressKey(runtime, id);
|
|
71
79
|
if (key !== lastProgressKey) {
|
|
72
80
|
lastProgressKey = key;
|
|
73
|
-
onUpdate?.({ content: [{ type: "text", text: progress }] });
|
|
81
|
+
onUpdate?.({ content: [{ type: "text", text: progress }], details: { progress: runtime.progress(id) } });
|
|
74
82
|
}
|
|
75
83
|
}
|
|
76
84
|
}
|
|
@@ -90,15 +98,52 @@ type ThemeLike = {
|
|
|
90
98
|
bold: (text: string) => string;
|
|
91
99
|
};
|
|
92
100
|
|
|
93
|
-
function
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
101
|
+
function transcriptTheme(theme: ThemeLike): TranscriptTheme {
|
|
102
|
+
return { fg: (color, text) => theme.fg(color, text), bold: (text) => theme.bold(text) };
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function markdownText(markdown: string): Markdown {
|
|
106
|
+
return new Markdown(markdown, 0, 0, getMarkdownTheme());
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function contentText(content: unknown): string {
|
|
110
|
+
if (!Array.isArray(content)) return String(content ?? "");
|
|
111
|
+
return content.map((part) => typeof part === "object" && part !== null && typeof (part as { text?: unknown }).text === "string" ? (part as { text: string }).text : "").filter(Boolean).join("\n");
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function renderToolTranscript(result: { content?: unknown; details?: unknown; isError?: boolean }, options: { expanded?: boolean }, theme: ThemeLike, label: "sidekick" | "read_subagent"): Component {
|
|
115
|
+
const details = result.details as (HandoffReport & { progress?: HandoffProgress }) | { progress?: HandoffProgress } | undefined;
|
|
116
|
+
const progress = details?.progress;
|
|
117
|
+
const report = progress ? undefined : details as HandoffReport | undefined;
|
|
118
|
+
const events = progress?.events ?? report?.events;
|
|
119
|
+
const partial = progress !== undefined;
|
|
120
|
+
const status = partial ? "working" : report?.status === "completed" && !result.isError ? "completed" : "error";
|
|
121
|
+
if (!events) return frameSidekick(theme, status, new Text(contentText(result.content), 0, 0));
|
|
122
|
+
const header = partial
|
|
123
|
+
? `${theme.fg("accent", theme.bold(`◆ ${label} working`))} ${theme.fg("dim", `· ${String(progress.toolCalls)} tool calls · ${duration(Date.now() - progress.startedAt)}`)}`
|
|
124
|
+
: `${theme.fg(report?.status === "completed" ? "success" : "error", "◆")} ${theme.fg("accent", theme.bold(`${label} ${report?.status ?? "done"}`))} ${theme.fg("dim", report ? `· ${report.id} · ${String(report.toolCalls)} tool calls · ${duration(report.durationMs)} · in ${String(report.usage.input)} / out ${String(report.usage.output)} tokens` : "")}`;
|
|
125
|
+
return frameSidekick(theme, status, renderSidekickTranscript(transcriptTheme(theme), {
|
|
126
|
+
events,
|
|
127
|
+
droppedEvents: progress?.droppedEvents,
|
|
128
|
+
header,
|
|
129
|
+
expanded: options.expanded === true,
|
|
130
|
+
isPartial: partial,
|
|
131
|
+
report,
|
|
132
|
+
renderText: markdownText,
|
|
133
|
+
}));
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function renderCompletionCard(theme: ThemeLike, report: HandoffReport | undefined): Component {
|
|
137
|
+
const status = report?.status === "completed" ? "completed" : "error";
|
|
138
|
+
if (!report) return frameSidekick(theme, "error", new Text(`${theme.fg("accent", "◆")} ${theme.fg("accent", theme.bold("sidekick done"))}`, 0, 0));
|
|
139
|
+
return frameSidekick(theme, status, renderSidekickTranscript(transcriptTheme(theme), {
|
|
140
|
+
events: report.events ?? [],
|
|
141
|
+
header: `${theme.fg(report.status === "completed" ? "success" : "error", "◆")} ${theme.fg("accent", theme.bold(`sidekick ${report.status}`))} ${theme.fg("dim", `· ${report.id} · ${String(report.toolCalls)} tool calls · ${duration(report.durationMs)}`)}`,
|
|
142
|
+
expanded: false,
|
|
143
|
+
isPartial: false,
|
|
144
|
+
report,
|
|
145
|
+
renderText: markdownText,
|
|
146
|
+
}));
|
|
102
147
|
}
|
|
103
148
|
|
|
104
149
|
export function registerFusionTools(pi: ExtensionAPI, deps: FusionToolDeps): void {
|
|
@@ -109,10 +154,15 @@ export function registerFusionTools(pi: ExtensionAPI, deps: FusionToolDeps): voi
|
|
|
109
154
|
label: "Sidekick",
|
|
110
155
|
description: "Hand off work to your persistent sidekick subagent (one per session; context and shells persist across handoffs; runs on the same machine). block:true (default) waits and returns the report. block:false returns immediately and the report arrives later as a <subagent_completion_notification>. Calling again while a handoff is running injects the message as an interrupt rather than starting a second sidekick.",
|
|
111
156
|
parameters: SidekickParams,
|
|
157
|
+
renderShell: "self",
|
|
158
|
+
renderCall: (args, theme) => frameSidekick(theme as unknown as ThemeLike, "working", new Text(`${theme.fg("toolTitle", theme.bold("◆ sidekick"))} ${theme.fg("dim", firstLine(String(args.message)).slice(0, 100))}`, 0, 0)),
|
|
159
|
+
renderResult: (result, options, theme) => renderToolTranscript(result, options, theme as unknown as ThemeLike, "sidekick"),
|
|
112
160
|
async execute(_toolCallId, params, signal, onUpdate, ctx) {
|
|
113
161
|
const runtime = deps.getRuntime(ctx);
|
|
114
162
|
if (!runtime) return result("Fusion is not active — pick a Fusion pair with /unipi:model.", undefined, true);
|
|
163
|
+
const wasBusy = runtime.isBusy();
|
|
115
164
|
const handoff = runtime.handoff(params.message);
|
|
165
|
+
if (!wasBusy) deps.onHandoffStart?.(ctx);
|
|
116
166
|
if (params.block === false) {
|
|
117
167
|
void handoff.done.then((report) => {
|
|
118
168
|
deps.onReport?.(ctx, report);
|
|
@@ -136,6 +186,9 @@ export function registerFusionTools(pi: ExtensionAPI, deps: FusionToolDeps): voi
|
|
|
136
186
|
label: "Read Sidekick",
|
|
137
187
|
description: "Read a sidekick handoff report by agent_id (omit for the latest). block:true waits for completion (default timeout 2700s when omitted); block:false returns the current progress snapshot immediately.",
|
|
138
188
|
parameters: ReadSubagentParams,
|
|
189
|
+
renderShell: "self",
|
|
190
|
+
renderCall: (args, theme) => frameSidekick(theme as unknown as ThemeLike, "working", new Text(`${theme.fg("toolTitle", theme.bold("◆ read_subagent"))} ${theme.fg("dim", args.agent_id ?? "latest")}`, 0, 0)),
|
|
191
|
+
renderResult: (result, options, theme) => renderToolTranscript(result, options, theme as unknown as ThemeLike, "read_subagent"),
|
|
139
192
|
async execute(_toolCallId, params, signal, onUpdate, ctx) {
|
|
140
193
|
const runtime = deps.getRuntime(ctx);
|
|
141
194
|
if (!runtime) return result("Fusion is not active — pick a Fusion pair with /unipi:model.", undefined, true);
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { Box, Container, Text, type Component } from "@earendil-works/pi-tui";
|
|
2
|
+
import type { SidekickEvent } from "./sidekick-runtime.js";
|
|
3
|
+
|
|
4
|
+
export interface ThemeLike {
|
|
5
|
+
fg: (color: string, text: string) => string;
|
|
6
|
+
bold: (text: string) => string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export class RailComponent implements Component {
|
|
10
|
+
constructor(private readonly inner: Component, private readonly rail: string) {}
|
|
11
|
+
|
|
12
|
+
render(width: number): string[] {
|
|
13
|
+
return this.inner.render(Math.max(1, width - 2)).map((line) => `${this.rail} ${line}`);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
invalidate(): void {
|
|
17
|
+
this.inner.invalidate?.();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
handleInput(data: string): void {
|
|
21
|
+
this.inner.handleInput?.(data);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function frameSidekick(theme: ThemeLike & { bg: (color: string, text: string) => string }, status: "working" | "completed" | "error", content: Component): Component {
|
|
26
|
+
const railColor = status === "working" ? "accent" : status === "completed" ? "success" : "error";
|
|
27
|
+
const rail = theme.fg(railColor, "▍");
|
|
28
|
+
const boxed = new Box(1, 0, (text) => theme.bg("customMessageBg", text));
|
|
29
|
+
boxed.addChild(new RailComponent(content, rail));
|
|
30
|
+
return boxed;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface TranscriptOptions {
|
|
34
|
+
events: readonly SidekickEvent[];
|
|
35
|
+
droppedEvents?: number;
|
|
36
|
+
header: string;
|
|
37
|
+
expanded: boolean;
|
|
38
|
+
isPartial: boolean;
|
|
39
|
+
report?: { text: string };
|
|
40
|
+
renderText: (markdown: string) => Component;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function firstLine(value: string): string {
|
|
44
|
+
return value.split("\n", 1)[0] ?? "";
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function truncate(value: string, max: number): string {
|
|
48
|
+
return value.length > max ? `${value.slice(0, Math.max(0, max - 1))}…` : value;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function primaryArg(name: string, args: Record<string, unknown> | undefined): string {
|
|
52
|
+
if (!args) return "";
|
|
53
|
+
const value = name === "bash"
|
|
54
|
+
? args.command
|
|
55
|
+
: name === "read" || name === "edit" || name === "write"
|
|
56
|
+
? args.path ?? args.file_path ?? args.filePath
|
|
57
|
+
: name === "sidekick"
|
|
58
|
+
? args.message
|
|
59
|
+
: Object.values(args).find((entry) => typeof entry === "string");
|
|
60
|
+
return typeof value === "string" ? truncate(firstLine(value), 100) : "";
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function toolComponent(theme: ThemeLike, event: Extract<SidekickEvent, { kind: "tool" }>, expanded: boolean): Text {
|
|
64
|
+
const title = `${event.isError ? theme.fg("error", "✗ ") : ""}${theme.fg("toolTitle", theme.bold(event.name))}`;
|
|
65
|
+
const argument = primaryArg(event.name, event.args);
|
|
66
|
+
const lines = [`${title}${argument.length > 0 ? ` ${theme.fg("accent", argument)}` : ""}`];
|
|
67
|
+
if (!event.done) {
|
|
68
|
+
lines[0] += theme.fg("warning", " ⋯ running");
|
|
69
|
+
} else if (event.output.length > 0) {
|
|
70
|
+
const output = event.output.split("\n");
|
|
71
|
+
const visible = expanded ? output.slice(-40) : output.slice(-3);
|
|
72
|
+
lines.push(...visible.map((line) => theme.fg("toolOutput", truncate(line, 160))));
|
|
73
|
+
}
|
|
74
|
+
return new Text(lines.join("\n"), 0, 0);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function renderSidekickTranscript(theme: ThemeLike, opts: TranscriptOptions): Component {
|
|
78
|
+
const box = new Container();
|
|
79
|
+
box.addChild(new Text(opts.header, 0, 0));
|
|
80
|
+
|
|
81
|
+
if (!opts.isPartial && !opts.expanded) {
|
|
82
|
+
if (opts.report?.text) box.addChild(opts.renderText(opts.report.text));
|
|
83
|
+
box.addChild(new Text(theme.fg("dim", `${String(opts.events.length)} steps · expand to see the transcript`), 0, 0));
|
|
84
|
+
return box;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const dropped = opts.droppedEvents ?? 0;
|
|
88
|
+
const start = opts.expanded ? 0 : Math.max(0, opts.events.length - 8);
|
|
89
|
+
if (opts.expanded && dropped > 0) {
|
|
90
|
+
box.addChild(new Text(theme.fg("dim", `… ${String(dropped)} earliest steps dropped`), 0, 0));
|
|
91
|
+
} else if (start > 0) {
|
|
92
|
+
box.addChild(new Text(theme.fg("dim", `… ${String(start + dropped)} earlier steps`), 0, 0));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
for (const event of opts.events.slice(start)) {
|
|
96
|
+
if (event.kind === "tool") box.addChild(toolComponent(theme, event, opts.expanded));
|
|
97
|
+
else if (event.text.trim()) box.addChild(opts.renderText(event.text.trim()));
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (!opts.isPartial && opts.expanded && opts.report?.text) {
|
|
101
|
+
// The final assistant message usually IS the report; don't print it twice.
|
|
102
|
+
const last = opts.events.at(-1);
|
|
103
|
+
if (last?.kind === "text" && last.text.trim() === opts.report.text.trim()) return box;
|
|
104
|
+
box.addChild(new Text(theme.fg("dim", "── report ──"), 0, 0));
|
|
105
|
+
box.addChild(opts.renderText(opts.report.text));
|
|
106
|
+
}
|
|
107
|
+
return box;
|
|
108
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/image",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.18.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.18.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.18.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.18.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.18.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.18.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.18.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.18.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.18.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.18.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.18.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.18.0",
|
|
43
|
+
"@pi-unipi/info-screen": "2.18.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.18.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.18.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.18.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.18.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.18.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.18.0",
|
|
35
|
+
"@pi-unipi/info-screen": "2.18.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.18.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.18.0",
|
|
13
13
|
"@earendil-works/pi-agent-core": "^0.84.0",
|
|
14
14
|
"acorn": "8.18.0"
|
|
15
15
|
},
|