this derivation will be built: /nix/store/yjliqcn9skfvq9g2iq86ccazzy64vcjl-treefmt-check.drv building '/nix/store/yjliqcn9skfvq9g2iq86ccazzy64vcjl-treefmt-check.drv' treefmt-check> tribuchet: building on eliza treefmt-check> treefmt v2.6.0traversed 1126 files treefmt-check> emitted 455 files for processing treefmt-check> formatted 455 files (4 changed) in 1.865s treefmt-check> M home/.pi/agent/extensions/inbox.ts treefmt-check> M home/.pi/agent/extensions/python/index.ts treefmt-check> diff --git a/home/.pi/agent/extensions/inbox.ts b/home/.pi/agent/extensions/inbox.ts treefmt-check> index 0b5f038..f693974 100644 treefmt-check> --- a/home/.pi/agent/extensions/inbox.ts treefmt-check> +++ b/home/.pi/agent/extensions/inbox.ts treefmt-check> @@ -30,15 +30,25 @@ function parse(raw: string): Event { treefmt-check> } treefmt-check> treefmt-check> export default function (pi: ExtensionAPI) { treefmt-check> - const path = join(process.env.XDG_RUNTIME_DIR ?? "/tmp", "pi-inbox", `${process.pid}.sock`); treefmt-check> + const path = join( treefmt-check> + process.env.XDG_RUNTIME_DIR ?? "/tmp", treefmt-check> + "pi-inbox", treefmt-check> + `${process.pid}.sock`, treefmt-check> + ); treefmt-check> treefmt-check> pi.registerMessageRenderer("inbox", (message, _options, theme) => { treefmt-check> const ev = message.details as Event; treefmt-check> let lines = ev.text.split("\n"); treefmt-check> if (lines.length > TAIL_LINES) { treefmt-check> - lines = [`… ${lines.length - TAIL_LINES} lines`, ...lines.slice(-TAIL_LINES)]; treefmt-check> + lines = [ treefmt-check> + `… ${lines.length - TAIL_LINES} lines`, treefmt-check> + ...lines.slice(-TAIL_LINES), treefmt-check> + ]; treefmt-check> } treefmt-check> - const title = theme.fg("accent", theme.bold(`▌inbox ${ev.source ?? ""}`.trimEnd())); treefmt-check> + const title = theme.fg( treefmt-check> + "accent", treefmt-check> + theme.bold(`▌inbox ${ev.source ?? ""}`.trimEnd()), treefmt-check> + ); treefmt-check> return new Text(`${title}\n${theme.fg("muted", lines.join("\n"))}`, 0, 0); treefmt-check> }); treefmt-check> treefmt-check> @@ -46,20 +56,27 @@ export default function (pi: ExtensionAPI) { treefmt-check> mkdirSync(join(path, ".."), { recursive: true, mode: 0o700 }); treefmt-check> rmSync(path, { force: true }); treefmt-check> const server = createServer(async (conn) => { treefmt-check> - const raw = (await text(conn).catch(() => "")).slice(0, MAX_BYTES); treefmt-check> - const ev = parse(raw); treefmt-check> - if (!ev.text) return; treefmt-check> - const header = ev.source ? `[inbox: ${ev.source}]` : "[inbox]"; treefmt-check> - pi.sendMessage( treefmt-check> - { customType: "inbox", content: `${header}\n${ev.text}`, display: true, details: ev }, treefmt-check> - { deliverAs: "followUp", triggerTurn: true }, treefmt-check> - ); treefmt-check> + const raw = (await text(conn).catch(() => "")).slice(0, MAX_BYTES); treefmt-check> + const ev = parse(raw); treefmt-check> + if (!ev.text) return; treefmt-check> + const header = ev.source ? `[inbox: ${ev.source}]` : "[inbox]"; treefmt-check> + pi.sendMessage( treefmt-check> + { treefmt-check> + customType: "inbox", treefmt-check> + content: `${header}\n${ev.text}`, treefmt-check> + display: true, treefmt-check> + details: ev, treefmt-check> + }, treefmt-check> + { deliverAs: "followUp", triggerTurn: true }, treefmt-check> + ); treefmt-check> }).listen(path); treefmt-check> process.env.PI_INBOX = path; treefmt-check> treefmt-check> pi.on("session_start", async (_event, ctx) => { treefmt-check> const file = ctx.sessionManager.getSessionFile(); treefmt-check> - process.env.PI_SESSION_ID = file ? basename(file, ".jsonl") : `pid-${process.pid}`; treefmt-check> + process.env.PI_SESSION_ID = file treefmt-check> + ? basename(file, ".jsonl") treefmt-check> + : `pid-${process.pid}`; treefmt-check> }); treefmt-check> treefmt-check> pi.on("session_shutdown", async () => { treefmt-check> diff --git a/home/.pi/agent/extensions/python/index.ts b/home/.pi/agent/extensions/python/index.ts treefmt-check> index ca86ebf..a841c8a 100644 treefmt-check> --- a/home/.pi/agent/extensions/python/index.ts treefmt-check> +++ b/home/.pi/agent/extensions/python/index.ts treefmt-check> @@ -58,121 +58,127 @@ export default function (pi: ExtensionAPI) { treefmt-check> registerTool(); treefmt-check> }); treefmt-check> treefmt-check> - const registerTool = () => pi.registerTool({ treefmt-check> - name: "python", treefmt-check> - label: "python", treefmt-check> - description: treefmt-check> - "Execute Python code in a persistent interpreter: variables, imports and open files survive between calls for the whole session. " + treefmt-check> - "The value of a trailing expression is echoed like in a REPL; use print() for anything else. " + treefmt-check> - "matplotlib figures are returned as images. Available: polars, matplotlib, requests, plumbum, pexpect, pyelftools + stdlib. " + treefmt-check> - `Output is truncated to the last ${DEFAULT_MAX_LINES} lines / ${ treefmt-check> - formatSize(DEFAULT_MAX_BYTES) treefmt-check> - }.`, treefmt-check> - promptSnippet: treefmt-check> - "Run Python in a persistent interpreter (state kept across calls; polars, matplotlib, requests, pexpect, pyelftools)", treefmt-check> - promptGuidelines: [ treefmt-check> - "Use python instead of bash for multi-step data work (JSON/CSV/logs/ELF), calculations, and anything where re-parsing input on every call would be wasteful; state persists, so load once and iterate.", treefmt-check> - "Drive interactive programs (ssh, REPLs, debuggers, installers) with pexpect inside the python tool: `child = pexpect.spawn(cmd, encoding='utf-8')` persists across calls; always pass `timeout=` to expect().", treefmt-check> - ...(process.env.PI_INBOX treefmt-check> - ? [ treefmt-check> - "Don't block on long waits in python: run them in a `threading.Thread` that calls the predefined `notify(text, source=\"python\")` when done. It arrives later as an `[inbox: ]` message.", treefmt-check> - ] treefmt-check> - : []), treefmt-check> - ], treefmt-check> - parameters: Type.Object({ treefmt-check> - code: Type.String({ description: "Python source to execute" }), treefmt-check> - timeout: Type.Optional( treefmt-check> - Type.Number({ treefmt-check> - description: "Timeout in seconds (interrupts the cell, keeps state)", treefmt-check> - }), treefmt-check> - ), treefmt-check> - }), treefmt-check> + const registerTool = () => treefmt-check> + pi.registerTool({ treefmt-check> + name: "python", treefmt-check> + label: "python", treefmt-check> + description: treefmt-check> + "Execute Python code in a persistent interpreter: variables, imports and open files survive between calls for the whole session. " + treefmt-check> + "The value of a trailing expression is echoed like in a REPL; use print() for anything else. " + treefmt-check> + "matplotlib figures are returned as images. Available: polars, matplotlib, requests, plumbum, pexpect, pyelftools + stdlib. " + treefmt-check> + `Output is truncated to the last ${DEFAULT_MAX_LINES} lines / ${ treefmt-check> + formatSize(DEFAULT_MAX_BYTES) treefmt-check> + }.`, treefmt-check> + promptSnippet: treefmt-check> + "Run Python in a persistent interpreter (state kept across calls; polars, matplotlib, requests, pexpect, pyelftools)", treefmt-check> + promptGuidelines: [ treefmt-check> + "Use python instead of bash for multi-step data work (JSON/CSV/logs/ELF), calculations, and anything where re-parsing input on every call would be wasteful; state persists, so load once and iterate.", treefmt-check> + "Drive interactive programs (ssh, REPLs, debuggers, installers) with pexpect inside the python tool: `child = pexpect.spawn(cmd, encoding='utf-8')` persists across calls; always pass `timeout=` to expect().", treefmt-check> + ...(process.env.PI_INBOX treefmt-check> + ? [ treefmt-check> + 'Don\'t block on long waits in python: run them in a `threading.Thread` that calls the predefined `notify(text, source="python")` when done. It arrives later as an `[inbox: ]` message.', treefmt-check> + ] treefmt-check> + : []), treefmt-check> + ], treefmt-check> + parameters: Type.Object({ treefmt-check> + code: Type.String({ description: "Python source to execute" }), treefmt-check> + timeout: Type.Optional( treefmt-check> + Type.Number({ treefmt-check> + description: treefmt-check> + "Timeout in seconds (interrupts the cell, keeps state)", treefmt-check> + }), treefmt-check> + ), treefmt-check> + }), treefmt-check> treefmt-check> - // Without this pi's fallback renders only the tool name, hiding the code. treefmt-check> - renderCall(args, theme, context) { treefmt-check> - const text = (context.lastComponent as Text | undefined) ?? treefmt-check> - new Text("", 0, 0); treefmt-check> - let out = theme.fg("toolTitle", theme.bold("python")); treefmt-check> - if (args.timeout) out += theme.fg("muted", ` (timeout ${args.timeout}s)`); treefmt-check> - const code = (args.code ?? "").trimEnd(); treefmt-check> - if (code) out += "\n" + highlightCode(code, "python").join("\n"); treefmt-check> - text.setText(out); treefmt-check> - return text; treefmt-check> - }, treefmt-check> + // Without this pi's fallback renders only the tool name, hiding the code. treefmt-check> + renderCall(args, theme, context) { treefmt-check> + const text = (context.lastComponent as Text | undefined) ?? treefmt-check> + new Text("", 0, 0); treefmt-check> + let out = theme.fg("toolTitle", theme.bold("python")); treefmt-check> + if (args.timeout) { treefmt-check> + out += theme.fg("muted", ` (timeout ${args.timeout}s)`); treefmt-check> + } treefmt-check> + const code = (args.code ?? "").trimEnd(); treefmt-check> + if (code) out += "\n" + highlightCode(code, "python").join("\n"); treefmt-check> + text.setText(out); treefmt-check> + return text; treefmt-check> + }, treefmt-check> treefmt-check> - renderResult(result, options, theme, context) { treefmt-check> - const text = (context.lastComponent as Text | undefined) ?? treefmt-check> - new Text("", 0, 0); treefmt-check> - const output = result.content treefmt-check> - .filter((c) => c.type === "text") treefmt-check> - .map((c) => (c as { text: string }).text) treefmt-check> - .join("\n") treefmt-check> - .trimEnd(); treefmt-check> - const images = result.content.filter((c) => c.type === "image").length; treefmt-check> - const lines = output ? output.split("\n") : []; treefmt-check> - // Tail, not head: tracebacks and REPL results come last. treefmt-check> - const shown = options.expanded ? lines : lines.slice(-10); treefmt-check> - const color = context.isError ? "error" : "toolOutput"; treefmt-check> - let out = theme.fg("muted", "─── output ───"); treefmt-check> - if (lines.length > shown.length) { treefmt-check> - out += theme.fg( treefmt-check> - "muted", treefmt-check> - `\n... (${lines.length - shown.length} earlier lines, `, treefmt-check> - ) + keyHint("app.tools.expand", "to expand") + theme.fg("muted", ")"); treefmt-check> - } treefmt-check> - if (shown.length) { treefmt-check> - out += "\n" + shown.map((l) => theme.fg(color, l)).join("\n"); treefmt-check> - } treefmt-check> - if (images) out += theme.fg("muted", `\n[${images} image(s)]`); treefmt-check> - text.setText(out); treefmt-check> - return text; treefmt-check> - }, treefmt-check> + renderResult(result, options, theme, context) { treefmt-check> + const text = (context.lastComponent as Text | undefined) ?? treefmt-check> + new Text("", 0, 0); treefmt-check> + const output = result.content treefmt-check> + .filter((c) => c.type === "text") treefmt-check> + .map((c) => (c as { text: string }).text) treefmt-check> + .join("\n") treefmt-check> + .trimEnd(); treefmt-check> + const images = result.content.filter((c) => c.type === "image").length; treefmt-check> + const lines = output ? output.split("\n") : []; treefmt-check> + // Tail, not head: tracebacks and REPL results come last. treefmt-check> + const shown = options.expanded ? lines : lines.slice(-10); treefmt-check> + const color = context.isError ? "error" : "toolOutput"; treefmt-check> + let out = theme.fg("muted", "─── output ───"); treefmt-check> + if (lines.length > shown.length) { treefmt-check> + out += theme.fg( treefmt-check> + "muted", treefmt-check> + `\n... (${lines.length - shown.length} earlier lines, `, treefmt-check> + ) + keyHint("app.tools.expand", "to expand") + theme.fg("muted", ")"); treefmt-check> + } treefmt-check> + if (shown.length) { treefmt-check> + out += "\n" + shown.map((l) => theme.fg(color, l)).join("\n"); treefmt-check> + } treefmt-check> + if (images) out += theme.fg("muted", `\n[${images} image(s)]`); treefmt-check> + text.setText(out); treefmt-check> + return text; treefmt-check> + }, treefmt-check> treefmt-check> - async execute(_id, params, signal, _onUpdate, ctx) { treefmt-check> - kernel ??= new Kernel(python, ctx.cwd); treefmt-check> - const ac = new AbortController(); treefmt-check> - signal?.addEventListener("abort", () => ac.abort(), { once: true }); treefmt-check> - let timedOut = false; treefmt-check> - const timer = params.timeout treefmt-check> - ? setTimeout(() => { treefmt-check> - timedOut = true; treefmt-check> - ac.abort(); treefmt-check> - }, params.timeout * 1000) treefmt-check> - : undefined; treefmt-check> - const r = await kernel.exec(params.code, ac.signal).finally(() => treefmt-check> - clearTimeout(timer) treefmt-check> - ); treefmt-check> - // Throw like bash so pi ends the run as "aborted" and sends queued prompts. treefmt-check> - if (signal?.aborted) throw new Error("Command aborted"); treefmt-check> - if (timedOut && r.error?.startsWith("KeyboardInterrupt")) { treefmt-check> - r.error = treefmt-check> - `Timed out after ${params.timeout}s (cell interrupted, interpreter state kept)`; treefmt-check> - } treefmt-check> + async execute(_id, params, signal, _onUpdate, ctx) { treefmt-check> + kernel ??= new Kernel(python, ctx.cwd); treefmt-check> + const ac = new AbortController(); treefmt-check> + signal?.addEventListener("abort", () => ac.abort(), { once: true }); treefmt-check> + let timedOut = false; treefmt-check> + const timer = params.timeout treefmt-check> + ? setTimeout(() => { treefmt-check> + timedOut = true; treefmt-check> + ac.abort(); treefmt-check> + }, params.timeout * 1000) treefmt-check> + : undefined; treefmt-check> + const r = await kernel.exec(params.code, ac.signal).finally(() => treefmt-check> + clearTimeout(timer) treefmt-check> + ); treefmt-check> + // Throw like bash so pi ends the run as "aborted" and sends queued prompts. treefmt-check> + if (signal?.aborted) throw new Error("Command aborted"); treefmt-check> + if (timedOut && r.error?.startsWith("KeyboardInterrupt")) { treefmt-check> + r.error = treefmt-check> + `Timed out after ${params.timeout}s (cell interrupted, interpreter state kept)`; treefmt-check> + } treefmt-check> treefmt-check> - let text = r.stdout; treefmt-check> - if (r.stderr) { treefmt-check> - text += (text && !text.endsWith("\n") ? "\n" : "") + r.stderr; treefmt-check> - } treefmt-check> - if (r.result !== null) { treefmt-check> - text += (text && !text.endsWith("\n") ? "\n" : "") + r.result; treefmt-check> - } treefmt-check> - if (r.error) text += (text && !text.endsWith("\n") ? "\n" : "") + r.error; treefmt-check> - const t = truncateTail(text || (r.images.length ? "" : "(no output)")); treefmt-check> - if (t.truncated) { treefmt-check> - t.content = treefmt-check> - `[output truncated: showing last ${t.outputLines} of ${t.totalLines} lines]\n${t.content}`; treefmt-check> - } treefmt-check> + let text = r.stdout; treefmt-check> + if (r.stderr) { treefmt-check> + text += (text && !text.endsWith("\n") ? "\n" : "") + r.stderr; treefmt-check> + } treefmt-check> + if (r.result !== null) { treefmt-check> + text += (text && !text.endsWith("\n") ? "\n" : "") + r.result; treefmt-check> + } treefmt-check> + if (r.error) { treefmt-check> + text += (text && !text.endsWith("\n") ? "\n" : "") + r.error; treefmt-check> + } treefmt-check> + const t = truncateTail(text || (r.images.length ? "" : "(no output)")); treefmt-check> + if (t.truncated) { treefmt-check> + t.content = treefmt-check> + `[output truncated: showing last ${t.outputLines} of ${t.totalLines} lines]\n${t.content}`; treefmt-check> + } treefmt-check> treefmt-check> - const content: ({ type: "text"; text: string } | { treefmt-check> - type: "image"; treefmt-check> - data: string; treefmt-check> - mimeType: string; treefmt-check> - })[] = []; treefmt-check> - if (t.content) content.push({ type: "text", text: t.content }); treefmt-check> - for (const data of r.images) { treefmt-check> - content.push({ type: "image", data, mimeType: "image/png" }); treefmt-check> - } treefmt-check> - return { content, details: undefined, isError: r.error !== null }; treefmt-check> - }, treefmt-check> - }); treefmt-check> + const content: ({ type: "text"; text: string } | { treefmt-check> + type: "image"; treefmt-check> + data: string; treefmt-check> + mimeType: string; treefmt-check> + })[] = []; treefmt-check> + if (t.content) content.push({ type: "text", text: t.content }); treefmt-check> + for (const data of r.images) { treefmt-check> + content.push({ type: "image", data, mimeType: "image/png" }); treefmt-check> + } treefmt-check> + return { content, details: undefined, isError: r.error !== null }; treefmt-check> + }, treefmt-check> + }); treefmt-check> } error: Cannot build '/nix/store/yjliqcn9skfvq9g2iq86ccazzy64vcjl-treefmt-check.drv'. Reason: builder failed with exit code 1. Output paths: /nix/store/hffpfxrsah6g1grig5dhz4am0401ygv6-treefmt-check Last 25 log lines: > - const content: ({ type: "text"; text: string } | { > - type: "image"; > - data: string; > - mimeType: string; > - })[] = []; > - if (t.content) content.push({ type: "text", text: t.content }); > - for (const data of r.images) { > - content.push({ type: "image", data, mimeType: "image/png" }); > - } > - return { content, details: undefined, isError: r.error !== null }; > - }, > - }); > + const content: ({ type: "text"; text: string } | { > + type: "image"; > + data: string; > + mimeType: string; > + })[] = []; > + if (t.content) content.push({ type: "text", text: t.content }); > + for (const data of r.images) { > + content.push({ type: "image", data, mimeType: "image/png" }); > + } > + return { content, details: undefined, isError: r.error !== null }; > + }, > + }); > } For full logs, run: nix log /nix/store/yjliqcn9skfvq9g2iq86ccazzy64vcjl-treefmt-check.drv