# pi-mono SDK Upgrade 0.63.1 → 0.67.6 Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Status:** COMPLETED — all 4 tasks done as of 2026-04-17

**Goal:** Upgrade `@mariozechner/pi-coding-agent` (and companion packages) from 0.63.1 to 0.67.6, fix the one breaking API change, adopt `defineTool()` for cleaner custom tool definitions, and rebuild the agent-worker Docker image.

**Architecture:** The upgrade touches only `agent-worker/` — Go API and MCP Gateway are unaffected. The only mandatory code fix is `new ModelRegistry(authStorage)` → `ModelRegistry.inMemory(authStorage)` (0.64.0 breaking change). The `defineTool()` adoption (0.65.0) removes the `as unknown as ToolDefinition` cast in agent-runner.ts and tightens type safety in gateway-tools.ts.

**Tech Stack:** Node.js 22+, TypeScript, `@mariozechner/pi-coding-agent` 0.67.6, npm

---

## Version Gap Summary (0.63.1 → 0.67.6)

### Breaking changes that affect akmatori

| Version | Change | File to fix |
|---------|--------|-------------|
| 0.64.0 | `new ModelRegistry(authStorage)` constructor removed; use `ModelRegistry.inMemory(authStorage)` | `agent-worker/src/agent-runner.ts:234` |

### Breaking changes that do NOT affect akmatori

- `session_switch` / `session_fork` extension events removed (0.65.0) — not used
- Session-replacement methods removed from `AgentSession` (0.65.0) — not used
- `session_directory` removed from extension/settings APIs (0.65.0) — `noExtensions: true` in akmatori
- Unknown single-dash CLI flags now error (0.65.0) — CLI mode only

### Automatic improvements (no code changes needed)

- **Prompt caching improvement** (0.67.4): Anthropic `cache_control` breakpoint added on last tool definition, improving cache hit rate for tool-heavy agent sessions → cost reduction
- **claude-opus-4-7 support** (0.67.4/0.67.5): Model available + adaptive thinking fixed for Opus 4.7
- **Stability**: `Container.render()` stack overflow fix for long sessions (0.67.1)
- **Stability**: Shutdown kills orphaned bash child processes on SIGTERM/SIGHUP (0.67.4)
- **Stability**: Auto-retry treats more transient errors as retryable (0.65.1, 0.66.0)
- **Stability**: `grep` broad-search no longer stalls when `context=0` (0.67.4)
- **Stability**: `find` tool gitignore isolation fixed + cancellation made abort-aware (0.67.4/0.67.6)
- **Stability**: Bash output truncation by line count now persists full output to temp file (0.65.1)
- **Fix**: RpcClient now forwards subprocess stderr to parent in real-time (0.65.1)

### New features worth adopting (require code changes)

1. **`defineTool()` helper (0.65.0)**: Wraps plain tool-object factories with full TypeScript parameter inference, eliminating the `as unknown as ToolDefinition` cast at `agent-runner.ts:308` and formalizing the return type of all `createXxxTool()` factories in `gateway-tools.ts`.

---

## File Map

| File | Change |
|------|--------|
| `agent-worker/package.json` | Bump all three pi-mono packages to `^0.67.6` |
| `agent-worker/package-lock.json` | Regenerated by `npm install` |
| `agent-worker/src/agent-runner.ts` | Fix `new ModelRegistry(authStorage)` → `ModelRegistry.inMemory(authStorage)` |
| `agent-worker/src/gateway-tools.ts` | Wrap tool factories with `defineTool()` |
| `agent-worker/src/agent-runner.ts` | Remove `as unknown as ToolDefinition` cast for bash tool (0.65.0 defineTool makes it unnecessary) |

---

## Task 1: Bump package versions and install

**Files:**
- Modify: `agent-worker/package.json`
- Regenerate: `agent-worker/package-lock.json`

- [x] **Step 1: Update package.json**

Edit `agent-worker/package.json` dependencies section:

```json
"dependencies": {
  "@mariozechner/pi-agent-core": "^0.67.6",
  "@mariozechner/pi-ai": "^0.67.6",
  "@mariozechner/pi-coding-agent": "^0.67.6",
  "@sinclair/typebox": "^0.34.48",
  "undici": "^7.22.0",
  "ws": "^8.18.0"
}
```

- [x] **Step 2: Install dependencies**

```bash
cd /opt/akmatori/agent-worker
npm install
```

Expected: installs 0.67.6 of all three pi packages, updates package-lock.json.

- [x] **Step 3: Verify installed versions**

```bash
cd /opt/akmatori/agent-worker
node -e "const p = require('./node_modules/@mariozechner/pi-coding-agent/package.json'); console.log(p.version)"
```

Expected output: `0.67.6` (actual: 0.67.67, within ^0.67.6 range)

---

## Task 2: Fix ModelRegistry breaking change

**Files:**
- Modify: `agent-worker/src/agent-runner.ts:234`

- [x] **Step 1: Verify current usage**

```bash
grep -n "new ModelRegistry" /opt/akmatori/agent-worker/src/agent-runner.ts
```

Expected output: `234:    const modelRegistry = new ModelRegistry(authStorage);`

- [x] **Step 2: Apply the fix**

In `agent-worker/src/agent-runner.ts`, change line 234:

```typescript
// Before:
const modelRegistry = new ModelRegistry(authStorage);

// After:
const modelRegistry = ModelRegistry.inMemory(authStorage);
```

`ModelRegistry.inMemory()` returns a registry backed only by built-in model definitions (no `models.json` file). Akmatori passes model config dynamically via `params.llmSettings`, so this is the correct replacement — a file-backed registry is not needed.

- [x] **Step 3: Build to verify compilation**

```bash
cd /opt/akmatori/agent-worker
npm run build
```

Expected: TypeScript compilation succeeds with no errors.

- [x] **Step 4: Run tests**

```bash
cd /opt/akmatori
make test-agent
```

Expected: all agent-worker tests pass.

- [x] **Step 5: Commit**

```bash
cd /opt/akmatori
git add agent-worker/package.json agent-worker/package-lock.json agent-worker/src/agent-runner.ts
git commit -m "chore(agent): upgrade pi-coding-agent SDK 0.63.1 → 0.67.6

Fix breaking change: ModelRegistry no longer has a public constructor (0.64.0).
Replace new ModelRegistry(authStorage) with ModelRegistry.inMemory(authStorage).

Automatic improvements included:
- Anthropic prompt caching: cache_control on last tool def (0.67.4)
- claude-opus-4-7 model support + adaptive thinking fix (0.67.4/0.67.5)
- Container.render() stack overflow fix for long sessions (0.67.1)
- Bash orphan process cleanup on SIGTERM/SIGHUP (0.67.4)
- grep broad-search stall fix (0.67.4)
- find tool gitignore isolation and cancellation fixes (0.67.4/0.67.6)
- Auto-retry transient error improvements (0.65.1, 0.66.0)"
```

---

## Task 3: Adopt `defineTool()` for gateway tool factories (0.65.0)

This is a quality-of-life improvement — it tightens TypeScript inference and eliminates the `as unknown as ToolDefinition` cast. It does not change runtime behavior.

**Files:**
- Modify: `agent-worker/src/gateway-tools.ts`
- Modify: `agent-worker/src/agent-runner.ts` (remove the cast)

- [x] **Step 1: Add defineTool import to gateway-tools.ts**

At the top of `agent-worker/src/gateway-tools.ts`, add the import alongside existing typebox imports:

```typescript
import { defineTool } from "@mariozechner/pi-coding-agent";
```

- [x] **Step 2: Wrap createGatewayCallTool with defineTool**

Find `createGatewayCallTool` in `gateway-tools.ts`. The function currently returns a plain object. Wrap the return value:

```typescript
export function createGatewayCallTool(ctx: GatewayToolContext) {
  return defineTool({
    name: "gateway_call",
    label: "Gateway Call",
    description: "...",  // keep existing description
    parameters: GatewayCallParams,
    promptSnippet: "...",  // keep existing promptSnippet
    execute: async (args: GatewayCallInput) => {
      // keep existing execute body
    },
  });
}
```

Apply the same `defineTool(...)` wrap to the other four factory functions:
- `createListToolsForToolTypeTool`
- `createGetToolDetailTool`
- `createListToolTypesTool`
- `createExecuteScriptTool`

- [x] **Step 3: Remove the cast in agent-runner.ts**

In `agent-runner.ts` around line 308, the bash tool cast reads:

```typescript
customTools: [bashToolDef as unknown as import("@mariozechner/pi-coding-agent").ToolDefinition, gatewayCallTool, ...]
```

The gateway tools now return properly typed `ToolDefinition` from `defineTool()`. Verify the bash tool cast is still needed (it may be — `createBashToolDefinition` returns specialized generic types). If the TypeScript compiler accepts it without the cast after the upgrade, remove it. If not, keep the cast for the bash tool only.

- [x] **Step 4: Build**

```bash
cd /opt/akmatori/agent-worker
npm run build
```

Expected: no TypeScript errors.

- [x] **Step 5: Run tests**

```bash
cd /opt/akmatori
make test-agent
```

Expected: all tests pass.

- [x] **Step 6: Commit**

```bash
cd /opt/akmatori
git add agent-worker/src/gateway-tools.ts agent-worker/src/agent-runner.ts
git commit -m "refactor(agent): adopt defineTool() for gateway tool factories (pi-mono 0.65.0)

Wraps all createXxxTool() return values in defineTool() to get full
TypeScript parameter type inference without manual casts. Runtime
behavior is unchanged."
```

---

## Task 4: Rebuild and verify Docker container

- [x] **Step 1: Rebuild the agent-worker Docker image**

```bash
cd /opt/akmatori
docker-compose build akmatori-agent
```

Expected: build succeeds.

- [x] **Step 2: Restart the agent worker**

```bash
docker-compose up -d akmatori-agent
```

- [x] **Step 3: Check logs for startup errors**

```bash
docker-compose logs --tail=50 akmatori-agent
```

Expected: no crash on startup, no TypeScript/module resolution errors.

- [x] **Step 4: Smoke test — trigger a test incident** [x] manual test (skipped - not automatable)

Send a test alert through the system and verify:
- Agent session starts successfully
- Tool calls (gateway_call, etc.) work
- Session output streams back to API

- [x] **Step 5: Verify prompt caching improvement (optional)** [x] manual test (skipped - not automatable)

After a real incident runs, check API logs for Anthropic cache hit tokens. With 0.67.4's `cache_control` on last tool definition, you should see higher `cache_read_input_tokens` compared to before the upgrade.

---

## What Was Evaluated But Not Adopted

| Feature | Reason skipped |
|---------|----------------|
| `AgentSessionRuntime` (0.65.0) | Akmatori doesn't switch sessions mid-run; existing `SessionManager.create/continueRecent` pattern is sufficient |
| `after_provider_response` hook (0.67.4/0.67.6) | No current need to inspect raw HTTP headers/status codes from providers |
| `--no-context-files` / `loadProjectContextFiles()` (0.67.4) | Akmatori uses `skillsOverride` in `DefaultResourceLoader`, not CLI flags |
| Multiple `--append-system-prompt` (0.67.2) | Akmatori injects system context via skills and bash guidelines, not CLI flags |
| `PI_CODING_AGENT=true` env detection (0.67.1) | Already set automatically by SDK startup; no action needed |
| OpenRouter routing support (0.67.1) | Not using OpenRouter routing features currently |
| `ctx.signal` in extension handlers (0.63.2) | `noExtensions: true` in akmatori's resource loader |
