pi-forge 1.2.2 → 1.2.4
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/README.md +1 -1
- package/dist/client/assets/{CodeMirrorEditor-BwTPp-8p.js → CodeMirrorEditor-M7HIAKX2.js} +4 -4
- package/dist/client/assets/{CodeMirrorEditor-BwTPp-8p.js.map → CodeMirrorEditor-M7HIAKX2.js.map} +1 -1
- package/dist/client/assets/index-DFDpaYie.css +1 -0
- package/dist/client/assets/index-DjYKKZRm.js +363 -0
- package/dist/client/assets/index-DjYKKZRm.js.map +1 -0
- package/dist/client/assets/workbox-window.prod.es5-Cch4wiA5.js.map +1 -1
- package/dist/client/index.html +2 -2
- package/dist/client/sw.js +1 -1
- package/dist/client/sw.js.map +1 -1
- package/dist/server/agent-resource-loader.js +11 -2
- package/dist/server/agent-resource-loader.js.map +1 -1
- package/dist/server/ask-user-question/envelope.js +56 -0
- package/dist/server/ask-user-question/envelope.js.map +1 -0
- package/dist/server/ask-user-question/prompt-strings.js +44 -0
- package/dist/server/ask-user-question/prompt-strings.js.map +1 -0
- package/dist/server/ask-user-question/registry.js +157 -0
- package/dist/server/ask-user-question/registry.js.map +1 -0
- package/dist/server/ask-user-question/tool.js +115 -0
- package/dist/server/ask-user-question/tool.js.map +1 -0
- package/dist/server/ask-user-question/types.js +27 -0
- package/dist/server/ask-user-question/types.js.map +1 -0
- package/dist/server/ask-user-question/validate.js +135 -0
- package/dist/server/ask-user-question/validate.js.map +1 -0
- package/dist/server/config.js +31 -0
- package/dist/server/config.js.map +1 -1
- package/dist/server/index.js +13 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/mcp/config.js +71 -30
- package/dist/server/mcp/config.js.map +1 -1
- package/dist/server/mcp/manager.js +199 -14
- package/dist/server/mcp/manager.js.map +1 -1
- package/dist/server/mcp/stdio-trust.js +86 -0
- package/dist/server/mcp/stdio-trust.js.map +1 -0
- package/dist/server/project-manager.js +8 -0
- package/dist/server/project-manager.js.map +1 -1
- package/dist/server/quick-actions.js +141 -0
- package/dist/server/quick-actions.js.map +1 -0
- package/dist/server/routes/ask-user-question.js +129 -0
- package/dist/server/routes/ask-user-question.js.map +1 -0
- package/dist/server/routes/config.js +7 -0
- package/dist/server/routes/config.js.map +1 -1
- package/dist/server/routes/mcp.js +165 -18
- package/dist/server/routes/mcp.js.map +1 -1
- package/dist/server/routes/projects.js +80 -0
- package/dist/server/routes/projects.js.map +1 -1
- package/dist/server/routes/quick-actions.js +384 -0
- package/dist/server/routes/quick-actions.js.map +1 -0
- package/dist/server/routes/todos.js +67 -0
- package/dist/server/routes/todos.js.map +1 -0
- package/dist/server/session-registry.js +52 -4
- package/dist/server/session-registry.js.map +1 -1
- package/dist/server/sse-bridge.js +84 -0
- package/dist/server/sse-bridge.js.map +1 -1
- package/dist/server/system-prompt-overrides.js +103 -0
- package/dist/server/system-prompt-overrides.js.map +1 -0
- package/dist/server/todo/envelope.js +87 -0
- package/dist/server/todo/envelope.js.map +1 -0
- package/dist/server/todo/invariants.js +21 -0
- package/dist/server/todo/invariants.js.map +1 -0
- package/dist/server/todo/prompt-strings.js +29 -0
- package/dist/server/todo/prompt-strings.js.map +1 -0
- package/dist/server/todo/reducer.js +189 -0
- package/dist/server/todo/reducer.js.map +1 -0
- package/dist/server/todo/replay.js +45 -0
- package/dist/server/todo/replay.js.map +1 -0
- package/dist/server/todo/store.js +92 -0
- package/dist/server/todo/store.js.map +1 -0
- package/dist/server/todo/task-graph.js +60 -0
- package/dist/server/todo/task-graph.js.map +1 -0
- package/dist/server/todo/tool.js +95 -0
- package/dist/server/todo/tool.js.map +1 -0
- package/dist/server/todo/types.js +23 -0
- package/dist/server/todo/types.js.map +1 -0
- package/package.json +1 -1
- package/dist/client/assets/index--G_jkVyP.js +0 -356
- package/dist/client/assets/index--G_jkVyP.js.map +0 -1
- package/dist/client/assets/index-B4ryaCak.css +0 -1
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { config } from "../config.js";
|
|
3
|
+
import { getProject } from "../project-manager.js";
|
|
4
|
+
import { scrubbedEnv } from "../pty-manager.js";
|
|
5
|
+
import { createQuickAction, DEFAULT_TIMEOUT_MS, deleteQuickAction, getQuickAction, isCommandAction, isPromptAction, MAX_COMMAND_BYTES, MAX_PROMPT_BYTES, MAX_TIMEOUT_MS, QuickActionNotFoundError, readQuickActions, updateQuickAction, } from "../quick-actions.js";
|
|
6
|
+
import { errorSchema } from "./_schemas.js";
|
|
7
|
+
/**
|
|
8
|
+
* Wire shape — same on the way in (POST/PUT body) and out
|
|
9
|
+
* (GET response). Discriminator is presence of `command` vs `text`;
|
|
10
|
+
* the validator below rejects both/neither with 400.
|
|
11
|
+
*/
|
|
12
|
+
const quickActionSchema = {
|
|
13
|
+
type: "object",
|
|
14
|
+
required: ["id", "name"],
|
|
15
|
+
properties: {
|
|
16
|
+
id: { type: "string" },
|
|
17
|
+
name: { type: "string" },
|
|
18
|
+
enabled: { type: "boolean" },
|
|
19
|
+
command: { type: "string" },
|
|
20
|
+
timeoutMs: { type: "integer" },
|
|
21
|
+
text: { type: "string" },
|
|
22
|
+
mode: { type: "string", enum: ["send", "insert"] },
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
const runResultSchema = {
|
|
26
|
+
type: "object",
|
|
27
|
+
required: ["success", "exitCode", "stdout", "stderr", "durationMs", "timedOut", "truncated"],
|
|
28
|
+
properties: {
|
|
29
|
+
success: { type: "boolean" },
|
|
30
|
+
exitCode: { type: ["integer", "null"] },
|
|
31
|
+
stdout: { type: "string" },
|
|
32
|
+
stderr: { type: "string" },
|
|
33
|
+
durationMs: { type: "integer" },
|
|
34
|
+
timedOut: { type: "boolean" },
|
|
35
|
+
truncated: { type: "boolean" },
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
/** Per-stream output cap. A chip that prints 100 MB of node_modules
|
|
39
|
+
* paths shouldn't drag the request handler down — truncate and flag
|
|
40
|
+
* it; the user can re-run in the integrated terminal if they need the
|
|
41
|
+
* full output. */
|
|
42
|
+
const MAX_OUTPUT_BYTES = 1_000_000;
|
|
43
|
+
/**
|
|
44
|
+
* Normalise + validate one wire body into a QuickAction-shaped patch.
|
|
45
|
+
* Centralises the one-of discriminator + byte caps so POST and PUT
|
|
46
|
+
* both produce identical 400s on the same bad input.
|
|
47
|
+
*/
|
|
48
|
+
function validateBody(body, reply) {
|
|
49
|
+
const trimmedName = body.name.trim();
|
|
50
|
+
if (trimmedName.length === 0) {
|
|
51
|
+
reply.code(400).send({ error: "invalid_name" });
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
const hasCmd = typeof body.command === "string" && body.command.length > 0;
|
|
55
|
+
const hasText = typeof body.text === "string" && body.text.length > 0;
|
|
56
|
+
if (hasCmd === hasText) {
|
|
57
|
+
reply.code(400).send({
|
|
58
|
+
error: "invalid_action",
|
|
59
|
+
message: "exactly one of `command` or `text` is required",
|
|
60
|
+
});
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
const out = { name: trimmedName };
|
|
64
|
+
if (body.enabled !== undefined)
|
|
65
|
+
out.enabled = body.enabled;
|
|
66
|
+
if (hasCmd) {
|
|
67
|
+
const cmd = body.command;
|
|
68
|
+
if (Buffer.byteLength(cmd, "utf8") > MAX_COMMAND_BYTES) {
|
|
69
|
+
reply.code(400).send({ error: "command_too_large" });
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
out.command = cmd;
|
|
73
|
+
if (body.timeoutMs !== undefined) {
|
|
74
|
+
const t = body.timeoutMs;
|
|
75
|
+
if (!Number.isInteger(t) || t <= 0) {
|
|
76
|
+
reply.code(400).send({ error: "invalid_timeout" });
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
79
|
+
out.timeoutMs = Math.min(t, MAX_TIMEOUT_MS);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
const text = body.text;
|
|
84
|
+
if (Buffer.byteLength(text, "utf8") > MAX_PROMPT_BYTES) {
|
|
85
|
+
reply.code(400).send({ error: "prompt_too_large" });
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
out.text = text;
|
|
89
|
+
out.mode = body.mode ?? "send";
|
|
90
|
+
}
|
|
91
|
+
return out;
|
|
92
|
+
}
|
|
93
|
+
function handleError(reply, err) {
|
|
94
|
+
if (err instanceof QuickActionNotFoundError) {
|
|
95
|
+
return reply.code(404).send({ error: "action_not_found" });
|
|
96
|
+
}
|
|
97
|
+
reply.log.error({ err }, "quick-actions route error");
|
|
98
|
+
return reply.code(500).send({ error: "internal_error" });
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Spawn the command under `/bin/sh -c` with a scrubbed env (same
|
|
102
|
+
* posture as the integrated terminal — no pi-forge / provider
|
|
103
|
+
* secrets leak into chip output). stdout and stderr are captured
|
|
104
|
+
* separately so the chat card can render them in distinct blocks.
|
|
105
|
+
*/
|
|
106
|
+
async function runCommand(command, cwd, timeoutMs) {
|
|
107
|
+
return new Promise((resolve) => {
|
|
108
|
+
const proc = spawn("/bin/sh", ["-c", command], {
|
|
109
|
+
cwd,
|
|
110
|
+
env: scrubbedEnv(),
|
|
111
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
112
|
+
});
|
|
113
|
+
const stdoutChunks = [];
|
|
114
|
+
const stderrChunks = [];
|
|
115
|
+
let stdoutLen = 0;
|
|
116
|
+
let stderrLen = 0;
|
|
117
|
+
let truncated = false;
|
|
118
|
+
let timedOut = false;
|
|
119
|
+
proc.stdout?.on("data", (chunk) => {
|
|
120
|
+
const remaining = MAX_OUTPUT_BYTES - stdoutLen;
|
|
121
|
+
if (remaining <= 0) {
|
|
122
|
+
truncated = true;
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
if (chunk.length > remaining) {
|
|
126
|
+
stdoutChunks.push(chunk.subarray(0, remaining));
|
|
127
|
+
stdoutLen += remaining;
|
|
128
|
+
truncated = true;
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
stdoutChunks.push(chunk);
|
|
132
|
+
stdoutLen += chunk.length;
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
proc.stderr?.on("data", (chunk) => {
|
|
136
|
+
const remaining = MAX_OUTPUT_BYTES - stderrLen;
|
|
137
|
+
if (remaining <= 0) {
|
|
138
|
+
truncated = true;
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
if (chunk.length > remaining) {
|
|
142
|
+
stderrChunks.push(chunk.subarray(0, remaining));
|
|
143
|
+
stderrLen += remaining;
|
|
144
|
+
truncated = true;
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
stderrChunks.push(chunk);
|
|
148
|
+
stderrLen += chunk.length;
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
const timer = setTimeout(() => {
|
|
152
|
+
timedOut = true;
|
|
153
|
+
try {
|
|
154
|
+
proc.kill("SIGTERM");
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
// best-effort
|
|
158
|
+
}
|
|
159
|
+
// SIGKILL grace — match the exec-route convention.
|
|
160
|
+
setTimeout(() => {
|
|
161
|
+
try {
|
|
162
|
+
proc.kill("SIGKILL");
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
// best-effort
|
|
166
|
+
}
|
|
167
|
+
}, 2000);
|
|
168
|
+
}, timeoutMs);
|
|
169
|
+
proc.on("error", (err) => {
|
|
170
|
+
clearTimeout(timer);
|
|
171
|
+
// Spawn error (ENOENT on `/bin/sh`, etc.) — surface as a failed
|
|
172
|
+
// run with the error on stderr so the chat card shows it.
|
|
173
|
+
resolve({
|
|
174
|
+
exitCode: null,
|
|
175
|
+
stdout: Buffer.concat(stdoutChunks).toString("utf8"),
|
|
176
|
+
stderr: err.message,
|
|
177
|
+
timedOut,
|
|
178
|
+
truncated,
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
proc.on("close", (code) => {
|
|
182
|
+
clearTimeout(timer);
|
|
183
|
+
resolve({
|
|
184
|
+
exitCode: code,
|
|
185
|
+
stdout: Buffer.concat(stdoutChunks).toString("utf8"),
|
|
186
|
+
stderr: Buffer.concat(stderrChunks).toString("utf8"),
|
|
187
|
+
timedOut,
|
|
188
|
+
truncated,
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
export const quickActionRoutes = async (fastify) => {
|
|
194
|
+
fastify.get("/quick-actions", {
|
|
195
|
+
schema: {
|
|
196
|
+
description: "List all quick-action chips. Global (not per-project) — chips " +
|
|
197
|
+
"are operator-personal, same install-private rationale as the " +
|
|
198
|
+
"other forge-owned config files.",
|
|
199
|
+
tags: ["config"],
|
|
200
|
+
response: {
|
|
201
|
+
200: {
|
|
202
|
+
type: "object",
|
|
203
|
+
required: ["actions"],
|
|
204
|
+
properties: {
|
|
205
|
+
actions: { type: "array", items: quickActionSchema },
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
}, async () => ({ actions: await readQuickActions() }));
|
|
211
|
+
fastify.post("/quick-actions", {
|
|
212
|
+
schema: {
|
|
213
|
+
description: "Create a quick-action chip. Exactly one of `command` or `text` " +
|
|
214
|
+
"must be set — presence is the kind discriminator (no `kind` " +
|
|
215
|
+
"field on the wire, matches the MCP server-config convention). " +
|
|
216
|
+
"400 on both/neither, 400 on byte-cap overflow.",
|
|
217
|
+
tags: ["config"],
|
|
218
|
+
body: {
|
|
219
|
+
type: "object",
|
|
220
|
+
required: ["name"],
|
|
221
|
+
additionalProperties: false,
|
|
222
|
+
properties: {
|
|
223
|
+
name: { type: "string", minLength: 1, maxLength: 200 },
|
|
224
|
+
enabled: { type: "boolean" },
|
|
225
|
+
command: { type: "string" },
|
|
226
|
+
timeoutMs: { type: "integer", minimum: 1 },
|
|
227
|
+
text: { type: "string" },
|
|
228
|
+
mode: { type: "string", enum: ["send", "insert"] },
|
|
229
|
+
},
|
|
230
|
+
},
|
|
231
|
+
response: {
|
|
232
|
+
201: quickActionSchema,
|
|
233
|
+
400: errorSchema,
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
}, async (req, reply) => {
|
|
237
|
+
const validated = validateBody(req.body, reply);
|
|
238
|
+
if (validated === undefined)
|
|
239
|
+
return reply;
|
|
240
|
+
try {
|
|
241
|
+
const created = await createQuickAction(validated);
|
|
242
|
+
return reply.code(201).send(created);
|
|
243
|
+
}
|
|
244
|
+
catch (err) {
|
|
245
|
+
return handleError(reply, err);
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
fastify.put("/quick-actions/:id", {
|
|
249
|
+
schema: {
|
|
250
|
+
description: "Replace a quick-action chip. Full record on the body — switching " +
|
|
251
|
+
"kind (command ↔ prompt) drops the now-unused fields. Same " +
|
|
252
|
+
"validation rules as POST.",
|
|
253
|
+
tags: ["config"],
|
|
254
|
+
params: {
|
|
255
|
+
type: "object",
|
|
256
|
+
required: ["id"],
|
|
257
|
+
properties: { id: { type: "string" } },
|
|
258
|
+
},
|
|
259
|
+
body: {
|
|
260
|
+
type: "object",
|
|
261
|
+
required: ["name"],
|
|
262
|
+
additionalProperties: false,
|
|
263
|
+
properties: {
|
|
264
|
+
name: { type: "string", minLength: 1, maxLength: 200 },
|
|
265
|
+
enabled: { type: "boolean" },
|
|
266
|
+
command: { type: "string" },
|
|
267
|
+
timeoutMs: { type: "integer", minimum: 1 },
|
|
268
|
+
text: { type: "string" },
|
|
269
|
+
mode: { type: "string", enum: ["send", "insert"] },
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
response: {
|
|
273
|
+
200: quickActionSchema,
|
|
274
|
+
400: errorSchema,
|
|
275
|
+
404: errorSchema,
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
}, async (req, reply) => {
|
|
279
|
+
const validated = validateBody(req.body, reply);
|
|
280
|
+
if (validated === undefined)
|
|
281
|
+
return reply;
|
|
282
|
+
try {
|
|
283
|
+
const updated = await updateQuickAction(req.params.id, validated);
|
|
284
|
+
return updated;
|
|
285
|
+
}
|
|
286
|
+
catch (err) {
|
|
287
|
+
return handleError(reply, err);
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
fastify.delete("/quick-actions/:id", {
|
|
291
|
+
schema: {
|
|
292
|
+
description: "Delete a quick-action chip.",
|
|
293
|
+
tags: ["config"],
|
|
294
|
+
params: {
|
|
295
|
+
type: "object",
|
|
296
|
+
required: ["id"],
|
|
297
|
+
properties: { id: { type: "string" } },
|
|
298
|
+
},
|
|
299
|
+
response: {
|
|
300
|
+
204: { type: "null" },
|
|
301
|
+
404: errorSchema,
|
|
302
|
+
},
|
|
303
|
+
},
|
|
304
|
+
}, async (req, reply) => {
|
|
305
|
+
try {
|
|
306
|
+
await deleteQuickAction(req.params.id);
|
|
307
|
+
return reply.code(204).send();
|
|
308
|
+
}
|
|
309
|
+
catch (err) {
|
|
310
|
+
return handleError(reply, err);
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
fastify.post("/quick-actions/:id/run", {
|
|
314
|
+
schema: {
|
|
315
|
+
description: "Execute a command-kind quick action in the named project's " +
|
|
316
|
+
"cwd. Returns captured stdout/stderr and the exit code. The " +
|
|
317
|
+
"spawned shell inherits a SCRUBBED env (same as the " +
|
|
318
|
+
"integrated terminal — no pi-forge or provider secrets). " +
|
|
319
|
+
"Hard-gated under MINIMAL_UI: command runs return 403 " +
|
|
320
|
+
"`command_actions_disabled_in_minimal` regardless of who " +
|
|
321
|
+
"is calling. Prompt-kind actions are not executable here " +
|
|
322
|
+
"(420-style validation error) — those are a pure client " +
|
|
323
|
+
"concern that route through the composer or sendPrompt.",
|
|
324
|
+
tags: ["config"],
|
|
325
|
+
params: {
|
|
326
|
+
type: "object",
|
|
327
|
+
required: ["id"],
|
|
328
|
+
properties: { id: { type: "string" } },
|
|
329
|
+
},
|
|
330
|
+
body: {
|
|
331
|
+
type: "object",
|
|
332
|
+
required: ["projectId"],
|
|
333
|
+
additionalProperties: false,
|
|
334
|
+
properties: {
|
|
335
|
+
projectId: { type: "string", minLength: 1 },
|
|
336
|
+
},
|
|
337
|
+
},
|
|
338
|
+
response: {
|
|
339
|
+
200: runResultSchema,
|
|
340
|
+
400: errorSchema,
|
|
341
|
+
403: errorSchema,
|
|
342
|
+
404: errorSchema,
|
|
343
|
+
},
|
|
344
|
+
},
|
|
345
|
+
}, async (req, reply) => {
|
|
346
|
+
// Defense in depth — the client also hides command chips
|
|
347
|
+
// under MINIMAL_UI, but a stale tab or scripted caller could
|
|
348
|
+
// still POST here. Refuse at the route.
|
|
349
|
+
if (config.minimalUi) {
|
|
350
|
+
return reply.code(403).send({ error: "command_actions_disabled_in_minimal" });
|
|
351
|
+
}
|
|
352
|
+
const action = await getQuickAction(req.params.id);
|
|
353
|
+
if (action === undefined) {
|
|
354
|
+
return reply.code(404).send({ error: "action_not_found" });
|
|
355
|
+
}
|
|
356
|
+
if (isPromptAction(action)) {
|
|
357
|
+
return reply.code(400).send({
|
|
358
|
+
error: "not_a_command_action",
|
|
359
|
+
message: "prompt actions are dispatched client-side, not via this route",
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
if (!isCommandAction(action)) {
|
|
363
|
+
return reply.code(400).send({ error: "invalid_action" });
|
|
364
|
+
}
|
|
365
|
+
const project = await getProject(req.body.projectId);
|
|
366
|
+
if (project === undefined) {
|
|
367
|
+
return reply.code(404).send({ error: "project_not_found" });
|
|
368
|
+
}
|
|
369
|
+
const timeoutMs = Math.min(action.timeoutMs ?? DEFAULT_TIMEOUT_MS, MAX_TIMEOUT_MS);
|
|
370
|
+
const started = Date.now();
|
|
371
|
+
const result = await runCommand(action.command, project.path, timeoutMs);
|
|
372
|
+
const durationMs = Date.now() - started;
|
|
373
|
+
return {
|
|
374
|
+
success: result.exitCode === 0 && !result.timedOut,
|
|
375
|
+
exitCode: result.exitCode,
|
|
376
|
+
stdout: result.stdout,
|
|
377
|
+
stderr: result.stderr,
|
|
378
|
+
durationMs,
|
|
379
|
+
timedOut: result.timedOut,
|
|
380
|
+
truncated: result.truncated,
|
|
381
|
+
};
|
|
382
|
+
});
|
|
383
|
+
};
|
|
384
|
+
//# sourceMappingURL=quick-actions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quick-actions.js","sourceRoot":"","sources":["../../src/routes/quick-actions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { getSession } from "../session-registry.js";
|
|
2
|
+
import { getState } from "../todo/store.js";
|
|
3
|
+
import { errorSchema } from "./_schemas.js";
|
|
4
|
+
/**
|
|
5
|
+
* GET /sessions/:id/todos
|
|
6
|
+
*
|
|
7
|
+
* Returns the current todo state for a session. Used by the UI
|
|
8
|
+
* panel as the initial fetch when an SSE snapshot hasn't landed
|
|
9
|
+
* yet (cold load, cross-tab join). The store's `getState` is
|
|
10
|
+
* cache-first with replay-on-miss, so this is honest after a
|
|
11
|
+
* server restart even if the cache is empty.
|
|
12
|
+
*
|
|
13
|
+
* The wire shape mirrors the SSE `todo_update` event so the
|
|
14
|
+
* client can use one normaliser for both paths.
|
|
15
|
+
*/
|
|
16
|
+
const taskSchema = {
|
|
17
|
+
type: "object",
|
|
18
|
+
required: ["id", "subject", "status"],
|
|
19
|
+
additionalProperties: true,
|
|
20
|
+
properties: {
|
|
21
|
+
id: { type: "integer" },
|
|
22
|
+
subject: { type: "string" },
|
|
23
|
+
description: { type: "string" },
|
|
24
|
+
activeForm: { type: "string" },
|
|
25
|
+
status: { type: "string", enum: ["pending", "in_progress", "completed", "deleted"] },
|
|
26
|
+
blockedBy: { type: "array", items: { type: "integer" } },
|
|
27
|
+
owner: { type: "string" },
|
|
28
|
+
metadata: { type: "object", additionalProperties: true },
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
export const todoRoutes = async (fastify) => {
|
|
32
|
+
fastify.get("/sessions/:id/todos", {
|
|
33
|
+
schema: {
|
|
34
|
+
description: "Return the current todo list for this session. Cache-first; " +
|
|
35
|
+
"rebuilds from the session branch on cache miss so a server " +
|
|
36
|
+
"restart doesn't lie about state.",
|
|
37
|
+
tags: ["sessions"],
|
|
38
|
+
params: {
|
|
39
|
+
type: "object",
|
|
40
|
+
required: ["id"],
|
|
41
|
+
properties: { id: { type: "string" } },
|
|
42
|
+
},
|
|
43
|
+
response: {
|
|
44
|
+
200: {
|
|
45
|
+
type: "object",
|
|
46
|
+
required: ["tasks", "nextId"],
|
|
47
|
+
properties: {
|
|
48
|
+
tasks: { type: "array", items: taskSchema },
|
|
49
|
+
nextId: { type: "integer" },
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
404: errorSchema,
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
}, async (req, reply) => {
|
|
56
|
+
const live = getSession(req.params.id);
|
|
57
|
+
if (live === undefined) {
|
|
58
|
+
return reply.code(404).send({ error: "session_not_found" });
|
|
59
|
+
}
|
|
60
|
+
// AgentSession.sessionManager is the public accessor (see
|
|
61
|
+
// agent-session.d.ts). getState is cache-first with replay-
|
|
62
|
+
// on-miss, so this stays honest after a server restart.
|
|
63
|
+
const state = getState(req.params.id, live.session.sessionManager);
|
|
64
|
+
return { tasks: state.tasks, nextId: state.nextId };
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
//# sourceMappingURL=todos.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"todos.js","sourceRoot":"","sources":["../../src/routes/todos.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,GAAG;IACjB,IAAI,EAAE,QAAQ;IACd,QAAQ,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,CAAC;IACrC,oBAAoB,EAAE,IAAI;IAC1B,UAAU,EAAE;QACV,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;QACvB,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QAC3B,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QAC/B,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QAC9B,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,SAAS,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS,CAAC,EAAE;QACpF,SAAS,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE;QACxD,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QACzB,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,oBAAoB,EAAE,IAAI,EAAE;KACzD;CACO,CAAC;AAEX,MAAM,CAAC,MAAM,UAAU,GAAuB,KAAK,EAAE,OAAO,EAAE,EAAE;IAC9D,OAAO,CAAC,GAAG,CACT,qBAAqB,EACrB;QACE,MAAM,EAAE;YACN,WAAW,EACT,8DAA8D;gBAC9D,6DAA6D;gBAC7D,kCAAkC;YACpC,IAAI,EAAE,CAAC,UAAU,CAAC;YAClB,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,QAAQ,EAAE,CAAC,IAAI,CAAC;gBAChB,UAAU,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;aACvC;YACD,QAAQ,EAAE;gBACR,GAAG,EAAE;oBACH,IAAI,EAAE,QAAQ;oBACd,QAAQ,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC;oBAC7B,UAAU,EAAE;wBACV,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE;wBAC3C,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;qBAC5B;iBACF;gBACD,GAAG,EAAE,WAAW;aACjB;SACF;KACF,EACD,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;QACnB,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACvC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC,CAAC;QAC9D,CAAC;QACD,0DAA0D;QAC1D,4DAA4D;QAC5D,wDAAwD;QACxD,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QACnE,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;IACtD,CAAC,CACF,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -9,6 +9,9 @@ import { readProjects } from "./project-manager.js";
|
|
|
9
9
|
import { filterEnabledTools, readToolOverrides } from "./tool-overrides.js";
|
|
10
10
|
import { discoverExtensionResources } from "./extensions-discovery.js";
|
|
11
11
|
import { customToolsForProject as mcpCustomToolsForProject, ensureProjectLoaded as mcpEnsureProjectLoaded, isGloballyEnabled as mcpIsGloballyEnabled, } from "./mcp/manager.js";
|
|
12
|
+
import { createAskUserQuestionTool } from "./ask-user-question/tool.js";
|
|
13
|
+
import { createTodoTool } from "./todo/tool.js";
|
|
14
|
+
import { clearForSession as clearTodoForSession, refreshFromBranch as refreshTodoFromBranch, } from "./todo/store.js";
|
|
12
15
|
export class SessionNotFoundError extends Error {
|
|
13
16
|
constructor(id) {
|
|
14
17
|
super(`session not found: ${id}`);
|
|
@@ -52,6 +55,15 @@ export const BUILTIN_TOOL_NAMES = [
|
|
|
52
55
|
"grep",
|
|
53
56
|
"find",
|
|
54
57
|
"ls",
|
|
58
|
+
// ask_user_question is implemented in pi-forge (see ask-user-question/),
|
|
59
|
+
// not in the pi SDK. Listed here so the Tools settings tab surfaces it
|
|
60
|
+
// under "Built-in tools" — disabling it filters it out of the allowlist
|
|
61
|
+
// passed to createAgentSession, so the agent never sees the tool.
|
|
62
|
+
"ask_user_question",
|
|
63
|
+
// todo is implemented in pi-forge (see todo/), contract-compatible with
|
|
64
|
+
// @juicesharp/rpiv-todo. Same disable-via-settings semantics as
|
|
65
|
+
// ask_user_question.
|
|
66
|
+
"todo",
|
|
55
67
|
];
|
|
56
68
|
/**
|
|
57
69
|
* Build the `tools` allowlist passed to `createAgentSession` for this
|
|
@@ -247,7 +259,14 @@ export async function createSession(projectId, workspacePath) {
|
|
|
247
259
|
// agentDir IS passed: without it, the SDK falls back to ~/.pi/agent and
|
|
248
260
|
// ignores PI_CONFIG_DIR entirely, breaking auth.json/models.json wiring
|
|
249
261
|
// for Phase 6's prompt route.
|
|
250
|
-
const
|
|
262
|
+
const mcpTools = await resolveMcpCustomTools(projectId, workspacePath);
|
|
263
|
+
// SessionManager.getSessionId() is synchronous and stable from
|
|
264
|
+
// create() onward — read it BEFORE createAgentSession so the
|
|
265
|
+
// forge-native ask_user_question tool can bind to the right
|
|
266
|
+
// session in its execute() closure.
|
|
267
|
+
const askTool = createAskUserQuestionTool(sessionManager.getSessionId());
|
|
268
|
+
const todoTool = createTodoTool(sessionManager.getSessionId(), sessionManager);
|
|
269
|
+
const customTools = [...mcpTools, askTool, todoTool];
|
|
251
270
|
const settingsManager = await buildSessionSettingsManager(workspacePath, projectId);
|
|
252
271
|
const resourceLoader = await buildForgeResourceLoader(workspacePath, config.piConfigDir, settingsManager, projectId);
|
|
253
272
|
const { session } = await createAgentSession({
|
|
@@ -426,7 +445,14 @@ export async function resumeSession(sessionId, projectId, workspacePath) {
|
|
|
426
445
|
// collapses to the project session dir.
|
|
427
446
|
const childSessionDir = match.parentSessionId !== undefined ? join(match.path, "..") : dir;
|
|
428
447
|
const sessionManager = SessionManager.open(match.path, childSessionDir, workspacePath);
|
|
429
|
-
const
|
|
448
|
+
const mcpTools = await resolveMcpCustomTools(projectId, workspacePath);
|
|
449
|
+
const askTool = createAskUserQuestionTool(sessionManager.getSessionId());
|
|
450
|
+
const todoTool = createTodoTool(sessionManager.getSessionId(), sessionManager);
|
|
451
|
+
const customTools = [...mcpTools, askTool, todoTool];
|
|
452
|
+
// Resumed session — refresh the todo cache from the branch so
|
|
453
|
+
// the UI panel sees the persisted state on first SSE connect,
|
|
454
|
+
// not an empty list.
|
|
455
|
+
refreshTodoFromBranch(sessionManager.getSessionId(), sessionManager);
|
|
430
456
|
const settingsManager = await buildSessionSettingsManager(workspacePath, projectId);
|
|
431
457
|
const resourceLoader = await buildForgeResourceLoader(workspacePath, config.piConfigDir, settingsManager, projectId);
|
|
432
458
|
const { session } = await createAgentSession({
|
|
@@ -604,6 +630,10 @@ export async function disposeSession(sessionId) {
|
|
|
604
630
|
catch {
|
|
605
631
|
// ignore — SDK doesn't currently throw, but H2-defensive
|
|
606
632
|
}
|
|
633
|
+
// Drop the todo cache for this session. The cache is a fast
|
|
634
|
+
// path; even without this, a future session with the same id
|
|
635
|
+
// would recover via replay-on-miss. Cleaner to be explicit.
|
|
636
|
+
clearTodoForSession(sessionId);
|
|
607
637
|
}
|
|
608
638
|
finally {
|
|
609
639
|
registry.delete(sessionId);
|
|
@@ -1015,7 +1045,14 @@ async function forkSessionLocked(sessionId, entryId) {
|
|
|
1015
1045
|
throw new Error("fork_failed");
|
|
1016
1046
|
const dir = sessionDirFor(source.projectId);
|
|
1017
1047
|
const sessionManager = SessionManager.open(newPath, dir, source.workspacePath);
|
|
1018
|
-
const
|
|
1048
|
+
const mcpTools = await resolveMcpCustomTools(source.projectId, source.workspacePath);
|
|
1049
|
+
const askTool = createAskUserQuestionTool(sessionManager.getSessionId());
|
|
1050
|
+
const todoTool = createTodoTool(sessionManager.getSessionId(), sessionManager);
|
|
1051
|
+
const customTools = [...mcpTools, askTool, todoTool];
|
|
1052
|
+
// Forked session — replay the branch (which now belongs to the
|
|
1053
|
+
// fork) so the new session's todo cache reflects the inherited
|
|
1054
|
+
// state, not the parent's stale entry.
|
|
1055
|
+
refreshTodoFromBranch(sessionManager.getSessionId(), sessionManager);
|
|
1019
1056
|
const settingsManager = await buildSessionSettingsManager(source.workspacePath, source.projectId);
|
|
1020
1057
|
const resourceLoader = await buildForgeResourceLoader(source.workspacePath, config.piConfigDir, settingsManager, source.projectId);
|
|
1021
1058
|
const { session } = await createAgentSession({
|
|
@@ -1079,7 +1116,18 @@ async function forkSessionLocked(sessionId, entryId) {
|
|
|
1079
1116
|
try {
|
|
1080
1117
|
source.unsubscribe();
|
|
1081
1118
|
const restoredManager = SessionManager.open(originalSourceFile, dir, source.workspacePath);
|
|
1082
|
-
const
|
|
1119
|
+
const restoredMcpTools = await resolveMcpCustomTools(source.projectId, source.workspacePath);
|
|
1120
|
+
const restoredAskTool = createAskUserQuestionTool(restoredManager.getSessionId());
|
|
1121
|
+
const restoredTodoTool = createTodoTool(restoredManager.getSessionId(), restoredManager);
|
|
1122
|
+
const restoredCustomTools = [
|
|
1123
|
+
...restoredMcpTools,
|
|
1124
|
+
restoredAskTool,
|
|
1125
|
+
restoredTodoTool,
|
|
1126
|
+
];
|
|
1127
|
+
// Re-derive the original source's todo cache from the (now
|
|
1128
|
+
// un-mutated) source JSONL — the SDK's fork machinery left
|
|
1129
|
+
// the cache pointing at fork state.
|
|
1130
|
+
refreshTodoFromBranch(restoredManager.getSessionId(), restoredManager);
|
|
1083
1131
|
const restoredSettingsManager = await buildSessionSettingsManager(source.workspacePath, source.projectId);
|
|
1084
1132
|
const restoredResourceLoader = await buildForgeResourceLoader(source.workspacePath, config.piConfigDir, restoredSettingsManager, source.projectId);
|
|
1085
1133
|
const { session: restoredSession } = await createAgentSession({
|