Commit Graph
7362 Commits
Author SHA1 Message Date
roboomp caee75de28 fix(ai): routed llama.cpp parallel tool calls by item.call_id
llama.cpp's /v1/responses emits function_call `output_item.added` with
only `item.call_id` (no `item.id`, no `output_index`); the matching
`function_call_arguments.delta` carries `item_id: "fc_<call_id>"`.
`processResponsesStream` keyed its lookup map by `item.id` only, so
the registry stayed empty and every delta fell back to `lastOpenItem`
— the most recently added block. With N parallel calls, N-1 of them
finalized with arguments `{}` and the agent rejected them with
`path: Invalid input: expected string, received undefined`, while the
trailing call hoarded every delta.

Register function-call and custom-tool-call items under `item.call_id`
as a secondary key alongside `item.id`/`output_index`, and look up by
the same fallback in `output_item.done`. Real OpenAI is unaffected
(distinct keys, both populated). Regression test pins the exact
llama.cpp emission shape.

Fixes #2015
2026-06-06 22:18:44 +00:00
can1357 485cc3fc0a fix(coding-agent): fixed streaming tool previews dropping scrolled-off output
- ToolExecutionComponent was updated to skip append-only treatment for finalized blocks and pass result state into `isStreamingPreviewAppendOnly`.
- Eval rendering was changed to render full code continuously and to report append-only status only once a result exists, avoiding commitment of stale pending previews.
- Live-region tests were added for expanded eval output overflow and for append-only transitions from pending to finalized streaming states.
2026-06-06 23:26:33 +02:00
can1357 f552ce4e6d perf(coding-agent): deferred heavy module imports to startup paths
- Lazy-loaded OTEL SDK, HTML export, TTSR, and autoresearch modules.
- Made resolveMemoryBackend async to import backends on demand.
- Replaced backend resolution with direct settings reads for rekey checks.
2026-06-06 23:25:18 +02:00
can1357 5ec6c0e7a7 fix(coding-agent): removed redundant official-id canonical shortcut
- Let heuristic candidate matching handle official ids uniformly.
2026-06-06 23:07:57 +02:00
can1357 76f08dd7d3 refactor(packages/coding-agent): migrated imports to pi-ai submodules
- Migrated Effort and THINKING_EFFORTS imports to @oh-my-pi/pi-ai/effort in CLI args and launch command files.
- Split model-registry dependencies across focused @oh-my-pi/pi-ai submodules instead of the root barrel export.
2026-06-06 22:58:33 +02:00
can1357 ba6cc67f38 refactor(packages/ai): migrated effort types to dependency-free module
- Added dependency-free `@oh-my-pi/pi-ai/effort` module and re-exported `Effort`/`THINKING_EFFORTS`.
- Moved `Effort` and `THINKING_EFFORTS` from `model-thinking.ts` to `effort.ts`, then migrated runtime/tests imports.
2026-06-06 22:58:33 +02:00
can1357 e5e93ff762 feat(packages/coding-agent): enabled setup-version-gated startup flow
- Deferred setup wizard import until setup was forced or version stale.
- Dynamically loaded ACP, RPC, and print mode runners only when used.
- Added a marketplace auto-update scheduler with off-mode early exit and non-blocking errors.
- Added setup-version assertions to keep CURRENT_SETUP_VERSION aligned with scenes.
2026-06-06 22:58:33 +02:00
can1357 a3fb07428f perf(packages/coding-agent): optimized model equivalence namespace cache
- Added a WeakMap cache in compileEquivalenceConfig to reuse compiled configs.
- Raised QUALIFIED_NAMESPACE_SUFFIX_CACHE_CAP and HEURISTIC_CANDIDATES_CACHE_CAP from 256 to 4096.
- Reworked resolveCanonicalIdForModel to build officialMatches during candidate iteration.
2026-06-06 22:58:33 +02:00
can1357 cc283cf50f feat(packages/coding-agent): added streaming append-only preview behavior
- Added `isStreamingPreviewAppendOnly` to `ToolRenderer` for per-tool streaming mode selection.
- Updated `ToolExecutionComponent` to query append-only predicates only while a call preview is streaming.
- Marked expanded write previews as append-only so over-tall streaming output can commit head rows.
- Threaded resolved status-line `segmentOptions` into `#buildSegmentContext` construction.
- Added regression tests for scrollback retention and append-only state transitions.
2026-06-06 22:58:33 +02:00
can1357 d5c1f6e3ab perf(packages/coding-agent): optimized LSP frame parsing via chunk queue
- Reworked message parsing to process complete frames from a pending chunk queue.
- Added chunk-aware header scanning and range copy to avoid repeated buffer concatenation.
- Persisted partially read bytes in client.messageBuffer during reader teardown.
2026-06-06 22:58:33 +02:00
can1357 9a2e766c90 perf(packages/tui): optimized per-frame TUI line fitting cache
- Added a per-frame cache for #fitLineToWidth results and cleared it at each #doRender.
- Reused memoized line-fit outputs to skip repeated visibleWidth/truncate work.
2026-06-06 22:58:33 +02:00
can1357 53b8f0f3fe docs(packages/hashline): clarified patch hunk rules for #TAG-safe edits
- Specified replace N..M ranges as inclusive to prevent accidental boundary truncation.
- Clarified that edits must target only lines actually read, not merely covered by a #TAG.
- Added guidance to keep pure insertions as insert hunks and avoid widening replace ranges.
2026-06-06 22:58:33 +02:00
can1357 ed55880f37 fix(ai): fixed orphaned tool-call handling for responses providers
- Added `repairOrphanResponsesToolCalls` to append placeholder outputs for orphan calls.
- Updated `openai-codex/request-transformer.ts` to repair unmatched tool-call/input pairs.
- Wrapped `openai-responses.ts` and `azure-openai-responses.ts` with orphan call repair before request conversion.
- Added regression coverage for orphan call repair in Codex and Responses tests.
2026-06-06 22:49:12 +02:00
can1357 4bf9a92b28 feat(utils): added module-load timing preload and DAG report
- Added Bun preload that records inclusive per-module windows and resolved static import edges via plugin hooks.
- Shared events through a dependency-free buffer so the preload and logger avoid importing each other.
- Rendered module spans as a body/TLA-ranked dependency tree, separating graph wait from top-level work.
- Back-folded captured load phase into the root window to shrink the opaque pre-instrumentation figure.
2026-06-06 22:48:57 +02:00
can1357 fde55bf927 fix(model): added bracket-affix stripping and string-keyed resolution cache
- Replaced WeakMap model cache with provider/id string keys for stable reuse.
- Returned official model ids directly when matched, before heuristics.
- Collapsed non-message token path to system prompt and tool schema totals.
2026-06-06 22:21:58 +02:00
can1357 20d19e8002 test: replaced blind sleeps with shared fixtures and condition polling
- Shared immutable model registries and auth storage via beforeAll/afterAll.
- Swapped fixed-delay settle sleeps for predicate polling and signals.
- Stubbed network/timers to drop wall-clock waits in registry and history tests.
- Added resetDisplay invalidation tests and startup-timing breakdown lines.
2026-06-06 22:09:04 +02:00
can1357 5721034739 fix(ui): forced full replay on tool output expand toggle
- Replaced viewport-only repaint with resetDisplay so committed scrollback reflects new heights.
- Added per-server rust-analyzer workspace-ready timing overrides as a test seam.
- Added clearSuppressedSelectors to reset retry-fallback cooldown state.
- Removed obsolete shared eval executors test.
2026-06-06 21:56:00 +02:00
can1357 5fc443f4af fix(ai): adjusted usage ranking comparator for stable metric ordering
- Added a tolerance-aware `compareUsageRankingMetric` helper with finite-value handling.
- Replaced usage provider sorting comparisons with the new comparator for secondary and primary usage metrics.
- Kept existing tie-breaker fields while stabilizing ordering for nearly equal metric values.
2026-06-06 21:36:39 +02:00
can1357 3b5b182553 Merge remote-tracking branch 'origin/farm/10b5f6a2/surface-subagent-abort-reason' 2026-06-06 21:34:33 +02:00
can1357 6e88643dfa Merge remote-tracking branch 'origin/farm/2750a3c2/fix-todo-renderer-and-anthropic-reasoning-flag' 2026-06-06 21:33:39 +02:00
can1357 1b73329b51 Merge remote-tracking branch 'origin/farm/e0b4f6c6/update-kagi-v1-docs' 2026-06-06 21:33:16 +02:00
can1357 133137c9a6 fix(eval): surfaced subagent abort reasons and disabled runtime cap
- Used `||` so empty stderr falls through to abortReason in agent bridge.
- Preferred assistant errorMessage over "Cancelled by caller" on internal aborts.
- Forced `maxRuntimeMs: 0` for eval subagents via ExecutorOptions override.
2026-06-06 21:33:07 +02:00
can1357 0bac7012cd feat(coding-agent/web): added GitHub Actions run/job scraping
- Parsed /actions/runs URLs into run and job render handlers.
- Rendered run metadata with per-job breakdown, showing steps for failed jobs.
- Fetched job logs via API token, stripping ISO timestamp prefixes.
2026-06-06 21:31:49 +02:00
can1357 bdbbfa9778 fix(eval): surfaced subagent abort reason
- Used `||` so empty stderr no longer masks the real abort reason.
2026-06-06 20:54:00 +02:00
roboomp 2620d3970c docs(web-search): updated kagi description to v1 endpoint
The runtime cutover to Kagi's V1 search API landed in #1272 but
docs/tools/web_search.md still described the sunset V0 endpoint
(GET /api/v0/search with 'Authorization: Bot ...'). Realigned the
Querying and Output bullets with the actual implementation in
packages/coding-agent/src/web/kagi.ts:

- POST https://kagi.com/api/v1/search with Bearer auth and JSON body.
- recency maps to filters.after as a UTC YYYY-MM-DD string.
- Output now includes the categorized bucket merge (search/video/news/
  infobox with title tags), adjacent_question + related_search related
  questions, direct_answer-derived answer, and meta.trace requestId.

Fixes #2009
2026-06-06 18:50:37 +00:00
Can BölükandGitHub 4ae58e1abc Merge pull request #2004 from basedcorp99/fix/antigravity-usage-display
fix(usage): sanitize Antigravity /usage display — dedupe by tier, fix account count, merge window data
2026-06-06 20:48:52 +02:00
Can BölükandGitHub fa7271c2c2 Merge branch 'main' into fix/antigravity-usage-display 2026-06-06 20:48:25 +02:00
Can BölükandGitHub 4fb0742da7 Merge pull request #2002 from basedcorp99/fix/cca-mixed-type-collapse-strips-type-keys
fix(ai): strip type-specific keys when CCA mixed-type collapse picks non-matching type
2026-06-06 20:48:12 +02:00
basedcorp99 f854596f83 fix: format antigravity usage tests 2026-06-06 20:43:19 +02:00
basedcorp99 f8ef2cf8e4 fix: format CCA schema normalization 2026-06-06 20:42:20 +02:00
basedcorp99 7c8fb4d8f6 fix(ai): also strip sibling type-specific keys during CCA mixed-type collapse
Address review feedback:
- Replace `as string` assertion with typed `chosenType` local
- Strip sibling keys from nextSchema that were copied via
  copySchemaWithout but belong to a type other than the chosen one
  (e.g. sibling `items` on a now-string-typed schema)
- Export ALL_CCA_TYPE_SPECIFIC_KEYS from fields.ts for sibling filtering
- Add regression test for the sibling-key edge case
2026-06-06 20:42:20 +02:00
basedcorp99 dee4db1602 chore(ai): update changelog with PR number 2026-06-06 20:42:20 +02:00
basedcorp99 807df56ba7 docs(ai): add unreleased changelog entry for CCA mixed-type combiner collapse fix 2026-06-06 20:42:20 +02:00
basedcorp99 2623bd75a2 test(ai): add stripResidualCombiners regression for mixed-type string|array collapse 2026-06-06 20:42:20 +02:00
basedcorp99 f3210ab862 fix(ai): strip type-specific keys when CCA mixed-type collapse picks non-matching type
When collapseMixedTypeCombinerVariants collapses an anyOf with mixed
types (e.g. string | array), it previously picked the first non-null
type but indiscriminately copied ALL mergedVariantFields — including
type-specific keys like "items" that only belong to array. This
produced schemas like {type: "string", items: {...}} which Google
Cloud Code Assist API rejects with 400.

Fix: filter mergedVariantFields against the chosen types allowed keys
(CLOUD_CODE_ASSIST_TYPE_SPECIFIC_KEYS) before copying, so array-only
keys are dropped when the winner is string (and vice versa).

Fixes 400 error on github tools "pr" parameter (anyOf string/array).
2026-06-06 20:42:20 +02:00
basedcorp99 60f79199ca fix(usage): only add project: dedup identifier when no email; preserve raw windowId
- #getUsageReportIdentifiers now only pushes project: when no email was
  found, preventing two users with different emails on the same GCP
  project from being merged at the usage-report level.

- Antigravity dedup key now uses quotaInfo.windowId directly before
  falling back to parseWindow's id. When resetTime is absent but
  windowId is set, separate windows no longer collapse to 'default'.
2026-06-06 20:42:15 +02:00
basedcorp99 794a64aae1 fix(usage): address review — order email before project, add tests, nits
- BLOCKING: reorder resolveProviderCredentialIdentityKey so email
  identity takes priority over project — two users with different
  emails on the same GCP project no longer get merged/hard-deleted.

- Added #getUsageReportScopeProjectId helper so Gemini CLI reports
  (which set projectId on limit.scope but not metadata) still get
  dedup coverage. Both metadata and scope projectId paths checked.

- formatAggregateAmount now falls back to limits.length when no
  scope.accountId values are present, preserving pre-existing
  behaviour for providers that don't set accountId on limits.

- Added 9 contract tests for the antigravity usage merge logic:
  tier dedup, worst-fraction-wins, mixed-case collapsing,
  reset-time-from-other-entry, windowId separation, metadata,
  sort order, and null-on-no-project.

- Nits: label='Usage' (so formatLimitTitle renders 'Usage (Default)'
  not bare 'Default'), id uses params.provider instead of hardcoded
  string, tier field drops redundant ?? undefined.
2026-06-06 20:42:15 +02:00
basedcorp99 15c0dff28e fix(usage): fall back to limit.scope.projectId when metadata.projectId is absent
Gemini CLI provider stores projectId on limit.scope but not in report
metadata, so the metadata-only projectId fallback added earlier missed
that case. Now all three lookup sites (dedup identifiers, TUI account
label, ACP account label) also check limit.scope.projectId.
2026-06-06 20:42:15 +02:00
basedcorp99 ca24f34044 fix(usage): merge antigravity dedup entries — keep bar data + reset time
When models within the same (tier, windowId) group have complementary
data — some carry remainingFraction but no resetTime, others carry
resetTime but no remainingFraction — merge them so the displayed entry
has both a real bar and the 'resets in…' line.

Also lowercases tier names for dedup keys so 'Default' and 'default'
are recognized as the same tier.

Adds projectId to OAuth credential identity extraction and to the
usage-report dedup identifiers so duplicate credential rows (same
Google Cloud project, separate login sessions) are pruned and merged
at both the store and usage-report levels.
2026-06-06 20:42:15 +02:00
basedcorp99 c933d34398 fix(usage): antigravity /usage display — dedupe by tier, fix account count, add projectId identity
- Antigravity usage provider now deduplicates model quota entries by tier
  instead of emitting one bar per model (15+ redundant bars for one account).
  The upstream API groups quota by tier — models within the same tier share
  the same quota bucket, so per-model bars were misleading noise.

- Reports now carry credential email and accountId in metadata so the
  /usage display and deduplicator can show meaningful account identities
  instead of 'account 1'.

- formatAggregateAmount no longer uses limits.length as account count.
  Instead counts unique accountId values from limit scopes — a single
  account's N incomplete limits no longer display as 'N accts'.

- Usage report dedup now considers metadata.projectId for Google Cloud
  providers so duplicate credential rows with the same project merge.

- account labels in both TUI and ACP markdown paths now fall back to
  metadata.projectId before the generic 'account N' placeholder.
2026-06-06 20:42:15 +02:00
roboomp 5046f0f47c fix(ai): treat missing anthropic baseUrl as official in thinking replay
resolveAnthropicBaseUrl defaults to https://api.anthropic.com when
model.baseUrl is absent (e.g. same-id custom overrides that only tweak
metadata), and the existing isAnthropicApiBaseUrl helper already treats
an empty/undefined baseUrl as official. The new isOfficialAnthropicEndpoint
helper classified the same model as non-official, so
shouldReplayUnsignedThinking would replay unsigned thinking as
type: thinking against the first-party API — which rejects it.

Drop the redundant helper and use isAnthropicApiBaseUrl as the single
source of truth. Add a regression test that pins the missing-baseUrl
case to the text fallback.
2026-06-06 18:34:17 +00:00
roboomp d08e4ebb1f fix(ai): generalize anthropic unsigned thinking replay
Anthropic-compatible reasoning providers commonly emit thinking blocks
without first-party Anthropic signatures while still expecting those
blocks back as native thinking on continuation. The previous follow-up
for #2005 fixed Xiaomi by provider/host allowlist, but the protocol
contract is broader and matches the behavior described in #1996.

Replace the Xiaomi-specific branch with a protocol-level rule:
- official api.anthropic.com keeps demoting unsigned thinking to text
- non-official anthropic-messages reasoning models replay unsigned
  thinking as type: thinking with an empty signature
- existing known non-signing DeepSeek/Z.AI compatibility remains

The regression test now uses a generic Anthropic-compatible reasoning
endpoint, includes the Xiaomi MiMo reporter configuration only as a
fixture, and guards non-reasoning unknown endpoints plus official
Anthropic behavior.

Fixes #2005
2026-06-06 18:29:43 +00:00
roboomp ae3477abfd style: bun run fix 2026-06-06 18:20:57 +00:00
roboomp 6dcbb07793 fix(ai): replay xiaomi mimo anthropic-compat thinking blocks unsigned
The Anthropic-compat endpoints hosted under *.xiaomimimo.com (every
Xiaomi MiMo Token Plan region plus api.xiaomimimo.com) emit thinking
blocks without a signature. convertAnthropicMessages defaulted to
"signing capable" for any endpoint not explicitly allowlisted as
non-signing, so MiMo's unsigned thinking blocks were demoted to text on
every continuation request. Without its prior reasoning replayed, MiMo
destabilized tool-call argument serialization — the root cause behind
the args?.ops?.map crash already mitigated at the renderer in #2005.

Extend isNonSigningAnthropicEndpoint to cover the xiaomi catalog
provider, every xiaomi-token-plan-* provider id, and any baseUrl on
xiaomimimo.com so the existing non-signing replay branch fires for MiMo
the same way it does for DeepSeek and Z.AI.

Fixes #2005
2026-06-06 18:20:27 +00:00
roboomp e83dbc177b style: bun run fix 2026-06-06 18:15:09 +00:00
roboomp cab465cba4 fix(eval): surfaced subagent abort reason through python agent() bridge
Python eval agent() collapsed every subagent runtime-limit abort into a
generic 'RuntimeError: bridge call __agent__ failed' instead of the real
reason. runEvalAgent built its failure message with:

  result.error ?? result.stderr ?? result.abortReason ?? <default>

? is nullish-coalescing, so result.stderr = "" (the executor's value for
a runtime-limit abort) short-circuited the chain and never reached
abortReason. The host bridge then shipped {ok: false, error: ""}, and
prelude.py's '<msg> or <fallback>' picked the named-bridge fallback.

Extracted buildSubagentFailureMessage(): aborted subagents prefer the
trimmed abortReason; otherwise fall through error, stderr (trimmed),
abortReason, and the named-bridge default. Empty/whitespace strings no
longer mask anything. The failure-detection condition also accepts
result.aborted so an abort with exitCode 0 (theoretically) still flows
the abort reason out.

Added a regression test asserting that runtime-limit aborts, whitespace
stderr/error, and totally blank aborts all produce non-empty messages
matching the executor's abortReason text.

Fixes #2006
2026-06-06 18:15:04 +00:00
can1357 a7f5e83067 chore: bump version to 15.9.69 2026-06-06 20:13:59 +02:00
can1357 43b22e9564 fix(coding-agent/web): defaulted perplexity ask to experimental model
- Forced authenticated ask requests to `experimental`, matching the anonymous fallback since the cookie session ignores pro upgrades.
- Kept TUI collapsed search answers full; capping now only applies in compact mode via `maxAnswerLines`.
- Preserved full multiline task pending preview instead of bounding it.
2026-06-06 20:13:06 +02:00
roboomp 1c5cb37df5 style: bun run fix 2026-06-06 18:12:08 +00:00
roboomp ce60b6626b fix(coding-agent): harden todo renderer against malformed streaming args
The todo tool's renderCall ran args?.ops?.map(...) directly, which throws
TypeError on any non-array ops value. parseStreamingJson surfaces such
shapes mid-stream: a partial Anthropic input_json_delta buffer like
'{"ops":"[{' becomes { ops: '[{' }, and intermediate states can hand back
null entries before object fields arrive. Each crash spammed Tool
renderer failed warnings and starved the TUI render loop.

Guard against:
- ops being any non-array (string, object, primitive)
- entries being null / non-object
- entry.items being a non-array

The fix is in the TUI renderer only — schema validation in the agent
loop is unchanged, so any genuinely malformed model output still
surfaces an invalid-args tool error to the model.

Fixes #2005
2026-06-06 18:11:42 +00:00