Commit Graph

82 Commits

Author SHA1 Message Date
Jonathan Singer aa95b0d465 Run Claude on OpenCode's Anthropic endpoint, and name the plan in the UI
Claude models are served on /messages, which the OpenAI SDK can't speak, so
those runs go through LiteLLM's Anthropic route instead. Prompt caching moves
with them, since LiteLLM consumes the injection points the raw SDK rejects.

Zen and Go now show up by name instead of both reading 'OpenCode
subscription', and Zen keeps its cost tracked: it bills prepaid credits per
request, so those runs were never actually free.
2026-08-31 21:07:10 +00:00
yoni 8ed2433574 Fix OpenCode routes: drop LiteLLM-only prompt-cache arg, persist subscription provider for viewer label 2026-08-31 21:06:48 +00:00
0xallam 0a6e8b01bf Fix user message retry lifecycle and TUI sync 2026-08-28 23:46:49 +03:00
devin-ai-integration[bot] cf179d564e fix(llm): bind dedupe credentials to a provider; send reasoning=max via extra_body (#1187)
Co-authored-by: Ahmed Allam <ahmed39652003@gmail.com>
2026-08-28 09:27:57 -07:00
devin-ai-integration[bot] 583af23d9a fix(llm): only attach prompt-cache points on routes LiteLLM serves (#1186)
Co-authored-by: Ahmed Allam <ahmed39652003@gmail.com>
2026-08-28 09:26:57 -07:00
yoni-at-strix 717ffc8f4c Isolate MCP connections per task and surface connection status in the UIs (#1181) 2026-08-27 14:10:44 -07:00
yoni-at-strix cbb0f57058 Reach MCP tools on demand instead of registering every one (#1175) 2026-08-26 16:31:08 -07:00
Ahmed Allam 8b655de615 Mirror the run's threat models into its state dir so resume keeps them 2026-08-27 01:36:47 +03:00
yoni-at-strix f4ef8867f6 Add MCP server support (#1137)
* add a generic MCP client and a config for connecting MCP servers

* Add MCP docs and CLI polish: docs page, startup connect summary, --mcp-config flag, compact tool output

* Add MCP connection notes and per-run selection; clean up on cancel and dedupe names

* Show errored MCP tool calls as failed in the TUI

* Sanitize namespaced tool names so model APIs accept them

* Show MCP tool calls distinctly in the terminal and the run viewer

* Say what MCP servers are worth connecting for

* Correct the notes docstring to match how notes reach the agent

* keep the mcp tests from reading your shell's STRIX_MCP_* vars
2026-08-24 14:00:16 -04:00
devin-ai-integration[bot] 391d81bea7 feat(agents): evidence discipline, and coverage as a first-class artifact (#961)
Co-authored-by: Ahmed Allam <ahmed39652003@gmail.com>
2026-08-24 03:34:09 -07:00
devin-ai-integration[bot] 1ce43d1b94 perf: take heavy imports off the startup path and pre-warm them in the background (#1141)
Co-authored-by: Ahmed Allam <ahmed39652003@gmail.com>
2026-08-20 20:24:08 -07:00
Alex Schapiro d6f2218756 Drop strict tool schemas on Claude routes 2026-08-20 23:12:23 +03:00
yoni-at-strix 8551339130 feat: place caller-provided files into the sandbox workspace (extra_files, --workspace-file) (#1085)
* add extra-files plumbing so orchestrators can drop single files into the sandbox workspace

* reject extra-file paths that collide with a local source tree

* add --workspace-file so CLI users can place files in the sandbox workspace

* reject repeated and control-character workspace paths

* revalidate persisted workspace files when resuming a run

* drop the workspace-file size limit
2026-08-14 16:43:08 -04:00
devin-ai-integration[bot] 174c16fa26 fix(llm): send OpenRouter app attribution on the request itself (#1045) 2026-08-10 11:24:02 -07:00
Ahmed Allam ae07af6159 chore: drop explanatory comment 2026-08-09 15:44:16 +03:00
Ahmed Allam 649a2e2140 fix(llm): omit parallel_tool_calls on tool-less requests 2026-08-09 15:44:16 +03:00
Ahmed Allam 06b158d1fa fix(runner): settle child agents before closing sessions at wind-down (#1025) 2026-08-08 18:17:58 -07:00
Ahmed Allam 72833b8e43 fix(runner): resume after a user interrupt instead of failing (#1023) 2026-08-08 16:44:12 -07:00
Ahmed Allam 1117ba6d4a fix(sessions): open a sqlite connection per operation, not per thread (#1022) 2026-08-08 16:20:01 -07:00
Ahmed Allam 58df71d3db fix(agents): let an agent wait on what it already said (#1020)
* let an agent wait on what it already said

An agent that answers in plain text is nudged to call a tool, and the only tool
that hands control back takes a required message. So it says the same thing
twice: once as text the user has already read, once as the argument it had to
supply to stop. Seen on a run whose whole instruction was "hi" - a greeting, then
the same greeting again through respond_to_user.

message is optional now. The nudge arms the tool with the text that was
delivered and says not to repeat it, so an agent that has said its piece can park
on it with an empty call. Anything it does want to add it passes normally.

Parking still cannot leave the user on silence: an empty call is refused unless
something was actually said, and the arming is single use - execution clears it
as soon as a turn ends any other way.

The interactive prompt now also says to answer and stop in one respond_to_user
call, which is what avoids the nudge in the first place.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* drop the worked example from the interactive prompt

"the user greeted you, asked something you can answer outright, or you need a
decision" was the run I had been reading, written into a rule that holds
whatever the reason. The rule is that replying and stopping is one call; listing
occasions only invites the model to check whether this is one of them.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* drop the arming flag; an empty message just waits

Passing the delivered text from execution into the tool, and refusing an empty
call without it, was machinery guarding against an agent parking having said
nothing. That leaves the user looking at "waiting for your reply" with a cursor
in front of them - they type. It does not need a mechanism.

What is left is the default on message, and the nudge saying the text already
landed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* only offer waiting on words that were written

The nudge told every agent its text had already been delivered, but it fires
whenever a turn leaves the agent running, and a turn can end with no tool call
and no text at all - _final_output_preview has carried <none> and <empty>
branches all along. An agent that said nothing was being invited to wait on an
answer the user never received, leaving them at a bare prompt.

It now reads the turn: waiting on what was said is offered only when something
was, and otherwise the agent is told plainly that the user has read nothing and
to send its message.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* leave the continuation nudge alone

Rewording it meant asserting from the outside whether the agent had spoken, and
the nudge fires whenever a turn leaves the agent running - text or no text. The
agent knows which it did without being told, so the guidance belongs in its
prompt, where the condition is its own to read.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* say it in the nudge, where the agent is reading

An agent stranded by the nudge reasons off the nudge. Told only to call
respond_to_user, it supplies a message, and since it has just answered in plain
text that message is the same answer again. The system prompt saying otherwise
sits thousands of tokens earlier and loses.

The clause goes on the line the agent acts on: call respond_to_user, with no
message if it has already said it. That reads true whatever the turn did,
including one that produced no text, because the agent is the one who knows
which — nothing here has to work it out from the outside.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-09 00:57:16 +03:00
Ahmed Allam b260a4ee38 fix(tui): make the mount prompt clickable, and skip the mount instead of abandoning the scan (#1015)
* make the working-directory prompt answer the mouse

Its Confirm and Cancel were drawn as buttons and did nothing when clicked: the
modal mouse handler had a case for every dialog except this one, so a click fell
through and the scan sat waiting on an answer the user believed they had given.
Only the keyboard could answer it.

The prompt is docked in a corner rather than centered, so it also needs its own
bounds; the centered ones every other dialog uses would have put the buttons in
the wrong place. Those bounds now come from the same placement cornerOverlay
draws with.

Two returns that hand back the model alongside a call that mutates it are now
sequenced explicitly. They work, but only because the compiler happens to
evaluate the call first, and one of them is what puts the prompt back in the
composer when the mount is declined.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* skip the mount instead of abandoning the scan

Declining the working-directory prompt threw the whole launch away and dropped
back to the start screen, which is a lot to lose for answering one question
about one directory. The two answers are now about the directory alone: mount it,
or run without it. The prompt is the whole of the input either way.

The buttons say which is which - Mount and Skip rather than Confirm and Cancel -
and the prompt says what skipping costs.

A run with neither target nor directory is a real run, so two things follow it.
It can be resumed: its instruction is what drives it, and that is in the run
record. And it tells the agent plainly that it has neither, because an agent
given no scope goes looking for the one it assumes it was meant to have.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-08 22:34:02 +03:00
Ahmed Allam 77c7b0df09 prompt changes 2026-08-06 15:39:43 +03:00
devin-ai-integration[bot] 0abe82d622 fix(agents): collapse repeated waits queued inside one model turn (#979)
* fix(agents): collapse repeated waits queued inside one model turn

* fix(agents): state that one wait is enough in every prompt variant

---------

Co-authored-by: Ahmed Allam <ahmed39652003@gmail.com>
2026-08-06 00:07:30 +03:00
Anurag Mewar 6719a70611 feat: support API specs and Postman collections as targets (#866) 2026-08-03 21:07:44 -07:00
Ahmed Allam 3bcf3778f0 fix(core): settle a non-interactive agent's status before its exception unwinds
An exception escaping a non-interactive cycle re-raised before the status
handling, so a dying child stayed 'running' and its parent waited out the
timeout on a completion report the child could no longer send. Set the
terminal status and wake the parent on the way out too.
2026-08-04 06:14:54 +03:00
Ahmed Allam 4a455b1e62 fix(core): recover from hallucinated tool names instead of ending the scan
A tool call for a name Strix does not register raised ModelBehaviorError
from the SDK turn resolver, which nothing retries: the root agent's raise
tore down the whole scan and a sub-agent died before its status was set.
Opt into the SDK's tool_not_found_behavior="return_error_to_model" so the
unknown call comes back as a tool result and the agent self-corrects.

The setting landed in openai-agents 0.19.0, which requires openai>=2.45,
so both pins move.
2026-08-04 06:14:54 +03:00
oyasumi 5bb9fe896b feat(tui): replace Textual with a Go/Bubble Tea interface (#941) 2026-08-03 19:23:07 -07:00
devin-ai-integration[bot] dbc427d816 feat(runtime): mount local targets instead of copying them in (#958)
Co-authored-by: Ahmed Allam <ahmed39652003@gmail.com>
2026-08-02 07:45:10 -07:00
Ahmed Allam b6cf156e95 fix(tools): tell a waiting parent when stop_agent stops its child 2026-08-02 15:43:43 +03:00
Ahmed Allam 002712284a fix(core): wake the parent when a child ends without a completion report 2026-08-02 15:43:43 +03:00
devin-ai-integration[bot] 797b37467e perf(cli): ~10x faster startup via lazy imports (#920)
* perf(cli): fast startup — lazy heavy imports + onedir standalone build

* perf(cli): drop legacy single-file compat from install/self-update

* perf(cli): simplify — drop constants module and extra lazy-import refactors

* refactor(update): strix --update just re-runs the install script

* perf(cli): drop packaging/install/update changes; deepen lazy imports instead

Reverts the onedir build, install.sh, and self-update changes so release
mechanics stay untouched. Startup cost is addressed purely by deferring
heavy imports (agents/openai, config.models, report state/writer, docker)
until a scan actually runs; DEFAULT_MAX_TURNS moves to strix.config.settings
so argparse no longer pulls the agents SDK.

---------

Co-authored-by: Ahmed Allam <ahmed39652003@gmail.com>
2026-08-02 06:24:31 +03:00
devin-ai-integration[bot] 2e7040240d feat(config): accept STRIX_REASONING_EFFORT=max for providers that support it (#956)
Co-authored-by: Ahmed Allam <allam@usestrix.com>
2026-08-01 17:10:01 -07:00
Ahmed Allam 1c1fa49961 refactor(tools): split wait_for_message into respond_to_user + wait_for_agents
One tool was doing three jobs (wait on the user, wait on other agents, and
- wrongly - wait for a long-running command), so the driver had to guess which
one an agent meant and used parent_id as the proxy: the root waits for a human,
everyone else waits for agents. That proxy is wrong, since the user can message
any agent from the TUI's agent tree.

Tool identity now carries the intent, and the coordinator records it as a
wait_kind that survives snapshot/restore:

  respond_to_user  -> wait_kind="user",   never auto-resumed (root or not)
  wait_for_agents  -> wait_kind="agents", auto-resumed on a 300s timer
  recovery exhaust -> wait_kind="stalled"

respond_to_user fuses the message and the yield into one call, so there is no
way to answer and then forget to stop - the two-step that gpt-4o-mini skipped
2/2 in live testing. Plain text still renders as before.

Auto-resume is also bounded now: an agent that re-parks after every timeout
burned a model turn every 300s for the rest of the scan (and, since parked
children notify their parent, spammed the parent's inbox on the same cycle).
After _MAX_IDLE_AUTO_RESUMES it stays parked until a real message arrives.
2026-08-02 02:15:51 +03:00
Ahmed Allam 742f382836 docs(core): correct the rationale for notifying a stalled child's parent
The user can message any agent from the TUI, not only the root, so the
justification is that the parent is an agent with no other way to learn
the child parked - not that the child has no human resumer.
2026-08-02 02:15:51 +03:00
Ahmed Allam 8f1bb64d16 fix(core): tell the parent when an interactive subagent parks
Parking is self-service only for the root, which the user is watching.
A parked child owes its parent a report it can no longer send, so the
parent would wait out its full timeout for nothing.
2026-08-02 02:15:51 +03:00
Ahmed Allam 49057f267f fix(tools): halve the wait_for_message ceiling to 300s
A mutual wait between two agents resolves only when both hit their cap,
so the ceiling is the worst-case idle burn. Name the constants instead of
repeating the literal, and align the interactive auto-resume timeout.
2026-08-02 02:15:51 +03:00
Ahmed Allam 6eec34df24 fix(core): persist the tool-call recovery counter across resumes
An exhausted agent parked in 'waiting' got a fresh nudge budget on every
600s auto-resume, so a wedged agent could nudge-park-nudge indefinitely.
Track the count on the coordinator, snapshot it, and reset it only on
real input or an explicit lifecycle tool.
2026-08-02 02:15:51 +03:00
Ahmed Allam f6f9469e00 fix(core): stop interactive runs stalling on a missing tool call
Interactive turns ended by plain text left the agent parked in 'waiting'
forever. Require an explicit lifecycle tool in both modes and nudge a
text-only turn back into a tool call, bounded by a recovery limit.
2026-08-02 02:15:51 +03:00
devin-ai-integration[bot] 5602bc23ca fix: pre-v1-style lifecycle resilience — mailbox delivery, uniform revival, unexitable runner, waiting timeout, broader retries, crash-safe identity (#923) 2026-08-01 11:17:08 -07:00
alex s a9deb84260 fix(llm): surface structured provider refusals (#944)
* fix(llm): surface structured provider refusals

* fix(llm): settle refused autonomous agents
2026-07-31 10:57:42 -04:00
devin-ai-integration[bot] d4e58b2cd0 fix(llm): pass LLM_EXTRA_HEADERS through ModelSettings so they reach the agent loop (#937) 2026-07-29 19:38:06 -07:00
devin-ai-integration[bot] e037d8d727 fix: recoverable guardrail blocks and decoupled crash-notify (#919)
Co-authored-by: Ahmed Allam <ahmed39652003@gmail.com>
2026-07-27 16:28:48 -07:00
Ahmed Allam 082d4ae62c fix(runtime): wake parent when child hits a terminal state (MaxTurnsExceeded) 2026-07-27 04:27:21 -07:00
devin-ai-integration[bot] c55a8fa4ba feat(runtime): graduated wrap-up warnings, budget reserve, and interactive budget pause/continue (#893)
Co-authored-by: Ahmed Allam <ahmed39652003@gmail.com>
2026-07-26 20:37:14 -07:00
seanturner83 27f9750cdc feat(llm): enable Bedrock/Anthropic prompt caching for Claude models (#772)
Co-authored-by: Sean Turner <sean.turner@zerohash.com>
Co-authored-by: Ahmed Allam <ahmed39652003@gmail.com>
2026-07-26 17:12:57 -07:00
devin-ai-integration[bot] 384338cf31 fix(runtime): retry transient mid-stream provider errors instead of crashing the scan (#891)
Co-authored-by: Ahmed Allam <ahmed39652003@gmail.com>
2026-07-26 16:23:31 -07:00
devin-ai-integration[bot] 3b79e97f00 feat(context): spill oversized tool output into the sandbox workspace (#882)
Co-authored-by: Ahmed Allam <ahmed39652003@gmail.com>
2026-07-26 14:42:22 -07:00
devin-ai-integration[bot] 66a283b71b feat(context): model-aware conversation compaction for long scans (#881) 2026-07-26 14:39:41 -07:00
Ahmed Allam f23fadfbff Rename root agent to Strix 2026-07-25 11:40:05 -07:00
yoni-at-strix cd8270c98b Sign in with a ChatGPT subscription for inference (#854)
Co-authored-by: Jonathan Singer <jonathansinger@Jonathans-MacBook-Pro.local>
Co-authored-by: Jonathan Singer <jonathansinger@Mac-3004.lan>
Co-authored-by: Ahmed Allam <ahmed39652003@gmail.com>
2026-07-24 15:41:19 -07:00