Commit Graph

4550 Commits

Author SHA1 Message Date
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
oldschoola 3e4c57c08d chore(coding-agent): record session-chain replay corruption fix in CHANGELOG
PR #1422 closes a real corruption window in the coding-agent end-to-end edit path (proven by the new test in packages/coding-agent/test/core/hashline.test.ts), but the coding-agent [Unreleased] section had no Fixed entry. AGENTS.md requires every package-affecting change to land under [Unreleased]; add the entry so the fix is not invisible at release time.
2026-05-27 18:55:48 +02:00
oldschoola 56a7212035 fix(hashline): require anchor-content alignment in session-chain replay recovery
The recovery fallback that replays edits onto current text when the structured-patch 3-way merge refuses guarded only on line-count equality. If a prior in-session edit rewrote the very line a later stale-hash edit re-targets, replay overwrote the new content with the stale-anchored payload and emitted a 'Verify the diff matches your intent' warning that does not block the write.

Concrete window: v0 line 5 = 'L5', v1 = 'L5-CHANGED' (same line count). Edit E2 authored against H0 anchored at line 5 lands on v1 because the line-count gate passes, silently replacing L5-CHANGED with the model's L5-MODEL.

Add a verifyAnchorContent gate: walk every edit's anchors and require previousText[line] === currentText[line]. Any mismatch returns null so the caller raises MismatchError and the model re-reads. The success path now emits the standard RECOVERY_SESSION_CHAIN_WARNING (the hedged REPLAY_WARNING text was only sensible when content was partially aligned; that case is now unreachable, and the constant is removed).

Tests: packages/hashline/test/recovery-session-chain.test.ts pins both the corruption refusal and the safe-replay positive case (anchor on an unchanged line, 3-way merge fails on neighbouring rewritten context, replay succeeds with the standard chain warning). packages/coding-agent/test/core/hashline.test.ts adds an end-to-end through executeHashlineSingle so the production patcher path is covered too.
2026-05-27 18:55:29 +02:00
Can Bölük 8fa6652eec Merge pull request #1418 from can1357/farm/76c380e7/provider-models-deprecation-cache
fix(providers): prune stale synthetic model cache entries
2026-05-27 19:53:12 +03:00
Can Bölük f9c5484892 Merge pull request #1425 from oldschoola/fix/search-regex-error-prefix
fix(search): wrap native regex-build errors in ToolError
2026-05-27 19:53:02 +03:00
can1357 9f1a442a06 fix(coding-agent): fixed xAI base URL resolution and pass resolved model to credentials
- Added check to avoid returning DEFAULT_BASE_URL when a custom provider base URL is configured.
- Passed resolvedModel argument to resolveXAIHttpCredentials call in image generation tool.
2026-05-27 18:46:03 +02:00
can1357 c5055d6623 feat(ai): added OpenRouter routing-variant suffix support
- Added `openrouterVariant` option to `SimpleStreamOptions` and `OpenAICompletionsOptions` to append routing suffixes (`:nitro`, `:floor`, `:online`, `:exacto`) to OpenRouter model IDs at request time.
- Skips appending when the model ID already carries an explicit colon-suffix.
- Exposed `providers.openrouterVariant` setting in the coding-agent UI under Settings → Providers.
- Plumbed through `pi-native-server` forwarder and `AgentSession` options preparation.
2026-05-27 18:41:47 +02:00
Can Bölük 77c2af46e7 Merge pull request #1444 from OutlineDriven/fix/compaction-reasoning-effort-fallback
fix(agent): compaction reasoning effort — fallback to off when reasoning unsupported
2026-05-27 19:41:40 +03:00
Can Bölük dc1eb8d96f Merge pull request #1446 from OutlineDriven/fix/xai-grok-oauth-stabilize
fix(ai,coding-agent): stabilize xAI Grok OAuth
2026-05-27 19:41:20 +03:00
metaphorics b76f39d3a6 fix(coding-agent): reopen approved plan on plan-mode reentry
Patch axis: extend

Displacement: net-zero; reuses existing plan reference state instead of adding persistence or overwriting approved artifacts

Rule violations averted: no approved-plan overwrite, no transcript format migration, no public CLI/API expansion

PASS/FAIL: PASS after plan-mode focused tests and package check. Note: system-prompt-templates has an unrelated HOME=/tmp path-shortening expectation failure.
2026-05-27 16:32:40 +00:00
metaphorics bb249cb911 test(coding-agent): mock authStorage + getProviderBaseUrl on image-gen xAI ctx
The Surface 1 commit added authStorage.hasNonEnvCredential as a credential
gate inside resolveXAIHttpCredentials, and the Surface 3 commit added
resolveXAIBaseURL which consults getProviderBaseUrl and getAll. The
existing image-gen xAI test mocked only getApiKeyForProvider on
modelRegistry, so the new code paths threw "undefined is not an object"
at runtime.

Add the missing mock surface:
  - authStorage.hasNonEnvCredential returns true for "xai-oauth" so the
    dedicated-credential gate routes through the xai-oauth branch (which
    the test's getApiKeyForProvider mock services).
  - getProviderBaseUrl returns undefined so resolveXAIBaseURL falls
    through to the XAI_BASE_URL / DEFAULT_BASE_URL leg, preserving the
    test's existing expectation that the request hits
    https://api.x.ai/v1/images/generations.
  - getAll returns [] so the per-model override check in
    resolveXAIBaseURL no-ops cleanly.

Op: correct
Restores: ref:feat/xai-grok-oauth@015437534 ref:feat/xai-grok-oauth@2c1abd7fa
2026-05-27 16:07:38 +00:00
metaphorics 2a7f716386 fix(coding-agent): route xAI image edits to /v1/images/edits; honor image_size
The xAI image branch on origin/main always posts to /v1/images/generations
and hard-codes `resolution: "1k"`, contradicting two advertised contracts:

  P1: generate_image schema declares `input: z.array(inputImageSchema)`
  globally; resolvedImages was populated for every provider but the xAI
  branch POST body only forwarded text fields. Image-edit and
  multi-reference prompts silently degraded to text-only.

  P2: user-supplied image_size was ignored on the xAI path even though
  every other provider honors it via resolveOpenAIImageSize /
  imageConfig.imageSize.

Fix:

  * Add XAIImageReference and XAIImageRequestBase typed interfaces;
    combine into a discriminated XAIImageRequestBody union with mutually-
    exclusive image / images fields (text-only branch carries
    `image?: never; images?: never`).
  * Route to POST /v1/images/edits when resolvedImages.length > 0; map
    1 source -> `image: {url, type}`, 2-3 sources -> `images: [{url,
    type}, ...]` per docs.x.ai. Cap at 3 with a tool-level error; xAI
    documents that limit.
  * Reuse the existing toDataUrl(InlineImageData) helper for the `url`
    field (data: URIs are accepted alongside public URLs per docs.x.ai).
    `type: "image_url"` is the OpenAI-compat discriminator every official
    xAI code example sends.
  * Add resolveXAIResolution(image_size): map OpenAI-style pixel size to
    xAI's discrete "1k" | "2k" tier. 1024x1024 -> 1k; anything wider ->
    2k. Absent image_size still defaults to "1k", matching hermes-agent
    DEFAULT_RESOLUTION (plugins/image_gen/xai/__init__.py:71).
  * buildXAIEditPayload uses tuple destructure + explicit guard rather
    than `resolvedImages[0]`, staying safe under future
    noUncheckedIndexedAccess: true.

No effect on the OpenAI / OpenAI-codex / antigravity / gemini / openrouter
branches.

Op: correct
Restores: ref:feat/xai-grok-oauth@ecedf7c7e
2026-05-27 15:49:23 +00:00
metaphorics 91ac3496d4 fix(coding-agent): respect per-model xAI baseUrl overrides for tool traffic
resolveXAIHttpCredentials honored only \$env.XAI_BASE_URL — every
per-model baseUrl pin (models.yml model.baseUrl) and every provider-
level override (providers.xai-oauth.baseUrl) was silently bypassed for
image and TTS HTTP requests, even when the chat path went through the
override correctly via Model.baseUrl on the Responses request.

Add resolveXAIBaseURL: (1) per-model override when merged.baseUrl
diverges from the bundled default, scoped to (provider, id) so xai and
xai-oauth entries with the same id don't cross-route, (2) provider-level
baseUrl from ModelRegistry.getProviderBaseUrl, (3) XAI_BASE_URL env,
(4) DEFAULT_BASE_URL. resolveXAIHttpCredentials takes an optional
modelId; probes pass undefined and fall through to env/default.

Op: correct
Restores: ref:feat/xai-grok-oauth@2c1abd7fa
2026-05-27 15:26:25 +00:00
metaphorics 6ef2a4f3f1 fix(ai,coding-agent): gate xai-oauth on dedicated credential source
The cross-provider env fallback (stream.ts: "xai-oauth" → XAI_OAUTH_TOKEN
|| XAI_API_KEY) lets an XAI_API_KEY-only setup silently satisfy the
xai-oauth credential branch in resolveXAIHttpCredentials. Once the
helper enters that branch it resolves baseURL under xai-oauth instead of
xai, bypassing providers.xai.baseUrl overrides for image/TTS traffic.

Add AuthStorage.hasNonEnvCredential — hasAuth minus the env-fallback
leg — and gate the xai-oauth branch on (dedicated credential source ||
$env.XAI_OAUTH_TOKEN). The XAI_API_KEY borrow now falls through to the
xai branch, preserving back-compat while restoring provider-level
baseUrl precedence for users with a dedicated xai-oauth source.

Op: correct
Restores: ref:feat/xai-grok-oauth@015437534
2026-05-27 15:25:09 +00:00
cognitive 25c6794cd5 fix(agent): compaction honors session thinking level and silent-clamps unsupported-effort models
Triple-stacked failure on the same axis (thinking effort) produced the
user-visible

    Error: Compaction failed: Thinking effort high is not supported by
           xai-oauth/grok-build.
    Supported efforts:

(empty list after the colon) whenever the active model was a curated
xAI catalog entry with compat.supportsReasoningEffort: false.

Three defects lined up. (1) Behavior: compaction at four call sites
in packages/agent/src/compaction/compaction.ts hardcoded
reasoning: Effort.High and never threaded session.thinkingLevel —
the user's /model :off selection (and any explicit low/medium) was
silently overridden. On every other model this was invisible.
(2) Validation: requireSupportedEffort threw at the openai-flavored
mapper layer before the wire-side omitReasoningEffort gate in
providers/xai-responses.ts ever ran; two contradictory guards on the
same wire param. (3) Message: when getSupportedEfforts returned [],
the rendered error tail was 'Supported efforts: ' with nothing after
the colon — disappears as a side-effect of fix #2.

Fix #1 — thread ThinkingLevel | undefined end-to-end. Add
SummaryOptions.thinkingLevel and HandoffOptions.thinkingLevel.
Convert via a single exhaustive switch (effortFromThinkingLevel) in
the new resolveCompactionEffort helper:
  - Off            → undefined  (omit reasoning entirely)
  - undefined/Inherit → Effort.High → clamp per model (preserves the
                                       historical default for users
                                       who never touched the dial)
  - explicit Effort → respect user → clamp per model

resolveCompactionEffort lives in compaction.ts; all four call sites
(generateSummary, generateHandoff, generateShortSummary,
generateTurnPrefixSummary) route through it. agent-session.ts threads
this.thinkingLevel into all three production compaction entry points
(manual /compact at L6201, auto-compaction at L6458 — the most-fired
path, originally missed in plan review — and direct generateHandoff
at L5465). The audit-gate test
(test/agent-session-compaction-thinking-threading.test.ts) scans the
file with a brace-balanced extractor and refuses any unthreaded site.

Fix #2 — silent-clamp at the openai-flavored mapper layer. Extract
exported modelOmitsReasoningEffort(model) in model-thinking.ts as the
single source of truth for compat.supportsReasoningEffort: false on
openai-responses* APIs. getSupportedEfforts now calls it instead of
inlining the check (pure refactor — observable behavior preserved).
resolveOpenAiReasoningEffort in stream.ts early-returns undefined
when the predicate is true, so the wire-side omitReasoningEffort
gate (providers/xai-responses.ts:78) becomes the single source of
truth for the actual strip — no redundant throw.

Three regression tests pin the contract:
  - packages/ai/test/xai-oauth-effort-strip.test.ts (5 tests):
    modelOmitsReasoningEffort returns true for grok-build and
    grok-4.20-0309-reasoning, false for grok-4.3 / Anthropic /
    openai-completions.
  - packages/agent/test/compaction-thinking-level.test.ts (5 tests):
    every ThinkingLevel outcome through generateHandoff — Off stays
    undefined (not coerced to High), Low stays Low, Inherit / undefined
    default to High, grok-build clamps to undefined regardless of
    requested level. Covers the Codex-caught Off-vs-not-provided
    distinction.
  - packages/coding-agent/test/agent-session-compaction-thinking-threading.test.ts
    (2 tests): brace-balanced source scan asserts every direct
    compact() / generateHandoff() in agent-session.ts threads
    'thinkingLevel: this.thinkingLevel'; floor of 3 threaded sites.

TDD red-green verified for fix #1: temporarily reverted the handoff
call-site back to hardcoded Effort.High → compaction-thinking-level
went 2 pass / 3 fail (Off coerced, Low overridden, grok-build throws);
restored → 5 pass / 0 fail.

Verified:
  - packages/agent:  127 pass / 0 fail
  - packages/ai:     1061 pass / 337 skip / 0 fail
  - packages/coding-agent (focused): 179 pass / 5 skip / 0 fail
  - biome + tsgo --noEmit clean across all three packages

Out of scope (follow-ups):
  - branch-summarization.ts:307 already passes no reasoning — no edit.
  - The empty-list error message at model-thinking.ts:296 is now
    structurally unreachable from the openai-responses path.
  - modelOmitsReasoningEffort and grokSupportsReasoningEffort
    (xai-responses.ts:22) overlap; collapse into a single predicate
    in a future commit.

Op: correct
Restores: spec:compaction-honors-session-thinking-level
Restores: spec:xai-oauth-grok-build-compaction-no-throw
(cherry picked from commit e07b47ee46769053c658819437e2478389a4cee0)
2026-05-27 15:01:20 +00:00
can1357 5be5053696 fix(coding-agent): widen xAI test header captures via holder 2026-05-27 15:52:43 +02:00
can1357 7fd69dbb81 fix(coding-agent): format image-gen test 2026-05-27 15:50:13 +02:00
can1357 ff94f91104 feat: added extraBody support, xAI fixes, and image provider updates
- Added `extraBody` merging into OpenAI Responses request params.
- Fixed xAI OAuth redirect URI to fail fast on port conflicts.
- Exposed `antigravity` and `xai` as explicit `providers.image` options.
- Added `isImageProviderPreference` guard, replacing inline string checks.
- Fixed TTS tool to resolve output path relative to cwd and require write approval.
2026-05-27 15:20:55 +02:00
can1357 a3b27d0cdb chore(ai): fixup xAI cherrypick 2026-05-27 15:15:53 +02:00
cognitive 35d268c5d6 refactor(ai,coding-agent): unexport internal xAI helpers + drop dead refresh-skew constant
Five symbols in packages/ai/src/utils/oauth/xai-oauth.ts were exported
but only consumed inside the file itself:

  - xaiOAuthDiscovery (used 3x internally)
  - XAIOAuthDiscovery (return type of xaiOAuthDiscovery)
  - buildXAIAuthorizeUrl (used 1x internally)
  - BuildXAIAuthorizeUrlOptions (arg type of buildXAIAuthorizeUrl)

One symbol was both exported and fully unused (zero internal or external
references, no test coupling): XAI_ACCESS_TOKEN_REFRESH_SKEW_SECONDS.
The accompanying comment claimed it was 'used by AuthStorage to refresh
ahead of expiry' but no such call exists; AuthStorage uses the standard
5-minute client-skew baked into the OAuthCredentials.expires field via
ACCESS_TOKEN_CLIENT_SKEW_MS.

packages/coding-agent/src/lib/xai-http.ts exported XAICredentials, but
no consumer imports the type by name (callers use type-inference from
resolveXAIHttpCredentials' return type). Unexporting it keeps the
public surface minimal.

bun check baseline 53 errors preserved; bun test xai-oauth 9/9 passing.

Op: compress
2026-05-27 15:08:14 +02:00
cognitive 939b371937 refactor(coding-agent/tools): drop XAI_ASPECT identity map
The XAI_ASPECT object mapped each key to itself and held two keys
(3:2, 2:3) the aspect_ratio schema can never produce. The lookup
XAI_ASPECT[params.aspect_ratio ?? "1:1"] is semantically equivalent
to params.aspect_ratio ?? "1:1" — the schema's enum
["1:1", "3:4", "4:3", "9:16", "16:9"] already constrains the
type, and xAI's /v1/images/generations accepts those strings directly.

bun check baseline 53 errors preserved (no new TS errors).

Op: compress
2026-05-27 15:08:14 +02:00
cognitive f0179c41d0 docs: changelog entries for xAI Grok OAuth, image-gen xai branch, and tts tool
Notes the new xAI Grok OAuth provider in /login, the XAI_OAUTH_TOKEN
env-var fallback, the four new optional fields on OpenAIResponsesOptions,
the generate_image xai branch, and the new tts tool.

Op: extend
2026-05-27 15:08:14 +02:00
cognitive bde0114f87 feat(coding-agent): add xAI Grok Voice TTS tool
Adds packages/coding-agent/src/tools/tts.ts: a CustomTool that POSTs to
https://api.x.ai/v1/tts using the shared xAI credentials helper
(supports both SuperGrok OAuth and plain XAI_API_KEY).

Built-in voices: ara, eve (default), leo, rex, sal. xAI also accepts
custom voice IDs (the schema does not enum-restrict voice_id). Output
codec inferred from output_path suffix (.wav → wav, else mp3). Max
15,000 characters per request. Composes the callers abort signal with
a 60s timeout fence.

Wired into sdk.ts immediately after the image-gen tool registration,
matching the await logger.time(...) pattern.

Ported from NousResearch/hermes-agent (MIT) — tools/tts_tool.py
L167-171 (constants) and L896-959 (_generate_xai_tts).

Op: extend
2026-05-27 15:08:13 +02:00
cognitive c7c285dc13 feat(coding-agent): add xAI credentials helper + image-gen xai branch
Adds packages/coding-agent/src/lib/xai-http.ts: a shared credential
resolver used by image generation (this commit) and TTS (next commit).
Tries the xai-oauth SuperGrok token first via
ModelRegistry.getApiKeyForProvider (refresh cascade lives there);
falls back to XAI_API_KEY. Ported from NousResearch/hermes-agent (MIT).

Extends imageGenTool with a "xai" provider branch that POSTs to
https://api.x.ai/v1/images/generations with the Grok Imagine surface:
grok-imagine-image (default, $0.02/image) or
grok-imagine-image-quality ($0.05/image). Aspect ratios 1:1, 16:9,
9:16, 4:3, 3:4, 3:2, 2:3. Resolutions 1k/2k. Decoded via the existing
saveImagesToTemp helper — no new image-handling code paths.

Op: extend
2026-05-27 15:07:53 +02:00
can1357 bf92a3dd4d chore: bump version to 15.5.6 2026-05-27 15:04:44 +02:00
can1357 f051cc6a0e feat(tools): added multi-range line selectors and raw mode support for URLs and directories
- Added support for multi-range line selectors on URLs (e.g., `:5-10,20-30`) and combining `:raw` mode with line range selectors.
- Added support for line range selectors on directory listings with offset and limit parameters.
- Fixed `:raw` selector being ignored for JSON and feed URLs and directory listing line selectors dropping offset parameter.
- Added clear error message for line offset beyond directory listing end.
- Refactored URL parsing and directory reading to support multiple comma-separated ranges and improved line-based slicing logic.
- Added comprehensive test coverage for multi-range selectors, raw mode combinations, and directory range operations.
2026-05-27 15:03:12 +02:00
can1357 ca86239bda Revert "wip: gentle"
This reverts commit 99bae2ce6c.
2026-05-27 15:01:59 +02:00
can1357 99bae2ce6c wip: gentle 2026-05-27 14:45:02 +02:00
can1357 8a0329026c refactor(hashline): redesigned patch syntax from sigil-ops to anchor+payload model
- Replaced `LINE↑`/`LINE↓`/`A-B:` op sigils with unified `A-B:` anchor + `|`/`↑`/`↓` payload sigils.
- Added `mode: "replacement"` tag to insert edits so the applier distinguishes replace-bucket from insert-bucket lines.
- Removed lenient fallbacks (implicit continuation, inline payload acceptance, escaped delimiter stripping).
- Updated grammar, prompt, tokenizer, parser, applier, and messages to match the new format.
2026-05-27 14:45:01 +02:00
can1357 f0c7df60d5 chore: bump version to 15.5.5 2026-05-27 14:44:30 +02:00
can1357 8f7f240b56 Merge remote-tracking branch 'origin/farm/e054d7f9/fix-legacy-pi-ai-type-export' 2026-05-27 14:43:43 +02:00
roboomp 802e3f3e63 fix(extensibility): resolved compat shims to bunfs entry paths in compiled binaries
Reviewer caught that the new `legacy-pi-ai-shim.ts` is only referenced
via a computed string path, so Bun's `--compile` static analyzer cannot
trace it into bunfs. The same gap existed for the pre-existing
`typebox.ts` shim — `path.resolve(import.meta.dir, "../typebox.ts")`
collapses to `/$bunfs/typebox.ts` in compiled mode (where
`import.meta.dir` is `/$bunfs/root`), which does not exist in bunfs.
Legacy plugins importing bare `@sinclair/typebox` or `@(scope)/pi-ai`
therefore hit "Cannot find module" in release builds.

- Branch `TYPEBOX_SHIM_PATH` and `LEGACY_PI_AI_SHIM_PATH` on
  `isCompiledBinary()`: in compiled mode they point at the
  `--root`-relative bunfs entry path with a `.js` extension
  (`/$bunfs/root/packages/coding-agent/src/extensibility/<file>.js`);
  in dev they keep the `path.resolve(import.meta.dir, "../<file>.ts")`
  source path so tests still resolve against the workspace tree.
- List both shims as additional `--compile` entrypoints in
  `scripts/build-binary.ts` so Bun actually emits them into bunfs at the
  paths the runtime expects.

Verified with a focused `bun build --compile` probe: `Bun.resolveSync`
returns the expected bunfs path for both shims when they are listed as
entries, and fails when they are not. Dev-mode test suite unchanged
(17 pass / 0 fail across the four legacy-pi compat test files).
2026-05-27 12:34:27 +00:00
roboomp 6f7da0769b fix(extensibility): redirected legacy pi-ai root imports through Type-compat shim
Plannotator-class legacy extensions still import `Type` from
`@(scope)/pi-ai` (e.g. `@earendil-works/pi-ai` rewritten to
`@oh-my-pi/pi-ai`). pi-ai 15.1.0 removed the root `Type` runtime
export, so extension load crashed with `Export named 'Type' not found`
even though the `@sinclair/typebox` Zod-backed shim still ships in the
coding agent.

Routed bare `@oh-my-pi/pi-ai` root specifiers — used by both the
mirrored-source rewriter and the Bun.plugin onResolve hook — through a
new sibling shim that re-exports the canonical pi-ai surface plus the
`Type` runtime from the existing TypeBox shim. Subpath imports such as
`@oh-my-pi/pi-ai/utils/oauth` continue to resolve directly against the
bundled pi-ai package.

Fixes #1437
2026-05-27 12:14:57 +00:00
can1357 abac192890 refactor(coding-agent/edit): removed optional path parameter from hashline edit operations
- Removed `path` field from hashline input parameters and function signatures across diff, execute, and params modules.
- Updated HashlinePatch.parse() calls to omit the path option, relying on the ¶PATH#HASH header in input instead.
- Removed unused warning tracking for escaped payload delimiters in hashline parser.
2026-05-27 13:34:10 +02:00
can1357 024690419d feat(hashline): added detection and stripping of extra backslashes
- Added detection and stripping of extra backslashes before indented payload rows, which models often emit when JSON-escaping the delimiter.
- Added `_input` field alias support in hashlineEditParamsSchema to accept provider-emitted variants.
- Added warning message for escaped payload delimiter acceptance to guide users toward canonical syntax.
2026-05-27 13:28:08 +02:00
can1357 51c9b7c956 refactor(coding-agent/edit): removed unused hashline streaming fallback code
- Removed unused constants STREAMING_FALLBACK_LINES and STREAMING_FALLBACK_WIDTH.
- Removed unused HASHLINE_TOKENIZER instance and helper functions trimHashlineStreamingSyntax and renderHashlineInputFallback.
- Removed unused imports for HashlineTokenizer, sanitizeText, replaceTabs, and truncateToWidth.
2026-05-27 13:23:34 +02:00
can1357 b0cedda9ae fix(hashline): modified scanInlineBody to strip the payload
- Modified scanInlineBody to strip the payload prefix when present at the start of inline content.
- Added test cases covering backslash-delimited payloads in insert, delete, and replace operations.
2026-05-27 13:21:42 +02:00
can1357 ed5615a6ca refactor(hashline): extracted streaming-tolerant patch parsing into dedicated functions
- Added `parsePatchStreaming` and `Executor.endStreaming` to handle in-flight ops gracefully during incremental parsing, dropping pending ops with no payload to avoid phantom edits.
- Introduced `PatchSection.applyPartialTo` as a streaming-aware counterpart to `applyTo`, using the new streaming parser for diff preview generation.
- Removed the custom `buildHashlineNaturalOrderPreviews` function and replaced it with calls to `applyPartialTo`, centralizing streaming logic in the parser layer.
2026-05-27 13:20:49 +02:00
can1357 41d509eff0 feat(find): grouped output by directory and clamped limit to 200
- Changed output format to group results under `# /` headers to reduce token usage for shared path prefixes.
- Clamped the `limit` parameter to 1-200 (default 200) instead of the previous 1000.
- Updated tests to assert against raw file lists instead of parsed text output.
2026-05-27 13:13:11 +02:00
can1357 558ef2ba33 feat(hashline): changed payload continuation prefix from + to \
- Updated the payload continuation syntax to use backslash (`\`) instead of plus (`+`) as the explicit prefix for multi-line payloads and blank lines.
- Modified grammar, format constants, parser comments, and all documentation and test cases to reflect the new syntax.
- This is a breaking change for existing hashline patches using the `+` prefix.
2026-05-27 13:06:59 +02:00
can1357 6643178d6a refactor: replaced instanceof Promise checks with isPromise utility
- Imported isPromise from node:util/types in four modules.
- Replaced four instanceof Promise checks with isPromise calls for more reliable promise detection.
2026-05-27 13:02:52 +02:00
can1357 fe3b982976 refactor(hashline): removed delete operation support from hashline format
- Removed the `!` delete sigil and all associated parsing, validation, and tokenization logic. The delete operation is no longer a supported edit kind.
- Updated grammar, format constants, and error messages to reference only insert and replace operations.
- Simplified the executor's overlap validation to handle only replace operations.
2026-05-27 13:01:50 +02:00
can1357 e3ff9826d1 fix(hashline): skipped markdown comments before hashline operations in parser
- Parser now buffers markdown-style `#` lines and skips them when they directly precede a hashline operation.
- It now preserves comment lines that are not immediately before an operation while still handling blank separators as regular raw input.
- Added focused parser tests plus prompt and changelog updates describing the new comment-skipping behavior.
2026-05-27 13:01:49 +02:00
can1357 7a44d802de refactor: streamlined diff generation output and clarified hashline prompt rules
- Reduced default context lines from 4 to 2 in diff generation.
- Removed leading and trailing ellipsis placeholders from generated diff strings.
- Clarified the destructive nature of the replace operator and added examples in the prompt.
2026-05-27 13:01:49 +02:00
can1357 44f0c14cb5 perf(coding-agent/tools): replaced readUrlCache with LRUCache to limit memory usage
- Replaced the standard Map cache with an LRUCache instance.
- Limited the maximum number of cached URL entries to 100.
2026-05-27 13:01:49 +02:00
can1357 d1920e9ca5 refactor(coding-agent/edit): removed redundant hashline headline from tool result output
- Simplified `renderSection` output assembly in hashline execution to stop injecting a separate headline.
- Removed conditional headline generation that prefixed create/update/status text before the header.
- Returned tool results containing only header, preview, and warnings content blocks.
2026-05-27 13:01:49 +02:00
Can Bölük ad8bf18189 Merge pull request #1426 from oldschoola/fix/session-emit-listener-isolation
fix(session): isolate event listener failures in agent fan-out
2026-05-27 13:45:01 +03:00
Can Bölük 0b52b8c0d0 Merge pull request #1419 from hezhiyang2000/fix/bash-busy-wait-yield
fix: eliminate Bun event-loop busy-wait with setTimeout keepalive (v2)
2026-05-27 13:39:01 +03:00
can1357 69ab1656ff chore: bump version to 15.5.4 2026-05-27 10:27:32 +02:00
can1357 552c93842f Merge remote-tracking branch 'origin/farm/fa17b3a4/scope-package-changelog-lookup' 2026-05-27 10:26:33 +02:00