Commit graph

440 commits

Author SHA1 Message Date
Mikael Hugo
d73a73d7f3 chore: node 24 native APIs, import.meta.dirname, parsers rename, dep updates
- Replace fileURLToPath(import.meta.url) with import.meta.dirname across
  scripts and extensions
- Rename parsers-legacy.ts → parsers.ts
- Remove deleted plan/spec docs (cicd-pipeline)
- Update package.json engines and deps across workspace packages
- Update web/package-lock.json

💘 Generated with Crush

Assisted-by: GLM-5.1 via Crush <crush@charm.land>
2026-05-02 06:18:25 +02:00
Mikael Hugo
980772cc90 refactor: migrate from better-sqlite3 to node:sqlite, npm glob to node:fs
Since Node >= 24 is the minimum engine, remove the better-sqlite3 fallback
chain from sf-db.ts, unit-ownership.ts, and cli-stats.ts. Use DatabaseSync
from node:sqlite directly. Also replace the `glob` npm package with built-in
node:fs/promises.glob and node:fs.globSync in pi-coding-agent LSP utils.

- Remove createRequire boilerplate and suppressSqliteWarning helper
- Simplify loadProvider() and openRawDb()
- Net -177 lines of fallback/middleware code

💘 Generated with Crush

Assisted-by: GLM-5.1 via Crush <crush@charm.land>
2026-05-02 06:13:57 +02:00
Mikael Hugo
df03312fa5 test: stabilize vitest compatibility 2026-05-02 05:36:57 +02:00
Mikael Hugo
3ddb8c84e0 chore: commit current worktree state 2026-05-02 05:11:03 +02:00
Mikael Hugo
e44237e526 test: final vitest API migration fixes across all packages and extensions 2026-05-02 04:49:34 +02:00
Mikael Hugo
5cf94c296e test: complete vitest mock API fixes for callCount and calls access 2026-05-02 04:47:41 +02:00
Mikael Hugo
1de5d5456a chore: complete vitest migration for remaining packages and API calls
- Convert remaining node:test → vitest imports in packages/* and studio/*
- Fix mock.callCount() → mock.callCount property access for vitest compat
- Fix mock.calls[N].arguments → mock.calls[N] for vitest compat
- Update tsconfig.extensions.json to exclude test files from tsc
- Harden migrate-to-vitest-all.mjs regex for single quotes and optional semicolons
2026-05-02 04:46:11 +02:00
Mikael Hugo
b62f7b20ec fix: convert node:test API calls to vitest equivalents
- t.after() → afterEach() with import injection
- t.before() → beforeEach() with import injection
- t.test() → test() (flatten subtests)
- t.skip() → return with skip comment
- Fix vitest.config.ts poolOptions deprecation for Vitest 4
- Run fix-vitest-api.mjs across 108 affected test files

💘 Generated with Crush

Assisted-by: GLM-5.1 via Crush <crush@charm.land>
2026-05-02 04:42:38 +02:00
Mikael Hugo
59aaf3dcf3 chore: migrate test suite from node:test to vitest
Add vitest.config.ts with forks pool, v8 coverage, and package aliases.
Run migrate-to-vitest.mjs to replace `from "node:test"` imports with
`from 'vitest'` across 749 test files, converting mock.fn→vi.fn and
mock.timers→vi fake timers where needed.

💘 Generated with Crush

Assisted-by: GLM-5.1 via Crush <crush@charm.land>
2026-05-02 04:37:33 +02:00
Mikael Hugo
2508822b8f refactor(pi-ai): simplify Codex OAuth + minor fixes across pi-ai and sf
- openai-codex.ts: replace hand-rolled PKCE flow with simple read of
  ~/.codex/auth.json written by the real codex CLI after user authentication.
  Removes ~250 lines of local callback server + browser dance code.
- openai-codex-responses.ts: minor residual cleanup
- openai-completions.ts: drop remaining `as any` stream_options cast
- anthropic-shared.ts: use `unknown` cast on thinkingNoBudget path
- pi-coding-agent/extensions/types.ts: minor type addition
- db-tools.ts: explicit AgentToolResult return type on execute handlers
- requesting-code-review/SKILL.md: prompt wording cleanup
- subagent/index.ts: capability registration wiring

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 03:25:39 +02:00
Mikael Hugo
2846c296ee chore(pi-ai): typecheck cleanup, empty-catch comments, OAuth audit notes
- package.json: add 'typecheck' script (build:pi + tsc --noEmit) so pi-ai
  and pi-coding-agent typecheck under the same command surface SF uses.
- anthropic-shared.ts: replace 'as any' casts with proper Anthropic SDK
  types (ServerToolUseBlockParam, WebSearchToolResultBlockParam,
  CacheControlEphemeral). The cache_control variant is documented inline
  so the cast is auditable.
- openai-completions.ts: drop the 'as any' on stream_options — the type
  system can verify the assignment now.
- openai-codex-responses.ts, package-manager.ts, skills.ts: annotate the
  three remaining empty catches with one-line WHY comments (best-effort
  cleanup, malformed ignore files, partial directory traversal). Empty
  catch with no rationale is an SF012 anti-pattern; with rationale it is
  a deliberate fallback.
- oauth/github-copilot.ts, oauth/openai-codex.ts: add UPSTREAM AUDIT
  blocks documenting why these hand-rolled OAuth flows stay hand-rolled
  rather than delegating to @octokit/auth-oauth-device or @openai/codex.
  AbortSignal coverage and provider-specific surface area are the gating
  concerns; re-audit triggers are named.
2026-05-02 03:20:25 +02:00
Mikael Hugo
ed47951960 feat(pi-ai): delegate google-gemini-cli auth + project to cli-core
Replace ~700 LOC of hand-rolled OAuth and onboarding with cli-core's own
getOauthClient + setupUser. The provider now reads ~/.gemini/oauth_creds.json
itself (via cli-core), refreshes tokens, and discovers the Code Assist
project + tier server-side — exactly like the real gemini CLI does.

- provider/google-gemini-cli.ts: drop apiKey={token,projectId} JSON
  plumbing; getCodeAssistServer() uses cli-core for everything
- delete utils/oauth/google-gemini-cli.ts (457 LOC: hand-rolled login,
  PKCE, callback server, discoverProject, onboardUser, tier handling)
- delete utils/oauth/google-oauth-utils.ts (201 LOC: only consumed by
  the deleted gemini-cli helper)
- oauth/index.ts: remove gemini-cli from BUILT_IN_OAUTH_PROVIDERS
  registry; google-gemini-cli is no longer SF-managed
- auth-storage.ts: update 3 error messages to direct users to the real
  gemini CLI for authentication instead of the removed /login command

Login UX: users authenticate with the real gemini CLI; we just consume
~/.gemini/oauth_creds.json. Whole-provider disable goes through manual
settings.json edit (per-model toggle still works in interactive UI).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 01:47:48 +02:00
Mikael Hugo
a055b3adf2 feat: structured notification event model with metadata-first classification
Replace brittle string-matching in headless-events.ts with structured
source/kind/blocking/dedupe_key metadata on notify() events. String
matching is preserved as a fallback for the ~940 untagged call sites.

- Add NotificationMetadata type to headless-types.ts (canonical definition)
- Extend rpc-types.ts notify event with optional metadata field
- Extend ExtensionUIContext.notify() signature with optional 3rd arg
- Pass metadata through RPC notify implementation in rpc-mode.ts
- Update headless-events.ts: isTerminalNotification, isBlockedNotification,
  isMilestoneReadyNotification, isPauseNotification all check metadata first
- Update notification-store.ts: store metadata on NotificationEntry; use
  metadata.dedupe_key as dedup key when provided (falls back to message hash)
- Update notify-interceptor.ts to thread metadata through to store + original
- Tag critical emit sites with structured metadata:
  stopAuto → { kind: "terminal" } (+ blocking: true when reason includes "block")
  pauseAuto → { kind: "terminal", blocking: true }
  guided-flow milestone ready → { kind: "approval_request", blocking: true }
- Update notification-overlay.ts to prefer metadata.source for [label] display
- Add 17-test regression suite (notification-event-model.test.ts)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-01 23:07:57 +02:00
Mikael Hugo
12e7333f1c feat: stabilize autonomous workflow system 2026-05-01 20:18:50 +02:00
Mikael Hugo
51202225ec test: Add canonicalizePath() utility using fs.realpathSync() with symli…
SF-Task: S01/T02
2026-04-30 22:42:08 +02:00
Mikael Hugo
8418e88730 feat: Port R101 setWorkingVisible API and R104 Azure Cognitive Services…
SF-Task: S01/T01
2026-04-30 22:28:01 +02:00
Mikael Hugo
b43bf6991e sf snapshot: pre-dispatch, uncommitted changes after 47m inactivity 2026-04-30 20:21:12 +02:00
Mikael Hugo
8e4081e6f1 test: Verified existing tests cover skill proposal writer and all four…
SF-Task: S03/T02
2026-04-30 19:33:16 +02:00
Mikael Hugo
2111da8e60 sf snapshot: pre-dispatch, uncommitted changes after 53m inactivity 2026-04-30 19:10:38 +02:00
Mikael Hugo
e90298f2e0 sf snapshot: pre-dispatch, uncommitted changes after 120m inactivity 2026-04-30 17:44:03 +02:00
Mikael Hugo
8677e73046 sf snapshot: pre-dispatch, uncommitted changes after 97m inactivity 2026-04-30 15:11:45 +02:00
Mikael Hugo
62d430ab23 Add provider smoke benchmark and headless updates 2026-04-30 10:19:18 +02:00
Mikael Hugo
cd69e85608 Harden SF model routing and harness contracts 2026-04-30 07:41:24 +02:00
Mikael Hugo
a45f873124 chore: snapshot WIP before resuming M004/S03 auto
84 files spanning provider capabilities, model routing, headless
runtime, sf auto subsystems, gitbook docs, and test coverage. Snapshotted
so headless auto can resume M004 (Production Readiness) S03
(Verification Gate Validation) on a clean tree.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 06:31:19 +02:00
Mikael Hugo
9c4bf9b3e6 fix(sf): use live ollama k2.6 routes 2026-04-29 21:38:51 +02:00
Mikael Hugo
d0907b6d87 port(pi-mono): disable undici body/headers idle timeouts on global dispatcher (refs ea90a6783)
Pi-mono Tier 0 #4 — manual port (sf went off-task; ported directly).

undici's default 300s bodyTimeout aborts long local-LLM SSE streams
(e.g. vLLM buffering a large tool call) with UND_ERR_BODY_TIMEOUT.
retry.provider.timeoutMs cannot lift this cap — it controls the
provider SDK's AbortController, not undici's per-socket idle timer.

Pass {bodyTimeout: 0, headersTimeout: 0} to EnvHttpProxyAgent. Provider
SDKs continue to enforce their own deadlines.

Type-check passes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 14:35:08 +02:00
Mikael Hugo
701ec8fb88 port(pi-mono): escape session metadata + image data in HTML export (refs 7617c1ad9, 57787b655)
Pi-mono Tier 0 #1 (security) — sf-driven port.

Two upstream security fixes (pi-mono PR #3819, #3883) that escape
user-controlled session content before embedding in HTML exports.
Crafted session content (image mime types, image data, model IDs,
tool names, entry IDs) could otherwise inject markup at the export
boundary.

What sf changed in
packages/pi-coding-agent/src/core/export-html/template.js:

- Image tags: escape `mimeType` and `data` attributes for both
  tool-result and user-message image renders (PR #3819).
- Session metadata: escape `msg.toolName`, `msg.role`, `entry.modelId`,
  `entry.thinkingLevel`, `entry.type`, `entry.id`, and
  `globalStats.models` (PR #3883).
- DOM id construction: renamed `entryId` → `entryDomId` and escape
  `entry.id` to prevent attribute-breakout from a crafted id.

The existing `escapeHtml()` helper was used at every site; no new
helper introduced. Type-check passes.

Co-Authored-By: sf v2.75.1 (session 150fe2c1)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 14:20:23 +02:00
Mikael Hugo
d38e5ea092 fix(schema): auto-coerce string → [string] for sf_* list fields + provider_model_allow tests
Two codex-rescue tasks landed together:

1. Auto-coerce JSON-schema validator: when a tool field declares
   {type:"array", items:{type:"string"}} and the model sends a single
   string, wrap it in [string] before validation instead of hard-rejecting.
   Fixes the recurring "keyDecisions: must be array" rejection on
   sf_complete_task that wasted retries.

2. Provider_model_allow filter (proper implementation with helpers):
   - resolveProviderModelAllowList / isProviderModelAllowed /
     filterModelsByProviderModelAllow helpers in preferences-models
   - Wired into model-registry and auto-model-selection
   - New tests/provider-model-allow.test.ts

Tools coerced: sf_complete_task, sf_complete_milestone, sf_plan_milestone,
sf_plan_slice, sf_replan_slice, sf_reassess_roadmap (key list fields).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: OpenAI Codex <noreply@openai.com>
2026-04-28 12:30:55 +02:00
Mikael Hugo
f98a1e360e batch: codex-rescue session output (multiple in-flight tasks)
Combined output of multiple parallel codex-rescue runs that produced
working-tree edits but didn't commit. Tasks contributing:

- prefs: per-provider model allow-list (provider_model_allow) — manual
- TUI scroll + unresponsive (a7884d1a / bt3fpn4y2)
- planningMeeting required (aa09e904 / br127l763)
- Logs UX 4-pack (a5c65314 / btcplhu7f)
- Gate auto-resolve + completion nudge (ae4c8b64 / bw1w1fjkp)
- sf_task_complete atomic + retry (a7a079b4 / b20cy5owv)
- Multi-model meeting + minimax M2.7 + draft promotion (a756faac / task-moifjknd-lwjc98)
- Per-role slice prompts (a94c3e1a)
- Per-role vision-meeting prompts (afd165a0 / task-moifple5-lcwtjl)
- Schema sweep (ac994b1e / task-moifq7pu-83coqz)
- Flow audit (ad26ecfd / bttj4vrqm)

Typecheck passes. Tests not run as a full suite — spot-check after merge.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: OpenAI Codex <noreply@openai.com>
2026-04-28 11:52:42 +02:00
Mikael Hugo
2911d3b93d port gsd2: reassess-roadmap opt-in (ADR-003 §4) + prefer toolDefinition.label
reassess-roadmap: flip default from true → false. Most reassess units
conclude "roadmap is fine" burning a session for no change; the
plan-slice prompt now carries a JIT preamble at zero cost. (#4778)

tool-execution: always prefer toolDefinition.label when non-empty,
even when label === name — allows tools to display their canonical
name explicitly. (#4758)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 08:33:50 +02:00
Mikael Hugo
4fdd8700a3 port gsd2 upstream features: scope classifier, composer v2, GPT-5.5, test timeout
- milestone-scope-classifier: add getMilestonePipelineVariant + milestoneRowToScopeInput
  wired into auto-dispatch trivial-skip for research/validation phases (#4781)
- auto-prompts: rename GSD→SF identifiers, add isSummaryCleanForSkip, prefs param
  on checkNeedsReassessment, buildExtractionStepsBlock from commands-extract-learnings
- unit-context-manifest + unit-context-composer: port v2 typed computed artifacts (#4924)
- skill-manifest: per-unit-type skill filter resolver (#4788, #4792)
- escalation: stub for ADR-011 mid-execution escalation (full port deferred)
- auto-start: extract decideSurvivorAction for testability (#4832)
- models: add gpt-5.5 + gpt-5.4-mini to cost table, router, and models.generated.ts
- types: EscalationArtifact, context_window_override, skip_clean_reassess,
  mid_execution_escalation, sketch_scope on SliceRow
- tool-execution: add visibleWidth import (was undefined)
- package.json: add --test-timeout=30000 to prevent parallel tests from freezing machine

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 08:08:11 +02:00
Mikael Hugo
e2147c0694 sf snapshot: pre-dispatch, uncommitted changes after 43m inactivity 2026-04-25 06:34:49 +02:00
ace-pm
e63184f91d
fix(migrations): drop press-any-key block to avoid stdin wedge
showDeprecationWarnings ran setRawMode(true)/once('data')/setRawMode(false)/
pause() right before pi-tui's own stdin setup. That handoff is fragile —
buffered bytes and mode flips between the migration prompt and the TUI's
raw-mode setup can leave stdin cooked and line-buffered, producing the
'Enter does nothing + garbled typing' symptom.

Warnings now print non-blocking. They stay visible in scrollback above
the TUI, so users still see them without a blocking acknowledge step.
2026-04-21 00:56:18 +02:00
Mikael Hugo
59806f8cc5 rip out antigravity from SF + pi-coding-agent UI/config layer
Antigravity (Google's IDE sandbox product, different from Gemini CLI) is
removed from:

  src/onboarding.ts                         — drop from LLM_PROVIDER_IDS + OAuth-flow picker
  src/pi-migration.ts                       — drop from LLM_PROVIDER_IDS migration list
  src/web/onboarding-service.ts             — drop from web-UI provider list
  src/tests/integration/web-onboarding-contract.test.ts — update contract
  src/resources/extensions/sf/doctor-providers.ts — drop from CLI_AUTH_PROVIDERS
  src/resources/extensions/sf/key-manager.ts      — drop UI listing
  src/resources/extensions/sf-usage-bar/index.ts  — delete entire quota fetcher block (~200 lines)
  packages/pi-coding-agent/src/cli/args.ts        — drop PI_AI_ANTIGRAVITY_VERSION doc
  packages/pi-coding-agent/src/utils/proxy-server.ts — drop from claude provider chain

Reason: antigravity has no vendor-published core library we can embed
(unlike @google/gemini-cli-core for the Gemini CLI). Continuing to
hand-roll OAuth against daily-cloudcode-pa.sandbox.googleapis.com is
exactly the pattern Google has started banning for third-party tools.
Removing the code removes the ban risk.

pi-ai provider code, OAuth util, and models.generated entries for
google-antigravity are removed in follow-up commits (separated for
reviewability — each layer verified independently).

Build passes. Note: this is a breaking change for any user who had
google-antigravity configured — they'll need to migrate to
google-gemini-cli (OAuth), google (API key), or google-vertex.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 10:39:36 +02:00
Mikael Hugo
233432d486 model-registry: drop google-antigravity from claude family_failover (preparing rip-out) 2026-04-19 10:35:56 +02:00
Mikael Hugo
ffe86284d2 model-registry: split direct vs family_failover providers per model family
Prior PROXY_FAMILY_PRIORITY table conflated "direct provider" with
"failover provider that happens to serve this family". Observed case:
claude-* family listed anthropic, google-antigravity, and
github-copilot all as "providers" — but only anthropic is the direct
vendor. google-antigravity re-serves Claude via Google's sandbox
IDE product (same endpoint as gemini-cli, different auth contract);
github-copilot re-serves via GitHub's paid platform.

This matters for the 429 fallback chain: a broken anthropic key
should try genuinely-vendored endpoints first (none, for Claude),
then fall into family_failover (antigravity, copilot), and only then
reach the generic GLOBAL_PROVIDER_FALLBACK (opencode, opencode-go,
openrouter, ollama-cloud). The old all-flat list hid this distinction.

New shape:
  { providers: [...], family_failover?: [...] }

Corrections applied:
  claude-*: providers=[anthropic], failover=[google-antigravity, github-copilot]
  gemini-*: providers=[google-gemini-cli, google, google-vertex],
            failover=[github-copilot]
  gpt-* / o* / codex-*: providers=[openai],
            failover=[azure-openai-responses, openai-codex, github-copilot]
  mimo-*: providers=[xiaomi]  (new: was [] — Xiaomi MiMo Open Platform
          is direct API at api.xiaomimimo.com / token-plan-sgp.xiaomimimo.com)

buildCandidateOrder stitches [direct, family_failover, global_fallback]
with deduplication. User overrides via settings.proxy.providerPriority
continue to replace only the direct-provider list, keeping family
failover and global fallback intact.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 10:20:32 +02:00
Mikael Hugo
6450b37025 core + search + benchmarks: auth-error recovery, multi-provider search, M2.7-highspeed entry
Four related improvements that landed in the working tree after the
auto-hardening merge but hadn't been committed:

1. auth_error as a distinct error type (auth-storage + retry-handler).
   Previously invalid/expired API keys would retry the same failing
   credential until the retry budget exhausted. Now:
     - classifyErrorType() recognizes 401s, "invalid api key",
       "authentication error", "unauthorized" etc as "auth_error"
     - RetryHandler triggers cross-provider fallback on auth_error just
       like it does for rate_limit and quota_exhausted — switch
       providers rather than burning retries on a broken key
   Outcome: a stale OPENCODE_API_KEY in sops now fails over to kimi or
   minimax immediately instead of stalling the unit.

2. Multi-provider search-key detection (native-search.ts).
   The "Web search: Set BRAVE_API_KEY" warning fired whenever a
   non-Anthropic model lacked BRAVE_API_KEY, even when the user had
   TAVILY_API_KEY or OLLAMA_API_KEY available. Now: the warning
   suppresses if any of BRAVE/TAVILY/OLLAMA keys is present, and the
   warning text lists all three options. Matches the preferences-
   validation allow-list for search_provider.

3. MiniMax-M2.7-highspeed benchmark entry (model-benchmarks.json).
   Routes the fast-tier variant of M2.7 through the Bayesian blender
   with inherited RULER scores. Lets dynamic routing consider the
   highspeed model when speed matters more than peak quality.

No regressions: the 41 pre-existing test failures in pi-coding-agent
(FallbackResolver chain-membership + LSP integration) are unchanged
relative to the prior commit.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 09:24:54 +02:00
Mikael Hugo
3bb93b1612 Cherry-pick process lifecycle fixes for multi-day autonomous operation
- shell: add trackDetachedChildPid / untrackDetachedChildPid /
  killTrackedDetachedChildren (#9b7948c)
- bash: track/untrack detached child PIDs so they are killed on shutdown
- interactive-mode: register SIGTERM/SIGHUP handlers for clean shutdown
  (#5d440b0); kill tracked bash children on shutdown
- rpc-mode: register SIGTERM/SIGHUP handlers, refactor to forceShutdown()
  that deduplicates shutdown path (#5d440b0); kill tracked bash children
- print-mode: register SIGTERM/SIGHUP handlers for graceful exit

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 14:38:55 +02:00
Mikael Hugo
aff49e52aa Cherry-pick 4 critical recovery fixes from pi-mono upstream
- agent-loop: wrap afterToolCall in try/catch so hook throws don't crash
  parallel tool batches (#3084)
- retry-handler: add "connection lost" to retryable error patterns (#3317)
- rpc-mode: redirect console.log to stderr to protect JSON stdout (#2388)
- openai-completions: ignore null/non-object chunks in stream (#2466)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 14:28:15 +02:00
Mikael Hugo
f153521c24 Cherry-pick tool bug fixes from pi-mono upstream
- compaction: fix repeated compaction dropping kept messages (#2608)
  Re-summarize from previous compaction's firstKeptEntryId instead of
  prevCompactionIndex+1; use buildSessionContext for accurate tokensBefore

- edit: add multi-edit support via edits[] array
  Single call can update multiple disjoint regions in one file;
  applyEditsToNormalizedContent matches all edits against original content
  and applies in reverse order for stable offsets

- bash: persist full output when line-count truncation occurs (#2852)
  ensureTempFile now called on any truncation, not only byte overflow;
  prevents data loss when output exceeds line limit before byte threshold

- bash-executor: same fix for remote/operations-based execution
  ensureTempFile includes SF cleanup registration (registerTempCleanup,
  bashTempFiles tracking)

- grep: include lineText from rg JSON events to avoid per-match file reads
  Eliminates stall when context=0 on broad searches (#3148)

- agent-session: forward isError override from afterToolCall extension hook
  Allows extensions to change error status of tool results (#3051)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 14:18:52 +02:00
Jeremy
b5e1beff8e fix(auth): self-heal stale Anthropic OAuth credential (#4399)
Anthropic OAuth was removed in v2.74.0 for TOS compliance (#3952). Users
who upgraded through that version still have type:"oauth" entries under
`anthropic` in auth.json which cannot resolve to a valid API key.

stale entry, so hasAuth("anthropic") kept reporting true and masked the
claude-code fallback path. Users had to hand-edit auth.json to recover.

Self-heal instead:

- AuthStorage.removeLegacyOAuthCredential(provider) strips only
  type:"oauth" entries and preserves any api_key credentials.
- sdk.ts getApiKey() calls it when the legacy-OAuth branch triggers,
  logs a one-line warning, and throws a message pointing the user at
  the "claude-code" provider when the `claude` binary is in PATH, or
  at ANTHROPIC_API_KEY otherwise.

Closes #4399

(cherry picked from commit b8ef6604617fda239a037cf5d5e6020b168d2e62)
2026-04-18 13:40:02 +02:00
Yeon Gil Kang
b73763d944 fix(pi-ai): hide unsupported ChatGPT codex oauth models
ChatGPT-backed Codex sign-in no longer exposes the removed 5.1/5.2 Codex variants. Filter those models from openai-codex OAuth so GSD stops surfacing selections that immediately fail while leaving API-key-backed OpenAI models available.

(cherry picked from commit 1aedba583916826fc5c6129037f61e9802010e46)
2026-04-18 13:35:45 +02:00
Mikael Hugo
78c5c3a78b Add proxy routing tests; fix two build errors
- 15 tests for ModelRegistry.getModelsForProxy covering family priority
  ordering, auth-ready promotion, overrides, and edge cases
- Fix StreamOptions cast in proxy-server.ts (lost during rebase conflict)
- Fix .ts import extension in args.test.ts (pre-existing)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 12:40:03 +02:00
Mikael Hugo
30730dd25b Fix rebrand artifacts, add family-priority model routing to proxy server
- Update Dockerfile image name and package.json URLs to singularity-ng/singularity-foundry
- Add uv to nix develop shell in flake.nix
- Rename resolveGsdRoot → resolveSFRoot in src/cli.ts
- Add PROXY_FAMILY_PRIORITY routing table + sortByFamilyPriority to proxy-server.ts
- Fix duplicate scope key and simplify link-workspace-packages.cjs
- Remove duplicate conditions in postinstall.js
- Add ES2024 target/lib to tsconfig.extensions.json
- Delete obsolete GSD recovery scripts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 12:28:27 +02:00
github-actions[bot]
8f160677b7
release: v2.75.0
https://claude.ai/code/session_013BwmqG3NuwwZY3vsUb4Y9Y
2026-04-17 17:26:59 +00:00
mikkihugo
dc0db3868a
Add per-family proxy provider priority system with TUI and 429 fallback
- model-registry: export PROXY_FAMILY_PRIORITY and GLOBAL_PROVIDER_FALLBACK
  constants; add getModelsForProxy() returning candidates ordered by family
  priority then global fallback (opencode → opencode-go → openrouter →
  ollama-cloud); add getModel() convenience wrapper
- proxy-server: add priorityOverrides option; handleChat iterates all
  candidates in priority order and falls through to the next on 429
- settings-manager: add ProxySettings type with providerPriority override
  map; add getProxyProviderPriority() / setProxyFamilyProvider() accessors
- settings-selector: add ProxyPrioritySubmenu — a two-level TUI submenu
  (family → provider) that dynamically generates entries from
  PROXY_FAMILY_PRIORITY; wired in interactive-mode with full callback

Family defaults: MiniMax→minimax, GLM→zai, Kimi→kimi-coding,
MiMo→global-fallback, Gemini/Gemma→google-gemini-cli, Claude→anthropic,
GPT/o-series→openai

https://claude.ai/code/session_013BwmqG3NuwwZY3vsUb4Y9Y

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-17 19:17:50 +02:00
ace-pm
f92ee8d64c
Rename @sf-run/* → @singularity-forge/* package scope
- All 373 source files updated
- Package.json scopes in all workspace packages
- Loader workspace symlink dir updated
- RpcClient import unified from pi-coding-agent (fixes type mismatch)
- Scripts, configs, flake.nix updated
- Workspace symlinks rebuilt
2026-04-15 22:56:33 +02:00
ace-pm
9d739dfa5d Rename GSD→SF: complete rebrand from fork origin
- All gsdDir/gsdRoot/gsdHome → sfDir/sfRootDir/sfHome
- GSDWorkspace* → SFWorkspace* interfaces
- bootstrapGsdProject → bootstrapProject
- runGSDDoctor → runSFDoctor
- GsdClient → SfClient, gsd-client.ts → sf-client.ts
- .gsd/ → .sf/ in all tests, docs, docker, native, vscode
- Auto-migration: headless detects .gsd/ → renames to .sf/
- Deleted gsd-phase-state.ts backward-compat re-export
- Renamed bin/gsd-from-source → bin/sf-from-source
- Updated mintlify docs, github workflows, docker configs
2026-04-15 18:33:47 +02:00
ace-pm
421fccd898 refactor: rebrand gsd_ tool names and references to sf_ namespace
Updates workflow tool names, documentation references, and internal naming
conventions across MCP server, CLI, tests, and web components to complete
the singularity-forge rebrand from gsd to sf.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 15:51:38 +02:00
ace-pm
6b0ac484ba refactor: update log prefixes and string values from gsd- to sf- namespace
Updates channel prefixes, log messages, comments, and configuration values
across daemon, mcp-server, and related packages to complete the rebrand from
gsd to sf-run naming.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 15:37:12 +02:00