Commit graph

64 commits

Author SHA1 Message Date
Jeremy
7ee1fa0c46 fix(pi-ai): remove Anthropic OAuth flow for TOS compliance
Delete the Anthropic OAuth module, remove it from the built-in provider
registry, strip the OAuth client branch from the Anthropic streaming
provider, and replace the daemon orchestrator's token refresh with a
simple ANTHROPIC_API_KEY requirement.

Anthropic access is now API key or local Claude Code CLI only.

Closes #3952
2026-04-10 17:33:34 -05:00
Jeremy
2ad315b9fb fix(gsd): wire ADR-005 infrastructure into live paths
Addresses Codex adversarial review findings — the ADR-005 registries
and filters were built but not connected to the actual model selection
and provider adapter paths.

Fix 1+2: Tool filtering applied after model selection
- selectAndApplyModel() now calls adjustToolSet() after pi.setModel()
- Incompatible tools are removed via pi.setActiveTools()
- adjust_tool_set hook fires to allow extension overrides
- Verbose output reports filtered tools with provider context

Fix 3: ProviderSwitchReport wired through all 6 provider adapters
- New transformMessagesWithReport() convenience wrapper creates report,
  passes it to transformMessages(), and logs non-empty reports to stderr
  when GSD_VERBOSE=1 or PI_VERBOSE=1
- All adapters updated: anthropic, google, openai-responses,
  openai-completions, mistral, bedrock
2026-04-10 12:49:49 -05:00
Jeremy
b1c0dafc70 feat(gsd): implement ADR-005 multi-model provider and tool strategy
Implements all 4 phases of ADR-005 (issue #2790):

Phase 1: Provider Capabilities Registry
- Declarative ProviderCapabilities interface and PROVIDER_CAPABILITIES
  registry covering all 12 API providers
- Consolidates scattered *-shared.ts knowledge into queryable registry
- Unknown providers get permissive defaults (backward compatible)

Phase 2: Tool Compatibility Metadata
- ToolCompatibility interface (producesImages, schemaFeatures, minCapabilityTier)
- compatibility field on ToolDefinition
- Tool compatibility registry with pre-populated built-in tools
- Auto-registration from registerTool() and MCP tool defaults

Phase 3: Tool-Compat Filter + ProviderSwitchReport
- ProviderSwitchReport tracks thinking blocks dropped/downgraded,
  tool call IDs remapped, synthetic results inserted, thought
  signatures dropped during cross-provider message transformation
- isToolCompatibleWithProvider(), filterToolsForProvider(), adjustToolSet()
  functions in model router
- filteredTools field on RoutingDecision
- Verbose output for filtered tools in auto-model-selection

Phase 4: adjustToolSet Extension Hook
- AdjustToolSetEvent and AdjustToolSetResult interfaces
- emitAdjustToolSet() on ExtensionAPI and ExtensionRuntime
- Default no-op handler in register-hooks.ts

Includes 47 new tests (20 provider caps + 10 switch report + 17 tool compat)

Closes #2790
2026-04-10 12:33:40 -05:00
mastertyko
ebf5ca398a fix(pi-ai): restore event stream factory export 2026-04-09 13:03:27 +02:00
mastertyko
304b1bf329 fix(pi-ai): recover XML parameters trapped in JSON strings 2026-04-08 17:43:28 +02:00
Jeremy
4ba2d5a219 feat(ollama): native /api/chat provider with full option exposure
Replace the OpenAI-compat shim with a native Ollama /api/chat streaming
provider that exposes all commonly-used Ollama options and surfaces
inference performance metrics.

Key changes:
- Native NDJSON streaming from /api/chat (no more OpenAI shim)
- Known models send num_ctx from capability table; unknown models defer
  to Ollama's default to avoid OOM on constrained hosts
- Exposes: temperature, top_p, top_k, repeat_penalty, seed, num_gpu,
  keep_alive, num_predict via per-model providerOptions
- Extracts <think>...</think> blocks for reasoning models (deepseek-r1, qwq)
- Surfaces InferenceMetrics (tokens/sec, durations) on AssistantMessage
- Adds remove and show actions to ollama_manage LLM tool
- Adds "ollama-chat" to KnownApi, providerOptions to Model<TApi>
- NDJSON parser uses strict mode for chat (fails on malformed frames)
- Mixed content+tool_call chunks handled independently

Closes #3544
2026-04-05 09:01:40 -05:00
Tibsfox
920fed7122 fix(pi-ai): extend repairToolJson to handle XML tags and truncated numbers
The existing repairToolJson only handles YAML bullet lists (#2660).
Two additional malformation patterns from smaller models now cause
tool call failures and stuck retry loops:

1. XML parameter tags mixed into JSON values (#3403):
   LLMs (especially Haiku-class) sometimes emit hybrid XML/JSON
   syntax like <parameter name="X">value</parameter> inside
   JSON string values. Add stripXmlParameterTags() to remove
   the tags while preserving content.

2. Truncated numeric values (#3464):
   Smaller models emit incomplete numbers like "exitCode": -,
   or "durationMs": , when values are cut off mid-generation.
   Add repairTruncatedNumbers() to replace these with 0.

Both repairs run before the existing YAML bullet repair phase.
The AJV validation layer (coerceTypes: true) then handles any
remaining string-to-number coercion.

Adds 13 new tests covering detection and repair for both patterns.

Closes #3464, closes #3403, addresses #3369
2026-04-04 03:59:55 -07:00
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
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
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
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
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
Jeremy McSpadden
f8814f5a15 refactor(pi-ai): replace model-ID pattern matching with capability metadata (#2548)
* refactor(pi-ai): replace model-ID pattern matching with capability metadata

Add ModelCapabilities to Model<TApi> and a CAPABILITY_PATCHES mechanism
so call sites read model.capabilities fields instead of parsing model IDs
or hardcoding provider names.

- types.ts: add ModelCapabilities interface (supportsXhigh, requiresToolCallId,
  supportsServiceTier, charsPerToken) and capabilities?: ModelCapabilities to
  Model<TApi>
- models.ts: add CAPABILITY_PATCHES table applied at registry init; patches
  declare GPT-5.x and Opus 4.6 capabilities once instead of repeating ID
  checks at every call site; supportsXhigh() now reads capabilities only
- service-tier.ts: extract SERVICE_TIER_MODEL_PREFIXES constant so the gating
  list has a single named home; add path comment pointing to issue #2546 for
  the full capability-driven follow-up

No behaviour change. New models and providers can declare capabilities in
their model definitions without touching function logic.

Closes #2546

* fix(pi-ai): apply capability patches to custom/discovered/extension models

Models constructed outside the static pi-ai registry (custom models
from models.json, extension-registered models, discovered models)
bypassed CAPABILITY_PATCHES — causing supportsXhigh() to silently
return false for GPT-5.x or Opus 4.6 variants registered through
those paths.

Export applyCapabilityPatches() from pi-ai and call it in ModelRegistry
after model assembly in all three construction paths: loadModels(),
applyProviderConfig(), and discoverModels().

Add regression tests covering patching, precedence, idempotency,
and synthetic models that mimic the custom/extension path.

Closes #2546
2026-03-26 16:38:29 -06:00
Jeremy McSpadden
f8c6ab0c54 chore: consolidate docs, remove stale artifacts, and repo hygiene (#2665)
* fix(vscode): add extensionKind and error handler for Remote SSH support

* fix(vscode): reject failed RPC startup

* docs: consolidate docs, remove stale artifacts, and repo hygiene

- Remove docs-internal/ (duplicate of docs/); update pr-risk-check.mjs path
- Sync 9 diverged files to latest content (commands, config, troubleshooting, etc.)
- Fix pi --web → gsd --web naming in docs/README.md
- Copy FRONTIER-TECHNIQUES.md and ADR-004 to docs/ before removal
- Delete orphaned PR screenshot folders (pr-876/, pr-1530/) — unreferenced
- Remove committed pnpm-lock.yaml files (project uses npm)
- Move PLAN.md → .plans/doctor-cleanup-consolidation.md
- Move web/left-native-tui-main-session-plan.md → .plans/
- Delete .DS_Store and vscode-extension/dist/ from disk

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 09:13:41 -06:00
mastertyko
43b1de6d59 fix: signal malformed tool arguments in toolcall_end event (#2647)
When the API stream is truncated mid-tool-call, PartialMessageBuilder
emits a toolcall_end event with { _raw: "<broken json>" } in the
arguments — but the event looks identical to a healthy tool completion.
Downstream consumers (error classifiers, tool handlers, activity log)
have no way to distinguish a truncated call from a completed one.

Add a malformedArguments: boolean flag to the toolcall_end event variant
in AssistantMessageEvent. The flag is set to true only in the JSON parse
catch path, so existing consumers (which do not check for it) are
unaffected. New consumers like classifyProviderError can use it to
handle truncated tool calls appropriately.

Closes #2574
2026-03-26 08:15:16 -06:00
TÂCHES
19addd2aa5 Merge pull request #2168 from frizynn/fix/ai-providers-memory-leaks
fix(ai): resolve WebSocket listener leaks and bound session cache
2026-03-25 22:15:32 -06:00
Tom Boucher
6793489b78 fix(pi-ai): restore alibaba-coding-plan provider via models.custom.ts (#2350)
The alibaba-coding-plan provider (8 models) was silently dropped when
models.generated.ts was regenerated from models.dev in PR #2118. This
provider uses a proprietary DashScope endpoint not tracked by models.dev,
so regeneration removes it every time.

Add models.custom.ts for manually-maintained providers that don't exist
in models.dev. The model registry (models.ts) now merges both generated
and custom models at startup. Custom entries are additive and never
overwrite generated ones.

Restores: qwen3.5-plus, qwen3-max-2026-01-23, qwen3-coder-next,
qwen3-coder-plus, MiniMax-M2.5, glm-5, glm-4.7, kimi-k2.5

Fixes #2339

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 07:19:27 -06:00
frizynn
498a4b5310 fix(ai): resolve WebSocket listener leaks and bound session cache
Fix two memory leaks in the OpenAI Codex Responses WebSocket code:

1. parseWebSocket() onMessage handler: The fire-and-forget async IIFE
   could error after the await on decodeWebSocketData(), swallowing the
   error and leaving all four event listeners attached to the socket
   indefinitely. Wrap the entire handler body in try/catch, signal the
   error to the generator loop via `failed`/`done`, and call cleanup()
   to remove listeners immediately. JSON SyntaxErrors are treated as
   non-fatal (malformed message skipped).

2. websocketSessionCache: The Map grows without bound when many distinct
   session IDs are used over the lifetime of a process. Add a
   MAX_WEBSOCKET_CACHE_SIZE (10) constant and evict the oldest entry
   (first key in insertion order) before inserting a new one, closing
   the evicted socket and clearing its idle timer.

Also extract the duplicated removeEventListener calls in parseWebSocket
into a shared cleanup() helper used by both the onMessage error path
and the finally block.
2026-03-22 22:30:11 -03:00
Derek Pearson
5ecf047553 fix(pi-ai): correct Copilot context window and output token limits (#2118)
* fix(gsd extension): detect initialized projects in health widget

Use .gsd presence plus project-state detection for the health widget so bootstrapped projects no longer appear as unloaded before metrics exist.

* fix(gsd extension): detect initialized projects in health widget

Use .gsd presence plus project-state detection for the health widget so bootstrapped projects no longer appear as unloaded before metrics exist.

* fix(pi-ai): correct Copilot context window and output token limits

- Remove github-copilot from 1M contextWindow override in generate-models.ts
- Add runtime fetching of model limits from Copilot /models API
- Apply fetched limits in modifyModels and refreshToken flows
- Regenerate models.generated.ts with corrected values
- Fix models.ts type constraints for providers not in MODELS

Fixes #2115

* fix(pi-ai): address QA round 1

- Use strict type/bounds checks for API limit values (QA-R1-001/005)
- Add caller-level try/catch in refreshToken for defense-in-depth (QA-R1-009)

* fix(pi-coding-agent): refresh model registry after OAuth token refresh

ModelRegistry.modifyModels() only ran at load time, so model limits
fetched during token refresh were persisted to auth.json but never
applied to the in-memory model objects. Users saw stale contextWindow
values (e.g., 144K from models.dev instead of 200K from the Copilot API).

Add credential change notification to AuthStorage: after a successful
OAuth token refresh, listeners are notified via queueMicrotask. The
ModelRegistry now registers a listener at construction that triggers
a full model reload, picking up the new limits from modifyModels().
2026-03-22 17:04:16 -06:00
Andrew
d93956ba4e feat(web): browser-based web interface (#1717)
* chore(M003/S01): auto-commit after plan-slice

* chore(M003/S01/T02): auto-commit after execute-task

* chore(M003/S01/T03): auto-commit after execute-task

* docs: queue M004 — web mode documentation and CI/CD integration

* chore(M003/S01/T04): auto-commit after execute-task

* chore(M003/S01): auto-commit after complete-slice

* chore(M003/S01): auto-commit after reassess-roadmap

* chore: production polish — real logo, remove scaffold remnants

- Replace placeholder 'G' box in header with real GSD logo icon SVG (currentColor, theme-aware)
- Delete 5 dead placeholder files (placeholder-logo.svg/png, placeholder-user.jpg, placeholder.jpg, placeholder.svg)
- Remove v0.app generator tag from layout metadata
- Remove unused @vercel/analytics dependency

* chore(M003/S02): auto-commit after research-slice

* chore(Q1): auto-commit after quick-task

* fix: remove duplicate parse cache block causing web mode boot failure

The 'Parse Cache' section in files.ts was duplicated (merge artifact),
causing 'Identifier CACHE_MAX has already been declared' when Node's
--experimental-strip-types loaded the file. This made /api/boot return
500, which caused waitForBootReady to time out and web mode launch to
fail with 'boot-ready:http 500'.

Removed the second (older) duplicate block, keeping the first one which
includes the improved mid-sample cache key.

* docs: add quick task summary and update STATE.md

* fix: replace sidebar icon+text with full logo image

Swap the inline SVG G-mark icon and 'GSD 2' text span in the app shell
header with an <img> referencing /logo-white.svg (the full GSD wordmark).
Removes the redundant text label. Sized at h-4 (16px) to fit the header.

* docs(S02): add slice plan

* chore: update state for S02 execution

* chore(M003/S02/T01): auto-commit after execute-task

* chore(M003/S02/T02): auto-commit after execute-task

* chore(M003/S02/T03): auto-commit after execute-task

* chore(M003/S02): auto-commit after complete-slice

* chore(M003/S02): auto-commit after reassess-roadmap

* chore(M003/S03): auto-commit after research-slice

* docs(S03): add slice plan

* chore(M003/S03/T01): auto-commit after execute-task

* chore(M003/S03/T02): auto-commit after execute-task

* chore(M003/S03/T03): auto-commit after execute-task

* chore(M003/S03): auto-commit after complete-slice

* chore(M003/S03): auto-commit after reassess-roadmap

* chore(M003/S04): auto-commit after research-slice

* docs(S04): add slice plan

* chore(M003/S04/T01): auto-commit after execute-task

* chore(M003/S04/T02): auto-commit after execute-task

* chore(M003/S04/T03): auto-commit after execute-task

* chore(M003/S04): auto-commit after complete-slice

* chore(M003/S04): auto-commit after reassess-roadmap

* chore(M003/S05): auto-commit after research-slice

* docs(S05): add slice plan

* chore(M003/S05/T01): auto-commit after execute-task

* chore(M003/S05/T02): auto-commit after execute-task

* chore(M003/S05): auto-commit after complete-slice

* chore(M003/S05): auto-commit after reassess-roadmap

* chore(M003/S06): auto-commit after research-slice

* docs: queue M005

* docs(S06): add slice plan

* chore(M003/S06/T01): auto-commit after execute-task

* chore(M003/S06/T02): auto-commit after execute-task

* chore(M003/S06): auto-commit after complete-slice

* chore(M003/S06): auto-commit after reassess-roadmap

* chore(M003/S07): auto-commit after research-slice

* docs(S07): add slice plan

* chore: update STATE.md for S07 execution

* chore(M003/S07/T01): auto-commit after execute-task

* chore(M003/S07/T02): auto-commit after execute-task

* chore(M003/S07/T03): auto-commit after execute-task

* chore(M003): record integration branch

* chore(M003/S07/T04): auto-commit after execute-task

* chore(M003/S07): auto-commit after complete-slice

* chore(M003/S07): auto-commit after reassess-roadmap

* chore(M003/S08): auto-commit after research-slice

* docs(S08): add slice plan

* chore(M003/S08/T01): auto-commit after execute-task

* chore(M003/S08/T02): auto-commit after execute-task

* chore(M003/S08): auto-commit after complete-slice

* chore(M003/S08): auto-commit after reassess-roadmap

* chore(M003/S09): auto-commit after research-slice

* docs(S09): add slice plan

* chore(M003/S09/T01): auto-commit after execute-task

* chore(M003/S09/T02): auto-commit after execute-task

* chore(M003/S09): auto-commit after complete-slice

* chore(M003): auto-commit after complete-milestone

* chore(M004): record integration branch

* chore: untrack .gsd/ runtime files from git index

* chore(M004): auto-commit after research-milestone

* feat(M006): multi-project workspace

- Bridge registry replacing singleton (Map<string, BridgeService> keyed by project path)
- resolveProjectCwd(request) for ?project= query param with env-var fallback
- All 26 API routes and 16 services threaded with project context
- Project discovery service scanning one directory level with smart detection
- /api/projects and /api/preferences routes
- ProjectStoreManager with per-project SSE lifecycle isolation
- Projects NavRail tab with kind badges and signal chips
- Onboarding dev root step (position 3, skippable)
- Context-aware launch detection (resolveContextAwareCwd)
- BootProjectInitializer for auto-registering boot project
- 25 new contract tests (8 bridge, 10 discovery, 7 launch)
- 1222 tests pass, both builds green

Squash-merged from milestone/M006 work on gsd/quick branch.
Includes M004 and M005 milestone artifacts.

* feat: add dev root setup in Projects view and Settings panel

- Projects view empty state now has inline dev root input with
  suggestion chips instead of just a text message
- Settings gear → Workspace tab shows dev root configuration
- /gsd prefs command surface includes dev root section at top
- PUT /api/preferences now merges with existing prefs (read-modify-write)
  instead of overwriting — fixes potential data loss of lastActiveProject
- Fixed pre-existing type issue: sectionLabel/sectionIcon Records use
  Partial<Record> to handle gsd-* sections that aren't in the map

* feat: native folder picker for dev root selection

- New /api/browse-directories?path= endpoint returns directory listings
  from the server filesystem (directories only, excludes dotfiles/node_modules)
- FolderPickerDialog component with directory browser: navigate folders,
  go up to parent, select current folder
- Projects view empty state shows 'Browse for Folder' button opening the picker
- Settings Workspace tab shows current path with 'Change' button opening picker
- Replaces text input approach — no more typing paths manually

* fix: move Projects icon to bottom of NavRail, above Git

Projects is a workspace-level navigation action, not a primary view.
Placing it in the bottom section alongside Git and Settings keeps
the top section focused on content views.

* feat: multi-project-aware exit dialog

When multiple projects are open, the exit button shows two options:
- Close current project (disconnects it, switches to another)
- Stop server (shuts down all projects and closes the tab)

With only one project open, shows the original simple 'Stop server' dialog.

Also adds closeProject(), getProjectCount(), and getActiveProjectPaths()
to ProjectStoreManager.

* feat: intercept browser tab close with confirmation and auto-shutdown

beforeunload triggers the browser's native 'Leave site?' confirmation
dialog when the user tries to close the tab. If they confirm, pagehide
fires sendBeacon to /api/shutdown, cleanly stopping all GSD instances.

* feat: remove session card from dashboard, fix beforeunload

- Removed the session card (model, cost, tokens, elapsed, auto mode,
  live tool/streaming indicators) from the dashboard right column
- Dashboard current slice section now takes full width
- Removed beforeunload handler (tab close silently shuts down via
  pagehide + sendBeacon instead of showing native browser dialog)
- Updated web-state-surfaces-contract test: removed assertion for
  activeToolExecution/streamingAssistantText in dashboard
- 1220/1221 tests pass (1 flaky context-store unrelated to changes)

* feat: show loading dialog when switching to a new project

When clicking a project that doesn't have a bridge instance yet,
a shadcn Dialog with a spinner and 'Opening [project]' message
appears instead of navigating to the dashboard with skeleton cards.
The dialog waits for the store's bootStatus to become 'ready' or
'error' (or 30s timeout) before navigating to the dashboard.

Clicking the already-active project navigates directly.

* feat: restore theme toggle and light/dark CSS from M005

M005's theme work was lost during the M006 squash merge (different
branch base). This restores:

- ThemeProvider in layout.tsx with class-based theming and FOIT prevention
- NavRail theme toggle cycling system → light → dark (Monitor/Sun/Moon icons)
- Light-mode :root CSS variables (monochrome oklch, inverted lightness)
- Dark .dark section with custom tokens (--success, --warning, --info,
  --terminal, --terminal-foreground, --code-line-number)
- suppressHydrationWarning on <html> for next-themes compatibility

* fix: switch logo between black/white variants based on theme

Uses paired dark:/hidden Tailwind classes — zero JS cost, no flash.

* chore: untrack .gsd/ runtime files from git index

* chore(Q2): auto-commit after quick-task

* feat(web): resizable milestone sidebar + rename tab title to GSD

- Add drag-to-resize handle on left edge of milestone sidebar
  (col-resize, 180-480px range, same pattern as terminal resize)
- Change document.title suffix from 'GSD 2' to 'GSD'
- Remove border-l from MilestoneExplorer (drag handle provides separation)

* docs: quick task 2 summary and state update

* feat: spawn GSD instance in right-side terminal, rename browser tab to GSD

- Add command option to PTY manager to spawn pi instead of default shell
- Thread command param through terminal API routes and ShellTerminal component
- DualTerminal right pane now launches a separate pi (GSD) instance
- Update header label to 'Right: Interactive GSD'
- Set browser tab title to 'GSD' instead of project folder name

* fix: use distinct default session ID for GSD terminal to avoid reusing stale zsh session

* fix: make shell terminal respect light/dark theme

- Add light xterm theme alongside existing dark theme
- Detect theme via next-themes useTheme and pass isDark to terminal instances
- Dynamically update xterm theme when user switches themes
- Replace all hardcoded dark bg colors (#0a0a0a, #0c0c0c, zinc-*) with
  theme-aware classes (bg-terminal, text-muted-foreground, etc.)

* feat: add loading spinner while terminal session initializes

* feat: replace left-side AutoTerminal with real GSD terminal instance

- Remove custom AutoTerminal React component
- Left side now runs a real pi terminal (sessionPrefix=gsd-main)
- Right side uses sessionPrefix=gsd-interactive for isolation
- Add sessionPrefix prop to ShellTerminal for distinct session IDs
- Update header labels: Left: Primary GSD | Right: Interactive GSD

* feat: auto-select STATE.md on files view initial load

* feat: pre-initialize dual terminal PTY sessions on boot

Keep DualTerminal always mounted (hidden when not active) so PTY
sessions spawn as soon as the bridge connects. Terminals are ready
immediately when the user switches to the power view.

* fix: move STATE.md auto-select effect after handleSelectFile declaration

Fixes TDZ ReferenceError — the useEffect was referencing handleSelectFile
before its useCallback declaration.

* chore(M006): record integration branch

* Squashed commit of the following:

commit e3f495a224f53e954798b6f96a59806db43bfdb0
Author: snowdamiz <yurlovandrew@gmail.com>
Date:   Tue Mar 17 16:12:50 2026 -0400

    chore: auto-commit before milestone merge

commit d9a0193c9c54fafcaff6bc0de7c169936f41b2df
Author: snowdamiz <yurlovandrew@gmail.com>
Date:   Tue Mar 17 08:35:53 2026 -0400

    chore: auto-commit before milestone merge

commit 010430059ca50c6b773ee4480e42d2c54a1c0b75
Author: snowdamiz <yurlovandrew@gmail.com>
Date:   Tue Mar 17 04:57:49 2026 -0400

    chore(M006): record integration branch

commit a6f6d0294c90a253585571a5a9615c7f3e41e7ea
Author: snowdamiz <yurlovandrew@gmail.com>
Date:   Tue Mar 17 04:57:36 2026 -0400

    docs: queue M006 — Multi-project workspace

commit b2dd57423835d132f6d3963abbb2bfc799e64100
Author: snowdamiz <yurlovandrew@gmail.com>
Date:   Tue Mar 17 03:43:52 2026 -0400

    chore(M005): record integration branch

# Conflicts:
#	.gsd/DECISIONS.md
#	.gsd/PROJECT.md
#	.gsd/REQUIREMENTS.md
#	.gsd/milestones/M006/M006-META.json
#	src/web/recovery-diagnostics-service.ts

* chore(M006): record integration branch

* feat(M006): Multi-Project Workspace

Completed slices:
- S01: Bridge registry and project-scoped API surface
- S02: Project discovery, Projects view, and store switching
- S03: Onboarding dev root step, context-aware launch, and final assembly

Branch: milestone/M006

* refactor(visualizer): redesign visualizer-view layout and tab structure

* docs(M007): context, requirements, and roadmap

* chore(M007): record integration branch

* docs(M007): rewrite roadmap and all slice plans to new template format

* chore(M007/S01/T01): auto-commit after execute-task

* chore(M007/S01/T02): auto-commit after execute-task

* chore(M007/S01): auto-commit after complete-slice

* chore(M007/S01): auto-commit after reassess-roadmap

* chore(M007/S02/T01): auto-commit after execute-task

* chore(M007/S02/T02): auto-commit after execute-task

* chore(M007/S02/T03): auto-commit after execute-task

* chore(M007/S02): auto-commit after complete-slice

* chore(M007/S02): auto-commit after reassess-roadmap

* chore(M007/S03/T01): auto-commit after execute-task

* chore(M007/S03/T02): auto-commit after execute-task

* chore(M007/S03): auto-commit after complete-slice

* chore(M007/S03): auto-commit after reassess-roadmap

* chore(M007/S04/T01): auto-commit after execute-task

* chore(M007/S04/T02): auto-commit after execute-task

* chore(M007/S04/T03): auto-commit after execute-task

* chore(M007/S04): auto-commit after complete-slice

* chore(M007): auto-commit after complete-milestone

* feat(M007): Chat Mode — Consumer-Grade GSD Interface

Completed slices:
- S01: PTY output parser and chat message model
- S02: Chat Mode view — main pane
- S03: TUI prompt intercept UI
- S04: Action toolbar and right panel lifecycle

Branch: milestone/M007

* feat(chat-mode): move Discuss to input bar

* fix(web): launch browser PTYs with GSD loader

* chore(M005): record integration branch

* feat(M005): Light Theme with System-Aware Toggle

Completed slices:
- S01: Theme foundation and NavRail toggle
- S02: Component color audit and visual verification

Branch: milestone/M005

* chore(M007): record integration branch

* feat(web): chat mode action bar, smart CTA, project-level status bar, centered visualizer tabs

- Chat input bar: top 3 buttons (Discuss, Next, Auto) + overflow menu with all /gsd subcommands grouped by category, tooltips on hover
- Action routing: main-panel commands (next, auto, stop, pause) vs action-panel commands (discuss, status, visualize, etc.)
- Removed Config, Hooks, Migrate, Inspect from action menu
- Smart placeholder CTA: derives contextual button from workspace state (New Milestone, Start Auto, Resume, Plan, etc.)
- Status bar: project-level totals (duration, tokens, cost) from visualizer API instead of session-scoped auto data
- Visualizer: centered tab bar

* docs(M008): context, requirements, and roadmap

* chore(M008): record integration branch

* chore(M008/S01): auto-commit after research-slice

* docs(S01): add slice plan

* chore(M008/S01/T01): auto-commit after execute-task

* chore(M008/S01/T02): auto-commit after execute-task

* chore(M008/S01): auto-commit after complete-slice

* chore(M008/S01): auto-commit after reassess-roadmap

* chore(M008/S02): auto-commit after research-slice

* docs(S02): add slice plan

* chore(M008/S02/T01): auto-commit after execute-task

* chore(M008/S02/T02): auto-commit after execute-task

* chore(M008/S02): auto-commit after complete-slice

* chore(M008/S02): auto-commit after reassess-roadmap

* chore(M008/S03): auto-commit after research-slice

* docs(S03): add slice plan

* chore(M008/S03/T01): auto-commit after execute-task

* chore(M008/S03/T02): auto-commit after execute-task

* chore(M008/S03/T03): auto-commit after execute-task

* chore(M008/S03): auto-commit after complete-slice

* chore(M008/S03): auto-commit after reassess-roadmap

* chore(M008/S04): auto-commit after research-slice

* docs(S04): add slice plan

* chore(M008/S04/T01): auto-commit after execute-task

* chore(M008/S04/T02): auto-commit after execute-task

* chore(M008/S04): auto-commit after complete-slice

* chore(M008/S04): auto-commit after reassess-roadmap

* chore(M008/S05): auto-commit after research-slice

* docs(S05): add slice plan

* chore(M008/S05/T01): auto-commit after execute-task

* chore(M008/S05/T02): auto-commit after execute-task

* chore(M008/S05): auto-commit after complete-slice

* chore(M008): auto-commit after complete-milestone

* feat(M008): Web Polish

Completed slices:
- S01: Projects Page Redesign
- S02: Browser Update UI
- S03: Theme Defaults & Light Mode Color Audit
- S04: Remote Questions Settings
- S05: Progress Bar Dynamics & Terminal Text Size

Branch: milestone/M008

* docs: project plan — 3 milestones (M009 editor, M010 upstream sync, M011 CI/CD+PWA)

* chore(M009): record integration branch

* chore(M009/S01): auto-commit after research-slice

* docs(S01): add slice plan

* chore(M009/S01/T01): auto-commit after execute-task

* chore(M009/S01/T02): auto-commit after execute-task

* chore(M009/S01): auto-commit after complete-slice

* chore(M009/S01): auto-commit after reassess-roadmap

* chore(M009/S02): auto-commit after research-slice

* docs(S02): add slice plan

* state: S02 executing, next T01

* chore(M009/S02/T01): auto-commit after execute-task

* chore(M009/S02/T02): auto-commit after execute-task

* chore: untrack .gsd/ runtime files from git index

* chore(M009/S04): auto-commit after plan-slice

* docs(S04): add slice plan

* feat(S04/T01): Added dual shiki theme loading (dark + light) driven by…

- web/components/gsd/file-content-viewer.tsx

* chore(M010): record integration branch

* chore(M011): record integration branch

* feat(S02/T01): Added dist/web/standalone/{server.js, public/manifest.js…

- scripts/validate-pack.js

* test(S02/T02): Created .github/workflows/web.yml with full web host CI…

- .github/workflows/web.yml

* fix gitignore

* chore: update .gitignore to match upstream, untrack ignored files

- Updated .gitignore to match upstream/main patterns
- Removed 498 tracked files now covered by .gitignore:
  - .gsd/ project state (milestones, plans, summaries, db files)
  - Stale lock files (bun.lock, root pnpm-lock.yaml, web/pnpm-lock.yaml)
- Preserved upstream-tracked files:
  - pkg/dist/core/export-html/ (negation rules)
  - packages/*/pnpm-lock.yaml (tracked upstream)

* feat(M011): PWA support — service worker, install prompt, CI workflow

Squash-merge of milestone/M011 branch.

- Serwist service worker integration with Next.js (sw.ts, sw-register.tsx)
- PWA manifest with standalone display mode and app icons
- Install prompt hook and dismissible banner component
- Web host CI workflow (.github/workflows/web.yml)
- Updated web/.gitignore for Serwist build artifacts
- validate-pack.js script addition

* refine .gitignore: track GSD project artifacts, ignore runtime state

* gitignore: restore full .gsd/ exclusion

* docs(M012): context, requirements, and roadmap

* feat(S01/T01): Squash-merged 443 upstream commits (v2.22→v2.31) into fo…

- .gitignore
- src/cli.ts
- src/resource-loader.ts
- src/resources/extensions/get-secrets-from-user.ts
- src/resources/extensions/gsd/workspace-index.ts
- package-lock.json

* chore: squash merge upstream/main (v2.22→v2.31)

Merges 443 upstream commits from v2.22 to v2.31.0. Resolves 12 conflict files. Preserves fork web-mode additions. Switches web build to webpack mode for NodeNext .js extension import compatibility.

* feat(S02/T01): Added a lowercase "beta" pill badge next to the GSD logo…

- web/components/gsd/app-shell.tsx

* feat(S03/T01): Branch FileContentViewer editable mode: non-markdown fil…

- web/components/gsd/file-content-viewer.tsx

* chore(S04/T01): Added image input pipeline for chat mode: drag-and-drop…

- web/lib/image-utils.ts
- web/components/gsd/chat-mode.tsx
- web/lib/pty-chat-parser.ts
- web/lib/gsd-workspace-store.tsx

* feat(S04/T02): Created /api/terminal/upload endpoint and wired drag-dro…

- web/app/api/terminal/upload/route.ts
- web/components/gsd/shell-terminal.tsx

* chore(S05/T01): Replaced left ShellTerminal with bridge-event Terminal…

- web/components/gsd/dual-terminal.tsx

* feat(S06/T01): Created GuidedDialog component wrapping ChatPane in a fu…

- web/components/gsd/guided-dialog.tsx
- web/components/gsd/project-welcome.tsx

* feat(S06/T02): Wired GuidedDialog into Dashboard with nullable state, o…

- web/components/gsd/dashboard.tsx

* merge upstream/main: sync with v2.31.2, resolve conflicts preserving fork web UI changes

- Version bumps: 2.31.0 → 2.31.2 across all packages
- Upstream refactors adopted: createGitService factory, dispatchUnit helper,
  STATE_REBUILD_MIN_INTERVAL_MS constant extraction, KNOWN_UNIT_TYPES centralization
- New upstream features merged: environment health checks, progress score,
  doctor providers, health widget, auto-reentrancy guard
- Fork-specific code preserved: web CLI branch, TTY check with --web hint,
  workspace index risk/depends/demo fields, dist-redirect web/ extensionless imports
- checkExistingEnvKeys moved inline (upstream deleted env-key-utils.ts)
- Fixed 5 pre-existing test failures: edit-mode slash command parity,
  gsd:web script assertion, dual-terminal store contract (moved to terminal.tsx)

* ci: consolidate web workflow into main CI pipeline

Moved web host install and build steps into the CI build job.
Removed the separate web.yml workflow.

* fix(tests): configure onboarding service in bridge/live tests for CI

Tests calling sendBridgeInput via the command route now configure
the onboarding service with in-memory auth storage. Without this,
collectOnboardingState() returns locked (no API key in CI env),
causing all command route calls to return HTTP 423.

* fix: CI and Windows portability for web mode tests

- cli.ts: early TTY check now skips when --web flag is set, allowing
  headless web mode launches in CI (fixes 5 runtime harness failures)
- auto-dashboard-service.ts: convert --import path to file:// URL via
  pathToFileURL() (fixes ERR_UNSUPPORTED_ESM_URL_SCHEME on Windows)
- web-mode-cli.test.ts: use resolve() for registry key lookups so
  Windows-normalized paths match (fixes registerInstance/unregisterInstance)
- web-mode-assembled.test.ts: configure onboarding service with
  in-memory auth for settings and slash-command tests (fixes 423 in CI)

* fix: Windows portability for all web service subprocess launchers

All 17 `--import` arguments across web service files now use
pathToFileURL().href instead of raw file paths. Node's --import
flag requires URL scheme on Windows (D:\ paths fail with
ERR_UNSUPPORTED_ESM_URL_SCHEME).

Affected services: auto-dashboard, recovery-diagnostics, hooks,
export, cleanup, forensics, history, settings, doctor, skill-health,
undo, visualizer, bridge, captures, cli-entry.

Also fixes:
- web-session-parity-contract: normalize git rev-parse output with
  resolve() for Windows backslash consistency

* fix: repair web recovery diagnostics CI failures

* test: align launched-host integration flows with current web UI

* fix(ci): stabilize packaged web onboarding flow

* feat(web): render main-session native TUI in power user mode

* Update web terminal parity and eslint setup

* Fix web lint and typecheck issues

* Normalize Power User terminal headers

* Restore Geist web font loading

* fix(web): update PWA app name and icon assets

* Remove web PWA functionality

* fix(web): scope terminal surfaces to active project

* feat(web): add project creation flow

* refactor(web): centralize workflow actions and simplify dashboard

* test(web): align packaged runtime integration flows

* fix: route dashboard/sidebar CTA commands through session API and handle RPC lock conflicts

Two bugs prevented the dashboard and sidebar workflow action buttons
(New Milestone, Start Auto, Initialize Project, etc.) from working:

1. Frontend: executeWorkflowActionInPowerMode sent commands via raw
   fetch to /api/bridge-terminal/input (PTY keystroke injection) instead
   of the session command pipeline (/api/session/command). The agent
   never received these commands. Refactored to accept a dispatch
   callback that callers wire through sendCommand(buildPromptCommand()).

2. Backend: guardRemoteSession in the /gsd extension called
   showNextAction() — an interactive TUI prompt — when it detected
   another session's lock. In RPC/web bridge mode this blocks forever
   since there is no terminal to answer the prompt. Now detects
   GSD_WEB_BRIDGE_TUI=1 and emits an actionable warning notification
   instead of blocking.

Files changed:
- web/lib/workflow-action-execution.ts (dispatch callback instead of raw fetch)
- web/components/gsd/dashboard.tsx (pass store-backed dispatch)
- web/components/gsd/sidebar.tsx (MilestoneExplorer + CollapsedMilestoneSidebar)
- src/resources/extensions/gsd/commands.ts (RPC-mode guard in guardRemoteSession)

* fix: terminal drag-drop image upload, Shift+Enter newline, and chat mode unified response bubble

Bug 1 - Power Mode drag-drop: Dropping images on either terminal pane
opened the file in a new tab instead of uploading. Fixed by switching
all drag/drop handlers to native DOM capture-phase listeners (React
synthetic events don't reliably fire through xterm's internal DOM).
Both panes now upload images via /api/terminal/upload and inject
@filepath into the terminal input. DualTerminal wrapper prevents
browser default file-navigation as a safety net.

Bug 2 - Chat Mode dual response: During streaming, the assistant
response and thinking indicator rendered as two separate UI blocks.
Fixed by moving thinking content inline into the assistant ChatBubble
via a new InlineThinking component. Removed the standalone
ThinkingIndicator. Thinking text now appears as a collapsible section
above the response text within the same bubble.

Bug 3 - Shift+Enter newline: xterm.js sends \r for both Enter and
Shift+Enter, but pi's TUI editor expects \n (LF) for newline
insertion. Added native DOM capture-phase keydown listeners on both
MainSessionTerminal and ShellTerminal that intercept Shift+Enter,
preventDefault to block xterm, and send \n through the input channel.

* chore: update lockfile and tsbuildinfo

* refactor: remove right-side action panel, route all commands through main bridge

- Remove ActionPanel, StructuredTerminalActionPane, and all PTY screen-scraping
  infrastructure (~700 lines deleted: stripTerminalChrome, isScreenChromeLine,
  normalizeScreenLine, beautifyParsedScreenContent, parseStructuredTerminalScreen,
  SCREEN_* constants, hidden xterm.js terminal buffer)

- All /gsd subcommands now dispatch through the main bridge session via
  sendCommand(buildPromptCommand()). No separate PTY instances.

- Add disabledDuringAuto flag to GSDActionDef. Commands that inject competing
  LLM prompts are disabled while auto-mode runs:
  - discuss: calls dispatchWorkflow -> pi.sendMessage (would conflict with auto)
  - triage: injects triage prompt via pi.sendMessage (same conflict)
  - All other commands verified safe: stop/pause control auto, steer explicitly
    handles auto with HARD STEER message, capture/knowledge/skip are file IO,
    status/queue/history/visualize are read-only, mode/prefs/doctor/export/
    cleanup/remote are config/maintenance

- Add inline PendingUiRequest rendering in ChatPane: select (single + multi),
  confirm, input, and editor requests appear as interactive chat bubbles in the
  message flow with native clickable controls and post-submission confirmation

- Wire FocusedPanel in app-shell.tsx as fallback overlay for pendingUiRequests
  in non-chat views (dashboard, power mode, files, etc.)

- Remove unused imports: AnimatePresence, motion, buildProjectAbsoluteUrl,
  buildProjectPath, HeadlessTerminal type, compact prop

* chore: gitignore tsbuildinfo files

* onboarding overhaul: add mode, project, and remote steps; refactor existing steps

- Add step-mode.tsx for user/dev mode selection
- Add step-project.tsx for project selection/creation
- Add step-remote.tsx for remote repository configuration
- Add use-user-mode.ts hook for mode state management
- Add /api/dev-mode route for dev mode toggle
- Refactor onboarding-gate.tsx flow and step sequencing
- Refactor step-authenticate, step-dev-root, step-optional,
  step-provider, step-ready, step-welcome with updated styling
- Update command-surface, app-shell, dashboard integrations
- Update dev-overrides and workflow-action-execution

* overhaul projects view, simplify boot readiness, add requireProjectCwd

- Redesign projects-view with Sheet/Dialog components and improved styling
- Simplify waitForBootReady: remove bridge phase tracking, return on first successful response
- Boot route returns minimal no-project payload when no project is configured
- Rename resolveProjectCwd → requireProjectCwd across all API routes
- Minor UI adjustments in app-shell, sidebar, terminal

* fix: update tests for upstream merge and UI refactor

Unit tests (7 fixes, 2133/2133 pass):
- smart-entry-complete: match upstream's chooser-based complete flow
- web-bridge-contract: add projectDetection to boot snapshot keys
- web-command-parity: await async registerExtension (upstream decomposition)
- web-mode-cli: update gsd:web script expectation (copy-resources added)
- web-state-surfaces: match refactored editorTextBuffer consumption
- web-workflow-action-execution: match new dispatch-based API, stub localStorage
- web-mode.ts: restore GSD_WEB_PROJECT_CWD in spawn env

Integration tests:
- web-mode-onboarding: simplify to API-only contract (locked→reject→retry→unlocked)
  without fragile browser UI assertions that depend on refactored wizard flow

* Clean up dashboard header and redesign project selection gate

- Simplify dashboard header: inline scope badge with title, remove
  workflow action buttons and status indicators
- Redesign project selection gate: center logo with subtitle, remove
  header bar and side gutters, cleaner layout
- Remove web-mode-runtime integration test

* settings: consolidate tabs, add General panel with font size controls

- Add General tab (terminal font size + code font size) as default settings landing
- Merge Thinking into Model tab (model selection + thinking level in one panel)
- Merge Queue + Compaction + Retry into Session tab (all session behavior knobs)
- Reduce settings nav from 8 tabs to 6 (+ admin when dev mode)
- Legacy section routes (thinking, queue, compaction, retry) still render correctly
- gsd-prefs mega-scroll uses GeneralPanel instead of separate Terminal/Editor panels

* fix: file explorer & visualizer use selected project context, resizable tree panel

- Route all fetch calls in files-view, visualizer-view, and status-bar
  through buildProjectUrl() so they respect the active project selection
  instead of falling back to GSD_WEB_PROJECT_CWD (server startup project)
- Make file explorer tree panel resizable (180-480px) with drag handle,
  matching the milestone sidebar resize pattern

* feat(web): file explorer Agent tab, merged headers, unified chat timeline

- Merge file path display + save button into single header row (3 layers → 2)
- Add Agent tab to file explorer left panel with embedded ChatPane
- Auto-open files in viewer when agent executes edit/write tools
- Show inline diff (red/green lines) for agent-edited files with auto-dismiss
- MD files default to Edit tab when agent-opened so raw changes are visible
- Unified chat timeline: tool executions render inline where they happen,
  not stacked at the bottom
- Persist user messages in workspace store so they survive tab switches
- Shorten chat input placeholder to 'Message…', remove hint text

* feat(chat): persist thinking blocks and render in chronological order

- Add TurnSegment type to track thinking/text/tool events in order
- Finalize streaming content into segments at phase transitions
  (thinking→text, text→thinking, tool start/end, turn boundary)
- Store completedTurnSegments parallel to liveTranscript for history
- Rebuild chat timeline from segments so thinking blocks render
  in their correct position between text and tool calls
- Thinking blocks now persist after streaming ends (collapsible)
- Restyle InlineThinking to monochrome (muted-foreground) — removes
  amber/warning colors for consistency with dark theme

* feat(web): add Integrations tab to settings panel for remote channel config

* feat(web): bot token input in settings and onboarding, card-based integrations panel

- Add PATCH endpoint to /api/remote-questions for saving bot tokens
  to ~/.gsd/agent/auth.json (same storage as TUI key manager)
- Redesign RemoteQuestionsPanel: card-based channel picker, inline
  token input with show/hide toggle, collapsible advanced settings,
  connected state banner with disconnect
- Add bot token input to onboarding StepRemote with same PATCH flow
- Remove 'configure via TUI or environment' messaging — web UI now
  handles the full setup end-to-end

* fix(web): address PR #1717 security review feedback

Security (blocking):
- Add bearer token auth to all API routes via Next.js middleware
- Generate random token at launch, pass to browser via URL fragment
- Add Origin/CORS validation rejecting cross-origin API requests
- Whitelist PTY commands (gsd, user shell, /bin/bash, /bin/zsh, /bin/sh)
- Restrict /api/browse-directories to devRoot scope

Cleanup:
- Move shiki, react-markdown, remark-gfm from root to web/package.json
- Remove as-any casts in input-controller.ts (extend host type properly)
- Add extensions_ready signal to RPC mode (fixes void bindExtensions race)
- Add test fixture dummy keys to .secretscanignore (fixes CI lint)

* fix(web): resolve Next.js 16 build warnings

- Rename middleware.ts → proxy.ts with proxy() export (Next.js 16 convention)
- Add @gsd/native to webpack externals (fixes package path resolution warning)
- Hide require fallback from webpack static analysis in pty-manager (fixes
  critical dependency warning)

* fix(web): pass auth token to boot readiness probe

The readiness probe hits /api/boot to check server startup, but the
proxy now requires a bearer token. Thread the authToken through
waitForBootReady → requestLocalJson so the probe authenticates.

* chore: sync lockfiles after moving deps to web/package.json

* fix(test): update web-mode-cli test for auth token in browser URL

The test asserted the exact opened URL, which now includes a random
auth token fragment. Updated to pattern-match the token and verify
GSD_WEB_AUTH_TOKEN is passed consistently in the spawn env.

* fix(test): pass auth token in web-mode-onboarding integration test

The runtime harness now extracts the auth token from the browser-open
stub log and exposes it on RuntimeLaunchResult.authToken. Added
runtimeAuthHeaders() helper. Updated the onboarding test to pass
Authorization headers on all fetch calls and waitForHttpOk.

* fix(test): match renamed nextMilestoneIdReserved in smart-entry-complete test

Upstream #1569 renamed nextMilestoneId → nextMilestoneIdReserved.
Updated the regex assertion to accept both names.

* feat(web): support GSD_WEB_ALLOWED_ORIGINS for secure tunnel setups

Adds a comma-separated GSD_WEB_ALLOWED_ORIGINS env var that merges
additional origins into the CORS allowlist. Defaults to localhost-only
when unset. Enables Tailscale Serve, Cloudflare Tunnel, ngrok, etc.
2026-03-21 12:16:54 -06:00
TÂCHES
43d8dbc9d3 fix: update Anthropic OAuth endpoints to platform.claude.com (#1608)
Anthropic migrated their OAuth infrastructure from console.anthropic.com
to platform.claude.com. The old URLs are decommissioned, breaking all
OAuth login flows.

Closes #1587

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 10:27:20 -06:00
Nathan Roe
39cd932abb feat: add anthropic-vertex provider for Claude on Vertex AI (#1533)
* feat: add anthropic-vertex provider for Claude models on Google Vertex AI

Add a new anthropic-vertex provider that enables using Claude models
(Opus 4.6, Sonnet 4.6, Haiku 4.5) through Google Vertex AI using the
@anthropic-ai/vertex-sdk package. Follows the same pattern as the
existing google/google-vertex provider split.

Detection uses ANTHROPIC_VERTEX_PROJECT_ID (same env var as Claude Code)
with CLOUD_ML_REGION for region selection, falling back to us-central1.

Extracts shared Anthropic utilities into anthropic-shared.ts (message
conversion, tool conversion, param building, stream processing) to
avoid duplication between anthropic.ts and anthropic-vertex.ts.

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

* feat: add full Claude model set for anthropic-vertex provider

Add 200K context window variants for Opus 4.6 and Sonnet 4.6, plus
older models (Sonnet 4.5, Sonnet 4, Opus 4.5, Opus 4.1, Opus 4, Haiku 4.5).

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

* fix: add @anthropic-ai/vertex-sdk to root dependencies

Required for the published package to resolve the vertex SDK at runtime.

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

* chore: remove unnecessary comments to match codebase style

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

* fix: remove duplicate stream functions after rebase

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

---------

Co-authored-by: Nathan Roe <nathan.roe@carvana.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 23:14:13 -06:00
TÂCHES
ad01d0ada4 Merge pull request #1365 from jbrahy/fix/openai-reasoning-encrypted-content-always-include
fix: always include reasoning.encrypted_content for OpenAI reasoning models
2026-03-19 16:38:24 -06:00
TÂCHES
a23c69aaae Merge pull request #1468 from frizynn/refactor/oauth-utils-consolidation
refactor: consolidate Google OAuth callback server and helper utilities
2026-03-19 15:50:59 -06:00
TÂCHES
86ada3a345 Merge pull request #1480 from frizynn/refactor/openai-providers-shared-base
refactor: consolidate shared code between OpenAI providers
2026-03-19 15:48:17 -06:00
Juan Francisco Lebrero
4e29ca4544 refactor: remove dead code (unused exports) (#1486)
Remove exported functions/constants/classes that are never imported
anywhere else in the codebase:

Fully removed (not used anywhere):
- nativeAvailable (native)
- getApiProviders, unregisterApiProviders (pi-ai/api-registry)
- createAssistantMessageEventStream (pi-ai/event-stream)
- getOverflowPatterns (pi-ai/overflow)
- validateToolCall (pi-ai/validation)
- getToolsDir (pi-coding-agent/config)
- emitSessionShutdownEvent (extensions/runner)
- syncContent, notifySaved (lsp/client)
- getServerForFile, hasCapability (lsp/config)
- severityToIcon, formatPosition, formatTextEdit, symbolKindToName (lsp/utils)
- clearApiKeyCache (model-registry)
- restoreModelFromSession (model-resolver)
- isLightTheme (theme)
- loadPhoton + all internal helpers (photon)
- extractAnsiCode (pi-tui/utils)

De-exported (used locally, not externally):
- extractRetryAfterMs, inferCopilotInitiator, extractRetryDelay,
  buildRequest, requiresToolCallId, registerBuiltInApiProviders,
  streamProxy, isBunRuntime, detectInstallMethod, getPackageDir,
  getPackageJsonPath, ansiToHtml, DEFAULT_APP_KEYBINDINGS,
  DEFAULT_KEYBINDINGS, shutdownClient, sendNotification, shutdownAll,
  applyTextEditsToString, wrapWithLspmux, severityToString,
  COMPACTION_SUMMARY_PREFIX/SUFFIX, BRANCH_SUMMARY_PREFIX/SUFFIX,
  bashExecutionToText, defaultModelPerProvider, parseModelPattern,
  parseCommandArgs, substituteArgs, loadEntriesFromFile,
  findMostRecentSession, FileSettingsStorage, InMemorySettingsStorage,
  migrateAuthToAuthJson, migrateSessionsFromAgentRoot,
  parseSearchQuery, matchSession, compareVersions, isWaylandSession,
  getToolPath, wordWrapLine
2026-03-19 15:33:32 -06:00
TÂCHES
d761e45a41 M001: The Minimal Machine — linear auto-loop, sole-authority state, sidecar queue, WorktreeResolver (#1419)
* refactor: replace recursive auto-dispatch with linear autoLoop, delete ~3k lines of dead code

Replace the complex recursive dispatch system (dispatchNextUnit, reentrancy
guards, stall detection, idempotency tracking, skip-depth machinery) with a
simple linear while(s.active) loop in auto-loop.ts.

Key changes:
- New auto-loop.ts with autoLoop(), runUnit(), resolveAgentEnd()
- Deleted auto-idempotency.ts, auto-stuck-detection.ts, session-lock.ts,
  mechanical-completion.ts, progress-score.ts, auto-constants.ts, unit-id.ts
- Extracted WorktreeResolver class for worktree path resolution
- Added auto-worktree-sync.ts for worktree synchronization
- Simplified auto.ts from ~1400 lines to ~400 lines
- Fixed 9 TypeScript errors (NotifyCtx type widening, capture typing)
- Comprehensive test coverage: 32 auto-loop tests + worktree resolver/DB tests

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

* fix: address 6 audit findings in auto-loop refactor

1. CRITICAL: Move pendingResolve to AutoSession + queue orphaned agent_end
   events instead of silently dropping them. Prevents permanent stalls when
   error-recovery sendMessage retries fire between loop iterations.

2. HIGH: Scope pendingResolve per-session via _activeSession ref, preventing
   concurrent /gsd auto sessions from corrupting each other's promises.

3. HIGH: Replace console.log in dispatchHookUnit with debugLog to prevent
   hook prompt content (potentially containing secrets) from leaking to stdout.

4. HIGH: Restore parked milestone handling in state.ts — Phase 1 skips
   parked milestones so they don't satisfy depends_on, Phase 2 registers
   them as 'parked' status. Add 'parked' to MilestoneRegistryEntry type.

5. MEDIUM: Restore queuePhaseActive parameter in shouldBlockContextWrite
   and re-export setQueuePhaseActive for guided-flow-queue.ts consumers.

6. MEDIUM: Add MAX_LOOP_ITERATIONS (500) lifetime cap to autoLoop to prevent
   runaway loops when units alternate between IDs.

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

* fix: resolve build breakers, add correctness fixes, and graduated recovery

Build breakers (CRITICAL):
- Restore unit-id.ts (deleted but still imported by complexity-classifier.ts, metrics.ts)
- Restore progress-score.ts (deleted but still imported by commands.ts, dashboard-overlay.ts, doctor.ts)
- Rewrite worktree-sync-milestones.test.ts to use new syncProjectRootToWorktree API

Correctness fixes (MEDIUM):
- Cap pendingAgentEndQueue to 3 entries to prevent unbounded growth from stale events
- Add milestoneId path traversal validation in WorktreeResolver
- Clear depthVerificationDone on session_start to prevent cross-session leaks in RPC mode
- Add verification gate for non-hook sidecar units (triage, quick-tasks)
- Remove dead handleAgentEnd import from index.ts

Graduated recovery (Jeremy's feedback):
- Blanket try/catch around loop body — one bad iteration no longer kills the session
- Graduated stuck recovery: at count 3 try artifact verification + cache invalidation,
  at count 5 hard stop (was: binary stop at 5 with no recovery attempt)
- Graduated error recovery: 1st error retries, 2nd invalidates caches, 3rd stops

Test results: 32/32 auto-loop, 28/28 worktree-resolver, 11/11 sidecar-queue, tsc clean.

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

* fix: restore copyWorktreeDb/reconcileWorktreeDb exports and fix loadToolApiKeys import

Two missing exports caused ~90% of the 120 pre-existing test failures:

1. copyWorktreeDb + reconcileWorktreeDb — imported by auto-worktree.ts but
   never added to gsd-db.ts. Restored with the original implementations.
2. loadToolApiKeys — moved to commands-config.ts but index.ts still imported
   from commands.ts. Fixed the import path.

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

* fix: move loadToolApiKeys import to commands-config.js

loadToolApiKeys was moved to commands-config.ts but index.ts still
imported it from commands.ts, causing runtime failures in all tests
that transitively load the extension entry point.

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

* test: fix provider error assertion on windows

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 14:56:00 -06:00
frizynn
1c5fdc9144 refactor: consolidate shared code between OpenAI providers
Extract duplicated patterns from openai-completions.ts,
openai-responses.ts, and azure-openai-responses.ts into a new
openai-shared.ts module:

- getOpenAIClass: unified lazy SDK loading (was duplicated in both)
- createOpenAIClient: shared client creation with Copilot headers,
  options header merging, and lazy loading (was ~30 lines each)
- buildInitialOutput: AssistantMessage initialization (was ~15 lines x3)
- assertStreamSuccess / finalizeStream / handleStreamError: stream
  lifecycle helpers (was ~10 lines each x3)
- clampReasoningForModel: reasoning effort clamping for gpt-5.x models
  (was duplicated in openai-responses.ts and azure-openai-responses.ts)

Net reduction: ~185 lines removed across the three provider files.
2026-03-19 16:39:12 -03:00
frizynn
d0cd3451fd refactor: consolidate OAuth callback server and helper utilities
Extract duplicated implementations of startCallbackServer, parseRedirectUrl,
getUserEmail, and token refresh logic from google-antigravity.ts and
google-gemini-cli.ts into a shared google-oauth-utils.ts module.
2026-03-19 15:55:10 -03:00
Tom Boucher
5187841c0b feat: auto-generate OpenRouter model registry from API + add missing models (#1407) (#1426)
Added scripts/generate-openrouter-models.mjs that fetches the full model
list from OpenRouter's API and generates TypeScript entries matching the
existing models.generated.ts format. Run with:
  node scripts/generate-openrouter-models.mjs > /tmp/openrouter.ts

Updated the OpenRouter section in models.generated.ts from 241 → 350
models, including all nvidia/nemotron variants requested in the issue.

Fixes #1407
2026-03-19 10:40:34 -06:00
John Brahy
c47ee71b2d fix: always include reasoning.encrypted_content for OpenAI reasoning models
When using a reasoning model (o1, o3, o4-mini, etc.) without explicitly
setting reasoningEffort or reasoningSummary, the include param was not
set. OpenAI returns a bare rs_... reasoning item ID which gets stored in
thinkingSignature and replayed in the next turn. Since store is false,
OpenAI cannot find the rs_... item server-side and returns a 404.

Fix: move params.include = ["reasoning.encrypted_content"] outside the
reasoningEffort/reasoningSummary guard so it is always set for any
reasoning model. This ensures the encrypted blob is returned and can be
replayed correctly without needing server-side storage.
2026-03-19 02:53:06 -07:00
Copilot
1020c140af Fix Codex server_error handling: extraction, retry matching, escalating backoff (#1106)
* Initial plan

* Fix OpenAI Codex error handling: proper error extraction, retry matching, and escalating backoff

- Fix mapCodexEvents to extract error details from nested event.error object
  (Codex API returns {type:"error", error:{type:"server_error", message:"..."}})
- Fix _isRetryableError regex: server.?error matches both server_error and server error
- Add escalating backoff for repeated transient auto-resumes (30s→60s→120s→240s→480s)
- Cap consecutive transient auto-resumes at 5 before pausing indefinitely
- Reset counter on successful unit completion

Co-authored-by: glittercowboy <186001655+glittercowboy@users.noreply.github.com>

* Improve regex test to be behavioral instead of structural

Co-authored-by: glittercowboy <186001655+glittercowboy@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: glittercowboy <186001655+glittercowboy@users.noreply.github.com>
2026-03-18 01:10:55 -06:00
Jeremy McSpadden
155c32e01b fix: strip model variant suffix for API key auth (#1097) (#1099)
* fix: strip model variant suffix for all auth methods, not just OAuth (#1097)

The model ID variant suffix (e.g., `[1m]` in `claude-opus-4-6[1m]`) was
only stripped for OAuth token auth. When using an API key, the suffix was
sent to the Anthropic API as-is, causing a 400 "upstream_error" because
`claude-opus-4-6[1m]` is not a valid API model ID.

The default Anthropic model is `claude-opus-4-6[1m]` (1M context variant),
so every API key user hits this on every request.

Fix: strip `[...]` suffix unconditionally for all auth methods.

* fix: update source-reading tests for post-refactor file locations

triage-dispatch.test.ts: read auto-post-unit.ts (dispatch logic moved
from auto.ts) and update comment string matches to reflect renamed
section headers.

token-profile.test.ts: read preferences-types.ts, preferences-validation.ts,
and preferences-models.ts (GSDPreferences interface and validation logic
split from preferences.ts).
2026-03-17 23:31:40 -06:00
Lex Christopherson
c1bc65bcca fix: switch alibaba-coding-plan to OpenAI-compat endpoint with proper compat flags (#1003) (#1057)
Co-Authored-By: Tom Boucher <trek-e@users.noreply.github.com>
2026-03-17 22:09:55 -06:00
Tom Boucher
85d48d3c97 fix: disable reasoning for MiniMax-M2.5 in alibaba-coding-plan provider (#1003) (#1055)
* docs: add Node LTS pinning guide for macOS Homebrew users

New doc (docs/node-lts-macos.md) explains how to pin Node 24 LTS
via Homebrew to avoid running on odd-numbered development releases.
Covers brew install/link/pin, version managers as alternatives,
and verification steps.

Added notice banner in README linking to the guide.

* fix: disable reasoning for MiniMax-M2.5 in alibaba-coding-plan provider (#1003)

MiniMax-M2.5 via Dashscope's Anthropic-compatible API does not
properly support extended thinking, causing the model to get stuck
in a thinking loop. Set reasoning: false for this model entry in
the alibaba-coding-plan provider.
2026-03-17 21:58:38 -06:00
Tom Boucher
d252168de5 fix: switch alibaba-coding-plan to OpenAI-compat endpoint with proper compat flags (#1003)
The alibaba-coding-plan provider was using the Anthropic-compatible
endpoint (/apps/anthropic) with anthropic-messages API, which caused
issues with thinking mode on several models (MiniMax-M2.5 thinking
loop, missing thinkingFormat for Qwen/GLM models).

Changes for all 8 models:
- API: anthropic-messages → openai-completions
- Endpoint: /apps/anthropic → /v1 (OpenAI-compatible)
- Added per-model compat flags:
  - Qwen models: thinkingFormat: 'qwen', supportsDeveloperRole: false
  - GLM models: thinkingFormat: 'qwen', supportsDeveloperRole: false
  - MiniMax-M2.5: supportsReasoningEffort: true, maxTokensField: 'max_tokens'
  - Kimi K2.5: thinkingFormat: 'zai', supportsDeveloperRole: false
- Enabled reasoning for qwen3-max (was incorrectly false)
- Fixed context windows to match tested values
- Fixed MiniMax-M2.5 maxTokens: 24576 → 65536
2026-03-17 21:11:18 -04:00
TÂCHES
3537f6b716 chore: fix chalk version mismatch and document pinned dependency rationale (#1030)
- Align pi-tui chalk from ^5.5.0 to ^5.6.2 (matches root, pi-ai, pi-coding-agent)
- Convert @mistralai/mistralai and openai to caret ranges (^1.14.1, ^6.26.0)
  in both root and pi-ai — no intentional pin rationale found in git history,
  versions were just hoisted as-is from workspace deps
- Keep gaxios@7.1.4 override pinned — intentionally set in 5c64f99 to
  eliminate glob@10.5.0 deprecation warnings from transitive deps

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 18:29:31 -06:00
TÂCHES
e66039162e perf: optimize SSE streaming buffer to avoid quadratic string growth (#1024)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 18:29:09 -06:00
TÂCHES
f8b16beddb fix: add missing package.json subpath exports and oauth stubs (#1014)
Add 7 missing subpath exports to @gsd/native (diff, gsd-parser,
highlight, json-parse, stream-process, truncate, ttsr) and create
root-level oauth.js/oauth.d.ts stub files for @gsd/pi-ai to match
the bedrock-provider pattern.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 18:01:56 -06:00
Jeremy McSpadden
0e0f47ef9f fix: failure recovery & resume safeguards (all 4 waves) (#956)
* fix: prevent data loss on crash with atomic writes, file locking, and error handling

Wave 1 of failure recovery safeguards:

1. Atomic session file rewrites (tmp+rename) — _rewriteFile() and forkFrom()
   now use atomicWriteFileSync to prevent session file corruption on crash
2. Atomic auto.lock writes — crash-recovery.ts writeLock() uses tmp+rename
   so the crash detection system itself can't be corrupted
3. unhandledRejection handler — catches silent process death from unhandled
   promise rejections in OAuth, extensions, LSP, or MCP connections
4. try/catch in emitToolCall — matches pattern used by emitUserBash,
   emitContext, and emitToolResult to prevent extension handler crashes
   from killing the entire agent turn
5. File locking on session appends — prevents concurrent pi instances from
   interleaving partial JSON lines in session JSONL files using the same
   proper-lockfile pattern established in auth-storage.ts and settings-manager.ts

* fix: add OAuth timeouts, RPC exit detection, and command context guards

Wave 2 of failure recovery safeguards:

1. OAuth fetch timeouts — all fetch() calls across all OAuth providers
   (Anthropic, OpenAI Codex, Google Antigravity, Google Gemini CLI,
   GitHub Copilot) now have 30-second AbortSignal.timeout() to prevent
   indefinite hangs when OAuth servers are unresponsive
2. RPC subprocess exit detection — pending requests are now rejected
   when the agent subprocess exits unexpectedly, preventing indefinite
   hangs in the RPC client
3. Extension command context guards — default handlers for newSession,
   fork, navigateTree, switchSession, and reload now throw explicit
   errors instead of silently returning success when called before
   bindCommandContext()
4. OAuth error detail preservation — token refresh errors now preserve
   the original error as `cause` for better diagnostics

* fix: resource cleanup, LSP retry, and crash detection on session resume

Wave 3 of failure recovery safeguards:

1. Atomic completed-units.json cleanup — milestone completion writes
   now use tmp+rename pattern for consistency with auto-recovery.ts
2. Bash temp file cleanup — track temp files created for large output
   and register a process exit handler to clean them up
3. Settings write queue flush on shutdown — call settingsManager.flush()
   during interactive mode shutdown so queued writes aren't lost
4. LSP initialization retry — wrap getOrCreateClient with up to 2 retries
   with exponential backoff (1s, 2s) for transient spawn failures
5. Crash detection on session resume — wasInterrupted() checks if last
   assistant turn had tool calls without results, shows warning on resume

* fix: blob garbage collection and LSP debug logging

Wave 4 of failure recovery safeguards:

1. Blob garbage collection — BlobStore.gc(referencedHashes) removes
   orphaned blobs not referenced by any session file, plus totalSize()
   for monitoring blob directory growth
2. LSP JSON parse error logging — malformed LSP messages are now logged
   at debug level (when DEBUG env is set) instead of being silently dropped
2026-03-17 16:03:49 -06:00
Tom Boucher
5d86159ea8 fix: replan-slice infinite loop, non-standard finish_reason crash, fork-resilient test (#866) 2026-03-17 11:47:07 -06:00
Tom Boucher
8872c9095e fix: mark transient network errors as retriable in Anthropic provider (#833) (#849) 2026-03-17 08:17:25 -06:00
TÂCHES
440e6e878f feat: render native web search in TUI + PREFER_BRAVE_SEARCH toggle (#806)
* feat: render native web search tool calls in TUI

The Anthropic streaming parser silently dropped server_tool_use and
web_search_tool_result content blocks, making native web search
invisible. Add ServerToolUseContent and WebSearchResultContent types,
handle both block types in the streaming parser and conversation replay,
and render them as ToolExecutionComponent in the interactive TUI.

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

* feat: add PREFER_BRAVE_SEARCH env var to bypass native web search

Set PREFER_BRAVE_SEARCH=1 to keep Brave/custom search tools active
on Anthropic models instead of injecting native server-side web search.

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

* fix: skip non-toolCall blocks in Mistral provider conversation replay

The ServerToolUseContent and WebSearchResultContent types added for
native web search don't have id/name/arguments properties, causing
TypeScript errors when the Mistral provider tried to push them as
tool calls.

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-16 23:35:20 -06:00
Jeremy McSpadden
6d77724378 perf: lazy-load LLM provider SDKs to reduce startup time
All major LLM provider SDKs were loaded eagerly at startup, penalizing
users regardless of which provider they actually use. This change defers
SDK loading until first API call for:

- @anthropic-ai/sdk (anthropic.ts)
- openai (openai-responses.ts, openai-completions.ts, azure-openai-responses.ts)
- @google/genai (google-vertex.ts)

The Bedrock provider already used this pattern. Now all 5 remaining
providers use the same async lazy-loader pattern:
- Static import changed to `import type` (erased at compile time)
- Module-level `let _SdkClass` cache variable
- `async function getSdkClass()` loader with singleton caching
- `createClient()` made async, uses `await getSdkClass()`
- Call sites updated with `await createClient()`

For google-vertex.ts, ThinkingLevel enum usage replaced with equivalent
string literals to eliminate the runtime import entirely.

All packages build cleanly. The startup improvement is proportional to
how many providers were installed — on typical installs this eliminates
eager loading of 30-40MB of SDK code.
2026-03-16 18:33:24 -05:00
TÂCHES
e4d47de1f6 Merge pull request #690 from trek-e/fix/688-thinking-minimal-gpt5
fix: clamp 'minimal' thinking level to 'low' for gpt-5.x models (#688)
2026-03-16 14:17:51 -06:00
Tom Boucher
1a499aecb2 fix: clamp 'minimal' thinking level to 'low' for gpt-5.x models (#688)
gpt-5.x models (via Copilot/OpenAI/Azure) don't support 'minimal' as a
reasoning effort level — they only accept 'none', 'low', 'medium',
'high', and 'xhigh'. Setting /thinking minimal with gpt-5.4 causes a
400 error.

The openai-codex-responses provider already had this clamping, but the
openai-responses and azure-openai-responses providers passed the value
through unclamped.

Add clampReasoningForModel() to both providers that maps 'minimal' to
'low' for gpt-5.x models, matching the existing behavior in
openai-codex-responses.

Fixes the bug portion of #688
2026-03-16 16:02:54 -04:00
Jamie McGregor Nelson
d4cf95f204 fix: type errors in claude-import.ts and marketplace-discovery.ts 2026-03-16 14:46:31 -04:00
Jamie McGregor Nelson
526fa7439d fix: add missing type declarations for typecheck
- Add @smithy/node-http-handler to pi-ai
- Add @types/proper-lockfile, @types/hosted-git-info, @types/sql.js to pi-coding-agent
- These were causing typecheck:extensions to fail due to missing type declarations
2026-03-16 12:29:45 -04:00
Andriyansyah Nurrachman
132ae92944 feat: update ollama cloud provider models (#578) 2026-03-15 22:22:29 -06:00
Mannan Kant
96f5b58bd3 fix(pi-ai): address review comments on #504 — exhaustive switch, tests, cleanup (#587)
- Restore exhaustive never check in mapStopReason (throw on unhandled FinishReason)
- Add 12 unit tests for sanitizeSchemaForGoogle covering patternProperties removal,
  const→enum conversion at various depths, arrays, deeply nested objects, pass-through
- Simplify redundant recursion branches into single typeof object catch-all
- Fix misleading comment ("only in anyOf/oneOf") — conversion happens everywhere
- Drop unnecessary (p: Part) annotation; TypeScript infers it from @google/genai types

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 22:21:20 -06:00