Skip to content

feat: index Devin sessions - #48

Merged
iAmCorey merged 5 commits into
iAmCorey:mainfrom
BUKOWSKIREAL:feat/devin-sessions
Sep 24, 2026
Merged

iAmCorey merged 5 commits into
iAmCorey:mainfrom
BUKOWSKIREAL:feat/devin-sessions

Conversation

@BUKOWSKIREAL

Copy link
Copy Markdown
Contributor

Summary

Adds Devin (Cognition's agent) as a twentieth adapter, closing #46.

Devin stores sessions in a plaintext SQLite database at ~/.local/share/devin/cli/sessions.db (XDG data dir; ~/Library/Application Support/devin is probed as a legacy macOS candidate). sessions carries metadata plus main_chain_id; message_nodes is a forest where retries and edits branch off mid-chain nodes. The visible transcript is the chain walked back from that leaf along parent_node_id. When the leaf column is missing (older schemas), dangling, or the walk cannot reach a root, the adapter falls back to every node in write order — a session body can never silently vanish.

  • hidden = 1 sessions (compaction helpers, deleted sessions) and zero-content sessions are not listed.
  • chat_message JSON is decoded per node: user/assistant/system/tool roles, thinking objects (sealed signatures dropped), tool_calls arguments with role="tool" rows back-filling output via tool_call_id, per-message generation_model (more authoritative than the session row's model), and metrics token counts accumulated along the main chain — including assistant nodes with empty content that still spent tokens.
  • Internal traffic folds to Meta rather than counting as conversation: system rows, non-user telemetry sources (cache keep-alive), is_user_input == false, and compaction request bodies; <summary> replies collapse into CompactSummary.
  • Open In resumes a session with devin --resume <id> inside its project directory (sessions are bucketed by cwd).
  • Remote sync mirrors cli/sessions.db (+ WAL) under the host cache. Credentials live under ~/.config/devin, outside the data root, and are never synced.

Reviewers may want to look at crates/wake-core/src/adapters/devin.rs (schema probing, main-chain reconstruction, Meta classification) and the synthetic fixture in crates/wake-core/tests/common/mod.rs, which exercises hidden sessions, a retry side branch, keep-alive/compaction Meta folding, and token accumulation.

Closes #46

BUKOWSKIREAL and others added 3 commits September 24, 2026 11:51
Devin (Cognition's agent) stores sessions in a plaintext SQLite database
at `~/.local/share/devin/cli/sessions.db` (XDG data dir; the macOS
app-support directory is probed as a legacy candidate). `sessions`
carries metadata plus `main_chain_id`; `message_nodes` is a forest where
retries and edits branch off mid-chain nodes, so the visible transcript
is the chain walked back from that leaf along `parent_node_id`. Missing
columns (older schemas), a dangling leaf or a cyclic chain fall back to
listing every node — a session body can never silently vanish.

- `hidden = 1` sessions (compaction helpers, deleted) and zero-content
  sessions are not listed.
- `chat_message` JSON is decoded per node: user/assistant/system/tool
  roles, `thinking` objects (sealed signatures dropped), `tool_calls`
  with `role="tool"` rows back-filling output by `tool_call_id`,
  per-message `generation_model`, and `metrics` token counts accumulated
  along the main chain — including assistant nodes with empty content
  that still spent tokens.
- Internal traffic folds to Meta: `system` rows, non-`user` telemetry
  sources (cache keep-alive), `is_user_input == false` and compaction
  request bodies; `<summary>` replies collapse into CompactSummary.
- Open In resumes with `devin --resume <id>` inside the session's
  project directory (sessions are bucketed by cwd).
- Remote sync mirrors `cli/sessions.db` (+ WAL) under the host cache;
  credentials live under `~/.config/devin`, outside the data root, and
  are never synced.

Closes iAmCorey#46

Co-Authored-By: Devin <noreply@cognition.ai>
Resolve the conflicts with Craft Agents (iAmCorey#44), which landed on main after
this branch was cut: Devin goes after Craft Agents in the enum, the sidebar
order, the roster, the remote layouts, the brand list, the chart colors and
the docs, and the agent counts become twenty-one. Both Unreleased CHANGELOG
entries are kept, and the Devin one credits the contributor.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…wn nodes

- main_chain: when a node on the way back from the leaf points at a parent
  that is not in the database, the walk stopped there and returned only the
  tail of the conversation. It now falls back to every node, as its doc
  comment says, and walks indices first so nodes are moved instead of cloned.
- decode_nodes: chat_message values that do not parse and roles outside the
  known set are counted as unknown lines, Wake's format-drift canary,
  instead of being dropped silently.
- Insights color: the azure at the top of the icon's gradient, which sits
  farther from Gemini and Cursor than the previous blue (CIEDE2000 from
  Gemini 9.2 -> 13.4).

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

Copy link
Copy Markdown
Owner

Thanks for this! It follows Wake's adapter conventions closely, and the fixture covers the tricky parts: the retry branch, the keep-alive and compaction traffic, and token accounting. I pushed two commits to your branch:

  1. Merge of main. Craft Agents (Support for Craft Agents #44) landed after you branched, and both PRs append to the same lists. Devin now comes after Craft Agents everywhere (enum and sidebar order, roster, remote layouts, brand list, chart colors, docs), the counts say twenty-one, and the CHANGELOG line credits you.
  2. fix(devin):
    • When a node on the way back from main_chain_id pointed at a parent that isn't in the database, main_chain returned only the tail of the session. It now falls back to every node, which is what its doc comment already promised. It also walks indices first, so nodes are moved instead of cloned.
    • chat_message values that don't parse, and roles other than user / assistant / tool / system, are now counted as unknown lines instead of being dropped silently. Wake uses that count to notice format drift.
    • The Insights color is now the azure at the top of the icon's gradient. The previous blue was hard to tell apart from Gemini's in the stacked chart.

One question I can't answer without a Devin install. A user message is folded into Meta whenever its metadata.telemetry.source is anything other than "user". Which values of that field show up in your database? For example:

SELECT json_extract(chat_message, '$.metadata.telemetry.source') AS source, count(*)
FROM message_nodes
WHERE json_extract(chat_message, '$.role') = 'user'
GROUP BY source;

If Devin Desktop or another entry point records real prompts under a different source, those prompts would disappear from titles, search and the Insights prompt counts, and I'd add those sources to the allow-list.

I'll merge once CI is green. A fix for the source question can follow separately.

iAmCorey and others added 2 commits September 25, 2026 00:51
On Windows, joining "cli/sessions.db" keeps the forward slash, so the
adapter's virtual path (…\devin\cli/sessions.db) and the fixture's
(…\.local/share/devin/cli/sessions.db) named the same file with different
strings, and devin_parse_contract failed on windows-2022. Both sides now
join one segment at a time and get native separators.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The icon in this PR was Devin Desktop's whole macOS app tile (a blueprint
grid with a W), which turns to noise at sidebar size and differs from the
logos every other agent uses. It is now the mark devin.ai uses: three
hexagons around a round notch, rendered from the site's SVG and cropped to
the mark. Like Cursor and Grok it is monochrome, so there is a white
version for dark mode (devin.png) and an ink one for light mode
(devin-light.png).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@iAmCorey
iAmCorey merged commit 7fa32e1 into iAmCorey:main Sep 24, 2026
3 checks passed
@BUKOWSKIREAL

BUKOWSKIREAL commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor Author

Data from my install (macOS, Devin Desktop — every session in sessions.db has backend_type = 'windsurf', so this covers the Desktop entry point):

SELECT json_extract(chat_message, '$.metadata.telemetry.source') AS source,
       json_extract(chat_message, '$.metadata.is_user_input')  AS is_user_input,
       count(*)
FROM message_nodes
WHERE json_extract(chat_message, '$.role') = 'user'
GROUP BY source, is_user_input;
source is_user_input count
user 1 3172
user NULL 176
cache_keepalive NULL 166

So for role = 'user' the only sources are user and cache_keepalive — real prompts, including ones typed into Devin Desktop, always record source = 'user'. Nothing else to allow-list on this install; cache_keepalive is exactly the internal traffic it's meant to fold. (Caveat: I can't speak for a pure-CLI Linux install.)

One subtlety worth knowing: the 176 source = 'user' rows with is_user_input NULL are compaction requests — their content starts with Conversation to summarize:. The source allow-list alone would not exclude them; they're only caught by the compaction-body matching already in the adapter. So that content check is load-bearing, not redundant.

Unrelated heads-up: Desktop also keeps a per-session ACP transport log at ~/Library/Application Support/devin/User/acp-messages/*.db with a different schema (messages(position, kind, payload)). The same sessions still land in sessions.db, so adapter coverage is unaffected — just flagging it in case Wake ever wants to read that store.

@BUKOWSKIREAL
BUKOWSKIREAL deleted the feat/devin-sessions branch September 24, 2026 17:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support for Devin CLI sessions

2 participants