Commit Graph

9 Commits

Author SHA1 Message Date
Mason Daugherty 564e5a05bc fix(code): run /offload server-side (#4696)
`/offload` now stores archived conversation history through the agent's
backend.

---

`/offload` previously summarized and saved conversation history in the
client process. In server and sandbox modes, that process does not own
the backend used by the agent: persistence could fail against a
read-only filesystem, and even a successfully written archive would not
be available to the agent through `read_file`.

This changes Deep Agents Code to run the existing `compact_conversation`
tool through the active agent instead. The command seeds a tool call
into the thread, approves the expected human-in-the-loop interrupt
because the user explicitly requested `/offload`, resumes the graph, and
reads the persisted summarization event back from server state. The
archive is therefore written through the agent's composite backend and
remains readable by the agent in local, server, and sandbox runs.

The old client-side `perform_offload` helper (and its `OffloadResult` /
`OffloadThresholdNotMet` / `OffloadModelError` result types) is removed,
as summarization and persistence now run through the agent. In local
mode, the `conversation_history` backend now roots under `~/.deepagents`
(via `_offload_fallback_root`, with a hardened private-temp fallback
when the home directory is not writable) instead of a throwaway
`tempfile.mkdtemp` directory, so offloaded history persists across
sessions.

The SDK's `compact_conversation` API is unchanged; this PR is confined
to Deep Agents Code.

Made by [Open
SWE](https://openswe.vercel.app/agents/1cbc308e-b411-2a09-bd6b-541e606ca4c5)

---------

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
2026-07-14 15:03:45 -04:00
Mason Daugherty bbd0f0d1dd fix(code): persist resume model state privately (#4400)
Deep Agents Code now records resume model state privately after
successful model calls, including model params, without exposing the
internal `effective_model` runtime context field in LangSmith traces.

```dcode -r 019f1a63-1fca-70a3-90bb-e94458e61f29```

---

Model resume bookkeeping now stays in private checkpoint state instead of being carried through runtime context as `effective_model`. The model middleware records the actual model request that completed, which also avoids persisting a requested override when server-side resolution falls back to the previous model.

## Changes
- Remove `effective_model` from `CLIContext` so it no longer appears as LangSmith trace metadata.
- Move `_model_spec` persistence into `ConfigurableModelMiddleware`, emitted after a successful model response using `ExtendedModelResponse` and a private state update.
- Persist `_model_params` alongside `_model_spec` so resumed sessions restore invocation params such as `temperature` or `max_tokens`.
- Keep subagent model middleware from writing parent-thread resume metadata.
- Leave `ResumeStateMiddleware` focused on `_context_tokens`, with model metadata owned by the middleware that resolves the actual request.
2026-07-01 18:13:17 -04:00
Mason Daugherty 8fca61dc03 feat(code): add rubric-backed goal workflow (#4365)
Adds rubric-driven acceptance criteria to Deep Agents Code and layers a
goal workflow on top of it.

A rubric is the explicit definition of done. Use it when you already
know the criteria the agent should satisfy before it considers the work
complete. Criteria can be sticky for the thread, one-shot for the next
turn, or loaded from a file. While the agent works, the TUI shows
grading lifecycle messages so the user can see when the work is being
checked, revised, satisfied, or stopped.

Usage examples:

```text
/rubric set tests pass; no unrelated files changed; help text is updated
/rubric next only change the auth callback; do not refactor unrelated code
/rubric file acceptance.md
/rubric show
/rubric clear
```

A goal is the objective-oriented workflow. Use it when you know the
outcome, but want `dcode` to propose acceptance criteria before
execution. `/goal <objective>` asks the model to draft criteria and
displays them in an inline review prompt. The user can accept the
criteria, edit them directly, reject them with feedback to regenerate,
or cancel. Accepted goal criteria become the sticky rubric for the
thread.

Usage examples:

```text
/goal add OAuth refresh handling
/goal show
/goal clear
```

The `--goal` CLI flag starts the same goal-review workflow when
launching the TUI. It is intentionally interactive: the generated
criteria must be reviewed before execution. After the user accepts the
proposal, the accepted goal is sent as the first task.

```bash
dcode --goal "add OAuth refresh handling"
```

`--goal` cannot be combined with `-n`, `-m`, `--skill`, or `--rubric`.
For non-interactive/headless runs, users should provide criteria
explicitly with `--rubric` instead:

```bash
dcode -n "implement OAuth refresh handling" --rubric "tests pass; no unrelated files changed"
dcode -n "implement OAuth refresh handling" --rubric @acceptance.md
```

Accepted goal/rubric state is persisted on the thread and restored on
resume. For example, a user can set `/goal add OAuth refresh handling`,
accept the proposed criteria, quit the TUI, and later resume the same
thread with the goal and criteria still active. That matters because the
acceptance criteria continue to guide future turns and remain visible in
`/goal show` instead of becoming hidden context that disappears between
sessions.

When the agent believes the goal is done, it does not get to declare
victory on its own. For example, after implementing OAuth refresh
handling, the agent can ask to mark the goal complete with evidence such
as "tests pass." `dcode` keeps that request pending until the rubric
check finishes. If the rubric still needs revision, the goal stays
active and the user sees why it was not completed. If the rubric is
satisfied, auto-approve mode records the completion automatically;
manual mode asks the user before changing the goal status. This keeps
the user's accepted criteria as the source of truth for whether the goal
is actually finished.

The active criteria and goal are also visible to the agent through
constrained tools. `get_rubric` lets the agent inspect the current
criteria and whether they came from a goal, a sticky rubric, or the
current invocation. `get_goal` lets it inspect the active objective,
status, criteria, and any prior note. `update_goal` lets it report when
it believes the goal is `complete` or `blocked` with evidence. The
constraints matter: the agent can read criteria and update progress, but
it cannot create, pause, resume, clear, or replace goals. Those
lifecycle actions stay user/system controlled so the model cannot
silently redefine or remove the user's objective.
2026-06-29 16:20:18 -04:00
Mason Daugherty 90ebb1d68c feat(code): add Fireworks session settings (#4360)
Fireworks-backed model calls now receive stable per-thread session
identity from Deep Agents Code runtime context.

## Changes
- Add `thread_id` to `CLIContext` so model-call middleware can see the
active LangGraph session without reading global config.
- Inject Fireworks session settings from the thread ID, adding
`prompt_cache_key` and `x-multi-turn-session-id` only when callers have
not already supplied equivalent values.
- Preserve existing model settings and headers, including
case-insensitive handling for legacy Fireworks affinity headers and
malformed `extra_headers`.
- Pass runtime context through non-interactive streaming and Textual
task execution so Fireworks session identity is available consistently.
2026-06-29 00:25:26 -04:00
Mason Daugherty 4600365ea0 fix(code): sync approval toggles during active runs (#4239)
Approval mode now has a live control path for remote `dcode` sessions
instead of relying only on the run-context snapshot captured at stream
start. That lets mid-run toggles take effect before the next gated tool
call, while failing closed to manual approval when the live state cannot
be synced or read.

## Changes
- **Live approval state:** Added `approval_mode_key`,
`approval_mode_payload`, `read_approval_mode_from_store`, and
`awrite_approval_mode` to store per-thread auto-approve state in the
LangGraph Store under a deterministic hashed thread key.
- **Interrupt decisions:** Updated `_should_interrupt_tool_call` to
prefer the live store value over stale context, so toggling from
auto-approve back to manual can interrupt subsequent gated tool calls in
the same active run.
- **TUI synchronization:** Updated
`DeepAgentsApp.action_toggle_auto_approve` and
`_on_auto_approve_enabled` to write the live approval mode whenever the
user toggles approval behavior.
- **Fail-closed behavior:** If manual approval cannot sync while an
agent is running, the app warns the user and cancels the active run
rather than allowing stale auto-approval to continue.
- **Remote support:** Added `RemoteAgent.aput_store_item` so remote
sessions can write unindexed LangGraph Store records used by the
server-side approval predicate.
- **Context reconstruction:** Preserved `auto_approve` and
`approval_mode_key` when dict-based runtime context is reconstructed
into `CLIContextSchema`.
- **Stream propagation:** Updated `execute_task_textual` to write live
approval state before each stream iteration and await async auto-approve
callbacks triggered from approval prompts.
2026-06-24 23:12:40 -04:00
Mason Daugherty 9e21c346a6 fix(code): skip tool interrupts once auto-approve is set (#4092)
Deep Agents Code no longer splits a turn into many runs when "approve
always" is enabled; gated tool interrupts are now suppressed at the
source.

---

When a user enables "approve always" in Deep Agents Code,
`HumanInTheLoopMiddleware` kept interrupting on every gated tool call
and the client auto-resolved each one. Each interrupt/resume cycle
starts a fresh agent run, so a single turn fragmented into many runs and
produced noisy, hard-to-parse traces.

The fix carries the auto-approve decision in run-scoped CLI context
(`CLIContext` / `CLIContextSchema.auto_approve`) rather than graph
state, and each `interrupt_on` config gains a `when` predicate
(`_should_interrupt_tool_call`) that reads `request.runtime.context`.
Once approve-always is in effect the predicate returns `False`, so the
middleware skips the interrupt entirely instead of pausing and being
patched on the client. The initial turn seeds the flag from session
settings (`app.py`), and `textual_adapter.py` refreshes it into context
on every stream iteration — so choosing "auto-approve all" mid-turn
propagates to the resuming stream and the remaining tool calls in that
same run also stop interrupting.

Auto-approve is sourced from run context rather than graph state for two
reasons: seeding state would require a first-turn `Command(update=...)`,
which the LangGraph API server rebuilds with `goto=None` and crashes
`_control_branch` on a fresh thread; and context is safer because the
model cannot self-approve by writing state. The predicate is fail-closed
— missing or malformed context still interrupts — and consumers accept
both a coerced `CLIContextSchema` (in-process) and a plain dict (over
the LangGraph API / RemoteGraph).

Made by [Open
SWE](https://openswe.vercel.app/agents/4b76ff9f-a307-5834-5471-a0d441f2a147)

---------

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Co-authored-by: Sydney Runkle <54324534+sydney-runkle@users.noreply.github.com>
2026-06-23 01:32:44 -04:00
open-swe[bot] 202e0bd3e5 feat(code): ChatGPT OAuth sign-in for Codex models (#3532)
Closes #1424

---

Adds a `Sign in with ChatGPT` OAuth flow to `/auth` in `deepagents-code`
and a new `openai_codex` model provider backed by upstream's
`ChatOpenAICodex`. Codex-eligible models (e.g. `gpt-5.5`) now appear
under their own auth context in the `/model` switcher, separate from the
API-key-backed `openai` provider.

The OAuth heavy-lifting — PKCE, refresh-aware file-backed token store,
the loopback callback HTTP server — lives upstream in
`langchain_openai.chatgpt_oauth` (langchain-ai/langchain#37569).

The new `run_browser_login` composes upstream's PKCE / authorize-URL /
callback-wait / token-exchange primitives so the Textual modal can
surface the authorize URL inline *before* the loopback wait begins. The
upstream `login_chatgpt()` helper prints the URL to stdout, which is
invisible inside a Textual app. The flow mirrors the `/mcp` loopback
pattern: a `ThreadingHTTPServer` on a fixed port, PKCE plus state CSRF,
browser launch with a manual-URL fallback, and a cancellable progress
modal.

_Opened collaboratively by Mason Daugherty and open-swe._

---------

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Co-authored-by: Mason Daugherty <61371264+mdrxy@users.noreply.github.com>
Co-authored-by: Mason Daugherty <github@mdrxy.com>
Co-authored-by: Mason Daugherty <mason@langchain.dev>
2026-06-13 02:36:01 -04:00
Mason Daugherty 550a8abf3c fix(code): restore resumed thread model (#3651)
Resumed threads now carry the model they last used, so `dcode -r` can
continue the conversation with the same provider/model instead of
silently falling back to the current default. Explicit `--model`
selections still take precedence, and resume-driven switches stay
session-only so they do not rewrite the user's saved model preferences.
2026-05-28 17:19:38 -04:00
Mason Daugherty 2ac7d41533 feat(code): port from libs/cli (#3388)
Release-As: 0.1.0
2026-05-12 20:45:09 +00:00