feat: add configuration persistence for model selections#4
Merged
adamdotdevin merged 1 commit intoanomalyco:devfrom May 14, 2025
Merged
Conversation
Member
|
love it, thanks! |
burgercrisis
added a commit
to burgercrisis/opencode
that referenced
this pull request
Jan 8, 2026
…d dank Windows Command Execution Fixes: - Add detectCommandShell() and parseCommand() functions for shell detection - Implement direct PowerShell execution bypassing cmd.exe wrapper - Add shell built-ins detection and needsShellExecution function - Fix stream draining to prevent race conditions (Promise.all) - Remove duplicate abort listeners Edit Tool Improvements: - Add newString validation guard (handles undefined/null/empty) - Add UnicodeNormalizedReplacer for smart quotes and em-dashes - Fix multi-line pattern matching with empty lines (Issue anomalyco#26) - Add unique match identification for replaceFirst functionality - Improve block anchor matching with variable gap handling Documentation: - Add verified-fixes-summary.md documenting all fixed issues - Add windows-command-execution-issues.md comprehensive analysis - Add linux-unix-mac-compatibility-analysis.md for cross-platform impact Fixes: Issues anomalyco#2, anomalyco#3, anomalyco#4, anomalyco#5, anomalyco#7, anomalyco#8, anomalyco#9, anomalyco#15, anomalyco#19, anomalyco#26
randomm
referenced
this pull request
in randomm/opencode
Jan 9, 2026
… (#4) * feat: implement Remory MCP integration (#3) - Add comprehensive TDD test suite for configuration validation - Update opencode.json to use Remory via Docker exec command - Add infrastructure tests for container health and connectivity - Include placeholder tests for memory operations and semantic search Following GitHub issue #3 requirements for enhanced memory capabilities. * test: enhance Remory integration test coverage (#3) - Add comprehensive test suite for Remory MCP integration - Validate Docker container health and connectivity - Test semantic search capabilities and performance - Verify memory tool compatibility with Remory backend - 100% test coverage for configuration validation - All tests passing with 7/7 success rate * docs: add comprehensive Remory memory service documentation (#3) - Document enhanced memory capabilities with semantic search - Add Docker container setup instructions - Detail 5-15x performance improvements over basic memory server - Include technical architecture and configuration examples - Document memory operations and performance benefits - Complete documentation requirements for issue #3 * docs: verify MCP configuration for local Remory instance The MCP memory configuration in opencode.json is already correctly set up to use the local Remory instance running in Docker. No changes needed.
11 tasks
kryptobaseddev
added a commit
to kryptobaseddev/opencode
that referenced
this pull request
Feb 22, 2026
… leaks Addresses the 4 remaining high-priority memory leak issues from the work plan (I-9385-A, I-7046-A, PR-14635, I-7046-C partial). I-9385-A (CRITICAL, Priority anomalyco#1) — tool/task.ts: call Session.remove() after extracting subagent task output. This fires the session.deleted event, which triggers cleanupSessionCaches() in the event-reducer — freeing all in-memory messages, parts, diffs, permissions, and status for the subagent session. The task_id in the output becomes a dead reference; if the LLM tries to resume, Session.get() fails gracefully and a fresh session is created. Validated: the cleanup infrastructure already existed but was never invoked for subagent sessions. I-7046-A (CRITICAL, Priority anomalyco#3) — session/compaction.ts: clear part.state.output and part.state.attachments when pruning compacted tool parts. Previously, prune() set time.compacted but left the full output string in both the DB row and the in-memory store. toModelMessages already substituted "[Old tool result content cleared]" for compacted parts — this change aligns stored data with that behavior, freeing the large strings from memory and disk. PR-14635 (HIGH, Priority anomalyco#4) — TUI event listener cleanup: - app.tsx: save the unsubscribe functions returned by all 6 sdk.event.on() calls; call them in a single onCleanup() handler. Previously, onCleanup was not even imported. - routes/session/index.tsx: save and clean up the message.part.updated listener. This component mounts/unmounts during session navigation, so each navigation previously added a duplicate listener. - component/prompt/index.tsx: save and clean up the PromptAppend listener. Same mount/unmount pattern as the session component. I-7046-C (partial) — the TUI event listener fixes above cover the most impactful instances of the missing-dispose pattern. A full audit of all subscribe() call sites remains as follow-up work. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
6 tasks
praxstack
referenced
this pull request
in praxstack/opencode
Feb 25, 2026
…r details - retry.ts: respect isRetryable:false and 4xx status in JSON error bodies (Issue #7) - provider.ts: cap Bedrock Anthropic models at 200K context (Issue #4) - batch.ts: include per-tool error details in failure output (Issue #9) - retry.test.ts: 5 new tests for catch-all retry classification
tamarazuk
added a commit
to tamarazuk/opencode
that referenced
this pull request
Mar 3, 2026
…odies - Refresh VCS state before idempotency check in create() to avoid TOCTOU race (anomalyco#4, anomalyco#12) - Use refreshed branch/defaultBranch in fallback PR return (anomalyco#9) - Validate base branch exists before attempting gh pr create (anomalyco#22) - Wrap review comment bodies in fenced blocks for structural separation (anomalyco#8)
sjawhar
added a commit
to sjawhar/opencode
that referenced
this pull request
Mar 8, 2026
- Finding #1: re-sync active sessions after disposal by saving fullSyncedSessions before clear and calling result.session.sync() after successful bootstrap - Finding #2: cap retries at 5 with exponential backoff (2s/4s/8s/16s/30s) and generation counter to cancel stale retries when newer disposal arrives - Finding anomalyco#3: move Instance.provide() inside while loop so each event stream reconnect iteration gets fresh context - Finding anomalyco#4: remove unconditional startEventStream(process.cwd()); add events RPC method; thread calls it only when not in external transport mode - Finding anomalyco#5: replace manual new Promise+setTimeout with sleep() from node:timers/promises - Finding anomalyco#6: reload() aborts current event stream and conditionally restarts it
sjawhar
added a commit
to sjawhar/opencode
that referenced
this pull request
Mar 8, 2026
- Finding #1: re-sync active sessions after disposal by saving fullSyncedSessions before clear and calling result.session.sync() after successful bootstrap - Finding #2: cap retries at 5 with exponential backoff (2s/4s/8s/16s/30s) and generation counter to cancel stale retries when newer disposal arrives - Finding anomalyco#3: move Instance.provide() inside while loop so each event stream reconnect iteration gets fresh context - Finding anomalyco#4: remove unconditional startEventStream(process.cwd()); add events RPC method; thread calls it only when not in external transport mode - Finding anomalyco#5: replace manual new Promise+setTimeout with sleep() from node:timers/promises - Finding anomalyco#6: reload() aborts current event stream and conditionally restarts it
sjawhar
added a commit
to sjawhar/opencode
that referenced
this pull request
Mar 8, 2026
- Finding #1: re-sync active sessions after disposal by saving fullSyncedSessions before clear and calling result.session.sync() after successful bootstrap - Finding #2: cap retries at 5 with exponential backoff (2s/4s/8s/16s/30s) and generation counter to cancel stale retries when newer disposal arrives - Finding anomalyco#3: move Instance.provide() inside while loop so each event stream reconnect iteration gets fresh context - Finding anomalyco#4: remove unconditional startEventStream(process.cwd()); add events RPC method; thread calls it only when not in external transport mode - Finding anomalyco#5: replace manual new Promise+setTimeout with sleep() from node:timers/promises - Finding anomalyco#6: reload() aborts current event stream and conditionally restarts it
1 task
tamarazuk
added a commit
to tamarazuk/opencode
that referenced
this pull request
Mar 21, 2026
…odies - Refresh VCS state before idempotency check in create() to avoid TOCTOU race (anomalyco#4, anomalyco#12) - Use refreshed branch/defaultBranch in fallback PR return (anomalyco#9) - Validate base branch exists before attempting gh pr create (anomalyco#22) - Wrap review comment bodies in fenced blocks for structural separation (anomalyco#8)
ESRE-dev
added a commit
to ESRE-dev/opencode
that referenced
this pull request
Mar 27, 2026
* Restructure watchdogTick so idle-detection sweeps
SessionActivity.list() independently of stuck-tool
query results — fixes Bug anomalyco#4 (idle gated behind
stuck-tool results) and Bug anomalyco#5 (leaf.length === 0
early return skipping idle detection entirely)
* Add pre-cancel map cleanup in the idle sweep to
prevent unbounded growth of stale entries
* Define CancelRequested bus event in processor and
publish from abortChildren so child sessions get
in-memory cancel alongside the DB updates (Bug anomalyco#7)
* Add SessionPrompt.init() subscribing to the event,
called from bootstrap alongside SessionActivity
* Wrap AI SDK iterator consumption in try/finally to
call iter.return() on abort, preventing leaked HTTP
connections (Bug anomalyco#8)
* Check abort signal before retry continue to stop
cancelled sessions from restarting loops (Bug anomalyco#9)
* Remove shadowed abort promise in permission-check
loop so pre-aborted signals reject immediately
instead of hanging (Bug anomalyco#10)
* Update watchdog tests for independent idle sweep
and add cancel-propagation event tests
ESRE-dev
added a commit
to ESRE-dev/opencode
that referenced
this pull request
Mar 27, 2026
* Restructure watchdogTick so idle-detection sweeps
SessionActivity.list() independently of stuck-tool
query results — fixes Bug anomalyco#4 (idle gated behind
stuck-tool results) and Bug anomalyco#5 (leaf.length === 0
early return skipping idle detection entirely)
* Add pre-cancel map cleanup in the idle sweep to
prevent unbounded growth of stale entries
* Define CancelRequested bus event in processor and
publish from abortChildren so child sessions get
in-memory cancel alongside the DB updates (Bug anomalyco#7)
* Add SessionPrompt.init() subscribing to the event,
called from bootstrap alongside SessionActivity
* Wrap AI SDK iterator consumption in try/finally to
call iter.return() on abort, preventing leaked HTTP
connections (Bug anomalyco#8)
* Check abort signal before retry continue to stop
cancelled sessions from restarting loops (Bug anomalyco#9)
* Remove shadowed abort promise in permission-check
loop so pre-aborted signals reject immediately
instead of hanging (Bug anomalyco#10)
* Update watchdog tests for independent idle sweep
and add cancel-propagation event tests
andreipromarketing-dev
pushed a commit
to andreipromarketing-dev/opencode
that referenced
this pull request
Apr 7, 2026
…t-errors-another-one Fix markdownlint errors (MD038, MD058, MD025, MD034)
andreipromarketing-dev
pushed a commit
to andreipromarketing-dev/opencode
that referenced
this pull request
Apr 7, 2026
* feat: add pending instinct TTL pruning and /prune command Pending instincts generated by the observer accumulate indefinitely with no cleanup mechanism. This adds lifecycle management: - `instinct-cli.py prune` — delete pending instincts older than 30 days (configurable via --max-age). Supports --dry-run and --quiet flags. - Enhanced `status` command — shows pending count, warns at 5+, highlights instincts expiring within 7 days. - `observer-loop.sh` — runs prune before each analysis cycle. - `/prune` slash command — user-facing command for manual pruning. Design rationale: council consensus (4/4) rejected auto-promote in favor of TTL-based garbage collection. Frequency of observation does not establish correctness. Unreviewed pending instincts auto-delete after 30 days; if the pattern is real, the observer will regenerate it. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * fix: remove duplicate functions, broaden extension filter, fix prune output - Remove duplicate _collect_pending_dirs and _parse_created_date defs - Use ALLOWED_INSTINCT_EXTENSIONS (.md/.yaml/.yml) instead of .md-only - Track actually-deleted items separately from expired for accurate output - Update README.md and AGENTS.md command counts: 59 → 60 Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * fix: address Copilot and CodeRabbit review findings - Use is_dir() instead of exists() for pending path checks - Change > to >= for --max-age boundary (--max-age 0 now prunes all) - Use CLV2_PYTHON_CMD env var in observer-loop.sh prune call - Remove unused source_dupes variable - Remove extraneous f-string prefix on static string Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * fix: update AGENTS.md project structure command count 59 → 60 Co-Authored-By: Claude <noreply@anthropic.com> * fix: address cubic and coderabbit review findings - Fix status early return skipping pending instinct warnings (cubic anomalyco#1) - Exclude already-expired items from expiring-soon filter (cubic anomalyco#2) - Warn on unparseable pending instinct age instead of silent skip (cubic anomalyco#4) - Log prune failures to observer.log instead of silencing (cubic anomalyco#5) Co-Authored-By: Claude <noreply@anthropic.com> * fix: YAML single-quote unescaping, f-string cleanup, add /prune to README - Fix single-quoted YAML unescaping: use '' doubling (YAML spec) not backslash escaping which only applies to double-quoted strings (greptile P1) - Remove extraneous f-string prefix on static string (coderabbit) - Add /prune to README command catalog and file tree (cubic) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Happy <yesreply@happy.engineering>
guazi04
pushed a commit
to guazi04/opencode
that referenced
this pull request
Apr 8, 2026
fix: 压缩核心工具描述(bash/todowrite/task),每条消息节省 ~4k tokens Closes anomalyco#4 See merge request iself-team/opencode!8
zhangdw156
added a commit
to zhangdw156/opencode
that referenced
this pull request
Apr 16, 2026
* chore: bootstrap benchmark runner type contracts Co-Authored-By: Claude Opus 4 <noreply@anthropic.com> * fix: improve adapter contract test with realistic params and assertions Co-Authored-By: Claude Opus 4 <noreply@anthropic.com> * feat: add benchmark hijack service with synthetic stream * fix: pass explicit enabled flag in hijack tests, clear queue on unbind Co-Authored-By: Claude Opus 4 <noreply@anthropic.com> * feat: wire benchmark hijack branch into llm run pipeline * feat: add benchmark runner core utilities and scoring Co-Authored-By: Claude Opus 4 <noreply@anthropic.com> * feat: add LongMemEval and LongBench-v2 benchmark adapters * feat: add BEAM adapter and end-to-end benchmark runner skeleton Co-Authored-By: Claude Opus 4 <noreply@anthropic.com> * feat: wire end-to-end benchmark evaluation with hijack Phase A/B flow - Promote BenchmarkHijack to Effect Service for DI across server routes and LLM - Add /benchmark/* HTTP routes for hijack control (bind/unbind/enqueue/clear/status) - Create benchmark-server.ts minimal entry point (avoids TUI/react deps) - Rewrite anchor-eval.ts with full Phase A (hijack replay) + Phase B (real LLM probe) - Implement HijackClient HTTP fetch wrapper - Fix tryStream to return null on empty queue (prevents title-gen race condition) - Skip hijack for small=true LLM calls (title generation) - Add run-all-plugins.ts for 7-plugin comparison evaluation - Verified end-to-end: all 7 plugins complete with LongMemEval (550 turns, 1 probe) Co-Authored-By: Claude Opus 4 <noreply@anthropic.com> * feat: refactor memory plugins to use shared LLM/embedding config and simplify implementations Remove regex-based fallbacks and hardcoded logic across all memory plugins, wiring them to use the shared config for LLM and embedding calls. Update benchmark runner and test harness accordingly. Co-Authored-By: Claude Opus 4 <noreply@anthropic.com> * fix: sanitize FTS5 queries and auto-load plugin env in benchmark runner - Sanitize FTS5 MATCH queries in all 7 plugins: strip special chars (?, *, ", etc.), quote each token, join with OR. This fixes the root cause of 0% benchmark accuracy — FTS5 syntax errors on probe questions containing special characters were silently swallowed by catch blocks. - Remove regex fallback and embedding null guards from plugin index files, making LLM/embedding required (per shared config refactor). - Auto-load plugins/opencode/.env in run-all-plugins.ts so benchmark runner works without manual `set -a; source .env`. - Verified: BEAM benchmark limit=1 on mem0 achieves 5% accuracy (1/20 probes correct), confirming end-to-end memory storage and retrieval. Co-Authored-By: Claude Opus 4 <noreply@anthropic.com> --------- Co-authored-by: claude <claude@example.com> Co-authored-by: Claude Opus 4 <noreply@anthropic.com>
Rwanbt
added a commit
to Rwanbt/opencode
that referenced
this pull request
Apr 19, 2026
…LLM paths A panic while holding any of our Mutex<Option<Child>> / Mutex<Option<Engine>> locks was poisoning the state permanently — the next lock() would panic again, so TTS/STT/LLM were dead until the app restarted. Introduce MutexSafe trait in util.rs (same spirit as mobile speech.rs lock_safe) and migrate all 33 call sites in llm.rs, speech.rs and lib.rs to state.child.lock_safe(). Poisoned-mutex cases now log a warning and keep serving — the guarded state (process handles, load flags) is idempotent across calls so resuming is safe. Closes anomalyco#4/21.
sorted-ai-bot
pushed a commit
to sorted-ai/opencode
that referenced
this pull request
Apr 25, 2026
Bridge was dying on startup because Hatch MCP client called tools/list before Java core finished registering capabilities. Added poll loop (max 20s) that waits for loaded_count > 0 before opening session and exec'ing bridge. Also records: MCPHUB alpha architecture rework pending (Go daemon scrap → Java-centric). Spec deviated from Proposal §4.3 'thin wrapper' intent. Post-rework, bridge connection issues #1/#3/anomalyco#4/anomalyco#5/anomalyco#8 are expected to be structurally eliminated. Hatch-side backlog unchanged: - HMD-03 VT-013/014: 50-turn verification (in progress) - HMD-02: deferred hack deletion (blocked on HMD-03) - anomalyco#6 websearch empty responses: Hatch adapter issue - anomalyco#7 webfetch HTML bloat: Hatch adapter issue
kitlangton
added a commit
that referenced
this pull request
May 1, 2026
… gap #4 phase 1) Adds the parallel `runNative()` path inside `session/llm.ts` so a narrow slice of sessions can flow through `@opencode-ai/llm` instead of the AI SDK `streamText`. Behavior is gated and shipped off by default; only callers that opt in see any difference. The full migration plan (audit gap #4) is parallel-path-with-flag, prove parity test-by-test, flip default last. This commit is phase 1: get the wire-up in place behind a flag with one protocol so we can see whether the design holds before committing to the full migration. Wire-up summary: - New flag `OPENCODE_EXPERIMENTAL_LLM_NATIVE` (also enabled by the umbrella `OPENCODE_EXPERIMENTAL`). Off by default. - The session-LLM `live` layer now consumes `RequestExecutor.Service`, and the `defaultLayer` provides `RequestExecutor.defaultLayer` so a Node fetch HTTP client backs every native stream. - `runNative(input)` returns `Stream<Event> | undefined`. `undefined` means "fall through to AI SDK." It returns a real stream only when every gate passes: the flag is set, the caller populated `input.nativeMessages` (the bridge needs typed `MessageV2.WithParts`, not the AI SDK `messages` array), the session has zero tools (Phase 2 will lift this), and the bridge routes the model to a protocol in `NATIVE_PROTOCOLS`. - `NATIVE_PROTOCOLS` is a single-entry set today: `anthropic-messages`. Other adapters are imported and registered with the client so the Phase 2 expansion is a one-line edit, not an architecture change. - Stream wiring: client.stream(req) -> Stream.flatMap(event -> fromIterable(map.map(event))) -> Stream.concat(suspended fromIterable(map.flush())) -> Stream.provideService( RequestExecutor.Service, executor). The flush stream is built lazily with `Stream.unwrap(Effect.sync(...))` so it observes the mapper final state after every upstream event has been mapped. - The mapper (`LLMNativeEvents.mapper`) emits AI-SDK-shaped session events from `LLMEvent` so downstream consumers see one shape. What this does NOT do (deferred to later phases): - No tool support on the native path (skipped, falls through). - No parity harness yet; Phase 2 builds it. - No production traffic; flag is off by default and no production caller populates `nativeMessages`. - No reasoning/cache/multi-modal coverage. Anthropic supports reasoning and cache via existing patches, so those start working as soon as a caller routes a real session through. Verification: opencode typecheck clean, bridge tests still green (33/0/0 across llm-native.test.ts + llm-bridge.test.ts); LLM package tests green (123/0/0).
kitlangton
added a commit
that referenced
this pull request
May 1, 2026
…phase 2) Adds `test/session/llm-native-stream.test.ts` — one focused test that proves the end-to-end wire-up `runNative` relies on actually produces session events from a scripted Anthropic SSE response. The test stays self-contained: - Builds a fake Anthropic `Provider.Info` + `Provider.Model` via `ProviderTest`. - Builds an `LLMRequest` via `LLMNative.request(...)` from a `MessageV2.WithParts` user message — the same call shape `runNative` uses inside `session/llm.ts`. - Creates an `LLMClient` with the same adapters list + `ProviderPatch.defaults` list as `runNative`. The adapters are imported directly from `@opencode-ai/llm`; if `runNative`'s `NATIVE_ADAPTERS` array changes, this test's `adapters` constant has to follow (commented). - Provides a single fixed-response HTTP layer that returns a scripted Anthropic SSE body. The layer helper is inlined (12 lines) rather than imported from `packages/llm/test/lib/http.ts` so the test doesn't reach across package boundaries. - Pipes the LLM stream through `LLMNativeEvents.mapper()` exactly as `runNative` does (`Stream.flatMap` + lazy `Stream.concat` for flush), runs it to completion, and asserts the key session events: `text-start` precedes `text-delta`, `finish-step` carries `finishReason: "stop"`, and `finish` carries the merged usage totals. This does NOT test the dispatch gate inside `session/llm.ts` (`!Flag.OPENCODE_EXPERIMENTAL_LLM_NATIVE`, missing `nativeMessages`, tools present, non-Anthropic protocol). Those are simple boolean conditions and don't need separate coverage. It also does not exercise the production `Service` layer — that's deferred to Phase 2 step 2 (tool support) and Phase 2 step 3 (production caller wiring). What the test buys: confidence that the conversion pipeline works and catches regressions in `LLMNative.request`, the LLM adapter set, or `LLMNativeEvents.mapper` before they would surface in a real session. Verification: 34/0/0 across the three bridge-area tests (`llm-native.test.ts` + `llm-native-stream.test.ts` + `llm-bridge.test.ts`); opencode typecheck clean.
kitlangton
added a commit
that referenced
this pull request
May 1, 2026
…hase 2 step 2a) Adds opt-in `nativeTools?: ReadonlyArray<Tool.Def>` to `LLM.StreamInput` so callers that route through the native path can attach typed opencode tool definitions alongside the AI SDK `tools` record. The gate in `runNative` widens accordingly: a session can use the native path when it has zero tools (existing behavior) OR when it explicitly provides `nativeTools` matching its AI SDK `tools` (new opt-in). When `nativeTools` reaches `LLMNative.request`, the existing `toolDefinition` converter folds each `Tool.Def` into the request's `tools` array and the LLM core lowers it onto the wire. This commit deliberately does NOT include the dispatch loop. A session that opts in by setting `nativeTools` and that triggers a `tool-call` from the model will see the call event but no `tool-result` because the native path has no execute handler yet. That's why no production caller populates `nativeTools`: phase 2 step 2b will land the dispatch loop and only then will real production sessions route through here. What this lays in place: - `StreamInput.nativeTools` typed against `Tool.Def[]` from `@/tool`. Aliased to `OpenCodeTool` at the import to dodge a clash with the AI SDK `Tool` type that the same file already imports. - The `runNative` gate flips from "no tools allowed" to "either no tools, or `nativeTools` is supplied". An AI SDK tool count > 0 with `nativeTools` undefined still falls through, so existing production sessions are unaffected. - `LLMNative.request` already accepted `tools: ReadonlyArray<Tool.Def>` and converts via `toolDefinition`. We just forward the input through; no LLM-bridge change. Smoke coverage: a new test in `llm-native-stream.test.ts` builds a typed `Tool.Def` (Effect Schema parameters), routes it through `LLMNative.request` + `LLMClient.prepare`, and asserts the prepared Anthropic target carries the tool as an `input_schema` block with the expected JSON Schema shape. This validates the conversion path that phase 2 step 2b will exercise from inside `runNative`. Verification: opencode typecheck clean; 35/0/0 across the three bridge-area tests (`llm-native.test.ts`, `llm-native-stream.test.ts`, `llm-bridge.test.ts`).
kitlangton
added a commit
that referenced
this pull request
May 1, 2026
…ative path (audit gap #4 phase 2 step 2b) Lands the streaming-dispatch tool loop for the LLM-native path. When the gate-passing session has `nativeTools` populated, the native runner forks an AI SDK `tool.execute(...)` the moment a `tool-call` event arrives mid-stream and injects a synthetic `tool-result` event back into the same stream when the handler resolves. Long-running tools no longer block subsequent tool-call streaming; the user sees each result land as soon as that specific handler completes. The driver loops across rounds: when a round ends with `reason: "tool-calls"` AND the dispatchers produced at least one result, the runner builds a continuation `LLMRequest` (assistant message echoing text/reasoning/tool-call content + tool messages with results) and recurses. Stops on a non-`tool-calls` finish, when `maxSteps` (default 10, mirrors `ToolRuntime.run`) is reached, or when the underlying scope is interrupted. New file `session/llm-native-tools.ts`: - `runWithTools({ client, request, tools, abort, maxSteps? })` is the public entry point. Returns a `Stream<LLMEvent, LLMError, RequestExecutor.Service>` of merged model events + synthetic tool results, ready to flow through `LLMNativeEvents.mapper` for consumption by the existing session processor. - `runOneRound` is the internal building block. It opens an unbounded `Queue<LLMEvent, LLMError | Cause.Done>`, forks a producer that streams the model and pushes each event to the queue, and forks a dispatcher (via a scope-bound `FiberSet`) for every non-provider-executed `tool-call`. Each dispatcher's result is pushed back into the same queue. After the model stream completes, the producer awaits `FiberSet.awaitEmpty` and ends the queue; consumers see end-of-stream. A `Deferred<RoundState>` resolves alongside so the multi-round driver can decide whether to recurse. - `dispatchTool` wraps the AI SDK `tool.execute(input, { toolCallId, messages, abortSignal })` call. Unknown-tool and execute-throws paths produce `tool-error` events instead of failing the stream (mirrors `ToolRuntime.run`'s defect-vs-recoverable boundary), so the model can self-correct on the next round. Wired into `runNative` (`session/llm.ts`): when `input.nativeTools` is non-empty, the upstream becomes `LLMNativeTools.runWithTools(...)` instead of `nativeClient.stream(...)`; the AI SDK `tools` record flows in as the dispatch table. Zero-tool sessions still take the direct-stream path (one round, no dispatch overhead). Mapper update (`session/llm-native-events.ts`): `tool-result` events whose `result.value` matches the opencode `Tool.ExecuteResult` shape (`{ output: string, title?: string, metadata?: object }`) now flow through to the AI-SDK-shaped session event with their `title` and `metadata` preserved. Provider-executed and synthetic results that don't match still fall back to `stringifyResult`. Without this, the session processor would see every native tool result as `{ title: "", metadata: {}, output: <JSON of the whole record> }`. Smoke test (`test/session/llm-native-stream.test.ts`): scripts a two-round Anthropic SSE backend — round 1 issues a `lookup` tool call, round 2 replies with text after the tool result feeds back. Asserts the full event sequence threads through `runWithTools`, the dispatcher, and the mapper: - `tool-call` event has the streamed JSON input parsed. - `tool-result` event carries the `ExecuteResult` shape with `title` + `output` populated (proving the mapper update works). - Round 2 text-delta arrives after the synthetic tool-result. - Final `finish` event has `finishReason: "stop"` (loop terminated). What this still does NOT do (deferred to step 3): - No production caller populates `nativeTools` yet; that's the `prompt.ts:resolveTools` change. Until that lands, the gate keeps every real session on the AI SDK path. - No parity harness comparing native + AI SDK event sequences for the same scripted session. That's step 4. Verification: opencode typecheck clean; 36/0/0 across the three bridge-area tests; 125/0/0 across the LLM package.
kitlangton
added a commit
that referenced
this pull request
May 1, 2026
…sions can route through the native path (audit gap #4 phase 2 step 3) Wires the prompt-side tool resolver to also surface opencode-native `Tool.Def[]` alongside the AI SDK record it already builds. With `OPENCODE_EXPERIMENTAL_LLM_NATIVE=1` set, real production sessions that satisfy the gate now stream through `LLMNativeTools.runWithTools` instead of `streamText` — the LLM-native path goes from "plumbing-only" to "actually used." Changes: - `prompt.ts:resolveTools` collects `Tool.Def[]` from the registry loop and tracks a feasibility flag. MCP tools (which only have AI SDK shape) flip the flag off; the synthesized `StructuredOutput` tool that the json_schema branch injects also flips it. The return shape becomes `{ tools, nativeTools }` where `nativeTools` is `undefined` whenever any non-registry tool source contributes — callers fall through to the AI SDK path automatically. The registry path stays in sync because every `tools[item.id] = tool({...})` is paired with a `nativeTools.push(item)` at the same loop iteration. - The single caller (`prompt.ts:1396`) destructures the new shape and passes `nativeTools` through to `handle.process(...)`. The json_schema branch sets `nativeTools = undefined` after injecting `StructuredOutput` so the gate falls through for structured-output sessions. - `runNative` (in `session/llm.ts`) gains two safety nets that work regardless of caller behavior: 1. Coverage check: if AI SDK tools are non-empty, every key must have a matching `Tool.Def` in `nativeTools`. A partial set falls through. Defends against future callers that might emit a partial native list. 2. Filter parity: `runNative` now calls the existing `resolveTools(input)` (the in-file permission/user-disabled filter) and intersects its keys with `nativeTools`, then feeds the filtered AI SDK record to the dispatcher and the filtered native list to `LLMNative.request`. Without this, sessions could see permission-disabled tools advertised on one path but not the other. - The dispatch path uses the filtered AI SDK tools record as the execute table: `LLMNativeTools.runWithTools({ tools: filteredAITools, ... })`. Tool definitions sent to the model are the filtered native list. Every tool the model sees can dispatch. What this enables: a session opted into the experimental flag, with a clean toolset (registry-only, no MCP, no structured output), running an Anthropic model, now exercises the streaming-dispatch loop end-to-end. Tool calls fire as soon as the model finishes streaming each tool's input; results land in the stream the moment each handler resolves. Multi-round behavior matches phase 2 step 2b. What this still does NOT do (deferred to step 4): - Parity test harness comparing native vs AI SDK event sequences for the same scripted session. Until that lands, broader confidence comes from running real sessions with the flag set. - MCP support on the native path. Sessions with MCP servers configured stay on AI SDK indefinitely. - Native support for the synthesized `StructuredOutput` tool. Verification: opencode typecheck clean for `src/session/*` (the TUI-side errors visible in the working tree are Kit's parallel work, untouched here); bridge area tests 36/0/0 across `llm-native.test.ts` + `llm-native-stream.test.ts` + `llm-bridge.test.ts`; `prompt.test.ts` still 47/0/0 (no regression from the resolveTools shape change).
zoulukuang
pushed a commit
to zoulukuang/deskfox
that referenced
this pull request
May 3, 2026
anomalyco#1 Rust write_text_file 接 root+path 用 PathBuf::join,因为 opencode 的 pathFromTab 返回相对 workspace root 的路径, 之前直接传给 std::fs::write 会相对进程 cwd 解析失败 (Phase 2 时用绝对路径测试,没暴露此 bug) anomalyco#2 saveEdit 写盘成功后 await file.load(p, { force: true }) 强制从磁盘重读,否则 UI 显示改前 stale 内容 user 已亲验 anomalyco#1 修复("保存生效"),anomalyco#2 待本 commit rebuild 后验。 详见 改动日志.md anomalyco#4。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
zoulukuang
pushed a commit
to zoulukuang/deskfox
that referenced
this pull request
May 3, 2026
…e force 真生效 [feat: file-tree-dnd] 新文件: - packages/app/src/context/file/undo-stack.ts:createUndoStack 容量 20,push move/copy entry,pop 用注入的 reverter 跑反向 - docs/features/file-tree-dnd/4-test-checklist.md:全套 32 条测试清单(A-G 七组),user 每次 build 对照 Tauri 改动: - text_file.rs: write_binary_file_absolute_base64(path, base64) — 解码 base64 + fs::write,500MB 上限,已存在则 already_exists - lib.rs: 注册新命令到 invoke_handler 前端改动: - tree-store.ts(关键 fix):force=true 必须绕过 inflight check,否则等到旧 stale promise → 拖放后源父目录不刷新 - file.tsx:挂 undoStack 到 useFile() - file-tree.tsx: - handleMoveDrop / pasteTo push undo entry - 新增 handleExternalDrop(File[]) 走 FileReader → base64 → Tauri 写盘(Tauri webview 不暴露 file.path,只能读内容) - undoLast: 从栈 pop 执行反向 rename/trash + 刷新涉及目录 - Ctrl+Z 接入 useFileTreeShortcuts(只在 level 0 注册) - dropHandlers 接受外部 OS files(dataTransfer.types 含 "Files"),onDrop 优先处理 dataTransfer.files 详见 docs/features/file-tree-dnd/3-changelog.md "Commit anomalyco#4" 段。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
zoulukuang
pushed a commit
to zoulukuang/deskfox
that referenced
this pull request
May 3, 2026
…: file-tree-dnd] - 改动日志.md 加 file-tree-dnd 索引行(4 笔 commit hash 列出) - docs/features/INDEX.md 把 file-tree-dnd 标 done - 4 个三文档全部 status: in-progress → done - docs/features/file-tree-dnd/3-changelog.md 回填 commit anomalyco#4 hash b9a4acc - .gitignore 加 .obsidian/(user 用 Obsidian 浏览 docs/features/,本地配置不入库) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
zoulukuang
pushed a commit
to zoulukuang/deskfox
that referenced
this pull request
May 3, 2026
审计发现 spec / plan 还停留在"规划阶段方案"层面,跟实际落地的最终方案有偏差。 本笔把 1-spec / 2-plan / 3-changelog 全部对齐到当前已 commit 的状态。 主要更新: - 1-spec.md:验收标准从 unchecked 占位改成 [x] 已通过;架构选型增加"外部文件 drop 终选方案"小节(撤销最初的 onDragDropEvent + dragDropEnabled 方案,改 FileReader → base64 → write_binary_file_absolute_base64) - 2-plan.md:Commit anomalyco#4 实施步骤改成 FileReader 对应实际方案;决策轨迹补 D4-D9(路径分隔符 / tree-store force fix / hook 多注册 / {...rest} 覆盖 / 外部 drop 终选 / build rename Defender 锁) - 3-changelog.md:总体 review 自检勾上 + 加 Commit anomalyco#5 / anomalyco#6 条目 + 回退方法填实际 hash Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
dgokeeffe
pushed a commit
to dgokeeffe/opencode-databricks
that referenced
this pull request
May 5, 2026
… reproducer context Code Reviewer subagent (fresh-context, with codebase access) flagged: - AI SDK line ref off by 18 (~L6283 → L6265 in ai@6.0.158, the resolved version per node_modules symlink) - Quirks anomalyco#3/anomalyco#6/anomalyco#7/anomalyco#8 not in transform.ts as the opener implied (anomalyco#7 in processor.ts, anomalyco#8 in llm.ts, anomalyco#6 in provider discovery) - "Two full days" / "every quirk within an hour" framing reads as venting to a PM audience; strip - Asks anomalyco#3+anomalyco#4 should be merged into one Responses-API-parity workstream - Reference-client ask should be #2 (highest-leverage deliverable) - Missing reproducer context: package versions, endpoint name Apply all of the above. Add direct GitHub links from the SDK-package quirks to upstream source lines and from the workaround text to llm.ts:407–461 so internal recipients can hand off to the SDK-package team without re-reading this doc. Add a versions-tested header. Co-authored-by: Isaac
Rwanbt
added a commit
to Rwanbt/opencode
that referenced
this pull request
May 5, 2026
…LLM paths A panic while holding any of our Mutex<Option<Child>> / Mutex<Option<Engine>> locks was poisoning the state permanently — the next lock() would panic again, so TTS/STT/LLM were dead until the app restarted. Introduce MutexSafe trait in util.rs (same spirit as mobile speech.rs lock_safe) and migrate all 33 call sites in llm.rs, speech.rs and lib.rs to state.child.lock_safe(). Poisoned-mutex cases now log a warning and keep serving — the guarded state (process handles, load flags) is idempotent across calls so resuming is safe. Closes anomalyco#4/21.
dgokeeffe
pushed a commit
to dgokeeffe/opencode-databricks
that referenced
this pull request
May 6, 2026
…xTools cap Add script/probe-aigw-quirks.ts — a reproducible per-family test of every catalogued quirk against AI Gateway, run once and committed so future sessions can re-verify in seconds. Replaces the partly-inferred AI Gateway status column with on-the-wire evidence. Findings (running against the aigw workspace, Claude / GPT / Gemini where applicable): #1 schema strict — STILL ACTIVE on all 3 families (server-side, harmless to opencode because our adapters generate proper schemas) #2/anomalyco#11 oversized itemId — STILL ACTIVE (GPT only) anomalyco#3 asymmetric streaming events — GONE (perfectly symmetric on aigw) anomalyco#4 reasoning_effort — works correctly (reasoning_tokens returned) anomalyco#5 cache_control — works correctly (verified with two-call populate+hit test; my earlier "fail" reading was a 1212-token prompt under the effective cache threshold) anomalyco#6 task=null on Codex/GPT-5 metadata — GONE (all 3 families now return task: "llm/v1/chat" correctly) anomalyco#7 finish_reason "other" — STILL ACTIVE (GPT) anomalyco#8 per-endpoint 89-tool cap — GONE on AI Gateway (verified all 3 families accept 89 tools; cap was a model-serving constraint) anomalyco#9, anomalyco#10 npm package lifecycle bugs — INERT on AI Gateway (we use @ai-sdk/openai, bundled provider not loaded) anomalyco#12 mismatched item IDs — STILL ACTIVE (GPT) Net: of 12 quirks, 4 still bite on AI Gateway (#1, #2/anomalyco#11, anomalyco#7, anomalyco#12), 4 are gone (anomalyco#3, anomalyco#6, anomalyco#8, plus anomalyco#4 always worked), anomalyco#5 works correctly, and 2 are bypassed by adapter choice. Anthropic and Gemini paths through @ai-sdk/anthropic and @ai-sdk/google are clean on AI Gateway. Code change consequence: drop the maxTools: 16 cap in familyDefaults for gpt/codex when on the AI Gateway path (anomalyco#8 is gone there). Cap stays on the model-serving path. 3-class regression test passes 3/3 on both surfaces after the change. Doc: replace the inferred AI Gateway status column with the empirical matrix, citing the probe script and the specific evidence per quirk. Co-authored-by: Isaac
zoulukuang
added a commit
to zoulukuang/deskfox
that referenced
this pull request
May 7, 2026
… md-export-pdf-word] [override-blacklist: bun.lock 自动重生 — 本 feat 范围内一次性] bun install 触发的 lockfile 自动重排(3453 ins / 3417 del),不是手动改。 wrapper 不可行性:bun.lock 是 bun 工具链生成,无法 wrapper / 改写;所有"加 dep" feat 都触动。 风险:0(纯 lockfile 重排,运行时行为不变,内容是依赖树规范化)。 本笔 R4 override 范围:仅本 feat anomalyco#1 commit 一笔;后续 anomalyco#2/anomalyco#3/anomalyco#4 不再触动 lockfile。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
zoulukuang
added a commit
to zoulukuang/deskfox
that referenced
this pull request
May 7, 2026
…rite 加 allow_overwrite [feat: md-export-pdf-word] 根因:write_binary_file_absolute_base64 是给文件拖入用的(commit anomalyco#4 file-tree-dnd), 故意校验"不存在"防止覆盖。导出 Word 复用此命令但 save dialog 已让用户确认替换, 后端拦截导致 toast "already_exists: /path/to.docx" + 文件实际未替换(数据风险)。 修:rust 加 allow_overwrite: Option<bool> 参数(default false 保拖入场景语义不变), 导出端 invoke 传 allowOverwrite: true。其他调用点(markdown-editor-extensions / file-tree) 不传 → undefined → unwrap_or(false) → 仍校验 already_exists,无回归。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
schaefer-iib-tu-darmstadt
added a commit
to schaefer-iib-tu-darmstadt/iibcode
that referenced
this pull request
May 7, 2026
IIBCODE_QUICKSTART.md becomes README.md so GitHub renders the
fork-specific docs first. The upstream English README + 21 translations
move to docs/upstream-readme/ (git mv preserves their history).
.gitattributes marks both paths merge=ours so 'git merge upstream/dev'
auto-keeps our version. Requires a one-time per-clone setup since the
driver itself isn't committed:
git config merge.ours.driver true
CLAUDE.md gotchas anomalyco#4 and anomalyco#5 document this and how to handle a newly
added upstream translation file (the rule only fires for existing
paths, so a brand-new README.cs.md slips through and needs a manual
git mv).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #3
I originally brought this up when I added model selection in the first place, I have these changes in open pr and figured I would copy it over to here since it is the new repo.