@elizaos/plugin-agent-orchestrator 2.0.0-beta.1 → 2.0.3-beta.3
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 +6 -8
- package/README.md +102 -30
- package/dist/cjs/index.node.cjs +17539 -17068
- package/dist/cjs/index.node.js.map +71 -61
- package/dist/node/index.node.js +17545 -17070
- package/dist/node/index.node.js.map +71 -61
- package/dist/node/src/actions/common.d.ts +62 -4
- package/dist/node/src/actions/common.d.ts.map +1 -1
- package/dist/node/src/actions/elizaos-capability.d.ts +3 -0
- package/dist/node/src/actions/elizaos-capability.d.ts.map +1 -0
- package/dist/node/src/actions/sandbox-stub.d.ts +9 -5
- package/dist/node/src/actions/sandbox-stub.d.ts.map +1 -1
- package/dist/node/src/actions/tasks.d.ts +22 -2
- package/dist/node/src/actions/tasks.d.ts.map +1 -1
- package/dist/node/src/api/agent-routes.d.ts +1 -1
- package/dist/node/src/api/agent-routes.d.ts.map +1 -1
- package/dist/node/src/api/bridge-routes.d.ts +57 -19
- package/dist/node/src/api/bridge-routes.d.ts.map +1 -1
- package/dist/node/src/api/credential-prompt.d.ts +38 -0
- package/dist/node/src/api/credential-prompt.d.ts.map +1 -0
- package/dist/node/src/api/orchestrator-routes.d.ts +25 -0
- package/dist/node/src/api/orchestrator-routes.d.ts.map +1 -0
- package/dist/node/src/api/parent-context-routes.d.ts.map +1 -1
- package/dist/node/src/api/route-utils.d.ts +23 -7
- package/dist/node/src/api/route-utils.d.ts.map +1 -1
- package/dist/node/src/api/routes.d.ts +1 -2
- package/dist/node/src/api/routes.d.ts.map +1 -1
- package/dist/node/src/evaluators/sub-agent-completion.d.ts +3 -0
- package/dist/node/src/evaluators/sub-agent-completion.d.ts.map +1 -0
- package/dist/node/src/index.d.ts +33 -8
- package/dist/node/src/index.d.ts.map +1 -1
- package/dist/node/src/providers/action-examples.d.ts.map +1 -1
- package/dist/node/src/providers/active-sub-agents.d.ts.map +1 -1
- package/dist/node/src/providers/active-workspace-context.d.ts +2 -2
- package/dist/node/src/providers/active-workspace-context.d.ts.map +1 -1
- package/dist/node/src/providers/available-agents.d.ts.map +1 -1
- package/dist/node/src/providers/coding-session-changes.d.ts +17 -0
- package/dist/node/src/providers/coding-session-changes.d.ts.map +1 -0
- package/dist/node/src/register-routes.d.ts +21 -1
- package/dist/node/src/register-routes.d.ts.map +1 -1
- package/dist/node/src/services/acceptance-criteria.d.ts +84 -0
- package/dist/node/src/services/acceptance-criteria.d.ts.map +1 -0
- package/dist/node/src/services/acp-native-transport.d.ts +111 -0
- package/dist/node/src/services/acp-native-transport.d.ts.map +1 -0
- package/dist/node/src/services/acp-service.d.ts +169 -4
- package/dist/node/src/services/acp-service.d.ts.map +1 -1
- package/dist/node/src/services/active-session-forward.d.ts +31 -0
- package/dist/node/src/services/active-session-forward.d.ts.map +1 -0
- package/dist/node/src/services/agent-name-assignment.d.ts +50 -0
- package/dist/node/src/services/agent-name-assignment.d.ts.map +1 -0
- package/dist/node/src/services/ansi-utils.d.ts +1 -1
- package/dist/node/src/services/app-deploy-guidance.d.ts +52 -0
- package/dist/node/src/services/app-deploy-guidance.d.ts.map +1 -0
- package/dist/node/src/services/audit.d.ts +18 -0
- package/dist/node/src/services/audit.d.ts.map +1 -0
- package/dist/node/src/services/coding-account-selection.d.ts +79 -0
- package/dist/node/src/services/coding-account-selection.d.ts.map +1 -0
- package/dist/node/src/services/completion-envelope.d.ts +63 -0
- package/dist/node/src/services/completion-envelope.d.ts.map +1 -0
- package/dist/node/src/services/completion-evidence.d.ts +144 -0
- package/dist/node/src/services/completion-evidence.d.ts.map +1 -0
- package/dist/node/src/services/config-env.d.ts +11 -7
- package/dist/node/src/services/config-env.d.ts.map +1 -1
- package/dist/node/src/services/goal-contract.d.ts +25 -0
- package/dist/node/src/services/goal-contract.d.ts.map +1 -0
- package/dist/node/src/services/goal-llm-verifier.d.ts +157 -0
- package/dist/node/src/services/goal-llm-verifier.d.ts.map +1 -0
- package/dist/node/src/services/goal-prompt.d.ts +82 -0
- package/dist/node/src/services/goal-prompt.d.ts.map +1 -0
- package/dist/node/src/services/independent-verifier.d.ts +58 -0
- package/dist/node/src/services/independent-verifier.d.ts.map +1 -0
- package/dist/node/src/services/interruption-decider.d.ts +43 -0
- package/dist/node/src/services/interruption-decider.d.ts.map +1 -0
- package/dist/node/src/services/opencode-config.d.ts +21 -0
- package/dist/node/src/services/opencode-config.d.ts.map +1 -0
- package/dist/node/src/services/orchestrator-device-support-matrix.d.ts +46 -0
- package/dist/node/src/services/orchestrator-device-support-matrix.d.ts.map +1 -0
- package/dist/node/src/services/orchestrator-task-mapper.d.ts +192 -0
- package/dist/node/src/services/orchestrator-task-mapper.d.ts.map +1 -0
- package/dist/node/src/services/orchestrator-task-service.d.ts +370 -0
- package/dist/node/src/services/orchestrator-task-service.d.ts.map +1 -0
- package/dist/node/src/services/orchestrator-task-store.d.ts +156 -0
- package/dist/node/src/services/orchestrator-task-store.d.ts.map +1 -0
- package/dist/node/src/services/orchestrator-task-types.d.ts +334 -0
- package/dist/node/src/services/orchestrator-task-types.d.ts.map +1 -0
- package/dist/node/src/services/parent-agent-broker.d.ts +5 -3
- package/dist/node/src/services/parent-agent-broker.d.ts.map +1 -1
- package/dist/node/src/services/parent-agent-dispatch.d.ts +62 -0
- package/dist/node/src/services/parent-agent-dispatch.d.ts.map +1 -0
- package/dist/node/src/services/screenshot-delivery.d.ts +38 -0
- package/dist/node/src/services/screenshot-delivery.d.ts.map +1 -0
- package/dist/node/src/services/session-event-queue.d.ts +1 -8
- package/dist/node/src/services/session-event-queue.d.ts.map +1 -1
- package/dist/node/src/services/session-store.d.ts +2 -1
- package/dist/node/src/services/session-store.d.ts.map +1 -1
- package/dist/node/src/services/skill-lifeops-context-broker.d.ts +1 -1
- package/dist/node/src/services/skill-lifeops-context-broker.d.ts.map +1 -1
- package/dist/node/src/services/skill-manifest.d.ts +1 -1
- package/dist/node/src/services/skill-recommender.d.ts +2 -0
- package/dist/node/src/services/skill-recommender.d.ts.map +1 -1
- package/dist/node/src/services/smithers-task-executor.d.ts +73 -0
- package/dist/node/src/services/smithers-task-executor.d.ts.map +1 -0
- package/dist/node/src/services/smithers-task-integration.d.ts +52 -0
- package/dist/node/src/services/smithers-task-integration.d.ts.map +1 -0
- package/dist/node/src/services/smithers-task-runner.d.ts +27 -0
- package/dist/node/src/services/smithers-task-runner.d.ts.map +1 -0
- package/dist/node/src/services/smithers-task-types.d.ts +96 -0
- package/dist/node/src/services/smithers-task-types.d.ts.map +1 -0
- package/dist/node/src/services/spawn-trajectory.d.ts +2 -2
- package/dist/node/src/services/spawn-trajectory.d.ts.map +1 -1
- package/dist/node/src/services/spend-allowance.d.ts +143 -0
- package/dist/node/src/services/spend-allowance.d.ts.map +1 -0
- package/dist/node/src/services/ssrf-guard.d.ts +66 -0
- package/dist/node/src/services/ssrf-guard.d.ts.map +1 -0
- package/dist/node/src/services/sub-agent-identity.d.ts +27 -0
- package/dist/node/src/services/sub-agent-identity.d.ts.map +1 -0
- package/dist/node/src/services/sub-agent-inbox.d.ts +26 -0
- package/dist/node/src/services/sub-agent-inbox.d.ts.map +1 -0
- package/dist/node/src/services/sub-agent-router.d.ts +142 -2
- package/dist/node/src/services/sub-agent-router.d.ts.map +1 -1
- package/dist/node/src/services/task-agent-frameworks.d.ts +21 -8
- package/dist/node/src/services/task-agent-frameworks.d.ts.map +1 -1
- package/dist/node/src/services/task-agent-routing.d.ts +33 -0
- package/dist/node/src/services/task-agent-routing.d.ts.map +1 -0
- package/dist/node/src/services/task-supervisor-service.d.ts +65 -0
- package/dist/node/src/services/task-supervisor-service.d.ts.map +1 -0
- package/dist/node/src/services/task-watchdog-service.d.ts +50 -0
- package/dist/node/src/services/task-watchdog-service.d.ts.map +1 -0
- package/dist/node/src/services/terminal-capabilities.d.ts +48 -0
- package/dist/node/src/services/terminal-capabilities.d.ts.map +1 -0
- package/dist/node/src/services/trajectory-context.d.ts +4 -8
- package/dist/node/src/services/trajectory-context.d.ts.map +1 -1
- package/dist/node/src/services/trajectory-feedback.d.ts +1 -1
- package/dist/node/src/services/types.d.ts +38 -2
- package/dist/node/src/services/types.d.ts.map +1 -1
- package/dist/node/src/services/view-deploy-guidance.d.ts +14 -0
- package/dist/node/src/services/view-deploy-guidance.d.ts.map +1 -0
- package/dist/node/src/services/workdir-validation.d.ts +10 -0
- package/dist/node/src/services/workdir-validation.d.ts.map +1 -0
- package/dist/node/src/services/workspace-diff.d.ts +50 -0
- package/dist/node/src/services/workspace-diff.d.ts.map +1 -0
- package/dist/node/src/services/workspace-git-ops.d.ts +2 -2
- package/dist/node/src/services/workspace-git-ops.d.ts.map +1 -1
- package/dist/node/src/services/workspace-github.d.ts +7 -7
- package/dist/node/src/services/workspace-github.d.ts.map +1 -1
- package/dist/node/src/services/workspace-lifecycle.d.ts +2 -15
- package/dist/node/src/services/workspace-lifecycle.d.ts.map +1 -1
- package/dist/node/src/services/workspace-service.d.ts +6 -2
- package/dist/node/src/services/workspace-service.d.ts.map +1 -1
- package/dist/node/src/setup-routes.d.ts.map +1 -1
- package/docs/SUBAGENT_FLOW_AND_PARITY.md +138 -0
- package/docs/default-eliza-skills-and-agent-bridge-plan.md +9 -15
- package/docs/economics-goal-runbook.md +140 -0
- package/docs/multi-account-orchestration.md +76 -0
- package/docs/orchestrator-buildout-followups.md +124 -0
- package/docs/orchestrator-dashboard-task-widget-secrets-assessment.md +174 -0
- package/docs/orchestrator-dashboard-task-widget-secrets-design.md +301 -0
- package/docs/research/orchestrator-view-research-report.md +273 -0
- package/docs/sub-agent-routing.md +53 -23
- package/package.json +111 -25
- package/PROJECT.md +0 -119
- package/dist/browser/index.browser.js +0 -21051
- package/dist/browser/index.browser.js.map +0 -29
- package/dist/browser/index.d.ts +0 -2
- package/dist/node/index.browser.d.ts +0 -3
- package/dist/node/index.browser.d.ts.map +0 -1
- package/dist/node/src/actions/cancel-task.d.ts +0 -3
- package/dist/node/src/actions/cancel-task.d.ts.map +0 -1
- package/dist/node/src/actions/coding-task-handlers.d.ts +0 -69
- package/dist/node/src/actions/coding-task-handlers.d.ts.map +0 -1
- package/dist/node/src/actions/coding-task-helpers.d.ts +0 -35
- package/dist/node/src/actions/coding-task-helpers.d.ts.map +0 -1
- package/dist/node/src/actions/create-task.d.ts +0 -8
- package/dist/node/src/actions/create-task.d.ts.map +0 -1
- package/dist/node/src/actions/eval-metadata.d.ts +0 -11
- package/dist/node/src/actions/eval-metadata.d.ts.map +0 -1
- package/dist/node/src/actions/finalize-workspace.d.ts +0 -11
- package/dist/node/src/actions/finalize-workspace.d.ts.map +0 -1
- package/dist/node/src/actions/list-agents.d.ts +0 -4
- package/dist/node/src/actions/list-agents.d.ts.map +0 -1
- package/dist/node/src/actions/manage-issues.d.ts +0 -11
- package/dist/node/src/actions/manage-issues.d.ts.map +0 -1
- package/dist/node/src/actions/provision-workspace.d.ts +0 -11
- package/dist/node/src/actions/provision-workspace.d.ts.map +0 -1
- package/dist/node/src/actions/send-to-agent.d.ts +0 -4
- package/dist/node/src/actions/send-to-agent.d.ts.map +0 -1
- package/dist/node/src/actions/spawn-agent.d.ts +0 -8
- package/dist/node/src/actions/spawn-agent.d.ts.map +0 -1
- package/dist/node/src/actions/stop-agent.d.ts +0 -4
- package/dist/node/src/actions/stop-agent.d.ts.map +0 -1
- package/dist/node/src/actions/task-control.d.ts +0 -3
- package/dist/node/src/actions/task-control.d.ts.map +0 -1
- package/dist/node/src/actions/task-history.d.ts +0 -3
- package/dist/node/src/actions/task-history.d.ts.map +0 -1
- package/dist/node/src/actions/task-share.d.ts +0 -3
- package/dist/node/src/actions/task-share.d.ts.map +0 -1
- package/dist/node/src/actions/task-thread-target.d.ts +0 -11
- package/dist/node/src/actions/task-thread-target.d.ts.map +0 -1
- package/dist/node/src/api/coordinator-routes.d.ts +0 -22
- package/dist/node/src/api/coordinator-routes.d.ts.map +0 -1
- package/dist/node/src/api/hook-routes.d.ts +0 -18
- package/dist/node/src/api/hook-routes.d.ts.map +0 -1
- package/dist/node/src/routes/coding-agents-fallback-routes.d.ts +0 -19
- package/dist/node/src/routes/coding-agents-fallback-routes.d.ts.map +0 -1
- package/dist/node/src/services/acpx-subprocess.d.ts +0 -3
- package/dist/node/src/services/acpx-subprocess.d.ts.map +0 -1
- package/dist/node/src/services/agent-credentials.d.ts +0 -23
- package/dist/node/src/services/agent-credentials.d.ts.map +0 -1
- package/dist/node/src/services/agent-metrics.d.ts +0 -30
- package/dist/node/src/services/agent-metrics.d.ts.map +0 -1
- package/dist/node/src/services/agent-selection.d.ts +0 -53
- package/dist/node/src/services/agent-selection.d.ts.map +0 -1
- package/dist/node/src/services/claude-code-skill-installer.d.ts +0 -33
- package/dist/node/src/services/claude-code-skill-installer.d.ts.map +0 -1
- package/dist/node/src/services/coordinator-event-normalizer.d.ts +0 -50
- package/dist/node/src/services/coordinator-event-normalizer.d.ts.map +0 -1
- package/dist/node/src/services/custom-validator-runner.d.ts +0 -66
- package/dist/node/src/services/custom-validator-runner.d.ts.map +0 -1
- package/dist/node/src/services/debug-capture.d.ts +0 -38
- package/dist/node/src/services/debug-capture.d.ts.map +0 -1
- package/dist/node/src/services/pty-auto-response.d.ts +0 -30
- package/dist/node/src/services/pty-auto-response.d.ts.map +0 -1
- package/dist/node/src/services/pty-init.d.ts +0 -55
- package/dist/node/src/services/pty-init.d.ts.map +0 -1
- package/dist/node/src/services/pty-service.d.ts +0 -218
- package/dist/node/src/services/pty-service.d.ts.map +0 -1
- package/dist/node/src/services/pty-session-io.d.ts +0 -49
- package/dist/node/src/services/pty-session-io.d.ts.map +0 -1
- package/dist/node/src/services/pty-spawn.d.ts +0 -104
- package/dist/node/src/services/pty-spawn.d.ts.map +0 -1
- package/dist/node/src/services/pty-types.d.ts +0 -94
- package/dist/node/src/services/pty-types.d.ts.map +0 -1
- package/dist/node/src/services/skill-callback-bridge.d.ts +0 -78
- package/dist/node/src/services/skill-callback-bridge.d.ts.map +0 -1
- package/dist/node/src/services/skill-essentials.d.ts +0 -16
- package/dist/node/src/services/skill-essentials.d.ts.map +0 -1
- package/dist/node/src/services/stall-classifier.d.ts +0 -69
- package/dist/node/src/services/stall-classifier.d.ts.map +0 -1
- package/dist/node/src/services/structured-proof-bridge.d.ts +0 -99
- package/dist/node/src/services/structured-proof-bridge.d.ts.map +0 -1
- package/dist/node/src/services/swarm-coordinator-prompts.d.ts +0 -93
- package/dist/node/src/services/swarm-coordinator-prompts.d.ts.map +0 -1
- package/dist/node/src/services/swarm-coordinator.d.ts +0 -473
- package/dist/node/src/services/swarm-coordinator.d.ts.map +0 -1
- package/dist/node/src/services/swarm-decision-loop.d.ts +0 -69
- package/dist/node/src/services/swarm-decision-loop.d.ts.map +0 -1
- package/dist/node/src/services/swarm-event-triage.d.ts +0 -49
- package/dist/node/src/services/swarm-event-triage.d.ts.map +0 -1
- package/dist/node/src/services/swarm-history.d.ts +0 -27
- package/dist/node/src/services/swarm-history.d.ts.map +0 -1
- package/dist/node/src/services/swarm-idle-watchdog.d.ts +0 -22
- package/dist/node/src/services/swarm-idle-watchdog.d.ts.map +0 -1
- package/dist/node/src/services/task-acceptance.d.ts +0 -8
- package/dist/node/src/services/task-acceptance.d.ts.map +0 -1
- package/dist/node/src/services/task-agent-auth.d.ts +0 -69
- package/dist/node/src/services/task-agent-auth.d.ts.map +0 -1
- package/dist/node/src/services/task-kind.d.ts +0 -3
- package/dist/node/src/services/task-kind.d.ts.map +0 -1
- package/dist/node/src/services/task-registry.d.ts +0 -550
- package/dist/node/src/services/task-registry.d.ts.map +0 -1
- package/dist/node/src/services/task-share.d.ts +0 -18
- package/dist/node/src/services/task-share.d.ts.map +0 -1
- package/dist/node/src/services/task-validation.d.ts +0 -69
- package/dist/node/src/services/task-validation.d.ts.map +0 -1
- package/dist/node/src/services/task-verifier-runner.d.ts +0 -5
- package/dist/node/src/services/task-verifier-runner.d.ts.map +0 -1
- package/dist/node/vitest.config.d.ts +0 -3
- package/dist/node/vitest.config.d.ts.map +0 -1
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Multi-account coding-agent orchestration
|
|
2
|
+
|
|
3
|
+
Goal: an Eliza orchestrator agent that runs **multiple Claude Code + Codex
|
|
4
|
+
subscriptions** (and rotates OpenCode across pooled Cerebras accounts), picks
|
|
5
|
+
the **least-used** account for each new
|
|
6
|
+
sub-agent, tracks per-account **session + weekly usage**, manages those
|
|
7
|
+
sub-agents in a **shared task room**, and decides **when to interrupt** a
|
|
8
|
+
running sub-agent vs. let it keep working.
|
|
9
|
+
|
|
10
|
+
## What already existed (do not rebuild)
|
|
11
|
+
|
|
12
|
+
| Layer | Location | Status |
|
|
13
|
+
|---|---|---|
|
|
14
|
+
| Account contracts (`LinkedAccountConfig`, `LinkedAccountUsage`, 12 provider ids) | `packages/contracts/src/service-routing.ts` | ✅ |
|
|
15
|
+
| Credential storage (`<stateDir>/auth/{providerId}/{accountId}.json`) | `packages/agent/src/auth/account-storage.ts` | ✅ |
|
|
16
|
+
| OAuth flows (Anthropic + Codex) + coding-plan keys + API keys | `packages/agent/src/auth/oauth-flow.ts`, `credentials.ts` | ✅ |
|
|
17
|
+
| `AccountPool` — priority / round-robin / **least-used** / quota-aware, affinity, health | `packages/app-core/src/services/account-pool.ts` | ✅ |
|
|
18
|
+
| Usage probes (`pollAnthropicUsage`, `pollCodexUsage`) + JSONL day counters | `packages/app-core/src/services/account-usage.ts` | ✅ |
|
|
19
|
+
| Accounts REST API (`/api/accounts/*` incl. OAuth SSE) | `packages/agent/src/api/accounts-routes.ts` | ✅ |
|
|
20
|
+
| Settings UI (AccountList / AccountCard / AddAccountDialog / RotationStrategyPicker) + `useAccounts` | `packages/ui/src/components/accounts/*` | ✅ |
|
|
21
|
+
| Multi-account API-key routing for the *main agent* | `credential-resolver.ts` → `resolveProviderCredentialMulti` | ✅ |
|
|
22
|
+
| Orchestrator tasks, sessions, task-rooms, event bridge, usage rollup, REST + SSE | `plugins/plugin-agent-orchestrator/*` | ✅ |
|
|
23
|
+
| `shouldRespond` (RESPOND/IGNORE/STOP) + per-room `TurnControllerRegistry` abort | `packages/core/src/*` | ✅ |
|
|
24
|
+
|
|
25
|
+
## The keystone gap
|
|
26
|
+
|
|
27
|
+
The `AccountPool` was wired into **API-key model routing** but **not into the
|
|
28
|
+
coding-agent spawn path**. Coding agents authenticate by *subscription*, not API
|
|
29
|
+
key: `applySubscriptionCredentialsLocal` never injects Claude/Codex tokens into
|
|
30
|
+
`process.env`, and `AcpService.buildEnv` even *strips* an OAuth
|
|
31
|
+
`ANTHROPIC_API_KEY` so Claude Code falls back to the single machine login
|
|
32
|
+
(`~/.claude`). So every spawned sub-agent used one account, with no rotation and
|
|
33
|
+
no per-account attribution.
|
|
34
|
+
|
|
35
|
+
The orchestrator plugin depends only on `@elizaos/core`, so it cannot import the
|
|
36
|
+
pool. `account-pool.ts` already solves this with `globalThis`-symbol **bridges**
|
|
37
|
+
(Anthropic + subscription-selector). We add a third: a **coding-agent selector
|
|
38
|
+
bridge**.
|
|
39
|
+
|
|
40
|
+
## Hitlist
|
|
41
|
+
|
|
42
|
+
### P0 — Keystone: account selection on spawn (round-robin / least-used)
|
|
43
|
+
- [x] `coding-account-bridge.ts` (app-core): install `Symbol.for("eliza.account-pool.coding-agent.v1")` bridge — `select(agentType)`, `markRateLimited`, `markNeedsReauth`, `recordUsage`, `describe()`.
|
|
44
|
+
- [x] Per-agent credential injection: claude → `CLAUDE_CODE_OAUTH_TOKEN`; codex → per-account `CODEX_HOME/auth.json` + minimal `config.toml`; opencode → `CEREBRAS_API_KEY` (pooled Cerebras); direct API providers → their env key.
|
|
45
|
+
- [x] Wire into `AcpService.spawnSession`: select before transport branch, merge `envPatch` into `customCredentials`, stamp `session.metadata.account*`, surface on `SpawnResult.metadata`.
|
|
46
|
+
- [x] `buildEnv`: when `CLAUDE_CODE_OAUTH_TOKEN` is injected for claude, drop `ANTHROPIC_API_KEY` so the selected subscription wins.
|
|
47
|
+
- [x] `OrchestratorTaskSession` carries `accountProviderId` / `accountId` / `accountLabel`; populate from `result.metadata`.
|
|
48
|
+
- [x] Exclude-on-failure retry: on auth/rate-limit error, mark account + re-select excluding it.
|
|
49
|
+
|
|
50
|
+
### P1 — Usage attribution + stats
|
|
51
|
+
- [x] `recordUsage` also calls the bridge → pool `recordCall` + `account-usage` JSONL keyed by the serving account.
|
|
52
|
+
- [x] `/api/orchestrator/accounts` route: connected accounts + live usage + which sub-agents are on which account.
|
|
53
|
+
- [x] Settings already shows per-account usage; orchestrator dashboard widget adds the accounts + usage summary.
|
|
54
|
+
|
|
55
|
+
### P2 — Room system + interruption decider
|
|
56
|
+
- [x] Per-participant interruption decider: a running sub-agent keeps working; a new room message is classified (deliver / queue / interrupt / ignore) before it is injected. The "busy" check covers `tool_running` (the dominant mid-turn state), not just `busy`; queued messages flush when the session returns to `ready`. An Eliza participant's `shouldRespond` verdict threads through unchanged when a caller supplies it; coding sub-agents use the structural decider. `multiParty` (more than one live sub-agent in the room) is computed in the forward handler so ambient-chatter suppression is live.
|
|
57
|
+
- [x] Task-room participant **view**: the "Coding accounts" sidebar widget shows the live sub-agent → account assignment map + per-account usage (the flat global map). The dedicated per-room participant roster (orchestrator + owning user + each sub-agent grouped by room, with `activeAgentCount` / `multiParty`) now ships as `GET /api/orchestrator/rooms` (`OrchestratorTaskService.getRoomRoster`), the room-scoped counterpart to `/accounts`. Rooms with no sub-agent sessions are omitted.
|
|
58
|
+
|
|
59
|
+
### P3 — Tests + mocks + live E2E
|
|
60
|
+
- [x] Mock account fixtures (multi-account, multi-provider) + an in-memory pool for unit tests.
|
|
61
|
+
- [x] Unit tests: selection strategy, per-agent env injection + API-key drop (Claude & Codex), intra-provider retry, usage attribution, interruption decider, route registration.
|
|
62
|
+
- [x] Live E2E (gated `ORCHESTRATOR_LIVE_MULTI_ACCOUNT=1`): validates the selector bridge + usage probe against ≥2 **real** linked accounts (distinct-account rotation via the exclude set; live session/weekly usage).
|
|
63
|
+
- [x] **Composed offline E2E** (`bun run --cwd plugins/plugin-agent-orchestrator test:e2e:multi-account`): real app-core `AccountPool` (real-format mock accounts in a temp state dir) → installed selector bridge → orchestrator `AcpService.spawnSession` / `sendToSession` → a REAL spawned subprocess (a fake "acpx" standing in for the subscription CLI). Asserts 11/11: two Claude spawns pick **distinct** accounts (least-used round-robin), each subprocess receives its account's `CLAUDE_CODE_OAUTH_TOKEN`, a follow-up prompt for the first Claude session reuses that session's selected account token, the parent `ANTHROPIC_API_KEY`/`OPENAI_API_KEY` are dropped, Codex gets a per-account `CODEX_HOME/auth.json` with the right token+account_id. Point `ELIZA_ACP_CLI` at the real binary + connect real accounts for true live-key validation. (This harness caught a real cli-transport bug: `runAcpx` rebuilt the env without `agentType`, re-adding the parent keys — now fixed.)
|
|
64
|
+
|
|
65
|
+
### P4 — Connect-accounts window
|
|
66
|
+
- [x] The connect-accounts window (Settings → Accounts: `AddAccountDialog` OAuth / API-key / coding-plan-key flows, `AccountList`, `RotationStrategyPicker`) pre-exists and is the surface for linking multiple accounts of each type.
|
|
67
|
+
|
|
68
|
+
## Known constraints / follow-ups
|
|
69
|
+
- **OpenCode pool-rotates across Cerebras accounts only.** OpenCode resolves a pooled key for exactly one backend — Cerebras (`CEREBRAS_API_KEY`, see `buildOpencodeSpawnConfig`) — so `opencode` is a multi-account selector type mapped to `cerebras-api`: it least-used-rotates across linked Cerebras accounts (the bridge injects the selected `CEREBRAS_API_KEY`, which OpenCode's config reads) and no-ops when none are linked (Eliza Cloud / single-key setups are unchanged). OpenCode's other backends (Eliza Cloud, local, user-configured opencode.json) are not pooled. Precedence: a `CEREBRAS_API_KEY` runtime **setting** still wins over a pooled injection — pooling is authoritative only when no single key is configured.
|
|
70
|
+
- **z.ai / Kimi / GLM have no first-party coding CLI.** Their linked accounts serve the main runtime's API-key routing (`resolveProviderCredentialMulti` for `zai-api` / `moonshot-api`) and OpenCode's provider config — there is no `zai`/`kimi`/`glm` spawnable agent type, so they are not advertised as coding-agent selector candidates.
|
|
71
|
+
|
|
72
|
+
## Quality bar
|
|
73
|
+
- No regression when zero accounts are linked (bridge returns null → today's behavior).
|
|
74
|
+
- Selected account is **observable** (session metadata + structured log + dashboard), never assumed.
|
|
75
|
+
- Subscription tokens only ever flow to the first-party coding subprocess (TOS), never into runtime `process.env`.
|
|
76
|
+
- Per-agent credential precedence is enforced: a selected Claude subscription drops `ANTHROPIC_API_KEY`; a selected Codex subscription (per-account `CODEX_HOME`) drops a forwarded `OPENAI_API_KEY` — so the chosen account always authenticates.
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# Orchestrator (`/orchestrator`) build-out — status & follow-ups
|
|
2
|
+
|
|
3
|
+
Date: 2026-05-29. Companion to [`research/orchestrator-view-research-report.md`](./research/orchestrator-view-research-report.md).
|
|
4
|
+
|
|
5
|
+
This records what was finished in the `nubs/orchestrator-view-feature` branch and the
|
|
6
|
+
exact, code-grounded plan for the remaining design-heavy work. The earlier research
|
|
7
|
+
report is largely **out of date**: the durable task model, SQL store, `/api/orchestrator/*`
|
|
8
|
+
routes, central goal-wrapper, validation-gated completion, token aggregation, the
|
|
9
|
+
`OrchestratorWorkbench` view, and the real (non-stub) client methods all already exist
|
|
10
|
+
(Shaw shipped most of it on 2026-05-29). Verify against current code, not the report's
|
|
11
|
+
line numbers.
|
|
12
|
+
|
|
13
|
+
## Done in this branch (verified)
|
|
14
|
+
|
|
15
|
+
1. **Mounted the sub-agent credential bridge** (`plugin-agent-orchestrator/src/api/routes.ts`).
|
|
16
|
+
`handleBridgeRoutes` was built+tested but never dispatched. + dispatcher regression test.
|
|
17
|
+
2. **Unified the goal-wrapper** so the `TASKS` planner action uses the central
|
|
18
|
+
`buildGoalPrompt`/`buildGoalFollowUp` (`goal-prompt.ts`, `actions/tasks.ts`) instead of a
|
|
19
|
+
divergent inline envelope. Workspace-routing / URL-mapping / swarm-room content preserved
|
|
20
|
+
via new optional `GoalPromptInput` fields. + equivalence test (action env == API env).
|
|
21
|
+
3. **Folded durable task threads into `getCodingAgentStatus`** (`packages/ui` client) — was
|
|
22
|
+
hardcoded to `taskThreadCount:0`. Documented the two genuinely-vestigial ACP stubs
|
|
23
|
+
(`/metrics`, `/workspace-files`) pointing at the real `/api/orchestrator/*` usage surface.
|
|
24
|
+
4. **Declared capability param schemas** for the 15 orchestrator view capabilities so
|
|
25
|
+
voice/NL routing can pass `taskId`/`title`/`goal`/etc. **Mounted the sensitive-request
|
|
26
|
+
REST routes** (`packages/app-core/src/api/server.ts`) — the secret create/submit/fulfill
|
|
27
|
+
path that orchestrator provider setup will use.
|
|
28
|
+
5. **Locked capability manifest↔dispatch parity** with a regression test
|
|
29
|
+
(`plugin-task-coordinator/__tests__/unit/orchestrator-capability-parity.test.ts`) + a
|
|
30
|
+
`test` script so CI runs it. The declared capabilities (`ORCHESTRATOR_CAPABILITIES` in
|
|
31
|
+
`index.ts`) must exactly match the ids `runOrchestratorCapability` dispatches; this drift
|
|
32
|
+
previously reopened (`orchestrator-update-task`/`-validate-task`).
|
|
33
|
+
|
|
34
|
+
## App-shell hardening (this branch)
|
|
35
|
+
|
|
36
|
+
**Stale/unreachable saved server can no longer wedge first-run.** A persisted
|
|
37
|
+
`elizaos:active-server` pointing at a now-dead / CSP-blocked remote backend pinned the
|
|
38
|
+
client to that address; the startup poll (`packages/ui/src/state/startup-phase-poll.ts`)
|
|
39
|
+
retried it until `BACKEND_TIMEOUT` and onboarding hung forever (clearing cookies didn't
|
|
40
|
+
help — the pointer lives in localStorage). Fix: on a *connection-level* failure (the request
|
|
41
|
+
never received an HTTP response) against a non-loopback, non-same-origin base on an http(s)
|
|
42
|
+
page — never on native mobile, where the remote IS the agent — clear the saved server,
|
|
43
|
+
re-point the client at the local origin, and reach the backend (one-shot). The decision is a
|
|
44
|
+
pure exported `shouldFallBackToLocalOrigin` covered by a unit matrix, plus an end-to-end
|
|
45
|
+
recovery test.
|
|
46
|
+
|
|
47
|
+
**Onboarding boot issues we hit that are environmental, not code bugs (no regression test
|
|
48
|
+
applies):**
|
|
49
|
+
- *"No provider registered for TEXT_EMBEDDING" → agent won't boot* — caused by a local
|
|
50
|
+
`ELIZA_DISABLE_LOCAL_EMBEDDINGS=1` in `.env.worktree` with no cloud route, i.e. *zero*
|
|
51
|
+
embedding providers. With local embeddings enabled the agent boots degraded-but-non-fatal
|
|
52
|
+
(the intended behavior). A graceful-degradation guard for the "no embedding provider at
|
|
53
|
+
all" edge would live in agent/runtime bootstrap, not here; flagged for the runtime owner.
|
|
54
|
+
- *Dev service-worker / HTTPS-upgrade theories* — investigated and **disproven** by
|
|
55
|
+
reproduction; the actual cause was the stale active-server above. The dev SW renders fine
|
|
56
|
+
with caching active. An optional dev-only self-unregistering SW remains available as a
|
|
57
|
+
hygiene improvement but guards no confirmed bug.
|
|
58
|
+
|
|
59
|
+
## Remaining work (specced, not yet built)
|
|
60
|
+
|
|
61
|
+
Ordered by leverage. `[BE]` backend, `[FE]` frontend, `[T]` tests.
|
|
62
|
+
|
|
63
|
+
### A. `orchestrator-open-task` should navigate the workbench `[FE]` — S/M
|
|
64
|
+
`runOrchestratorCapability` ("open-task") fetches detail but does not call `setSelectedId`,
|
|
65
|
+
so a voice "open task X" returns data without visually navigating. `interact()` is a
|
|
66
|
+
module-level function with no handle to the live component state. Fix: have the workbench
|
|
67
|
+
register a navigation callback (e.g. a module-scoped `setSelectedTaskHandler` the mounted
|
|
68
|
+
`OrchestratorWorkbench` sets in a `useEffect`, called by the open-task capability), or route
|
|
69
|
+
selection through the existing `?task=` deep-link that `readInitialTaskId` already reads.
|
|
70
|
+
|
|
71
|
+
### B. Bridge-backed provider setup `[BE][FE]` — M (design-touching)
|
|
72
|
+
Today `LlmProviderSection`/`CodingAgentSettingsSection` write `ANTHROPIC_API_KEY` etc.
|
|
73
|
+
straight into agent env via `client.updateConfig({ env })` — not the vault. Now that the
|
|
74
|
+
sensitive-request REST routes are mounted, wire missing-key flows to fire `SECRETS
|
|
75
|
+
action=request` (or POST `/api/sensitive-requests`) so secrets land in `sharedVault`. Reuse
|
|
76
|
+
the existing `ProviderCard`/`ProviderPanels`/`useProviderSelection` components rather than the
|
|
77
|
+
bespoke password inputs. Needs a decision on which providers/scopes/validation; do not change
|
|
78
|
+
secret-storage policy without the design owner. Secure-cloud / secure-local / insecure-local
|
|
79
|
+
fallbacks + redaction tests per the report's "Secret And OAuth Flow" section.
|
|
80
|
+
|
|
81
|
+
### C. Workbench UX gaps `[FE]` — small each, need visual iteration
|
|
82
|
+
From the fidelity review of `OrchestratorWorkbench.tsx` (largely complete; these are the gaps):
|
|
83
|
+
- **Jump-to-latest / autoscroll** in the timeline — no scroll ref/affordance today (net-new).
|
|
84
|
+
- **Change-provider control** — no UI and no `orchestrator-change-provider` capability/backend; provider policy is read-only. Needs a backend capability first.
|
|
85
|
+
- **Branch display** in the sub-agent roster (only repo/workdir shown).
|
|
86
|
+
- **System-event collapse**: only a global show/hide toggle, not expandable clusters.
|
|
87
|
+
- **Verification checklist**: only per-artifact status pills, no dedicated pass/fail surface.
|
|
88
|
+
- **Per-task USD spend** in the left rail (rail shows tokens; cost only in header + inspector).
|
|
89
|
+
- **Provider "state"**: shows policy/identity, not live health/availability.
|
|
90
|
+
|
|
91
|
+
### D. Remote / mobile for the orchestrator `[BE][FE]` — L (separate design)
|
|
92
|
+
Pairing primitives exist (`auth-pairing-routes`, `tunnel-to-mobile-client`) but **no `tunnel`
|
|
93
|
+
runtime service is registered** (so `runtime.getService("tunnel")` lookups and
|
|
94
|
+
`tunnel_authenticated_link` delivery are inert). The workbench is **polling-only**
|
|
95
|
+
(`POLL_INTERVAL_MS = 5000`); there is no SSE/WS for task updates. Needs: a registered tunnel
|
|
96
|
+
service (`getStatus/isActive/getUrl`), a relay decision (cloud gateway vs Headscale/ngrok per
|
|
97
|
+
the tunnel-to-mobile design), remote-API auth, and SSE/WS to replace the 5s poll so remote/
|
|
98
|
+
mobile clients aren't hammering. Do not attempt blind — design + visual iteration required.
|
|
99
|
+
|
|
100
|
+
### E. Test depth `[T]`
|
|
101
|
+
Add the report's e2e workflow matrix with mocked providers (create/fork/pause-all/archive/
|
|
102
|
+
search/secret-flows/validation-failure-reopen), keeping live Claude/Codex tests env-gated.
|
|
103
|
+
Also add an integration-level test that drives a `/credentials/*` request through the runtime
|
|
104
|
+
route matcher (`matchPluginRoutePath`), not just the in-process dispatcher, so the
|
|
105
|
+
registry-registration gap (fixed in this branch) can't silently reopen.
|
|
106
|
+
|
|
107
|
+
### F. Deferred from adversarial review (low priority, not regressions)
|
|
108
|
+
- **Bridge loopback hardening** `[BE]` — `bridge-routes.ts:isLoopback` trusts only
|
|
109
|
+
`req.socket.remoteAddress` (same model as the existing parent-context bridge). If the
|
|
110
|
+
runtime is ever fronted by a loopback-bound reverse proxy, mirror the extra checks from
|
|
111
|
+
`isTrustedLocalRequest` (reject forwarded/proxy-client headers and cross-site
|
|
112
|
+
`sec-fetch-site`). The single-use scopedToken remains the per-request defense regardless.
|
|
113
|
+
- **Re-anchor follow-ups to the durable goal** `[BE]` — `buildGoalFollowUp` reads
|
|
114
|
+
`metadata.goal`, but the planner spawn paths in `tasks.ts` never stamp a `goal` key, so
|
|
115
|
+
follow-ups currently re-anchor to the latest message rather than the original objective.
|
|
116
|
+
Stash `goal: task` (or the durable goal) onto session metadata at spawn time to realize
|
|
117
|
+
the intended re-anchoring. Not a regression — the old code sent raw text.
|
|
118
|
+
|
|
119
|
+
## How to work this branch
|
|
120
|
+
Isolated worktree `/home/nubs/Git/iqlabs/eliza-labs/eliza-orchestrator-feat`, branch
|
|
121
|
+
`nubs/orchestrator-view-feature`. Fresh worktrees need `@elizaos/core` built first
|
|
122
|
+
(`cd packages/core && bun run build`) or vitest can't resolve `@elizaos/core`; building the
|
|
123
|
+
full plugin set is required to run app-core integration tests. Rebase onto the active branch
|
|
124
|
+
before merging (file sets don't overlap with the desktop/local-inference work in flight).
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# Slice 1 critical assessment — chat task widget + OAuth secrets widget
|
|
2
|
+
|
|
3
|
+
Companion to
|
|
4
|
+
[`orchestrator-dashboard-task-widget-secrets-design.md`](./orchestrator-dashboard-task-widget-secrets-design.md).
|
|
5
|
+
Recorded after the first implementation pass, before any UI screenshot.
|
|
6
|
+
|
|
7
|
+
## What landed
|
|
8
|
+
|
|
9
|
+
| Area | Files | Net change |
|
|
10
|
+
|---|---|---|
|
|
11
|
+
| `[TASK:id]title[/TASK]` parser | `packages/ui/src/components/chat/message-task-parser.ts` (new) + test (new) | Pure parser, strict UUID-shaped threadId, truncates titles, ignores unterminated tags. 9/9 tests green. |
|
|
12
|
+
| `TaskWidget` component | `packages/ui/src/components/chat/widgets/task-widget.tsx` (new) + test (new) | One-line title + one-line status (status · agents · relative · tokens). Polls `getCodingAgentTaskThread` every 5s, stops on terminal status, silent on 404 ("Task removed."), click dispatches `eliza:navigate:view` → `/orchestrator?taskId=…`. 6/6 tests green. |
|
|
13
|
+
| Wire-up in chat | `packages/ui/src/components/chat/MessageContent.tsx` (edit) + integration test (new) | New `kind: "task-widget"` segment + dispatch. Prose around the block continues to render. 4/4 integration tests green. |
|
|
14
|
+
| Sensitive-request OAuth | `packages/ui/src/components/chat/MessageContent.tsx` (edit) + extended test | New `OAuthRequestPanel` rendered when `form.kind === "oauth"`. Opens authorization URL in a popup; on popup block, surfaces "Pop-up blocked" without falling back to the chat stream. Scopes are visible; the URL itself is never substituted into chat text. The secret form keeps its current behavior. |
|
|
15
|
+
| Type widening | `packages/ui/src/api/client-types-chat.ts` (edit) | `SensitiveRequestForm.kind` widened to `"secret" \| "oauth"` with three optional fields: `provider`, `scopes`, `authorizationUrl`. |
|
|
16
|
+
| Tests added | 4 vitest files | Parser (9), Widget (6), MessageContent integration (4), OAuth in SensitiveRequestBlock (3 new). Whole `src/components/chat` suite: 49/49 green. |
|
|
17
|
+
| Lint / typecheck | — | `bun run --cwd packages/ui lint` clean. `bun run --cwd packages/ui typecheck` clean. |
|
|
18
|
+
|
|
19
|
+
## Honest gaps
|
|
20
|
+
|
|
21
|
+
These are not "in the design doc but I forgot" — they were called out as
|
|
22
|
+
follow-ups in the doc itself. Listing here so the next pass knows the
|
|
23
|
+
priority order:
|
|
24
|
+
|
|
25
|
+
1. **No emission point in `TASKS_CREATE`.** The widget RENDERS, but no
|
|
26
|
+
production action yet emits `[TASK:<id>]<title>[/TASK]` after a successful
|
|
27
|
+
durable-task creation. `runCreate` in
|
|
28
|
+
[`tasks.ts`](../src/actions/tasks.ts) spawns ACP sessions, not durable
|
|
29
|
+
task threads — the link between an action callback and a durable
|
|
30
|
+
`taskId` is not in place. Without that, the widget only renders if
|
|
31
|
+
the agent text already contains the block, which is the e2e seam used
|
|
32
|
+
in tests. The natural next step is wiring `OrchestratorTaskService`'s
|
|
33
|
+
`createTask` (or a separate `TASKS_CREATE_THREAD` sub-action) so that
|
|
34
|
+
on success it returns a `taskId` and the callback text concatenates the
|
|
35
|
+
block. That is a one-line emission change + a unit test in the plugin,
|
|
36
|
+
but it touches the create flow's wiring and was scoped as a separate
|
|
37
|
+
slice.
|
|
38
|
+
2. **No OAuth backend adapter yet.** The UI widget works, but no
|
|
39
|
+
`SensitiveRequest` with `target.kind === "oauth"` is produced by the
|
|
40
|
+
policy classifier today; the inline adapter rejects non-secret. A
|
|
41
|
+
sibling `owner-app-oauth-adapter.ts` (and a `target.kind: "oauth"`) is
|
|
42
|
+
the next backend step. See `orchestrator-buildout-followups.md` section B.
|
|
43
|
+
3. **No Playwright spec yet for the chat path.** Component-level tests cover
|
|
44
|
+
the rendering, dispatch, and event contract; an end-to-end "send chat
|
|
45
|
+
→ assistant emits block → widget appears → click → workbench task
|
|
46
|
+
detail visible" would need MSW-style routes for the chat backend plus a
|
|
47
|
+
way to inject the assistant turn. The existing
|
|
48
|
+
`orchestrator-gui-workbench.spec.ts` already covers the create-flow and
|
|
49
|
+
the rail → inspector path. The chat-side spec is in slice 4 of the
|
|
50
|
+
design doc; it didn't land in this pass.
|
|
51
|
+
4. **`OrchestratorGlanceStrip` was descoped.** On second read of
|
|
52
|
+
[`WorkbenchHeader`](../../../plugins/plugin-task-coordinator/src/OrchestratorWorkbench.tsx#L597),
|
|
53
|
+
the header already reads "12 tasks · 1 active · 3 done" with the same
|
|
54
|
+
minimal language the design called for, and adds a usage chip on the
|
|
55
|
+
right. A separate strip would have been redundant and added a second
|
|
56
|
+
row that competes with the same information. The right follow-up if a
|
|
57
|
+
user calls this out specifically is making the inline counts
|
|
58
|
+
click-to-filter, NOT introducing a new pinned tile.
|
|
59
|
+
5. **Inspector terminal-task cleanup (slice 5) was descoped.** It's a
|
|
60
|
+
handful of `if (TERMINAL_STATUSES.has(status)) return null;` guards in
|
|
61
|
+
`TaskInspector`; not landed because the inspector is 4142 LOC and I
|
|
62
|
+
prioritized the user-visible chat gap. Worth a follow-up.
|
|
63
|
+
|
|
64
|
+
## Security audit of what landed
|
|
65
|
+
|
|
66
|
+
- **Secret form (`SensitiveRequestBlock`)** — submission still goes
|
|
67
|
+
through `client.updateSecrets`, never through the chat message stream.
|
|
68
|
+
Existing test asserts the raw secret never appears anywhere in the
|
|
69
|
+
rendered DOM. Added a `data-testid="sensitive-request-submit"` so
|
|
70
|
+
Playwright can target the submit cleanly; behavior unchanged.
|
|
71
|
+
- **OAuth widget (`OAuthRequestPanel`)** — three guards:
|
|
72
|
+
1. The authorization URL is only consumed inside `window.open()`. It is
|
|
73
|
+
never substituted into the visible chat text. The new test asserts
|
|
74
|
+
the URL substring is not present anywhere in `container.textContent`.
|
|
75
|
+
2. Popup is opened with `noopener,noreferrer` so the consent page can't
|
|
76
|
+
`window.opener.*` back to chat.
|
|
77
|
+
3. A blocked popup surfaces "Pop-up blocked. Allow pop-ups for this
|
|
78
|
+
site to continue." rather than silently falling back to a chat
|
|
79
|
+
message that would re-render the URL.
|
|
80
|
+
- **TaskWidget** — only reads structured status fields (`status`,
|
|
81
|
+
`sessionCount`, `activeSessionCount`, `latestActivityAt`,
|
|
82
|
+
`usage.totalTokens`). It does not render `metadata` or `messages`. A
|
|
83
|
+
regression test asserts secret-shaped strings smuggled through `metadata`
|
|
84
|
+
do not appear in the rendered DOM.
|
|
85
|
+
|
|
86
|
+
## Test coverage table
|
|
87
|
+
|
|
88
|
+
| File | Suite | Count | Status |
|
|
89
|
+
|---|---|---|---|
|
|
90
|
+
| `message-task-parser.test.ts` | parser unit | 9 | green |
|
|
91
|
+
| `widgets/task-widget.test.tsx` | component unit | 6 | green |
|
|
92
|
+
| `MessageContent.task-widget.test.tsx` | integration | 4 | green |
|
|
93
|
+
| `MessageContent.sensitive-request.test.tsx` | sensitive widget (extended) | 7 | green |
|
|
94
|
+
| Whole `src/components/chat` suite | — | 49 | green |
|
|
95
|
+
|
|
96
|
+
`bun run --cwd packages/ui lint` clean. `bun run --cwd packages/ui typecheck` clean.
|
|
97
|
+
`bun run --cwd packages/app-core typecheck` shows two pre-existing
|
|
98
|
+
`@elizaos/plugin-commands` resolution errors unrelated to this change.
|
|
99
|
+
|
|
100
|
+
## What a screenshot pass would look for (next session)
|
|
101
|
+
|
|
102
|
+
Not run in this session because there is no live UI to capture. The
|
|
103
|
+
checklist for that pass:
|
|
104
|
+
|
|
105
|
+
- **Chat surface, message with a task block** —
|
|
106
|
+
- Title line truncates without ellipsis-jitter at 320px width.
|
|
107
|
+
- Status line wraps gracefully; the dot/label/agents/tokens chips
|
|
108
|
+
never wrap mid-chip.
|
|
109
|
+
- Pulse animation is visible on `active` and `validating`, absent
|
|
110
|
+
on terminal states.
|
|
111
|
+
- Click → orchestrator workbench shows the matching task selected.
|
|
112
|
+
- **Chat surface, OAuth request** —
|
|
113
|
+
- "Connect <provider>" button reads exactly like the surrounding chat
|
|
114
|
+
accent (no accidental blue).
|
|
115
|
+
- Scopes line truncates at small widths.
|
|
116
|
+
- Pop-up blocked state surfaces inline, not modal.
|
|
117
|
+
- **Chat surface, secret request** — unchanged, but confirm the new
|
|
118
|
+
`data-testid` didn't shift any spacing.
|
|
119
|
+
- **Orchestrator workbench, `?taskId=…` arrival** — task is selected,
|
|
120
|
+
inspector visible without scrolling.
|
|
121
|
+
|
|
122
|
+
## Post-review fixes (second pass)
|
|
123
|
+
|
|
124
|
+
After fanning out independent code-review + aesthetic + verification agents, four
|
|
125
|
+
findings were addressed in this same change-set:
|
|
126
|
+
|
|
127
|
+
1. **`window.open(..., "noopener,noreferrer")` bug** — per the HTML spec
|
|
128
|
+
`noopener` forces `window.open` to return `null`, so the popup-blocked
|
|
129
|
+
detection misfired in every real browser. Removed `noopener` from the
|
|
130
|
+
features string, kept `noreferrer`, and added an explicit
|
|
131
|
+
`popup.opener = null` immediately after open as a belt-and-suspenders
|
|
132
|
+
measure. Test asserts `noreferrer` is present and `noopener` is not, and
|
|
133
|
+
that `opener` is nulled.
|
|
134
|
+
2. **`TaskWidget` infinite poll on auth error** — added a
|
|
135
|
+
`MAX_CONSECUTIVE_ERRORS = 3` cap on the silent-error counter; after three
|
|
136
|
+
consecutive 401/403/etc the widget freezes on the last good state and
|
|
137
|
+
stops polling. Counter resets on the next successful fetch.
|
|
138
|
+
3. **Slop pass — `ExternalLink` decorative icon removed** from `TaskWidget`.
|
|
139
|
+
The whole card is already a `<button>` with `hover:bg-bg-hover`; the icon
|
|
140
|
+
added zero info at a glance.
|
|
141
|
+
4. **Slop pass — "The value will not be sent as a chat message." removed**
|
|
142
|
+
from the secret-form widget. A `type="password"` input is its own
|
|
143
|
+
signal; the trust copy stays on the OAuth panel where the user is
|
|
144
|
+
genuinely navigating to a third-party origin.
|
|
145
|
+
5. **OAuth panel testid** — added `data-testid="sensitive-request-oauth"`
|
|
146
|
+
to the panel wrapper for parity with `sensitive-request`.
|
|
147
|
+
|
|
148
|
+
Reopen-on-terminal was reconsidered and intentionally left as-is: done/failed
|
|
149
|
+
tasks have an Archive button that transitions them to `archived`, which
|
|
150
|
+
exposes Reopen. The path exists — it just isn't a single-click escape from
|
|
151
|
+
done → reopened. Acceptable.
|
|
152
|
+
|
|
153
|
+
The legacy `SensitiveRequestOauthTarget` (lowercase `a`) coexists with the
|
|
154
|
+
new `SensitiveRequestOAuthTarget` (capital `A`) in the
|
|
155
|
+
`SensitiveRequestTarget` union. The new OAuth adapter defends with an
|
|
156
|
+
`isOAuthTarget` runtime narrower, so downstream consumers that already
|
|
157
|
+
relied on the loose shape are unaffected. Consolidating these two into a
|
|
158
|
+
single tight type is a follow-up (it widens the blast radius beyond this
|
|
159
|
+
change-set).
|
|
160
|
+
|
|
161
|
+
## What to revisit if a user looks at this and says "still too busy"
|
|
162
|
+
|
|
163
|
+
- The header's `12 tasks · 1 active · 3 done` line already aims at
|
|
164
|
+
minimal/dense. If that still reads as cluttered, the next reduction
|
|
165
|
+
is dropping `tasks` (just show counts and labels) and making the
|
|
166
|
+
divider thinner.
|
|
167
|
+
- The widget's status line is four chips by default. If three of the
|
|
168
|
+
four are zero (e.g. fresh task, no agents, no tokens), only `status`
|
|
169
|
+
+ `relative` render — that's already the case via the existing
|
|
170
|
+
conditional renders.
|
|
171
|
+
- The OAuth panel intentionally explains *why* it's safe ("token is
|
|
172
|
+
stored securely and never shown in chat"). That sentence is the only
|
|
173
|
+
prose in the panel and it's important for trust; it should not be
|
|
174
|
+
cut.
|