diff options
| author | Paul Buetow <paul@buetow.org> | 2026-05-30 22:00:00 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-05-30 22:00:00 +0300 |
| commit | 222976aa236c5d59cbacb2b325e3344f92f6f152 (patch) | |
| tree | f4041b3fb2bac03eae57214deb884c4f3524d091 /pi | |
| parent | 5b0eb1cac2e43b709dd199b3df438ba2a23a38a0 (diff) | |
fix(reload-runtime): remove broken lastCtx.reload() call from tool
Tools receive ExtensionContext, which does not have a reload() method.
Only ExtensionCommandContext (command handlers) has reload().
The tool now always queues /reload-runtime as a follow-up command,
matching the upstream example pattern. This fixes:
lastCtx.reload is not a function
Diffstat (limited to 'pi')
| -rw-r--r-- | pi/agent/extensions/reload-runtime/index.ts | 25 | ||||
| -rw-r--r-- | pi/plans/gemtexter-bash-to-gawk.md | 49 |
2 files changed, 54 insertions, 20 deletions
diff --git a/pi/agent/extensions/reload-runtime/index.ts b/pi/agent/extensions/reload-runtime/index.ts index aceeddc..e2eec33 100644 --- a/pi/agent/extensions/reload-runtime/index.ts +++ b/pi/agent/extensions/reload-runtime/index.ts @@ -1,24 +1,19 @@ -import type { ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-agent"; +import type { ExtensionAPI } from "@mariozechner/pi-coding-agent"; import { Type } from "@sinclair/typebox"; export default function (pi: ExtensionAPI) { - // Capture ctx so the tool can call ctx.reload() directly, avoiding a - // follow-up user message that would re-trigger the AI and cause a reload loop. - let lastCtx: ExtensionContext | undefined; - - pi.on("session_start", async (_event, ctx) => { - lastCtx = ctx; - }); - + // Command entrypoint for reload. + // Treat reload as terminal for this handler. pi.registerCommand("reload-runtime", { description: "Reload extensions, skills, prompts, and themes", handler: async (_args, ctx) => { - lastCtx = ctx; await ctx.reload(); return; }, }); + // LLM-callable tool. Tools get ExtensionContext, so they cannot call ctx.reload() directly. + // Instead, queue a follow-up user command that executes the command above. pi.registerTool({ name: "reload_runtime", label: "Reload Runtime", @@ -26,16 +21,6 @@ export default function (pi: ExtensionAPI) { description: "Reload extensions, skills, prompts, and themes. Call this once after editing extension files. Do not call it again in the same turn.", parameters: Type.Object({}), async execute() { - if (lastCtx) { - // Direct reload via ctx avoids injecting a follow-up user message, - // which would start a new AI turn and risk a reload loop. - await lastCtx.reload(); - return { - content: [{ type: "text", text: "Runtime reloaded." }], - details: {}, - }; - } - // Fallback if ctx is not yet available (should not happen in practice). pi.sendUserMessage("/reload-runtime", { deliverAs: "followUp" }); return { content: [{ type: "text", text: "Queued /reload-runtime as a follow-up command." }], diff --git a/pi/plans/gemtexter-bash-to-gawk.md b/pi/plans/gemtexter-bash-to-gawk.md new file mode 100644 index 0000000..8a1fd26 --- /dev/null +++ b/pi/plans/gemtexter-bash-to-gawk.md @@ -0,0 +1,49 @@ +# Plan: Convert gemtexter from GNU Bash to GNU Awk + +## Overview + +Assess feasibility of porting gemtexter from GNU Bash to GNU Awk (gawk), considering the extensive use of bash-specific features. + +## Current State Analysis + +The gemtexter project (~1000 LOC) consists of: +- **Main script** (`gemtexter`) - CLI entry point, sourcing, argument parsing +- **10 library files** in `lib/` - source'd by main script +- **Key features**: namespaced functions, associative arrays, process substitution, background jobs, eval for templates, parallel generation + +## Feasibility Assessment: **MEDIUM-HIGH COMPLEXITY** + +### Awk-Can-Do ✅ +- All text processing (Gemtext → HTML/MD) +- File I/O and regex matching +- Associative arrays +- Functions and control flow +- Subprocess via `system()` / `| getline` + +### Awk-Cannot-Do ⚠️ +- **No process substitution** (`<(...)`) - critical for `while read < <(find ...)` +- **No background jobs** (`&`, `wait -n`) - parallelization requires rewrite +- **No source/require** - all code must be single file +- **No eval equivalent** - template blocks need redesign +- **No namespaced functions** - `module::func` becomes `module_func` +- **No `local` keyword** - variable scoping via function parameters +- **Different string manipulation** - bash `${var/pat/repl}` ≠ gawk + +## Task Plan + +1. **Audit all bash-specific constructs** - categorize what can/cannot map to gawk +2. **Design gawk architecture** - single-file vs multi-file approach, how to handle "sourcing" +3. **Prototype core conversion** - pick one library (e.g., `html.source.sh`) as proof of concept +4. **Handle process substitution rewrites** - rewrite `while read < <(find ...)` patterns +5. **Redesign template system** - replace bash `eval` blocks with gawk-compatible approach +6. **Migrate parallel generation** - convert `&`/`wait` to sequential or `xargs -P` +7. **Migrate remaining libraries** - one by one, keeping tests passing +8. **Integration testing** - verify all `--generate`, `--test`, `--publish` modes work + +## Effort Estimate + +- **Phase 1 (Feasibility)**: 1-2 tasks +- **Phase 2 (Core Migration)**: 3-5 tasks +- **Phase 3 (Testing/Polish)**: 2-3 tasks + +**Total**: ~10 tasks, significant rewrite effort. Awk is excellent at text processing but shell scripting is fundamentally different. |
