Skip to content

v0.7.0

Latest

Choose a tag to compare

@MichaelKinsy MichaelKinsy released this 05 Nov 19:12
· 40 commits to main since this release
Immutable release. Only release title and notes can be modified.
beb5644

PiG 0.7.0

image

PiG 0.7.0 is a fix, SDK and Pi-catch-up release. It follows Pi v1.5.0 and carries two commits from Pi's main branch that are ahead of that release (D231 and D233). It follows PiG 0.5.3. There was no 0.6.0 release, so the work that was planned for it ships here. Install it with go install github.com/MichaelKinsy/PiG/cmd/pig@latest or npm i -g @pi-in-go/pig.

PiG is a Go implementation of Pi, the reference. Pi's behavior is the contract, and every place PiG differs is a numbered divergence. PiG is not an official Pi project, and Pi's maintainers have not endorsed it. It was created by Michael Kinsy and originally developed at Hewlett Packard Enterprise.

This is a minor release because it adds a large part of the extension SDK surface (Common Lisp extensions, Pi's Type, createProvider, the extension runner and session runtime), moves the Bedrock provider to its own Go package, changes the Durable watch API and bumps stored formats. Read "Upgrading" before you update Go code or share a Durable store with an older build.

Thanks

This release has fixes that came straight from your reports and patches 🐷

  • @mblarsen reported #374, where a Node extension kept reading ctx.isIdle() as false after a run settled, which held back pi-intercom messages. Their fix is the one that landed, with their authorship.
  • @dorokuma asked for #384, a way for a subprocess extension to remove the blank rows a hidden thinking run leaves, found a second trigger path, and tested the result against their compact-ui port before the release. They are also credited on the fix for the crash a markdown transformer could cause while an answer streams.
  • @jihongwei reported #385, the embedded reflect.Type that made binaries about 6 MB larger when a reflection-heavy package such as protobuf was linked too, and sent #301 (MCP reconnect after a cancelled client cleanup) and #302 (extension entry append for embedding hosts).
  • @NicoSenerman reported #389, where pig install recorded a package path that startup could not resolve and the package's tools disappeared without a visible error.
  • @semiherdogan reported #395, where subagents of pi-open-agents failed to start, and traced it to the missing dist/cli.js.
  • @ShoichiTect reported #396 and #397, the session that stopped again after bg and the interrupted system call after fg, each with a paired Pi result.
  • @bharatvaj reported #402, where Option+Up did not remove a message from the steering queue in macOS Terminal.
  • @runningman84 reported #380, the llama.cpp returned HTTP 404 from /llama against llama-swap.
  • @balcsida reported #321 and #322 (SDK helpers and the edit override) sent #378, which scopes BuildModel's catalog lookup to the requested provider, and sent herdr-app #299, which makes PiG a known agent in the herdr desktop app with its own icon, name and agent menu entry (in herdr 0.1.12 and later).
  • @rafiksalama is credited on the fix that stops a Session whose Events nobody reads from blocking Send.
  • @SkrOYC asked for #308 and sent the Nix flake (#368).
  • @xoviat asked for #315, the OpenRouter :nitro and :floor variants.
  • @nyxiereal sent #388, which resolved the landing blockers of the parity snapshot cleanup that keeps only the snapshots of the active Pi pin.
  • @yxd-ym reported #299 and sent #300, so pig status no longer reports a shared extension name as an unhealthy duplicate.
  • @Neiko2002 reported #394, which made the bug report form require only "What happened".

Fixes for reported issues

  • #374. The Node runtime answered ctx.isIdle() from a cached value that changed only on events, while Pi reads it live. It now asks the host on each call, and tests in every SDK read it outside any event. Background callbacks such as pi-intercom's see a finished run as idle.
  • #380. /llama against llama-swap used to end in a bare llama.cpp returned HTTP 404 on load or unload, because llama-swap has no load or unload endpoint and loads a model when a request names it. PiG now recognises llama-swap and says to add it to models.json as an openai-completions provider and pick models with /model. A 404 from a real llama.cpp router keeps Pi's text (D212). The llama.cpp docs page has a llama-swap section.
  • #384. An extension can call pi.ownThinkingRuns(enabled) (OwnThinkingRuns in Go, own_thinking_runs in Rust and Python, own-thinking-runs in Lisp). While any extension owns thinking runs, a hidden run, or one that a Markdown transformer rewrote to empty text, leaves no stub row and no blank rows around it. It handles spacing only, so pair it with a transformer to hide the text. Without such an extension the message draws as Pi does (D214).
  • #385. The field metadata in durable/internal/ordered embedded reflect.Type anonymously, which made the linker keep every exported method of every reachable type. The field is named now, and a test fails if an anonymous one returns. A program that links protobuf next to PiG is about 6 MB smaller.
  • #389. pig install /abs/path records the path as you typed it. Before, it stored a path relative to the agent directory, which resolved to nothing when PIG_HOME was reached through another spelling (D215). A configured local Package whose directory is missing is a startup warning that names the pig remove command, and pig install --validate-only with no source checks every local-path entry and exits 1 when one is missing (D216). Entries written by an earlier version stay relative, so run pig install <absolute path> again for those.
  • #395. PiG pointed @earendil-works/pi-coding-agent at a shim file instead of a package root, so pi-open-agents looked for a dist/cli.js that was not there. The package now resolves to a root laid out like Pi's, with dist/index.js and a dist/cli.js that starts PiG. pi-agent-core, pi-tui and pi-ai got the same layout. A test now compares every Pi package PiG serves against Pi's layout.
  • #396. A suspended session that gets SIGCONT while its process group does not own the terminal (bg) no longer re-enters raw mode and draws into the shell. It stops again and waits for fg. Pi does the same as PiG did here, so this is a numbered divergence (D227).
  • #397. After Ctrl+Z, bg and fg, the session returns instead of ending with Error: interrupted system call, because raw-mode entry and exit retry an interrupted ioctl as Node's libuv does. A write to a terminal that went away now ends the session with exit 129 as Pi does, and any other terminal write error restores the terminal, records a crash and exits 1. Real-terminal stop, bg and fg tests now run on macOS.
  • #402. Terminal.app sends Option+Up as plain Up in its default profile, so PiG recalled history while the queued message stayed queued and still went out. In Terminal.app, plain Up with an empty editor and a queued message now restores the queued messages to the editor and clears the queue, and the hint under the queue names Up. In tmux, ssh and other terminals PiG shows one dim line, once per run, when Up recalls a copy of a queued message. Mapping Option+Up to \033[1;3A in Terminal's keyboard settings also works. Pi 1.5.0 behaves as PiG did before (D228).

Pi catch-up

  • Pi v1.5.0, including Pi 1.5.0's schema validation of tool arguments as plain JSON Schema. Type.Refine callbacks are no longer run on a tool's arguments, so check such constraints in the tool's execute() (D226).
  • D231. RPC mode acts on an extension's ctx.shutdown() while idle, for example from a timer, instead of waiting for the next command (Pi main 1708b4788, ahead of the pin).
  • D233. An MCP Streamable HTTP application/json reply over maxMessageBytes (default 16 MiB) is rejected with MCP JSON response exceeds N bytes, and an HTTP error body is read only up to its first 8 KiB (Pi main 4a8b60bc3, ahead of the pin).
  • Package changelogs. After a package update PiG shows the package's changelog entries under "Extension Updates", and a manifest may name its file with pi.changelogPath.
  • pi.exec() takes maxBuffer and reports truncated in every SDK, and keyText() and keyHint() format the user's keybindings in extension renderers.
  • Images are decoded and encoded the way Pi's Photon does, pixel for pixel on the oracle corpus, for PNG, JPEG, WebP, GIF, BMP and TIFF.
  • The Durable core follows Pi's continue submissions, maxTurns, afterRun hooks, deferred commits and telemetry spans.

Extension SDKs

  • Common Lisp extensions. pig extension init --lang lisp scaffolds an ASDF system, and PiG builds it into a cached SBCL image that runs isolated or packed beside other Lisp extensions. The Lisp SDK serves the extension API the Go, Rust and Python SDKs serve.
  • The Go, Rust and Python SDKs export Pi's Type (TypeBox 1.3.27), createProvider, createExtensionRuntime and ExtensionRunner, createAgentSessionRuntime, createAgentSessionServices, buildSessionContext, and TuiAltScreen.
  • The Go SDK has sdk.FindCutPoint, sdk.SessionEntryToContextMessages and sdk.EstimateTokens, and an edit-tool override keeps the model's legacy edit shapes.
  • examples/headless is a complete small embed with the session API, MCP servers and one provider. The Go SDK page lists the pig_strip_* build tags and what each saves.

Chord, Durable and Piglets

  • Chord v2 (chord/next, experimental) as in Pi: host, store, documents, links, plugins and HTTP components, plus chord.Watch.
  • Durable has continue submissions, WhenIdleReject, SubmitIn, MaxTurns, AfterRun hooks, BeforeProviderRequest, pi.live.runFailure and a windowed ConversationView.
  • A Piglet's tool scope bounds the Session tool registry (see Security), a Piglet Binary accepts overlay Piglets, and build.closed: true makes a Binary refuse --piglet, PIG_PIGLET_PATH, PIG_PIGLET_NAME and --system-prompt.
  • A Nix flake builds PiG from source (nix run github:MichaelKinsy/PiG), with a CI check on its vendor hash.
  • OpenRouter :nitro and :floor variants are listed beside every OpenRouter model and resolve by name (D199).
  • pig update can run a wrapper or another package manager through PI_SELF_UPDATE_COMMAND or the selfUpdateCommand setting.

Size and speed

Sizes and counts are from the release regression runs against the 0.6.0 release-branch build. Memory figures are the ones recorded in the changelog fragments, each from its own measurement.

  • The pig binary is 0.41% to 0.47% larger on the six release targets (linux/amd64 68,792,480 to 69,103,776 bytes, +0.45%).
  • The first interactive frame makes about 22% fewer allocations (30,354 to 23,668).
  • Extension conformance passes 5185 sub-tests with 0 failures and 29 skipped, and the 116 parity-perf cases all pass.
  • Resuming a 365 MB session peaked at 2 GB at startup and now peaks at about 130 MB. /fork and /clone of a 427 MB session peaked at 4.8 to 5.1 GB and now peak at about 280 MB. A 375 MB session resumed from inside PiG held 2.2 GB until exit and now holds about 100 MB.
  • A program that embeds PiG and links no Bedrock package is smaller (39.9 MB to 36.7 MB for examples/headless on linux/amd64, and 18.3 MB to 15.0 MB for a program that only imports ai).

Upgrading

Breaking changes for Go code and the SDKs (each has a before and after in the CHANGELOG).

  • ai: the Bedrock provider moved to ai/providers/bedrock (bedrock.NewBedrockProvider and the rest). Importing ai alone no longer links the AWS SDK.
  • chord, durable/session: the watch handle moved from Durable to Chord. Use chord.Watch with chord.NewWatch.
  • durable/harness: Conversation.Watch and Harness.ObserveConversation take a *ConversationWindow (pass nil for the defaults), WatchEvents, AgentEventStream and the agent event types are removed, and Harness.RetryTask is removed. A task cut off restartLimit times in a row now ends visibly.
  • Stored formats. pi.live is version 3, pi.tool is version 3 and pi.generation is version 2, and submission records may be continue. Older stores open through a migration, but a build that expects the older versions cannot read a store this version wrote.
  • Programs that embed the extension host call subprocess.EnableTuiAltScreens() and subprocess.EnableEditorViews(), and import coding/extension/host/lispcell for Lisp extensions. The pig command does all three.
  • Go SDK: HostHelpers.HighlightCode loses its markdown parameter.
  • Type.Refine callbacks no longer run (D226).
  • pig extension upgrade rewrites what has one safe form and lists the rest.

Security

PiG 0.4.0 through 0.5.3 applied a Piglet's tools lists to the model's active set only. A tool exposed as codemode or deferred stayed callable from codemode scripts, and tool_search could find and load it, although the Piglet did not list it. This release enforces the scope in the Session tool registry. A tool outside the scope is not registered, so it is not listed, active, callable from codemode or findable by tool_search, and no later setActiveTools call, registration or reload brings it back. A Piglet Binary or a run with pig --piglet gets the fix when you upgrade PiG and rebuild the Binary.

Full changelog

See CHANGELOG.md (0.7.0 section).