pi-forge 1.2.5 → 1.3.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.
Files changed (64) hide show
  1. package/README.md +1 -1
  2. package/dist/client/assets/{CodeMirrorEditor-DXmxwE2Z.js → CodeMirrorEditor-BuLFJjB1.js} +13 -13
  3. package/dist/client/assets/CodeMirrorEditor-BuLFJjB1.js.map +1 -0
  4. package/dist/client/assets/index-CEqSkIuy.css +1 -0
  5. package/dist/client/assets/index-GubcPYw6.js +375 -0
  6. package/dist/client/assets/index-GubcPYw6.js.map +1 -0
  7. package/dist/client/assets/{workbox-window.prod.es5-Cch4wiA5.js → workbox-window.prod.es5-Bd17z0YL.js} +2 -2
  8. package/dist/client/assets/{workbox-window.prod.es5-Cch4wiA5.js.map → workbox-window.prod.es5-Bd17z0YL.js.map} +1 -1
  9. package/dist/client/index.html +2 -2
  10. package/dist/client/sw.js +1 -1
  11. package/dist/client/sw.js.map +1 -1
  12. package/dist/server/git-clone.js +364 -0
  13. package/dist/server/git-clone.js.map +1 -0
  14. package/dist/server/index.js +22 -0
  15. package/dist/server/index.js.map +1 -1
  16. package/dist/server/orchestration/config.js +61 -0
  17. package/dist/server/orchestration/config.js.map +1 -0
  18. package/dist/server/orchestration/event-bridge.js +93 -0
  19. package/dist/server/orchestration/event-bridge.js.map +1 -0
  20. package/dist/server/orchestration/inbox.js +199 -0
  21. package/dist/server/orchestration/inbox.js.map +1 -0
  22. package/dist/server/orchestration/init.js +39 -0
  23. package/dist/server/orchestration/init.js.map +1 -0
  24. package/dist/server/orchestration/store.js +352 -0
  25. package/dist/server/orchestration/store.js.map +1 -0
  26. package/dist/server/orchestration/tools.js +769 -0
  27. package/dist/server/orchestration/tools.js.map +1 -0
  28. package/dist/server/orchestration/types.js +57 -0
  29. package/dist/server/orchestration/types.js.map +1 -0
  30. package/dist/server/processes/manager.js +23 -1
  31. package/dist/server/processes/manager.js.map +1 -1
  32. package/dist/server/project-manager.js +46 -32
  33. package/dist/server/project-manager.js.map +1 -1
  34. package/dist/server/routes/control.js +9 -0
  35. package/dist/server/routes/control.js.map +1 -1
  36. package/dist/server/routes/health.js +14 -1
  37. package/dist/server/routes/health.js.map +1 -1
  38. package/dist/server/routes/orchestration.js +464 -0
  39. package/dist/server/routes/orchestration.js.map +1 -0
  40. package/dist/server/routes/projects.js +239 -14
  41. package/dist/server/routes/projects.js.map +1 -1
  42. package/dist/server/routes/sessions.js +53 -34
  43. package/dist/server/routes/sessions.js.map +1 -1
  44. package/dist/server/routes/webhooks.js +362 -0
  45. package/dist/server/routes/webhooks.js.map +1 -0
  46. package/dist/server/session-registry.js +226 -3
  47. package/dist/server/session-registry.js.map +1 -1
  48. package/dist/server/sse-bridge.js +85 -14
  49. package/dist/server/sse-bridge.js.map +1 -1
  50. package/dist/server/webhooks/dispatcher.js +254 -0
  51. package/dist/server/webhooks/dispatcher.js.map +1 -0
  52. package/dist/server/webhooks/event-bridge.js +185 -0
  53. package/dist/server/webhooks/event-bridge.js.map +1 -0
  54. package/dist/server/webhooks/init.js +55 -0
  55. package/dist/server/webhooks/init.js.map +1 -0
  56. package/dist/server/webhooks/store.js +394 -0
  57. package/dist/server/webhooks/store.js.map +1 -0
  58. package/dist/server/webhooks/types.js +32 -0
  59. package/dist/server/webhooks/types.js.map +1 -0
  60. package/package.json +4 -4
  61. package/dist/client/assets/CodeMirrorEditor-DXmxwE2Z.js.map +0 -1
  62. package/dist/client/assets/index-CMSjnWtF.js +0 -365
  63. package/dist/client/assets/index-CMSjnWtF.js.map +0 -1
  64. package/dist/client/assets/index-Cp8qEy7Q.css +0 -1
@@ -0,0 +1,394 @@
1
+ /**
2
+ * Disk-backed store for webhook configs + delivery history.
3
+ *
4
+ * Two files in `${FORGE_DATA_DIR}/`:
5
+ * - `webhooks.json` — config (one entry per webhook)
6
+ * - `webhook-deliveries.json` — rolling history (FIFO capped per webhook)
7
+ *
8
+ * Separated so config writes (rare, single-tenant operator) don't
9
+ * fight delivery writes (frequent, fired by the agent loop). Same
10
+ * atomic-write + per-file lock pattern as `project-manager.ts`.
11
+ *
12
+ * Single-process / single-tenant: locks are in-process promises,
13
+ * not file locks. Cross-process safety would need a real flock.
14
+ */
15
+ import { randomUUID } from "node:crypto";
16
+ import { chmod, mkdir, readFile, rename, unlink, writeFile } from "node:fs/promises";
17
+ import { join } from "node:path";
18
+ import { config } from "../config.js";
19
+ import { isWebhookEvent, MAX_DELIVERIES_PER_WEBHOOK, } from "./types.js";
20
+ const WEBHOOKS_FILE = () => join(config.forgeDataDir, "webhooks.json");
21
+ const DELIVERIES_FILE = () => join(config.forgeDataDir, "webhook-deliveries.json");
22
+ async function ensureDir() {
23
+ await mkdir(config.forgeDataDir, { recursive: true });
24
+ }
25
+ /**
26
+ * Atomic JSON write: tmp file → fsync → rename. The temp filename
27
+ * embeds a uuid so concurrent calls (which shouldn't happen under
28
+ * the lock, but defense in depth) don't collide. The `chmod 0600`
29
+ * after creation matters for `webhooks.json` specifically because
30
+ * it can contain HMAC secrets — same posture as `jwt-secret` /
31
+ * `password-hash`.
32
+ */
33
+ async function atomicWriteJson(target, data, mode) {
34
+ await ensureDir();
35
+ const tmp = `${target}.${randomUUID()}.tmp`;
36
+ await writeFile(tmp, JSON.stringify(data, null, 2), "utf8");
37
+ try {
38
+ await chmod(tmp, mode);
39
+ await rename(tmp, target);
40
+ }
41
+ catch (err) {
42
+ await unlink(tmp).catch(() => undefined);
43
+ throw err;
44
+ }
45
+ }
46
+ // ---- webhooks.json (config) ----
47
+ let configLock = Promise.resolve();
48
+ function withConfigLock(fn) {
49
+ const next = configLock.then(fn, fn);
50
+ configLock = next.catch(() => undefined);
51
+ return next;
52
+ }
53
+ function isScope(v) {
54
+ if (typeof v !== "object" || v === null)
55
+ return false;
56
+ const r = v;
57
+ if (r.kind === "global")
58
+ return true;
59
+ if (r.kind === "project" && typeof r.projectId === "string")
60
+ return true;
61
+ return false;
62
+ }
63
+ function isWebhookConfig(v) {
64
+ if (typeof v !== "object" || v === null)
65
+ return false;
66
+ const r = v;
67
+ return (typeof r.id === "string" &&
68
+ typeof r.name === "string" &&
69
+ typeof r.url === "string" &&
70
+ Array.isArray(r.events) &&
71
+ r.events.every((e) => isWebhookEvent(e)) &&
72
+ isScope(r.scope) &&
73
+ typeof r.enabled === "boolean" &&
74
+ typeof r.createdAt === "string");
75
+ }
76
+ export async function readWebhooks() {
77
+ await ensureDir();
78
+ try {
79
+ const raw = await readFile(WEBHOOKS_FILE(), "utf8");
80
+ const parsed = JSON.parse(raw);
81
+ if (!Array.isArray(parsed))
82
+ return [];
83
+ return parsed.filter(isWebhookConfig);
84
+ }
85
+ catch (err) {
86
+ if (err.code === "ENOENT")
87
+ return [];
88
+ throw err;
89
+ }
90
+ }
91
+ async function writeWebhooks(webhooks) {
92
+ // mode 0o600 — webhooks.json holds HMAC secrets. Same posture as
93
+ // ~/.pi-forge/jwt-secret and ~/.pi-forge/password-hash.
94
+ await atomicWriteJson(WEBHOOKS_FILE(), webhooks, 0o600);
95
+ }
96
+ export class WebhookNotFoundError extends Error {
97
+ code = "webhook_not_found";
98
+ constructor(id) {
99
+ super(`Webhook not found: ${id}`);
100
+ this.name = "WebhookNotFoundError";
101
+ }
102
+ }
103
+ export class InvalidWebhookError extends Error {
104
+ code;
105
+ constructor(code, message) {
106
+ super(message);
107
+ this.code = code;
108
+ this.name = "InvalidWebhookError";
109
+ }
110
+ }
111
+ /**
112
+ * Same `***REDACTED***` sentinel `config-manager.ts` uses for inline
113
+ * `apiKey` in models.json. The webhook headers map can hold things
114
+ * like `Authorization: Bearer …` — we round-trip header VALUES
115
+ * through this sentinel so the wire never carries the real value
116
+ * and editing in the UI doesn't overwrite the stored secret with
117
+ * the sentinel string. Header NAMES stay visible (knowing a webhook
118
+ * has an `Authorization` header isn't sensitive; the value is).
119
+ */
120
+ export const SECRET_PLACEHOLDER = "***REDACTED***";
121
+ /**
122
+ * Build the wire-safe headers object: same keys, every value
123
+ * replaced with the sentinel. The persisted file stays unchanged;
124
+ * this redaction is purely on the read path. The companion
125
+ * `mergeHeadersOnWrite` below restores the real values when the
126
+ * client PATCHes back unchanged headers.
127
+ */
128
+ export function redactHeaders(headers) {
129
+ if (headers === undefined)
130
+ return undefined;
131
+ const out = {};
132
+ for (const name of Object.keys(headers)) {
133
+ out[name] = SECRET_PLACEHOLDER;
134
+ }
135
+ return out;
136
+ }
137
+ /**
138
+ * On PATCH, treat any header VALUE that's literally the sentinel
139
+ * as "keep the existing value." Same semantics as the apiKey
140
+ * round-trip in writeModelsJson. New headers (typed-in values, not
141
+ * sentinel) replace; header NAMES that were dropped from the
142
+ * incoming map are dropped from storage.
143
+ *
144
+ * Returns `undefined` for the empty case so the caller can drop
145
+ * the field entirely from the stored config (rather than persist
146
+ * an empty object).
147
+ */
148
+ export function mergeHeadersOnWrite(incoming, existing) {
149
+ const out = {};
150
+ for (const [name, value] of Object.entries(incoming)) {
151
+ if (value === SECRET_PLACEHOLDER) {
152
+ const prior = existing?.[name];
153
+ if (prior !== undefined)
154
+ out[name] = prior;
155
+ // No prior value → silently drop. The sentinel was sent
156
+ // because the UI showed it, but if there's nothing to keep
157
+ // (e.g. the existing config was just deleted), skip.
158
+ }
159
+ else {
160
+ out[name] = value;
161
+ }
162
+ }
163
+ return Object.keys(out).length === 0 ? undefined : out;
164
+ }
165
+ /**
166
+ * Validate a webhook URL: HTTPS only (same rationale as the clone
167
+ * route — embedding secrets / tokens over cleartext is asking for
168
+ * trouble). HTTP is rejected even on the explicit insecureTls
169
+ * path; `insecureTls` only relaxes cert validation, not the
170
+ * scheme.
171
+ */
172
+ export function validateWebhookUrl(raw) {
173
+ let parsed;
174
+ try {
175
+ parsed = new URL(raw);
176
+ }
177
+ catch {
178
+ throw new InvalidWebhookError("invalid_url", `Not a valid URL: ${raw}`);
179
+ }
180
+ if (parsed.protocol !== "https:") {
181
+ throw new InvalidWebhookError("unsupported_protocol", `Only HTTPS webhook URLs are supported (got ${parsed.protocol}).`);
182
+ }
183
+ if (parsed.hostname.length === 0) {
184
+ throw new InvalidWebhookError("invalid_url", "URL is missing a host.");
185
+ }
186
+ return parsed;
187
+ }
188
+ export async function createWebhook(input) {
189
+ const name = input.name.trim();
190
+ if (name.length === 0) {
191
+ throw new InvalidWebhookError("invalid_name", "Webhook name cannot be empty.");
192
+ }
193
+ validateWebhookUrl(input.url);
194
+ if (input.events.length === 0) {
195
+ throw new InvalidWebhookError("no_events", "Webhook must subscribe to at least one event.");
196
+ }
197
+ if (input.secret === SECRET_PLACEHOLDER) {
198
+ throw new InvalidWebhookError("invalid_secret", "Secret cannot be the redaction sentinel.");
199
+ }
200
+ if (input.headers !== undefined) {
201
+ for (const value of Object.values(input.headers)) {
202
+ if (value === SECRET_PLACEHOLDER) {
203
+ // No prior config exists on create — a sentinel value here
204
+ // would persist as a literal "***REDACTED***" header value
205
+ // and confuse subsequent edits. Reject explicitly.
206
+ throw new InvalidWebhookError("invalid_header", "Header values cannot be the redaction sentinel on create.");
207
+ }
208
+ }
209
+ }
210
+ return withConfigLock(async () => {
211
+ const list = await readWebhooks();
212
+ const webhook = {
213
+ id: randomUUID(),
214
+ name,
215
+ url: input.url,
216
+ events: [...input.events],
217
+ scope: input.scope,
218
+ enabled: input.enabled ?? true,
219
+ createdAt: new Date().toISOString(),
220
+ };
221
+ if (input.secret !== undefined && input.secret.length > 0)
222
+ webhook.secret = input.secret;
223
+ if (input.headers !== undefined && Object.keys(input.headers).length > 0)
224
+ webhook.headers = { ...input.headers };
225
+ if (input.insecureTls === true)
226
+ webhook.insecureTls = true;
227
+ list.push(webhook);
228
+ await writeWebhooks(list);
229
+ return webhook;
230
+ });
231
+ }
232
+ export async function updateWebhook(id, patch) {
233
+ if (patch.url !== undefined)
234
+ validateWebhookUrl(patch.url);
235
+ if (patch.events !== undefined && patch.events.length === 0) {
236
+ throw new InvalidWebhookError("no_events", "Webhook must subscribe to at least one event.");
237
+ }
238
+ if (patch.name !== undefined && patch.name.trim().length === 0) {
239
+ throw new InvalidWebhookError("invalid_name", "Webhook name cannot be empty.");
240
+ }
241
+ return withConfigLock(async () => {
242
+ const list = await readWebhooks();
243
+ const idx = list.findIndex((w) => w.id === id);
244
+ if (idx === -1)
245
+ throw new WebhookNotFoundError(id);
246
+ const existing = list[idx];
247
+ const updated = {
248
+ ...existing,
249
+ ...(patch.name !== undefined ? { name: patch.name.trim() } : {}),
250
+ ...(patch.url !== undefined ? { url: patch.url } : {}),
251
+ ...(patch.events !== undefined ? { events: [...patch.events] } : {}),
252
+ ...(patch.scope !== undefined ? { scope: patch.scope } : {}),
253
+ ...(patch.enabled !== undefined ? { enabled: patch.enabled } : {}),
254
+ };
255
+ // Optional fields: explicit-undefined-in-patch means "clear it".
256
+ // We can't tell `undefined` from "not provided" in a JSON body,
257
+ // so opt for "absent in body = leave alone, empty-string = clear"
258
+ // for secret/headers; insecureTls is a boolean toggle so any
259
+ // explicit value wins.
260
+ //
261
+ // Secret: empty-string clears; the SECRET_PLACEHOLDER sentinel
262
+ // means "keep the existing secret" (the wire never exposes the
263
+ // real value, so a UI round-trip would otherwise overwrite the
264
+ // stored secret with the literal "***REDACTED***" string).
265
+ if (patch.secret !== undefined) {
266
+ if (patch.secret.length === 0)
267
+ delete updated.secret;
268
+ else if (patch.secret === SECRET_PLACEHOLDER) {
269
+ // Leave `updated.secret` whatever the spread of `existing`
270
+ // carried — i.e., no change.
271
+ }
272
+ else
273
+ updated.secret = patch.secret;
274
+ }
275
+ if (patch.headers !== undefined) {
276
+ // Round-trip protection for header VALUES (Bearer tokens
277
+ // etc.). Per-name: sentinel → keep prior; new value → use;
278
+ // missing-from-incoming → drop. `mergeHeadersOnWrite`
279
+ // returns undefined when the merged map is empty, which
280
+ // collapses to "no headers configured."
281
+ const merged = mergeHeadersOnWrite(patch.headers, existing.headers);
282
+ if (merged === undefined)
283
+ delete updated.headers;
284
+ else
285
+ updated.headers = merged;
286
+ }
287
+ if (patch.insecureTls !== undefined) {
288
+ if (patch.insecureTls)
289
+ updated.insecureTls = true;
290
+ else
291
+ delete updated.insecureTls;
292
+ }
293
+ list[idx] = updated;
294
+ await writeWebhooks(list);
295
+ return updated;
296
+ });
297
+ }
298
+ export async function deleteWebhook(id) {
299
+ await withConfigLock(async () => {
300
+ const list = await readWebhooks();
301
+ const next = list.filter((w) => w.id !== id);
302
+ if (next.length === list.length)
303
+ throw new WebhookNotFoundError(id);
304
+ await writeWebhooks(next);
305
+ });
306
+ // Best-effort: prune this webhook's delivery records too. A
307
+ // failure here just leaves orphan records that nothing reads;
308
+ // the deletion of the config itself is already done.
309
+ await withDeliveriesLock(async () => {
310
+ const records = await readDeliveriesRaw();
311
+ const pruned = records.filter((r) => r.webhookId !== id);
312
+ if (pruned.length !== records.length) {
313
+ await writeDeliveries(pruned);
314
+ }
315
+ }).catch(() => undefined);
316
+ }
317
+ export async function getWebhook(id) {
318
+ const list = await readWebhooks();
319
+ return list.find((w) => w.id === id);
320
+ }
321
+ // ---- webhook-deliveries.json (history) ----
322
+ let deliveriesLock = Promise.resolve();
323
+ function withDeliveriesLock(fn) {
324
+ const next = deliveriesLock.then(fn, fn);
325
+ deliveriesLock = next.catch(() => undefined);
326
+ return next;
327
+ }
328
+ function isDeliveryRecord(v) {
329
+ if (typeof v !== "object" || v === null)
330
+ return false;
331
+ const r = v;
332
+ return (typeof r.id === "string" &&
333
+ typeof r.webhookId === "string" &&
334
+ typeof r.deliveryId === "string" &&
335
+ typeof r.event === "string" &&
336
+ typeof r.attempt === "number" &&
337
+ (r.status === "delivered" || r.status === "failed" || r.status === "error") &&
338
+ typeof r.durationMs === "number" &&
339
+ typeof r.requestedAt === "string");
340
+ }
341
+ async function readDeliveriesRaw() {
342
+ await ensureDir();
343
+ try {
344
+ const raw = await readFile(DELIVERIES_FILE(), "utf8");
345
+ const parsed = JSON.parse(raw);
346
+ if (!Array.isArray(parsed))
347
+ return [];
348
+ return parsed.filter(isDeliveryRecord);
349
+ }
350
+ catch (err) {
351
+ if (err.code === "ENOENT")
352
+ return [];
353
+ throw err;
354
+ }
355
+ }
356
+ async function writeDeliveries(records) {
357
+ // Deliveries don't contain secrets but mode 0600 anyway: the
358
+ // file lives alongside webhooks.json and there's no reason for
359
+ // anything outside the pi-forge process to read it.
360
+ await atomicWriteJson(DELIVERIES_FILE(), records, 0o600);
361
+ }
362
+ /**
363
+ * Append a delivery record and trim the per-webhook history to the
364
+ * latest `MAX_DELIVERIES_PER_WEBHOOK` entries. FIFO eviction so
365
+ * the most recent N stays visible in the UI.
366
+ */
367
+ export async function recordDelivery(record) {
368
+ await withDeliveriesLock(async () => {
369
+ const list = await readDeliveriesRaw();
370
+ list.push(record);
371
+ // Trim per-webhook. Walk newest-to-oldest, keep first N per id.
372
+ // Cheaper than groupBy on small N (cap=100, total ~few-hundred).
373
+ const kept = [];
374
+ const counts = new Map();
375
+ for (let i = list.length - 1; i >= 0; i--) {
376
+ const r = list[i];
377
+ const n = (counts.get(r.webhookId) ?? 0) + 1;
378
+ counts.set(r.webhookId, n);
379
+ if (n <= MAX_DELIVERIES_PER_WEBHOOK)
380
+ kept.push(r);
381
+ }
382
+ kept.reverse();
383
+ await writeDeliveries(kept);
384
+ });
385
+ }
386
+ /**
387
+ * Return delivery records for one webhook, newest first. Bounded
388
+ * by the per-webhook cap so this is cheap to call from the UI.
389
+ */
390
+ export async function readDeliveriesForWebhook(webhookId) {
391
+ const all = await readDeliveriesRaw();
392
+ return all.filter((r) => r.webhookId === webhookId).reverse();
393
+ }
394
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/webhooks/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Wire-shape definitions for the webhook feature. The config file
3
+ * (`${FORGE_DATA_DIR}/webhooks.json`) and the rolling delivery log
4
+ * (`${FORGE_DATA_DIR}/webhook-deliveries.json`) both serialize using
5
+ * these types directly. Adding fields is safe (older
6
+ * configs/deliveries deserialize with the new fields undefined);
7
+ * renaming or removing requires a migration step.
8
+ */
9
+ /**
10
+ * Canonical event list. Iteration order matches the UI's checklist
11
+ * order; the order is part of the user-visible surface (the
12
+ * Settings tab renders checkboxes in this order).
13
+ */
14
+ export const WEBHOOK_EVENTS = [
15
+ "agent_end",
16
+ "ask_user_question",
17
+ "process_alert",
18
+ "auto_retry_end",
19
+ "compaction_end",
20
+ "session_created",
21
+ "session_deleted",
22
+ ];
23
+ export function isWebhookEvent(v) {
24
+ return typeof v === "string" && WEBHOOK_EVENTS.includes(v);
25
+ }
26
+ /**
27
+ * Cap on persisted delivery records per webhook. Older deliveries
28
+ * roll off FIFO. 100 is enough for "did my last few fires work?"
29
+ * debugging without letting the file grow unbounded.
30
+ */
31
+ export const MAX_DELIVERIES_PER_WEBHOOK = 100;
32
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/webhooks/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAgBH;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAA4B;IACrD,WAAW;IACX,mBAAmB;IACnB,eAAe;IACf,gBAAgB;IAChB,gBAAgB;IAChB,iBAAiB;IACjB,iBAAiB;CACT,CAAC;AAEX,MAAM,UAAU,cAAc,CAAC,CAAU;IACvC,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAK,cAAoC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACpF,CAAC;AAmFD;;;;GAIG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,GAAG,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-forge",
3
- "version": "1.2.5",
3
+ "version": "1.3.0",
4
4
  "description": "Browser UI for the pi coding agent — embedded HTTP server with a React workbench (chat, file browser, terminal, git, MCP).",
5
5
  "keywords": [
6
6
  "pi",
@@ -45,9 +45,9 @@
45
45
  "@fastify/swagger": "^9.5.0",
46
46
  "@fastify/swagger-ui": "^5.2.3",
47
47
  "@fastify/websocket": "^11.0.2",
48
- "@earendil-works/pi-agent-core": "0.74.0",
49
- "@earendil-works/pi-ai": "0.74.0",
50
- "@earendil-works/pi-coding-agent": "0.74.0",
48
+ "@earendil-works/pi-agent-core": "0.75.5",
49
+ "@earendil-works/pi-ai": "0.75.5",
50
+ "@earendil-works/pi-coding-agent": "0.75.5",
51
51
  "@modelcontextprotocol/sdk": "^1.29.0",
52
52
  "exceljs": "^4.4.0",
53
53
  "fastify": "^5.3.2",