Files
orca/resources/plugins/declarative
Neil e24af39c47 feat(plugins): host API 1.7 — workspace ids, project/terminal list, terminal focus/close (#41508)
* feat(plugins): host API 1.7 — workspace ids, project/terminal list, terminal focus/close

Plugins that track workspaces and terminals across Orca had to read the private runtime
token or shell out to the CLI. Host API 1.7 gives them the same through consented methods:

- workspace.readContext (and workspace.changed) carry `workspaceId`, the id workspace.list
  gives; workspace.created/removed and agent.status.changed add `workspaceListId` beside
  their existing raw `workspaceId`, which keeps its meaning.
- workspace.list rows name their `projectId`; opt-in `includeStatus` joins each row's agent
  state, unread flag, live terminal count and last activity from worktree.ps.
- project.list (workspace:read), terminal.list (workspace:read), terminal.focus
  (workspace:write, desktop only, steers only this window) and terminal.close
  (terminal:send, reports whether the process is known to have stopped).
- Runtime refusals (unknown or ambiguous workspace, stale or exited terminal) reach plugins
  as fixed messages instead of runtime wording.
- Consent copy for workspace:read, workspace:write and terminal:send says what they now
  allow; terminal.focus and terminal.close are audited by terminal id.
- PLUGIN_SCHEMA_NEWEST_SINCE covers the editor typography and theme video floors it missed,
  and the provisional 1.7 floor, so development builds accept plugins requiring them.

* fix(plugins): narrow terminal.close and harden host API 1.7 from review

- terminal.close closes only terminals of the focused workspace (the check terminal.sendText
  uses) or ones this plugin opened with terminal.create or agent.launch, recorded in a bounded
  per-plugin registry that is forgotten when its worker stops or it is disabled or removed.
  terminal.focus stays any-terminal; summaries and terminal:send copy say so.
- Lifecycle events carry the worktree's identity and host: from the new row on create, and read
  host-qualified before the purge on every removal path. agent.status.changed looks up the
  identity on the reporting host only. The global removed-identity map is gone.
- includeStatus shares one in-flight worktree.ps and a 1 s cache across plugins, and reports
  statusTruncated when that listing stopped short.
- Stored remote contexts get their identity host-qualified; panels and editors never get a raw,
  path-bearing workspace id from readContext or workspace.changed.
- Runtime refusals map to fixed messages (tab pinned, no window, tab gone, host disconnected);
  any other runtime error or malformed answer is a fixed action_failed with the detail logged.
- hostId is `local`, `ssh:` or `runtime:` in both workspace.list and project.list; rows past the
  id or path bounds are left out with truncated set instead of failing the list.
- The mock testing host answers terminal.focus and terminal.close by default.

* fix(plugins): keep shipped host API values and codes; honest terminal results

- workspace.list hostId keeps the values 1.3 shipped (recorded host, else null; folder rows
  their executionHostId); project.list always names the host. Both summaries say which.
- Methods that shipped before 1.7 report every runtime refusal as action_failed, as before;
  the unavailable/conflict mapping applies to 1.7 methods only.
- includeStatus shares a pending worktree.ps however long it runs; the 1 s TTL starts when it
  lands.
- The opened-terminal registry records only for a call still approved and not cancelled, and is
  pruned on disable or removal only, so event-driven workers keep close rights across restarts.
- terminal.close answers { closed: true }: a local close cannot tell whether the process exited.
  terminal.focus answers focused: false when the request was superseded or not navigated.
- workspace.list and project.list cut labels to 512 instead of failing the list.
- Removal events from the runtime job and the IPC retry are tested to carry the identity read
  before the purge; folder deletion carries its host.

* fix(plugins): name the status-listing owner type
2026-11-12 04:06:19 -08:00
..