docs: update all documentation for agor rebrand and dual-repo structure
This commit is contained in:
parent
5fadd1c022
commit
421c38cd8c
21 changed files with 225 additions and 207 deletions
|
|
@ -5,7 +5,7 @@
|
|||
- Docs are in `docs/`. Architecture in `docs/architecture.md`.
|
||||
- v2 Phases 1-7 + multi-machine (A-D) + profiles/skills complete. Extras: SSH, ctx, themes, detached mode, auto-updater, shiki, copy/paste, session resume, drag-resize, session groups, Deno sidecar, Claude profiles, skill discovery.
|
||||
- v3 Mission Control (All Phases 1-10 + Production Readiness Complete): project groups, workspace store, 15+ Workspace components, session continuity, multi-provider adapter pattern, worktree isolation, session anchors, Memora adapter, SOLID refactoring, multi-agent orchestration (btmsg/bttask, 4 Tier 1 roles, role-specific tabs), dashboard metrics, auto-wake scheduler, reviewer agent. Production: sidecar supervisor (auto-restart, exponential backoff), FTS5 search (3 virtual tables, Spotlight overlay), plugin system (Web Worker sandbox, permission-gated), Landlock sandbox (kernel 6.2+), secrets management (system keyring), OS+in-app notifications, keyboard-first UX (18+ palette commands, vi-nav), agent health monitoring (heartbeats, dead letter queue), audit logging, error classification (6 types), optimistic locking (bttask). Hardening: TLS relay, SPKI pinning (TOFU), WAL checkpoint (5min), subagent delegation fix, plugin sandbox tests (26), SidecarManager actor pattern, per-message btmsg acknowledgment, Aider autonomous mode. 507 vitest + 110 cargo + 109 E2E.
|
||||
- Consult Memora (tag: `bterminal`) before making architectural changes.
|
||||
- Consult Memora (tag: `agor`) before making architectural changes.
|
||||
|
||||
## Documentation References
|
||||
|
||||
|
|
@ -34,7 +34,7 @@
|
|||
- Agent dispatcher (`src/lib/agent-dispatcher.ts`) is a thin coordinator (260 lines) routing sidecar events to the agent store. Delegates to extracted modules: `utils/session-persistence.ts` (session-project maps, persistSessionForProject), `utils/subagent-router.ts` (spawn + route subagent panes), `utils/auto-anchoring.ts` (triggerAutoAnchor on compaction), `utils/worktree-detection.ts` (detectWorktreeFromCwd pure function). Provider-aware via message-adapters.ts.
|
||||
- AgentQueryOptions supports `provider` field (defaults to 'claude', flows Rust -> sidecar), `provider_config` blob (Rust passes through as serde_json::Value), `permission_mode` (defaults to 'bypassPermissions'), `setting_sources` (defaults to ['user', 'project']), `system_prompt`, `model`, `claude_config_dir` (for multi-account), `additional_directories`, `worktree_name` (when set, passed as `extraArgs: { worktree: name }` to SDK → `--worktree <name>` CLI flag), `extra_env` (HashMap<String,String>, injected into sidecar process env; used for BTMSG_AGENT_ID).
|
||||
- Multi-agent orchestration: Tier 1 (management agents: Manager, Architect, Tester, Reviewer) defined in groups.json `agents[]`, converted to ProjectConfig via `agentToProject()`, rendered as full ProjectBoxes. Tier 2 (project agents) are regular ProjectConfig entries. Both tiers get system prompts. Tier 1 prompt built by `generateAgentPrompt()` (utils/agent-prompts.ts): 7 sections (Identity, Environment, Team, btmsg docs, bttask docs, Custom context, Workflow). Tier 2 gets optional `project.systemPrompt` as custom context. BTMSG_AGENT_ID env var injected for Tier 1 agents only (enables btmsg/bttask CLI usage). Periodic re-injection: AgentSession runs 1-hour timer, sends context refresh prompt when agent is idle (autoPrompt → AgentPane → startQuery with resume=true).
|
||||
- bttask kanban: Rust bttask.rs module reads/writes tasks table in shared btmsg.db (~/.local/share/bterminal/btmsg.db). 7 operations: list_tasks, create_task, update_task_status, delete_task, add_comment, task_comments, review_queue_count. Frontend: TaskBoardTab.svelte (kanban 5 columns, 5s poll). CLI `bttask` tool gives agents direct access; Manager has full CRUD, Reviewer has read + status + comments, other roles have read-only + comments. On task→review transition, auto-posts to #review-queue btmsg channel (ensure_review_channels creates #review-queue + #review-log idempotently). Reviewer agent gets Tasks tab in ProjectBox (reuses TaskBoardTab). reviewQueueDepth in AttentionInput: 10pts per review task, capped at 50 (priority between file_conflict 70 and context_high 40). ProjectBox polls review_queue_count every 10s for reviewer agents → setReviewQueueDepth() in health store.
|
||||
- bttask kanban: Rust bttask.rs module reads/writes tasks table in shared btmsg.db (~/.local/share/agor/btmsg.db). 7 operations: list_tasks, create_task, update_task_status, delete_task, add_comment, task_comments, review_queue_count. Frontend: TaskBoardTab.svelte (kanban 5 columns, 5s poll). CLI `bttask` tool gives agents direct access; Manager has full CRUD, Reviewer has read + status + comments, other roles have read-only + comments. On task→review transition, auto-posts to #review-queue btmsg channel (ensure_review_channels creates #review-queue + #review-log idempotently). Reviewer agent gets Tasks tab in ProjectBox (reuses TaskBoardTab). reviewQueueDepth in AttentionInput: 10pts per review task, capped at 50 (priority between file_conflict 70 and context_high 40). ProjectBox polls review_queue_count every 10s for reviewer agents → setReviewQueueDepth() in health store.
|
||||
- btmsg/bttask SQLite conventions: Both btmsg.rs and bttask.rs open shared btmsg.db with WAL mode + 5s busy_timeout (concurrent access from Python CLIs + Rust backend). All queries use named column access (`row.get("column_name")`) — never positional indices. Rust structs use `#[serde(rename_all = "camelCase")]`; TypeScript interfaces MUST match camelCase wire format. TestingTab uses `convertFileSrc()` for Tauri 2.x asset URLs (not `asset://localhost/`).
|
||||
- ArchitectureTab: PlantUML diagram viewer/editor. Stores .puml files in `.architecture/` project dir. Renders via plantuml.com server using ~h hex encoding (no Java dependency). 4 templates: Class, Sequence, State, Component. Editor + SVG preview toggle.
|
||||
- TestingTab: Dual-mode component (mode='selenium'|'tests'). Selenium: watches `.selenium/screenshots/` for PNG/JPG, displays in gallery with session log, 3s poll. Tests: discovers files in standard dirs (tests/, test/, spec/, __tests__/, e2e/), shows content.
|
||||
|
|
@ -49,7 +49,7 @@
|
|||
- Agent preview terminal: `AgentPreviewPane.svelte` is a read-only xterm.js terminal (disableStdin:true) that subscribes to an agent session's messages via `$derived(getAgentSession(sessionId))` and renders tool calls/results in real-time. Bash commands shown as cyan `❯ cmd`, file ops as yellow `[Read] path`, results as plain text (80-line truncation), errors in red. Spawned via 👁 button in TerminalTabs (appears when agentSessionId prop is set). TerminalTab type: `'agent-preview'` with `agentSessionId` field. Deduplicates — won't create two previews for the same session. ProjectBox passes mainSessionId to TerminalTabs.
|
||||
- Maximum 4 active xterm.js instances to avoid WebKit2GTK memory issues. Agent preview uses disableStdin and no PTY so is lighter, but still counts.
|
||||
- Store files using Svelte 5 runes (`$state`, `$derived`) MUST have `.svelte.ts` extension (not `.ts`). Import with `.svelte` suffix. Plain `.ts` compiles but fails at runtime with "rune_outside_svelte".
|
||||
- Session persistence uses rusqlite (bundled) with WAL mode. Data dir: `dirs::data_dir()/bterminal/sessions.db`.
|
||||
- Session persistence uses rusqlite (bundled) with WAL mode. Data dir: `dirs::data_dir()/agor/sessions.db`.
|
||||
- Layout store persists to SQLite on every addPane/removePane/setPreset/setPaneGroup change (fire-and-forget). Restores on app startup via `restoreFromDb()`.
|
||||
- Session groups: Pane.group? field in layout store, group_name column in sessions table, collapsible group headers in sidebar. Right-click pane to set group.
|
||||
- File watcher uses notify crate v6, watches parent directory (NonRecursive), emits `file-changed` Tauri events.
|
||||
|
|
@ -69,29 +69,29 @@
|
|||
- Theme system: 17 themes in 3 groups — 4 Catppuccin + 7 Editor (VSCode Dark+, Atom One Dark, Monokai, Dracula, Nord, Solarized Dark, GitHub Dark) + 6 Deep Dark (Tokyo Night, Gruvbox Dark, Ayu Dark, Poimandres, Vesper, Midnight). All map to same 26 --ctp-* CSS custom properties — zero component changes needed. ThemeId replaces CatppuccinFlavor. getCurrentTheme()/setTheme() are primary API (deprecated wrappers exist). THEME_LIST has ThemeMeta with group metadata for custom dropdown UI. Open terminals hot-swap via onThemeChange() callback registry in theme.svelte.ts. Typography uses --ui-font-family/--ui-font-size (UI elements, sans-serif fallback) and --term-font-family/--term-font-size (terminal, monospace fallback) CSS custom properties (defined in catppuccin.css). initTheme() restores all 4 font settings (ui_font_family, ui_font_size, term_font_family, term_font_size) from SQLite on startup.
|
||||
- Detached pane mode: App.svelte checks URL param `?detached=1` and renders a single pane without sidebar/grid chrome. Used for pop-out windows.
|
||||
- Shiki syntax highlighting uses lazy singleton pattern (avoid repeated WASM init). 13 languages preloaded. Used in MarkdownPane and AgentPane text messages.
|
||||
- Cargo workspace at repo root: members = [src-tauri, bterminal-core, bterminal-relay]. Cargo.lock is at workspace root, not in src-tauri/.
|
||||
- EventSink trait (bterminal-core/src/event.rs) abstracts event emission. PtyManager and SidecarManager are in bterminal-core, not src-tauri. src-tauri has thin re-exports.
|
||||
- RemoteManager (src-tauri/src/remote.rs) manages WebSocket client connections to bterminal-relay instances. 12 Tauri commands prefixed with `remote_`.
|
||||
- Cargo workspace at repo root: members = [src-tauri, agor-core, agor-relay]. Cargo.lock is at workspace root, not in src-tauri/.
|
||||
- EventSink trait (agor-core/src/event.rs) abstracts event emission. PtyManager and SidecarManager are in agor-core, not src-tauri. src-tauri has thin re-exports.
|
||||
- RemoteManager (src-tauri/src/remote.rs) manages WebSocket client connections to agor-relay instances. 12 Tauri commands prefixed with `remote_`.
|
||||
- remote-bridge.ts adapter wraps remote machine management IPC. machines.svelte.ts store tracks remote machine state.
|
||||
- Pane.remoteMachineId?: string routes operations through RemoteManager instead of local managers. Bridge adapters (pty-bridge, agent-bridge) check this field.
|
||||
- bterminal-relay binary (bterminal-relay/) is a standalone WebSocket server with token auth, rate limiting, and per-connection isolated managers. Commands return structured responses (pty_created, pong, error) with commandId for correlation via send_error() helper.
|
||||
- agor-relay binary (agor-relay/) is a standalone WebSocket server with token auth, rate limiting, and per-connection isolated managers. Commands return structured responses (pty_created, pong, error) with commandId for correlation via send_error() helper.
|
||||
- RemoteManager reconnection: exponential backoff (1s-30s cap) on disconnect, attempt_tcp_probe() (TCP-only, no WS upgrade), emits remote-machine-reconnecting and remote-machine-reconnect-ready events. Frontend listeners in remote-bridge.ts; machines store auto-reconnects on ready.
|
||||
- v3 workspace store (`workspace.svelte.ts`) replaces layout store for v3. Groups loaded from `~/.config/bterminal/groups.json` via `groups-bridge.ts`. State: groups, activeGroupId, activeTab, focusedProjectId. Derived: activeGroup, activeProjects.
|
||||
- v3 workspace store (`workspace.svelte.ts`) replaces layout store for v3. Groups loaded from `~/.config/agor/groups.json` via `groups-bridge.ts`. State: groups, activeGroupId, activeTab, focusedProjectId. Derived: activeGroup, activeProjects.
|
||||
- v3 groups backend (`groups.rs`): load_groups(), save_groups(), default_groups(). Tauri commands: groups_load, groups_save.
|
||||
- Telemetry (`telemetry.rs`): tracing + optional OTLP export to Tempo. `BTERMINAL_OTLP_ENDPOINT` env var controls (absent = console-only). TelemetryGuard in AppState with Drop-based shutdown. Frontend events route through `frontend_log` Tauri command → Rust tracing (no browser OTEL SDK — WebKit2GTK incompatible). `telemetry-bridge.ts` provides `tel.info/warn/error()` convenience API. Docker stack at `docker/tempo/` (Grafana port 9715).
|
||||
- E2E test mode (`BTERMINAL_TEST=1`): watcher.rs and fs_watcher.rs skip file watchers, wake-scheduler disabled via `disableWakeScheduler()`, `is_test_mode` Tauri command bridges to frontend. Data/config dirs overridable via `BTERMINAL_TEST_DATA_DIR`/`BTERMINAL_TEST_CONFIG_DIR`. E2E uses WebDriverIO + tauri-driver, single session, TCP readiness probe. Phase A: 7 data-testid-based scenarios in `agent-scenarios.test.ts` (deterministic assertions). Phase B: 6 scenarios in `phase-b.test.ts` (multi-project grid, independent tab switching, status bar fleet state, LLM-judged agent responses/code generation, context tab verification). LLM judge (`llm-judge.ts`): raw fetch to Anthropic API using claude-haiku-4-5, structured verdict (pass/fail + reasoning + confidence), `assertWithJudge()` with configurable threshold, skips when `ANTHROPIC_API_KEY` absent. CI workflow (`.github/workflows/e2e.yml`): unit + cargo + e2e jobs, xvfb-run, path-filtered triggers, LLM tests gated on secret. Test fixtures in `fixtures.ts` create isolated temp environments. Results tracked via JSON store in `results-db.ts`.
|
||||
- Telemetry (`telemetry.rs`): tracing + optional OTLP export to Tempo. `AGOR_OTLP_ENDPOINT` env var controls (absent = console-only). TelemetryGuard in AppState with Drop-based shutdown. Frontend events route through `frontend_log` Tauri command → Rust tracing (no browser OTEL SDK — WebKit2GTK incompatible). `telemetry-bridge.ts` provides `tel.info/warn/error()` convenience API. Docker stack at `docker/tempo/` (Grafana port 9715).
|
||||
- E2E test mode (`AGOR_TEST=1`): watcher.rs and fs_watcher.rs skip file watchers, wake-scheduler disabled via `disableWakeScheduler()`, `is_test_mode` Tauri command bridges to frontend. Data/config dirs overridable via `AGOR_TEST_DATA_DIR`/`AGOR_TEST_CONFIG_DIR`. E2E uses WebDriverIO + tauri-driver, single session, TCP readiness probe. Phase A: 7 data-testid-based scenarios in `agent-scenarios.test.ts` (deterministic assertions). Phase B: 6 scenarios in `phase-b.test.ts` (multi-project grid, independent tab switching, status bar fleet state, LLM-judged agent responses/code generation, context tab verification). LLM judge (`llm-judge.ts`): raw fetch to Anthropic API using claude-haiku-4-5, structured verdict (pass/fail + reasoning + confidence), `assertWithJudge()` with configurable threshold, skips when `ANTHROPIC_API_KEY` absent. CI workflow (`.github/workflows/e2e.yml`): unit + cargo + e2e jobs, xvfb-run, path-filtered triggers, LLM tests gated on secret. Test fixtures in `fixtures.ts` create isolated temp environments. Results tracked via JSON store in `results-db.ts`.
|
||||
- v3 SQLite additions: agent_messages table (per-project message persistence), project_agent_state table (sdkSessionId, cost, status per project), sessions.project_id column.
|
||||
- v3 App.svelte: VSCode-style sidebar layout. Horizontal: left icon rail (GlobalTabBar, 2.75rem, single Settings gear icon) + expandable drawer panel (Settings only, content-driven width, max 50%) + main workspace (ProjectGrid always visible) + StatusBar. Sidebar has Settings only — Sessions/Docs/Context are project-specific (in ProjectBox tabs). Keyboard: Ctrl+B (toggle sidebar), Ctrl+, (settings), Escape (close).
|
||||
- v3 component tree: App -> GlobalTabBar (settings icon) + sidebar-panel? (SettingsTab) + workspace (ProjectGrid) + StatusBar. See `docs/architecture.md` for full tree.
|
||||
- MarkdownPane reactively watches filePath changes via $effect (not onMount-only). Uses sans-serif font (Inter, system-ui), all --ctp-* theme vars. Styled blockquotes with translucent backgrounds, table row hover, link hover underlines. Inner `.markdown-pane-scroll` wrapper with `container-type: inline-size` for responsive padding via `--bterminal-pane-padding-inline`.
|
||||
- AgentPane UI (redesigned 2026-03-09): sans-serif root font (`system-ui, -apple-system, sans-serif`), monospace only on code/tool names. Tool calls paired with results in collapsible `<details>` groups via `$derived.by` toolResultMap (cache-guarded by tool_result count). Hook messages collapsed into compact `<details>` with gear icon. Context window meter inline in status strip. Cost bar minimal (no background, subtle border-top). Session summary with translucent surface background. Two-phase scroll anchoring (`$effect.pre` + `$effect`). Tool-aware output truncation (Bash 500 lines, Read/Write 50, Glob/Grep 20, default 30). Colors softened via `color-mix()`. Inner `.agent-pane-scroll` wrapper with `container-type: inline-size` for responsive padding via shared `--bterminal-pane-padding-inline` variable.
|
||||
- MarkdownPane reactively watches filePath changes via $effect (not onMount-only). Uses sans-serif font (Inter, system-ui), all --ctp-* theme vars. Styled blockquotes with translucent backgrounds, table row hover, link hover underlines. Inner `.markdown-pane-scroll` wrapper with `container-type: inline-size` for responsive padding via `--agor-pane-padding-inline`.
|
||||
- AgentPane UI (redesigned 2026-03-09): sans-serif root font (`system-ui, -apple-system, sans-serif`), monospace only on code/tool names. Tool calls paired with results in collapsible `<details>` groups via `$derived.by` toolResultMap (cache-guarded by tool_result count). Hook messages collapsed into compact `<details>` with gear icon. Context window meter inline in status strip. Cost bar minimal (no background, subtle border-top). Session summary with translucent surface background. Two-phase scroll anchoring (`$effect.pre` + `$effect`). Tool-aware output truncation (Bash 500 lines, Read/Write 50, Glob/Grep 20, default 30). Colors softened via `color-mix()`. Inner `.agent-pane-scroll` wrapper with `container-type: inline-size` for responsive padding via shared `--agor-pane-padding-inline` variable.
|
||||
- ProjectBox uses CSS `style:display` (flex/none) instead of `{#if}` for tab content panes — keeps AgentSession mounted across tab switches (prevents session ID reset and message loss). Terminal section also uses `style:display`. Grid rows: auto auto 1fr auto.
|
||||
- Svelte 5 event syntax: use `onclick` not `on:click`. Svelte 5 requires lowercase event handler attributes (no colon syntax).
|
||||
|
||||
## Memora Tags
|
||||
|
||||
Project tag: `bterminal`
|
||||
Common tag combinations: `bterminal,architecture`, `bterminal,research`, `bterminal,tech-stack`
|
||||
Project tag: `agor`
|
||||
Common tag combinations: `agor,architecture`, `agor,research`, `agor,tech-stack`
|
||||
|
||||
## Operational Rules
|
||||
|
||||
|
|
|
|||
75
CHANGELOG.md
75
CHANGELOG.md
|
|
@ -7,8 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
- **Dual-repo commercial structure** — agents-orchestrator/agents-orchestrator private repo as commercial source of truth, DexterFromLab/agent-orchestrator as community mirror. Two git remotes (origin + orchestrator) configured locally
|
||||
- **agor-pro plugin crate** — Tauri 2.x plugin for commercial features. Feature-gated via `--features pro`. Registered via `app.handle().plugin(agor_pro::init())` in setup(). Scaffold with `pro_status` command
|
||||
- **Commercial Tauri config overlay** — `tauri.conf.commercial.json` with separate bundle ID (`com.agentsorchestrator.pro`) and updater endpoints
|
||||
- **Asymmetric test configuration** — `AGOR_EDITION=pro` env var enables `tests/commercial/` in vitest. Pro: 509 tests, Community: 507 tests. Same framework, different coverage
|
||||
- **CI leak prevention** — `leak-check.yml` blocks commercial code on community pushes. `commercial-build.yml` validates pro edition. `pat-health.yml` weekly PAT monitoring
|
||||
- **Pre-push hook** — `.githooks/pre-push` detects and blocks commercial paths when pushing to origin
|
||||
- **Makefile** — setup, build, build-pro, test, test-pro, sync, clean targets
|
||||
- **Commercial docs** — CONTRIBUTING.md (dual-repo model, CLA, SPDX), MAINTENANCE.md (PAT rotation, sync workflow, release checklists), LICENSE-COMMERCIAL
|
||||
|
||||
### Changed
|
||||
- **Repo flattened** — all source code moved from `v2/` subdirectory to repo root. 351-commit history squashed by upstream rebuild. Branch `hib_changes_v2` created from new flat `main` with reconciled docs, CLI tools, and scaffolding. All path references in CLAUDE.md and docs/ updated
|
||||
- **bterminal→agor rebrand** — Cargo crates: bterminal-core→agor-core, bterminal-relay→agor-relay. Env vars: BTERMINAL_*→AGOR_*. Config paths: ~/.config/agor, ~/.local/share/agor. CSS: --agor-pane-padding-inline. Plugin API: `agor` object. Package names: agents-orchestrator, agor-sidecar
|
||||
- **Repo flattened** — all source code moved from `v2/` subdirectory to repo root. 351-commit history squashed by upstream rebuild. Branch `hib_changes_v2` created from new flat `main` with reconciled docs, CLI tools, and scaffolding
|
||||
|
||||
### Added
|
||||
- **Plugin sandbox Web Worker migration** — replaced `new Function()` sandbox with dedicated Web Worker per plugin. True process-level isolation — no DOM, no Tauri IPC, no main-thread access. Permission-gated API proxied via postMessage with RPC pattern. 26 tests (MockWorker class in vitest)
|
||||
|
|
@ -32,14 +43,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
### Added
|
||||
- **Comprehensive documentation suite** — 4 new docs: `architecture.md` (end-to-end system architecture with component hierarchy, data flow, IPC patterns), `sidecar.md` (multi-provider runner lifecycle, env stripping, NDJSON protocol, build pipeline), `orchestration.md` (btmsg messaging, bttask kanban, agent roles, wake scheduler, session anchors, health monitoring), `production.md` (sidecar supervisor, Landlock sandbox, FTS5 search, plugin system, secrets management, notifications, audit logging, error classification, telemetry)
|
||||
- **Sidecar crash recovery/supervision** — `bterminal-core/src/supervisor.rs`: SidecarSupervisor wraps SidecarManager with auto-restart, exponential backoff (1s base, 30s cap, 5 retries), SidecarHealth enum (Healthy/Degraded/Failed), 5min stability window. 17 tests
|
||||
- **Sidecar crash recovery/supervision** — `agor-core/src/supervisor.rs`: SidecarSupervisor wraps SidecarManager with auto-restart, exponential backoff (1s base, 30s cap, 5 retries), SidecarHealth enum (Healthy/Degraded/Failed), 5min stability window. 17 tests
|
||||
- **Notification system** — OS desktop notifications via `notify-rust` + in-app NotificationCenter.svelte (bell icon, unread badge, history max 100, 6 notification types). Agent dispatcher emits on complete/error/crash. notifications-bridge.ts adapter
|
||||
- **Secrets management** — `keyring` crate with linux-native (libsecret). SecretsManager in secrets.rs: store/get/delete/list with `__bterminal_keys__` metadata tracking. SettingsTab Secrets section. secrets-bridge.ts adapter. No plaintext fallback
|
||||
- **Secrets management** — `keyring` crate with linux-native (libsecret). SecretsManager in secrets.rs: store/get/delete/list with `__agor_keys__` metadata tracking. SettingsTab Secrets section. secrets-bridge.ts adapter. No plaintext fallback
|
||||
- **Keyboard-first UX** — Alt+1-5 project jump, Ctrl+H/L vi-nav, Ctrl+Shift+1-9 tab switch, Ctrl+J terminal toggle, Ctrl+Shift+K focus agent, Ctrl+Shift+F search overlay. `isEditing()` guard prevents conflicts. CommandPalette rewritten: 18+ commands, 6 categories, fuzzy filter, arrow nav, keyboard shortcuts overlay
|
||||
- **Agent health monitoring** — heartbeats table + dead_letter_queue table in btmsg.db. 15s heartbeat polling in ProjectBox. Stale detection (5min threshold). ProjectHeader heart indicator (green/yellow/red). StatusBar health badge
|
||||
- **FTS5 full-text search** — rusqlite upgraded to `bundled-full`. SearchDb with 3 FTS5 virtual tables (search_messages, search_tasks, search_btmsg). SearchOverlay.svelte: Spotlight-style Ctrl+Shift+F overlay, 300ms debounce, grouped results with FTS5 highlight snippets
|
||||
- **Plugin system** — `~/.config/bterminal/plugins/` with plugin.json manifest. plugins.rs: discovery, path-traversal-safe file reading, permission validation. plugin-host.ts: sandboxed `new Function()` execution, permission-gated API (palette, btmsg:read, bttask:read, events). plugins.svelte.ts store. SettingsTab plugins section. Example hello plugin
|
||||
- **Landlock sandbox** — `bterminal-core/src/sandbox.rs`: SandboxConfig with RW/RO paths, applied via `pre_exec()` in sidecar child process. Requires kernel 6.2+ (graceful fallback). Per-project toggle in SettingsTab
|
||||
- **Plugin system** — `~/.config/agor/plugins/` with plugin.json manifest. plugins.rs: discovery, path-traversal-safe file reading, permission validation. plugin-host.ts: sandboxed `new Function()` execution, permission-gated API (palette, btmsg:read, bttask:read, events). plugins.svelte.ts store. SettingsTab plugins section. Example hello plugin
|
||||
- **Landlock sandbox** — `agor-core/src/sandbox.rs`: SandboxConfig with RW/RO paths, applied via `pre_exec()` in sidecar child process. Requires kernel 6.2+ (graceful fallback). Per-project toggle in SettingsTab
|
||||
- **Error classification** — `error-classifier.ts`: classifyApiError() with 6 types (rate_limit, auth, quota, overloaded, network, unknown), actionable messages, retry delays. 20 tests
|
||||
- **Audit log** — audit_log table in btmsg.db. AuditLogTab.svelte: Manager-only tab, filter by type+agent, 5s auto-refresh. audit-bridge.ts adapter. Events: agent_start/stop/error, task changes, wake events, prompt injection
|
||||
- **Usage meter** — UsageMeter.svelte: compact inline cost/token meter with color thresholds (50/75/90%), hover tooltip. Integrated in AgentPane cost bar
|
||||
|
|
@ -47,7 +58,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- **Optimistic locking for bttask** — `version` column in tasks table. `WHERE id=? AND version=?` in update_task_status(). Conflict detection in TaskBoardTab. Both Rust + Python CLI updated
|
||||
- **Unified test runner** — `v2/scripts/test-all.sh` runs vitest + cargo tests with optional E2E (`--e2e` flag). npm scripts: `test:all`, `test:all:e2e`, `test:cargo`. Summary output with color-coded pass/fail
|
||||
- **Testing gate rule** — `.claude/rules/20-testing-gate.md` requires running full test suite after every major change (new features, refactors touching 3+ files, store/adapter/bridge/backend changes)
|
||||
- **E2E test mode infrastructure** — `BTERMINAL_TEST=1` env var disables file watchers (watcher.rs, fs_watcher.rs), wake scheduler, and allows data/config dir overrides via `BTERMINAL_TEST_DATA_DIR`/`BTERMINAL_TEST_CONFIG_DIR`. New `is_test_mode` Tauri command bridges test state to frontend
|
||||
- **E2E test mode infrastructure** — `AGOR_TEST=1` env var disables file watchers (watcher.rs, fs_watcher.rs), wake scheduler, and allows data/config dir overrides via `AGOR_TEST_DATA_DIR`/`AGOR_TEST_CONFIG_DIR`. New `is_test_mode` Tauri command bridges test state to frontend
|
||||
- **E2E data-testid attributes** — Stable test selectors on 7 key Svelte components: AgentPane (agent-pane, data-agent-status, agent-messages, agent-stop, agent-prompt, agent-submit), ProjectBox (project-box, data-project-id, project-tabs, terminal-toggle), StatusBar, AgentSession, GlobalTabBar, CommandPalette, TerminalTabs
|
||||
- **E2E Phase A scenarios** — 7 human-authored test scenarios (22 tests) in `agent-scenarios.test.ts`: app structural integrity, settings panel, agent pane initial state, terminal tab management, command palette, project focus/tab switching, agent prompt submission (graceful Claude CLI skip)
|
||||
- **E2E test fixtures** — `tests/e2e/fixtures.ts`: creates isolated temp environments with data/config dirs, git repos, and groups.json. `createTestFixture()`, `createMultiProjectFixture()`, `destroyTestFixture()`
|
||||
|
|
@ -61,18 +72,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- **E2E fixture env propagation** — `tauri:options.env` does not reliably set process-level env vars for Rust `std::env::var()`. Added `process.env` injection at module scope in wdio.conf.js so fixture groups.json is loaded instead of real user config
|
||||
- **LLM judge CLI context pollution** — Claude CLI loaded project CLAUDE.md files causing model to refuse JSON output. Fixed by running judge from `cwd: /tmp` with `--setting-sources user` and `--system-prompt` flags
|
||||
- **E2E mocha timeout** — Increased global mocha timeout from 60s to 180s. Agent-running tests (B4/B5) need 120s+ for Claude CLI round-trip
|
||||
- **E2E test suite — 27 failures fixed** across 3 spec files: bterminal.test.ts (22 — stale v2 CSS selectors, v3 tab order/count, JS-dispatched KeyboardEvent for Ctrl+K, idempotent palette open/close, backdrop click close, scrollIntoView for below-fold settings, scoped theme dropdown selectors), agent-scenarios.test.ts (3 — JS click for settings button, programmatic focus check, graceful 40s agent timeout with skip), phase-b.test.ts (2 — waitUntil for project box render, conditional null handling for burn-rate/cost elements). 82 E2E passing, 0 failing, 4 skipped
|
||||
- **E2E test suite — 27 failures fixed** across 3 spec files: agor.test.ts (22 — stale v2 CSS selectors, v3 tab order/count, JS-dispatched KeyboardEvent for Ctrl+K, idempotent palette open/close, backdrop click close, scrollIntoView for below-fold settings, scoped theme dropdown selectors), agent-scenarios.test.ts (3 — JS click for settings button, programmatic focus check, graceful 40s agent timeout with skip), phase-b.test.ts (2 — waitUntil for project box render, conditional null handling for burn-rate/cost elements). 82 E2E passing, 0 failing, 4 skipped
|
||||
- **AgentPane.svelte missing closing `>`** — div tag with data-testid attributes was missing closing angle bracket, causing template parse issues
|
||||
|
||||
### Changed
|
||||
- **WebDriverIO config** — TCP readiness probe replaces blind 2s sleep for tauri-driver startup (200ms interval, 10s deadline). Added BTERMINAL_TEST=1 passthrough in capabilities
|
||||
- **WebDriverIO config** — TCP readiness probe replaces blind 2s sleep for tauri-driver startup (200ms interval, 10s deadline). Added AGOR_TEST=1 passthrough in capabilities
|
||||
|
||||
### Security
|
||||
- `claude_read_skill` path traversal: added `canonicalize()` + `starts_with()` validation to prevent reading arbitrary files via crafted skill paths (commands/claude.rs)
|
||||
- **Sidecar env allowlist hardening** — added `ANTHROPIC_*` to Rust-level `strip_provider_env_var()` as defense-in-depth (Claude CLI uses credentials file, not env for auth). Dual-layer stripping documented: Rust layer (first checkpoint) + JS runner layer (per-provider)
|
||||
- **Plugin sandbox hardening** — 13 shadowed globals in `new Function()` sandbox (window, document, fetch, globalThis, self, XMLHttpRequest, WebSocket, Function, importScripts, require, process, Deno, __TAURI__, __TAURI_INTERNALS__). `this` bound to undefined via `.call()`. 35 tests covering all shadows, permissions, and lifecycle. Known escape vectors documented in JSDoc
|
||||
- **WAL checkpoint** — periodic `PRAGMA wal_checkpoint(TRUNCATE)` every 5 minutes on sessions.db + btmsg.db to prevent unbounded WAL growth under sustained multi-agent load. 2 tests
|
||||
- **TLS support for bterminal-relay** — optional `--tls-cert` and `--tls-key` CLI args. Server wraps TCP streams with native-tls. Client already supports `wss://` URLs. Generic handler refactor avoids code duplication
|
||||
- **TLS support for agor-relay** — optional `--tls-cert` and `--tls-key` CLI args. Server wraps TCP streams with native-tls. Client already supports `wss://` URLs. Generic handler refactor avoids code duplication
|
||||
- **Landlock fallback logging** — improved warning message with kernel version requirement (6.2+) and documented 3 enforcement states
|
||||
|
||||
### Fixed
|
||||
|
|
@ -104,7 +115,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- **Regression tests for btmsg/bttask bug fixes** — 49 new tests: btmsg.rs (8, in-memory SQLite with named column access regression for status vs system_prompt), bttask.rs (7, named column access + serde camelCase), sidecar strip_provider_env_var (8, all prefix combinations), btmsg-bridge.test.ts (17, camelCase fields + IPC commands), bttask-bridge.test.ts (10, camelCase + IPC), plantuml-encode.test.ts (7, hex encoding algorithm). Total: 327 vitest + 72 cargo
|
||||
- **Configurable stall threshold** — per-project range slider (5–60 min, step 5) in SettingsTab. `stallThresholdMin` in `ProjectConfig` (groups.json), `setStallThreshold()` API in health store with `stallThresholds` Map and `DEFAULT_STALL_THRESHOLD_MS` fallback. ProjectBox `$effect` syncs config → store on mount/change
|
||||
- **Memora adapter** — `MemoraAdapter` (memora-bridge.ts) implements `MemoryAdapter` interface, bridging to Memora's SQLite database (`~/.local/share/memora/memories.db`) via read-only Rust backend (`memora.rs`). FTS5 text search, tag filtering via `json_each()`. 4 Tauri commands (memora_available, memora_list, memora_search, memora_get). Registered in App.svelte onMount. 16 vitest + 7 cargo tests. MemoriesTab now shows Memora memories on startup
|
||||
- **Codex provider runner** — `sidecar/codex-runner.ts` wraps `@openai/codex-sdk` (dynamic import, graceful failure if not installed). Maps Codex ThreadEvents (agent_message, reasoning, command_execution, file_change, mcp_tool_call, web_search) to common AgentMessage format via `codex-messages.ts` adapter. Sandbox/approval mode mapping from BTerminal permission modes. Session resume via thread ID. `providers/codex.ts` ProviderMeta (gpt-5.4 default, hasSandbox, supportsResume). 19 adapter tests
|
||||
- **Codex provider runner** — `sidecar/codex-runner.ts` wraps `@openai/codex-sdk` (dynamic import, graceful failure if not installed). Maps Codex ThreadEvents (agent_message, reasoning, command_execution, file_change, mcp_tool_call, web_search) to common AgentMessage format via `codex-messages.ts` adapter. Sandbox/approval mode mapping from Agents Orchestrator permission modes. Session resume via thread ID. `providers/codex.ts` ProviderMeta (gpt-5.4 default, hasSandbox, supportsResume). 19 adapter tests
|
||||
- **Ollama provider runner** — `sidecar/ollama-runner.ts` uses direct HTTP to `localhost:11434/api/chat` with NDJSON streaming (zero external dependencies). Health check before session start. Configurable host/model/num_ctx/think via providerConfig. Supports Qwen3 extended thinking. `ollama-messages.ts` adapter maps streaming chunks to AgentMessage (text, thinking, cost with token counts). `providers/ollama.ts` ProviderMeta (qwen3:8b default, modelSelection only). 11 adapter tests
|
||||
- All 3 providers registered in App.svelte onMount + message-adapters.ts. `build:sidecar` builds all 3 runners
|
||||
- **S-1 Phase 3: Worktree isolation per project** — per-project `useWorktrees` toggle in SettingsTab. When enabled, agents run in git worktrees at `<repo>/.claude/worktrees/<sessionId>/` via SDK `extraArgs: { worktree: sessionId }`. CWD-based worktree detection in agent-dispatcher (`detectWorktreeFromCwd()`) matches `.claude/`, `.codex/`, `.cursor/` worktree patterns on init events. Dual detection: CWD-based (primary) + tool_call-based (subagent fallback). 8 files, +125 lines, 7 new tests. 226 vitest + 42 cargo tests
|
||||
|
|
@ -127,7 +138,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- Collapsible cost summary in AgentPane: `cost.result` wrapped in `<details>` (collapsed by default, expandable with 80-char preview) (AgentPane.svelte)
|
||||
- Project max aspect ratio setting: `project_max_aspect` (float 0.3–3.0, default 1.0) limits project box width via CSS `max-width: calc(100vh * var(--project-max-aspect))` (SettingsTab.svelte, ProjectGrid.svelte, App.svelte)
|
||||
- No-implicit-push rule: `.claude/rules/52-no-implicit-push.md` — never push unless user explicitly asks
|
||||
- `StartupWMClass=bterminal` in install-v2.sh .desktop template for GNOME auto-move extension compatibility
|
||||
- `StartupWMClass=agor` in install-v2.sh .desktop template for GNOME auto-move extension compatibility
|
||||
- MarkdownPane link navigation: relative file links open in Files tab, external URLs open in system browser via `xdg-open`, anchor links scroll in-page (MarkdownPane.svelte, ProjectFiles.svelte, lib.rs)
|
||||
- `open_url` Tauri command for opening http/https URLs in system browser (lib.rs)
|
||||
- Tab system overhaul: renamed Claude→Model, Files→Docs, added 3 new tabs (Files, SSH, Memory) with PERSISTED-EAGER/LAZY mount strategies (ProjectBox.svelte)
|
||||
|
|
@ -172,8 +183,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- SettingsTab: added Providers section with collapsible per-provider config panels (enabled toggle, default model, capabilities display) and per-project provider dropdown
|
||||
- AgentPane: capability-driven rendering via ProviderCapabilities props (hasProfiles, hasSkills, supportsResume gates)
|
||||
- AgentPane UI redesign: sans-serif root font (system-ui), tool calls paired with results in collapsible `<details>` groups, hook messages collapsed into compact labels, context window usage meter in status strip, cost bar made minimal (no background), session summary with translucent background, two-phase scroll anchoring, tool-aware output truncation (Bash 500/Read 50/Glob 20 lines), colors softened via `color-mix()`, responsive margins via container queries (AgentPane.svelte)
|
||||
- MarkdownPane: added inner scroll wrapper with `container-type: inline-size`, responsive padding via shared `--bterminal-pane-padding-inline` variable (MarkdownPane.svelte)
|
||||
- Added `--bterminal-pane-padding-inline: clamp(0.75rem, 3.5cqi, 2rem)` shared CSS variable for responsive pane padding (catppuccin.css)
|
||||
- MarkdownPane: added inner scroll wrapper with `container-type: inline-size`, responsive padding via shared `--agor-pane-padding-inline` variable (MarkdownPane.svelte)
|
||||
- Added `--agor-pane-padding-inline: clamp(0.75rem, 3.5cqi, 2rem)` shared CSS variable for responsive pane padding (catppuccin.css)
|
||||
|
||||
### Fixed
|
||||
- FilesTab invalid HTML nesting: file tab bar used `<button>` inside `<button>` which Svelte/browser rejects — changed outer element to `<div role="tab">` (FilesTab.svelte)
|
||||
|
|
@ -182,21 +193,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- Cost bar shows only last turn's cost instead of cumulative session total: `updateAgentCost()` changed from assignment to accumulation (`+=`) so continued sessions properly sum costs across all turns (agents.svelte.ts)
|
||||
- ProjectBox tab switch destroys running agent sessions: changed `{#if activeTab}` conditional rendering to CSS `style:display` (flex/none) for all three content panes and terminal section — ClaudeSession now stays mounted across tab switches, preserving session ID, message history, and running agents (ProjectBox.svelte)
|
||||
- Sidecar env var stripping now whitelists `CLAUDE_CODE_EXPERIMENTAL_*` vars (both Rust sidecar.rs and JS agent-runner.ts) — previously all `CLAUDE*` vars were stripped, blocking feature flags like agent teams from reaching the SDK (sidecar.rs, agent-runner.ts)
|
||||
- E2E terminal tab tests: scoped selectors to `.tab-bar .tab-title` (was `.tab-title` which matched project tabs), used `browser.execute()` for DOM text reads to avoid stale element issues (bterminal.test.ts)
|
||||
- E2E terminal tab tests: scoped selectors to `.tab-bar .tab-title` (was `.tab-title` which matched project tabs), used `browser.execute()` for DOM text reads to avoid stale element issues (agor.test.ts)
|
||||
- E2E wdio.conf.js: added `wdio:enforceWebDriverClassic: true` to disable BiDi negotiation (wdio v9 injects `webSocketUrl:true` which tauri-driver rejects), removed unnecessary `browserName: 'wry'`, fixed binary path to Cargo workspace target dir (`v2/target/debug/` not `v2/src-tauri/target/debug/`)
|
||||
- E2E consolidated to single spec file: Tauri creates one app session per spec file; multiple files caused "invalid session id" on 2nd+ file (wdio.conf.js, bterminal.test.ts)
|
||||
- E2E WebDriver clicks on Svelte 5 components: `element.click()` doesn't reliably trigger onclick handlers inside complex components via WebKit2GTK/tauri-driver; replaced with `browser.execute()` JS-level clicks for .ptab, .dropdown-trigger, .panel-close (bterminal.test.ts)
|
||||
- E2E consolidated to single spec file: Tauri creates one app session per spec file; multiple files caused "invalid session id" on 2nd+ file (wdio.conf.js, agor.test.ts)
|
||||
- E2E WebDriver clicks on Svelte 5 components: `element.click()` doesn't reliably trigger onclick handlers inside complex components via WebKit2GTK/tauri-driver; replaced with `browser.execute()` JS-level clicks for .ptab, .dropdown-trigger, .panel-close (agor.test.ts)
|
||||
- Removed `tauri-plugin-log` entirely — `telemetry::init()` already registers tracing-subscriber which bridges the `log` crate; adding plugin-log after panics with "attempted to set a logger after the logging system was already initialized" (lib.rs, Cargo.toml)
|
||||
|
||||
### Changed
|
||||
- E2E tests expanded from 6 smoke tests to 48 tests across 8 describe blocks: Smoke (6), Workspace & Projects (8), Settings Panel (6), Keyboard Shortcuts (5), Command Palette (5), Terminal Tabs (7), Theme Switching (3), Settings Interaction (8) — all in single bterminal.test.ts file
|
||||
- E2E tests expanded from 6 smoke tests to 48 tests across 8 describe blocks: Smoke (6), Workspace & Projects (8), Settings Panel (6), Keyboard Shortcuts (5), Command Palette (5), Terminal Tabs (7), Theme Switching (3), Settings Interaction (8) — all in single agor.test.ts file
|
||||
- wdio.conf.js: added SKIP_BUILD env var to skip cargo tauri build when debug binary already exists
|
||||
|
||||
### Removed
|
||||
- Ollama-specific warning toast from AgentPane when injecting anchors — replaced by generic configurable budget scale slider (AgentPane.svelte)
|
||||
- Unused `notify` import from AgentPane (AgentPane.svelte)
|
||||
- `tauri-plugin-log` dependency from Cargo.toml — redundant with telemetry::init() tracing-subscriber setup
|
||||
- Individual E2E spec files (smoke.test.ts, keyboard.test.ts, settings.test.ts, workspace.test.ts) — consolidated into bterminal.test.ts
|
||||
- Individual E2E spec files (smoke.test.ts, keyboard.test.ts, settings.test.ts, workspace.test.ts) — consolidated into agor.test.ts
|
||||
- Workspace teardown race: `switchGroup()` now awaits `waitForPendingPersistence()` before clearing agent state, preventing data loss when agents complete during group switch (agent-dispatcher.ts, workspace.svelte.ts)
|
||||
- SettingsTab switchGroup click handler made async with await to properly handle the async switchGroup() flow (SettingsTab.svelte)
|
||||
- Re-entrant sidecar exit handler race condition: added `restarting` guard flag preventing double-restart on rapid disconnect/reconnect (agent-dispatcher.ts)
|
||||
|
|
@ -226,7 +237,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
### Added
|
||||
- E2E testing infrastructure: WebdriverIO v9.24 + tauri-driver setup with `wdio.conf.js` (lifecycle hooks for tauri-driver spawn/kill, debug binary build), 6 smoke tests (`smoke.test.ts`), TypeScript config, `test:e2e` npm script, 4 new devDeps (@wdio/cli, @wdio/local-runner, @wdio/mocha-framework, @wdio/spec-reporter)
|
||||
- `waitForPendingPersistence()` export in agent-dispatcher.ts: counter-based fence that resolves when all in-flight `persistSessionForProject()` calls complete
|
||||
- OpenTelemetry instrumentation: `telemetry.rs` module with TelemetryGuard (Drop-based shutdown), tracing + optional OTLP/HTTP export to Tempo, controlled by `BTERMINAL_OTLP_ENDPOINT` env var (absent = console-only fallback)
|
||||
- OpenTelemetry instrumentation: `telemetry.rs` module with TelemetryGuard (Drop-based shutdown), tracing + optional OTLP/HTTP export to Tempo, controlled by `AGOR_OTLP_ENDPOINT` env var (absent = console-only fallback)
|
||||
- `#[tracing::instrument]` on 10 key Tauri commands: pty_spawn, pty_kill, agent_query, agent_stop, agent_restart, remote_connect, remote_disconnect, remote_agent_query, remote_agent_stop, remote_pty_spawn
|
||||
- `frontend_log` Tauri command: routes frontend telemetry events (level + message + context JSON) to Rust tracing layer with `source="frontend"` field
|
||||
- `telemetry-bridge.ts` adapter: `tel.info/warn/error/debug/trace()` convenience wrappers for frontend → Rust tracing bridge via IPC
|
||||
|
|
@ -322,7 +333,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- v3 Mission Control (All Phases 1-10 complete): multi-project dashboard with project groups, per-project Claude sessions, team agents panel, terminal tabs, 3 workspace tabs (Sessions/Docs/Context) + settings drawer
|
||||
- v3 session continuity (P6): `persistSessionForProject()` saves agent state + messages to SQLite on session complete; `registerSessionProject()` maps session to project; `ClaudeSession.restoreMessagesFromRecords()` restores cached messages on mount
|
||||
- v3 workspace teardown (P7): `clearAllAgentSessions()` clears agent sessions on group switch; terminal tabs reset via `switchGroup()`
|
||||
- v3 data model: `groups.rs` (Rust structs + load/save `~/.config/bterminal/groups.json`), `groups.ts` (TypeScript interfaces), `groups-bridge.ts` (IPC adapter), `--group` CLI argument
|
||||
- v3 data model: `groups.rs` (Rust structs + load/save `~/.config/agor/groups.json`), `groups.ts` (TypeScript interfaces), `groups-bridge.ts` (IPC adapter), `--group` CLI argument
|
||||
- v3 workspace store (`workspace.svelte.ts`): replaces `layout.svelte.ts`, manages groups/activeGroupId/activeTab/focusedProjectId with Svelte 5 runes
|
||||
- v3 SQLite migrations: `agent_messages` table (per-project message persistence), `project_agent_state` table (sdkSessionId/cost/status per project), `project_id` column on sessions
|
||||
- 12 new Workspace components: GlobalTabBar, ProjectGrid, ProjectBox, ProjectHeader, ClaudeSession, TeamAgentsPanel, AgentCard, TerminalTabs, CommandPalette, DocsTab, ContextTab, SettingsTab
|
||||
|
|
@ -357,7 +368,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- Stale TilingGrid reference in AgentPane.svelte comment (TilingGrid was deleted in v3 P10)
|
||||
|
||||
### Changed
|
||||
- StatusBar rewritten for v3 workspace store: shows active group name, project count, agent count instead of pane counts; version label updated to "BTerminal v3"
|
||||
- StatusBar rewritten for v3 workspace store: shows active group name, project count, agent count instead of pane counts; version label updated to "Agents Orchestrator v3"
|
||||
- Agent dispatcher subagent routing: project-scoped sessions skip layout pane creation (subagents render in TeamAgentsPanel instead); detached mode still creates layout pane
|
||||
- AgentPane `cwd` prop renamed to `initialCwd` — now editable via text input in session toolbar instead of fixed prop
|
||||
|
||||
|
|
@ -369,7 +380,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
### Fixed
|
||||
- AgentPane Svelte 5 event modifier syntax: `on:click` changed to `onclick` (Svelte 5 requires lowercase event handler attributes, not colon syntax)
|
||||
- CLAUDE* env var stripping now applied at Rust level in SidecarManager (bterminal-core/src/sidecar.rs): `env_clear()` + `envs(clean_env)` strips all CLAUDE-prefixed vars before spawning sidecar process, providing primary defense against nesting detection (JS-side stripping retained as defense-in-depth)
|
||||
- CLAUDE* env var stripping now applied at Rust level in SidecarManager (agor-core/src/sidecar.rs): `env_clear()` + `envs(clean_env)` strips all CLAUDE-prefixed vars before spawning sidecar process, providing primary defense against nesting detection (JS-side stripping retained as defense-in-depth)
|
||||
|
||||
### Changed
|
||||
- Sidecar resolution unified: single pre-built `agent-runner.mjs` bundle replaces separate `agent-runner-deno.ts` + `agent-runner.ts` lookup; same `.mjs` file runs under both Deno and Node.js
|
||||
|
|
@ -396,11 +407,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
### Previously Added
|
||||
- Exponential backoff reconnection in RemoteManager: on disconnect, spawns async task with 1s/2s/4s/8s/16s/30s-cap backoff, uses attempt_tcp_probe() (TCP-only, no WS upgrade, 5s timeout, default port 9750), emits remote-machine-reconnecting and remote-machine-reconnect-ready events
|
||||
- Frontend reconnection listeners: onRemoteMachineReconnecting and onRemoteMachineReconnectReady in remote-bridge.ts; machines store sets status to 'reconnecting' and auto-calls connectMachine() on ready
|
||||
- Relay command response propagation: bterminal-relay now sends structured responses (pty_created, pong, error) back to client via shared event channel with commandId correlation
|
||||
- send_error() helper in bterminal-relay for consistent error reporting across all command handlers
|
||||
- Relay command response propagation: agor-relay now sends structured responses (pty_created, pong, error) back to client via shared event channel with commandId correlation
|
||||
- send_error() helper in agor-relay for consistent error reporting across all command handlers
|
||||
- PTY creation confirmation flow: pty_create command returns pty_created event with session ID and commandId; RemoteManager emits remote-pty-created Tauri event
|
||||
- bterminal-core shared crate with EventSink trait: extracted PtyManager and SidecarManager into reusable crate at v2/bterminal-core/, EventSink trait abstracts event emission for both Tauri and WebSocket contexts
|
||||
- bterminal-relay WebSocket server binary: standalone Rust binary at v2/bterminal-relay/ with token auth (--port, --token, --insecure CLI flags), rate limiting (10 attempts, 5min lockout), per-connection isolated PTY + sidecar managers
|
||||
- agor-core shared crate with EventSink trait: extracted PtyManager and SidecarManager into reusable crate at v2/agor-core/, EventSink trait abstracts event emission for both Tauri and WebSocket contexts
|
||||
- agor-relay WebSocket server binary: standalone Rust binary at v2/agor-relay/ with token auth (--port, --token, --insecure CLI flags), rate limiting (10 attempts, 5min lockout), per-connection isolated PTY + sidecar managers
|
||||
- RemoteManager for multi-machine WebSocket connections: v2/src-tauri/src/remote.rs manages WebSocket client connections to relay instances, 12 new Tauri commands for remote operations, heartbeat ping every 15s
|
||||
- Remote machine management UI in settings: SettingsDialog "Remote Machines" section for add/remove/connect/disconnect
|
||||
- Auto-grouping of remote panes in sidebar: remote panes auto-grouped by machine label in SessionList
|
||||
|
|
@ -435,14 +446,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- tempfile dev dependency for Rust test isolation
|
||||
|
||||
### Fixed
|
||||
- Sidecar env var leak: both agent-runner.ts and agent-runner-deno.ts now strip ALL `CLAUDE*` prefixed env vars before spawning the claude CLI, preventing silent hangs when BTerminal is launched from within a Claude Code terminal session (previously only CLAUDECODE was removed)
|
||||
- Sidecar env var leak: both agent-runner.ts and agent-runner-deno.ts now strip ALL `CLAUDE*` prefixed env vars before spawning the claude CLI, preventing silent hangs when Agents Orchestrator is launched from within a Claude Code terminal session (previously only CLAUDECODE was removed)
|
||||
|
||||
### Changed
|
||||
- RemoteManager reconnection probe refactored from attempt_ws_connect() (full WS handshake + auth) to attempt_tcp_probe() (TCP-only connect, no resource allocation on relay)
|
||||
- bterminal-relay command handlers refactored: all error paths now use send_error() helper instead of log::error!() only; pong response sent via event channel instead of no-op
|
||||
- agor-relay command handlers refactored: all error paths now use send_error() helper instead of log::error!() only; pong response sent via event channel instead of no-op
|
||||
- RemoteManager disconnect handler: scoped mutex release before event emission to prevent deadlocks; spawns reconnection task
|
||||
- PtyManager and SidecarManager extracted from src-tauri to bterminal-core shared crate (src-tauri now has thin re-export wrappers)
|
||||
- Cargo workspace structure at v2/ level: members = [src-tauri, bterminal-core, bterminal-relay], Cargo.lock moved from src-tauri/ to workspace root
|
||||
- PtyManager and SidecarManager extracted from src-tauri to agor-core shared crate (src-tauri now has thin re-export wrappers)
|
||||
- Cargo workspace structure at v2/ level: members = [src-tauri, agor-core, agor-relay], Cargo.lock moved from src-tauri/ to workspace root
|
||||
- agent-bridge.ts and pty-bridge.ts extended with remote routing (check remoteMachineId, route to remote_* commands)
|
||||
- Agent dispatcher refactored to split messages: parentId-bearing messages routed to child panes via toolUseToChildPane Map, main session messages stay in parent
|
||||
- Agent store createAgentSession() now accepts optional parent parameter for registering bidirectional parent/child links
|
||||
|
|
@ -464,10 +475,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- Shiki syntax highlighting: lazy singleton highlighter with catppuccin-mocha theme, 13 preloaded languages, integrated in MarkdownPane and AgentPane text messages (Phase 5)
|
||||
- Tauri auto-updater plugin: tauri-plugin-updater (Rust + npm) + updater.ts frontend utility (Phase 6)
|
||||
- Markdown rendering in agent text messages with Shiki code highlighting (Phase 5)
|
||||
- Build-from-source installer `install-v2.sh` with 6-step dependency checking (Node.js 20+, Rust 1.77+, WebKit2GTK, GTK3, and 8 other system libraries), auto-install via apt, binary install to `~/.local/bin/bterminal-v2` with desktop entry (Phase 6)
|
||||
- Build-from-source installer `install-v2.sh` with 6-step dependency checking (Node.js 20+, Rust 1.77+, WebKit2GTK, GTK3, and 8 other system libraries), auto-install via apt, binary install to `~/.local/bin/agents-orchestrator` with desktop entry (Phase 6)
|
||||
- Tauri bundle configuration for .deb and AppImage targets with category, descriptions, and deb dependencies (Phase 6)
|
||||
- GitHub Actions release workflow (`.github/workflows/release.yml`): triggered on `v*` tags, builds on Ubuntu 22.04 with Rust/npm caching, uploads .deb + AppImage as GitHub Release artifacts (Phase 6)
|
||||
- Regenerated application icons from `bterminal.svg` as RGBA PNGs (32x32, 128x128, 256x256, 512x512, .ico) (Phase 6)
|
||||
- Regenerated application icons from `agor.svg` as RGBA PNGs (32x32, 128x128, 256x256, 512x512, .ico) (Phase 6)
|
||||
- Agent tree visualization: SVG tree of tool calls with horizontal layout, bezier edges, status-colored nodes (AgentTree.svelte + agent-tree.ts) (Phase 5)
|
||||
- Global status bar showing terminal/agent pane counts, active agents with pulse animation, total tokens and cost (StatusBar.svelte) (Phase 5)
|
||||
- Toast notification system with auto-dismiss (4s), max 5 visible, color-coded by type (notifications.svelte.ts + ToastContainer.svelte) (Phase 5)
|
||||
|
|
|
|||
46
CLAUDE.md
46
CLAUDE.md
|
|
@ -1,10 +1,10 @@
|
|||
# BTerminal — Project Guide for Claude
|
||||
# Agents Orchestrator — Project Guide for Claude
|
||||
|
||||
## Project Overview
|
||||
|
||||
Terminal emulator with SSH and Claude Code session management. v1 (GTK3+VTE Python) is production-stable. v2 redesign (Tauri 2.x + Svelte 5 + Claude Agent SDK) Phases 1-7 + multi-machine (A-D) + profiles/skills complete. Packaging: .deb + AppImage via GitHub Actions CI. v3 Mission Control (All Phases 1-10 Complete + Production Readiness): multi-project dashboard with project groups, per-project Claude sessions with session continuity, team agents panel, terminal tabs, VSCode-style left sidebar, multi-agent orchestration (Tier 1 management agents: Manager/Architect/Tester/Reviewer with role-specific tabs, btmsg inter-agent messaging, bttask kanban task board with optimistic locking). Production features: sidecar crash recovery/supervision, FTS5 full-text search, plugin system (Web Worker sandbox, 26 tests), Landlock sandboxing, secrets management (system keyring), OS + in-app notifications, keyboard-first UX (18+ palette commands), agent health monitoring + dead letter queue, audit logging, error classification. Hardening: TLS relay support, SPKI certificate pinning (TOFU), WAL checkpoint (5min), subagent delegation fix, SidecarManager actor pattern (mpsc), per-message btmsg acknowledgment (seen_messages), Aider autonomous mode toggle.
|
||||
|
||||
- **Repository:** github.com/DexterFromLab/BTerminal
|
||||
- **Repository:** github.com/DexterFromLab/Agents Orchestrator
|
||||
- **License:** MIT
|
||||
- **Primary target:** Linux x86_64
|
||||
|
||||
|
|
@ -16,7 +16,7 @@ Terminal emulator with SSH and Claude Code session management. v1 (GTK3+VTE Pyth
|
|||
|
||||
| Path | Description |
|
||||
|------|-------------|
|
||||
| `bterminal.py` | v1 main application (2092 lines, GTK3+VTE) |
|
||||
| `agor.py` | v1 main application (2092 lines, GTK3+VTE) |
|
||||
| `ctx` | Context manager CLI tool (SQLite-based) |
|
||||
| `install.sh` | v1 system installer |
|
||||
| `install-v2.sh` | v2 build-from-source installer (Node.js 20+, Rust 1.77+, system libs) |
|
||||
|
|
@ -29,11 +29,11 @@ Terminal emulator with SSH and Claude Code session management. v1 (GTK3+VTE Pyth
|
|||
| `docs/multi-machine.md` | Multi-machine architecture (implemented, Phases A-D) |
|
||||
| `docs/release-notes.md` | v3.0 release notes |
|
||||
| `docs/e2e-testing.md` | E2E testing facility: fixtures, test mode, LLM judge, spec phases, CI |
|
||||
| `Cargo.toml` | Cargo workspace root (members: src-tauri, bterminal-core, bterminal-relay) |
|
||||
| `bterminal-core/` | Shared crate: EventSink trait, PtyManager, SidecarManager |
|
||||
| `bterminal-relay/` | Standalone relay binary (WebSocket server, token auth, CLI) |
|
||||
| `src-tauri/src/pty.rs` | PTY backend (thin re-export from bterminal-core) |
|
||||
| `src-tauri/src/groups.rs` | Groups config (load/save ~/.config/bterminal/groups.json) |
|
||||
| `Cargo.toml` | Cargo workspace root (members: src-tauri, agor-core, agor-relay) |
|
||||
| `agor-core/` | Shared crate: EventSink trait, PtyManager, SidecarManager |
|
||||
| `agor-relay/` | Standalone relay binary (WebSocket server, token auth, CLI) |
|
||||
| `src-tauri/src/pty.rs` | PTY backend (thin re-export from agor-core) |
|
||||
| `src-tauri/src/groups.rs` | Groups config (load/save ~/.config/agor/groups.json) |
|
||||
| `src-tauri/src/fs_watcher.rs` | ProjectFsWatcher (inotify per-project recursive file change detection, S-1 Phase 2) |
|
||||
| `src-tauri/src/lib.rs` | AppState + setup + handler registration (~170 lines) |
|
||||
| `src-tauri/src/commands/` | 16 domain command modules (pty, agent, watcher, session, persistence, knowledge, claude, groups, files, remote, misc, bttask, notifications, plugins, search, secrets) |
|
||||
|
|
@ -43,16 +43,16 @@ Terminal emulator with SSH and Claude Code session management. v1 (GTK3+VTE Pyth
|
|||
| `src-tauri/src/secrets.rs` | SecretsManager (keyring crate, linux-native/libsecret, store/get/delete/list with metadata tracking) |
|
||||
| `src-tauri/src/plugins.rs` | Plugin discovery (scan config dir for plugin.json, path-traversal-safe file reading, permission validation) |
|
||||
| `src-tauri/src/notifications.rs` | Desktop notifications (notify-rust, graceful fallback if daemon unavailable) |
|
||||
| `bterminal-core/src/supervisor.rs` | SidecarSupervisor (auto-restart, exponential backoff 1s-30s, 5 retries, SidecarHealth enum, 17 tests) |
|
||||
| `bterminal-core/src/sandbox.rs` | Landlock sandbox (SandboxConfig RW/RO paths, pre_exec() integration, kernel 6.2+ graceful fallback) |
|
||||
| `src-tauri/src/sidecar.rs` | SidecarManager (thin re-export from bterminal-core) |
|
||||
| `agor-core/src/supervisor.rs` | SidecarSupervisor (auto-restart, exponential backoff 1s-30s, 5 retries, SidecarHealth enum, 17 tests) |
|
||||
| `agor-core/src/sandbox.rs` | Landlock sandbox (SandboxConfig RW/RO paths, pre_exec() integration, kernel 6.2+ graceful fallback) |
|
||||
| `src-tauri/src/sidecar.rs` | SidecarManager (thin re-export from agor-core) |
|
||||
| `src-tauri/src/event_sink.rs` | TauriEventSink (implements EventSink for AppHandle) |
|
||||
| `src-tauri/src/remote.rs` | RemoteManager (WebSocket client connections to relays) |
|
||||
| `src-tauri/src/session/` | SessionDb module: mod.rs (struct + migrate), sessions.rs, layout.rs, settings.rs, ssh.rs, agents.rs, metrics.rs, anchors.rs |
|
||||
| `src-tauri/src/watcher.rs` | FileWatcherManager (notify crate, file change events) |
|
||||
| `src-tauri/src/ctx.rs` | CtxDb (read-only access to ~/.claude-context/context.db) |
|
||||
| `src-tauri/src/memora.rs` | MemoraDb (read-only access to ~/.local/share/memora/memories.db, FTS5 search) |
|
||||
| `src-tauri/src/telemetry.rs` | OTEL telemetry (TelemetryGuard, tracing + OTLP export, BTERMINAL_OTLP_ENDPOINT) |
|
||||
| `src-tauri/src/telemetry.rs` | OTEL telemetry (TelemetryGuard, tracing + OTLP export, AGOR_OTLP_ENDPOINT) |
|
||||
| `src/lib/stores/workspace.svelte.ts` | v3 workspace store (project groups, tabs, focus, replaces layout store) |
|
||||
| `src/lib/stores/layout.svelte.ts` | v2 layout store (panes, presets, groups, persistence, Svelte 5 runes) |
|
||||
| `src/lib/stores/agents.svelte.ts` | Agent session store (messages, cost, parent/child hierarchy) |
|
||||
|
|
@ -96,7 +96,7 @@ Terminal emulator with SSH and Claude Code session management. v1 (GTK3+VTE Pyth
|
|||
| `tests/e2e/wdio.conf.js` | WebDriverIO config (tauri-driver lifecycle, TCP probe, test env vars) |
|
||||
| `tests/e2e/fixtures.ts` | E2E test fixture generator (isolated temp dirs, git repos, groups.json) |
|
||||
| `tests/e2e/results-db.ts` | JSON test results store (run/step tracking, no native deps) |
|
||||
| `tests/e2e/specs/bterminal.test.ts` | E2E smoke tests (CSS class selectors, 50+ tests) |
|
||||
| `tests/e2e/specs/agor.test.ts` | E2E smoke tests (CSS class selectors, 50+ tests) |
|
||||
| `tests/e2e/specs/agent-scenarios.test.ts` | Phase A E2E scenarios (data-testid selectors, 7 scenarios, 22 tests) |
|
||||
| `tests/e2e/specs/phase-b.test.ts` | Phase B E2E scenarios (multi-project, LLM-judged assertions, 6 scenarios) |
|
||||
| `tests/e2e/llm-judge.ts` | LLM judge helper (Claude API assertions, confidence thresholds) |
|
||||
|
|
@ -170,25 +170,25 @@ Terminal emulator with SSH and Claude Code session management. v1 (GTK3+VTE Pyth
|
|||
## v1 Stack
|
||||
|
||||
- Python 3, GTK3 (PyGObject), VTE 2.91
|
||||
- Config: `~/.config/bterminal/` (sessions.json, claude_sessions.json)
|
||||
- Config: `~/.config/agor/` (sessions.json, claude_sessions.json)
|
||||
- Context DB: `~/.claude-context/context.db`
|
||||
- Theme: Catppuccin Mocha
|
||||
|
||||
## v2/v3 Stack (v2 complete, v3 All Phases 1-10 complete, branch: v2-mission-control)
|
||||
|
||||
- Tauri 2.x (Rust backend) + Svelte 5 (frontend)
|
||||
- Cargo workspace: bterminal-core (shared), bterminal-relay (remote binary), src-tauri (Tauri app)
|
||||
- Cargo workspace: agor-core (shared), agor-relay (remote binary), src-tauri (Tauri app)
|
||||
- xterm.js with Canvas addon (no WebGL on WebKit2GTK)
|
||||
- Agent sessions via `@anthropic-ai/claude-agent-sdk` query() function (migrated from raw CLI spawning)
|
||||
- Sidecar uses SDK internally (single .mjs bundle, Deno-first + Node.js fallback, stdio NDJSON to Rust, auto-detects Claude CLI path via findClaudeCli(), supports CLAUDE_CONFIG_DIR override for multi-account)
|
||||
- portable-pty for terminal management (in bterminal-core)
|
||||
- Multi-machine: bterminal-relay WebSocket server + RemoteManager WebSocket client
|
||||
- portable-pty for terminal management (in agor-core)
|
||||
- Multi-machine: agor-relay WebSocket server + RemoteManager WebSocket client
|
||||
- SQLite session persistence (rusqlite, WAL mode) + layout restore on startup
|
||||
- File watcher (notify crate) for live markdown viewer
|
||||
- OpenTelemetry: tracing + tracing-subscriber + opentelemetry 0.28 + tracing-opentelemetry 0.29, OTLP/HTTP to Tempo, BTERMINAL_OTLP_ENDPOINT env var
|
||||
- Rust deps (src-tauri): tauri, bterminal-core (path), rusqlite (bundled-full, FTS5), dirs, notify, serde, tokio, tokio-tungstenite, futures-util, tracing, tracing-subscriber, opentelemetry, opentelemetry_sdk, opentelemetry-otlp, tracing-opentelemetry, tauri-plugin-updater, tauri-plugin-dialog, notify-rust, keyring (linux-native)
|
||||
- Rust deps (bterminal-core): portable-pty, uuid, serde, serde_json, log, landlock
|
||||
- Rust deps (bterminal-relay): bterminal-core, tokio, tokio-tungstenite, clap, env_logger, futures-util
|
||||
- OpenTelemetry: tracing + tracing-subscriber + opentelemetry 0.28 + tracing-opentelemetry 0.29, OTLP/HTTP to Tempo, AGOR_OTLP_ENDPOINT env var
|
||||
- Rust deps (src-tauri): tauri, agor-core (path), rusqlite (bundled-full, FTS5), dirs, notify, serde, tokio, tokio-tungstenite, futures-util, tracing, tracing-subscriber, opentelemetry, opentelemetry_sdk, opentelemetry-otlp, tracing-opentelemetry, tauri-plugin-updater, tauri-plugin-dialog, notify-rust, keyring (linux-native)
|
||||
- Rust deps (agor-core): portable-pty, uuid, serde, serde_json, log, landlock
|
||||
- Rust deps (agor-relay): agor-core, tokio, tokio-tungstenite, clap, env_logger, futures-util
|
||||
- npm deps: @anthropic-ai/claude-agent-sdk, @xterm/xterm, @xterm/addon-canvas, @xterm/addon-fit, @tauri-apps/api, @tauri-apps/plugin-updater, @tauri-apps/plugin-dialog, marked, shiki, pdfjs-dist, vitest (dev)
|
||||
- Source: `` directory
|
||||
|
||||
|
|
@ -197,7 +197,7 @@ Terminal emulator with SSH and Claude Code session management. v1 (GTK3+VTE Pyth
|
|||
```bash
|
||||
# v1 (current production)
|
||||
./install.sh # Install system-wide
|
||||
bterminal # Run
|
||||
agor # Run
|
||||
|
||||
# v1 Dependencies (Debian/Ubuntu)
|
||||
sudo apt install python3-gi gir1.2-gtk-3.0 gir1.2-vte-2.91
|
||||
|
|
@ -215,7 +215,7 @@ npm run test:e2e # E2E only (WebDriverIO)
|
|||
|
||||
# Telemetry stack (Tempo + Grafana)
|
||||
cd docker/tempo && docker compose up -d # Grafana at http://localhost:9715
|
||||
BTERMINAL_OTLP_ENDPOINT=http://localhost:4318 npm run tauri dev # Enable OTLP export
|
||||
AGOR_OTLP_ENDPOINT=http://localhost:4318 npm run tauri dev # Enable OTLP export
|
||||
```
|
||||
|
||||
## Conventions
|
||||
|
|
|
|||
14
README.md
14
README.md
|
|
@ -63,8 +63,8 @@ Agent Orchestrator lets you run multiple Claude Code agents in parallel, organiz
|
|||
Agent Orchestrator (Tauri 2.x)
|
||||
├── Rust backend (src-tauri/)
|
||||
│ ├── Commands: groups, sessions, btmsg, bttask, search, secrets, plugins, notifications
|
||||
│ ├── bterminal-core: PtyManager, SidecarManager, EventSink trait
|
||||
│ └── bterminal-relay: WebSocket server for remote machines (+ TLS)
|
||||
│ ├── agor-core: PtyManager, SidecarManager, EventSink trait
|
||||
│ └── agor-relay: WebSocket server for remote machines (+ TLS)
|
||||
├── Svelte 5 frontend (src/)
|
||||
│ ├── Workspace: ProjectGrid, ProjectBox (per-project tabs), StatusBar
|
||||
│ ├── Stores: workspace, agents, health, conflicts, wake-scheduler, plugins
|
||||
|
|
@ -97,21 +97,21 @@ npm run tauri:build
|
|||
|
||||
## Configuration
|
||||
|
||||
Config: `~/.config/bterminal/groups.json` — project groups, agents, prompts (human-editable JSON).
|
||||
Config: `~/.config/agor/groups.json` — project groups, agents, prompts (human-editable JSON).
|
||||
|
||||
Database: `~/.local/share/bterminal/` — sessions.db (sessions, metrics, anchors), btmsg.db (messages, tasks, agents).
|
||||
Database: `~/.local/share/agor/` — sessions.db (sessions, metrics, anchors), btmsg.db (messages, tasks, agents).
|
||||
|
||||
## Multi-Machine Support
|
||||
|
||||
```
|
||||
Agent Orchestrator --WebSocket/TLS--> bterminal-relay (Remote Machine)
|
||||
Agent Orchestrator --WebSocket/TLS--> agor-relay (Remote Machine)
|
||||
├── PtyManager (remote terminals)
|
||||
└── SidecarManager (remote agents)
|
||||
```
|
||||
|
||||
```bash
|
||||
cd v2 && cargo build --release -p bterminal-relay
|
||||
./target/release/bterminal-relay --port 9750 --token <secret> --tls-cert cert.pem --tls-key key.pem
|
||||
cd v2 && cargo build --release -p agor-relay
|
||||
./target/release/agor-relay --port 9750 --token <secret> --tls-cert cert.pem --tls-key key.pem
|
||||
```
|
||||
|
||||
## Keyboard Shortcuts
|
||||
|
|
|
|||
29
TODO.md
29
TODO.md
|
|
@ -1,28 +1,35 @@
|
|||
# Agent Orchestrator — TODO
|
||||
# Agents Orchestrator — TODO
|
||||
|
||||
## Dual-Repo & Commercial
|
||||
|
||||
- [ ] **First commercial feature** — Implement initial agor-pro feature inside the plugin crate, verify both editions build/test independently.
|
||||
- [ ] **CLA setup** — Configure CLA-assistant.io on community repo (DexterFromLab/agent-orchestrator) before accepting external PRs.
|
||||
- [ ] **Community export workflow** — Define and document the process for stripping commercial content and pushing to DexterFromLab origin.
|
||||
- [ ] **Dual CI validation** — Verify both leak-check.yml and commercial-build.yml workflows work in GitHub Actions.
|
||||
|
||||
## Multi-Machine (v3.1)
|
||||
|
||||
- [ ] **Real-world relay testing** — TLS added, code complete in bridges/stores. Needs 2-machine test to verify relay + RemoteManager end-to-end. Multi-machine UI not yet surfaced in v3 ProjectBox.
|
||||
- [ ] **SPKI pin persistence** — TOFU pinning implemented (probe_spki_hash + in-memory pin store in RemoteManager), but pins are lost on restart. Persist to groups.json or separate config file.
|
||||
- [ ] **Real-world relay testing** — TLS added, code complete in bridges/stores. Needs 2-machine test to verify relay + RemoteManager end-to-end.
|
||||
- [ ] **SPKI pin persistence** — TOFU pinning implemented but pins are lost on restart. Persist to groups.json or separate config file.
|
||||
|
||||
## Multi-Agent (v3.1)
|
||||
|
||||
- [ ] **Agent Teams real-world testing** — Subagent delegation prompt + `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1` env injection done. Needs real multi-agent session to verify Manager spawns child agents via SDK teams.
|
||||
- [ ] **Agent Teams real-world testing** — Subagent delegation prompt + env injection done. Needs real multi-agent session to verify Manager spawns child agents.
|
||||
|
||||
## Reliability
|
||||
|
||||
- [ ] **Soak test** — Run 4-hour soak with 6+ agents across 3+ projects. Monitor: memory growth, SQLite WAL size, xterm.js instance count, sidecar supervisor restarts.
|
||||
- [ ] **WebKit2GTK Worker verification** — Verify Web Worker Blob URL approach works in Tauri's WebKit2GTK webview (tested in vitest only so far).
|
||||
- [ ] **Soak test** — Run 4-hour soak with 6+ agents across 3+ projects. Monitor: memory, WAL size, xterm count, supervisor restarts.
|
||||
- [ ] **WebKit2GTK Worker verification** — Verify Web Worker Blob URL approach in Tauri's WebKit2GTK webview.
|
||||
|
||||
## Completed
|
||||
|
||||
- [x] Plugin sandbox migration — new Function() → Web Worker isolation, 26 tests | Done: 2026-03-15
|
||||
- [x] seen_messages startup pruning — pruneSeen() on app startup, fire-and-forget | Done: 2026-03-15
|
||||
- [x] bterminal→agor rebrand + dual-repo commercial structure | Done: 2026-03-17
|
||||
- [x] Tribunal-codex dual-repo strategy (S-3+S-1 hybrid, 80% confidence) | Done: 2026-03-17
|
||||
- [x] Plugin sandbox migration — Web Worker isolation, 26 tests | Done: 2026-03-15
|
||||
- [x] seen_messages startup pruning | Done: 2026-03-15
|
||||
- [x] Tribunal priorities: Aider security, SidecarManager actor, SPKI pinning, btmsg reliability, Aider tests | Done: 2026-03-14
|
||||
- [x] Dead code cleanup — 7 warnings resolved, 4 new Tauri commands wired | Done: 2026-03-14
|
||||
- [x] Dead code cleanup — 7 warnings resolved, 4 new Tauri commands | Done: 2026-03-14
|
||||
- [x] E2E fixture + judge hardening | Done: 2026-03-12
|
||||
- [x] LLM judge refactor + E2E docs | Done: 2026-03-12
|
||||
- [x] v3 Hardening Sprint (TLS, WAL, Landlock, plugin tests, Phase C E2E) | Done: 2026-03-12
|
||||
- [x] v3 Production Readiness — all 13 tribunal items | Done: 2026-03-12
|
||||
- [x] Unified test runner + testing gate rule | Done: 2026-03-12
|
||||
- [x] E2E Phase B + 27 test fixes | Done: 2026-03-12
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@ description: "Project documentation index"
|
|||
|
||||
# Agent Orchestrator Documentation
|
||||
|
||||
Agent Orchestrator (formerly BTerminal) is a multi-project AI agent orchestration dashboard built with Tauri 2.x, Svelte 5, and the Claude Agent SDK. It transforms a traditional terminal emulator into a mission control for running, monitoring, and coordinating multiple AI agent sessions across multiple codebases simultaneously.
|
||||
Agent Orchestrator (formerly Agents Orchestrator) is a multi-project AI agent orchestration dashboard built with Tauri 2.x, Svelte 5, and the Claude Agent SDK. It transforms a traditional terminal emulator into a mission control for running, monitoring, and coordinating multiple AI agent sessions across multiple codebases simultaneously.
|
||||
|
||||
The application has three major version milestones:
|
||||
|
||||
- **v1** — A single-file Python GTK3+VTE terminal emulator with Claude Code session management. Production-stable, still shipped as `bterminal`.
|
||||
- **v1** — A single-file Python GTK3+VTE terminal emulator with Claude Code session management. Production-stable, still shipped as `agor`.
|
||||
- **v2** — A ground-up rewrite using Tauri 2.x (Rust backend) + Svelte 5 (frontend). Multi-pane terminal with structured agent sessions, subagent tree visualization, session persistence, multi-machine relay support, 17 themes, and comprehensive packaging.
|
||||
- **v3 (Mission Control)** — A further redesign on top of v2's codebase. Replaces the free-form pane grid with a project-group dashboard. Adds multi-agent orchestration (4 management roles), inter-agent messaging (btmsg), task boards (bttask), session anchors, health monitoring, FTS5 search, plugin system, Landlock sandboxing, secrets management, and 704 automated tests.
|
||||
|
||||
|
|
@ -28,7 +28,7 @@ The application has three major version milestones:
|
|||
|----------|---------------|
|
||||
| [architecture.md](architecture.md) | End-to-end system architecture: Rust backend, Svelte frontend, sidecar layer, data model, layout system, data flow, IPC patterns |
|
||||
| [decisions.md](decisions.md) | Architecture decisions log: rationale and dates for all major design choices |
|
||||
| [multi-machine.md](multi-machine.md) | Multi-machine relay architecture: bterminal-core extraction, bterminal-relay binary, RemoteManager, WebSocket protocol, reconnection |
|
||||
| [multi-machine.md](multi-machine.md) | Multi-machine relay architecture: agor-core extraction, agor-relay binary, RemoteManager, WebSocket protocol, reconnection |
|
||||
|
||||
### Subsystem Guides
|
||||
|
||||
|
|
@ -82,8 +82,8 @@ For research context, read [findings.md](findings.md). For implementation histor
|
|||
| Path | Purpose |
|
||||
|------|---------|
|
||||
| `src-tauri/src/` | Rust backend: commands, SQLite, btmsg, bttask, search, secrets, plugins |
|
||||
| `bterminal-core/` | Shared Rust crate: PtyManager, SidecarManager, EventSink trait, Landlock sandbox |
|
||||
| `bterminal-relay/` | Standalone relay binary for remote machine support |
|
||||
| `agor-core/` | Shared Rust crate: PtyManager, SidecarManager, EventSink trait, Landlock sandbox |
|
||||
| `agor-relay/` | Standalone relay binary for remote machine support |
|
||||
| `src/lib/` | Svelte 5 frontend: components, stores, adapters, utils, providers |
|
||||
| `sidecar/` | Agent sidecar runners (Claude, Codex, Ollama) — compiled to ESM bundles |
|
||||
| `tests/e2e/` | WebDriverIO E2E tests, fixtures, LLM judge |
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ The Rust code is organized as a Cargo workspace with three members:
|
|||
```
|
||||
v2/
|
||||
├── Cargo.toml # Workspace root
|
||||
├── bterminal-core/ # Shared crate
|
||||
├── agor-core/ # Shared crate
|
||||
│ └── src/
|
||||
│ ├── lib.rs
|
||||
│ ├── pty.rs # PtyManager (portable-pty)
|
||||
|
|
@ -67,7 +67,7 @@ v2/
|
|||
│ ├── supervisor.rs # SidecarSupervisor (crash recovery)
|
||||
│ ├── sandbox.rs # Landlock sandbox
|
||||
│ └── event.rs # EventSink trait
|
||||
├── bterminal-relay/ # Remote machine relay
|
||||
├── agor-relay/ # Remote machine relay
|
||||
│ └── src/main.rs # WebSocket server + token auth
|
||||
└── src-tauri/ # Tauri application
|
||||
└── src/
|
||||
|
|
@ -88,13 +88,13 @@ v2/
|
|||
├── watcher.rs # File watcher (notify crate)
|
||||
├── fs_watcher.rs # Per-project filesystem watcher (inotify)
|
||||
├── event_sink.rs # TauriEventSink implementation
|
||||
├── pty.rs # Thin re-export from bterminal-core
|
||||
└── sidecar.rs # Thin re-export from bterminal-core
|
||||
├── pty.rs # Thin re-export from agor-core
|
||||
└── sidecar.rs # Thin re-export from agor-core
|
||||
```
|
||||
|
||||
### Why a Workspace?
|
||||
|
||||
The `bterminal-core` crate exists so that both the Tauri application and the standalone `bterminal-relay` binary can share PtyManager and SidecarManager code. The `EventSink` trait abstracts event emission — TauriEventSink wraps Tauri's AppHandle, while the relay uses a WebSocket-based EventSink.
|
||||
The `agor-core` crate exists so that both the Tauri application and the standalone `agor-relay` binary can share PtyManager and SidecarManager code. The `EventSink` trait abstracts event emission — TauriEventSink wraps Tauri's AppHandle, while the relay uses a WebSocket-based EventSink.
|
||||
|
||||
### AppState
|
||||
|
||||
|
|
@ -116,8 +116,8 @@ The backend manages two SQLite databases, both in WAL mode with 5-second busy ti
|
|||
|
||||
| Database | Location | Purpose |
|
||||
|----------|----------|---------|
|
||||
| `sessions.db` | `~/.local/share/bterminal/` | Sessions, layout, settings, agent state, metrics, anchors |
|
||||
| `btmsg.db` | `~/.local/share/bterminal/` | Inter-agent messages, tasks, agents registry, audit log |
|
||||
| `sessions.db` | `~/.local/share/agor/` | Sessions, layout, settings, agent state, metrics, anchors |
|
||||
| `btmsg.db` | `~/.local/share/agor/` | Inter-agent messages, tasks, agents registry, audit log |
|
||||
|
||||
WAL checkpoints run every 5 minutes via a background tokio task to prevent unbounded WAL growth.
|
||||
|
||||
|
|
@ -301,7 +301,7 @@ Here is the complete path of a user prompt through the system:
|
|||
|
||||
## Configuration
|
||||
|
||||
### Project Groups (`~/.config/bterminal/groups.json`)
|
||||
### Project Groups (`~/.config/agor/groups.json`)
|
||||
|
||||
Human-editable JSON file defining project groups and their projects. Loaded at startup by `groups.rs`. Not hot-reloaded — changes require app restart or group switch.
|
||||
|
||||
|
|
@ -313,16 +313,16 @@ Key-value store for user preferences: theme, fonts, shell, CWD, provider setting
|
|||
|
||||
| Variable | Purpose |
|
||||
|----------|---------|
|
||||
| `BTERMINAL_TEST` | Enables test mode (disables watchers, wake scheduler) |
|
||||
| `BTERMINAL_TEST_DATA_DIR` | Redirects SQLite database storage |
|
||||
| `BTERMINAL_TEST_CONFIG_DIR` | Redirects groups.json config |
|
||||
| `BTERMINAL_OTLP_ENDPOINT` | Enables OpenTelemetry OTLP export |
|
||||
| `AGOR_TEST` | Enables test mode (disables watchers, wake scheduler) |
|
||||
| `AGOR_TEST_DATA_DIR` | Redirects SQLite database storage |
|
||||
| `AGOR_TEST_CONFIG_DIR` | Redirects groups.json config |
|
||||
| `AGOR_OTLP_ENDPOINT` | Enables OpenTelemetry OTLP export |
|
||||
|
||||
---
|
||||
|
||||
## Data Model
|
||||
|
||||
### Project Group Config (`~/.config/bterminal/groups.json`)
|
||||
### Project Group Config (`~/.config/agor/groups.json`)
|
||||
|
||||
Human-editable JSON file defining workspaces. Each group contains up to 5 projects. Loaded at startup by `groups.rs`, not hot-reloaded.
|
||||
|
||||
|
|
@ -335,12 +335,12 @@ Human-editable JSON file defining workspaces. Each group contains up to 5 projec
|
|||
"name": "AI Projects",
|
||||
"projects": [
|
||||
{
|
||||
"id": "bterminal",
|
||||
"name": "BTerminal",
|
||||
"identifier": "bterminal",
|
||||
"id": "agor",
|
||||
"name": "Agents Orchestrator",
|
||||
"identifier": "agor",
|
||||
"description": "Terminal emulator with Claude integration",
|
||||
"icon": "\uf120",
|
||||
"cwd": "/home/user/code/BTerminal",
|
||||
"cwd": "/home/user/code/Agents Orchestrator",
|
||||
"profile": "default",
|
||||
"enabled": true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ This document records significant architecture decisions made during the develop
|
|||
| Decision | Rationale | Date |
|
||||
|----------|-----------|------|
|
||||
| JSON for groups config, SQLite for session state | JSON is human-editable, shareable, version-controllable. SQLite for ephemeral runtime state. Load at startup only — no hot-reload, no split-brain risk. | 2026-03-07 |
|
||||
| btmsg/bttask shared SQLite DB | Both CLI tools share `~/.local/share/bterminal/btmsg.db`. Single DB simplifies deployment — agents already have the path. Read-only for non-Manager roles via CLI permissions. | 2026-03-11 |
|
||||
| btmsg/bttask shared SQLite DB | Both CLI tools share `~/.local/share/agor/btmsg.db`. Single DB simplifies deployment — agents already have the path. Read-only for non-Manager roles via CLI permissions. | 2026-03-11 |
|
||||
|
||||
## Layout & UI
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# E2E Testing Facility
|
||||
|
||||
BTerminal's end-to-end testing uses **WebDriverIO + tauri-driver** to drive the real Tauri application through WebKit2GTK's inspector protocol. The facility has three pillars:
|
||||
Agents Orchestrator's end-to-end testing uses **WebDriverIO + tauri-driver** to drive the real Tauri application through WebKit2GTK's inspector protocol. The facility has three pillars:
|
||||
|
||||
1. **Test Fixtures** — isolated fake environments with dummy projects
|
||||
2. **Test Mode** — app-level env vars that disable watchers and redirect data/config paths
|
||||
|
|
@ -47,10 +47,10 @@ LLM_JUDGE_BACKEND=api ANTHROPIC_API_KEY=sk-... npm run test:e2e
|
|||
│ tauri-driver (port 4444) │
|
||||
│ WebDriver protocol ↔ WebKit2GTK inspector │
|
||||
├─────────────────────────────────────────────────────────┤
|
||||
│ BTerminal debug binary │
|
||||
│ BTERMINAL_TEST=1 (disables watchers, wake scheduler) │
|
||||
│ BTERMINAL_TEST_DATA_DIR → isolated SQLite DBs │
|
||||
│ BTERMINAL_TEST_CONFIG_DIR → test groups.json │
|
||||
│ Agents Orchestrator debug binary │
|
||||
│ AGOR_TEST=1 (disables watchers, wake scheduler) │
|
||||
│ AGOR_TEST_DATA_DIR → isolated SQLite DBs │
|
||||
│ AGOR_TEST_CONFIG_DIR → test groups.json │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
|
|
@ -58,7 +58,7 @@ LLM_JUDGE_BACKEND=api ANTHROPIC_API_KEY=sk-... npm run test:e2e
|
|||
|
||||
The fixture generator creates isolated temporary environments so tests never touch real user data. Each fixture includes:
|
||||
|
||||
- **Temp root dir** under `/tmp/bterminal-e2e-{timestamp}/`
|
||||
- **Temp root dir** under `/tmp/agor-e2e-{timestamp}/`
|
||||
- **Data dir** — empty, SQLite databases created at runtime
|
||||
- **Config dir** — contains a generated `groups.json` with test projects
|
||||
- **Project dir** — a real git repo with `README.md` and `hello.py` (for agent testing)
|
||||
|
|
@ -74,10 +74,10 @@ const fixture = createTestFixture('my-test');
|
|||
// fixture.dataDir → /tmp/my-test-1710234567890/data/
|
||||
// fixture.configDir → /tmp/my-test-1710234567890/config/
|
||||
// fixture.projectDir → /tmp/my-test-1710234567890/test-project/
|
||||
// fixture.env → { BTERMINAL_TEST: '1', BTERMINAL_TEST_DATA_DIR: '...', BTERMINAL_TEST_CONFIG_DIR: '...' }
|
||||
// fixture.env → { AGOR_TEST: '1', AGOR_TEST_DATA_DIR: '...', AGOR_TEST_CONFIG_DIR: '...' }
|
||||
|
||||
// The test project is a git repo with:
|
||||
// README.md — "# Test Project\n\nA simple test project for BTerminal E2E tests."
|
||||
// README.md — "# Test Project\n\nA simple test project for Agents Orchestrator E2E tests."
|
||||
// hello.py — "def greet(name: str) -> str:\n return f\"Hello, {name}!\""
|
||||
// Both committed as "initial commit"
|
||||
|
||||
|
|
@ -105,17 +105,17 @@ Pass `fixture.env` to the app to redirect all data/config paths:
|
|||
|
||||
| Variable | Effect |
|
||||
|----------|--------|
|
||||
| `BTERMINAL_TEST=1` | Disables file watchers, wake scheduler, enables `is_test_mode` |
|
||||
| `BTERMINAL_TEST_DATA_DIR` | Redirects `sessions.db` and `btmsg.db` storage |
|
||||
| `BTERMINAL_TEST_CONFIG_DIR` | Redirects `groups.json` config loading |
|
||||
| `AGOR_TEST=1` | Disables file watchers, wake scheduler, enables `is_test_mode` |
|
||||
| `AGOR_TEST_DATA_DIR` | Redirects `sessions.db` and `btmsg.db` storage |
|
||||
| `AGOR_TEST_CONFIG_DIR` | Redirects `groups.json` config loading |
|
||||
|
||||
## Pillar 2: Test Mode
|
||||
|
||||
When `BTERMINAL_TEST=1` is set:
|
||||
When `AGOR_TEST=1` is set:
|
||||
|
||||
- **Rust backend**: `watcher.rs` and `fs_watcher.rs` skip file watchers
|
||||
- **Frontend**: `is_test_mode` Tauri command returns true, wake scheduler disabled via `disableWakeScheduler()`
|
||||
- **Data isolation**: `BTERMINAL_TEST_DATA_DIR` / `BTERMINAL_TEST_CONFIG_DIR` override default paths
|
||||
- **Data isolation**: `AGOR_TEST_DATA_DIR` / `AGOR_TEST_CONFIG_DIR` override default paths
|
||||
|
||||
The WebDriverIO config (`wdio.conf.js`) passes these env vars via `tauri:options.env` in capabilities.
|
||||
|
||||
|
|
@ -176,7 +176,7 @@ The CLI backend unsets `CLAUDECODE` env var to avoid nested session errors when
|
|||
|
||||
| File | Phase | Tests | Focus |
|
||||
|------|-------|-------|-------|
|
||||
| `bterminal.test.ts` | Smoke | ~50 | Basic UI rendering, CSS class selectors |
|
||||
| `agor.test.ts` | Smoke | ~50 | Basic UI rendering, CSS class selectors |
|
||||
| `agent-scenarios.test.ts` | A | 22 | `data-testid` selectors, 7 deterministic scenarios |
|
||||
| `phase-b.test.ts` | B | ~15 | Multi-project grid, LLM-judged agent responses |
|
||||
| `phase-c.test.ts` | C | 27 | Hardening features (palette, search, notifications, keyboard, settings, health, metrics, context, files) |
|
||||
|
|
@ -221,7 +221,7 @@ db.finishRun('run-001', 'passed', 45000);
|
|||
The CI pipeline runs on push/PR with path-filtered triggers:
|
||||
|
||||
1. **Unit tests** — `npm run test` (vitest)
|
||||
2. **Cargo tests** — `cargo test` (with `env -u BTERMINAL_TEST` to prevent env leakage)
|
||||
2. **Cargo tests** — `cargo test` (with `env -u AGOR_TEST` to prevent env leakage)
|
||||
3. **E2E tests** — `xvfb-run npm run test:e2e` (virtual framebuffer for headless WebKit2GTK)
|
||||
|
||||
LLM-judged tests are gated on the `ANTHROPIC_API_KEY` secret — they skip gracefully in forks or when the secret is absent.
|
||||
|
|
@ -278,5 +278,5 @@ Key settings:
|
|||
| Tests hang on startup | Kill stale `tauri-driver` processes: `pkill -f tauri-driver` |
|
||||
| All tests skip LLM judge | Install Claude CLI or set `ANTHROPIC_API_KEY` |
|
||||
| SIGUSR2 / exit code 144 | Stale tauri-driver on port 4444 — kill and retry |
|
||||
| `BTERMINAL_TEST` leaking to cargo | Run cargo tests with `env -u BTERMINAL_TEST cargo test` |
|
||||
| `AGOR_TEST` leaking to cargo | Run cargo tests with `env -u AGOR_TEST cargo test` |
|
||||
| No display available | Use `xvfb-run` or ensure X11/Wayland display is set |
|
||||
|
|
|
|||
|
|
@ -231,7 +231,7 @@ Before implementing multi-provider support, a systematic coupling analysis mappe
|
|||
|
||||
**CRITICAL — hardcoded SDK, must abstract:**
|
||||
- `sidecar/agent-runner.ts` — imports Claude Agent SDK, calls `query()`, hardcoded `findClaudeCli()`. Became `claude-runner.ts` with other providers getting separate runners.
|
||||
- `bterminal-core/src/sidecar.rs` — `AgentQueryOptions` had no `provider` field. `SidecarCommand` hardcoded runner path. Added provider-based runner selection.
|
||||
- `agor-core/src/sidecar.rs` — `AgentQueryOptions` had no `provider` field. `SidecarCommand` hardcoded runner path. Added provider-based runner selection.
|
||||
- `src/lib/adapters/sdk-messages.ts` — `parseMessage()` assumed Claude SDK JSON format. Became `claude-messages.ts` with per-provider parsers.
|
||||
|
||||
**HIGH — TS mirror types, provider-specific commands:**
|
||||
|
|
@ -245,7 +245,7 @@ Before implementing multi-provider support, a systematic coupling analysis mappe
|
|||
|
||||
**LOW — already generic:**
|
||||
- `agents.svelte.ts`, `health.svelte.ts`, `conflicts.svelte.ts` — provider-agnostic.
|
||||
- `bterminal-relay/` — forwards `AgentQueryOptions` as-is.
|
||||
- `agor-relay/` — forwards `AgentQueryOptions` as-is.
|
||||
|
||||
### Key Insights
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
## Overview
|
||||
|
||||
Extend BTerminal to manage Claude agent sessions and terminal panes running on **remote machines** over WebSocket, while keeping the local sidecar path unchanged.
|
||||
Extend Agents Orchestrator to manage Claude agent sessions and terminal panes running on **remote machines** over WebSocket, while keeping the local sidecar path unchanged.
|
||||
|
||||
## Problem
|
||||
|
||||
|
|
@ -15,7 +15,7 @@ WebView ←→ Rust (Tauri IPC) ←→ Local Sidecar (stdio NDJSON)
|
|||
←→ Local PTY (portable-pty)
|
||||
```
|
||||
|
||||
Target state: BTerminal acts as a **mission control** that observes agents and terminals running on multiple machines (dev servers, cloud VMs, CI runners).
|
||||
Target state: Agents Orchestrator acts as a **mission control** that observes agents and terminals running on multiple machines (dev servers, cloud VMs, CI runners).
|
||||
|
||||
## Design Constraints
|
||||
|
||||
|
|
@ -31,7 +31,7 @@ Target state: BTerminal acts as a **mission control** that observes agents and t
|
|||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────────────┐
|
||||
│ BTerminal (Controller) │
|
||||
│ Agents Orchestrator (Controller) │
|
||||
│ │
|
||||
│ ┌──────────┐ Tauri IPC ┌──────────────────────────────┐ │
|
||||
│ │ WebView │ ←────────────→ │ Rust Backend │ │
|
||||
|
|
@ -49,7 +49,7 @@ Target state: BTerminal acts as a **mission control** that observes agents and t
|
|||
│ Local │ │ Remote Machine │
|
||||
│ Sidecar │ │ │
|
||||
│ (Deno/ │ │ ┌────────────────┐ │
|
||||
│ Node.js) │ │ │ bterminal-relay│ │
|
||||
│ Node.js) │ │ │ agor-relay│ │
|
||||
│ │ │ │ (Rust binary) │ │
|
||||
└───────────┘ │ │ │ │
|
||||
│ │ ├── PTY mgr │ │
|
||||
|
|
@ -61,7 +61,7 @@ Target state: BTerminal acts as a **mission control** that observes agents and t
|
|||
|
||||
### Components
|
||||
|
||||
#### 1. `bterminal-relay` — Remote Agent (Rust binary)
|
||||
#### 1. `agor-relay` — Remote Agent (Rust binary)
|
||||
|
||||
A standalone Rust binary that runs on each remote machine. It:
|
||||
|
||||
|
|
@ -73,12 +73,12 @@ A standalone Rust binary that runs on each remote machine. It:
|
|||
**Why a Rust binary?** Reuses existing `PtyManager` and `SidecarManager` code from `src-tauri/src/`. Extracted into a shared crate.
|
||||
|
||||
```
|
||||
bterminal-relay/
|
||||
├── Cargo.toml # depends on bterminal-core
|
||||
agor-relay/
|
||||
├── Cargo.toml # depends on agor-core
|
||||
├── src/
|
||||
│ └── main.rs # WebSocket server + auth
|
||||
│
|
||||
bterminal-core/ # shared crate (extracted from src-tauri)
|
||||
agor-core/ # shared crate (extracted from src-tauri)
|
||||
├── Cargo.toml
|
||||
├── src/
|
||||
│ ├── pty.rs # PtyManager (from src-tauri/src/pty.rs)
|
||||
|
|
@ -249,20 +249,20 @@ Stored in SQLite `settings` table as JSON: `remote_machines` key.
|
|||
|
||||
## Implementation (All Phases Complete)
|
||||
|
||||
### Phase A: Extract `bterminal-core` crate [DONE]
|
||||
### Phase A: Extract `agor-core` crate [DONE]
|
||||
|
||||
- Cargo workspace at level (Cargo.toml with members: src-tauri, bterminal-core, bterminal-relay)
|
||||
- PtyManager and SidecarManager extracted to bterminal-core/
|
||||
- EventSink trait (bterminal-core/src/event.rs) abstracts event emission
|
||||
- Cargo workspace at level (Cargo.toml with members: src-tauri, agor-core, agor-relay)
|
||||
- PtyManager and SidecarManager extracted to agor-core/
|
||||
- EventSink trait (agor-core/src/event.rs) abstracts event emission
|
||||
- TauriEventSink (src-tauri/src/event_sink.rs) implements EventSink for AppHandle
|
||||
- src-tauri pty.rs and sidecar.rs are thin re-export wrappers
|
||||
|
||||
### Phase B: Build `bterminal-relay` binary [DONE]
|
||||
### Phase B: Build `agor-relay` binary [DONE]
|
||||
|
||||
- bterminal-relay/src/main.rs — WebSocket server (tokio-tungstenite)
|
||||
- agor-relay/src/main.rs — WebSocket server (tokio-tungstenite)
|
||||
- Token auth on WebSocket upgrade (Authorization: Bearer header)
|
||||
- CLI: --port (default 9750), --token (required), --insecure (allow ws://)
|
||||
- Routes RelayCommand to bterminal-core managers, forwards RelayEvent over WebSocket
|
||||
- Routes RelayCommand to agor-core managers, forwards RelayEvent over WebSocket
|
||||
- Rate limiting: 10 failed auth attempts triggers 5-minute lockout
|
||||
- Per-connection isolated PtyManager + SidecarManager instances
|
||||
- Command response propagation: structured responses (pty_created, pong, error) sent back via shared event channel
|
||||
|
|
@ -316,7 +316,7 @@ Stored in SQLite `settings` table as JSON: `remote_machines` key.
|
|||
|
||||
## What This Does NOT Cover (Future)
|
||||
|
||||
- **Multi-controller** — multiple BTerminal instances observing the same relay (needs pub/sub)
|
||||
- **Multi-controller** — multiple Agents Orchestrator instances observing the same relay (needs pub/sub)
|
||||
- **Relay discovery** — automatic detection of relays on LAN (mDNS/Bonjour)
|
||||
- **Agent migration** — moving a running agent from one machine to another
|
||||
- **Relay-to-relay** — direct communication between remote machines
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ Agent (via btmsg CLI)
|
|||
└── btmsg heartbeat → updates agent heartbeat
|
||||
│
|
||||
▼
|
||||
btmsg.db (SQLite, WAL mode, ~/.local/share/bterminal/btmsg.db)
|
||||
btmsg.db (SQLite, WAL mode, ~/.local/share/agor/btmsg.db)
|
||||
│
|
||||
├── agents table — registered agents with roles
|
||||
├── messages table — DMs and channel messages
|
||||
|
|
@ -274,7 +274,7 @@ The pure scoring function in `wake-scorer.ts` is tested with 24 unit tests. The
|
|||
3. Every 5 seconds, AgentSession polls wake events
|
||||
4. If score exceeds threshold (for smart strategy), triggers wake
|
||||
5. On group switch, `clearWakeScheduler()` cancels all timers
|
||||
6. In test mode (`BTERMINAL_TEST=1`), wake scheduler is disabled via `disableWakeScheduler()`
|
||||
6. In test mode (`AGOR_TEST=1`), wake scheduler is disabled via `disableWakeScheduler()`
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# BTerminal v2 — Implementation Phases
|
||||
# Agents Orchestrator v2 — Implementation Phases
|
||||
|
||||
See [architecture.md](architecture.md) for system architecture and [decisions.md](decisions.md) for design decisions.
|
||||
|
||||
|
|
@ -15,7 +15,7 @@ See [architecture.md](architecture.md) for system architecture and [decisions.md
|
|||
|
||||
### File Structure
|
||||
```
|
||||
bterminal-v2/
|
||||
agents-orchestrator/
|
||||
src-tauri/
|
||||
src/
|
||||
main.rs # Tauri app entry
|
||||
|
|
@ -217,12 +217,12 @@ bterminal-v2/
|
|||
- [x] install-v2.sh — build-from-source installer with dependency checks (Node.js 20+, Rust 1.77+, system libs)
|
||||
- Checks: WebKit2GTK, GTK3, GLib, libayatana-appindicator, librsvg, openssl, build-essential, pkg-config, curl, wget, FUSE
|
||||
- Prompts to install missing packages via apt
|
||||
- Builds with `npx tauri build`, installs binary as `bterminal-v2` in `~/.local/bin/`
|
||||
- Builds with `npx tauri build`, installs binary as `agents-orchestrator` in `~/.local/bin/`
|
||||
- Creates desktop entry and installs SVG icon
|
||||
- [x] Tauri bundle configuration — targets: `["deb", "appimage"]`, category: DeveloperTool
|
||||
- .deb depends: libwebkit2gtk-4.1-0, libgtk-3-0, libayatana-appindicator3-1
|
||||
- AppImage: bundleMediaFramework disabled
|
||||
- [x] Icons regenerated from bterminal.svg — RGBA PNGs (32x32, 128x128, 128x128@2x, 512x512, .ico)
|
||||
- [x] Icons regenerated from agor.svg — RGBA PNGs (32x32, 128x128, 128x128@2x, 512x512, .ico)
|
||||
- [x] GitHub Actions release workflow (`.github/workflows/release.yml`)
|
||||
- Triggered on `v*` tags, Ubuntu 22.04 runner
|
||||
- Caches Rust and npm dependencies
|
||||
|
|
@ -260,16 +260,16 @@ bterminal-v2/
|
|||
|
||||
## Multi-Machine Support (Phases A-D) [status: complete]
|
||||
|
||||
Architecture designed in [multi-machine.md](multi-machine.md). Implementation extends BTerminal to manage agents and terminals on remote machines over WebSocket.
|
||||
Architecture designed in [multi-machine.md](multi-machine.md). Implementation extends Agents Orchestrator to manage agents and terminals on remote machines over WebSocket.
|
||||
|
||||
### Phase A: Extract `bterminal-core` crate [status: complete]
|
||||
### Phase A: Extract `agor-core` crate [status: complete]
|
||||
- [x] Created Cargo workspace at level (Cargo.toml with members)
|
||||
- [x] Extracted PtyManager and SidecarManager into shared `bterminal-core` crate
|
||||
- [x] Created EventSink trait to abstract Tauri event emission (bterminal-core/src/event.rs)
|
||||
- [x] Extracted PtyManager and SidecarManager into shared `agor-core` crate
|
||||
- [x] Created EventSink trait to abstract Tauri event emission (agor-core/src/event.rs)
|
||||
- [x] TauriEventSink in src-tauri/src/event_sink.rs implements EventSink
|
||||
- [x] src-tauri pty.rs and sidecar.rs now thin re-exports from bterminal-core
|
||||
- [x] src-tauri pty.rs and sidecar.rs now thin re-exports from agor-core
|
||||
|
||||
### Phase B: Build `bterminal-relay` binary [status: complete]
|
||||
### Phase B: Build `agor-relay` binary [status: complete]
|
||||
- [x] WebSocket server using tokio-tungstenite with token auth
|
||||
- [x] CLI flags: --port, --token, --insecure (clap)
|
||||
- [x] Routes RelayCommand to PtyManager/SidecarManager, forwards RelayEvent over WebSocket
|
||||
|
|
@ -299,7 +299,7 @@ Architecture designed in [multi-machine.md](multi-machine.md). Implementation ex
|
|||
|
||||
### Remaining Work
|
||||
- [x] Reconnection logic with exponential backoff — implemented in remote.rs
|
||||
- [x] Relay command response propagation — implemented in bterminal-relay main.rs
|
||||
- [x] Relay command response propagation — implemented in agor-relay main.rs
|
||||
- [ ] Real-world relay testing (2 machines)
|
||||
- [ ] TLS/certificate pinning
|
||||
|
||||
|
|
@ -323,7 +323,7 @@ Architecture designed in [multi-machine.md](multi-machine.md). Implementation ex
|
|||
- [x] expandSkillPrompt(): reads skill content, injects as prompt with optional user args
|
||||
|
||||
### Extended AgentQueryOptions
|
||||
- [x] Rust struct (bterminal-core/src/sidecar.rs): setting_sources, system_prompt, model, claude_config_dir, additional_directories
|
||||
- [x] Rust struct (agor-core/src/sidecar.rs): setting_sources, system_prompt, model, claude_config_dir, additional_directories
|
||||
- [x] Sidecar JSON passthrough (both agent-runner.ts and agent-runner-deno.ts)
|
||||
- [x] SDK query() options: settingSources defaults to ['user', 'project'], systemPrompt, model, additionalDirectories
|
||||
- [x] CLAUDE_CONFIG_DIR env injection for multi-account support
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ Agent Orchestrator includes several production-readiness features that ensure re
|
|||
|
||||
## Sidecar Supervisor (Crash Recovery)
|
||||
|
||||
The `SidecarSupervisor` in `bterminal-core/src/supervisor.rs` automatically restarts crashed sidecar processes.
|
||||
The `SidecarSupervisor` in `agor-core/src/supervisor.rs` automatically restarts crashed sidecar processes.
|
||||
|
||||
### Behavior
|
||||
|
||||
|
|
@ -56,7 +56,7 @@ The sandbox is applied via `pre_exec()` on the child process command, before the
|
|||
|------|--------|--------|
|
||||
| Project CWD | Read/Write | Agent needs to read and modify project files |
|
||||
| `/tmp` | Read/Write | Temporary files during operation |
|
||||
| `~/.local/share/bterminal/` | Read/Write | SQLite databases (btmsg, sessions) |
|
||||
| `~/.local/share/agor/` | Read/Write | SQLite databases (btmsg, sessions) |
|
||||
| System library paths | Read-only | Node.js/Deno runtime dependencies |
|
||||
| `~/.claude/` or config dir | Read-only | Claude configuration and credentials |
|
||||
|
||||
|
|
@ -119,7 +119,7 @@ The plugin system allows extending Agent Orchestrator with custom commands and e
|
|||
|
||||
### Plugin Discovery
|
||||
|
||||
Plugins live in `~/.config/bterminal/plugins/`. Each plugin is a directory containing a `plugin.json` manifest:
|
||||
Plugins live in `~/.config/agor/plugins/`. Each plugin is a directory containing a `plugin.json` manifest:
|
||||
|
||||
```json
|
||||
{
|
||||
|
|
@ -290,10 +290,10 @@ A background tokio task runs `PRAGMA wal_checkpoint(TRUNCATE)` every 5 minutes o
|
|||
|
||||
## TLS Relay Support
|
||||
|
||||
The `bterminal-relay` binary supports TLS for encrypted WebSocket connections:
|
||||
The `agor-relay` binary supports TLS for encrypted WebSocket connections:
|
||||
|
||||
```bash
|
||||
bterminal-relay \
|
||||
agor-relay \
|
||||
--port 9750 \
|
||||
--token <secret> \
|
||||
--tls-cert /path/to/cert.pem \
|
||||
|
|
@ -308,7 +308,7 @@ Certificate pinning (comparing relay certificate fingerprints) is planned for v3
|
|||
|
||||
## OpenTelemetry Observability
|
||||
|
||||
The Rust backend supports optional OTLP trace export via the `BTERMINAL_OTLP_ENDPOINT` environment variable.
|
||||
The Rust backend supports optional OTLP trace export via the `AGOR_OTLP_ENDPOINT` environment variable.
|
||||
|
||||
### Backend (`telemetry.rs`)
|
||||
|
||||
|
|
@ -334,7 +334,7 @@ A pre-configured Tempo + Grafana stack lives in `docker/tempo/`:
|
|||
```bash
|
||||
cd docker/tempo && docker compose up -d
|
||||
# Grafana at http://localhost:9715
|
||||
# Set BTERMINAL_OTLP_ENDPOINT=http://localhost:4318 to enable export
|
||||
# Set AGOR_OTLP_ENDPOINT=http://localhost:4318 to enable export
|
||||
```
|
||||
|
||||
---
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
## Session: 2026-03-05
|
||||
|
||||
### Research Phase (complete)
|
||||
- [x] Analyzed current BTerminal v1 codebase (2092 lines Python, GTK3+VTE)
|
||||
- [x] Queried Memora — no existing BTerminal memories
|
||||
- [x] Analyzed current Agents Orchestrator v1 codebase (2092 lines Python, GTK3+VTE)
|
||||
- [x] Queried Memora — no existing Agents Orchestrator memories
|
||||
- [x] Researched Claude Agent SDK — found structured streaming, subagent tracking, hooks
|
||||
- [x] Researched Tauri + xterm.js ecosystem — found 4+ working projects
|
||||
- [x] Researched terminal latency benchmarks — xterm.js acceptable for AI output
|
||||
|
|
@ -114,7 +114,7 @@ Architecture decision: Initially used `claude` CLI with `--output-format stream-
|
|||
### Phase 6: Packaging + Distribution (2026-03-06)
|
||||
- [x] Created install-v2.sh — build-from-source installer with 6-step dependency check process
|
||||
- [x] Updated v2/src-tauri/tauri.conf.json: bundle targets ["deb", "appimage"]
|
||||
- [x] Regenerated all icons in v2/src-tauri/icons/ from bterminal.svg as RGBA PNGs
|
||||
- [x] Regenerated all icons in v2/src-tauri/icons/ from agor.svg as RGBA PNGs
|
||||
- [x] Created .github/workflows/release.yml — CI workflow triggered on v* tags
|
||||
- [x] Build verified: .deb (4.3 MB), AppImage (103 MB) both built successfully
|
||||
|
||||
|
|
@ -177,33 +177,33 @@ Architecture decision: Initially used `claude` CLI with `--output-format stream-
|
|||
- [x] getTotalCost() recursive helper, total cost shown in parent pane
|
||||
|
||||
#### TAURI_SIGNING_PRIVATE_KEY
|
||||
- [x] Set via `gh secret set` on DexterFromLab/BTerminal GitHub repo
|
||||
- [x] Set via `gh secret set` on DexterFromLab/Agents Orchestrator GitHub repo
|
||||
|
||||
### Session: 2026-03-06 (continued) — Multi-Machine Architecture Design
|
||||
|
||||
#### Multi-Machine Support Architecture
|
||||
- [x] Designed full multi-machine architecture in docs/multi-machine.md (303 lines)
|
||||
- [x] Three-layer model: BTerminal (controller) + bterminal-relay (remote binary) + unified frontend
|
||||
- [x] Three-layer model: Agents Orchestrator (controller) + agor-relay (remote binary) + unified frontend
|
||||
- [x] WebSocket NDJSON protocol: RelayCommand/RelayEvent envelope wrapping existing sidecar format
|
||||
- [x] Authentication: pre-shared token + TLS, rate limiting, lockout
|
||||
- [x] Autonomous relay model: agents keep running when controller disconnects
|
||||
- [x] Reconnection with exponential backoff (1s-30s), state_sync on reconnect
|
||||
- [x] 4-phase implementation plan: A (extract bterminal-core crate), B (relay binary), C (RemoteManager), D (frontend)
|
||||
- [x] 4-phase implementation plan: A (extract agor-core crate), B (relay binary), C (RemoteManager), D (frontend)
|
||||
- [x] Updated TODO.md and docs/task_plan.md to reference the design
|
||||
|
||||
### Session: 2026-03-06 (continued) — Multi-Machine Implementation (Phases A-D)
|
||||
|
||||
#### Phase A: bterminal-core crate extraction
|
||||
- [x] Created Cargo workspace at v2/ level (v2/Cargo.toml, workspace members: src-tauri, bterminal-core, bterminal-relay)
|
||||
- [x] Extracted PtyManager into v2/bterminal-core/src/pty.rs
|
||||
- [x] Extracted SidecarManager into v2/bterminal-core/src/sidecar.rs
|
||||
- [x] Created EventSink trait (v2/bterminal-core/src/event.rs) to abstract event emission
|
||||
#### Phase A: agor-core crate extraction
|
||||
- [x] Created Cargo workspace at v2/ level (v2/Cargo.toml, workspace members: src-tauri, agor-core, agor-relay)
|
||||
- [x] Extracted PtyManager into v2/agor-core/src/pty.rs
|
||||
- [x] Extracted SidecarManager into v2/agor-core/src/sidecar.rs
|
||||
- [x] Created EventSink trait (v2/agor-core/src/event.rs) to abstract event emission
|
||||
- [x] TauriEventSink (v2/src-tauri/src/event_sink.rs) implements EventSink for Tauri AppHandle
|
||||
- [x] src-tauri/src/pty.rs and sidecar.rs now thin re-export wrappers
|
||||
- [x] Cargo.lock moved from src-tauri/ to workspace root (v2/)
|
||||
|
||||
#### Phase B: bterminal-relay binary
|
||||
- [x] New Rust binary at v2/bterminal-relay/ with WebSocket server (tokio-tungstenite)
|
||||
#### Phase B: agor-relay binary
|
||||
- [x] New Rust binary at v2/agor-relay/ with WebSocket server (tokio-tungstenite)
|
||||
- [x] Token auth via Authorization: Bearer header on WebSocket upgrade
|
||||
- [x] CLI flags: --port (default 9750), --token (required), --insecure (allow ws://)
|
||||
- [x] Routes RelayCommand types (pty_create/write/resize/close, agent_query/stop, sidecar_restart, ping)
|
||||
|
|
@ -234,14 +234,14 @@ Architecture decision: Initially used `claude` CLI with `--output-format stream-
|
|||
- svelte-check: clean (0 errors)
|
||||
|
||||
#### New dependencies added
|
||||
- bterminal-core: serde, serde_json, log, portable-pty, uuid (extracted from src-tauri)
|
||||
- bterminal-relay: tokio, tokio-tungstenite, clap, env_logger, futures-util
|
||||
- agor-core: serde, serde_json, log, portable-pty, uuid (extracted from src-tauri)
|
||||
- agor-relay: tokio, tokio-tungstenite, clap, env_logger, futures-util
|
||||
- src-tauri: tokio-tungstenite, tokio, futures-util, uuid (added for RemoteManager)
|
||||
|
||||
### Session: 2026-03-06 (continued) — Relay Hardening & Reconnection
|
||||
|
||||
#### Relay Command Response Propagation
|
||||
- [x] Shared event channel between EventSink and command response sender (sink_tx clone in bterminal-relay)
|
||||
- [x] Shared event channel between EventSink and command response sender (sink_tx clone in agor-relay)
|
||||
- [x] send_error() helper function: all command failures now emit RelayEvent with commandId + error message instead of just logging
|
||||
- [x] ping command: now sends pong response via event channel (was a no-op)
|
||||
- [x] pty_create: returns pty_created event with session ID and commandId for correlation
|
||||
|
|
|
|||
|
|
@ -10,14 +10,14 @@
|
|||
- [x] Tool-aware output truncation (Bash 500, Read/Write 50, Glob/Grep 20, default 30 lines)
|
||||
- [x] Colors softened via `color-mix(in srgb, var(--ctp-*) 65%, var(--ctp-surface1) 35%)`
|
||||
- [x] MarkdownPane: container query wrapper, shared responsive padding variable
|
||||
- [x] catppuccin.css: `--bterminal-pane-padding-inline: clamp(0.75rem, 3.5cqi, 2rem)`
|
||||
- [x] catppuccin.css: `--agor-pane-padding-inline: clamp(0.75rem, 3.5cqi, 2rem)`
|
||||
- [x] 139/139 vitest passing, 0 new TypeScript errors
|
||||
- [ ] Visual verification in dev mode (pending)
|
||||
|
||||
### Session: 2026-03-06 (continued) — Sidecar Env Var Bug Fix
|
||||
|
||||
#### CLAUDE* Environment Variable Leak (critical fix)
|
||||
- [x] Diagnosed silent hang in agent sessions when BTerminal launched from Claude Code terminal
|
||||
- [x] Diagnosed silent hang in agent sessions when Agents Orchestrator launched from Claude Code terminal
|
||||
- [x] Root cause: Claude Code sets ~8 CLAUDE* env vars for nesting/sandbox detection
|
||||
- [x] Fixed both sidecar runners to filter out all keys starting with 'CLAUDE'
|
||||
|
||||
|
|
@ -154,7 +154,7 @@
|
|||
#### Phase 10: Dead Component Removal + Polish
|
||||
- [x] Deleted 7 dead v2 components (~1,836 lines): TilingGrid, PaneContainer, PaneHeader, SessionList, SshSessionList, SshDialog, SettingsDialog
|
||||
- [x] Removed empty directories: Layout/, Sidebar/, Settings/, SSH/
|
||||
- [x] Rewrote StatusBar for workspace store (group name, project count, "BTerminal v3")
|
||||
- [x] Rewrote StatusBar for workspace store (group name, project count, "Agents Orchestrator v3")
|
||||
- [x] Fixed subagent routing: project-scoped sessions skip layout pane (render in TeamAgentsPanel)
|
||||
- [x] Updated v3-task_plan.md to mark all 10 phases complete
|
||||
|
||||
|
|
@ -237,7 +237,7 @@
|
|||
- [x] App.svelte: restore on startup via getSetting()
|
||||
|
||||
#### Desktop Integration
|
||||
- [x] install-v2.sh: added `StartupWMClass=bterminal` to .desktop template
|
||||
- [x] install-v2.sh: added `StartupWMClass=agor` to .desktop template
|
||||
- [x] GNOME auto-move extension compatible
|
||||
|
||||
#### No-Implicit-Push Rule
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@
|
|||
- [x] Deleted `TilingGrid.svelte` (328 lines), `PaneContainer.svelte` (113 lines), `PaneHeader.svelte` (44 lines)
|
||||
- [x] Deleted `SessionList.svelte` (374 lines), `SshSessionList.svelte` (263 lines), `SshDialog.svelte` (281 lines), `SettingsDialog.svelte` (433 lines)
|
||||
- [x] Removed empty directories: Layout/, Sidebar/, Settings/, SSH/
|
||||
- [x] Rewrote StatusBar.svelte for workspace store (group name, project count, agent count, "BTerminal v3" label)
|
||||
- [x] Rewrote StatusBar.svelte for workspace store (group name, project count, agent count, "Agents Orchestrator v3" label)
|
||||
- [x] Fixed subagent routing in agent-dispatcher: project-scoped sessions skip layout pane creation (subagents render in TeamAgentsPanel instead)
|
||||
- [x] Updated v3-task_plan.md to mark all 10 phases complete
|
||||
|
||||
|
|
@ -389,7 +389,7 @@ All editor themes map to the same `--ctp-*` CSS custom property names (26 vars).
|
|||
|
||||
#### OTEL Telemetry Implementation
|
||||
- [x] Added 6 Rust deps: tracing, tracing-subscriber, opentelemetry 0.28, opentelemetry_sdk 0.28, opentelemetry-otlp 0.28, tracing-opentelemetry 0.29
|
||||
- [x] Created `v2/src-tauri/src/telemetry.rs` — TelemetryGuard, layer composition, OTLP export via BTERMINAL_OTLP_ENDPOINT env var
|
||||
- [x] Created `v2/src-tauri/src/telemetry.rs` — TelemetryGuard, layer composition, OTLP export via AGOR_OTLP_ENDPOINT env var
|
||||
- [x] Integrated into lib.rs: TelemetryGuard in AppState, init before Tauri builder
|
||||
- [x] Instrumented 10 Tauri commands with `#[tracing::instrument]`: pty_spawn, pty_kill, agent_query/stop/restart, remote_connect/disconnect/agent_query/agent_stop/pty_spawn
|
||||
- [x] Added `frontend_log` Tauri command for frontend→Rust tracing bridge
|
||||
|
|
@ -436,7 +436,7 @@ All editor themes map to the same `--ctp-*` CSS custom property names (26 vars).
|
|||
- [x] Removed tauri-plugin-log from Cargo.toml dependency
|
||||
|
||||
#### E2E Coverage Expansion (25 tests, single spec file)
|
||||
- [x] Consolidated 4 spec files into single bterminal.test.ts — Tauri creates one app session per spec file; after first spec completes, app closes and subsequent specs get "invalid session id"
|
||||
- [x] Consolidated 4 spec files into single agor.test.ts — Tauri creates one app session per spec file; after first spec completes, app closes and subsequent specs get "invalid session id"
|
||||
- [x] Added Workspace & Projects tests (8): project grid, project boxes, header with name, 3 project tabs, active highlight, tab switching, status bar counts
|
||||
- [x] Added Settings Panel tests (6): settings tab, sections, theme dropdown, dropdown open+options, group list, close button
|
||||
- [x] Added Keyboard Shortcuts tests (5): Ctrl+K command palette, Ctrl+, settings, Ctrl+B sidebar, Escape close, palette group list
|
||||
|
|
@ -810,7 +810,7 @@ Ran nemezis-audit on Rust backend. 0 verified exploitable findings, 10 recon tar
|
|||
- [x] Admin role (tier 0), channel messaging (create/list/send/history), mark-read, global feed
|
||||
|
||||
#### btmsg Rust Backend + Tauri Bridge
|
||||
- [x] Created btmsg.rs module — SQLite-backed messaging (shared DB: ~/.local/share/bterminal/btmsg.db)
|
||||
- [x] Created btmsg.rs module — SQLite-backed messaging (shared DB: ~/.local/share/agor/btmsg.db)
|
||||
- [x] 8+ Tauri commands: btmsg_inbox, btmsg_send, btmsg_read, btmsg_contacts, btmsg_feed, btmsg_channels, etc.
|
||||
- [x] CommsTab: sidebar chat interface with activity feed, DMs, channels (Ctrl+M)
|
||||
|
||||
|
|
@ -827,7 +827,7 @@ Ran nemezis-audit on Rust backend. 0 verified exploitable findings, 10 recon tar
|
|||
|
||||
#### BTMSG_AGENT_ID Environment Passthrough (5-layer chain)
|
||||
- [x] agent-bridge.ts: added extra_env?: Record<string,string> to AgentQueryOptions
|
||||
- [x] bterminal-core/sidecar.rs: added extra_env: HashMap<String,String> with #[serde(default)]
|
||||
- [x] agor-core/sidecar.rs: added extra_env: HashMap<String,String> with #[serde(default)]
|
||||
- [x] claude-runner.ts: extraEnv merged into cleanEnv after provider var stripping
|
||||
- [x] codex-runner.ts: same extraEnv pattern
|
||||
- [x] AgentSession injects { BTMSG_AGENT_ID: project.id } for agent projects
|
||||
|
|
@ -922,7 +922,7 @@ Reviewed and integrated Dexter's multi-agent orchestration branch (dexter_change
|
|||
#### Test Counts
|
||||
- Vitest: 327 passed (was 286, +41)
|
||||
- Cargo src-tauri: 64 passed (was 49, +15)
|
||||
- Cargo bterminal-core: 8 passed (was 0, +8)
|
||||
- Cargo agor-core: 8 passed (was 0, +8)
|
||||
|
||||
### E2E Testing Engine — Phase A (2026-03-12)
|
||||
|
||||
|
|
@ -945,8 +945,8 @@ Reviewed and integrated Dexter's multi-agent orchestration branch (dexter_change
|
|||
|
||||
#### WebDriverIO Config Improvements
|
||||
- [x] TCP readiness probe replaces blind 2s sleep for tauri-driver startup
|
||||
- [x] BTERMINAL_TEST=1 env var passed to Tauri app via capabilities
|
||||
- [x] Optional BTERMINAL_TEST_DATA_DIR / BTERMINAL_TEST_CONFIG_DIR passthrough
|
||||
- [x] AGOR_TEST=1 env var passed to Tauri app via capabilities
|
||||
- [x] Optional AGOR_TEST_DATA_DIR / AGOR_TEST_CONFIG_DIR passthrough
|
||||
|
||||
#### Test Infrastructure Files
|
||||
- [x] `v2/tests/e2e/fixtures.ts` — isolated test fixture generator (temp dirs, git repos, groups.json)
|
||||
|
|
@ -1014,7 +1014,7 @@ Reviewed and integrated Dexter's multi-agent orchestration branch (dexter_change
|
|||
Implemented ALL 13 features from tribunal assessment in 3 parallel waves (11 sub-agents total). 60+ files changed, 3861 insertions.
|
||||
|
||||
#### Wave 1: Core Infrastructure (3 agents)
|
||||
- [x] **Sidecar supervisor** — `bterminal-core/src/supervisor.rs`: SidecarSupervisor with exponential backoff (1s-30s, 5 retries), SidecarHealth enum, 5min stability window, 17 tests
|
||||
- [x] **Sidecar supervisor** — `agor-core/src/supervisor.rs`: SidecarSupervisor with exponential backoff (1s-30s, 5 retries), SidecarHealth enum, 5min stability window, 17 tests
|
||||
- [x] **FTS5 search** — rusqlite `bundled-full`, SearchDb with 3 FTS5 virtual tables, SearchOverlay.svelte (Ctrl+Shift+F), search-bridge.ts
|
||||
- [x] **Secrets management** — `keyring` crate (linux-native/libsecret), SecretsManager, secrets-bridge.ts, SettingsTab section
|
||||
|
||||
|
|
@ -1023,7 +1023,7 @@ Implemented ALL 13 features from tribunal assessment in 3 parallel waves (11 sub
|
|||
- [x] **Keyboard-first UX** — Alt+1-5 jump, Ctrl+H/L vi-nav, Ctrl+Shift+1-9 tabs, Ctrl+J terminal, CommandPalette rewrite (18+ cmds, 6 categories)
|
||||
- [x] **Agent health monitoring** — heartbeats + dead_letter_queue tables, 15s poll, ProjectHeader heart indicator, StatusBar badge
|
||||
- [x] **Plugin system** — plugins.rs discovery, plugin-host.ts sandboxed runtime, plugins.svelte.ts store, example plugin
|
||||
- [x] **Landlock sandbox** — bterminal-core/src/sandbox.rs, SandboxConfig, pre_exec() integration, per-project toggle
|
||||
- [x] **Landlock sandbox** — agor-core/src/sandbox.rs, SandboxConfig, pre_exec() integration, per-project toggle
|
||||
|
||||
#### Wave 3: Integration (3 agents)
|
||||
- [x] **Error classification** — error-classifier.ts (6 types, retry logic), 20 tests
|
||||
|
|
@ -1053,7 +1053,7 @@ Executed tribunal-recommended hybrid S-2/S-1 hardening sprint. Fixed 3 security/
|
|||
- [x] Added "Multi-Agent Delegation" section to Manager workflow in `agent-prompts.ts`
|
||||
- [x] Inject `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1` env var for Manager agents in `AgentSession.svelte`
|
||||
|
||||
#### TLS for bterminal-relay
|
||||
#### TLS for agor-relay
|
||||
- [x] Added `--tls-cert` and `--tls-key` optional CLI args to relay binary
|
||||
- [x] `build_tls_acceptor()` using `native_tls::Identity::from_pkcs8`
|
||||
- [x] Refactored to generic `accept_ws_with_auth<S>` and `run_ws_session<S>` (avoids code duplication)
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ Full codebase exploration of 13+ files revealed coupling at 4 severity levels:
|
|||
| File | Coupling | Impact |
|
||||
|------|----------|--------|
|
||||
| `sidecar/agent-runner.ts` | Imports `@anthropic-ai/claude-agent-sdk`, calls `query()`, hardcoded `findClaudeCli()` | Entire sidecar is Claude-only. Must become `claude-runner.ts`. Other providers get own runners. |
|
||||
| `bterminal-core/src/sidecar.rs` | `AgentQueryOptions` struct has no `provider` field. `SidecarCommand` hardcodes `agent-runner.mjs` path. | Must add `provider: String` field. Runner selection must be provider-based. |
|
||||
| `agor-core/src/sidecar.rs` | `AgentQueryOptions` struct has no `provider` field. `SidecarCommand` hardcodes `agent-runner.mjs` path. | Must add `provider: String` field. Runner selection must be provider-based. |
|
||||
| `src/lib/adapters/sdk-messages.ts` | `parseMessage()` assumes Claude SDK JSON format (assistant/user/result types, subagent tool names like `dispatch_agent`) | Must become `claude-messages.ts`. Other providers get own parsers. Registry selects by provider. |
|
||||
|
||||
#### HIGH (TS mirror types, provider-specific commands)
|
||||
|
|
@ -37,7 +37,7 @@ Full codebase exploration of 13+ files revealed coupling at 4 severity levels:
|
|||
| `src/lib/stores/agents.svelte.ts` | AgentMessage type is already generic (text, tool_call, tool_result). No Claude-specific logic. | No changes needed. Common AgentMessage type stays. |
|
||||
| `src/lib/stores/health.svelte.ts` | Tracks activity/cost/context per project. Provider-agnostic. | No changes needed. |
|
||||
| `src/lib/stores/conflicts.svelte.ts` | File overlap detection. Provider-agnostic (operates on tool_call file paths). | No changes needed. |
|
||||
| `bterminal-relay/` | Forwards AgentQueryOptions as-is. No provider logic. | No changes needed (will forward `provider` field transparently). |
|
||||
| `agor-relay/` | Forwards AgentQueryOptions as-is. No provider logic. | No changes needed (will forward `provider` field transparently). |
|
||||
|
||||
### Key Design Insights
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ Multi-provider agent support (Claude Code, Codex CLI, Ollama) via adapter patter
|
|||
| 1.3 | Create Claude provider meta | NEW: `src/lib/providers/claude.ts` | done |
|
||||
| 1.4 | Rename sdk-messages.ts → claude-messages.ts | RENAME + update imports | done |
|
||||
| 1.5 | Create message adapter registry | NEW: `src/lib/adapters/message-adapters.ts` | done |
|
||||
| 1.6 | Update Rust AgentQueryOptions | MOD: `bterminal-core/src/sidecar.rs` | done |
|
||||
| 1.6 | Update Rust AgentQueryOptions | MOD: `agor-core/src/sidecar.rs` | done |
|
||||
| 1.7 | Update agent-bridge.ts options shape | MOD: `src/lib/adapters/agent-bridge.ts` | done |
|
||||
| 1.8 | Rename agent-runner.ts → claude-runner.ts | RENAME + update build script | done |
|
||||
| 1.9 | Add provider field to ProjectConfig | MOD: `src/lib/types/groups.ts` | done |
|
||||
|
|
@ -54,9 +54,9 @@ Multi-provider agent support (Claude Code, Codex CLI, Ollama) via adapter patter
|
|||
|
||||
| # | Task | Files | Status |
|
||||
|---|------|-------|--------|
|
||||
| 3.1 | SidecarManager provider-based runner selection | MOD: `bterminal-core/src/sidecar.rs` | done |
|
||||
| 3.2 | Per-provider runner discovery | MOD: `bterminal-core/src/sidecar.rs` | done |
|
||||
| 3.3 | Provider-specific env var stripping | MOD: `bterminal-core/src/sidecar.rs` | done |
|
||||
| 3.1 | SidecarManager provider-based runner selection | MOD: `agor-core/src/sidecar.rs` | done |
|
||||
| 3.2 | Per-provider runner discovery | MOD: `agor-core/src/sidecar.rs` | done |
|
||||
| 3.3 | Provider-specific env var stripping | MOD: `agor-core/src/sidecar.rs` | done |
|
||||
|
||||
## Type System
|
||||
|
||||
|
|
@ -123,7 +123,7 @@ AgentPane.svelte (renders AgentMessage, capability-driven)
|
|||
- `claude-bridge.ts` → `provider-bridge.ts` (genericized)
|
||||
|
||||
### Modified Files (Phase 1)
|
||||
- `bterminal-core/src/sidecar.rs` — AgentQueryOptions struct
|
||||
- `agor-core/src/sidecar.rs` — AgentQueryOptions struct
|
||||
- `src-tauri/src/lib.rs` — command handlers
|
||||
- `src/lib/adapters/agent-bridge.ts` — options interface
|
||||
- `src/lib/agent-dispatcher.ts` — provider routing
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
## Mission Control — Multi-Project AI Agent Orchestration
|
||||
|
||||
BTerminal v3.0 is a ground-up redesign of the terminal interface, built for managing multiple AI agent sessions across multiple projects simultaneously. The Mission Control dashboard replaces the single-pane terminal with a full orchestration workspace.
|
||||
Agents Orchestrator v3.0 is a ground-up redesign of the terminal interface, built for managing multiple AI agent sessions across multiple projects simultaneously. The Mission Control dashboard replaces the single-pane terminal with a full orchestration workspace.
|
||||
|
||||
### What's New
|
||||
|
||||
|
|
@ -62,7 +62,7 @@ BTerminal v3.0 is a ground-up redesign of the terminal interface, built for mana
|
|||
- Landlock sandbox: kernel 6.2+ filesystem restriction for sidecar processes
|
||||
- Plugin sandbox: 13 shadowed globals, strict mode, frozen API, permission-gated
|
||||
- Secrets management: system keyring (libsecret), no plaintext fallback
|
||||
- TLS support for bterminal-relay (optional `--tls-cert`/`--tls-key`)
|
||||
- TLS support for agor-relay (optional `--tls-cert`/`--tls-key`)
|
||||
- Sidecar environment stripping: dual-layer (Rust + JS) credential isolation
|
||||
- Audit logging: agent events, task changes, wake events, prompt injections
|
||||
|
||||
|
|
@ -74,7 +74,7 @@ BTerminal v3.0 is a ground-up redesign of the terminal interface, built for mana
|
|||
|
||||
### Multi-Machine (Early Access)
|
||||
|
||||
bterminal-relay enables running agent sessions across multiple Linux machines via WebSocket. TLS encryption is supported. This feature is architecturally complete but not yet surfaced in the v3 UI — available for advanced users via the relay binary and bridges.
|
||||
agor-relay enables running agent sessions across multiple Linux machines via WebSocket. TLS encryption is supported. This feature is architecturally complete but not yet surfaced in the v3 UI — available for advanced users via the relay binary and bridges.
|
||||
|
||||
**v3.1 roadmap:** Certificate pinning, UI integration, real-world multi-machine testing.
|
||||
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ Deno is preferred because it has faster cold-start time (~50ms vs ~150ms for Nod
|
|||
|
||||
### Crash Recovery (SidecarSupervisor)
|
||||
|
||||
The `SidecarSupervisor` in `bterminal-core/src/supervisor.rs` provides automatic crash recovery:
|
||||
The `SidecarSupervisor` in `agor-core/src/supervisor.rs` provides automatic crash recovery:
|
||||
|
||||
- Monitors the sidecar child process for unexpected exits
|
||||
- On crash: waits with exponential backoff (1s → 2s → 4s → 8s → 16s → 30s cap)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue