Commit Graph

6313 Commits

Author SHA1 Message Date
can1357 1191fdedc0 fix(scripts): added fetch.pruneTags=false to git wrapper to
- Added fetch.pruneTags=false to git wrapper to prevent tag deletion during concurrent maintenance.
- Implemented atomic tag creation and push with retry logic to defend against tags being pruned by background git maintenance processes.
- Changed push strategy to use --atomic flag and retry up to 3 times on refspec mismatch errors.
2026-05-28 12:37:26 +02:00
can1357 eca3a08d25 chore: bump version to 15.5.9 2026-05-28 12:09:01 +02:00
can1357 cc258b1757 feat(natives): added embedded addon tarball extraction in natives
- Added embedded addon tarball output in `embed-native.ts` using `embedded-addons.<platform>.tar.gz` artifacts.
- Added metadata-rich addon types with `size`, `filePath`, and optional `archive` fields.
- Updated extraction to prioritize archive unpacking and skip cached `.node` files when sizes match.
- Added `extractEmbeddedAddonArchive()` with archive parsing and safe validation of archive entry names and kinds.
- Adjusted release profile to disable line-table generation and strip symbols in `Cargo.toml`.
- Added CI-only ELF validation for forbidden sections and regression coverage for issue-823 archive extraction.
2026-05-28 11:48:32 +02:00
can1357 6cc91fcb37 chore: bump version to 15.5.8 2026-05-28 10:37:49 +02:00
can1357 91d15b2ec8 fix(hashline)!: removed single-number hunk header shorthand
- Rejected bare `A` anchors; single-line ranges must now be spelled `A A`.
- Added a descriptive error for single-number headers to guide model output.
- Updated grammar, tokenizer, prompt docs, and tests to reflect the change.
2026-05-28 10:36:49 +02:00
can1357 509963bd63 feat(coding-agent/internal-urls): enabled vault:// protocol behind vault.enabled gate
- Added a `vault.enabled` setting and `isVaultEnabled` guard, and vault resolve, write, and path resolution now threw a disabled error when the feature was off.
- Improved CLI handling by parsing active vault path output and treating `Error:` lines from stdout/stderr as command failures.
- Updated tests to validate the disabled gate, cached active-vault path resolution, and CLI error surfacing on successful exit codes.
2026-05-28 10:17:56 +02:00
can1357 5053a6a4d3 fix(coding-agent): corrected coding-agent incomplete stop recovery logic
- Handled "incomplete" stop reasons in session recovery and auto-compaction workflows.
- Dropped the prior assistant turn before attempting recovery on incomplete-length stops.
- Expanded auto-compaction reason types and triggers to include "incomplete".
- Updated internal URLs parsing internals, export order, tests, and Obsidian URI prompt docs.
2026-05-28 10:10:34 +02:00
can1357 1709172bfe feat(coding-agent): added obsidian integration
- Added vault:// URL parsing, typed variants, and path resolution with vault-root validation.
- Added VaultProtocolHandler with fs and Obsidian CLI-backed resolve/read/write/list support plus caching.
- Added vault scheme integration in router, path utils, and plan-mode guard using resolveVaultUrlToPath.
- Documented vault:// read/edit and `?op`-scoped URI formats in system prompts when Obsidian is available.
- Secured vault:// operations by rejecting traversal, absolute, and symlink-escape path cases.
- Fixed response.incomplete recovery by dropping truncated turns and promoting context.
- Added internal tests for vault protocol parsing, caching, CLI behavior, and invalid-path defenses.
2026-05-28 10:10:34 +02:00
can1357 c1fa0e9f50 refactor(agent): replaced keepalive utility with disposable EventLoopKeepalive
- Replaced the `keepaliveWhile` Promise wrapper with a new `EventLoopKeepalive` class that registers and disposes an interval timer through `Symbol.dispose`.
- Updated `Agent` to instantiate `EventLoopKeepalive` via `using` during prompt execution instead of manually managing an interval.
- Wrapped interactive mode's await path with the new helper and removed redundant `keepaliveWhile` usage from the CLI entrypoint.
2026-05-28 09:51:57 +02:00
Can Bölük e799ef560e Merge pull request #1464 from hezhiyang2000/fix/agent-prompt-keepalive
fix: add EventLoopKeepalive to Agent.prompt() for session.prompt() busy-wait
2026-05-28 10:46:27 +03:00
Can Bölük 20584149ea Merge pull request #1461 from can1357/farm/c2d56198/http-mcp-get-sse-timeout
fix(mcp): bound optional HTTP SSE startup
2026-05-28 10:46:17 +03:00
Can Bölük 8eb4ff13d6 Merge pull request #1471 from daandden/fix/codex-web-search-gpt55
fix(codex): prefer gpt-5.5 for web search
2026-05-28 10:46:09 +03:00
Can Bölük 3d292aa48a Merge pull request #1470 from duiguangbin810/fix/docs-typos-and-changelog
docs: fix stale links and add missing CHANGELOGs
2026-05-28 10:46:02 +03:00
Can Bölük 8e22eb6473 Merge pull request #1468 from oldschoola/feat/wafer-provider
feat(ai): add Wafer Pass and Wafer Serverless providers
2026-05-28 10:45:55 +03:00
Can Bölük 80260c6fc4 Merge pull request #1466 from shyndman/shared-python-memory-space
fix(coding-agent): share Python kernel for `$`
2026-05-28 10:45:37 +03:00
Vu Anh Nguyen 674d9b00a2 fix(codex): prefer gpt-5.5 for web search 2026-05-28 14:02:52 +07:00
hezhiyang2000 f71e1db0c2 fix: restore #emit listener isolation (isPromise + try/catch)
The previous commit accidentally dropped the try/catch in #emit
because the local agent.ts was based on an older main that lacked
the listener-isolation code. Restore it to match main.
2026-05-28 14:09:01 +08:00
duiguangbin810 271a86eabb docs: fix stale links and add missing CHANGELOGs
- Fix typo "stauts" → "status" in stream.test.ts comment
- Update frontmatter.ts link to packages/utils/src/ (moved from coding-agent)
- Update notebook.ts link to src/edit/ (moved from src/tools/)
- Mark removed bash-normalize.ts in docs and update description
- Add CHANGELOG.md for swarm-extension and utils packages

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 13:54:56 +08:00
bench-local aed34e9ed2 fix(ai): correct Wafer cost convention — retail rate for Serverless, zero for Pass
Addresses codex review on PR #1468 (P2): the bundled catalog was
under-reporting Serverless costs and (in the original commit, since
fixed) zeroing billable models.

Two issues compounded:

1. The `*_cents_per_million` field on `/v1/models` is *not* literal
   cents. Cross-referencing every published model on wafer.ai's
   Serverless rate card against the API envelope yields an exact 1.25×
   ratio (120 → $1.50, 48 → $0.60, 88 → $1.10, 15 → $0.19, …). The
   mapper now converts via `value × 125 / 10000` (multiply-first so the
   result is a finite dyadic for every observed value — `12 × 0.0125`
   produced `0.15000000000000002`, the integer-first form yields exactly
   `0.15`).
2. The Pass SKU is a flat-rate subscription with no per-token charge.
   Convention in this repo is to seed plan providers at `cost: 0`
   (see `kimi-code`, `firepass`, `alibaba-coding-plan`). The mapper now
   short-circuits Pass with all-zero cost regardless of envelope.

Updated all 7 wafer-serverless bundled entries to retail rates and
zeroed the 2 wafer-pass entries.

Tests:
- Existing assertion on Kimi-K2.6's cost updated to the retail rate
  (1.1 / 4.8 / 0.1125).
- New mapper-level test fans the same upstream record through both
  `waferPassModelManagerOptions` and `waferServerlessModelManagerOptions`
  and asserts Pass → `{ 0, 0, 0, 0 }`, Serverless → retail conversion
  (120/360/12 → 1.5/4.5/0.15). Locks the convention against future
  regressions.

7 pass, 0 fail, 66 expect() calls. `bun check` clean.
2026-05-27 21:10:19 -07:00
bench-local 36d8d2eb3c fix(ai): pick Wafer thinking format per upstream backend, not blanket zai
The prior `mapWaferModel` pinned `thinkingFormat: "zai"` on every reasoning
model. That's the native shape for Z.AI/GLM and Moonshot Kimi, but the
wrong wire for DeepSeek and Alibaba Qwen — and Wafer passes the body
through to the partner backend rather than normalizing.

  - DeepSeek V4 reasoning uses `reasoning_effort` ("openai" format) and
    requires `reasoning_content` replay on assistant tool-call turns.
    Sending `thinking: { type: "enabled" }` is either ignored or 400'd
    depending on the backend; in either case it skips engaging thinking.
  - Alibaba Qwen models use top-level `enable_thinking: boolean`
    ("qwen" format), not zai's binary thinking object.

The mapper now reads `wafer.provider` from the `/v1/models` envelope and
maps:
  - `zai` / `moonshotai` → `thinkingFormat: "zai"`
  - `qwen`               → `thinkingFormat: "qwen"`
  - `deepseek` and unknown → omit; `detectOpenAICompat` picks the right
    default from the id at request time (deepseek-* → "openai" effort
    plus reasoning_content replay + tool-choice/reasoning guards).

Bundled catalog updated to match:
  - `GLM-5.1` (Pass + Serverless) and `Kimi-K2.6` keep `thinkingFormat: "zai"`
    explicitly — auto-detect would mis-pick "openai" for these because
    the Wafer baseUrl doesn't match the api.z.ai / api.moonshot.ai URL
    patterns in `detectOpenAICompat`.
  - `qwen3.7-max` drops the explicit override; `isQwen` autodetect
    catches the lowercase id and picks "qwen".
  - `deepseek-v4-flash` / `deepseek-v4-pro` drop the explicit override;
    `isDeepseekFamily` autodetect activates `reasoning_effort` mapping
    (minimal..high → "high", xhigh → "max") plus the deepseek-specific
    invariants (`requiresReasoningContentForToolCalls`,
    `disableReasoningOnToolChoice`).

Tests:
  - `wafer.test.ts` extended with an explicit `thinkingFormat` assertion
    on every reasoning bundled entry (locks the regression).
  - New mapper-level test `Wafer dynamic discovery mapper` feeds a
    synthetic `/v1/models` response with one entry per upstream
    (zai, moonshotai, qwen, deepseek, future-provider, plus a
    non-reasoning entry) and asserts the per-upstream `thinkingFormat`
    branch — so a future regen against the live `/v1/models` can't
    silently regress this.

6 pass, 0 fail, 62 expect() calls.
2026-05-27 21:02:09 -07:00
bench-local 1f38f8d99c feat(ai): complete Wafer Serverless bundled catalog from live /v1/models
The earlier bundled catalog was missing three Serverless-only models and
had two entries whose metadata didn't match what `/v1/models` returns.
Cross-referenced against the live https://pass.wafer.ai/v1/models response
(public, unauthenticated) and rebuilt the wafer-serverless block from it.

Added:
- `qwen3.7-max` — 256k ctx, reasoning, $5/$15/$0.50 per M.
  Canonical id is lowercase; round-trips verbatim on the wire.
- `deepseek-v4-flash` — 1M ctx, reasoning, $0.14/$0.28/$0.01 per M.
- `deepseek-v4-pro` — 1M ctx, reasoning, $1.74/$3.48/$0.02 per M.

Fixed:
- `Kimi-K2.6` cost was 0; live pricing is 88/384/9 cents per M
  → $0.88/$3.84/$0.09.
- `Qwen3.6-35B-A3B` was bundled with 32k context and text-only;
  live `/v1/models` reports 256k and `vision: true`.

All three new reasoning models carry the same zai-style thinking compat
as the existing GLM/Kimi entries (`thinkingFormat: "zai"`,
`reasoningContentField: "reasoning_content"`) — Wafer normalizes reasoning
output to `reasoning_content` regardless of upstream provider.

Tests extended to cover the new entries plus the corrected Kimi pricing
and Qwen3.6 context/vision (5 cases, 47 expect() calls, all passing).
2026-05-27 20:53:34 -07:00
hezhiyang2000 af2011f5a1 fix: use inline setInterval instead of EventLoopKeepalive import
EventLoopKeepalive is not exported from yield.ts on main.
Use setInterval + unref() directly, matching the pattern in
keepaliveWhile(). Biome import order also fixed (type imports
before value imports within the same group).
2026-05-28 11:51:24 +08:00
hezhiyang2000 38d77f819d style: fix Biome import order (type imports before value imports)
Biome organizeImports sorts type imports before value imports within
the same relative-path group. Move EventLoopKeepalive import after
all type imports.
2026-05-28 11:50:15 +08:00
bench-local f6ca76728b feat(ai): add Wafer Pass and Wafer Serverless providers
Wafer (https://wafer.ai) exposes a single OpenAI-compatible endpoint
(`https://pass.wafer.ai/v1`) for two SKUs whose entitlement differs
server-side, so we model them as two parallel providers — mirroring the
firepass/fireworks split so a user with both subscriptions can switch
without re-pasting:

- `wafer-pass` — flat-rate. `/v1/models` is filtered to entries whose
  `wafer.tier === "pass_included"`.
- `wafer-serverless` — pay-as-you-go superset of Pass.

Both issue `wfr_…` keys. `/login wafer-pass` and `/login wafer-serverless`
paste-and-validate via `/v1/models`. `WAFER_PASS_API_KEY` and
`WAFER_SERVERLESS_API_KEY` are wired through `getEnvApiKey`.

Bundled catalog:
- `wafer-pass`: GLM-5.1, Qwen3.5-397B-A17B.
- `wafer-serverless`: GLM-5.1, Qwen3.5-397B-A17B, Kimi-K2.6, Qwen3.6-35B-A3B.

Dynamic discovery via `/v1/models` overlays additional models at runtime
and folds the `wafer` envelope (tier, capabilities, cents/M pricing) into
the canonical `Model<"openai-completions">` shape. GLM-family entries
carry the zai-style thinking compat (`thinkingFormat: "zai"`,
`reasoningContentField: "reasoning_content"`) so reasoning tokens land in
the right field. Cents-per-million → dollars-per-million via /100.

Tests (`packages/ai/test/wafer.test.ts`, 5 cases): bundled catalog
contract for both providers and wire-id pass-through (case-sensitive,
no rewrite — `GLM-5.1` must round-trip verbatim or upstream 404s).
Optional `packages/ai/test/wafer.live.ts` exercises a real round-trip
against `pass.wafer.ai` when `WAFER_PASS_API_KEY` is set.
2026-05-27 20:45:33 -07:00
Scott Hyndman e46ee155a8 fix(coding-agent): shared Python kernels between eval and user shortcut
- Namespaced `AgentSession.executePython()` session IDs before invoking the Python executor.
- Added a regression test proving eval state is visible to the user shortcut path.
2026-05-27 22:16:23 -04:00
hezhiyang2000 6fb1983fbc fix: add EventLoopKeepalive to Agent.prompt()
Bun 1.3.x event loop busy-waits when the only pending work is an
unresolved Promise. Agent.prompt() sets #runningPromise via
Promise.withResolvers() which stays unresolved during the entire
agent loop execution (LLM calls + tool iterations), causing ~100%
CPU even when the process is idle.

PR #1419 added keepaliveWhile() to getUserInput() in main.ts, but
session.prompt() callers (interactive mode, resume, etc.) still
await the unresolved #runningPromise, bypassing the keepalive.

Install EventLoopKeepalive directly in Agent.prompt() so all
callers are covered. Dispose in the finally block after the agent
loop completes.
2026-05-28 10:07:22 +08:00
can1357 fe0b7794d8 Merge remote-tracking branch 'origin/farm/2f1f3156/fix-google-vertex-models' 2026-05-28 03:29:17 +02:00
can1357 3c4023037e fix(ai): heal leaked stream markup
Unify Kimi, DSML, ANTML, and thinking-tag stream markup parsing behind StreamMarkupHealing so providers do not carry separate collectors.

Fixed #1462
2026-05-28 03:27:39 +02:00
can1357 7dd00c015b feat: hashline improvements for spark
- Redesigned hashline patch syntax from anchor-based (`A-B:`) to hunk-header format (`@@ A..B @@`) with unified-diff compatibility.
- Removed `autoDropPureInsertDuplicates` option and simplified apply behavior to preserve duplicated boundary and context lines.
- Changed repeat operator from `^A-B` to `&A..B` and range separator from `-` to `..` for consistency with hunk-header syntax.
- Added image resizing and dimension notes to eval tool output; improved write tool hashline header sanitation for legacy formats.
- Removed 521 lines of boundary-duplicate absorption code and simplified parser to auto-convert bare body rows and unified-diff contamination.
2026-05-28 03:06:52 +02:00
can1357 b4238b10d3 fix: resolved auth-gateway handling of 429 usage-limit responses
- Classified usage-limit gateway responses as `429 rate_limit_error` in auth handling paths.
- Aligned auth-gateway and pi-native key retrieval with derived `sessionId` for `getApiKey` lookups.
- Handled usage-limit auth failures by rotating credentials with retry hints and returning undefined when none available.
- Replaced stream auth checks with retryable-upstream logic for 401 and usage-limit errors before content.
- Expanded `extractRetryHint` parsing for `~`, `sec`, `ms`, and minute/hour units.
- Added coverage for classifyGatewayError, retry-hint parsing variants, and stream-auth retry edge cases.
2026-05-28 02:56:54 +02:00
can1357 7e46c4483b feat(ai): added image downscaling over 20 images in Anthropic prompt prep
- Updated Anthropic prompt preparation to downscale image blocks to 2000px when a request has more than 20 images.
- Added regression tests in `anthropic-many-image-resize.test.ts` for resizing above threshold and no-op below threshold.
2026-05-28 02:23:01 +02:00
can1357 230ca08409 fix(ai): resolved auth-gateway classification by status-code precedence
- Added optional `name` support to tool message schema, coercing blank values to undefined.
- Tracked assistant tool-call IDs to resolve `tool` message names from prior calls when wire names are missing.
- Updated auth-gateway classification to prefer explicit/embedded status codes over text heuristics.
- Added word-boundary matching, expanded parse/error tests, and updated changelog entries.
2026-05-28 01:45:32 +02:00
roboomp 2266fdae82 fix(mcp): honor disabled mcp timeouts for sse startup
When the operator disables MCP client-side timeouts via timeout: 0 or OMP_MCP_TIMEOUT_MS=0, do not impose a 1s startup deadline on the optional HTTP GET SSE listener — let the listener wait as long as the server takes so server-to-client messages are not lost.

Refs #1460
2026-05-27 23:37:10 +00:00
roboomp c0c9049cca fix(mcp): bounded optional http sse startup
Abort the optional Streamable HTTP GET SSE listener attempt after a short bounded startup window so POST-only request/response servers can finish initialization.

Fixes #1460
2026-05-27 23:32:38 +00:00
can1357 7c64576524 feat(hashline): replaced file-hash anchors with opaque snapshot-store tags
- Replaced 4-hex content-derived file hashes with 3-hex opaque tags minted by InMemorySnapshotStore, making tags session-bound pointers rather than content fingerprints.
- Removed lru-cache dependency; replaced LRU-bounded per-path rings with a flat 4096-slot global ring using a scrambled permutation to prevent LLM tag extrapolation.
- Made SnapshotStore required in Patcher (was optional); tag resolution now drives stale-anchor detection instead of recomputing hashes at apply time.
- Changed literal payload sigil from `|` to `+` and accepted `^A` shorthand for `^A-A`; added lenient recovery for bare bodies, lone `-` rows, and overlapping bare/concrete block pairs.
2026-05-28 01:00:23 +02:00
can1357 3d5f0d8868 refactor(coding-agent/cli): switched auth-broker serve to dedicated logger transport setter
- Updated the auth-broker CLI to import the transport setter from the logger module.
- Replaced the logger.setTransports call in runServe with the dedicated setTransports helper.
2026-05-28 00:51:35 +02:00
can1357 6491fff8f6 feat(ai): added strict auth-gateway mode with completion-probe checks
- Added strict `auth-gateway` check mode, propagated `--strict`, and updated strict output/exit rules.
- Added `checkCredentials` completion-probe support with timeout and provider-aware payload helpers.
- Changed OAuth credential checks to refresh first, preserve usage results, and skip completion on refresh failures.
- Added tests for completion-probe execution, OAuth refresh rejection, and `completion.reason`/sentinel behavior.
2026-05-28 00:35:15 +02:00
can1357 9474e95cb5 feat(coding-agent/tools): enabled shebang files to be auto-marked executable
- Added a `madeExecutable` result field to `WriteToolDetails` to surface executable changes.
- Implemented `maybeMarkExecutableForShebang` to chmod shebang files executable while preserving existing mode bits and swallowing chmod errors.
- Updated write flow and renderer output to return and display when a file was auto-marked executable.
2026-05-28 00:34:11 +02:00
can1357 7fa55750f9 feat(hashline): introduced explicit range syntax and repeat edit kind for hashline
- Replaced anchor shorthand syntax with explicit range format (1: -> 1-1:) and removed ^/v sigils in favor of ^A-B repeat and A-B:- delete operations.
- Added repeat edit kind to support ^A-B syntax for copying lines A through B, and inline delete syntax A-B:- for range deletions.
- Removed after_anchor cursor kind and standalone delete rows; empty anchor blocks now produce blank-line replacements instead of deletions.
- Updated parser, tokenizer, and type system to discriminate literal and repeat payloads, and refactored apply/recovery logic to expand repeat edits into individual inserts.
- Updated coding-agent test fixtures and settings documentation to reflect new hashline syntax and behavior.
2026-05-27 22:51:21 +02:00
roboomp ac7f6e4d11 fix(ai): added vertex anthropic_version to rawPredict bodies
Rewrote Vertex Claude rawPredict request bodies to drop the Anthropic "model" field and inject "anthropic_version": "vertex-2023-10-16", matching Vertex's required JSON shape, and asserted both invariants in the regression test.

Fixes #1456
2026-05-27 19:32:38 +00:00
roboomp e8b510160c fix(ai): routed vertex claude through raw predict
Mapped Google Vertex Claude catalog entries to the Anthropic messages transport, rewrote placeholder rawPredict URLs with ADC auth, and covered the request URL and payload shape.

Fixes #1456
2026-05-27 19:26:05 +00:00
roboomp 3ea4981eeb fix(ai): updated google vertex model catalog
Replaced Google Vertex project discovery with the models.dev catalog so bundled model selection includes current Vertex MaaS and Gemini entries while pruning retired fallbacks.

Fixes #1456
2026-05-27 19:14:26 +00:00
can1357 6fac33f099 chore: fix broken native export headers 2026-05-27 20:27:07 +02:00
can1357 1dbd2a0659 fix(coding-agent): pin streaming diff preview to tail of the diff 2026-05-27 19:57:54 +02:00
can1357 b87cd8f93f chore: bump version to 15.5.7 2026-05-27 19:01:33 +02:00
can1357 0ab8e87f7d test(coding-agent): updated test input to match model typing and replacements
- Narrowed the xai-oauth bundled model cast to `Model<"openai-responses">` in its regression test.
- Changed hashline stale-recovery fixtures to use `repl(...)` for both line-replacement payloads instead of `extra(pl(...))`.
2026-05-27 19:01:11 +02:00
roboomp 9362cbf13d style: bun run fix 2026-05-27 19:00:49 +02:00
roboomp efba782fa7 fix(tools): isolate read URL reader-mode fallback chain from remote stalls
A stalled Jina reader request shared the overall reader-mode AbortSignal
with the downstream trafilatura/lynx/native fallbacks. When Jina hung
until the budget timer fired, the shared signal aborted and the catch
handler's signal?.throwIfAborted() re-threw before any local fallback
ran.

- Bound Jina and Parallel extract to their own per-attempt sub-budget
  (REMOTE_READER_MAX_MS, capped at 10s) so a remote stall cannot consume
  the whole overall reader-mode budget.
- Catch handlers now rethrow only on real userSignal cancellation, not
  on remote sub-budget or overall budget expiry.
- Wrap trafilatura/lynx in their own try/catch so a subprocess failure
  or abort does not skip the in-process native renderer.
- Always attempt the native renderer last: it works on already-loaded
  HTML with no network or subprocess, so even an exhausted overall
  budget still yields a result.

Fixes #1449
2026-05-27 19:00:49 +02:00
Can Bölük bb57d5eee5 Merge pull request #1442 from hanbinnoh/fix/xiaomi-tp-cn-fallback
fix(xiaomi): add CN token-plan cluster as last fallback
2026-05-27 20:00:42 +03:00
Can Bölük fde04c28b2 Merge pull request #1422 from oldschoola/hashline-session-chain-content-gate
fix(hashline): require anchor-content alignment in session-chain replay recovery
2026-05-27 19:58:09 +03:00