Commit graph

390 commits

Author SHA1 Message Date
Jeremy McSpadden
04ebe3f0a0 feat(extensions): add Ollama extension for first-class local LLM support (#3371)
Self-contained extension at src/resources/extensions/ollama/ that
auto-detects a running Ollama instance, discovers locally pulled models,
and registers them as a first-class provider with zero configuration.

Features:
- Auto-discovery of local models via /api/tags on session_start
- Capability detection (vision, reasoning, context window) for 40+ model families
- /ollama slash command with status, list, pull, remove, ps subcommands
- ollama_manage LLM-callable tool for agent-driven model operations
- Onboarding flow with auto-detect (no API key required)
- Non-blocking async probe — doesn't delay TUI paint
- Respects OLLAMA_HOST env var for non-default endpoints

Core changes (minimal):
- Add "ollama" to KnownProvider in pi-ai types
- Add "ollama" key resolution in env-api-keys.ts
- Add "ollama" default model in model-resolver.ts
- Add "Ollama (Local)" to onboarding wizard with probe flow
2026-04-01 08:37:31 -06:00
Jeremy McSpadden
e0d130e682 feat(extensions): wire up topological sort and unified registry filtering (#3152)
- Add extension-manifest.ts and extension-sort.ts to pi-coding-agent
  with manifest reading and Kahn's BFS topological sort algorithm
- Add extensionPathsTransform hook to DefaultResourceLoader that runs
  between path merging and loadExtensions() — enables pre-load
  filtering and reordering without modifying pi internals
- Wire GSD's buildResourceLoader() to provide a transform that:
  1. Filters ALL extensions (including community) through the GSD registry
  2. Sorts in topological dependency order via sortExtensionPaths()
- Mark discoverAndLoadExtensions() as @deprecated (dead code path)
- Add 16 tests covering manifest reading, dependency sorting, cycles,
  missing deps, and non-array deps

Previously, dependencies.extensions in manifests was decorative (sort
existed but was never called), and gsd extensions disable only worked
for bundled extensions. Community extensions in ~/.gsd/agent/extensions/
bypassed the registry entirely.
2026-03-31 11:54:48 -06:00
Tom Boucher
893c525578 fix(read-tool): clamp offset to file bounds instead of throwing (#3007) (#3042)
When an agent requests read(file, offset: 30) on a 13-line file, the
read tool threw "Offset 30 is beyond end of file" which propagated as
invalid JSON downstream during milestone completion. Now clamps the
offset to the last line and prepends a notice, allowing the agent to
continue with valid content.

Fixes both read.ts and hashline-read.ts variants.

Closes #3007

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 14:48:01 -06:00
Tom Boucher
3a1cedd7de fix(compaction): add chunked fallback when messages exceed model context window (#3038)
When a session grows beyond the context window of available models,
generateSummary() now detects the overflow and falls back to chunked
summarization: split messages into context-fitting chunks, summarize
the first chunk, then iteratively merge subsequent chunks using the
existing UPDATE_SUMMARIZATION_PROMPT path.

Closes #2932

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 14:47:41 -06:00
Tom Boucher
fad23944e7 fix: add Windows shell guard to remaining spawn sites (#3058)
Three spawn call sites were missing `shell: process.platform === "win32"`,
causing ENOENT/EINVAL errors on Windows where npm-installed tools are .cmd
batch scripts that require shell resolution:

- exec.ts: hardcoded `shell: false` -> platform-guarded
- lsp/index.ts: missing shell option on project-type command spawn
- lsp/lspmux.ts: missing shell option on lspmux binary spawn

Adds a structural regression test that scans all spawn sites invoking
user-facing binaries and asserts the Windows shell guard is present.

Closes #2854

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 14:44:20 -06:00
Tom Boucher
9dc6a6a97d fix: prevent LLM from confusing background task output with user input (#3069)
* fix: wrap custom messages with system notification prefix in LLM context

Background job completion notifications (delivered as custom messages via
sendMessage with deliverAs: "followUp") were converted to plain role: "user"
messages in convertToLlm(), making the LLM indistinguishable from actual
human input. This caused the agent to confuse background task output with
user messages, responding to job completions as if the user had typed them.

Wrap all custom messages with a clear system notification prefix that
includes the customType and an explicit instruction that the content is
an automated system event, not user input. This follows the same pattern
used by branchSummary and compactionSummary messages which already use
structured prefixes/suffixes.

Closes #3026

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: resolve TS import extension and type errors in messages test

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 14:42:56 -06:00
Tom Boucher
5f660bf3ce fix: recover from many-image dimension overflow by stripping older images (#3075)
When a session accumulates many images (screenshots, file reads), the
Anthropic API enforces a 2000px dimension limit for "many-image requests"
and returns a 400 error. Previously this error was not classified as
retryable, causing the session to get permanently stuck in an error loop
with no recovery path.

This adds automatic recovery: detect the specific "image dimensions exceed
max allowed size for many-image requests" error, strip older images from
the conversation history (keeping the 5 most recent), and auto-retry.
Also handles manual retry (continue/retry) by downsizing before retrying.

Closes #2874

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 14:40:35 -06:00
Tom Boucher
2f3ffbfc10 fix: repair YAML bullet lists in malformed tool-call JSON (#3090)
* fix: repair YAML bullet lists in malformed tool-call JSON (#2660)

When LLMs copy YAML template formatting into tool-call arguments, they
produce `"key": - item` instead of `"key": ["item"]`, causing JSON parse
errors that block milestone completion. Add a repairToolJson() utility
that detects and converts YAML-style bullet lists into JSON arrays before
parsing. Integrated into both the PartialMessageBuilder (claude-code-cli)
and the anthropic-shared streaming provider, with fallback in
parseStreamingJson for all other providers.

Closes #2660

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: use .js import extension in repair-tool-json test

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 14:37:09 -06:00
Tom Boucher
abd9be24e9 fix: align @gsd/native module type with compiled output (#3253)
* fix: align @gsd/native module type with compiled output (#2861)

The package declared "type": "module" and used "import"-only export
conditions, but the addon loader used import.meta.url which is
incompatible when the parent package enforces ESM resolution on
Node.js v24. Switch to "type": "commonjs" with "default" export
conditions and remove the import.meta.url/__dirname shim (CJS
provides both natively).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: restore dual CJS/ESM compat for native addon loader

The ESM-to-CJS conversion removed import.meta.url polyfills, but the CI
test loader (dist-redirect.mjs) transpiles this file to ESM via
ts.transpileModule — making __dirname and require unavailable at test time.

Add runtime typeof guards that use the CJS globals when available (compiled
output) and fall back to import.meta.url in ESM (test runner). Use
@ts-expect-error to suppress TS1470 for the import.meta branches that are
unreachable in the compiled CJS output.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: use indirect eval for import.meta.url to avoid CJS parse-time error

import.meta is a parse-time syntax error in CJS — typeof guards don't
help because Node.js rejects the syntax before executing any code.
Wrapping in new Function("return import.meta.url") hides the syntax
from the CJS parser while still working when executed as ESM (test runner).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: replace new Function(import.meta.url) with loader-injected CJS globals

import.meta is static syntax unavailable in new Function() and eval()
scopes, causing rtk-portability CI failures across all platforms.

Instead of trying to access import.meta.url indirectly, the test loader
(dist-redirect.mjs) now injects __dirname, __filename, and require as a
preamble when transpiling workspace packages to ESM. This lets native.ts
use __dirname/require directly in both CJS (production) and ESM (CI test)
contexts without any import.meta.url fallback.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 13:51:57 -06:00
Tom Boucher
2ea668ee09 fix: handle pause_turn stop reason to prevent 400 errors with native web search (#2869) (#3248)
Map pause_turn to "pauseTurn" instead of "stop" so the agent loop
continues when Anthropic's server pauses a long-running turn (e.g.
native web search hitting its iteration limit). Previously the
incomplete server_tool_use block was saved to history, causing a
400 invalid_request_error on the next API call.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 13:51:18 -06:00
Tom Boucher
a725fa2d9d fix: classify long-context entitlement 429 as quota_exhausted, not rate_limit (#2803) (#3257)
The "Extra usage is required for long context requests" error from
Anthropic is a billing gate, not a transient rate limit. Classify it as
quota_exhausted so the handler enters the fallback path instead of an
infinite backoff loop. When no cross-provider fallback exists, attempt a
[1m] to base model downgrade before stopping cleanly.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 13:50:36 -06:00
Tom Boucher
3d896eee8a fix: skip TUI render loop on non-TTY stdout to prevent CPU burn (#3095) (#3263)
When gsd is spawned as an RPC bridge child process, stdout is a pipe
(process.stdout.isTTY === undefined). The TUI render loop would run at
~4,600 renders/sec writing ANSI escape codes to the pipe, consuming
500%+ CPU per process while idle.

Add isTTY guard to Terminal interface, ProcessTerminal.start(), TUI.start(),
and requestRender() so the entire render pipeline is skipped on non-TTY stdout.
RemoteTerminal (browser-backed) correctly reports isTTY=true.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 13:49:55 -06:00
TÂCHES
efe61c2fcc wip: M005 daemon — orchestrator, event bridge, formatter, batcher improvements (#2929)
Saves in-progress daemon work from M005-m138xe that was sitting uncommitted.
Includes orchestrator expansion, event bridge/formatter enhancements,
message batcher tweaks, and discord bot additions.
2026-03-27 20:22:30 -06:00
github-actions[bot]
1783559610 release: v2.58.0 2026-03-28 02:14:33 +00:00
TÂCHES
8d0a81ff89 Merge pull request #2925 from gsd-build/fix/2923-double-startauto-race
fix(auto): guard startAuto() against concurrent invocation
2026-03-27 19:45:38 -06:00
github-actions[bot]
ab7961000e release: v2.57.0 2026-03-28 00:06:04 +00:00
TÂCHES
a2705218f7 Merge pull request #2890 from Matt-Aurora-Ventures/feat/zai-glm-models
feat(models): add GLM-5.1 to Z.AI provider
2026-03-27 17:38:48 -06:00
Lex Christopherson
eb2cfa580c fix: Fixed 3 bugs (launchd JSON parsing, login race condition, interact…
- "packages/daemon/src/launchd.ts"
- "packages/daemon/src/discord-bot.ts"
- "packages/daemon/src/launchd.test.ts"

GSD-Task: S07/T02
2026-03-27 17:17:40 -06:00
Matt Haynes
9b3c21f25a test(models): add GLM-5.1 custom model tests
Tests cover: provider registration, base URL + API type, reasoning +
context window specs, and non-collision with generated zai models.

Required by CI lint gate (require-tests.sh).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-27 16:48:11 -06:00
Lex Christopherson
0de87955d3 feat: Added 6 discord.js shard/error/warn event listeners for reconnect…
- "packages/daemon/src/discord-bot.ts"
- "packages/daemon/src/daemon.ts"
- "packages/daemon/src/daemon.test.ts"

GSD-Task: S06/T02
2026-03-27 16:20:10 -06:00
Lex Christopherson
14297845e9 test: Created launchd.ts with plist XML generation, install/uninstall/s…
- "packages/daemon/src/launchd.ts"
- "packages/daemon/src/launchd.test.ts"
- "packages/daemon/src/cli.ts"
- "packages/daemon/src/index.ts"

GSD-Task: S06/T01
2026-03-27 16:16:44 -06:00
Lex Christopherson
d1c948086e merge: Resolve conflicts with origin/main
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 15:56:48 -06:00
Lex Christopherson
898e797772 feat: Extended DaemonConfig with control_channel_id and orchestrator se…
- "packages/daemon/src/types.ts"
- "packages/daemon/src/config.ts"
- "packages/daemon/src/daemon.ts"
- "packages/daemon/src/discord-bot.ts"
- "packages/daemon/src/discord-bot.test.ts"
- "packages/daemon/src/index.ts"

GSD-Task: S05/T02
2026-03-27 15:46:58 -06:00
Lex Christopherson
bbba5f83b9 test: Built Orchestrator class with 5 LLM tool definitions, tool-use ag…
- "packages/daemon/src/orchestrator.ts"
- "packages/daemon/src/orchestrator.test.ts"
- "packages/daemon/package.json"

GSD-Task: S05/T01
2026-03-27 15:39:53 -06:00
github-actions[bot]
b5715c20bb release: v2.56.0 2026-03-27 21:29:07 +00:00
Lex Christopherson
6ef99ee727 test: Wired EventBridge into Daemon lifecycle with /gsd-verbose slash c…
- "packages/daemon/src/commands.ts"
- "packages/daemon/src/discord-bot.ts"
- "packages/daemon/src/daemon.ts"
- "packages/daemon/src/index.ts"
- "packages/daemon/src/discord-bot.test.ts"

GSD-Task: S04/T04
2026-03-27 15:17:53 -06:00
Lex Christopherson
f26ec3a55d test: Built EventBridge orchestrator wiring session events to Discord w…
- "packages/daemon/src/event-bridge.ts"
- "packages/daemon/src/event-bridge.test.ts"

GSD-Task: S04/T03
2026-03-27 15:11:52 -06:00
Lex Christopherson
05abf86912 test: Built rate-limit-aware MessageBatcher with timer/capacity flush,…
- "packages/daemon/src/message-batcher.ts"
- "packages/daemon/src/message-batcher.test.ts"

GSD-Task: S04/T02
2026-03-27 15:04:55 -06:00
Lex Christopherson
4c8bbca46f feat: Created pure-function event formatters (10 functions) mapping RPC…
- "packages/daemon/src/event-formatter.ts"
- "packages/daemon/src/verbosity.ts"
- "packages/daemon/src/event-formatter.test.ts"
- "packages/daemon/src/verbosity.test.ts"
- "packages/daemon/src/types.ts"
- "packages/daemon/src/config.ts"

GSD-Task: S04/T01
2026-03-27 15:01:19 -06:00
Matt Haynes
64f0a5e7b3 feat(models): add GLM-5.1 to Z.AI provider in custom models
GLM-5.1 is the latest Zhipu AI model with 204K context window and
131K max output tokens. It uses the Z.AI Coding Plan endpoint
(OpenAI-compatible) and supports reasoning via enable_thinking.

Not yet tracked by models.dev, so added to models.custom.ts alongside
existing alibaba-coding-plan entries. Merges additively with the
generated Z.AI provider (glm-5, glm-5-turbo, etc.).

Specs from https://docs.z.ai/devpack/using5.1

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-27 14:49:43 -06:00
github-actions[bot]
a6bb48e82d release: v2.55.0 2026-03-27 20:44:58 +00:00
Lex Christopherson
b5adaf2d9f test: Created commands.ts with slash command definitions and registrati…
- "packages/daemon/src/commands.ts"
- "packages/daemon/src/discord-bot.ts"
- "packages/daemon/src/discord-bot.test.ts"
- "packages/daemon/src/index.ts"

GSD-Task: S03/T03
2026-03-27 14:43:03 -06:00
Lex Christopherson
d13885a54e test: Built ChannelManager with category resolution, channel create/arc…
- "packages/daemon/src/channel-manager.ts"
- "packages/daemon/src/discord-bot.test.ts"

GSD-Task: S03/T02
2026-03-27 14:39:00 -06:00
Lex Christopherson
31af5ecfbd feat: Added discord.js v14, DiscordBot class with auth guard and lifecy…
- "packages/daemon/src/discord-bot.ts"
- "packages/daemon/src/discord-bot.test.ts"
- "packages/daemon/src/daemon.ts"
- "packages/daemon/src/index.ts"
- "packages/daemon/package.json"

GSD-Task: S03/T01
2026-03-27 14:33:36 -06:00
Lex Christopherson
7732558d04 test: Wired scanner and session manager into Daemon with scanProjects()…
- "packages/daemon/src/daemon.ts"
- "packages/daemon/src/index.ts"
- "packages/daemon/src/daemon.test.ts"

GSD-Task: S02/T03
2026-03-27 14:20:02 -06:00
Lex Christopherson
5910c6523e test: Built SessionManager with EventEmitter lifecycle events, Logger i…
- "packages/daemon/src/session-manager.ts"
- "packages/daemon/src/session-manager.test.ts"
- "packages/daemon/src/types.ts"
- "packages/daemon/package.json"

GSD-Task: S02/T02
2026-03-27 14:15:18 -06:00
Lex Christopherson
9af08f6480 test: Extended daemon types with session management interfaces and buil…
- "packages/daemon/src/types.ts"
- "packages/daemon/src/project-scanner.ts"
- "packages/daemon/src/project-scanner.test.ts"

GSD-Task: S02/T01
2026-03-27 14:08:04 -06:00
Lex Christopherson
2a0d63accd test: Built Daemon class with lifecycle management, CLI entry point wit…
- "packages/daemon/src/daemon.ts"
- "packages/daemon/src/cli.ts"
- "packages/daemon/src/daemon.test.ts"
- "packages/daemon/src/index.ts"

GSD-Task: S01/T03
2026-03-27 13:52:58 -06:00
Lex Christopherson
fa2bde5677 test: Implemented YAML config loader with validation/defaults and struc…
- "packages/daemon/src/config.ts"
- "packages/daemon/src/logger.ts"
- "packages/daemon/src/daemon.test.ts"

GSD-Task: S01/T02
2026-03-27 13:43:46 -06:00
Lex Christopherson
c37eb1a5c3 feat: Created packages/daemon workspace package with DaemonConfig/LogLe…
- "packages/daemon/package.json"
- "packages/daemon/tsconfig.json"
- "packages/daemon/src/types.ts"
- "packages/daemon/src/index.ts"

GSD-Task: S01/T01
2026-03-27 13:40:25 -06:00
mastertyko
c5907c3677 fix(interactive): fully remove providers from /providers (#2852)
* test(integration): suppress npm pack buffer overflows

* fix(interactive): fully remove providers from /providers
2026-03-27 09:53:35 -06:00
github-actions[bot]
97de0a6d94 release: v2.54.0 2026-03-27 14:54:34 +00:00
TÂCHES
a91b8bec34 feat: Headless Integration Hardening & Release (M002) (#2811)
* feat: Migrated headless orchestrator to use execution_complete events,…

- "src/headless.ts"
- "src/headless-ui.ts"
- "src/tests/headless-v2-migration.test.ts"

GSD-Task: S06/T02

* test: Wired pi-coding-agent to re-export JSONL utils from @gsd/rpc-clie…

- "packages/pi-coding-agent/src/modes/rpc/jsonl.ts"
- "packages/pi-coding-agent/package.json"
- "packages/rpc-client/src/index.ts"
- "packages/rpc-client/src/jsonl.ts"
- "packages/rpc-client/src/rpc-client.ts"
- "packages/rpc-client/src/rpc-types.ts"
- "packages/rpc-client/src/rpc-client.test.ts"
- "packages/rpc-client/package.json"

GSD-Task: S06/T03

* feat: Wire --resume flag to resolve session IDs via prefix matching and…

- "src/headless.ts"
- "dist/headless.js"

GSD-Task: S01/T01

* test: Added 5 e2e integration tests proving headless JSON batch, SIGINT…

- "src/tests/integration/e2e-headless.test.ts"

GSD-Task: S01/T02

* test: Updated @gsd/rpc-client and @gsd/mcp-server to 2.52.0 with publis…

- "packages/rpc-client/package.json"
- "packages/mcp-server/package.json"
- "packages/rpc-client/.npmignore"
- "packages/mcp-server/.npmignore"

GSD-Task: S02/T01

* chore: auto-commit after complete-milestone

GSD-Unit: M002-gzq23a

* fix: revert jsonl.ts to inline implementation — @gsd-build/rpc-client not available at source-level test time in CI

The re-export from @gsd-build/rpc-client fails in CI because tests run against
TypeScript source (--experimental-strip-types) before any build step. The npm
dependency resolves to node_modules/ which requires dist/ to exist. Reverting
to the original inline implementation eliminates the cross-package dependency
for source-level imports.
2026-03-26 23:33:22 -06:00
Lex Christopherson
98eb2ae802 fix: revert jsonl.ts to inline implementation — @gsd-build/rpc-client not available at source-level test time in CI
The re-export from @gsd-build/rpc-client fails in CI because tests run against
TypeScript source (--experimental-strip-types) before any build step. The npm
dependency resolves to node_modules/ which requires dist/ to exist. Reverting
to the original inline implementation eliminates the cross-package dependency
for source-level imports.
2026-03-26 23:20:53 -06:00
Lex Christopherson
2cc7653efb chore: auto-commit after complete-milestone
GSD-Unit: M002-gzq23a
2026-03-26 22:57:10 -06:00
Lex Christopherson
b22f5d5bd6 test: Updated @gsd/rpc-client and @gsd/mcp-server to 2.52.0 with publis…
- "packages/rpc-client/package.json"
- "packages/mcp-server/package.json"
- "packages/rpc-client/.npmignore"
- "packages/mcp-server/.npmignore"

GSD-Task: S02/T01
2026-03-26 22:13:27 -06:00
github-actions[bot]
112090706e release: v2.53.0 2026-03-27 02:50:02 +00:00
Lex Christopherson
bb6d64a5ba test: Wired pi-coding-agent to re-export JSONL utils from @gsd/rpc-clie…
- "packages/pi-coding-agent/src/modes/rpc/jsonl.ts"
- "packages/pi-coding-agent/package.json"
- "packages/rpc-client/src/index.ts"
- "packages/rpc-client/src/jsonl.ts"
- "packages/rpc-client/src/rpc-client.ts"
- "packages/rpc-client/src/rpc-types.ts"
- "packages/rpc-client/src/rpc-client.test.ts"
- "packages/rpc-client/package.json"

GSD-Task: S06/T03
2026-03-26 20:17:05 -06:00
github-actions[bot]
34bbee21bc release: v2.52.0 2026-03-27 00:07:48 +00:00
TÂCHES
1c2d7ab307 fix: add missing runtime stage name to Dockerfile (#2765)
* feat: Registered 6 MCP tools (gsd_execute, gsd_status, gsd_result, gsd_…

- "packages/mcp-server/src/server.ts"
- "packages/mcp-server/src/cli.ts"
- "packages/mcp-server/src/index.ts"
- "packages/rpc-client/dist/index.d.ts"

GSD-Task: S05/T02

* docs: Added 31 integration tests, build pipeline, and consumer README f…

- "packages/mcp-server/src/mcp-server.test.ts"
- "packages/mcp-server/README.md"
- "packages/mcp-server/dist/"

GSD-Task: S05/T03

* fix: add missing runtime stage name to Dockerfile

CI pipeline uses `docker build --target runtime` but the FROM line
lacked the `AS runtime` alias, causing the build to fail.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 17:52:45 -06:00