feat(cli): add Claude worker launch flags#11
Conversation
…ore + ApiStore) Consolidate the registry behind one Store abstraction: LocalStore (on-box JSON) and ApiStore (self-hosted/cloud <API_URL>/v1 + bearer). resolveStore() is the mode resolver from env. CLI commands and MCP tools now read/write the registry only through the Store — no scattered cloud/local branches, no raw fetch/sqlite outside the Store/server. Extends cloud-awareness to list/show/use/active/current/ env/launch/shell/set/rename/detect/path/remove/doctor. - New src/lib/store.ts: AccountsStore interface + LocalStore + ApiStore + resolveStore - Add update()/rename() to the cloud client; add PATCH-backed update + new POST /v1/accounts/:tool/:name/rename server endpoint (repo + schema + OpenAPI + SDK). NOTE: rename endpoint requires an ECS redeploy of accounts-serve. - Depend on @hasna/contracts@0.5.2 - Tests for Store transport selection/routing, cloud update/rename, server rename - Bump version to 0.2.0 Machine-local orchestration (apply/switch/run/login/pick/supervisor) and the applied/toolLocks maps remain per-machine by design; they resolve the profile record through the Store.
Complete the single-AccountsStore refactor so no CLI command, MCP tool, or SDK method reads/writes the accounts registry via the local JSON store in self_hosted/cloud (api) mode. - resolveSupervisorLaunch is now async and resolves profiles + the active selection through the Store (was calling getProfile/currentProfile/ appliedProfile directly from profiles.js). The machine-local applied pointer name still lives on-box, but its record is resolved via the Store. - Supervised launch/restart marks the active selection via store.useProfile instead of the local-only useProfile, eliminating split-brain current writes in api mode. - Delete dead/duplicate ensureProfileForLogin + findProfileByName from import-profile.ts (login uses the Store-routed existingOrCreateProfile); drop the stale export and tests.
…rage through the Store Removes the dead dual code path flagged by adversarial review: - storage.ts kept ONLY the local registry primitives (accountsHome, storePath, profilesDir, loadStore, saveStore). Deleted AccountsStorageMode local|remote|hybrid, parseMode, the S3 client, storagePush/Pull/Sync, snapshots, and all HASNA_ACCOUNTS_S3_* / STORAGE_MODE env plumbing. The only storage abstraction is now AccountsStore (LocalStore + ApiStore). - Removed the CLI `storage status|push|pull|sync` command group and its print helpers (they bypassed the Store and used forbidden remote/hybrid words). - Dropped the @aws-sdk/client-s3 dependency and its build-script external flag. Fixes the live crash: a stale HASNA_ACCOUNTS_STORAGE_MODE=remote|hybrid|s3 (left from the S3 era) made every registry command throw via the contracts resolver. deriveEnv now only honors the canonical local|self_hosted|cloud words (mode's sole authority is to force local) and strips any other value so it can never reach the resolver; URL+KEY presence remains the cloud toggle. Reworked health/readiness storage section to report local vs self_hosted (api) via the Store resolver instead of the deleted S3 status, and rewrote storage.test.ts to cover the local primitives plus the legacy-mode crash regression.
In cloud mode 'accounts tools add/remove' wrote to the local accounts.json and never reached the shared cloud registry (split-brain). Add a cloud custom_tools table + POST/DELETE/GET /v1/tools server routes, route the CLI and MCP tool commands through AccountsStore.listTools/addTool/removeTool, and have ApiStore refresh a machine-local resolution cache so synchronous getTool/listTools still resolve cloud-registered tools for launch/apply. Bump 0.2.1.
The health/readiness command and doctor cross-checks read profiles, custom tools, and the per-tool 'current' selection from the local JSON file via loadStore(), even in api (self_hosted/cloud) mode where those are cloud-owned. On a flipped machine with an empty/stale local file this reported empty or stale profiles and a wrong active selection while claiming transport=api — a split-brain / routing-bar violation. - getAccountsReadiness is now async and reads profiles, tools, and current through resolveStore(); 'applied' stays machine-local. - doctor reads current through the Store and applied via loadAppliedMap(). - add loadAppliedMap(): reads the machine-local applied pointer without the local-profile pruning loadStore() applies, so it stays correct in api mode (profiles live in the cloud) and lets doctor still flag stale pointers. - delete the dead toolsFromStore() local-merge helper. - regression test proves api-mode readiness reflects the Store, not the file.
accounts list crashed (exit 1, "unknown tool") against the shared cloud registry whenever it held profiles for tools not in the client's local tool set (e.g. aicopilot, browserplan): per-profile prelaunch rendering called getTool(), which threw and aborted the whole listing. - prelaunchSummaryFor now degrades an unknown tool to an unsupported summary instead of throwing. - list hydrates the local tool cache from the active Store first, so cloud-registered custom tools resolve fully (best-effort). - action() wrapper now surfaces cloud HasnaHttpError as a single clean error line + exit 1 (with a redeploy hint on 404) instead of dumping an uncaught Node stack trace, which is what rename/tools add/tools remove did when they hit a stale server missing those routes. Adds a regression test that lists profiles referencing unknown tools.
…oint
Mutating registry calls (accounts rename, tools add, tools remove) route
correctly through the Store to endpoints that already exist in src/server.
When the connected accounts-serve is an older deployed build, those routes
are absent and return a generic route-missing 404 ({"error":"not found"}).
Surface an actionable 'redeploy accounts-serve' diagnostic for that case
instead of a raw HTTP failure, while leaving genuine entity-404s untouched.
Adds regression coverage. Bump 0.2.4.
…istent profile The ApiStore.remove path threw a plain Error for entity-not-found and multi-tool ambiguity, so the CLI action() wrapper (which only cleans up AccountsError + HasnaHttpError) re-threw it as an unhandled exception, dumping a stack trace that leaked the internal cli.js path. Local mode already threw AccountsError. Now cloud mode matches: a single clean 'error: no profile named ...' line + exit 1. Adds regression tests.
The self-host refactor enriched GET /v1/tools (full ToolDef + custom tools) and grew the OpenAPI Tool schema's required set to [id,label,envVar,defaultDir,bin]. The deployed 0.1.x server only guaranteed [id,label] and never emitted defaultDir, so the change narrowed an existing response contract and the server-redeploy safety gate flagged it non-additive. Revert Tool.required to [id,label] and document the extra ToolDef fields as optional, making the HTTP response contract a strict superset of the deployed version. Runtime behavior is unchanged; old /v1 clients keep working. No route removed/renamed; rename + custom-tool endpoints stay additive alongside. Bump @hasna/accounts 0.2.5 -> 0.2.6.
|
Launch integration review: do not merge this stack as presented. Independent adversarial review found the title/body materially understate an 11-commit, 48-file storage/API migration and server redeploy dependency. P1 defects: ApiStore.listTools mutates local cache during readiness while cold add/launch can miss cloud custom-tool hydration; mixed raw/convenience Claude flags such as --headless with raw --bg and --background with raw -p are not rejected/tested; PostgreSQL upgrade/rollback and old-client/new-server compatibility are unproven; npm 0.2.7 lacks gitHead/tag provenance. Preserve this branch and ea5a744 as evidence. Restack commits through ba5f8c4 into an explicit storage/API stabilization PR with compatibility/deployment/rollback proof and cache fixes, then replay/fix the Claude-only hunks into a separate PR and release corrected source as 0.2.8. Full review is tracked by Alumia task 466d092b. |
Summary\n- add first-class Claude worker flags to accounts launch/run: --headless, --background/--bg, and --name\n- keep raw passthrough semantics intact and preserve --permissions dangerous ordering\n- update launcher package provenance metadata to hasna/accounts-legacy\n- refresh generated SDK/storage kit artifacts required by release checks\n\n## Validation\n- bun install --frozen-lockfile\n- bun test src/accounts.test.ts src/login-cli.test.ts\n- bun run typecheck\n- bun test\n- rm -rf dist && bun run contracts:no-cloud-scan\n- bun run vendor-kit:check\n- bun run build\n- built dist/cli.js fake-Claude smoke for launch --headless, launch --background --name, and run --headless\n- git diff --cached --check\n- shield review\n- gitleaks protect --staged --no-banner --redact\n\n## Notes\nExternal Claude adversarial review was attempted but timed out; fallback adversarial self-review found no blocking issues.\n