pi-forge 0.0.0 → 1.1.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.
Files changed (103) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +48 -4
  3. package/bin/pi-forge.mjs +37 -0
  4. package/dist/client/assets/CodeMirrorEditor-BqaaP1EE.js +34 -0
  5. package/dist/client/assets/CodeMirrorEditor-BqaaP1EE.js.map +1 -0
  6. package/dist/client/assets/index-B-529kgJ.css +32 -0
  7. package/dist/client/assets/index-BzKzxXFs.js +392 -0
  8. package/dist/client/assets/index-BzKzxXFs.js.map +1 -0
  9. package/dist/client/assets/workbox-window.prod.es5-BBnX5xw4.js +3 -0
  10. package/dist/client/assets/workbox-window.prod.es5-BBnX5xw4.js.map +1 -0
  11. package/dist/client/icons/icon-192.png +0 -0
  12. package/dist/client/icons/icon-512.png +0 -0
  13. package/dist/client/icons/icon-maskable-512.png +0 -0
  14. package/dist/client/icons/icon.svg +9 -0
  15. package/dist/client/index.html +24 -0
  16. package/dist/client/manifest.webmanifest +1 -0
  17. package/dist/client/offline.html +142 -0
  18. package/dist/client/sw.js +3 -0
  19. package/dist/client/sw.js.map +1 -0
  20. package/dist/client/workbox-6d7155ed.js +3 -0
  21. package/dist/client/workbox-6d7155ed.js.map +1 -0
  22. package/dist/server/agent-resource-loader.js +126 -0
  23. package/dist/server/agent-resource-loader.js.map +1 -0
  24. package/dist/server/attachment-converters.js +96 -0
  25. package/dist/server/attachment-converters.js.map +1 -0
  26. package/dist/server/auth.js +209 -0
  27. package/dist/server/auth.js.map +1 -0
  28. package/dist/server/compaction-history.js +106 -0
  29. package/dist/server/compaction-history.js.map +1 -0
  30. package/dist/server/concurrency.js +49 -0
  31. package/dist/server/concurrency.js.map +1 -0
  32. package/dist/server/config-export.js +220 -0
  33. package/dist/server/config-export.js.map +1 -0
  34. package/dist/server/config-manager.js +528 -0
  35. package/dist/server/config-manager.js.map +1 -0
  36. package/dist/server/config.js +326 -0
  37. package/dist/server/config.js.map +1 -0
  38. package/dist/server/conversion-worker.mjs +90 -0
  39. package/dist/server/diagnostics.js +137 -0
  40. package/dist/server/diagnostics.js.map +1 -0
  41. package/dist/server/extensions-discovery.js +147 -0
  42. package/dist/server/extensions-discovery.js.map +1 -0
  43. package/dist/server/file-manager.js +734 -0
  44. package/dist/server/file-manager.js.map +1 -0
  45. package/dist/server/file-references.js +215 -0
  46. package/dist/server/file-references.js.map +1 -0
  47. package/dist/server/file-searcher.js +385 -0
  48. package/dist/server/file-searcher.js.map +1 -0
  49. package/dist/server/git-runner.js +684 -0
  50. package/dist/server/git-runner.js.map +1 -0
  51. package/dist/server/index.js +468 -0
  52. package/dist/server/index.js.map +1 -0
  53. package/dist/server/mcp/config.js +133 -0
  54. package/dist/server/mcp/config.js.map +1 -0
  55. package/dist/server/mcp/manager.js +351 -0
  56. package/dist/server/mcp/manager.js.map +1 -0
  57. package/dist/server/mcp/tool-bridge.js +173 -0
  58. package/dist/server/mcp/tool-bridge.js.map +1 -0
  59. package/dist/server/project-manager.js +301 -0
  60. package/dist/server/project-manager.js.map +1 -0
  61. package/dist/server/pty-manager.js +354 -0
  62. package/dist/server/pty-manager.js.map +1 -0
  63. package/dist/server/routes/_schemas.js +73 -0
  64. package/dist/server/routes/_schemas.js.map +1 -0
  65. package/dist/server/routes/auth.js +164 -0
  66. package/dist/server/routes/auth.js.map +1 -0
  67. package/dist/server/routes/config.js +1163 -0
  68. package/dist/server/routes/config.js.map +1 -0
  69. package/dist/server/routes/control.js +464 -0
  70. package/dist/server/routes/control.js.map +1 -0
  71. package/dist/server/routes/exec.js +217 -0
  72. package/dist/server/routes/exec.js.map +1 -0
  73. package/dist/server/routes/files.js +847 -0
  74. package/dist/server/routes/files.js.map +1 -0
  75. package/dist/server/routes/git.js +837 -0
  76. package/dist/server/routes/git.js.map +1 -0
  77. package/dist/server/routes/health.js +97 -0
  78. package/dist/server/routes/health.js.map +1 -0
  79. package/dist/server/routes/mcp.js +300 -0
  80. package/dist/server/routes/mcp.js.map +1 -0
  81. package/dist/server/routes/projects.js +259 -0
  82. package/dist/server/routes/projects.js.map +1 -0
  83. package/dist/server/routes/prompt.js +496 -0
  84. package/dist/server/routes/prompt.js.map +1 -0
  85. package/dist/server/routes/sessions.js +783 -0
  86. package/dist/server/routes/sessions.js.map +1 -0
  87. package/dist/server/routes/stream.js +69 -0
  88. package/dist/server/routes/stream.js.map +1 -0
  89. package/dist/server/routes/terminal.js +335 -0
  90. package/dist/server/routes/terminal.js.map +1 -0
  91. package/dist/server/session-registry.js +1197 -0
  92. package/dist/server/session-registry.js.map +1 -0
  93. package/dist/server/skill-overrides.js +151 -0
  94. package/dist/server/skill-overrides.js.map +1 -0
  95. package/dist/server/skills-export.js +257 -0
  96. package/dist/server/skills-export.js.map +1 -0
  97. package/dist/server/sse-bridge.js +220 -0
  98. package/dist/server/sse-bridge.js.map +1 -0
  99. package/dist/server/tool-overrides.js +277 -0
  100. package/dist/server/tool-overrides.js.map +1 -0
  101. package/dist/server/turn-diff-builder.js +280 -0
  102. package/dist/server/turn-diff-builder.js.map +1 -0
  103. package/package.json +53 -12
@@ -0,0 +1,217 @@
1
+ import { spawn } from "node:child_process";
2
+ import { errorSchema } from "./_schemas.js";
3
+ import { getSession } from "../session-registry.js";
4
+ import { scrubbedEnv } from "../pty-manager.js";
5
+ /**
6
+ * One-shot user bash execution — the chat input's `!` / `!!` prefix.
7
+ *
8
+ * Mirrors pi-tui's UserBashEvent semantics:
9
+ * - `!cmd` → output appended to the session's message history as a
10
+ * BashExecutionMessage; the next agent turn sees it in
11
+ * LLM context.
12
+ * - `!!cmd` → same render, `excludeFromContext: true` keeps it out
13
+ * of the next turn's prompt. Local convenience only.
14
+ *
15
+ * Implementation uses the SDK's `AgentSession.executeBash()` directly.
16
+ * That call:
17
+ * 1. Spawns the command via the BashOperations we hand it
18
+ * 2. Pushes a BashExecutionMessage into `agent.state.messages` so
19
+ * the next prompt's context window includes it (or skips it
20
+ * when excludeFromContext is true)
21
+ * 3. Persists the message via `sessionManager.appendMessage` so the
22
+ * session JSONL captures it on agent_end (pi defers session
23
+ * writes until at least one assistant message has landed —
24
+ * our message is held in the in-memory list until then)
25
+ *
26
+ * Hand-rolling the spawn would let us emit ANSI-stripped output and
27
+ * apply our own timeout, but it would NOT update agent.state.messages
28
+ * (that's a private field). The SDK's path is the supported way to
29
+ * inject context.
30
+ *
31
+ * Security posture: BashOperations is overridden to inject our
32
+ * `scrubbedEnv()` — an allowlist-based filter that only passes
33
+ * known-harmless system vars (PATH, HOME, TERM, locales, …). pi-forge
34
+ * secrets, provider keys, cloud credentials, and any other host-env
35
+ * vars are dropped unless the operator opts them back in via
36
+ * `TERMINAL_PASSTHROUGH_ENV`. Matches the integrated terminal's
37
+ * posture. The agent's own bash TOOL may still have an env-exposure
38
+ * surface — that's a separate fix for a separate code path.
39
+ */
40
+ const DEFAULT_TIMEOUT_MS = 30_000;
41
+ /**
42
+ * Build a BashOperations that delegates to local spawn, but with our
43
+ * scrubbed env. createLocalBashOperations from the SDK would inherit
44
+ * `process.env` verbatim, leaking secrets the pi-forge process
45
+ * carries (JWT_SECRET, API_KEY, etc.) — see
46
+ * pty-manager.TERMINAL_ENV_ALLOWLIST for the full set of allowed
47
+ * passthrough vars and rationale.
48
+ */
49
+ function forgeBashOperations() {
50
+ return {
51
+ exec: (command, cwd, options) => {
52
+ return new Promise((resolve, reject) => {
53
+ const proc = spawn("/bin/sh", ["-c", command], {
54
+ cwd,
55
+ env: scrubbedEnv(),
56
+ stdio: ["ignore", "pipe", "pipe"],
57
+ });
58
+ // Honor an external AbortSignal (the SDK ties this to its own
59
+ // _bashAbortController so abortBash() propagates).
60
+ const onAbort = () => {
61
+ try {
62
+ proc.kill("SIGTERM");
63
+ }
64
+ catch {
65
+ // best-effort
66
+ }
67
+ // SIGKILL after grace if SIGTERM is ignored.
68
+ setTimeout(() => {
69
+ try {
70
+ proc.kill("SIGKILL");
71
+ }
72
+ catch {
73
+ // best-effort
74
+ }
75
+ }, 2000);
76
+ };
77
+ if (options.signal !== undefined) {
78
+ if (options.signal.aborted)
79
+ onAbort();
80
+ else
81
+ options.signal.addEventListener("abort", onAbort, { once: true });
82
+ }
83
+ // Stream chunks back so the SDK's truncation-and-buffering
84
+ // logic gets to apply (executor caps total output, writes
85
+ // overflow to a temp file, etc.).
86
+ proc.stdout?.on("data", (data) => options.onData(data));
87
+ proc.stderr?.on("data", (data) => options.onData(data));
88
+ proc.on("error", (err) => reject(err));
89
+ proc.on("close", (code) => resolve({ exitCode: code }));
90
+ });
91
+ },
92
+ };
93
+ }
94
+ /**
95
+ * Wrap a BashOperations so that `options.signal` is the union of the
96
+ * caller's signal and our own timeout signal. The SDK's executeBash
97
+ * passes its abort controller as `options.signal`; we still need our
98
+ * 30s wall-clock cap, so this union forwards an abort from EITHER
99
+ * source to the inner exec.
100
+ */
101
+ function timeoutOperations(inner, timeoutSignal) {
102
+ return {
103
+ exec: (command, cwd, options) => {
104
+ const merged = options.signal !== undefined ? mergeSignals(options.signal, timeoutSignal) : timeoutSignal;
105
+ return inner.exec(command, cwd, { ...options, signal: merged });
106
+ },
107
+ };
108
+ }
109
+ function mergeSignals(a, b) {
110
+ const controller = new AbortController();
111
+ const onAbort = () => controller.abort();
112
+ if (a.aborted || b.aborted) {
113
+ controller.abort();
114
+ }
115
+ else {
116
+ a.addEventListener("abort", onAbort, { once: true });
117
+ b.addEventListener("abort", onAbort, { once: true });
118
+ }
119
+ return controller.signal;
120
+ }
121
+ export const execRoutes = async (fastify) => {
122
+ fastify.post("/sessions/:id/exec", {
123
+ schema: {
124
+ description: "Run a one-shot bash command in the session's project cwd " +
125
+ "(the chat input's `!` / `!!` prefix dispatches here). The " +
126
+ "result is added to the session's in-memory context AND " +
127
+ "persisted to the session JSONL (deferred until the next " +
128
+ "agent turn finalizes — pi's session-write is gated on " +
129
+ "having at least one assistant message). With " +
130
+ "`excludeFromContext: true` (the `!!` prefix) the result " +
131
+ "is recorded but kept out of the next turn's LLM input. " +
132
+ "Output is captured whole — no streaming for v1. The " +
133
+ "spawned shell inherits a scrubbed env (no pi-forge / " +
134
+ "provider secrets), same posture as the integrated " +
135
+ "terminal.",
136
+ tags: ["sessions"],
137
+ params: {
138
+ type: "object",
139
+ required: ["id"],
140
+ properties: { id: { type: "string" } },
141
+ },
142
+ body: {
143
+ type: "object",
144
+ required: ["command"],
145
+ additionalProperties: false,
146
+ properties: {
147
+ command: { type: "string", minLength: 1, maxLength: 4096 },
148
+ excludeFromContext: { type: "boolean" },
149
+ },
150
+ },
151
+ response: {
152
+ 200: {
153
+ type: "object",
154
+ required: ["exitCode", "output", "durationMs", "truncated", "cancelled"],
155
+ properties: {
156
+ exitCode: { type: ["integer", "null"] },
157
+ output: { type: "string" },
158
+ durationMs: { type: "integer" },
159
+ truncated: { type: "boolean" },
160
+ cancelled: { type: "boolean" },
161
+ },
162
+ },
163
+ 404: errorSchema,
164
+ 500: errorSchema,
165
+ },
166
+ },
167
+ }, async (req, reply) => {
168
+ const live = getSession(req.params.id);
169
+ if (live === undefined) {
170
+ return reply.code(404).send({ error: "session_not_found" });
171
+ }
172
+ const { command, excludeFromContext = false } = req.body;
173
+ const started = Date.now();
174
+ // Defense-in-depth timeout — the SDK's bash executor has its
175
+ // own truncation behavior but no time cap. We pre-bake an abort
176
+ // signal that fires after DEFAULT_TIMEOUT_MS so a runaway loop
177
+ // can't tie up the request handler indefinitely.
178
+ const timeoutController = new AbortController();
179
+ const timer = setTimeout(() => timeoutController.abort(), DEFAULT_TIMEOUT_MS);
180
+ try {
181
+ const result = await live.session.executeBash(command, undefined, {
182
+ excludeFromContext,
183
+ operations: timeoutOperations(forgeBashOperations(), timeoutController.signal),
184
+ });
185
+ const durationMs = Date.now() - started;
186
+ live.lastActivityAt = new Date();
187
+ // Cross-tab refetch trigger — every other browser viewing this
188
+ // session schedules a getMessages refetch on `user_bash_result`.
189
+ // The acting tab refetches off the HTTP response directly.
190
+ for (const c of live.clients) {
191
+ try {
192
+ c.send({ type: "user_bash_result" });
193
+ }
194
+ catch {
195
+ // best-effort fan-out; sse-bridge handles client drop on its own
196
+ }
197
+ }
198
+ return {
199
+ exitCode: result.exitCode === undefined ? null : result.exitCode,
200
+ output: result.output,
201
+ durationMs,
202
+ truncated: result.truncated,
203
+ cancelled: result.cancelled,
204
+ };
205
+ }
206
+ catch (err) {
207
+ return reply.code(500).send({
208
+ error: "exec_failed",
209
+ message: err instanceof Error ? err.message : String(err),
210
+ });
211
+ }
212
+ finally {
213
+ clearTimeout(timer);
214
+ }
215
+ });
216
+ };
217
+ //# sourceMappingURL=exec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exec.js","sourceRoot":"","sources":["../../src/routes/exec.ts"],"names":[],"mappings":"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"}