@bojackduy/opencode-loopd 1.11.2 → 1.12.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -6,7 +6,8 @@
6
6
 
7
7
  ### Added
8
8
 
9
- - **Agent model discovery and same-goal recovery** — `loopd_list_models` exposes safe provider/model metadata, host capabilities, and owner-scoped goal identities; `switch_goal_model` validates ownership/availability, defers busy workers, and preserves the existing worker session and budgets. Optional `fallbackModels` prepares ordered, one-shot alternatives only for observed provider quota/rate-limit errors; interactive goals never auto-wake. Explicit `resume:true` applies only to provider-limit-blocked goals. Remaining quota/reset information is **unknown/unsupported** in the inspected host APIs, never inferred from connected accounts or API keys. Covered by automated host/service/tool tests; no live provider-exhaustion or TUI proof claimed.
9
+ - **Unified same-goal identity switching** — `switch_goal_identity` replaces the separate model/agent owner tools and control operations. Optional `model` and `agent` fields support one-field changes or a combined transaction; at least one is required. Combined assignments persist atomically, busy pairs defer together, and successful host changes roll back on partial failure. Dashboard `:model`/`:agent` dispatch the unified operation. The existing goal, worker session, transcript, progress, checks and budgets are preserved; there is no implicit interactive wake. Explicit resume requires a blocked goal (model-only still requires a provider-limit blocker).
10
+ - **Agent model discovery and same-goal recovery** — `loopd_list_models` exposes safe provider/model metadata, host capabilities, and owner-scoped goal identities; `switch_goal_identity` validates ownership/availability, defers busy workers, and preserves the existing worker session and budgets. Optional `fallbackModels` prepares ordered, one-shot alternatives only for observed provider quota/rate-limit errors; interactive goals never auto-wake. Remaining quota/reset information is **unknown/unsupported** in the inspected host APIs, never inferred from connected accounts or API keys. Covered by automated host/service/tool tests; no live provider-exhaustion or TUI proof claimed.
10
11
  - **M1 pty parity** — `env` (values to host, names-only persistence), `timeout_seconds` (in-memory deadline → terminate path, `endReason=timeout`, always notifies), `shell:true` (`/bin/sh -c`), `pattern`+`ignore_case` log read (ANSI-stripped match, ReDoS guard), `terminate remove:true`, `endReason` (`exit|terminate|timeout|until|missing`) on every terminal transition.
11
12
  - **M2 sentinel watcher engine** — `watch_filter`/`watch_until`/`watch_ignore_case`/`watch_until_action (stop|keep)` at start, `loopd_command_watch` on running commands; 2s coalescing (20 lines/4KB), 100-lines/sec flood-suspend (process keeps running), 30-push budget; `until:stop` terminates with `endReason=until` and exactly one owner message; `loopd_command_await until:` wakes a goal once on match without stopping.
12
13
  - **M3 surface** — watch badges + endReason in Commands tab, watch counters in detail panel, SKILL.md watching guide with pty + sentinel migration tables, de-polled `loopd_command_get` docs.
package/README.md CHANGED
@@ -22,7 +22,7 @@
22
22
  - **Scheduled intervals** — `scheduleEveryMs`/`scheduleMaxRuns` auto-requeues the same goal every N ms (e.g., `10s` monitor, `1h` report) without manual `/goal` spam — `5s` poll, `skip-if-running`, `workspaceWrite` serialization, inbox `Scheduled tick N/M`.
23
23
  - **Modal TUI dashboard** — `<leader>o` or `/loop` opens a focused dialog (no leak to chat prompt). Vim-style navigation, live running indicator, per-status borders.
24
24
  - **Command sessions, not blocked shells** — run installs, builds, dev servers, and REPLs as background OS processes with a fullscreen terminal, owner exit notifications, line-level `filter`/`until` watches, and timeouts — instead of freezing the agent turn in `bash`.
25
- - **Switch models mid-run** — `loopd_list_models` discovers providers/models and quota status; `switch_goal_model` moves a goal to another model on the *same* worker/session when a provider hits quota. Optional ordered `fallbackModels` switch automatically on 429s. Dashboard: `:model`/`:models`.
25
+ - **Switch identity mid-run** — `loopd_list_models` discovers models and agents; `switch_goal_identity` changes a goal's model, agent, or both on the *same* worker/session. Combined changes persist atomically and roll back on partial failure. Optional ordered `fallbackModels` switch automatically on 429s. Dashboard: `:model`/`:agent` and `:models`/`:agents`.
26
26
  - **Manual mode for interactive work** — `interactive: true` (or `:interactive`) stops the engine from starting turns on its own; every turn comes from your `:send`/nudge. For tasks where the worker waits for input.
27
27
 
28
28
  Keywords: `opencode` `opencode-plugin` `background-agent` `autonomous` `subagent` `loop` `goal` `tui` `codex` `claude-code` `worker`
@@ -180,7 +180,7 @@ read_goal_transcript() — last N worker messages (what it's doing)
180
180
  send_goal_input(goalID, msg) — steer: "skip appendix PDFs"
181
181
  pause_goal(goalID) / resume / clear
182
182
  loopd_list_models() — providers/models, quota status (unknown where hosts can't report it)
183
- switch_goal_model(goalID, model) — same goal, new model (same worker/session)
183
+ switch_goal_identity({goal_id, model?, agent?}) — same goal, new identity (same worker/session; at least one field required)
184
184
  loopd_command_start(...) — installs/builds/servers as background processes (never block the turn in bash)
185
185
  ```
186
186
 
@@ -309,7 +309,7 @@ When a provider hits quota or rate limits mid-run:
309
309
 
310
310
  ```
311
311
  loopd_list_models() — what's connected, quota status (or honestly unknown)
312
- switch_goal_model(goalID, "other-provider/good-model") — same goal, same worker/session, transcript kept
312
+ switch_goal_identity({goal_id, model:"other-provider/good-model"}) — same goal, same worker/session, transcript kept
313
313
  ```
314
314
 
315
315
  - Busy workers defer the switch to the next turn (`→ pending … applies next turn`); idle ones switch immediately. On v1 the new model takes effect from the next prompt (no mid-stream session switch API); v2 switches the live session where supported, else reports `unsupported` without touching anything.