-
Notifications
You must be signed in to change notification settings - Fork 3.3k
feat(agent): tinyagents 1.5 migration wave — vendored SDK, dual-write sessions, goals/todos shadows, journals, middleware dedupe #4473
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
a1ee598
1ec4c3a
c7f2873
e2f010c
4c28958
fbafad2
dd63b3a
5568ca2
1c4ce63
ce22061
ba20de2
1ac896f
634231a
2a97eb5
044c721
02be67b
5a1227d
efa23cd
1a2f124
7d71262
7b8f52a
800d620
840969f
e7bdbb7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -126,3 +126,4 @@ distribution.cer | |
| # Release note previews | ||
| CHANGELOG.preview.md | ||
| *.profraw | ||
| *.diff | ||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,21 +1,21 @@ | ||
| # 00 — Baseline: crate, features, native links | ||
|
|
||
| Current status (2026-07-02): baseline dependency alignment is complete in both | ||
| Cargo worlds. `tinyagents 1.3.0` is resolved with the `sqlite` feature, | ||
| Current status (2026-07-03): baseline dependency alignment is complete in both | ||
| Cargo worlds. `tinyagents 1.5.0` is resolved with the `sqlite` feature, | ||
| OpenHuman pins `rusqlite = "=0.40.0"`, both worlds patch through | ||
| `vendor/rusqlite-0.40.0` and `vendor/libsqlite3-sys-0.38.0`, and the SDK-gaps | ||
| inventory has been refreshed against the published 1.3.0 crate source. | ||
|
|
||
| ## Steps | ||
|
|
||
| 1. **Bump `tinyagents` to `"1.3"`** (done in both Cargo worlds — root and | ||
| 1. **Bump `tinyagents` to `"1.5.0"`** (done in both Cargo worlds — root and | ||
| `app/src-tauri/`). Known 1.1→1.2 break already handled | ||
| (`MessageDelta::text` ctor). Note: the `openai` crate feature was removed | ||
| after 1.2.0 (1.2.1+ features are only `sqlite`/`repl`) — we never enabled | ||
| it, so no impact. See "1.3.0 delta" below for new API this plan uses. | ||
| 2. **Align rusqlite to 0.40** in both worlds (`Cargo.toml` root and | ||
| `app/src-tauri/Cargo.toml`). OpenHuman pins `rusqlite = "=0.40.0"` and | ||
| enables `tinyagents = { version = "1.3", features = ["sqlite"] }`. | ||
| enables `tinyagents = { version = "1.5.0", features = ["sqlite"] }`. | ||
|
Comment on lines
+3
to
+18
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
rg -n 'NoProgressTracker|with_node_retry|1\.4\.0|1\.5\.0' docs/tinyagents-full-migration-plan/CONTINUATION-2026-07.md docs/tinyagents-full-migration-plan/HANDOFF-2026-07-03.md 2>/dev/nullRepository: tinyhumansai/openhuman Length of output: 4144 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '\n== baseline excerpts ==\n'
sed -n '1,120p' docs/tinyagents-full-migration-plan/00-baseline.md | cat -n
printf '\n== continuation excerpts ==\n'
sed -n '1,120p' docs/tinyagents-full-migration-plan/CONTINUATION-2026-07.md | cat -n
printf '\n== handoff excerpts ==\n'
sed -n '1,120p' docs/tinyagents-full-migration-plan/HANDOFF-2026-07-03.md | cat -nRepository: tinyhumansai/openhuman Length of output: 31494 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '\n== baseline references to delta/gaps ==\n'
rg -n '1\.3\.0 delta|SDK-gaps|NoProgressTracker|with_node_retry|1\.4\.0|1\.5\.0' docs/tinyagents-full-migration-plan/00-baseline.md docs/tinyagents-full-migration-plan/CONTINUATION-2026-07.md docs/tinyagents-full-migration-plan/HANDOFF-2026-07-03.mdRepository: tinyhumansai/openhuman Length of output: 5066 Update 🤖 Prompt for AI Agents |
||
| Compatibility notes: | ||
| - `rusqlite 0.40` and `libsqlite3-sys 0.38` are consumed directly from | ||
| crates.io. Their build scripts use the `cfg_select!` macro (stable from | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,103 @@ | ||
| # C2b — Task board / todos onto `graph::todos` (parity note) | ||
|
|
||
| Status: **first slice landed** (branch `feat/tinyagents-c2-todos`). Adapter-first, | ||
| shadow-only. Legacy stays authoritative; nothing here changes product behavior. | ||
|
|
||
| This note pairs with the CONTINUATION plan §C2 (step 3) and records what the | ||
| crate `tinyagents::graph::todos` surface maps onto in OpenHuman, and what it does | ||
| **not** — the residue that must stay in the product host after a future cutover. | ||
|
|
||
| ## What landed in this slice | ||
|
|
||
| - `src/openhuman/todos/graph_shadow.rs` — the adapter: | ||
| - Total, lossless status mapping OpenHuman ↔ crate (`map_status_to_crate` / | ||
| `map_status_from_crate`) — the two `TaskCardStatus` enums share the same | ||
| seven variants (`Todo`, `AwaitingApproval`, `Ready`, `InProgress`, | ||
| `Blocked`, `Done`, `Rejected`). | ||
| - `TaskBoardCard` field-by-field conversion (`to_crate_card`) — all metadata | ||
| (objective, plan, assignedAgent, allowedTools, approvalMode, | ||
| acceptanceCriteria, evidence, notes, blocker, sessionThreadId, | ||
| sourceMetadata, order, updatedAt) preserved. | ||
| - `spawn_mirror` — after every authoritative `todos::ops::save_cards` write of | ||
| a `Thread` board, mirrors the persisted cards into a crate `FileStore` | ||
| (`<workspace>/tinyagents_graph_store`) under namespace `graph.todos`. Fire- | ||
| and-forget, log-only; a crate rejection (e.g. the single-`InProgress` | ||
| invariant) is warn-logged as a **DIVERGENCE**. | ||
| - `spawn_shadow_claim` — wired into `todos::ops::claim_card` (which is the | ||
| single claim entry-point the dispatcher's two claim sites in | ||
| `task_dispatcher/dispatch.rs` funnel through, plus RPC/reclaim callers). It | ||
| seeds the crate board with the pre-claim snapshot and replays the crate | ||
| `claim_card` CAS, warn-logging when the crate ok/err verdict disagrees with | ||
| the authoritative legacy claim. | ||
|
|
||
| The legacy claim/save path is byte-for-byte preserved: `claim_card` was | ||
| refactored to compute one ok/err verdict via an extracted `apply_claim` helper | ||
| (so the shadow sees the same not-found / wrong-status / invariant outcomes), but | ||
| the persisted result and all existing tests are unchanged. | ||
|
|
||
| ## Crate `TodoTool` vs `agent/tools/todo.rs` — what maps | ||
|
|
||
| The crate ships a single multiplexer `TodoTool` (`op`-dispatched) that is a near | ||
| drop-in for the OpenHuman `todo` tool. Shared surface: | ||
|
|
||
| | Concern | Crate `TodoTool` | OpenHuman `tools/todo.rs` | Match? | | ||
| | --- | --- | --- | --- | | ||
| | Dispatch style | single tool, `op` field | single tool, `op` field | yes | | ||
| | Thread binding | `ToolExecutionContext::thread_id` (never an arg) | `thread_context::current_thread_id()` + `fork_context` parent | yes (both bind to current thread, never an arg) | | ||
| | `add`/`edit`/`update_status`/`remove`/`replace`/`clear`/`list` | present | present | yes | | ||
| | Optional card fields | objective/plan/assignedAgent/allowedTools/approvalMode/acceptanceCriteria/evidence/notes/blocker | same | yes | | ||
| | Return shape | `{ threadId, cards, markdown }` | `{ threadId, cards, markdown }` | yes | | ||
| | Status aliases | `parse_status` (pending→todo, approved→ready, …) | `ops::parse_status` (identical alias table) | yes | | ||
| | Single-`InProgress` invariant | `enforce_single_in_progress` (hard error) | `enforce_single_in_progress` (identical) | yes | | ||
| | `claim_card` CAS | `store::claim_card(expected, target)` | `ops::claim_card(expected, target)` | yes (identical semantics; proven by shadow tests) | | ||
|
|
||
| ## What does NOT map (product residue — must stay in the host) | ||
|
|
||
| 1. **Approval-gate coupling.** OpenHuman's `todo` tool stamps a default | ||
| `approvalMode` by reading `config.autonomy.require_task_plan_approval` | ||
| (`default_task_approval_mode`), and the dispatcher's | ||
| `requires_plan_approval` + `TaskPlanAwaitingApproval` `DomainEvent` drive the | ||
| interactive plan-review gate. The crate `TodoTool` has **no** config read and | ||
| **no** approval-gate wiring — it exposes `decide_plan`/`revise_plan` state | ||
| transitions only. The gate policy stays product. | ||
| 2. **`DomainEvent` emissions.** `ops::claim_card`/mutations emit | ||
| `AgentProgress::TaskBoardUpdated` (via `fork_context` `on_progress`) and the | ||
| dispatcher publishes `TaskPlanAwaitingApproval`. The crate store emits | ||
| nothing. All event vocabulary stays product (ledger: keep). | ||
| 3. **RPC projection shapes.** `threads.task_board_*` and `openhuman.todos_*` | ||
| (see `todos/schemas.rs`) are the wire contracts the kanban UI binds to | ||
| (`app/src/services/api/todosApi.ts`, `USER_TASKS_THREAD_ID = "user-tasks"`). | ||
| These are **unchanged** by this slice and, per §C2, become read-side | ||
| projections over the crate store only at cutover — not now. | ||
| 4. **Scratch board.** OpenHuman has a thread-less in-memory `BoardLocation::Scratch` | ||
| fallback (tool calls outside a chat thread). The crate board is always | ||
| `(Store, thread_id)`, so scratch mutations have **no** crate mirror target — | ||
| the shadow skips them (trace-logged). | ||
| 5. **Persistence substrate + timestamps.** Product persists RFC3339 | ||
| `updated_at` to `<workspace>/agent_task_boards/<hex(thread_id)>.json`; the | ||
| crate uses epoch-millis strings in a `Store` namespace. The mirror does not | ||
| reconcile timestamps (cosmetic). Card-id minting also differs | ||
| (`task-<uuid>` product vs `task-<seq>` crate) but ids are passed through, so a | ||
| persisted board round-trips. | ||
| 6. **Run lifecycle.** `todos/runs.rs` (run records, heartbeats, stale-reclaim) | ||
| and `task_dispatcher/` executor mechanics (executor resolution, autonomous | ||
| run, board write-back) are **not** part of the crate todos surface — they | ||
| stay product and are the §C2 step-3 "runner node" work, tracked separately. | ||
|
|
||
| ## Single-writer constraint | ||
|
|
||
| The crate `Store` has no compare-and-set, so ns `graph.todos` assumes a single | ||
| writer. The core process is that single writer (both the mirror and the | ||
| shadow-claim run in-core). Documented in the module header; honoured because all | ||
| mutations funnel through `todos::ops`. | ||
|
|
||
| ## Next (not in this slice) | ||
|
|
||
| - Flip the mirror from shadow to authoritative (crate store becomes the source | ||
| of truth; legacy JSON becomes a projection or is retired). | ||
| - Reimplement `threads.task_board_*` / `openhuman.todos_*` as projections over | ||
| the crate store. | ||
| - Replace the dispatcher claim/poll loop with the crate `claim_card` CAS + a | ||
| graph runner node, keeping `DomainEvent` emission + channel bindings product. | ||
| - Delete `task_board.rs` + todo CRUD mechanics + dispatcher executor mechanics | ||
| (~3.2k + tests) once parity logs are clean. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because this patch makes both Cargo worlds resolve
tinyagentsfromvendor/tinyagents, SDK changes can now change the compiled product without touchingCargo.toml,Cargo.lock, orsrc/**. I checked the PR CI path filters in.github/workflows/pr-ci.ymland they do not includevendor/tinyagentsor.gitmodules, so a PR that only bumps the submodule pointer would skip the Rust quality/coverage lanes and the Playwright artifact build/cache despite changing a compiled dependency. Add the submodule path (and usually.gitmodules) to the Rust/Tauri/playwright filters and related artifact cache keys so vendored SDK updates are actually built and tested.Useful? React with 👍 / 👎.