diff --git a/.agents/skills/add-api-endpoint/SKILL.md b/.agents/skills/add-api-endpoint/SKILL.md index c4ca76e0..0b87b3e0 100644 --- a/.agents/skills/add-api-endpoint/SKILL.md +++ b/.agents/skills/add-api-endpoint/SKILL.md @@ -1,20 +1,20 @@ --- name: add-api-endpoint -description: Add or modify an OpenBot Hono HTTP route or ConnectRPC method while preserving authentication, provider boundaries, Web-standard request handling, generated contracts, and focused tests. +description: Add or modify a Dispatch Hono HTTP route or ConnectRPC method while preserving authentication, provider boundaries, Web-standard request handling, generated contracts, and focused tests. metadata: - author: openbot + author: dispatch version: "1.0.0" argument-hint: --- # Add Or Modify An API Endpoint -OpenBot uses ConnectRPC for authenticated control operations and Hono for protocol-native HTTP routes. Keep handlers thin and portable across the local Node server and Vercel Functions. +Dispatch uses ConnectRPC for authenticated control operations and Hono for protocol-native HTTP routes. Keep handlers thin and portable across the local Node server and Vercel Functions. ## Process 1. Choose the surface: - - ConnectRPC: control-plane methods used by OpenBot clients. + - ConnectRPC: control-plane methods used by Dispatch clients. - Hono: setup unlock, health, ChatKit compatibility, or signed Tilde webhooks/tools. 2. For ConnectRPC, edit the owning proto, run `pnpm contracts:generate`, then implement the method in `apps/control-service` or `apps/computer-service`. 3. For Hono, edit `apps/control-service/src/app.ts` and keep Web-standard request handling. @@ -22,7 +22,7 @@ OpenBot uses ConnectRPC for authenticated control operations and Hono for protoc 5. Apply the existing authorization mechanism before business work. 6. Delegate external behavior to the owning provider package's `src/core.ts` or `src/core/index.ts` contract and matching adapter. Keep route code provider-neutral. 7. Preserve `Request.signal` through `ProviderCallContext`. -8. When an OpenBot client consumes the endpoint, add or extend the grouped contract and client call in `packages/client-runtime` in the same change. Web and Electron consume it from there; they never declare the request, response, or event shape themselves. +8. When a Dispatch client consumes the endpoint, add or extend the grouped contract and client call in `packages/client-runtime` in the same change. Web and Electron consume it from there; they never declare the request, response, or event shape themselves. 9. Add focused tests beside the server surface. Test status/code, response shape, authorization, and the owning provider call. ## Authentication And Scope diff --git a/.agents/skills/add-db-changes/SKILL.md b/.agents/skills/add-db-changes/SKILL.md index b024bf54..3b2c00fa 100644 --- a/.agents/skills/add-db-changes/SKILL.md +++ b/.agents/skills/add-db-changes/SKILL.md @@ -1,15 +1,15 @@ --- name: add-db-changes -description: Add or alter OpenBot's Drizzle schema, SQLite-compatible migration statements, libSQL/Turso persistence code, and migration tests without moving Tilde-owned data or secrets into the control database. +description: Add or alter Dispatch's Drizzle schema, SQLite-compatible migration statements, libSQL/Turso persistence code, and migration tests without moving Tilde-owned data or secrets into the control database. metadata: - author: openbot + author: dispatch version: "1.0.0" argument-hint: --- # Database Schema And Query Changes -OpenBot uses Drizzle over local SQLite or remote libSQL/Turso. The database stores installation, onboarding, sandbox lease, and deployment checkpoint state only. Tilde owns agents, chats, tools, skills, and memory. `EnvProvider` owns secrets. +Dispatch uses Drizzle over local SQLite or remote libSQL/Turso. The database stores installation, onboarding, sandbox lease, and deployment checkpoint state only. Tilde owns agents, chats, tools, skills, and memory. `EnvProvider` owns secrets. The source of truth is: @@ -42,8 +42,8 @@ packages/db/src/migrations.test.ts ## Tests ```bash -pnpm --filter @tryopenbot/db test -pnpm --filter @tryopenbot/control-service test +pnpm --filter @trytilde/dispatch-db test +pnpm --filter @trytilde/dispatch-control-service test pnpm check ``` diff --git a/.agents/skills/create-or-update-agent/SKILL.md b/.agents/skills/create-or-update-agent/SKILL.md index 2492f779..deeb7c9a 100644 --- a/.agents/skills/create-or-update-agent/SKILL.md +++ b/.agents/skills/create-or-update-agent/SKILL.md @@ -1,6 +1,6 @@ --- name: create-or-update-agent -description: Create or modify the full primary OpenBot agent or one of its full subagents under configuration/agent, including its ChatKit endpoint, instructions, instrumentation, tools, skills, library code, and sandbox workspace seed. Use whenever adding an agent, changing an agent's filesystem layout or entrypoint, or updating agent build and deployment discovery. +description: Create or modify the full primary Dispatch agent or one of its full subagents under configuration/agent, including its ChatKit endpoint, instructions, instrumentation, tools, skills, library code, and sandbox workspace seed. Use whenever adding an agent, changing an agent's filesystem layout or entrypoint, or updating agent build and deployment discovery. --- # Create Or Update Agent @@ -34,7 +34,7 @@ configuration/ ``` - The primary path has the stable ID `factory`. Derive each subagent ID from its directory name using lowercase kebab-case matching `^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$`. -- To create a subagent interactively, run `pnpm openbot new-agent` and enter its display name. From an agent or other non-interactive shell, run `pnpm openbot new-agent ""`. The CLI loads `configuration/templates/agent/**/*.hbs`, derives the ID, strips each `.hbs` suffix, materializes the complete full tree below `configuration/agent/subagents/`, then invokes idempotent development provisioning for every authored agent. Customize the generated files afterward. Do not hand-copy another agent directory or duplicate remote provisioning in the command. +- To create a subagent interactively, run `pnpm tilde new-agent` and enter its display name. From an agent or other non-interactive shell, run `pnpm tilde new-agent ""`. The CLI loads `configuration/templates/agent/**/*.hbs`, derives the ID, strips each `.hbs` suffix, materializes the complete full tree below `configuration/agent/subagents/`, then invokes idempotent development provisioning for every authored agent. Customize the generated files afterward. Do not hand-copy another agent directory or duplicate remote provisioning in the command. - Treat `configuration/templates/agent/` as fork-owned defaults for future agents. Change it when all newly created agents need different SDK imports, environment variables, tools, skills, instructions, or workspace seeds. Template edits never rewrite existing agents. - Never import provider packages or `configuration/index.ts` from authored agents. Integrate model, MCP, skills, Composio, and other vendor SDKs directly in agent code so provider abstractions do not constrain agent development. - Require `agent.ts` and `instructions.ts`. @@ -43,8 +43,8 @@ configuration/ - Keep reusable import-only TypeScript in `lib/`. - Default-export one Vercel AI SDK tool from each file in `tools/`. - Require the scaffolded computer tools `await_shell.ts`, `bash.ts`, `copy_from_computer.ts`, `copy_to_computer.ts`, `read_file.ts`, `write_file.ts`, `glob.ts`, `grep.ts`, and `screenshot.ts`. Import them explicitly in `agent.ts` under matching tool names. -- Keep each authored computer-tool file as a thin default export from `@tryopenbot/computer-tools`, passing the path-derived agent ID as a fixed option. Shared implementations and Zod schemas belong to that non-provider runtime utility package, not in each agent and not in the proto package. Never call Microsandbox, Vercel Sandbox, `fetch`, or an untyped computer endpoint from an agent tool. -- Authenticate the typed client with the SOPS-installed `OPENBOT_COMPUTER_SERVICE_API_KEY`. Do not generate, derive, return, log, or persist a second agent-local computer credential. +- Keep each authored computer-tool file as a thin default export from `@trytilde/dispatch-computer-tools`, passing the path-derived agent ID as a fixed option. Shared implementations and Zod schemas belong to that non-provider runtime utility package, not in each agent and not in the proto package. Never call Microsandbox, Vercel Sandbox, `fetch`, or an untyped computer endpoint from an agent tool. +- Authenticate the typed client with the SOPS-installed `DISPATCH_COMPUTER_SERVICE_API_KEY`. Do not generate, derive, return, log, or persist a second agent-local computer credential. - Store specification-conformant skill Markdown files or skill folders under `skills/`. - Preserve the scaffolded `skills/create-agent/SKILL.md`; it teaches runtime agents to use the non-interactive `new-agent` command from a writable source checkout and to leave deployment explicit. - Keep skills and sandbox workspace seeds inside their owning agent directory. Never create, read, or migrate content to global `configuration/skills/` or `configuration/sandbox/` directories; those paths are unsupported. @@ -53,7 +53,7 @@ configuration/ ## Instrument startup -Use `defineInstrumentation({ setup })` from `@tryopenbot/configuration/instrumentation`. Keep `configuration/instrumentation.ts` installation-wide and `instrumentation.ts` in either full agent directory agent-specific. Both are optional at runtime; an empty `setup` function is valid. +Use `defineInstrumentation({ setup })` from `@trytilde/dispatch-configuration/instrumentation`. Keep `configuration/instrumentation.ts` installation-wide and `instrumentation.ts` in either full agent directory agent-specific. Both are optional at runtime; an empty `setup` function is valid. Run global instrumentation first, agent instrumentation second, and import `agent.ts` only afterward. Supply the path-derived `agentName`. Instrumentation is a server startup hook, not an agent tool or request hook. @@ -61,9 +61,9 @@ Run global instrumentation first, agent instrumentation second, and import `agen Treat each `agent.ts` as an independently buildable agent-service entrypoint. Keep local development's combined server and production's separate agent artifacts aligned. Vercel builds must remain concurrent across agents. -All agents share one OpenBot Computer, filesystem, and process identity. If `sandbox/workspace/**` contains files, deployment seeds them once into `/workspace/`. Commands and relative paths default there, but agents can use absolute paths, inspect sibling directories, and administer the shared machine. Treat the agent directory as an organizational default, never as a security boundary. +All agents share one Dispatch Computer, filesystem, and process identity. If `sandbox/workspace/**` contains files, deployment seeds them once into `/workspace/`. Commands and relative paths default there, but agents can use absolute paths, inspect sibling directories, and administer the shared machine. Treat the agent directory as an organizational default, never as a security boundary. -Keep the authored directory name `sandbox/` and Eve-compatible tool filenames only because OpenBot follows Eve's project layout where possible. Use Computer for APIs, environment variables, classes, and prose about the runtime. Computer-service owns agent-ID validation, default-directory selection, and background-job ownership; callers must not send a username or treat the ID as authorization for filesystem paths. +Keep the authored directory name `sandbox/` and Eve-compatible tool filenames only because Dispatch follows Eve's project layout where possible. Use Computer for APIs, environment variables, classes, and prose about the runtime. Computer-service owns agent-ID validation, default-directory selection, and background-job ownership; callers must not send a username or treat the ID as authorization for filesystem paths. Create `/workspace/` only when the authored `sandbox/workspace/**` is populated, and seed it only once. Never overwrite an existing deployed directory during an ordinary agent deployment. State clearly when changing seed files that already-deployed agents will not receive those changes without explicit future reconciliation or computer replacement. Reject symlinks in agent source and workspace seeds. @@ -71,14 +71,14 @@ Scaffold `sandbox/workspace/.profile`. Bash tools run `bash -lc` with `HOME=/wor ## Initialize examples -Keep `openbot init` seeding the default Handlebars files into `configuration/templates/agent/` without overwriting fork edits, then using them to generate the full primary Factory agent. `openbot new-agent` uses the same template for full subagents. The initial agent includes: +Keep `tilde init` seeding the default Handlebars files into `configuration/templates/agent/` without overwriting fork edits, then using them to generate the full primary Factory agent. `tilde new-agent` uses the same template for full subagents. The initial agent includes: - `agent.ts` importing `instructions.ts` - an empty global and agent instrumentation hook -- all standard computer tools; factory-only skills (create-agent, test-agent, deploy-agent, develop-openbot) live in `configuration/templates/factory/` and render into the primary agent only +- all standard computer tools; factory-only skills (create-agent, test-agent, deploy-agent, develop-dispatch) live in `configuration/templates/factory/` and render into the primary agent only - a sandbox workspace seed with `.profile` -Generate source files from the fork-owned Handlebars template through `@tryopenbot/utilities`; do not embed whole generated files in TypeScript strings. The CLI's packaged assets only seed a missing template during init. +Generate source files from the fork-owned Handlebars template through `@trytilde/dispatch-utilities`; do not embed whole generated files in TypeScript strings. The CLI's packaged assets only seed a missing template during init. ## Verify diff --git a/.agents/skills/create-or-update-agent/agents/openai.yaml b/.agents/skills/create-or-update-agent/agents/openai.yaml index e1b833c1..b4eeb9b1 100644 --- a/.agents/skills/create-or-update-agent/agents/openai.yaml +++ b/.agents/skills/create-or-update-agent/agents/openai.yaml @@ -1,4 +1,4 @@ interface: display_name: "Create or Update Agent" - short_description: "Maintain OpenBot agent project layouts" - default_prompt: "Use $create-or-update-agent to create or update the primary OpenBot agent or a full subagent under configuration/agent." + short_description: "Maintain Dispatch agent project layouts" + default_prompt: "Use $create-or-update-agent to create or update the primary Dispatch agent or a full subagent under configuration/agent." diff --git a/.agents/skills/create-pr/SKILL.md b/.agents/skills/create-pr/SKILL.md index 807d84fb..8824b021 100644 --- a/.agents/skills/create-pr/SKILL.md +++ b/.agents/skills/create-pr/SKILL.md @@ -1,11 +1,11 @@ --- name: create-pr -description: Prepare, commit, push, and open or update a draft pull request for OpenBot after focused validation, mandatory architecture and ADR review, contract and state review, final diff inspection, and intentional Git scope selection. +description: Prepare, commit, push, and open or update a draft pull request for Dispatch after focused validation, mandatory architecture and ADR review, contract and state review, final diff inspection, and intentional Git scope selection. --- # Create PR -Use when the user asks to open, publish, prepare, or update a PR for the current OpenBot branch. +Use when the user asks to open, publish, prepare, or update a PR for the current Dispatch branch. ## Required Order @@ -14,7 +14,7 @@ Use when the user asks to open, publish, prepare, or update a PR for the current 3. Run `pre-commit-checks` and fix in-scope failures. 4. Review protobuf, Tilde API reconciliation, environment, deployment, package README, public documentation, and Changesets impact. 5. Run the cross-client parity gate for `apps/desktop` and `apps/web`. Confirm the port/no-port decision with the user before publishing. -6. Run the CLI ownership gate: every developer workflow and operator behavior belongs in the `openbot` CLI. Refactor before publishing. +6. Run the CLI ownership gate: every developer workflow and operator behavior belongs in the Tilde CLI. Refactor before publishing. 7. Run the external dependency gate: if a contributor must install something new or different, update the setup instructions in the same PR. 8. Run the metadata semantics gate. Internal behavior in metadata blocks publication. 9. Run the architecture and ADR gate. Resolve any user decision before publishing. @@ -52,8 +52,8 @@ Add focused checks by surface: - protobuf: `pnpm contracts:generate` - server/providers: corresponding package tests - browser flow: `pnpm test:e2e` -- Electron packaging: `pnpm --filter @tryopenbot/desktop package` -- shared client contracts: `pnpm --filter @tryopenbot/client-runtime test` +- Electron packaging: `pnpm --filter @trytilde/dispatch-desktop package` +- shared client contracts: `pnpm --filter @trytilde/dispatch-client-runtime test` Record exact commands and failures. Do not claim checks that did not run. @@ -89,7 +89,7 @@ For an upstream PR, `git ls-files configuration` must print only the sentinel. F ## Cross-Client Parity Gate -OpenBot has two owner clients: `apps/desktop` (Electron) and `apps/web` (React DOM). This gate is mandatory and never skipped, including for PRs that touch only one of them. +Dispatch has two owner clients: `apps/desktop` (Electron) and `apps/web` (React DOM). This gate is mandatory and never skipped, including for PRs that touch only one of them. Ask and answer explicitly: **has this PR added or changed functionality in Electron desktop or the web app that needs to be ported to the other client?** @@ -119,10 +119,10 @@ Record the result in the PR body under a `Cross-client parity` heading as a per- ## CLI Ownership Gate -Per ADR-0018, the `openbot` CLI is the single command surface for operating an installation and developing the codebase. Before publishing, inspect the diff for logic that landed in the wrong place: +Per ADR-0018, the Tilde CLI is the single command surface for operating an installation and developing the codebase. Before publishing, inspect the diff for logic that landed in the wrong place: -- new `scripts/*.mjs` files, package-local helper scripts, or multi-step shell one-liners added to package.json scripts — refactor into an `openbot` command; root and package scripts stay thin delegations. -- command lines that exist only in documentation or skill prose but that developers or agents will run repeatedly — promote to an `openbot` command and have the prose reference it. +- new `scripts/*.mjs` files, package-local helper scripts, or multi-step shell one-liners added to package.json scripts — refactor into a `tilde` command; root and package scripts stay thin delegations. +- command lines that exist only in documentation or skill prose but that developers or agents will run repeatedly — promote to a `tilde` command and have the prose reference it. - a second CLI, binary, or runner package for developer workflow — fold it into `cli`. That split was tried and reversed; see ADR-0018's Updates. - host names, addresses, or machine-specific paths in package code — move them to fork-owned configuration such as `configuration/dev-hosts.json`. @@ -155,7 +155,7 @@ Record the result under an `External dependencies` heading. When nothing changed ## Metadata Semantics Gate Metadata is allowed only for provider-specific facts that cannot be normalized -and opaque client extensions that OpenBot/Tilde never interpret. Inspect the +and opaque client extensions that Dispatch/Tilde never interpret. Inspect the full PR, generated agent templates, and upstream Tilde contract changes: ```bash @@ -181,7 +181,7 @@ Always inspect the complete diff for major architecture, strongly opinionated co Review at least: -- ownership and boundaries across OpenBot, Tilde, providers, database, sandbox, client runtime, web, and desktop +- ownership and boundaries across Dispatch, Tilde, providers, database, sandbox, client runtime, web, and desktop - public protocols, compatibility, authentication, secrets, deployment, and failure policy - framework, storage, provider, or platform choices with meaningful switching cost - cross-package layering and strong coding conventions future maintainers may otherwise undo @@ -214,7 +214,7 @@ Use the checked-in `.github/pull_request_template.md` when present and complete ## Changesets Gate -OpenBot uses Changesets and versions all workspace packages as one fixed group. Follow `add-changeset` when a PR changes owner-visible behavior or a package API. Do not edit package versions or changelogs directly; the Changesets workflow owns the unified version pull request. Documentation-only, test-only, CI-only, and internal refactors need no placeholder changeset. +Dispatch uses Changesets and versions all workspace packages as one fixed group. Follow `add-changeset` when a PR changes owner-visible behavior or a package API. Do not edit package versions or changelogs directly; the Changesets workflow owns the unified version pull request. Documentation-only, test-only, CI-only, and internal refactors need no placeholder changeset. ## Package README Gate @@ -240,7 +240,7 @@ Use this sequence: 1. Finish initial validation and commit the implementation, tests, ADRs, READMEs, and ordinary documentation. 2. Push the branch and open the draft PR before generating the update record. 3. Read the stable PR number from GitHub; never guess or use a local sequence. -4. Analyze the full PR diff, commit history, review discussion, and all threads in the coding agent's database on the current machine. Inspect every locally available thread, not only the current chat or task. Retain implementation evidence relevant to this PR in the update record. Preserve actionable but out-of-scope OpenBot feature planning in the PR body or a PR comment using the exact `` block syntax from `CONTEXT.md`; link an existing issue when one exists, group only work with the same owner and trigger, and include concrete acceptance proof. Do not copy unrelated planning into the repository update record. +4. Analyze the full PR diff, commit history, review discussion, and all threads in the coding agent's database on the current machine. Inspect every locally available thread, not only the current chat or task. Retain implementation evidence relevant to this PR in the update record. Preserve actionable but out-of-scope Dispatch feature planning in the PR body or a PR comment using the exact `` block syntax from `CONTEXT.md`; link an existing issue when one exists, group only work with the same owner and trigger, and include concrete acceptance proof. Do not copy unrelated planning into the repository update record. 5. Create `docs/updates/.md`, commit it, and push it to the same draft PR. 6. After every later code, test, documentation, rebase, conflict-resolution, or accepted-review change, regenerate the same record from all evidence and push its update before declaring the PR current. @@ -253,7 +253,7 @@ Write the record in detailed caveman style with these exact sections: 3. `Summarized package changes` 4. `Critical to apply to forks`, starting with exactly `yes` or `no`, then the reason and concrete fork action -Include breaking imports, path moves, configuration or secret migration, provider obligations, deployment topology, removed behavior, and checks a customized fork must run. State `no updates` only in `configuration/docs/update-notes/.md` when `openbot update` finds no upstream commits; never use it as an upstream PR update record. +Include breaking imports, path moves, configuration or secret migration, provider obligations, deployment topology, removed behavior, and checks a customized fork must run. State `no updates` only in `configuration/docs/update-notes/.md` when `dispatch update` finds no upstream commits; never use it as an upstream PR update record. Before final handoff, verify: diff --git a/.agents/skills/customize-dispatch/agents/openai.yaml b/.agents/skills/customize-dispatch/agents/openai.yaml new file mode 100644 index 00000000..21e7ee81 --- /dev/null +++ b/.agents/skills/customize-dispatch/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "Customize Dispatch" + short_description: "Change repository-owned Dispatch behavior safely" + default_prompt: "Inspect this Dispatch fork and implement the requested repository configuration change." diff --git a/.agents/skills/customize-openbot/agents/openai.yaml b/.agents/skills/customize-openbot/agents/openai.yaml deleted file mode 100644 index d184e4e5..00000000 --- a/.agents/skills/customize-openbot/agents/openai.yaml +++ /dev/null @@ -1,4 +0,0 @@ -interface: - display_name: "Customize OpenBot" - short_description: "Change repository-owned OpenBot behavior safely" - default_prompt: "Inspect this OpenBot fork and implement the requested repository configuration change." diff --git a/.agents/skills/diagnose/SKILL.md b/.agents/skills/diagnose/SKILL.md index 0be031bb..6138b11f 100644 --- a/.agents/skills/diagnose/SKILL.md +++ b/.agents/skills/diagnose/SKILL.md @@ -7,7 +7,7 @@ description: Disciplined diagnosis loop for hard bugs and performance regression A discipline for hard bugs. Skip phases only when explicitly justified. -When exploring OpenBot, start with `README.md`, `AGENTS.md`, the public route or protobuf method, the owning provider interface/adapter, and nearby tests. Check `CONTEXT.md` or ADRs only when they exist. +When exploring Dispatch, start with `README.md`, `AGENTS.md`, the public route or protobuf method, the owning provider interface/adapter, and nearby tests. Check `CONTEXT.md` or ADRs only when they exist. ## Phase 1 — Build a feedback loop @@ -53,7 +53,7 @@ Do not proceed to Phase 2 until you have a loop you believe in. ### Frontend and e2e bugs For frontend-visible behavior, use the root Playwright setup or run -`OPENBOT_NO_DESKTOP=1 pnpm dev`. Inspect DOM, console, network, relevant +`DISPATCH_NO_DESKTOP=1 pnpm dev`. Inspect DOM, console, network, relevant ConnectRPC/HTTP responses, and visible state. Store ad hoc screenshots or traces outside git and reference them by absolute path. Do not treat server tests as sufficient when the user-visible flow can be exercised in the browser. diff --git a/.agents/skills/e2e-debug-and-qa/SKILL.md b/.agents/skills/e2e-debug-and-qa/SKILL.md index aab23627..54dcf22b 100644 --- a/.agents/skills/e2e-debug-and-qa/SKILL.md +++ b/.agents/skills/e2e-debug-and-qa/SKILL.md @@ -1,11 +1,11 @@ --- name: e2e-debug-and-qa -description: Run and inspect OpenBot browser or desktop workflows with the repository Playwright setup. Use for onboarding, setup authentication, chat, provider, sandbox, visual, console, network, or Electron behavior that must be verified on the real surface. +description: Run and inspect Dispatch browser or desktop workflows with the repository Playwright setup. Use for onboarding, setup authentication, chat, provider, sandbox, visual, console, network, or Electron behavior that must be verified on the real surface. --- # E2E Debug And Q&A -Answer from the running OpenBot surface when static inspection is insufficient. +Answer from the running Dispatch surface when static inspection is insufficient. ## Purpose @@ -41,7 +41,7 @@ The checked-in Playwright server uses isolated setup data, disables the desktop For manual inspection: ```bash -OPENBOT_NO_DESKTOP=1 pnpm dev +DISPATCH_NO_DESKTOP=1 pnpm dev ``` `pnpm dev` starts the control server on `127.0.0.1:4100` and web app on `127.0.0.1:4173` by default. It uses Tilde Tunnel only when Tilde credentials are configured. Do not add unrelated wildcard DNS, ngrok, or database services to browser setup. diff --git a/.agents/skills/edit-openbot-configuration/SKILL.md b/.agents/skills/edit-dispatch-configuration/SKILL.md similarity index 83% rename from .agents/skills/edit-openbot-configuration/SKILL.md rename to .agents/skills/edit-dispatch-configuration/SKILL.md index 9d80bc0a..14bf721e 100644 --- a/.agents/skills/edit-openbot-configuration/SKILL.md +++ b/.agents/skills/edit-dispatch-configuration/SKILL.md @@ -1,9 +1,9 @@ --- -name: edit-openbot-configuration -description: Edit a fork's repository-owned OpenBot composition, providers, agent defaults, instrumentation, environment declarations, and templates under configuration/. Use when changing configuration/index.ts, configuration/providers/, configuration/instrumentation.ts, configuration/templates/agent/, or the defaults used by openbot new-agent. +name: edit-dispatch-configuration +description: Edit a fork's repository-owned Dispatch composition, providers, agent defaults, instrumentation, environment declarations, and templates under configuration/. Use when changing configuration/index.ts, configuration/providers/, configuration/instrumentation.ts, configuration/templates/agent/, or the defaults used by tilde new-agent. --- -# Edit OpenBot configuration +# Edit Dispatch configuration ## Read ownership first @@ -24,7 +24,7 @@ Keep fork choices in `configuration/`. Modify upstream packages only when the ne If provider composition changes in `configuration/index.ts`, inspect `configuration/templates/agent/`. Update the template when future agents need matching environment variables or direct SDK/endpoint wiring. Authored agents must not import provider packages; integrate OpenAI, Tilde, Composio, or another chosen system directly in agent code. -Each file below `configuration/templates/agent/` must end in `.hbs`. `openbot new-agent` preserves its relative path, removes `.hbs`, and renders these strict values: +Each file below `configuration/templates/agent/` must end in `.hbs`. `tilde new-agent` preserves its relative path, removes `.hbs`, and renders these strict values: - `AGENT_ID` - `AGENT_ID_JSON` diff --git a/.agents/skills/edit-dispatch-configuration/agents/openai.yaml b/.agents/skills/edit-dispatch-configuration/agents/openai.yaml new file mode 100644 index 00000000..44d3fe6c --- /dev/null +++ b/.agents/skills/edit-dispatch-configuration/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "Edit Dispatch Configuration" + short_description: "Edit fork-owned Dispatch configuration safely" + default_prompt: "Use $edit-dispatch-configuration to update this fork configuration and its agent template safely." diff --git a/.agents/skills/edit-openbot-configuration/agents/openai.yaml b/.agents/skills/edit-openbot-configuration/agents/openai.yaml deleted file mode 100644 index 6920451e..00000000 --- a/.agents/skills/edit-openbot-configuration/agents/openai.yaml +++ /dev/null @@ -1,4 +0,0 @@ -interface: - display_name: "Edit OpenBot Configuration" - short_description: "Edit fork-owned OpenBot configuration safely" - default_prompt: "Use $edit-openbot-configuration to update this fork configuration and its agent template safely." diff --git a/.agents/skills/expose-api-change/SKILL.md b/.agents/skills/expose-api-change/SKILL.md index 74c4afb3..2a315a82 100644 --- a/.agents/skills/expose-api-change/SKILL.md +++ b/.agents/skills/expose-api-change/SKILL.md @@ -7,7 +7,7 @@ description: Self-refresh loop for exposing intentional Tilde API changes throug ## Process -1. Run `pnpm openbot sdk refresh`. +1. Run `pnpm tilde sdk refresh`. 2. Inspect OpenAPI operation and schema diffs. 3. Confirm every Tilde-owned value is an explicit schema field. Do not accept message/session metadata as a substitute for typed identity, audience, @@ -24,4 +24,4 @@ description: Self-refresh loop for exposing intentional Tilde API changes throug - Use camelCase in TypeScript APIs. - Preserve existing public names unless the user explicitly asks for a breaking change. - When the upstream API lacks a typed core field, fix the upstream contract; - do not add a hand-authored metadata parser in OpenBot. + do not add a hand-authored metadata parser in Dispatch. diff --git a/.agents/skills/frontend-design/SKILL.md b/.agents/skills/frontend-design/SKILL.md index 8a47ede6..98f40bdd 100644 --- a/.agents/skills/frontend-design/SKILL.md +++ b/.agents/skills/frontend-design/SKILL.md @@ -1,6 +1,6 @@ --- name: frontend-design -description: Guidance for distinctive, intentional visual design when building new UI or reshaping an existing one across OpenBot's web and Electron desktop clients. Helps with aesthetic direction, typography, platform fit, and making choices that don't read as templated defaults. +description: Guidance for distinctive, intentional visual design when building new UI or reshaping an existing one across Dispatch's web and Electron desktop clients. Helps with aesthetic direction, typography, platform fit, and making choices that don't read as templated defaults. license: Complete terms in LICENSE.txt --- @@ -8,9 +8,9 @@ license: Complete terms in LICENSE.txt Approach this as the design lead at a small studio known for giving every client a visual identity that could not be mistaken for anyone else's. This client has already rejected proposals that felt templated, and is paying for a distinctive point of view: make deliberate, opinionated choices about palette, typography, and layout that are specific to this brief, and take one real aesthetic risk you can justify. -## OpenBot clients +## Dispatch clients -OpenBot ships the same product through two clients, and a design decision here is a decision for both: +Dispatch ships the same product through two clients, and a design decision here is a decision for both: - `apps/web` — React 19, React DOM, Vite, TanStack Router, and `packages/ui`. - `apps/desktop` — Electron shell rendering the web client. diff --git a/.agents/skills/grill-with-docs/ADR-FORMAT.md b/.agents/skills/grill-with-docs/ADR-FORMAT.md index 2468b9cc..2cb7232d 100644 --- a/.agents/skills/grill-with-docs/ADR-FORMAT.md +++ b/.agents/skills/grill-with-docs/ADR-FORMAT.md @@ -47,7 +47,7 @@ Use the smallest Mermaid diagram that explains a boundary, flow, hierarchy, or s Always review a PR diff for major architecture, strongly opinionated code, or durable code/product design decisions. A decision qualifies when it establishes or materially changes a durable rule future work must follow, especially: -- ownership or boundaries between OpenBot, Tilde, providers, database, sandbox, web, or desktop +- ownership or boundaries between Dispatch, Tilde, providers, database, sandbox, web, or desktop - public protocols, compatibility, authentication, secrets, deployment, or failure policy - framework, storage, provider, or platform choices with meaningful switching cost - cross-package layering or a strong coding convention that future maintainers may otherwise undo diff --git a/.agents/skills/grill-with-docs/SKILL.md b/.agents/skills/grill-with-docs/SKILL.md index c670cae4..50ee73ba 100644 --- a/.agents/skills/grill-with-docs/SKILL.md +++ b/.agents/skills/grill-with-docs/SKILL.md @@ -1,6 +1,6 @@ --- name: grill-with-docs -description: Stress-test an OpenBot plan against its documented architecture, provider ownership, contracts, deployment model, and domain language. Ask one decision at a time and update durable documentation only as decisions become clear. +description: Stress-test a Dispatch plan against its documented architecture, provider ownership, contracts, deployment model, and domain language. Ask one decision at a time and update durable documentation only as decisions become clear. --- @@ -19,8 +19,8 @@ Read the smallest relevant set: - `README.md`: product, setup, runtime, deployment, and ownership boundaries. - `AGENTS.md`: coding and validation rules. -- `packages/control-service-proto/proto/openbot/control/v1/control.proto`: owner-facing control contract. -- `packages/computer-service-proto/proto/openbot/computer/v1/computer.proto`: internal computer contract. +- `packages/control-service-proto/proto/dispatch/control/v1/control.proto`: owner-facing control contract. +- `packages/computer-service-proto/proto/dispatch/computer/v1/computer.proto`: internal computer contract. - `packages/-provider/src/core.ts` or `packages/-provider/src/core/index.ts`: domain provider seams; the package root only re-exports them. - Tilde-backed provider lifecycles: API-reconciled remote resources and persisted IDs. - `PROVENANCE.md`: copied-source and clean-room constraints. @@ -33,7 +33,7 @@ Read `CONTEXT.md` and relevant records under `docs/adrs/` when they exist. Creat Keep these distinctions explicit: -- OpenBot control state vs Tilde-owned agents, chats, tools, skills, and memory. +- Dispatch control state vs Tilde-owned agents, chats, tools, skills, and memory. - Local/Vercel environment secrets vs future persisted control state vs sandbox files. - Provider interface vs concrete adapter vs UI/client. - Web app vs Electron shell vs computer-service sandbox API. @@ -43,7 +43,7 @@ Call out any plan that crosses one of these boundaries without a reason. ### Sharpen fuzzy language -Replace overloaded terms with the repository's concrete concepts. For example, distinguish OpenBot installation, Tilde organization/team, Tilde agent, ChatKit session, sandbox instance, provider adapter, and environment provider. +Replace overloaded terms with the repository's concrete concepts. For example, distinguish Dispatch installation, Tilde organization/team, Tilde agent, ChatKit session, sandbox instance, provider adapter, and environment provider. ### Discuss concrete scenarios diff --git a/.agents/skills/implement-provider/SKILL.md b/.agents/skills/implement-provider/SKILL.md index afbde2ef..bcb20ae3 100644 --- a/.agents/skills/implement-provider/SKILL.md +++ b/.agents/skills/implement-provider/SKILL.md @@ -1,9 +1,9 @@ --- name: implement-provider -description: Add or refactor an OpenBot provider implementation while preserving narrow control, provisioning, initialization, and deployment boundaries. Use whenever editing a provider package or changing provider-specific build, deploy, initialization, or external resource reconciliation. +description: Add or refactor a Dispatch provider implementation while preserving narrow control, provisioning, initialization, and deployment boundaries. Use whenever editing a provider package or changing provider-specific build, deploy, initialization, or external resource reconciliation. --- -# Implement an OpenBot provider +# Implement a Dispatch provider Keep provider-specific behavior behind its domain core contract and keep composition outside the adapter. Read the relevant ADRs, the owning package's `src/core.ts` or `src/core/index.ts`, implementation, runtime selection, and focused tests before editing. Do not create a separate `*-provider-core` package. @@ -11,7 +11,7 @@ Keep provider-specific behavior behind its domain core contract and keep composi 1. Identify the concrete consumer. A provider operation is valid only when used by the control service, initialization/startup provisioning, external resource reconciliation, or a check/build/deploy lifecycle. Remove unused and speculative contract methods. Do not expose an internal provider interface through RPC unless a user-facing service boundary requires it. 2. Read the matching provider package, configuration composition, and tests. Preserve `ProviderCallContext`, `ProviderError`, cancellation, deadlines, request IDs, and idempotency where the contract defines them. If the change alters provider construction or runtime assumptions in `configuration/index.ts`, inspect `configuration/templates/agent/` too. Update the fork-owned agent template when newly scaffolded agents need different environment variables, tools, prompts, or endpoint wiring. -3. Add the smallest provider-specific implementation. Keep selection in composition code. Before adding vendor helpers, inspect `@tryopenbot/platform-integrations`: shared platform clients, authentication, request/error normalization, account lookup, deployment commands, and other cross-domain vendor operations belong under `src//.ts`. Domain-specific API calls and record mapping stay in the adapter. +3. Add the smallest provider-specific implementation. Keep selection in composition code. Before adding vendor helpers, inspect `@trytilde/dispatch-platform-integrations`: shared platform clients, authentication, request/error normalization, account lookup, deployment commands, and other cross-domain vendor operations belong under `src//.ts`. Domain-specific API calls and record mapping stay in the adapter. 4. Implement only the initialization or lifecycle capabilities the provider supports. Every hook must be idempotent: repeated calls reconcile stable resources and never create duplicates. Keep vendor-specific get/create/update/delete sequences and configuration persistence inside the adapter; CLI code only schedules hooks. An inference provider may provision accounts or credentials, but providers must not supply model factories, prompts, AI SDK tools, or arbitrary vendor functions to authored agents. Code under `configuration/agent/`, including `subagents/`, must integrate its SDKs directly and must not import provider packages. Put shared non-provider runtime utilities in a purpose-specific package. 5. Add focused contract and artifact tests, then run the provider package checks before broader repository gates. @@ -47,7 +47,7 @@ types. ## Provider-owned assets - Store TypeScript, JavaScript, JSON, service units, plists, shell files, and every other generated-file source under `assets/` as Handlebars templates with the target extension followed by `.hbs`, such as `entry.ts.hbs` or `vercel.json.hbs`. Do not embed whole files in TypeScript string literals. -- Resolve templates relative to `import.meta.url` and render them through `@tryopenbot/utilities`. Build and deploy methods must render or bundle every required template into their ignored artifact; do not materialize provider assets with `copyFile()` even when a template is currently static. +- Resolve templates relative to `import.meta.url` and render them through `@trytilde/dispatch-utilities`. Build and deploy methods must render or bundle every required template into their ignored artifact; do not materialize provider assets with `copyFile()` even when a template is currently static. - Put assets shared completely by sibling providers under `src/base/assets/`; add provider-specific asset directories only when their contents or control flow actually diverge. - Use strict templates so missing values fail. Escape values for the target format before rendering. Use ordinary Handlebars expressions for text that needs HTML escaping and triple braces only for deliberately pre-encoded target-language fragments such as `JSON.stringify(...)` output. - Do not create ad hoc `replaceAll()` renderers, multiline whole-file strings, or alternate template engines. @@ -76,4 +76,4 @@ types. Run the focused platform and provider tests and typechecks. Audit the diff for duplicated Tilde/Vercel helpers, cross-domain provider utility imports, provider contract interfaces outside `src/core.ts` or `src/core/index.ts`, embedded whole-file templates, non-Handlebars generation, raw provider-asset copies, stale flat-provider imports, secrets, and unrelated generated output. Run `pnpm check` and `pnpm build` when the change affects deployment artifacts or shared contracts. Also audit metadata: every metadata key must be provider-specific, name its sole -adapter owner, and remain invisible to core OpenBot behavior and renderers. +adapter owner, and remain invisible to core Dispatch behavior and renderers. diff --git a/.agents/skills/implement-provider/agents/openai.yaml b/.agents/skills/implement-provider/agents/openai.yaml index e7db6e97..631fddb1 100644 --- a/.agents/skills/implement-provider/agents/openai.yaml +++ b/.agents/skills/implement-provider/agents/openai.yaml @@ -1,4 +1,4 @@ interface: display_name: "Implement Provider" - short_description: "Build and refactor OpenBot providers safely" - default_prompt: "Use $implement-provider to add or refactor an OpenBot provider implementation." + short_description: "Build and refactor Dispatch providers safely" + default_prompt: "Use $implement-provider to add or refactor a Dispatch provider implementation." diff --git a/.agents/skills/improve-codebase-architecture/SKILL.md b/.agents/skills/improve-codebase-architecture/SKILL.md index 9019e13a..333c5026 100644 --- a/.agents/skills/improve-codebase-architecture/SKILL.md +++ b/.agents/skills/improve-codebase-architecture/SKILL.md @@ -1,6 +1,6 @@ --- name: improve-codebase-architecture -description: Find deepening opportunities in OpenBot's TypeScript monorepo using its provider contracts, protobuf API, control-state ownership, runtime composition, and documented decisions. Use for refactoring, consolidation, testability, or AI-navigability reviews. +description: Find deepening opportunities in Dispatch's TypeScript monorepo using its provider contracts, protobuf API, control-state ownership, runtime composition, and documented decisions. Use for refactoring, consolidation, testability, or AI-navigability reviews. --- # Improve Codebase Architecture @@ -49,7 +49,7 @@ For each candidate provide: - benefits for locality, leverage, and tests - compatibility or migration risk -Use OpenBot concepts, not generic placeholders. Do not design interfaces until the user selects a candidate. +Use Dispatch concepts, not generic placeholders. Do not design interfaces until the user selects a candidate. ### 3. Grilling loop diff --git a/.agents/skills/lean-build/SKILL.md b/.agents/skills/lean-build/SKILL.md index 419ac992..accfac4c 100644 --- a/.agents/skills/lean-build/SKILL.md +++ b/.agents/skills/lean-build/SKILL.md @@ -5,7 +5,7 @@ description: Build feature work with high overbuilding risk. Use for new behavio # Lean build -OpenBot's provider and ownership boundaries remain mandatory. Turn the feature into the narrowest complete outcome that fits the existing system. +Dispatch's provider and ownership boundaries remain mandatory. Turn the feature into the narrowest complete outcome that fits the existing system. - Derive observable acceptance and explicit non-goals from request and repository. - Trace entry point through layers owning invariants. diff --git a/.agents/skills/pre-commit-checks/SKILL.md b/.agents/skills/pre-commit-checks/SKILL.md index 386dd0bc..034ea6f3 100644 --- a/.agents/skills/pre-commit-checks/SKILL.md +++ b/.agents/skills/pre-commit-checks/SKILL.md @@ -1,6 +1,6 @@ --- name: pre-commit-checks -description: Run OpenBot's TypeScript, protobuf, Vitest, build, browser, provider, and desktop checks before committing, pushing, opening a PR, or handing off work. Use risk-based focused checks first, then repository gates. +description: Run Dispatch's TypeScript, protobuf, Vitest, build, browser, provider, and desktop checks before committing, pushing, opening a PR, or handing off work. Use risk-based focused checks first, then repository gates. --- # Pre-Commit Checks @@ -14,7 +14,7 @@ Inspect the worktree and secret-bearing paths before broad checks: ```bash git status --short --branch git diff -- .env .env.* '*.env' '*.local' -git check-ignore -v .env.local .data .vercel .openbot-deploy +git check-ignore -v .env.local .data .vercel .dispatch-deploy ``` Never stage credentials, setup codes, browser profiles, local databases, Vercel metadata, decrypted deployment files, or test artifacts. @@ -34,7 +34,7 @@ and opaque client extensions that core code never reads. Fail the handoff when agent templates, SDKs, control routes, client runtime, UI, or provider composition use metadata for internal authorization, identity, routing, lifecycle, retries, relationships, models, budgets, runs, jobs, compaction, or -memory semantics. Require a typed Tilde/OpenBot contract instead. +memory semantics. Require a typed Tilde/Dispatch contract instead. ## Required Gates @@ -48,14 +48,14 @@ pnpm build `pnpm check` regenerates protobuf contracts, type-checks scripts and packages, and runs package lint/test tasks plus deployment-script tests. Run focused tests first while iterating: ```bash -pnpm --filter @tryopenbot/control-service test -pnpm --filter @tryopenbot/agent-service-provider test -pnpm --filter @tryopenbot/computer-service-provider test -pnpm --filter @tryopenbot/client-runtime test -pnpm --filter @tryopenbot/desktop test +pnpm --filter @trytilde/dispatch-control-service test +pnpm --filter @trytilde/dispatch-agent-service-provider test +pnpm --filter @trytilde/dispatch-computer-service-provider test +pnpm --filter @trytilde/dispatch-client-runtime test +pnpm --filter @trytilde/dispatch-desktop test ``` -Run `pnpm test:e2e` when browser behavior changed or the user requested end-to-end proof. Run `pnpm --filter @tryopenbot/desktop package` when packaging, preload, Electron startup, or bundled-resource behavior changed. +Run `pnpm test:e2e` when browser behavior changed or the user requested end-to-end proof. Run `pnpm --filter @trytilde/dispatch-desktop package` when packaging, preload, Electron startup, or bundled-resource behavior changed. ## TypeScript Fix Policy @@ -85,7 +85,7 @@ Edit the `.proto` source, never generated TypeScript. Do not commit `apps/web/sr ## Release Notes -OpenBot uses Changesets with one fixed group for every workspace package. Follow `add-changeset` for owner-visible behavior or package API changes. Do not edit versions or changelogs directly. Documentation-only, test-only, CI-only, and internal refactors need no placeholder changeset. +Dispatch uses Changesets with one fixed group for every workspace package. Follow `add-changeset` for owner-visible behavior or package API changes. Do not edit versions or changelogs directly. Documentation-only, test-only, CI-only, and internal refactors need no placeholder changeset. ## Fix Before Commit @@ -95,7 +95,7 @@ OpenBot uses Changesets with one fixed group for every workspace package. Follow - Generated contracts match protobuf sources. - Diff contains no secrets, local state, generated noise, or unrelated edits. - Changed metadata is provider-specific or client-opaque and has no internal - OpenBot/Tilde semantics. + Dispatch/Tilde semantics. - A valid changeset is present when release impact requires one, or the handoff explains why none is needed. - Changed provider contract interfaces are defined in `src/core.ts` or `src/core/index.ts`, re-exported by the package root, and reflected in the package README's `Public API` section. - New or changed major UX surfaces and state interactions consume `packages/client-runtime` contracts. `apps/web` and `apps/desktop` added no local wire types, fetch/SSE parsing, or duplicate snapshots; only presentation-only state is component-local. diff --git a/.agents/skills/run-dispatch/SKILL.md b/.agents/skills/run-dispatch/SKILL.md new file mode 100644 index 00000000..4c8b6b95 --- /dev/null +++ b/.agents/skills/run-dispatch/SKILL.md @@ -0,0 +1,16 @@ +--- +name: run-dispatch +description: Initialize, validate, run, build, deploy, or diagnose a Dispatch fork locally or on Vercel. Use for first-run configuration, development startup, provider build checks, local service deployment, Vercel Build Output deployment, and service health proof. +--- + +# Run Dispatch + +1. Require Node 24 and pnpm 10, then run `pnpm install`. +2. If `configuration/` contains only `.gitkeep`, run the interactive `pnpm tilde init`. Fork values belong only in `configuration/.env` and `configuration/secrets.enc.yaml`; never create or load a root `.env` or root SOPS document. +3. Confirm `configuration/index.ts` explicitly constructs every provider role. Agent entrypoints read their runtime environment directly and must not import a second provider composition module. Init defaults agent, chat, skill, and tool providers to Tilde without asking the owner to select domain providers. +4. Run `DISPATCH_NO_DESKTOP=1 pnpm tilde dev` for a headless proof, or `pnpm tilde dev` when Electron is available. The CLI owns the control-service process; desktop only connects to it and never starts it. +5. Build without mutation using `pnpm tilde deploy --skip-deploy --service all`. Use `--service agents` or `--service control` for one artifact. +6. Use `pnpm tilde deploy --yes` only when the user authorizes real deployment. Local providers install separate systemd user services on Linux or launchd agents on macOS. Vercel providers deploy independent prebuilt agent and control projects; the idempotent agent provider reconciles endpoints before the agent service consumes newly issued credentials, and the control runtime deploys last. +7. Probe control `/healthz`, agent-service `/healthz`, an unsigned agent endpoint expecting authentication failure, and the web SPA. Never print decrypted secrets or deployment environment files. + +The desktop package requires `DISPATCH_CONTROL_ORIGIN` outside CLI development, defaulting to the CLI development origin `http://127.0.0.1:4100`. It is always a client. diff --git a/.agents/skills/run-dispatch/agents/openai.yaml b/.agents/skills/run-dispatch/agents/openai.yaml new file mode 100644 index 00000000..2057c608 --- /dev/null +++ b/.agents/skills/run-dispatch/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "Run Dispatch" + short_description: "Set up, validate, and run this Dispatch fork" + default_prompt: "Set up and run this Dispatch fork, diagnosing any configuration problem." diff --git a/.agents/skills/run-openbot/SKILL.md b/.agents/skills/run-openbot/SKILL.md deleted file mode 100644 index 4f75bccb..00000000 --- a/.agents/skills/run-openbot/SKILL.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -name: run-openbot -description: Initialize, validate, run, build, deploy, or diagnose an OpenBot fork locally or on Vercel. Use for first-run configuration, development startup, provider build checks, local service deployment, Vercel Build Output deployment, and service health proof. ---- - -# Run OpenBot - -1. Require Node 24 and pnpm 10, then run `pnpm install`. -2. If `configuration/` contains only `.gitkeep`, run the interactive `pnpm openbot init`. Fork values belong only in `configuration/.env` and `configuration/secrets.enc.yaml`; never create or load a root `.env` or root SOPS document. -3. Confirm `configuration/index.ts` explicitly constructs every provider role. Agent entrypoints read their runtime environment directly and must not import a second provider composition module. Init defaults agent, chat, skill, and tool providers to Tilde without asking the owner to select domain providers. -4. Run `OPENBOT_NO_DESKTOP=1 pnpm openbot dev` for a headless proof, or `pnpm openbot dev` when Electron is available. The CLI owns the control-service process; desktop only connects to it and never starts it. -5. Build without mutation using `pnpm openbot deploy --skip-deploy --service all`. Use `--service agents` or `--service control` for one artifact. -6. Use `pnpm openbot deploy --yes` only when the user authorizes real deployment. Local providers install separate systemd user services on Linux or launchd agents on macOS. Vercel providers deploy independent prebuilt agent and control projects; the idempotent agent provider reconciles endpoints before the agent service consumes newly issued credentials, and the control runtime deploys last. -7. Probe control `/healthz`, agent-service `/healthz`, an unsigned agent endpoint expecting authentication failure, and the web SPA. Never print decrypted secrets or deployment environment files. - -The desktop package requires `OPENBOT_CONTROL_ORIGIN` outside CLI development, defaulting to the CLI development origin `http://127.0.0.1:4100`. It is always a client. diff --git a/.agents/skills/run-openbot/agents/openai.yaml b/.agents/skills/run-openbot/agents/openai.yaml deleted file mode 100644 index a6357904..00000000 --- a/.agents/skills/run-openbot/agents/openai.yaml +++ /dev/null @@ -1,4 +0,0 @@ -interface: - display_name: "Run OpenBot" - short_description: "Set up, validate, and run this OpenBot fork" - default_prompt: "Set up and run this OpenBot fork, diagnosing any configuration problem." diff --git a/.agents/skills/tilde/SKILL.md b/.agents/skills/tilde/SKILL.md index 2661b043..d802a02b 100644 --- a/.agents/skills/tilde/SKILL.md +++ b/.agents/skills/tilde/SKILL.md @@ -31,7 +31,7 @@ Tilde is a TypeScript-first platform for building and operating AI agents. It pr - Call `tilde_whoami` before performing workspace-scoped configuration and use the returned `team_id`. - Discover provider, credential source, and tool identifiers from Tilde. Never guess identifiers. - Keep API keys, webhook signing keys, OAuth credentials, claim tokens, and PINs out of source code, logs, chat history, and generated state. -- OpenBot does not use a Tilde state file during normal operation. Reconcile Tilde resources through typed, idempotent provider lifecycles. For one-time setup or team migration, the operator may manually export and import state with the Tilde CLI. +- Dispatch does not use a Tilde state file during normal operation. Reconcile Tilde resources through typed, idempotent provider lifecycles. For one-time setup or team migration, the operator may manually export and import state with the Tilde CLI. - Keep webhook verification and server-side credentials in ChatKit endpoints. - Ask before changing or deleting existing resources when the requested scope is ambiguous. diff --git a/.agents/skills/update-openbot/SKILL.md b/.agents/skills/update-dispatch/SKILL.md similarity index 68% rename from .agents/skills/update-openbot/SKILL.md rename to .agents/skills/update-dispatch/SKILL.md index b13fb68d..582dfd34 100644 --- a/.agents/skills/update-openbot/SKILL.md +++ b/.agents/skills/update-dispatch/SKILL.md @@ -1,13 +1,13 @@ --- -name: update-openbot -description: Update a fork from the OpenBot upstream repository while preserving fork-owned configuration. Use for upstream syncs, conflict resolution, and compatibility migrations. +name: update-dispatch +description: Update a fork from the Dispatch upstream repository while preserving fork-owned configuration. Use for upstream syncs, conflict resolution, and compatibility migrations. --- -# Update OpenBot +# Update Dispatch 1. Inspect remotes, branch status, and uncommitted changes. Do not overwrite fork work. 2. Fetch the configured upstream and merge or rebase in a dedicated branch according to the repository convention. 3. Treat `configuration/index.ts` and the complete `configuration/` tree as fork-owned. Resolve conflicts by preserving their intent while adopting updated interfaces. 4. Do not copy upstream secrets or generated deployment state. -5. Regenerate the repository manifest and contracts, then run `pnpm openbot check`, `pnpm check`, and `pnpm build`. +5. Regenerate the repository manifest and contracts, then run `pnpm tilde check`, `pnpm check`, and `pnpm build`. 6. Summarize upstream changes, fork conflict decisions, and any required configuration migration. diff --git a/.agents/skills/update-dispatch/agents/openai.yaml b/.agents/skills/update-dispatch/agents/openai.yaml new file mode 100644 index 00000000..dee6809e --- /dev/null +++ b/.agents/skills/update-dispatch/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "Update Dispatch" + short_description: "Bring upstream Dispatch changes into a fork" + default_prompt: "Update this Dispatch fork from upstream while preserving repository configuration." diff --git a/.agents/skills/update-openapi-generated-client/SKILL.md b/.agents/skills/update-openapi-generated-client/SKILL.md index 4d7a29d7..dcb5993f 100644 --- a/.agents/skills/update-openapi-generated-client/SKILL.md +++ b/.agents/skills/update-openapi-generated-client/SKILL.md @@ -9,8 +9,8 @@ Use this when `/root/tilde-api/openapi.cloud.json` or a worktree OpenAPI file ch ## Process -1. Run `pnpm openbot sdk refresh`. -2. Run `pnpm openbot sdk validate`. +1. Run `pnpm tilde sdk refresh`. +2. Run `pnpm tilde sdk validate`. 3. Inspect generated type diffs. 4. Do not manually edit generated files. 5. Update hand-authored wrappers only when operation names or schema shapes changed. diff --git a/.agents/skills/update-openbot/agents/openai.yaml b/.agents/skills/update-openbot/agents/openai.yaml deleted file mode 100644 index 64901b6c..00000000 --- a/.agents/skills/update-openbot/agents/openai.yaml +++ /dev/null @@ -1,4 +0,0 @@ -interface: - display_name: "Update OpenBot" - short_description: "Bring upstream OpenBot changes into a fork" - default_prompt: "Update this OpenBot fork from upstream while preserving repository configuration." diff --git a/.agents/skills/upstream-pr/SKILL.md b/.agents/skills/upstream-pr/SKILL.md index 01c0796f..b3e7f9f6 100644 --- a/.agents/skills/upstream-pr/SKILL.md +++ b/.agents/skills/upstream-pr/SKILL.md @@ -1,6 +1,6 @@ --- name: upstream-pr -description: Prepare a focused change from an OpenBot fork for contribution to upstream. Use when separating reusable core or provider improvements from fork-specific configuration. +description: Prepare a focused change from a Dispatch fork for contribution to upstream. Use when separating reusable core or provider improvements from fork-specific configuration. --- # Contribute Upstream diff --git a/.agents/skills/upstream-pr/agents/openai.yaml b/.agents/skills/upstream-pr/agents/openai.yaml index a1c3a6ba..1837bf42 100644 --- a/.agents/skills/upstream-pr/agents/openai.yaml +++ b/.agents/skills/upstream-pr/agents/openai.yaml @@ -1,4 +1,4 @@ interface: display_name: "Contribute Upstream" - short_description: "Prepare a focused OpenBot upstream contribution" - default_prompt: "Turn this fork change into a focused, validated upstream OpenBot pull request." + short_description: "Prepare a focused Dispatch upstream contribution" + default_prompt: "Turn this fork change into a focused, validated upstream Dispatch pull request." diff --git a/.agents/skills/vercel/SKILL.md b/.agents/skills/vercel/SKILL.md index 7676b3ab..26e60880 100644 --- a/.agents/skills/vercel/SKILL.md +++ b/.agents/skills/vercel/SKILL.md @@ -1,18 +1,18 @@ --- name: vercel -description: Deploy, configure, inspect, or troubleshoot OpenBot on Vercel, including Vercel Functions, provider-owned Vercel assets, and project environment variables. Use for preview or production deployments, Vercel configuration changes, deployment failures, environment setup, or changes involving cli/src/commands/deploy.ts or the Vercel service providers. +description: Deploy, configure, inspect, or troubleshoot Dispatch on Vercel, including Vercel Functions, provider-owned Vercel assets, and project environment variables. Use for preview or production deployments, Vercel configuration changes, deployment failures, environment setup, or changes involving cli/src/commands/deploy.ts or the Vercel service providers. --- -# Operate OpenBot on Vercel +# Operate Dispatch on Vercel -Use OpenBot's coordinated deployment workflow. It owns the coupled Vercel, Tilde, environment, and Sandbox setup that a generic `vercel deploy` cannot reproduce. +Use Dispatch's coordinated deployment workflow. It owns the coupled Vercel, Tilde, environment, and Sandbox setup that a generic `vercel deploy` cannot reproduce. ## Inspect before acting 1. Read `README.md` under **Deploy**, `package.json`, `cli/src/commands/deploy.ts`, the relevant `packages/*-service-provider/src/vercel/` implementation, and its `assets/` directory. 2. Check `git status --short --branch` and whether `.vercel/project.json` exists. Read linked-project metadata only when needed; do not edit `.vercel/` by hand. 3. Read the installed CLI and SDK versions from `package.json`. Consult the current official Vercel docs before changing an API or configuration shape; do not rely on remembered signatures. -4. Never print, grep into chat, or pass secrets on the command line. Treat `.env.local`, `.openbot-deploy/secrets.enc.env`, Vercel tokens, Tilde credentials, and setup codes as secret material. +4. Never print, grep into chat, or pass secrets on the command line. Treat `.env.local`, `.dispatch-deploy/secrets.enc.env`, Vercel tokens, Tilde credentials, and setup codes as secret material. ## Deploy @@ -41,9 +41,9 @@ The deployment coordinator prepares the Vercel project and stable origin, allows Use the deployment coordinator and Vercel service provider with a preview target so the provider builds the prebuilt artifact and materializes its project configuration. Do not add a repository-root `vercel.json` or bypass the service provider with a raw source deployment. Use the linked project and explicit team scope already established for the checkout. Do not reconcile production Tilde resources or overwrite production environment variables for a preview. Inspect the resulting deployment and verify the changed user flow when credentials and authorization permit. -## Preserve OpenBot's Vercel contract +## Preserve Dispatch's Vercel contract -- Keep Vercel entrypoints and configuration as `*.hbs` files in their owning provider's `vercel/assets/` directory. Render them through `@tryopenbot/utilities`; the deploy lifecycle materializes `vercel.json` in the ignored artifact root. +- Keep Vercel entrypoints and configuration as `*.hbs` files in their owning provider's `vercel/assets/` directory. Render them through `@trytilde/dispatch-utilities`; the deploy lifecycle materializes `vercel.json` in the ignored artifact root. - Keep `.vercel/output/config.json` aligned with the generated functions and static assets; it owns routing for prebuilt deployments. - Keep `/rpc/*`, `/healthz`, and SPA behavior aligned with `apps/control-service` and `apps/web`. - Keep provider secrets in the control-plane environment provider; never copy them into a Sandbox. diff --git a/.agents/skills/vercel/agents/openai.yaml b/.agents/skills/vercel/agents/openai.yaml index cebf70f8..5fb600bd 100644 --- a/.agents/skills/vercel/agents/openai.yaml +++ b/.agents/skills/vercel/agents/openai.yaml @@ -1,4 +1,4 @@ interface: - display_name: "Vercel for OpenBot" - short_description: "Deploy and operate OpenBot on Vercel" - default_prompt: "Use $vercel to deploy or troubleshoot this OpenBot project on Vercel." + display_name: "Vercel for Dispatch" + short_description: "Deploy and operate Dispatch on Vercel" + default_prompt: "Use $vercel to deploy or troubleshoot this Dispatch project on Vercel." diff --git a/.changeset/README.md b/.changeset/README.md index 65d47b45..7b8a6b27 100644 --- a/.changeset/README.md +++ b/.changeset/README.md @@ -1,6 +1,6 @@ # Changesets -Add one Markdown file here for owner-visible behavior or package API changes. Every OpenBot workspace package belongs to one fixed version group, so release versions move together. +Add one Markdown file here for owner-visible behavior or package API changes. Every Dispatch workspace package belongs to one fixed version group, so release versions move together. ```bash pnpm changeset diff --git a/.changeset/accept-prefixed-memory-sync-error.md b/.changeset/accept-prefixed-memory-sync-error.md index 1ae49cd5..95405ec2 100644 --- a/.changeset/accept-prefixed-memory-sync-error.md +++ b/.changeset/accept-prefixed-memory-sync-error.md @@ -1,23 +1,23 @@ --- -"@tryopenbot/agent-provider": patch -"@tryopenbot/agent-service-provider": patch -"@tryopenbot/auth-provider": patch -"openbot": patch -"@tryopenbot/computer-service-provider": patch -"@tryopenbot/client-runtime": patch -"@tryopenbot/computer-tools": patch -"@tryopenbot/computer-service": patch -"@tryopenbot/computer-service-proto": patch -"@tryopenbot/configuration": patch -"@tryopenbot/desktop": patch -"@tryopenbot/utilities": patch -"@tryopenbot/platform-integrations": patch -"@tryopenbot/control-service-provider": patch -"@tryopenbot/runtime-provider": patch -"@tryopenbot/control-service": patch -"@tryopenbot/ui": patch -"@tryopenbot/web": patch -"@tryopenbot/git-provider": patch +"@trytilde/dispatch-agent-provider": patch +"@trytilde/dispatch-agent-service-provider": patch +"@trytilde/dispatch-auth-provider": patch +"@trytilde/cli": patch +"@trytilde/dispatch-computer-service-provider": patch +"@trytilde/dispatch-client-runtime": patch +"@trytilde/dispatch-computer-tools": patch +"@trytilde/dispatch-computer-service": patch +"@trytilde/dispatch-computer-service-proto": patch +"@trytilde/dispatch-configuration": patch +"@trytilde/dispatch-desktop": patch +"@trytilde/dispatch-utilities": patch +"@trytilde/dispatch-platform-integrations": patch +"@trytilde/dispatch-control-service-provider": patch +"@trytilde/dispatch-runtime-provider": patch +"@trytilde/dispatch-control-service": patch +"@trytilde/dispatch-ui": patch +"@trytilde/dispatch-web": patch +"@trytilde/dispatch-git-provider": patch --- Recognize Tilde's service-unavailable prefix on the retryable memory-binding checkpoint. diff --git a/.changeset/add-agent-avatar-entry.md b/.changeset/add-agent-avatar-entry.md index 26aaa876..6bc17853 100644 --- a/.changeset/add-agent-avatar-entry.md +++ b/.changeset/add-agent-avatar-entry.md @@ -1,23 +1,23 @@ --- -"@tryopenbot/agent-provider": minor -"@tryopenbot/agent-service-provider": minor -"@tryopenbot/auth-provider": minor -"openbot": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/client-runtime": minor -"@tryopenbot/computer-tools": minor -"@tryopenbot/computer-service": minor -"@tryopenbot/computer-service-proto": minor -"@tryopenbot/configuration": minor -"@tryopenbot/desktop": minor -"@tryopenbot/utilities": minor -"@tryopenbot/platform-integrations": minor -"@tryopenbot/control-service-provider": minor -"@tryopenbot/runtime-provider": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor -"@tryopenbot/git-provider": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/dispatch-auth-provider": minor +"@trytilde/cli": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-client-runtime": minor +"@trytilde/dispatch-computer-tools": minor +"@trytilde/dispatch-computer-service": minor +"@trytilde/dispatch-computer-service-proto": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-utilities": minor +"@trytilde/dispatch-platform-integrations": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-runtime-provider": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor +"@trytilde/dispatch-git-provider": minor --- -Add a standalone `AgentAvatar` entry with component-scoped styles for applications that do not use the complete OpenBot interface. +Add a standalone `AgentAvatar` entry with component-scoped styles for applications that do not use the complete Dispatch interface. diff --git a/.changeset/add-agent-context-compaction.md b/.changeset/add-agent-context-compaction.md index 2314c864..a14bbf52 100644 --- a/.changeset/add-agent-context-compaction.md +++ b/.changeset/add-agent-context-compaction.md @@ -1,5 +1,5 @@ --- -"openbot": minor +"@trytilde/cli": minor "@trytilde/sdk": minor "@trytilde/sdk-vercel-ai-node": minor --- diff --git a/.changeset/add-agent-workspaces.md b/.changeset/add-agent-workspaces.md index b999b866..4a4f5893 100644 --- a/.changeset/add-agent-workspaces.md +++ b/.changeset/add-agent-workspaces.md @@ -1,20 +1,20 @@ --- -"@tryopenbot/agent-provider": minor -"@tryopenbot/agent-service-provider": minor -"openbot": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/computer-tools": minor -"@tryopenbot/computer-service": minor -"@tryopenbot/computer-service-proto": minor -"@tryopenbot/configuration": minor -"@tryopenbot/desktop": minor -"@tryopenbot/utilities": minor -"@tryopenbot/platform-integrations": minor -"@tryopenbot/control-service-provider": minor -"@tryopenbot/runtime-provider": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/cli": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-computer-tools": minor +"@trytilde/dispatch-computer-service": minor +"@trytilde/dispatch-computer-service-proto": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-utilities": minor +"@trytilde/dispatch-platform-integrations": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-runtime-provider": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor --- Add agent-centric chat workspaces with rich streamed messages and isolated live Computer desktops per agent. diff --git a/.changeset/add-automatic-memory.md b/.changeset/add-automatic-memory.md index c089b248..0a4db408 100644 --- a/.changeset/add-automatic-memory.md +++ b/.changeset/add-automatic-memory.md @@ -2,25 +2,25 @@ "@trytilde/api-client": minor "@trytilde/sdk": minor "@trytilde/sdk-vercel-ai-node": minor -"@tryopenbot/agent-provider": minor -"@tryopenbot/agent-service-provider": minor -"@tryopenbot/auth-provider": minor -"openbot": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/client-runtime": minor -"@tryopenbot/computer-tools": minor -"@tryopenbot/computer-service": minor -"@tryopenbot/computer-service-proto": minor -"@tryopenbot/configuration": minor -"@tryopenbot/desktop": minor -"@tryopenbot/utilities": minor -"@tryopenbot/platform-integrations": minor -"@tryopenbot/control-service-provider": minor -"@tryopenbot/runtime-provider": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor -"@tryopenbot/git-provider": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/dispatch-auth-provider": minor +"@trytilde/cli": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-client-runtime": minor +"@trytilde/dispatch-computer-tools": minor +"@trytilde/dispatch-computer-service": minor +"@trytilde/dispatch-computer-service-proto": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-utilities": minor +"@trytilde/dispatch-platform-integrations": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-runtime-provider": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor +"@trytilde/dispatch-git-provider": minor --- -Add automatic memory recall, owner-managed facts, and a least-privilege Memory Catcher synthesizer to OpenBot bots. +Add automatic memory recall, owner-managed facts, and a least-privilege Memory Catcher synthesizer to Dispatch bots. diff --git a/.changeset/add-chatkit-search.md b/.changeset/add-chatkit-search.md index 00caa3c5..c23152c2 100644 --- a/.changeset/add-chatkit-search.md +++ b/.changeset/add-chatkit-search.md @@ -1,10 +1,10 @@ --- "@trytilde/api-client": minor "@trytilde/sdk": minor -"@tryopenbot/client-runtime": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor -"@tryopenbot/desktop": minor +"@trytilde/dispatch-client-runtime": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor +"@trytilde/dispatch-desktop": minor --- Add consolidated ChatKit search across bots, conversation titles, and messages to the shared client runtime and expose it in the web, Electron, and mobile clients. diff --git a/.changeset/add-chatkit-tool-observability.md b/.changeset/add-chatkit-tool-observability.md index 1c63e182..9b9c7a0a 100644 --- a/.changeset/add-chatkit-tool-observability.md +++ b/.changeset/add-chatkit-tool-observability.md @@ -2,25 +2,25 @@ "@trytilde/api-client": minor "@trytilde/sdk": minor "@trytilde/sdk-vercel-ai-node": minor -"@tryopenbot/agent-provider": patch -"@tryopenbot/agent-service-provider": patch -"@tryopenbot/auth-provider": patch -"openbot": patch -"@tryopenbot/computer-service-provider": patch -"@tryopenbot/client-runtime": patch -"@tryopenbot/computer-tools": patch -"@tryopenbot/computer-service": patch -"@tryopenbot/computer-service-proto": patch -"@tryopenbot/configuration": patch -"@tryopenbot/desktop": patch -"@tryopenbot/utilities": patch -"@tryopenbot/platform-integrations": patch -"@tryopenbot/control-service-provider": patch -"@tryopenbot/runtime-provider": patch -"@tryopenbot/control-service": patch -"@tryopenbot/ui": patch -"@tryopenbot/web": patch -"@tryopenbot/git-provider": patch +"@trytilde/dispatch-agent-provider": patch +"@trytilde/dispatch-agent-service-provider": patch +"@trytilde/dispatch-auth-provider": patch +"@trytilde/cli": patch +"@trytilde/dispatch-computer-service-provider": patch +"@trytilde/dispatch-client-runtime": patch +"@trytilde/dispatch-computer-tools": patch +"@trytilde/dispatch-computer-service": patch +"@trytilde/dispatch-computer-service-proto": patch +"@trytilde/dispatch-configuration": patch +"@trytilde/dispatch-desktop": patch +"@trytilde/dispatch-utilities": patch +"@trytilde/dispatch-platform-integrations": patch +"@trytilde/dispatch-control-service-provider": patch +"@trytilde/dispatch-runtime-provider": patch +"@trytilde/dispatch-control-service": patch +"@trytilde/dispatch-ui": patch +"@trytilde/dispatch-web": patch +"@trytilde/dispatch-git-provider": patch --- -Add canonical ChatKit registration and execution reporting for local Vercel AI SDK tools, including first-class dynamic child correlation, and enable it in generated OpenBot agents. +Add canonical ChatKit registration and execution reporting for local Vercel AI SDK tools, including first-class dynamic child correlation, and enable it in generated Dispatch agents. diff --git a/.changeset/add-chatkit-work-management.md b/.changeset/add-chatkit-work-management.md index 25e28378..4ea23c31 100644 --- a/.changeset/add-chatkit-work-management.md +++ b/.changeset/add-chatkit-work-management.md @@ -1,6 +1,6 @@ --- "@trytilde/sdk": minor -"openbot": minor +"@trytilde/cli": minor --- Add session-bound goal and task management APIs and default agent tools for durable work tracking. diff --git a/.changeset/add-cli-package.md b/.changeset/add-cli-package.md index 6fa4831f..8710c06a 100644 --- a/.changeset/add-cli-package.md +++ b/.changeset/add-cli-package.md @@ -1,6 +1,6 @@ --- -"openbot": minor -"@tryopenbot/control-service": patch +"@trytilde/cli": minor +"@trytilde/dispatch-control-service": patch --- Move repository operations into the React Ink CLI and make it own local Hono startup. diff --git a/.changeset/add-codex-subscription-inference.md b/.changeset/add-codex-subscription-inference.md index c507042e..36714140 100644 --- a/.changeset/add-codex-subscription-inference.md +++ b/.changeset/add-codex-subscription-inference.md @@ -1,24 +1,24 @@ --- -"@tryopenbot/agent-provider": minor -"@tryopenbot/agent-service-provider": minor -"@tryopenbot/auth-provider": minor -"openbot": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/client-runtime": minor -"@tryopenbot/computer-tools": minor -"@tryopenbot/computer-service": minor -"@tryopenbot/computer-service-proto": minor -"@tryopenbot/configuration": minor -"@tryopenbot/desktop": minor -"@tryopenbot/utilities": minor -"@tryopenbot/platform-integrations": minor -"@tryopenbot/control-service-provider": minor -"@tryopenbot/runtime-provider": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor -"@tryopenbot/git-provider": minor -"@tryopenbot/inference-provider": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/dispatch-auth-provider": minor +"@trytilde/cli": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-client-runtime": minor +"@trytilde/dispatch-computer-tools": minor +"@trytilde/dispatch-computer-service": minor +"@trytilde/dispatch-computer-service-proto": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-utilities": minor +"@trytilde/dispatch-platform-integrations": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-runtime-provider": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor +"@trytilde/dispatch-git-provider": minor +"@trytilde/dispatch-inference-provider": minor --- Add optional local and Vercel-hosted ChatGPT subscription inference with Codex device-code authentication, provider-owned agent templates and deployment assets, AI SDK 7 support, resumable staged init selectors that immediately configure the selected provider while offering every built-in alternative, checkout-scoped gitignored user configuration, and correct separation of provider-managed and team-owned Tilde registry membership. diff --git a/.changeset/add-coding-agent-chatkit-audit.md b/.changeset/add-coding-agent-chatkit-audit.md index e13f0127..00660fee 100644 --- a/.changeset/add-coding-agent-chatkit-audit.md +++ b/.changeset/add-coding-agent-chatkit-audit.md @@ -3,25 +3,25 @@ "@trytilde/sdk-codex": minor "@trytilde/sdk-claude-code": minor "@trytilde/sdk-cursor": minor -"@tryopenbot/agent-provider": minor -"@tryopenbot/agent-service-provider": minor -"@tryopenbot/auth-provider": minor -"openbot": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/client-runtime": minor -"@tryopenbot/computer-tools": minor -"@tryopenbot/computer-service": minor -"@tryopenbot/computer-service-proto": minor -"@tryopenbot/configuration": minor -"@tryopenbot/desktop": minor -"@tryopenbot/utilities": minor -"@tryopenbot/platform-integrations": minor -"@tryopenbot/control-service-provider": minor -"@tryopenbot/runtime-provider": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor -"@tryopenbot/git-provider": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/dispatch-auth-provider": minor +"@trytilde/cli": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-client-runtime": minor +"@trytilde/dispatch-computer-tools": minor +"@trytilde/dispatch-computer-service": minor +"@trytilde/dispatch-computer-service-proto": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-utilities": minor +"@trytilde/dispatch-platform-integrations": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-runtime-provider": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor +"@trytilde/dispatch-git-provider": minor --- -Add Codex, Claude Code, and Cursor hook adapters that record searchable ChatKit messages and canonical tool executions while `openbot plugin` installs Tilde MCP servers and skills. +Add Codex, Claude Code, and Cursor hook adapters that record searchable ChatKit messages and canonical tool executions while `tilde plugin` installs Tilde MCP servers and skills. diff --git a/.changeset/add-computer-provider-boundary.md b/.changeset/add-computer-provider-boundary.md index beefa8c6..763d8c64 100644 --- a/.changeset/add-computer-provider-boundary.md +++ b/.changeset/add-computer-provider-boundary.md @@ -1,13 +1,13 @@ --- -"@tryopenbot/agent-provider": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/computer-service": minor -"@tryopenbot/computer-service-proto": minor -"@tryopenbot/configuration": minor -"@tryopenbot/desktop": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-computer-service": minor +"@trytilde/dispatch-computer-service-proto": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor --- Add the internal computer provider boundary, Microsandbox and Vercel implementations, a capability-protected computer service, and a shared multi-stage OCI image build and deployment lifecycle. diff --git a/.changeset/add-cua-driver-computer-use.md b/.changeset/add-cua-driver-computer-use.md index 35e203cf..6a8406e4 100644 --- a/.changeset/add-cua-driver-computer-use.md +++ b/.changeset/add-cua-driver-computer-use.md @@ -1,23 +1,23 @@ --- -"@tryopenbot/agent-provider": minor -"@tryopenbot/agent-service-provider": minor -"@tryopenbot/auth-provider": minor -"openbot": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/client-runtime": minor -"@tryopenbot/computer-tools": minor -"@tryopenbot/computer-service": minor -"@tryopenbot/computer-service-proto": minor -"@tryopenbot/configuration": minor -"@tryopenbot/desktop": minor -"@tryopenbot/utilities": minor -"@tryopenbot/platform-integrations": minor -"@tryopenbot/control-service-provider": minor -"@tryopenbot/runtime-provider": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor -"@tryopenbot/git-provider": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/dispatch-auth-provider": minor +"@trytilde/cli": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-client-runtime": minor +"@trytilde/dispatch-computer-tools": minor +"@trytilde/dispatch-computer-service": minor +"@trytilde/dispatch-computer-service-proto": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-utilities": minor +"@trytilde/dispatch-platform-integrations": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-runtime-provider": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor +"@trytilde/dispatch-git-provider": minor --- -Make Cua Driver the Computer's programmatic GUI backend, expose its runtime catalog as direct local tools, and reconcile canonical and OpenBot computer-use skills for every agent. +Make Cua Driver the Computer's programmatic GUI backend, expose its runtime catalog as direct local tools, and reconcile canonical and Dispatch computer-use skills for every agent. diff --git a/.changeset/add-desktop-release-publication.md b/.changeset/add-desktop-release-publication.md index b14c9a92..7b3a7676 100644 --- a/.changeset/add-desktop-release-publication.md +++ b/.changeset/add-desktop-release-publication.md @@ -1,6 +1,6 @@ --- -"openbot": minor -"@tryopenbot/desktop": minor +"@trytilde/cli": minor +"@trytilde/dispatch-desktop": minor --- -Add `openbot desktop release` and a manually triggered desktop release workflow. Desktop artifacts publish to the shared updates bucket under a fork-guarded prefix with a `version.json` update manifest, and macOS builds are signed and notarized when credentials are present. +Add `tilde desktop release` and a manually triggered desktop release workflow. Desktop artifacts publish to the shared updates bucket under a fork-guarded prefix with a `version.json` update manifest, and macOS builds are signed and notarized when credentials are present. diff --git a/.changeset/add-developer-workflow-commands.md b/.changeset/add-developer-workflow-commands.md index a96149f3..510dce5a 100644 --- a/.changeset/add-developer-workflow-commands.md +++ b/.changeset/add-developer-workflow-commands.md @@ -1,5 +1,5 @@ --- -"openbot": minor +"@trytilde/cli": minor --- -Add the developer workflow to the `openbot` CLI for humans and sandboxed agents working on the codebase. Repository gates `e2e` and `desktop package` join `check`, `build`, and `test`; a `mobile` command group carries Expo runs with the Android and Node toolchain resolved, an idempotent headless emulator with loopback VNC, SDK setup, AVD creation, screenshots, logs, and doctor; `connect` and `remote` reach fork-configured mac and Linux dev hosts over ssh. Root scripts adopt a verb:target taxonomy (`dev:mobile:*`, `connect`, `dev:remote`, `doctor`). +Add the developer workflow to the Tilde CLI for humans and sandboxed agents working on the codebase. Repository gates `e2e` and `desktop package` join `check`, `build`, and `test`; a `mobile` command group carries Expo runs with the Android and Node toolchain resolved, an idempotent headless emulator with loopback VNC, SDK setup, AVD creation, screenshots, logs, and doctor; `connect` and `remote` reach fork-configured mac and Linux dev hosts over ssh. Root scripts adopt a verb:target taxonomy (`dev:mobile:*`, `connect`, `dev:remote`, `doctor`). diff --git a/.changeset/add-domain-agent-provider.md b/.changeset/add-domain-agent-provider.md index ff22283a..ca021471 100644 --- a/.changeset/add-domain-agent-provider.md +++ b/.changeset/add-domain-agent-provider.md @@ -1,10 +1,10 @@ --- -"@tryopenbot/agent-provider": minor -"@tryopenbot/configuration": minor -"@tryopenbot/desktop": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor --- Add domain-owned agent provider APIs and a provider-neutral control service protocol for Tilde agents and sessions. diff --git a/.changeset/add-durable-agent-jobs.md b/.changeset/add-durable-agent-jobs.md index 50fe668d..6be2c20f 100644 --- a/.changeset/add-durable-agent-jobs.md +++ b/.changeset/add-durable-agent-jobs.md @@ -1,7 +1,7 @@ --- "@trytilde/sdk": minor -"@tryopenbot/inference-provider": minor -"openbot": minor +"@trytilde/dispatch-inference-provider": minor +"@trytilde/cli": minor --- Add high-level durable background-agent job helpers and a default authored tool for delegating, inspecting, steering, stopping, resuming, and collecting child work. diff --git a/.changeset/add-durable-agent-runs.md b/.changeset/add-durable-agent-runs.md index 1e5c8a98..7b98d6c6 100644 --- a/.changeset/add-durable-agent-runs.md +++ b/.changeset/add-durable-agent-runs.md @@ -1,5 +1,5 @@ --- -"openbot": minor +"@trytilde/cli": minor "@trytilde/sdk": minor "@trytilde/sdk-vercel-ai-node": minor --- diff --git a/.changeset/add-durable-agent-setup.md b/.changeset/add-durable-agent-setup.md index 4d2ba0ab..c8aafe71 100644 --- a/.changeset/add-durable-agent-setup.md +++ b/.changeset/add-durable-agent-setup.md @@ -1,23 +1,23 @@ --- -"@tryopenbot/agent-provider": minor -"@tryopenbot/agent-service-provider": minor -"@tryopenbot/auth-provider": minor -"openbot": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/client-runtime": minor -"@tryopenbot/computer-tools": minor -"@tryopenbot/computer-service": minor -"@tryopenbot/computer-service-proto": minor -"@tryopenbot/configuration": minor -"@tryopenbot/desktop": minor -"@tryopenbot/utilities": minor -"@tryopenbot/platform-integrations": minor -"@tryopenbot/control-service-provider": minor -"@tryopenbot/runtime-provider": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor -"@tryopenbot/git-provider": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/dispatch-auth-provider": minor +"@trytilde/cli": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-client-runtime": minor +"@trytilde/dispatch-computer-tools": minor +"@trytilde/dispatch-computer-service": minor +"@trytilde/dispatch-computer-service-proto": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-utilities": minor +"@trytilde/dispatch-platform-integrations": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-runtime-provider": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor +"@trytilde/dispatch-git-provider": minor --- Run new-agent setup durably in the trusted development Computer and resume its progress after navigation or reload. diff --git a/.changeset/add-durable-work-pane-and-routines.md b/.changeset/add-durable-work-pane-and-routines.md index b72f8c5b..f3796702 100644 --- a/.changeset/add-durable-work-pane-and-routines.md +++ b/.changeset/add-durable-work-pane-and-routines.md @@ -1,9 +1,9 @@ --- "@trytilde/sdk": minor -"@tryopenbot/client-runtime": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor -"openbot": minor +"@trytilde/dispatch-client-runtime": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor +"@trytilde/cli": minor --- Expose durable goals, tasks, background jobs, and routines through the shared web/Electron Work pane and teach default agents when to plan, delegate, steer, and schedule recurring work. diff --git a/.changeset/add-encrypted-initialization.md b/.changeset/add-encrypted-initialization.md index 066d3e45..8ea0af89 100644 --- a/.changeset/add-encrypted-initialization.md +++ b/.changeset/add-encrypted-initialization.md @@ -1,19 +1,19 @@ --- -"@tryopenbot/agent-provider": minor -"openbot": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/computer-service": minor -"@tryopenbot/computer-service-proto": minor -"@tryopenbot/configuration": minor -"@tryopenbot/inference-provider": minor -"@tryopenbot/platform-integrations": minor -"@tryopenbot/desktop": minor -"@tryopenbot/control-service-provider": minor -"@tryopenbot/agent-service-provider": minor -"@tryopenbot/runtime-provider": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/cli": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-computer-service": minor +"@trytilde/dispatch-computer-service-proto": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-inference-provider": minor +"@trytilde/dispatch-platform-integrations": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/dispatch-runtime-provider": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor --- Add interactive encrypted configuration initialization and provider-defined onboarding questions. diff --git a/.changeset/add-exe-code-storage.md b/.changeset/add-exe-code-storage.md index 17920bd3..e351766b 100644 --- a/.changeset/add-exe-code-storage.md +++ b/.changeset/add-exe-code-storage.md @@ -1,23 +1,23 @@ --- -"@tryopenbot/agent-provider": minor -"@tryopenbot/agent-service-provider": minor -"@tryopenbot/auth-provider": minor -"openbot": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/client-runtime": minor -"@tryopenbot/computer-tools": minor -"@tryopenbot/computer-service": minor -"@tryopenbot/computer-service-proto": minor -"@tryopenbot/configuration": minor -"@tryopenbot/desktop": minor -"@tryopenbot/utilities": minor -"@tryopenbot/platform-integrations": minor -"@tryopenbot/control-service-provider": minor -"@tryopenbot/runtime-provider": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor -"@tryopenbot/git-provider": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/dispatch-auth-provider": minor +"@trytilde/cli": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-client-runtime": minor +"@trytilde/dispatch-computer-tools": minor +"@trytilde/dispatch-computer-service": minor +"@trytilde/dispatch-computer-service-proto": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-utilities": minor +"@trytilde/dispatch-platform-integrations": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-runtime-provider": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor +"@trytilde/dispatch-git-provider": minor --- Add a single-VM exe.dev runtime with a host-native Computer, trusted development mode, public noVNC routing, and repository-scoped Code Storage Git with optional GitHub sync. diff --git a/.changeset/add-expo-client-runtime.md b/.changeset/add-expo-client-runtime.md index 85275327..2605a5eb 100644 --- a/.changeset/add-expo-client-runtime.md +++ b/.changeset/add-expo-client-runtime.md @@ -1,10 +1,10 @@ --- -"@tryopenbot/client-runtime": minor -"@tryopenbot/web": minor -"@tryopenbot/desktop": minor -"@tryopenbot/auth-provider": minor -"@tryopenbot/control-service": minor -"@tryopenbot/control-service-provider": minor +"@trytilde/dispatch-client-runtime": minor +"@trytilde/dispatch-web": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-auth-provider": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-control-service-provider": minor --- Add a shared Zustand client runtime and grouped UI contracts, migrate web and Electron authentication and chat onto it, and add the first Expo mobile client with control-service selection, native authentication, sidebar, and conversation workflows. diff --git a/.changeset/add-factory-agent-and-git-provider.md b/.changeset/add-factory-agent-and-git-provider.md index b6c3d7b5..bd7ba701 100644 --- a/.changeset/add-factory-agent-and-git-provider.md +++ b/.changeset/add-factory-agent-and-git-provider.md @@ -1,14 +1,14 @@ --- -"@tryopenbot/git-provider": minor -"@tryopenbot/agent-provider": minor -"@tryopenbot/agent-service-provider": minor -"openbot": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/control-service": minor -"@tryopenbot/configuration": minor -"@tryopenbot/runtime-provider": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor +"@trytilde/dispatch-git-provider": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/cli": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-runtime-provider": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor --- -Replace the Hello World primary agent with the Factory agent and give it an end-to-end build/test/deploy loop. A new `@tryopenbot/git-provider` derives the fork repository from the checkout's origin remote, brokers a GitHub App credential through Tilde, and reconciles GitHub REST and git-over-HTTPS reverse-proxy profiles; the trusted development sandbox attaches its seeded source tree to the owner's fork through that proxy so the factory agent has an authenticated git client without holding a token. The factory agent's computer tools target the development sandbox, its skills cover creating, locally testing (Tilde local-runtime tunnel), and deploying agents, and the primary agent additionally receives the brokered GitHub toolkit on its MCP server. A background orchestrator (`openbot orchestrate`) owns the lifecycle: edits route every agent through the local-runtime tunnel with hot reload, and settled edits are verified, published to the openbot/sandbox-edits branch, and redeployed automatically. Every subagent can edit its own source in the development sandbox, and the web workspace's New Agent entry scaffolds, registers, and opens a chat with the agent itself. +Replace the Hello World primary agent with the Factory agent and give it an end-to-end build/test/deploy loop. A new `@trytilde/dispatch-git-provider` derives the fork repository from the checkout's origin remote, brokers a GitHub App credential through Tilde, and reconciles GitHub REST and git-over-HTTPS reverse-proxy profiles; the trusted development sandbox attaches its seeded source tree to the owner's fork through that proxy so the factory agent has an authenticated git client without holding a token. The factory agent's computer tools target the development sandbox, its skills cover creating, locally testing (Tilde local-runtime tunnel), and deploying agents, and the primary agent additionally receives the brokered GitHub toolkit on its MCP server. A background orchestrator (`dispatch orchestrate`) owns the lifecycle: edits route every agent through the local-runtime tunnel with hot reload, and settled edits are verified, published to the dispatch/sandbox-edits branch, and redeployed automatically. Every subagent can edit its own source in the development sandbox, and the web workspace's New Agent entry scaffolds, registers, and opens a chat with the agent itself. diff --git a/.changeset/add-hosted-inference-metering.md b/.changeset/add-hosted-inference-metering.md index 39e0ae96..6ccd663c 100644 --- a/.changeset/add-hosted-inference-metering.md +++ b/.changeset/add-hosted-inference-metering.md @@ -1,9 +1,9 @@ --- "@trytilde/sdk": minor "@trytilde/sdk-vercel-ai-node": minor -"@tryopenbot/inference-provider": minor -"@tryopenbot/platform-integrations": minor -"openbot": minor +"@trytilde/dispatch-inference-provider": minor +"@trytilde/dispatch-platform-integrations": minor +"@trytilde/cli": minor --- Add AI-credit reservation and receipt APIs, meter managed project-OIDC model calls with durable AgentRun effect recovery, release authoritative BYOK receipts, and exclude direct-key and subscription-backed inference. diff --git a/.changeset/add-in-chat-connector-configuration.md b/.changeset/add-in-chat-connector-configuration.md index f2e02fa9..bf10e7af 100644 --- a/.changeset/add-in-chat-connector-configuration.md +++ b/.changeset/add-in-chat-connector-configuration.md @@ -1,10 +1,10 @@ --- -"@tryopenbot/connector-tools": minor -"@tryopenbot/client-runtime": minor -"@tryopenbot/control-service": minor -"@tryopenbot/agent-provider": minor -"@tryopenbot/ui": minor -"openbot": minor +"@trytilde/dispatch-connector-tools": minor +"@trytilde/dispatch-client-runtime": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-ui": minor +"@trytilde/cli": minor --- Bots configure their own connectors from chat. The new `configure_connector` diff --git a/.changeset/add-multiplayer-room-ui.md b/.changeset/add-multiplayer-room-ui.md index a214b566..f8558c7a 100644 --- a/.changeset/add-multiplayer-room-ui.md +++ b/.changeset/add-multiplayer-room-ui.md @@ -1,5 +1,5 @@ --- -"@tryopenbot/client-runtime": minor +"@trytilde/dispatch-client-runtime": minor --- Add dormant multiplayer room roster and invitation runtime contracts for a future owner UI. diff --git a/.changeset/add-participant-session-activity.md b/.changeset/add-participant-session-activity.md index 49955c66..095cbb7a 100644 --- a/.changeset/add-participant-session-activity.md +++ b/.changeset/add-participant-session-activity.md @@ -1,23 +1,23 @@ --- -"@tryopenbot/agent-provider": minor -"@tryopenbot/agent-service-provider": minor -"@tryopenbot/auth-provider": minor -"openbot": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/client-runtime": minor -"@tryopenbot/computer-tools": minor -"@tryopenbot/computer-service": minor -"@tryopenbot/computer-service-proto": minor -"@tryopenbot/configuration": minor -"@tryopenbot/desktop": minor -"@tryopenbot/utilities": minor -"@tryopenbot/platform-integrations": minor -"@tryopenbot/control-service-provider": minor -"@tryopenbot/runtime-provider": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor -"@tryopenbot/git-provider": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/dispatch-auth-provider": minor +"@trytilde/cli": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-client-runtime": minor +"@trytilde/dispatch-computer-tools": minor +"@trytilde/dispatch-computer-service": minor +"@trytilde/dispatch-computer-service-proto": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-utilities": minor +"@trytilde/dispatch-platform-integrations": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-runtime-provider": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor +"@trytilde/dispatch-git-provider": minor --- Show participant joins and leaves as lightweight session activity while keeping them out of the message transcript. diff --git a/.changeset/add-plugins-catalog-prototype.md b/.changeset/add-plugins-catalog-prototype.md index a4f69247..be9b3c10 100644 --- a/.changeset/add-plugins-catalog-prototype.md +++ b/.changeset/add-plugins-catalog-prototype.md @@ -1,23 +1,23 @@ --- -"@tryopenbot/agent-provider": minor -"@tryopenbot/agent-service-provider": minor -"@tryopenbot/auth-provider": minor -"openbot": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/client-runtime": minor -"@tryopenbot/computer-tools": minor -"@tryopenbot/computer-service": minor -"@tryopenbot/computer-service-proto": minor -"@tryopenbot/configuration": minor -"@tryopenbot/desktop": minor -"@tryopenbot/utilities": minor -"@tryopenbot/platform-integrations": minor -"@tryopenbot/control-service-provider": minor -"@tryopenbot/runtime-provider": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor -"@tryopenbot/git-provider": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/dispatch-auth-provider": minor +"@trytilde/cli": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-client-runtime": minor +"@trytilde/dispatch-computer-tools": minor +"@trytilde/dispatch-computer-service": minor +"@trytilde/dispatch-computer-service-proto": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-utilities": minor +"@trytilde/dispatch-platform-integrations": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-runtime-provider": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor +"@trytilde/dispatch-git-provider": minor --- Add the initial settings catalogue for browsing and assigning tools and skills to bots. diff --git a/.changeset/add-rich-content-surfaces.md b/.changeset/add-rich-content-surfaces.md index 06e7c8a8..960abf35 100644 --- a/.changeset/add-rich-content-surfaces.md +++ b/.changeset/add-rich-content-surfaces.md @@ -1,5 +1,5 @@ --- -"@tryopenbot/ui": minor +"@trytilde/dispatch-ui": minor --- Add reusable rich content, full Markdown, code, Computer handoff, model picker, form, status, and animated voice components with Storybook coverage. diff --git a/.changeset/add-routines-and-signals.md b/.changeset/add-routines-and-signals.md index a98e89ff..ec1d7b9f 100644 --- a/.changeset/add-routines-and-signals.md +++ b/.changeset/add-routines-and-signals.md @@ -1,8 +1,8 @@ --- -"@tryopenbot/control-service": minor -"@tryopenbot/client-runtime": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-client-runtime": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor --- Add routines and signals: per-agent routines with schedule and provider-event diff --git a/.changeset/add-runtime-provider.md b/.changeset/add-runtime-provider.md index d4c93c88..8699fc9a 100644 --- a/.changeset/add-runtime-provider.md +++ b/.changeset/add-runtime-provider.md @@ -1,11 +1,11 @@ --- -"@tryopenbot/control-service-provider": minor -"@tryopenbot/agent-service-provider": minor -"@tryopenbot/runtime-provider": minor -"openbot": patch -"@tryopenbot/configuration": patch -"@tryopenbot/agent-provider": patch -"@tryopenbot/computer-service-provider": patch +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/dispatch-runtime-provider": minor +"@trytilde/cli": patch +"@trytilde/dispatch-configuration": patch +"@trytilde/dispatch-agent-provider": patch +"@trytilde/dispatch-computer-service-provider": patch --- Add one-command provider lifecycle deployment with separate control and agent diff --git a/.changeset/add-safe-self-extension-proposals.md b/.changeset/add-safe-self-extension-proposals.md index 7bcad523..3c1ea429 100644 --- a/.changeset/add-safe-self-extension-proposals.md +++ b/.changeset/add-safe-self-extension-proposals.md @@ -1,6 +1,6 @@ --- "@trytilde/sdk": minor -"openbot": minor +"@trytilde/cli": minor --- Add durable human-reviewed self-extension proposals and a propose-only default agent tool. diff --git a/.changeset/add-shared-platform-initialization.md b/.changeset/add-shared-platform-initialization.md index cfe93f96..a335fdb8 100644 --- a/.changeset/add-shared-platform-initialization.md +++ b/.changeset/add-shared-platform-initialization.md @@ -1,19 +1,19 @@ --- -"@tryopenbot/agent-provider": minor -"@tryopenbot/agent-service-provider": minor -"openbot": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/computer-service": minor -"@tryopenbot/computer-service-proto": minor -"@tryopenbot/configuration": minor -"@tryopenbot/desktop": minor -"@tryopenbot/utilities": minor -"@tryopenbot/control-service-provider": minor -"@tryopenbot/runtime-provider": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor -"@tryopenbot/platform-integrations": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/cli": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-computer-service": minor +"@trytilde/dispatch-computer-service-proto": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-utilities": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-runtime-provider": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor +"@trytilde/dispatch-platform-integrations": minor --- Represent shared Tilde and Vercel access as concrete platform implementations, centralize their common request and deployment helpers, initialize each once across its dependent providers, and allow init to revisit existing provider configuration with stored prompt defaults. Load fork-owned TypeScript configuration through the standalone CLI's TypeScript loader so generated `.js` specifiers resolve their `.ts` sources. diff --git a/.changeset/add-skills-provider-boundary.md b/.changeset/add-skills-provider-boundary.md index b65f45d9..a3476ee0 100644 --- a/.changeset/add-skills-provider-boundary.md +++ b/.changeset/add-skills-provider-boundary.md @@ -1,10 +1,10 @@ --- -"@tryopenbot/agent-provider": minor -"@tryopenbot/configuration": minor -"@tryopenbot/desktop": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor --- Add domain-owned skills provider APIs, typed Tilde skill management, verified package assets, and owner control methods. diff --git a/.changeset/add-speaker-personal-tool-federation.md b/.changeset/add-speaker-personal-tool-federation.md index 33b099a9..9a1d7352 100644 --- a/.changeset/add-speaker-personal-tool-federation.md +++ b/.changeset/add-speaker-personal-tool-federation.md @@ -1,6 +1,6 @@ --- -"@tryopenbot/agent-provider": minor -"openbot": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/cli": minor "@trytilde/sdk-vercel-ai-node": minor --- diff --git a/.changeset/add-tilde-cloud-hosting.md b/.changeset/add-tilde-cloud-hosting.md index d22b15cd..2f7bd417 100644 --- a/.changeset/add-tilde-cloud-hosting.md +++ b/.changeset/add-tilde-cloud-hosting.md @@ -1,12 +1,12 @@ --- -"openbot": minor -"@tryopenbot/configuration": minor -"@tryopenbot/control-service-provider": minor -"@tryopenbot/agent-service-provider": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/git-provider": minor -"@tryopenbot/inference-provider": minor -"@tryopenbot/platform-integrations": minor +"@trytilde/cli": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-git-provider": minor +"@trytilde/dispatch-inference-provider": minor +"@trytilde/dispatch-platform-integrations": minor --- Add the Tilde Cloud runtime, managed Vercel credential boundary, persistent sandbox-local Git provider, managed owner identity files, and project-scoped OIDC access to Vercel Sandbox and AI Gateway. diff --git a/.changeset/add-tilde-installation-auth.md b/.changeset/add-tilde-installation-auth.md index de07c5bd..b4d9426f 100644 --- a/.changeset/add-tilde-installation-auth.md +++ b/.changeset/add-tilde-installation-auth.md @@ -1,21 +1,21 @@ --- -"@tryopenbot/agent-provider": minor -"@tryopenbot/agent-service-provider": minor -"@tryopenbot/auth-provider": minor -"openbot": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/computer-tools": minor -"@tryopenbot/computer-service": minor -"@tryopenbot/computer-service-proto": minor -"@tryopenbot/configuration": minor -"@tryopenbot/desktop": minor -"@tryopenbot/utilities": minor -"@tryopenbot/platform-integrations": minor -"@tryopenbot/control-service-provider": minor -"@tryopenbot/runtime-provider": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/dispatch-auth-provider": minor +"@trytilde/cli": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-computer-tools": minor +"@trytilde/dispatch-computer-service": minor +"@trytilde/dispatch-computer-service-proto": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-utilities": minor +"@trytilde/dispatch-platform-integrations": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-runtime-provider": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor --- -Add team-scoped Tilde sign-in, browser sessions, and secure desktop token refresh for OpenBot installations. +Add team-scoped Tilde sign-in, browser sessions, and secure desktop token refresh for Dispatch installations. diff --git a/.changeset/add-tools-provider.md b/.changeset/add-tools-provider.md index 48251bc5..b76a71e8 100644 --- a/.changeset/add-tools-provider.md +++ b/.changeset/add-tools-provider.md @@ -1,10 +1,10 @@ --- -"@tryopenbot/agent-provider": minor -"@tryopenbot/configuration": minor -"@tryopenbot/desktop": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor --- Add a domain-owned tools provider API and Tilde Harness SDK implementation for agent tool execution. diff --git a/.changeset/agent-resource-bundles.md b/.changeset/agent-resource-bundles.md index d476d7d6..9cab7316 100644 --- a/.changeset/agent-resource-bundles.md +++ b/.changeset/agent-resource-bundles.md @@ -1,23 +1,23 @@ --- -"@tryopenbot/agent-provider": minor -"@tryopenbot/agent-service-provider": minor -"@tryopenbot/auth-provider": minor -"openbot": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/client-runtime": minor -"@tryopenbot/computer-tools": minor -"@tryopenbot/computer-service": minor -"@tryopenbot/computer-service-proto": minor -"@tryopenbot/configuration": minor -"@tryopenbot/desktop": minor -"@tryopenbot/utilities": minor -"@tryopenbot/platform-integrations": minor -"@tryopenbot/control-service-provider": minor -"@tryopenbot/runtime-provider": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor -"@tryopenbot/git-provider": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/dispatch-auth-provider": minor +"@trytilde/cli": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-client-runtime": minor +"@trytilde/dispatch-computer-tools": minor +"@trytilde/dispatch-computer-service": minor +"@trytilde/dispatch-computer-service-proto": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-utilities": minor +"@trytilde/dispatch-platform-integrations": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-runtime-provider": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor +"@trytilde/dispatch-git-provider": minor "@trytilde/api-client": minor "@trytilde/sdk": minor --- diff --git a/.changeset/app-icons.md b/.changeset/app-icons.md index bae27f53..e927f776 100644 --- a/.changeset/app-icons.md +++ b/.changeset/app-icons.md @@ -1,6 +1,6 @@ --- -"@tryopenbot/desktop": minor -"@tryopenbot/web": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-web": minor --- -Carry the OpenBot mark across every client. Electron takes `apps/desktop/build/icon.png` as a rounded 1024px artwork, which electron-builder renders into the macOS `.icns` and the Linux icon set, replacing the unrelated placeholder mark it shipped with. The web app gains a favicon of the same drawing. +Carry the Dispatch mark across every client. Electron takes `apps/desktop/build/icon.png` as a rounded 1024px artwork, which electron-builder renders into the macOS `.icns` and the Linux icon set, replacing the unrelated placeholder mark it shipped with. The web app gains a favicon of the same drawing. diff --git a/.changeset/arch-aware-android-image.md b/.changeset/arch-aware-android-image.md index c6f34080..09124b6b 100644 --- a/.changeset/arch-aware-android-image.md +++ b/.changeset/arch-aware-android-image.md @@ -1,5 +1,5 @@ --- -"openbot": patch +"@trytilde/cli": patch --- -Select the Android emulator system image by host CPU: `arm64-v8a` on Apple Silicon and `x86_64` elsewhere. `openbot mobile setup` and `openbot mobile avd` previously hardcoded `x86_64`, which has no hardware acceleration path on an Apple Silicon Mac and produces an unusable emulator. +Select the Android emulator system image by host CPU: `arm64-v8a` on Apple Silicon and `x86_64` elsewhere. `tilde mobile setup` and `tilde mobile avd` previously hardcoded `x86_64`, which has no hardware acceleration path on an Apple Silicon Mac and produces an unusable emulator. diff --git a/.changeset/bound-tilde-reconciliation-concurrency.md b/.changeset/bound-tilde-reconciliation-concurrency.md index 4165f21f..c0d8575f 100644 --- a/.changeset/bound-tilde-reconciliation-concurrency.md +++ b/.changeset/bound-tilde-reconciliation-concurrency.md @@ -1,23 +1,23 @@ --- -"@tryopenbot/agent-provider": patch -"@tryopenbot/agent-service-provider": patch -"@tryopenbot/auth-provider": patch -"openbot": patch -"@tryopenbot/computer-service-provider": patch -"@tryopenbot/client-runtime": patch -"@tryopenbot/computer-tools": patch -"@tryopenbot/computer-service": patch -"@tryopenbot/computer-service-proto": patch -"@tryopenbot/configuration": patch -"@tryopenbot/desktop": patch -"@tryopenbot/utilities": patch -"@tryopenbot/platform-integrations": patch -"@tryopenbot/control-service-provider": patch -"@tryopenbot/runtime-provider": patch -"@tryopenbot/control-service": patch -"@tryopenbot/ui": patch -"@tryopenbot/web": patch -"@tryopenbot/git-provider": patch +"@trytilde/dispatch-agent-provider": patch +"@trytilde/dispatch-agent-service-provider": patch +"@trytilde/dispatch-auth-provider": patch +"@trytilde/cli": patch +"@trytilde/dispatch-computer-service-provider": patch +"@trytilde/dispatch-client-runtime": patch +"@trytilde/dispatch-computer-tools": patch +"@trytilde/dispatch-computer-service": patch +"@trytilde/dispatch-computer-service-proto": patch +"@trytilde/dispatch-configuration": patch +"@trytilde/dispatch-desktop": patch +"@trytilde/dispatch-utilities": patch +"@trytilde/dispatch-platform-integrations": patch +"@trytilde/dispatch-control-service-provider": patch +"@trytilde/dispatch-runtime-provider": patch +"@trytilde/dispatch-control-service": patch +"@trytilde/dispatch-ui": patch +"@trytilde/dispatch-web": patch +"@trytilde/dispatch-git-provider": patch --- Bound concurrent Tilde skill and tool reconciliation while preserving input order and deterministic errors. diff --git a/.changeset/build-ui-git-artifacts.md b/.changeset/build-ui-git-artifacts.md index b812e6ce..8662ca6f 100644 --- a/.changeset/build-ui-git-artifacts.md +++ b/.changeset/build-ui-git-artifacts.md @@ -1,23 +1,23 @@ --- -"@tryopenbot/agent-provider": patch -"@tryopenbot/agent-service-provider": patch -"@tryopenbot/auth-provider": patch -"openbot": patch -"@tryopenbot/computer-service-provider": patch -"@tryopenbot/client-runtime": patch -"@tryopenbot/computer-tools": patch -"@tryopenbot/computer-service": patch -"@tryopenbot/computer-service-proto": patch -"@tryopenbot/configuration": patch -"@tryopenbot/desktop": patch -"@tryopenbot/utilities": patch -"@tryopenbot/platform-integrations": patch -"@tryopenbot/control-service-provider": patch -"@tryopenbot/runtime-provider": patch -"@tryopenbot/control-service": patch -"@tryopenbot/ui": patch -"@tryopenbot/web": patch -"@tryopenbot/git-provider": patch +"@trytilde/dispatch-agent-provider": patch +"@trytilde/dispatch-agent-service-provider": patch +"@trytilde/dispatch-auth-provider": patch +"@trytilde/cli": patch +"@trytilde/dispatch-computer-service-provider": patch +"@trytilde/dispatch-client-runtime": patch +"@trytilde/dispatch-computer-tools": patch +"@trytilde/dispatch-computer-service": patch +"@trytilde/dispatch-computer-service-proto": patch +"@trytilde/dispatch-configuration": patch +"@trytilde/dispatch-desktop": patch +"@trytilde/dispatch-utilities": patch +"@trytilde/dispatch-platform-integrations": patch +"@trytilde/dispatch-control-service-provider": patch +"@trytilde/dispatch-runtime-provider": patch +"@trytilde/dispatch-control-service": patch +"@trytilde/dispatch-ui": patch +"@trytilde/dispatch-web": patch +"@trytilde/dispatch-git-provider": patch --- -Build `@tryopenbot/ui` artifacts when the package is installed directly from Git. +Build `@trytilde/dispatch-ui` artifacts when the package is installed directly from Git. diff --git a/.changeset/bulk-mcp-function-mappings.md b/.changeset/bulk-mcp-function-mappings.md index eefb7306..39665bb0 100644 --- a/.changeset/bulk-mcp-function-mappings.md +++ b/.changeset/bulk-mcp-function-mappings.md @@ -1,23 +1,23 @@ --- -"@tryopenbot/agent-provider": patch -"@tryopenbot/agent-service-provider": patch -"@tryopenbot/auth-provider": patch -"openbot": patch -"@tryopenbot/computer-service-provider": patch -"@tryopenbot/client-runtime": patch -"@tryopenbot/computer-tools": patch -"@tryopenbot/computer-service": patch -"@tryopenbot/computer-service-proto": patch -"@tryopenbot/configuration": patch -"@tryopenbot/desktop": patch -"@tryopenbot/utilities": patch -"@tryopenbot/platform-integrations": patch -"@tryopenbot/control-service-provider": patch -"@tryopenbot/runtime-provider": patch -"@tryopenbot/control-service": patch -"@tryopenbot/ui": patch -"@tryopenbot/web": patch -"@tryopenbot/git-provider": patch +"@trytilde/dispatch-agent-provider": patch +"@trytilde/dispatch-agent-service-provider": patch +"@trytilde/dispatch-auth-provider": patch +"@trytilde/cli": patch +"@trytilde/dispatch-computer-service-provider": patch +"@trytilde/dispatch-client-runtime": patch +"@trytilde/dispatch-computer-tools": patch +"@trytilde/dispatch-computer-service": patch +"@trytilde/dispatch-computer-service-proto": patch +"@trytilde/dispatch-configuration": patch +"@trytilde/dispatch-desktop": patch +"@trytilde/dispatch-utilities": patch +"@trytilde/dispatch-platform-integrations": patch +"@trytilde/dispatch-control-service-provider": patch +"@trytilde/dispatch-runtime-provider": patch +"@trytilde/dispatch-control-service": patch +"@trytilde/dispatch-ui": patch +"@trytilde/dispatch-web": patch +"@trytilde/dispatch-git-provider": patch "@trytilde/api-client": minor "@trytilde/sdk": minor --- diff --git a/.changeset/cap-agent-tool-loops.md b/.changeset/cap-agent-tool-loops.md index ac7bdc47..9a12c14b 100644 --- a/.changeset/cap-agent-tool-loops.md +++ b/.changeset/cap-agent-tool-loops.md @@ -1,5 +1,5 @@ --- -"@tryopenbot/inference-provider": patch +"@trytilde/dispatch-inference-provider": patch --- Bound the default Vercel AI SDK agent tool loop at 50 steps to prevent unbounded cyclic runs. diff --git a/.changeset/check-xcode-minimum.md b/.changeset/check-xcode-minimum.md index be41d29a..f839b747 100644 --- a/.changeset/check-xcode-minimum.md +++ b/.changeset/check-xcode-minimum.md @@ -1,5 +1,5 @@ --- -"openbot": patch +"@trytilde/cli": patch --- -Check the Xcode version in `openbot mobile doctor` on macOS, reading the minimum from the installed React Native's CocoaPods helpers so it cannot drift from what `pod install` enforces. React Native 0.86 requires Xcode 16.1; below that, an iOS build fails partway through `pod install` with `Please upgrade XCode` rather than at the toolchain check. Passthrough command failures — `mobile expo`, `mobile logs`, the repository gates — also stop printing the run-log crash notice, because the child process has already reported the error. +Check the Xcode version in `tilde mobile doctor` on macOS, reading the minimum from the installed React Native's CocoaPods helpers so it cannot drift from what `pod install` enforces. React Native 0.86 requires Xcode 16.1; below that, an iOS build fails partway through `pod install` with `Please upgrade XCode` rather than at the toolchain check. Passthrough command failures — `mobile expo`, `mobile logs`, the repository gates — also stop printing the run-log crash notice, because the child process has already reported the error. diff --git a/.changeset/collapse-agent-resources.md b/.changeset/collapse-agent-resources.md index b4149322..a912e787 100644 --- a/.changeset/collapse-agent-resources.md +++ b/.changeset/collapse-agent-resources.md @@ -1,20 +1,20 @@ --- -"@tryopenbot/agent-provider": minor -"@tryopenbot/agent-service-provider": minor -"openbot": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/computer-tools": minor -"@tryopenbot/computer-service": minor -"@tryopenbot/computer-service-proto": minor -"@tryopenbot/configuration": minor -"@tryopenbot/desktop": minor -"@tryopenbot/utilities": minor -"@tryopenbot/platform-integrations": minor -"@tryopenbot/control-service-provider": minor -"@tryopenbot/runtime-provider": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/cli": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-computer-tools": minor +"@trytilde/dispatch-computer-service": minor +"@trytilde/dispatch-computer-service-proto": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-utilities": minor +"@trytilde/dispatch-platform-integrations": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-runtime-provider": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor --- Collapse Tilde agent, skill, registry, MCP, and tool reconciliation into one `AgentProvider` lifecycle, and replace the owner-facing Chat Provider and ConnectRPC projection with the native Tilde REST/SSE bridge. diff --git a/.changeset/collapse-tilde-facades.md b/.changeset/collapse-tilde-facades.md index 05d6b614..01ce957a 100644 --- a/.changeset/collapse-tilde-facades.md +++ b/.changeset/collapse-tilde-facades.md @@ -1,28 +1,28 @@ --- -"@tryopenbot/agent-provider": minor -"@tryopenbot/agent-service-provider": minor -"@tryopenbot/auth-provider": minor -"openbot": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/client-runtime": minor -"@tryopenbot/computer-tools": minor -"@tryopenbot/computer-service": minor -"@tryopenbot/computer-service-proto": minor -"@tryopenbot/configuration": minor -"@tryopenbot/desktop": minor -"@tryopenbot/utilities": minor -"@tryopenbot/platform-integrations": minor -"@tryopenbot/control-service-provider": minor -"@tryopenbot/runtime-provider": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor -"@tryopenbot/git-provider": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/dispatch-auth-provider": minor +"@trytilde/cli": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-client-runtime": minor +"@trytilde/dispatch-computer-tools": minor +"@trytilde/dispatch-computer-service": minor +"@trytilde/dispatch-computer-service-proto": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-utilities": minor +"@trytilde/dispatch-platform-integrations": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-runtime-provider": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor +"@trytilde/dispatch-git-provider": minor --- Use native Tilde plugin, connector, routine, and signal resources through one authenticated allowlisted bridge, and remove the corresponding control-service route APIs. -Plugin inventory now pages Tilde's native MCP, skill, provider, and registry collections directly; it no longer depends on Tilde's OpenBot-specific aggregate catalogue or its first-page limit. +Plugin inventory now pages Tilde's native MCP, skill, provider, and registry collections directly; it no longer depends on Tilde's Dispatch-specific aggregate catalogue or its first-page limit. Routines now consume Tilde's native trigger/version contract, and signal history uses native trigger IDs while accepting legacy rule IDs during the migration window. Signal provider and instance inventories follow every continuation token. @@ -33,5 +33,5 @@ Fresh installations and future agents now explicitly select ChatKit `agentLoop` The ChatKit credential bridge now permits only the workspace, queue, observation, and attachment operations used by Client Runtime instead of forwarding the complete ChatKit namespace. Migration: -- Replace direct calls to `/api/plugins`, `/api/connectors`, `/api/routines`, and `/api/signals` with `@tryopenbot/client-runtime`. +- Replace direct calls to `/api/plugins`, `/api/connectors`, `/api/routines`, and `/api/signals` with `@trytilde/dispatch-client-runtime`. - Replace `registerConnectorRoutes` with `registerConnectorAuthorizedRoute` when constructing a custom control service. diff --git a/.changeset/complete-coding-agent-audit.md b/.changeset/complete-coding-agent-audit.md index b1d0c2ba..4d3f2d5a 100644 --- a/.changeset/complete-coding-agent-audit.md +++ b/.changeset/complete-coding-agent-audit.md @@ -2,25 +2,25 @@ "@trytilde/sdk": minor "@trytilde/sdk-opencode": minor "@trytilde/sdk-gemini-cli": minor -"@tryopenbot/agent-provider": minor -"@tryopenbot/agent-service-provider": minor -"@tryopenbot/auth-provider": minor -"openbot": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/client-runtime": minor -"@tryopenbot/computer-tools": minor -"@tryopenbot/computer-service": minor -"@tryopenbot/computer-service-proto": minor -"@tryopenbot/configuration": minor -"@tryopenbot/desktop": minor -"@tryopenbot/utilities": minor -"@tryopenbot/platform-integrations": minor -"@tryopenbot/control-service-provider": minor -"@tryopenbot/runtime-provider": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor -"@tryopenbot/git-provider": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/dispatch-auth-provider": minor +"@trytilde/cli": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-client-runtime": minor +"@trytilde/dispatch-computer-tools": minor +"@trytilde/dispatch-computer-service": minor +"@trytilde/dispatch-computer-service-proto": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-utilities": minor +"@trytilde/dispatch-platform-integrations": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-runtime-provider": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor +"@trytilde/dispatch-git-provider": minor --- -Add OpenCode and Gemini CLI adapters that record searchable ChatKit messages and canonical tool executions while `openbot plugin` installs their native audit integrations. +Add OpenCode and Gemini CLI adapters that record searchable ChatKit messages and canonical tool executions while `tilde plugin` installs their native audit integrations. diff --git a/.changeset/complete-workspace-plugins.md b/.changeset/complete-workspace-plugins.md index b6225fc6..109f29ff 100644 --- a/.changeset/complete-workspace-plugins.md +++ b/.changeset/complete-workspace-plugins.md @@ -1,23 +1,23 @@ --- -"@tryopenbot/agent-provider": minor -"@tryopenbot/agent-service-provider": minor -"@tryopenbot/auth-provider": minor -"openbot": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/client-runtime": minor -"@tryopenbot/computer-tools": minor -"@tryopenbot/computer-service": minor -"@tryopenbot/computer-service-proto": minor -"@tryopenbot/configuration": minor -"@tryopenbot/desktop": minor -"@tryopenbot/utilities": minor -"@tryopenbot/platform-integrations": minor -"@tryopenbot/control-service-provider": minor -"@tryopenbot/runtime-provider": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor -"@tryopenbot/git-provider": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/dispatch-auth-provider": minor +"@trytilde/cli": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-client-runtime": minor +"@trytilde/dispatch-computer-tools": minor +"@trytilde/dispatch-computer-service": minor +"@trytilde/dispatch-computer-service-proto": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-utilities": minor +"@trytilde/dispatch-platform-integrations": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-runtime-provider": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor +"@trytilde/dispatch-git-provider": minor --- Add bot-scoped tool and skill management, durable live conversation activity, atomic bot setup presentation, and an Electron Computer preview to the owner workspace. diff --git a/.changeset/config.json b/.changeset/config.json index 68c44a23..facf1230 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -9,25 +9,25 @@ "commit": false, "fixed": [ [ - "@tryopenbot/agent-provider", - "@tryopenbot/agent-service-provider", - "@tryopenbot/auth-provider", - "openbot", - "@tryopenbot/computer-service-provider", - "@tryopenbot/client-runtime", - "@tryopenbot/computer-tools", - "@tryopenbot/computer-service", - "@tryopenbot/computer-service-proto", - "@tryopenbot/configuration", - "@tryopenbot/desktop", - "@tryopenbot/utilities", - "@tryopenbot/platform-integrations", - "@tryopenbot/control-service-provider", - "@tryopenbot/runtime-provider", - "@tryopenbot/control-service", - "@tryopenbot/ui", - "@tryopenbot/web", - "@tryopenbot/git-provider" + "@trytilde/dispatch-agent-provider", + "@trytilde/dispatch-agent-service-provider", + "@trytilde/dispatch-auth-provider", + "@trytilde/cli", + "@trytilde/dispatch-computer-service-provider", + "@trytilde/dispatch-client-runtime", + "@trytilde/dispatch-computer-tools", + "@trytilde/dispatch-computer-service", + "@trytilde/dispatch-computer-service-proto", + "@trytilde/dispatch-configuration", + "@trytilde/dispatch-desktop", + "@trytilde/dispatch-utilities", + "@trytilde/dispatch-platform-integrations", + "@trytilde/dispatch-control-service-provider", + "@trytilde/dispatch-runtime-provider", + "@trytilde/dispatch-control-service", + "@trytilde/dispatch-ui", + "@trytilde/dispatch-web", + "@trytilde/dispatch-git-provider" ] ], "linked": [], diff --git a/.changeset/connect-owner-chat.md b/.changeset/connect-owner-chat.md index 7a13444a..3743a40c 100644 --- a/.changeset/connect-owner-chat.md +++ b/.changeset/connect-owner-chat.md @@ -1,14 +1,14 @@ --- -"openbot": patch -"@tryopenbot/control-service": minor -"@tryopenbot/control-service-provider": minor -"@tryopenbot/computer-service-provider": patch -"@tryopenbot/agent-service-provider": patch -"@tryopenbot/utilities": patch -"@tryopenbot/web": minor -"@tryopenbot/runtime-provider": patch -"@tryopenbot/platform-integrations": patch -"@tryopenbot/agent-provider": patch +"@trytilde/cli": patch +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-computer-service-provider": patch +"@trytilde/dispatch-agent-service-provider": patch +"@trytilde/dispatch-utilities": patch +"@trytilde/dispatch-web": minor +"@trytilde/dispatch-runtime-provider": patch +"@trytilde/dispatch-platform-integrations": patch +"@trytilde/dispatch-agent-provider": patch --- Connect the owner workspace to configured Chat Provider agents in local and deployed modes. diff --git a/.changeset/consolidate-dispatch-runtime.md b/.changeset/consolidate-dispatch-runtime.md new file mode 100644 index 00000000..dc1ed5c2 --- /dev/null +++ b/.changeset/consolidate-dispatch-runtime.md @@ -0,0 +1,23 @@ +--- +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/dispatch-auth-provider": minor +"@trytilde/cli": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-client-runtime": minor +"@trytilde/dispatch-computer-tools": minor +"@trytilde/dispatch-computer-service": minor +"@trytilde/dispatch-computer-service-proto": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-utilities": minor +"@trytilde/dispatch-platform-integrations": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-runtime-provider": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor +"@trytilde/dispatch-git-provider": minor +--- + +Add a consolidated Dispatch runtime deployment, direct secure ChatKit workspace streaming, persisted unified routines, and bulk tool assignment. diff --git a/.changeset/consolidate-openbot-runtime.md b/.changeset/consolidate-openbot-runtime.md deleted file mode 100644 index e7ba79df..00000000 --- a/.changeset/consolidate-openbot-runtime.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -"@tryopenbot/agent-provider": minor -"@tryopenbot/agent-service-provider": minor -"@tryopenbot/auth-provider": minor -"openbot": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/client-runtime": minor -"@tryopenbot/computer-tools": minor -"@tryopenbot/computer-service": minor -"@tryopenbot/computer-service-proto": minor -"@tryopenbot/configuration": minor -"@tryopenbot/desktop": minor -"@tryopenbot/utilities": minor -"@tryopenbot/platform-integrations": minor -"@tryopenbot/control-service-provider": minor -"@tryopenbot/runtime-provider": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor -"@tryopenbot/git-provider": minor ---- - -Add a consolidated OpenBot runtime deployment, direct secure ChatKit workspace streaming, persisted unified routines, and bulk tool assignment. diff --git a/.changeset/consolidate-provider-packages.md b/.changeset/consolidate-provider-packages.md index 3d5357f1..1f822337 100644 --- a/.changeset/consolidate-provider-packages.md +++ b/.changeset/consolidate-provider-packages.md @@ -1,18 +1,18 @@ --- -"@tryopenbot/agent-provider": minor -"@tryopenbot/agent-service-provider": minor -"openbot": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/computer-service": minor -"@tryopenbot/computer-service-proto": minor -"@tryopenbot/configuration": minor -"@tryopenbot/control-service-provider": minor -"@tryopenbot/control-service": minor -"@tryopenbot/desktop": minor -"@tryopenbot/runtime-provider": minor -"@tryopenbot/ui": minor -"@tryopenbot/utilities": minor -"@tryopenbot/web": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/cli": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-computer-service": minor +"@trytilde/dispatch-computer-service-proto": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-runtime-provider": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-utilities": minor +"@trytilde/dispatch-web": minor --- Consolidate provider contracts into their owning packages and add isolated agent workspaces plus a trusted, SOPS-capable development sandbox deployment. diff --git a/.changeset/consolidate-tilde-roundtrips.md b/.changeset/consolidate-tilde-roundtrips.md index 0e5e5546..d42849d0 100644 --- a/.changeset/consolidate-tilde-roundtrips.md +++ b/.changeset/consolidate-tilde-roundtrips.md @@ -1,9 +1,9 @@ --- -"@tryopenbot/agent-provider": minor -"@tryopenbot/client-runtime": minor -"@tryopenbot/control-service": minor -"@tryopenbot/web": minor -"@tryopenbot/connector-tools": patch +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-client-runtime": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-web": minor +"@trytilde/dispatch-connector-tools": patch "@trytilde/api-client": minor "@trytilde/sdk": minor --- diff --git a/.changeset/desktop-commands.md b/.changeset/desktop-commands.md index 1cfb3626..3ff1ac67 100644 --- a/.changeset/desktop-commands.md +++ b/.changeset/desktop-commands.md @@ -1,5 +1,5 @@ --- -"openbot": minor +"@trytilde/cli": minor --- -Add `openbot desktop dev` and `openbot desktop package`, and make the Electron shell runnable on a display-less host. Desktop renders to its own virtual screen on display `:2` with loopback VNC on 5901, separate from the Android emulator's `:1` and 5900 so both run at once; `openbot connect` forwards both screens, and `openbot remote desktop` and `desktop-package` run them on a configured host. Also builds unbuilt workspace dependencies before starting Expo, so a fresh clone no longer fails Metro bundling with `Unable to resolve "@tryopenbot/client-runtime"` when its `dist` is missing. +Add `tilde desktop dev` and `tilde desktop package`, and make the Electron shell runnable on a display-less host. Desktop renders to its own virtual screen on display `:2` with loopback VNC on 5901, separate from the Android emulator's `:1` and 5900 so both run at once; `tilde connect` forwards both screens, and `tilde remote desktop` and `desktop-package` run them on a configured host. Also builds unbuilt workspace dependencies before starting Expo, so a fresh clone no longer fails Metro bundling with `Unable to resolve "@trytilde/dispatch-client-runtime"` when its `dist` is missing. diff --git a/.changeset/desktop-publisher-namespace.md b/.changeset/desktop-publisher-namespace.md index 8d0bd1b3..8e94b3a9 100644 --- a/.changeset/desktop-publisher-namespace.md +++ b/.changeset/desktop-publisher-namespace.md @@ -1,6 +1,6 @@ --- -"@tryopenbot/desktop": minor -"openbot": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/cli": minor --- -Name the desktop identity for its publisher too: the Electron `appId` moves from `dev.openbot.desktop` to `ai.trytilde.openbot`, matching the mobile identifier, and resolves from the same `OPENBOT_APP_ID` a fork already sets for Expo. Done before the first signed release, after which the identifier is baked into every signed artifact. +Name the desktop identity for its publisher too: the Electron `appId` moves from `dev.dispatch.desktop` to `ai.trytilde.dispatch`, matching the mobile identifier, and resolves from the same `DISPATCH_APP_ID` a fork already sets for Expo. Done before the first signed release, after which the identifier is baked into every signed artifact. diff --git a/.changeset/drop-inherited-compiler-flags.md b/.changeset/drop-inherited-compiler-flags.md index 6a2bde4f..bae153db 100644 --- a/.changeset/drop-inherited-compiler-flags.md +++ b/.changeset/drop-inherited-compiler-flags.md @@ -1,5 +1,5 @@ --- -"openbot": patch +"@trytilde/cli": patch --- -Report compiler search paths that break Xcode module builds in `openbot mobile doctor`. A global `CPPFLAGS` pointing at Homebrew LLVM makes clang find an incompatible C standard library, so an iOS build fails inside the SDK's own modulemap with `found_incompatible_headers__check_search_paths` and a cascade of `could not build module 'Foundation'` that names neither the variable nor the shell. Doctor now names them; it does not change them, because the developer's environment is theirs to own. +Report compiler search paths that break Xcode module builds in `tilde mobile doctor`. A global `CPPFLAGS` pointing at Homebrew LLVM makes clang find an incompatible C standard library, so an iOS build fails inside the SDK's own modulemap with `found_incompatible_headers__check_search_paths` and a cascade of `could not build module 'Foundation'` that names neither the variable nor the shell. Doctor now names them; it does not change them, because the developer's environment is theirs to own. diff --git a/.changeset/durable-code-storage.md b/.changeset/durable-code-storage.md index adb622cf..c6fa3dcc 100644 --- a/.changeset/durable-code-storage.md +++ b/.changeset/durable-code-storage.md @@ -1,23 +1,23 @@ --- -"@tryopenbot/agent-provider": patch -"@tryopenbot/agent-service-provider": patch -"@tryopenbot/auth-provider": patch -"openbot": patch -"@tryopenbot/computer-service-provider": patch -"@tryopenbot/client-runtime": patch -"@tryopenbot/computer-tools": patch -"@tryopenbot/computer-service": patch -"@tryopenbot/computer-service-proto": patch -"@tryopenbot/configuration": patch -"@tryopenbot/desktop": patch -"@tryopenbot/utilities": patch -"@tryopenbot/platform-integrations": patch -"@tryopenbot/control-service-provider": patch -"@tryopenbot/runtime-provider": patch -"@tryopenbot/control-service": patch -"@tryopenbot/ui": patch -"@tryopenbot/web": patch -"@tryopenbot/git-provider": patch +"@trytilde/dispatch-agent-provider": patch +"@trytilde/dispatch-agent-service-provider": patch +"@trytilde/dispatch-auth-provider": patch +"@trytilde/cli": patch +"@trytilde/dispatch-computer-service-provider": patch +"@trytilde/dispatch-client-runtime": patch +"@trytilde/dispatch-computer-tools": patch +"@trytilde/dispatch-computer-service": patch +"@trytilde/dispatch-computer-service-proto": patch +"@trytilde/dispatch-configuration": patch +"@trytilde/dispatch-desktop": patch +"@trytilde/dispatch-utilities": patch +"@trytilde/dispatch-platform-integrations": patch +"@trytilde/dispatch-control-service-provider": patch +"@trytilde/dispatch-runtime-provider": patch +"@trytilde/dispatch-control-service": patch +"@trytilde/dispatch-ui": patch +"@trytilde/dispatch-web": patch +"@trytilde/dispatch-git-provider": patch --- Keep the scoped Code Storage repository authoritative inside trusted exe.dev runtimes. diff --git a/.changeset/exe-single-vm-runtime.md b/.changeset/exe-single-vm-runtime.md index 31f17607..3e27457b 100644 --- a/.changeset/exe-single-vm-runtime.md +++ b/.changeset/exe-single-vm-runtime.md @@ -1,23 +1,23 @@ --- -"@tryopenbot/agent-provider": minor -"@tryopenbot/agent-service-provider": minor -"@tryopenbot/auth-provider": minor -"openbot": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/client-runtime": minor -"@tryopenbot/computer-tools": minor -"@tryopenbot/computer-service": minor -"@tryopenbot/computer-service-proto": minor -"@tryopenbot/configuration": minor -"@tryopenbot/desktop": minor -"@tryopenbot/utilities": minor -"@tryopenbot/platform-integrations": minor -"@tryopenbot/control-service-provider": minor -"@tryopenbot/runtime-provider": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor -"@tryopenbot/git-provider": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/dispatch-auth-provider": minor +"@trytilde/cli": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-client-runtime": minor +"@trytilde/dispatch-computer-tools": minor +"@trytilde/dispatch-computer-service": minor +"@trytilde/dispatch-computer-service-proto": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-utilities": minor +"@trytilde/dispatch-platform-integrations": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-runtime-provider": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor +"@trytilde/dispatch-git-provider": minor --- Add a persistent exe.dev single-VM runtime with Code Storage deployment, host Computer desktops, and explicit reconciliation recovery controls. diff --git a/.changeset/expose-owner-account-context.md b/.changeset/expose-owner-account-context.md index dd81be94..811238b7 100644 --- a/.changeset/expose-owner-account-context.md +++ b/.changeset/expose-owner-account-context.md @@ -1,23 +1,23 @@ --- -"@tryopenbot/agent-provider": minor -"@tryopenbot/agent-service-provider": minor -"@tryopenbot/auth-provider": minor -"openbot": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/client-runtime": minor -"@tryopenbot/computer-tools": minor -"@tryopenbot/computer-service": minor -"@tryopenbot/computer-service-proto": minor -"@tryopenbot/configuration": minor -"@tryopenbot/desktop": minor -"@tryopenbot/utilities": minor -"@tryopenbot/platform-integrations": minor -"@tryopenbot/control-service-provider": minor -"@tryopenbot/runtime-provider": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor -"@tryopenbot/git-provider": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/dispatch-auth-provider": minor +"@trytilde/cli": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-client-runtime": minor +"@trytilde/dispatch-computer-tools": minor +"@trytilde/dispatch-computer-service": minor +"@trytilde/dispatch-computer-service-proto": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-utilities": minor +"@trytilde/dispatch-platform-integrations": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-runtime-provider": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor +"@trytilde/dispatch-git-provider": minor --- Expose the authenticated owner's display name, avatar, organization, and workspace through the shared session contract. diff --git a/.changeset/extract-workspace-ui.md b/.changeset/extract-workspace-ui.md index bbe5b5e4..b86d3616 100644 --- a/.changeset/extract-workspace-ui.md +++ b/.changeset/extract-workspace-ui.md @@ -1,20 +1,20 @@ --- -"@tryopenbot/agent-provider": minor -"@tryopenbot/agent-service-provider": minor -"openbot": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/computer-tools": minor -"@tryopenbot/computer-service": minor -"@tryopenbot/computer-service-proto": minor -"@tryopenbot/configuration": minor -"@tryopenbot/desktop": minor -"@tryopenbot/utilities": minor -"@tryopenbot/platform-integrations": minor -"@tryopenbot/control-service-provider": minor -"@tryopenbot/runtime-provider": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/cli": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-computer-tools": minor +"@trytilde/dispatch-computer-service": minor +"@trytilde/dispatch-computer-service-proto": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-utilities": minor +"@trytilde/dispatch-platform-integrations": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-runtime-provider": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor --- -Add the complete reusable OpenBot workspace component system, exact light palette, motion curves, agent identity artwork, continuous chat composition, rich message content, activity surface, and Computer pane to `@tryopenbot/ui`. +Add the complete reusable Dispatch workspace component system, exact light palette, motion curves, agent identity artwork, continuous chat composition, rich message content, activity surface, and Computer pane to `@trytilde/dispatch-ui`. diff --git a/.changeset/fix-atomic-agent-creation.md b/.changeset/fix-atomic-agent-creation.md index 9f9f0511..76968972 100644 --- a/.changeset/fix-atomic-agent-creation.md +++ b/.changeset/fix-atomic-agent-creation.md @@ -1,23 +1,23 @@ --- -"@tryopenbot/agent-provider": patch -"@tryopenbot/agent-service-provider": patch -"@tryopenbot/auth-provider": patch -"openbot": patch -"@tryopenbot/computer-service-provider": patch -"@tryopenbot/client-runtime": patch -"@tryopenbot/computer-tools": patch -"@tryopenbot/computer-service": patch -"@tryopenbot/computer-service-proto": patch -"@tryopenbot/configuration": patch -"@tryopenbot/desktop": patch -"@tryopenbot/utilities": patch -"@tryopenbot/platform-integrations": patch -"@tryopenbot/control-service-provider": patch -"@tryopenbot/runtime-provider": patch -"@tryopenbot/control-service": patch -"@tryopenbot/ui": patch -"@tryopenbot/web": patch -"@tryopenbot/git-provider": patch +"@trytilde/dispatch-agent-provider": patch +"@trytilde/dispatch-agent-service-provider": patch +"@trytilde/dispatch-auth-provider": patch +"@trytilde/cli": patch +"@trytilde/dispatch-computer-service-provider": patch +"@trytilde/dispatch-client-runtime": patch +"@trytilde/dispatch-computer-tools": patch +"@trytilde/dispatch-computer-service": patch +"@trytilde/dispatch-computer-service-proto": patch +"@trytilde/dispatch-configuration": patch +"@trytilde/dispatch-desktop": patch +"@trytilde/dispatch-utilities": patch +"@trytilde/dispatch-platform-integrations": patch +"@trytilde/dispatch-control-service-provider": patch +"@trytilde/dispatch-runtime-provider": patch +"@trytilde/dispatch-control-service": patch +"@trytilde/dispatch-ui": patch +"@trytilde/dispatch-web": patch +"@trytilde/dispatch-git-provider": patch --- Keep newly created bots on the local-runtime tunnel until their complete agent template is ready, reconcile independent Tilde resources concurrently behind a shared request ceiling, and keep managed skill and tool assignments idempotent. diff --git a/.changeset/fix-background-chat-streams.md b/.changeset/fix-background-chat-streams.md index 59c301b8..2935b24a 100644 --- a/.changeset/fix-background-chat-streams.md +++ b/.changeset/fix-background-chat-streams.md @@ -1,23 +1,23 @@ --- -"@tryopenbot/agent-provider": patch -"@tryopenbot/agent-service-provider": patch -"@tryopenbot/auth-provider": patch -"openbot": patch -"@tryopenbot/computer-service-provider": patch -"@tryopenbot/client-runtime": patch -"@tryopenbot/computer-tools": patch -"@tryopenbot/computer-service": patch -"@tryopenbot/computer-service-proto": patch -"@tryopenbot/configuration": patch -"@tryopenbot/desktop": patch -"@tryopenbot/utilities": patch -"@tryopenbot/platform-integrations": patch -"@tryopenbot/control-service-provider": patch -"@tryopenbot/runtime-provider": patch -"@tryopenbot/control-service": patch -"@tryopenbot/ui": patch -"@tryopenbot/web": patch -"@tryopenbot/git-provider": patch +"@trytilde/dispatch-agent-provider": patch +"@trytilde/dispatch-agent-service-provider": patch +"@trytilde/dispatch-auth-provider": patch +"@trytilde/cli": patch +"@trytilde/dispatch-computer-service-provider": patch +"@trytilde/dispatch-client-runtime": patch +"@trytilde/dispatch-computer-tools": patch +"@trytilde/dispatch-computer-service": patch +"@trytilde/dispatch-computer-service-proto": patch +"@trytilde/dispatch-configuration": patch +"@trytilde/dispatch-desktop": patch +"@trytilde/dispatch-utilities": patch +"@trytilde/dispatch-platform-integrations": patch +"@trytilde/dispatch-control-service-provider": patch +"@trytilde/dispatch-runtime-provider": patch +"@trytilde/dispatch-control-service": patch +"@trytilde/dispatch-ui": patch +"@trytilde/dispatch-web": patch +"@trytilde/dispatch-git-provider": patch --- Keep agent activity, streamed messages, previews, and unread state updating while another chat is active. diff --git a/.changeset/fix-cua-managed-skill-errors.md b/.changeset/fix-cua-managed-skill-errors.md index ce379a44..0b1262fe 100644 --- a/.changeset/fix-cua-managed-skill-errors.md +++ b/.changeset/fix-cua-managed-skill-errors.md @@ -1,6 +1,6 @@ --- -"@tryopenbot/computer-service": patch -"@tryopenbot/agent-provider": patch +"@trytilde/dispatch-computer-service": patch +"@trytilde/dispatch-agent-provider": patch --- Map typed Cua driver failures into actionable tool results and rely on Tilde's globally managed canonical Cua skill while cleaning legacy registry membership. diff --git a/.changeset/fix-dev-repository-root.md b/.changeset/fix-dev-repository-root.md index ae40037e..88b79dcb 100644 --- a/.changeset/fix-dev-repository-root.md +++ b/.changeset/fix-dev-repository-root.md @@ -1,18 +1,18 @@ --- -"@tryopenbot/agent-provider": patch -"@tryopenbot/agent-service-provider": patch -"openbot": patch -"@tryopenbot/computer-service-provider": patch -"@tryopenbot/computer-service": patch -"@tryopenbot/computer-service-proto": patch -"@tryopenbot/configuration": patch -"@tryopenbot/desktop": patch -"@tryopenbot/utilities": patch -"@tryopenbot/control-service-provider": patch -"@tryopenbot/runtime-provider": patch -"@tryopenbot/control-service": patch -"@tryopenbot/ui": patch -"@tryopenbot/web": patch +"@trytilde/dispatch-agent-provider": patch +"@trytilde/dispatch-agent-service-provider": patch +"@trytilde/cli": patch +"@trytilde/dispatch-computer-service-provider": patch +"@trytilde/dispatch-computer-service": patch +"@trytilde/dispatch-computer-service-proto": patch +"@trytilde/dispatch-configuration": patch +"@trytilde/dispatch-desktop": patch +"@trytilde/dispatch-utilities": patch +"@trytilde/dispatch-control-service-provider": patch +"@trytilde/dispatch-runtime-provider": patch +"@trytilde/dispatch-control-service": patch +"@trytilde/dispatch-ui": patch +"@trytilde/dispatch-web": patch --- -Keep standalone `openbot dev` agent discovery rooted in the fork repository. +Keep standalone `tilde dev` agent discovery rooted in the fork repository. diff --git a/.changeset/fix-development-sandbox-symlinks.md b/.changeset/fix-development-sandbox-symlinks.md index 211de51a..321ea387 100644 --- a/.changeset/fix-development-sandbox-symlinks.md +++ b/.changeset/fix-development-sandbox-symlinks.md @@ -1,5 +1,5 @@ --- -"@tryopenbot/computer-service-provider": patch +"@trytilde/dispatch-computer-service-provider": patch --- Seed tracked repository symlinks into the trusted development sandbox instead of failing, so a repository that links `.claude/skills` at `.agents/skills` or `CLAUDE.md` at `AGENTS.md` can still start development. Symlink targets must stay relative and resolve inside the repository. diff --git a/.changeset/fix-doctor-diagnostic-exit.md b/.changeset/fix-doctor-diagnostic-exit.md index 96bc547f..5012256b 100644 --- a/.changeset/fix-doctor-diagnostic-exit.md +++ b/.changeset/fix-doctor-diagnostic-exit.md @@ -1,5 +1,5 @@ --- -"openbot": patch +"@trytilde/cli": patch --- -Report `openbot mobile doctor` failures as diagnostics rather than crashes. A missing tool no longer prints `OpenBot exited unsuccessfully` with a run-log path; the command keeps its non-zero exit code but owns its explanation. Doctor also gains a warning level, warns when the JDK major version is outside the Android Gradle Plugin's supported 17 and 21, names `openbot mobile setup` as the remedy on each failing Android tool check, and checks for CocoaPods on macOS. +Report `tilde mobile doctor` failures as diagnostics rather than crashes. A missing tool no longer prints `Tilde exited unsuccessfully` with a run-log path; the command keeps its non-zero exit code but owns its explanation. Doctor also gains a warning level, warns when the JDK major version is outside the Android Gradle Plugin's supported 17 and 21, names `tilde mobile setup` as the remedy on each failing Android tool check, and checks for CocoaPods on macOS. diff --git a/.changeset/fix-exe-branch-reconciliation.md b/.changeset/fix-exe-branch-reconciliation.md index baccc860..4d5d36d1 100644 --- a/.changeset/fix-exe-branch-reconciliation.md +++ b/.changeset/fix-exe-branch-reconciliation.md @@ -1,23 +1,23 @@ --- -"@tryopenbot/agent-provider": patch -"@tryopenbot/agent-service-provider": patch -"@tryopenbot/auth-provider": patch -"openbot": patch -"@tryopenbot/computer-service-provider": patch -"@tryopenbot/client-runtime": patch -"@tryopenbot/computer-tools": patch -"@tryopenbot/computer-service": patch -"@tryopenbot/computer-service-proto": patch -"@tryopenbot/configuration": patch -"@tryopenbot/desktop": patch -"@tryopenbot/utilities": patch -"@tryopenbot/platform-integrations": patch -"@tryopenbot/control-service-provider": patch -"@tryopenbot/runtime-provider": patch -"@tryopenbot/control-service": patch -"@tryopenbot/ui": patch -"@tryopenbot/web": patch -"@tryopenbot/git-provider": patch +"@trytilde/dispatch-agent-provider": patch +"@trytilde/dispatch-agent-service-provider": patch +"@trytilde/dispatch-auth-provider": patch +"@trytilde/cli": patch +"@trytilde/dispatch-computer-service-provider": patch +"@trytilde/dispatch-client-runtime": patch +"@trytilde/dispatch-computer-tools": patch +"@trytilde/dispatch-computer-service": patch +"@trytilde/dispatch-computer-service-proto": patch +"@trytilde/dispatch-configuration": patch +"@trytilde/dispatch-desktop": patch +"@trytilde/dispatch-utilities": patch +"@trytilde/dispatch-platform-integrations": patch +"@trytilde/dispatch-control-service-provider": patch +"@trytilde/dispatch-runtime-provider": patch +"@trytilde/dispatch-control-service": patch +"@trytilde/dispatch-ui": patch +"@trytilde/dispatch-web": patch +"@trytilde/dispatch-git-provider": patch --- Switch an existing exe.dev checkout to the requested deployment branch before fast-forwarding it. diff --git a/.changeset/fix-exe-code-storage-helper.md b/.changeset/fix-exe-code-storage-helper.md index b94f001e..054cbde3 100644 --- a/.changeset/fix-exe-code-storage-helper.md +++ b/.changeset/fix-exe-code-storage-helper.md @@ -1,23 +1,23 @@ --- -"@tryopenbot/agent-provider": patch -"@tryopenbot/agent-service-provider": patch -"@tryopenbot/auth-provider": patch -"openbot": patch -"@tryopenbot/computer-service-provider": patch -"@tryopenbot/client-runtime": patch -"@tryopenbot/computer-tools": patch -"@tryopenbot/computer-service": patch -"@tryopenbot/computer-service-proto": patch -"@tryopenbot/configuration": patch -"@tryopenbot/desktop": patch -"@tryopenbot/utilities": patch -"@tryopenbot/platform-integrations": patch -"@tryopenbot/control-service-provider": patch -"@tryopenbot/runtime-provider": patch -"@tryopenbot/control-service": patch -"@tryopenbot/ui": patch -"@tryopenbot/web": patch -"@tryopenbot/git-provider": patch +"@trytilde/dispatch-agent-provider": patch +"@trytilde/dispatch-agent-service-provider": patch +"@trytilde/dispatch-auth-provider": patch +"@trytilde/cli": patch +"@trytilde/dispatch-computer-service-provider": patch +"@trytilde/dispatch-client-runtime": patch +"@trytilde/dispatch-computer-tools": patch +"@trytilde/dispatch-computer-service": patch +"@trytilde/dispatch-computer-service-proto": patch +"@trytilde/dispatch-configuration": patch +"@trytilde/dispatch-desktop": patch +"@trytilde/dispatch-utilities": patch +"@trytilde/dispatch-platform-integrations": patch +"@trytilde/dispatch-control-service-provider": patch +"@trytilde/dispatch-runtime-provider": patch +"@trytilde/dispatch-control-service": patch +"@trytilde/dispatch-ui": patch +"@trytilde/dispatch-web": patch +"@trytilde/dispatch-git-provider": patch --- Keep exe.dev Code Storage reconciliation independent from non-exported environment fields. diff --git a/.changeset/fix-fork-development-reliability.md b/.changeset/fix-fork-development-reliability.md index b2002b4f..cb2d94b2 100644 --- a/.changeset/fix-fork-development-reliability.md +++ b/.changeset/fix-fork-development-reliability.md @@ -1,7 +1,7 @@ --- -"openbot": patch -"@tryopenbot/computer-service-provider": patch -"@tryopenbot/ui": patch +"@trytilde/cli": patch +"@trytilde/dispatch-computer-service-provider": patch +"@trytilde/dispatch-ui": patch --- Resolve the workspace root when the task runner starts the CLI inside a package, wait for the control service before dependent development traffic, and keep the computer image test independent of the fork's repository name. diff --git a/.changeset/fix-fork-first-run.md b/.changeset/fix-fork-first-run.md index 1fd4207d..de73af85 100644 --- a/.changeset/fix-fork-first-run.md +++ b/.changeset/fix-fork-first-run.md @@ -1,18 +1,18 @@ --- -"@tryopenbot/agent-provider": patch -"@tryopenbot/agent-service-provider": patch -"openbot": patch -"@tryopenbot/computer-service-provider": patch -"@tryopenbot/computer-service": patch -"@tryopenbot/computer-service-proto": patch -"@tryopenbot/configuration": patch -"@tryopenbot/desktop": patch -"@tryopenbot/utilities": patch -"@tryopenbot/control-service-provider": patch -"@tryopenbot/runtime-provider": patch -"@tryopenbot/control-service": patch -"@tryopenbot/ui": patch -"@tryopenbot/web": patch +"@trytilde/dispatch-agent-provider": patch +"@trytilde/dispatch-agent-service-provider": patch +"@trytilde/cli": patch +"@trytilde/dispatch-computer-service-provider": patch +"@trytilde/dispatch-computer-service": patch +"@trytilde/dispatch-computer-service-proto": patch +"@trytilde/dispatch-configuration": patch +"@trytilde/dispatch-desktop": patch +"@trytilde/dispatch-utilities": patch +"@trytilde/dispatch-control-service-provider": patch +"@trytilde/dispatch-runtime-provider": patch +"@trytilde/dispatch-control-service": patch +"@trytilde/dispatch-ui": patch +"@trytilde/dispatch-web": patch --- Install initialized forks, resolve development packages from source, create Vercel image repositories automatically, and manage described secret and environment values through the CLI. diff --git a/.changeset/fix-local-agent-creation.md b/.changeset/fix-local-agent-creation.md index f435da73..32dcc371 100644 --- a/.changeset/fix-local-agent-creation.md +++ b/.changeset/fix-local-agent-creation.md @@ -1,6 +1,6 @@ --- -"openbot": patch -"@tryopenbot/control-service": patch +"@trytilde/cli": patch +"@trytilde/dispatch-control-service": patch --- Create agents in the checkout owned by a running local development lifecycle while preserving trusted-sandbox creation for deployed control services. diff --git a/.changeset/fix-local-oauth-callbacks.md b/.changeset/fix-local-oauth-callbacks.md index 3d742e49..da4c9f5b 100644 --- a/.changeset/fix-local-oauth-callbacks.md +++ b/.changeset/fix-local-oauth-callbacks.md @@ -1,21 +1,21 @@ --- -"@tryopenbot/agent-provider": patch -"@tryopenbot/agent-service-provider": patch -"@tryopenbot/auth-provider": patch -"openbot": patch -"@tryopenbot/computer-service-provider": patch -"@tryopenbot/computer-tools": patch -"@tryopenbot/computer-service": patch -"@tryopenbot/computer-service-proto": patch -"@tryopenbot/configuration": patch -"@tryopenbot/desktop": patch -"@tryopenbot/utilities": patch -"@tryopenbot/platform-integrations": patch -"@tryopenbot/control-service-provider": patch -"@tryopenbot/runtime-provider": patch -"@tryopenbot/control-service": patch -"@tryopenbot/ui": patch -"@tryopenbot/web": patch +"@trytilde/dispatch-agent-provider": patch +"@trytilde/dispatch-agent-service-provider": patch +"@trytilde/dispatch-auth-provider": patch +"@trytilde/cli": patch +"@trytilde/dispatch-computer-service-provider": patch +"@trytilde/dispatch-computer-tools": patch +"@trytilde/dispatch-computer-service": patch +"@trytilde/dispatch-computer-service-proto": patch +"@trytilde/dispatch-configuration": patch +"@trytilde/dispatch-desktop": patch +"@trytilde/dispatch-utilities": patch +"@trytilde/dispatch-platform-integrations": patch +"@trytilde/dispatch-control-service-provider": patch +"@trytilde/dispatch-runtime-provider": patch +"@trytilde/dispatch-control-service": patch +"@trytilde/dispatch-ui": patch +"@trytilde/dispatch-web": patch --- Keep local browser authentication on the Vite origin and reconcile loopback OAuth callbacks during development. diff --git a/.changeset/fix-memory-catcher-response-mode.md b/.changeset/fix-memory-catcher-response-mode.md index ced46399..70844953 100644 --- a/.changeset/fix-memory-catcher-response-mode.md +++ b/.changeset/fix-memory-catcher-response-mode.md @@ -1,5 +1,5 @@ --- -"openbot": patch +"@trytilde/cli": patch --- Run Memory Catcher as a background agent loop so synthesis does not require conversational participant-routing headers. diff --git a/.changeset/fix-memory-catcher-system-history.md b/.changeset/fix-memory-catcher-system-history.md index ee1d8ba3..500cc233 100644 --- a/.changeset/fix-memory-catcher-system-history.md +++ b/.changeset/fix-memory-catcher-system-history.md @@ -1,5 +1,5 @@ --- -"openbot": patch +"@trytilde/cli": patch --- Exclude historic system records from Memory Catcher model messages because its system prompt is supplied through the dedicated instructions field. diff --git a/.changeset/fix-remote-dev-origin.md b/.changeset/fix-remote-dev-origin.md index f42f7612..89c31d14 100644 --- a/.changeset/fix-remote-dev-origin.md +++ b/.changeset/fix-remote-dev-origin.md @@ -1,23 +1,23 @@ --- -"@tryopenbot/agent-provider": patch -"@tryopenbot/agent-service-provider": patch -"@tryopenbot/auth-provider": patch -"openbot": patch -"@tryopenbot/computer-service-provider": patch -"@tryopenbot/client-runtime": patch -"@tryopenbot/computer-tools": patch -"@tryopenbot/computer-service": patch -"@tryopenbot/computer-service-proto": patch -"@tryopenbot/configuration": patch -"@tryopenbot/desktop": patch -"@tryopenbot/utilities": patch -"@tryopenbot/platform-integrations": patch -"@tryopenbot/control-service-provider": patch -"@tryopenbot/runtime-provider": patch -"@tryopenbot/control-service": patch -"@tryopenbot/ui": patch -"@tryopenbot/web": patch -"@tryopenbot/git-provider": patch +"@trytilde/dispatch-agent-provider": patch +"@trytilde/dispatch-agent-service-provider": patch +"@trytilde/dispatch-auth-provider": patch +"@trytilde/cli": patch +"@trytilde/dispatch-computer-service-provider": patch +"@trytilde/dispatch-client-runtime": patch +"@trytilde/dispatch-computer-tools": patch +"@trytilde/dispatch-computer-service": patch +"@trytilde/dispatch-computer-service-proto": patch +"@trytilde/dispatch-configuration": patch +"@trytilde/dispatch-desktop": patch +"@trytilde/dispatch-utilities": patch +"@trytilde/dispatch-platform-integrations": patch +"@trytilde/dispatch-control-service-provider": patch +"@trytilde/dispatch-runtime-provider": patch +"@trytilde/dispatch-control-service": patch +"@trytilde/dispatch-ui": patch +"@trytilde/dispatch-web": patch +"@trytilde/dispatch-git-provider": patch --- Allow cookie-authenticated requests through a host-matched HTTPS development proxy without weakening origin checks. diff --git a/.changeset/fix-transcript-and-desktop-shell.md b/.changeset/fix-transcript-and-desktop-shell.md index 403f787d..4eaaff6f 100644 --- a/.changeset/fix-transcript-and-desktop-shell.md +++ b/.changeset/fix-transcript-and-desktop-shell.md @@ -1,23 +1,23 @@ --- -"@tryopenbot/agent-provider": patch -"@tryopenbot/agent-service-provider": patch -"@tryopenbot/auth-provider": patch -"openbot": patch -"@tryopenbot/computer-service-provider": patch -"@tryopenbot/client-runtime": patch -"@tryopenbot/computer-tools": patch -"@tryopenbot/computer-service": patch -"@tryopenbot/computer-service-proto": patch -"@tryopenbot/configuration": patch -"@tryopenbot/desktop": patch -"@tryopenbot/utilities": patch -"@tryopenbot/platform-integrations": patch -"@tryopenbot/control-service-provider": patch -"@tryopenbot/runtime-provider": patch -"@tryopenbot/control-service": patch -"@tryopenbot/ui": patch -"@tryopenbot/web": patch -"@tryopenbot/git-provider": patch +"@trytilde/dispatch-agent-provider": patch +"@trytilde/dispatch-agent-service-provider": patch +"@trytilde/dispatch-auth-provider": patch +"@trytilde/cli": patch +"@trytilde/dispatch-computer-service-provider": patch +"@trytilde/dispatch-client-runtime": patch +"@trytilde/dispatch-computer-tools": patch +"@trytilde/dispatch-computer-service": patch +"@trytilde/dispatch-computer-service-proto": patch +"@trytilde/dispatch-configuration": patch +"@trytilde/dispatch-desktop": patch +"@trytilde/dispatch-utilities": patch +"@trytilde/dispatch-platform-integrations": patch +"@trytilde/dispatch-control-service-provider": patch +"@trytilde/dispatch-runtime-provider": patch +"@trytilde/dispatch-control-service": patch +"@trytilde/dispatch-ui": patch +"@trytilde/dispatch-web": patch +"@trytilde/dispatch-git-provider": patch --- Keep the transcript loading skeleton, scroll-to-bottom control, and Electron drag regions stable across themes and workspace states. diff --git a/.changeset/fix-workspace-diagnostics-and-layout.md b/.changeset/fix-workspace-diagnostics-and-layout.md index 5e67706c..88a5f067 100644 --- a/.changeset/fix-workspace-diagnostics-and-layout.md +++ b/.changeset/fix-workspace-diagnostics-and-layout.md @@ -1,23 +1,23 @@ --- -"@tryopenbot/agent-provider": patch -"@tryopenbot/agent-service-provider": patch -"@tryopenbot/auth-provider": patch -"openbot": patch -"@tryopenbot/computer-service-provider": patch -"@tryopenbot/client-runtime": patch -"@tryopenbot/computer-tools": patch -"@tryopenbot/computer-service": patch -"@tryopenbot/computer-service-proto": patch -"@tryopenbot/configuration": patch -"@tryopenbot/desktop": patch -"@tryopenbot/utilities": patch -"@tryopenbot/platform-integrations": patch -"@tryopenbot/control-service-provider": patch -"@tryopenbot/runtime-provider": patch -"@tryopenbot/control-service": patch -"@tryopenbot/ui": patch -"@tryopenbot/web": patch -"@tryopenbot/git-provider": patch +"@trytilde/dispatch-agent-provider": patch +"@trytilde/dispatch-agent-service-provider": patch +"@trytilde/dispatch-auth-provider": patch +"@trytilde/cli": patch +"@trytilde/dispatch-computer-service-provider": patch +"@trytilde/dispatch-client-runtime": patch +"@trytilde/dispatch-computer-tools": patch +"@trytilde/dispatch-computer-service": patch +"@trytilde/dispatch-computer-service-proto": patch +"@trytilde/dispatch-configuration": patch +"@trytilde/dispatch-desktop": patch +"@trytilde/dispatch-utilities": patch +"@trytilde/dispatch-platform-integrations": patch +"@trytilde/dispatch-control-service-provider": patch +"@trytilde/dispatch-runtime-provider": patch +"@trytilde/dispatch-control-service": patch +"@trytilde/dispatch-ui": patch +"@trytilde/dispatch-web": patch +"@trytilde/dispatch-git-provider": patch --- Improve local diagnostics, preserve chat state while loading, and refine the workspace composer, steering queue, rich media, typography, sizing, and resize behaviour. diff --git a/.changeset/fix-workspace-entry-detection.md b/.changeset/fix-workspace-entry-detection.md index 7b3e1f37..bd371c0c 100644 --- a/.changeset/fix-workspace-entry-detection.md +++ b/.changeset/fix-workspace-entry-detection.md @@ -1,5 +1,5 @@ --- -"openbot": patch +"@trytilde/cli": patch --- -Detect an unbuilt workspace dependency by its runtime export condition rather than the first one listed. A package whose `exports` map starts with `types` and `development` pointing at TypeScript source looked built even when its `dist` was missing, so `openbot mobile expo` skipped the build and Metro failed with `While trying to resolve module @tryopenbot/client-runtime ... specifies a main module field that could not be resolved`. +Detect an unbuilt workspace dependency by its runtime export condition rather than the first one listed. A package whose `exports` map starts with `types` and `development` pointing at TypeScript source looked built even when its `dist` was missing, so `tilde mobile expo` skipped the build and Metro failed with `While trying to resolve module @trytilde/dispatch-client-runtime ... specifies a main module field that could not be resolved`. diff --git a/.changeset/float-computer-preview.md b/.changeset/float-computer-preview.md index de3c6f10..92e0e841 100644 --- a/.changeset/float-computer-preview.md +++ b/.changeset/float-computer-preview.md @@ -1,23 +1,23 @@ --- -"@tryopenbot/agent-provider": patch -"@tryopenbot/agent-service-provider": patch -"@tryopenbot/auth-provider": patch -"openbot": patch -"@tryopenbot/computer-service-provider": patch -"@tryopenbot/client-runtime": patch -"@tryopenbot/computer-tools": patch -"@tryopenbot/computer-service": patch -"@tryopenbot/computer-service-proto": patch -"@tryopenbot/configuration": patch -"@tryopenbot/desktop": patch -"@tryopenbot/utilities": patch -"@tryopenbot/platform-integrations": patch -"@tryopenbot/control-service-provider": patch -"@tryopenbot/runtime-provider": patch -"@tryopenbot/control-service": patch -"@tryopenbot/ui": patch -"@tryopenbot/web": patch -"@tryopenbot/git-provider": patch +"@trytilde/dispatch-agent-provider": patch +"@trytilde/dispatch-agent-service-provider": patch +"@trytilde/dispatch-auth-provider": patch +"@trytilde/cli": patch +"@trytilde/dispatch-computer-service-provider": patch +"@trytilde/dispatch-client-runtime": patch +"@trytilde/dispatch-computer-tools": patch +"@trytilde/dispatch-computer-service": patch +"@trytilde/dispatch-computer-service-proto": patch +"@trytilde/dispatch-configuration": patch +"@trytilde/dispatch-desktop": patch +"@trytilde/dispatch-utilities": patch +"@trytilde/dispatch-platform-integrations": patch +"@trytilde/dispatch-control-service-provider": patch +"@trytilde/dispatch-runtime-provider": patch +"@trytilde/dispatch-control-service": patch +"@trytilde/dispatch-ui": patch +"@trytilde/dispatch-web": patch +"@trytilde/dispatch-git-provider": patch --- Restore the floating bottom-right Computer preview in web and desktop workspaces. diff --git a/.changeset/fold-tilde-sdk-into-dispatch.md b/.changeset/fold-tilde-sdk-into-dispatch.md new file mode 100644 index 00000000..d3b4883b --- /dev/null +++ b/.changeset/fold-tilde-sdk-into-dispatch.md @@ -0,0 +1,29 @@ +--- +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/dispatch-auth-provider": minor +"@trytilde/cli": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-client-runtime": minor +"@trytilde/dispatch-computer-tools": minor +"@trytilde/dispatch-computer-service": minor +"@trytilde/dispatch-computer-service-proto": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-utilities": minor +"@trytilde/dispatch-platform-integrations": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-runtime-provider": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor +"@trytilde/dispatch-git-provider": minor +"@trytilde/api-client": minor +--- + +Move the Tilde TypeScript SDK into the Dispatch monorepo under the `@trytilde/sdk*` package names and add Tilde authentication, state, tunnel, plugin, and SDK workflows to `dispatch`. + +Migration: +- Replace `@trytilde/harness-sdk*` imports with the corresponding `@trytilde/sdk*` package. +- Replace `@trytilde/harness-plugins` and coding-agent wrapper binaries with `tilde plugin`. +- Replace `tilde auth|state|tunnel` with `tilde auth|state|tunnel`. diff --git a/.changeset/fold-tilde-sdk-into-openbot.md b/.changeset/fold-tilde-sdk-into-openbot.md deleted file mode 100644 index 8217dacf..00000000 --- a/.changeset/fold-tilde-sdk-into-openbot.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -"@tryopenbot/agent-provider": minor -"@tryopenbot/agent-service-provider": minor -"@tryopenbot/auth-provider": minor -"openbot": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/client-runtime": minor -"@tryopenbot/computer-tools": minor -"@tryopenbot/computer-service": minor -"@tryopenbot/computer-service-proto": minor -"@tryopenbot/configuration": minor -"@tryopenbot/desktop": minor -"@tryopenbot/utilities": minor -"@tryopenbot/platform-integrations": minor -"@tryopenbot/control-service-provider": minor -"@tryopenbot/runtime-provider": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor -"@tryopenbot/git-provider": minor -"@trytilde/api-client": minor ---- - -Move the Tilde TypeScript SDK into the OpenBot monorepo under the `@trytilde/sdk*` package names and add Tilde authentication, state, tunnel, plugin, and SDK workflows to `openbot`. - -Migration: -- Replace `@trytilde/harness-sdk*` imports with the corresponding `@trytilde/sdk*` package. -- Replace `@trytilde/harness-plugins` and coding-agent wrapper binaries with `openbot plugin`. -- Replace `tilde auth|state|tunnel` with `openbot auth|state|tunnel`. diff --git a/.changeset/fork-first-configuration.md b/.changeset/fork-first-configuration.md index 1e1fa2a4..21c0d965 100644 --- a/.changeset/fork-first-configuration.md +++ b/.changeset/fork-first-configuration.md @@ -1,14 +1,14 @@ --- -"@tryopenbot/configuration": minor -"@tryopenbot/desktop": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor -"openbot": minor -"@tryopenbot/agent-service-provider": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/computer-service": minor -"@tryopenbot/computer-service-proto": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor +"@trytilde/cli": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-computer-service": minor +"@trytilde/dispatch-computer-service-proto": minor --- -Add one fork-owned `configuration/` tree for directly authored Vercel AI SDK-compatible agent endpoints, agent-scoped skills and workspace seeds, and provider integrations, with an interactive terminal CLI for setup and operation. Concrete implementations are grouped under `Configuration({ providers: { ... } })`; repository resources use canonical file locations instead of configurable paths. OpenBot discovers committed agent modules without generating or publishing TypeScript at runtime. +Add one fork-owned `configuration/` tree for directly authored Vercel AI SDK-compatible agent endpoints, agent-scoped skills and workspace seeds, and provider integrations, with an interactive terminal CLI for setup and operation. Concrete implementations are grouped under `Configuration({ providers: { ... } })`; repository resources use canonical file locations instead of configurable paths. Dispatch discovers committed agent modules without generating or publishing TypeScript at runtime. diff --git a/.changeset/improve-mobile-search.md b/.changeset/improve-mobile-search.md index 0dc2b61c..cad77839 100644 --- a/.changeset/improve-mobile-search.md +++ b/.changeset/improve-mobile-search.md @@ -1,23 +1,23 @@ --- -"@tryopenbot/agent-provider": patch -"@tryopenbot/agent-service-provider": patch -"@tryopenbot/auth-provider": patch -"openbot": patch -"@tryopenbot/computer-service-provider": patch -"@tryopenbot/client-runtime": patch -"@tryopenbot/computer-tools": patch -"@tryopenbot/computer-service": patch -"@tryopenbot/computer-service-proto": patch -"@tryopenbot/configuration": patch -"@tryopenbot/desktop": patch -"@tryopenbot/utilities": patch -"@tryopenbot/platform-integrations": patch -"@tryopenbot/control-service-provider": patch -"@tryopenbot/runtime-provider": patch -"@tryopenbot/control-service": patch -"@tryopenbot/ui": patch -"@tryopenbot/web": patch -"@tryopenbot/git-provider": patch +"@trytilde/dispatch-agent-provider": patch +"@trytilde/dispatch-agent-service-provider": patch +"@trytilde/dispatch-auth-provider": patch +"@trytilde/cli": patch +"@trytilde/dispatch-computer-service-provider": patch +"@trytilde/dispatch-client-runtime": patch +"@trytilde/dispatch-computer-tools": patch +"@trytilde/dispatch-computer-service": patch +"@trytilde/dispatch-computer-service-proto": patch +"@trytilde/dispatch-configuration": patch +"@trytilde/dispatch-desktop": patch +"@trytilde/dispatch-utilities": patch +"@trytilde/dispatch-platform-integrations": patch +"@trytilde/dispatch-control-service-provider": patch +"@trytilde/dispatch-runtime-provider": patch +"@trytilde/dispatch-control-service": patch +"@trytilde/dispatch-ui": patch +"@trytilde/dispatch-web": patch +"@trytilde/dispatch-git-provider": patch --- Improve mobile navigation, settings, dialogs, search results, and chat composer behavior. diff --git a/.changeset/improve-mobile-workspace.md b/.changeset/improve-mobile-workspace.md index 72728f08..996c267d 100644 --- a/.changeset/improve-mobile-workspace.md +++ b/.changeset/improve-mobile-workspace.md @@ -1,23 +1,23 @@ --- -"@tryopenbot/agent-provider": patch -"@tryopenbot/agent-service-provider": patch -"@tryopenbot/auth-provider": patch -"openbot": patch -"@tryopenbot/computer-service-provider": patch -"@tryopenbot/client-runtime": patch -"@tryopenbot/computer-tools": patch -"@tryopenbot/computer-service": patch -"@tryopenbot/computer-service-proto": patch -"@tryopenbot/configuration": patch -"@tryopenbot/desktop": patch -"@tryopenbot/utilities": patch -"@tryopenbot/platform-integrations": patch -"@tryopenbot/control-service-provider": patch -"@tryopenbot/runtime-provider": patch -"@tryopenbot/control-service": patch -"@tryopenbot/ui": patch -"@tryopenbot/web": patch -"@tryopenbot/git-provider": patch +"@trytilde/dispatch-agent-provider": patch +"@trytilde/dispatch-agent-service-provider": patch +"@trytilde/dispatch-auth-provider": patch +"@trytilde/cli": patch +"@trytilde/dispatch-computer-service-provider": patch +"@trytilde/dispatch-client-runtime": patch +"@trytilde/dispatch-computer-tools": patch +"@trytilde/dispatch-computer-service": patch +"@trytilde/dispatch-computer-service-proto": patch +"@trytilde/dispatch-configuration": patch +"@trytilde/dispatch-desktop": patch +"@trytilde/dispatch-utilities": patch +"@trytilde/dispatch-platform-integrations": patch +"@trytilde/dispatch-control-service-provider": patch +"@trytilde/dispatch-runtime-provider": patch +"@trytilde/dispatch-control-service": patch +"@trytilde/dispatch-ui": patch +"@trytilde/dispatch-web": patch +"@trytilde/dispatch-git-provider": patch --- Make the web workspace mobile-friendly with a slide-out navigation sheet, touch-sized controls, safe-area spacing, and a composer that keeps Enter available for new lines on touch devices. diff --git a/.changeset/improve-workspace-tools-settings.md b/.changeset/improve-workspace-tools-settings.md index b2add557..4373a409 100644 --- a/.changeset/improve-workspace-tools-settings.md +++ b/.changeset/improve-workspace-tools-settings.md @@ -1,9 +1,9 @@ --- -"@tryopenbot/control-service": minor -"@tryopenbot/web": minor -"@tryopenbot/client-runtime": minor -"@tryopenbot/ui": minor -"openbot": patch +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-web": minor +"@trytilde/dispatch-client-runtime": minor +"@trytilde/dispatch-ui": minor +"@trytilde/cli": patch --- Improve connector, plugin, routine, conversation-thread, and tool-message behavior across the shared workspace runtime and clients. diff --git a/.changeset/isolate-memory-synthesis-batch.md b/.changeset/isolate-memory-synthesis-batch.md index 15615cdf..d5f88d37 100644 --- a/.changeset/isolate-memory-synthesis-batch.md +++ b/.changeset/isolate-memory-synthesis-batch.md @@ -1,5 +1,5 @@ --- -"openbot": patch +"@trytilde/cli": patch --- Isolate Memory Catcher inference to the current signed batch so stale retry leases cannot influence memory mutations. diff --git a/.changeset/keep-code-storage-remotes-clean.md b/.changeset/keep-code-storage-remotes-clean.md index 2e3a38bf..7281c14a 100644 --- a/.changeset/keep-code-storage-remotes-clean.md +++ b/.changeset/keep-code-storage-remotes-clean.md @@ -1,23 +1,23 @@ --- -"@tryopenbot/agent-provider": patch -"@tryopenbot/agent-service-provider": patch -"@tryopenbot/auth-provider": patch -"openbot": patch -"@tryopenbot/computer-service-provider": patch -"@tryopenbot/client-runtime": patch -"@tryopenbot/computer-tools": patch -"@tryopenbot/computer-service": patch -"@tryopenbot/computer-service-proto": patch -"@tryopenbot/configuration": patch -"@tryopenbot/desktop": patch -"@tryopenbot/utilities": patch -"@tryopenbot/platform-integrations": patch -"@tryopenbot/control-service-provider": patch -"@tryopenbot/runtime-provider": patch -"@tryopenbot/control-service": patch -"@tryopenbot/ui": patch -"@tryopenbot/web": patch -"@tryopenbot/git-provider": patch +"@trytilde/dispatch-agent-provider": patch +"@trytilde/dispatch-agent-service-provider": patch +"@trytilde/dispatch-auth-provider": patch +"@trytilde/cli": patch +"@trytilde/dispatch-computer-service-provider": patch +"@trytilde/dispatch-client-runtime": patch +"@trytilde/dispatch-computer-tools": patch +"@trytilde/dispatch-computer-service": patch +"@trytilde/dispatch-computer-service-proto": patch +"@trytilde/dispatch-configuration": patch +"@trytilde/dispatch-desktop": patch +"@trytilde/dispatch-utilities": patch +"@trytilde/dispatch-platform-integrations": patch +"@trytilde/dispatch-control-service-provider": patch +"@trytilde/dispatch-runtime-provider": patch +"@trytilde/dispatch-control-service": patch +"@trytilde/dispatch-ui": patch +"@trytilde/dispatch-web": patch +"@trytilde/dispatch-git-provider": patch --- Keep Code Storage credentials out of persistent Git remote URLs while preserving unattended reconciliation. diff --git a/.changeset/log-memory-catcher-inference.md b/.changeset/log-memory-catcher-inference.md index 72839041..af11bc9a 100644 --- a/.changeset/log-memory-catcher-inference.md +++ b/.changeset/log-memory-catcher-inference.md @@ -1,5 +1,5 @@ --- -"openbot": patch +"@trytilde/cli": patch --- Log bounded, redacted Memory Catcher inference failures so background synthesis failures can be diagnosed without exposing request payloads. diff --git a/.changeset/meter-memory-synthesis.md b/.changeset/meter-memory-synthesis.md index 47750b36..bd55867b 100644 --- a/.changeset/meter-memory-synthesis.md +++ b/.changeset/meter-memory-synthesis.md @@ -1,25 +1,25 @@ --- "@trytilde/sdk-vercel-ai-node": minor "@trytilde/sdk": minor -"@tryopenbot/agent-provider": minor -"@tryopenbot/agent-service-provider": minor -"@tryopenbot/auth-provider": minor -"openbot": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/client-runtime": minor -"@tryopenbot/computer-tools": minor -"@tryopenbot/computer-service": minor -"@tryopenbot/computer-service-proto": minor -"@tryopenbot/configuration": minor -"@tryopenbot/desktop": minor -"@tryopenbot/utilities": minor -"@tryopenbot/platform-integrations": minor -"@tryopenbot/control-service-provider": minor -"@tryopenbot/runtime-provider": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor -"@tryopenbot/git-provider": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/dispatch-auth-provider": minor +"@trytilde/cli": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-client-runtime": minor +"@trytilde/dispatch-computer-tools": minor +"@trytilde/dispatch-computer-service": minor +"@trytilde/dispatch-computer-service-proto": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-utilities": minor +"@trytilde/dispatch-platform-integrations": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-runtime-provider": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor +"@trytilde/dispatch-git-provider": minor --- Meter Memory Catcher synthesis through durable hosted inference billing. diff --git a/.changeset/migrate-chatkit-rest-routes.md b/.changeset/migrate-chatkit-rest-routes.md index 35eb0fed..045c2b8f 100644 --- a/.changeset/migrate-chatkit-rest-routes.md +++ b/.changeset/migrate-chatkit-rest-routes.md @@ -1,29 +1,29 @@ --- -"@tryopenbot/agent-provider": minor -"@tryopenbot/agent-service-provider": minor -"@tryopenbot/auth-provider": minor -"openbot": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/client-runtime": minor -"@tryopenbot/computer-tools": minor -"@tryopenbot/computer-service": minor -"@tryopenbot/computer-service-proto": minor -"@tryopenbot/configuration": minor -"@tryopenbot/desktop": minor -"@tryopenbot/utilities": minor -"@tryopenbot/platform-integrations": minor -"@tryopenbot/control-service-provider": minor -"@tryopenbot/runtime-provider": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor -"@tryopenbot/git-provider": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/dispatch-auth-provider": minor +"@trytilde/cli": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-client-runtime": minor +"@trytilde/dispatch-computer-tools": minor +"@trytilde/dispatch-computer-service": minor +"@trytilde/dispatch-computer-service-proto": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-utilities": minor +"@trytilde/dispatch-platform-integrations": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-runtime-provider": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor +"@trytilde/dispatch-git-provider": minor "@trytilde/api-client": minor "@trytilde/sdk": minor --- -Migrate OpenBot to Tilde's regular ChatKit activity, agent, session, message, search, turn, and realtime-ticket REST routes while preserving the ChatKit realtime contract. +Migrate Dispatch to Tilde's regular ChatKit activity, agent, session, message, search, turn, and realtime-ticket REST routes while preserving the ChatKit realtime contract. Migration: -- Replace `OpenBotClient.getBootstrap` with `OpenBotClient.getActivity`. +- Replace `DispatchClient.getBootstrap` with `DispatchClient.getActivity`. - Read the agent page from the activity response's `activity` field. diff --git a/.changeset/mobile-owner-parity.md b/.changeset/mobile-owner-parity.md index 1bc2bb11..2b8f5d73 100644 --- a/.changeset/mobile-owner-parity.md +++ b/.changeset/mobile-owner-parity.md @@ -1,23 +1,23 @@ --- -"@tryopenbot/agent-provider": minor -"@tryopenbot/agent-service-provider": minor -"@tryopenbot/auth-provider": minor -"openbot": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/client-runtime": minor -"@tryopenbot/computer-tools": minor -"@tryopenbot/computer-service": minor -"@tryopenbot/computer-service-proto": minor -"@tryopenbot/configuration": minor -"@tryopenbot/desktop": minor -"@tryopenbot/utilities": minor -"@tryopenbot/platform-integrations": minor -"@tryopenbot/control-service-provider": minor -"@tryopenbot/runtime-provider": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor -"@tryopenbot/git-provider": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/dispatch-auth-provider": minor +"@trytilde/cli": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-client-runtime": minor +"@trytilde/dispatch-computer-tools": minor +"@trytilde/dispatch-computer-service": minor +"@trytilde/dispatch-computer-service-proto": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-utilities": minor +"@trytilde/dispatch-platform-integrations": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-runtime-provider": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor +"@trytilde/dispatch-git-provider": minor --- Add shared queued-turn controls and native owner-client parity for onboarding, rich chat, attachments, and Computer takeover. diff --git a/.changeset/narrow-provider-boundaries.md b/.changeset/narrow-provider-boundaries.md index 3210349a..f5e48033 100644 --- a/.changeset/narrow-provider-boundaries.md +++ b/.changeset/narrow-provider-boundaries.md @@ -1,10 +1,10 @@ --- -"openbot": minor -"@tryopenbot/agent-provider": minor -"@tryopenbot/agent-service-provider": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/computer-tools": minor -"@tryopenbot/configuration": minor +"@trytilde/cli": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-computer-tools": minor +"@trytilde/dispatch-configuration": minor --- Separate chat APIs from agent provisioning, remove unused model-facing provider diff --git a/.changeset/official-store-publication.md b/.changeset/official-store-publication.md index 73d3a101..6958c9ad 100644 --- a/.changeset/official-store-publication.md +++ b/.changeset/official-store-publication.md @@ -1,5 +1,5 @@ --- -"openbot": minor +"@trytilde/cli": minor --- -Add store publication for the official OpenBot app through EAS. `openbot mobile release build|submit|status|credentials` drives `eas-cli`, requires an explicit `--yes` before spending build minutes or changing a public listing, and refuses to use the official EAS project from any remote other than `trytilde/dispatch`. `apps/mobile/app.json` becomes `app.config.ts` so a fork can point at its own EAS project, bundle identifier, and Expo owner through the environment rather than editing a tracked file. Recorded in ADR-0027. +Add store publication for the official Dispatch app through EAS. `tilde mobile release build|submit|status|credentials` drives `eas-cli`, requires an explicit `--yes` before spending build minutes or changing a public listing, and refuses to use the official EAS project from any remote other than `trytilde/dispatch`. `apps/mobile/app.json` becomes `app.config.ts` so a fork can point at its own EAS project, bundle identifier, and Expo owner through the environment rather than editing a tracked file. Recorded in ADR-0027. diff --git a/.changeset/onboarding-in-client-runtime.md b/.changeset/onboarding-in-client-runtime.md index aa04d30d..414d9985 100644 --- a/.changeset/onboarding-in-client-runtime.md +++ b/.changeset/onboarding-in-client-runtime.md @@ -1,7 +1,7 @@ --- -"@tryopenbot/client-runtime": minor -"@tryopenbot/web": patch -"@tryopenbot/ui": patch +"@trytilde/dispatch-client-runtime": minor +"@trytilde/dispatch-web": patch +"@trytilde/dispatch-ui": patch --- -Move onboarding state into `@tryopenbot/client-runtime`. Completion and the resulting agent description are persisted, survive reload, and decide whether a client shows first-run at all, so per ADR-0017 they are runtime state rather than renderer state. The runtime owns the contract, validation, and read/write, and the platform supplies key/value storage — `localStorage` on web, and the same interface accepts Expo SecureStore or the Electron bridge unchanged. `OnboardingResult` now has one definition, re-exported by `@tryopenbot/ui` so callers keep a single type. +Move onboarding state into `@trytilde/dispatch-client-runtime`. Completion and the resulting agent description are persisted, survive reload, and decide whether a client shows first-run at all, so per ADR-0017 they are runtime state rather than renderer state. The runtime owns the contract, validation, and read/write, and the platform supplies key/value storage — `localStorage` on web, and the same interface accepts Expo SecureStore or the Electron bridge unchanged. `OnboardingResult` now has one definition, re-exported by `@trytilde/dispatch-ui` so callers keep a single type. diff --git a/.changeset/polish-routines-and-providers.md b/.changeset/polish-routines-and-providers.md index 56b89414..ae3214a5 100644 --- a/.changeset/polish-routines-and-providers.md +++ b/.changeset/polish-routines-and-providers.md @@ -1,23 +1,23 @@ --- -"@tryopenbot/agent-provider": patch -"@tryopenbot/agent-service-provider": patch -"@tryopenbot/auth-provider": patch -"openbot": patch -"@tryopenbot/computer-service-provider": patch -"@tryopenbot/client-runtime": patch -"@tryopenbot/computer-tools": patch -"@tryopenbot/computer-service": patch -"@tryopenbot/computer-service-proto": patch -"@tryopenbot/configuration": patch -"@tryopenbot/desktop": patch -"@tryopenbot/utilities": patch -"@tryopenbot/platform-integrations": patch -"@tryopenbot/control-service-provider": patch -"@tryopenbot/runtime-provider": patch -"@tryopenbot/control-service": patch -"@tryopenbot/ui": patch -"@tryopenbot/web": patch -"@tryopenbot/git-provider": patch +"@trytilde/dispatch-agent-provider": patch +"@trytilde/dispatch-agent-service-provider": patch +"@trytilde/dispatch-auth-provider": patch +"@trytilde/cli": patch +"@trytilde/dispatch-computer-service-provider": patch +"@trytilde/dispatch-client-runtime": patch +"@trytilde/dispatch-computer-tools": patch +"@trytilde/dispatch-computer-service": patch +"@trytilde/dispatch-computer-service-proto": patch +"@trytilde/dispatch-configuration": patch +"@trytilde/dispatch-desktop": patch +"@trytilde/dispatch-utilities": patch +"@trytilde/dispatch-platform-integrations": patch +"@trytilde/dispatch-control-service-provider": patch +"@trytilde/dispatch-runtime-provider": patch +"@trytilde/dispatch-control-service": patch +"@trytilde/dispatch-ui": patch +"@trytilde/dispatch-web": patch +"@trytilde/dispatch-git-provider": patch --- Polish the mobile composer and account menu, deduplicate provider cards, resolve trusted icons, cache plugin catalogues, and add end-user routine provider and routine management settings. diff --git a/.changeset/provision-ndk-and-cmake.md b/.changeset/provision-ndk-and-cmake.md index 42fc4af0..ecaa79f9 100644 --- a/.changeset/provision-ndk-and-cmake.md +++ b/.changeset/provision-ndk-and-cmake.md @@ -1,5 +1,5 @@ --- -"openbot": patch +"@trytilde/cli": patch --- -Provision the NDK and CMake in `openbot mobile setup`, reading the NDK version React Native pins in its `gradle/libs.versions.toml` rather than restating it, and check the NDK in `openbot mobile doctor`. The Android Gradle Plugin downloads both partway through a build otherwise, and a mismatch surfaces as a failed `configureCMakeDebug` task that names neither the NDK nor the cause. +Provision the NDK and CMake in `tilde mobile setup`, reading the NDK version React Native pins in its `gradle/libs.versions.toml` rather than restating it, and check the NDK in `tilde mobile doctor`. The Android Gradle Plugin downloads both partway through a build otherwise, and a mismatch surfaces as a failed `configureCMakeDebug` task that names neither the NDK nor the cause. diff --git a/.changeset/publish-public-packages.md b/.changeset/publish-public-packages.md index 277f5f7f..0fd27cff 100644 --- a/.changeset/publish-public-packages.md +++ b/.changeset/publish-public-packages.md @@ -1,21 +1,21 @@ --- -"@tryopenbot/agent-provider": minor -"@tryopenbot/agent-service-provider": minor -"openbot": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/computer-service": minor -"@tryopenbot/computer-service-proto": minor -"@tryopenbot/configuration": minor -"@tryopenbot/desktop": minor -"@tryopenbot/utilities": minor -"@tryopenbot/control-service-provider": minor -"@tryopenbot/runtime-provider": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/cli": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-computer-service": minor +"@trytilde/dispatch-computer-service-proto": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-utilities": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-runtime-provider": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor --- -Publish all OpenBot workspace packages publicly with runnable JavaScript artifacts and declarations, and provide `openbot` as an installable standalone CLI. +Publish all Dispatch workspace packages publicly with runnable JavaScript artifacts and declarations, and provide `dispatch` as an installable standalone CLI. Refresh selected AWS profile credentials through AWS CLI before SOPS operations so IAM Identity Center sessions work during initialization and later secret access. @@ -23,5 +23,5 @@ Support AI agents and automation with non-interactive initialization through sta Migration: -- Replace the internal package name `@tryopenbot/cli` with the public `openbot` package. -- Invoke the installed CLI with `openbot ` or `npx openbot `. +- Replace the internal package name `@trytilde/dispatch-cli` with the public `dispatch` package. +- Invoke the installed CLI with `tilde ` or `npx @trytilde/cli `. diff --git a/.changeset/reconcile-provider-lifecycles.md b/.changeset/reconcile-provider-lifecycles.md index 03b67e6c..0423a577 100644 --- a/.changeset/reconcile-provider-lifecycles.md +++ b/.changeset/reconcile-provider-lifecycles.md @@ -1,20 +1,20 @@ --- -"@tryopenbot/agent-provider": minor -"@tryopenbot/agent-service-provider": minor -"openbot": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/computer-tools": minor -"@tryopenbot/computer-service": minor -"@tryopenbot/computer-service-proto": minor -"@tryopenbot/configuration": minor -"@tryopenbot/desktop": minor -"@tryopenbot/utilities": minor -"@tryopenbot/platform-integrations": minor -"@tryopenbot/control-service-provider": minor -"@tryopenbot/runtime-provider": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/cli": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-computer-tools": minor +"@trytilde/dispatch-computer-service": minor +"@trytilde/dispatch-computer-service-proto": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-utilities": minor +"@trytilde/dispatch-platform-integrations": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-runtime-provider": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor --- Reconcile authored agents, skills, tools, services, and Computers through idempotent provider lifecycles in development and deployment. diff --git a/.changeset/refine-continuous-chat.md b/.changeset/refine-continuous-chat.md index d37853b2..b2379a56 100644 --- a/.changeset/refine-continuous-chat.md +++ b/.changeset/refine-continuous-chat.md @@ -1,20 +1,20 @@ --- -"@tryopenbot/agent-provider": minor -"@tryopenbot/agent-service-provider": minor -"openbot": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/computer-tools": minor -"@tryopenbot/computer-service": minor -"@tryopenbot/computer-service-proto": minor -"@tryopenbot/configuration": minor -"@tryopenbot/desktop": minor -"@tryopenbot/utilities": minor -"@tryopenbot/platform-integrations": minor -"@tryopenbot/control-service-provider": minor -"@tryopenbot/runtime-provider": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/cli": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-computer-tools": minor +"@trytilde/dispatch-computer-service": minor +"@trytilde/dispatch-computer-service-proto": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-utilities": minor +"@trytilde/dispatch-platform-integrations": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-runtime-provider": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor --- Refine the owner workspace into a continuous per-agent chat with the reference light palette, patterned agent avatars, message replies, file composition, and Tilde connector authorization cards. diff --git a/.changeset/refresh-managed-cua-resources.md b/.changeset/refresh-managed-cua-resources.md index 9a6c34c3..ac35c50c 100644 --- a/.changeset/refresh-managed-cua-resources.md +++ b/.changeset/refresh-managed-cua-resources.md @@ -1,23 +1,23 @@ --- -"@tryopenbot/agent-provider": patch -"@tryopenbot/agent-service-provider": patch -"@tryopenbot/auth-provider": patch -"openbot": patch -"@tryopenbot/computer-service-provider": patch -"@tryopenbot/client-runtime": patch -"@tryopenbot/computer-tools": patch -"@tryopenbot/computer-service": patch -"@tryopenbot/computer-service-proto": patch -"@tryopenbot/configuration": patch -"@tryopenbot/desktop": patch -"@tryopenbot/utilities": patch -"@tryopenbot/platform-integrations": patch -"@tryopenbot/control-service-provider": patch -"@tryopenbot/runtime-provider": patch -"@tryopenbot/control-service": patch -"@tryopenbot/ui": patch -"@tryopenbot/web": patch -"@tryopenbot/git-provider": patch +"@trytilde/dispatch-agent-provider": patch +"@trytilde/dispatch-agent-service-provider": patch +"@trytilde/dispatch-auth-provider": patch +"@trytilde/cli": patch +"@trytilde/dispatch-computer-service-provider": patch +"@trytilde/dispatch-client-runtime": patch +"@trytilde/dispatch-computer-tools": patch +"@trytilde/dispatch-computer-service": patch +"@trytilde/dispatch-computer-service-proto": patch +"@trytilde/dispatch-configuration": patch +"@trytilde/dispatch-desktop": patch +"@trytilde/dispatch-utilities": patch +"@trytilde/dispatch-platform-integrations": patch +"@trytilde/dispatch-control-service-provider": patch +"@trytilde/dispatch-runtime-provider": patch +"@trytilde/dispatch-control-service": patch +"@trytilde/dispatch-ui": patch +"@trytilde/dispatch-web": patch +"@trytilde/dispatch-git-provider": patch --- Discover current managed Cua skills and Vercel credentials after provider resources are reprovisioned. diff --git a/.changeset/remove-dead-workspace-surfaces.md b/.changeset/remove-dead-workspace-surfaces.md index 45267587..336efec7 100644 --- a/.changeset/remove-dead-workspace-surfaces.md +++ b/.changeset/remove-dead-workspace-surfaces.md @@ -1,6 +1,6 @@ --- -"@tryopenbot/ui": minor -"@tryopenbot/web": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor --- -Remove the unreachable conversation outline and background tasks panels, and route the web authentication gate through the shared client runtime instead of its own session fetch. `AsyncTasksPanel`, `ConversationOutlinePanel`, and their types are no longer exported from `@tryopenbot/ui`. The gate now bootstraps the runtime, which also fixes the runtime never being initialized, and the onboarding no longer persists a result nothing read. +Remove the unreachable conversation outline and background tasks panels, and route the web authentication gate through the shared client runtime instead of its own session fetch. `AsyncTasksPanel`, `ConversationOutlinePanel`, and their types are no longer exported from `@trytilde/dispatch-ui`. The gate now bootstraps the runtime, which also fixes the runtime never being initialized, and the onboarding no longer persists a result nothing read. diff --git a/.changeset/remove-mobile-client.md b/.changeset/remove-mobile-client.md index 7a3c1a5e..1d8f18ad 100644 --- a/.changeset/remove-mobile-client.md +++ b/.changeset/remove-mobile-client.md @@ -1,27 +1,27 @@ --- -"@tryopenbot/agent-provider": minor -"@tryopenbot/agent-service-provider": minor -"@tryopenbot/auth-provider": minor -"openbot": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/client-runtime": minor -"@tryopenbot/computer-tools": minor -"@tryopenbot/computer-service": minor -"@tryopenbot/computer-service-proto": minor -"@tryopenbot/configuration": minor -"@tryopenbot/desktop": minor -"@tryopenbot/utilities": minor -"@tryopenbot/platform-integrations": minor -"@tryopenbot/control-service-provider": minor -"@tryopenbot/runtime-provider": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor -"@tryopenbot/git-provider": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/dispatch-auth-provider": minor +"@trytilde/cli": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-client-runtime": minor +"@trytilde/dispatch-computer-tools": minor +"@trytilde/dispatch-computer-service": minor +"@trytilde/dispatch-computer-service-proto": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-utilities": minor +"@trytilde/dispatch-platform-integrations": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-runtime-provider": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor +"@trytilde/dispatch-git-provider": minor --- -Remove the paused Expo mobile client, Android/iOS tooling, EAS publication workflow, and `openbot mobile` command group from main. The complete implementation remains preserved on the `codex/mobile-archive` DO NOT MERGE branch. +Remove the paused Expo mobile client, Android/iOS tooling, EAS publication workflow, and `tilde mobile` command group from main. The complete implementation remains preserved on the `codex/mobile-archive` DO NOT MERGE branch. Migration: -- Stop invoking `openbot mobile`, mobile root scripts, Metro/adb tunnels, or `mobile-v*` releases. +- Stop invoking `tilde mobile`, mobile root scripts, Metro/adb tunnels, or `mobile-v*` releases. - Use the web workspace or Electron desktop client while the product foundation is stabilized. diff --git a/.changeset/rename-computer-service-provider.md b/.changeset/rename-computer-service-provider.md index edd539ce..88c18bd2 100644 --- a/.changeset/rename-computer-service-provider.md +++ b/.changeset/rename-computer-service-provider.md @@ -1,5 +1,5 @@ --- -"@tryopenbot/computer-service-provider": minor +"@trytilde/dispatch-computer-service-provider": minor --- Rename the Computer lifecycle package to clarify that it builds, deploys, and provisions the Computer service, and remove the `computer-tools` compatibility re-export so agent runtime tools remain independently owned. diff --git a/.changeset/rename-dispatch-product.md b/.changeset/rename-dispatch-product.md new file mode 100644 index 00000000..bbf8c40a --- /dev/null +++ b/.changeset/rename-dispatch-product.md @@ -0,0 +1,31 @@ +--- +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/dispatch-auth-provider": minor +"@trytilde/cli": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-client-runtime": minor +"@trytilde/dispatch-computer-tools": minor +"@trytilde/dispatch-computer-service": minor +"@trytilde/dispatch-computer-service-proto": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-utilities": minor +"@trytilde/dispatch-platform-integrations": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-runtime-provider": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor +"@trytilde/dispatch-git-provider": minor +"@trytilde/api-client": minor +"@trytilde/sdk": minor +"@trytilde/sdk-vercel-ai-node": minor +--- + +Rename the product to Dispatch, publish its packages under `@trytilde/dispatch-*`, and replace the product-named CLI with `@trytilde/cli` and the `tilde` executable. + +Migration: +- Replace previous product-package imports and dependencies with their matching `@trytilde/dispatch-*` names. +- Install `@trytilde/cli` and invoke commands through `tilde`. +- Adopt the `DISPATCH_*` environment namespace and `.dispatch` state paths. diff --git a/.changeset/rename-github-repositories.md b/.changeset/rename-github-repositories.md index 08660e4a..34b9ac0c 100644 --- a/.changeset/rename-github-repositories.md +++ b/.changeset/rename-github-repositories.md @@ -1,5 +1,5 @@ --- -"openbot": patch +"@trytilde/cli": patch "@trytilde/api-client": patch "@trytilde/sdk": patch "@trytilde/sdk-react": patch diff --git a/.changeset/replace-chatkit-realtime-contract.md b/.changeset/replace-chatkit-realtime-contract.md index 976ac6d6..e80c0c94 100644 --- a/.changeset/replace-chatkit-realtime-contract.md +++ b/.changeset/replace-chatkit-realtime-contract.md @@ -1,23 +1,23 @@ --- -"@tryopenbot/agent-provider": minor -"@tryopenbot/agent-service-provider": minor -"@tryopenbot/auth-provider": minor -"openbot": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/client-runtime": minor -"@tryopenbot/computer-tools": minor -"@tryopenbot/computer-service": minor -"@tryopenbot/computer-service-proto": minor -"@tryopenbot/configuration": minor -"@tryopenbot/desktop": minor -"@tryopenbot/utilities": minor -"@tryopenbot/platform-integrations": minor -"@tryopenbot/control-service-provider": minor -"@tryopenbot/runtime-provider": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor -"@tryopenbot/git-provider": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/dispatch-auth-provider": minor +"@trytilde/cli": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-client-runtime": minor +"@trytilde/dispatch-computer-tools": minor +"@trytilde/dispatch-computer-service": minor +"@trytilde/dispatch-computer-service-proto": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-utilities": minor +"@trytilde/dispatch-platform-integrations": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-runtime-provider": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor +"@trytilde/dispatch-git-provider": minor --- Replace the owner-chat transport with typed ChatKit workspace and realtime contracts, including per-user read state and explicit queue and turn lifecycle events. diff --git a/.changeset/reset-application-shell.md b/.changeset/reset-application-shell.md index 3335c896..37b3e50c 100644 --- a/.changeset/reset-application-shell.md +++ b/.changeset/reset-application-shell.md @@ -1,6 +1,6 @@ --- -"@tryopenbot/control-service": minor -"@tryopenbot/web": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-web": minor --- Reset the application to a setup-free UX shell, an empty owner control contract, and a bare Hono server that remains healthy on Vercel. diff --git a/.changeset/resolve-jdk-like-gradle.md b/.changeset/resolve-jdk-like-gradle.md index aa2e3f2a..a250c0c1 100644 --- a/.changeset/resolve-jdk-like-gradle.md +++ b/.changeset/resolve-jdk-like-gradle.md @@ -1,5 +1,5 @@ --- -"openbot": patch +"@trytilde/cli": patch --- -Resolve the JDK in `openbot mobile doctor` the way Gradle does: `JAVA_HOME` first, `PATH` only as a fallback, with the source named in the output. On a machine with several JDKs installed — a linked Homebrew `openjdk` shadowing a keg-only `openjdk@21`, for instance — the previous check reported the compiler on `PATH` while Gradle built against a different one, so a correctly configured host could still be told its JDK was unsupported. Doctor now also notes when `JAVA_HOME` and `PATH` disagree. +Resolve the JDK in `tilde mobile doctor` the way Gradle does: `JAVA_HOME` first, `PATH` only as a fallback, with the source named in the output. On a machine with several JDKs installed — a linked Homebrew `openjdk` shadowing a keg-only `openjdk@21`, for instance — the previous check reported the compiler on `PATH` while Gradle built against a different one, so a correctly configured host could still be told its JDK was unsupported. Doctor now also notes when `JAVA_HOME` and `PATH` disagree. diff --git a/.changeset/retry-memory-binding-provisioning.md b/.changeset/retry-memory-binding-provisioning.md index aca93b5c..82f5731f 100644 --- a/.changeset/retry-memory-binding-provisioning.md +++ b/.changeset/retry-memory-binding-provisioning.md @@ -1,23 +1,23 @@ --- -"@tryopenbot/agent-provider": patch -"@tryopenbot/agent-service-provider": patch -"@tryopenbot/auth-provider": patch -"openbot": patch -"@tryopenbot/computer-service-provider": patch -"@tryopenbot/client-runtime": patch -"@tryopenbot/computer-tools": patch -"@tryopenbot/computer-service": patch -"@tryopenbot/computer-service-proto": patch -"@tryopenbot/configuration": patch -"@tryopenbot/desktop": patch -"@tryopenbot/utilities": patch -"@tryopenbot/platform-integrations": patch -"@tryopenbot/control-service-provider": patch -"@tryopenbot/runtime-provider": patch -"@tryopenbot/control-service": patch -"@tryopenbot/ui": patch -"@tryopenbot/web": patch -"@tryopenbot/git-provider": patch +"@trytilde/dispatch-agent-provider": patch +"@trytilde/dispatch-agent-service-provider": patch +"@trytilde/dispatch-auth-provider": patch +"@trytilde/cli": patch +"@trytilde/dispatch-computer-service-provider": patch +"@trytilde/dispatch-client-runtime": patch +"@trytilde/dispatch-computer-tools": patch +"@trytilde/dispatch-computer-service": patch +"@trytilde/dispatch-computer-service-proto": patch +"@trytilde/dispatch-configuration": patch +"@trytilde/dispatch-desktop": patch +"@trytilde/dispatch-utilities": patch +"@trytilde/dispatch-platform-integrations": patch +"@trytilde/dispatch-control-service-provider": patch +"@trytilde/dispatch-runtime-provider": patch +"@trytilde/dispatch-control-service": patch +"@trytilde/dispatch-ui": patch +"@trytilde/dispatch-web": patch +"@trytilde/dispatch-git-provider": patch --- Allow bounded Agent Resource Bundle polling while memory bindings finish synchronizing. diff --git a/.changeset/show-all-cli-commands.md b/.changeset/show-all-cli-commands.md index a544c5dc..74568906 100644 --- a/.changeset/show-all-cli-commands.md +++ b/.changeset/show-all-cli-commands.md @@ -1,23 +1,23 @@ --- -"@tryopenbot/agent-provider": patch -"@tryopenbot/agent-service-provider": patch -"@tryopenbot/auth-provider": patch -"openbot": patch -"@tryopenbot/computer-service-provider": patch -"@tryopenbot/client-runtime": patch -"@tryopenbot/computer-tools": patch -"@tryopenbot/computer-service": patch -"@tryopenbot/computer-service-proto": patch -"@tryopenbot/configuration": patch -"@tryopenbot/desktop": patch -"@tryopenbot/utilities": patch -"@tryopenbot/platform-integrations": patch -"@tryopenbot/control-service-provider": patch -"@tryopenbot/runtime-provider": patch -"@tryopenbot/control-service": patch -"@tryopenbot/ui": patch -"@tryopenbot/web": patch -"@tryopenbot/git-provider": patch +"@trytilde/dispatch-agent-provider": patch +"@trytilde/dispatch-agent-service-provider": patch +"@trytilde/dispatch-auth-provider": patch +"@trytilde/cli": patch +"@trytilde/dispatch-computer-service-provider": patch +"@trytilde/dispatch-client-runtime": patch +"@trytilde/dispatch-computer-tools": patch +"@trytilde/dispatch-computer-service": patch +"@trytilde/dispatch-computer-service-proto": patch +"@trytilde/dispatch-configuration": patch +"@trytilde/dispatch-desktop": patch +"@trytilde/dispatch-utilities": patch +"@trytilde/dispatch-platform-integrations": patch +"@trytilde/dispatch-control-service-provider": patch +"@trytilde/dispatch-runtime-provider": patch +"@trytilde/dispatch-control-service": patch +"@trytilde/dispatch-ui": patch +"@trytilde/dispatch-web": patch +"@trytilde/dispatch-git-provider": patch --- -Show every public top-level `openbot` command in the interactive launcher. +Show every public top-level `tilde` command in the interactive launcher. diff --git a/.changeset/type-chatkit-execution-context.md b/.changeset/type-chatkit-execution-context.md index a556f3e2..9c461019 100644 --- a/.changeset/type-chatkit-execution-context.md +++ b/.changeset/type-chatkit-execution-context.md @@ -1,6 +1,6 @@ --- "@trytilde/sdk-vercel-ai-node": minor -"openbot": patch +"@trytilde/cli": patch --- Consume Tilde-authored AgentRun, delegated-job, and message timestamp fields through typed ChatKit request context instead of message metadata. diff --git a/.changeset/use-handlebars-file-templates.md b/.changeset/use-handlebars-file-templates.md index 2a1bab54..93755e24 100644 --- a/.changeset/use-handlebars-file-templates.md +++ b/.changeset/use-handlebars-file-templates.md @@ -1,10 +1,10 @@ --- -"@tryopenbot/utilities": minor -"openbot": minor -"@tryopenbot/agent-service-provider": minor -"@tryopenbot/control-service-provider": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/computer-service": minor +"@trytilde/dispatch-utilities": minor +"@trytilde/cli": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-computer-service": minor --- Standardize generated source, configuration, service, deployment, and provider assets on strict Handlebars templates. diff --git a/.changeset/use-xfce-computer-desktop.md b/.changeset/use-xfce-computer-desktop.md index 09135106..41e49340 100644 --- a/.changeset/use-xfce-computer-desktop.md +++ b/.changeset/use-xfce-computer-desktop.md @@ -1,23 +1,23 @@ --- -"@tryopenbot/agent-provider": minor -"@tryopenbot/agent-service-provider": minor -"@tryopenbot/auth-provider": minor -"openbot": minor -"@tryopenbot/computer-service-provider": minor -"@tryopenbot/client-runtime": minor -"@tryopenbot/computer-tools": minor -"@tryopenbot/computer-service": minor -"@tryopenbot/computer-service-proto": minor -"@tryopenbot/configuration": minor -"@tryopenbot/desktop": minor -"@tryopenbot/utilities": minor -"@tryopenbot/platform-integrations": minor -"@tryopenbot/control-service-provider": minor -"@tryopenbot/runtime-provider": minor -"@tryopenbot/control-service": minor -"@tryopenbot/ui": minor -"@tryopenbot/web": minor -"@tryopenbot/git-provider": minor +"@trytilde/dispatch-agent-provider": minor +"@trytilde/dispatch-agent-service-provider": minor +"@trytilde/dispatch-auth-provider": minor +"@trytilde/cli": minor +"@trytilde/dispatch-computer-service-provider": minor +"@trytilde/dispatch-client-runtime": minor +"@trytilde/dispatch-computer-tools": minor +"@trytilde/dispatch-computer-service": minor +"@trytilde/dispatch-computer-service-proto": minor +"@trytilde/dispatch-configuration": minor +"@trytilde/dispatch-desktop": minor +"@trytilde/dispatch-utilities": minor +"@trytilde/dispatch-platform-integrations": minor +"@trytilde/dispatch-control-service-provider": minor +"@trytilde/dispatch-runtime-provider": minor +"@trytilde/dispatch-control-service": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor +"@trytilde/dispatch-git-provider": minor --- Replace the Computer's Openbox desktop with a focused XFCE session and permanent Files and browser launchers. diff --git a/.changeset/wait-for-computer-session.md b/.changeset/wait-for-computer-session.md index de5ad71e..9d95ca5e 100644 --- a/.changeset/wait-for-computer-session.md +++ b/.changeset/wait-for-computer-session.md @@ -1,23 +1,23 @@ --- -"@tryopenbot/agent-provider": patch -"@tryopenbot/agent-service-provider": patch -"@tryopenbot/auth-provider": patch -"openbot": patch -"@tryopenbot/computer-service-provider": patch -"@tryopenbot/client-runtime": patch -"@tryopenbot/computer-tools": patch -"@tryopenbot/computer-service": patch -"@tryopenbot/computer-service-proto": patch -"@tryopenbot/configuration": patch -"@tryopenbot/desktop": patch -"@tryopenbot/utilities": patch -"@tryopenbot/platform-integrations": patch -"@tryopenbot/control-service-provider": patch -"@tryopenbot/runtime-provider": patch -"@tryopenbot/control-service": patch -"@tryopenbot/ui": patch -"@tryopenbot/web": patch -"@tryopenbot/git-provider": patch +"@trytilde/dispatch-agent-provider": patch +"@trytilde/dispatch-agent-service-provider": patch +"@trytilde/dispatch-auth-provider": patch +"@trytilde/cli": patch +"@trytilde/dispatch-computer-service-provider": patch +"@trytilde/dispatch-client-runtime": patch +"@trytilde/dispatch-computer-tools": patch +"@trytilde/dispatch-computer-service": patch +"@trytilde/dispatch-computer-service-proto": patch +"@trytilde/dispatch-configuration": patch +"@trytilde/dispatch-desktop": patch +"@trytilde/dispatch-utilities": patch +"@trytilde/dispatch-platform-integrations": patch +"@trytilde/dispatch-control-service-provider": patch +"@trytilde/dispatch-runtime-provider": patch +"@trytilde/dispatch-control-service": patch +"@trytilde/dispatch-ui": patch +"@trytilde/dispatch-web": patch +"@trytilde/dispatch-git-provider": patch --- Wait for an active Computer desktop session before running CUA actions and report readiness consistently through Computer tools. diff --git a/.changeset/wire-self-extension-tool.md b/.changeset/wire-self-extension-tool.md index 266602bf..3749d152 100644 --- a/.changeset/wire-self-extension-tool.md +++ b/.changeset/wire-self-extension-tool.md @@ -1,5 +1,5 @@ --- -"openbot": patch +"@trytilde/cli": patch --- Wire the scaffolded propose-only self-extension tool into default agent runtime tools. diff --git a/.changeset/workspace-ui-v2.md b/.changeset/workspace-ui-v2.md index ea81f708..230de21b 100644 --- a/.changeset/workspace-ui-v2.md +++ b/.changeset/workspace-ui-v2.md @@ -1,8 +1,8 @@ --- -"@tryopenbot/ui": minor -"@tryopenbot/web": minor -"@tryopenbot/client-runtime": minor -"@tryopenbot/agent-provider": minor +"@trytilde/dispatch-ui": minor +"@trytilde/dispatch-web": minor +"@trytilde/dispatch-client-runtime": minor +"@trytilde/dispatch-agent-provider": minor --- -Rebuild the workspace UI on vendored shadcn/ui, Beautiful UI, and AI Elements sources: semantic design tokens with light/dark class-based theming, the generated agent avatar engine, sidebar rows with an account menu and command palette actions, persisted client workspace switching with an automatic loopback development workspace, composer shortcuts and attachment thumbnails, queue-authoritative message submission and steering with deployment-enforced Tilde queue policies, causally ordered late replies, direct screenshot media rendering without tool-result JSON, segmented assistant transcript rendering with prose-only bubbles and merged tool runs, and a first-run onboarding flow. OpenBot-authored surfaces carry the `ob-` class prefix and OpenBot's own copy. +Rebuild the workspace UI on vendored shadcn/ui, Beautiful UI, and AI Elements sources: semantic design tokens with light/dark class-based theming, the generated agent avatar engine, sidebar rows with an account menu and command palette actions, persisted client workspace switching with an automatic loopback development workspace, composer shortcuts and attachment thumbnails, queue-authoritative message submission and steering with deployment-enforced Tilde queue policies, causally ordered late replies, direct screenshot media rendering without tool-result JSON, segmented assistant transcript rendering with prose-only bubbles and merged tool runs, and a first-run onboarding flow. Dispatch-authored surfaces carry the `dispatch-` class prefix and Dispatch's own copy. diff --git a/.github/workflows/release-desktop.yml b/.github/workflows/release-desktop.yml index 69ca8045..dff5b5d6 100644 --- a/.github/workflows/release-desktop.yml +++ b/.github/workflows/release-desktop.yml @@ -55,7 +55,7 @@ jobs: # Publishing changes a public feed, so the repository gates run before anything is # packaged. Once here rather than in each matrix job: the tree is the same for both. - name: Check - run: vp run --filter openbot start -- check + run: vp run --filter @trytilde/cli start -- check - id: plan shell: bash @@ -78,9 +78,9 @@ jobs: runs-on: ${{ matrix.os }} timeout-minutes: 90 env: - OPENBOT_DESKTOP_UPDATES_BUCKET: ${{ vars.DESKTOP_UPDATES_S3_BUCKET }} - OPENBOT_DESKTOP_UPDATES_PREFIX: ${{ vars.DESKTOP_UPDATES_S3_PREFIX }} - OPENBOT_DESKTOP_UPDATES_BASE_URL: ${{ vars.DESKTOP_UPDATES_BASE_URL }} + DISPATCH_DESKTOP_UPDATES_BUCKET: ${{ vars.DESKTOP_UPDATES_S3_BUCKET }} + DISPATCH_DESKTOP_UPDATES_PREFIX: ${{ vars.DESKTOP_UPDATES_S3_PREFIX }} + DISPATCH_DESKTOP_UPDATES_BASE_URL: ${{ vars.DESKTOP_UPDATES_BASE_URL }} steps: - name: Checkout uses: actions/checkout@v4 @@ -135,9 +135,9 @@ jobs: if: ${{ !inputs.dry_run }} runs-on: ubuntu-latest env: - OPENBOT_DESKTOP_UPDATES_BUCKET: ${{ vars.DESKTOP_UPDATES_S3_BUCKET }} - OPENBOT_DESKTOP_UPDATES_PREFIX: ${{ vars.DESKTOP_UPDATES_S3_PREFIX }} - OPENBOT_DESKTOP_UPDATES_BASE_URL: ${{ vars.DESKTOP_UPDATES_BASE_URL }} + DISPATCH_DESKTOP_UPDATES_BUCKET: ${{ vars.DESKTOP_UPDATES_S3_BUCKET }} + DISPATCH_DESKTOP_UPDATES_PREFIX: ${{ vars.DESKTOP_UPDATES_S3_PREFIX }} + DISPATCH_DESKTOP_UPDATES_BASE_URL: ${{ vars.DESKTOP_UPDATES_BASE_URL }} steps: - name: Checkout uses: actions/checkout@v4 diff --git a/.gitignore b/.gitignore index c2ecb105..e506fb75 100644 --- a/.gitignore +++ b/.gitignore @@ -14,8 +14,8 @@ configuration/.env configuration/secrets.enc.yaml /local-user-config.json .vercel/ -.openbot-deploy/ -.openbot/ +.dispatch-deploy/ +.dispatch/ *.log apps/web/src/routeTree.gen.ts apps/desktop/out/ diff --git a/.vercelignore b/.vercelignore index 3ea0432c..da43e7ea 100644 --- a/.vercelignore +++ b/.vercelignore @@ -4,7 +4,7 @@ node_modules .turbo .cache .data -.openbot-deploy +.dispatch-deploy plan coverage playwright-report diff --git a/AGENTS.md b/AGENTS.md index 96449365..47eb0b65 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,6 +1,6 @@ -# OpenBot — AGENTS.md +# Dispatch — AGENTS.md -OpenBot is a TypeScript monorepo for a local or Vercel-hosted agent workspace. It combines a React/Vite web app, an Electron desktop shell, Hono and ConnectRPC services, provider adapters, Tilde ChatKit, and local or Vercel sandboxes. +Dispatch is a TypeScript monorepo for a local or Vercel-hosted agent workspace. It combines a React/Vite web app, an Electron desktop shell, Hono and ConnectRPC services, provider adapters, Tilde ChatKit, and local or Vercel sandboxes. ## Start here @@ -8,7 +8,7 @@ OpenBot is a TypeScript monorepo for a local or Vercel-hosted agent workspace. I 2. Inspect `git status --short --branch`; preserve unrelated work. 3. Read the owning package and its tests before editing. 4. Read relevant records under `docs/adrs/` before changing a recorded decision. -5. Use `.agents/skills//SKILL.md` for repository workflows. Runtime skills under the primary `configuration/agent/skills/` or a `configuration/agent/subagents//skills/` directory serve that OpenBot agent, not the coding-agent process. +5. Use `.agents/skills//SKILL.md` for repository workflows. Runtime skills under the primary `configuration/agent/skills/` or a `configuration/agent/subagents//skills/` directory serve that Dispatch agent, not the coding-agent process. ## Toolchain and commands @@ -23,18 +23,18 @@ pnpm check pnpm build pnpm test pnpm test:e2e -pnpm --filter @tryopenbot/desktop package +pnpm --filter @trytilde/dispatch-desktop package ``` Run focused package tests while iterating: ```bash -pnpm --filter openbot test -pnpm --filter @tryopenbot/control-service test -pnpm --filter openbot test +pnpm --filter @trytilde/cli test +pnpm --filter @trytilde/dispatch-control-service test +pnpm --filter @trytilde/cli test ``` -Root scripts follow a verb:target taxonomy and delegate to `openbot`: +Root scripts follow a verb:target taxonomy and delegate to `tilde`: ```bash pnpm connect -- @@ -43,13 +43,13 @@ pnpm dev:desktop pnpm desktop:package ``` -`openbot` resolves a real Node binary in `cli/src/toolchain.ts`, so no command needs a `PATH` prefix. Extend that module rather than prefixing a command. Remote hosts live in fork-owned `configuration/dev-hosts.json`. +`tilde` resolves a real Node binary in `cli/src/toolchain.ts`, so no command needs a `PATH` prefix. Extend that module rather than prefixing a command. Remote hosts live in fork-owned `configuration/dev-hosts.json`. -Per ADR-0018, every developer workflow is an `openbot` command — repository gates (`check`, `build`, `test`, `e2e`, `desktop package`), `connect`, and `remote`. Do not add loose `scripts/*.mjs`, package-local helper scripts, or repeat-use command lines that live only in docs; promote them to CLI commands. Root scripts stay thin plumbing the CLI delegates to. +Per ADR-0018, every developer workflow is a `tilde` command — repository gates (`check`, `build`, `test`, `e2e`, `desktop package`), `connect`, and `remote`. Do not add loose `scripts/*.mjs`, package-local helper scripts, or repeat-use command lines that live only in docs; promote them to CLI commands. Root scripts stay thin plumbing the CLI delegates to. ## Repository map -- `cli`: React Ink CLI (`openbot`) owning both operator commands for installations and the developer workflow for humans and sandboxed agents — repository gates and remote desktop hosts. Command entrypoints live under `cli/src/commands/`, while shared process, environment, initialization, and UI helpers remain at `cli/src/`. Remote host identity stays in fork-owned `configuration/dev-hosts.json`. See ADR-0018. +- `cli`: React Ink CLI (`tilde`) owning both operator commands for installations and the developer workflow for humans and sandboxed agents — repository gates and remote desktop hosts. Command entrypoints live under `cli/src/commands/`, while shared process, environment, initialization, and UI helpers remain at `cli/src/`. Remote host identity stays in fork-owned `configuration/dev-hosts.json`. See ADR-0018. - `apps/web`: React 19, Vite, TanStack Router, and the browser adapter for the shared client runtime. - `apps/control-service`: Hono HTTP routes, the allowlisted Tilde ChatKit REST/SSE bridge, and the local control-service entrypoint. - `apps/desktop`: Electron main/preload shell and packaged local server. @@ -62,7 +62,7 @@ Per ADR-0018, every developer workflow is an `openbot` command — repository ga - `packages/connector-tools`: typed Vercel AI SDK tools for in-chat connector (Tilde tool-provider) configuration; a runtime utility, not a provider. - `packages/connector-tools`: typed Vercel AI SDK tools for in-chat connector (Tilde tool-provider) configuration; a runtime utility, not a provider. - `packages/configuration`: typed contract for the fork-owned composition root. -- `packages/utilities`: shared OpenBot utilities, including strict Handlebars rendering and domain-neutral JSON guards/accessors. Import browser-safe JSON helpers through `@tryopenbot/utilities/json`. +- `packages/utilities`: shared Dispatch utilities, including strict Handlebars rendering and domain-neutral JSON guards/accessors. Import browser-safe JSON helpers through `@trytilde/dispatch-utilities/json`. - `configuration`: fork-owned Eve-compatible agent directories, future-agent templates, provider composition, and provider plugins. - `packages/runtime-provider`: shared build and phased deployment contracts and coordinator. - `packages/control-service-provider`, `packages/agent-service-provider`: independent local and Vercel service artifacts and deployment. @@ -81,7 +81,7 @@ Per ADR-0018, every developer workflow is an `openbot` command — repository ga - Client-consumed request, response, and event shapes belong in `packages/client-runtime` contracts, validated where data enters the client. Apps must not re-declare them per surface. - Keep `/auth/native-config` public, no-store, and limited to provider-owned public PKCE metadata for the desktop installation. - Keep Hono routes for protocol-native HTTP surfaces: setup unlock, ChatKit compatibility, signed Tilde callbacks/tools, and health. -- Edit `packages/computer-service-proto/proto/openbot/computer/v1/computer.proto` for the internal Computer API, then run `pnpm contracts:generate`. +- Edit `packages/computer-service-proto/proto/dispatch/computer/v1/computer.proto` for the internal Computer API, then run `pnpm contracts:generate`. - Keep handlers thin: validate input, authorize, call the owning provider/store, map to protobuf or HTTP response. - Preserve Web-standard `Request`/`Response` behavior so the same server works locally and in Vercel Functions. - Preserve raw request bodies and webhook verification on signed Tilde routes. @@ -90,11 +90,11 @@ Per ADR-0018, every developer workflow is an `openbot` command — repository ga `metadata`, `providerMetadata`, and similarly named JSON objects are allowed only for provider-specific facts that cannot be normalized into a shared -domain, or for opaque client extensions that OpenBot and Tilde store/forward +domain, or for opaque client extensions that Dispatch and Tilde store/forward without interpreting. A GitHub pull-request number or provider-native content fragment is valid provider metadata when the GitHub adapter alone owns it. -Never read or write metadata for OpenBot/Tilde-owned authorization, identity, +Never read or write metadata for Dispatch/Tilde-owned authorization, identity, audience, routing, relationships, lifecycle, retries, state machines, models, budgets, runs, jobs, compaction, memory ownership/provenance, or other internal semantics. Those values require generated Tilde fields, shared client-runtime @@ -122,7 +122,7 @@ contracts, provider core contracts, or another typed interface. - Define provider contracts in `core.ts` or `core/` inside the owning provider package and keep implementations beside them. Do not expose internal provider interfaces over RPC by default. - Use the `implement-provider` skill whenever adding or editing a provider implementation. - Keep small implementations in `.ts`. When one owns multiple responsibilities or runtime files, use `/index.ts`, cohesive subfiles, and `assets/`. -- Store generated-file sources as `*.hbs` assets, not TypeScript strings. Provider build and deploy lifecycles render them through `@tryopenbot/utilities` into ignored artifacts; runtime persistence and user-supplied bytes remain byte-preserving data. +- Store generated-file sources as `*.hbs` assets, not TypeScript strings. Provider build and deploy lifecycles render them through `@trytilde/dispatch-utilities` into ignored artifacts; runtime persistence and user-supplied bytes remain byte-preserving data. - Pass `ProviderCallContext` through calls so cancellation, deadlines, request IDs, and idempotency remain available. - Convert provider-specific failures to `ProviderError` at the adapter boundary. - Keep provider selection in composition code, not UI branches. @@ -140,7 +140,7 @@ contracts, provider core contracts, or another typed interface. - Avoid duplicating remote snapshots or SSE reconciliation in renderers; conversation state keeps one reconciliation owner. - Keep `client-runtime` free of React, DOM, Electron, and Node imports. Platform adapters own credentials, uploads, navigation, and presentation-only state. - Reuse `packages/ui` for web and Electron; keep direct Beautiful UI modifications documented in its provenance files. -- Desktop publication is upstream-only too: signed builds go to `desktop/openbot//` in the shared `tilde-app-updates-prod` bucket, and `openbot desktop release` refuses the official bucket from another remote. A fork publishes its own builds by setting `OPENBOT_DESKTOP_UPDATES_BUCKET`. `version.json` is the client update contract; `latest-*.yml` is published unused so electron-updater can be adopted later without a re-release. Never commit an Apple certificate or App Store Connect key. See ADR-0028. +- Desktop publication is upstream-only too: signed builds go to `desktop/dispatch//` in the shared `tilde-app-updates-prod` bucket, and `tilde desktop release` refuses the official bucket from another remote. A fork publishes its own builds by setting `DISPATCH_DESKTOP_UPDATES_BUCKET`. `version.json` is the client update contract; `latest-*.yml` is published unused so electron-updater can be adopted later without a re-release. Never commit an Apple certificate or App Store Connect key. See ADR-0028. - Adding or changing a user-facing capability in web or desktop obliges an explicit decision about the other client. `create-pr` blocks on the cross-client parity gate, so state per capability whether it is ported, deferred with a `` block, or genuinely not portable with the platform reason. - Electron renderer must not gain direct Node.js access. Keep privileged work in main/preload with a narrow bridge. - Preserve same-origin proxying between packaged web assets and the local control server. @@ -148,16 +148,16 @@ contracts, provider core contracts, or another typed interface. ### Tilde and AI runtime - Use the canonical Tilde skill and `https://trytilde.ai/llms.txt` for current Tilde behavior. -- Use `openbot sdk refresh` after intentional Tilde OpenAPI changes. Generated source lives only under `packages/api-client/src/generated/`; public SDK behavior belongs in hand-authored `packages/sdk/src/` wrappers. -- Public SDK names are `@trytilde/sdk*`; do not reintroduce Harness package names, a standalone Tilde CLI, or a plugin helper package. `openbot auth|state|tunnel|plugin` owns those commands. -- Tilde SDK JSON types, guards, and accessors belong in `@trytilde/sdk/json`; SDK packages must not depend on `@tryopenbot/utilities`. +- Use `tilde sdk refresh` after intentional Tilde OpenAPI changes. Generated source lives only under `packages/api-client/src/generated/`; public SDK behavior belongs in hand-authored `packages/sdk/src/` wrappers. +- Public SDK names are `@trytilde/sdk*`; the unified CLI is `@trytilde/cli` with the `tilde` binary. Do not reintroduce Harness package names or a separate plugin helper package. `tilde auth|state|tunnel|plugin` owns those commands. +- Tilde SDK JSON types, guards, and accessors belong in `@trytilde/sdk/json`; SDK packages must not depend on `@trytilde/dispatch-utilities`. - Keep ChatKit webhook verification, history conversion, streaming, and credentials server-side. -- Reconcile Tilde resources through the typed API client inside idempotent provider lifecycles. OpenBot does not use a Tilde state file during normal operation; operators may use `openbot state` for one-time team-to-team state migration. +- Reconcile Tilde resources through the typed API client inside idempotent provider lifecycles. Dispatch does not use a Tilde state file during normal operation; operators may use `tilde state` for one-time team-to-team state migration. - Do not guess Tilde identifiers or expose one-time API/webhook keys. - The agent loop uses Vercel AI SDK. Verify current SDK signatures before changing them. - Agent model, MCP, skill, and other external integrations are ordinary authored code. Keep the matching defaults in `configuration/templates/agent/`; migrate existing agents explicitly. - The full primary agent lives at `configuration/agent/`; full additional agents live at `configuration/agent/subagents//`. Nested subagents are unsupported. Follow ADR-0011 for their identical Eve-compatible subset, ChatKit entrypoint, instrumentation ordering, and one-time `/workspace/` seeds on the shared computer. -- Keep `sandbox/workspace/` as the sole Eve-compatibility naming exception. Use Computer in runtime APIs and require each agent's standard Computer tools to import `@tryopenbot/computer-tools`, which calls the typed computer-service API with that agent's fixed ID. +- Keep `sandbox/workspace/` as the sole Eve-compatibility naming exception. Use Computer in runtime APIs and require each agent's standard Computer tools to import `@trytilde/dispatch-computer-tools`, which calls the typed computer-service API with that agent's fixed ID. ### Sandboxes @@ -170,11 +170,11 @@ contracts, provider core contracts, or another typed interface. ### Fork files -- Repository resources use fixed paths, not `OpenBotConfiguration` options: the primary agent in `configuration/agent/`, additional agents in `configuration/agent/subagents//`, future-agent templates in `configuration/templates/agent/**/*.hbs`, agent-local skills and workspace seeds inside either full agent directory, and custom providers in `configuration/providers/`. Global `configuration/skills/` and `configuration/sandbox/` directories are unsupported. +- Repository resources use fixed paths, not `DispatchConfiguration` options: the primary agent in `configuration/agent/`, additional agents in `configuration/agent/subagents//`, future-agent templates in `configuration/templates/agent/**/*.hbs`, agent-local skills and workspace seeds inside either full agent directory, and custom providers in `configuration/providers/`. Global `configuration/skills/` and `configuration/sandbox/` directories are unsupported. ## Local development -`pnpm dev` delegates to `openbot dev`, loads `.env.local`, generates contracts, and starts the watched Hono app, web app, and Electron when available. +`pnpm dev` delegates to `tilde dev`, loads `.env.local`, generates contracts, and starts the watched Hono app, web app, and Electron when available. - Default web URL: `http://127.0.0.1:4173`. - Default control server: `http://127.0.0.1:4100`. @@ -184,7 +184,7 @@ contracts, provider core contracts, or another typed interface. ## Security -- Never print, commit, or paste `.env.local`, `.openbot-deploy/`, setup codes, API keys, webhook keys, database tokens, or browser session data. +- Never print, commit, or paste `.env.local`, `.dispatch-deploy/`, setup codes, API keys, webhook keys, database tokens, or browser session data. - Keep tracked environment files as sanitized examples only. - Validate paths and capabilities before file, process, or desktop operations. - Ask before destructive actions, external publication, paid changes, production deployment, or resource deletion. @@ -221,7 +221,7 @@ For browser-visible changes, verify the real route, console, network, and visibl - `frontend-design`: visual direction across the web and Electron clients. - `diagnose`: evidence-led debugging. - `implement-provider`: provider implementation structure, assets, lifecycles, and tests. -- `edit-openbot-configuration`: fork-owned composition, custom providers, and future-agent templates. +- `edit-dispatch-configuration`: fork-owned composition, custom providers, and future-agent templates. - `vercel`, `tilde`: platform-specific work. - `update-openapi-generated-client`, `add-sdk-wrapper`, `expose-api-change`: generated Tilde API refresh and stable SDK wrapper work. - `safe-refactor`, `surgical-patch`, `migration`, `lean-build`, `verify-and-stop`: scope-specific engineering workflows. diff --git a/CONTEXT.md b/CONTEXT.md index 3940aa5b..637430e8 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -1,23 +1,23 @@ -# OpenBot +# Dispatch -OpenBot is an agent workspace that combines conversation with an isolated computer. This glossary names its product and ownership boundaries consistently. +Dispatch is an agent workspace that combines conversation with an isolated computer. This glossary names its product and ownership boundaries consistently. ## Language -**OpenBot Installation**: -A single deployed or locally running OpenBot instance with its own setup and control state. +**Dispatch Installation**: +A single deployed or locally running Dispatch instance with its own setup and control state. _Avoid_: deployment, instance, or account when the installation is meant -**OpenBot Workspace**: +**Dispatch Workspace**: The user-facing place where an owner chats with bots and uses their computer. _Avoid_: Tilde workspace **Owner**: -The person responsible for configuring and operating an **OpenBot Installation**. +The person responsible for configuring and operating an **Dispatch Installation**. _Avoid_: admin, user, or customer when ownership is meant **Installation Resource**: -The OAuth protected-resource identity assigned to one **OpenBot Installation**. Its exact URI is +The OAuth protected-resource identity assigned to one **Dispatch Installation**. Its exact URI is the required access-token audience for that installation. _Avoid_: client ID or scope when the protected installation is meant @@ -30,7 +30,7 @@ _Avoid_: treating a decoded token or session cookie alone as authorization The Tilde ownership and billing boundary selected during setup. **Tilde Team**: -The Tilde workspace and runtime isolation boundary selected by an OpenBot installation. Tilde resources may be `team`, personal `user`, or private `user_team`; OpenBot's authored-agent lifecycle continues to reconcile team resources unless it explicitly opts into a personal API. +The Tilde workspace and runtime isolation boundary selected by a Dispatch installation. Tilde resources may be `team`, personal `user`, or private `user_team`; Dispatch's authored-agent lifecycle continues to reconcile team resources unless it explicitly opts into a personal API. **Tilde Resource Ownership**: A tagged authorization boundary. `team` carries organization and team, `user` carries organization and owner without a team, and `user_team` carries organization, execution team, and owner. Child records inherit their root's ownership. @@ -41,7 +41,7 @@ The registered runtime resource in a **Tilde Team** that implements a bot. _Avoid_: bot when the registered runtime resource is meant **Bot**: -The owner-facing name for a **Tilde Agent** available for conversation through OpenBot. +The owner-facing name for a **Tilde Agent** available for conversation through Dispatch. _Avoid_: agent in owner-facing UI and copy **ChatKit Session**: @@ -54,12 +54,12 @@ and recent complete conversation tail; it never deletes or rewrites the canonical **ChatKit Session** transcript. _Avoid_: ChatKit summarization -**OpenBot Computer**: +**Dispatch Computer**: The isolated, resumable computer an agent can use for files, commands, browser work, and desktop interaction. _Avoid_: host, server **Control State**: -OpenBot-owned installation, onboarding, computer lease, deployment progress, repository reconciliation mappings, and source-publication progress. +Dispatch-owned installation, onboarding, computer lease, deployment progress, repository reconciliation mappings, and source-publication progress. _Avoid_: agent state, chat state _Avoid_: credentials, runtime state @@ -73,27 +73,27 @@ _Avoid_: frontend state library, shared components, or server SDK ## Relationships - An **Owner** authenticates through OIDC without a pairing-code gate. -- Each **OpenBot Installation** has one **Installation Resource** and accepts only access tokens +- Each **Dispatch Installation** has one **Installation Resource** and accepts only access tokens with that exact audience. - Tilde login may provide SSO across installations, but each installation keeps independent access tokens and host-only cookies. -- An **OpenBot Installation** presents one **OpenBot Workspace**. -- An **OpenBot Installation** connects to one **Tilde Organization** and **Tilde Team**. +- An **Dispatch Installation** presents one **Dispatch Workspace**. +- An **Dispatch Installation** connects to one **Tilde Organization** and **Tilde Team**. - A **Tilde Team** owns one or more **Tilde Agents**, presented to owners as **Bots**. Ordinary sessions are team-owned; private ChatKit sessions use `user_team` ownership. -- An **OpenBot Installation** controls at most one active **OpenBot Computer**. -- **Control State** belongs to OpenBot; agent and conversation state belongs to the **Tilde Team**. -- Every OpenBot client reaches an **OpenBot Workspace** through the **Client Runtime**; renderers own +- An **Dispatch Installation** controls at most one active **Dispatch Computer**. +- **Control State** belongs to Dispatch; agent and conversation state belongs to the **Tilde Team**. +- Every Dispatch client reaches an **Dispatch Workspace** through the **Client Runtime**; renderers own presentation only. - Tilde provider lifecycles reconcile their resources through the typed API client. ## Example dialogue -> **Developer:** "Should this new chat record go into OpenBot control state?" -> **Domain expert:** "No. A ChatKit Session belongs to the Tilde Team; OpenBot stores only Control State for the installation and its computer." +> **Developer:** "Should this new chat record go into Dispatch control state?" +> **Domain expert:** "No. A ChatKit Session belongs to the Tilde Team; Dispatch stores only Control State for the installation and its computer." ## Flagged ambiguities -- "workspace" can mean the **OpenBot Workspace**, a Tilde team, or the computer filesystem; use the explicit term. +- "workspace" can mean the **Dispatch Workspace**, a Tilde team, or the computer filesystem; use the explicit term. - "agent" can mean a **Tilde Agent** or the software implementing its behavior; use **Tilde Agent** for the registered runtime resource and **Bot** in owner-facing UI. - "state" can mean **Control State** or Tilde-owned runtime data; name the owner and kind. @@ -119,6 +119,6 @@ Work: persist the computer-service-provider build lifecycle's source digest and Background SDLC automation (ADR-0017): agents or the orchestrator should open pull requests from -the `openbot/sandbox-edits` branch and merge them once checks pass, completing the automated +the `dispatch/sandbox-edits` branch and merge them once checks pass, completing the automated software lifecycle. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3ad5740c..7687bf16 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,12 +1,12 @@ # Contributing -Everything in this repository is driven by one CLI. `openbot` operates an installation — +Everything in this repository is driven by one CLI. `tilde` operates an installation — `init`, `dev`, `deploy`, `secrets`, `env` — and carries the developer workflow: repository gates and remote desktop hosts. Prefer a CLI command over a hand-written script or a remembered command line; see [ADR-0018](docs/adrs/0018-developer-workflow-cli.md). -Run it as `pnpm openbot ` inside the repository, or `openbot ` from a global -`npm install --global openbot`. +Run it as `pnpm tilde ` inside the repository, or `tilde ` from a global +`npm install --global @trytilde/cli`. ## Prerequisites @@ -17,14 +17,14 @@ Required on every platform: | Node.js | 24.x | pinned by `engines`; the CLI and every package target it | | pnpm | 10.33.1 | pinned by `packageManager`; `corepack enable pnpm` installs it | | Git | any recent | worktrees and fork workflow | -| GitHub CLI (`gh`) | any recent | `openbot init` verifies authenticated access; PR workflow | +| GitHub CLI (`gh`) | any recent | `tilde init` verifies authenticated access; PR workflow | Needed only for the surfaces you touch: | Surface | Dependency | Notes | | --- | --- | --- | | Browser end-to-end | Playwright browsers | `pnpm exec playwright install chromium` | -| Desktop publication | the AWS CLI, a Developer ID Application certificate, an App Store Connect API key | upstream only, see ADR-0028. Only `openbot desktop release publish|manifest|status` needs them; building and packaging locally does not. Without the Apple credentials the build still succeeds and produces unsigned artifacts | +| Desktop publication | the AWS CLI, a Developer ID Application certificate, an App Store Connect API key | upstream only, see ADR-0028. Only `tilde desktop release publish|manifest|status` needs them; building and packaging locally does not. Without the Apple credentials the build still succeeds and produces unsigned artifacts | | Local Computer, deployment | Microsandbox, SOPS, age | see [docs/sandbox.md](docs/sandbox.md) and [docs/configuration.md](docs/configuration.md) | ## Setup on Linux @@ -37,11 +37,11 @@ corepack enable pnpm # repository gh repo clone trytilde/dispatch && cd dispatch pnpm install -pnpm openbot check +pnpm tilde check ``` A Linux host without a display runs the Electron shell behind Xvfb with x11vnc bound to -loopback on VNC 5901. `pnpm openbot connect -- ` forwards that desktop. +loopback on VNC 5901. `pnpm tilde connect -- ` forwards that desktop. ## Setup on macOS @@ -53,18 +53,18 @@ corepack enable pnpm # repository gh repo clone trytilde/dispatch && cd dispatch pnpm install -pnpm openbot check +pnpm tilde check ``` ## Working on a change ```bash -pnpm openbot check # contracts, types, lint, package tests -pnpm openbot build # every package, plus artifact verification -pnpm openbot test # repository tests -pnpm openbot e2e # browser Playwright suite -pnpm openbot desktop dev # launch the Electron shell -pnpm openbot desktop package # Electron packaging +pnpm tilde check # contracts, types, lint, package tests +pnpm tilde build # every package, plus artifact verification +pnpm tilde test # repository tests +pnpm tilde e2e # browser Playwright suite +pnpm tilde desktop dev # launch the Electron shell +pnpm tilde desktop package # Electron packaging pnpm --filter test # narrowest useful check while iterating ``` @@ -92,7 +92,7 @@ which stays untracked upstream. ## Publishing the desktop app Desktop publication is upstream-only for the same reason (ADR-0028). Signed builds go to -`s3://tilde-app-updates-prod/desktop/openbot//`, and `openbot desktop release` refuses +`s3://tilde-app-updates-prod/desktop/dispatch//`, and `tilde desktop release` refuses the official bucket from any other remote: ```bash @@ -110,7 +110,7 @@ the manually triggered **Release desktop** workflow, which needs these repositor | `AWS_OIDC_ROLE_ARN` | Role the workflow assumes through GitHub OIDC | | `AWS_REGION` | Region of the updates bucket | | `DESKTOP_UPDATES_S3_BUCKET` | Bucket name; omit upstream to take the default | -| `DESKTOP_UPDATES_S3_PREFIX` | Prefix above the channel, default `desktop/openbot` | +| `DESKTOP_UPDATES_S3_PREFIX` | Prefix above the channel, default `desktop/dispatch` | | `DESKTOP_UPDATES_BASE_URL` | Public https origin used for download URLs | and these repository secrets for a signed, notarized macOS build: @@ -125,8 +125,8 @@ and these repository secrets for a signed, notarized macOS build: Without the certificate secrets the build still succeeds but produces **unsigned** artifacts that macOS Gatekeeper refuses, recorded as `signed: false` in `version.json`. A fork publishes -to its own bucket with `OPENBOT_DESKTOP_UPDATES_BUCKET`, optionally -`OPENBOT_DESKTOP_UPDATES_PREFIX` and `OPENBOT_DESKTOP_UPDATES_BASE_URL`. Never commit an Apple +to its own bucket with `DISPATCH_DESKTOP_UPDATES_BUCKET`, optionally +`DISPATCH_DESKTOP_UPDATES_PREFIX` and `DISPATCH_DESKTOP_UPDATES_BASE_URL`. Never commit an Apple certificate or an App Store Connect key. ## Changing an external dependency diff --git a/LICENSE b/LICENSE index 32a30f89..aed99cfc 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2026 OpenBot contributors +Copyright (c) 2026 Dispatch contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/PROVENANCE.md b/PROVENANCE.md index cc76b8ab..c7f2f33d 100644 --- a/PROVENANCE.md +++ b/PROVENANCE.md @@ -1,9 +1,9 @@ # Provenance -One index of everything in this repository that OpenBot did not write: where it +One index of everything in this repository that Dispatch did not write: where it came from, who owns changes to it, and where its verification data lives. -OpenBot's own source is MIT licensed. Nothing below changes that; the entries are +Dispatch's own source is MIT licensed. Nothing below changes that; the entries are about material with a different origin living inside the tree. ## Companion files @@ -13,20 +13,20 @@ duplicate each other: | File | Holds | | --- | --- | -| [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md) | License status, copyright, and the recorded OpenBot modifications per upstream project | +| [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md) | License status, copyright, and the recorded Dispatch modifications per upstream project | | [`packages/ui/src/beautiful-ui/PROVENANCE.md`](packages/ui/src/beautiful-ui/PROVENANCE.md) | Per-file SHA-256 at retrieval for the vendored web component tree | | [`skills-lock.json`](skills-lock.json) | Source repository, ref, path, and content hash per vendored coding-agent skill | The rules these files exist to enforce are recorded as decisions in [`docs/adrs/0022-vendored-web-component-sources.md`](docs/adrs/0022-vendored-web-component-sources.md) (vendor by copy, keep the upstream tree pristine, record every drift) and -[`docs/adrs/0021-openbot-owned-ui-naming-and-copy.md`](docs/adrs/0021-openbot-owned-ui-naming-and-copy.md) -(OpenBot-authored surfaces carry OpenBot's own identifiers and copy). +[`docs/adrs/0021-dispatch-owned-ui-naming-and-copy.md`](docs/adrs/0021-dispatch-owned-ui-naming-and-copy.md) +(Dispatch-authored surfaces carry Dispatch's own identifiers and copy). ## Vendored source Distributed as source rather than as a package, so it is copied into the tree and -maintained here. Each row is upstream material, not OpenBot's own work. +maintained here. Each row is upstream material, not Dispatch's own work. | Path | Upstream | License | Verification | | --- | --- | --- | --- | @@ -39,24 +39,24 @@ maintained here. Each row is upstream material, not OpenBot's own work. `packages/ui` rather than as vendored source, so it needs no entry here beyond its notices record. -## OpenBot-authored, sitting next to vendored source +## Dispatch-authored, sitting next to vendored source These directories are easy to mistake for upstream material because of where they -live. They are OpenBot's own work, and OpenBot owns their naming, copy, and +live. They are Dispatch's own work, and Dispatch owns their naming, copy, and license status: - `packages/ui/src/beautiful-ui/atoms/` — reconstructions of primitives the - publisher never released as source. Written by OpenBot against the published + publisher never released as source. Written by Dispatch against the published visual result, not copied. They are not covered by the `upstream/` hashes and carry no borrowed provenance. -- `packages/ui/src/beautiful-ui/blocks/` — OpenBot-authored composition built on +- `packages/ui/src/beautiful-ui/blocks/` — Dispatch-authored composition built on the vendored primitives. - The 22 skills under `.agents/skills/` with no entry in `skills-lock.json`. Absence from the lockfile is the test: anything listed there is vendored with a - recorded hash, anything else is OpenBot's own. + recorded hash, anything else is Dispatch's own. The workspace UI was built with a third-party product as its visual target. The -implementation is the vendored libraries above plus OpenBot's own code; no source +implementation is the vendored libraries above plus Dispatch's own code; no source was taken from that product, and per ADR-0021 no identifier or user-visible string is carried from it either. Refer to it as the reference build. @@ -67,23 +67,23 @@ and outside formatter and linter ownership: | Path | Generated from | Command | | --- | --- | --- | -| `packages/api-client/src/generated/` | `packages/api-client/specs/openapi.cloud.json` | `pnpm openbot sdk refresh` | -| `packages/sdk/src/generated/schema.d.ts` | `packages/api-client/specs/openapi.cloud.json` | `pnpm openbot sdk refresh` | -| `packages/computer-service-proto/src/gen/` | `proto/openbot/computer/v1/computer.proto` | `pnpm contracts:generate` | +| `packages/api-client/src/generated/` | `packages/api-client/specs/openapi.cloud.json` | `pnpm tilde sdk refresh` | +| `packages/sdk/src/generated/schema.d.ts` | `packages/api-client/specs/openapi.cloud.json` | `pnpm tilde sdk refresh` | +| `packages/computer-service-proto/src/gen/` | `proto/dispatch/computer/v1/computer.proto` | `pnpm contracts:generate` | | `apps/web/src/routeTree.gen.ts` | the TanStack route files | the Vite dev/build pipeline | ## First-party source consolidation The `packages/api-client` and `packages/sdk*` source, the Tilde command implementations under `cli/src/tilde/`, and the three SDK coding-agent skills were consolidated from the public `trytilde/harness-sdk` -repository at `f0d77de4ebaff204c40149320296ceeb93cdfa20`. They are now first-party OpenBot monorepo source, +repository at `f0d77de4ebaff204c40149320296ceeb93cdfa20`. They are now first-party Dispatch monorepo source, maintained and licensed under this repository's MIT license rather than a vendored upstream tree. ## Working with any of this **Never edit a vendored tree silently.** The hashes are the evidence that the license terms were honored, so an unrecorded edit destroys the audit trail. Put -OpenBot composition outside the vendored directory instead. When a change to +Dispatch composition outside the vendored directory instead. When a change to upstream source is genuinely necessary, record it in that tree's `PROVENANCE.md` and in the notices file in the same commit. diff --git a/README.md b/README.md index e956b9f9..f46f735a 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,25 @@ -# OpenBot +# Dispatch -OpenBot is being rebuilt from the user experience downward. The current workspace connects its owner-facing chat to configured agents while provider and computer capabilities continue to expand behind narrow contracts. +Dispatch is being rebuilt from the user experience downward. The current workspace connects its owner-facing chat to configured agents while provider and computer capabilities continue to expand behind narrow contracts. ## Run locally Requirements: Node.js 24 and pnpm 10. -Install the standalone CLI with `npm install --global openbot`, or use `npx openbot`. Create and enter a completely empty destination directory before running init; any visible or hidden entry makes initialization stop before prompts or external changes. +Install the standalone CLI with `npm install --global @trytilde/cli`, or use `npx @trytilde/cli`. Create and enter a completely empty destination directory before running init; any visible or hidden entry makes initialization stop before prompts or external changes. AI agents and automation can initialize without a TTY by piping a JSON answer object through standard input: ```bash -openbot init --non-interactive --json < openbot-answers.json +tilde init --non-interactive --json < dispatch-answers.json ``` Secrets therefore stay out of process arguments. See `cli/README.md` for stable answer IDs and a complete example. ```bash -mkdir my-openbot -cd my-openbot -openbot init +mkdir my-dispatch +cd my-dispatch +tilde init pnpm install pnpm dev ``` @@ -28,22 +28,22 @@ pnpm dev - API: `http://127.0.0.1:4100` - Health: `http://127.0.0.1:4100/healthz` -A fresh upstream checkout intentionally contains only `configuration/.gitignore`, which hides all configuration contents. `openbot init` creates and clones the owner repository into the empty destination before configuring it; successful initialization removes that exact upstream sentinel so the fork can commit its configuration and initial agent. Commit the deletion with the generated configuration. Ordinary upstream merges preserve the fork's committed deletion while upstream leaves the sentinel unchanged. No setup or pairing code is required. +A fresh upstream checkout intentionally contains only `configuration/.gitignore`, which hides all configuration contents. `tilde init` creates and clones the owner repository into the empty destination before configuring it; successful initialization removes that exact upstream sentinel so the fork can commit its configuration and initial agent. Commit the deletion with the generated configuration. Ordinary upstream merges preserve the fork's committed deletion while upstream leaves the sentinel unchanged. No setup or pairing code is required. ## Develop this repository -Contributors and coding agents drive the repository through the same `openbot` CLI, which +Contributors and coding agents drive the repository through the same Tilde CLI, which carries the developer workflow beside its operator commands (ADR-0018): ```bash -pnpm openbot check # contracts, types, lint, package tests -pnpm openbot build # every package, plus artifact verification -pnpm openbot test # repository tests -pnpm openbot e2e # browser Playwright suite -pnpm openbot desktop dev # Electron shell, headless with VNC on a display-less host -pnpm openbot desktop package # Electron packaging -pnpm openbot connect -- # tunnel a remote host's Electron desktop -pnpm openbot sdk refresh # regenerate, build, and test the Tilde SDK +pnpm tilde check # contracts, types, lint, package tests +pnpm tilde build # every package, plus artifact verification +pnpm tilde test # repository tests +pnpm tilde e2e # browser Playwright suite +pnpm tilde desktop dev # Electron shell, headless with VNC on a display-less host +pnpm tilde desktop package # Electron packaging +pnpm tilde connect -- # tunnel a remote host's Electron desktop +pnpm tilde sdk refresh # regenerate, build, and test the Tilde SDK ``` Prerequisites differ per platform and surface. See [CONTRIBUTING.md](CONTRIBUTING.md) for Linux @@ -52,19 +52,19 @@ and macOS setup from scratch. ## Deploy ```bash -openbot init -pnpm openbot new-agent +tilde init +pnpm tilde new-agent pnpm deploy:prod -- --dry-run --json pnpm deploy:prod -- --yes ``` -`openbot init` creates `configuration/index.ts` and `configuration/.env`, seeds the fork-owned `configuration/templates/agent/` defaults, configures SOPS, generates a dedicated age identity for the trusted development sandbox, and asks for an independent owner identity. Managed owner identities support HashiCorp Vault Transit, Azure Key Vault, Google Cloud KMS, and AWS KMS. Local fallbacks store a generated owner age identity in 1Password or the native operating-system keychain. Provider-contributed questions are saved either to `.env` or `configuration/secrets.enc.yaml`; secret input is never written to command arguments. +`tilde init` creates `configuration/index.ts` and `configuration/.env`, seeds the fork-owned `configuration/templates/agent/` defaults, configures SOPS, generates a dedicated age identity for the trusted development sandbox, and asks for an independent owner identity. Managed owner identities support HashiCorp Vault Transit, Azure Key Vault, Google Cloud KMS, and AWS KMS. Local fallbacks store a generated owner age identity in 1Password or the native operating-system keychain. Provider-contributed questions are saved either to `.env` or `configuration/secrets.enc.yaml`; secret input is never written to command arguments. Every interactive init run shows React Ink selectors for provider domains with multiple built-in implementations. Each selector includes every available implementation and preselects the provider currently composed in `configuration/index.ts`, so rerunning init can update runtime or inference without editing generated composition by hand. As soon as a provider is selected, init asks and provisions that provider's configuration before showing another provider domain; selecting ChatGPT therefore starts Codex device login before any Tilde setup. Init rewrites only a recognized, canonical built-in composition. A custom or owner-edited composition remains selectable as the current value and must be changed explicitly. Init offers Vercel AI Gateway or a ChatGPT subscription through Codex for local and directly managed Vercel runtimes; Vercel AI Gateway remains the default. Directly managed Gateway setup creates a named key stored in SOPS as `AI_GATEWAY_API_KEY`, while Tilde Cloud uses automatic project OIDC and stores no Gateway key. Both default to `openai/gpt-5.6-sol`. The Codex path always runs device-code login, stores the opaque Codex credential cache in SOPS as `CODEX_AUTH_JSON`, and defaults to `gpt-5.6-sol`. Development checks and refreshes that cache before services start and requests another device login when an owner is present; production deployment refreshes valid credentials but stops with an explicit reauthentication instruction when they are missing, expired, or revoked. Vercel agent functions receive the Linux Codex executable and opt into Vercel Large Functions because the native binary exceeds the standard function bundle limit. -The selected inference provider seeds its SDK-specific `inference.ts.hbs` into the fork-owned default agent template. When init changes inference providers, it migrates the future template and existing agents only when each affected file still exactly matches the previous provider scaffold; fork-owned edits stop the switch with an explicit migration error. Generated agents keep the same AI SDK call shape and import vendor SDKs directly. Codex app-server receives the ordinary OpenBot AI SDK tool set through the provider package's local MCP bridge. Sampling controls and strict structured-output behavior remain subject to the community provider's documented limitations. +The selected inference provider seeds its SDK-specific `inference.ts.hbs` into the fork-owned default agent template. When init changes inference providers, it migrates the future template and existing agents only when each affected file still exactly matches the previous provider scaffold; fork-owned edits stop the switch with an explicit migration error. Generated agents keep the same AI SDK call shape and import vendor SDKs directly. Codex app-server receives the ordinary Dispatch AI SDK tool set through the provider package's local MCP bridge. Sampling controls and strict structured-output behavior remain subject to the community provider's documented limitations. Tilde-managed Vercel project OIDC enables hosted inference billing. The agent reserves organization AI credits before each Gateway call, persists the @@ -79,27 +79,27 @@ cannot start a Gateway call even when BYOK is configured. Gateway receipts supply authoritative hosted cost, so hosted jobs do not need manual price-rate configuration. Non-hosted jobs declaring `max_cost_microusd` still require -`OPENBOT_MODEL_INPUT_COST_MICROUSD_PER_MILLION` and -`OPENBOT_MODEL_OUTPUT_COST_MICROUSD_PER_MILLION`. AgentRun budgets are checked +`DISPATCH_MODEL_INPUT_COST_MICROUSD_PER_MILLION` and +`DISPATCH_MODEL_OUTPUT_COST_MICROUSD_PER_MILLION`. AgentRun budgets are checked after each model call and can overshoot by that final call; reservation preflight still prevents spending beyond the organization's available Tilde credits. If a durable inference effect is planned, uncertain, or recovered after its -response is lost, OpenBot never repeats that provider call automatically. It +response is lost, Dispatch never repeats that provider call automatically. It marks the current AgentRun failed after exact billing reconciliation; a later owner request creates a new run explicitly. Root `.env`, `.env.local`, and root SOPS files are intentionally unsupported. Fork configuration comes only from `configuration/.env` and `configuration/secrets.enc.yaml`; contributor machines and CI supply repository-maintenance values through their process environment, so contributor configuration cannot silently propagate into forks. -`openbot dev` checks every runtime provider, starts the shared Computer through Microsandbox, and reconciles Tilde resources for every authored agent before starting the watched control/agent server. Vercel service providers perform no remote development deployment, and a configured Vercel Sandbox provider delegates development to Microsandbox. Computer image inputs are watched; changes rebuild the image and replace the local sandbox while preserving its `/workspace` volume. Tilde creates or updates each local-running Vercel AI SDK endpoint, synchronizes authored skills and an exact registry, creates one dynamic MCP server, and enables the Tilde control-plane toolkit per agent. A Vercel service deployment also enables its proxied MCP connection. Their IDs are maintained as `AGENT__*` values in `configuration/.env`; one-time endpoint credentials remain encrypted. Each reconciliation first checks stable identity and current fields, creates missing resources, and updates only drift. Run the command under the Tilde tunnel when ChatKit must reach local agent routes. +`tilde dev` checks every runtime provider, starts the shared Computer through Microsandbox, and reconciles Tilde resources for every authored agent before starting the watched control/agent server. Vercel service providers perform no remote development deployment, and a configured Vercel Sandbox provider delegates development to Microsandbox. Computer image inputs are watched; changes rebuild the image and replace the local sandbox while preserving its `/workspace` volume. Tilde creates or updates each local-running Vercel AI SDK endpoint, synchronizes authored skills and an exact registry, creates one dynamic MCP server, and enables the Tilde control-plane toolkit per agent. A Vercel service deployment also enables its proxied MCP connection. Their IDs are maintained as `AGENT__*` values in `configuration/.env`; one-time endpoint credentials remain encrypted. Each reconciliation first checks stable identity and current fields, creates missing resources, and updates only drift. Run the command under the Tilde tunnel when ChatKit must reach local agent routes. -OpenBot does not import or export Tilde state during normal lifecycle commands. For a one-time -setup or migration to another environment, an operator can run `openbot state export` and -`openbot state import`; subsequent OpenBot runs reconcile that imported state through the API. +Dispatch does not import or export Tilde state during normal lifecycle commands. For a one-time +setup or migration to another environment, an operator can run `tilde state export` and +`tilde state import`; subsequent Dispatch runs reconcile that imported state through the API. ## Tilde SDK -This monorepo owns the public Tilde TypeScript SDK packages alongside OpenBot: +This monorepo owns the public Tilde TypeScript SDK packages alongside Dispatch: - `@trytilde/api-client`: generated API client and URL helpers. - `@trytilde/sdk`: stable hand-authored Tilde client, ChatKit, MCP, skill, and reverse-proxy APIs. @@ -107,19 +107,19 @@ This monorepo owns the public Tilde TypeScript SDK packages alongside OpenBot: - `@trytilde/sdk-vercel-ai-node` and `@trytilde/sdk-vercel-ai-react`: Vercel AI SDK adapters. - `@trytilde/sdk-codex`, `@trytilde/sdk-claude-code`, `@trytilde/sdk-cursor`, `@trytilde/sdk-opencode`, and `@trytilde/sdk-gemini-cli`: native coding-agent hook adapters that record canonical ChatKit audit events. -Use `openbot auth`, `openbot state`, `openbot tunnel`, and `openbot plugin`; there is no separate -Tilde CLI or plugin package. SDK packages version independently from OpenBot's fixed package group. -Run `openbot sdk refresh` after an intentional Tilde OpenAPI change. +Use `tilde auth`, `tilde state`, `tilde tunnel`, and `tilde plugin` through `@trytilde/cli`; +there is no separate plugin package. SDK packages version independently from Dispatch's fixed package group. +Run `tilde sdk refresh` after an intentional Tilde OpenAPI change. -Use `pnpm openbot secrets set NAME --description "Purpose"` and `pnpm openbot secrets unset NAME` to maintain encrypted values without learning SOPS commands. Every secret is stored as `{ description, value }`; SOPS leaves the description readable and encrypts only `value`. Setting a value requires a current SOPS release with `set --value-stdin` support so plaintext never appears in the process list. Use `pnpm openbot env set NAME VALUE --description "Purpose"` and `pnpm openbot env unset NAME` for plaintext configuration; descriptions are rendered as comments immediately above assignments. +Use `pnpm tilde secrets set NAME --description "Purpose"` and `pnpm tilde secrets unset NAME` to maintain encrypted values without learning SOPS commands. Every secret is stored as `{ description, value }`; SOPS leaves the description readable and encrypts only `value`. Setting a value requires a current SOPS release with `set --value-stdin` support so plaintext never appears in the process list. Use `pnpm tilde env set NAME VALUE --description "Purpose"` and `pnpm tilde env unset NAME` for plaintext configuration; descriptions are rendered as comments immediately above assignments. Commit `configuration/index.ts`, `.sops.yaml`, and `secrets.enc.yaml` after initialization. Never commit `configuration/.env` or root `local-user-config.json`. The latter stores this checkout's SOPS owner lookup metadata under `sops` and is gitignored. Interactive SOPS-backed commands such as `dev`, `deploy`, and secret mutation configure it inline when it is absent; non-interactive commands fail with instructions to rerun interactively. The sandbox age private key is encrypted as `SECRETS_SOPS_AGE_KEY.value`. Trusted-sandbox deployment refreshes `.env`, `.sops.yaml`, and `secrets.enc.yaml`, installs the identity as a mode-`0400` file readable only by the sandbox Linux user, and sources a loader from `.bashrc` and `.bash_profile` to export dotenv and decrypted SOPS values. -The CLI checks and builds every selected provider that exposes `buildable`, then plans and deploys providers that expose `deployable`. `openbot deploy --skip-deploy` stops after producing artifacts. `openbot deploy --service agents --yes` builds and deploys the agent project without compiling or redeploying control; `--service control` does the inverse. A configured computer provider builds its shared image before agent functions and the control runtime. For Vercel Sandbox, deployment creates the Vercel projects first and then creates the agent project's VCR repository on the first image push; local Microsandbox keeps the content-tagged Docker image local. Provider lifecycles persist their own environment and encrypted secrets; deployment results retain named handoff outputs. +The CLI checks and builds every selected provider that exposes `buildable`, then plans and deploys providers that expose `deployable`. `tilde deploy --skip-deploy` stops after producing artifacts. `tilde deploy --service agents --yes` builds and deploys the agent project without compiling or redeploying control; `--service control` does the inverse. A configured computer provider builds its shared image before agent functions and the control runtime. For Vercel Sandbox, deployment creates the Vercel projects first and then creates the agent project's VCR repository on the first image push; local Microsandbox keeps the content-tagged Docker image local. Provider lifecycles persist their own environment and encrypted secrets; deployment results retain named handoff outputs. `configuration/index.ts` is the only composition root and explicitly constructs every provider role under its `providers` object. Agent entrypoints read their runtime environment directly and do not import the composition root or a second runtime-provider module. Init selects one Tilde agent provider that reconciles the agent, its authored skills, dynamic MCP server, Tilde control-plane tools, and deployment-platform MCP integrations. The full primary agent lives at `configuration/agent/`; `new-agent` creates equally complete agents below `configuration/agent/subagents//`. Each owns its instrumentation, skills, tools, and workspace seed. Custom provider source lives under `configuration/providers/`. When provider wiring changes, inspect `configuration/templates/agent/` so future agents receive matching environment variables, tools, prompts, and endpoint setup. Global `configuration/skills/` and `configuration/sandbox/` directories are unsupported, and filesystem locations are not configuration options. -The agent-local folder remains named `sandbox/workspace/` to stay structurally compatible with Eve where practical; runtime terminology is Computer everywhere else. Run `pnpm openbot new-agent` to create an agent from its display name by rendering the fork-owned `configuration/templates/agent/**/*.hbs` tree. Template edits affect future agents only. Each generated agent explicitly owns thin tool files for shell, background-shell waiting, file access, search, and screenshots. Their shared Zod schemas and typed computer-service implementations live in `@tryopenbot/computer-tools`; every file fixes the path-derived agent ID outside its model-visible schema. Populated seeds initialize `/workspace/` once on the shared computer. That path is the agent's default directory, not a security boundary. Agent source imports vendor SDKs directly and never imports provider packages. +The agent-local folder remains named `sandbox/workspace/` to stay structurally compatible with Eve where practical; runtime terminology is Computer everywhere else. Run `pnpm tilde new-agent` to create an agent from its display name by rendering the fork-owned `configuration/templates/agent/**/*.hbs` tree. Template edits affect future agents only. Each generated agent explicitly owns thin tool files for shell, background-shell waiting, file access, search, and screenshots. Their shared Zod schemas and typed computer-service implementations live in `@trytilde/dispatch-computer-tools`; every file fixes the path-derived agent ID outside its model-visible schema. Populated seeds initialize `/workspace/` once on the shared computer. That path is the agent's default directory, not a security boundary. Agent source imports vendor SDKs directly and never imports provider packages. Agent Bash tools run `bash -lc` with `HOME=/workspace/`. Init scaffolds each agent's `sandbox/workspace/.profile`, which Bash loads before @@ -127,7 +127,7 @@ each command and which may source an optional `.bashrc`. Like every workspace seed, the profile is copied only when that agent is first registered; editing it does not modify an existing deployed workspace. -`openbot init` also generates `COMPUTER_SERVICE_API_KEY` in the SOPS document and preserves that name in the runtime environment. Agent and control services receive it through their normal secret installation, and each computer receives the same value when it is created. Computer-service rejects every RPC without the exact bearer key; the key is never returned as a deployment output or written into a generated public artifact. +`tilde init` also generates `COMPUTER_SERVICE_API_KEY` in the SOPS document and preserves that name in the runtime environment. Agent and control services receive it through their normal secret installation, and each computer receives the same value when it is created. Computer-service rejects every RPC without the exact bearer key; the key is never returned as a deployment output or written into a generated public artifact. - `vercel` builds a control/web project and a separate agent project. Every configured agent is a parallel-built Vercel Function; both projects deploy from prebuilt artifacts. - `tilde-cloud` uses the same Vercel service and Sandbox implementations behind Tilde's hosted control plane. A single Tilde API request creates a dedicated team, projects, OIDC-backed AI Gateway access, persistent Computer, and deterministic Vercel project hostname. Custom Cloudflare DNS is a follow-up. Its `CodeStorageGitProvider` keeps the hosted Code Storage repository authoritative inside the Computer and reconciles the configured GitHub fork. Tilde retains its Vercel credential exclusively in the deployment worker; Dispatch publishes content-addressed prebuilt releases through a team-scoped Tilde capability. @@ -144,8 +144,8 @@ The production build stages the web app in the control provider's `.vercel/outpu ## Current application boundary -- `cli` owns the React Ink `openbot` CLI: operator commands, development process supervision, provider deployment coordination, repository gates, remote desktop runs, and ssh tunnels for humans and sandboxed agents alike. -- `packages/api-client` and `packages/sdk*` own the public Tilde TypeScript integration surface and remain usable outside OpenBot; coding-agent plugin setup belongs to `openbot plugin`. +- `cli` owns the React Ink Tilde CLI: operator commands, development process supervision, provider deployment coordination, repository gates, remote desktop runs, and ssh tunnels for humans and sandboxed agents alike. +- `packages/api-client` and `packages/sdk*` own the public Tilde TypeScript integration surface and remain usable outside Dispatch; coding-agent plugin setup belongs to `tilde plugin`. - `packages/runtime-provider` owns the optional provider deployment contract and runtime-last coordinator. - `packages/control-service-provider` owns local and Vercel control/web builds and deployment. - `packages/agent-service-provider` owns Eve-compatible agent-directory discovery, instrumentation startup, concurrent per-agent Vercel bundles, the local agent server, and deployment. @@ -163,4 +163,4 @@ pnpm build pnpm test:e2e ``` -OpenBot is MIT licensed. See [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md) and [PROVENANCE.md](PROVENANCE.md). +Dispatch is MIT licensed. See [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md) and [PROVENANCE.md](PROVENANCE.md). diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md index d716c82f..bbcf97bb 100644 --- a/THIRD_PARTY_NOTICES.md +++ b/THIRD_PARTY_NOTICES.md @@ -1,6 +1,6 @@ # Third-party notices -OpenBot itself is licensed under MIT. Third-party materials retain their own +Dispatch itself is licensed under MIT. Third-party materials retain their own copyright and license status. ## Beautiful UI @@ -17,9 +17,9 @@ copyright and license status. An earlier 2026-08-12 retrieval came from the `TurboKach/ai-native-react-components` mirror while the site returned Vercel `DEPLOYMENT_DISABLED`; the 2026-08-17 retrieval from the live site supersedes -it. Per-file SHA-256 values at retrieval and the small recorded OpenBot +it. Per-file SHA-256 values at retrieval and the small recorded Dispatch modifications (analytics removal, import-path rewrites) are documented in -`packages/ui/src/beautiful-ui/PROVENANCE.md`. OpenBot-specific composition is +`packages/ui/src/beautiful-ui/PROVENANCE.md`. Dispatch-specific composition is kept outside the upstream directory. ## shadcn/ui @@ -27,17 +27,17 @@ kept outside the upstream directory. - Source: (distributed via the shadcn registry CLI) - License: MIT - Files: `packages/ui/src/components/ui/` -- OpenBot modifications: import paths rewritten to relative form; the +- Dispatch modifications: import paths rewritten to relative form; the registry's `accent` utilities remapped to the Beautiful UI `hover`/`ink` tokens; `dialog.tsx`, `command.tsx`, and `dropdown-menu.tsx` are - OpenBot-authored on Radix/cmdk primitives rather than registry copies. + Dispatch-authored on Radix/cmdk primitives rather than registry copies. ## Vercel AI Elements - Source: (distributed via the `ai-elements` CLI, Apache-2.0) - Files: `packages/ui/src/components/ai-elements/` -- OpenBot modifications: import paths rewritten to relative form; `accent` +- Dispatch modifications: import paths rewritten to relative form; `accent` utilities remapped as above; a type cast added for the `streamdown`/`@streamdown/*` shiki version skew. @@ -56,5 +56,5 @@ kept outside the upstream directory. - Bundled skill source commit: `70db98d1bcd92890d778f4978e0eb107a4b66c1b` - Bundled files: `packages/agent-provider/src/tilde/assets/cua-driver/` - License: MIT -- OpenBot modifications: none to the bundled canonical skill files; OpenBot's - separate computer-use overlay is original OpenBot material. +- Dispatch modifications: none to the bundled canonical skill files; Dispatch's + separate computer-use overlay is original Dispatch material. diff --git a/apps/computer-service/README.md b/apps/computer-service/README.md index f57377f7..fa8bc907 100644 --- a/apps/computer-service/README.md +++ b/apps/computer-service/README.md @@ -1,10 +1,10 @@ -# @tryopenbot/computer-service +# @trytilde/dispatch-computer-service -The API-key-protected ConnectRPC server that runs inside an OpenBot Computer image. It executes lifecycle bundles, agent-scoped commands and file operations, Cua Driver GUI automation, port discovery, and VNC tunneling. +The API-key-protected ConnectRPC server that runs inside a Dispatch Computer image. It executes lifecycle bundles, agent-scoped commands and file operations, Cua Driver GUI automation, port discovery, and VNC tunneling. ## Public API -This package is a service executable and declares no importable package exports. Its network contract is `@tryopenbot/computer-service-proto`, mounted under `/rpc`; the listening port is `COMPUTER_SERVICE_PORT` or `4101`. +This package is a service executable and declares no importable package exports. Its network contract is `@trytilde/dispatch-computer-service-proto`, mounted under `/rpc`; the listening port is `COMPUTER_SERVICE_PORT` or `4101`. Model-facing requests include an agent ID. The service validates it and defaults relative command and file operations to `/workspace/`. Agents otherwise share the computer's process identity and filesystem, so this directory is not a security boundary. Agent tools call this service through the generated typed client. The web and desktop applications do not call it directly. @@ -12,6 +12,6 @@ Every RPC requires `Authorization: Bearer `. Init crea Model-controlled processes start with an allowlisted environment, so the service key and other computer-service environment variables are not inherited. `HOME` is the agent directory, allowing its seeded `.profile` to initialize Bash login shells. -Background shell commands detach from the service process and keep private job metadata, bounded output, and an exit-status file under `/workspace/.openbot/jobs`. `AwaitExec` validates the originating agent ID and can recover a running or completed job after computer-service restarts; jobs still belong to the lifetime of the Computer itself. +Background shell commands detach from the service process and keep private job metadata, bounded output, and an exit-status file under `/workspace/.dispatch/jobs`. `AwaitExec` validates the originating agent ID and can recover a running or completed job after computer-service restarts; jobs still belong to the lifetime of the Computer itself. `ListCuaTools` and `CallCuaTool` expose the exact runtime Cua catalog and result envelope. One lazy private worker receives each agent's display, isolated home/XDG state (including Cua's browser data), and accessibility environment. Legacy screenshot and input RPCs are compatibility translations through Cua. noVNC remains a separate owner preview and takeover transport. diff --git a/apps/computer-service/package.json b/apps/computer-service/package.json index 09521d4c..3593954f 100644 --- a/apps/computer-service/package.json +++ b/apps/computer-service/package.json @@ -1,8 +1,8 @@ { - "name": "@tryopenbot/computer-service", + "name": "@trytilde/dispatch-computer-service", "version": "0.1.0", "bin": { - "openbot-computer-service": "./dist/index.js" + "dispatch-computer-service": "./dist/index.js" }, "files": [ "dist", @@ -28,8 +28,8 @@ "@connectrpc/connect": "2.1.2", "@connectrpc/connect-node": "2.1.2", "@trycua/cua-driver": "0.21.0", - "@tryopenbot/computer-service-proto": "workspace:*", - "@tryopenbot/utilities": "workspace:*" + "@trytilde/dispatch-computer-service-proto": "workspace:*", + "@trytilde/dispatch-utilities": "workspace:*" }, "devDependencies": { "@types/node": "24.3.0", diff --git a/apps/computer-service/src/background-exec.test.ts b/apps/computer-service/src/background-exec.test.ts index 8e8dcc56..bb665085 100644 --- a/apps/computer-service/src/background-exec.test.ts +++ b/apps/computer-service/src/background-exec.test.ts @@ -10,7 +10,7 @@ afterEach(async () => ); async function registry(): Promise { - const root = await mkdtemp(join(tmpdir(), "openbot-background-jobs-")); + const root = await mkdtemp(join(tmpdir(), "dispatch-background-jobs-")); roots.push(root); return new BackgroundExecRegistry(root); } diff --git a/apps/computer-service/src/background-exec.ts b/apps/computer-service/src/background-exec.ts index 220755ae..ef5cbfac 100644 --- a/apps/computer-service/src/background-exec.ts +++ b/apps/computer-service/src/background-exec.ts @@ -27,7 +27,7 @@ interface BackgroundJobMetadata { */ export class BackgroundExecRegistry { constructor( - readonly stateRoot = process.env.BACKGROUND_JOBS_DIRECTORY ?? "/workspace/.openbot/jobs", + readonly stateRoot = process.env.BACKGROUND_JOBS_DIRECTORY ?? "/workspace/.dispatch/jobs", ) {} async start( diff --git a/apps/computer-service/src/capability.ts b/apps/computer-service/src/capability.ts index 34c55f9f..76b85494 100644 --- a/apps/computer-service/src/capability.ts +++ b/apps/computer-service/src/capability.ts @@ -6,6 +6,6 @@ export function validComputerServiceApiKey( ): boolean { const candidate = authorization?.startsWith("Bearer ") ? authorization.slice(7) : ""; const digest = (value: string) => - createHmac("sha256", "openbot/computer-service-api-key/v1").update(value).digest(); + createHmac("sha256", "dispatch/computer-service-api-key/v1").update(value).digest(); return timingSafeEqual(digest(candidate), digest(expected)); } diff --git a/apps/computer-service/src/cua.test.ts b/apps/computer-service/src/cua.test.ts index 61673df6..c369f3a3 100644 --- a/apps/computer-service/src/cua.test.ts +++ b/apps/computer-service/src/cua.test.ts @@ -5,7 +5,7 @@ import { VerificationStatus, type CuaDriverLike, } from "@trycua/cua-driver"; -import { CuaActionCompletion } from "@tryopenbot/computer-service-proto"; +import { CuaActionCompletion } from "@trytilde/dispatch-computer-service-proto"; import { afterEach, describe, expect, it, vi } from "vite-plus/test"; import { callCuaTool, cuaTesting, listCuaTools, shutdownCuaWorkers } from "./cua.js"; diff --git a/apps/computer-service/src/cua.ts b/apps/computer-service/src/cua.ts index 99d2419b..6d8a6a9a 100644 --- a/apps/computer-service/src/cua.ts +++ b/apps/computer-service/src/cua.ts @@ -10,8 +10,8 @@ import { } from "@trycua/cua-driver"; import { spawn } from "node:child_process"; import { Code, ConnectError } from "@connectrpc/connect"; -import { CuaActionCompletion } from "@tryopenbot/computer-service-proto"; -import { isRecord } from "@tryopenbot/utilities/json"; +import { CuaActionCompletion } from "@trytilde/dispatch-computer-service-proto"; +import { isRecord } from "@trytilde/dispatch-utilities/json"; import { agentDesktopEnvironment, ensureAgentDesktop } from "./desktop.js"; export interface CuaToolCatalogEntry { @@ -54,7 +54,7 @@ async function defaultDriverFactory(agentId: string, signal?: AbortSignal): Prom }; const worker = CuaDriver.createPrivateWorker({ binaryPath, - hostBundleId: "ai.tryopenbot.computer-service", + hostBundleId: "ai.trydispatch.computer-service", startupTimeoutMs: 30_000n, shutdownTimeoutMs: 10_000n, configuredDriver: { diff --git a/apps/computer-service/src/desktop.test.ts b/apps/computer-service/src/desktop.test.ts index adac67ec..89847bc0 100644 --- a/apps/computer-service/src/desktop.test.ts +++ b/apps/computer-service/src/desktop.test.ts @@ -20,7 +20,7 @@ afterEach(async () => { describe("agent desktops", () => { it("allocates stable, separate displays when agents start concurrently", async () => { - const temporaryDirectory = await mkdtemp(join(tmpdir(), "openbot-desktop-test-")); + const temporaryDirectory = await mkdtemp(join(tmpdir(), "dispatch-desktop-test-")); temporaryDirectories.push(temporaryDirectory); const binaryDirectory = join(temporaryDirectory, "bin"); const desktopRoot = join(temporaryDirectory, "desktops"); @@ -61,7 +61,7 @@ describe("agent desktops", () => { ].sort(), ); expect(info).toHaveBeenCalledWith( - "[openbot-vnc] started desktop", + "[dispatch-vnc] started desktop", expect.objectContaining({ agentId: "first-agent", display: first.display, diff --git a/apps/computer-service/src/desktop.ts b/apps/computer-service/src/desktop.ts index af1aa641..3bc46f67 100644 --- a/apps/computer-service/src/desktop.ts +++ b/apps/computer-service/src/desktop.ts @@ -4,8 +4,8 @@ import { join } from "node:path"; import { setTimeout as delay } from "node:timers/promises"; import { Code, ConnectError } from "@connectrpc/connect"; -const desktopRoot = process.env.COMPUTER_DESKTOP_ROOT ?? "/workspace/.openbot/desktops"; -const tokenFile = process.env.COMPUTER_VNC_TOKEN_FILE ?? "/opt/openbot/novnc.tokens"; +const desktopRoot = process.env.COMPUTER_DESKTOP_ROOT ?? "/workspace/.dispatch/desktops"; +const tokenFile = process.env.COMPUTER_VNC_TOKEN_FILE ?? "/opt/dispatch/novnc.tokens"; const pending = new Map>(); let capabilityWrite = Promise.resolve(); let desktopAllocation = Promise.resolve(); @@ -95,7 +95,7 @@ async function ensureAgentDesktopNow( function logDesktop(message: string, fields: Record): void { if (!fields.requestId) return; - console.info(`[openbot-vnc] ${message}`, fields); + console.info(`[dispatch-vnc] ${message}`, fields); } async function startAndPersistDesktop( @@ -178,7 +178,7 @@ async function startDesktop( }; await ensureSessionBus(environment.DBUS_SESSION_BUS_ADDRESS, environment, signal); const session = spawn( - process.env.COMPUTER_DESKTOP_SESSION ?? "/opt/openbot/desktop-session.sh", + process.env.COMPUTER_DESKTOP_SESSION ?? "/opt/dispatch/desktop-session.sh", [], { detached: true, diff --git a/apps/computer-service/src/index.ts b/apps/computer-service/src/index.ts index 203952e5..0a4033f1 100644 --- a/apps/computer-service/src/index.ts +++ b/apps/computer-service/src/index.ts @@ -11,7 +11,7 @@ const server = createServer( connectNodeAdapter({ routes: registerComputerService, requestPathPrefix: "/rpc" }), ); server.listen(port, "0.0.0.0", () => - console.log(`OpenBot computer service listening on port ${port}`), + console.log(`Dispatch computer service listening on port ${port}`), ); async function stop() { diff --git a/apps/computer-service/src/lifecycle.test.ts b/apps/computer-service/src/lifecycle.test.ts index fd83af87..8b5f86b2 100644 --- a/apps/computer-service/src/lifecycle.test.ts +++ b/apps/computer-service/src/lifecycle.test.ts @@ -1,19 +1,19 @@ import { createHash } from "node:crypto"; import { describe, expect, it } from "vite-plus/test"; -import { LifecyclePhase } from "@tryopenbot/computer-service-proto"; +import { LifecyclePhase } from "@trytilde/dispatch-computer-service-proto"; import { lifecycleBundleDigest } from "./lifecycle.js"; describe("lifecycleBundleDigest", () => { it("is stable across input order and changes with file content", () => { const file = (path: string, content: string) => ({ - $typeName: "openbot.computer.v1.LifecycleFile" as const, + $typeName: "dispatch.computer.v1.LifecycleFile" as const, path, content: new TextEncoder().encode(content), mode: 0o755, sha256: createHash("sha256").update(content).digest("hex"), }); const script = { - $typeName: "openbot.computer.v1.LifecycleScript" as const, + $typeName: "dispatch.computer.v1.LifecycleScript" as const, id: "start", path: "start.sh", phases: [LifecyclePhase.CREATE], diff --git a/apps/computer-service/src/lifecycle.ts b/apps/computer-service/src/lifecycle.ts index cbd0d32c..8c7d0cb9 100644 --- a/apps/computer-service/src/lifecycle.ts +++ b/apps/computer-service/src/lifecycle.ts @@ -8,13 +8,13 @@ import { Code, ConnectError } from "@connectrpc/connect"; import { LifecyclePhase, type ApplyLifecycleBundleRequest, -} from "@tryopenbot/computer-service-proto"; -import { materializeFileTemplate } from "@tryopenbot/utilities"; +} from "@trytilde/dispatch-computer-service-proto"; +import { materializeFileTemplate } from "@trytilde/dispatch-utilities"; const execute = promisify(execFile); const manifestTemplate = fileURLToPath(new URL("./assets/manifest.json.hbs", import.meta.url)); function lifecycleRoot(): string { - return resolve(process.env.COMPUTER_LIFECYCLE_ROOT ?? "/opt/openbot/lifecycle"); + return resolve(process.env.COMPUTER_LIFECYCLE_ROOT ?? "/opt/dispatch/lifecycle"); } function currentRoot(): string { diff --git a/apps/computer-service/src/services.ts b/apps/computer-service/src/services.ts index eb58b5e8..cb40c3eb 100644 --- a/apps/computer-service/src/services.ts +++ b/apps/computer-service/src/services.ts @@ -3,7 +3,7 @@ import { createConnection } from "node:net"; import { posix } from "node:path"; import { promisify } from "node:util"; import { Code, ConnectError, type ConnectRouter, type HandlerContext } from "@connectrpc/connect"; -import { ComputerService } from "@tryopenbot/computer-service-proto"; +import { ComputerService } from "@trytilde/dispatch-computer-service-proto"; import { agentCommand, agentVisiblePath } from "./agent.js"; import { BackgroundExecRegistry } from "./background-exec.js"; import { validComputerServiceApiKey } from "./capability.js"; @@ -189,9 +189,9 @@ export function registerComputerService(router: ConnectRouter): void { }, async ensureDesktop(request, context) { authorized(context); - const requestId = context.requestHeader.get("x-openbot-request-id")?.trim() || undefined; + const requestId = context.requestHeader.get("x-dispatch-request-id")?.trim() || undefined; const startedAt = Date.now(); - console.info("[openbot-vnc] computer desktop requested", { + console.info("[dispatch-vnc] computer desktop requested", { agentId: request.agentId, hasCapability: Boolean(request.capability), requestId, @@ -203,7 +203,7 @@ export function registerComputerService(router: ConnectRouter): void { context.signal, requestId, ); - console.info("[openbot-vnc] computer desktop ready", { + console.info("[dispatch-vnc] computer desktop ready", { agentId: request.agentId, display: desktop.display, elapsedMs: Date.now() - startedAt, @@ -213,7 +213,7 @@ export function registerComputerService(router: ConnectRouter): void { return { display: desktop.display, vncPort: desktop.vncPort }; } catch (error) { console.error( - "[openbot-vnc] computer desktop failed", + "[dispatch-vnc] computer desktop failed", { agentId: request.agentId, elapsedMs: Date.now() - startedAt, requestId }, error instanceof Error ? error : new Error(String(error)), ); diff --git a/apps/computer-service/tsdown.config.ts b/apps/computer-service/tsdown.config.ts index 7b13e2cf..604b5f1b 100644 --- a/apps/computer-service/tsdown.config.ts +++ b/apps/computer-service/tsdown.config.ts @@ -12,8 +12,8 @@ export default defineConfig({ alwaysBundle: [ /@bufbuild\/protobuf/, /@connectrpc\//, - /@tryopenbot\/computer-service-proto/, - /@tryopenbot\/utilities/, + /@trytilde\/dispatch-computer-service-proto/, + /@trytilde\/dispatch-utilities/, /handlebars/, ], }, diff --git a/apps/control-service/README.md b/apps/control-service/README.md index 6fee1abe..9fdf4e66 100644 --- a/apps/control-service/README.md +++ b/apps/control-service/README.md @@ -1,4 +1,4 @@ -# @tryopenbot/control-service +# @trytilde/dispatch-control-service The portable Hono control application. It serves health, exposes raw allowlisted same-origin Tilde bridges under `/api/chat/*` and `/api/tilde/*`, exchanges an HttpOnly browser session for a single-use registered-Origin ticket or an authenticated native bearer for an Origin-free native ticket, and serves the built web UI with SPA fallback both locally and in a Vercel Function. Client Runtime uses that ticket to connect directly to Tilde's team WebSocket and projects Tilde-owned settings resources without domain facades in this service. @@ -16,11 +16,11 @@ The portable Hono control application. It serves health, exposes raw allowlisted decision using only the owner bearer already verified by `requireOwner`; it never substitutes the installation API key and returns only the tokenless approval projection consumed by clients. - `registerComputerPreview(app, provider, options)` exposes the narrow owner preview redirect without making Computer service browser-accessible. -- `registerConnectorAuthorizedRoute(app)` serves only the public OAuth completion page that bounces desktop flows to the `openbot://` deep link. Connector resources and setup use native Tilde APIs through `registerTildeProxy`. +- `registerConnectorAuthorizedRoute(app)` serves only the public OAuth completion page that bounces desktop flows to the `dispatch://` deep link. Connector resources and setup use native Tilde APIs through `registerTildeProxy`. The package default application also exposes `GET /healthz`. There is no owner-facing ConnectRPC surface or pairing-code setup route. -Owner-authenticated `POST /api/agents` starts `openbot new-agent` inside the trusted development +Owner-authenticated `POST /api/agents` starts `tilde new-agent` inside the trusted development Computer as a background job. `GET /api/agents/setup/:jobId` reports that job without exposing the Computer API key or shell output to the browser. The command owns source creation and idempotent Tilde reconciliation; the status route does not provision a second time or require a separate diff --git a/apps/control-service/package.json b/apps/control-service/package.json index 75fa13be..a595a4f1 100644 --- a/apps/control-service/package.json +++ b/apps/control-service/package.json @@ -1,5 +1,5 @@ { - "name": "@tryopenbot/control-service", + "name": "@trytilde/dispatch-control-service", "version": "0.1.0", "files": [ "dist", @@ -38,10 +38,10 @@ "@connectrpc/connect": "2.1.2", "@connectrpc/connect-node": "2.1.2", "@hono/node-server": "1.19.1", - "@tryopenbot/auth-provider": "workspace:*", - "@tryopenbot/computer-service-proto": "workspace:*", - "@tryopenbot/computer-service-provider": "workspace:*", - "@tryopenbot/utilities": "workspace:*", + "@trytilde/dispatch-auth-provider": "workspace:*", + "@trytilde/dispatch-computer-service-proto": "workspace:*", + "@trytilde/dispatch-computer-service-provider": "workspace:*", + "@trytilde/dispatch-utilities": "workspace:*", "hono": "4.13.1" }, "devDependencies": { diff --git a/apps/control-service/src/agent-create.ts b/apps/control-service/src/agent-create.ts index 0be3e26c..d154fdc2 100644 --- a/apps/control-service/src/agent-create.ts +++ b/apps/control-service/src/agent-create.ts @@ -3,8 +3,8 @@ import { randomUUID } from "node:crypto"; import { createClient } from "@connectrpc/connect"; import { createConnectTransport } from "@connectrpc/connect-node"; import type { Hono } from "hono"; -import { ComputerService } from "@tryopenbot/computer-service-proto"; -import { agentIdFromName } from "@tryopenbot/utilities"; +import { ComputerService } from "@trytilde/dispatch-computer-service-proto"; +import { agentIdFromName } from "@trytilde/dispatch-utilities"; export interface AgentCreationOptions { environment?: NodeJS.ProcessEnv; @@ -80,7 +80,7 @@ export function registerAgentCreation(app: Hono, options: AgentCreationOptions = ? { agentId: "factory", command: "pnpm", - arguments: ["openbot", "new-agent", name, "--json"], + arguments: ["tilde", "new-agent", name, "--json"], cwd: options.repositoryRoot, timeoutMilliseconds: createTimeoutMs, background: true, @@ -90,7 +90,7 @@ export function registerAgentCreation(app: Hono, options: AgentCreationOptions = command: "bash", arguments: [ "-lc", - `source /workspace/.openbot/development/profile.sh && cd /workspace/openbot && pnpm openbot new-agent ${shellQuote(name)} --json`, + `source /workspace/.dispatch/development/profile.sh && cd /workspace/dispatch && pnpm tilde new-agent ${shellQuote(name)} --json`, ], cwd: "", timeoutMilliseconds: createTimeoutMs, diff --git a/apps/control-service/src/app.test.ts b/apps/control-service/src/app.test.ts index 1b08de5e..a82611b2 100644 --- a/apps/control-service/src/app.test.ts +++ b/apps/control-service/src/app.test.ts @@ -3,8 +3,8 @@ import { tmpdir } from "node:os"; import { join } from "node:path"; import { afterEach, describe, expect, it, vi } from "vite-plus/test"; import { Code, ConnectError } from "@connectrpc/connect"; -import type { AuthProvider } from "@tryopenbot/auth-provider"; -import type { ComputerProvider } from "@tryopenbot/computer-service-provider"; +import type { AuthProvider } from "@trytilde/dispatch-auth-provider"; +import type { ComputerProvider } from "@trytilde/dispatch-computer-service-provider"; import { app, createApp } from "./app.js"; const temporaryRoots: string[] = []; @@ -24,7 +24,7 @@ function testAuthProvider(): AuthProvider { authorizationEndpoint: "https://identity.test/authorize", tokenEndpoint: "https://identity.test/token", clientId: "client-one", - scope: "openid offline_access openbot:control", + scope: "openid offline_access dispatch:control", }), authorizationUrl: () => new URL("https://identity.test/authorize"), exchangeCode: async () => ({ accessToken: "browser-token", expiresIn: 3600 }), @@ -32,20 +32,20 @@ function testAuthProvider(): AuthProvider { verify: async () => ({ subject: "owner-one", groups: [], - scope: ["openbot:control"], + scope: ["dispatch:control"], }), } as unknown as AuthProvider; } -describe("bare OpenBot server", () => { +describe("bare Dispatch server", () => { it("reports healthy without setup", async () => { - const response = await app.request("https://openbot.test/healthz"); + const response = await app.request("https://dispatch.test/healthz"); expect(response.status).toBe(200); - await expect(response.json()).resolves.toEqual({ ok: true, service: "openbot" }); + await expect(response.json()).resolves.toEqual({ ok: true, service: "dispatch" }); }); it("reports native authentication as unavailable when it is not configured", async () => { - const response = await app.request("https://openbot.test/auth/native-config"); + const response = await app.request("https://dispatch.test/auth/native-config"); expect(response.status).toBe(503); await expect(response.json()).resolves.toEqual({ error: "Owner authentication is not configured", @@ -53,17 +53,19 @@ describe("bare OpenBot server", () => { }); it("does not expose an API namespace", async () => { - const response = await app.request("https://openbot.test/api/setup/unlock", { method: "POST" }); + const response = await app.request("https://dispatch.test/api/setup/unlock", { + method: "POST", + }); expect(response.status).toBe(404); }); it("serves the public connector OAuth completion handoff", async () => { const response = await createApp({ webRoot: "/missing" }).request( - "https://openbot.test/connectors/authorized?client=electron", + "https://dispatch.test/connectors/authorized?client=electron", ); expect(response.status).toBe(200); expect(response.headers.get("cache-control")).toBe("no-store"); - await expect(response.text()).resolves.toContain("openbot://connectors/authorized"); + await expect(response.text()).resolves.toContain("dispatch://connectors/authorized"); }); it("passes allowlisted owner settings operations through to Tilde unchanged", async () => { @@ -92,7 +94,7 @@ describe("bare OpenBot server", () => { }); const response = await tildeApp.request( - "https://openbot.test/api/tilde/automations/routine-one?view=owner", + "https://dispatch.test/api/tilde/automations/routine-one?view=owner", { method: "PUT", headers: { @@ -122,7 +124,7 @@ describe("bare OpenBot server", () => { const unsupported = [ ["/api/tilde/identity/api-key", "POST"], - ["/api/tilde/openbot/plugins/catalog", "GET"], + ["/api/tilde/dispatch/plugins/catalog", "GET"], ["/api/tilde/provider-setup/catalog", "GET"], ["/api/tilde/provider-setup/setup-one/resume", "POST"], ["/api/tilde/signals/deliveries/delivery-one/retry", "POST"], @@ -130,7 +132,7 @@ describe("bare OpenBot server", () => { ["/api/tilde/credential/source/oauth/resource-server", "POST"], ] as const; for (const [path, method] of unsupported) { - const response = await tildeApp.request(`https://openbot.test${path}`, { method }); + const response = await tildeApp.request(`https://dispatch.test${path}`, { method }); expect(response.status, `${method} ${path}`).toBe(404); } expect(tildeFetch).not.toHaveBeenCalled(); @@ -156,7 +158,7 @@ describe("bare OpenBot server", () => { }); const response = await tildeApp.request( - "https://openbot.test/api/tilde/mcp/tool-group/github%2Fwork", + "https://dispatch.test/api/tilde/mcp/tool-group/github%2Fwork", { method: "DELETE" }, ); @@ -188,7 +190,7 @@ describe("bare OpenBot server", () => { agentCreation: { execute, awaitExecution }, }); - const response = await agentApp.request("https://openbot.test/api/agents", { + const response = await agentApp.request("https://dispatch.test/api/agents", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ name: "Test" }), @@ -205,12 +207,12 @@ describe("bare OpenBot server", () => { agentId: "factory", command: "bash", background: true, - arguments: ["-lc", expect.stringContaining("openbot new-agent 'Test' --json")], + arguments: ["-lc", expect.stringContaining("tilde new-agent 'Test' --json")], }), expect.objectContaining({ authorization: "Bearer computer-key" }), ); - const status = await agentApp.request(`https://openbot.test/api/agents/setup/${jobId}`, { + const status = await agentApp.request(`https://dispatch.test/api/agents/setup/${jobId}`, { headers: { authorization: "Bearer owner-token" }, }); expect(status.status).toBe(200); @@ -238,7 +240,7 @@ describe("bare OpenBot server", () => { agentCreation: { repositoryRoot: "/repository", execute }, }); - const response = await agentApp.request("https://openbot.test/api/agents", { + const response = await agentApp.request("https://dispatch.test/api/agents", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ name: "Tasa" }), @@ -249,7 +251,7 @@ describe("bare OpenBot server", () => { { agentId: "factory", command: "pnpm", - arguments: ["openbot", "new-agent", "Tasa", "--json"], + arguments: ["tilde", "new-agent", "Tasa", "--json"], cwd: "/repository", timeoutMilliseconds: 600_000, background: true, @@ -259,7 +261,7 @@ describe("bare OpenBot server", () => { }); it("completes a development setup job through the local background runner", async () => { - const root = await mkdtemp(join(tmpdir(), "openbot-agent-create-")); + const root = await mkdtemp(join(tmpdir(), "dispatch-agent-create-")); temporaryRoots.push(root); const pnpm = join(root, "pnpm"); await writeFile( @@ -272,7 +274,7 @@ describe("bare OpenBot server", () => { agentCreation: { repositoryRoot: root }, }); - const started = await agentApp.request("https://openbot.test/api/agents", { + const started = await agentApp.request("https://dispatch.test/api/agents", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ name: "Tasa" }), @@ -284,7 +286,7 @@ describe("bare OpenBot server", () => { for (let attempt = 0; attempt < 50 && status.status === "setting_up"; attempt += 1) { await new Promise((resolvePromise) => setTimeout(resolvePromise, 10)); status = (await ( - await agentApp.request(`https://openbot.test/api/agents/setup/${jobId}`) + await agentApp.request(`https://dispatch.test/api/agents/setup/${jobId}`) ).json()) as typeof status; } @@ -317,9 +319,9 @@ describe("bare OpenBot server", () => { agentCreation: { awaitExecution }, }); - const running = await agentApp.request(`https://openbot.test/api/agents/setup/${jobId}`); + const running = await agentApp.request(`https://dispatch.test/api/agents/setup/${jobId}`); await expect(running.json()).resolves.toEqual({ status: "setting_up" }); - const failed = await agentApp.request(`https://openbot.test/api/agents/setup/${jobId}`); + const failed = await agentApp.request(`https://dispatch.test/api/agents/setup/${jobId}`); await expect(failed.json()).resolves.toEqual({ status: "failed", error: "Tilde setup failed" }); }); @@ -339,7 +341,7 @@ describe("bare OpenBot server", () => { }, }); - const response = await agentApp.request("https://openbot.test/api/agents", { + const response = await agentApp.request("https://dispatch.test/api/agents", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ name: "Test" }), @@ -362,13 +364,13 @@ describe("bare OpenBot server", () => { environment: { COMPUTER_ID: "computer-one" }, }); const response = await computerApp.request( - `https://openbot.test/api/computer/hello-world/preview?trace_id=${traceId}`, + `https://dispatch.test/api/computer/hello-world/preview?trace_id=${traceId}`, ); expect(response.status).toBe(307); expect(response.headers.get("location")).toBe("https://computer.test/vnc.html?token=opaque"); expect(response.headers.get("cache-control")).toBe("no-store"); expect(response.headers.get("referrer-policy")).toBe("no-referrer"); - expect(response.headers.get("x-openbot-vnc-trace-id")).toBe(traceId); + expect(response.headers.get("x-dispatch-vnc-trace-id")).toBe(traceId); expect(previewAgentDesktop).toHaveBeenCalledWith( "hello-world", expect.objectContaining({ @@ -378,7 +380,7 @@ describe("bare OpenBot server", () => { }), ); expect(info).toHaveBeenCalledWith( - "[openbot-vnc] preview redirect ready", + "[dispatch-vnc] preview redirect ready", expect.objectContaining({ agentId: "hello-world", endpointOrigin: "https://computer.test", @@ -388,7 +390,7 @@ describe("bare OpenBot server", () => { ); expect(JSON.stringify(info.mock.calls)).not.toContain("opaque"); - const invalid = await computerApp.request("https://openbot.test/api/computer/../preview"); + const invalid = await computerApp.request("https://dispatch.test/api/computer/../preview"); expect(invalid.status).not.toBe(307); }); @@ -405,7 +407,7 @@ describe("bare OpenBot server", () => { controller.abort(); const response = await computerApp.request( - "https://openbot.test/api/computer/hello-world/preview", + "https://dispatch.test/api/computer/hello-world/preview", { signal: controller.signal }, ); @@ -418,8 +420,8 @@ describe("bare OpenBot server", () => { const chatApp = createApp({ tildeChatProxy: { apiKey: "secret-api-key", - orgId: "openbot-org", - teamId: "openbot-team", + orgId: "dispatch-org", + teamId: "dispatch-team", baseUrl: "https://tilde.test", fetch: async (input, request) => { const url = @@ -438,7 +440,7 @@ describe("bare OpenBot server", () => { }); const response = await chatApp.request( - "https://openbot.test/api/chat/session/session-one/observe?attach_to_child_sessions=true", + "https://dispatch.test/api/chat/session/session-one/observe?attach_to_child_sessions=true", { headers: { authorization: "Bearer browser-token", "last-event-id": "event-one" } }, ); @@ -450,11 +452,11 @@ describe("bare OpenBot server", () => { await expect(response.text()).resolves.toContain("message_streaming"); expect(calls).toHaveLength(1); expect(calls[0]?.url).toBe( - "https://tilde.test/api/v1/team/openbot-team/chatkit/session/session-one/observe?attach_to_child_sessions=true", + "https://tilde.test/api/v1/team/dispatch-team/chatkit/session/session-one/observe?attach_to_child_sessions=true", ); const headers = new Headers(calls[0]?.request.headers); expect(headers.get("x-api-key")).toBe("secret-api-key"); - expect(headers.get("x-tilde-org-id")).toBe("openbot-org"); + expect(headers.get("x-tilde-org-id")).toBe("dispatch-org"); expect(headers.get("authorization")).toBeNull(); expect(headers.get("accept-encoding")).toBe("identity"); expect(headers.get("last-event-id")).toBe("event-one"); @@ -468,9 +470,9 @@ describe("bare OpenBot server", () => { authProvider: testAuthProvider(), tildeChatProxy: { apiKey: "secret-api-key", - orgId: "openbot-org", - teamId: "openbot-team", - baseUrl: "https://openbot-org.api.trytilde.ai", + orgId: "dispatch-org", + teamId: "dispatch-team", + baseUrl: "https://dispatch-org.api.trytilde.ai", fetch: async (input, request) => { upstreamUrl = input instanceof Request ? input.url : input instanceof URL ? input.href : input; @@ -485,10 +487,13 @@ describe("bare OpenBot server", () => { }, }); - const response = await chatApp.request("https://openbot.test/api/chat/realtime/socket-ticket", { - method: "POST", - headers: { cookie: "openbot_access=browser-token", origin: "https://openbot.test" }, - }); + const response = await chatApp.request( + "https://dispatch.test/api/chat/realtime/socket-ticket", + { + method: "POST", + headers: { cookie: "dispatch_access=browser-token", origin: "https://dispatch.test" }, + }, + ); expect(response.status).toBe(200); expect(response.headers.get("cache-control")).toBe("no-store"); @@ -497,17 +502,17 @@ describe("bare OpenBot server", () => { protocol: "tilde.chatkit-realtime.ticket", expires_at: "2026-08-26T12:00:00Z", websocket_url: - "wss://openbot-org.api.trytilde.ai/api/v1/team/openbot-team/chatkit/realtime?org_id=openbot-org", + "wss://dispatch-org.api.trytilde.ai/api/v1/team/dispatch-team/chatkit/realtime?org_id=dispatch-org", }); expect(upstreamUrl).toBe( - "https://openbot-org.api.trytilde.ai/api/v1/team/openbot-team/identity/openbot/chatkit-realtime-ticket", + "https://dispatch-org.api.trytilde.ai/api/v1/team/dispatch-team/identity/dispatch/chatkit-realtime-ticket", ); expect(upstreamHeaders.get("authorization")).toBe("Bearer browser-token"); - expect(upstreamHeaders.get("x-tilde-org-id")).toBe("openbot-org"); + expect(upstreamHeaders.get("x-tilde-org-id")).toBe("dispatch-org"); expect(upstreamHeaders.get("content-type")).toBe("application/json"); expect(JSON.parse(upstreamBody)).toEqual({ transport: "browser", - origin: "https://openbot.test", + origin: "https://dispatch.test", }); }); @@ -517,9 +522,9 @@ describe("bare OpenBot server", () => { authProvider: testAuthProvider(), tildeChatProxy: { apiKey: "secret-api-key", - orgId: "openbot-org", - teamId: "openbot-team", - baseUrl: "https://openbot-org.api.trytilde.ai", + orgId: "dispatch-org", + teamId: "dispatch-team", + baseUrl: "https://dispatch-org.api.trytilde.ai", fetch: async (_input, request) => { upstreamBody = typeof request?.body === "string" ? request.body : ""; return Response.json({ @@ -531,14 +536,17 @@ describe("bare OpenBot server", () => { }, }); - const response = await chatApp.request("https://openbot.test/api/chat/realtime/socket-ticket", { - method: "POST", - headers: { - authorization: "Bearer native-token", - "content-type": "application/json", + const response = await chatApp.request( + "https://dispatch.test/api/chat/realtime/socket-ticket", + { + method: "POST", + headers: { + authorization: "Bearer native-token", + "content-type": "application/json", + }, + body: JSON.stringify({ transport: "native" }), }, - body: JSON.stringify({ transport: "native" }), - }); + ); expect(response.status).toBe(200); expect(JSON.parse(upstreamBody)).toEqual({ transport: "native" }); @@ -550,9 +558,9 @@ describe("bare OpenBot server", () => { authProvider: testAuthProvider(), tildeChatProxy: { apiKey: "secret-api-key", - orgId: "openbot-org", - teamId: "openbot-team", - baseUrl: "https://openbot-org.api.trytilde.ai", + orgId: "dispatch-org", + teamId: "dispatch-team", + baseUrl: "https://dispatch-org.api.trytilde.ai", fetch: async (_input, request) => { upstreamBody = typeof request?.body === "string" ? request.body : ""; return Response.json({ @@ -564,20 +572,23 @@ describe("bare OpenBot server", () => { }, }); - const response = await chatApp.request("https://openbot.test/api/chat/realtime/socket-ticket", { - method: "POST", - headers: { - authorization: "Bearer injected-token", - origin: "https://openbot.test", - "content-type": "application/json", + const response = await chatApp.request( + "https://dispatch.test/api/chat/realtime/socket-ticket", + { + method: "POST", + headers: { + authorization: "Bearer injected-token", + origin: "https://dispatch.test", + "content-type": "application/json", + }, + body: JSON.stringify({ transport: "browser" }), }, - body: JSON.stringify({ transport: "browser" }), - }); + ); expect(response.status).toBe(200); expect(JSON.parse(upstreamBody)).toEqual({ transport: "browser", - origin: "https://openbot.test", + origin: "https://dispatch.test", }); }); @@ -586,23 +597,26 @@ describe("bare OpenBot server", () => { authProvider: testAuthProvider(), tildeChatProxy: { apiKey: "secret-api-key", - orgId: "openbot-org", - teamId: "openbot-team", + orgId: "dispatch-org", + teamId: "dispatch-team", fetch: async () => { throw new Error("native cookie request must not reach Tilde"); }, }, }); - const response = await chatApp.request("https://openbot.test/api/chat/realtime/socket-ticket", { - method: "POST", - headers: { - cookie: "openbot_access=browser-token", - origin: "https://openbot.test", - "content-type": "application/json", + const response = await chatApp.request( + "https://dispatch.test/api/chat/realtime/socket-ticket", + { + method: "POST", + headers: { + cookie: "dispatch_access=browser-token", + origin: "https://dispatch.test", + "content-type": "application/json", + }, + body: JSON.stringify({ transport: "native" }), }, - body: JSON.stringify({ transport: "native" }), - }); + ); expect(response.status).toBe(403); }); @@ -612,8 +626,8 @@ describe("bare OpenBot server", () => { const chatApp = createApp({ tildeChatProxy: { apiKey: "secret-api-key", - orgId: "openbot-org", - teamId: "openbot-team", + orgId: "dispatch-org", + teamId: "dispatch-team", fetch: async (_input, request) => { body = new Uint8Array(await new Response(request?.body).arrayBuffer()); return Response.json({ status: "uploaded" }); @@ -621,13 +635,13 @@ describe("bare OpenBot server", () => { }, }); const response = await chatApp.request( - "https://openbot.test/api/chat/session/session-one/attachment/attachment-one/content", + "https://dispatch.test/api/chat/session/session-one/attachment/attachment-one/content", { method: "PUT", body: new Uint8Array([0, 1, 2, 255]) }, ); expect(response.status).toBe(200); expect([...body]).toEqual([0, 1, 2, 255]); - const invalid = await chatApp.request("https://openbot.test/api/chat/session%5Ctool"); + const invalid = await chatApp.request("https://dispatch.test/api/chat/session%5Ctool"); expect(invalid.status).toBe(400); }); @@ -636,8 +650,8 @@ describe("bare OpenBot server", () => { const chatApp = createApp({ tildeChatProxy: { apiKey: "secret-api-key", - orgId: "openbot-org", - teamId: "openbot-team", + orgId: "dispatch-org", + teamId: "dispatch-team", fetch: async () => { upstreamCalls += 1; return new Response(null, { status: 204 }); @@ -645,7 +659,7 @@ describe("bare OpenBot server", () => { }, }); - const response = await chatApp.request("https://openbot.test/api/chat/agents/agent-one", { + const response = await chatApp.request("https://dispatch.test/api/chat/agents/agent-one", { method: "DELETE", }); @@ -661,8 +675,8 @@ describe("bare OpenBot server", () => { const chatApp = createApp({ tildeChatProxy: { apiKey: "secret-api-key", - orgId: "openbot-org", - teamId: "openbot-team", + orgId: "dispatch-org", + teamId: "dispatch-team", baseUrl: "https://tilde.test", fetch: async (input, request) => { const url = @@ -680,11 +694,11 @@ describe("bare OpenBot server", () => { ["DELETE", "sessions/session-one/participants/human-instance"], ]; for (const [method, path] of routes) { - const response = await chatApp.request(`https://openbot.test/api/chat/${path}`, { method }); + const response = await chatApp.request(`https://dispatch.test/api/chat/${path}`, { method }); expect(response.status).toBe(200); } expect(calls).toEqual( - routes.map(([method, path]) => [method, `/api/v1/team/openbot-team/chatkit/${path}`]), + routes.map(([method, path]) => [method, `/api/v1/team/dispatch-team/chatkit/${path}`]), ); }); @@ -693,8 +707,8 @@ describe("bare OpenBot server", () => { const chatApp = createApp({ tildeChatProxy: { apiKey: "secret-api-key", - orgId: "openbot-org", - teamId: "openbot-team", + orgId: "dispatch-org", + teamId: "dispatch-team", baseUrl: "https://tilde.test", fetch: async (input) => { calls.push( @@ -706,16 +720,16 @@ describe("bare OpenBot server", () => { }); const accepted = await chatApp.request( - "https://openbot.test/api/chat/_root/org/openbot-org/team/openbot-team/session/session-one/attachment/attachment-one/file.txt", + "https://dispatch.test/api/chat/_root/org/dispatch-org/team/dispatch-team/session/session-one/attachment/attachment-one/file.txt", { method: "PUT", body: "proof" }, ); expect(accepted.status).toBe(204); expect(calls).toEqual([ - "https://tilde.test/api/v1/chatkit/org/openbot-org/team/openbot-team/session/session-one/attachment/attachment-one/file.txt", + "https://tilde.test/api/v1/chatkit/org/dispatch-org/team/dispatch-team/session/session-one/attachment/attachment-one/file.txt", ]); const rejected = await chatApp.request( - "https://openbot.test/api/chat/_root/org/another-org/team/openbot-team/session/session-one/attachment/attachment-one/file.txt", + "https://dispatch.test/api/chat/_root/org/another-org/team/dispatch-team/session/session-one/attachment/attachment-one/file.txt", { method: "PUT", body: "proof" }, ); expect(rejected.status).toBe(400); @@ -728,8 +742,8 @@ describe("bare OpenBot server", () => { const chatApp = createApp({ tildeChatProxy: { apiKey: "secret-api-key", - orgId: "openbot-org", - teamId: "openbot-team", + orgId: "dispatch-org", + teamId: "dispatch-team", fetch: async (_input, request) => { uploaded = new Uint8Array(await new Response(request?.body).arrayBuffer()); uploadContentType = new Headers(request?.headers).get("content-type"); @@ -738,9 +752,9 @@ describe("bare OpenBot server", () => { }, }); const signedUrl = - "https://bucket.r2.cloudflarestorage.com/data/chatkit/org/openbot-org/team/openbot-team/session/session-one/file.txt?signature=private"; + "https://bucket.r2.cloudflarestorage.com/data/chatkit/org/dispatch-org/team/dispatch-team/session/session-one/file.txt?signature=private"; const accepted = await chatApp.request( - `https://openbot.test/api/chat/_upload?url=${encodeURIComponent(signedUrl)}`, + `https://dispatch.test/api/chat/_upload?url=${encodeURIComponent(signedUrl)}`, { method: "PUT", headers: { "content-type": "text/plain" }, body: "proof" }, ); expect(accepted.status).toBe(200); @@ -748,27 +762,27 @@ describe("bare OpenBot server", () => { expect(uploadContentType).toBe("text/plain"); const rejected = await chatApp.request( - `https://openbot.test/api/chat/_upload?url=${encodeURIComponent("https://evil.test/file")}`, + `https://dispatch.test/api/chat/_upload?url=${encodeURIComponent("https://evil.test/file")}`, { method: "PUT", body: "proof" }, ); expect(rejected.status).toBe(400); }); it("serves built web assets and SPA routes when a web root is available", async () => { - const webRoot = await mkdtemp(join(tmpdir(), "openbot-hono-web-")); + const webRoot = await mkdtemp(join(tmpdir(), "dispatch-hono-web-")); temporaryRoots.push(webRoot); await mkdir(join(webRoot, "assets")); - await writeFile(join(webRoot, "index.html"), "
OpenBot web
"); + await writeFile(join(webRoot, "index.html"), "
Dispatch web
"); await writeFile(join(webRoot, "assets", "app.js"), "export const ready = true;"); const webApp = createApp({ webRoot }); - const asset = await webApp.request("https://openbot.test/assets/app.js"); + const asset = await webApp.request("https://dispatch.test/assets/app.js"); expect(asset.status).toBe(200); expect(asset.headers.get("cache-control")).toBe("public, max-age=31536000, immutable"); - const frontendRoute = await webApp.request("https://openbot.test/api/setup/unlock"); + const frontendRoute = await webApp.request("https://dispatch.test/api/setup/unlock"); expect(frontendRoute.status).toBe(200); expect(frontendRoute.headers.get("cache-control")).toBe("no-cache"); - await expect(frontendRoute.text()).resolves.toBe("
OpenBot web
"); + await expect(frontendRoute.text()).resolves.toBe("
Dispatch web
"); }); }); diff --git a/apps/control-service/src/app.ts b/apps/control-service/src/app.ts index 59720f06..829bc08d 100644 --- a/apps/control-service/src/app.ts +++ b/apps/control-service/src/app.ts @@ -5,8 +5,8 @@ import { fileURLToPath } from "node:url"; import { serveStatic } from "@hono/node-server/serve-static"; import { Hono } from "hono"; import { secureHeaders } from "hono/secure-headers"; -import type { AuthProvider } from "@tryopenbot/auth-provider"; -import type { ComputerProvider } from "@tryopenbot/computer-service-provider"; +import type { AuthProvider } from "@trytilde/dispatch-auth-provider"; +import type { ComputerProvider } from "@trytilde/dispatch-computer-service-provider"; import { registerAgentCreation, type AgentCreationOptions } from "./agent-create.js"; import { registerTildeChatProxy, type TildeChatProxyOptions } from "./chat-proxy.js"; import { registerTildeProxy, type TildeProxyOptions } from "./tilde-proxy.js"; @@ -34,7 +34,7 @@ export function createApp(options: AppOptions = {}): Hono { const app = new Hono(); const webRoot = options.webRoot ?? defaultWebRoot; app.use("*", secureHeaders()); - app.get("/healthz", (context) => context.json({ ok: true, service: "openbot" })); + app.get("/healthz", (context) => context.json({ ok: true, service: "dispatch" })); if (options.authProvider) { registerOwnerAuth(app, options.authProvider, options); const middleware = requireOwner(options.authProvider, options); diff --git a/apps/control-service/src/auth.test.ts b/apps/control-service/src/auth.test.ts index 1ec5cc72..3b718edc 100644 --- a/apps/control-service/src/auth.test.ts +++ b/apps/control-service/src/auth.test.ts @@ -1,5 +1,5 @@ import { afterEach, describe, expect, it, vi } from "vite-plus/test"; -import type { AuthProvider } from "@tryopenbot/auth-provider"; +import type { AuthProvider } from "@trytilde/dispatch-auth-provider"; import { createApp } from "./app.js"; afterEach(() => vi.unstubAllEnvs()); @@ -7,7 +7,7 @@ afterEach(() => vi.unstubAllEnvs()); describe("owner authentication", () => { it("exposes public native OAuth metadata without credentials", async () => { const app = createApp({ authProvider: stubProvider(), webRoot: "/missing" }); - const response = await app.request("https://openbot.test/auth/native-config"); + const response = await app.request("https://dispatch.test/auth/native-config"); expect(response.status).toBe(200); expect(response.headers.get("cache-control")).toBe("no-store"); @@ -15,18 +15,18 @@ describe("owner authentication", () => { authorization_endpoint: "https://identity.test/authorize", token_endpoint: "https://identity.test/token", client_id: "client-one", - scope: "openid offline_access openbot:control", + scope: "openid offline_access dispatch:control", }); }); it("completes browser PKCE login and establishes host-only token cookies", async () => { const provider = stubProvider(); const app = createApp({ authProvider: provider, webRoot: "/missing" }); - const login = await app.request("https://openbot.test/auth/login"); + const login = await app.request("https://dispatch.test/auth/login"); expect(login.status).toBe(302); const authorizationInput = provider.authorizationUrl.mock.calls[0]?.[0]; expect(authorizationInput).toMatchObject({ - redirectUri: "https://openbot.test/auth/callback", + redirectUri: "https://dispatch.test/auth/callback", }); expect(authorizationInput?.state).toBeTruthy(); expect(authorizationInput?.codeChallenge).toBeTruthy(); @@ -34,20 +34,20 @@ describe("owner authentication", () => { const loginCookies = login.headers.getSetCookie(); const callbackCookie = loginCookies.map((cookie) => cookie.split(";", 1)[0]).join("; "); const callback = await app.request( - `https://openbot.test/auth/callback?code=code-one&state=${encodeURIComponent(authorizationInput?.state ?? "")}`, + `https://dispatch.test/auth/callback?code=code-one&state=${encodeURIComponent(authorizationInput?.state ?? "")}`, { headers: { cookie: callbackCookie } }, ); expect(callback.status).toBe(302); expect(provider.exchangeCode).toHaveBeenCalledWith({ code: "code-one", codeVerifier: expect.any(String), - redirectUri: "https://openbot.test/auth/callback", + redirectUri: "https://dispatch.test/auth/callback", }); const established = callback.headers.getSetCookie(); expect(established).toEqual( expect.arrayContaining([ - expect.stringContaining("openbot_access=fresh-token"), - expect.stringContaining("openbot_refresh=refresh-one"), + expect.stringContaining("dispatch_access=fresh-token"), + expect.stringContaining("dispatch_refresh=refresh-one"), ]), ); for (const cookie of established) { @@ -57,7 +57,7 @@ describe("owner authentication", () => { }); it("keeps the development callback on the browser origin", async () => { - vi.stubEnv("PUBLIC_ORIGIN", "https://our-ob-control.vercel.app"); + vi.stubEnv("PUBLIC_ORIGIN", "https://our-dispatch-control.vercel.app"); const provider = stubProvider(); const app = createApp({ authProvider: provider, devMode: true, webRoot: "/missing" }); @@ -76,20 +76,20 @@ describe("owner authentication", () => { }); it("uses the configured HTTPS origin for a matching remote development host", async () => { - vi.stubEnv("PUBLIC_ORIGIN", "https://our-openbot.exe.xyz"); + vi.stubEnv("PUBLIC_ORIGIN", "https://our-dispatch.exe.xyz"); const provider = stubProvider(); const app = createApp({ authProvider: provider, devMode: true, webRoot: "/missing" }); const login = await app.request("http://127.0.0.1:4100/auth/login", { headers: { - "x-forwarded-host": "our-openbot.exe.xyz", + "x-forwarded-host": "our-dispatch.exe.xyz", "x-forwarded-proto": "http", }, }); expect(login.status).toBe(302); expect(provider.authorizationUrl).toHaveBeenCalledWith( - expect.objectContaining({ redirectUri: "https://our-openbot.exe.xyz/auth/callback" }), + expect.objectContaining({ redirectUri: "https://our-dispatch.exe.xyz/auth/callback" }), ); for (const cookie of login.headers.getSetCookie()) expect(cookie).toContain("Secure"); }); @@ -114,15 +114,15 @@ describe("owner authentication", () => { const provider = stubProvider(); provider.verify.mockImplementation(async (token) => { if (token === "expired") throw new Error("expired"); - return { subject: "human-one", groups: [], scope: ["openbot:control"] }; + return { subject: "human-one", groups: [], scope: ["dispatch:control"] }; }); const app = createApp({ authProvider: provider, webRoot: "/missing" }); const response = await app.request("/auth/session", { - headers: { cookie: "openbot_access=expired; openbot_refresh=refresh-one" }, + headers: { cookie: "dispatch_access=expired; dispatch_refresh=refresh-one" }, }); expect(response.status).toBe(200); expect(provider.refresh).toHaveBeenCalledWith("refresh-one"); - expect(response.headers.get("set-cookie")).toContain("openbot_access=fresh-token"); + expect(response.headers.get("set-cookie")).toContain("dispatch_access=fresh-token"); }); it("returns account details supplied by the authentication provider", async () => { @@ -131,7 +131,7 @@ describe("owner authentication", () => { name: "Daniel Blignaut", email: "owner@example.com", organization: { id: "org-one", name: "Tilde", role: "owner" }, - workspace: { id: "team-one", name: "OpenBot", role: "owner" }, + workspace: { id: "team-one", name: "Dispatch", role: "owner" }, })); const app = createApp({ authProvider: provider, @@ -152,7 +152,7 @@ describe("owner authentication", () => { name: "Daniel Blignaut", email: "owner@example.com", organization: { id: "org-one", name: "Tilde", role: "owner" }, - workspace: { id: "team-one", name: "OpenBot", role: "owner" }, + workspace: { id: "team-one", name: "Dispatch", role: "owner" }, }, }); expect(provider.account).toHaveBeenCalledWith( @@ -163,22 +163,22 @@ describe("owner authentication", () => { it("requires a matching origin for unsafe cookie-authenticated requests", async () => { const app = createApp({ authProvider: stubProvider(), webRoot: "/missing" }); - const rejected = await app.request("https://openbot.test/api/computer/missing/preview", { + const rejected = await app.request("https://dispatch.test/api/computer/missing/preview", { method: "POST", - headers: { cookie: "openbot_access=valid-token" }, + headers: { cookie: "dispatch_access=valid-token" }, }); expect(rejected.status).toBe(403); - const accepted = await app.request("https://openbot.test/api/computer/missing/preview", { + const accepted = await app.request("https://dispatch.test/api/computer/missing/preview", { method: "POST", headers: { - cookie: "openbot_access=valid-token", - origin: "https://openbot.test", + cookie: "dispatch_access=valid-token", + origin: "https://dispatch.test", }, }); expect(accepted.status).toBe(404); - const bearer = await app.request("https://openbot.test/api/computer/missing/preview", { + const bearer = await app.request("https://dispatch.test/api/computer/missing/preview", { method: "POST", headers: { authorization: "Bearer valid-token" }, }); @@ -193,7 +193,7 @@ describe("owner authentication", () => { webRoot: "/missing", }); const headers = { - cookie: "openbot_access=valid-token", + cookie: "dispatch_access=valid-token", origin: "http://localhost:4173", "x-forwarded-host": "localhost:4173", "x-forwarded-proto": "http", @@ -216,13 +216,13 @@ describe("owner authentication", () => { const app = createApp({ authProvider: stubProvider(), devMode: true, - environment: { PUBLIC_ORIGIN: "https://our-openbot.exe.xyz" }, + environment: { PUBLIC_ORIGIN: "https://our-dispatch.exe.xyz" }, webRoot: "/missing", }); const headers = { - cookie: "openbot_access=valid-token", - origin: "https://our-openbot.exe.xyz", - "x-forwarded-host": "our-openbot.exe.xyz", + cookie: "dispatch_access=valid-token", + origin: "https://our-dispatch.exe.xyz", + "x-forwarded-host": "our-dispatch.exe.xyz", "x-forwarded-proto": "http", }; @@ -248,7 +248,7 @@ function stubProvider() { authorizationEndpoint: "https://identity.test/authorize", tokenEndpoint: "https://identity.test/token", clientId: "client-one", - scope: "openid offline_access openbot:control", + scope: "openid offline_access dispatch:control", }), authorizationUrl: vi.fn(() => new URL("https://identity.test/authorize")), exchangeCode: vi.fn(async () => ({ @@ -261,7 +261,7 @@ function stubProvider() { refreshToken: "refresh-one", expiresIn: 3600, })), - verify: vi.fn(async () => ({ subject: "human-one", groups: [], scope: ["openbot:control"] })), + verify: vi.fn(async () => ({ subject: "human-one", groups: [], scope: ["dispatch:control"] })), } as unknown as AuthProvider & { account: ReturnType | undefined; authorizationUrl: ReturnType; diff --git a/apps/control-service/src/auth.ts b/apps/control-service/src/auth.ts index a50b1b01..892fd0a3 100644 --- a/apps/control-service/src/auth.ts +++ b/apps/control-service/src/auth.ts @@ -6,7 +6,7 @@ import type { OAuthTokens, OwnerAccount, OwnerPrincipal, -} from "@tryopenbot/auth-provider"; +} from "@trytilde/dispatch-auth-provider"; declare module "hono" { interface ContextVariableMap { @@ -15,10 +15,10 @@ declare module "hono" { } } -const accessCookie = "openbot_access"; -const refreshCookie = "openbot_refresh"; -const stateCookie = "openbot_oauth_state"; -const verifierCookie = "openbot_oauth_verifier"; +const accessCookie = "dispatch_access"; +const refreshCookie = "dispatch_refresh"; +const stateCookie = "dispatch_oauth_state"; +const verifierCookie = "dispatch_oauth_verifier"; interface OwnerAuthOptions { devMode?: boolean; diff --git a/apps/control-service/src/capability-approvals.test.ts b/apps/control-service/src/capability-approvals.test.ts index 66cb3d61..4dc3553b 100644 --- a/apps/control-service/src/capability-approvals.test.ts +++ b/apps/control-service/src/capability-approvals.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it, vi } from "vite-plus/test"; -import type { AuthProvider } from "@tryopenbot/auth-provider"; +import type { AuthProvider } from "@trytilde/dispatch-auth-provider"; import { createApp } from "./app.js"; function testAuthProvider(): AuthProvider { @@ -10,12 +10,12 @@ function testAuthProvider(): AuthProvider { authorizationEndpoint: "https://identity.test/authorize", tokenEndpoint: "https://identity.test/token", clientId: "client-one", - scope: "openid offline_access openbot:control", + scope: "openid offline_access dispatch:control", }), authorizationUrl: () => new URL("https://identity.test/authorize"), exchangeCode: async () => ({ accessToken: "human-token", expiresIn: 3600 }), refresh: async () => ({ accessToken: "human-token", expiresIn: 3600 }), - verify: async () => ({ subject: "owner-one", groups: [], scope: ["openbot:control"] }), + verify: async () => ({ subject: "owner-one", groups: [], scope: ["dispatch:control"] }), } as unknown as AuthProvider; } @@ -66,7 +66,7 @@ describe("capability approval proxy", () => { }, }); const response = await app.request( - "https://openbot.test/api/capability-approvals/proposal-a/decision", + "https://dispatch.test/api/capability-approvals/proposal-a/decision", { method: "POST", headers: { authorization: "Bearer human-token", "content-type": "application/json" }, @@ -121,7 +121,7 @@ describe("capability approval proxy", () => { }, }); const response = await app.request( - "https://openbot.test/api/capability-approvals/proposal-a/decision", + "https://dispatch.test/api/capability-approvals/proposal-a/decision", { method: "POST", headers: { "content-type": "application/json" }, @@ -153,7 +153,7 @@ describe("capability approval proxy", () => { }, }); const response = await app.request( - "https://openbot.test/api/capability-approvals/proposal-a/decision", + "https://dispatch.test/api/capability-approvals/proposal-a/decision", { method: "POST", headers: { authorization: "Bearer human-token", "content-type": "application/json" }, @@ -207,9 +207,12 @@ describe("capability approval proxy", () => { fetch: upstream as typeof fetch, }, }); - const response = await app.request("https://openbot.test/api/capability-approvals/proposal-a", { - headers: { authorization: "Bearer human-token" }, - }); + const response = await app.request( + "https://dispatch.test/api/capability-approvals/proposal-a", + { + headers: { authorization: "Bearer human-token" }, + }, + ); expect(response.status).toBe(200); await expect(response.json()).resolves.toMatchObject({ id: "proposal-a", status: "executed" }); }); @@ -249,9 +252,12 @@ describe("capability approval proxy", () => { ), }, }); - const response = await app.request("https://openbot.test/api/capability-approvals/proposal-a", { - headers: { authorization: "Bearer human-token" }, - }); + const response = await app.request( + "https://dispatch.test/api/capability-approvals/proposal-a", + { + headers: { authorization: "Bearer human-token" }, + }, + ); expect(response.status).toBe(502); await expect(response.json()).resolves.toEqual({ error: "Invalid capability response" }); }); diff --git a/apps/control-service/src/chat-proxy.ts b/apps/control-service/src/chat-proxy.ts index 0fe2283f..4d63a6a9 100644 --- a/apps/control-service/src/chat-proxy.ts +++ b/apps/control-service/src/chat-proxy.ts @@ -88,7 +88,7 @@ export interface TildeChatProxyOptions { /** * Temporary same-origin bridge for Tilde ChatKit. It intentionally preserves * raw request bodies, response bodies, and SSE streams instead of projecting - * them into OpenBot's narrower control RPC contract. + * them into Dispatch's narrower control RPC contract. */ export function registerTildeChatProxy(app: Hono, configuredOptions?: TildeChatProxyOptions): void { app.post("/api/chat/realtime/socket-ticket", async (context) => { @@ -113,7 +113,7 @@ export function registerTildeChatProxy(app: Hono, configuredOptions?: TildeChatP if (transport === "browser" && !validHttpOrigin(origin)) return context.json({ error: "Browser socket tickets require an HTTP Origin" }, 403); const ticketUrl = new URL( - `/api/v1/team/${encodeURIComponent(options.teamId)}/identity/openbot/chatkit-realtime-ticket`, + `/api/v1/team/${encodeURIComponent(options.teamId)}/identity/dispatch/chatkit-realtime-ticket`, baseUrl, ); const upstream = await (options.fetch ?? globalThis.fetch)(ticketUrl, { @@ -196,7 +196,7 @@ export function registerTildeChatProxy(app: Hono, configuredOptions?: TildeChatP } catch (error) { if (context.req.raw.signal.aborted) throw error; console.error( - "[openbot-chat-proxy] upstream request threw", + "[dispatch-chat-proxy] upstream request threw", { elapsedMs: Date.now() - startedAt, method: context.req.method, @@ -249,7 +249,7 @@ async function logUpstreamFailure( } catch { // Preserve the upstream response even when its diagnostic clone cannot be consumed. } - console.error("[openbot-chat-proxy] upstream request failed", { + console.error("[dispatch-chat-proxy] upstream request failed", { elapsedMs: Date.now() - startedAt, method: context.req.method, path, diff --git a/apps/control-service/src/computer-preview.ts b/apps/control-service/src/computer-preview.ts index 1e72d1ec..91009c11 100644 --- a/apps/control-service/src/computer-preview.ts +++ b/apps/control-service/src/computer-preview.ts @@ -3,7 +3,7 @@ import type { Hono } from "hono"; import { ComputerProviderError, type ComputerProvider, -} from "@tryopenbot/computer-service-provider"; +} from "@trytilde/dispatch-computer-service-provider"; export interface ComputerPreviewOptions { devMode?: boolean; @@ -26,7 +26,7 @@ export function registerComputerPreview( ? requestedTraceId : randomUUID(); const startedAt = Date.now(); - console.info("[openbot-vnc] preview requested", { agentId, requestId }); + console.info("[dispatch-vnc] preview requested", { agentId, requestId }); try { const endpoint = await provider.previewAgentDesktop(agentId, { requestId, @@ -34,7 +34,7 @@ export function registerComputerPreview( ...(options.environment ? { environment: options.environment } : {}), signal: context.req.raw.signal, }); - console.info("[openbot-vnc] preview redirect ready", { + console.info("[dispatch-vnc] preview redirect ready", { agentId, elapsedMs: Date.now() - startedAt, endpointOrigin: endpoint.url.origin, @@ -45,11 +45,11 @@ export function registerComputerPreview( const response = context.redirect(endpoint.url.toString(), 307); response.headers.set("cache-control", "no-store"); response.headers.set("referrer-policy", "no-referrer"); - response.headers.set("x-openbot-vnc-trace-id", requestId); + response.headers.set("x-dispatch-vnc-trace-id", requestId); return response; } catch (error) { if (context.req.raw.signal.aborted) { - console.info("[openbot-vnc] preview request aborted", { + console.info("[dispatch-vnc] preview request aborted", { agentId, elapsedMs: Date.now() - startedAt, requestId, @@ -57,7 +57,7 @@ export function registerComputerPreview( return new Response(null, { status: 499 }); } console.error( - "[openbot-vnc] preview request failed", + "[dispatch-vnc] preview request failed", { agentId, elapsedMs: Date.now() - startedAt, requestId }, error instanceof Error ? error : new Error(String(error)), ); diff --git a/apps/control-service/src/connector-authorized.ts b/apps/control-service/src/connector-authorized.ts index ea29a1df..2fafc997 100644 --- a/apps/control-service/src/connector-authorized.ts +++ b/apps/control-service/src/connector-authorized.ts @@ -14,14 +14,14 @@ export function registerConnectorAuthorizedRoute(app: Hono): void { function connectorAuthorizedPage(client: "electron" | "mobile" | "web"): string { const deepLinked = client === "electron" || client === "mobile"; const hint = deepLinked - ? "Returning you to OpenBot… If nothing happens, switch back to the OpenBot app." - : "You can close this tab and return to OpenBot."; + ? "Returning you to Dispatch… If nothing happens, switch back to the Dispatch app." + : "You can close this tab and return to Dispatch."; const redirect = deepLinked - ? '' + ? '' : ""; return [ "", - 'OpenBot', + 'Dispatch', "", "
", "

Authorization complete

", diff --git a/apps/control-service/src/service.ts b/apps/control-service/src/service.ts index 0e092b13..d072951e 100644 --- a/apps/control-service/src/service.ts +++ b/apps/control-service/src/service.ts @@ -6,5 +6,5 @@ if (!Number.isSafeInteger(port) || port < 1 || port > 65_535) throw new Error("PORT must be a valid TCP port"); serve({ fetch: app.fetch, port, hostname: "127.0.0.1" }, () => { - console.log(`OpenBot control service listening at http://127.0.0.1:${port}`); + console.log(`Dispatch control service listening at http://127.0.0.1:${port}`); }); diff --git a/apps/control-service/src/tilde-proxy.ts b/apps/control-service/src/tilde-proxy.ts index ca796b22..c4e02e2c 100644 --- a/apps/control-service/src/tilde-proxy.ts +++ b/apps/control-service/src/tilde-proxy.ts @@ -25,7 +25,7 @@ interface AllowedRoute { const methods = (...values: AllowedMethod[]): ReadonlySet => new Set(values); /** - * Owner-facing Tilde resources that OpenBot renders but does not own. This is + * Owner-facing Tilde resources that Dispatch renders but does not own. This is * deliberately an operation allowlist rather than an unrestricted API proxy. */ const allowedRoutes: readonly AllowedRoute[] = [ diff --git a/apps/control-service/test/e2e-server.ts b/apps/control-service/test/e2e-server.ts index 48659a54..4234ba91 100644 --- a/apps/control-service/test/e2e-server.ts +++ b/apps/control-service/test/e2e-server.ts @@ -1,8 +1,8 @@ import { serve } from "@hono/node-server"; -import type { AuthProvider } from "@tryopenbot/auth-provider"; +import type { AuthProvider } from "@trytilde/dispatch-auth-provider"; import { createApp } from "../src/app.js"; -const controlPort = Number(process.env.OPENBOT_E2E_CONTROL_PORT || "4100"); +const controlPort = Number(process.env.DISPATCH_E2E_CONTROL_PORT || "4100"); const computerApiKey = "e2e-computer-service-api-key-000000"; const agentSetupJobId = "33333333-3333-4333-8333-333333333333"; let agentSetupChecks = 0; @@ -12,7 +12,7 @@ const authProvider: AuthProvider = { authorizationEndpoint: "https://identity.test/authorize", tokenEndpoint: "https://identity.test/token", clientId: "e2e-client", - scope: "openid openbot:control", + scope: "openid dispatch:control", }), authorizationUrl: ({ redirectUri }) => { const url = new URL("https://identity.test/authorize"); @@ -31,14 +31,14 @@ const authProvider: AuthProvider = { subject: "e2e-owner", email: "owner@example.com", groups: ["e2e-team-member"], - scope: ["openbot:control"], + scope: ["dispatch:control"], }; }, account: async () => ({ name: "Daniel Blignaut", email: "owner@example.com", organization: { id: "org-one", name: "Tilde", role: "owner" }, - workspace: { id: "team-one", name: "OpenBot", role: "owner" }, + workspace: { id: "team-one", name: "Dispatch", role: "owner" }, }), }; @@ -55,7 +55,7 @@ const app = createApp({ if (options.authorization !== `Bearer ${computerApiKey}`) return { exitCode: 1, stdout: "", stderr: "Computer service API key required" }; const script = request.arguments.at(-1) ?? ""; - if (!script.includes("source /workspace/.openbot/development/profile.sh")) + if (!script.includes("source /workspace/.dispatch/development/profile.sh")) return { exitCode: 1, stdout: "", diff --git a/apps/desktop/README.md b/apps/desktop/README.md index 7c468d81..ab1606a6 100644 --- a/apps/desktop/README.md +++ b/apps/desktop/README.md @@ -1,7 +1,7 @@ -# @tryopenbot/desktop +# @trytilde/dispatch-desktop -The Electron desktop shell for the OpenBot web UI and local control service. Privileged Node.js behavior remains in Electron main/preload code behind a narrow bridge; the renderer stays browser-compatible. +The Electron desktop shell for the Dispatch web UI and local control service. Privileged Node.js behavior remains in Electron main/preload code behind a narrow bridge; the renderer stays browser-compatible. ## Public API -This package is an Electron application and declares no importable package exports. It loads the same-origin web surface, proxies control routes to `CONTROL_ORIGIN` or the CLI development default at `http://127.0.0.1:4100`, and exposes only the preload bridge required by that UI. It never starts control service; `openbot dev` or a separate deployment owns that process. +This package is an Electron application and declares no importable package exports. It loads the same-origin web surface, proxies control routes to `CONTROL_ORIGIN` or the CLI development default at `http://127.0.0.1:4100`, and exposes only the preload bridge required by that UI. It never starts control service; `tilde dev` or a separate deployment owns that process. diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 8008f9d7..c094b665 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -1,10 +1,10 @@ { - "name": "@tryopenbot/desktop", + "name": "@trytilde/dispatch-desktop", "version": "0.1.0", - "description": "OpenBot desktop client", + "description": "Dispatch desktop client", "license": "MIT", "author": { - "name": "OpenBot contributors", + "name": "Dispatch contributors", "email": "opensource@trytilde.ai" }, "repository": "https://github.com/trytilde/dispatch", @@ -23,17 +23,17 @@ "check": "vp check", "dev": "vp run build && electron .", "lint": "vp lint", - "package": "vp run --filter \"@tryopenbot/web...\" build && vp run build && node scripts/package-current.mjs", - "package:linux": "vp run --filter \"@tryopenbot/web...\" build && vp run build && electron-builder --linux", - "package:mac": "vp run --filter \"@tryopenbot/web...\" build && vp run build && electron-builder --mac", + "package": "vp run --filter \"@trytilde/dispatch-web...\" build && vp run build && node scripts/package-current.mjs", + "package:linux": "vp run --filter \"@trytilde/dispatch-web...\" build && vp run build && electron-builder --linux", + "package:mac": "vp run --filter \"@trytilde/dispatch-web...\" build && vp run build && electron-builder --mac", "prepack": "pnpm build", - "release:linux": "vp run --filter \"@tryopenbot/web...\" build && vp run build && electron-builder --linux --x64 --publish never", - "release:mac": "vp run --filter \"@tryopenbot/web...\" build && vp run build && electron-builder --mac --arm64 --publish never", + "release:linux": "vp run --filter \"@trytilde/dispatch-web...\" build && vp run build && electron-builder --linux --x64 --publish never", + "release:mac": "vp run --filter \"@trytilde/dispatch-web...\" build && vp run build && electron-builder --mac --arm64 --publish never", "test": "vp test run --passWithNoTests", "typecheck": "tsc --noEmit" }, "dependencies": { - "@tryopenbot/client-runtime": "workspace:*" + "@trytilde/dispatch-client-runtime": "workspace:*" }, "devDependencies": { "@types/node": "24.3.0", @@ -46,17 +46,17 @@ "vite-plus": "catalog:" }, "build": { - "appId": "ai.trytilde.openbot", - "productName": "OpenBot", + "appId": "ai.trytilde.dispatch", + "productName": "Dispatch", "protocols": [ { - "name": "OpenBot", + "name": "Dispatch", "schemes": [ - "openbot" + "dispatch" ] } ], - "executableName": "openbot", + "executableName": "dispatch", "icon": "build/icon.png", "directories": { "output": "out" @@ -94,10 +94,10 @@ "publish": [ { "provider": "generic", - "url": "${env.OPENBOT_DESKTOP_UPDATES_URL}", + "url": "${env.DISPATCH_DESKTOP_UPDATES_URL}", "channel": "latest" } ] }, - "desktopName": "OpenBot.desktop" + "desktopName": "Dispatch.desktop" } diff --git a/apps/desktop/scripts/package-current.mjs b/apps/desktop/scripts/package-current.mjs index 7ea6a559..fe0bcf1f 100644 --- a/apps/desktop/scripts/package-current.mjs +++ b/apps/desktop/scripts/package-current.mjs @@ -3,7 +3,7 @@ import { spawnSync } from "node:child_process"; const target = process.platform === "darwin" ? "--mac" : process.platform === "linux" ? "--linux" : undefined; if (!target) { - process.stderr.write("OpenBot desktop packaging supports macOS and Linux only.\n"); + process.stderr.write("Dispatch desktop packaging supports macOS and Linux only.\n"); process.exit(1); } @@ -12,12 +12,12 @@ const executable = process.platform === "win32" ? "electron-builder.cmd" : "elec // no bucket, so point it somewhere obviously local rather than leaving it empty. const env = { ...process.env, - OPENBOT_DESKTOP_UPDATES_URL: - process.env.OPENBOT_DESKTOP_UPDATES_URL ?? "http://127.0.0.1/desktop", + DISPATCH_DESKTOP_UPDATES_URL: + process.env.DISPATCH_DESKTOP_UPDATES_URL ?? "http://127.0.0.1/desktop", }; // appId has to be a command-line override: electron-builder strips ${env.*} macros out of // that field. package.json carries the official default, so this only differs for a fork. -const appId = process.env.OPENBOT_APP_ID?.trim(); +const appId = process.env.DISPATCH_APP_ID?.trim(); const args = appId ? [target, `-c.appId=${appId}`] : [target]; const result = spawnSync(executable, args, { stdio: "inherit", shell: false, env }); if (result.error) throw result.error; diff --git a/apps/desktop/src/auth.test.ts b/apps/desktop/src/auth.test.ts index 6dd128aa..dc3e0ae8 100644 --- a/apps/desktop/src/auth.test.ts +++ b/apps/desktop/src/auth.test.ts @@ -60,12 +60,12 @@ describe("DesktopAuth", () => { const auth = new DesktopAuth(path, controlOrigin); await auth.load(); - await expect(auth.status("https://openbot.example")).resolves.toEqual({ + await expect(auth.status("https://dispatch.example")).resolves.toEqual({ authenticated: true, user: { subject: "user-1", name: "Owner", email: "owner@example.com" }, }); expect(request).toHaveBeenCalledWith( - new URL("https://openbot.example/auth/session"), + new URL("https://dispatch.example/auth/session"), expect.any(Object), ); }); @@ -79,7 +79,7 @@ describe("DesktopAuth", () => { const auth = new DesktopAuth(path, controlOrigin); await auth.load(); - await expect(auth.status("https://openbot.example")).resolves.toBeNull(); + await expect(auth.status("https://dispatch.example")).resolves.toBeNull(); await expect(readFile(path)).rejects.toMatchObject({ code: "ENOENT" }); }); @@ -153,7 +153,7 @@ function requestUrl(input: URL | RequestInfo): string { } async function storedCredentials(expiresIn = 3600): Promise { - const root = await mkdtemp(join(tmpdir(), "openbot-desktop-auth-")); + const root = await mkdtemp(join(tmpdir(), "dispatch-desktop-auth-")); cleanups.push(async () => rm(root, { recursive: true, force: true })); const path = join(root, "auth.enc"); await writeFile( diff --git a/apps/desktop/src/auth.ts b/apps/desktop/src/auth.ts index 0c10a232..47370692 100644 --- a/apps/desktop/src/auth.ts +++ b/apps/desktop/src/auth.ts @@ -5,11 +5,11 @@ import { safeStorage, shell } from "electron"; import { AuthenticatedSessionSchema, type AuthenticatedSession, -} from "@tryopenbot/client-runtime/contracts/auth"; +} from "@trytilde/dispatch-client-runtime/contracts/auth"; import { NativeAuthConfigurationSchema, type NativeAuthConfiguration, -} from "@tryopenbot/client-runtime/contracts/installation"; +} from "@trytilde/dispatch-client-runtime/contracts/installation"; interface StoredTokens { accessToken: string; @@ -42,7 +42,7 @@ export class DesktopAuth { signal: AbortSignal.timeout(10_000), }); if (!response.ok) - throw new Error(`OpenBot authentication is not configured (${response.status})`); + throw new Error(`Dispatch authentication is not configured (${response.status})`); return NativeAuthConfigurationSchema.parse(await response.json()); })(); try { @@ -71,7 +71,7 @@ export class DesktopAuth { const configuration = await this.#nativeConfiguration(); const url = new URL(configuration.authorization_endpoint); url.searchParams.set("client_id", configuration.client_id); - url.searchParams.set("redirect_uri", "openbot://auth/callback"); + url.searchParams.set("redirect_uri", "dispatch://auth/callback"); url.searchParams.set("response_type", "code"); url.searchParams.set("scope", configuration.scope); url.searchParams.set("state", state); @@ -89,7 +89,7 @@ export class DesktopAuth { async handleCallback(value: string): Promise { const url = new URL(value); - if (url.protocol !== "openbot:" || url.host !== "auth" || url.pathname !== "/callback") + if (url.protocol !== "dispatch:" || url.host !== "auth" || url.pathname !== "/callback") return false; const pending = this.#pending; if (!pending) return true; @@ -102,7 +102,7 @@ export class DesktopAuth { grant_type: "authorization_code", code, code_verifier: pending.verifier, - redirect_uri: "openbot://auth/callback", + redirect_uri: "dispatch://auth/callback", }); if (!tokens.refresh_token) throw new Error("OIDC response did not include a refresh token"); this.#tokens = { accessToken: tokens.access_token, refreshToken: tokens.refresh_token }; diff --git a/apps/desktop/src/local-server.test.ts b/apps/desktop/src/local-server.test.ts index 4f7fb3a6..a0c90a90 100644 --- a/apps/desktop/src/local-server.test.ts +++ b/apps/desktop/src/local-server.test.ts @@ -12,12 +12,12 @@ afterEach(async () => { describe("Electron renderer server", () => { it("serves SPA fallbacks and streams control requests with loopback cookies", async () => { - const staticRoot = await mkdtemp(join(tmpdir(), "openbot-electron-web-")); - await writeFile(join(staticRoot, "index.html"), "
OpenBot renderer
"); + const staticRoot = await mkdtemp(join(tmpdir(), "dispatch-electron-web-")); + await writeFile(join(staticRoot, "index.html"), "
Dispatch renderer
"); const upstream = createServer((request, response) => { response.setHeader( "set-cookie", - "openbot_session=example; HttpOnly; Secure; SameSite=Strict", + "dispatch_session=example; HttpOnly; Secure; SameSite=Strict", ); response.end( `${request.url}:${request.headers.cookie ?? "none"}:${request.headers.authorization ?? "none"}`, @@ -31,7 +31,7 @@ describe("Electron renderer server", () => { `http://127.0.0.1:${address.port}`, { accessToken: async () => "desktop-token", - tildeBaseUrl: "https://openbot-org.api.trytilde.ai/path-is-ignored", + tildeBaseUrl: "https://dispatch-org.api.trytilde.ai/path-is-ignored", }, ); cleanups.push(async () => renderer.close()); @@ -41,9 +41,9 @@ describe("Electron renderer server", () => { cleanups.push(async () => rm(staticRoot, { recursive: true, force: true })); const rendered = await fetch(`${renderer.origin}/agents/one`); - expect(await rendered.text()).toContain("OpenBot renderer"); + expect(await rendered.text()).toContain("Dispatch renderer"); expect(rendered.headers.get("content-security-policy")).toContain( - "connect-src 'self' wss://openbot-org.api.trytilde.ai", + "connect-src 'self' wss://dispatch-org.api.trytilde.ai", ); const proxied = await fetch(`${renderer.origin}/healthz`, { headers: { cookie: "client=value" }, diff --git a/apps/desktop/src/local-server.ts b/apps/desktop/src/local-server.ts index 70520b81..8c6e1320 100644 --- a/apps/desktop/src/local-server.ts +++ b/apps/desktop/src/local-server.ts @@ -44,7 +44,7 @@ export async function startRendererServer( if (response.headersSent) response.destroy(error instanceof Error ? error : undefined); else { response.writeHead(502, { "content-type": "application/json; charset=utf-8" }); - response.end(JSON.stringify({ error: "The OpenBot control server is unavailable." })); + response.end(JSON.stringify({ error: "The Dispatch control server is unavailable." })); } }); }); @@ -69,7 +69,7 @@ async function handleRequest( tildeSocketOrigin: string, options: RendererServerOptions, ): Promise { - const url = new URL(request.url ?? "/", "http://openbot.local"); + const url = new URL(request.url ?? "/", "http://dispatch.local"); if (isControlPath(url.pathname)) { await proxyRequest( request, diff --git a/apps/desktop/src/main.ts b/apps/desktop/src/main.ts index 51274d71..5a819bd9 100644 --- a/apps/desktop/src/main.ts +++ b/apps/desktop/src/main.ts @@ -4,7 +4,7 @@ import { startRendererServer, type RendererServer } from "./local-server.js"; import { DesktopAuth } from "./auth.js"; if (process.platform === "win32") - throw new Error("OpenBot Desktop currently supports macOS and Linux"); + throw new Error("Dispatch Desktop currently supports macOS and Linux"); // A packaged build takes its mark from the app bundle, but an unpackaged run would otherwise // show the stock Electron icon. build/icon.png is not shipped in the package, so resolve it @@ -19,13 +19,13 @@ let desktopAuth: DesktopAuth | undefined; const pendingProtocolUrls: string[] = []; if (!app.requestSingleInstanceLock()) app.quit(); -app.setAsDefaultProtocolClient("openbot"); +app.setAsDefaultProtocolClient("dispatch"); app.on("open-url", (event, url) => { event.preventDefault(); void handleProtocolUrl(url); }); app.on("second-instance", (_event, argv) => { - const url = argv.find((value) => value.startsWith("openbot://")); + const url = argv.find((value) => value.startsWith("dispatch://")); if (url) void handleProtocolUrl(url); window?.show(); window?.focus(); @@ -67,7 +67,7 @@ async function createWindow(): Promise { } async function main(): Promise { - ipcMain.handle("openbot:open-external", async (_event, value: unknown) => { + ipcMain.handle("dispatch:open-external", async (_event, value: unknown) => { if (typeof value !== "string") throw new Error("A URL is required"); const url = new URL(value); if (url.protocol !== "https:" && url.protocol !== "http:") @@ -80,9 +80,9 @@ async function main(): Promise { if (developmentIcon && process.platform === "darwin") app.dock?.setIcon(developmentIcon); desktopAuth = new DesktopAuth(join(app.getPath("userData"), "auth.enc"), controlOrigin); await desktopAuth.load(); - ipcMain.handle("openbot:auth-status", () => desktopAuth!.status()); - ipcMain.handle("openbot:sign-in", () => desktopAuth!.signIn()); - ipcMain.handle("openbot:sign-out", () => desktopAuth!.signOut()); + ipcMain.handle("dispatch:auth-status", () => desktopAuth!.status()); + ipcMain.handle("dispatch:sign-in", () => desktopAuth!.signIn()); + ipcMain.handle("dispatch:sign-out", () => desktopAuth!.signOut()); for (const url of pendingProtocolUrls.splice(0)) await desktopAuth.handleCallback(url); await createWindow(); app.on("activate", () => { @@ -107,6 +107,6 @@ async function handleProtocolUrl(url: string): Promise { } void main().catch((error: unknown) => { - console.error("OpenBot Desktop failed to start", error); + console.error("Dispatch Desktop failed to start", error); app.quit(); }); diff --git a/apps/desktop/src/preload.ts b/apps/desktop/src/preload.ts index f330dd4f..d4cd146d 100644 --- a/apps/desktop/src/preload.ts +++ b/apps/desktop/src/preload.ts @@ -1,15 +1,15 @@ import { contextBridge, ipcRenderer } from "electron"; -import type { DesktopClientBridge } from "@tryopenbot/client-runtime/contracts/platform"; +import type { DesktopClientBridge } from "@trytilde/dispatch-client-runtime/contracts/platform"; const bridge = { platform: process.platform === "darwin" ? "mac" : "linux", controlOrigin: process.env.CONTROL_ORIGIN ?? "", async openExternal(value: string): Promise { - await ipcRenderer.invoke("openbot:open-external", value); + await ipcRenderer.invoke("dispatch:open-external", value); }, - authStatus: () => ipcRenderer.invoke("openbot:auth-status"), - signIn: () => ipcRenderer.invoke("openbot:sign-in"), - signOut: () => ipcRenderer.invoke("openbot:sign-out"), + authStatus: () => ipcRenderer.invoke("dispatch:auth-status"), + signIn: () => ipcRenderer.invoke("dispatch:sign-in"), + signOut: () => ipcRenderer.invoke("dispatch:sign-out"), } as const satisfies DesktopClientBridge; -contextBridge.exposeInMainWorld("openbotDesktop", bridge); +contextBridge.exposeInMainWorld("dispatchDesktop", bridge); diff --git a/apps/desktop/tsdown.config.ts b/apps/desktop/tsdown.config.ts index d3209a8c..295447f2 100644 --- a/apps/desktop/tsdown.config.ts +++ b/apps/desktop/tsdown.config.ts @@ -9,7 +9,7 @@ export default defineConfig({ sourcemap: true, // The Electron main bundle is CJS, but the workspace runtime is ESM-only by its exports // conditions, so it must be bundled rather than required at runtime. - deps: { neverBundle: ["electron"], alwaysBundle: [/^@tryopenbot\//] }, + deps: { neverBundle: ["electron"], alwaysBundle: [/^@trytilde\/dispatch-/] }, outputOptions: { entryFileNames: "[name].cjs", sourcemapExcludeSources: true, diff --git a/apps/web/README.md b/apps/web/README.md index fd19a92b..d5e991ed 100644 --- a/apps/web/README.md +++ b/apps/web/README.md @@ -1,6 +1,6 @@ -# @tryopenbot/web +# @trytilde/dispatch-web -The React 19 and Vite owner interface for OpenBot. It uses TanStack Router and is served by the control service locally or by the runtime provider's static CDN artifact on Vercel. +The React 19 and Vite owner interface for Dispatch. It uses TanStack Router and is served by the control service locally or by the runtime provider's static CDN artifact on Vercel. ## Public API diff --git a/apps/web/index.html b/apps/web/index.html index f3a1dbd3..e333828c 100644 --- a/apps/web/index.html +++ b/apps/web/index.html @@ -5,7 +5,7 @@ - OpenBot + Dispatch
diff --git a/apps/web/package.json b/apps/web/package.json index 5d2b83a5..8b1c8e1d 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -1,5 +1,5 @@ { - "name": "@tryopenbot/web", + "name": "@trytilde/dispatch-web", "version": "0.1.0", "files": [ "dist", @@ -20,8 +20,8 @@ }, "dependencies": { "@tanstack/react-router": "1.170.27", - "@tryopenbot/client-runtime": "workspace:*", - "@tryopenbot/ui": "workspace:*", + "@trytilde/dispatch-client-runtime": "workspace:*", + "@trytilde/dispatch-ui": "workspace:*", "motion": "^13.1.0", "react": "19.1.2", "react-dom": "19.1.2", diff --git a/apps/web/src/auth-gate.tsx b/apps/web/src/auth-gate.tsx index 255c9336..45edbf86 100644 --- a/apps/web/src/auth-gate.tsx +++ b/apps/web/src/auth-gate.tsx @@ -3,15 +3,15 @@ import { Onboarding, WorkspaceAccessScreen, type OnboardingResult, -} from "@tryopenbot/ui"; +} from "@trytilde/dispatch-ui"; import { completeOnboarding, loadOnboarding, type OnboardingStorage, -} from "@tryopenbot/client-runtime"; +} from "@trytilde/dispatch-client-runtime"; import { type ReactNode, useEffect, useState } from "react"; import { useStore } from "zustand"; -import { openBotRuntime } from "./runtime.js"; +import { dispatchRuntime } from "./runtime.js"; import { useClientWorkspace } from "./workspaces.js"; // Onboarding state is owned by the client runtime per ADR-0017; the browser only @@ -48,7 +48,7 @@ export function AuthGate({ children: ReactNode; skipOnboarding?: boolean; }) { - const auth = useStore(openBotRuntime.store, (state) => state.auth); + const auth = useStore(dispatchRuntime.store, (state) => state.auth); const workspace = useClientWorkspace(); const [signingIn, setSigningIn] = useState(false); const [seen, setSeen] = useState(skipOnboarding ? true : undefined); @@ -56,7 +56,7 @@ export function AuthGate({ // Settings only need authenticated agent navigation. The workspace upgrades this // initialization to include conversations, previews, and the team event stream. useEffect(() => { - void openBotRuntime.actions.initialize({ + void dispatchRuntime.actions.initialize({ workspace: !window.location.pathname.startsWith("/settings"), }); }, []); @@ -79,7 +79,7 @@ export function AuthGate({ signingIn={signingIn} onSignIn={() => { setSigningIn(true); - void openBotRuntime.actions + void dispatchRuntime.actions .signIn({ workspace: !window.location.pathname.startsWith("/settings") }) .catch(() => undefined) .finally(() => setSigningIn(false)); @@ -97,7 +97,7 @@ export function AuthGate({ onCancelSignIn={() => setSigningIn(false)} onSignIn={() => { setSigningIn(true); - void openBotRuntime.actions + void dispatchRuntime.actions .signIn() .catch(() => undefined) .finally(() => setSigningIn(false)); diff --git a/apps/web/src/desktop.d.ts b/apps/web/src/desktop.d.ts index 9d7ac05d..bb09c99e 100644 --- a/apps/web/src/desktop.d.ts +++ b/apps/web/src/desktop.d.ts @@ -1,8 +1,8 @@ -import type { DesktopClientBridge } from "@tryopenbot/client-runtime/contracts/platform"; +import type { DesktopClientBridge } from "@trytilde/dispatch-client-runtime/contracts/platform"; declare global { interface Window { - openbotDesktop?: DesktopClientBridge; + dispatchDesktop?: DesktopClientBridge; } } diff --git a/apps/web/src/main.tsx b/apps/web/src/main.tsx index 5cfea87c..b9c52bb0 100644 --- a/apps/web/src/main.tsx +++ b/apps/web/src/main.tsx @@ -1,8 +1,8 @@ import { StrictMode } from "react"; import { createRoot } from "react-dom/client"; import { RouterProvider } from "@tanstack/react-router"; -import "@tryopenbot/ui/openbot-ui.css"; -import { initTheme } from "@tryopenbot/ui"; +import "@trytilde/dispatch-ui/dispatch-ui.css"; +import { initTheme } from "@trytilde/dispatch-ui"; import { router } from "./router.js"; import { AuthGate } from "./auth-gate.js"; import { ClientWorkspaceGate } from "./workspaces.js"; @@ -10,7 +10,7 @@ import { ClientWorkspaceGate } from "./workspaces.js"; initTheme(); const root = document.getElementById("root"); -if (!root) throw new Error("OpenBot root element is missing"); +if (!root) throw new Error("Dispatch root element is missing"); createRoot(root).render( diff --git a/apps/web/src/router.tsx b/apps/web/src/router.tsx index 14d00a6a..f42c3ce5 100644 --- a/apps/web/src/router.tsx +++ b/apps/web/src/router.tsx @@ -1,5 +1,5 @@ import { createRootRoute, createRoute, createRouter } from "@tanstack/react-router"; -import { OpenBotApp } from "./screens/openbot-app.js"; +import { DispatchApp } from "./screens/dispatch-app.js"; import { SettingsApp, SettingsGeneralApp, @@ -37,7 +37,7 @@ function validateWorkspaceSearch(search: Record): WorkspaceSear }; } -const WorkspaceApp = () => ; +const WorkspaceApp = () => ; const rootRoute = createRootRoute({ notFoundComponent: WorkspaceApp }); const indexRoute = createRoute({ diff --git a/apps/web/src/runtime.ts b/apps/web/src/runtime.ts index 4600fadf..14097ee1 100644 --- a/apps/web/src/runtime.ts +++ b/apps/web/src/runtime.ts @@ -1,18 +1,18 @@ import { createClientAuthAdapter, - createOpenBotClient, - createOpenBotRuntime, + createDispatchClient, + createDispatchRuntime, type AgentSetupState, type ClientAuthAdapter, -} from "@tryopenbot/client-runtime"; +} from "@trytilde/dispatch-client-runtime"; -const client = createOpenBotClient(); +const client = createDispatchClient(); -const auth: ClientAuthAdapter = window.openbotDesktop +const auth: ClientAuthAdapter = window.dispatchDesktop ? { - getSession: () => window.openbotDesktop!.authStatus(), - signIn: () => window.openbotDesktop!.signIn(), - signOut: () => window.openbotDesktop!.signOut(), + getSession: () => window.dispatchDesktop!.authStatus(), + signIn: () => window.dispatchDesktop!.signIn(), + signOut: () => window.dispatchDesktop!.signOut(), } : createClientAuthAdapter(client, { async signIn() { @@ -20,7 +20,7 @@ const auth: ClientAuthAdapter = window.openbotDesktop }, }); -const agentSetupStorageKey = "openbot:agent-setup"; +const agentSetupStorageKey = "dispatch:agent-setup"; const agentSetupPersistence = { load(): AgentSetupState | null { @@ -52,4 +52,4 @@ const agentSetupPersistence = { }, }; -export const openBotRuntime = createOpenBotRuntime({ client, auth, agentSetupPersistence }); +export const dispatchRuntime = createDispatchRuntime({ client, auth, agentSetupPersistence }); diff --git a/apps/web/src/screens/agent-details.tsx b/apps/web/src/screens/agent-details.tsx index 9d7863ff..137c83fd 100644 --- a/apps/web/src/screens/agent-details.tsx +++ b/apps/web/src/screens/agent-details.tsx @@ -1,6 +1,10 @@ import { useEffect, useMemo, useRef, useState } from "react"; import { useStore } from "zustand"; -import type { Routine, SignalInstance, UpdateRoutineInput } from "@tryopenbot/client-runtime"; +import type { + Routine, + SignalInstance, + UpdateRoutineInput, +} from "@trytilde/dispatch-client-runtime"; import { AgentDetailsPane, RoutineEditor, @@ -9,14 +13,18 @@ import { SignalProviderDialog, type SignalTestStatus, WorkOverview, -} from "@tryopenbot/ui"; -import { errorMessage, signalProviderById, workConversationKey } from "@tryopenbot/client-runtime"; -import { openBotRuntime } from "../runtime.js"; +} from "@trytilde/dispatch-ui"; +import { + errorMessage, + signalProviderById, + workConversationKey, +} from "@trytilde/dispatch-client-runtime"; +import { dispatchRuntime } from "../runtime.js"; /** * Wires the agent details pane (routines + drill-in editor) and the signal * provider connect dialog to the client runtime store. Presentation lives in - * @tryopenbot/ui; this container owns data and dispatch (ADR-0023). + * @trytilde/dispatch-ui; this container owns data and dispatch (ADR-0023). */ export interface AgentDetailsContainerProps { @@ -37,10 +45,10 @@ export function AgentDetailsContainer({ onClose, onOpenRoutine, }: AgentDetailsContainerProps) { - const routinesState = useStore(openBotRuntime.store, (state) => state.routines); - const workState = useStore(openBotRuntime.store, (state) => state.work); - const signals = useStore(openBotRuntime.store, (state) => state.signals); - const sidebar = useStore(openBotRuntime.store, (state) => state.sidebar); + const routinesState = useStore(dispatchRuntime.store, (state) => state.routines); + const workState = useStore(dispatchRuntime.store, (state) => state.work); + const signals = useStore(dispatchRuntime.store, (state) => state.signals); + const sidebar = useStore(dispatchRuntime.store, (state) => state.sidebar); const [saveFailed, setSaveFailed] = useState(false); const [deleteFailed, setDeleteFailed] = useState(false); const [running, setRunning] = useState(false); @@ -72,16 +80,16 @@ export function AgentDetailsContainer({ useEffect(() => { if (!open || !agentId) return; - openBotRuntime.actions.startRoutinePolling(agentId); - void openBotRuntime.actions.refreshSignalProviders().catch(() => undefined); - void openBotRuntime.actions.refreshSignalInstances().catch(() => undefined); - return () => openBotRuntime.actions.stopRoutinePolling(); + dispatchRuntime.actions.startRoutinePolling(agentId); + void dispatchRuntime.actions.refreshSignalProviders().catch(() => undefined); + void dispatchRuntime.actions.refreshSignalInstances().catch(() => undefined); + return () => dispatchRuntime.actions.stopRoutinePolling(); }, [agentId, open]); useEffect(() => { if (!open || !agentId || !sessionId || routineParam) return; - openBotRuntime.actions.startWorkPolling(agentId, sessionId); - return () => openBotRuntime.actions.stopWorkPolling(); + dispatchRuntime.actions.startWorkPolling(agentId, sessionId); + return () => dispatchRuntime.actions.stopWorkPolling(); }, [agentId, open, routineParam, sessionId]); const routine = @@ -104,7 +112,7 @@ export function AgentDetailsContainer({ useEffect(() => { if (!eventInstanceIds) return; for (const instanceId of eventInstanceIds.split(",")) { - void openBotRuntime.actions.refreshSignalDeliveries(instanceId).catch(() => undefined); + void dispatchRuntime.actions.refreshSignalDeliveries(instanceId).catch(() => undefined); } }, [eventInstanceIds]); @@ -140,7 +148,7 @@ export function AgentDetailsContainer({ const toggling = input.enabled !== undefined; if (toggling) setTogglePending(true); try { - await openBotRuntime.actions.updateRoutine(routine.id, agentId, input); + await dispatchRuntime.actions.updateRoutine(routine.id, agentId, input); setSaveFailed(false); } catch { setSaveFailed(true); @@ -159,7 +167,7 @@ export function AgentDetailsContainer({ creatingRef.current = true; const priorIds = new Set(routines.map((candidate) => candidate.id)); try { - await openBotRuntime.actions.createRoutine({ + await dispatchRuntime.actions.createRoutine({ agentId, name: input.name, instruction: input.instruction, @@ -167,7 +175,7 @@ export function AgentDetailsContainer({ triggers: input.triggers, }); setSaveFailed(false); - const created = (openBotRuntime.store.getState().routines.byAgentId[agentId] ?? []).find( + const created = (dispatchRuntime.store.getState().routines.byAgentId[agentId] ?? []).find( (candidate: Routine) => !priorIds.has(candidate.id), ); if (!created) { @@ -189,7 +197,7 @@ export function AgentDetailsContainer({ pendingDraftRef.current = null; if (!pending) return; try { - await openBotRuntime.actions.updateRoutine(routineId, agentId, { + await dispatchRuntime.actions.updateRoutine(routineId, agentId, { name: pending.name, instruction: pending.instruction, triggers: pending.triggers, @@ -205,7 +213,7 @@ export function AgentDetailsContainer({ return; } try { - await openBotRuntime.actions.deleteRoutine(routine.id, agentId); + await dispatchRuntime.actions.deleteRoutine(routine.id, agentId); setDeleteFailed(false); onOpenRoutine(undefined); } catch { @@ -217,7 +225,7 @@ export function AgentDetailsContainer({ if (!routine || running) return; setRunning(true); try { - await openBotRuntime.actions.runRoutine(routine.id, agentId); + await dispatchRuntime.actions.runRoutine(routine.id, agentId); } catch { setSaveFailed(true); } finally { @@ -228,19 +236,19 @@ export function AgentDetailsContainer({ function selectSession(sessionId: string): void { const agent = sidebar.agents.find((candidate) => candidate.id === agentId); const session = agent?.sessions.items.find((candidate) => candidate.id === sessionId); - if (session) void openBotRuntime.actions.selectSession(agentId, session); + if (session) void dispatchRuntime.actions.selectSession(agentId, session); } async function steerJob(jobId: string, instruction: string): Promise { - await openBotRuntime.actions.steerBackgroundJob(agentId, sessionId, jobId, instruction); + await dispatchRuntime.actions.steerBackgroundJob(agentId, sessionId, jobId, instruction); } async function stopJob(jobId: string): Promise { - await openBotRuntime.actions.stopBackgroundJob(agentId, sessionId, jobId); + await dispatchRuntime.actions.stopBackgroundJob(agentId, sessionId, jobId); } async function resumeJob(jobId: string, instruction?: string): Promise { - await openBotRuntime.actions.resumeBackgroundJob(agentId, sessionId, jobId, instruction); + await dispatchRuntime.actions.resumeBackgroundJob(agentId, sessionId, jobId, instruction); } const connectProvider = connectProviderId @@ -343,7 +351,7 @@ export function SignalConnectContainer({ onClose, onConnected, }: SignalConnectContainerProps) { - const signals = useStore(openBotRuntime.store, (state) => state.signals); + const signals = useStore(dispatchRuntime.store, (state) => state.signals); const [creating, setCreating] = useState(false); const [error, setError] = useState(""); const [instance, setInstance] = useState(undefined); @@ -352,7 +360,7 @@ export function SignalConnectContainer({ useEffect(() => { if (signals.providers.length === 0) { - void openBotRuntime.actions.refreshSignalProviders().catch(() => undefined); + void dispatchRuntime.actions.refreshSignalProviders().catch(() => undefined); } // eslint-disable-next-line react-hooks/exhaustive-deps -- recover the catalog once }, []); @@ -364,7 +372,7 @@ export function SignalConnectContainer({ setCreating(true); setError(""); try { - const created = await openBotRuntime.actions.createSignalInstance({ + const created = await dispatchRuntime.actions.createSignalInstance({ providerType: providerTypeId, displayName: input.displayName, ...(input.signingSecret ? { signingSecret: input.signingSecret } : {}), @@ -382,7 +390,7 @@ export function SignalConnectContainer({ setTestStatus("sending"); setTestError(""); try { - await openBotRuntime.actions.testSignalInstance(instance.id); + await dispatchRuntime.actions.testSignalInstance(instance.id); setTestStatus("delivered"); } catch (reason) { setTestStatus("failed"); diff --git a/apps/web/src/screens/openbot-app.tsx b/apps/web/src/screens/dispatch-app.tsx similarity index 92% rename from apps/web/src/screens/openbot-app.tsx rename to apps/web/src/screens/dispatch-app.tsx index f7242831..043de8e3 100644 --- a/apps/web/src/screens/openbot-app.tsx +++ b/apps/web/src/screens/dispatch-app.tsx @@ -23,7 +23,7 @@ import { messageText, type QueuedTurn, agentConversationSessions, -} from "@tryopenbot/client-runtime"; +} from "@trytilde/dispatch-client-runtime"; import { useNavigate, useSearch } from "@tanstack/react-router"; import { useStore } from "zustand"; import { @@ -54,25 +54,25 @@ import { type WorkspaceSearchResult, WorkspaceShell, useWorkspaceLayout, -} from "@tryopenbot/ui"; +} from "@trytilde/dispatch-ui"; import type { WorkspaceSearch } from "../router.js"; import { AgentDetailsContainer } from "./agent-details.js"; -import { openBotRuntime } from "../runtime.js"; +import { dispatchRuntime } from "../runtime.js"; import { optimisticParts, type PendingFile, uploadAttachments } from "../web-attachments.js"; import { useClientWorkspace } from "../workspaces.js"; import { shouldExpandComposer } from "./composer-layout.js"; import { rankWorkspaceSearchHits, searchHitId } from "./search-results.js"; -export function OpenBotApp() { +export function DispatchApp() { useEffect(() => { - void openBotRuntime.actions.initialize({ workspace: true }); + void dispatchRuntime.actions.initialize({ workspace: true }); }, []); - const auth = useStore(openBotRuntime.store, (state) => state.auth); - const sidebar = useStore(openBotRuntime.store, (state) => state.sidebar); - const conversation = useStore(openBotRuntime.store, (state) => state.conversation); - const agentSetup = useStore(openBotRuntime.store, (state) => state.agentSetup); - const chatSearch = useStore(openBotRuntime.store, (state) => state.search); + const auth = useStore(dispatchRuntime.store, (state) => state.auth); + const sidebar = useStore(dispatchRuntime.store, (state) => state.sidebar); + const conversation = useStore(dispatchRuntime.store, (state) => state.conversation); + const agentSetup = useStore(dispatchRuntime.store, (state) => state.agentSetup); + const chatSearch = useStore(dispatchRuntime.store, (state) => state.search); const { agents, nextAgentToken, selectedAgentId: agentId, loading } = sidebar; const { selectedSessionId: sessionId, @@ -256,17 +256,17 @@ export function OpenBotApp() { setReplyingTo(null); setThreadRootId(""); restoredSessionRef.current = ""; - void openBotRuntime.actions.selectSession(agent.id, session); + void dispatchRuntime.actions.selectSession(agent.id, session); return; } } useEffect(() => { if (!searchOpen || !search.trim()) { - openBotRuntime.actions.clearSearch(); + dispatchRuntime.actions.clearSearch(); return; } - const handle = window.setTimeout(() => void openBotRuntime.actions.searchChatKit(search), 250); + const handle = window.setTimeout(() => void dispatchRuntime.actions.searchChatKit(search), 250); return () => window.clearTimeout(handle); }, [search, searchOpen]); @@ -302,7 +302,7 @@ export function OpenBotApp() { setReplyingTo(null); setThreadRootId(""); restoredSessionRef.current = ""; - void openBotRuntime.actions.selectAgent(agent.id); + void dispatchRuntime.actions.selectAgent(agent.id); } async function send(event: FormEvent): Promise { @@ -316,7 +316,7 @@ export function OpenBotApp() { let activeSessionId = sessionId; try { if (outgoingFiles.length > 0) - activeSessionId = await openBotRuntime.actions.ensureSession( + activeSessionId = await dispatchRuntime.actions.ensureSession( titleFrom(text, outgoingFiles), ); setDraft(""); @@ -330,7 +330,7 @@ export function OpenBotApp() { for (const pending of outgoingFiles) setFiles((current) => [...current, { ...pending, status: "uploading", progress: 0 }]); const uploaded = await uploadAttachments( - openBotRuntime.client, + dispatchRuntime.client, activeSessionId, outgoingFiles.map((pending) => pending.file), (index, progress) => setFileState(outgoingFiles[index]!.id, { progress }), @@ -347,7 +347,7 @@ export function OpenBotApp() { } } - await openBotRuntime.actions.sendMessage({ + await dispatchRuntime.actions.sendMessage({ text, attachmentIds, attachmentCompletions, @@ -356,16 +356,16 @@ export function OpenBotApp() { }); clearFiles(); } catch (reason) { - openBotRuntime.actions.setError(errorMessage(reason)); + dispatchRuntime.actions.setError(errorMessage(reason)); } } async function stop(): Promise { if (!sessionId) return; try { - await openBotRuntime.actions.interrupt(); + await dispatchRuntime.actions.interrupt(); } catch (reason) { - openBotRuntime.actions.setError(errorMessage(reason)); + dispatchRuntime.actions.setError(errorMessage(reason)); } } @@ -420,7 +420,7 @@ export function OpenBotApp() { async function removeFile(pending: PendingFile): Promise { if (pending.attachmentId && sessionId) { - await openBotRuntime.client + await dispatchRuntime.client .deleteAttachment(sessionId, pending.attachmentId) .catch(() => undefined); } @@ -429,15 +429,15 @@ export function OpenBotApp() { async function loadOlderMessages(): Promise { if (!sessionId || !nextMessageToken) return; - await openBotRuntime.actions.loadOlderMessages(); + await dispatchRuntime.actions.loadOlderMessages(); } async function loadMoreAgents(): Promise { if (!nextAgentToken) return; try { - await openBotRuntime.actions.loadMoreAgents(); + await dispatchRuntime.actions.loadMoreAgents(); } catch (reason) { - openBotRuntime.actions.setError(errorMessage(reason)); + dispatchRuntime.actions.setError(errorMessage(reason)); } } @@ -446,13 +446,13 @@ export function OpenBotApp() { try { await operation(); } catch (reason) { - openBotRuntime.actions.setError(errorMessage(reason)); + dispatchRuntime.actions.setError(errorMessage(reason)); } } async function editQueuedTurn(turn: QueuedTurn): Promise { const text = queuedTurnText(turn); - await mutateQueue(() => openBotRuntime.actions.removeQueuedTurn(turn.id)); + await mutateQueue(() => dispatchRuntime.actions.removeQueuedTurn(turn.id)); setDraft(text === "Queued agent turn" ? "" : text); } @@ -485,7 +485,7 @@ export function OpenBotApp() { function closeSearch(): void { setSearchOpen(false); setSearch(""); - openBotRuntime.actions.clearSearch(); + dispatchRuntime.actions.clearSearch(); } const composer = ( @@ -536,17 +536,17 @@ export function OpenBotApp() { async function submitCreateAgent(candidateName: string, avatarId: string): Promise { const name = candidateName.trim(); if (!name || agentSetup.status === "starting" || agentSetup.status === "setting_up") return; - openBotRuntime.actions.setError(""); + dispatchRuntime.actions.setError(""); setCreateAgentOpen(false); - await openBotRuntime.actions.startAgentSetup(name, avatarId); + await dispatchRuntime.actions.startAgentSetup(name, avatarId); } const connectorActions: ConnectorPartActions = { busy: Boolean(connectorSetup?.submitting), onSelectAccount: (selection, account) => { - void openBotRuntime.client + void dispatchRuntime.client .bindConnector(agentId, account.id) - .catch((reason) => openBotRuntime.actions.setError(errorMessage(reason))); + .catch((reason) => dispatchRuntime.actions.setError(errorMessage(reason))); }, onAddAccount: (selection) => { // Route the modal open through the URL so back/close and redirects work. @@ -567,11 +567,11 @@ export function OpenBotApp() { throw new Error("The capability decision could not be recorded. Please try again."); } try { - await openBotRuntime.actions.sendMessage({ + await dispatchRuntime.actions.sendMessage({ text: `Capability change ${decision === "approve" ? "approved" : "declined"} by the authenticated owner. proposal_id=${updated.id}. Continue the original task from this durable decision and use only server-provided setup continuations.`, }); } catch { - openBotRuntime.actions.setError( + dispatchRuntime.actions.setError( "The capability decision was recorded, but the agent could not be resumed.", ); } @@ -584,7 +584,7 @@ export function OpenBotApp() { if (selection.credentialSources.length > 0) return; // Payloads opened by URL (or older tool outputs) carry no credential // sources; recover them from the catalog. - void openBotRuntime.client + void dispatchRuntime.client .listConnectorProviders() .then((providers) => { const provider = providers.find( @@ -654,7 +654,7 @@ export function OpenBotApp() { const selection = connectorSetup.selection; setConnectorSetup({ ...connectorSetup, submitting: true, error: undefined }); try { - const result = await openBotRuntime.client.createConnectorAccount({ + const result = await dispatchRuntime.client.createConnectorAccount({ providerTypeId: selection.providerTypeId, credentialSourceTypeId: input.credentialSourceTypeId, displayName: input.displayName, @@ -678,7 +678,7 @@ export function OpenBotApp() { const watcher = new AbortController(); connectorWatchRef.current?.abort(); connectorWatchRef.current = watcher; - void waitForConnectorAccountActive(openBotRuntime.client, { + void waitForConnectorAccountActive(dispatchRuntime.client, { providerTypeId: selection.providerTypeId, accountId: result.account.id, signal: watcher.signal, @@ -697,7 +697,7 @@ export function OpenBotApp() { } async function finishConnectorSetup(result: CreateConnectorAccountResult): Promise { - await openBotRuntime.client.bindConnector(agentId, result.account.id); + await dispatchRuntime.client.bindConnector(agentId, result.account.id); closeConnectorSetup(); setConnectorRoute(undefined); } @@ -744,10 +744,10 @@ export function OpenBotApp() { onSelectSearchResult={(id) => { const hit = searchHitsById.get(id); if (!hit) return; - void openBotRuntime.actions + void dispatchRuntime.actions .selectSearchHit(hit) .then(closeSearch) - .catch((reason) => openBotRuntime.actions.setError(errorMessage(reason))); + .catch((reason) => dispatchRuntime.actions.setError(errorMessage(reason))); }} onSelectAgent={selectSidebarChat} onLoadMore={() => void loadMoreAgents()} @@ -755,14 +755,14 @@ export function OpenBotApp() { onOpenPlugins={() => void navigate({ to: "/settings/plugins/tools" })} onOpenSettings={() => void navigate({ to: "/settings" })} onSwitchWorkspace={() => clientWorkspace.openWorkspaceSelector()} - onSignOut={() => void openBotRuntime.actions.signOut()} + onSignOut={() => void dispatchRuntime.actions.signOut()} onResize={layout.beginSidebarResize} /> setMobileSidebarOpen(true)} @@ -802,9 +802,9 @@ export function OpenBotApp() { pendingRun = null; }; const resolveAttachmentUrl = (sessionKey: string, attachmentId: string) => - openBotRuntime.client.getAttachmentDownloadUrl(sessionKey, attachmentId); + dispatchRuntime.client.getAttachmentDownloadUrl(sessionKey, attachmentId); const rewriteUrl = (value: string) => - openBotRuntime.client.rewriteTildeUrl(value); + dispatchRuntime.client.rewriteTildeUrl(value); let participantEventIndex = 0; const renderParticipantEventsBefore = (timestamp: number) => { while (participantEventIndex < participantEvents.length) { @@ -977,10 +977,12 @@ export function OpenBotApp() { if (turn) void editQueuedTurn(turn); }} onReorder={(id, queuePosition) => - void mutateQueue(() => openBotRuntime.actions.reorderQueuedTurn(id, queuePosition)) + void mutateQueue(() => dispatchRuntime.actions.reorderQueuedTurn(id, queuePosition)) } - onRemove={(id) => void mutateQueue(() => openBotRuntime.actions.removeQueuedTurn(id))} - onRunNow={(id) => void mutateQueue(() => openBotRuntime.actions.steerQueuedTurn(id))} + onRemove={(id) => + void mutateQueue(() => dispatchRuntime.actions.removeQueuedTurn(id)) + } + onRunNow={(id) => void mutateQueue(() => dispatchRuntime.actions.steerQueuedTurn(id))} /> {composer} @@ -1001,12 +1003,12 @@ export function OpenBotApp() { capabilityApprovalActions={capabilityApprovalActions} message={threadRoot} resolveAttachmentUrl={(selectedSessionId, attachmentId) => - openBotRuntime.client.getAttachmentDownloadUrl( + dispatchRuntime.client.getAttachmentDownloadUrl( selectedSessionId, attachmentId, ) } - rewriteUrl={(value) => openBotRuntime.client.rewriteTildeUrl(value)} + rewriteUrl={(value) => dispatchRuntime.client.rewriteTildeUrl(value)} /> @@ -1079,7 +1081,7 @@ export function OpenBotApp() { avatarId={agentSetup.avatarId} error={agentSetup.error} name={agentSetup.agent?.name ?? "New bot"} - onClose={() => openBotRuntime.actions.dismissAgentSetup()} + onClose={() => dispatchRuntime.actions.dismissAgentSetup()} open={agentSetup.status !== "idle"} status={agentSetup.status === "idle" ? "starting" : agentSetup.status} /> @@ -1087,7 +1089,7 @@ export function OpenBotApp() { ); } -const SCROLL_STORAGE_KEY = "openbot:chat-scroll"; +const SCROLL_STORAGE_KEY = "dispatch:chat-scroll"; function readScrollSnapshots(): Record { try { diff --git a/apps/web/src/screens/search-results.test.ts b/apps/web/src/screens/search-results.test.ts index 0491ba3b..e2d37766 100644 --- a/apps/web/src/screens/search-results.test.ts +++ b/apps/web/src/screens/search-results.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from "vite-plus/test"; -import type { ChatKitSearchHit } from "@tryopenbot/client-runtime"; +import type { ChatKitSearchHit } from "@trytilde/dispatch-client-runtime"; import { rankWorkspaceSearchHits, searchHitId } from "./search-results.js"; const now = "2026-08-30T00:00:00.000Z"; diff --git a/apps/web/src/screens/search-results.ts b/apps/web/src/screens/search-results.ts index 20de4999..2d39e57c 100644 --- a/apps/web/src/screens/search-results.ts +++ b/apps/web/src/screens/search-results.ts @@ -1,4 +1,4 @@ -import { messageText, type ChatKitSearchHit } from "@tryopenbot/client-runtime"; +import { messageText, type ChatKitSearchHit } from "@trytilde/dispatch-client-runtime"; export function searchHitId(hit: ChatKitSearchHit): string { if (hit.kind === "agent") return `agent:${hit.agent?.id ?? hit.session.id}`; diff --git a/apps/web/src/screens/settings-app.tsx b/apps/web/src/screens/settings-app.tsx index 78bb057a..0fc5e819 100644 --- a/apps/web/src/screens/settings-app.tsx +++ b/apps/web/src/screens/settings-app.tsx @@ -2,13 +2,13 @@ import { useEffect, useMemo, useRef, useState, type CSSProperties, type ReactNod import { useNavigate } from "@tanstack/react-router"; import { motion } from "motion/react"; import { useStore } from "zustand"; -import { errorMessage, type SignalInstance } from "@tryopenbot/client-runtime"; +import { errorMessage, type SignalInstance } from "@trytilde/dispatch-client-runtime"; import { connectorAuthorizedReturnUrl, waitForConnectorAccountActive, type ChatAgent, type PluginsCatalog as PluginsCatalogSnapshot, -} from "@tryopenbot/client-runtime"; +} from "@trytilde/dispatch-client-runtime"; import { BackIcon, BotSelectionDialog, @@ -33,8 +33,8 @@ import { type ConnectorSetupSubmit, SignalsIcon, type ThemePreference, -} from "@tryopenbot/ui"; -import { openBotRuntime } from "../runtime.js"; +} from "@trytilde/dispatch-ui"; +import { dispatchRuntime } from "../runtime.js"; import { SignalConnectContainer } from "./agent-details.js"; const settingsSections = [ @@ -154,7 +154,7 @@ function PluginsSettings({ async function refresh(): Promise { setError(""); try { - setCatalog(await openBotRuntime.client.getPluginsCatalog()); + setCatalog(await dispatchRuntime.client.getPluginsCatalog()); } catch (reason) { setError(reason instanceof Error ? reason.message : "Could not load plugins"); } finally { @@ -195,7 +195,7 @@ function PluginsSettings({ setError(""); setCatalog((current) => updateToolAssignment(current, accountId, agentId, enabled)); try { - await openBotRuntime.client.setToolAccountForAgent(accountId, agentId, enabled); + await dispatchRuntime.client.setToolAccountForAgent(accountId, agentId, enabled); return true; } catch (reason) { setCatalog((current) => updateToolAssignment(current, accountId, agentId, previouslyEnabled)); @@ -211,7 +211,7 @@ function PluginsSettings({ async function deleteToolAccounts(accountIds: readonly string[]): Promise { setError(""); try { - await openBotRuntime.client.deleteConnectorAccounts(accountIds); + await dispatchRuntime.client.deleteConnectorAccounts(accountIds); setCatalog((current) => ({ ...current, tools: current.tools.map((entry) => ({ @@ -244,7 +244,7 @@ function PluginsSettings({ setError(""); setCatalog((current) => updateSkillAssignment(current, skillId, agentId, enabled)); try { - await openBotRuntime.client.setSkillForAgent(skillId, agentId, enabled); + await dispatchRuntime.client.setSkillForAgent(skillId, agentId, enabled); } catch (reason) { setCatalog((current) => updateSkillAssignment(current, skillId, agentId, previouslyEnabled)); setError(reason instanceof Error ? reason.message : "Could not update skill"); @@ -256,7 +256,7 @@ function PluginsSettings({ const current = setup; setSetup({ ...current, submitting: true, error: undefined }); try { - const result = await openBotRuntime.client.createConnectorAccount({ + const result = await dispatchRuntime.client.createConnectorAccount({ providerTypeId: current.providerId, credentialSourceTypeId: input.credentialSourceTypeId, displayName: input.displayName, @@ -273,7 +273,7 @@ function PluginsSettings({ setupWatcher.current?.abort(); const watcher = new AbortController(); setupWatcher.current = watcher; - const active = await waitForConnectorAccountActive(openBotRuntime.client, { + const active = await waitForConnectorAccountActive(dispatchRuntime.client, { providerTypeId: current.providerId, accountId: result.account.id, signal: watcher.signal, @@ -394,8 +394,8 @@ export function SettingsApp({ section = "general" }: SettingsAppProps = {}) { const navigate = useNavigate(); const [theme, setTheme] = useState(() => getThemePreference()); const [mobileNavigationOpen, setMobileNavigationOpen] = useState(false); - const agents = useStore(openBotRuntime.store, (state) => state.sidebar.agents); - const macDesktop = window.openbotDesktop?.platform === "mac"; + const agents = useStore(dispatchRuntime.store, (state) => state.sidebar.agents); + const macDesktop = window.dispatchDesktop?.platform === "mac"; return ( state.signals); - const routines = useStore(openBotRuntime.store, (state) => state.routines); + const signals = useStore(dispatchRuntime.store, (state) => state.signals); + const routines = useStore(dispatchRuntime.store, (state) => state.routines); const [connectProviderId, setConnectProviderId] = useState(""); const [creatingForBot, setCreatingForBot] = useState(false); const [editing, setEditing] = useState<{ agentId: string; routineId: string | null } | null>( @@ -590,15 +590,15 @@ function RoutineSettingsContainer({ agents }: { agents: readonly ChatAgent[] }) const noticeTimersRef = useRef>({}); useEffect(() => { - void openBotRuntime.actions.refreshSignalProviders().catch(() => undefined); - void openBotRuntime.actions.refreshSignalInstances().catch(() => undefined); + void dispatchRuntime.actions.refreshSignalProviders().catch(() => undefined); + void dispatchRuntime.actions.refreshSignalInstances().catch(() => undefined); }, []); const agentIdsKey = agents.map((agent) => agent.id).join("\0"); useEffect(() => { - void Promise.all(agents.map((agent) => openBotRuntime.actions.refreshRoutines(agent.id))).catch( - () => undefined, - ); + void Promise.all( + agents.map((agent) => dispatchRuntime.actions.refreshRoutines(agent.id)), + ).catch(() => undefined); // Bot identity, not array identity, controls the remote snapshots. // eslint-disable-next-line react-hooks/exhaustive-deps }, [agentIdsKey]); @@ -655,11 +655,11 @@ function RoutineSettingsContainer({ agents }: { agents: readonly ChatAgent[] }) instances={signals.instances} onConnectProvider={setConnectProviderId} onDeleteInstance={(instance) => - void withNotice(instance, () => openBotRuntime.actions.deleteSignalInstance(instance.id)) + void withNotice(instance, () => dispatchRuntime.actions.deleteSignalInstance(instance.id)) } onToggleInstance={(instance, enabled) => void withNotice(instance, async () => { - await openBotRuntime.actions.updateSignalInstance(instance.id, { + await dispatchRuntime.actions.updateSignalInstance(instance.id, { status: enabled ? "enabled" : "disabled", }); }) @@ -672,11 +672,11 @@ function RoutineSettingsContainer({ agents }: { agents: readonly ChatAgent[] }) error={routines.error || undefined} onCreate={() => setCreatingForBot(true)} onDelete={(routine) => - void openBotRuntime.actions.deleteRoutine(routine.id, routine.agent_id) + void dispatchRuntime.actions.deleteRoutine(routine.id, routine.agent_id) } onEdit={(routine) => setEditing({ agentId: routine.agent_id, routineId: routine.id })} onToggle={(routine, enabled) => - void openBotRuntime.actions.updateRoutine(routine.id, routine.agent_id, { enabled }) + void dispatchRuntime.actions.updateRoutine(routine.id, routine.agent_id, { enabled }) } providers={signals.providers} rows={routineRows} @@ -707,15 +707,15 @@ function RoutineSettingsContainer({ agents }: { agents: readonly ChatAgent[] }) if (creatingRef.current) return; creatingRef.current = true; const prior = new Set( - (openBotRuntime.store.getState().routines.byAgentId[editing.agentId] ?? []).map( + (dispatchRuntime.store.getState().routines.byAgentId[editing.agentId] ?? []).map( (routine) => routine.id, ), ); - void openBotRuntime.actions + void dispatchRuntime.actions .createRoutine({ agentId: editing.agentId, ...input }) .then(() => { const created = ( - openBotRuntime.store.getState().routines.byAgentId[editing.agentId] ?? [] + dispatchRuntime.store.getState().routines.byAgentId[editing.agentId] ?? [] ).find((routine) => !prior.has(routine.id)); if (created) setEditing({ agentId: editing.agentId, routineId: created.id }); }) @@ -725,7 +725,7 @@ function RoutineSettingsContainer({ agents }: { agents: readonly ChatAgent[] }) }} onDelete={() => { if (!editedRoutine) return setEditing(null); - void openBotRuntime.actions + void dispatchRuntime.actions .deleteRoutine(editedRoutine.id, editing.agentId) .then(() => setEditing(null)); }} @@ -733,13 +733,13 @@ function RoutineSettingsContainer({ agents }: { agents: readonly ChatAgent[] }) onTestRun={() => { if (!editedRoutine || running) return; setRunning(true); - void openBotRuntime.actions + void dispatchRuntime.actions .runRoutine(editedRoutine.id, editing.agentId) .finally(() => setRunning(false)); }} onUpdate={(input) => { if (editedRoutine) - void openBotRuntime.actions.updateRoutine( + void dispatchRuntime.actions.updateRoutine( editedRoutine.id, editing.agentId, input, diff --git a/apps/web/src/web-attachments.ts b/apps/web/src/web-attachments.ts index c8066e63..2f6cbd1e 100644 --- a/apps/web/src/web-attachments.ts +++ b/apps/web/src/web-attachments.ts @@ -2,8 +2,8 @@ import type { Attachment, AttachmentCompletion, ChatPart, - OpenBotClient, -} from "@tryopenbot/client-runtime"; + DispatchClient, +} from "@trytilde/dispatch-client-runtime"; export interface PendingFile { id: string; @@ -22,7 +22,7 @@ export interface UploadedAttachment { } export async function uploadAttachments( - client: OpenBotClient, + client: DispatchClient, sessionId: string, files: File[], onProgress: (index: number, progress: number) => void, diff --git a/apps/web/src/workspaces.tsx b/apps/web/src/workspaces.tsx index 1e3b6c88..70b870b1 100644 --- a/apps/web/src/workspaces.tsx +++ b/apps/web/src/workspaces.tsx @@ -1,6 +1,6 @@ import { addClientWorkspace, - createOpenBotClient, + createDispatchClient, decodeClientWorkspaceTransfer, discoverControlService, encodeClientWorkspaceTransfer, @@ -13,14 +13,14 @@ import { selectClientWorkspace, type ClientWorkspaceRegistry, type ClientWorkspaceStorage, -} from "@tryopenbot/client-runtime"; -import { SelectWorkspaceScreen, WorkspaceSelectorDialog } from "@tryopenbot/ui"; +} from "@trytilde/dispatch-client-runtime"; +import { SelectWorkspaceScreen, WorkspaceSelectorDialog } from "@trytilde/dispatch-ui"; import { createContext, type ReactNode, useContext, useEffect, useMemo, useState } from "react"; -const transferParameter = "openbot-workspaces"; -const joinParameter = "openbot-join"; -const joinNameParameter = "openbot-workspace-name"; -const pendingJoinKey = "openbot.pending-workspace"; +const transferParameter = "dispatch-workspaces"; +const joinParameter = "dispatch-join"; +const joinNameParameter = "dispatch-workspace-name"; +const pendingJoinKey = "dispatch.pending-workspace"; interface PendingWorkspaceJoin { controlOrigin: string; @@ -94,7 +94,7 @@ export function ClientWorkspaceGate({ children }: { children: ReactNode }) { }, []); useEffect(() => { - if (!registry || window.openbotDesktop) return; + if (!registry || window.dispatchDesktop) return; const activeWorkspace = registry.workspaces.find( (item) => item.id === registry.active_workspace_id, ); @@ -112,16 +112,16 @@ export function ClientWorkspaceGate({ children }: { children: ReactNode }) { try { const controlOrigin = normalizeControlOrigin(value); if (controlOrigin !== shellControlOrigin) { - if (window.openbotDesktop) + if (window.dispatchDesktop) throw new Error("This desktop build can only use its configured control server"); safeStorage(() => sessionStorage.removeItem(pendingJoinKey), undefined); navigateToWorkspace(controlOrigin, baseRegistry, { controlOrigin, name }); return; } await discoverControlService(controlOrigin, workspaceFetch(shellControlOrigin)); - const session = window.openbotDesktop - ? await window.openbotDesktop.authStatus() - : await createOpenBotClient({ fetch: workspaceFetch(shellControlOrigin) }).getSession(); + const session = window.dispatchDesktop + ? await window.dispatchDesktop.authStatus() + : await createDispatchClient({ fetch: workspaceFetch(shellControlOrigin) }).getSession(); if (!session) { safeStorage( () => @@ -131,9 +131,9 @@ export function ClientWorkspaceGate({ children }: { children: ReactNode }) { ), undefined, ); - if (window.openbotDesktop) { - await window.openbotDesktop.signIn(); - if (!(await window.openbotDesktop.authStatus())) + if (window.dispatchDesktop) { + await window.dispatchDesktop.signIn(); + if (!(await window.dispatchDesktop.authStatus())) throw new Error("Authentication did not complete"); } else { location.assign("/auth/login"); @@ -168,7 +168,7 @@ export function ClientWorkspaceGate({ children }: { children: ReactNode }) { const workspace = next.workspaces.find((item) => item.id === next.active_workspace_id); if (!workspace) return setRegistry(next); if (workspace.control_origin !== shellControlOrigin) { - if (window.openbotDesktop) { + if (window.dispatchDesktop) { setError("This desktop build can only use its configured control server"); return; } @@ -200,7 +200,7 @@ export function ClientWorkspaceGate({ children }: { children: ReactNode }) { if (!activeWorkspace) return ; if (activeWorkspace.control_origin !== shellControlOrigin) { - if (window.openbotDesktop) + if (window.dispatchDesktop) return ( ({ target: controlOrigin, xfwd: true }); const computerVncTarget = process.env.EXE_DEV_COMPUTER_VNC_TARGET?.trim(); const exeDevPublicOrigin = process.env.EXE_DEV_PUBLIC_ORIGIN?.trim(); diff --git a/cli/README.md b/cli/README.md index d5d456bc..f066b757 100644 --- a/cli/README.md +++ b/cli/README.md @@ -1,48 +1,48 @@ -# openbot +# dispatch -The React Ink CLI for OpenBot. It operates an installation — initialization, development supervision, encrypted secret maintenance, service execution, provider-coordinated deployment — and it carries the developer workflow for the codebase itself: repository gates and remote desktop hosts. One command surface serves operators, fork developers, and sandboxed agents (ADR-0018). Commands are parsed with `arg`; command entrypoints live under `src/commands/`. +The React Ink CLI for Dispatch. It operates an installation — initialization, development supervision, encrypted secret maintenance, service execution, provider-coordinated deployment — and it carries the developer workflow for the codebase itself: repository gates and remote desktop hosts. One command surface serves operators, fork developers, and sandboxed agents (ADR-0018). Commands are parsed with `arg`; command entrypoints live under `src/commands/`. Provider lifecycle failures identify both the concrete implementation and provider domain. CLI failures always print the complete redacted stack and cause chain below the concise error message; the same stack is included in JSON error output and the private run log. ## Install ```bash -npm install --global openbot -openbot --help +npm install --global @trytilde/cli +dispatch --help ``` -The CLI operates on the OpenBot repository in the current working directory. For a new installation, run `openbot init` from a completely empty destination directory; it verifies canonical OpenBot, creates an owned GitHub repository, clones the verified revision, and writes configuration. Running `openbot init` again from that initialized repository revisits every provider domain with multiple implementations in a React Ink selector. Each selector contains all built-ins and preselects the configured provider, then immediately asks and provisions that provider's configuration before proceeding to another domain. It does not recreate the repository or replace the existing SOPS ownership configuration. A cloned checkout left incomplete by provider failure is resumed rather than treated as a new empty destination. The CLI can also run without a global install using `npx openbot`. +The CLI operates on the Dispatch repository in the current working directory. For a new installation, run `tilde init` from a completely empty destination directory; it verifies canonical Dispatch, creates an owned GitHub repository, clones the verified revision, and writes configuration. Running `tilde init` again from that initialized repository revisits every provider domain with multiple implementations in a React Ink selector. Each selector contains all built-ins and preselects the configured provider, then immediately asks and provisions that provider's configuration before proceeding to another domain. It does not recreate the repository or replace the existing SOPS ownership configuration. A cloned checkout left incomplete by provider failure is resumed rather than treated as a new empty destination. The CLI can also run without a global install using `npx @trytilde/cli`. ## Commands -- For a new installation, `openbot init` rejects any non-empty destination before prompts or network mutation, verifies Git and authenticated GitHub CLI/SSH access, then accepts either a bare repository name for the authenticated account or `owner/name` for an authorized organization. It creates either a public fork or independent private mirror. After cloning it creates `configuration/.env`, `configuration/index.ts`, SOPS recipients and encrypted secrets, asks whether inference should use Vercel AI Gateway or a ChatGPT subscription, seeds the selected provider's source into `configuration/templates/agent/`, then scaffolds the Factory agent from that template. Gateway setup stores `AI_GATEWAY_API_KEY`; Codex setup always uses device-code login and stores its opaque auth cache as encrypted `CODEX_AUTH_JSON`. For Vercel agent services, deployment also packages the Linux Codex executable and enables Vercel Large Functions. -- In an already initialized OpenBot repository, `openbot init` decrypts the current values, preselects the configured runtime and inference providers while offering every built-in alternative, uses stored values as prompt defaults, updates only active platform/provider destinations, preserves unrelated environment and secret entries, re-encrypts with the existing SOPS recipients, and runs `vp install` again. Switching recognized built-ins rewrites only the canonical generated composition and exact previous-provider agent scaffolds; custom composition or fork-edited agent files require an explicit migration. SOPS owner lookup metadata lives in the checkout's gitignored root `local-user-config.json`. Any interactive command that needs it configures it inline when missing; non-interactive commands stop with an actionable error. -- `openbot init --non-interactive --json` runs the same path from a JSON object on standard input. This is the supported automation and AI-agent interface for Vercel inference: secrets do not appear in process arguments, missing core answers fail before repository creation, and success or failure is machine-readable JSON. ChatGPT subscription setup intentionally requires interactive device-code authentication. -- `openbot init --help` prints the complete JSON Schema for that stdin object. It includes field names, human-readable descriptions, allowed values, conditional required fields, validation patterns, secret markers, and questions contributed dynamically by the selected runtime providers. -- `openbot new-agent` asks for an agent name, derives its kebab-case ID, and renders the fork-owned `configuration/templates/agent/**/*.hbs` tree under `configuration/agent/subagents//` without overwriting an existing agent. Every subagent gets the full instrumentation, tools, skills, and `sandbox/workspace` tree. Agents use `openbot new-agent "Research Agent" --json` for a machine-readable result. -- `openbot dev` checks all configured runtime providers, builds and starts the local Microsandbox Computer, then reconciles each authored agent's Tilde Vercel AI SDK endpoint, dynamic MCP server, and skill registry. Vercel service adapters skip remote work in this mode; Tilde enables local-running endpoints. The command supervises the combined control/agent HMR server, web, optional Electron process, and a Computer image watcher that rebuilds and replaces Microsandbox after Computer source or Containerfile changes. It persists non-secret `AGENT__*` resource IDs in `configuration/.env` and newly issued endpoint credentials in SOPS. Use the Tilde tunnel when ChatKit must reach the local agent routes. -- `openbot deploy` builds selected providers, optionally stops with `--skip-deploy`, or plans and deploys providers with the runtime last. +- For a new installation, `tilde init` rejects any non-empty destination before prompts or network mutation, verifies Git and authenticated GitHub CLI/SSH access, then accepts either a bare repository name for the authenticated account or `owner/name` for an authorized organization. It creates either a public fork or independent private mirror. After cloning it creates `configuration/.env`, `configuration/index.ts`, SOPS recipients and encrypted secrets, asks whether inference should use Vercel AI Gateway or a ChatGPT subscription, seeds the selected provider's source into `configuration/templates/agent/`, then scaffolds the Factory agent from that template. Gateway setup stores `AI_GATEWAY_API_KEY`; Codex setup always uses device-code login and stores its opaque auth cache as encrypted `CODEX_AUTH_JSON`. For Vercel agent services, deployment also packages the Linux Codex executable and enables Vercel Large Functions. +- In an already initialized Dispatch repository, `tilde init` decrypts the current values, preselects the configured runtime and inference providers while offering every built-in alternative, uses stored values as prompt defaults, updates only active platform/provider destinations, preserves unrelated environment and secret entries, re-encrypts with the existing SOPS recipients, and runs `vp install` again. Switching recognized built-ins rewrites only the canonical generated composition and exact previous-provider agent scaffolds; custom composition or fork-edited agent files require an explicit migration. SOPS owner lookup metadata lives in the checkout's gitignored root `local-user-config.json`. Any interactive command that needs it configures it inline when missing; non-interactive commands stop with an actionable error. +- `tilde init --non-interactive --json` runs the same path from a JSON object on standard input. This is the supported automation and AI-agent interface for Vercel inference: secrets do not appear in process arguments, missing core answers fail before repository creation, and success or failure is machine-readable JSON. ChatGPT subscription setup intentionally requires interactive device-code authentication. +- `tilde init --help` prints the complete JSON Schema for that stdin object. It includes field names, human-readable descriptions, allowed values, conditional required fields, validation patterns, secret markers, and questions contributed dynamically by the selected runtime providers. +- `tilde new-agent` asks for an agent name, derives its kebab-case ID, and renders the fork-owned `configuration/templates/agent/**/*.hbs` tree under `configuration/agent/subagents//` without overwriting an existing agent. Every subagent gets the full instrumentation, tools, skills, and `sandbox/workspace` tree. Agents use `tilde new-agent "Research Agent" --json` for a machine-readable result. +- `tilde dev` checks all configured runtime providers, builds and starts the local Microsandbox Computer, then reconciles each authored agent's Tilde Vercel AI SDK endpoint, dynamic MCP server, and skill registry. Vercel service adapters skip remote work in this mode; Tilde enables local-running endpoints. The command supervises the combined control/agent HMR server, web, optional Electron process, and a Computer image watcher that rebuilds and replaces Microsandbox after Computer source or Containerfile changes. It persists non-secret `AGENT__*` resource IDs in `configuration/.env` and newly issued endpoint credentials in SOPS. Use the Tilde tunnel when ChatKit must reach the local agent routes. +- `tilde deploy` builds selected providers, optionally stops with `--skip-deploy`, or plans and deploys providers with the runtime last. - The exe.dev runtime option reconciles one named 2-vCPU/8-GB VM, exposes Vite on its HTTPS origin, clones the Code Storage fork, and keeps `pnpm dev` running through systemd user linger. The host itself is the Computer and receives the trusted development configuration. This is an explicit trusted single-VM mode, not a sandbox boundary for untrusted agents. -- `openbot secrets set NAME --description TEXT` and `openbot secrets unset NAME` maintain described `configuration/secrets.enc.yaml` entries without putting plaintext values in command arguments. SOPS encrypts only each entry's `value`; its `description` stays readable. Agents pipe values with `--stdin`; descriptions are mandatory. -- `openbot env set NAME VALUE --description TEXT` and `openbot env unset NAME` maintain `configuration/.env`. Descriptions are mandatory and appear as plaintext comments above quoted values. -- `openbot auth ` owns Tilde authentication and team selection. `openbot state ` performs explicit team-state migrations, while normal OpenBot lifecycles continue to reconcile resources through providers. -- `openbot tunnel -- ` runs a local service behind its Tilde local-runtime tunnel. `openbot plugin --cli ` configures selected Tilde MCP servers, skill registries, and native hooks that record searchable ChatKit messages and canonical tool executions for every supported harness. Use `--agent-id` to select the audit agent, or the first visible agent is used. `--launch` optionally starts the configured harness. -- `openbot sdk ` owns generated OpenAPI refresh, SDK package validation, clean packed-consumer verification, and explicitly confirmed npm publication for the `@trytilde/sdk*` packages in this monorepo. -- `openbot check`, `openbot build`, `openbot test`, and `openbot e2e` delegate to the matching repository scripts, which remain the single definition of what each gate runs. `openbot desktop package` packages the Electron app. Extra arguments pass through. -- `openbot desktop dev [--headless] [--display N] [--vnc-port PORT]` builds and launches the Electron shell. On a machine with a display it opens a window; on a display-less host it renders to a virtual screen published over loopback VNC on port 5901. `openbot desktop package` packages the app for the host platform. -- `openbot desktop release ` publishes signed desktop builds to the updates bucket. `build` packages, signs, and notarizes; `publish` uploads this platform's artifacts and its release entry; `manifest` rebuilds `version.json` from the entries already in the bucket; `status` prints the resolved target. `publish` and `manifest` require `--yes` because both change a public feed, and all of them refuse the official bucket from a remote other than `trytilde/dispatch`. See ADR-0028. -- `openbot connect [--print] [--no-desktop]` opens the ssh tunnel that carries a remote Electron screen to this machine's loopback. -- `openbot remote ` runs a desktop task on a configured host over ssh. `desktop-package` produces artifacts for the remote's platform because Electron Builder targets the host it runs on. +- `tilde secrets set NAME --description TEXT` and `tilde secrets unset NAME` maintain described `configuration/secrets.enc.yaml` entries without putting plaintext values in command arguments. SOPS encrypts only each entry's `value`; its `description` stays readable. Agents pipe values with `--stdin`; descriptions are mandatory. +- `tilde env set NAME VALUE --description TEXT` and `tilde env unset NAME` maintain `configuration/.env`. Descriptions are mandatory and appear as plaintext comments above quoted values. +- `tilde auth ` owns Tilde authentication and team selection. `tilde state ` performs explicit team-state migrations, while normal Dispatch lifecycles continue to reconcile resources through providers. +- `tilde tunnel -- ` runs a local service behind its Tilde local-runtime tunnel. `tilde plugin --cli ` configures selected Tilde MCP servers, skill registries, and native hooks that record searchable ChatKit messages and canonical tool executions for every supported harness. Use `--agent-id` to select the audit agent, or the first visible agent is used. `--launch` optionally starts the configured harness. +- `tilde sdk ` owns generated OpenAPI refresh, SDK package validation, clean packed-consumer verification, and explicitly confirmed npm publication for the `@trytilde/sdk*` packages in this monorepo. +- `tilde check`, `tilde build`, `tilde test`, and `tilde e2e` delegate to the matching repository scripts, which remain the single definition of what each gate runs. `tilde desktop package` packages the Electron app. Extra arguments pass through. +- `tilde desktop dev [--headless] [--display N] [--vnc-port PORT]` builds and launches the Electron shell. On a machine with a display it opens a window; on a display-less host it renders to a virtual screen published over loopback VNC on port 5901. `tilde desktop package` packages the app for the host platform. +- `tilde desktop release ` publishes signed desktop builds to the updates bucket. `build` packages, signs, and notarizes; `publish` uploads this platform's artifacts and its release entry; `manifest` rebuilds `version.json` from the entries already in the bucket; `status` prints the resolved target. `publish` and `manifest` require `--yes` because both change a public feed, and all of them refuse the official bucket from a remote other than `trytilde/dispatch`. See ADR-0028. +- `tilde connect [--print] [--no-desktop]` opens the ssh tunnel that carries a remote Electron screen to this machine's loopback. +- `tilde remote ` runs a desktop task on a configured host over ssh. `desktop-package` produces artifacts for the remote's platform because Electron Builder targets the host it runs on. - Development hosts are fork-owned configuration in `configuration/dev-hosts.json`, never package code. Any command also accepts a raw `user@host`: ```json { "hosts": { - "build": { "ssh": "root@198.51.100.7", "platform": "linux", "path": "~/openbot" }, - "mini": { "ssh": "me@mac-mini.local", "platform": "mac", "path": "~/openbot" } + "build": { "ssh": "root@198.51.100.7", "platform": "linux", "path": "~/dispatch" }, + "mini": { "ssh": "me@mac-mini.local", "platform": "mac", "path": "~/dispatch" } } } ``` @@ -51,34 +51,34 @@ Developer commands require a repository checkout and fail with a clear error out ## Public API -This package is an application and declares no importable package exports. Its internal command functions are implementation details; invoke the installed `openbot` executable, `npx openbot`, or the repository-local `pnpm openbot` script. +This package is an application and declares no importable package exports. Its internal command functions are implementation details; invoke the installed `tilde` executable, `npx @trytilde/cli`, or the repository-local `pnpm tilde` script. ## Non-interactive initialization Run from the completely empty destination directory and pipe answers on standard input: ```bash -openbot init --non-interactive --json < openbot-answers.json +tilde init --non-interactive --json < dispatch-answers.json ``` For a private Vercel installation using AWS KMS, the answer object is: ```json { - "repository-name": "my-openbot", + "repository-name": "my-dispatch", "repository-visibility": "private", "owner-identity": "aws-kms", - "aws-kms-key-arn": "arn:aws:kms:us-east-1:123456789012:alias/openbot-sops", + "aws-kms-key-arn": "arn:aws:kms:us-east-1:123456789012:alias/dispatch-sops", "aws-profile": "admin", "runtime": "vercel", "inference": "vercel", "vercel-token": "secret", - "vercel-control-project": "my-openbot-control", - "vercel-agent-project": "my-openbot-agents", + "vercel-control-project": "my-dispatch-control", + "vercel-agent-project": "my-dispatch-agents", "tilde-api-key": "secret", "tilde-org-id": "org-id", "tilde-team-id": "team-id", - "vercel-ai-gateway-api-key-name": "My OpenBot agents" + "vercel-ai-gateway-api-key-name": "My Dispatch agents" } ``` @@ -87,8 +87,8 @@ For a private Vercel installation using AWS KMS, the answer object is: Other agent-safe mutations follow the same stdout JSON and nonzero-exit convention: ```bash -openbot new-agent "Research Agent" --json -printf '%s' "$SECRET_VALUE" | openbot secrets set API_TOKEN --stdin --json -openbot secrets unset API_TOKEN --json -openbot deploy --dry-run --json +tilde new-agent "Research Agent" --json +printf '%s' "$SECRET_VALUE" | tilde secrets set API_TOKEN --stdin --json +tilde secrets unset API_TOKEN --json +tilde deploy --dry-run --json ``` diff --git a/cli/package.json b/cli/package.json index 540eac99..4a838c85 100644 --- a/cli/package.json +++ b/cli/package.json @@ -1,8 +1,8 @@ { - "name": "openbot", + "name": "@trytilde/cli", "version": "0.1.0", "bin": { - "openbot": "./dist/index.js" + "tilde": "./dist/index.js" }, "files": [ "dist", @@ -26,20 +26,20 @@ "dependencies": { "@hono/node-server": "1.19.1", "@inquirer/checkbox": "5.2.1", - "@tryopenbot/agent-provider": "workspace:*", - "@tryopenbot/agent-service-provider": "workspace:*", - "@tryopenbot/auth-provider": "workspace:*", - "@tryopenbot/computer-service-provider": "workspace:*", - "@tryopenbot/computer-tools": "workspace:*", - "@tryopenbot/configuration": "workspace:*", - "@tryopenbot/connector-tools": "workspace:*", - "@tryopenbot/control-service": "workspace:*", - "@tryopenbot/control-service-provider": "workspace:*", - "@tryopenbot/git-provider": "workspace:*", - "@tryopenbot/inference-provider": "workspace:*", - "@tryopenbot/platform-integrations": "workspace:*", - "@tryopenbot/runtime-provider": "workspace:*", - "@tryopenbot/utilities": "workspace:*", + "@trytilde/dispatch-agent-provider": "workspace:*", + "@trytilde/dispatch-agent-service-provider": "workspace:*", + "@trytilde/dispatch-auth-provider": "workspace:*", + "@trytilde/dispatch-computer-service-provider": "workspace:*", + "@trytilde/dispatch-computer-tools": "workspace:*", + "@trytilde/dispatch-configuration": "workspace:*", + "@trytilde/dispatch-connector-tools": "workspace:*", + "@trytilde/dispatch-control-service": "workspace:*", + "@trytilde/dispatch-control-service-provider": "workspace:*", + "@trytilde/dispatch-git-provider": "workspace:*", + "@trytilde/dispatch-inference-provider": "workspace:*", + "@trytilde/dispatch-platform-integrations": "workspace:*", + "@trytilde/dispatch-runtime-provider": "workspace:*", + "@trytilde/dispatch-utilities": "workspace:*", "@trytilde/sdk": "workspace:*", "@trytilde/sdk-claude-code": "workspace:*", "@trytilde/sdk-codex": "workspace:*", diff --git a/cli/src/agent-lifecycle.test.ts b/cli/src/agent-lifecycle.test.ts index 9b563a33..436005ff 100644 --- a/cli/src/agent-lifecycle.test.ts +++ b/cli/src/agent-lifecycle.test.ts @@ -1,6 +1,9 @@ -import type { AgentProvider } from "@tryopenbot/agent-provider"; -import { discoverAgents, type AgentServiceProvider } from "@tryopenbot/agent-service-provider"; -import type { DeployableProvider } from "@tryopenbot/runtime-provider"; +import type { AgentProvider } from "@trytilde/dispatch-agent-provider"; +import { + discoverAgents, + type AgentServiceProvider, +} from "@trytilde/dispatch-agent-service-provider"; +import type { DeployableProvider } from "@trytilde/dispatch-runtime-provider"; import { describe, expect, it, vi } from "vite-plus/test"; import { formatAgentLifecycleProgress, @@ -8,7 +11,7 @@ import { serialDeploymentPersistence, } from "./agent-lifecycle.js"; -vi.mock("@tryopenbot/agent-service-provider", async (importOriginal) => ({ +vi.mock("@trytilde/dispatch-agent-service-provider", async (importOriginal) => ({ ...(await importOriginal()), discoverAgents: vi.fn(async () => [ { @@ -127,7 +130,7 @@ describe("agent resource lifecycle", () => { await reconcileAgentResources({ repositoryRoot: "/repository", agentIds: ["research-assistant"], - environment: { OPENBOT_AUTOMATIC_MEMORY_MODE: "personal_plus_agent" }, + environment: { DISPATCH_AUTOMATIC_MEMORY_MODE: "personal_plus_agent" }, devMode: true, providers: { agent: { @@ -293,7 +296,7 @@ describe("agent resource lifecycle", () => { await reconcileAgentResources({ repositoryRoot: "/repository", - environment: { OPENBOT_AUTOMATIC_MEMORY_MODE: "personal_plus_agent" }, + environment: { DISPATCH_AUTOMATIC_MEMORY_MODE: "personal_plus_agent" }, devMode: true, providers: { agent: { diff --git a/cli/src/agent-lifecycle.ts b/cli/src/agent-lifecycle.ts index eea16d1f..0141119e 100644 --- a/cli/src/agent-lifecycle.ts +++ b/cli/src/agent-lifecycle.ts @@ -1,5 +1,8 @@ -import type { AgentProvider } from "@tryopenbot/agent-provider"; -import { discoverAgents, type AgentServiceProvider } from "@tryopenbot/agent-service-provider"; +import type { AgentProvider } from "@trytilde/dispatch-agent-provider"; +import { + discoverAgents, + type AgentServiceProvider, +} from "@trytilde/dispatch-agent-service-provider"; import { DeploymentOutputs, persistEnvironment, @@ -9,7 +12,7 @@ import { type DeploymentReporter, type DeployableProvider, runProviderLifecycleHook, -} from "@tryopenbot/runtime-provider"; +} from "@trytilde/dispatch-runtime-provider"; import { setEncryptedSecret, setEnvironmentValue, @@ -76,7 +79,7 @@ export async function reconcileAgentResources( const prefix = `AGENT_${source.slug.replaceAll("-", "_").toUpperCase()}`; const value = options.environment[`${prefix}_AUTOMATIC_MEMORY_MODE`] ?? - options.environment.OPENBOT_AUTOMATIC_MEMORY_MODE; + options.environment.DISPATCH_AUTOMATIC_MEMORY_MODE; return (value?.trim().toLowerCase() ?? "none") !== "none"; }); let sources = selectedAgentIds diff --git a/cli/src/agent-scaffold.test.ts b/cli/src/agent-scaffold.test.ts index 42568208..cc6e4c4c 100644 --- a/cli/src/agent-scaffold.test.ts +++ b/cli/src/agent-scaffold.test.ts @@ -10,12 +10,12 @@ import { } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { discoverAgents } from "@tryopenbot/agent-service-provider"; +import { discoverAgents } from "@trytilde/dispatch-agent-service-provider"; import { setImmediate } from "node:timers/promises"; import { fileURLToPath } from "node:url"; -import { VercelAgentServiceProvider } from "@tryopenbot/agent-service-provider"; -import { CodexInferenceProvider } from "@tryopenbot/inference-provider"; -import { DeploymentOutputs } from "@tryopenbot/runtime-provider"; +import { VercelAgentServiceProvider } from "@trytilde/dispatch-agent-service-provider"; +import { CodexInferenceProvider } from "@trytilde/dispatch-inference-provider"; +import { DeploymentOutputs } from "@trytilde/dispatch-runtime-provider"; import { afterEach, describe, expect, it } from "vite-plus/test"; import { agentIdFromName, @@ -61,8 +61,8 @@ describe("agent scaffolding", () => { expect(agentSource).not.toContain("runtime-providers"); expect(agentSource).toContain("context.mcp.connect"); expect(agentSource).not.toContain("createMCPClient({"); - expect(agentSource).not.toContain("@tryopenbot/agent-provider"); - expect(agentSource).not.toContain("@tryopenbot/tools-provider"); + expect(agentSource).not.toContain("@trytilde/dispatch-agent-provider"); + expect(agentSource).not.toContain("@trytilde/dispatch-tools-provider"); expect(agentSource).toContain("AGENT_RESEARCH_ASSISTANT_MCP_SERVER_ID"); expect(agentSource).toContain("tools: await localTools(sessionId)"); expect(agentSource).toContain("createCuaTools"); @@ -89,7 +89,7 @@ describe("agent scaffolding", () => { expect(agentSource).not.toContain("TILDE_BASE_URL"); expect(agentSource).toContain("prepareInference(tools, request.signal, jobModelId)"); expect(agentSource).toContain("HostedInferenceBillingController"); - expect(agentSource).toContain("OPENBOT_HOSTED_INFERENCE_BILLING"); + expect(agentSource).toContain("DISPATCH_HOSTED_INFERENCE_BILLING"); expect(agentSource).toContain("onLanguageModelCallStart"); expect(agentSource).toContain("onLanguageModelCallEnd"); expect(agentSource).toContain("inferenceBilling.preflight"); @@ -158,10 +158,10 @@ describe("agent scaffolding", () => { ); expect( await readFile(join(root, "configuration/agent/skills/create-agent/SKILL.md"), "utf8"), - ).toContain('pnpm openbot new-agent ""'); + ).toContain('pnpm tilde new-agent ""'); expect( - await readFile(join(root, "configuration/agent/skills/develop-openbot/SKILL.md"), "utf8"), - ).toContain("openbot/sandbox-edits"); + await readFile(join(root, "configuration/agent/skills/develop-dispatch/SKILL.md"), "utf8"), + ).toContain("dispatch/sandbox-edits"); // Factory-only skills never scaffold into subagents; subagents get self-edit instead. await expect(access(join(directory, "skills/create-agent/SKILL.md"))).rejects.toMatchObject({ code: "ENOENT", @@ -236,7 +236,7 @@ describe("agent scaffolding", () => { expect(catcherSource).toContain('message.role !== "system"'); expect(catcherSource).toContain("messages: context.messages"); expect(catcherSource).not.toContain("context.session.history()"); - expect(catcherSource).toContain("OPENBOT_HOSTED_INFERENCE_BILLING"); + expect(catcherSource).toContain("DISPATCH_HOSTED_INFERENCE_BILLING"); expect(catcherSource).toContain("onLanguageModelCallStart"); expect(catcherSource).toContain("failForReconciliation"); expect(catcherSource).not.toContain('model: "zai/glm-5.3-flash"'); @@ -297,7 +297,7 @@ describe("agent scaffolding", () => { it("accepts an inference-provider contribution for future agents", async () => { const workspaceRoot = fileURLToPath(new URL("../../", import.meta.url)); - const root = await mkdtemp(join(workspaceRoot, ".openbot-agent-typecheck-")); + const root = await mkdtemp(join(workspaceRoot, ".dispatch-agent-typecheck-")); temporaryDirectories.push(root); await Promise.all( ["tsconfig.base.json", "tsconfig.node.json"].map((name) => @@ -350,13 +350,13 @@ describe("agent scaffolding", () => { it("requires init to seed the fork-owned agent template", async () => { const root = await temporaryRepository(); await expect(scaffoldPrimaryAgent(root, "Factory")).rejects.toThrow( - `${agentTemplateDirectory} is missing; run openbot init`, + `${agentTemplateDirectory} is missing; run tilde init`, ); }); it("materializes a primary agent accepted by the real agent-service typecheck", async () => { const workspaceRoot = fileURLToPath(new URL("../../", import.meta.url)); - const root = await mkdtemp(join(workspaceRoot, ".openbot-agent-typecheck-")); + const root = await mkdtemp(join(workspaceRoot, ".dispatch-agent-typecheck-")); temporaryDirectories.push(root); await Promise.all( ["tsconfig.base.json", "tsconfig.node.json"].map((name) => @@ -398,7 +398,7 @@ describe("agent scaffolding", () => { }); async function temporaryRepository(): Promise { - const path = await mkdtemp(join(tmpdir(), "openbot-agent-scaffold-")); + const path = await mkdtemp(join(tmpdir(), "dispatch-agent-scaffold-")); temporaryDirectories.push(path); return path; } diff --git a/cli/src/agent-scaffold.ts b/cli/src/agent-scaffold.ts index 2a0754c8..34dbffe4 100644 --- a/cli/src/agent-scaffold.ts +++ b/cli/src/agent-scaffold.ts @@ -12,16 +12,16 @@ import { } from "node:fs/promises"; import { dirname, relative, resolve } from "node:path"; import { fileURLToPath } from "node:url"; -import { agentIdFromName, materializeFileTemplate } from "@tryopenbot/utilities"; +import { agentIdFromName, materializeFileTemplate } from "@trytilde/dispatch-utilities"; import { type InferenceAgentTemplateFile, VercelInferenceProvider, -} from "@tryopenbot/inference-provider"; +} from "@trytilde/dispatch-inference-provider"; import { primaryAgentDirectory, primaryAgentId, subagentDirectory, -} from "@tryopenbot/agent-service-provider"; +} from "@trytilde/dispatch-agent-service-provider"; const defaultAgentTemplates = [ ["agent.ts", "./assets/agents/factory/agent.ts.hbs"], @@ -99,8 +99,8 @@ const memoryCatcherTemplates = [ const factoryAgentTemplates = [ ["skills/create-agent/SKILL.md", "./assets/agents/factory/skills/create-agent/SKILL.md.hbs"], [ - "skills/develop-openbot/SKILL.md", - "./assets/agents/factory/skills/develop-openbot/SKILL.md.hbs", + "skills/develop-dispatch/SKILL.md", + "./assets/agents/factory/skills/develop-dispatch/SKILL.md.hbs", ], ] as const; @@ -192,7 +192,7 @@ async function seedTemplateDirectory( return directory; } -export { agentIdFromName } from "@tryopenbot/utilities"; +export { agentIdFromName } from "@trytilde/dispatch-utilities"; /** Materialize one complete authored agent without overwriting an existing directory. */ export async function scaffoldAgent( @@ -336,7 +336,7 @@ async function materializeAgent( async function assertSingularAgentLayout(repositoryRoot: string): Promise { const primary = resolve(repositoryRoot, primaryAgentDirectory); if (!(await exists(primary))) - throw new Error("configuration/agent is missing; run openbot init first"); + throw new Error("configuration/agent is missing; run tilde init first"); await assertOrdinaryDirectory(primary, "Primary agent"); const nested = resolve(repositoryRoot, subagentDirectory); if (await exists(nested)) await assertOrdinaryDirectory(nested, "Subagent collection"); @@ -370,7 +370,7 @@ async function walkAgentTemplates(directory: string): Promise { } catch (error) { if ((error as NodeJS.ErrnoException).code === "ENOENT") throw new Error( - `${agentTemplateDirectory} is missing; run openbot init to scaffold the agent template`, + `${agentTemplateDirectory} is missing; run tilde init to scaffold the agent template`, ); throw error; } diff --git a/cli/src/assets/agents/factory/agent.ts.hbs b/cli/src/assets/agents/factory/agent.ts.hbs index a6b46fcb..5ae7a11f 100644 --- a/cli/src/assets/agents/factory/agent.ts.hbs +++ b/cli/src/assets/agents/factory/agent.ts.hbs @@ -18,7 +18,7 @@ import { createCuaTools, createTildeMediaDownloader, createTildeMediaUploader, -} from "@tryopenbot/computer-tools"; +} from "@trytilde/dispatch-computer-tools"; import { consumeStream, convertToModelMessages, @@ -163,10 +163,10 @@ export default chatKitEndpoint({ objective: requestObjective(context.messages), idempotencyKey: triggerId, budget: { - maxSteps: positiveIntegerEnv("OPENBOT_AGENT_RUN_MAX_STEPS", 500), + maxSteps: positiveIntegerEnv("DISPATCH_AGENT_RUN_MAX_STEPS", 500), maxDurationSeconds: jobBudget?.max_duration_seconds ?? - positiveIntegerEnv("OPENBOT_AGENT_RUN_MAX_SECONDS", 3_600), + positiveIntegerEnv("DISPATCH_AGENT_RUN_MAX_SECONDS", 3_600), maxInputTokens: jobBudget?.max_input_tokens, maxOutputTokens: jobBudget?.max_output_tokens, maxCostMicrousd: jobBudget?.max_cost_microusd, @@ -191,7 +191,7 @@ export default chatKitEndpoint({ if (!ownsRunLease) return Response.json({ status: "run_already_claimed", run_id: currentAgentRun.id }, { status: 202 }); const hostedInferenceBillingEnabled = - process.env.OPENBOT_HOSTED_INFERENCE_BILLING === "1"; + process.env.DISPATCH_HOSTED_INFERENCE_BILLING === "1"; if ( jobBudget?.max_cost_microusd !== undefined && !hostedInferenceBillingEnabled && @@ -255,10 +255,10 @@ export default chatKitEndpoint({ stepId: `${currentAgentRun.generation}:${currentAgentRun.continuationCount + 1}`, effectScope: `continuation:${currentAgentRun.continuationCount + 1}`, estimatedCostMicrousd: positiveIntegerEnv( - "OPENBOT_HOSTED_INFERENCE_RESERVE_MICROUSD", + "DISPATCH_HOSTED_INFERENCE_RESERVE_MICROUSD", 250_000, ), - tags: ["hosted-openbot", `agent:${{{AGENT_ID_JSON}}}`], + tags: ["hosted-dispatch", `agent:${{{AGENT_ID_JSON}}}`], }); const triggerMessageId = context.messages.at(-1)?.id; const automaticMemory = triggerMessageId @@ -301,7 +301,7 @@ export default chatKitEndpoint({ .filter((id): id is string => typeof id === "string" && id.length > 0) .at(-1) : sourceMessageIds.at(-1), - contextWindowTokens: positiveIntegerEnv("OPENBOT_AGENT_CONTEXT_WINDOW_TOKENS", 128_000), + contextWindowTokens: positiveIntegerEnv("DISPATCH_AGENT_CONTEXT_WINDOW_TOKENS", 128_000), }); const providerPrepareStep = "prepareStep" in inference && typeof inference.prepareStep === "function" @@ -496,10 +496,10 @@ function estimateCostMicrousd( required: boolean, ): number { const inputPerMillion = Number( - process.env.OPENBOT_MODEL_INPUT_COST_MICROUSD_PER_MILLION ?? 0, + process.env.DISPATCH_MODEL_INPUT_COST_MICROUSD_PER_MILLION ?? 0, ); const outputPerMillion = Number( - process.env.OPENBOT_MODEL_OUTPUT_COST_MICROUSD_PER_MILLION ?? 0, + process.env.DISPATCH_MODEL_OUTPUT_COST_MICROUSD_PER_MILLION ?? 0, ); if (required && (!(inputPerMillion > 0) || !(outputPerMillion > 0))) throw new Error("cost_meter_unavailable"); @@ -510,8 +510,8 @@ function estimateCostMicrousd( function costMeterAvailable(): boolean { return ( - Number(process.env.OPENBOT_MODEL_INPUT_COST_MICROUSD_PER_MILLION ?? 0) > 0 && - Number(process.env.OPENBOT_MODEL_OUTPUT_COST_MICROUSD_PER_MILLION ?? 0) > 0 + Number(process.env.DISPATCH_MODEL_INPUT_COST_MICROUSD_PER_MILLION ?? 0) > 0 && + Number(process.env.DISPATCH_MODEL_OUTPUT_COST_MICROUSD_PER_MILLION ?? 0) > 0 ); } diff --git a/cli/src/assets/agents/factory/instructions.ts.hbs b/cli/src/assets/agents/factory/instructions.ts.hbs index a29cb555..7727b7b4 100644 --- a/cli/src/assets/agents/factory/instructions.ts.hbs +++ b/cli/src/assets/agents/factory/instructions.ts.hbs @@ -9,7 +9,7 @@ export default [ "## Your tools\n\nYour file, shell, screenshot, connector, and Cua Driver tools (read_file, write_file, bash, glob, grep, screenshot, configure_connector, and friends) are ordinary direct tools: call them immediately with their declared parameters.\n\nSEARCH_TOOLS, GET_TOOL_SCHEMAS, and MULTI_EXECUTE_TOOL only discover and invoke additional live tools from the dynamic registry; never use them for your direct tools, and never invent parameters or successful outcomes. Always fetch a dynamic tool's schema with GET_TOOL_SCHEMAS before invoking it. If a dynamic tool call fails or returns a suspiciously empty result, refetch its schema and compare — this conversation is long-lived and the schema may have gone stale. Before re-running a mutation, first read back whether it already took effect, so you fix a silent no-op without double-firing a call that succeeded.", - "## Changing your Tilde setup\n\nWhen a missing connector, skill, registry, wiki, memory bank, routine, tool, or bot would materially help, explain the exact change and why in ordinary language. Always use propose_self_extension so the user receives a secure Yes/No approval card bound to the exact change, including when their earlier message requested the change; free-text confirmation is not approval. You cannot approve your own request. Stop after proposing, then continue setup and the original task only after the authenticated card decision returns. Provider account choice, OAuth, and credentials always happen through the generic setup card; never request or repeat credential values in chat. Distinguish changing this bot, changing future-bot defaults, and modifying the OpenBot source; never silently widen one into another.", + "## Changing your Tilde setup\n\nWhen a missing connector, skill, registry, wiki, memory bank, routine, tool, or bot would materially help, explain the exact change and why in ordinary language. Always use propose_self_extension so the user receives a secure Yes/No approval card bound to the exact change, including when their earlier message requested the change; free-text confirmation is not approval. You cannot approve your own request. Stop after proposing, then continue setup and the original task only after the authenticated card decision returns. Provider account choice, OAuth, and credentials always happen through the generic setup card; never request or repeat credential values in chat. Distinguish changing this bot, changing future-bot defaults, and modifying the Dispatch source; never silently widen one into another.", "## Goals and tasks\n\nmanage_goals is your durable outcome ledger and manage_tasks is your durable deliverable queue for this conversation. For substantial multi-step work, first list active goals and reuse the matching one after a restart or compaction instead of duplicating it. A goal records the outcome the user expects; a task records independently deliverable work. Use dependencies only when one task truly cannot start before another finishes, and link delegated background work to the task it serves in your own reasoning. Update progress only when it materially changes. Waiting for OAuth or a user decision is input-required, not failure. Mark a task completed only after its result has actually been delivered; mark the goal terminal only when the overall outcome is delivered, genuinely failed, or canceled. Do not narrate ledger mechanics to the user. Skip bookkeeping for ordinary conversation, lookups, and trivial one-step actions.", diff --git a/cli/src/assets/agents/factory/instrumentation.ts.hbs b/cli/src/assets/agents/factory/instrumentation.ts.hbs index 37cd8d52..a2f4a6e6 100644 --- a/cli/src/assets/agents/factory/instrumentation.ts.hbs +++ b/cli/src/assets/agents/factory/instrumentation.ts.hbs @@ -1,4 +1,4 @@ -import { defineInstrumentation } from "@tryopenbot/configuration/instrumentation"; +import { defineInstrumentation } from "@trytilde/dispatch-configuration/instrumentation"; export default defineInstrumentation({ async setup({ agentName }: { agentName: string }): Promise { diff --git a/cli/src/assets/agents/factory/sandbox/workspace/.profile.hbs b/cli/src/assets/agents/factory/sandbox/workspace/.profile.hbs index 69f70aec..93a80b06 100644 --- a/cli/src/assets/agents/factory/sandbox/workspace/.profile.hbs +++ b/cli/src/assets/agents/factory/sandbox/workspace/.profile.hbs @@ -1,4 +1,4 @@ -# OpenBot runs agent Bash tools as login shells with HOME=/workspace/, so this +# Dispatch runs agent Bash tools as login shells with HOME=/workspace/, so this # file is loaded before every command. Put agent-specific environment and shell # setup here. Keep secrets out of authored workspace files. diff --git a/cli/src/assets/agents/factory/skills/create-agent/SKILL.md.hbs b/cli/src/assets/agents/factory/skills/create-agent/SKILL.md.hbs index e840e505..496e4143 100644 --- a/cli/src/assets/agents/factory/skills/create-agent/SKILL.md.hbs +++ b/cli/src/assets/agents/factory/skills/create-agent/SKILL.md.hbs @@ -1,14 +1,14 @@ --- name: create-agent -description: Use when the owner asks to create, scaffold, or add another OpenBot agent in the current source checkout. +description: Use when the owner asks to create, scaffold, or add another Dispatch agent in the current source checkout. --- # Create an agent -From the writable OpenBot repository root at `/workspace/openbot`, run: +From the writable Dispatch repository root at `/workspace/dispatch`, run: ```bash -pnpm openbot new-agent "" +pnpm tilde new-agent "" ``` Let the CLI derive the agent ID and create the complete @@ -30,5 +30,5 @@ agent. If the integration should become a default, update The command also registers the agent with Tilde, so the owner can chat with it immediately; the background orchestrator publishes and redeploys the -project on its own. If this computer does not contain a writable OpenBot +project on its own. If this computer does not contain a writable Dispatch source checkout, report that instead of writing elsewhere. diff --git a/cli/src/assets/agents/factory/skills/develop-openbot/SKILL.md.hbs b/cli/src/assets/agents/factory/skills/develop-dispatch/SKILL.md.hbs similarity index 69% rename from cli/src/assets/agents/factory/skills/develop-openbot/SKILL.md.hbs rename to cli/src/assets/agents/factory/skills/develop-dispatch/SKILL.md.hbs index 16b11f59..683c9eb7 100644 --- a/cli/src/assets/agents/factory/skills/develop-openbot/SKILL.md.hbs +++ b/cli/src/assets/agents/factory/skills/develop-dispatch/SKILL.md.hbs @@ -1,19 +1,19 @@ --- -name: develop-openbot -description: Use when working with the OpenBot source checkout in the trusted development sandbox, locating the repository, running CLI commands, or preparing pull requests. +name: develop-dispatch +description: Use when working with the Dispatch source checkout in the trusted development sandbox, locating the repository, running CLI commands, or preparing pull requests. --- -# Develop OpenBot +# Develop Dispatch Your computer tools run inside the trusted development sandbox. The writable -OpenBot fork lives at `/workspace/openbot` with its full deployment +Dispatch fork lives at `/workspace/dispatch` with its full deployment environment; run repository commands from that directory with `pnpm`. The software lifecycle is automated — never run git pushes or deployment commands for routine work. A background orchestrator watches the checkout: your first edit routes every agent through the local-runtime tunnel with hot reload, and once edits settle it verifies the project, publishes the tree to -the `openbot/sandbox-edits` branch, redeploys agent services, and routes +the `dispatch/sandbox-edits` branch, redeploys agent services, and routes agents back to their deployed endpoints. Just edit files and tell the owner the change is live. @@ -21,7 +21,7 @@ Git is authenticated through the Tilde GitHub reverse proxy (plain `https://github.com/` URLs work for `origin` — the owner's fork — and `upstream`). Never print the git configuration's credential headers. Open a pull request with the GitHub tools on your MCP server only when the owner -explicitly asks for one; the orchestrator's `openbot/sandbox-edits` branch is +explicitly asks for one; the orchestrator's `dispatch/sandbox-edits` branch is the source for it. The deployment environment and decrypted secrets load automatically in login diff --git a/cli/src/assets/agents/factory/tools/await_shell.ts.hbs b/cli/src/assets/agents/factory/tools/await_shell.ts.hbs index bba3c038..db77bea0 100644 --- a/cli/src/assets/agents/factory/tools/await_shell.ts.hbs +++ b/cli/src/assets/agents/factory/tools/await_shell.ts.hbs @@ -1,4 +1,4 @@ -import { createAwaitShellTool } from "@tryopenbot/computer-tools"; +import { createAwaitShellTool } from "@trytilde/dispatch-computer-tools"; // An agent-specific computer overrides the shared computer, e.g. the factory agent's // trusted development sandbox. diff --git a/cli/src/assets/agents/factory/tools/bash.ts.hbs b/cli/src/assets/agents/factory/tools/bash.ts.hbs index 1ca4cb93..2f0959f2 100644 --- a/cli/src/assets/agents/factory/tools/bash.ts.hbs +++ b/cli/src/assets/agents/factory/tools/bash.ts.hbs @@ -1,4 +1,4 @@ -import { createBashTool } from "@tryopenbot/computer-tools"; +import { createBashTool } from "@trytilde/dispatch-computer-tools"; // An agent-specific computer overrides the shared computer, e.g. the factory agent's // trusted development sandbox. diff --git a/cli/src/assets/agents/factory/tools/configure_connector.ts.hbs b/cli/src/assets/agents/factory/tools/configure_connector.ts.hbs index d07820ae..919b7e1e 100644 --- a/cli/src/assets/agents/factory/tools/configure_connector.ts.hbs +++ b/cli/src/assets/agents/factory/tools/configure_connector.ts.hbs @@ -1,4 +1,4 @@ -import { createConfigureConnectorTool } from "@tryopenbot/connector-tools"; +import { createConfigureConnectorTool } from "@trytilde/dispatch-connector-tools"; export default createConfigureConnectorTool({ apiKey: () => process.env.AGENT_{{AGENT_ENV_PREFIX}}_API_KEY!, diff --git a/cli/src/assets/agents/factory/tools/copy_from_computer.ts.hbs b/cli/src/assets/agents/factory/tools/copy_from_computer.ts.hbs index 86f80bd1..5e605729 100644 --- a/cli/src/assets/agents/factory/tools/copy_from_computer.ts.hbs +++ b/cli/src/assets/agents/factory/tools/copy_from_computer.ts.hbs @@ -1,4 +1,4 @@ -import { createCopyFromComputerTool, type MediaUploader } from "@tryopenbot/computer-tools"; +import { createCopyFromComputerTool, type MediaUploader } from "@trytilde/dispatch-computer-tools"; // An agent-specific computer overrides the shared computer, e.g. the factory agent's // trusted development sandbox. diff --git a/cli/src/assets/agents/factory/tools/copy_to_computer.ts.hbs b/cli/src/assets/agents/factory/tools/copy_to_computer.ts.hbs index 575601ab..464eb1cf 100644 --- a/cli/src/assets/agents/factory/tools/copy_to_computer.ts.hbs +++ b/cli/src/assets/agents/factory/tools/copy_to_computer.ts.hbs @@ -1,4 +1,4 @@ -import { createCopyToComputerTool, type MediaDownloader } from "@tryopenbot/computer-tools"; +import { createCopyToComputerTool, type MediaDownloader } from "@trytilde/dispatch-computer-tools"; // An agent-specific computer overrides the shared computer, e.g. the factory agent's // trusted development sandbox. diff --git a/cli/src/assets/agents/factory/tools/glob.ts.hbs b/cli/src/assets/agents/factory/tools/glob.ts.hbs index 1175a642..829b8f48 100644 --- a/cli/src/assets/agents/factory/tools/glob.ts.hbs +++ b/cli/src/assets/agents/factory/tools/glob.ts.hbs @@ -1,4 +1,4 @@ -import { createGlobTool } from "@tryopenbot/computer-tools"; +import { createGlobTool } from "@trytilde/dispatch-computer-tools"; // An agent-specific computer overrides the shared computer, e.g. the factory agent's // trusted development sandbox. diff --git a/cli/src/assets/agents/factory/tools/grep.ts.hbs b/cli/src/assets/agents/factory/tools/grep.ts.hbs index 85a73dd6..190e0379 100644 --- a/cli/src/assets/agents/factory/tools/grep.ts.hbs +++ b/cli/src/assets/agents/factory/tools/grep.ts.hbs @@ -1,4 +1,4 @@ -import { createGrepTool } from "@tryopenbot/computer-tools"; +import { createGrepTool } from "@trytilde/dispatch-computer-tools"; // An agent-specific computer overrides the shared computer, e.g. the factory agent's // trusted development sandbox. diff --git a/cli/src/assets/agents/factory/tools/read_file.ts.hbs b/cli/src/assets/agents/factory/tools/read_file.ts.hbs index fe5db4c9..32997d46 100644 --- a/cli/src/assets/agents/factory/tools/read_file.ts.hbs +++ b/cli/src/assets/agents/factory/tools/read_file.ts.hbs @@ -1,4 +1,4 @@ -import { createReadFileTool } from "@tryopenbot/computer-tools"; +import { createReadFileTool } from "@trytilde/dispatch-computer-tools"; // An agent-specific computer overrides the shared computer, e.g. the factory agent's // trusted development sandbox. diff --git a/cli/src/assets/agents/factory/tools/screenshot.ts.hbs b/cli/src/assets/agents/factory/tools/screenshot.ts.hbs index bd985fe6..c3f0c7d0 100644 --- a/cli/src/assets/agents/factory/tools/screenshot.ts.hbs +++ b/cli/src/assets/agents/factory/tools/screenshot.ts.hbs @@ -1,4 +1,4 @@ -import { createScreenshotTool, type MediaUploader } from "@tryopenbot/computer-tools"; +import { createScreenshotTool, type MediaUploader } from "@trytilde/dispatch-computer-tools"; // An agent-specific computer overrides the shared computer, e.g. the factory agent's // trusted development sandbox. diff --git a/cli/src/assets/agents/factory/tools/write_file.ts.hbs b/cli/src/assets/agents/factory/tools/write_file.ts.hbs index 17d7d503..3fc4f8ed 100644 --- a/cli/src/assets/agents/factory/tools/write_file.ts.hbs +++ b/cli/src/assets/agents/factory/tools/write_file.ts.hbs @@ -1,4 +1,4 @@ -import { createWriteFileTool } from "@tryopenbot/computer-tools"; +import { createWriteFileTool } from "@trytilde/dispatch-computer-tools"; // An agent-specific computer overrides the shared computer, e.g. the factory agent's // trusted development sandbox. diff --git a/cli/src/assets/agents/instrumentation.ts.hbs b/cli/src/assets/agents/instrumentation.ts.hbs index 37cd8d52..a2f4a6e6 100644 --- a/cli/src/assets/agents/instrumentation.ts.hbs +++ b/cli/src/assets/agents/instrumentation.ts.hbs @@ -1,4 +1,4 @@ -import { defineInstrumentation } from "@tryopenbot/configuration/instrumentation"; +import { defineInstrumentation } from "@trytilde/dispatch-configuration/instrumentation"; export default defineInstrumentation({ async setup({ agentName }: { agentName: string }): Promise { diff --git a/cli/src/assets/agents/memory-catcher/agent.ts.hbs b/cli/src/assets/agents/memory-catcher/agent.ts.hbs index b8ac2618..ded1d4bb 100644 --- a/cli/src/assets/agents/memory-catcher/agent.ts.hbs +++ b/cli/src/assets/agents/memory-catcher/agent.ts.hbs @@ -52,14 +52,14 @@ export default chatKitEndpoint({ agentId: {{{AGENT_ID_JSON}}}, webhookId: context.webhookId, messages: context.messages, - billingEnabled: process.env.OPENBOT_HOSTED_INFERENCE_BILLING === "1", + billingEnabled: process.env.DISPATCH_HOSTED_INFERENCE_BILLING === "1", validateBatch: (input) => client.memory.synthesisSession(context.sessionId).validateBatch(input), estimatedCostMicrousd: positiveIntegerEnv( - "OPENBOT_HOSTED_INFERENCE_RESERVE_MICROUSD", + "DISPATCH_HOSTED_INFERENCE_RESERVE_MICROUSD", 250_000, ), - tags: ["hosted-openbot", "agent:memory-catcher", "purpose:memory-synthesis"], + tags: ["hosted-dispatch", "agent:memory-catcher", "purpose:memory-synthesis"], }); } catch (error) { await mcp.closeMcp(); diff --git a/cli/src/assets/agents/shared/skills/tilde-control-plane/SKILL.md.hbs b/cli/src/assets/agents/shared/skills/tilde-control-plane/SKILL.md.hbs index 27ad4158..6f836319 100644 --- a/cli/src/assets/agents/shared/skills/tilde-control-plane/SKILL.md.hbs +++ b/cli/src/assets/agents/shared/skills/tilde-control-plane/SKILL.md.hbs @@ -5,7 +5,7 @@ description: Orientation to the Tilde control-plane tool families available on t # The Tilde control plane -Every OpenBot agent's MCP server carries the team-scoped Tilde control-plane toolkit (`tilde_*`). Ground rules: +Every Dispatch agent's MCP server carries the team-scoped Tilde control-plane toolkit (`tilde_*`). Ground rules: - Team-scoped: never pass `org_id` or `team_id` arguments; the workspace is inferred. - Never guess identifiers (`tool_group_source_type_id`, `credential_source_type_id`, instance ids); take them from search results. diff --git a/cli/src/assets/agents/shared/skills/tilde-dev-tunnels/SKILL.md.hbs b/cli/src/assets/agents/shared/skills/tilde-dev-tunnels/SKILL.md.hbs index 10aa7cbc..32900a16 100644 --- a/cli/src/assets/agents/shared/skills/tilde-dev-tunnels/SKILL.md.hbs +++ b/cli/src/assets/agents/shared/skills/tilde-dev-tunnels/SKILL.md.hbs @@ -14,10 +14,10 @@ Your `tilde_*` tools are team-scoped: never pass `org_id` or `team_id` arguments ## Local CLI steps for the human ```bash -pnpm exec openbot auth login -pnpm exec openbot tunnel -- pnpm dev +pnpm exec tilde auth login +pnpm exec tilde tunnel -- pnpm dev ``` -Replace `pnpm dev` with the app's normal dev command; `pnpm exec openbot auth set-team` fixes a wrong team. The CLI passes the chosen port as `PORT` and `TUNNEL_PORT`, and the process must stay running while Tilde delivers ChatKit messages, webhooks, and tool invocations. +Replace `pnpm dev` with the app's normal dev command; `pnpm exec tilde auth set-team` fixes a wrong team. The CLI passes the chosen port as `PORT` and `TUNNEL_PORT`, and the process must stay running while Tilde delivers ChatKit messages, webhooks, and tool invocations. Warn the user: the tunnel exposes every route served by the dev process to the public internet — disable or protect unrelated routes. Signed Harness SDK wrappers such as `chatKitEndpoint` reject requests without a valid Tilde signature, but that protects only the wrapped endpoint. diff --git a/cli/src/assets/agents/subagent/skills/self-edit/SKILL.md.hbs b/cli/src/assets/agents/subagent/skills/self-edit/SKILL.md.hbs index 8f5a79a7..b0e2f74c 100644 --- a/cli/src/assets/agents/subagent/skills/self-edit/SKILL.md.hbs +++ b/cli/src/assets/agents/subagent/skills/self-edit/SKILL.md.hbs @@ -5,8 +5,8 @@ description: Use when the owner asks you to change your own instructions, person # Edit yourself -Your authored source lives in the OpenBot checkout at -`/workspace/openbot/configuration/agent/subagents/{{AGENT_ID}}`: +Your authored source lives in the Dispatch checkout at +`/workspace/dispatch/configuration/agent/subagents/{{AGENT_ID}}`: - `instructions.ts` — your system instructions and persona. Edit this to change how you behave. diff --git a/cli/src/assets/configuration/exe-dev.ts.hbs b/cli/src/assets/configuration/exe-dev.ts.hbs index 2d171d52..44620194 100644 --- a/cli/src/assets/configuration/exe-dev.ts.hbs +++ b/cli/src/assets/configuration/exe-dev.ts.hbs @@ -1,11 +1,11 @@ -import { TildeAgentProvider } from "@tryopenbot/agent-provider"; -import { ExeDevRuntimeServiceProvider } from "@tryopenbot/agent-service-provider"; -import { TildeAuthProvider } from "@tryopenbot/auth-provider"; -import { Configuration } from "@tryopenbot/configuration"; -import { ExeDevComputerProvider } from "@tryopenbot/computer-service-provider"; -import { CodeStorageGitProvider } from "@tryopenbot/git-provider"; -import { {{#if CODEX_INFERENCE}}CodexInferenceProvider{{else}}VercelInferenceProvider{{/if}} } from "@tryopenbot/inference-provider"; -import { ExeDevPlatform, TildePlatform{{#unless CODEX_INFERENCE}}, VercelPlatform{{/unless}} } from "@tryopenbot/platform-integrations"; +import { TildeAgentProvider } from "@trytilde/dispatch-agent-provider"; +import { ExeDevRuntimeServiceProvider } from "@trytilde/dispatch-agent-service-provider"; +import { TildeAuthProvider } from "@trytilde/dispatch-auth-provider"; +import { Configuration } from "@trytilde/dispatch-configuration"; +import { ExeDevComputerProvider } from "@trytilde/dispatch-computer-service-provider"; +import { CodeStorageGitProvider } from "@trytilde/dispatch-git-provider"; +import { {{#if CODEX_INFERENCE}}CodexInferenceProvider{{else}}VercelInferenceProvider{{/if}} } from "@trytilde/dispatch-inference-provider"; +import { ExeDevPlatform, TildePlatform{{#unless CODEX_INFERENCE}}, VercelPlatform{{/unless}} } from "@trytilde/dispatch-platform-integrations"; const tilde = new TildePlatform({ apiKey: process.env.TILDE_API_KEY!, diff --git a/cli/src/assets/configuration/local.ts.hbs b/cli/src/assets/configuration/local.ts.hbs index f3606aab..7454bb7e 100644 --- a/cli/src/assets/configuration/local.ts.hbs +++ b/cli/src/assets/configuration/local.ts.hbs @@ -1,11 +1,11 @@ -import { TildeAgentProvider } from "@tryopenbot/agent-provider"; -import { LocalRuntimeServiceProvider } from "@tryopenbot/agent-service-provider"; -import { TildeAuthProvider } from "@tryopenbot/auth-provider"; -import { Configuration } from "@tryopenbot/configuration"; -import { MicrosandboxComputerProvider } from "@tryopenbot/computer-service-provider"; -import { GitHubGitProvider } from "@tryopenbot/git-provider"; -import { {{#if CODEX_INFERENCE}}CodexInferenceProvider{{else}}VercelInferenceProvider{{/if}} } from "@tryopenbot/inference-provider"; -import { TildePlatform{{#unless CODEX_INFERENCE}}, VercelPlatform{{/unless}} } from "@tryopenbot/platform-integrations"; +import { TildeAgentProvider } from "@trytilde/dispatch-agent-provider"; +import { LocalRuntimeServiceProvider } from "@trytilde/dispatch-agent-service-provider"; +import { TildeAuthProvider } from "@trytilde/dispatch-auth-provider"; +import { Configuration } from "@trytilde/dispatch-configuration"; +import { MicrosandboxComputerProvider } from "@trytilde/dispatch-computer-service-provider"; +import { GitHubGitProvider } from "@trytilde/dispatch-git-provider"; +import { {{#if CODEX_INFERENCE}}CodexInferenceProvider{{else}}VercelInferenceProvider{{/if}} } from "@trytilde/dispatch-inference-provider"; +import { TildePlatform{{#unless CODEX_INFERENCE}}, VercelPlatform{{/unless}} } from "@trytilde/dispatch-platform-integrations"; const tilde = new TildePlatform({ apiKey: process.env.TILDE_API_KEY!, diff --git a/cli/src/assets/configuration/tilde-cloud.ts.hbs b/cli/src/assets/configuration/tilde-cloud.ts.hbs index 5e3fb2f0..ec7120fd 100644 --- a/cli/src/assets/configuration/tilde-cloud.ts.hbs +++ b/cli/src/assets/configuration/tilde-cloud.ts.hbs @@ -1,11 +1,11 @@ -import { TildeAgentProvider } from "@tryopenbot/agent-provider"; -import { VercelRuntimeServiceProvider } from "@tryopenbot/agent-service-provider"; -import { TildeAuthProvider } from "@tryopenbot/auth-provider"; -import { Configuration } from "@tryopenbot/configuration"; -import { VercelSandboxComputerProvider } from "@tryopenbot/computer-service-provider"; -import { LocalGitProvider } from "@tryopenbot/git-provider"; -import { VercelInferenceProvider } from "@tryopenbot/inference-provider"; -import { TildePlatform, VercelPlatform } from "@tryopenbot/platform-integrations"; +import { TildeAgentProvider } from "@trytilde/dispatch-agent-provider"; +import { VercelRuntimeServiceProvider } from "@trytilde/dispatch-agent-service-provider"; +import { TildeAuthProvider } from "@trytilde/dispatch-auth-provider"; +import { Configuration } from "@trytilde/dispatch-configuration"; +import { VercelSandboxComputerProvider } from "@trytilde/dispatch-computer-service-provider"; +import { LocalGitProvider } from "@trytilde/dispatch-git-provider"; +import { VercelInferenceProvider } from "@trytilde/dispatch-inference-provider"; +import { TildePlatform, VercelPlatform } from "@trytilde/dispatch-platform-integrations"; const tilde = new TildePlatform({ apiKey: process.env.TILDE_API_KEY!, diff --git a/cli/src/assets/configuration/vercel.ts.hbs b/cli/src/assets/configuration/vercel.ts.hbs index 30f29e62..d24e88ab 100644 --- a/cli/src/assets/configuration/vercel.ts.hbs +++ b/cli/src/assets/configuration/vercel.ts.hbs @@ -1,11 +1,11 @@ -import { TildeAgentProvider } from "@tryopenbot/agent-provider"; -import { VercelRuntimeServiceProvider } from "@tryopenbot/agent-service-provider"; -import { TildeAuthProvider } from "@tryopenbot/auth-provider"; -import { Configuration } from "@tryopenbot/configuration"; -import { VercelSandboxComputerProvider } from "@tryopenbot/computer-service-provider"; -import { GitHubGitProvider } from "@tryopenbot/git-provider"; -import { {{#if CODEX_INFERENCE}}CodexInferenceProvider{{else}}VercelInferenceProvider{{/if}} } from "@tryopenbot/inference-provider"; -import { TildePlatform, VercelPlatform } from "@tryopenbot/platform-integrations"; +import { TildeAgentProvider } from "@trytilde/dispatch-agent-provider"; +import { VercelRuntimeServiceProvider } from "@trytilde/dispatch-agent-service-provider"; +import { TildeAuthProvider } from "@trytilde/dispatch-auth-provider"; +import { Configuration } from "@trytilde/dispatch-configuration"; +import { VercelSandboxComputerProvider } from "@trytilde/dispatch-computer-service-provider"; +import { GitHubGitProvider } from "@trytilde/dispatch-git-provider"; +import { {{#if CODEX_INFERENCE}}CodexInferenceProvider{{else}}VercelInferenceProvider{{/if}} } from "@trytilde/dispatch-inference-provider"; +import { TildePlatform, VercelPlatform } from "@trytilde/dispatch-platform-integrations"; const tilde = new TildePlatform({ apiKey: process.env.TILDE_API_KEY!, diff --git a/cli/src/commands/connect.ts b/cli/src/commands/connect.ts index 1f4e679c..58785726 100644 --- a/cli/src/commands/connect.ts +++ b/cli/src/commands/connect.ts @@ -15,7 +15,7 @@ export async function runConnect(argv: readonly string[]): Promise { ); const [name] = options._; if (!name) { - console.error("Usage: openbot connect [--print] [--no-desktop]"); + console.error("Usage: tilde connect [--print] [--no-desktop]"); return 1; } const host = resolveHost(name, loadHosts(repositoryRoot())); diff --git a/cli/src/commands/deploy.test.ts b/cli/src/commands/deploy.test.ts index 4eaab16e..2dbcae4e 100644 --- a/cli/src/commands/deploy.test.ts +++ b/cli/src/commands/deploy.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from "vite-plus/test"; -import { buildProviders, type DeploymentContext } from "@tryopenbot/runtime-provider"; +import { buildProviders, type DeploymentContext } from "@trytilde/dispatch-runtime-provider"; import { agentEndpointCutoverOrigins, deploymentScope, @@ -114,22 +114,22 @@ describe("deploy-prod", () => { expect( agentEndpointCutoverOrigins({ consolidatedRuntime: true, - environment: { AGENT_SERVICE_ORIGIN: "https://openbot-agents.vercel.app/" }, - targetOrigin: "https://openbot-runtime.vercel.app/", + environment: { AGENT_SERVICE_ORIGIN: "https://dispatch-agents.vercel.app/" }, + targetOrigin: "https://dispatch-runtime.vercel.app/", }), ).toEqual({ - preparationOrigin: "https://openbot-agents.vercel.app", - targetOrigin: "https://openbot-runtime.vercel.app", + preparationOrigin: "https://dispatch-agents.vercel.app", + targetOrigin: "https://dispatch-runtime.vercel.app", }); expect( agentEndpointCutoverOrigins({ consolidatedRuntime: false, environment: { AGENT_SERVICE_ORIGIN: "https://stale.example" }, - targetOrigin: "https://openbot-agents.vercel.app", + targetOrigin: "https://dispatch-agents.vercel.app", }), ).toEqual({ - preparationOrigin: "https://openbot-agents.vercel.app", - targetOrigin: "https://openbot-agents.vercel.app", + preparationOrigin: "https://dispatch-agents.vercel.app", + targetOrigin: "https://dispatch-agents.vercel.app", }); }); }); diff --git a/cli/src/commands/deploy.ts b/cli/src/commands/deploy.ts index f65c40a3..6bfee568 100644 --- a/cli/src/commands/deploy.ts +++ b/cli/src/commands/deploy.ts @@ -1,14 +1,14 @@ import { resolve } from "node:path"; import arg from "arg"; -import type { OpenBotConfiguration } from "@tryopenbot/configuration"; -import { discoverAgentWorkspaces } from "@tryopenbot/agent-service-provider"; +import type { DispatchConfiguration } from "@trytilde/dispatch-configuration"; +import { discoverAgentWorkspaces } from "@trytilde/dispatch-agent-service-provider"; import { buildProviders, deployProviders, type DeploymentContext, type DeploymentEvent, type DeploymentParticipant, -} from "@tryopenbot/runtime-provider"; +} from "@trytilde/dispatch-runtime-provider"; import { discoveredAgentIds, persistAgentSandboxUrls, @@ -49,9 +49,9 @@ export function deploymentScope( } export function serviceDeploymentParticipants(options: { - agentService: OpenBotConfiguration["providers"]["agentService"]; - controlService: OpenBotConfiguration["providers"]["controlService"]; - inference: OpenBotConfiguration["providers"]["inference"]; + agentService: DispatchConfiguration["providers"]["agentService"]; + controlService: DispatchConfiguration["providers"]["controlService"]; + inference: DispatchConfiguration["providers"]["inference"]; deployAgents: boolean; consolidatedRuntime: boolean; }): DeploymentParticipant[] { @@ -158,9 +158,9 @@ export async function runProductionDeploy(argv: readonly string[]): Promise ({ - summary: "Seed or resume the trusted OpenBot development sandbox", + summary: "Seed or resume the trusted Dispatch development sandbox", steps: [ "Preserve its mutable source tree", "Install the aggregate deployment environment and SOPS identity", @@ -327,10 +327,10 @@ export async function runProductionDeploy(argv: readonly string[]): Promise { +async function loadRepositoryConfiguration(): Promise { const path = resolve(repositoryRoot, "configuration/index.ts"); - const module = await loadConfigurationModule<{ default?: OpenBotConfiguration }>(path); + const module = await loadConfigurationModule<{ default?: DispatchConfiguration }>(path); if (!module.default) - throw new Error("configuration/index.ts must export the OpenBot configuration as default"); + throw new Error("configuration/index.ts must export the Dispatch configuration as default"); return module.default; } diff --git a/cli/src/commands/desktop/dev.ts b/cli/src/commands/desktop/dev.ts index 0abc05d9..3deecb7f 100644 --- a/cli/src/commands/desktop/dev.ts +++ b/cli/src/commands/desktop/dev.ts @@ -2,7 +2,7 @@ // // On a machine with a display this simply opens a window. On a display-less host — // the remote Linux build box — Electron gets a virtual screen published over loopback -// VNC. Reach it with `openbot connect `. +// VNC. Reach it with `tilde connect `. import { spawn } from "node:child_process"; import arg from "arg"; import { ensureVirtualScreen, ensureVncServer, hasNativeDisplay } from "../../virtual-display.js"; @@ -31,11 +31,11 @@ export async function runDesktopDev(argv: readonly string[]): Promise { }); await ensureVncServer({ displayNumber, vncPort }); console.log( - `electron will render on :${displayNumber}; view it with openbot connect (VNC ${vncPort})`, + `electron will render on :${displayNumber}; view it with tilde connect (VNC ${vncPort})`, ); } - return spawnPnpm(["--filter", "@tryopenbot/desktop", "dev"], environment); + return spawnPnpm(["--filter", "@trytilde/dispatch-desktop", "dev"], environment); } function spawnPnpm(args: readonly string[], environment: Record): Promise { diff --git a/cli/src/commands/desktop/index.ts b/cli/src/commands/desktop/index.ts index 5047f9f2..a565d287 100644 --- a/cli/src/commands/desktop/index.ts +++ b/cli/src/commands/desktop/index.ts @@ -19,7 +19,7 @@ export async function runDesktop(rest: readonly string[]): Promise { return runRelease(args); default: console.error( - `Usage: openbot desktop <${desktopSubcommands.map(([name]) => name.split(" ")[0]).join("|")}>`, + `Usage: tilde desktop <${desktopSubcommands.map(([name]) => name.split(" ")[0]).join("|")}>`, ); return 1; } diff --git a/cli/src/commands/desktop/package.ts b/cli/src/commands/desktop/package.ts index 8a2c9835..d48c00d8 100644 --- a/cli/src/commands/desktop/package.ts +++ b/cli/src/commands/desktop/package.ts @@ -1,11 +1,11 @@ // Packages the Electron app. Electron Builder targets the host platform, so a mac -// build must run on a mac and a Linux build on Linux; `openbot remote desktop` +// build must run on a mac and a Linux build on Linux; `tilde remote desktop` // covers the cross-platform case. import { spawn } from "node:child_process"; import { repositoryRoot } from "../../workspace.js"; export async function runDesktopPackage(args: readonly string[]): Promise { - const child = spawn("pnpm", ["--filter", "@tryopenbot/desktop", "package", ...args], { + const child = spawn("pnpm", ["--filter", "@trytilde/dispatch-desktop", "package", ...args], { cwd: repositoryRoot(), stdio: "inherit", }); diff --git a/cli/src/commands/desktop/release.test.ts b/cli/src/commands/desktop/release.test.ts index 7917ac34..ecc98c64 100644 --- a/cli/src/commands/desktop/release.test.ts +++ b/cli/src/commands/desktop/release.test.ts @@ -15,67 +15,67 @@ describe("resolveTarget", () => { it("defaults to the official bucket and nests the channel under the prefix", () => { const target = resolveTarget("latest"); expect(target.bucket).toBe(officialBucket); - expect(target.prefix).toBe("desktop/openbot/latest"); + expect(target.prefix).toBe("desktop/dispatch/latest"); expect(target.baseUrl).toBe( - `https://${officialBucket}.s3.us-east-1.amazonaws.com/desktop/openbot/latest`, + `https://${officialBucket}.s3.us-east-1.amazonaws.com/desktop/dispatch/latest`, ); }); // An unset `vars.DESKTOP_UPDATES_S3_BUCKET` arrives as "", which `??` would accept // and resolve the bucket to an empty string. it("falls back to the official bucket when the override is set but empty", () => { - process.env.OPENBOT_DESKTOP_UPDATES_BUCKET = ""; - process.env.OPENBOT_DESKTOP_UPDATES_PREFIX = ""; - process.env.OPENBOT_DESKTOP_UPDATES_BASE_URL = ""; + process.env.DISPATCH_DESKTOP_UPDATES_BUCKET = ""; + process.env.DISPATCH_DESKTOP_UPDATES_PREFIX = ""; + process.env.DISPATCH_DESKTOP_UPDATES_BASE_URL = ""; try { const target = resolveTarget("latest"); expect(target.bucket).toBe(officialBucket); - expect(target.prefix).toBe("desktop/openbot/latest"); + expect(target.prefix).toBe("desktop/dispatch/latest"); expect(target.baseUrl).toContain(officialBucket); } finally { - delete process.env.OPENBOT_DESKTOP_UPDATES_BUCKET; - delete process.env.OPENBOT_DESKTOP_UPDATES_PREFIX; - delete process.env.OPENBOT_DESKTOP_UPDATES_BASE_URL; + delete process.env.DISPATCH_DESKTOP_UPDATES_BUCKET; + delete process.env.DISPATCH_DESKTOP_UPDATES_PREFIX; + delete process.env.DISPATCH_DESKTOP_UPDATES_BASE_URL; } }); it("lets a fork redirect the bucket, prefix, and public base url", () => { - process.env.OPENBOT_DESKTOP_UPDATES_BUCKET = "a-fork-bucket"; - process.env.OPENBOT_DESKTOP_UPDATES_PREFIX = "/builds/"; - process.env.OPENBOT_DESKTOP_UPDATES_BASE_URL = "https://downloads.example.test/"; + process.env.DISPATCH_DESKTOP_UPDATES_BUCKET = "a-fork-bucket"; + process.env.DISPATCH_DESKTOP_UPDATES_PREFIX = "/builds/"; + process.env.DISPATCH_DESKTOP_UPDATES_BASE_URL = "https://downloads.example.test/"; try { const target = resolveTarget("beta"); expect(target.bucket).toBe("a-fork-bucket"); expect(target.prefix).toBe("builds/beta"); expect(target.baseUrl).toBe("https://downloads.example.test/builds/beta"); } finally { - delete process.env.OPENBOT_DESKTOP_UPDATES_BUCKET; - delete process.env.OPENBOT_DESKTOP_UPDATES_PREFIX; - delete process.env.OPENBOT_DESKTOP_UPDATES_BASE_URL; + delete process.env.DISPATCH_DESKTOP_UPDATES_BUCKET; + delete process.env.DISPATCH_DESKTOP_UPDATES_PREFIX; + delete process.env.DISPATCH_DESKTOP_UPDATES_BASE_URL; } }); }); describe("resolveAppId", () => { it("defaults to the publisher's identifier", () => { - expect(resolveAppId()).toBe("ai.trytilde.openbot"); + expect(resolveAppId()).toBe("ai.trytilde.dispatch"); }); - it("honours the OPENBOT_APP_ID a fork sets for desktop", () => { - process.env.OPENBOT_APP_ID = "com.example.fork"; + it("honours the DISPATCH_APP_ID a fork sets for desktop", () => { + process.env.DISPATCH_APP_ID = "com.example.fork"; try { expect(resolveAppId()).toBe("com.example.fork"); } finally { - delete process.env.OPENBOT_APP_ID; + delete process.env.DISPATCH_APP_ID; } }); it("falls back when the override is set but empty", () => { - process.env.OPENBOT_APP_ID = ""; + process.env.DISPATCH_APP_ID = ""; try { - expect(resolveAppId()).toBe("ai.trytilde.openbot"); + expect(resolveAppId()).toBe("ai.trytilde.dispatch"); } finally { - delete process.env.OPENBOT_APP_ID; + delete process.env.DISPATCH_APP_ID; } }); }); @@ -86,7 +86,7 @@ describe("publicationGuard", () => { it("refuses the official bucket from a fork and names the override", () => { const message = publicationGuard(forkCheckout(), officialBucket); expect(message).toContain("Refusing to publish"); - expect(message).toContain("OPENBOT_DESKTOP_UPDATES_BUCKET"); + expect(message).toContain("DISPATCH_DESKTOP_UPDATES_BUCKET"); }); it("allows a fork that publishes to its own bucket", () => { @@ -96,13 +96,13 @@ describe("publicationGuard", () => { describe("artifactKind", () => { it("recognises the installable artifacts and ignores builder debris", () => { - expect(artifactKind("OpenBot-0.2.0-mac-arm64.dmg")).toBe("dmg"); - expect(artifactKind("OpenBot-0.2.0-mac-arm64.zip")).toBe("zip"); - expect(artifactKind("OpenBot-0.2.0-linux-x86_64.AppImage")).toBe("appimage"); - expect(artifactKind("OpenBot-0.2.0-linux-amd64.deb")).toBe("deb"); - expect(artifactKind("OpenBot-0.2.0-mac-arm64.zip.blockmap")).toBeUndefined(); + expect(artifactKind("Dispatch-0.2.0-mac-arm64.dmg")).toBe("dmg"); + expect(artifactKind("Dispatch-0.2.0-mac-arm64.zip")).toBe("zip"); + expect(artifactKind("Dispatch-0.2.0-linux-x86_64.AppImage")).toBe("appimage"); + expect(artifactKind("Dispatch-0.2.0-linux-amd64.deb")).toBe("deb"); + expect(artifactKind("Dispatch-0.2.0-mac-arm64.zip.blockmap")).toBeUndefined(); expect(artifactKind("latest-mac.yml")).toBeUndefined(); - expect(artifactKind(".openbot-release-state.json")).toBeUndefined(); + expect(artifactKind(".dispatch-release-state.json")).toBeUndefined(); }); }); @@ -113,15 +113,15 @@ describe("platformEntry", () => { releasedAt: "2026-08-19T09:00:00.000Z", signed: true, notarized: true, - baseUrl: "https://downloads.example.test/desktop/openbot/latest", + baseUrl: "https://downloads.example.test/desktop/dispatch/latest", files: [ - { name: "OpenBot-0.2.0-mac-arm64.dmg", size: 10, sha512: "aaa" }, - { name: "OpenBot-0.2.0-mac-arm64.zip.blockmap", size: 1, sha512: "bbb" }, + { name: "Dispatch-0.2.0-mac-arm64.dmg", size: 10, sha512: "aaa" }, + { name: "Dispatch-0.2.0-mac-arm64.zip.blockmap", size: 1, sha512: "bbb" }, ], }); expect(entry.artifacts).toHaveLength(1); expect(entry.artifacts[0]?.url).toBe( - "https://downloads.example.test/desktop/openbot/latest/OpenBot-0.2.0-mac-arm64.dmg", + "https://downloads.example.test/desktop/dispatch/latest/Dispatch-0.2.0-mac-arm64.dmg", ); expect(entry.notarized).toBe(true); }); @@ -207,5 +207,5 @@ function entryFor(version: string) { /** A checkout whose `origin` is not the upstream repository. */ function forkCheckout(): string { - return "/nonexistent-openbot-fork-checkout"; + return "/nonexistent-dispatch-fork-checkout"; } diff --git a/cli/src/commands/desktop/release.ts b/cli/src/commands/desktop/release.ts index 78a83793..32b2903b 100644 --- a/cli/src/commands/desktop/release.ts +++ b/cli/src/commands/desktop/release.ts @@ -1,4 +1,4 @@ -// Publication of the OpenBot desktop app to the shared app-updates bucket. +// Publication of the Dispatch desktop app to the shared app-updates bucket. // // Official publication is upstream-only; forks select their own bucket (ADR-0028). // A fork inherits every tracked file, so the official bucket name sitting in this @@ -24,16 +24,16 @@ import { repositoryRoot } from "../../workspace.js"; /** * The shared Tilde bucket, defined in infrastructure-terraform/shared/app_updates.tf. - * It already carries Tilde's own Electrobun feed under `desktop/`, so OpenBot takes a + * It already carries Tilde's own Electrobun feed under `desktop/`, so Dispatch takes a * nested prefix; public read is granted to `desktop/*` and therefore covers it. */ const officialUpdatesBucket = "tilde-app-updates-prod"; /** * Reverse-DNS of the publisher, not of the product or platform. A fork may override it - * through OPENBOT_APP_ID. + * through DISPATCH_APP_ID. */ -const officialAppId = "ai.trytilde.openbot"; -const officialUpdatesPrefix = "desktop/openbot"; +const officialAppId = "ai.trytilde.dispatch"; +const officialUpdatesPrefix = "desktop/dispatch"; const officialUpdatesRegion = "us-east-1"; export const releaseSubcommands: readonly (readonly [string, string])[] = [ @@ -45,7 +45,7 @@ export const releaseSubcommands: readonly (readonly [string, string])[] = [ /** The Electron appId, defaulting to the official identifier. */ export function resolveAppId(): string { - return optionalEnvironment("OPENBOT_APP_ID") ?? officialAppId; + return optionalEnvironment("DISPATCH_APP_ID") ?? officialAppId; } export interface PublicationTarget { @@ -60,11 +60,11 @@ export interface PublicationTarget { * to publish its own builds; nothing here is required for a fork that never publishes. */ export function resolveTarget(channel: string): PublicationTarget { - const bucket = optionalEnvironment("OPENBOT_DESKTOP_UPDATES_BUCKET") ?? officialUpdatesBucket; - const root = optionalEnvironment("OPENBOT_DESKTOP_UPDATES_PREFIX") ?? officialUpdatesPrefix; + const bucket = optionalEnvironment("DISPATCH_DESKTOP_UPDATES_BUCKET") ?? officialUpdatesBucket; + const root = optionalEnvironment("DISPATCH_DESKTOP_UPDATES_PREFIX") ?? officialUpdatesPrefix; const region = optionalEnvironment("AWS_REGION") ?? officialUpdatesRegion; const prefix = `${trimSlashes(root)}/${channel}`; - const configuredBase = optionalEnvironment("OPENBOT_DESKTOP_UPDATES_BASE_URL"); + const configuredBase = optionalEnvironment("DISPATCH_DESKTOP_UPDATES_BASE_URL"); const base = configuredBase ? trimTrailingSlash(configuredBase) : `https://${bucket}.s3.${region}.amazonaws.com`; @@ -77,10 +77,10 @@ export function publicationGuard(root: string, bucket: string): string | undefin if (isUpstreamRepository(root)) return undefined; const found = remoteRepository(root) ?? "an unknown remote"; return ( - `Refusing to publish to the official OpenBot updates bucket from ${found}.\n` + + `Refusing to publish to the official Dispatch updates bucket from ${found}.\n` + `Desktop publication belongs to ${upstreamRepository} (ADR-0028). To publish a fork's ` + - `own builds, create a bucket for it and set OPENBOT_DESKTOP_UPDATES_BUCKET, plus ` + - `optionally OPENBOT_DESKTOP_UPDATES_PREFIX and OPENBOT_DESKTOP_UPDATES_BASE_URL.` + `own builds, create a bucket for it and set DISPATCH_DESKTOP_UPDATES_BUCKET, plus ` + + `optionally DISPATCH_DESKTOP_UPDATES_PREFIX and DISPATCH_DESKTOP_UPDATES_BASE_URL.` ); } @@ -221,7 +221,7 @@ export async function runRelease(argv: readonly string[], store?: ObjectStore): return runStatus(root, target, store); default: console.error( - `Usage: openbot desktop release <${releaseSubcommands.map(([name]) => name).join("|")}>`, + `Usage: tilde desktop release <${releaseSubcommands.map(([name]) => name).join("|")}>`, ); return 1; } @@ -262,7 +262,7 @@ export function resolveSigning(environment: NodeJS.ProcessEnv = process.env): Si }; } - const directory = mkdtempSync(join(tmpdir(), "openbot-signing-")); + const directory = mkdtempSync(join(tmpdir(), "dispatch-signing-")); const certificatePath = join(directory, "certificate.p12"); writeFileSync(certificatePath, Buffer.from(certificate, "base64"), { mode: 0o600 }); const resolved: Record = { @@ -299,15 +299,15 @@ async function runBuild( ): Promise { const platform = requested ?? hostPlatform(); if (platform !== "mac" && platform !== "linux") { - console.error(`Unsupported --platform ${platform}. OpenBot desktop releases mac and linux.`); + console.error(`Unsupported --platform ${platform}. Dispatch desktop releases mac and linux.`); return 1; } const signing = platform === "mac" ? resolveSigning() : unsignedLinux(); for (const warning of signing.warnings) console.warn(`! ${warning}`); // Both of these are command-line overrides rather than package.json config. Notarization, - // so an ordinary `openbot desktop package` never tries to reach Apple; appId, because + // so an ordinary `tilde desktop package` never tries to reach Apple; appId, because // electron-builder strips `${env.*}` macros out of that field and would otherwise bake a - // literal `env.OPENBOTAPPID` into the bundle. + // literal `env.DISPATCHAPPID` into the bundle. // // Passed without a `--` separator: pnpm forwards `--` through to the script verbatim // rather than consuming it, and electron-builder then ignores everything after it. @@ -317,7 +317,7 @@ async function runBuild( "pnpm", [ "--filter", - "@tryopenbot/desktop", + "@trytilde/dispatch-desktop", platform === "mac" ? "release:mac" : "release:linux", ...overrides, ], @@ -325,7 +325,7 @@ async function runBuild( { ...signing.environment, // Interpolated into latest-*.yml by the generic publish provider. - OPENBOT_DESKTOP_UPDATES_URL: target.baseUrl, + DISPATCH_DESKTOP_UPDATES_URL: target.baseUrl, }, ); if (code !== 0) return code; @@ -367,7 +367,7 @@ async function runPublish( const outputDirectory = join(desktopAppDirectory(root), "out"); if (!existsSync(outputDirectory)) { console.error( - `No build output at ${outputDirectory}. Run \`openbot desktop release build\` first.`, + `No build output at ${outputDirectory}. Run \`tilde desktop release build\` first.`, ); return 1; } @@ -488,7 +488,7 @@ async function runStatus( /** Records what the build actually did so `publish` reports it rather than guessing. */ function releaseStatePath(root: string): string { - return join(desktopAppDirectory(root), "out", ".openbot-release-state.json"); + return join(desktopAppDirectory(root), "out", ".dispatch-release-state.json"); } function readReleaseState(root: string): { signed: boolean; notarized: boolean } { @@ -503,7 +503,7 @@ function readReleaseState(root: string): { signed: boolean; notarized: boolean } } export function desktopAppDirectory(root: string): string { - return join(root, optionalEnvironment("OPENBOT_DESKTOP_DIR") ?? "apps/desktop"); + return join(root, optionalEnvironment("DISPATCH_DESKTOP_DIR") ?? "apps/desktop"); } function desktopVersion(root: string): string { @@ -568,7 +568,7 @@ function awsCliStore(bucket: string): ObjectStore { await require0(["s3", "cp", localPath, `s3://${bucket}/${key}`]); }, async putText(text, key, contentType) { - const directory = mkdtempSync(join(tmpdir(), "openbot-upload-")); + const directory = mkdtempSync(join(tmpdir(), "dispatch-upload-")); const path = join(directory, basename(key)); writeFileSync(path, text); await require0(["s3", "cp", path, `s3://${bucket}/${key}`, "--content-type", contentType]); @@ -589,7 +589,7 @@ function awsCliStore(bucket: string): ObjectStore { return output.trim() === "" || output.trim() === "None" ? [] : output.trim().split(/\s+/); }, async getText(key) { - const directory = mkdtempSync(join(tmpdir(), "openbot-download-")); + const directory = mkdtempSync(join(tmpdir(), "dispatch-download-")); const path = join(directory, "object"); const result = await run(["s3", "cp", `s3://${bucket}/${key}`, path]); if (result.code !== 0) return undefined; diff --git a/cli/src/commands/dev.test.ts b/cli/src/commands/dev.test.ts index a0226af6..134b364e 100644 --- a/cli/src/commands/dev.test.ts +++ b/cli/src/commands/dev.test.ts @@ -10,10 +10,10 @@ import { describe("development package command", () => { it("keeps child output while suppressing pnpm lifecycle errors on shutdown", () => { - expect(developmentPackageCommand("@tryopenbot/web", "dev", ["--port", "4173"])).toEqual([ + expect(developmentPackageCommand("@trytilde/dispatch-web", "dev", ["--port", "4173"])).toEqual([ "--reporter=silent", "--filter", - "@tryopenbot/web", + "@trytilde/dispatch-web", "dev", "--port", "4173", diff --git a/cli/src/commands/dev.ts b/cli/src/commands/dev.ts index 630b7c8e..c8f7db0f 100644 --- a/cli/src/commands/dev.ts +++ b/cli/src/commands/dev.ts @@ -1,7 +1,7 @@ import { resolve } from "node:path"; import type { ChildProcess } from "node:child_process"; -import type { OpenBotConfiguration } from "@tryopenbot/configuration"; -import { waitForHealth } from "@tryopenbot/control-service-provider"; +import type { DispatchConfiguration } from "@trytilde/dispatch-configuration"; +import { waitForHealth } from "@trytilde/dispatch-control-service-provider"; import { runLocalRuntimeTunnelCommand } from "../tilde/runtime-tunnel.js"; import { formatAgentLifecycleProgress, reconcileAgentResources } from "../agent-lifecycle.js"; import { loadConfigurationModule } from "../configuration-loader.js"; @@ -26,7 +26,7 @@ export async function runDevelopment(): Promise { const serverPort = env.PORT ?? "4100"; const configuration = await loadDevelopmentConfiguration(env); const infrastructureProgress = createStreamingProgress( - "Preparing OpenBot development infrastructure", + "Preparing Dispatch development infrastructure", ); try { await reconcileDevelopmentInfrastructure({ @@ -43,9 +43,9 @@ export async function runDevelopment(): Promise { if (label) infrastructureProgress.setLabel(label); }, }); - infrastructureProgress.succeed("OpenBot development infrastructure ready"); + infrastructureProgress.succeed("Dispatch development infrastructure ready"); } catch (error) { - infrastructureProgress.fail("OpenBot development infrastructure failed"); + infrastructureProgress.fail("Dispatch development infrastructure failed"); throw error; } await runChecked("pnpm", ["contracts:generate"], env); @@ -63,13 +63,13 @@ export async function runDevelopment(): Promise { process.once("exit", () => computerWatcher.close()); const webPort = env.WEB_PORT ?? "4173"; - console.log(`OpenBot web: http://127.0.0.1:${webPort}`); - console.log(`OpenBot control and agent HMR server: http://127.0.0.1:${serverPort}`); + console.log(`Dispatch web: http://127.0.0.1:${webPort}`); + console.log(`Dispatch control and agent HMR server: http://127.0.0.1:${serverPort}`); const [serverCommand, serverArguments] = developmentServerCommand(); const server = await startTunneledAgentService(serverCommand, serverArguments, env); await writeLiveAgentServiceOrigin(repositoryRoot, server.agentServiceOrigin); - if (env.OPENBOT_SKIP_AGENT_RECONCILE === "1") { + if (env.DISPATCH_SKIP_AGENT_RECONCILE === "1") { console.log("Agent resource reconciliation skipped by operator configuration"); } else try { @@ -91,13 +91,13 @@ export async function runDevelopment(): Promise { } const web = run( "pnpm", - developmentPackageCommand("@tryopenbot/web", "dev", [ + developmentPackageCommand("@trytilde/dispatch-web", "dev", [ "--port", webPort, "--host", env.WEB_HOST ?? "127.0.0.1", ]), - developmentChildEnvironment(shellEnvironment, { OPENBOT_CONTROL_PORT: serverPort }), + developmentChildEnvironment(shellEnvironment, { DISPATCH_CONTROL_PORT: serverPort }), ); const children = [server.child, web]; @@ -111,10 +111,12 @@ export async function runDevelopment(): Promise { CONTROL_ORIGIN: `http://127.0.0.1:${serverPort}`, DESKTOP_DEV_URL: `http://127.0.0.1:${webPort}`, }); - children.push(run("pnpm", developmentPackageCommand("@tryopenbot/desktop", "dev"), desktopEnv)); + children.push( + run("pnpm", developmentPackageCommand("@trytilde/dispatch-desktop", "dev"), desktopEnv), + ); } else { console.log( - "OpenBot desktop: skipped (set DISPLAY/WAYLAND_DISPLAY, or run on macOS; NO_DESKTOP=1 disables it explicitly)", + "Dispatch desktop: skipped (set DISPLAY/WAYLAND_DISPLAY, or run on macOS; NO_DESKTOP=1 disables it explicitly)", ); } @@ -129,14 +131,14 @@ export async function runDevelopment(): Promise { export async function loadDevelopmentConfiguration( environment: NodeJS.ProcessEnv, -): Promise { +): Promise { const path = resolve(repositoryRoot, "configuration/index.ts"); - const module = await loadConfigurationModule<{ default?: OpenBotConfiguration }>( + const module = await loadConfigurationModule<{ default?: DispatchConfiguration }>( path, environment, ); if (!module.default) - throw new Error("configuration/index.ts must export the OpenBot configuration as default"); + throw new Error("configuration/index.ts must export the Dispatch configuration as default"); return module.default; } @@ -180,7 +182,7 @@ export function developmentTunnelOptions( if (!apiKey || !orgId || !teamId) return undefined; const port = Number(environment.PORT ?? "4100"); if (!Number.isSafeInteger(port) || port < 1 || port > 65_535) - throw new Error(`Invalid OpenBot development server port: ${environment.PORT}`); + throw new Error(`Invalid Dispatch development server port: ${environment.PORT}`); return { baseUrl: environment.TILDE_BASE_URL?.trim() || "https://api.trytilde.ai", apiKey, diff --git a/cli/src/commands/env.ts b/cli/src/commands/env.ts index c28e71ab..3151dea3 100644 --- a/cli/src/commands/env.ts +++ b/cli/src/commands/env.ts @@ -12,7 +12,7 @@ export async function runEnvironment(argv: readonly string[]): Promise [--json]"); + throw new Error("Usage: tilde env [--json]"); if (operation === "set") { if (!value) throw new Error("env set requires a non-empty VALUE"); const description = parsed["--description"]?.trim(); diff --git a/cli/src/commands/index.tsx b/cli/src/commands/index.tsx index b684418d..ad14a5bc 100644 --- a/cli/src/commands/index.tsx +++ b/cli/src/commands/index.tsx @@ -56,7 +56,7 @@ export async function runCommand(command: string, args: readonly string[]): Prom ); return; } - return show(); + return show(); } if (command === "new-agent") { const result = await runNewAgent(args); @@ -72,7 +72,7 @@ export async function runCommand(command: string, args: readonly string[]): Prom } if (command === "dev") { rejectArguments(command, args); - if (process.stdout.isTTY) show(); + if (process.stdout.isTTY) show(); return runDevelopment(); } if (command === "orchestrate") { diff --git a/cli/src/commands/init.test.ts b/cli/src/commands/init.test.ts index d601bbf1..eb8d1662 100644 --- a/cli/src/commands/init.test.ts +++ b/cli/src/commands/init.test.ts @@ -17,13 +17,13 @@ describe("non-interactive initialization prompts", () => { it("answers stable input and selection IDs", async () => { const prompts = createNonInteractivePrompts({ - "repository-name": "agent-openbot", + "repository-name": "agent-dispatch", "repository-visibility": "private", }); await expect( prompts.input("GitHub repository name", { id: "repository-name", required: true }), - ).resolves.toBe("agent-openbot"); + ).resolves.toBe("agent-dispatch"); await expect( prompts.select( "GitHub repository visibility", @@ -90,7 +90,7 @@ describe("non-interactive initialization prompts", () => { it("validates all Vercel inputs before repository bootstrap can mutate", () => { expect(() => validateNonInteractiveCoreAnswers({ - "repository-name": "agent-openbot", + "repository-name": "agent-dispatch", "repository-visibility": "private", "owner-identity": "aws-kms", "aws-kms-key-arn": "arn:aws:kms:us-east-1:123:key/test", @@ -106,17 +106,17 @@ describe("non-interactive initialization prompts", () => { validateNonInteractiveCoreAnswers( { "owner-identity": "managed-file", - "managed-owner-identity-path": "/workspace/.openbot/owner-age-key", + "managed-owner-identity-path": "/workspace/.dispatch/owner-age-key", runtime: "tilde-cloud", inference: "vercel", - "vercel-runtime-project": "openbot-research", - "openbot-hosted-instance-id": "hosted-openbot-research", - "openbot-hosted-computer-id": "openbot-research", - "openbot-hosted-computer-service-url": "https://computer.test/rpc", + "vercel-runtime-project": "dispatch-research", + "dispatch-hosted-instance-id": "hosted-dispatch-research", + "dispatch-hosted-computer-id": "dispatch-research", + "dispatch-hosted-computer-service-url": "https://computer.test/rpc", "tilde-api-key": "instance-key", "tilde-org-id": "org-one", - "tilde-team-id": "openbot-research", - "openbot-deployment-name": "Research", + "tilde-team-id": "dispatch-research", + "dispatch-deployment-name": "Research", }, { existingRepository: true }, ), @@ -135,15 +135,15 @@ describe("non-interactive initialization prompts", () => { expect.objectContaining({ const: "vercel" }), ]); expect(schema.properties["vercel-token"]?.description).toContain("Required for Vercel"); - expect(schema.properties["vercel-token"]?.["x-openbot-provider"]).toBe("Vercel"); - expect(schema.properties["vercel-token"]?.["x-openbot-runtimes"]).toEqual(["local", "vercel"]); + expect(schema.properties["vercel-token"]?.["x-dispatch-provider"]).toBe("Vercel"); + expect(schema.properties["vercel-token"]?.["x-dispatch-runtimes"]).toEqual(["local", "vercel"]); expect(schema.properties["vercel-token"]?.writeOnly).toBe(true); expect(schema.properties["vercel-runtime-project"]?.description).toContain( "single Vercel project", ); expect(schema.properties["vercel-agent-project"]).toBeUndefined(); - expect(schema.properties["tilde-api-key"]?.["x-openbot-provider"]).toBe("Tilde"); - expect(schema.properties["tilde-api-key"]?.["x-openbot-runtimes"]).toEqual([ + expect(schema.properties["tilde-api-key"]?.["x-dispatch-provider"]).toBe("Tilde"); + expect(schema.properties["tilde-api-key"]?.["x-dispatch-runtimes"]).toEqual([ "local", "vercel", "tilde-cloud", @@ -164,7 +164,7 @@ describe("non-interactive initialization prompts", () => { "tilde-api-key", "tilde-org-id", "tilde-team-id", - "openbot-deployment-name", + "dispatch-deployment-name", "github-app-name", ]); }); diff --git a/cli/src/commands/init.tsx b/cli/src/commands/init.tsx index 12887f43..fe1601ce 100644 --- a/cli/src/commands/init.tsx +++ b/cli/src/commands/init.tsx @@ -4,9 +4,9 @@ import { Box, Text, render, useApp, useInput } from "ink"; import { builtInRuntimeInitializationProviders, inferenceChoices, - initializeOpenBot, - isInitializedOpenBotRepository, - isOpenBotRepository, + initializeDispatch, + isInitializedDispatchRepository, + isDispatchRepository, ownerIdentityChoices, plainInitializationReporter, processCommandRunner, @@ -17,7 +17,7 @@ import { } from "../initialization.js"; import { repositoryRoot } from "../paths.js"; import { - bootstrapOpenBotRepository, + bootstrapDispatchRepository, repositoryVisibilityChoices, } from "../repository-bootstrap.js"; import { @@ -29,7 +29,7 @@ import { import { collectProviderInitializations, type ProviderInitializationQuestion, -} from "@tryopenbot/runtime-provider"; +} from "@trytilde/dispatch-runtime-provider"; export type InitializationJsonSchema = Readonly>; @@ -59,10 +59,10 @@ export async function runInitialization( const json = parsed["--json"] ?? false; if (!nonInteractive && (!process.stdin.isTTY || !process.stdout.isTTY)) throw new Error( - "openbot init requires an interactive terminal or --non-interactive with JSON answers on stdin", + "tilde init requires an interactive terminal or --non-interactive with JSON answers on stdin", ); - const initialized = await isInitializedOpenBotRepository(repositoryRoot); - const existingRepository = await isOpenBotRepository(repositoryRoot); + const initialized = await isInitializedDispatchRepository(repositoryRoot); + const existingRepository = await isDispatchRepository(repositoryRoot); const answers = nonInteractive ? await readJsonAnswersFromStdin() : undefined; const prompts = answers ? createNonInteractivePrompts( @@ -70,12 +70,12 @@ export async function runInitialization( ) : inkPrompts; if (!initialized && !existingRepository) - await bootstrapOpenBotRepository({ + await bootstrapDispatchRepository({ destination: repositoryRoot, prompts, runner: processCommandRunner, }); - await initializeOpenBot({ + await initializeDispatch({ repositoryRoot, prompts, interactive: !nonInteractive, @@ -124,8 +124,8 @@ function createInkInitializationReporter(): InitializationEventReporter { const reason = typeof details.reason === "string" ? details.reason : undefined; panel.timeout( reason - ? `${reason}; openbot dev or deploy resumes authorization.` - : "Authorization not completed yet; openbot dev or deploy resumes it.", + ? `${reason}; tilde dev or deploy resumes authorization.` + : "Authorization not completed yet; tilde dev or deploy resumes it.", ); panel = undefined; return; @@ -147,15 +147,15 @@ export function initializationJsonSchema(): InitializationJsonSchema { "GitHub repository to create. Use a repository name for the authenticated GitHub account, or owner/name for an organization.", }, "repository-visibility": selectSchema( - "Visibility of the GitHub repository created for this OpenBot installation.", + "Visibility of the GitHub repository created for this Dispatch installation.", repositoryVisibilityChoices, ), "owner-identity": selectSchema( - "Identity system owners will use to encrypt and decrypt OpenBot secrets with SOPS.", + "Identity system owners will use to encrypt and decrypt Dispatch secrets with SOPS.", ownerIdentityChoices, ), runtime: selectSchema( - "Runtime where OpenBot control, agent, and computer services will be deployed.", + "Runtime where Dispatch control, agent, and computer services will be deployed.", runtimeChoices, ), inference: selectSchema( @@ -208,7 +208,7 @@ export function initializationJsonSchema(): InitializationJsonSchema { ), "onepassword-vault": conditionedSchema( requiredStringSchema( - "1Password vault where OpenBot should store the generated owner age identity.", + "1Password vault where Dispatch should store the generated owner age identity.", ), "owner-identity", "onepassword", @@ -242,17 +242,17 @@ export function initializationJsonSchema(): InitializationJsonSchema { unknown >; const runtimes = [ - ...((existing?.["x-openbot-runtimes"] as string[] | undefined) ?? []), + ...((existing?.["x-dispatch-runtimes"] as string[] | undefined) ?? []), runtime, ]; const existingWithoutRuntimes = existing && { ...existing }; - if (existingWithoutRuntimes) delete existingWithoutRuntimes["x-openbot-runtimes"]; + if (existingWithoutRuntimes) delete existingWithoutRuntimes["x-dispatch-runtimes"]; if ( existingWithoutRuntimes && JSON.stringify(existingWithoutRuntimes) !== JSON.stringify(field) ) throw new Error(`Providers define conflicting initialization field: ${question.id}`); - properties[question.id] = { ...field, "x-openbot-runtimes": [...new Set(runtimes)] }; + properties[question.id] = { ...field, "x-dispatch-runtimes": [...new Set(runtimes)] }; if (question.required) required.add(question.id); } } @@ -261,10 +261,10 @@ export function initializationJsonSchema(): InitializationJsonSchema { return { $schema: "https://json-schema.org/draft/2020-12/schema", - $id: "urn:tryopenbot:schema:init-input", - title: "OpenBot non-interactive initialization input", + $id: "urn:trydispatch:schema:init-input", + title: "Dispatch non-interactive initialization input", description: - "JSON object accepted on standard input by `openbot init --non-interactive --json`. Secret fields must be supplied through stdin, never command arguments.", + "JSON object accepted on standard input by `tilde init --non-interactive --json`. Secret fields must be supplied through stdin, never command arguments.", type: "object", additionalProperties: false, properties, @@ -276,7 +276,7 @@ export function initializationJsonSchema(): InitializationJsonSchema { "inference", ], allOf: conditions, - "x-openbot-command": "openbot init --non-interactive --json", + "x-tilde-command": "tilde init --non-interactive --json", }; } @@ -303,7 +303,7 @@ function requiredStringSchema(description: string): unknown { function conditionedSchema(schema: unknown, field: string, equals: string): unknown { return { ...(schema as Record), - "x-openbot-condition": { field, equals }, + "x-dispatch-condition": { field, equals }, }; } @@ -324,9 +324,11 @@ function providerQuestionSchema( return { ...(base as Record), ...(question.validation ? { pattern: question.validation.pattern } : {}), - "x-openbot-provider": provider, - "x-openbot-destination": question.destination, - ...(question.validation ? { "x-openbot-validation-message": question.validation.message } : {}), + "x-dispatch-provider": provider, + "x-dispatch-destination": question.destination, + ...(question.validation + ? { "x-dispatch-validation-message": question.validation.message } + : {}), }; } diff --git a/cli/src/commands/new-agent.test.ts b/cli/src/commands/new-agent.test.ts index d9ed75bb..c59f862f 100644 --- a/cli/src/commands/new-agent.test.ts +++ b/cli/src/commands/new-agent.test.ts @@ -4,7 +4,7 @@ const mocks = vi.hoisted(() => ({ input: vi.fn(), loadDevelopmentConfiguration: vi.fn(async () => ({ providers: {} })), loadLocalEnvironment: vi.fn(async () => ({ - AGENT_SERVICE_ORIGIN: "https://our-ob-agents.vercel.app", + AGENT_SERVICE_ORIGIN: "https://our-dispatch-agents.vercel.app", })), readLiveAgentServiceOrigin: vi.fn(async () => "https://local.trytilde-sb.com"), reconcileAgentResources: vi.fn(async () => undefined), diff --git a/cli/src/commands/new-agent.tsx b/cli/src/commands/new-agent.tsx index b8712560..7676f84c 100644 --- a/cli/src/commands/new-agent.tsx +++ b/cli/src/commands/new-agent.tsx @@ -18,7 +18,7 @@ export async function runNewAgent(args: readonly string[] = []): Promise { state = "publishing"; try { console.log("Edits settled: verifying the project"); - await runChecked("pnpm", ["--filter", "openbot", "typecheck"], env); + await runChecked("pnpm", ["--filter", "@trytilde/cli", "typecheck"], env); if (aborted()) return; console.log(`Publishing to ${SANDBOX_EDITS_BRANCH}`); await publishSandboxEdits(env); diff --git a/cli/src/commands/plugin.test.ts b/cli/src/commands/plugin.test.ts index df5da937..740a5d21 100644 --- a/cli/src/commands/plugin.test.ts +++ b/cli/src/commands/plugin.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it } from "vite-plus/test"; import { defaultCommandForCli, parseTildePluginArgs, tildePluginHelpText } from "./plugin.js"; -describe("OpenBot Tilde plugin command", () => { +describe("Dispatch Tilde plugin command", () => { it("parses configure-only invocations", () => { expect( parseTildePluginArgs([ @@ -32,6 +32,6 @@ describe("OpenBot Tilde plugin command", () => { passthrough: ["--dangerously-skip-permissions"], }); expect(defaultCommandForCli("claude")).toBe("claude"); - expect(tildePluginHelpText()).toContain("openbot plugin --cli"); + expect(tildePluginHelpText()).toContain("tilde plugin --cli"); }); }); diff --git a/cli/src/commands/plugin.ts b/cli/src/commands/plugin.ts index e91c2886..0c05df40 100644 --- a/cli/src/commands/plugin.ts +++ b/cli/src/commands/plugin.ts @@ -220,8 +220,8 @@ function runChildCommand(command: string, args: string[]): Promise { export function tildePluginHelpText(): string { return `Usage: - openbot plugin --cli [options] - openbot plugin audit --cli + tilde plugin --cli [options] + tilde plugin audit --cli Options: --base-url Tilde API base URL. Default: TILDE_API_BASE_URL or ${DEFAULT_TILDE_API_BASE_URL} diff --git a/cli/src/commands/remote.ts b/cli/src/commands/remote.ts index 4432ba63..0face46b 100644 --- a/cli/src/commands/remote.ts +++ b/cli/src/commands/remote.ts @@ -14,7 +14,7 @@ export async function runRemote(argv: readonly string[]): Promise { const [name, task = "desktop"] = options._; if (!name || !(task in tasks)) { console.error( - `Usage: openbot remote <${Object.keys(tasks).join("|")}> (default: desktop)`, + `Usage: tilde remote <${Object.keys(tasks).join("|")}> (default: desktop)`, ); return 1; } @@ -22,7 +22,7 @@ export async function runRemote(argv: readonly string[]): Promise { // Electron Builder targets the host platform, so a mac artifact needs a mac host. if (task === "desktop-package" && host.platform !== "mac") console.log(`note: ${name} is ${host.platform}; this produces ${host.platform} artifacts only`); - const repositoryPath = host.path ?? "~/openbot"; + const repositoryPath = host.path ?? "~/dispatch"; const command = `cd ${repositoryPath} && ${tasks[task]}`; console.log(`${host.ssh}: ${command}`); // -t keeps interactive desktop development attached to this terminal. @@ -36,6 +36,6 @@ export async function runRemote(argv: readonly string[]): Promise { resolvePromise(exitCode ?? 0); }); }); - if (code === 0 && task === "desktop") console.log(`next: openbot connect ${name}`); + if (code === 0 && task === "desktop") console.log(`next: tilde connect ${name}`); return code; } diff --git a/cli/src/commands/sdk.test.ts b/cli/src/commands/sdk.test.ts index 877e5cd1..7c168571 100644 --- a/cli/src/commands/sdk.test.ts +++ b/cli/src/commands/sdk.test.ts @@ -1,12 +1,12 @@ import { describe, expect, it } from "vite-plus/test"; import { runSdk, sdkHelpText } from "./sdk.js"; -describe("OpenBot SDK command", () => { +describe("Dispatch SDK command", () => { it("documents every SDK workflow", () => { expect(sdkHelpText()).toContain("refresh|validate|smoke|publish"); }); it("requires explicit publication confirmation", async () => { - await expect(runSdk(["publish"])).rejects.toThrow("requires `openbot sdk publish --yes`"); + await expect(runSdk(["publish"])).rejects.toThrow("requires `tilde sdk publish --yes`"); }); }); diff --git a/cli/src/commands/sdk.ts b/cli/src/commands/sdk.ts index dae8f7d2..a5665959 100644 --- a/cli/src/commands/sdk.ts +++ b/cli/src/commands/sdk.ts @@ -13,7 +13,7 @@ export async function runSdk(args: readonly string[]): Promise { if (!isSdkAction(action)) throw new Error(sdkUsage()); if (action === "publish") { if (rest.length !== 1 || rest[0] !== "--yes") - throw new Error("Publishing Tilde SDK packages requires `openbot sdk publish --yes`."); + throw new Error("Publishing Tilde SDK packages requires `tilde sdk publish --yes`."); await runScript("scripts/publish-tilde-sdk-packages.mjs", "node"); return; } @@ -48,7 +48,7 @@ Commands: } function sdkUsage(): string { - return "Usage: openbot sdk "; + return "Usage: tilde sdk "; } async function validateOpenApi(): Promise { diff --git a/cli/src/commands/secrets.ts b/cli/src/commands/secrets.ts index 2ceb48e4..b730eb17 100644 --- a/cli/src/commands/secrets.ts +++ b/cli/src/commands/secrets.ts @@ -17,7 +17,7 @@ export async function runSecrets(argv: readonly string[]): Promise NAME [--description TEXT] [--stdin] [--json]", + "Usage: tilde secrets NAME [--description TEXT] [--stdin] [--json]", ); if (operation === "set") { const description = parsed["--description"]?.trim(); diff --git a/cli/src/commands/serve.test.ts b/cli/src/commands/serve.test.ts index f05b1232..b7e2f8bd 100644 --- a/cli/src/commands/serve.test.ts +++ b/cli/src/commands/serve.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it } from "vite-plus/test"; import { parsePort } from "./serve.js"; -describe("OpenBot development server", () => { +describe("Dispatch development server", () => { it("uses the default control port", () => expect(parsePort(undefined)).toBe(4100)); it("accepts a valid configured port", () => expect(parsePort("5123")).toBe(5123)); it("rejects invalid ports", () => { diff --git a/cli/src/commands/serve.ts b/cli/src/commands/serve.ts index bb7665ea..e2de8376 100644 --- a/cli/src/commands/serve.ts +++ b/cli/src/commands/serve.ts @@ -1,6 +1,6 @@ import { serve } from "@hono/node-server"; -import { createApp } from "@tryopenbot/control-service"; -import { createAgentServiceApp } from "@tryopenbot/agent-service-provider"; +import { createApp } from "@trytilde/dispatch-control-service"; +import { createAgentServiceApp } from "@trytilde/dispatch-agent-service-provider"; import { Hono } from "hono"; import { loadLocalEnvironment } from "../environment.js"; import { loadDevelopmentConfiguration } from "./dev.js"; @@ -40,7 +40,7 @@ export async function runDevelopmentServer(): Promise { ); await new Promise((resolvePromise, reject) => { const server = serve({ fetch: combined.fetch, port, hostname: "127.0.0.1" }, () => { - console.log(`OpenBot listening at http://127.0.0.1:${port}`); + console.log(`Dispatch listening at http://127.0.0.1:${port}`); }); const shutdown = (): void => { server.close((error) => (error ? reject(error) : resolvePromise())); diff --git a/cli/src/commands/tilde.test.ts b/cli/src/commands/tilde.test.ts index dac315aa..0f55b177 100644 --- a/cli/src/commands/tilde.test.ts +++ b/cli/src/commands/tilde.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it } from "vite-plus/test"; import { parseTildeArgs, tildeHelpText } from "./tilde.js"; -describe("OpenBot Tilde commands", () => { +describe("Tilde commands", () => { it("parses authentication and state migration commands", () => { expect(parseTildeArgs(["auth", "whoami", "--base-url", "https://api.test"])).toMatchObject({ authAction: "whoami", @@ -19,8 +19,7 @@ describe("OpenBot Tilde commands", () => { }); }); - it("uses only the OpenBot command surface", () => { - expect(tildeHelpText()).toContain("Usage: openbot"); - expect(tildeHelpText()).not.toContain("Usage: tilde"); + it("uses the Tilde command surface", () => { + expect(tildeHelpText()).toContain("Usage: tilde"); }); }); diff --git a/cli/src/commands/tilde.tsx b/cli/src/commands/tilde.tsx index 8c01d213..22d2ec07 100644 --- a/cli/src/commands/tilde.tsx +++ b/cli/src/commands/tilde.tsx @@ -132,7 +132,7 @@ export async function runTildeCommand( } export function tildeHelpText(): string { - return `Usage: openbot [options] + return `Usage: tilde [options] Commands: auth Sign in, sign out, select a team, or show the current identity @@ -145,7 +145,7 @@ Options: async function runAuthCommand(args: ParsedArgs): Promise { if (!args.authAction) { - throw new Error("Usage: openbot auth "); + throw new Error("Usage: tilde auth "); } if (args.authAction === "login") { await runAuthLogin(args); @@ -215,7 +215,7 @@ async function runAuthWhoami(args: ParsedArgs): Promise { async function runStateCommand(args: ParsedArgs): Promise { const baseUrl = resolveBaseUrl(args); if (!args.stateAction) { - throw new Error("Usage: openbot state [options] "); + throw new Error("Usage: tilde state [options] "); } if (!args.filePath) { throw new Error(stateUsage(args.stateAction)); @@ -251,7 +251,7 @@ async function runStateCommand(args: ParsedArgs): Promise { async function runTunnelCommand(args: ParsedArgs): Promise { if (args.command.length === 0) { - throw new Error("Usage: openbot tunnel [-p PORT] -- "); + throw new Error("Usage: tilde tunnel [-p PORT] -- "); } const baseUrl = resolveBaseUrl(args); const options: RunLocalRuntimeTunnelCommandOptions = { @@ -286,7 +286,7 @@ async function runTunnelCommand(args: ParsedArgs): Promise { export function parseTildeArgs(args: string[]): ParsedArgs { if (args[0] !== "auth" && args[0] !== "state" && args[0] !== "tunnel") { - throw new Error("Usage: openbot [options]"); + throw new Error("Usage: tilde [options]"); } const parsed: ParsedArgs = { commandName: args[0], command: [] }; let positionalCount = 0; @@ -326,10 +326,10 @@ export function parseTildeArgs(args: string[]): ParsedArgs { } if (parsed.commandName === "auth" && !arg.startsWith("-")) { if (parsed.authAction !== undefined) { - throw new Error("Usage: openbot auth "); + throw new Error("Usage: tilde auth "); } if (arg !== "login" && arg !== "logout" && arg !== "set-team" && arg !== "whoami") { - throw new Error("Usage: openbot auth "); + throw new Error("Usage: tilde auth "); } parsed.authAction = arg; continue; @@ -337,7 +337,7 @@ export function parseTildeArgs(args: string[]): ParsedArgs { if (parsed.commandName === "state" && !arg.startsWith("-")) { if (parsed.stateAction === undefined) { if (arg !== "import" && arg !== "export") { - throw new Error("Usage: openbot state [options] "); + throw new Error("Usage: tilde state [options] "); } parsed.stateAction = arg; continue; @@ -395,7 +395,7 @@ function resolveRequiredTeamId(args: ParsedArgs, baseUrl: string): string { } const selected = readSelectedTeamId(baseUrl); if (!selected) { - throw new Error("No Tilde team selected. Run `openbot auth set-team` or pass `--team-id`."); + throw new Error("No Tilde team selected. Run `tilde auth set-team` or pass `--team-id`."); } return selected; } @@ -409,12 +409,12 @@ function requiredImportOutputFilePath(args: ParsedArgs): string { function stateUsage(action?: StateAction): string { if (action === "import") { - return "Usage: openbot state import [--team-id TEAM_ID] "; + return "Usage: tilde state import [--team-id TEAM_ID] "; } if (action === "export") { - return "Usage: openbot state export [--team-id TEAM_ID] "; + return "Usage: tilde state export [--team-id TEAM_ID] "; } - return "Usage: openbot state [options] "; + return "Usage: tilde state [options] "; } async function importState(input: { diff --git a/cli/src/configuration-loader.test.ts b/cli/src/configuration-loader.test.ts index 6272ac1c..1973d38d 100644 --- a/cli/src/configuration-loader.test.ts +++ b/cli/src/configuration-loader.test.ts @@ -23,7 +23,7 @@ afterEach(async () => { describe("configuration loader", () => { it("maps generated .js specifiers to fork-owned TypeScript files", async () => { - const root = await mkdtemp(join(tmpdir(), "openbot-configuration-loader-")); + const root = await mkdtemp(join(tmpdir(), "dispatch-configuration-loader-")); temporaryDirectories.push(root); await writeFile( join(root, "index.ts"), @@ -31,7 +31,7 @@ describe("configuration loader", () => { ); await writeFile( join(root, "providers.ts"), - "export default { marker: process.env.OPENBOT_LOADER_MARKER };\n", + "export default { marker: process.env.DISPATCH_LOADER_MARKER };\n", ); const configurationPath = join(root, "index.ts"); @@ -44,11 +44,11 @@ describe("configuration loader", () => { import { loadConfigurationModule } from ${JSON.stringify(loaderUrl.href)}; await runWithTypeScriptLoader(async () => { const loaded = await loadConfigurationModule(${JSON.stringify(configurationPath)}, { - OPENBOT_LOADER_MARKER: "loaded", + DISPATCH_LOADER_MARKER: "loaded", }); await writeFile(${JSON.stringify(resultPath)}, JSON.stringify({ loaded: loaded.default, - restored: process.env.OPENBOT_LOADER_MARKER, + restored: process.env.DISPATCH_LOADER_MARKER, })); }); `, @@ -63,7 +63,7 @@ describe("configuration loader", () => { }); it("selects development exports for unbuilt workspace packages", async () => { - const root = await mkdtemp(join(tmpdir(), "openbot-workspace-loader-")); + const root = await mkdtemp(join(tmpdir(), "dispatch-workspace-loader-")); temporaryDirectories.push(root); const packageRoot = join(root, "node_modules", "@example", "provider"); await mkdir(join(packageRoot, "src"), { recursive: true }); diff --git a/cli/src/development-lifecycle.test.ts b/cli/src/development-lifecycle.test.ts index 348c1f3c..f8edda9f 100644 --- a/cli/src/development-lifecycle.test.ts +++ b/cli/src/development-lifecycle.test.ts @@ -1,22 +1,22 @@ import { mkdtemp, writeFile } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import type { OpenBotConfiguration } from "@tryopenbot/configuration"; -import type { DeploymentContext, DeployableProvider } from "@tryopenbot/runtime-provider"; +import type { DispatchConfiguration } from "@trytilde/dispatch-configuration"; +import type { DeploymentContext, DeployableProvider } from "@trytilde/dispatch-runtime-provider"; import { describe, expect, it, vi } from "vite-plus/test"; import { developmentInputFingerprint, reconcileDevelopmentInfrastructure, } from "./development-lifecycle.js"; -vi.mock("@tryopenbot/agent-service-provider", async (importOriginal) => ({ +vi.mock("@trytilde/dispatch-agent-service-provider", async (importOriginal) => ({ ...(await importOriginal()), discoverAgentWorkspaces: vi.fn(async () => []), })); describe("development lifecycle", () => { it("fingerprints watched inputs by content instead of filesystem notifications", async () => { - const root = await mkdtemp(join(tmpdir(), "openbot-computer-watch-")); + const root = await mkdtemp(join(tmpdir(), "dispatch-computer-watch-")); const source = join(root, "source.ts"); await writeFile(source, "export const value = 1;\n"); const before = await developmentInputFingerprint([source]); @@ -59,7 +59,7 @@ describe("development lifecycle", () => { agentService: service("agents"), controlService: service("control"), auth: provider("auth"), - } as unknown as OpenBotConfiguration["providers"]; + } as unknown as DispatchConfiguration["providers"]; await reconcileDevelopmentInfrastructure({ repositoryRoot: "/repository", diff --git a/cli/src/development-lifecycle.ts b/cli/src/development-lifecycle.ts index 431c7d5f..0891e776 100644 --- a/cli/src/development-lifecycle.ts +++ b/cli/src/development-lifecycle.ts @@ -2,8 +2,8 @@ import { createHash } from "node:crypto"; import { watch, type FSWatcher } from "node:fs"; import { lstat, readFile, readdir, readlink, stat } from "node:fs/promises"; import { relative, resolve } from "node:path"; -import type { OpenBotConfiguration } from "@tryopenbot/configuration"; -import { discoverAgentWorkspaces } from "@tryopenbot/agent-service-provider"; +import type { DispatchConfiguration } from "@trytilde/dispatch-configuration"; +import { discoverAgentWorkspaces } from "@trytilde/dispatch-agent-service-provider"; import { buildProviders, deployProviders, @@ -12,7 +12,7 @@ import { type DeploymentContext, type DeploymentParticipant, type DeploymentReporter, -} from "@tryopenbot/runtime-provider"; +} from "@trytilde/dispatch-runtime-provider"; import { discoveredAgentIds, persistAgentSandboxUrls, @@ -22,7 +22,7 @@ import { export interface DevelopmentLifecycleOptions { repositoryRoot: string; environment: NodeJS.ProcessEnv; - providers: OpenBotConfiguration["providers"]; + providers: DispatchConfiguration["providers"]; report?: DeploymentReporter; interactive?: boolean; } @@ -66,7 +66,7 @@ export async function reconcileDevelopmentInfrastructure( provider: { deployable: { plan: async () => ({ - summary: "Seed or resume the trusted OpenBot development sandbox", + summary: "Seed or resume the trusted Dispatch development sandbox", steps: [ "Preserve its mutable source tree and git remotes", "Install the aggregate deployment environment and SOPS identity", @@ -75,7 +75,7 @@ export async function reconcileDevelopmentInfrastructure( }), deploy: async (context: DeploymentContext) => { const computerId = - options.environment.DEVELOPMENT_SANDBOX_ID?.trim() || "openbot-development"; + options.environment.DEVELOPMENT_SANDBOX_ID?.trim() || "dispatch-development"; const agentIds = await discoveredAgentIds(context.repositoryRoot); const result = await options.providers.computer.deployDevelopmentSandbox( { computerId, agentWorkspaceIds: agentIds }, @@ -235,7 +235,7 @@ async function reconcileParticipants( }); if (!participants.some(({ id }) => id === "computer")) return; - const computerId = options.environment.COMPUTER_ID?.trim() || "openbot-computer"; + const computerId = options.environment.COMPUTER_ID?.trim() || "dispatch-computer"; await runProviderLifecycleHook( options.providers.computer, "Computer Provider", diff --git a/cli/src/environment.test.ts b/cli/src/environment.test.ts index 594e074c..cf36b587 100644 --- a/cli/src/environment.test.ts +++ b/cli/src/environment.test.ts @@ -23,8 +23,8 @@ describe("developmentChildEnvironment", () => { for (const name of [ "TILDE_API_KEY", "SOPS_AGE_KEY", - "OPENBOT_OIDC_TOKEN_ENDPOINT", - "OPENBOT_OIDC_CLIENT_ID", + "DISPATCH_OIDC_TOKEN_ENDPOINT", + "DISPATCH_OIDC_CLIENT_ID", ]) expect(child).not.toHaveProperty(name); }); diff --git a/cli/src/hosts.test.ts b/cli/src/hosts.test.ts index 369230ec..0cc522b7 100644 --- a/cli/src/hosts.test.ts +++ b/cli/src/hosts.test.ts @@ -15,7 +15,7 @@ describe("loadHosts", () => { writeFileSync( join(root, "configuration", "dev-hosts.json"), JSON.stringify({ - hosts: { build: { ssh: "root@198.51.100.7", platform: "linux", path: "~/openbot" } }, + hosts: { build: { ssh: "root@198.51.100.7", platform: "linux", path: "~/dispatch" } }, }), ); expect(loadHosts(root).build?.ssh).toBe("root@198.51.100.7"); diff --git a/cli/src/hosts.ts b/cli/src/hosts.ts index ae8d540e..457ba47d 100644 --- a/cli/src/hosts.ts +++ b/cli/src/hosts.ts @@ -9,7 +9,7 @@ export interface DevHost { /** ssh destination, e.g. "root@203.0.113.7" or an ~/.ssh/config alias. */ ssh: string; platform: "linux" | "mac"; - /** Repository path on the host. Defaults to "~/openbot". */ + /** Repository path on the host. Defaults to "~/dispatch". */ path?: string; /** Electron shell screen. */ desktopVncPort?: number; @@ -27,7 +27,7 @@ export function loadHosts(repositoryRoot: string): Record { } // A named host wins; anything else is treated as a raw ssh destination so -// `openbot connect user@203.0.113.7` needs no configuration at all. +// `tilde connect user@203.0.113.7` needs no configuration at all. export function resolveHost(nameOrSsh: string, hosts: Record): DevHost { const named = hosts[nameOrSsh]; if (named) return named; diff --git a/cli/src/index.test.tsx b/cli/src/index.test.tsx index ed6d1d1b..a13f7756 100644 --- a/cli/src/index.test.tsx +++ b/cli/src/index.test.tsx @@ -3,7 +3,7 @@ import { render } from "ink-testing-library"; import { parseInvocation } from "./commands/index.js"; import { CommandMenu, Help } from "./ui.js"; -describe("OpenBot CLI", () => { +describe("Tilde CLI", () => { it("parses commands after pnpm's separator", () => expect(parseInvocation(["--", "deploy", "--dry-run"])).toEqual({ command: "deploy", @@ -14,10 +14,10 @@ describe("OpenBot CLI", () => { expect(parseInvocation(["-h"])).toEqual({ command: "help", rest: [] })); it("renders discoverable command help", () => { const { lastFrame } = render(); - expect(lastFrame()).toContain("Fork it. Configure it. Run it."); + expect(lastFrame()).toContain("Dispatch. Fork it. Configure it. Run it."); expect(lastFrame()).toContain("init"); expect(lastFrame()).toContain("deploy --yes"); - expect(lastFrame()).not.toContain("Run the built OpenBot app"); + expect(lastFrame()).not.toContain("Run the built Dispatch app"); }); it("supports keyboard navigation in the launcher", () => { let selected = ""; diff --git a/cli/src/index.tsx b/cli/src/index.tsx index 39445082..953df9a8 100644 --- a/cli/src/index.tsx +++ b/cli/src/index.tsx @@ -88,7 +88,7 @@ function isHelpInvocation(argv: readonly string[]): boolean { function referenceUnexpectedExit(log: CliRunLog): void { if (process.argv.includes("--json")) printJson({ error: "Command exited unsuccessfully", log: log.path }); - else process.stderr.write(`OpenBot exited unsuccessfully. Full details: ${log.path}\n`); + else process.stderr.write(`Tilde exited unsuccessfully. Full details: ${log.path}\n`); } function showFailure(error: unknown, log: CliRunLog): void { @@ -112,6 +112,6 @@ function sensitiveEnvironmentValues(environment: NodeJS.ProcessEnv): string[] { runWithTypeScriptLoader(runLoggedCli).catch((error) => { const message = error instanceof Error ? (error.stack ?? error.message) : String(error); - process.stderr.write(`OpenBot CLI failed before logging could start:\n${message}\n`); + process.stderr.write(`Tilde CLI failed before logging could start:\n${message}\n`); process.exitCode = 1; }); diff --git a/cli/src/initialization.test.ts b/cli/src/initialization.test.ts index 37880b21..963927c8 100644 --- a/cli/src/initialization.test.ts +++ b/cli/src/initialization.test.ts @@ -3,16 +3,19 @@ import { spawnSync } from "node:child_process"; import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; -import { CodexInferenceProvider, VercelInferenceProvider } from "@tryopenbot/inference-provider"; +import { + CodexInferenceProvider, + VercelInferenceProvider, +} from "@trytilde/dispatch-inference-provider"; import { ExeDevRuntimeServiceProvider, VercelRuntimeServiceProvider, -} from "@tryopenbot/agent-service-provider"; +} from "@trytilde/dispatch-agent-service-provider"; import { ExeDevComputerProvider, VercelSandboxComputerProvider, -} from "@tryopenbot/computer-service-provider"; -import { renderFileTemplatePath } from "@tryopenbot/utilities"; +} from "@trytilde/dispatch-computer-service-provider"; +import { renderFileTemplatePath } from "@trytilde/dispatch-utilities"; import { afterEach, describe, expect, it, vi } from "vite-plus/test"; import { parse as parseYaml, stringify as stringifyYaml } from "yaml"; import { @@ -21,9 +24,9 @@ import { builtInRuntimeInitializationProviders, configuredRuntimeChoice, inferenceChoicesForRuntime, - initializeOpenBot, - isInitializedOpenBotRepository, - isOpenBotRepository, + initializeDispatch, + isInitializedDispatchRepository, + isDispatchRepository, loadDeploymentConfiguration, processCommandRunner, prepareInferenceTemplateMigration, @@ -46,7 +49,7 @@ afterEach(async () => { ); }); -describe("OpenBot initialization", () => { +describe("Dispatch initialization", () => { it("recognizes consolidation only when both service roles share one provider instance", () => { const shared = new VercelRuntimeServiceProvider(); const providers = { @@ -120,7 +123,7 @@ describe("OpenBot initialization", () => { try { await expect( - initializeOpenBot({ + initializeDispatch({ repositoryRoot, runner, request, @@ -136,7 +139,7 @@ describe("OpenBot initialization", () => { input: vi.fn(async (_prompt, options) => { events.push(`input:${options?.id ?? "unknown"}`); if (options?.id === "onepassword-vault") return "Engineering"; - if (options?.id === "onepassword-item-title") return "OpenBot owner identity"; + if (options?.id === "onepassword-item-title") return "Dispatch owner identity"; return ""; }), }, @@ -153,7 +156,7 @@ describe("OpenBot initialization", () => { it("preselects configured providers while offering every built-in alternative", async () => { const workspaceRoot = fileURLToPath(new URL("../../", import.meta.url)); - const repositoryRoot = await mkdtemp(join(workspaceRoot, ".openbot-provider-selection-")); + const repositoryRoot = await mkdtemp(join(workspaceRoot, ".dispatch-provider-selection-")); temporaryDirectories.push(repositoryRoot); const configurationTemplate = fileURLToPath( new URL("./assets/configuration/vercel.ts.hbs", import.meta.url), @@ -204,7 +207,7 @@ describe("OpenBot initialization", () => { it("refuses to rewrite an owner-edited built-in composition", async () => { const workspaceRoot = fileURLToPath(new URL("../../", import.meta.url)); - const repositoryRoot = await mkdtemp(join(workspaceRoot, ".openbot-provider-selection-")); + const repositoryRoot = await mkdtemp(join(workspaceRoot, ".dispatch-provider-selection-")); temporaryDirectories.push(repositoryRoot); const configurationTemplate = fileURLToPath( new URL("./assets/configuration/vercel.ts.hbs", import.meta.url), @@ -298,12 +301,12 @@ describe("OpenBot initialization", () => { ).toContain("createCodexAppServer"); }); - it("rejects initialization outside an OpenBot repository before writing configuration", async () => { - const repositoryRoot = await mkdtemp(join(tmpdir(), "not-openbot-init-")); + it("rejects initialization outside a Dispatch repository before writing configuration", async () => { + const repositoryRoot = await mkdtemp(join(tmpdir(), "not-dispatch-init-")); temporaryDirectories.push(repositoryRoot); await expect( - initializeOpenBot({ + initializeDispatch({ repositoryRoot, userConfigurationPath: testUserConfigurationPath(repositoryRoot), prompts: { @@ -311,7 +314,7 @@ describe("OpenBot initialization", () => { input: vi.fn(async () => ""), }, }), - ).rejects.toThrow("openbot init must run from the root of a cloned OpenBot repository"); + ).rejects.toThrow("tilde init must run from the root of a cloned Dispatch repository"); await expect(access(join(repositoryRoot, "configuration"))).rejects.toMatchObject({ code: "ENOENT", @@ -321,8 +324,8 @@ describe("OpenBot initialization", () => { it("recognizes a cloned checkout separately from a completed initialization", async () => { const repositoryRoot = await temporaryRepository(); - await expect(isOpenBotRepository(repositoryRoot)).resolves.toBe(true); - await expect(isInitializedOpenBotRepository(repositoryRoot)).resolves.toBe(false); + await expect(isDispatchRepository(repositoryRoot)).resolves.toBe(true); + await expect(isInitializedDispatchRepository(repositoryRoot)).resolves.toBe(false); }); it("generates valid-looking age identities", () => { @@ -379,8 +382,8 @@ describe("OpenBot initialization", () => { runWithInputFile: processCommandRunner.runWithInputFile, }; const selections = ["onepassword", "local", "vercel"]; - const inputs = ["Engineering", "OpenBot owner identity"]; - await initializeOpenBot({ + const inputs = ["Engineering", "Dispatch owner identity"]; + await initializeDispatch({ repositoryRoot, userConfigurationPath: testUserConfigurationPath(repositoryRoot), runner, @@ -393,7 +396,7 @@ describe("OpenBot initialization", () => { "tilde-team-id": "tilde-team", "vercel-token": "vercel-private", "vercel-team-id": "", - "vercel-ai-gateway-api-key-name": "OpenBot agents", + "vercel-ai-gateway-api-key-name": "Dispatch agents", }; return options?.id ? (providerAnswers[options.id] ?? "") : (inputs.shift() ?? ""); }, @@ -432,7 +435,7 @@ describe("OpenBot initialization", () => { expect(primaryAgent).toContain('responseMode: "agentLoop"'); expect(primaryAgent).not.toContain("createChatKitAttachmentFilePartHandler"); expect(primaryAgent).not.toContain("base64"); - expect(primaryAgent).not.toContain("@tryopenbot/agent-provider"); + expect(primaryAgent).not.toContain("@trytilde/dispatch-agent-provider"); expect( await readFile(join(repositoryRoot, "configuration/agent/instructions.ts"), "utf8"), ).toContain("export default"); @@ -459,16 +462,16 @@ describe("OpenBot initialization", () => { ).toContain("createGrepTool"); expect( await readFile( - join(repositoryRoot, "configuration/agent/skills/develop-openbot/SKILL.md"), + join(repositoryRoot, "configuration/agent/skills/develop-dispatch/SKILL.md"), "utf8", ), - ).toContain("name: develop-openbot"); + ).toContain("name: develop-dispatch"); expect( await readFile( join(repositoryRoot, "configuration/agent/skills/create-agent/SKILL.md"), "utf8", ), - ).toContain("pnpm openbot new-agent"); + ).toContain("pnpm tilde new-agent"); expect( await readFile( join(repositoryRoot, "configuration/agent/sandbox/workspace/.profile"), @@ -502,7 +505,7 @@ describe("OpenBot initialization", () => { await writeFixture(repositoryRoot, "configuration/.gitignore", "private-cache/\n"); await expect( - initializeOpenBot({ + initializeDispatch({ repositoryRoot, userConfigurationPath: testUserConfigurationPath(repositoryRoot), prompts: { @@ -564,7 +567,7 @@ describe("OpenBot initialization", () => { }; await expect( - initializeOpenBot({ + initializeDispatch({ repositoryRoot, prompts: { select, input }, runner, @@ -584,15 +587,15 @@ describe("OpenBot initialization", () => { const answers = ["onepassword", "vercel", "vercel"]; const inputs: Record = { "onepassword-vault": "Engineering", - "onepassword-item-title": "OpenBot owner identity", + "onepassword-item-title": "Dispatch owner identity", "vercel-token": "vercel-secret", "vercel-team-id": "", - "vercel-runtime-project": "openbot-runtime", - "vercel-ai-gateway-api-key-name": "OpenBot agents", + "vercel-runtime-project": "dispatch-runtime", + "vercel-ai-gateway-api-key-name": "Dispatch agents", "tilde-api-key": "tilde-secret", "tilde-org-id": "tilde-org", "tilde-team-id": "tilde-team", - "openbot-deployment-name": "OpenBot", + "dispatch-deployment-name": "Dispatch", "tilde-base-url": "", }; const promptInput = vi.fn(async (_prompt, options) => inputs[options?.id ?? ""] ?? ""); @@ -614,18 +617,18 @@ describe("OpenBot initialization", () => { }), }; - await initializeOpenBot({ + await initializeDispatch({ repositoryRoot, prompts, request: async (input) => (input instanceof Request ? input.url : input instanceof URL ? input.href : input).includes( - "/identity/openbot/deployments", + "/identity/dispatch/deployments", ) ? Response.json({ - client_id: "openbot-client", - audience: "urn:tilde:openbot:openbot-client", + client_id: "dispatch-client", + audience: "urn:tilde:dispatch:dispatch-client", issuer: "https://tilde-org.api.trytilde.ai/api/v1/team/tilde-team/identity/oauth", - scope: "openid profile email offline_access openbot:control", + scope: "openid profile email offline_access dispatch:control", authorization_endpoint: "https://api.trytilde.ai/api/v1/identity/oauth/authorize", token_endpoint: "https://api.trytilde.ai/api/v1/identity/oauth/token", jwks_uri: "https://api.trytilde.ai/api/v1/identity/.well-known/jwks.json", @@ -640,12 +643,12 @@ describe("OpenBot initialization", () => { expect(promptInput).toHaveBeenCalledTimes(13); const environment = await readFile(join(repositoryRoot, "configuration/.env"), "utf8"); expect(environment).not.toContain("RUNTIME_PROVIDER"); - expect(environment).toContain('VERCEL_RUNTIME_PROJECT="openbot-runtime"'); + expect(environment).toContain('VERCEL_RUNTIME_PROJECT="dispatch-runtime"'); expect(environment).toContain( "# Name of the single Vercel project that will host the web app, control API, and isolated agent functions.", ); expect(environment).not.toContain("VERCEL_AGENT_PROJECT"); - expect(environment).toContain('VERCEL_AI_GATEWAY_API_KEY_NAME="OpenBot agents"'); + expect(environment).toContain('VERCEL_AI_GATEWAY_API_KEY_NAME="Dispatch agents"'); expect(environment).not.toContain("OPENAI_BASE_URL"); expect(environment).toContain('TILDE_ORG_ID="tilde-org"'); expect(environment).toContain('TILDE_TEAM_ID="tilde-team"'); @@ -671,7 +674,7 @@ describe("OpenBot initialization", () => { expect(encrypted).not.toContain("vercel-secret"); const metadata = await readFile(testUserConfigurationPath(repositoryRoot), "utf8"); expect(metadata).toContain('"sops"'); - expect(metadata).toContain("op://Engineering/OpenBot owner identity/password"); + expect(metadata).toContain("op://Engineering/Dispatch owner identity/password"); await expect( access(join(repositoryRoot, "configuration/sops.identity.json")), ).rejects.toMatchObject({ code: "ENOENT" }); @@ -792,8 +795,8 @@ export default { }), }; - expect(await isInitializedOpenBotRepository(repositoryRoot)).toBe(true); - await initializeOpenBot({ + expect(await isInitializedDispatchRepository(repositoryRoot)).toBe(true); + await initializeDispatch({ repositoryRoot, prompts, runner, @@ -810,7 +813,7 @@ export default { ["tilde-api-key", undefined], ["tilde-org-id", "stored-org"], ["tilde-team-id", undefined], - ["openbot-deployment-name", "OpenBot"], + ["dispatch-deployment-name", "Dispatch"], ["tilde-base-url", "https://api.trytilde.ai"], ]), ); @@ -822,7 +825,7 @@ export default { const reencrypted = parseYaml(encryptionInput ?? "") as typeof storedSecrets; expect(reencrypted).toMatchObject({ TILDE_API_KEY: { - description: "API key used by OpenBot services to access the selected Tilde team.", + description: "API key used by Dispatch services to access the selected Tilde team.", value: "entered-tilde", }, }); @@ -964,7 +967,7 @@ export default { const select = vi.fn(async () => "onepassword"); const prompts: InitializationPrompts = { select, - input: vi.fn(async () => "op://Engineering/OpenBot owner identity/password"), + input: vi.fn(async () => "op://Engineering/Dispatch owner identity/password"), }; await loadDeploymentConfiguration(repositoryRoot, { @@ -980,7 +983,7 @@ export default { sops: { ownerIdentity: { kind: "onepassword", - reference: "op://Engineering/OpenBot owner identity/password", + reference: "op://Engineering/Dispatch owner identity/password", }, }, }); @@ -1078,11 +1081,11 @@ export default { }); async function temporaryRepository(): Promise { - const path = await mkdtemp(join(tmpdir(), "openbot-init-")); + const path = await mkdtemp(join(tmpdir(), "dispatch-init-")); temporaryDirectories.push(path); - await writeFixture(path, "package.json", '{"name":"@tryopenbot/workspace"}\n'); + await writeFixture(path, "package.json", '{"name":"@trytilde/dispatch-workspace"}\n'); await writeFixture(path, "pnpm-workspace.yaml", "packages:\n - cli\n"); - await writeFixture(path, "cli/package.json", '{"name":"openbot"}\n'); + await writeFixture(path, "cli/package.json", '{"name":"@trytilde/cli"}\n'); await writeFixture(path, "configuration/.gitignore", "*\n!.gitignore\n"); return path; } diff --git a/cli/src/initialization.ts b/cli/src/initialization.ts index 43c80e3d..7d6640a0 100644 --- a/cli/src/initialization.ts +++ b/cli/src/initialization.ts @@ -11,31 +11,31 @@ import { ExeDevRuntimeServiceProvider, LocalRuntimeServiceProvider, VercelRuntimeServiceProvider, -} from "@tryopenbot/agent-service-provider"; -import { TildeAuthProvider } from "@tryopenbot/auth-provider"; -import { tildeAgentProviderInitialization } from "@tryopenbot/agent-provider"; +} from "@trytilde/dispatch-agent-service-provider"; +import { TildeAuthProvider } from "@trytilde/dispatch-auth-provider"; +import { tildeAgentProviderInitialization } from "@trytilde/dispatch-agent-provider"; import type { - OpenBotConfiguration, + DispatchConfiguration, SopsOwnerIdentityConfiguration, UserConfiguration, -} from "@tryopenbot/configuration"; +} from "@trytilde/dispatch-configuration"; import { ExeDevComputerProvider, MicrosandboxComputerProvider, VercelSandboxComputerProvider, -} from "@tryopenbot/computer-service-provider"; +} from "@trytilde/dispatch-computer-service-provider"; import { collectProviderInitializations, initializeProviders, type InitializableProvider, type ProviderInitialization, type ProviderInitializationQuestion, -} from "@tryopenbot/runtime-provider"; +} from "@trytilde/dispatch-runtime-provider"; import { CodeStorageGitProvider, GitHubGitProvider, LocalGitProvider, -} from "@tryopenbot/git-provider"; +} from "@trytilde/dispatch-git-provider"; import { CODEX_INFERENCE_PROVIDER, CodexInferenceProvider, @@ -43,9 +43,13 @@ import { type InferenceProvider, VERCEL_INFERENCE_PROVIDER, VercelInferenceProvider, -} from "@tryopenbot/inference-provider"; -import { ExeDevPlatform, tildePlatform, VercelPlatform } from "@tryopenbot/platform-integrations"; -import { materializeFileTemplate, renderFileTemplatePath } from "@tryopenbot/utilities"; +} from "@trytilde/dispatch-inference-provider"; +import { + ExeDevPlatform, + tildePlatform, + VercelPlatform, +} from "@trytilde/dispatch-platform-integrations"; +import { materializeFileTemplate, renderFileTemplatePath } from "@trytilde/dispatch-utilities"; import { agentTemplateDirectory, scaffoldAgentTemplates, @@ -207,7 +211,7 @@ export const runtimeChoices: readonly SelectChoice[] = [ { value: "local", label: "Local", - description: "Run OpenBot as user services on this computer.", + description: "Run Dispatch as user services on this computer.", }, { value: "vercel", @@ -269,8 +273,8 @@ export function inferenceChoicesForRuntime( : inferenceChoices; } -export async function initializeOpenBot(options: InitializationOptions): Promise { - await assertOpenBotRepositoryRoot(options.repositoryRoot); +export async function initializeDispatch(options: InitializationOptions): Promise { + await assertDispatchRepositoryRoot(options.repositoryRoot); const runner = options.runner ?? processCommandRunner; const configurationDirectory = resolve(options.repositoryRoot, "configuration"); const environmentPath = resolve(configurationDirectory, ".env"); @@ -285,9 +289,9 @@ export async function initializeOpenBot(options: InitializationOptions): Promise if (existingMarkers.some(Boolean)) { if (!existingMarkers.every(Boolean)) throw new Error( - "OpenBot has an incomplete SOPS configuration; preserve or remove it before retrying init", + "Dispatch has an incomplete SOPS configuration; preserve or remove it before retrying init", ); - await reconfigureOpenBot(options, runner, { + await reconfigureDispatch(options, runner, { configurationPath, environmentPath, secretsPath, @@ -301,7 +305,7 @@ export async function initializeOpenBot(options: InitializationOptions): Promise await createBlankEnvironment(environmentPath); const sandboxIdentity = generateAgeIdentity(); const ownerKind = await options.prompts.select( - "How should owners decrypt OpenBot secrets?", + "How should owners decrypt Dispatch secrets?", ownerIdentityChoices, { id: "owner-identity" }, ); @@ -440,8 +444,8 @@ export async function initializeOpenBot(options: InitializationOptions): Promise await runner.run("vp", ["install"], { cwd: options.repositoryRoot }); } -export async function isInitializedOpenBotRepository(repositoryRoot: string): Promise { - if (!(await isOpenBotRepository(repositoryRoot))) return false; +export async function isInitializedDispatchRepository(repositoryRoot: string): Promise { + if (!(await isDispatchRepository(repositoryRoot))) return false; const configurationDirectory = resolve(repositoryRoot, "configuration"); const markers = await Promise.all( [".sops.yaml", "secrets.enc.yaml"].map((name) => exists(resolve(configurationDirectory, name))), @@ -449,16 +453,16 @@ export async function isInitializedOpenBotRepository(repositoryRoot: string): Pr return markers.every(Boolean); } -export async function isOpenBotRepository(repositoryRoot: string): Promise { +export async function isDispatchRepository(repositoryRoot: string): Promise { try { - await assertOpenBotRepositoryRoot(repositoryRoot); + await assertDispatchRepositoryRoot(repositoryRoot); return true; } catch { return false; } } -async function reconfigureOpenBot( +async function reconfigureDispatch( options: InitializationOptions, runner: InitializationCommandRunner, paths: { @@ -476,7 +480,7 @@ async function reconfigureOpenBot( const allEnvironmentValues: Record = Object.fromEntries( Object.entries(state.environmentValues).map(([name, value]) => [ name, - { description: "Existing OpenBot environment value.", value }, + { description: "Existing Dispatch environment value.", value }, ]), ); const provisioningValues = { @@ -622,7 +626,7 @@ async function loadExistingInitializationState( ? sopsConfiguration.creation_rules[0] : undefined; if (!creationRule || typeof creationRule !== "object" || Array.isArray(creationRule)) - throw new Error("configuration/.sops.yaml does not contain an OpenBot creation rule"); + throw new Error("configuration/.sops.yaml does not contain a Dispatch creation rule"); const resolvedSecrets: Record = {}; for (const [name, described] of Object.entries(secretValues)) { @@ -683,16 +687,16 @@ async function encryptSecretsDocument( return encrypted.stdout; } -async function assertOpenBotRepositoryRoot(repositoryRoot: string): Promise { +async function assertDispatchRepositoryRoot(repositoryRoot: string): Promise { try { const workspaceManifest = await readFile(resolve(repositoryRoot, "package.json"), "utf8"); const workspace = JSON.parse(workspaceManifest) as { name?: unknown }; - if (workspace.name === "@tryopenbot/workspace") return; + if (workspace.name === "@trytilde/dispatch-workspace") return; } catch { // Report one stable repository-boundary error for missing or invalid markers. } throw new Error( - "openbot init must run from the root of a cloned OpenBot repository; change to that directory and retry", + "tilde init must run from the root of a cloned Dispatch repository; change to that directory and retry", ); } @@ -1029,9 +1033,9 @@ async function storeInNativeKeychain( [ "store", "--label", - "OpenBot SOPS identity", + "Dispatch SOPS identity", "service", - "ai.openbot.sops", + "ai.dispatch.sops", "account", "owner", ], @@ -1088,7 +1092,7 @@ async function loadStoredOwnerMetadata( if (kind === "onepassword") { const reference = await prompts.input("1Password secret reference", { id: "onepassword-reference", - description: "For example: op://Engineering/OpenBot owner identity/password", + description: "For example: op://Engineering/Dispatch owner identity/password", required: true, }); ownerIdentity = { kind: "onepassword", reference }; @@ -1112,7 +1116,7 @@ async function readSopsCreationRule(repositoryRoot: string): Promise; if ( configuration.version !== 1 || (configuration.sops !== undefined && (typeof configuration.sops !== "object" || Array.isArray(configuration.sops))) ) - throw new Error(`OpenBot user configuration has an unsupported schema: ${path}`); + throw new Error(`Dispatch user configuration has an unsupported schema: ${path}`); if ( configuration.sops?.ownerIdentity !== undefined && !isSopsOwnerIdentityConfiguration(configuration.sops.ownerIdentity) ) - throw new Error(`OpenBot user SOPS configuration is invalid: ${path}`); + throw new Error(`Dispatch user SOPS configuration is invalid: ${path}`); return configuration as UserConfiguration; } @@ -1184,7 +1188,7 @@ async function storeUserOwnerIdentity( function missingUserSopsConfigurationError(path: string): Error { return new Error( - `SOPS owner configuration is missing from ${path}. Run this command in an interactive terminal (or run openbot init) to configure the existing owner identity; non-interactive commands cannot choose it safely.`, + `SOPS owner configuration is missing from ${path}. Run this command in an interactive terminal (or run tilde init) to configure the existing owner identity; non-interactive commands cannot choose it safely.`, ); } @@ -1211,7 +1215,7 @@ async function loadStoredOwnerIdentity( return ( await runner.run( "secret-tool", - ["lookup", "service", "ai.openbot.sops", "account", "owner"], + ["lookup", "service", "ai.dispatch.sops", "account", "owner"], { cwd: repositoryRoot }, ) ).stdout.trim(); @@ -1219,7 +1223,7 @@ async function loadStoredOwnerIdentity( return ( await runner.run( "security", - ["find-generic-password", "-w", "-s", "ai.openbot.sops", "-a", "owner"], + ["find-generic-password", "-w", "-s", "ai.dispatch.sops", "-a", "owner"], { cwd: repositoryRoot }, ) ).stdout.trim(); @@ -1292,7 +1296,7 @@ function parseSecretsDocument(value: unknown): { function parseDescribedSecretsDocument(value: unknown): Record { if (!value || typeof value !== "object" || Array.isArray(value)) - throw new Error("Invalid encrypted OpenBot secrets document"); + throw new Error("Invalid encrypted Dispatch secrets document"); const root = value as Record; const result: Record = {}; for (const [storedName, entry] of Object.entries(root)) { @@ -1477,12 +1481,12 @@ export async function selectInitializationProviders( onSelected?: InitializationProviderStageHandler, ): Promise { if (await exists(path)) { - const module = await importConfiguredOpenBot( + const module = await importConfiguredDispatch( path, initializationDiscoveryEnvironment(environment ?? process.env), ); if (!module.default) - throw new Error("configuration/index.ts must export the OpenBot configuration as default"); + throw new Error("configuration/index.ts must export the Dispatch configuration as default"); const currentGroups = configuredInitializationProviderGroups(module.default); const currentProviders = [ ...currentGroups.runtime, @@ -1493,7 +1497,7 @@ export async function selectInitializationProviders( const currentInference = configuredInferenceChoice(module.default); const runtime = await selectProviderChoice( prompts, - "Where should OpenBot run?", + "Where should Dispatch run?", "runtime", runtimeChoices, currentRuntime, @@ -1503,7 +1507,7 @@ export async function selectInitializationProviders( if (runtimeChanged) { if (runtime === "current" || !currentRuntime || !currentInference) throw new Error( - "OpenBot cannot automatically rewrite a custom provider composition. Keep the current selections or edit configuration/index.ts explicitly.", + "Dispatch cannot automatically rewrite a custom provider composition. Keep the current selections or edit configuration/index.ts explicitly.", ); await assertCanonicalBuiltInConfiguration(path, currentRuntime, currentInference); } @@ -1515,7 +1519,7 @@ export async function selectInitializationProviders( const inference = await selectProviderChoice( prompts, - "How should OpenBot run inference?", + "How should Dispatch run inference?", "inference", inferenceChoices, currentInference, @@ -1525,7 +1529,7 @@ export async function selectInitializationProviders( if (inferenceChanged) { if (inference === "current" || !currentRuntime || !currentInference) throw new Error( - "OpenBot cannot automatically rewrite a custom provider composition. Keep the current selections or edit configuration/index.ts explicitly.", + "Dispatch cannot automatically rewrite a custom provider composition. Keep the current selections or edit configuration/index.ts explicitly.", ); if (!runtimeChanged) await assertCanonicalBuiltInConfiguration(path, currentRuntime, currentInference); @@ -1550,7 +1554,7 @@ export async function selectInitializationProviders( }; if (runtime === "current" || inference === "current") throw new Error( - "OpenBot cannot automatically rewrite a custom provider composition. Keep the current selections or edit configuration/index.ts explicitly.", + "Dispatch cannot automatically rewrite a custom provider composition. Keep the current selections or edit configuration/index.ts explicitly.", ); return { providers: [ @@ -1564,7 +1568,7 @@ export async function selectInitializationProviders( configurationSource: await renderBuiltInConfiguration(runtime, inference), }; } - const runtime = await prompts.select("Where do you want to deploy OpenBot?", runtimeChoices, { + const runtime = await prompts.select("Where do you want to deploy Dispatch?", runtimeChoices, { id: "runtime", initialValue: "vercel", }); @@ -1578,7 +1582,7 @@ export async function selectInitializationProviders( const runtimeProviders = builtInRuntimeProviderGroup(runtime); await onSelected?.({ domain: "runtime", providers: runtimeProviders }); const inference = await prompts.select( - "How should OpenBot run inference?", + "How should Dispatch run inference?", inferenceChoicesForRuntime(runtime), { id: "inference", @@ -1668,17 +1672,17 @@ function initializationDiscoveryEnvironment(environment: NodeJS.ProcessEnv): Nod for (const providers of selections) { for (const initialization of collectProviderInitializations(providers)) { for (const question of initialization.questions) { - result[question.destination.key] ??= `openbot-initialization-${question.id}`; + result[question.destination.key] ??= `dispatch-initialization-${question.id}`; } } } return result; } -async function importConfiguredOpenBot( +async function importConfiguredDispatch( path: string, environment: NodeJS.ProcessEnv, -): Promise<{ default?: OpenBotConfiguration }> { +): Promise<{ default?: DispatchConfiguration }> { return loadConfigurationModule(path, environment); } @@ -1743,7 +1747,7 @@ function inferenceTemplateFiles(providers: readonly InitializableProvider[]) { }); if (contributions.length > 1) throw new Error( - `OpenBot supports one inference agent template contribution; found ${contributions.length}`, + `Dispatch supports one inference agent template contribution; found ${contributions.length}`, ); return contributions[0]?.files ?? []; } @@ -2003,7 +2007,7 @@ function uniqueInitializationQuestions( return [...result.values()]; } -function configuredInitializationProviderGroups(configuration: OpenBotConfiguration): { +function configuredInitializationProviderGroups(configuration: DispatchConfiguration): { runtime: InitializableProvider[]; inference: InitializableProvider[]; shared: InitializableProvider[]; @@ -2026,7 +2030,7 @@ function configuredInitializationProviderGroups(configuration: OpenBotConfigurat } export function configuredRuntimeChoice( - configuration: OpenBotConfiguration, + configuration: DispatchConfiguration, ): RuntimeChoice | undefined { if (configuration.providers.controlService !== configuration.providers.agentService) return undefined; @@ -2059,7 +2063,7 @@ export function configuredRuntimeChoice( } function configuredInferenceChoice( - configuration: OpenBotConfiguration, + configuration: DispatchConfiguration, ): InferenceChoice | undefined { switch (constructorName(configuration.providers.inference)) { case "VercelInferenceProvider": @@ -2219,7 +2223,7 @@ const macKeychainStoreProgram = ` import Foundation import Security let data = FileHandle.standardInput.readDataToEndOfFile() -let deleteQuery: [String: Any] = [kSecClass as String: kSecClassGenericPassword, kSecAttrService as String: "ai.openbot.sops", kSecAttrAccount as String: "owner"] +let deleteQuery: [String: Any] = [kSecClass as String: kSecClassGenericPassword, kSecAttrService as String: "ai.dispatch.sops", kSecAttrAccount as String: "owner"] SecItemDelete(deleteQuery as CFDictionary) var addQuery = deleteQuery addQuery[kSecValueData as String] = data @@ -2257,7 +2261,7 @@ export const processCommandRunner: InitializationCommandRunner = { }); }, async runWithInputFile(command, args, options) { - const directory = await mkdtemp(resolve(tmpdir(), "openbot-sops-")); + const directory = await mkdtemp(resolve(tmpdir(), "dispatch-sops-")); const pipe = resolve(directory, "input"); try { await processCommandRunner.run("mkfifo", [pipe], { diff --git a/cli/src/live-agent-service.test.ts b/cli/src/live-agent-service.test.ts index e46e72be..ddb1c5c9 100644 --- a/cli/src/live-agent-service.test.ts +++ b/cli/src/live-agent-service.test.ts @@ -16,7 +16,7 @@ afterEach(async () => { describe("live agent service state", () => { it("round-trips the live lifecycle origin and clears only its own state", async () => { - const root = await mkdtemp(join(tmpdir(), "openbot-live-agent-")); + const root = await mkdtemp(join(tmpdir(), "dispatch-live-agent-")); roots.push(root); await writeLiveAgentServiceOrigin(root, "https://local.trytilde-sb.com/"); @@ -26,7 +26,7 @@ describe("live agent service state", () => { }); it("rejects stale state owned by a process that is no longer running", async () => { - const root = await mkdtemp(join(tmpdir(), "openbot-live-agent-")); + const root = await mkdtemp(join(tmpdir(), "dispatch-live-agent-")); roots.push(root); await writeLiveAgentServiceOrigin(root, "https://local.trytilde-sb.com"); await writeFile( diff --git a/cli/src/logging.test.ts b/cli/src/logging.test.ts index aeabfe91..93ab765f 100644 --- a/cli/src/logging.test.ts +++ b/cli/src/logging.test.ts @@ -6,8 +6,8 @@ import { cliFailureDetails, createCliRunLog } from "./logging.js"; describe("CLI run logging", () => { it("creates a private random run log and removes logs older than three days", async () => { - const homeDirectory = await mkdtemp(join(tmpdir(), "openbot-cli-log-")); - const directory = join(homeDirectory, ".openbot", "logs"); + const homeDirectory = await mkdtemp(join(tmpdir(), "dispatch-cli-log-")); + const directory = join(homeDirectory, ".dispatch", "logs"); await mkdir(directory, { recursive: true }); await chmod(directory, 0o755); const oldLog = join(directory, "old.log"); @@ -35,13 +35,13 @@ describe("CLI run logging", () => { expect((await stat(directory)).mode & 0o777).toBe(0o700); expect((await stat(log.path)).mode & 0o777).toBe(0o600); const contents = await readFile(log.path, "utf8"); - expect(contents).toContain("OpenBot CLI run started"); + expect(contents).toContain("Tilde CLI run started"); expect(contents).toContain("Test failure Error: complete stack required"); expect(contents).toContain("logging.test.ts"); }); it("redacts sensitive values from complete error stacks", async () => { - const homeDirectory = await mkdtemp(join(tmpdir(), "openbot-cli-log-redact-")); + const homeDirectory = await mkdtemp(join(tmpdir(), "dispatch-cli-log-redact-")); const secret = "do-not-record-this-token"; const log = await createCliRunLog({ homeDirectory, @@ -57,7 +57,7 @@ describe("CLI run logging", () => { }); it("adds a stack even when non-Error values are thrown", async () => { - const homeDirectory = await mkdtemp(join(tmpdir(), "openbot-cli-log-string-error-")); + const homeDirectory = await mkdtemp(join(tmpdir(), "dispatch-cli-log-string-error-")); const log = await createCliRunLog({ homeDirectory, randomId: "string-error-run" }); log.writeError("plain failure"); log.close(); diff --git a/cli/src/logging.ts b/cli/src/logging.ts index 58a63c55..e701da81 100644 --- a/cli/src/logging.ts +++ b/cli/src/logging.ts @@ -45,7 +45,7 @@ export async function createCliRunLog({ randomId?: string; redact?: (value: string) => string; } = {}): Promise { - const directory = join(homeDirectory, ".openbot", "logs"); + const directory = join(homeDirectory, ".dispatch", "logs"); await mkdir(directory, { recursive: true, mode: 0o700 }); await chmod(directory, 0o700); await removeExpiredLogs(directory, now); @@ -97,7 +97,7 @@ export async function createCliRunLog({ }, }; - log.write("system", "OpenBot CLI run started", { + log.write("system", "Tilde CLI run started", { command: process.argv[2] ?? "interactive", cwd: process.cwd(), node: process.version, diff --git a/cli/src/paths.test.ts b/cli/src/paths.test.ts index 71c78dd1..782b41c6 100644 --- a/cli/src/paths.test.ts +++ b/cli/src/paths.test.ts @@ -10,11 +10,11 @@ describe("repository root", () => { }); it("finds the workspace root when a task runner starts inside a package", async () => { - const root = await mkdtemp(join(tmpdir(), "openbot-repository-root-")); + const root = await mkdtemp(join(tmpdir(), "dispatch-repository-root-")); try { await writeFile( join(root, "package.json"), - JSON.stringify({ name: "@tryopenbot/workspace" }), + JSON.stringify({ name: "@trytilde/dispatch-workspace" }), ); await mkdir(join(root, "cli")); diff --git a/cli/src/paths.ts b/cli/src/paths.ts index 451c12d1..9484b387 100644 --- a/cli/src/paths.ts +++ b/cli/src/paths.ts @@ -8,17 +8,17 @@ export function resolveRepositoryRoot( ): string { if (explicitDirectory) return resolve(explicitDirectory); const invocationDirectory = resolve(initialDirectory ?? currentDirectory); - return findOpenBotWorkspaceRoot(invocationDirectory) ?? invocationDirectory; + return findDispatchWorkspaceRoot(invocationDirectory) ?? invocationDirectory; } -function findOpenBotWorkspaceRoot(startDirectory: string): string | undefined { +function findDispatchWorkspaceRoot(startDirectory: string): string | undefined { let directory = startDirectory; while (true) { try { const manifest = JSON.parse(readFileSync(resolve(directory, "package.json"), "utf8")) as { name?: unknown; }; - if (manifest.name === "@tryopenbot/workspace") return directory; + if (manifest.name === "@trytilde/dispatch-workspace") return directory; } catch { // Keep looking: standalone init also starts in a directory without a package manifest. } @@ -31,5 +31,5 @@ function findOpenBotWorkspaceRoot(startDirectory: string): string | undefined { export const repositoryRoot = resolveRepositoryRoot( process.cwd(), process.env.INIT_CWD, - process.env.OPENBOT_REPOSITORY_ROOT, + process.env.DISPATCH_REPOSITORY_ROOT, ); diff --git a/cli/src/repository-bootstrap.test.ts b/cli/src/repository-bootstrap.test.ts index d6f8ec75..3be2392b 100644 --- a/cli/src/repository-bootstrap.test.ts +++ b/cli/src/repository-bootstrap.test.ts @@ -3,7 +3,7 @@ import { tmpdir } from "node:os"; import { join } from "node:path"; import { afterEach, describe, expect, it, vi } from "vite-plus/test"; import type { InitializationCommandRunner, InitializationPrompts } from "./initialization.js"; -import { bootstrapOpenBotRepository } from "./repository-bootstrap.js"; +import { bootstrapDispatchRepository } from "./repository-bootstrap.js"; const temporaryDirectories: string[] = []; @@ -13,14 +13,14 @@ afterEach(async () => { ); }); -describe("OpenBot repository bootstrap", () => { +describe("Dispatch repository bootstrap", () => { it("rejects an incompatible canonical revision before prompts or repository creation", async () => { const destination = await temporaryDirectory(); const { prompts, input, select } = testPrompts(); - const { runner, run } = testRunner(destination, { canonicalPackageName: "openbot" }); + const { runner, run } = testRunner(destination, { canonicalPackageName: "dispatch" }); - await expect(bootstrapOpenBotRepository({ destination, prompts, runner })).rejects.toThrow( - "The canonical OpenBot repository is older than this CLI", + await expect(bootstrapDispatchRepository({ destination, prompts, runner })).rejects.toThrow( + "The canonical Dispatch repository is older than this CLI", ); expect(input).not.toHaveBeenCalled(); @@ -39,8 +39,8 @@ describe("OpenBot repository bootstrap", () => { const { prompts, input, select } = testPrompts(); const { runner, run } = testRunner(destination); - await expect(bootstrapOpenBotRepository({ destination, prompts, runner })).rejects.toThrow( - "openbot init requires a completely empty directory", + await expect(bootstrapDispatchRepository({ destination, prompts, runner })).rejects.toThrow( + "tilde init requires a completely empty directory", ); expect(input).not.toHaveBeenCalled(); @@ -50,16 +50,17 @@ describe("OpenBot repository bootstrap", () => { it("creates and verifies a public fork before configuration", async () => { const destination = await temporaryDirectory(); - const { prompts } = testPrompts("my-openbot", "public"); + const { prompts } = testPrompts("my-dispatch", "public"); const { runner, run } = testRunner(destination); - await bootstrapOpenBotRepository({ destination, prompts, runner }); + await bootstrapDispatchRepository({ destination, prompts, runner }); const calls = run.mock.calls; expect(calls.some(([command, args]) => command === "gh" && args.includes("fork"))).toBe(true); expect( calls.some( - ([command, args]) => command === "gh" && args.join(" ") === "repo clone owner/my-openbot .", + ([command, args]) => + command === "gh" && args.join(" ") === "repo clone owner/my-dispatch .", ), ).toBe(true); expect( @@ -76,7 +77,7 @@ describe("OpenBot repository bootstrap", () => { const { prompts, input } = testPrompts(" trytilde/our-dispatch ", "public"); const { runner, run } = testRunner(destination); - await bootstrapOpenBotRepository({ destination, prompts, runner }); + await bootstrapDispatchRepository({ destination, prompts, runner }); expect(input).toHaveBeenCalledWith("GitHub repository (owner/name)", { id: "repository-name", @@ -102,16 +103,16 @@ describe("OpenBot repository bootstrap", () => { it("creates a private repository through a temporary bare mirror", async () => { const destination = await temporaryDirectory(); - const { prompts } = testPrompts("private-openbot", "private"); + const { prompts } = testPrompts("private-dispatch", "private"); const { runner, run } = testRunner(destination); - await bootstrapOpenBotRepository({ destination, prompts, runner }); + await bootstrapDispatchRepository({ destination, prompts, runner }); const calls = run.mock.calls; expect( calls.some( ([command, args]) => - command === "gh" && args.join(" ") === "repo create owner/private-openbot --private", + command === "gh" && args.join(" ") === "repo create owner/private-dispatch --private", ), ).toBe(true); expect(calls.some(([command, args]) => command === "git" && args.includes("--bare"))).toBe( @@ -124,28 +125,28 @@ describe("OpenBot repository bootstrap", () => { it("creates a private mirror in the requested GitHub organization", async () => { const destination = await temporaryDirectory(); - const { prompts } = testPrompts("trytilde/private-openbot", "private"); + const { prompts } = testPrompts("trytilde/private-dispatch", "private"); const { runner, run } = testRunner(destination); - await bootstrapOpenBotRepository({ destination, prompts, runner }); + await bootstrapDispatchRepository({ destination, prompts, runner }); expect( run.mock.calls.some( ([command, args]) => - command === "gh" && args.join(" ") === "repo create trytilde/private-openbot --private", + command === "gh" && args.join(" ") === "repo create trytilde/private-dispatch --private", ), ).toBe(true); expect( run.mock.calls.some( ([command, args]) => - command === "gh" && args.join(" ") === "repo clone trytilde/private-openbot .", + command === "gh" && args.join(" ") === "repo clone trytilde/private-dispatch .", ), ).toBe(true); }); }); async function temporaryDirectory(): Promise { - const path = await mkdtemp(join(tmpdir(), "openbot-bootstrap-")); + const path = await mkdtemp(join(tmpdir(), "dispatch-bootstrap-")); temporaryDirectories.push(path); return path; } @@ -169,7 +170,7 @@ function testRunner(destination: string, options: { canonicalPackageName?: strin if (command === "gh" && args[0] === "api" && args[1]?.includes("contents/package.json")) return { stdout: Buffer.from( - JSON.stringify({ name: options.canonicalPackageName ?? "@tryopenbot/workspace" }), + JSON.stringify({ name: options.canonicalPackageName ?? "@trytilde/dispatch-workspace" }), ).toString("base64"), stderr: "", }; @@ -177,7 +178,7 @@ function testRunner(destination: string, options: { canonicalPackageName?: strin ownedRepository = args[2] ?? ""; await writeFile( join(destination, "package.json"), - JSON.stringify({ name: "@tryopenbot/workspace" }), + JSON.stringify({ name: "@trytilde/dispatch-workspace" }), ); } if (command === "git" && args.join(" ") === "remote get-url origin") diff --git a/cli/src/repository-bootstrap.ts b/cli/src/repository-bootstrap.ts index 13361ea8..e077433f 100644 --- a/cli/src/repository-bootstrap.ts +++ b/cli/src/repository-bootstrap.ts @@ -10,12 +10,12 @@ export const repositoryVisibilityChoices = [ { value: "private", label: "Private", - description: "Create an independent private mirror of OpenBot.", + description: "Create an independent private mirror of Dispatch.", }, { value: "public", label: "Public", - description: "Create a public GitHub fork of OpenBot.", + description: "Create a public GitHub fork of Dispatch.", }, ] as const; @@ -25,7 +25,7 @@ export interface RepositoryBootstrapOptions { runner: InitializationCommandRunner; } -export async function bootstrapOpenBotRepository( +export async function bootstrapDispatchRepository( options: RepositoryBootstrapOptions, ): Promise { await assertEmptyDirectory(options.destination); @@ -91,7 +91,7 @@ export async function bootstrapOpenBotRepository( function parseCanonicalHead(result: { stdout: string }): string { const head = result.stdout.trim().split(/\s+/)[0]; if (!head || !/^[0-9a-f]{40}$/i.test(head)) - throw new Error("Git did not return the canonical OpenBot HEAD revision"); + throw new Error("Git did not return the canonical Dispatch HEAD revision"); return head; } @@ -117,11 +117,11 @@ async function assertCanonicalRevisionCompatible( name?: unknown; }; } catch { - throw new Error("GitHub returned an invalid canonical OpenBot package manifest"); + throw new Error("GitHub returned an invalid canonical Dispatch package manifest"); } - if (manifest.name !== "@tryopenbot/workspace") + if (manifest.name !== "@trytilde/dispatch-workspace") throw new Error( - "The canonical OpenBot repository is older than this CLI; publish the matching OpenBot source before running init", + "The canonical Dispatch repository is older than this CLI; publish the matching Dispatch source before running init", ); } @@ -150,11 +150,11 @@ async function ensureUpstreamRemote(options: RepositoryBootstrapOptions): Promis }) ).stdout.trim(); if (existing.replace(/\.git$/, "") === canonicalRepositoryUrl.replace(/\.git$/, "")) return; - throw new Error("Existing upstream remote does not point to canonical OpenBot"); + throw new Error("Existing upstream remote does not point to canonical Dispatch"); } catch (error) { if ( error instanceof Error && - error.message === "Existing upstream remote does not point to canonical OpenBot" + error.message === "Existing upstream remote does not point to canonical Dispatch" ) throw error; } @@ -166,9 +166,7 @@ async function ensureUpstreamRemote(options: RepositoryBootstrapOptions): Promis async function assertEmptyDirectory(destination: string): Promise { const entries = await readdir(destination); if (entries.length) - throw new Error( - "openbot init requires a completely empty directory, including no hidden files", - ); + throw new Error("tilde init requires a completely empty directory, including no hidden files"); } async function createPrivateMirror( @@ -178,8 +176,8 @@ async function createPrivateMirror( await options.runner.run("gh", ["repo", "create", ownedRepository, "--private"], { cwd: options.destination, }); - const temporaryDirectory = await mkdtemp(resolve(tmpdir(), "openbot-mirror-")); - const bareRepository = resolve(temporaryDirectory, "openbot.git"); + const temporaryDirectory = await mkdtemp(resolve(tmpdir(), "dispatch-mirror-")); + const bareRepository = resolve(temporaryDirectory, "dispatch.git"); try { await options.runner.run("git", ["clone", "--bare", canonicalRepositoryUrl, bareRepository], { cwd: options.destination, @@ -200,13 +198,13 @@ async function assertClonedRepository( const manifest = JSON.parse( await readFile(resolve(options.destination, "package.json"), "utf8"), ) as { name?: unknown }; - if (manifest.name !== "@tryopenbot/workspace") - throw new Error("The cloned repository is not a compatible OpenBot workspace"); + if (manifest.name !== "@trytilde/dispatch-workspace") + throw new Error("The cloned repository is not a compatible Dispatch workspace"); const clonedHead = ( await options.runner.run("git", ["rev-parse", "HEAD"], { cwd: options.destination }) ).stdout.trim(); if (clonedHead !== canonicalHead) - throw new Error("The cloned repository does not match the OpenBot revision verified by init"); + throw new Error("The cloned repository does not match the Dispatch revision verified by init"); const origin = ( await options.runner.run("git", ["remote", "get-url", "origin"], { cwd: options.destination, @@ -218,7 +216,7 @@ async function assertClonedRepository( }) ).stdout.trim(); if (!origin.includes(ownedRepository)) - throw new Error(`OpenBot origin does not point to ${ownedRepository}`); + throw new Error(`Dispatch origin does not point to ${ownedRepository}`); if (upstream.replace(/\.git$/, "") !== canonicalRepositoryUrl.replace(/\.git$/, "")) - throw new Error("OpenBot upstream does not point to the canonical repository"); + throw new Error("Dispatch upstream does not point to the canonical repository"); } diff --git a/cli/src/tilde/coding-agent-audit.test.ts b/cli/src/tilde/coding-agent-audit.test.ts index 5acd7d99..2620b9a6 100644 --- a/cli/src/tilde/coding-agent-audit.test.ts +++ b/cli/src/tilde/coding-agent-audit.test.ts @@ -18,7 +18,7 @@ describe("coding-agent audit integration", () => { const second = await installCodingAgentAuditHooks({ cli, homeDir, mcpServers: [] }); expect(second).toBe(first); const contents = await readFile(first!, "utf8"); - expect(contents.match(new RegExp(`openbot plugin audit --cli ${cli}`, "g"))?.length).toBe( + expect(contents.match(new RegExp(`tilde plugin audit --cli ${cli}`, "g"))?.length).toBe( cli === "gemini" ? 5 : 7, ); }, diff --git a/cli/src/tilde/coding-agent-audit.ts b/cli/src/tilde/coding-agent-audit.ts index 32f32654..e0dd8224 100644 --- a/cli/src/tilde/coding-agent-audit.ts +++ b/cli/src/tilde/coding-agent-audit.ts @@ -157,7 +157,7 @@ async function mergeClaudeHooks(path: string): Promise { ]; for (const event of events) { const existing = Array.isArray(hooks[event]) ? hooks[event] : []; - const command = "openbot plugin audit --cli claude"; + const command = "tilde plugin audit --cli claude"; const hasCommand = JSON.stringify(existing).includes(command); hooks[event] = hasCommand ? existing @@ -188,7 +188,7 @@ async function mergeCursorHooks(path: string): Promise { ]; for (const event of events) { const existing = Array.isArray(hooks[event]) ? hooks[event] : []; - const command = "openbot plugin audit --cli cursor"; + const command = "tilde plugin audit --cli cursor"; hooks[event] = existing.some((entry) => isJsonObject(entry) && entry.command === command) ? existing : [...existing, { command }]; @@ -208,7 +208,7 @@ async function installOpenCodePlugin(homeDir: string): Promise { async function mergeGeminiHooks(path: string): Promise { const document = await readJsonObject(path); const hooks = isJsonObject(document.hooks) ? document.hooks : {}; - const command = "openbot plugin audit --cli gemini"; + const command = "tilde plugin audit --cli gemini"; for (const event of ["SessionStart", "SessionEnd", "BeforeAgent", "AfterAgent", "AfterTool"]) { const existing = Array.isArray(hooks[event]) ? hooks[event] : []; if (JSON.stringify(existing).includes(command)) continue; diff --git a/cli/src/typescript-loader.ts b/cli/src/typescript-loader.ts index 8f2d2e9f..b124796f 100644 --- a/cli/src/typescript-loader.ts +++ b/cli/src/typescript-loader.ts @@ -1,6 +1,6 @@ import { spawn } from "node:child_process"; -const loaderEnvironment = "OPENBOT_CLI_TYPESCRIPT_LOADER"; +const loaderEnvironment = "TILDE_CLI_TYPESCRIPT_LOADER"; /** Re-exec the standalone CLI with tsx so generated .js specifiers resolve TypeScript files. */ export async function runWithTypeScriptLoader(run: () => Promise): Promise { @@ -9,7 +9,7 @@ export async function runWithTypeScriptLoader(run: () => Promise): Promise return; } const entrypoint = process.argv[1]; - if (!entrypoint) throw new Error("OpenBot CLI entrypoint is unavailable"); + if (!entrypoint) throw new Error("Tilde CLI entrypoint is unavailable"); const child = spawn( process.execPath, [ diff --git a/cli/src/ui.tsx b/cli/src/ui.tsx index 307a97d4..227090c4 100644 --- a/cli/src/ui.tsx +++ b/cli/src/ui.tsx @@ -28,7 +28,7 @@ export interface SyncReportView { } const commands = [ - ["init", "Initialize OpenBot interactively"], + ["init", "Initialize Dispatch interactively"], ["init --non-interactive --json", "Initialize from JSON answers on stdin"], ["new-agent NAME --json", "Scaffold an agent non-interactively"], ["secrets set NAME --description TEXT --stdin", "Set a described secret from stdin"], @@ -40,7 +40,7 @@ const commands = [ ["tunnel", "Run a local command behind a Tilde tunnel"], ["plugin", "Configure Tilde resources for a coding-agent CLI"], ["sdk", "Develop and verify the Tilde SDK packages"], - ["dev", "Start the local OpenBot development environment"], + ["dev", "Start the local Dispatch development environment"], ["check", "Run repository validation"], ["build", "Build the deployable application shell"], ["test", "Run repository tests"], @@ -81,9 +81,9 @@ export function Brand({ subtitle }: { subtitle?: string }) { return ( - OPENBOT + TILDE - {subtitle ?? "Fork it. Configure it. Run it."} + {subtitle ?? "Dispatch. Fork it. Configure it. Run it."} ); } @@ -95,7 +95,7 @@ export function Help() { Usage {" "} - openbot <command> [options] + tilde <command> [options] Commands @@ -538,7 +538,7 @@ function GitHubAuthorizationView({ {status === "waiting" ? ( {frame} Waiting for GitHub… {seconds}s{" "} - (Ctrl+C exits; openbot dev or deploy resumes authorization) + (Ctrl+C exits; tilde dev or deploy resumes authorization) ) : status === "connected" ? ( ✓ GitHub App connected. diff --git a/cli/src/upstream.ts b/cli/src/upstream.ts index 8e5f83a2..e550b7ea 100644 --- a/cli/src/upstream.ts +++ b/cli/src/upstream.ts @@ -1,4 +1,4 @@ -// Identifies the canonical OpenBot repository. +// Identifies the canonical Dispatch repository. // // Official publication targets belong to trytilde/dispatch. A fork inherits tracked // configuration, so publication guards must live in code. diff --git a/cli/src/virtual-display.ts b/cli/src/virtual-display.ts index 611bfae2..83892f35 100644 --- a/cli/src/virtual-display.ts +++ b/cli/src/virtual-display.ts @@ -1,6 +1,6 @@ // Runs a graphical program on a host with no display: Xvfb owns a virtual screen and // x11vnc exposes it on loopback only, so a remote developer reaches it through -// `openbot connect` rather than an open port. +// `tilde connect` rather than an open port. // // Used by the Electron desktop shell on a display-less Linux host. import { spawn, spawnSync } from "node:child_process"; @@ -46,7 +46,7 @@ export async function ensureVncServer(display: VirtualDisplay): Promise { detach("x11vnc", [ "-display", `:${display.displayNumber}`, - // Loopback only. Reach it through `openbot connect`, never a public bind. + // Loopback only. Reach it through `tilde connect`, never a public bind. "-localhost", "-rfbport", display.vncPort, diff --git a/cli/src/workspace.ts b/cli/src/workspace.ts index e11689f5..1d29c11a 100644 --- a/cli/src/workspace.ts +++ b/cli/src/workspace.ts @@ -10,7 +10,7 @@ export function repositoryRoot(start: string = process.cwd()): string { const parent = dirname(current); if (parent === current) throw new Error( - "Not inside an OpenBot repository: no pnpm-workspace.yaml or .git found upward", + "Not inside a Dispatch repository: no pnpm-workspace.yaml or .git found upward", ); current = parent; } diff --git a/docs/adrs/0001-fork-owned-configuration.md b/docs/adrs/0001-fork-owned-configuration.md index b6ac0133..91e27138 100644 --- a/docs/adrs/0001-fork-owned-configuration.md +++ b/docs/adrs/0001-fork-owned-configuration.md @@ -11,24 +11,24 @@ ## Context -OpenBot must be simple to fork and customize while keeping upstream core changes reusable. Scattered imports or a layer-merging model would obscure ownership and make upgrades harder. +Dispatch must be simple to fork and customize while keeping upstream core changes reusable. Scattered imports or a layer-merging model would obscure ownership and make upgrades harder. ## Decision -`openbot init` creates `configuration/index.ts` inside the one fork-owned `configuration/` tree. The entrypoint calls `Configuration({ providers: { ... } })` with concrete provider instances grouped by domain as `controlService`, `agentService`, `chat`, `agent`, `computer`, `skills`, and `tools`. Provider packages export implementations but no string-to-provider selector factories; changing an implementation is an explicit source change in the fork composition root. +`tilde init` creates `configuration/index.ts` inside the one fork-owned `configuration/` tree. The entrypoint calls `Configuration({ providers: { ... } })` with concrete provider instances grouped by domain as `controlService`, `agentService`, `chat`, `agent`, `computer`, `skills`, and `tools`. Provider packages export implementations but no string-to-provider selector factories; changing an implementation is an explicit source change in the fork composition root. -Repository content is always discovered from canonical paths: the primary agent from `configuration/agent/`, subagents from `configuration/agent/subagents//`, skills and workspace seeds inside each owning agent, and custom provider source from `configuration/providers/`. The primary keeps the stable ID `factory`; subagent IDs come from their directory names. Global `configuration/skills/` and `configuration/sandbox/` directories are unsupported. These paths and the `/api/agents` route prefix are conventions, not `OpenBotConfiguration` options. +Repository content is always discovered from canonical paths: the primary agent from `configuration/agent/`, subagents from `configuration/agent/subagents//`, skills and workspace seeds inside each owning agent, and custom provider source from `configuration/providers/`. The primary keeps the stable ID `factory`; subagent IDs come from their directory names. Global `configuration/skills/` and `configuration/sandbox/` directories are unsupported. These paths and the `/api/agents` route prefix are conventions, not `DispatchConfiguration` options. -Agent directories use the Eve-compatible subset recorded in ADR-0011. Their `agent.ts` default-exports a Tilde `chatKitEndpoint` request handler, while `instructions.ts`, instrumentation, libraries, authored tools, authored skills, and sandbox workspace seeds remain colocated with the agent. OpenBot does not define a second execution SDK or use Eve's loader. Build-time discovery federates these endpoints; deployment registers agent workspaces without overwriting existing persistent files. +Agent directories use the Eve-compatible subset recorded in ADR-0011. Their `agent.ts` default-exports a Tilde `chatKitEndpoint` request handler, while `instructions.ts`, instrumentation, libraries, authored tools, authored skills, and sandbox workspace seeds remain colocated with the agent. Dispatch does not define a second execution SDK or use Eve's loader. Build-time discovery federates these endpoints; deployment registers agent workspaces without overwriting existing persistent files. -Provider composition configures OpenBot's control, provisioning, and deployment machinery; it is not an agent dependency-injection container. Authored agents instantiate their model, MCP, skill, Composio, or other vendor clients directly. `configuration/templates/agent/` owns those defaults for newly scaffolded agents. +Provider composition configures Dispatch's control, provisioning, and deployment machinery; it is not an agent dependency-injection container. Authored agents instantiate their model, MCP, skill, Composio, or other vendor clients directly. `configuration/templates/agent/` owns those defaults for newly scaffolded agents. -OpenBot stores only reconciliation mappings, digests, and leases as Control State. Tilde remains authoritative for registered agents, skills, conversations, tools, and memory; credentials remain in `EnvProvider`. +Dispatch stores only reconciliation mappings, digests, and leases as Control State. Tilde remains authoritative for registered agents, skills, conversations, tools, and memory; credentials remain in `EnvProvider`. ```mermaid flowchart LR F["configuration/index.ts"] --> P["Concrete providers"] - P --> B["OpenBot build"] + P --> B["Dispatch build"] B --> H["Hono agent endpoints"] B --> R["Tilde reconciliation"] E["Edit committed agent module"] --> B @@ -44,13 +44,13 @@ flowchart LR - 2026-08-13T11:12:53+02:00: Moved provider selection into generated `configuration/index.ts` with explicit concrete construction and removed descriptor-driven selector factories. - 2026-08-13T11:20:28+02:00: Grouped concrete implementations under `providers` and made agents, skills, custom provider source, and sandbox resources use fixed file-based conventions instead of configurable paths. -- 2026-08-13T12:27:55+02:00: Replaced flat agent modules with path-identified agent directories modeled on Eve while retaining OpenBot's ChatKit runtime and shared-computer boundary. +- 2026-08-13T12:27:55+02:00: Replaced flat agent modules with path-identified agent directories modeled on Eve while retaining Dispatch's ChatKit runtime and shared-computer boundary. - 2026-08-13T13:23:44+02:00: Removed installation-level skill and sandbox configuration; skills and workspace seeds now exist only inside their owning agent directory. -- 2026-08-13T16:00:30+02:00: Reduced the repository's initial `configuration/` tree to `.gitkeep`; every fork must run `openbot init` to materialize its composition root, encrypted configuration, instrumentation, and first agent. +- 2026-08-13T16:00:30+02:00: Reduced the repository's initial `configuration/` tree to `.gitkeep`; every fork must run `tilde init` to materialize its composition root, encrypted configuration, instrumentation, and first agent. - 2026-08-13T16:21:00+02:00: Prohibited root environment and SOPS configuration. Fork values load only from `configuration/`; contributor and CI values come from the process environment and never become fork defaults. - 2026-08-13T16:27:00+02:00: Kept all seven roles explicit in `configuration/index.ts` while moving the five agent-runtime instances to `configuration/runtime-providers.ts`, preventing service build/deploy tooling from entering agent artifacts. - 2026-08-13T17:13:43+02:00: Replaced the upstream `.gitkeep` with an ignore-all `configuration/.gitignore`; successful init removes only that exact sentinel so upstream contributions stay configuration-free while forks commit their generated configuration and preserve the deletion across normal merges. - 2026-08-14T10:18:00+02:00: Consolidated all provider construction in `configuration/index.ts`, removed `configuration/runtime-providers.ts`, and kept generated agent entrypoints independent by reading their runtime environment directly. -- 2026-08-14T10:28:18+02:00: Limited provider composition to OpenBot control and lifecycle concerns; authored agents now integrate external SDKs directly and keep future defaults in the agent template. +- 2026-08-14T10:28:18+02:00: Limited provider composition to Dispatch control and lifecycle concerns; authored agents now integrate external SDKs directly and keep future defaults in the agent template. - 2026-08-14T15:27:17+02:00: Established one full primary agent at `configuration/agent/` and equally capable full agents under `configuration/agent/subagents//`. - 2026-08-18T16:30:00Z: Renamed the primary agent from `hello-world` to `factory` and added the `providers.git` slot to the composition root. Recorded retroactively; PR 57 amended this record's prose without an entry. diff --git a/docs/adrs/0002-unified-changesets-versioning.md b/docs/adrs/0002-unified-changesets-versioning.md index ccfaab56..45a7be09 100644 --- a/docs/adrs/0002-unified-changesets-versioning.md +++ b/docs/adrs/0002-unified-changesets-versioning.md @@ -3,12 +3,12 @@ ## In brief - Changesets records release impact. No second release-note system. -- All OpenBot product packages one fixed group. Tilde SDK packages independent. +- All Dispatch product packages one fixed group. Tilde SDK packages independent. - Packages publish publicly. GitHub Action currently opens a version PR only. ## Context -OpenBot is a public-package monorepo whose application packages evolve as one product. Independent +Dispatch is a public-package monorepo whose application packages evolve as one product. Independent version drift inside that product would imply unsupported compatibility boundaries, while direct version edits would make release intent difficult to review. General `@trytilde/sdk*` packages also live in the repository, but their external consumers and Tilde API compatibility form a separate @@ -16,7 +16,7 @@ release boundary. ## Decision -Changesets manages release notes and package versions. Every OpenBot product package belongs to one +Changesets manages release notes and package versions. Every Dispatch product package belongs to one fixed group and is configured for public npm publication. Tilde SDK packages remain outside that group and version independently. Contributors add changesets for owner-visible behavior or package API changes. GitHub Actions may create or update a version pull request; the current workflow does @@ -26,13 +26,13 @@ not publish packages automatically. flowchart LR C["Contributor changeset"] --> A["Changesets Action"] A --> V["Unified version pull request"] - V --> G["Fixed OpenBot versions"] + V --> G["Fixed Dispatch versions"] V --> S["Independent Tilde SDK versions"] ``` ## Consequences -- One release number describes the complete OpenBot product package set. +- One release number describes the complete Dispatch product package set. - Public package artifacts are generated and verified before publication. - Enabling automatic npm publication remains a separate workflow decision. @@ -40,4 +40,4 @@ flowchart LR - 2026-08-13T17:50:21+02:00: Configured every workspace package for public publication and kept automatic publishing outside the current workflow. - 2026-08-13T18:01:43+02:00: Made native package imports resolve built artifacts while the explicit development condition continues to expose TypeScript sources. -- 2026-08-24T15:45:48+02:00: Kept the imported Tilde SDK packages outside OpenBot's fixed version group because their public API and external consumers form an independent compatibility boundary. +- 2026-08-24T15:45:48+02:00: Kept the imported Tilde SDK packages outside Dispatch's fixed version group because their public API and external consumers form an independent compatibility boundary. diff --git a/docs/adrs/0004-domain-provider-packages.md b/docs/adrs/0004-domain-provider-packages.md index cc09cc2d..3102a12e 100644 --- a/docs/adrs/0004-domain-provider-packages.md +++ b/docs/adrs/0004-domain-provider-packages.md @@ -11,7 +11,7 @@ ## Context -OpenBot originally grouped chat data, external resource provisioning, model selection, prompt injection, tools, skills, and Computer operations behind broad provider contracts. That made providers look like a generic agent plugin system and forced authored agents through abstractions designed for OpenBot's control plane. +Dispatch originally grouped chat data, external resource provisioning, model selection, prompt injection, tools, skills, and Computer operations behind broad provider contracts. That made providers look like a generic agent plugin system and forced authored agents through abstractions designed for Dispatch's control plane. The web and desktop need access to Tilde-owned conversation state without duplicating Tilde's contract. Startup and deployment need typed external-resource lifecycles. Authored agents need freedom to use whichever SDKs and services fit their job. @@ -26,7 +26,7 @@ A provider operation is valid only when it is consumed by one of these boundarie Provider contracts live in `src/core.ts` or `src/core/` in the owning domain package. Adapters live beside them. Contracts contain only operations used by those boundaries; speculative and convenience methods are removed. -Tilde owns conversation-facing agent, session, message, attachment, queue, and streaming contracts. OpenBot does not project those operations through a Chat Provider or control RPC. The browser uses an allowlisted same-origin REST/SSE bridge that preserves Tilde's request and response shapes while the server supplies team credentials. +Tilde owns conversation-facing agent, session, message, attachment, queue, and streaming contracts. Dispatch does not project those operations through a Chat Provider or control RPC. The browser uses an allowlisted same-origin REST/SSE bridge that preserves Tilde's request and response shapes while the server supplies team credentials. `agent-provider` exposes one idempotent deployment lifecycle for the complete external footprint of an authored agent. Its Tilde adapter owns endpoint lookup, creation, repair, status reconciliation, authored-skill synchronization, exact skill-registry membership, dynamic MCP reconciliation, Tilde control-plane tools, and deployment-platform MCP integrations. These are cohesive internal reconcilers, not separately configurable Skills or Tools Providers. The CLI schedules the aggregate lifecycle once per agent and never contains vendor CRUD. @@ -34,7 +34,7 @@ The old model-facing inference-model provider is removed. A narrow `inference-pr Code under `configuration/agent/`, including its `subagents/`, must not import provider packages or `configuration/index.ts`. Agents instantiate model clients, MCP clients, skill clients, Composio, and other SDKs directly. Defaults for future agents live in `configuration/templates/agent/`; existing agents change only through explicit edits. -The standard typed Computer AI tools are a reusable runtime utility in `@tryopenbot/computer-tools`, separate from `computer-service-provider`. They call the capability-protected Computer service. `computer-service-provider` retains only provisioning and lifecycle methods in its public contract, while concrete adapters may use internal Computer operations to implement those lifecycles. The provider package does not depend on or re-export `computer-tools`. +The standard typed Computer AI tools are a reusable runtime utility in `@trytilde/dispatch-computer-tools`, separate from `computer-service-provider`. They call the capability-protected Computer service. `computer-service-provider` retains only provisioning and lifecycle methods in its public contract, while concrete adapters may use internal Computer operations to implement those lifecycles. The provider package does not depend on or re-export `computer-tools`. Shared vendor plumbing used across domains belongs in `platform-integrations`. Multiple adapters share one concrete platform instance so initialization runs once. Domain mapping and error translation remain in each adapter. @@ -81,9 +81,9 @@ flowchart LR - 2026-08-29T14:55:00Z: Made the Agent Provider omit memory from new bundle requests. Tilde memory banks require an explicit opt-in; agent creation must not enroll or fail on them implicitly. Bundle omission preserves an existing - agent-owned bank, so users can enable memory explicitly without OpenBot + agent-owned bank, so users can enable memory explicitly without Dispatch deleting it on later reconciliation. -- 2026-08-25T12:35:12+02:00: Replaced client-side agent/MCP/registry choreography with Tilde's durable Agent Resource Bundle API. OpenBot still authors runtime source and reconciles ChatKit realtime plus credential-bearing platform integrations, while Tilde owns the canonical MCP server, skill registry, default memory bank, bindings, credential rotation, and deletion cleanup. +- 2026-08-25T12:35:12+02:00: Replaced client-side agent/MCP/registry choreography with Tilde's durable Agent Resource Bundle API. Dispatch still authors runtime source and reconciles ChatKit realtime plus credential-bearing platform integrations, while Tilde owns the canonical MCP server, skill registry, default memory bank, bindings, credential rotation, and deletion cleanup. - 2026-08-25T19:41:00+02:00: Made Tilde's stable machine-user profile the canonical agent identity. The Agent Provider renders and uploads a deterministic PNG avatar after bundle convergence; display-name and avatar updates no longer depend on device-local onboarding state. - 2026-08-25T20:12:00+02:00: The owner-facing agent-creation route establishes the initial bundle with the deployment API key delegated by the signed-in human. Later machine-only deploys reconcile the same bundle without replacing that individual lifecycle owner. @@ -96,7 +96,7 @@ flowchart LR - 2026-08-13T13:17:11+02:00: Renamed `computer-providers` to singular `computer-provider`. - 2026-08-14T10:28:18+02:00: Split chat operations from agent provisioning, removed inference and model-facing provider hooks, moved Computer AI tools to a non-provider package, and prohibited provider imports from authored agents. - 2026-08-14T10:55:00+02:00: Replaced public agent-resource CRUD with an idempotent `Deployable`; the Tilde adapter now discovers desired agents, reconciles Vercel AI SDK endpoints for development and production, and clears an endpoint before removing a stale managed agent. -- 2026-08-14T18:40:00+02:00: Removed the Tilde state file from OpenBot's normal lifecycle. Tilde providers now reconcile agents, authored skills, exact registries, dynamic MCP servers, the Tilde control-plane toolkit, and deployment-platform MCP integrations directly through typed APIs. Operators may still use the Tilde CLI manually for one-time team-to-team state migration. +- 2026-08-14T18:40:00+02:00: Removed the Tilde state file from Dispatch's normal lifecycle. Tilde providers now reconcile agents, authored skills, exact registries, dynamic MCP servers, the Tilde control-plane toolkit, and deployment-platform MCP integrations directly through typed APIs. Operators may still use the Tilde CLI manually for one-time team-to-team state migration. - 2026-08-16T15:08:39+02:00: Removed Chat, Skills, and Tools Provider packages. Tilde conversation traffic now retains its native REST/SSE contract, while one Agent Provider lifecycle reconciles each authored agent and all of its external skills, tools, and MCP resources. -- 2026-08-17T20:05:00+02:00: Renamed `@tryopenbot/computer-provider` to `@tryopenbot/computer-service-provider` and removed its `computer-tools` compatibility export and dependency so service lifecycle and agent runtime tools remain separate package boundaries. +- 2026-08-17T20:05:00+02:00: Renamed `@trytilde/dispatch-computer-provider` to `@trytilde/dispatch-computer-service-provider` and removed its `computer-tools` compatibility export and dependency so service lifecycle and agent runtime tools remain separate package boundaries. - 2026-08-25T12:00:00+02:00: Kept one Agent Provider lifecycle while moving its dependent Tilde reconciliation sequence behind one typed, idempotent bundle operation at the Tilde composition root. diff --git a/docs/adrs/0006-provider-deployment-lifecycle.md b/docs/adrs/0006-provider-deployment-lifecycle.md index 4cf2500f..860ac19d 100644 --- a/docs/adrs/0006-provider-deployment-lifecycle.md +++ b/docs/adrs/0006-provider-deployment-lifecycle.md @@ -2,7 +2,7 @@ ## In brief -- One `openbot deploy` plans, optionally configures, then deploys opted-in providers. +- One `tilde deploy` plans, optionally configures, then deploys opted-in providers. - Providers without an exposed `deployable` are skipped entirely. - `configure()` is optional. Use it only for stable identity or prerequisites. - Distinct provider instances deploy independently; one shared runtime instance may satisfy both control and agent roles. @@ -11,7 +11,7 @@ ## Context -OpenBot can use the same vendor through several domain providers. For example, separate provider implementations might both use Vercel. Automatically collapsing those implementations into one vendor deployment would couple otherwise independent domains and require an infrastructure ownership model that the application does not yet have. +Dispatch can use the same vendor through several domain providers. For example, separate provider implementations might both use Vercel. Automatically collapsing those implementations into one vendor deployment would couple otherwise independent domains and require an infrastructure ownership model that the application does not yet have. There is also an ordering cycle: a provider such as Tilde can need the runtime's stable public origin before it deploys, while the runtime needs the secrets and environment variables produced by Tilde before it releases application code. @@ -39,13 +39,13 @@ checks, lets Tilde reconcile external resources, and makes service deployables no-op because one watched Hono process owns control and agent routes. Deployment environment selection remains separate from this lifecycle-mode flag. -The local runtime implementation writes a private runtime environment file, then installs OpenBot as a user service: systemd on Linux or launchd on macOS. Service definitions contain only the environment-file path, not secret values. +The local runtime implementation writes a private runtime environment file, then installs Dispatch as a user service: systemd on Linux or launchd on macOS. Service definitions contain only the environment-file path, not secret values. -Do not adopt a general infrastructure state engine yet. Alchemy has a useful resource/output/reconciliation model, but without built-in Vercel and Tilde resources OpenBot would still need custom providers plus another state lifecycle. +Do not adopt a general infrastructure state engine yet. Alchemy has a useful resource/output/reconciliation model, but without built-in Vercel and Tilde resources Dispatch would still need custom providers plus another state lifecycle. ```mermaid flowchart LR - C["openbot deploy"] --> P["Plan every provider"] + C["tilde deploy"] --> P["Plan every provider"] P --> F["Configure stable identities"] F --> D["Deploy non-runtime providers"] D --> O["Aggregate outputs, env, and secrets"] diff --git a/docs/adrs/0007-sops-bootstrap-and-provider-init.md b/docs/adrs/0007-sops-bootstrap-and-provider-init.md index 6c15d809..a38c2bac 100644 --- a/docs/adrs/0007-sops-bootstrap-and-provider-init.md +++ b/docs/adrs/0007-sops-bootstrap-and-provider-init.md @@ -16,23 +16,23 @@ ## Context -OpenBot must be able to run and mutate its complete development setup inside a sandbox, then deploy providers and the final runtime. That sandbox needs deployment credentials and a durable way to decrypt repository secrets after its first creation. Encrypting its private identity only to itself would create a bootstrap cycle, while giving every agent computer the identity would collapse the control and computer trust boundaries. +Dispatch must be able to run and mutate its complete development setup inside a sandbox, then deploy providers and the final runtime. That sandbox needs deployment credentials and a durable way to decrypt repository secrets after its first creation. Encrypting its private identity only to itself would create a bootstrap cycle, while giving every agent computer the identity would collapse the control and computer trust boundaries. Provider setup also needs interactive input, but provider packages must not depend on Ink because the same onboarding will later be renderable in the web application. ## Decision -`openbot init` creates `configuration/.env` first, then generates an X25519 age identity dedicated to the trusted development sandbox. Age is smaller and easier to automate safely than a generated PGP identity. The owner selects a second independent recipient: HashiCorp Vault Transit, Azure Key Vault, Google Cloud KMS, AWS KMS, a generated age identity stored in 1Password, or a generated age identity stored in the operating system keychain. +`tilde init` creates `configuration/.env` first, then generates an X25519 age identity dedicated to the trusted development sandbox. Age is smaller and easier to automate safely than a generated PGP identity. The owner selects a second independent recipient: HashiCorp Vault Transit, Azure Key Vault, Google Cloud KMS, AWS KMS, a generated age identity stored in 1Password, or a generated age identity stored in the operating system keychain. -Both recipients occupy the same SOPS key group, so either can decrypt. Threshold key groups are not used. Every top-level secret is a `{ description, value }` mapping; `encrypted_regex: ^value$` keeps descriptions readable while encrypting values. The sandbox private identity is stored only inside `configuration/secrets.enc.yaml` at `SECRETS_SOPS_AGE_KEY.value`. On deployment, the owner recipient decrypts that value and the computer provider writes it to `/workspace/.openbot/development/sops-age-key.txt` with mode `0400` inside a mode-`0700` directory. +Both recipients occupy the same SOPS key group, so either can decrypt. Threshold key groups are not used. Every top-level secret is a `{ description, value }` mapping; `encrypted_regex: ^value$` keeps descriptions readable while encrypting values. The sandbox private identity is stored only inside `configuration/secrets.enc.yaml` at `SECRETS_SOPS_AGE_KEY.value`. On deployment, the owner recipient decrypts that value and the computer provider writes it to `/workspace/.dispatch/development/sops-age-key.txt` with mode `0400` inside a mode-`0700` directory. -The trusted development sandbox is a deployment controller and secret-bearing boundary. Every deployment refreshes `configuration/.env`, `configuration/.sops.yaml`, and `configuration/secrets.enc.yaml` in its source tree. Its `.bashrc` and `.bash_profile` source an idempotent loader that sources dotenv values, points SOPS at the private age-key file, decrypts the top-level described secrets, and exports their values. There are no lifecycle secret groups or separate sandbox environment result fields. Ordinary OpenBot Computers created for agents never receive the SOPS identity or the fork configuration files. +The trusted development sandbox is a deployment controller and secret-bearing boundary. Every deployment refreshes `configuration/.env`, `configuration/.sops.yaml`, and `configuration/secrets.enc.yaml` in its source tree. Its `.bashrc` and `.bash_profile` source an idempotent loader that sources dotenv values, points SOPS at the private age-key file, decrypts the top-level described secrets, and exports their values. There are no lifecycle secret groups or separate sandbox environment result fields. Ordinary Dispatch Computers created for agents never receive the SOPS identity or the fork configuration files. Providers may expose serializable initialization metadata: label, description, questions, validation, choices, and a destination mapping to either `.env` or encrypted secrets. Providers do not expose terminal components or browser components. The CLI renders that schema with Ink; a later browser flow can render the same schema. When several domain providers use the same external platform, they reference one concrete `Platform` implementation by stable ID. The initializer collects its initialization contract once and rejects conflicting definitions. `TildePlatform` owns one shared connection and lazily cached Harness SDK client, plus shared request, cancellation, and error-normalization helpers used by its agent, skills, and tools adapters. `VercelPlatform` owns the shared credential and account scope plus common project, environment, deployment-output, and registry operations used by its control-service, agent-service, and computer adapters. Domain providers continue to own role-specific inputs, entity mapping, domain error translation, and artifact behavior. Destination-key deduplication remains a final collision check rather than the ownership mechanism. -After the initial bootstrap, running `openbot init` inside the configured repository is a reconciliation operation. For each provider domain with multiple built-in implementations, the React Ink selector always offers every implementation and preselects the implementation recognized in the active provider graph. Provider domains are staged: immediately after selection, init asks that provider's questions and runs its provisioning hook before presenting another provider selector or shared-platform setup. This makes authorization causally adjacent to the choice and prevents an unrelated later provider failure from blocking it. Init decrypts current described secrets, pre-populates each platform and provider question from its destination, and updates only the destinations represented by the selected graph. Unknown environment and secret entries remain intact. Init rewrites `configuration/index.ts` only when the current file exactly matches the canonical source for its recognized built-in composition. A custom or owner-edited composition remains available as the current selection but requires an explicit edit to change. When inference changes, init likewise replaces provider-contributed template and existing-agent files only when every affected file exactly matches the previous provider scaffold, and it completes those migrations before committing the new composition. A cloned OpenBot checkout without completed SOPS markers is resumable after provider failure and is not bootstrapped again. The existing SOPS creation rule and owner metadata remain authoritative, and `vp install` runs after reconciliation. Changing SOPS recipients is an explicit owner maintenance operation, not an init prompt. +After the initial bootstrap, running `tilde init` inside the configured repository is a reconciliation operation. For each provider domain with multiple built-in implementations, the React Ink selector always offers every implementation and preselects the implementation recognized in the active provider graph. Provider domains are staged: immediately after selection, init asks that provider's questions and runs its provisioning hook before presenting another provider selector or shared-platform setup. This makes authorization causally adjacent to the choice and prevents an unrelated later provider failure from blocking it. Init decrypts current described secrets, pre-populates each platform and provider question from its destination, and updates only the destinations represented by the selected graph. Unknown environment and secret entries remain intact. Init rewrites `configuration/index.ts` only when the current file exactly matches the canonical source for its recognized built-in composition. A custom or owner-edited composition remains available as the current selection but requires an explicit edit to change. When inference changes, init likewise replaces provider-contributed template and existing-agent files only when every affected file exactly matches the previous provider scaffold, and it completes those migrations before committing the new composition. A cloned Dispatch checkout without completed SOPS markers is resumable after provider failure and is not bootstrapped again. The existing SOPS creation rule and owner metadata remain authoritative, and `vp install` runs after reconciliation. Changing SOPS recipients is an explicit owner maintenance operation, not an init prompt. Plaintext sent to SOPS stays in memory. The CLI uses a private named pipe for SOPS versions that require an input filename; the FIFO contains no stored file data. Generated owner age identities are passed to 1Password or native keychain commands over standard input, never command arguments. @@ -40,7 +40,7 @@ Owner identity lookup metadata is machine-, user-, and checkout-specific. It liv ```mermaid flowchart LR - I["openbot init"] --> A["Generated sandbox age recipient"] + I["tilde init"] --> A["Generated sandbox age recipient"] I --> O["Owner recipient"] A --> S["SOPS secrets.enc.yaml"] O --> S @@ -65,10 +65,10 @@ flowchart LR - 2026-08-21T19:57:19+01:00: Staged init by provider domain so selection immediately runs that provider's questions and provisioning, placed Codex device login before shared Tilde setup, and made post-clone failures resumable. - 2026-08-21T16:34:56+01:00: Made every interactive provider selector show all built-in implementations with the configured provider preselected, and added guarded canonical composition plus inference-scaffold migration for provider changes. - 2026-08-14T15:14:30+02:00: Removed lifecycle secret grouping for the trusted development sandbox. Deployment now refreshes the fork `.env`, SOPS config, and encrypted secrets, writes the age identity as a `0400` user-owned file, and loads dotenv plus decrypted SOPS values from Bash profiles. -- 2026-08-14T10:27:59+02:00: Moved user-specific SOPS owner lookup metadata from the fork into typed `~/.openbot/config.json` state, added interactive recovery, and made non-interactive commands fail instead of guessing missing identity configuration. +- 2026-08-14T10:27:59+02:00: Moved user-specific SOPS owner lookup metadata from the fork into typed `~/.dispatch/config.json` state, added interactive recovery, and made non-interactive commands fail instead of guessing missing identity configuration. - 2026-08-14T00:21:24+02:00: Replaced metadata-only initialization dependencies with concrete `Platform` implementations, moved common Tilde and Vercel operations out of domain providers, and made init re-runnable with stored prompt defaults, config reconciliation, existing SOPS ownership, and dependency installation preserved. - 2026-08-13T23:59:56+02:00: Added stable shared platform initialization dependencies so Tilde and Vercel setup is collected once across their domain providers while role-specific questions remain with the consuming provider. -- 2026-08-13T23:34:00+02:00: Replaced grouped secret mappings with mandatory described top-level entries, encrypted only `value`, adopted concise repository-facing built-in names, and added described `openbot env set|unset` management for plaintext configuration. +- 2026-08-13T23:34:00+02:00: Replaced grouped secret mappings with mandatory described top-level entries, encrypted only `value`, adopted concise repository-facing built-in names, and added described `tilde env set|unset` management for plaintext configuration. - 2026-08-13T12:53:05+02:00: Implemented the trusted development sandbox as a sandbox-role deployment participant that seeds repository source once, installs the aggregate deployment environment with mode `0600`, verifies SOPS decryption, and remains separate from ordinary agent workspaces. - 2026-08-13T14:49:44+02:00: Added a SOPS-generated static computer-service API key shared only with control, agent, and computer runtimes; computer RPC authorization validates that exact bearer key, and model-controlled Linux processes start with a clean allowlisted environment that excludes it. diff --git a/docs/adrs/0008-split-control-and-agent-service-artifacts.md b/docs/adrs/0008-split-control-and-agent-service-artifacts.md index 321a1855..b2227f5d 100644 --- a/docs/adrs/0008-split-control-and-agent-service-artifacts.md +++ b/docs/adrs/0008-split-control-and-agent-service-artifacts.md @@ -3,19 +3,19 @@ ## In brief - Build and deploy one runtime artifact containing control, web, and agent entrypoints. -- One Vercel project owns the whole OpenBot runtime. +- One Vercel project owns the whole Dispatch runtime. - Every agent source becomes its own Vercel Function entrypoint. - Agent functions remain isolated at execution, but deploy and roll back atomically with control and web. - Local production and development each use one Hono process. - Software-producing providers implement `Buildable.check()` and `Buildable.build()` as well as `Deployable`. -- `openbot deploy` always checks and builds selected services first. `--skip-deploy` stops after artifacts exist. +- `tilde deploy` always checks and builds selected services first. `--skip-deploy` stops after artifacts exist. - Use native Go TypeScript (`tsgo`) for artifact checks and tsdown/Rolldown for bundles. Vite+ owns repository orchestration and validation. ## Context -Agent implementations change more frequently than the owner-facing control API and web application. The original decision optimized that difference with separate control and agent projects, but it also duplicated project identity, environment reconciliation, deployment coordination, and local service supervision. Tilde now exposes enough unified control-plane operations that OpenBot no longer benefits from retaining a second service boundary merely to coordinate those resources. +Agent implementations change more frequently than the owner-facing control API and web application. The original decision optimized that difference with separate control and agent projects, but it also duplicated project identity, environment reconciliation, deployment coordination, and local service supervision. Tilde now exposes enough unified control-plane operations that Dispatch no longer benefits from retaining a second service boundary merely to coordinate those resources. -OpenBot also needs equivalent local production behavior without making development operate multiple unnecessary processes. Build tooling is part of this boundary: the old tsup pipeline is deprecated, and JavaScript TypeScript checking is too slow for a directory of independently bundled agents. +Dispatch also needs equivalent local production behavior without making development operate multiple unnecessary processes. Build tooling is part of this boundary: the old tsup pipeline is deprecated, and JavaScript TypeScript checking is too slow for a directory of independently bundled agents. ## Decision @@ -23,7 +23,7 @@ OpenBot also needs equivalent local production behavior without making developme Vercel receives one prebuilt Build Output API artifact. Its project contains static web assets, the control Hono Function, and one `.func` per authored agent. Changed agent builds execute concurrently through tsdown's Rolldown/Oxc pipeline; content digests reuse unchanged function directories and conservatively invalidate on shared package or lockfile changes. One deployment publishes the complete runtime, while the agent endpoints retain independent function execution, scaling, bundles, and logs. -Local builds emit one Node artifact that mounts agent routes before the control/web fallback. Deployment installs `openbot-control` as the sole user service on port 4100. After that service passes its health check and Tilde endpoint cutover succeeds, deployment disables and preserves a legacy `openbot-agents` service definition as a recoverable `.retired` file. Repeated deployments converge without repeating retirement. +Local builds emit one Node artifact that mounts agent routes before the control/web fallback. Deployment installs `dispatch-control` as the sole user service on port 4100. After that service passes its health check and Tilde endpoint cutover succeeds, deployment disables and preserves a legacy `dispatch-agents` service definition as a recoverable `.retired` file. Repeated deployments converge without repeating retirement. During development both local and Vercel service deployables stop after their checks and leave startup to that watched process. The Computer image has a diff --git a/docs/adrs/0009-service-names-and-single-computer-api.md b/docs/adrs/0009-service-names-and-single-computer-api.md index 84e2a5b1..6c8b13c4 100644 --- a/docs/adrs/0009-service-names-and-single-computer-api.md +++ b/docs/adrs/0009-service-names-and-single-computer-api.md @@ -4,7 +4,7 @@ - Name application packages after the service they own. - `apps/control-service` owns the owner-facing Hono HTTP service. -- `apps/computer-service` is the only API running inside an OpenBot Computer. +- `apps/computer-service` is the only API running inside a Dispatch Computer. - Keep ConnectRPC for the generated, API-key-protected Computer contract. - Remove the legacy `box-host` package and `BoxService` protocol. - Keep Vercel-specific control adapters in `control-service-provider`, not the portable application or repository root. @@ -22,8 +22,8 @@ transport rather than its domain, and contained a Vercel-only fetch wrapper. ## Decision -Rename `apps/server` and `@tryopenbot/server` to `apps/control-service` and -`@tryopenbot/control-service`. Keep its Hono app and local Node entrypoint portable. +Rename `apps/server` and `@trytilde/dispatch-server` to `apps/control-service` and +`@trytilde/dispatch-control-service`. Keep its Hono app and local Node entrypoint portable. The Vercel control provider owns the Web fetch adapter as a typed asset and bundles it as part of its prebuilt artifact lifecycle. @@ -60,6 +60,6 @@ flowchart LR - 2026-08-13T11:12:53+02:00: Required the shared computer image to compile the sole computer service in a multi-stage container build instead of copying a host-built bundle. - 2026-08-13T12:09:51+02:00: Removed the obsolete legacy contracts package after `computer-service-proto` became the only computer RPC contract. -- 2026-08-13T17:33:29+02:00: Renamed the private workspace package scope from `@openbot` to `@tryopenbot` while retaining the `openbot` CLI command. +- 2026-08-13T17:33:29+02:00: Renamed the private workspace package scope from `@dispatch` to `@trytilde/dispatch-*` while retaining the Tilde CLI command. - 2026-08-15T13:25:19+02:00: Made computer-service the owner of per-agent display reconciliation and capability-routed VNC streams inside the one shared Computer. - 2026-08-16T15:08:39+02:00: Retained ConnectRPC exclusively for the internal Computer API while removing owner-facing ConnectRPC from control-service. Frontend code never calls Computer service directly. diff --git a/docs/adrs/0010-provider-owned-deployment-assets.md b/docs/adrs/0010-provider-owned-deployment-assets.md index 3738c0d8..5b23b350 100644 --- a/docs/adrs/0010-provider-owned-deployment-assets.md +++ b/docs/adrs/0010-provider-owned-deployment-assets.md @@ -16,7 +16,7 @@ Provider implementations produced complete TypeScript entrypoints, JSON configur Small providers may remain in `src/.ts`. Once a provider owns multiple lifecycle responsibilities or runtime files, it moves to `src//index.ts`, focused sibling modules, and `src//assets/`. Generated-file sources use the target extension followed by `.hbs` and are resolved relative to `import.meta.url`. -`Buildable.build()` bundles executable assets and renders configuration into an ignored deployment artifact. `Deployable.deploy()` renders project configuration that is only needed to invoke the platform. Both use the file-template utilities exported by `@tryopenbot/utilities`, whose strict Handlebars compilation rejects missing values. Values are escaped for their target format before rendering; deliberately pre-encoded fragments use triple braces. Complete files are not stored in TypeScript strings, rendered by ad hoc replacement functions, or copied directly from provider assets. +`Buildable.build()` bundles executable assets and renders configuration into an ignored deployment artifact. `Deployable.deploy()` renders project configuration that is only needed to invoke the platform. Both use the file-template utilities exported by `@trytilde/dispatch-utilities`, whose strict Handlebars compilation rejects missing values. Values are escaped for their target format before rendering; deliberately pre-encoded fragments use triple braces. Complete files are not stored in TypeScript strings, rendered by ad hoc replacement functions, or copied directly from provider assets. For Vercel prebuilt deployments, each service provider owns an `assets/vercel.json.hbs`, Function entrypoints, Function configuration, and Build Output configuration as Handlebars assets. The build emits `.vercel/output/config.json`, which owns prebuilt routing. The deploy lifecycle renders `vercel.json` to that service's artifact root immediately before invoking Vercel. No root `vercel.json` is tracked. @@ -50,6 +50,6 @@ flowchart LR ## Updates - 2026-08-13T11:12:53+02:00: Standardized generated source, configuration, service, deployment, and provider assets on strict Handlebars templates while keeping runtime persistence and user file bytes byte preserving. -- 2026-08-13T12:09:51+02:00: Moved file-template helpers into the shared `@openbot/utilities` package so future cross-domain utilities have one neutral home. -- 2026-08-13T17:33:29+02:00: Renamed the private workspace package scope from `@openbot` to `@tryopenbot`; provider asset ownership and lifecycle boundaries are unchanged. -- 2026-08-17T20:05:00+02:00: Renamed the Computer lifecycle and image owner to `@tryopenbot/computer-service-provider`; asset ownership and rendering behavior are unchanged. +- 2026-08-13T12:09:51+02:00: Moved file-template helpers into the shared `@dispatch/utilities` package so future cross-domain utilities have one neutral home. +- 2026-08-13T17:33:29+02:00: Renamed the private workspace package scope from `@dispatch` to `@trytilde/dispatch-*`; provider asset ownership and lifecycle boundaries are unchanged. +- 2026-08-17T20:05:00+02:00: Renamed the Computer lifecycle and image owner to `@trytilde/dispatch-computer-service-provider`; asset ownership and rendering behavior are unchanged. diff --git a/docs/adrs/0011-eve-compatible-agent-layout.md b/docs/adrs/0011-eve-compatible-agent-layout.md index 5b9e5322..da90fcb7 100644 --- a/docs/adrs/0011-eve-compatible-agent-layout.md +++ b/docs/adrs/0011-eve-compatible-agent-layout.md @@ -18,7 +18,7 @@ ## Context -OpenBot needs a predictable, portable authored-agent layout without inventing vocabulary that already exists in Vercel's Eve SDK. Eve's filesystem model is a useful convention, but OpenBot uses Tilde ChatKit endpoints, its own provider composition, one shared computer, and independently built local or Vercel agent-service artifacts. Blind Eve compatibility would therefore promise runtime behavior OpenBot does not have. +Dispatch needs a predictable, portable authored-agent layout without inventing vocabulary that already exists in Vercel's Eve SDK. Eve's filesystem model is a useful convention, but Dispatch uses Tilde ChatKit endpoints, its own provider composition, one shared computer, and independently built local or Vercel agent-service artifacts. Blind Eve compatibility would therefore promise runtime behavior Dispatch does not have. ## Decision @@ -46,22 +46,22 @@ configuration/ └── sandbox/workspace/** ``` -`agent.ts` is required and default-exports the request handler returned by Tilde `chatKitEndpoint(...)`. `instructions.ts` is required, default-exports the system instructions, and is imported explicitly by `agent.ts`. OpenBot does not support `instructions.md`. +`agent.ts` is required and default-exports the request handler returned by Tilde `chatKitEndpoint(...)`. `instructions.ts` is required, default-exports the system instructions, and is imported explicitly by `agent.ts`. Dispatch does not support `instructions.md`. Init seeds `configuration/templates/agent/` from packaged defaults only when the -directory is missing. `openbot new-agent` recursively renders that fork-owned +directory is missing. `tilde new-agent` recursively renders that fork-owned template, preserves relative paths, and removes `.hbs` suffixes. Template edits affect future agents only; existing authored agents are never regenerated implicitly. Provider-composition changes may therefore require both a template update and an explicit migration of existing agents. -The optional instrumentation files use Eve's `defineInstrumentation({ setup })` authoring shape from `@tryopenbot/configuration/instrumentation`. `configuration/instrumentation.ts` runs first for every agent at server startup; an optional agent-local `instrumentation.ts` runs second; only then does OpenBot import `agent.ts`. OpenBot supplies the resolved path-derived `agentName`. Instrumentation is a server startup hook, not an agent tool. +The optional instrumentation files use Eve's `defineInstrumentation({ setup })` authoring shape from `@trytilde/dispatch-configuration/instrumentation`. `configuration/instrumentation.ts` runs first for every agent at server startup; an optional agent-local `instrumentation.ts` runs second; only then does Dispatch import `agent.ts`. Dispatch supplies the resolved path-derived `agentName`. Instrumentation is a server startup hook, not an agent tool. -Every file under `tools/` default-exports a Vercel AI SDK tool. Every skill is a spec-conformant Markdown file or skill package. `lib/` is ordinary import-only TypeScript. Skills remain authored structure without automatic loading. Tools are explicitly imported by `agent.ts`; OpenBot does not use a directory loader. Channels, connections, hooks, schedules, and nested subagents are not supported. +Every file under `tools/` default-exports a Vercel AI SDK tool. Every skill is a spec-conformant Markdown file or skill package. `lib/` is ordinary import-only TypeScript. Skills remain authored structure without automatic loading. Tools are explicitly imported by `agent.ts`; Dispatch does not use a directory loader. Channels, connections, hooks, schedules, and nested subagents are not supported. -OpenBot terminology calls the runtime a Computer, so new APIs, environment variables, and provider contracts use `computer`. The authored `sandbox/workspace/**` path and familiar model-facing tool names are deliberate compatibility exceptions that keep OpenBot agent repositories structurally familiar without changing the shared-computer model. +Dispatch terminology calls the runtime a Computer, so new APIs, environment variables, and provider contracts use `computer`. The authored `sandbox/workspace/**` path and familiar model-facing tool names are deliberate compatibility exceptions that keep Dispatch agent repositories structurally familiar without changing the shared-computer model. -Every agent explicitly contains `await_shell.ts`, `bash.ts`, `copy_from_computer.ts`, `copy_to_computer.ts`, `read_file.ts`, `write_file.ts`, `glob.ts`, `grep.ts`, and `screenshot.ts`. Each file is a thin default export from `@tryopenbot/computer-tools` with the path-derived agent ID fixed outside its model-visible schema. This non-provider utility owns the reusable Vercel AI SDK tools and Zod schemas; computer-service-proto remains transport-only. Agent code does not call Microsandbox, Vercel Sandbox, or an untyped HTTP endpoint directly. The API-key-protected computer-service validates the request and uses the fixed agent ID to select `/workspace/` as the default directory and to scope durable background-job handles. +Every agent explicitly contains `await_shell.ts`, `bash.ts`, `copy_from_computer.ts`, `copy_to_computer.ts`, `read_file.ts`, `write_file.ts`, `glob.ts`, `grep.ts`, and `screenshot.ts`. Each file is a thin default export from `@trytilde/dispatch-computer-tools` with the path-derived agent ID fixed outside its model-visible schema. This non-provider utility owns the reusable Vercel AI SDK tools and Zod schemas; computer-service-proto remains transport-only. Agent code does not call Microsandbox, Vercel Sandbox, or an untyped HTTP endpoint directly. The API-key-protected computer-service validates the request and uses the fixed agent ID to select `/workspace/` as the default directory and to scope durable background-job handles. Authored agents do not import any provider package or the fork's provider composition. They instantiate model, MCP, skill, Composio, and other vendor clients directly. The fork-owned template carries direct-integration defaults to future agents without turning providers into an agent plugin API. @@ -75,11 +75,11 @@ every Bash command has one deterministic startup file; that profile may source an optional `.bashrc`. The profile contains no secrets and follows the same one-time seed semantics as every other authored workspace file. -OpenBot does not reproduce Eve's one-sandbox-per-agent model. One OpenBot Computer, filesystem, and service process identity are shared by all agents. Computer-service gives each agent its own virtual display and persistent browser profile inside that Computer so concurrent desktop work does not collide visually. When an agent has authored workspace seed files, deployment creates `/workspace/` and copies them there. Commands and relative file paths default to that directory, while absolute paths can address the wider machine. Agent IDs provide routing context, not filesystem, process, or desktop isolation: agents can inspect or modify sibling directories and administer the shared machine subject to the computer process's operating-system privileges. +Dispatch does not reproduce Eve's one-sandbox-per-agent model. One Dispatch Computer, filesystem, and service process identity are shared by all agents. Computer-service gives each agent its own virtual display and persistent browser profile inside that Computer so concurrent desktop work does not collide visually. When an agent has authored workspace seed files, deployment creates `/workspace/` and copies them there. Commands and relative file paths default to that directory, while absolute paths can address the wider machine. Agent IDs provide routing context, not filesystem, process, or desktop isolation: agents can inspect or modify sibling directories and administer the shared machine subject to the computer process's operating-system privileges. Files from either agent form's `sandbox/workspace/**` are copied only when the populated agent directory is first seeded. Empty seed trees do not create `/workspace/`. Ordinary later agent deployments detect the marker and leave the persistent directory untouched. Consequently, edits to authored workspace seeds do not appear for already deployed agents; applying them requires a future explicit workspace reconciliation or destructive computer replacement operation. -Agent-service discovery, checking, content digests, local federation, and parallel Vercel function builds use `agent.ts` inside each directory as the entrypoint. OpenBot follows Eve's layout where possible, but it does not load these folders with Eve and does not claim behavioral compatibility. +Agent-service discovery, checking, content digests, local federation, and parallel Vercel function builds use `agent.ts` inside each directory as the entrypoint. Dispatch follows Eve's layout where possible, but it does not load these folders with Eve and does not claim behavioral compatibility. ```mermaid flowchart LR @@ -98,7 +98,7 @@ flowchart LR ## Consequences -- Fork authors get a familiar Eve-shaped tree without coupling OpenBot deployment to Eve. +- Fork authors get a familiar Eve-shaped tree without coupling Dispatch deployment to Eve. - Each agent remains an independently compiled function entrypoint. - Required computer tools are explicit; arbitrary tools and skills remain author-controlled. - Persistent agent workspaces are protected from silent seed overwrites. @@ -115,13 +115,13 @@ flowchart LR - 2026-08-13T14:29:49+02:00: Kept `sandbox/workspace` solely for Eve layout compatibility, required one typed computer tool file per supported operation, and moved agent-to-user execution enforcement into computer-service. - 2026-08-13T14:49:44+02:00: Standardized required scaffolding on Eve's `bash`, `read_file`, `write_file`, `glob`, and `grep`; each tool fixes its agent ID outside model input and routes through computer-service. - 2026-08-13T15:19:48+02:00: Standardized agent Bash commands on login-shell startup and scaffolded a one-time workspace `.profile` that may source `.bashrc`. -- 2026-08-13T15:36:39+02:00: Made `openbot new-agent` the canonical agent scaffolder, reused it from init, centralized standard tool implementations in computer-provider, and removed the redundant hello-world tool. +- 2026-08-13T15:36:39+02:00: Made `tilde new-agent` the canonical agent scaffolder, reused it from init, centralized standard tool implementations in computer-provider, and removed the redundant hello-world tool. - 2026-08-13T15:41:25+02:00: Replaced per-agent Linux users and mount namespaces with one shared filesystem; populated seeds now initialize `/workspace/` and commands default there without treating it as a security boundary. - 2026-08-13T16:42:00+02:00: Added explicit copy-to, copy-from, screenshot, background-shell, and await-shell scaffolding with Zod schemas; background job state now survives computer-service restarts on the Computer's persistent disk. -- 2026-08-13T17:33:29+02:00: Renamed authored agent imports from the private `@openbot` workspace scope to `@tryopenbot`; the Eve-compatible filesystem layout and `openbot` CLI remain unchanged. +- 2026-08-13T17:33:29+02:00: Renamed authored agent imports from the private `@dispatch` workspace scope to `@trytilde/dispatch-*`; the Eve-compatible filesystem layout and Tilde CLI remain unchanged. - 2026-08-14T03:15:00+02:00: Kept `new-agent` filesystem-only and made `dev` reconcile each authored agent's Tilde ChatKit endpoint, MCP server, and skill registry before server startup. Non-secret resource IDs live in `configuration/.env`; endpoint credentials remain in encrypted configuration, and generated agents select their own MCP server and registry through those per-agent variables. - 2026-08-14T10:03:00+02:00: Made `configuration/templates/agent/` the fork-owned source for future agents. Init seeds it without overwriting owner edits; `new-agent` renders it recursively, while existing agents remain unchanged. -- 2026-08-14T10:28:18+02:00: Moved reusable Computer AI tools to `@tryopenbot/computer-tools`, instrumentation helpers to `@tryopenbot/configuration/instrumentation`, and prohibited provider imports from authored agents; agent integrations now use their vendor SDKs directly. +- 2026-08-14T10:28:18+02:00: Moved reusable Computer AI tools to `@trytilde/dispatch-computer-tools`, instrumentation helpers to `@trytilde/dispatch-configuration/instrumentation`, and prohibited provider imports from authored agents; agent integrations now use their vendor SDKs directly. - 2026-08-14T10:55:00+02:00: Made `new-agent` invoke the same idempotent development lifecycle as `dev` after filesystem scaffolding; the Tilde agent provider, rather than the CLI, owns endpoint reconciliation and local tunneling. - 2026-08-14T15:27:17+02:00: Made `configuration/agent/` the full primary agent and `configuration/agent/subagents//` the canonical home for equally complete additional agents. Discovery and builds reject deeper nesting. - 2026-08-15T13:25:19+02:00: Added one persistent virtual display and browser profile per agent inside the shared Computer; display routing does not add sandbox or operating-system isolation. diff --git a/docs/adrs/0013-repository-bootstrap-and-fork-updates.md b/docs/adrs/0013-repository-bootstrap-and-fork-updates.md index 4d103a1c..d35fb9ce 100644 --- a/docs/adrs/0013-repository-bootstrap-and-fork-updates.md +++ b/docs/adrs/0013-repository-bootstrap-and-fork-updates.md @@ -5,12 +5,12 @@ - Init owns GitHub repository bootstrap. Empty directory only. No partial in-place setup. - Public means GitHub fork. Private means independent mirror. Never claim private fork-network membership. - Every upstream PR ships caveman update metadata. No undocumented fork impact. -- `openbot update` merges upstream, then hands review to coding agent. Never declare fork behavior preserved automatically. +- `dispatch update` merges upstream, then hands review to coding agent. Never declare fork behavior preserved automatically. - Future code-forge provider replaces direct `gh` orchestration. Manual GitHub flow is temporary. ## Context -OpenBot is designed to be customized in a user-owned repository. The current `pnpm openbot init` assumes the repository already exists, which leaves repository ownership, visibility, upstream remotes, and future upgrades as manual steps. Private GitHub repositories cannot be members of the public upstream's fork network, so public and private bootstrap paths are necessarily different. +Dispatch is designed to be customized in a user-owned repository. The current `pnpm tilde init` assumes the repository already exists, which leaves repository ownership, visibility, upstream remotes, and future upgrades as manual steps. Private GitHub repositories cannot be members of the public upstream's fork network, so public and private bootstrap paths are necessarily different. Forks may change any package and cannot safely consume upstream releases from a package boundary alone. Upstream changes therefore need durable, machine-readable-enough human guidance, and updating a fork must explicitly hand semantic verification to the user's coding agent. @@ -18,16 +18,16 @@ Forks may change any package and cannot safely consume upstream releases from a ### Bootstrap an owned repository before configuration -`openbot init` becomes a standalone bootstrap command that runs from the intended, completely empty destination directory. Any entry, including hidden files, makes init fail before prompts or network mutation. The command must be distributable independently of a cloned OpenBot workspace; the existing repository-local `pnpm openbot init` invocation is transitional and cannot implement this decision by itself. +`tilde init` becomes a standalone bootstrap command that runs from the intended, completely empty destination directory. Any entry, including hidden files, makes init fail before prompts or network mutation. The command must be distributable independently of a cloned Dispatch workspace; the existing repository-local `pnpm tilde init` invocation is transitional and cannot implement this decision by itself. -Init checks that `git` and authenticated GitHub CLI access are available. It resolves canonical OpenBot's HEAD, verifies that revision has the workspace contract required by the installed CLI, and later verifies that the owned clone is at the same revision. Missing `gh`, failed `gh auth status`, unavailable SSH access, an incompatible canonical revision, an existing destination repository, or any Git operation failure aborts repository bootstrap and prevents repository creation or configuration initialization. +Init checks that `git` and authenticated GitHub CLI access are available. It resolves canonical Dispatch's HEAD, verifies that revision has the workspace contract required by the installed CLI, and later verifies that the owned clone is at the same revision. Missing `gh`, failed `gh auth status`, unavailable SSH access, an incompatible canonical revision, an existing destination repository, or any Git operation failure aborts repository bootstrap and prevents repository creation or configuration initialization. The user chooses a repository owner/name and visibility. A bare name defaults to the account reported by the authenticated GitHub CLI; an explicit `owner/name` may target a GitHub organization where that account has repository-creation permission. Visibility defaults to private. -- Public: use `gh repo fork` with the requested name, clone it into the current empty directory, and retain the canonical OpenBot repository as `upstream`. -- Private: create a new private GitHub repository, make a temporary bare clone of canonical OpenBot, mirror its refs to the new repository, remove the temporary bare repository, clone the private repository into the current directory, and add canonical OpenBot as `upstream`. This is an independent repository copy, not a GitHub fork. +- Public: use `gh repo fork` with the requested name, clone it into the current empty directory, and retain the canonical Dispatch repository as `upstream`. +- Private: create a new private GitHub repository, make a temporary bare clone of canonical Dispatch, mirror its refs to the new repository, remove the temporary bare repository, clone the private repository into the current directory, and add canonical Dispatch as `upstream`. This is an independent repository copy, not a GitHub fork. -Temporary mirror state lives in a securely created temporary directory and is always cleaned up. The implementation must not use a predictable repository-local seed directory. `origin` always names the user repository; `upstream` always names canonical OpenBot. Only after clone and remote verification succeed does init continue with SOPS, provider configuration, instrumentation, and initial-agent scaffolding inside the new repository. +Temporary mirror state lives in a securely created temporary directory and is always cleaned up. The implementation must not use a predictable repository-local seed directory. `origin` always names the user repository; `upstream` always names canonical Dispatch. Only after clone and remote verification succeed does init continue with SOPS, provider configuration, instrumentation, and initial-agent scaffolding inside the new repository. The first implementation may invoke `gh` and `git` through typed command-runner boundaries. Follow-up work will introduce a code-forge or `GitProvider` domain and replace these direct GitHub operations with provider calls without changing the bootstrap contract. @@ -41,7 +41,7 @@ flowchart TD V -->|"private"| M["Private mirrored repository"] F --> C["Clone into current directory"] M --> C - C --> U["origin=user repository; upstream=OpenBot"] + C --> U["origin=user repository; upstream=Dispatch"] U --> I["Configuration and SOPS init"] ``` @@ -62,7 +62,7 @@ PR preparation and CI treat a missing, stale, wrongly numbered, or malformed upd ### Update a customized fork and require semantic review -`openbot update` requires a clean worktree, an `upstream` remote pointing to canonical OpenBot, and the user's current branch. It fetches `upstream/main`, identifies the upstream range since the current merge base, and runs a normal merge. Git fast-forwards when possible and creates a merge commit when the fork has diverged. The command does not rebase, force-reset, discard fork commits, auto-resolve conflicts, push, or deploy. +`dispatch update` requires a clean worktree, an `upstream` remote pointing to canonical Dispatch, and the user's current branch. It fetches `upstream/main`, identifies the upstream range since the current merge base, and runs a normal merge. Git fast-forwards when possible and creates a merge commit when the fork has diverged. The command does not rebase, force-reset, discard fork commits, auto-resolve conflicts, push, or deploy. Before attempting the merge, the command always creates `configuration/docs/update-notes/.md`. Init seeds `configuration/docs/update-notes/README.md` explaining that these are fork-owned verification notes rather than upstream release notes. @@ -77,7 +77,7 @@ A follow-up will automatically launch the user's configured default coding agent ```mermaid flowchart LR P["Draft upstream PR"] --> D["docs/updates/PR-number.md"] - D --> F["Fork openbot update"] + D --> F["Fork dispatch update"] F --> N["configuration/docs/update-notes/upstream-hash.md"] F --> M{"Merge result"} M -->|"success"| A["Coding-agent semantic review"] @@ -89,7 +89,7 @@ flowchart LR - Fresh users receive a repository they own before any credentials or fork configuration exist. - Public repositories preserve GitHub fork relationships; private repositories sacrifice fork-network metadata for actual privacy. -- The independently installable `openbot` CLI owns empty-directory repository bootstrap and configuration initialization. +- The independently installable Tilde CLI owns empty-directory repository bootstrap and configuration initialization. - Update notes require the draft PR to exist first and must be refreshed as its implementation or review outcome changes. - Merge automation handles Git history only. Coding-agent review owns semantic preservation of arbitrary fork customizations. - Direct GitHub CLI orchestration is accepted temporary coupling until the code-forge provider exists. @@ -98,8 +98,8 @@ flowchart LR - 2026-08-13T16:59:19+02:00: Added follow-up boundaries for a forge-specific repository provider and automatic default coding-agent launch after every update result, with safe manual fallback and no implied review completion. - 2026-08-13T17:08:19+02:00: Replaced commit-hash update records with stable PR-number records, required draft-PR creation before generation, required continuous refresh, and expanded evidence gathering to every local coding-agent thread with strict privacy filtering. -- 2026-08-13T17:50:21+02:00: Added the public standalone `openbot` package and executable entrypoint; empty-directory repository provisioning remains separate implementation work. -- 2026-08-13T18:15:10+02:00: Added an early cloned-repository guard so transitional init cannot write partial configuration outside an OpenBot checkout while empty-directory bootstrap remains unimplemented. +- 2026-08-13T17:50:21+02:00: Added the public `@trytilde/cli` package and `tilde` executable entrypoint; empty-directory repository provisioning remains separate implementation work. +- 2026-08-13T18:15:10+02:00: Added an early cloned-repository guard so transitional init cannot write partial configuration outside a Dispatch checkout while empty-directory bootstrap remains unimplemented. - 2026-08-13T18:24:38+02:00: Replaced transitional in-clone init with empty-directory-only GitHub bootstrap for public forks and private mirrors, including preflight checks and verified origin/upstream remotes. - 2026-08-13T18:27:43+02:00: Added stdin JSON answers and JSON results for non-interactive init, using stable core and provider question IDs so AI agents execute the same validated bootstrap path without a TTY or secrets in arguments; agent scaffolding and secret mutations also expose explicit JSON/stdin modes. - 2026-08-13T18:29:50+02:00: Allowed repository bootstrap to target an authorized GitHub organization through explicit `owner/name` input while preserving bare-name account defaults. diff --git a/docs/adrs/0014-owner-chat-control-api.md b/docs/adrs/0014-owner-chat-control-api.md index 728194d0..a6ebb01e 100644 --- a/docs/adrs/0014-owner-chat-control-api.md +++ b/docs/adrs/0014-owner-chat-control-api.md @@ -10,19 +10,19 @@ ## Context -Tilde owns agents, ChatKit sessions, messages, and agent execution, while OpenBot owns the +Tilde owns agents, ChatKit sessions, messages, and agent execution, while Dispatch owns the owner-facing workspace. The original reset shell had no chat transport, so a running or deployed installation could provision an agent without letting its owner converse with it. ## Decision -OpenBot clients call `/api/chat/*` using Tilde's resource shapes directly. Web and packaged desktop use the same-origin route; mobile uses the installation's absolute HTTPS origin. Hono maps only the ChatKit team subtree, the configured organization/team root attachment subtree, and validated signed attachment uploads. It forwards raw request bodies and response streams, removes browser-supplied credentials and hop-by-hop headers, injects the configured Tilde credentials, disables caching, and preserves upstream status codes and content types. +Dispatch clients call `/api/chat/*` using Tilde's resource shapes directly. Web and packaged desktop use the same-origin route; mobile uses the installation's absolute HTTPS origin. Hono maps only the ChatKit team subtree, the configured organization/team root attachment subtree, and validated signed attachment uploads. It forwards raw request bodies and response streams, removes browser-supplied credentials and hop-by-hop headers, injects the configured Tilde credentials, disables caching, and preserves upstream status codes and content types. -The bridge does not accept tenant overrides and cannot proxy arbitrary Tilde control-plane APIs. Tilde remains authoritative for agents, sessions, messages, attachments, queues, events, and interruption. OpenBot keeps no duplicate conversation contract or state. Local Vite, packaged desktop, local production, and the Vercel control Function all route the same `/api/*` surface to Hono. +The bridge does not accept tenant overrides and cannot proxy arbitrary Tilde control-plane APIs. Tilde remains authoritative for agents, sessions, messages, attachments, queues, events, and interruption. Dispatch keeps no duplicate conversation contract or state. Local Vite, packaged desktop, local production, and the Vercel control Function all route the same `/api/*` surface to Hono. Agent responses still execute through the Agent Provider-managed endpoint, whether that endpoint is a development tunnel or the deployed agent service. -OpenBot also needs owner-visible activity for agents whose conversations are not currently open. The +Dispatch also needs owner-visible activity for agents whose conversations are not currently open. The client runtime obtains a short-lived, single-use ChatKit workspace ticket from the authenticated control service, then connects directly to Tilde's documented WebSocket. The exchange forwards the current owner bearer token server-to-server; browser JavaScript never receives it. Web and Electron request a @@ -40,14 +40,14 @@ separates client ping, server control frames, and typed domain events into disti retaining the single physical channel. The direct socket forwards the client's last applied durable revision as `after_revision`, so a reconnect replays events produced while the client was offline. The framework-neutral client runtime owns heartbeat, revision cursors, capped exponential reconnect -backoff with jitter, strict discriminated-union parsing, and direct event reduction. Tilde sends a ready barrier with the current revision; OpenBot +backoff with jitter, strict discriminated-union parsing, and direct event reduction. Tilde sends a ready barrier with the current revision; Dispatch refreshes authoritative sidebar and selected-session state before advancing that cursor, closing the initial REST-to-WebSocket race. Event cursors advance only after client reconciliation succeeds. Selecting a conversation updates Tilde's per-user session read state; the resulting targeted event synchronizes that owner's other clients without placing unread state on the shared session. -The replacement is an intentional hard cutover. OpenBot retains no old route, ticket, protocol, -frame, payload, or parser alias. API and OpenBot deployments move and roll back together. +The replacement is an intentional hard cutover. Dispatch retains no old route, ticket, protocol, +frame, payload, or parser alias. API and Dispatch deployments move and roll back together. ```mermaid flowchart LR @@ -66,7 +66,7 @@ flowchart LR - Conversation state remains authoritative in the Tilde Team. - Control deployments route `/api/*` to the Hono Function and keep credentials server-side. -- Tilde status codes, JSON bodies, attachment bytes, and SSE frames cross without an OpenBot projection layer. +- Tilde status codes, JSON bodies, attachment bytes, and SSE frames cross without a Dispatch projection layer. - The bridge is intentionally Tilde-specific; a second chat backend requires a new product decision rather than a generic provider contract in advance. - The control service no longer holds one upstream WebSocket per browser; its retained role is the owner-authorized ticket exchange and the existing REST/SSE compatibility bridge. diff --git a/docs/adrs/0015-agent-desktop-sessions.md b/docs/adrs/0015-agent-desktop-sessions.md index 73c13024..75d98f00 100644 --- a/docs/adrs/0015-agent-desktop-sessions.md +++ b/docs/adrs/0015-agent-desktop-sessions.md @@ -9,13 +9,13 @@ ## Context -Owners need to watch and take over the Computer used by a selected agent. A single shared display makes simultaneous agents overwrite each other's pointer, browser, and visible state. One sandbox per agent would prevent that interference but would break OpenBot's deliberate shared-Computer model and multiply image, filesystem, and lifecycle cost. +Owners need to watch and take over the Computer used by a selected agent. A single shared display makes simultaneous agents overwrite each other's pointer, browser, and visible state. One sandbox per agent would prevent that interference but would break Dispatch's deliberate shared-Computer model and multiply image, filesystem, and lifecycle cost. The renderer also cannot receive provider lifecycle, process, file, raw endpoint, or service-credential authority merely to show a desktop. ## Decision -OpenBot keeps one shared Computer. Computer-service maintains an idempotent desktop registry below `/workspace/.openbot/desktops/` and allocates one X display and browser profile per agent. All sessions still share the same sandbox, operating-system identity, filesystem, network, and computer-service process. An agent ID selects a display; it does not isolate the agent. +Dispatch keeps one shared Computer. Computer-service maintains an idempotent desktop registry below `/workspace/.dispatch/desktops/` and allocates one X display and browser profile per agent. All sessions still share the same sandbox, operating-system identity, filesystem, network, and computer-service process. An agent ID selects a display; it does not isolate the agent. One noVNC gateway serves the Computer. The Computer Provider derives an agent-scoped capability and asks computer-service to reconcile its mapping to the selected display. Repeated workspace deployment, preview, screenshot, input, and wake calls converge on the same display and profile. diff --git a/docs/adrs/0016-tilde-oidc-installation-authorization.md b/docs/adrs/0016-tilde-oidc-installation-authorization.md index d93da25b..f9dab48c 100644 --- a/docs/adrs/0016-tilde-oidc-installation-authorization.md +++ b/docs/adrs/0016-tilde-oidc-installation-authorization.md @@ -2,7 +2,7 @@ ## In brief -- Tilde Identity default authority. OpenBot installation stays OIDC client and resource server. No per-installation identity provider. +- Tilde Identity default authority. Dispatch installation stays OIDC client and resource server. No per-installation identity provider. - One installation, one resource identifier, one access-token audience. Scope says allowed action, never installation identity. - Web gets host-only HttpOnly cookies. Electron main and mobile get native PKCE credentials. UI gets no token. - Central Tilde login gives multi-installation SSO. Installation cookies and access tokens never cross installations. @@ -11,7 +11,7 @@ ## Context -OpenBot serves the same owner workspace from a local control service, a Vercel control deployment, +Dispatch serves the same owner workspace from a local control service, a Vercel control deployment, and an Electron shell. The control service currently has no owner authentication or control database, even though its chat, attachment, and Computer-preview operations can expose sensitive installation data and capabilities. @@ -26,18 +26,18 @@ and audience-restricted JWT verification. OAuth audience and scope are not interchangeable. The audience identifies where a token may be redeemed; scope describes what access is granted there. OAuth Resource Indicators explicitly warn against overloading scope with resource identity and define a standard mechanism for selecting an -audience-restricted token. Sharing one cookie or one broad token among OpenBot installations would +audience-restricted token. Sharing one cookie or one broad token among Dispatch installations would enlarge the replay and revocation boundary. Better Auth remains useful as an application session framework, but deploying an identity authority -inside every OpenBot installation would duplicate accounts and make every installation responsible +inside every Dispatch installation would duplicate accounts and make every installation responsible for issuer keys, discovery, consent, client registration, and recovery. Its OIDC Provider plugin is also documented as active development, with incomplete JWKS support and planned replacement by its OAuth Provider plugin. It is not the default trust anchor. ## Decision -Tilde Identity is OpenBot's default OAuth authorization server and OpenID Provider. An OpenBot +Tilde Identity is Dispatch's default OAuth authorization server and OpenID Provider. A Dispatch installation is registered to a Tilde Team during onboarding, and any current team member may authorize it. Registration assigns a stable installation ID, an issuer-assigned resource URI, and OAuth client metadata for the installation's supported web and native redirects. The client is @@ -58,13 +58,13 @@ The OAuth client and protected resource remain distinct concepts: operating agents, or administering the installation. Installation IDs are never encoded as scope names. - Subject membership, owner role, and other installation entitlements use subject, role, group, or - entitlement claims and server-side authorization policy. Possessing a generic OpenBot scope is + entitlement claims and server-side authorization policy. Possessing a generic Dispatch scope is not proof that the subject owns this installation. -Tilde's own login cookie provides SSO at the authorization-server origin. Opening another OpenBot +Tilde's own login cookie provides SSO at the authorization-server origin. Opening another Dispatch installation starts a new PKCE authorization flow for that installation resource; an existing Tilde session can complete it without prompting the Owner again. Each installation still receives its own -audience-restricted access token and host-only session cookies. OpenBot does not issue a default +audience-restricted access token and host-only session cookies. Dispatch does not issue a default multi-audience token and never shares an installation cookie across origins. Browser clients use Authorization Code with PKCE. The control-service callback exchanges the code @@ -79,7 +79,7 @@ Electron uses the system browser and a registered native redirect. The Electron the PKCE verifier, callback, refresh lifecycle, and operating-system-protected token storage. Its existing loopback renderer proxy attaches the access token as an Authorization bearer when calling the control service. The preload bridge exposes only bounded authentication state and sign-in or -sign-out commands. The renderer never receives tokens or an unrestricted auth client. OpenBot does +sign-out commands. The renderer never receives tokens or an unrestricted auth client. Dispatch does not rely on the external browser and Electron sharing a cookie jar. Expo mobile uses the same public-client Authorization Code with PKCE flow and a registered app-scheme @@ -90,7 +90,7 @@ or AsyncStorage. Mobile and Electron may share server-side OAuth client registra registration explicitly allowlists both native redirects. Mobile selects the installation before authentication. The Owner enters a control-service origin; -the app verifies its public OpenBot health response and reads the provider-owned public client ID, +the app verifies its public Dispatch health response and reads the provider-owned public client ID, scope, authorization endpoint, and token endpoint from `/auth/native-config`. This route has no credentials, tenant overrides, tokens, issuer signing material, or authorization decision. Hosted origins and OAuth endpoints require HTTPS. The selected origin and token record are associated, and @@ -103,7 +103,7 @@ configured issuer, installation audience, authorized client, token purpose, subj link, and route scope. It then supplies a typed owner principal to handlers and provider calls. Static application assets, health, public native-auth discovery, and the narrowly bounded login, callback, session-refresh, and logout routes are the only public control surfaces. Installation registration belongs to the Tilde -team API and is never exposed by the OpenBot control service. +team API and is never exposed by the Dispatch control service. Owner authentication does not replace other trust boundaries. Signed Tilde callbacks and tools, agent-service endpoints, Computer-service requests, deployment credentials, and future user-desktop @@ -114,21 +114,21 @@ registration-revocation operation is introduced. The initial implementation has Logout clears the local cookies or Electron credentials and revokes upstream refresh authority when supported. Already issued access tokens remain valid only for their short lifetime; expired tokens fail closed when the issuer is unavailable. Immediate per-request revocation would require -introspection or OpenBot control persistence and is intentionally not introduced by this decision. +introspection or Dispatch control persistence and is intentionally not introduced by this decision. Alternative OIDC issuers may implement the same contract. They must support discovery, Authorization Code with PKCE, installation-specific resource audiences, required JWT validation claims, and the configured web and native redirects. The audience may be fixed by a one-resource client registration or selected with RFC 8707 when a client can address multiple resources. Operators may supply client registration manually when the issuer does not support dynamic registration. Better Auth may back -such a centralized issuer or a future session adapter, but OpenBot does not deploy its OIDC Provider +such a centralized issuer or a future session adapter, but Dispatch does not deploy its OIDC Provider plugin per installation. ```mermaid flowchart LR O["Owner"] -->|"central login"| I["Tilde Identity"] - I -->|"aud: installation A"| A["OpenBot A control"] - I -->|"aud: installation B"| B["OpenBot B control"] + I -->|"aud: installation A"| A["Dispatch A control"] + I -->|"aud: installation B"| B["Dispatch B control"] W["Web"] -->|"host-only cookie"| A E["Electron main"] -->|"bearer via loopback proxy"| A M["Expo mobile"] -->|"bearer from SecureStore"| A diff --git a/docs/adrs/0017-shared-client-runtime-and-expo-mobile.md b/docs/adrs/0017-shared-client-runtime-and-expo-mobile.md index 5eaf3ea3..0e11a75b 100644 --- a/docs/adrs/0017-shared-client-runtime-and-expo-mobile.md +++ b/docs/adrs/0017-shared-client-runtime-and-expo-mobile.md @@ -10,7 +10,7 @@ - Tilde REST and SSE stay wire authority. No duplicate server protocol package. - Mobile owns onboarding, workspace selection, auth, chat-list navigation, rich chat, prompt queues, attachments, and Computer take-over. No offline or background sending. - Runtime is mandatory for major UX surfaces and state interactions. Presentation-only state stays local. -- assistant-ui native supplies transcript and composer behavior over the external OpenBot store. No second chat authority. +- assistant-ui native supplies transcript and composer behavior over the external Dispatch store. No second chat authority. - BNA UI plus repository-owned native components supply mobile presentation. Tokens in `theme/colors.ts`. ## Context @@ -23,10 +23,10 @@ APIs or reduce the native app to web-shaped UI. ## Decision -`@tryopenbot/client-runtime` owns the framework-neutral owner-client boundary. Its contracts are +`@trytilde/dispatch-client-runtime` owns the framework-neutral owner-client boundary. Its contracts are small Zod schemas and inferred types grouped by UI capability: installation, authentication, sidebar, messages, events, queue, attachments, and platform bridges. The schemas validate data where it enters the -client. They describe what OpenBot UI needs from Tilde's existing REST/SSE wire shapes; they do not +client. They describe what Dispatch UI needs from Tilde's existing REST/SSE wire shapes; they do not create a new control-service protocol or claim ownership of Tilde resources. The package also owns the fetch/SSE client, pure event reducers, auth adapter contract, and a @@ -53,7 +53,7 @@ contract; Expo owns PKCE, SecureStore, navigation, native file selection, and Re Web and mobile therefore share contracts and behavior but render separate component trees. Before authentication, Expo asks the Owner for a control-service origin. It requires HTTPS outside -loopback development, verifies the OpenBot health response, loads public native PKCE metadata from +loopback development, verifies the Dispatch health response, loads public native PKCE metadata from `/auth/native-config`, and persists only the normalized origin in SecureStore. A service change clears installation-scoped credentials before creating a new runtime. @@ -76,7 +76,7 @@ layer is reviewable, patchable, and diffable in this repository like any other c Native chat uses assistant-ui's React Native external-store runtime and primitives. assistant-ui owns transcript virtualization, message context, auto-scroll, and composer interaction only; `client-runtime` remains the sole source of messages, sessions, streaming state, attachments, and -queued turns. Tilde remains wire and resource authority. OpenBot does not adopt Assistant Cloud; +queued turns. Tilde remains wire and resource authority. Dispatch does not adopt Assistant Cloud; the `assistant-cloud` package is present only because assistant-ui's Metro bundle statically resolves that optional peer. diff --git a/docs/adrs/0018-developer-workflow-cli.md b/docs/adrs/0018-developer-workflow-cli.md index 6c68502d..50119cd7 100644 --- a/docs/adrs/0018-developer-workflow-cli.md +++ b/docs/adrs/0018-developer-workflow-cli.md @@ -2,11 +2,11 @@ ## In brief -- The `openbot` CLI owns the entire developer workflow alongside operator commands. +- The Tilde CLI owns the entire developer workflow alongside operator commands. - Repository gates: `check`, `build`, `test`, `e2e`, `desktop package`. -- Mobile group: `openbot mobile expo|emulator|avd|setup|screenshot|logs|doctor`. -- Remote hosts: `openbot connect ` and `openbot remote `. -- Every developer workflow lands as an `openbot` command — never loose `scripts/*.mjs`, package-local helpers, or command lines living only in skill prose. +- Mobile group: `tilde mobile expo|emulator|avd|setup|screenshot|logs|doctor`. +- Remote hosts: `tilde connect ` and `tilde remote `. +- Every developer workflow lands as a `tilde` command — never loose `scripts/*.mjs`, package-local helpers, or command lines living only in skill prose. - Root scripts follow t3code's verb:target taxonomy (`dev:mobile:*`, `connect`, `doctor`) as thin plumbing. - Remote host identity is fork-owned `configuration/dev-hosts.json`, never package code. - Argv-first with plain output and exit codes; Ink renders only interactive surfaces. @@ -20,10 +20,10 @@ display-less remote needs a headless emulator, loopback VNC, and ssh tunnels to That logic first accumulated as untested `apps/mobile/scripts/*.mjs` with no owner, no help, and no path to a fork developer's or sandboxed agent's hands. -A separate published `@tryopenbot/dev-cli` package was built first, on the theory that the +A separate published `@trytilde/dispatch-dev-cli` package was built first, on the theory that the operator CLI and the developer CLI serve different audiences with different dependency weight. That boundary did not survive contact: the fork developer and the sandboxed agent -already have the `openbot` CLI in hand, the CLI already fronted `check`, `build`, and `test` +already have the Tilde CLI in hand, the CLI already fronted `check`, `build`, and `test` through the same delegation the gates need, versions were locked together by the fixed changeset group anyway, and two binaries meant two help surfaces for one repository. The package was folded into `cli` and deleted in the same branch that introduced it. @@ -34,7 +34,7 @@ rather than inline shell. ## Decision -The `openbot` CLI is the single command surface for operating an installation and developing +The Tilde CLI is the single command surface for operating an installation and developing the codebase. Sandboxed agents may fork, modify, and develop the repository, so the developer workflow is product surface and ships in the published CLI. @@ -51,7 +51,7 @@ adb to a workstation; `remote` runs a task on a configured host, and `ios` requi host. `connect` and `remote` stay top-level because they address development hosts, not the mobile app. -Every developer workflow lands as an `openbot` command, not as loose `scripts/*.mjs` files, +Every developer workflow lands as a `tilde` command, not as loose `scripts/*.mjs` files, package-local scripts, or command lines living only in skill prose. Root `package.json` keeps the verb:target taxonomy as thin plumbing; trivial single-filter delegations remain plain scripts. `create-pr` enforces this with a CLI ownership gate before publication. @@ -64,7 +64,7 @@ directory. ```mermaid flowchart LR - R["root scripts: dev:mobile:*, connect, doctor"] --> C["openbot CLI"] + R["root scripts: dev:mobile:*, connect, doctor"] --> C["Tilde CLI"] M["apps/mobile scripts"] --> C C -->|"mobile expo, mobile emulator"| L["this machine: mac or linux"] C -->|"check, build, test, e2e, desktop package"| G["repository gates"] @@ -88,7 +88,7 @@ flowchart LR ## Updates - 2026-08-29T07:28:00+02:00: ADR-0033 removed the mobile command group, Android/iOS toolchain resolution, Metro/adb tunnels, and EAS release surface. `connect` and `remote` now serve Electron desktop development only. -- 2026-08-18T13:30:00+02:00: Initial decision as a separate published `@tryopenbot/dev-cli`. +- 2026-08-18T13:30:00+02:00: Initial decision as a separate published `@trytilde/dispatch-dev-cli`. - 2026-08-18T14:20:00+02:00: Grouped every mobile command under `mobile ` and added `avd`, `setup`, `screenshot`, and `logs`. - 2026-08-18T15:00:00+02:00: Repository gates became commands; every developer workflow must land as a command; `create-pr` gained the CLI ownership gate. -- 2026-08-18T15:40:00+02:00: Folded `dev-cli` into the `openbot` CLI and deleted the package. One command surface for operators, developers, and agents; the audience split had produced two binaries with one fixed version and duplicate gate delegation. +- 2026-08-18T15:40:00+02:00: Folded `dev-cli` into the Tilde CLI and deleted the package. One command surface for operators, developers, and agents; the audience split had produced two binaries with one fixed version and duplicate gate delegation. diff --git a/docs/adrs/0019-sandbox-live-runtime-and-background-sdlc.md b/docs/adrs/0019-sandbox-live-runtime-and-background-sdlc.md index e03cfee9..4eae59e5 100644 --- a/docs/adrs/0019-sandbox-live-runtime-and-background-sdlc.md +++ b/docs/adrs/0019-sandbox-live-runtime-and-background-sdlc.md @@ -4,8 +4,8 @@ - Background orchestrator owns the lifecycle. Agents never build, test, or deploy themselves. - First edit flips every agent to the tunnel. Whole-repo, never per-agent. -- Settle 30 s, then verify, publish to `openbot/sandbox-edits`, redeploy, flip back. -- Local `openbot dev` creates agents in its live checkout. Deployed creation stays in sandbox. +- Settle 30 s, then verify, publish to `dispatch/sandbox-edits`, redeploy, flip back. +- Local `tilde dev` creates agents in its live checkout. Deployed creation stays in sandbox. - Workspace UI has no build/test/deploy modes. One continuous chat. - Cost: every agent's tools run inside the trusted development sandbox. Accepted. @@ -13,22 +13,22 @@ Agents were previously moved between the local-runtime tunnel and their deployed endpoints by an explicit owner action — a Deploy step in the workspace UI, or a factory-agent skill that committed, -pushed, and ran `openbot deploy`. That made the software lifecycle a decision an agent had to be +pushed, and ran `tilde deploy`. That made the software lifecycle a decision an agent had to be aware of and get right, and it split the owner experience into build, test, and deploy modes. The target experience, established by the reference build the workspace UX was derived from, is that creating and tweaking an agent is one continuous chat and instruction changes take effect -immediately. OpenBot agents are authored TypeScript, so a lifecycle still exists — but agents +immediately. Dispatch agents are authored TypeScript, so a lifecycle still exists — but agents should not be the ones driving it. ## Decision -- A background orchestrator (`openbot orchestrate`) owns the lifecycle. It serves agents from the +- A background orchestrator (`dispatch orchestrate`) owns the lifecycle. It serves agents from the trusted development sandbox through the Tilde local-runtime tunnel with hot reload and watches the checkout for edits. - The first edit flips **every** agent to the tunnel (whole-repo, never per-agent: changes to shared files can affect any agent). After edits settle (30 seconds without file changes), the - orchestrator verifies the project, commits and pushes the tree to the `openbot/sandbox-edits` + orchestrator verifies the project, commits and pushes the tree to the `dispatch/sandbox-edits` branch through the Tilde git reverse proxy, redeploys agent services, and flips agents back to their deployed endpoints. A failed stage leaves agents on the tunnel and retries after the next settle. @@ -38,7 +38,7 @@ should not be the ones driving it. receives a `self-edit` skill and computer tools that run in the development sandbox, so any agent can edit its own instructions, skills, and tools — the orchestrator makes the edits live. - The workspace UI has no build/test/deploy modes. `POST /api/agents` uses the repository CLI in - the checkout that owns the live agent runtime: local `openbot dev` runs `openbot new-agent` + the checkout that owns the live agent runtime: local `tilde dev` runs `tilde new-agent` directly in its local checkout, while a deployed control service delegates the same command to the trusted development sandbox. Both paths open a chat with the created agent; production never gains direct access to an operator's local checkout. @@ -56,7 +56,7 @@ stateDiagram-v2 ``` The orchestrator runs supervised inside the development sandbox: the sandbox setup script installs -a restart-looped supervisor that starts `openbot orchestrate` with the sandbox age identity, and +a restart-looped supervisor that starts `dispatch orchestrate` with the sandbox age identity, and the computer image carries the pinned `cloudflared` binary the local-runtime tunnel requires. ## Consequences @@ -67,14 +67,14 @@ the computer image carries the pinned `cloudflared` binary the local-runtime tun - Every agent's tools run in the trusted sandbox, so every agent operates inside the trust boundary that previously applied only to the factory agent. A fork running untrusted third-party agents must weigh this before adopting. -- `openbot/sandbox-edits` accumulates automated commits; merging them into the default branch is +- `dispatch/sandbox-edits` accumulates automated commits; merging them into the default branch is an explicit owner (or agent, on request) action via pull request. - Local development agent creation mutates only the explicitly running checkout and inherits its operator environment. Deployed creation retains the sandbox API key and trust boundary. Automate the rest of the SDLC around the sandbox-edits branch: the orchestrator (or an agent -acting on owner intent) should open pull requests from `openbot/sandbox-edits`, keep them updated, +acting on owner intent) should open pull requests from `dispatch/sandbox-edits`, keep them updated, and merge them once checks pass, so the default branch converges with the live tree without manual git work. @@ -87,13 +87,13 @@ git work. replaced the nonstandard `Status` section with the accepted-date note carried here, and added the orchestrator state diagram. Named the UX source as the reference build rather than the third-party product, per repository convention. Accepted 2026-08-18. -- 2026-08-26T15:31:31+01:00: Split agent creation by runtime ownership: local `openbot dev` +- 2026-08-26T15:31:31+01:00: Split agent creation by runtime ownership: local `tilde dev` scaffolds in its live checkout, while deployed control services continue through the trusted development sandbox. - 2026-08-27T15:15:00+02:00: Added the optional exe.dev mode from ADR-0032, where the trusted development lifecycle is itself the continuously running deployment and therefore never flips back to a separately built runtime. -- 2026-08-29T14:12:00+02:00: Made `openbot new-agent` the sole source and remote-resource +- 2026-08-29T14:12:00+02:00: Made `tilde new-agent` the sole source and remote-resource reconciliation lifecycle for owner-facing creation. The control service now reports the background command result instead of repeating Tilde bundle provisioning with a separate human bearer token; an authorized installation agent API key may establish the new agent lifecycle. diff --git a/docs/adrs/0020-brokered-hosted-git-access.md b/docs/adrs/0020-brokered-hosted-git-access.md index a2949086..966af6e5 100644 --- a/docs/adrs/0020-brokered-hosted-git-access.md +++ b/docs/adrs/0020-brokered-hosted-git-access.md @@ -4,7 +4,7 @@ - Hosted-git access is a provider domain. `git-provider` owns it. GitHub and Code Storage have distinct credential models. - Credential is a Tilde-brokered GitHub App via `server_token_exchange`. No raw PAT. No token in the repository, in `configuration/`, or inside any Computer. -- Sandboxes reach GitHub only through the `openbot-github-rest` and `openbot-github-git` reverse proxies. Repository-local git config, team API-key headers. +- Sandboxes reach GitHub only through the `dispatch-github-rest` and `dispatch-github-git` reverse proxies. Repository-local git config, team API-key headers. - The trusted development sandbox is the sole checkout holder. Ordinary Computers never get the fork or control-plane credentials. - Init derives the fork repository from `origin` and never blocks on authorization; the deployment lifecycle is the idempotent finisher. - Cost: git operations depend on Tilde availability. Accepted. @@ -19,7 +19,7 @@ present. The obvious implementation — mint a personal access token, put it in encrypted configuration, hand it to the sandbox — is the one that must not happen. A token that reaches a Computer is a token that -reaches agent-authored code running in that Computer, and OpenBot's security story depends on agent +reaches agent-authored code running in that Computer, and Dispatch's security story depends on agent code never holding control-plane credentials. The reasoning is not visible from the call sites, so a later contributor could "simplify" the proxy away and silently dissolve the boundary. @@ -30,11 +30,11 @@ in `src/core.ts`; `GitHubGitProvider` is the first and only adapter. The composi `providers.git` slot. The credential is a GitHub App, provisioned through Tilde's provider-app flow and brokered per -request via `server_token_exchange`. OpenBot never holds a raw PAT and never persists a usable +request via `server_token_exchange`. Dispatch never holds a raw PAT and never persists a usable GitHub token; only non-secret `GIT_GITHUB_*` identifiers land in `configuration/.env`. Sandboxes never authenticate to GitHub directly. The provider reconciles two Tilde reverse-proxy -profiles — `openbot-github-rest` for `api.github.com` and `openbot-github-git` for `github.com` — +profiles — `dispatch-github-rest` for `api.github.com` and `dispatch-github-git` for `github.com` — and the development sandbox gets repository-local git configuration whose `insteadOf` rewrite sends every `https://github.com/` operation through the proxy with team API-key headers. The sandbox holds no GitHub secret, so a compromised agent process cannot exfiltrate one. @@ -42,7 +42,7 @@ no GitHub secret, so a compromised agent process cannot exfiltrate one. Only the trusted development sandbox holds the fork checkout. Ordinary agent Computers do not get the repository and do not get the proxy configuration. -Authorization is interactive but never blocking. `openbot init` derives the fork repository from the +Authorization is interactive but never blocking. `tilde init` derives the fork repository from the checkout's `origin` remote, asks for the App name (globally unique per customer) and an optional owning organization, and serves GitHub's App-manifest form from an ephemeral loopback server. A non-interactive or failed run degrades to a `git.github.authorization.required` event; the @@ -51,10 +51,10 @@ credential connects. ```mermaid flowchart LR - Init["openbot init"] -->|"App manifest, loopback callback"| GitHubApp["GitHub App (per installation)"] + Init["tilde init"] -->|"App manifest, loopback callback"| GitHubApp["GitHub App (per installation)"] GitHubApp -->|"credential connects"| Tilde[("Tilde")] GP["git-provider: GitHubGitProvider"] -->|"server_token_exchange,\nreconcile proxy profiles"| Tilde - Dev["Trusted development sandbox\nfork checkout"] -->|"git, insteadOf rewrite\n+ team API-key headers"| Proxy["openbot-github-git\nopenbot-github-rest"] + Dev["Trusted development sandbox\nfork checkout"] -->|"git, insteadOf rewrite\n+ team API-key headers"| Proxy["dispatch-github-git\ndispatch-github-rest"] Proxy --> GH[("GitHub fork")] Computer["Ordinary agent Computer"] -.->|"no checkout,\nno credential"| GH ``` @@ -64,7 +64,7 @@ flowchart LR - Git operations depend on Tilde availability; a proxy outage stops publishing rather than falling back to a direct authenticated path. Accepted, because the fallback is the boundary violation. - A second forge is a new adapter behind the same contract, not a new credential story. -- Forks must rerun `openbot init` to gain the `providers.git` slot and complete App authorization; +- Forks must rerun `tilde init` to gain the `providers.git` slot and complete App authorization; a fork that hand-maintains `configuration/index.ts` adds the slot itself. - ADR-0013's temporary `gh`/`git` coupling is retired for sandbox-side operations. Contributor-side bootstrap flows that still shell `gh` on a developer machine are unaffected. @@ -74,7 +74,7 @@ flowchart LR - 2026-08-18T16:30:00Z: Recorded retroactively while backfilling PR 57's documentation. The decision shipped with that PR; only the record is new. - 2026-08-27T15:15:00+02:00: Added Code Storage as the machine-oriented hosted adapter. Its - organization key is setup-only and transient; OpenBot persists only a repository-scoped, + organization key is setup-only and transient; Dispatch persists only a repository-scoped, read/write, no-force-push JWT. Repository creation may opt into GitHub App continuous sync or a one-time public import. - 2026-09-03T02:25:00+02:00: Kept Code Storage checkout remotes credential-free. Reconciliation now diff --git a/docs/adrs/0021-openbot-owned-ui-naming-and-copy.md b/docs/adrs/0021-dispatch-owned-ui-naming-and-copy.md similarity index 72% rename from docs/adrs/0021-openbot-owned-ui-naming-and-copy.md rename to docs/adrs/0021-dispatch-owned-ui-naming-and-copy.md index 33e5a54b..27d8fb2f 100644 --- a/docs/adrs/0021-openbot-owned-ui-naming-and-copy.md +++ b/docs/adrs/0021-dispatch-owned-ui-naming-and-copy.md @@ -1,9 +1,9 @@ -# ADR-0021: OpenBot-owned UI naming and copy +# ADR-0021: Dispatch-owned UI naming and copy ## In brief -- OpenBot-authored UI owns its own names and its own words. No identifier or user-visible string carried from a reference build. -- One class prefix: `ob-`. Design tokens `--ob-*`, class families `ob-*`. No second prefix. +- Dispatch-authored UI owns its own names and its own words. No identifier or user-visible string carried from a reference build. +- One class prefix: `dispatch-`. Design tokens `--dispatch-*`, class families `dispatch-*`. No second prefix. - Exception: CSS generic keywords. `ui-sans-serif` and `ui-monospace` are font values, not classes. Never rewritten. - Vendored third-party trees stay byte-pristine. Per-file hashes in the tree's `PROVENANCE.md` must verify. Modifications recorded there, never silent. - No gate catches a violation. Typecheck, lint, and tests stay green either way. Review is the enforcement. @@ -13,26 +13,26 @@ Parts of the workspace UI were reconstructed with a third-party reference build as the visual target, and the reconstruction carried that build's internal class families (`ui-*`) and its -interface copy through verbatim into OpenBot-authored files. Nothing functional depended on either: +interface copy through verbatim into Dispatch-authored files. Nothing functional depended on either: identifiers and user-visible strings are expression, not interface. The coupling is invisible to every gate the repository runs. `pnpm check`, `pnpm build`, and -`pnpm test` cannot tell `ob-markdown__link` from `ui-markdown__link`, or one wording of an aria +`pnpm test` cannot tell `dispatch-markdown__link` from `ui-markdown__link`, or one wording of an aria label from another. A contributor reconstructing another component, reapplying a stale patch, or resolving a merge conflict toward the older side reintroduces it with every check green. Rules that no check enforces decay unless they are written where conventions are looked up. ## Decision -Every OpenBot-authored surface carries OpenBot-authored names and OpenBot-authored wording. +Every Dispatch-authored surface carries Dispatch-authored names and Dispatch-authored wording. -Class families use the `ob-` prefix, matching the `--ob-*` custom properties already defined in -`packages/ui/src/openbot-ui.css`. One prefix, one owner. The single exception is CSS generic +Class families use the `dispatch-` prefix, matching the `--dispatch-*` custom properties already defined in +`packages/ui/src/dispatch-ui.css`. One prefix, one owner. The single exception is CSS generic font keywords — `ui-sans-serif` and `ui-monospace` are values in the `--font-sans` and `--font-mono` stacks, not class names, and are never rewritten. User-visible copy — panel titles, aria labels, status lines, permission dialog text, placeholders — -is written for OpenBot rather than inherited. Account and identity defaults are generic +is written for Dispatch rather than inherited. Account and identity defaults are generic (`"Your account"`), never a person's name. Vendored third-party trees are the counterpart rule and move in the opposite direction: files under @@ -46,7 +46,7 @@ reapplying local patches, or reconstructing further components. ```mermaid flowchart LR - A["packages/ui/src/*\nOpenBot-authored"] -->|"ob-* classes,\nOpenBot copy"| P["Product surfaces"] + A["packages/ui/src/*\nDispatch-authored"] -->|"dispatch-* classes,\nDispatch copy"| P["Product surfaces"] A -->|"import only,\nfiles untouched"| V["beautiful-ui/upstream/\nthird-party, byte-pristine"] V -. "per-file SHA-256 must verify" .-> R["PROVENANCE.md"] ``` @@ -66,3 +66,5 @@ flowchart LR - 2026-08-19T09:00:00Z: Recorded retroactively while backfilling PR 49's documentation. The rule was applied in full by that PR; only the record is new. +- 2026-09-03T15:03:26+02:00: Renamed the product-owned UI identity to Dispatch, including the + stylesheet and its class and design-token prefix. diff --git a/docs/adrs/0022-vendored-web-component-sources.md b/docs/adrs/0022-vendored-web-component-sources.md index 5a7c99a1..93660911 100644 --- a/docs/adrs/0022-vendored-web-component-sources.md +++ b/docs/adrs/0022-vendored-web-component-sources.md @@ -4,7 +4,7 @@ - Vendor web components by copy: shadcn/ui, Beautiful UI, AI Elements live in `packages/ui` source. No npm UI-kit dependency. - `beautiful-ui/upstream/` stays pristine. Every drift recorded in `PROVENANCE.md` against per-file retrieval SHA-256. No unrecorded edit. -- Unpublished upstream primitives are reconstructed in `beautiful-ui/atoms/`, OpenBot-authored. No pretend provenance. +- Unpublished upstream primitives are reconstructed in `beautiful-ui/atoms/`, Dispatch-authored. No pretend provenance. - Licenses and modifications live in `THIRD_PARTY_NOTICES.md`. Kept current on every vendored change. - shadcn `accent` remaps to `hover`/`ink`; Beautiful UI owns `--color-accent`. No token collision. - Cost: manual upstream refresh, no automatic updates. Accepted for auditability and offline builds. @@ -32,8 +32,8 @@ The vendored tree is layered by ownership: - `beautiful-ui/upstream/` holds files retrieved from the publisher's live published source. It stays pristine. Each file's retrieval SHA-256 is recorded in `PROVENANCE.md`, and the only permitted drift — an analytics call removed, import paths rewritten — is recorded there too. -- `beautiful-ui/atoms/` holds OpenBot-authored reconstructions of primitives the publisher never - released as source. They are labeled as OpenBot's own work rather than given borrowed provenance. +- `beautiful-ui/atoms/` holds Dispatch-authored reconstructions of primitives the publisher never + released as source. They are labeled as Dispatch's own work rather than given borrowed provenance. - `components/ui/` and `components/ai-elements/` hold shadcn/ui and AI Elements copies, whose licenses and modifications are recorded in the root `THIRD_PARTY_NOTICES.md`. @@ -47,7 +47,7 @@ flowchart LR I["packages/ui index.ts"] --> S["components/ui\nshadcn, modifications recorded"] I --> E["components/ai-elements\nAI Elements, modifications recorded"] I --> U["beautiful-ui/upstream\npristine, hashed"] - I --> T["beautiful-ui/atoms\nOpenBot-authored"] + I --> T["beautiful-ui/atoms\nDispatch-authored"] U -. "per-file SHA-256" .-> P["PROVENANCE.md"] S -. "license + modifications" .-> N["THIRD_PARTY_NOTICES.md"] E -.-> N diff --git a/docs/adrs/0023-workspace-ui-package-owns-presentation.md b/docs/adrs/0023-workspace-ui-package-owns-presentation.md index c666ec64..c743ff22 100644 --- a/docs/adrs/0023-workspace-ui-package-owns-presentation.md +++ b/docs/adrs/0023-workspace-ui-package-owns-presentation.md @@ -2,9 +2,9 @@ ## In brief -- `@tryopenbot/ui` owns presentation: markup, class names, motion, component state. No fetching in the package. +- `@trytilde/dispatch-ui` owns presentation: markup, class names, motion, component state. No fetching in the package. - Applications own data, routing, composition. `apps/web` passes props. No app-local workspace stylesheet. -- One stylesheet: `@tryopenbot/ui/openbot-ui.css`, exported from the package. `apps/web/src/styles.css` deleted, not overridden. +- One stylesheet: `@trytilde/dispatch-ui/dispatch-ui.css`, exported from the package. `apps/web/src/styles.css` deleted, not overridden. - Storybook is package-owned and imports the real exports. No demo app, no duplicated production components. - One continuous bot conversation per agent, plus selectable named threads. No duplicate bot session row. - Narrow web viewports use full-screen workspace navigation and search, bottom-drawer settings and @@ -18,19 +18,19 @@ rendering path owned by one application. The desktop shell renders the same surf consumer cannot reuse components that live in an application's source tree. The reasoning is not visible from the code. A reader seeing `apps/web/src/main.tsx` import -`@tryopenbot/ui/openbot-ui.css` cannot tell whether an app-local override is still permitted, and +`@trytilde/dispatch-ui/dispatch-ui.css` cannot tell whether an app-local override is still permitted, and later work has already assumed the boundary exists — ADR-0021 governs class naming inside the package, ADR-0022 governs vendored component sources inside it — without any record establishing that the package owns presentation in the first place. ## Decision -`@tryopenbot/ui` owns presentation. Markup, class names, motion, and component state live in the +`@trytilde/dispatch-ui` owns presentation. Markup, class names, motion, and component state live in the package, and nothing in the package fetches. Applications own the data path, routing, and composition, and drive components through props. -The workspace stylesheet moves with that ownership. `packages/ui/src/openbot-ui.css` is the single -workspace stylesheet, exported through the package's `./openbot-ui.css` entry. The app-local +The workspace stylesheet moves with that ownership. `packages/ui/src/dispatch-ui.css` is the single +workspace stylesheet, exported through the package's `./dispatch-ui.css` entry. The app-local `apps/web/src/styles.css` is deleted rather than kept as an override layer: a fork or application that needs its own styling adds a fork-owned stylesheet imported after the package one. @@ -55,7 +55,7 @@ flowchart LR M["apps/mobile native renderer"] -->|"shared session model"| D["client-runtime data path"] A -->|"shared session model"| D D --> T["continuous bot session + named threads"] - U --> C["openbot-ui.css: single workspace stylesheet"] + U --> C["dispatch-ui.css: single workspace stylesheet"] U --> S["Storybook catalog: real exports"] U --> R["narrow viewport: full-screen nav/search + drawer dialogs"] ``` diff --git a/docs/adrs/0024-semantic-design-tokens-and-theming.md b/docs/adrs/0024-semantic-design-tokens-and-theming.md index 5a220a4b..40fb5ae8 100644 --- a/docs/adrs/0024-semantic-design-tokens-and-theming.md +++ b/docs/adrs/0024-semantic-design-tokens-and-theming.md @@ -2,8 +2,8 @@ ## In brief -- OpenBot owns token values. Vendored `globals.css` owns the utility mapping. No edit inside `beautiful-ui/upstream/`. -- Override by import order. `openbot-ui.css` after `beautiful-ui.css`. Provenance hashes stay valid. +- Dispatch owns token values. Vendored `globals.css` owns the utility mapping. No edit inside `beautiful-ui/upstream/`. +- Override by import order. `dispatch-ui.css` after `beautiful-ui.css`. Provenance hashes stay valid. - Tokens are semantic, not chromatic: `--page`, `--canvas`, `--surface`, `--inset`, `--ink`/`-2`/`-3`, `--line`/`--line-strong`, `--hover`/`--hover-2`. No `--grey-400`. - Hover and selected fills are alpha on grey, not solid greys. They hold on any surface. - Theming is class-based: `.dark` plus `color-scheme` on `documentElement`, set by `theme.ts`. Never `prefers-color-scheme` alone — a media query cannot express an explicit override. @@ -16,7 +16,7 @@ ## Context The vendored Beautiful UI stylesheet already maps every Tailwind utility onto raw custom properties, -so whoever sets those properties owns the product's entire visual identity. That should be OpenBot, +so whoever sets those properties owns the product's entire visual identity. That should be Dispatch, not the vendor — but ADR-0022 requires `beautiful-ui/upstream/` to stay byte-pristine, because its per-file SHA-256 values are the provenance evidence. Editing the vendored `globals.css` to change a color would invalidate them. @@ -31,8 +31,8 @@ quietly losing to a reset, with nothing failing. ## Decision -OpenBot owns token values; the vendored stylesheet keeps owning the utility mapping. The values are -overridden by import order — `openbot-ui.css` imported after `beautiful-ui.css` — never by editing +Dispatch owns token values; the vendored stylesheet keeps owning the utility mapping. The values are +overridden by import order — `dispatch-ui.css` imported after `beautiful-ui.css` — never by editing inside `beautiful-ui/upstream/`. That keeps ADR-0022's provenance hashes valid. Tokens are semantic rather than chromatic. `--page`, `--canvas`, `--surface`, `--inset`, the `--ink` @@ -51,7 +51,7 @@ Element resets live in `@layer base`. ```mermaid flowchart LR V["beautiful-ui/upstream/globals.css\n@theme inline mapping"] --> U["Tailwind utilities"] - C["openbot-ui.css\ntoken values, :root and .dark"] -->|"later import wins"| U + C["dispatch-ui.css\ntoken values, :root and .dark"] -->|"later import wins"| U T["theme.ts"] -->|".dark + color-scheme"| R["documentElement"] R --> C ``` diff --git a/docs/adrs/0026-vite-plus-toolchain.md b/docs/adrs/0026-vite-plus-toolchain.md index 184715d9..eeacc664 100644 --- a/docs/adrs/0026-vite-plus-toolchain.md +++ b/docs/adrs/0026-vite-plus-toolchain.md @@ -11,13 +11,13 @@ ## Context -OpenBot previously split development tasks across pnpm scripts, Turbo, Vite, Vitest, TypeScript, and package-specific lint aliases. That made `lint` mean type-checking in most packages, provided no repository formatter, and required multiple orchestration paths in local development, CI, deployment, and packaging. +Dispatch previously split development tasks across pnpm scripts, Turbo, Vite, Vitest, TypeScript, and package-specific lint aliases. That made `lint` mean type-checking in most packages, provided no repository formatter, and required multiple orchestration paths in local development, CI, deployment, and packaging. The repository needs one documented command surface that can run consistently across its workspace while retaining package-specific artifact tools such as tsdown/Rolldown, native Go TypeScript (`tsgo`), and protobuf generation. ## Decision -Vite+ is OpenBot's repository-wide toolchain entry point. `vp check` owns Oxfmt formatting, Oxlint linting, and type-aware TypeScript checks. `vp test`, `vp build`, and `vp run` own test, Vite application build, and workspace task execution. Vite+ delegates dependency management to the pinned pnpm version. +Vite+ is Dispatch's repository-wide toolchain entry point. `vp check` owns Oxfmt formatting, Oxlint linting, and type-aware TypeScript checks. `vp test`, `vp build`, and `vp run` own test, Vite application build, and workspace task execution. Vite+ delegates dependency management to the pinned pnpm version. Package scripts have stable meanings: `lint` runs `vp lint`, `typecheck` runs `tsc --noEmit`, and `check` runs `vp check`. The native `tsgo` compiler remains an explicitly named artifact check where ADR-0008 requires it; it is not a lint alias. @@ -44,7 +44,7 @@ flowchart LR - Runtime boundaries are compiler-visible: accidental browser API use in Node packages and accidental Node-global use in browser packages fail type-checking. - External source maps improve production stack traces without copying authored source into map files. - New lint and formatter policy belongs in the root Vite+ configuration. -- Vite+ upgrades must preserve the pinned Vite/Vitest workspace overrides and pass the complete OpenBot validation pipeline. +- Vite+ upgrades must preserve the pinned Vite/Vitest workspace overrides and pass the complete Dispatch validation pipeline. ## Updates diff --git a/docs/adrs/0027-in-chat-connector-configuration.md b/docs/adrs/0027-in-chat-connector-configuration.md index e68db1be..b469b0cc 100644 --- a/docs/adrs/0027-in-chat-connector-configuration.md +++ b/docs/adrs/0027-in-chat-connector-configuration.md @@ -11,7 +11,7 @@ ## Context -OpenBot bots already carry the team-scoped Tilde control plane on their MCP servers, so an agent can in principle discover, enable, and map provider tools for itself. What was missing was the owner-facing half: no in-chat way to choose which provider account a bot should use, no secure path for entering new credentials, and no instructions teaching agents the discovery-enable-map workflow instead of improvising through the browser or shell. +Dispatch bots already carry the team-scoped Tilde control plane on their MCP servers, so an agent can in principle discover, enable, and map provider tools for itself. What was missing was the owner-facing half: no in-chat way to choose which provider account a bot should use, no secure path for entering new credentials, and no instructions teaching agents the discovery-enable-map workflow instead of improvising through the browser or shell. ## Decision @@ -32,17 +32,17 @@ sequenceDiagram - `splitMessageSegments` routes completed `configure_connector` parts to their own transcript row so ADR-0025 tool-chip collapsing does not swallow the card. - The selection is a native Tilde mutation carrying `tool_group_source_type_id` and `tool_group_instance_id`. Tilde enables and maps the selected account atomically, so connector setup does not consume a second model turn. - The control service, which already holds the team API key for the chat proxy, remains only the authenticated credential boundary. It strips browser credentials, injects the installation credential, and forwards an exact method/path allowlist without translating connector resources. -- Plugin inventory pages Tilde's native MCP servers, tool groups, proxied servers, skills, trusted providers, and skill registries. Their `agent_id` and binding fields are authoritative; the browser never submits a list of agent IDs and no OpenBot-specific aggregate catalogue is required. +- Plugin inventory pages Tilde's native MCP servers, tool groups, proxied servers, skills, trusted providers, and skill registries. Their `agent_id` and binding fields are authoritative; the browser never submits a list of agent IDs and no Dispatch-specific aggregate catalogue is required. ## Consequences -- New package `@tryopenbot/connector-tools` (Tilde-facing runtime utility for authored agents, sibling of `computer-tools`). +- New package `@trytilde/dispatch-connector-tools` (Tilde-facing runtime utility for authored agents, sibling of `computer-tools`). - Existing forks must migrate `configuration/agent` manually: add `tools/configure_connector.ts`, register it in `agent.ts`, refresh `instructions.ts`, and copy the eight Tilde skills. - Mobile renders the same payload natively, including API-key and custom-schema credential forms; brokered OAuth opens the system browser and the user taps Done to hand back to the agent. - Provider branding comes from Tilde catalog metadata (`icon_url`, plumbed as `icon_url`/`iconUrl` through the payload, routes, and both clients) with an initials tile as the fallback while the live catalog omits it. - Follow-up: accounts are create-only from chat — the setup form blanks secret fields and cannot re-submit an existing account with unchanged secrets; editing credentials stays in the Tilde dashboard for now. -- Brokered OAuth returns land on the public control-service page `/connectors/authorized`; the waiting dialog polls the account status and hands back to the agent automatically, and desktop flows are bounced from the system browser to the `openbot://connectors/authorized` deep link, which focuses the app window. -- Mobile mirrors the same return flow: the native sheet passes `connectorAuthorizedReturnUrl(controlOrigin, "mobile")`, the landing page bounces `client=mobile` to the `openbot://` scheme the Expo app already registers, and the sheet polls `waitForConnectorAccountActive` to auto-send the hand-back (Done stays as a manual fallback). +- Brokered OAuth returns land on the public control-service page `/connectors/authorized`; the waiting dialog polls the account status and hands back to the agent automatically, and desktop flows are bounced from the system browser to the `dispatch://connectors/authorized` deep link, which focuses the app window. +- Mobile mirrors the same return flow: the native sheet passes `connectorAuthorizedReturnUrl(controlOrigin, "mobile")`, the landing page bounces `client=mobile` to the `dispatch://` scheme the Expo app already registers, and the sheet polls `waitForConnectorAccountActive` to auto-send the hand-back (Done stays as a manual fallback). ## Updates diff --git a/docs/adrs/0027-official-app-store-publication.md b/docs/adrs/0027-official-app-store-publication.md index 232588cd..d8c5bd48 100644 --- a/docs/adrs/0027-official-app-store-publication.md +++ b/docs/adrs/0027-official-app-store-publication.md @@ -5,19 +5,19 @@ ## In brief - One published mobile app. `trytilde/dispatch` owns the EAS project, bundle identifier, and both store listings. -- Tilde publishes, OpenBot is the app. EAS project `ace1107b-b007-451a-8e50-2b571c40593e`, owner `trytilde`, identifier `ai.trytilde.openbot`. +- Tilde publishes, Dispatch is the app. EAS project `ace1107b-b007-451a-8e50-2b571c40593e`, owner `trytilde`, identifier `ai.trytilde.dispatch`. - Forks cannot publish to it. The guard is code in the CLI, not a comment in a config file. -- A fork releases its own app by setting `OPENBOT_EAS_PROJECT_ID`, `OPENBOT_APP_ID`, and `OPENBOT_EXPO_OWNER`. +- A fork releases its own app by setting `DISPATCH_EAS_PROJECT_ID`, `DISPATCH_APP_ID`, and `DISPATCH_EXPO_OWNER`. - `app.json` becomes `app.config.ts` so store identity can be overridden without editing a tracked file. -- `openbot mobile release build|submit|status|credentials`. Nothing spends money or publishes without `--yes`. +- `tilde mobile release build|submit|status|credentials`. Nothing spends money or publishes without `--yes`. - `eas-cli` runs through `npx eas-cli@latest`, deliberately unpinned. - A `mobile-v*` tag releases through GitHub Actions, which calls the same CLI command a human would. - Store credentials stay in EAS and Apple/Google, never in this repository. ## Context -OpenBot is forkable by design: ADR-0001 makes `configuration/` fork-owned, and every fork is a -real installation. App store publication does not follow that shape. There is one "OpenBot" in +Dispatch is forkable by design: ADR-0001 makes `configuration/` fork-owned, and every fork is a +real installation. App store publication does not follow that shape. There is one "Dispatch" in the App Store and Play Store, one bundle identifier, one set of review relationships, and one EAS project holding the signing credentials. That identity belongs upstream. @@ -28,30 +28,30 @@ authorization to protect a public listing is not a boundary — it is a hope. ## Decision -Tilde is the publisher and OpenBot is the app, so the identifier is reverse-DNS of the -publisher's domain — `ai.trytilde.openbot` — rather than of the product name. The display name -stays `OpenBot`, and the Expo owner is the `trytilde` account that holds the store +Tilde is the publisher and Dispatch is the app, so the identifier is reverse-DNS of the +publisher's domain — `ai.trytilde.dispatch` — rather than of the product name. The display name +stays `Dispatch`, and the Expo owner is the `trytilde` account that holds the store relationships. An identifier cannot be changed after a first store submission, so it is fixed before the first release rather than after. -`openbot init` neither asks about EAS nor requires it. Almost no fork publishes its own mobile +`tilde init` neither asks about EAS nor requires it. Almost no fork publishes its own mobile app, so making store publication part of initialization would charge every fork owner a question, an account, and a failure mode for something they will never use. Publication is a -separate, upstream-only workflow reached through `openbot mobile release`; a fork that does want +separate, upstream-only workflow reached through `tilde mobile release`; a fork that does want its own app opts in by setting the environment overrides, and only then. `trytilde/dispatch` owns store publication. The official EAS project is `ace1107b-b007-451a-8e50-2b571c40593e` under owner `trytilde`, with identifier -`ai.trytilde.openbot`, and `apps/mobile/eas.json` carries the development, preview, and +`ai.trytilde.dispatch`, and `apps/mobile/eas.json` carries the development, preview, and production profiles. Production uses `appVersionSource: remote` with `autoIncrement`, so build numbers live in EAS rather than in a tracked file where every fork merge would conflict. `app.json` becomes `app.config.ts`. Store identity reads from the environment with the official -values as defaults, so a fork overrides `OPENBOT_EAS_PROJECT_ID`, `OPENBOT_APP_ID`, -`OPENBOT_EXPO_OWNER`, and optionally the name, slug, and scheme from its own +values as defaults, so a fork overrides `DISPATCH_EAS_PROJECT_ID`, `DISPATCH_APP_ID`, +`DISPATCH_EXPO_OWNER`, and optionally the name, slug, and scheme from its own `configuration/.env` without editing a file that upstream also owns. -Publication runs through `openbot mobile release`, per ADR-0018. Its guard refuses when the +Publication runs through `tilde mobile release`, per ADR-0018. Its guard refuses when the resolved EAS project is the official one and `origin` is not `trytilde/dispatch`, naming the override a fork needs. This is deliberately narrow: a fork with its own EAS project is not blocked, because the thing being protected is the official identity, not the act of releasing. @@ -59,11 +59,11 @@ blocked, because the thing being protected is the official identity, not the act `submit` changes a public listing. Releases are automated by tag rather than by branch. `.github/workflows/mobile-release.yml` -runs on a `mobile-v*` tag or a manual dispatch, and it invokes `openbot mobile release build` +runs on a `mobile-v*` tag or a manual dispatch, and it invokes `tilde mobile release build` rather than `eas-cli` directly, so CI and a human release through one code path with one guard. The job is additionally fenced to `github.repository == 'trytilde/dispatch'`; a fork's Actions run would already fail the CLI guard and has no `EXPO_TOKEN`, but a public listing deserves a fence -that is readable in the workflow file. `openbot check` runs first, because an iOS build costs +that is readable in the workflow file. `tilde check` runs first, because an iOS build costs plan minutes and a queue wait that a typecheck failure should not consume. CI holds exactly one credential, `EXPO_TOKEN`, and holds it as a repository secret read from the @@ -82,7 +82,7 @@ Apple and Google consoles. None of them enter this repository, `configuration/`, ```mermaid flowchart LR - U["trytilde/dispatch"] -->|"openbot mobile release"| G["upstream guard"] + U["trytilde/dispatch"] -->|"tilde mobile release"| G["upstream guard"] F["a fork"] -->|"official project id"| G G -->|"refuse, name the override"| F G -->|"allow"| E["EAS project ace1107b"] @@ -108,5 +108,5 @@ flowchart LR - 2026-08-29T07:28:00+02:00: Superseded operationally by ADR-0033. Main no longer contains the mobile app or EAS publication workflow; the complete prior implementation is preserved only on the DO NOT MERGE mobile archive branch. - 2026-08-19T10:20:00+02:00: Initial decision. -- 2026-08-19T10:55:00+02:00: Named Tilde as publisher and OpenBot as the app, moving the identifier from `dev.openbot.mobile` to `ai.trytilde.openbot` before any store submission, and recorded that `openbot init` must never ask about EAS or require it. -- 2026-08-19T13:40:00+02:00: Hardened the guard against an empty `OPENBOT_EAS_PROJECT_ID`. GitHub Actions substitutes an empty string for an unset repository variable, and `??` accepted it, so the official project compared unequal to itself and the refusal never fired. Overrides now read through `optionalEnvironment`, which treats empty and whitespace as absent. +- 2026-08-19T10:55:00+02:00: Named Tilde as publisher and Dispatch as the app, moving the identifier from `dev.dispatch.mobile` to `ai.trytilde.dispatch` before any store submission, and recorded that `tilde init` must never ask about EAS or require it. +- 2026-08-19T13:40:00+02:00: Hardened the guard against an empty `DISPATCH_EAS_PROJECT_ID`. GitHub Actions substitutes an empty string for an unset repository variable, and `??` accepted it, so the official project compared unequal to itself and the refusal never fired. Overrides now read through `optionalEnvironment`, which treats empty and whitespace as absent. diff --git a/docs/adrs/0028-desktop-release-publication.md b/docs/adrs/0028-desktop-release-publication.md index a4f240ea..a0cc3110 100644 --- a/docs/adrs/0028-desktop-release-publication.md +++ b/docs/adrs/0028-desktop-release-publication.md @@ -3,11 +3,11 @@ ## In brief - One published desktop app. `trytilde/dispatch` owns the artifacts and the update feed. -- Artifacts go to the existing shared bucket `tilde-app-updates-prod` under `desktop/openbot//`. +- Artifacts go to the existing shared bucket `tilde-app-updates-prod` under `desktop/dispatch//`. - No new bucket. Tilde's own Electrobun feed already lives at `desktop/`, and public read is granted to `desktop/*`, so the nested prefix inherits it. - Forks cannot publish there. The guard is code in the CLI, and a scoped GitHub OIDC role is the backstop. -- A fork publishes its own builds by setting `OPENBOT_DESKTOP_UPDATES_BUCKET`. -- `openbot desktop release build|publish|manifest|status`. Nothing uploads without `--yes`. +- A fork publishes its own builds by setting `DISPATCH_DESKTOP_UPDATES_BUCKET`. +- `tilde desktop release build|publish|manifest|status`. Nothing uploads without `--yes`. - `version.json` is the client contract, keyed by platform. `latest-*.yml` rides along unused for a later electron-updater. - macOS is signed with a Developer ID certificate and notarized through notarytool. Missing credentials degrade to an unsigned build, recorded as `signed: false`. - Manually triggered only. Nothing releases on a push or a tag. @@ -16,7 +16,7 @@ ADR-0027 settled mobile publication: one store identity, owned upstream, with the refusal in code because a fork inherits every tracked file. The desktop app has the same shape and none of -the machinery. `openbot desktop package` produces a local unsigned build and stops there. +the machinery. `tilde desktop package` produces a local unsigned build and stops there. Three facts about the existing infrastructure shaped this. @@ -39,7 +39,7 @@ are new work here rather than a pattern to copy. ## Decision -Artifacts go to `s3://tilde-app-updates-prod/desktop/openbot//`. Reusing the shared +Artifacts go to `s3://tilde-app-updates-prod/desktop/dispatch//`. Reusing the shared bucket costs one shared blast radius and saves a near-duplicate Terraform module; the nested prefix inherits both the public-read statement and the lifecycle rule without editing either. @@ -51,7 +51,7 @@ policy names `repo:trytilde/dispatch:*`, is the backstop: a fork cannot assume i what the CLI does. Neither workflow carries an `if: github.repository ==` guard, so a fork with its own bucket and its own role runs both unmodified. -The version is whatever `@tryopenbot/desktop` already has. Changesets owns it through the fixed +The version is whatever `@trytilde/dispatch-desktop` already has. Changesets owns it through the fixed group, so a release publishes the current version rather than inventing one, and `publish` refuses a version already present unless `--overwrite` is passed. @@ -66,10 +66,10 @@ electron-builder also emits `latest-mac.yml` and `latest-linux.yml` through a `g provider. Nothing reads them today. They are published anyway so that adopting electron-updater later is a client change rather than a re-run of every past release. -The Electron `appId` is `ai.trytilde.openbot`, matching the mobile identifier for the reason +The Electron `appId` is `ai.trytilde.dispatch`, matching the mobile identifier for the reason ADR-0027 gives: the identifier is reverse-DNS of the publisher, not of the product or the platform. Desktop and mobile therefore share one identifier, and one variable renames both: -`OPENBOT_APP_ID`, already read by `apps/mobile/app.config.ts`, now also resolves the Electron +`DISPATCH_APP_ID`, already read by `apps/mobile/app.config.ts`, now also resolves the Electron `appId`. They are distinct records to Apple regardless, because the desktop app is distributed with Developer ID rather than through a store, and nothing keys off the two being different. @@ -86,11 +86,11 @@ this decision and additionally releases from a `mobile-v*` tag; this ADR does no ```mermaid flowchart LR - U["trytilde/dispatch"] -->|"workflow_dispatch"| C["openbot desktop release"] + U["trytilde/dispatch"] -->|"workflow_dispatch"| C["tilde desktop release"] F["a fork"] -->|"official bucket"| C C -->|"refuse, name the override"| F C -->|"allow"| O["GitHub OIDC role"] - O --> S["s3://tilde-app-updates-prod/desktop/openbot"] + O --> S["s3://tilde-app-updates-prod/desktop/dispatch"] S --> V["version.json"] S --> Y["latest-*.yml (unused)"] F -->|"own bucket + own role"| S2["the fork's own bucket"] @@ -99,7 +99,7 @@ flowchart LR ## Consequences - One update feed with one owner, and a fork cannot reach it by inheriting tracked files. -- OpenBot and the Tilde desktop app share a bucket. A policy or lifecycle change to +- Dispatch and the Tilde desktop app share a bucket. A policy or lifecycle change to `tilde-app-updates-prod` affects both. - A new GitHub OIDC provider exists in the shared AWS account. It is a trust relationship with GitHub, and every future role scoped to it inherits that. @@ -119,5 +119,5 @@ flowchart LR ## Updates - 2026-08-19T13:30:00+02:00: Initial decision. -- 2026-08-19T15:10:00+02:00: Moved the Electron `appId` from `dev.openbot.desktop` to `ai.trytilde.openbot`, before the first signed release makes it permanent. -- 2026-08-19T15:35:00+02:00: Made that identifier environment-overridable through the existing `OPENBOT_APP_ID`, so a fork renames the desktop and Expo clients with one variable instead of editing a tracked file. It is applied as an `electron-builder` command-line override, not a `${env.*}` macro and not a spawn environment variable: electron-builder strips macros out of `appId`, and pnpm forwards a `--` separator through to the script rather than consuming it, so overrides must follow the script name directly. `package.json` keeps the official value as the literal default. Both paths are verified against `CFBundleIdentifier` in a packaged bundle rather than against the config. +- 2026-08-19T15:10:00+02:00: Moved the Electron `appId` from `dev.dispatch.desktop` to `ai.trytilde.dispatch`, before the first signed release makes it permanent. +- 2026-08-19T15:35:00+02:00: Made that identifier environment-overridable through the existing `DISPATCH_APP_ID`, so a fork renames the desktop and Expo clients with one variable instead of editing a tracked file. It is applied as an `electron-builder` command-line override, not a `${env.*}` macro and not a spawn environment variable: electron-builder strips macros out of `appId`, and pnpm forwards a `--` separator through to the script rather than consuming it, so overrides must follow the script name directly. `package.json` keeps the official value as the literal default. Both paths are verified against `CFBundleIdentifier` in a packaged bundle rather than against the config. diff --git a/docs/adrs/0029-cua-driver-computer-use.md b/docs/adrs/0029-cua-driver-computer-use.md index ed081516..352c2a46 100644 --- a/docs/adrs/0029-cua-driver-computer-use.md +++ b/docs/adrs/0029-cua-driver-computer-use.md @@ -10,9 +10,9 @@ ## Context -OpenBot already routes each agent to a computer-service-owned virtual display and browser profile while keeping one shared Computer. Programmatic screenshots and input previously had separate command-backed implementations in computer-service and provider adapters. That duplicated ownership, limited agents to a small fixed action surface, and could bypass the same lifecycle used by richer GUI automation. +Dispatch already routes each agent to a computer-service-owned virtual display and browser profile while keeping one shared Computer. Programmatic screenshots and input previously had separate command-backed implementations in computer-service and provider adapters. That duplicated ownership, limited agents to a small fixed action surface, and could bypass the same lifecycle used by richer GUI automation. -Cua Driver publishes a runtime tool catalog and a result envelope containing text, images, structured and raw JSON, verification state, degradation, errors, and explicit completion uncertainty. OpenBot needs that fidelity without exposing a generic model-facing dispatcher or moving display ownership into a provider. +Cua Driver publishes a runtime tool catalog and a result envelope containing text, images, structured and raw JSON, verification state, degradation, errors, and explicit completion uncertainty. Dispatch needs that fidelity without exposing a generic model-facing dispatcher or moving display ownership into a provider. ## Decision @@ -22,9 +22,9 @@ Computer-service lazily creates one supervised private Cua worker for each valid `ListCuaTools` and `CallCuaTool` are the internal typed API. Results preserve the catalog schema and the SDK envelope, including ordered content, uploaded-image bytes, structured and raw JSON, verification, degradation, error codes, and `not started`, `completed`, or `unknown` action completion. Legacy screenshot and input RPCs translate to Cua calls. Computer providers retain desktop preview/provisioning but no direct screenshot or input implementation. -`@tryopenbot/computer-tools` loads the complete catalog before an agent starts, converts each JSON Schema with the AI SDK JSON-Schema adapter, rejects name collisions, and exposes one local tool per identical Cua name. Returned images cross the existing session-scoped Tilde attachment boundary rather than becoming model-visible base64. +`@trytilde/dispatch-computer-tools` loads the complete catalog before an agent starts, converts each JSON Schema with the AI SDK JSON-Schema adapter, rejects name collisions, and exposes one local tool per identical Cua name. Returned images cross the existing session-scoped Tilde attachment boundary rather than becoming model-visible base64. -Agent Provider always reconciles an OpenBot-owned computer-use overlay. Tilde exposes the canonical `trycua/cua` `skills/gui-automation/SKILL.md` package as a managed skill, so OpenBot neither discovers nor attaches it to individual agent registries. Reconciliation removes a legacy explicit canonical Cua registry member when one is returned, while preserving the overlay and user-owned registry skills. +Agent Provider always reconciles a Dispatch-owned computer-use overlay. Tilde exposes the canonical `trycua/cua` `skills/gui-automation/SKILL.md` package as a managed skill, so Dispatch neither discovers nor attaches it to individual agent registries. Reconciliation removes a legacy explicit canonical Cua registry member when one is returned, while preserving the overlay and user-owned registry skills. ```mermaid flowchart LR @@ -41,7 +41,7 @@ flowchart LR ## Consequences -- GUI tool availability follows the installed Cua runtime exactly instead of an OpenBot-maintained action list. +- GUI tool availability follows the installed Cua runtime exactly instead of a Dispatch-maintained action list. - A worker or transport interruption can report unknown completion, so agent guidance requires observation before any retry. - Display routing still is not process, filesystem, network, or authorization isolation. - Unrestricted mode is a deliberate initial installation policy, not a permanent public default. @@ -56,7 +56,7 @@ Work: expose explicit per-installation or per-agent Cua permission policy with a Owner: client-runtime, Computer Service, and agent skill lifecycle Trigger: Cua Driver computer use and managed Cua skills are deployed and stable -Work: design an owner-guided demonstration flow using Cua recording, durable recoverable delivery, and automatic publication of learned skills to every OpenBot agent registry +Work: design an owner-guided demonstration flow using Cua recording, durable recoverable delivery, and automatic publication of learned skills to every Dispatch agent registry diff --git a/docs/adrs/0030-tilde-sdk-and-cli-ownership.md b/docs/adrs/0030-tilde-sdk-and-cli-ownership.md index 336866eb..c14d51dd 100644 --- a/docs/adrs/0030-tilde-sdk-and-cli-ownership.md +++ b/docs/adrs/0030-tilde-sdk-and-cli-ownership.md @@ -2,21 +2,21 @@ ## In brief -- Keep OpenBot product name. No umbrella rename. +- Keep Dispatch product name. No umbrella rename. - Tilde SDK packages live here. No Harness repository dependency. -- `openbot` owns auth, state, tunnel, plugin commands. No second CLI or plugin package. +- `@trytilde/cli` and its `tilde` binary own auth, state, tunnel, plugin, and Dispatch commands. - Public SDK names use `@trytilde/sdk*`. No `harness` package names. -- SDK versions stay independent. OpenBot fixed group unchanged. +- SDK versions stay independent. Dispatch fixed group unchanged. ## Context -OpenBot consumed the generated Tilde API client, core SDK, Vercel AI adapter, and Tilde CLI +Dispatch consumed the generated Tilde API client, core SDK, Vercel AI adapter, and Tilde CLI from `trytilde/harness-sdk`. A single Tilde capability therefore required coordinated SDK and -OpenBot changes, releases, or Git commit pins. Coding agents also needed two repositories to trace +Dispatch changes, releases, or Git commit pins. Coding agents also needed two repositories to trace one call path. The Harness name described an old implementation context rather than a useful public boundary. -OpenBot remains a distinct application: it owns installations, clients, Computers, provider +Dispatch remains a distinct application: it owns installations, clients, Computers, provider lifecycles, and deployment. Tilde remains the platform and SDK namespace. Source locality does not collapse those product and state boundaries. @@ -27,17 +27,17 @@ The generated client, core SDK, React adapters, and Vercel AI adapters live unde `@trytilde/sdk-react`, `@trytilde/sdk-vercel-ai-node`, `@trytilde/sdk-vercel-ai-react`, `@trytilde/sdk-codex`, `@trytilde/sdk-claude-code`, `@trytilde/sdk-cursor`, `@trytilde/sdk-opencode`, and `@trytilde/sdk-gemini-cli`. -Coding-agent MCP and skill-registry setup is an internal part of the OpenBot CLI, not another +Coding-agent MCP and skill-registry setup is an internal part of the Tilde CLI, not another public package. The old `@trytilde/harness-sdk*` and `@trytilde/harness-plugins` names receive no in-repository compatibility packages. -The standalone `@trytilde/cli`, `tilde`, and `t` binaries are removed. Their authentication, team -selection, state import/export, and local-runtime tunnel commands become `openbot auth`, -`openbot state`, and `openbot tunnel`. Coding-agent resource setup becomes `openbot plugin`. -OpenAPI refresh and package validation become the `openbot sdk` developer command. +The Tilde CLI is published as `@trytilde/cli` with the `tilde` binary. Its authentication, team +selection, state import/export, and local-runtime tunnel commands are `tilde auth`, +`tilde state`, and `tilde tunnel`. Coding-agent resource setup becomes `tilde plugin`. +OpenAPI refresh and package validation become the `tilde sdk` developer command. -SDK package versions remain independent of OpenBot's fixed Changesets group because they are -general Tilde integration contracts with consumers outside the OpenBot application. Workspace +SDK package versions remain independent of Dispatch's fixed Changesets group because they are +general Tilde integration contracts with consumers outside the Dispatch application. Workspace dependencies provide atomic source changes; packed-consumer smoke tests preserve the external npm boundary. Existing auth and tunnel state locations are compatibility read paths, while new writes use names without Harness. @@ -46,26 +46,28 @@ use names without Harness. flowchart LR A["Tilde API OpenAPI"] --> G["@trytilde/api-client"] G --> S["@trytilde/sdk and adapters"] - S --> O["OpenBot providers and authored agents"] - C["openbot CLI"] --> S + S --> O["Dispatch providers and authored agents"] + C["Tilde CLI"] --> S C --> T["auth, state, tunnel, plugin"] ``` ## Consequences -- One repository and pull request can change a Tilde SDK contract and every OpenBot consumer. +- One repository and pull request can change a Tilde SDK contract and every Dispatch consumer. - External SDK consumers keep a narrow package boundary and independent release cadence. -- Consumers of old Harness package names or the `tilde` binary need an explicit migration. +- Consumers of old Harness package names or the previous product-named binary need an explicit migration. - Tilde API OpenAPI remains an external service contract even though generation now runs here. ## Updates - 2026-08-30: Harness-neutral ChatKit recording remains in `@trytilde/sdk`, while Codex, Claude Code, and Cursor hook-wire adapters use dedicated - `@trytilde/sdk-*` packages. `openbot plugin` remains the one setup command: it + `@trytilde/sdk-*` packages. `tilde plugin` remains the one setup command: it installs Tilde MCP and skill resources, native harness hooks, non-secret ChatKit routing configuration, and a packaged Codex plugin where Codex requires plugin-owned hooks. - 2026-08-31: OpenCode and Gemini CLI receive matching dedicated adapters and native fail-open audit installation, completing ChatKit audit support across - every coding harness configured by `openbot plugin`. + every coding harness configured by `tilde plugin`. +- 2026-09-03T15:03:26+02:00: Published the unified command surface as `@trytilde/cli` with the + `tilde` binary while retaining Dispatch as the application name. diff --git a/docs/adrs/0031-routines-and-signals.md b/docs/adrs/0031-routines-and-signals.md index e38e8ab8..2d885379 100644 --- a/docs/adrs/0031-routines-and-signals.md +++ b/docs/adrs/0031-routines-and-signals.md @@ -20,14 +20,14 @@ and Signals remain execution substrates rather than derived authorization resour ### Authoritative Tilde root and legacy migration -OpenBot creates or replaces one Routine through the compatibility `/automations` path. Tilde -validates the complete trigger set and atomically persists the root and children. OpenBot sends the +Dispatch creates or replaces one Routine through the compatibility `/automations` path. Tilde +validates the complete trigger set and atomically persists the root and children. Dispatch sends the current `version` as `expected_version`, and preserves server-owned action/session/metadata fields when editing the presentation subset. List/get return native trigger membership; run uses a durable client run ID. Tilde's data migration copies prior Automation roots/members and standalone SignalRules before the -native API starts. OpenBot has no metadata scan or mapping database. +native API starts. Dispatch has no metadata scan or mapping database. ```mermaid flowchart LR @@ -71,7 +71,7 @@ rebuilds the root from derived ChatKit/SignalRule collections. ### Provider connections Signal provider instances are managed inline from the trigger card and inventoried -at `/settings/signals`. OpenBot is self-hosted, so provisioning is user-visible: the +at `/settings/signals`. Dispatch is self-hosted, so provisioning is user-visible: the client runtime pre-assigns `spi_` ids to render the deterministic webhook URL, and the signing secret is supplied by the owner, write-only, placed in `configuration.provider_webhook_signing_key`. Providers are catalog-driven, not @@ -103,10 +103,10 @@ Work: render the routines list, editor, and provider connect flow natively again `webhook_verification` descriptor in the signals provider catalog. - `@trytilde/api-client`: generated routines, signals, metadata, and webhook verification contracts. Stable hand-authored behavior remains owned by - `@trytilde/sdk`; OpenBot does not reintroduce the retired Harness package names. + `@trytilde/sdk`; Dispatch does not reintroduce the retired Harness package names. ## Updates -- 2026-08-26T16:18:13+01:00: Replaced OpenBot's stateless metadata composition and mutation fan-out with Tilde's persisted Automation aggregate, retaining a thin owner-authenticated compatibility facade and automatic legacy adoption. +- 2026-08-26T16:18:13+01:00: Replaced Dispatch's stateless metadata composition and mutation fan-out with Tilde's persisted Automation aggregate, retaining a thin owner-authenticated compatibility facade and automatic legacy adoption. - 2026-08-29T00:34:00+02:00: Removed the Routines and Signals domain facades. Client Runtime now validates and projects the native Tilde resources through one operation-allowlisted credential bridge, retaining the HttpOnly installation session without duplicating Tilde APIs. - 2026-08-29T03:18:00+02:00: Replaced materialized ChatKit Routine and SignalRule members with Tilde's native Routine triggers. Client Runtime now preserves optimistic versions and native trigger metadata, pages Signals completely, and uses trigger IDs for delivery history. diff --git a/docs/adrs/0032-agent-bound-conversation-work.md b/docs/adrs/0032-agent-bound-conversation-work.md index ff58c89c..a4a1fd52 100644 --- a/docs/adrs/0032-agent-bound-conversation-work.md +++ b/docs/adrs/0032-agent-bound-conversation-work.md @@ -4,7 +4,7 @@ - Use both goals and tasks: one records the desired outcome, the other records executable work. - Bind the SDK and agent tools to the current agent and ChatKit session outside model input. -- Keep Tilde as the durable authority; OpenBot retains no parallel work database. +- Keep Tilde as the durable authority; Dispatch retains no parallel work database. - Give authored agents durable bookkeeping guidance without exposing it as user narration. ## Decision diff --git a/docs/adrs/0032-exe-dev-single-vm-runtime.md b/docs/adrs/0032-exe-dev-single-vm-runtime.md index 4e350bee..746441ad 100644 --- a/docs/adrs/0032-exe-dev-single-vm-runtime.md +++ b/docs/adrs/0032-exe-dev-single-vm-runtime.md @@ -3,7 +3,7 @@ ## In brief - One persistent exe.dev VM. Runtime plus Computer. 24/7. -- Run `openbot dev`, supervised by systemd user linger. +- Run `tilde dev`, supervised by systemd user linger. - Host is Computer. No process namespace. Whole 2-vCPU/8-GB VM may be used. - Configuration secrets are available. This VM is trusted. - Public Vite origin proxies capability-scoped noVNC and WebSocket traffic. @@ -34,7 +34,7 @@ remote checkout rather than overwriting live edits. `ExeDevComputerProvider` shares the same `ExeDevPlatform` identity. The outer production lifecycle is runtime-owned; inside the VM, `HostComputerProvider` installs computer-service, Chromium, Xvnc/noVNC, Cua, and desktop assets directly on Linux and supervises them with a systemd user -service. `/workspace/openbot` points at the same live checkout used by `pnpm dev`. The provider +service. `/workspace/dispatch` points at the same live checkout used by `pnpm dev`. The provider shares one `COMPUTER_ID` with the trusted development sandbox. There is no inner process, filesystem, user, network, CPU, or memory boundary. diff --git a/docs/adrs/0033-agent-owned-context-compaction.md b/docs/adrs/0033-agent-owned-context-compaction.md index 6e460eef..bf7e6877 100644 --- a/docs/adrs/0033-agent-owned-context-compaction.md +++ b/docs/adrs/0033-agent-owned-context-compaction.md @@ -3,14 +3,14 @@ ## In brief - Every authored agent owns its context-compaction loop through AI SDK `prepareStep`. -- Tilde records lifecycle and memory evidence; it does not summarize for OpenBot. +- Tilde records lifecycle and memory evidence; it does not summarize for Dispatch. - The default agent compacts near 80% of a configurable context window. - A structured handoff precedes a complete recent user-turn tail. - Provider preparation runs first and compaction preserves its non-context overrides. ## Context -OpenBot conversations are durable in Tilde, but model context is request-local. +Dispatch conversations are durable in Tilde, but model context is request-local. Long sessions need a compact representation without deleting or rewriting the canonical transcript. Provider-native compaction would couple authored agents to one inference adapter, while moving the loop into Tilde would make ChatKit own @@ -18,10 +18,10 @@ model behavior that belongs to the agent. ## Decision -The default OpenBot agent creates a request-scoped compaction controller and +The default Dispatch agent creates a request-scoped compaction controller and composes it with any inference-provider `prepareStep`. Before a step, the controller estimates the complete persisted context and triggers at 80% of -`OPENBOT_AGENT_CONTEXT_WINDOW_TOKENS` (128,000 by default). +`DISPATCH_AGENT_CONTEXT_WINDOW_TOKENS` (128,000 by default). Compaction uses the active model with tools disabled by omission, a structured handoff prompt, up to three attempts, progressive input reduction, and a diff --git a/docs/adrs/0033-pause-mobile-client.md b/docs/adrs/0033-pause-mobile-client.md index b798c06d..c6dfceed 100644 --- a/docs/adrs/0033-pause-mobile-client.md +++ b/docs/adrs/0033-pause-mobile-client.md @@ -10,7 +10,7 @@ ## Context -OpenBot grew an Expo owner client while its control, ChatKit, tools, Computer, authentication, and deployment foundations were still changing quickly. Keeping Android and iOS in every build and parity gate made those foundational changes carry a second renderer, native toolchains, simulators, EAS credentials, and store-release infrastructure before the primary product path was stable. +Dispatch grew an Expo owner client while its control, ChatKit, tools, Computer, authentication, and deployment foundations were still changing quickly. Keeping Android and iOS in every build and parity gate made those foundational changes carry a second renderer, native toolchains, simulators, EAS credentials, and store-release infrastructure before the primary product path was stable. The mobile implementation is useful work and must remain recoverable, but leaving it on main implies it is maintained and release-ready. It is neither. A Git branch and deliberately unmergeable PR preserve the exact source and history without keeping that operational promise in the active tree. @@ -40,4 +40,4 @@ Mobile may return only after the web/desktop foundation has stable contracts and ## Updates -- 2026-08-29T07:28:00+02:00: Initial decision, explicitly requested by the product owner while stabilizing the OpenBot foundation. +- 2026-08-29T07:28:00+02:00: Initial decision, explicitly requested by the product owner while stabilizing the Dispatch foundation. diff --git a/docs/adrs/0034-durable-background-agent-jobs.md b/docs/adrs/0034-durable-background-agent-jobs.md index 9f92815f..629f8299 100644 --- a/docs/adrs/0034-durable-background-agent-jobs.md +++ b/docs/adrs/0034-durable-background-agent-jobs.md @@ -8,7 +8,7 @@ Accepted Tilde owns provider-neutral, durable child-job state, parent/child correlation, idempotent dispatch and effect receipts, leases, terminal wakes, transcript and -artifact references, and owner authorization. OpenBot owns authored delegation +artifact references, and owner authorization. Dispatch owns authored delegation tools, inference policy, optional caller-selected child models, parallel fan-out, and parent-side aggregation. @@ -31,12 +31,12 @@ attachment IDs, while `collectResult` resolves fresh authorized download URLs. ## Consequences -- OpenBot can launch independent children concurrently and continue its parent +- Dispatch can launch independent children concurrently and continue its parent inference without blocking on each child. - Horizontally scaled workers use database leases and one-winner claims. - Recovery retries are safe only through recorded idempotency/effect receipts; providers must not be called outside that boundary. -- OpenBot may apply provider-specific time, token, and cost enforcement while +- Dispatch may apply provider-specific time, token, and cost enforcement while Tilde persists and exposes the caller-selected hard budgets. - The owner-facing Work surface lists active and recent children, opens durable results/artifacts, and supports steer, stop, and resume on web, Electron, and diff --git a/docs/adrs/0034-opt-in-automatic-memory.md b/docs/adrs/0034-opt-in-automatic-memory.md index b8e78130..1049e006 100644 --- a/docs/adrs/0034-opt-in-automatic-memory.md +++ b/docs/adrs/0034-opt-in-automatic-memory.md @@ -2,10 +2,10 @@ ## In brief -- The reusable Tilde SDK and OpenBot both default automatic memory to `none`. +- The reusable Tilde SDK and Dispatch both default automatic memory to `none`. Owners opt in during initialization or with fork-owned environment settings. - Tilde derives memory authority from the durable triggering ChatKit message; - OpenBot never supplies a user identity or bank ID during recall. + Dispatch never supplies a user identity or bank ID during recall. - The agent inserts a deterministic bounded projection after stable instructions and any compaction checkpoint so provider prompt-prefix caching remains useful. - Memory Catcher is a least-privilege user-deployed background agent with one @@ -14,10 +14,10 @@ ## Decision -OpenBot uses the high-level Tilde automatic-memory controller around inference. +Dispatch uses the high-level Tilde automatic-memory controller around inference. An owner can select `none`, `personal`, `personal_plus_agent`, or `team`, and can -inspect, edit, or delete visible facts. OpenBot's deployment default is `none`. -`OPENBOT_AUTOMATIC_MEMORY_MODE` selects the installation default and +inspect, edit, or delete visible facts. Dispatch's deployment default is `none`. +`DISPATCH_AUTOMATIC_MEMORY_MODE` selects the installation default and `AGENT__AUTOMATIC_MEMORY_MODE` overrides one bot. Only `personal_plus_agent` provisions a bot-owned bank; moving away sends an explicit disabled bank spec so repeated deployment removes that owned bank. @@ -25,7 +25,7 @@ explicit disabled bank spec so repeated deployment removes that owned bank. Recall is tied to the newest durable triggering message ID. Tilde authenticates the recipient bot, resolves the effective actor and current bank visibility, and returns bounded provenance for the bank, memory, evidence, source, and learning -bot. OpenBot inserts that projection as a dynamic system suffix: +bot. Dispatch inserts that projection as a dynamic system suffix: ```mermaid flowchart LR @@ -38,7 +38,7 @@ flowchart LR Q --> S[Memory Catcher session bound to one bank] ``` -ChatKit, not the OpenBot model loop, performs idempotent post-turn evidence +ChatKit, not the Dispatch model loop, performs idempotent post-turn evidence enqueueing. Explicit owner facts remain owner-editable and protected from automatic overwrite. diff --git a/docs/adrs/0035-durable-agent-run-host.md b/docs/adrs/0035-durable-agent-run-host.md index c2fc00fb..5bdb8422 100644 --- a/docs/adrs/0035-durable-agent-run-host.md +++ b/docs/adrs/0035-durable-agent-run-host.md @@ -3,7 +3,7 @@ ## In brief - Tilde owns durable runs, leases, steps, wakeups, budgets, and effect receipts. -- OpenBot owns model calls and hidden continuation policy. +- Dispatch owns model calls and hidden continuation policy. - Three continuations without a tool call or measurable progress pause the run. - Repeated tool/response patterns stall visibly instead of looping forever. - Effect intent is written before execution; uncertain non-idempotent effects diff --git a/docs/adrs/0036-multiplayer-room-client-parity.md b/docs/adrs/0036-multiplayer-room-client-parity.md index 6db0886e..6b96a0aa 100644 --- a/docs/adrs/0036-multiplayer-room-client-parity.md +++ b/docs/adrs/0036-multiplayer-room-client-parity.md @@ -2,19 +2,19 @@ Status: Accepted -OpenBot retains the shared client-runtime room contract for durable roster, +Dispatch retains the shared client-runtime room contract for durable roster, roles, invitation lifecycle, departure, typing/presence, and shared session attachments. The public Tilde SDK remains the supported programmatic surface. Owner-facing web, desktop, and mobile room controls are intentionally deferred; the earlier raw-user-ID invitation UI was not a shippable identity experience. -Tilde owns membership, admission, authorization, and event audiences. OpenBot +Tilde owns membership, admission, authorization, and event audiences. Dispatch owns presentation and bounded group-turn policy. Client code must not copy a participant's credential, personal tool, or private memory into shared room configuration. -Owner: OpenBot web and mobile clients +Owner: Dispatch web and mobile clients Trigger: when multiplayer owner UX is prioritized Work: restore room roster, presence, invitation, and moderation UI using shared client-runtime contracts; replace raw Tilde user-ID entry with human identity diff --git a/docs/adrs/0038-metadata-is-extension-data.md b/docs/adrs/0038-metadata-is-extension-data.md index 39b07ee6..cbb0cbfb 100644 --- a/docs/adrs/0038-metadata-is-extension-data.md +++ b/docs/adrs/0038-metadata-is-extension-data.md @@ -5,8 +5,8 @@ Status: Accepted ## In brief - Metadata is limited to provider-specific facts that cannot be normalized and - opaque client extensions that OpenBot/Tilde never interpret. -- OpenBot does not parse metadata for identity, authorization, audience, + opaque client extensions that Dispatch/Tilde never interpret. +- Dispatch does not parse metadata for identity, authorization, audience, routing, lifecycle, retries, relationships, runs, jobs, compaction, models, budgets, or memory. - Missing Tilde fields are fixed in the upstream DTO/OpenAPI and consumed after @@ -17,7 +17,7 @@ Status: Accepted ## Context -OpenBot historically accepted arbitrary ChatKit message metadata and provider +Dispatch historically accepted arbitrary ChatKit message metadata and provider metadata. Recent runtime work parsed server-authored `tildeAgentRun` and `tildeAgentJob` objects directly in the generated agent template, read queue timestamps from metadata, and discriminated Signals through metadata. These @@ -26,12 +26,12 @@ keys outside the generated Tilde contract. ## Decision -OpenBot follows Tilde API ADR 0022. Provider adapters may preserve upstream +Dispatch follows Tilde API ADR 0022. Provider adapters may preserve upstream facts such as GitHub pull-request identifiers and provider-native payload fragments when those facts have no provider-neutral representation. Clients -may attach opaque extensions when OpenBot and Tilde only store and return them. +may attach opaque extensions when Dispatch and Tilde only store and return them. -All OpenBot/Tilde-owned semantics use generated DTOs, shared client-runtime +All Dispatch/Tilde-owned semantics use generated DTOs, shared client-runtime contracts, provider core contracts, or another explicit typed interface. Runtime validation around `unknown` or `Record` is not an acceptable substitute. Backwards compatibility or avoiding an upstream schema @@ -41,7 +41,7 @@ change does not justify an internal metadata protocol. - Existing internal metadata consumers are migration debt and should be replaced in security-first order. -- API and OpenBot changes that span repositories must pay the explicit contract +- API and Dispatch changes that span repositories must pay the explicit contract and generated-client cost. - PR and pre-commit skills require metadata classification and block internal semantics. diff --git a/docs/adrs/README.md b/docs/adrs/README.md index 5e4ac94d..25ff7887 100644 --- a/docs/adrs/README.md +++ b/docs/adrs/README.md @@ -30,7 +30,7 @@ The `In brief` bullets use caveman style: terse fragments, exact nouns, explicit ## Decision -{What OpenBot will do, including the important no.} +{What Dispatch will do, including the important no.} ```mermaid flowchart LR diff --git a/docs/agents.md b/docs/agents.md index 0db1e82a..14883ee9 100644 --- a/docs/agents.md +++ b/docs/agents.md @@ -1,17 +1,17 @@ # Agents -The primary agent lives at `configuration/agent/` and uses the stable ID `factory`. `openbot new-agent` creates full additional agents at `configuration/agent/subagents//`, where the directory name is the ID. Every agent has the same supported files, lifecycle, endpoint, instrumentation, skills, tools, and workspace seed. A subagent cannot contain another `subagents/` directory. +The primary agent lives at `configuration/agent/` and uses the stable ID `factory`. `tilde new-agent` creates full additional agents at `configuration/agent/subagents//`, where the directory name is the ID. Every agent has the same supported files, lifecycle, endpoint, instrumentation, skills, tools, and workspace seed. A subagent cannot contain another `subagents/` directory. -`agent.ts` must default-export the request handler returned by Tilde `chatKitEndpoint(...)`; OpenBot mounts it at `/api/agents/`. `instructions.ts` default-exports the system instructions and is explicitly imported by `agent.ts`. +`agent.ts` must default-export the request handler returned by Tilde `chatKitEndpoint(...)`; Dispatch mounts it at `/api/agents/`. `instructions.ts` default-exports the system instructions and is explicitly imported by `agent.ts`. The supported authored tree is `agent.ts`, `instructions.ts`, optional `instrumentation.ts`, `lib/`, `tools/`, `skills/`, and `sandbox/workspace/**`. Configuration-wide `configuration/instrumentation.ts` runs before every agent-local instrumentation hook and before importing the endpoint. Tools must default-export a Vercel AI SDK tool and are explicitly imported by `agent.ts`; skills conform to the agent skill specification but are not loaded automatically yet. Channels, connections, hooks, schedules, and nested subagents are unsupported. -The directory remains named `sandbox/` only to follow Eve's project layout where practical. OpenBot calls the runtime an OpenBot Computer everywhere else. Every agent contains explicit `await_shell`, `bash`, file, search, and screenshot tool files. Each is a thin default export from `@tryopenbot/computer-tools` with the path-derived agent ID fixed outside the model-visible input schema; agents never call a sandbox provider SDK or untyped endpoint directly. Every agent also carries `tools/configure_connector.ts`, a thin default export from `@tryopenbot/connector-tools` that emits the in-chat connector account picker (ADR-0027), plus the eight `tilde-*` platform skills under `skills/`. +The directory remains named `sandbox/` only to follow Eve's project layout where practical. Dispatch calls the runtime a Dispatch Computer everywhere else. Every agent contains explicit `await_shell`, `bash`, file, search, and screenshot tool files. Each is a thin default export from `@trytilde/dispatch-computer-tools` with the path-derived agent ID fixed outside the model-visible input schema; agents never call a sandbox provider SDK or untyped endpoint directly. Every agent also carries `tools/configure_connector.ts`, a thin default export from `@trytilde/dispatch-connector-tools` that emits the in-chat connector account picker (ADR-0027), plus the eight `tilde-*` platform skills under `skills/`. -Authored agents must not import OpenBot provider packages or `configuration/index.ts`. Integrate model, MCP, skill, Composio, and other vendor SDKs directly in `agent.ts`, `tools/`, or `lib/`. When an integration should be standard for new agents, update `configuration/templates/agent/`; edit existing agents explicitly. +Authored agents must not import Dispatch provider packages or `configuration/index.ts`. Integrate model, MCP, skill, Composio, and other vendor SDKs directly in `agent.ts`, `tools/`, or `lib/`. When an integration should be standard for new agents, update `configuration/templates/agent/`; edit existing agents explicitly. Personal tool federation is opt-in. Set -`OPENBOT_PERSONAL_TOOL_FEDERATION_MODE=all` to let each verified ChatKit +`DISPATCH_PERSONAL_TOOL_FEDERATION_MODE=all` to let each verified ChatKit speaker bring every active personal account to a shared agent, or `selected` to enforce the MCP server's provider/tool allowlist. The default is `none`. Generated agents use `context.mcp.connect(...)`; Tilde resolves accounts @@ -22,13 +22,13 @@ Authored agents also own context compaction. The default template composes a request-scoped ChatKit compaction controller into Vercel AI SDK `prepareStep`, reports its lifecycle with the agent and session IDs, and leaves the canonical ChatKit transcript untouched. Configure the model's context size with -`OPENBOT_AGENT_CONTEXT_WINDOW_TOKENS`; replace the controller in authored code +`DISPATCH_AGENT_CONTEXT_WINDOW_TOKENS`; replace the controller in authored code when a model needs another policy. Tilde persists lifecycle events but does not run the compaction loop. See ADR-0033 and the [AI SDK compaction guide](https://ai-sdk.dev/cookbook/guides/agent-context-compaction). Automatic memory is owner-selectable and defaults off. Set -`OPENBOT_AUTOMATIC_MEMORY_MODE` to `personal`, `personal_plus_agent`, or `team`, +`DISPATCH_AUTOMATIC_MEMORY_MODE` to `personal`, `personal_plus_agent`, or `team`, or use `AGENT__AUTOMATIC_MEMORY_MODE` for one bot. Enabled ordinary agents recall automatic memory before inference. Stable instructions remain the provider-cache prefix; the bounded provenance-bearing @@ -40,10 +40,10 @@ least-privilege background synthesizer under synthesis tools, uses the installation's selected inference provider, never sends human messages, and owns no memory bank itself. See ADR-0034. -All agents share one OpenBot Computer, filesystem, and process identity. If an agent's authored `sandbox/workspace/**` contains files, deployment seeds them once into `/workspace/`. The computer service uses the fixed agent ID to choose that default directory, but it is not a security boundary: agents can use absolute paths, see sibling directories, and administer the shared machine. Changes to authored seed files do not update an already deployed agent directory. +All agents share one Dispatch Computer, filesystem, and process identity. If an agent's authored `sandbox/workspace/**` contains files, deployment seeds them once into `/workspace/`. The computer service uses the fixed agent ID to choose that default directory, but it is not a security boundary: agents can use absolute paths, see sibling directories, and administer the shared machine. Changes to authored seed files do not update an already deployed agent directory. -Run `pnpm openbot new-agent` and enter the display name to scaffold a complete subagent safely; then edit its ordinary source files in the fork. The command loads every `configuration/templates/agent/**/*.hbs` file, preserves its relative path, removes the `.hbs` suffix, and renders strict agent values. Init seeds that fork-owned template when it is missing and uses it for the primary Factory agent; factory-only skills render from `configuration/templates/factory/**/*.hbs` into the primary agent alone. Later init runs preserve template changes, and template edits affect only future agents. This command only changes the authored filesystem before invoking normal idempotent development reconciliation. +Run `pnpm tilde new-agent` and enter the display name to scaffold a complete subagent safely; then edit its ordinary source files in the fork. The command loads every `configuration/templates/agent/**/*.hbs` file, preserves its relative path, removes the `.hbs` suffix, and renders strict agent values. Init seeds that fork-owned template when it is missing and uses it for the primary Factory agent; factory-only skills render from `configuration/templates/factory/**/*.hbs` into the primary agent alone. Later init runs preserve template changes, and template edits affect only future agents. This command only changes the authored filesystem before invoking normal idempotent development reconciliation. -`openbot dev` performs the remote lifecycle reconciliation before starting services. For each authored directory it creates or updates the Tilde Vercel AI SDK endpoint in local-running mode, creates an agent-specific dynamic MCP server and skill registry, writes their non-secret IDs to `configuration/.env` as `AGENT__*`, and stores newly issued endpoint credentials in encrypted configuration. Generated agents read their own agent, MCP-server, and registry variables. Run development through the Tilde tunnel when ChatKit must call the local endpoint. +`tilde dev` performs the remote lifecycle reconciliation before starting services. For each authored directory it creates or updates the Tilde Vercel AI SDK endpoint in local-running mode, creates an agent-specific dynamic MCP server and skill registry, writes their non-secret IDs to `configuration/.env` as `AGENT__*`, and stores newly issued endpoint credentials in encrypted configuration. Generated agents read their own agent, MCP-server, and registry variables. Run development through the Tilde tunnel when ChatKit must call the local endpoint. Reconciliation is idempotent: existing resources are reused and updated rather than duplicated. When an authored directory is deleted, the agent provider uses its persisted managed ID to clear the Vercel AI SDK endpoint, disable and remove the stale Tilde agent, and remove its stored endpoint IDs and credentials. diff --git a/docs/configuration.md b/docs/configuration.md index 586d006c..ea9e1613 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -1,8 +1,8 @@ # Repository configuration -The upstream repository initially tracks only `configuration/.gitignore`, with every configuration entry ignored. Run the standalone `openbot init` command from a completely empty destination directory; it creates and clones the owner repository before configuration begins. After initialization succeeds, init removes that exact sentinel so the fork can commit its generated configuration. Commit the sentinel deletion with the generated files. Git preserves that committed deletion during ordinary merges while upstream leaves the sentinel unchanged; if upstream ever changes it, resolve the delete/modify conflict in favor of the fork's configuration. A provider failure after clone leaves a resumable checkout. Init creates `configuration/index.ts` as the single fork-owned composition root and `configuration/templates/agent/` as the fork-owned source for future agents. The selected inference provider seeds its SDK-specific source into that template. On later interactive init runs, every provider domain with multiple built-ins is shown as a React Ink selector with the configured implementation preselected and all alternatives available. Selection is staged: init asks and provisions the selected provider immediately before presenting another provider domain. Init may rewrite a recognized canonical built-in composition, but it preserves custom or owner-edited composition. An inference switch migrates the future template and existing agents only while the affected files exactly match the previous provider scaffold. `index.ts` names and constructs every provider role explicitly. Agent entrypoints read their runtime environment directly instead of importing provider composition. Provider packages do not select implementations from string IDs. `Configuration()` only type-checks provider selection. Tracked source must not contain credentials. +The upstream repository initially tracks only `configuration/.gitignore`, with every configuration entry ignored. Run the standalone `tilde init` command from a completely empty destination directory; it creates and clones the owner repository before configuration begins. After initialization succeeds, init removes that exact sentinel so the fork can commit its generated configuration. Commit the sentinel deletion with the generated files. Git preserves that committed deletion during ordinary merges while upstream leaves the sentinel unchanged; if upstream ever changes it, resolve the delete/modify conflict in favor of the fork's configuration. A provider failure after clone leaves a resumable checkout. Init creates `configuration/index.ts` as the single fork-owned composition root and `configuration/templates/agent/` as the fork-owned source for future agents. The selected inference provider seeds its SDK-specific source into that template. On later interactive init runs, every provider domain with multiple built-ins is shown as a React Ink selector with the configured implementation preselected and all alternatives available. Selection is staged: init asks and provisions the selected provider immediately before presenting another provider domain. Init may rewrite a recognized canonical built-in composition, but it preserves custom or owner-edited composition. An inference switch migrates the future template and existing agents only while the affected files exactly match the previous provider scaffold. `index.ts` names and constructs every provider role explicitly. Agent entrypoints read their runtime environment directly instead of importing provider composition. Provider packages do not select implementations from string IDs. `Configuration()` only type-checks provider selection. Tracked source must not contain credentials. -OpenBot never loads root `.env`, `.env.local`, or a root SOPS document. Fork-owned values live only in `configuration/.env` and `configuration/secrets.enc.yaml`. User-specific SOPS lookup metadata lives in the gitignored root `local-user-config.json` under `sops`, so each checkout selects the correct owner authority. Interactive commands configure the file inline when it is absent. Contributors and CI use their process environment for repository-maintenance credentials. +Dispatch never loads root `.env`, `.env.local`, or a root SOPS document. Fork-owned values live only in `configuration/.env` and `configuration/secrets.enc.yaml`. User-specific SOPS lookup metadata lives in the gitignored root `local-user-config.json` under `sops`, so each checkout selects the correct owner authority. Interactive commands configure the file inline when it is absent. Contributors and CI use their process environment for repository-maintenance credentials. ```json { @@ -17,13 +17,13 @@ OpenBot never loads root `.env`, `.env.local`, or a root SOPS document. Fork-own ``` ```ts -import { Configuration } from "@tryopenbot/configuration"; -import { TildeAgentProvider } from "@tryopenbot/agent-provider"; -import { VercelAgentServiceProvider } from "@tryopenbot/agent-service-provider"; -import { VercelControlServiceProvider } from "@tryopenbot/control-service-provider"; -import { VercelSandboxComputerProvider } from "@tryopenbot/computer-service-provider"; -import { VercelInferenceProvider } from "@tryopenbot/inference-provider"; -import { TildePlatform, VercelPlatform } from "@tryopenbot/platform-integrations"; +import { Configuration } from "@trytilde/dispatch-configuration"; +import { TildeAgentProvider } from "@trytilde/dispatch-agent-provider"; +import { VercelAgentServiceProvider } from "@trytilde/dispatch-agent-service-provider"; +import { VercelControlServiceProvider } from "@trytilde/dispatch-control-service-provider"; +import { VercelSandboxComputerProvider } from "@trytilde/dispatch-computer-service-provider"; +import { VercelInferenceProvider } from "@trytilde/dispatch-inference-provider"; +import { TildePlatform, VercelPlatform } from "@trytilde/dispatch-platform-integrations"; const tilde = new TildePlatform({ apiKey: process.env.TILDE_API_KEY!, @@ -44,7 +44,7 @@ export default Configuration({ }); ``` -This composition is for OpenBot control, provisioning, and deployment. Agent files do not import it or any provider package. Put model, MCP, skill, Composio, and other vendor SDK wiring directly in the agent and in `configuration/templates/agent/` when it should be a future default. +This composition is for Dispatch control, provisioning, and deployment. Agent files do not import it or any provider package. Put model, MCP, skill, Composio, and other vendor SDK wiring directly in the agent and in `configuration/templates/agent/` when it should be a future default. Repository resources always use their canonical file locations: @@ -67,7 +67,7 @@ accepts the Code Storage organization key only as transient setup input, and per repository-only JWT as a SOPS secret. The remote VM receives the decrypted fork configuration because this mode deliberately promotes the trusted development lifecycle to an always-on runtime. -`openbot new-agent` renders the fork-owned agent template, preserves relative +`tilde new-agent` renders the fork-owned agent template, preserves relative paths, and removes each `.hbs` suffix. Init seeds the default template when it is missing. When an init selector changes inference providers, init can replace the previous provider scaffold across the future template and existing agents, @@ -80,9 +80,9 @@ explicitly when required. The Vercel Sandbox computer provider does not ask for a registry. Deployment creates the control and agent Vercel projects first, then authenticates Docker -with the deployment token and creates `openbot-computer` in the agent project's +with the deployment token and creates `dispatch-computer` in the agent project's built-in Vercel Container Registry on first push. The local Microsandbox provider tags its local image from the Git remote, such as -`trytilde/openbot-computer:`. +`trytilde/dispatch-computer:`. -Run `pnpm openbot check` after every configuration change. Provider build checks also run automatically before `pnpm openbot deploy` creates or deploys an artifact. +Run `pnpm tilde check` after every configuration change. Provider build checks also run automatically before `pnpm tilde deploy` creates or deploys an artifact. diff --git a/docs/forks.md b/docs/forks.md index 758dedef..929d0940 100644 --- a/docs/forks.md +++ b/docs/forks.md @@ -1,17 +1,17 @@ # Maintain a fork -Public forks can use the Vercel clone flow directly. Private installations should mirror the repository into a private Git host and connect that repository to Vercel. OpenBot never writes source changes back to either repository at runtime. +Public forks can use the Vercel clone flow directly. Private installations should mirror the repository into a private Git host and connect that repository to Vercel. Dispatch never writes source changes back to either repository at runtime. Keep the upstream project as a second remote: ```bash git remote add upstream https://github.com/trytilde/dispatch.git git fetch upstream -git switch -c update/openbot +git switch -c update/dispatch git merge upstream/main pnpm install -pnpm openbot check -pnpm openbot build +pnpm tilde check +pnpm tilde build ``` -A fork's own development hosts live in `configuration/dev-hosts.json`, so they survive an upstream merge untouched. Treat `configuration/index.ts` and the complete `configuration/` tree as fork-owned during conflict resolution. The `.agents/skills/update-openbot` workflow gives coding agents the same rule. Put generally useful contracts and implementations in a focused upstream pull request; keep business-specific agents and secrets in the fork. +A fork's own development hosts live in `configuration/dev-hosts.json`, so they survive an upstream merge untouched. Treat `configuration/index.ts` and the complete `configuration/` tree as fork-owned during conflict resolution. The `.agents/skills/update-dispatch` workflow gives coding agents the same rule. Put generally useful contracts and implementations in a focused upstream pull request; keep business-specific agents and secrets in the fork. diff --git a/docs/lifecycle.md b/docs/lifecycle.md index 4d455103..86a21642 100644 --- a/docs/lifecycle.md +++ b/docs/lifecycle.md @@ -1,14 +1,14 @@ -# OpenBot lifecycle +# Dispatch lifecycle -OpenBot uses typed lifecycle hooks. Hooks own work. Events only report progress. +Dispatch uses typed lifecycle hooks. Hooks own work. Events only report progress. ## Initialization -`openbot init` creates or revisits fork-owned configuration. Shared platforms are collected once, even when several providers use them. +`tilde init` creates or revisits fork-owned configuration. Shared platforms are collected once, even when several providers use them. ```mermaid flowchart TD - A["openbot init"] --> B{"Initialized repository?"} + A["tilde init"] --> B{"Initialized repository?"} B -- "No" --> C["Verify canonical revision and GitHub access"] C --> D["Create public fork or private mirror"] D --> E["Clone and verify owned repository"] @@ -49,11 +49,11 @@ Keep initialization deterministic. It should collect configuration, validate acc ## Adding an agent -`openbot new-agent` materializes source, then runs the same idempotent development reconciliation used by `openbot dev`. Production deployment runs that lifecycle again with the deployed agent-service base URL. +`tilde new-agent` materializes source, then runs the same idempotent development reconciliation used by `tilde dev`. Production deployment runs that lifecycle again with the deployed agent-service base URL. ```mermaid flowchart TD - A["openbot new-agent"] --> B["Normalize display name into agent ID"] + A["tilde new-agent"] --> B["Normalize display name into agent ID"] B --> C{"Agent directory exists?"} C -- "Yes" --> D["Stop without overwriting"] C -- "No" --> E["Load configuration/templates/agent/**/*.hbs"] @@ -100,14 +100,14 @@ Repository builds and deployment artifact builds are related but distinct. ```mermaid flowchart TD - A["openbot build"] --> B["Delegate to pnpm build"] + A["tilde build"] --> B["Delegate to pnpm build"] B --> C["Generate protobuf contracts"] C --> D["Run workspace package builds"] D --> E["Type-check and bundle packages and apps"] E --> F["Copy package assets"] F --> G["Verify published package artifacts and standalone CLI"] - H["openbot deploy"] --> I["Select deployment participants"] + H["tilde deploy"] --> I["Select deployment participants"] I --> J{"Participant exposes buildable?"} J -- "Yes" --> K["Buildable.check"] K --> L["Buildable.build"] @@ -127,11 +127,11 @@ Package `build` scripts compile publishable workspace packages. They are not pro ## Deploying -`openbot deploy` builds first, plans every deployable participant, configures prerequisites, then deploys the runtime last. +`tilde deploy` builds first, plans every deployable participant, configures prerequisites, then deploys the runtime last. ```mermaid flowchart TD - A["openbot deploy"] --> B["Load decrypted deployment configuration"] + A["tilde deploy"] --> B["Load decrypted deployment configuration"] B --> C["Compose selected participants"] C --> D["Buildable.check for each buildable participant"] D --> E["Buildable.build for each buildable participant"] diff --git a/docs/metadata-usage-audit.md b/docs/metadata-usage-audit.md index 4795fa15..278782f0 100644 --- a/docs/metadata-usage-audit.md +++ b/docs/metadata-usage-audit.md @@ -23,7 +23,7 @@ Governing decision: [ADR-0038](adrs/0038-metadata-is-extension-data.md) | AgentMail, GitHub, Slack and Linq message metadata | Provider-specific; parsed by the corresponding ChatKit provider adapter | `packages/sdk-vercel-ai-node/src/chatkit-provider-metadata.ts` | | AI SDK attachment `providerMetadata` | Provider wire extension | `packages/sdk-vercel-ai-node/src/chatkit-attachments.ts`; `packages/computer-tools/src/attachments.ts` | | Coding-agent source/session/cwd/model annotations | Client-opaque message extension; Tilde core does not interpret them | `packages/sdk/src/chatkit/coding-agent.ts` | -| Routine, task and job metadata exposed unchanged by SDK wrappers | Client-opaque while Tilde/OpenBot do not interpret it | `packages/sdk/src/chatkit/{routines,work,jobs}.ts` | +| Routine, task and job metadata exposed unchanged by SDK wrappers | Client-opaque while Tilde/Dispatch do not interpret it | `packages/sdk/src/chatkit/{routines,work,jobs}.ts` | | Link-preview metadata | Typed presentation object, not a generic domain control bag | `packages/ui/src/content-components.tsx` | ## Excluded lexical uses @@ -39,5 +39,5 @@ ADR-0038. 2. Typed Signal and message summary fields. 3. Typed credential/provider catalogue descriptors. -The corresponding Tilde fields must land first; OpenBot must refresh generated +The corresponding Tilde fields must land first; Dispatch must refresh generated contracts rather than replacing one magic metadata parser with another. diff --git a/docs/providers.md b/docs/providers.md index bb03b4d2..c8a2fef1 100644 --- a/docs/providers.md +++ b/docs/providers.md @@ -1,11 +1,11 @@ # Providers -Providers adapt OpenBot itself to external systems. Keep a provider only when at least one of these owns the call: +Providers adapt Dispatch itself to external systems. Keep a provider only when at least one of these owns the call: - the control service, on behalf of the desktop or web app; - initialization or startup provisioning; - a `check`, `build`, `plan`, `configure`, or `deploy` lifecycle; -- reconciliation of external resources required before OpenBot starts. +- reconciliation of external resources required before Dispatch starts. Anything else belongs in the code that actually uses it. @@ -28,7 +28,7 @@ Every lifecycle method is idempotent. `check`, `build`, `plan`, `configure`, and Authored-agent reconciliation discovers agents once and supplies one Agent Provider lifecycle with the agent ID and absolute source path. The Tilde implementation reconciles the endpoint first, then authored skills and exact registry membership, then MCP and tool resources. A partially completed run is safe to repeat. -The built-in Tilde adapters use the typed API client directly. They identify resources by persisted IDs and stable OpenBot names, create missing resources, compare mutable fields, and update only drift. Authored `SKILL.md` files are keyed by repository-relative source path; removed files are removed from the agent-owned remote set and registry membership is exact. OpenBot does not import or export a Tilde state file during normal lifecycles. An operator may use the Tilde CLI manually to export a team's state and import it into another team for one-time setup or environment migration; OpenBot then resumes idempotent API reconciliation against that imported state. +The built-in Tilde adapters use the typed API client directly. They identify resources by persisted IDs and stable Dispatch names, create missing resources, compare mutable fields, and update only drift. Authored `SKILL.md` files are keyed by repository-relative source path; removed files are removed from the agent-owned remote set and registry membership is exact. Dispatch does not import or export a Tilde state file during normal lifecycles. An operator may use the Tilde CLI manually to export a team's state and import it into another team for one-time setup or environment migration; Dispatch then resumes idempotent API reconciliation against that imported state. Every Tilde agent receives a dynamic MCP server and a team-scoped Tilde control-plane toolkit. The primary factory agent additionally receives the brokered GitHub toolkit reconciled by the git provider; no raw GitHub token ever enters the repository or a Computer — sandboxes authenticate git through the Tilde reverse proxy. When the selected service deployment platform is Vercel, the Agent Provider's internal tools reconciler also manages Vercel's proxied MCP connection using the configured Vercel token. Development agent endpoints use Tilde local-runtime tunnel mode; production endpoints use their public service origin. Authored local tools execute inside that agent service, so they share its tunnel instead of registering a second custom HTTP endpoint. @@ -36,9 +36,9 @@ Every Tilde agent receives a dynamic MCP server and a team-scoped Tilde control- Code under `configuration/agent/`, including `subagents//`, must not import provider packages or `configuration/index.ts`. Providers do not contribute live model objects, prompts, AI SDK tools, arbitrary vendor methods, or generic plugin functions to a running agent. An inference provider may contribute source files while init seeds `configuration/templates/agent/`; those files immediately become fork-owned and import the vendor SDK directly. -Integrate the desired SDK directly in the authored agent. For example, an agent may use OpenAI, Anthropic, Tilde, Composio, or a custom API without first extending a provider interface. This keeps agent development unconstrained by OpenBot's control-plane abstractions. +Integrate the desired SDK directly in the authored agent. For example, an agent may use OpenAI, Anthropic, Tilde, Composio, or a custom API without first extending a provider interface. This keeps agent development unconstrained by Dispatch's control-plane abstractions. -Shared utilities that are not providers may still be imported. Instrumentation lives in `@tryopenbot/configuration/instrumentation`. The standard typed Computer tools live in `@tryopenbot/computer-tools`; they call the Computer service rather than a Computer provider. +Shared utilities that are not providers may still be imported. Instrumentation lives in `@trytilde/dispatch-configuration/instrumentation`. The standard typed Computer tools live in `@trytilde/dispatch-computer-tools`; they call the Computer service rather than a Computer provider. When all future agents need the same integration, update `configuration/templates/agent/`. Template changes affect newly scaffolded agents only, so migrate the primary and existing directories under `configuration/agent/subagents/` explicitly when required. @@ -52,7 +52,7 @@ Initialization questions are collected once per shared platform. Provider-specif The default `VercelInferenceProvider` shares the installation's `VercelPlatform`. Init asks for the AI Gateway key name, creates the key only when `AI_GATEWAY_API_KEY` is absent, and persists that canonical secret through SOPS. Its template contribution passes a `creator/model` string directly to AI SDK so the built-in default provider routes through AI Gateway. -`CodexInferenceProvider` is available with local and Vercel OpenBot runtimes. It always authenticates through `codex login --device-auth` in an isolated `CODEX_HOME` configured for file credentials. It persists the complete opaque auth document as `CODEX_AUTH_JSON` through SOPS, then uses Codex app-server's account read with refresh during init, development, and non-dry-run deployment checks. Non-interactive deployment never starts a nested login; invalid credentials stop with instructions to run interactive init. Its default-agent contribution uses `ai-sdk-provider-codex-cli` app-server mode and `gpt-5.6-sol`. OpenBot's AI SDK tool definitions are adapted to the package's local MCP tool representation because Codex executes its own tool loop. For Vercel, the inference build runs after the agent-service build, copies the Linux x64 Codex executable into every prebuilt Node function, and persists `VERCEL_SUPPORT_LARGE_FUNCTIONS=1`; the native binary makes Vercel Large Functions a deployment requirement. The provider contract still never crosses into request-time model selection. +`CodexInferenceProvider` is available with local and Vercel Dispatch runtimes. It always authenticates through `codex login --device-auth` in an isolated `CODEX_HOME` configured for file credentials. It persists the complete opaque auth document as `CODEX_AUTH_JSON` through SOPS, then uses Codex app-server's account read with refresh during init, development, and non-dry-run deployment checks. Non-interactive deployment never starts a nested login; invalid credentials stop with instructions to run interactive init. Its default-agent contribution uses `ai-sdk-provider-codex-cli` app-server mode and `gpt-5.6-sol`. Dispatch's AI SDK tool definitions are adapted to the package's local MCP tool representation because Codex executes its own tool loop. For Vercel, the inference build runs after the agent-service build, copies the Linux x64 Codex executable into every prebuilt Node function, and persists `VERCEL_SUPPORT_LARGE_FUNCTIONS=1`; the native binary makes Vercel Large Functions a deployment requirement. The provider contract still never crosses into request-time model selection. ## Adding or changing a provider @@ -82,7 +82,7 @@ For continuous private GitHub sync, configure the Code Storage GitHub App integr `https://.code.storage/webhooks/github`. 3. Install the App on the selected repository and save its App ID, private key, and webhook secret in the Code Storage Integrations dashboard. -4. Run `openbot init`, select exe.dev and GitHub App sync, then enter the organization key only in +4. Run `tilde init`, select exe.dev and GitHub App sync, then enter the organization key only in the setup-only prompt. Rotate or revoke that organization key after setup. Public sync is a one-time import and does not forward later pushes. GitHub App sync is continuous diff --git a/docs/sandbox.md b/docs/sandbox.md index ed7e6744..9702a2af 100644 --- a/docs/sandbox.md +++ b/docs/sandbox.md @@ -2,6 +2,6 @@ Agent workspace seeds live only under `configuration/agent/sandbox/workspace/**` for the primary or `configuration/agent/subagents//sandbox/workspace/**` for a subagent. Global `configuration/sandbox/` assets and bootstrap scripts are unsupported. One computer, filesystem, and process identity are shared across agents. A populated seed is copied once to `/workspace/` and commands default there; empty seeds create no directory. These directories are organizational, not isolation boundaries, and editing a seed never changes an already deployed directory automatically. -The authored folder is called `sandbox/` only for compatibility with Eve's project layout. OpenBot runtime terminology uses Computer, including computer-service, computer-service-provider, environment variables, and tool filenames. +The authored folder is called `sandbox/` only for compatibility with Eve's project layout. Dispatch runtime terminology uses Computer, including computer-service, computer-service-provider, environment variables, and tool filenames. -OpenBot does not load secrets from repository configuration or copy control-plane credentials into an agent workspace. Workspace seeds must not contain OpenAI, Tilde, Vercel, database, or other control-plane credentials. +Dispatch does not load secrets from repository configuration or copy control-plane credentials into an agent workspace. Workspace seeds must not contain OpenAI, Tilde, Vercel, database, or other control-plane credentials. diff --git a/docs/superpowers/specs/2026-08-24-routines-signals-design.md b/docs/superpowers/specs/2026-08-24-routines-signals-design.md index a3ab1ff4..64212fa5 100644 --- a/docs/superpowers/specs/2026-08-24-routines-signals-design.md +++ b/docs/superpowers/specs/2026-08-24-routines-signals-design.md @@ -5,12 +5,12 @@ Status: Approved (user), implementation in progress ## Summary -OpenBot gains one user-facing concept, **Routines**: per-agent cards with a name, an +Dispatch gains one user-facing concept, **Routines**: per-agent cards with a name, an instruction, and 1–8 OR'd **triggers**. A trigger is either a **schedule** (backed by a Tilde ChatKit routine — a UTC cron job) or a **provider event** (backed by a Tilde signal rule on a signal provider instance). The UX follows the recovered reference implementation routines experience with deliberate, recorded deviations. Signal provider connections -(webhook URL + signing secret) get an OpenBot-owned setup flow, since a self-hosted +(webhook URL + signing secret) get a Dispatch-owned setup flow, since a self-hosted deployment cannot hide provisioning behind a managed dashboard. ## Decisions (user-approved) @@ -24,8 +24,8 @@ deployment cannot hide provisioning behind a managed dashboard. 4. **Mobile**: deferred with ``; contracts and runtime state land in `client-runtime` so Expo only needs screens later. 5. **Grouping**: a new optional `metadata: Object` field on Tilde `Routine` and - `SignalRule` (upstream `trytilde/api` change). OpenBot stamps - `{"openbot": {"group": "", "trigger": ""}}` and reconstructs unified + `SignalRule` (upstream `trytilde/api` change). Dispatch stamps + `{"dispatch": {"group": "", "trigger": ""}}` and reconstructs unified cards statelessly from list calls. No local DB, no title markers. 6. **Tilde SDK abstractions** (added requirement): the SDK's unprocessed-message handling must expose a correctly typed shape for every signal provider and signal @@ -54,7 +54,7 @@ deployment cannot hide provisioning behind a managed dashboard. - Keep generated source internal to `@trytilde/api-client`; do not restore retired Harness package names or a separately pinned SDK repository. -### Phase 2 — OpenBot backend (`apps/control-service`) +### Phase 2 — Dispatch backend (`apps/control-service`) New `src/routines.ts` and `src/signals.ts`, modeled on `src/connectors.ts` (env-driven options, `tildeJson` helper, `requireOwner`, registration in `app.ts`), @@ -84,7 +84,7 @@ Routes: - Contract groups `contracts/routines.ts`, `contracts/signals.ts` (Zod, passthrough, paged, colocated tests) following `contracts/connectors.ts`. -- `OpenBotClient` methods; `routines` and `signalProviders` slices + actions in +- `DispatchClient` methods; `routines` and `signalProviders` slices + actions in `state/runtime.ts`; polling refresh while the pane is open via the injectable `schedule`/`cancelScheduled`; stale-while-revalidate so lists never flash empty. diff --git a/docs/superpowers/specs/2026-08-24-routines-signals-wire-contract.md b/docs/superpowers/specs/2026-08-24-routines-signals-wire-contract.md index ab22869a..96f92701 100644 --- a/docs/superpowers/specs/2026-08-24-routines-signals-wire-contract.md +++ b/docs/superpowers/specs/2026-08-24-routines-signals-wire-contract.md @@ -1,4 +1,4 @@ -# Routines & Signals — OpenBot wire contract +# Routines & Signals — Dispatch wire contract Companion to `2026-08-24-routines-signals-design.md`. This is the authoritative shape for the owner routes served by `apps/control-service` and validated by @@ -9,12 +9,12 @@ missing (connectors pattern). ## Unified routine A unified routine is reconstructed from Tilde resources stamped with -`metadata.openbot = { group: "", trigger: "" }`: +`metadata.dispatch = { group: "", trigger: "" }`: - schedule trigger ↔ ChatKit routine (`title` = name, `prompt` = instruction) - event trigger ↔ signal rule (`display_name` = name) -Tilde resources without an `openbot.group` stamp are ignored by the unified list. +Tilde resources without an `dispatch.group` stamp are ignored by the unified list. ```jsonc // Routine @@ -51,7 +51,7 @@ Tilde resources without an `openbot.group` stamp are ignored by the unified list - `GET /api/routines?agent_id=` → `{ "items": Routine[] }` Lists all pages of Tilde routines + signal rules for the team, groups by - `metadata.openbot.group`, filters to the agent (`agent_inbox_id` on routines, + `metadata.dispatch.group`, filters to the agent (`agent_inbox_id` on routines, `action.agent_inbox_id` on rules). `agent_id` required. - `POST /api/routines` body: ```jsonc @@ -88,7 +88,7 @@ client refreshes separately). `signal_type`, `filter: { json_equals: filters }`, `action: { type: "invoke_chatkit_agent", agent_inbox_id }`, `session_policy` resolved at create time from the provider catalog's signal type: - `{ type: "session_key_template", namespace: "openbot", + `{ type: "session_key_template", namespace: "dispatch", template: , create_if_missing: true, title_template: }`, @@ -167,7 +167,7 @@ week / Every month) and `cronForPreset(...)` — all pure, shared web/Expo. `SignalDeliverySchema`, inputs `CreateSignalInstanceInput`, `UpdateSignalInstanceInput`, `TestSignalInstanceInput`. -`OpenBotClient` methods: `listRoutines(agentId)`, `createRoutine(input)`, +`DispatchClient` methods: `listRoutines(agentId)`, `createRoutine(input)`, `updateRoutine(groupId, agentId, input)`, `deleteRoutine(groupId, agentId)`, `runRoutine(groupId, agentId)`, `listSignalProviders()`, `listSignalInstances()`, `createSignalInstance(input)`, `updateSignalInstance(id, input)`, diff --git a/docs/updates/101.md b/docs/updates/101.md index 97f3463f..04c297a3 100644 --- a/docs/updates/101.md +++ b/docs/updates/101.md @@ -39,7 +39,7 @@ flowchart LR ## Summarized package changes -- `@tryopenbot/client-runtime` +- `@trytilde/dispatch-client-runtime` - Add the strict ChatKit event/frame schemas, direct reducers, access refresh, read-state mutation, queue reconciliation, and regression coverage. - Control service @@ -71,9 +71,9 @@ Validation completed: yes Merge `trytilde/common-js#20` first, then deploy `trytilde/api#175` and this -OpenBot update together. The socket change is intentionally incompatible in -both directions, so mixed old/new API and OpenBot deployments are unsupported. +Dispatch update together. The socket change is intentionally incompatible in +both directions, so mixed old/new API and Dispatch deployments are unsupported. Run the API's additive per-user read-state migration before enabling the new -client. No OpenBot secret, environment, fork configuration, portable state, or +client. No Dispatch secret, environment, fork configuration, portable state, or resource-identity migration is required. `configuration/` remains fork-owned; the upstream PR contains only its canonical ignore-all sentinel. diff --git a/docs/updates/102.md b/docs/updates/102.md index c689e504..5c4fe39c 100644 --- a/docs/updates/102.md +++ b/docs/updates/102.md @@ -1,29 +1,29 @@ # Intent of the change -- Make real `AgentAvatar` reusable without whole OpenBot UI barrel. -- Keep avatar appearance. Avoid global OpenBot theme and token leakage. +- Make real `AgentAvatar` reusable without whole Dispatch UI barrel. +- Keep avatar appearance. Avoid global Dispatch theme and token leakage. - Remove required packed `client-runtime` workspace dependency from avatar consumers. # Architecture changes ```mermaid flowchart LR - Consumer --> Avatar["@tryopenbot/ui/agent-avatar"] - Consumer --> Styles["@tryopenbot/ui/agent-avatar.css"] + Consumer --> Avatar["@trytilde/dispatch-ui/agent-avatar"] + Consumer --> Styles["@trytilde/dispatch-ui/agent-avatar.css"] Avatar --> React Avatar --> Assets["packaged avatar artwork"] - FullUI["@tryopenbot/ui root"] -. optional peer .-> Runtime["@tryopenbot/client-runtime"] + FullUI["@trytilde/dispatch-ui root"] -. optional peer .-> Runtime["@trytilde/dispatch-client-runtime"] ``` - New public avatar subpath points only at packed `dist` JavaScript and declarations. - New stylesheet is component-scoped. It defines avatar layout and opacity transition only. It defines no theme tokens. -- `@tryopenbot/client-runtime` becomes optional peer plus workspace development dependency. Full UI consumers needing runtime-backed exports still install it. Standalone avatar consumers do not. +- `@trytilde/dispatch-client-runtime` becomes optional peer plus workspace development dependency. Full UI consumers needing runtime-backed exports still install it. Standalone avatar consumers do not. - No provider, protocol, state, configuration, deployment, authentication, or authorization boundary changes. - ADR review found no new durable decision. Existing UI package owns this public interface. # Summarized package changes -- `@tryopenbot/ui` +- `@trytilde/dispatch-ui` - exports `./agent-avatar` and `./agent-avatar.css`; - packages scoped avatar CSS; - documents standalone consumer imports; @@ -36,4 +36,4 @@ flowchart LR # Critical to apply to forks -yes — forks or downstream apps wanting only the avatar should pin a release or immutable Git commit containing this change, import `AgentAvatar` from `@tryopenbot/ui/agent-avatar`, and import `@tryopenbot/ui/agent-avatar.css`. Do not import `openbot-ui.css` only for the avatar. Full root-package consumers using runtime-backed UI exports must keep `@tryopenbot/client-runtime` installed explicitly. +yes — forks or downstream apps wanting only the avatar should pin a release or immutable Git commit containing this change, import `AgentAvatar` from `@trytilde/dispatch-ui/agent-avatar`, and import `@trytilde/dispatch-ui/agent-avatar.css`. Do not import `dispatch-ui.css` only for the avatar. Full root-package consumers using runtime-backed UI exports must keep `@trytilde/dispatch-client-runtime` installed explicitly. diff --git a/docs/updates/103.md b/docs/updates/103.md index e83ade12..27a63300 100644 --- a/docs/updates/103.md +++ b/docs/updates/103.md @@ -20,10 +20,10 @@ flowchart LR # Summarized package changes -- `@tryopenbot/control-service`: compare unsafe browser requests against the host-matched configured HTTPS development origin before localhost discovery or internal request-origin fallback. +- `@trytilde/dispatch-control-service`: compare unsafe browser requests against the host-matched configured HTTPS development origin before localhost discovery or internal request-origin fallback. - Regression coverage proves the matching exe.dev origin proceeds while a foreign origin remains rejected. - Unified patch Changeset added for the fixed workspace release group. -- Production proof on `our-openbot.exe.xyz`: matching public origin reaches the authentication boundary, foreign origin returns 403, and root/health remain 200. +- Production proof on `our-dispatch.exe.xyz`: matching public origin reaches the authentication boundary, foreign origin returns 403, and root/health remain 200. # Critical to apply diff --git a/docs/updates/104.md b/docs/updates/104.md index e3ef6a6b..41eac77d 100644 --- a/docs/updates/104.md +++ b/docs/updates/104.md @@ -1,7 +1,7 @@ # Intent of the change -- Make `@tryopenbot/ui` usable as a pnpm Git dependency from a clean consumer. -- Ensure public built subpaths such as `@tryopenbot/ui/agent-avatar` exist before pnpm packs the selected workspace package. +- Make `@trytilde/dispatch-ui` usable as a pnpm Git dependency from a clean consumer. +- Ensure public built subpaths such as `@trytilde/dispatch-ui/agent-avatar` exist before pnpm packs the selected workspace package. - Prevent the production-only failure where a warm local package store hid missing Git artifacts. # Architecture changes @@ -10,20 +10,20 @@ No ownership boundary changes. The UI package still owns its public artifacts; i ```mermaid flowchart LR - C["pnpm Git consumer"] --> P["OpenBot workspace prepare"] - P --> U["@tryopenbot/ui prepare"] + C["pnpm Git consumer"] --> P["Dispatch workspace prepare"] + P --> U["@trytilde/dispatch-ui prepare"] U --> D["dist avatar artifacts"] D --> C ``` # Summarized package changes -- `@tryopenbot/ui` runs its existing build from `prepare`, in addition to `prepack`. +- `@trytilde/dispatch-ui` runs its existing build from `prepare`, in addition to `prepack`. - The avatar packaging test fixes the Git-install lifecycle as part of the public subpath contract. - A clean external pnpm consumer installed the pushed Git commit, found the avatar JavaScript, declarations, and scoped CSS, and imported `AgentAvatar` successfully. -- The OpenBot fixed package group receives a patch changeset. +- The Dispatch fixed package group receives a patch changeset. - Repository checks and builds pass. Existing non-blocking lint warnings remain unrelated. # Critical to apply to forks -yes — forks or applications that pin `@tryopenbot/ui` directly from Git must update their immutable OpenBot commit to include this change. Keep `@tryopenbot/workspace` and `@tryopenbot/ui` allowed in pnpm build policy so the trusted Git dependency may generate and pack its artifacts. No state, secret, API, provider, or configuration migration is required. +yes — forks or applications that pin `@trytilde/dispatch-ui` directly from Git must update their immutable Dispatch commit to include this change. Keep `@trytilde/dispatch-workspace` and `@trytilde/dispatch-ui` allowed in pnpm build policy so the trusted Git dependency may generate and pack its artifacts. No state, secret, API, provider, or configuration migration is required. diff --git a/docs/updates/106.md b/docs/updates/106.md index 459a87d8..542e17a8 100644 --- a/docs/updates/106.md +++ b/docs/updates/106.md @@ -1,6 +1,6 @@ # Intent of the change -The Tilde SDK now lives in the OpenBot packages monorepo under ADR-0030. This change exposes the +The Tilde SDK now lives in the Dispatch packages monorepo under ADR-0030. This change exposes the ChatKit observability API added by [trytilde/api#188](https://github.com/trytilde/api/pull/188) and uses it for locally bound MCP tools. @@ -11,11 +11,11 @@ them into the wrapper call. Remote MCP execution remains owned by Tilde and is n # Architecture changes No ownership boundary changes. Tilde API remains the observability control plane and persistence -owner. OpenBot's public SDK packages translate authored local-tool activity into that API. +owner. Dispatch's public SDK packages translate authored local-tool activity into that API. ```mermaid flowchart LR - Agent["Authored OpenBot agent"] --> MCP["createMCPClient"] + Agent["Authored Dispatch agent"] --> MCP["createMCPClient"] MCP --> Register["Register complete local tool catalog"] MCP --> Execute["Execute local tool"] Execute --> Report["Report started / completed / failed"] @@ -45,24 +45,24 @@ from Tilde's OpenAPI document. - Registers the complete local tool catalog when the MCP client connects. - Reports local started, completed, and failed states to ChatKit. - Closes the remote MCP client if local catalog registration fails. -- OpenBot agent template +- Dispatch agent template - Passes the authored agent ID and ChatKit session ID into `createMCPClient`. - Documentation and release metadata - Documents the new adapter inputs and behavior. - - Adds a Changeset for all affected published packages and the fixed OpenBot package group. + - Adds a Changeset for all affected published packages and the fixed Dispatch package group. - Uses stable generated-source provenance instead of a machine-local filesystem path. Validation completed: -- `pnpm openbot sdk refresh` passed: 632 operations validated; all five SDK packages built; 158 +- `pnpm tilde sdk refresh` passed: 632 operations validated; all five SDK packages built; 158 focused tests passed. -- `pnpm openbot sdk validate` passed. +- `pnpm tilde sdk validate` passed. - Focused SDK checks and tests passed with existing warnings only. - Repository `pnpm build` passed, including web and Expo exports. - Repository checks excluding the pre-existing untracked `reference/` directory passed with zero errors. The unfiltered formatting gate only reports files in that unrelated directory. -No client UI, protobuf, dependency, credential, secret, or persisted OpenBot configuration changes. +No client UI, protobuf, dependency, credential, secret, or persisted Dispatch configuration changes. Live Tilde SDK E2E was not run because the required team, API key, and agent ID are unavailable. # Critical to apply to forks diff --git a/docs/updates/107.md b/docs/updates/107.md index 71a603aa..78ca9ba1 100644 --- a/docs/updates/107.md +++ b/docs/updates/107.md @@ -1,6 +1,6 @@ # Intent of the change -- Ship the Tilde SDK side of API PR 191 from its new home in OpenBot. +- Ship the Tilde SDK side of API PR 191 from its new home in Dispatch. - Let endpoint authors choose direct agent-loop replies or tool-only visible replies. - Give models useful provider actions without giving them session, participant, trigger-message, thread, repository, issue, or recipient routing authority. diff --git a/docs/updates/108.md b/docs/updates/108.md index 9bd78a9a..36a36e3c 100644 --- a/docs/updates/108.md +++ b/docs/updates/108.md @@ -1,18 +1,18 @@ # Intent of the change -OpenBot had four owner APIs that copied Tilde domains: plugins/connectors, +Dispatch had four owner APIs that copied Tilde domains: plugins/connectors, routines, and signals. They fetched Tilde, renamed fields, rebuilt assignments -from browser-supplied agent IDs, and sent another OpenBot-shaped response. +from browser-supplied agent IDs, and sent another Dispatch-shaped response. -Remove those facades. Keep only the credential boundary OpenBot genuinely owns: +Remove those facades. Keep only the credential boundary Dispatch genuinely owns: the browser has an HttpOnly installation session, while the Tilde API key must stay server-side. Clients now call native Tilde operations through one strict allowlist and validate/project the responses in shared Client Runtime. -Result: settings no longer send every agent ID, both active OpenBot clients share +Result: settings no longer send every agent ID, both active Dispatch clients share one transport, and control-service loses more than four thousand lines of duplicated routes and tests. Plugin inventory also no longer calls Tilde's -OpenBot-specific aggregate: it exhausts the native MCP and Skills pages instead. +Dispatch-specific aggregate: it exhausts the native MCP and Skills pages instead. The remaining ChatKit credential bridge now admits only the exact workspace, queue, observation, and attachment operations Client Runtime consumes; it no longer forwards the whole ChatKit namespace. @@ -42,10 +42,10 @@ flowchart LR over Tilde's generated MCP and Skills resource contracts. MCP server and skill registry `agent_id` fields are the assignment source of truth. - The native resource loaders follow every continuation token. This removes the - OpenBot aggregate endpoint's silent first-100-items ceiling. + Dispatch aggregate endpoint's silent first-100-items ceiling. - Connector setup uses Tilde `provider-setup`, managed MCP, credential, binding, and registry operations directly through the bridge. Secrets still travel - browser → authenticated OpenBot bridge → Tilde and never enter chat messages. + browser → authenticated Dispatch bridge → Tilde and never enter chat messages. - Routines page the authoritative native root and preserve `version`, root and trigger metadata, enablement, event action, instruction policy, and `session_policy` during full desired-state PUTs. @@ -58,7 +58,7 @@ flowchart LR # Summarized package changes -- `@tryopenbot/control-service` +- `@trytilde/dispatch-control-service` - Add `registerTildeProxy` and `registerConnectorAuthorizedRoute`. - Remove `registerConnectorRoutes` and `/api/plugins`, `/api/connectors`, `/api/routines`, `/api/signals`. @@ -67,30 +67,30 @@ flowchart LR observation, and attachment operations; reject unrendered administrative operations before they reach Tilde. - Expose only public Tilde team/origin metadata in `/auth/session`. - - Treat `openbot new-agent` as the sole source-and-Tilde reconciliation + - Treat `tilde new-agent` as the sole source-and-Tilde reconciliation lifecycle. A completed background command is ready; control-service no longer repeats bundle provisioning or requires a second owner bearer token. - Generate primary and future agent endpoints with explicit `agentLoop` response mode, matching the required ChatKit SDK contract. -- `@tryopenbot/client-runtime` +- `@trytilde/dispatch-client-runtime` - Add native Tilde plugin/connector, Routine, and signal clients. - - Replace Tilde's OpenBot-specific plugin aggregate with paginated native MCP, + - Replace Tilde's Dispatch-specific plugin aggregate with paginated native MCP, skill, provider, and registry reads typed by `@trytilde/api-client`. - Discover assignments from Tilde resources; no `agent_id[]` catalog query. - Keep pagination, secret-redaction, OAuth, managed-provider, binding, and webhook behavior shared across renderers. - Add focused native-resource, optimistic-version, complete pagination, trigger-progress, and custom-origin regressions. -- `@tryopenbot/platform-integrations` +- `@trytilde/dispatch-platform-integrations` - Remove the permanent API-key-plus-human-bearer delegation path. The Tilde platform now sends exactly one installation API key whose owning user is authorized by Tilde as a human or agent. - Keep the package README aligned with that single-credential contract; the retired machine-on-behalf terminology is no longer presented as supported. -- `@tryopenbot/agent-provider` +- `@trytilde/dispatch-agent-provider` - Stop provisioning a memory bank for every new agent. Memory remains opt-in on Tilde, and omission preserves any existing agent-owned bank. -- `@tryopenbot/web` +- `@trytilde/dispatch-web` - Proxy `/api/tilde` during development. - Stop supplying all agent IDs to plugin catalog loads. - Browser tests @@ -103,26 +103,26 @@ flowchart LR checked-in spec now also carries `ChatRequest.agent` and its canonical agent/avatar schemas, exposes only human/agent identities, and exactly matches Tilde `main`. - - Rebase on merged OpenBot #109 so the public `context.agent` SDK surface is + - Rebase on merged Dispatch #109 so the public `context.agent` SDK surface is baseline behavior rather than duplicated by this PR. - - Rebase on merged OpenBot #110; the facade collapse now targets the active + - Rebase on merged Dispatch #110; the facade collapse now targets the active web and Electron clients while the native client remains archived in #111. - Validate all 606 OpenAPI operations plus packaged SDK artifacts. Checks run on the final implementation head: -- `pnpm --filter @tryopenbot/control-service test` — 34 passed after removing +- `pnpm --filter @trytilde/dispatch-control-service test` — 34 passed after removing the duplicate provisioning-path tests. -- `pnpm --filter @tryopenbot/client-runtime test` — 94 passed. -- `pnpm --filter @tryopenbot/ui test` — 67 passed. +- `pnpm --filter @trytilde/dispatch-client-runtime test` — 94 passed. +- `pnpm --filter @trytilde/dispatch-ui test` — 67 passed. - `pnpm --filter @trytilde/sdk-vercel-ai-node test` — 86 passed. - `pnpm check` — passed; only existing repository warnings remain. - `pnpm build` — passed after merged #110 removed the paused native clients, including web, desktop, package, and CLI artifact verification. -- `TILDE_OPENAPI_PATH= pnpm openbot sdk refresh` — +- `TILDE_OPENAPI_PATH= pnpm tilde sdk refresh` — passed after #193 merged; generated spec exactly matches Tilde `main` and all five SDK package suites pass. -- `pnpm openbot sdk validate` — passed; 606 operations and all five SDK packages. +- `pnpm tilde sdk validate` — passed; 606 operations and all five SDK packages. - `CI=1 pnpm test:e2e` — 15 passed, 1 existing skip. - `git diff --check` — passed. @@ -133,7 +133,7 @@ yes This removes public pre-1.0 control-service APIs. A customized fork must: 1. Replace direct `/api/plugins`, `/api/connectors`, `/api/routines`, and - `/api/signals` calls with `@tryopenbot/client-runtime`. + `/api/signals` calls with `@trytilde/dispatch-client-runtime`. 2. Replace `registerConnectorRoutes` imports with `registerTildeProxy` and `registerConnectorAuthorizedRoute` when constructing a custom control app. 3. Route `/api/tilde/*` to control-service on any custom CDN, reverse proxy, or @@ -141,7 +141,7 @@ This removes public pre-1.0 control-service APIs. A customized fork must: 4. Re-run the control-service/client-runtime tests and browser settings, connector, routine, and signal flows against the fork's Tilde environment. -Deploy Tilde API #168, #193, #195, #196, and #197 before this OpenBot release. Signal deliveries now expose +Deploy Tilde API #168, #193, #195, #196, and #197 before this Dispatch release. Signal deliveries now expose `matched_trigger_ids`; Routine updates must preserve the complete trigger set and send the current `version` as `expected_version`. Agent creation now relies on the installation API key being recognized as an authorized agent actor; the diff --git a/docs/updates/11.md b/docs/updates/11.md index 6d367d22..8075eabb 100644 --- a/docs/updates/11.md +++ b/docs/updates/11.md @@ -1,8 +1,8 @@ -# OpenBot architecture rebuild and coding workflows +# Dispatch architecture rebuild and coding workflows ## Intent of the change -- Reset OpenBot from owner UX down. Remove legacy server/provider maze. +- Reset Dispatch from owner UX down. Remove legacy server/provider maze. - Keep provider contracts internal TypeScript. RPC only for real service boundaries. - Make fork own configuration, agents, tools, skills, secrets, and deployment choices. - Make dev, local production, and Vercel production use the same provider lifecycles. @@ -50,22 +50,22 @@ flowchart TD ## Summarized package changes -- `@openbot/agent-provider`: agent/session/message boundary; Tilde Harness SDK adapter; prompt/tool hooks. -- `@openbot/agent-service-provider`: discover Eve-shaped agents; instrumentation ordering; local server; parallel Vercel functions; registration inputs. -- `@openbot/computer-provider`: singular package; OCI image build/deploy; Microsandbox and Vercel implementations; shell, await, file, copy, glob, grep, screenshot tools. -- `@openbot/computer-service-proto`: internal lifecycle, execution, file, desktop, ports, VNC transport, background jobs, and await. -- `@openbot/configuration`: all seven roles mandatory; `RuntimeProviders` keeps deployment compilers out of agent bundles. -- `@openbot/control-service-proto`: intentionally empty owner contract. -- `@openbot/control-service-provider`: provider-owned Handlebars assets; local systemd/launchd; Vercel Build Output API. -- `@openbot/inference-model-provider`: explicit OpenAI API-key and OAuth constructors. -- `@openbot/runtime-provider`: optional `Buildable` and `Deployable`; secret classes; sandbox aggregation; runtime-last ordering. -- `@openbot/skills-provider`: core skill boundary and Tilde implementation. -- `@openbot/tools-provider`: Vercel AI SDK tools and Tilde implementation. -- `@openbot/utilities`: strict Handlebars file templates. -- `@openbot/cli`: SOPS identities, provider setup, agent scaffolding, dev supervisor, selective deployment, and safe sentinel removal. +- `@dispatch/agent-provider`: agent/session/message boundary; Tilde Harness SDK adapter; prompt/tool hooks. +- `@dispatch/agent-service-provider`: discover Eve-shaped agents; instrumentation ordering; local server; parallel Vercel functions; registration inputs. +- `@dispatch/computer-provider`: singular package; OCI image build/deploy; Microsandbox and Vercel implementations; shell, await, file, copy, glob, grep, screenshot tools. +- `@dispatch/computer-service-proto`: internal lifecycle, execution, file, desktop, ports, VNC transport, background jobs, and await. +- `@dispatch/configuration`: all seven roles mandatory; `RuntimeProviders` keeps deployment compilers out of agent bundles. +- `@dispatch/control-service-proto`: intentionally empty owner contract. +- `@dispatch/control-service-provider`: provider-owned Handlebars assets; local systemd/launchd; Vercel Build Output API. +- `@dispatch/inference-model-provider`: explicit OpenAI API-key and OAuth constructors. +- `@dispatch/runtime-provider`: optional `Buildable` and `Deployable`; secret classes; sandbox aggregation; runtime-last ordering. +- `@dispatch/skills-provider`: core skill boundary and Tilde implementation. +- `@dispatch/tools-provider`: Vercel AI SDK tools and Tilde implementation. +- `@dispatch/utilities`: strict Handlebars file templates. +- `@dispatch/cli`: SOPS identities, provider setup, agent scaffolding, dev supervisor, selective deployment, and safe sentinel removal. - Init refuses custom fork-owned `configuration/.gitignore`; stops before writing `.env`. - Removed legacy server, Box API, providers/provider-sdk, database/contracts, root Vercel files, setup code, and global configuration skills/sandbox. -- `.agents/skills/create-or-update-agent`: fixed Eve-compatible tree, Zod Computer tools, instrumentation, instructions, libraries, skills, workspace seed, and `openbot new-agent`. +- `.agents/skills/create-or-update-agent`: fixed Eve-compatible tree, Zod Computer tools, instrumentation, instructions, libraries, skills, workspace seed, and `tilde new-agent`. - `.agents/skills/implement-provider`: provider-local core contracts, Handlebars assets, optional build/deploy lifecycle, prompt/tool hooks, and adapter tests. - `.agents/skills/create-pr`: README/public API gate, provider core placement, configuration ownership, ADR review, PR-number update records, all-thread evidence review, and requested skip marker. - Other coding-agent skills use current package names, paths, contracts, and deployment commands. diff --git a/docs/updates/110.md b/docs/updates/110.md index 176380a9..6de27476 100644 --- a/docs/updates/110.md +++ b/docs/updates/110.md @@ -9,7 +9,7 @@ # Architecture changes - Delete `apps/mobile` renderer and native configuration. -- Delete `openbot mobile` CLI group: doctor, setup, Expo run, Android emulator, screenshots, logs, release. +- Delete `tilde mobile` CLI group: doctor, setup, Expo run, Android emulator, screenshots, logs, release. - Delete mobile remote-host transport: Metro, adb, emulator VNC, mobile task dispatch. - Keep remote Electron desktop task and tunnel. - Delete mobile publication workflow and EAS/App Store/Play Store machinery. @@ -29,14 +29,14 @@ flowchart LR # Summarized package changes - `apps/mobile`: removed complete Expo/React Native application, native auth adapter, ChatKit renderer, connector setup, Computer screen, BNA UI source, themes, navigation, onboarding, assets, app config, Metro config, and EAS config. -- `openbot` CLI: removed `mobile` commands, Android SDK/NDK discovery, platform doctor, emulator and Expo orchestration, mobile release, mobile workspace discovery, Metro/adb tunnels, and mobile remote tasks. `connect` and `remote` now serve Electron desktop only. -- `@tryopenbot/desktop`: removes mobile deep-link branches and keeps Electron-specific behavior. -- `@tryopenbot/client-runtime`: no wire/state behavior change. Documentation and presentation contracts stop claiming an active Expo consumer. -- `@tryopenbot/control-service` and `@tryopenbot/ui`: remove mobile OAuth-return wording and mobile-client discriminator branches. +- Tilde CLI: removed `mobile` commands, Android SDK/NDK discovery, platform doctor, emulator and Expo orchestration, mobile release, mobile workspace discovery, Metro/adb tunnels, and mobile remote tasks. `connect` and `remote` now serve Electron desktop only. +- `@trytilde/dispatch-desktop`: removes mobile deep-link branches and keeps Electron-specific behavior. +- `@trytilde/dispatch-client-runtime`: no wire/state behavior change. Documentation and presentation contracts stop claiming an active Expo consumer. +- `@trytilde/dispatch-control-service` and `@trytilde/dispatch-ui`: remove mobile OAuth-return wording and mobile-client discriminator branches. - Root workspace: removes mobile scripts and package, trims lockfile by roughly 4,100 lines, and removes mobile release workflow. - Repository guidance: removes Android/iOS/Expo prerequisites and commands from README, contributor guide, AGENTS, skills, provenance, and workflow ADRs. - Release: fixed pre-1.0 package group receives a minor Changeset because public CLI commands and a supported client disappear. -- Rebase: merged OpenBot #109 remains baseline SDK behavior; removing the native +- Rebase: merged Dispatch #109 remains baseline SDK behavior; removing the native renderer does not alter its server-side `context.agent` contract. Validation completed: @@ -58,7 +58,7 @@ Forks carrying mobile customizations must preserve them before updating. This up Fork action: 1. Create a preservation branch or tag before applying this update. Upstream reference is `codex/mobile-archive`. -2. Remove fork scripts that invoke `openbot mobile`, `dev:mobile*`, `release:mobile`, Metro, adb, emulator VNC, or `mobile-v*` releases. +2. Remove fork scripts that invoke `tilde mobile`, `dev:mobile*`, `release:mobile`, Metro, adb, emulator VNC, or `mobile-v*` releases. 3. Remove mobile-only fields from `configuration/dev-hosts.json`; Electron `desktopVncPort` remains supported. 4. Remove native secrets and EAS/store credentials from external secret managers when the fork no longer needs them. This PR contains and migrates no secret values. 5. Run frozen install, `pnpm check`, `pnpm build`, and Electron packaging after updating. diff --git a/docs/updates/112.md b/docs/updates/112.md index f6331a1d..0acb2685 100644 --- a/docs/updates/112.md +++ b/docs/updates/112.md @@ -1,6 +1,6 @@ # Intent of the change -Make the shared OpenBot web workspace usable at phone widths. Navigation must remain reachable without consuming the whole viewport, the prompt composer must stay inside safe areas, and mobile keyboards must be able to insert newlines without accidentally sending. +Make the shared Dispatch web workspace usable at phone widths. Navigation must remain reachable without consuming the whole viewport, the prompt composer must stay inside safe areas, and mobile keyboards must be able to insert newlines without accidentally sending. # Architecture changes @@ -19,11 +19,11 @@ flowchart LR # Summarized package changes -- `@tryopenbot/web`: add the narrow-screen navigation trigger and responsive workspace shell composition. -- `@tryopenbot/ui`: add the Shadcn/Radix Sheet primitive, responsive sidebar, touch-visible controls, safe-area and overflow styling, and mobile-aware composer keyboard behavior. -- `@tryopenbot/ui`: add focused composer coverage and a 390px Playwright regression for navigation and prompt composition. +- `@trytilde/dispatch-web`: add the narrow-screen navigation trigger and responsive workspace shell composition. +- `@trytilde/dispatch-ui`: add the Shadcn/Radix Sheet primitive, responsive sidebar, touch-visible controls, safe-area and overflow styling, and mobile-aware composer keyboard behavior. +- `@trytilde/dispatch-ui`: add focused composer coverage and a 390px Playwright regression for navigation and prompt composition. - Release metadata: add a fixed-group Changeset for the owner-visible responsive behavior. # Critical to apply to forks -no — forks receive the responsive behavior through the normal OpenBot package update. There is no configuration, state, credential, API, provider, dependency, or deployment migration. Customized workspace/sidebar/composer markup should be regression-tested at a 390px viewport after updating. +no — forks receive the responsive behavior through the normal Dispatch package update. There is no configuration, state, credential, API, provider, dependency, or deployment migration. Customized workspace/sidebar/composer markup should be regression-tested at a 390px viewport after updating. diff --git a/docs/updates/114.md b/docs/updates/114.md index 63cff171..6a526568 100644 --- a/docs/updates/114.md +++ b/docs/updates/114.md @@ -21,7 +21,7 @@ flowchart LR ``` - Client-runtime remains network and projection owner. -- UI remains presentation owner. It does not add a new OpenBot provider API. +- UI remains presentation owner. It does not add a new Dispatch provider API. - Native provider wins as setup surface. Managed connections merge into same provider entry. - Tilde data remains authority. Cache is ephemeral and cleared by mutations. - Routine provider cards and routine rows reuse existing signals/routines contracts and actions. @@ -29,19 +29,19 @@ flowchart LR # Summarized package changes -- `@tryopenbot/client-runtime` +- `@trytilde/dispatch-client-runtime` - Adds `TildePluginsTransport` with optional dynamic API origin. - Resolves relative server icon paths. - Coalesces native and managed records. - Adds short catalogue caching and mutation invalidation. - Adds regression coverage for duplicate providers, relative icons, and cache reuse. -- `@tryopenbot/ui` +- `@trytilde/dispatch-ui` - Adds `RoutineProvidersSettings` and `RoutineSettings` exports. - Renders responsive provider cards and searchable/filterable routine management. - Uses local fallback marks instead of arbitrary remote `default.svg` URLs. - Hides duplicate email account heading. - Tightens mobile composer geometry. -- `@tryopenbot/web` +- `@trytilde/dispatch-web` - Connects routine provider and routine management surfaces to shared runtime actions. - Uses the existing routine editor for create/edit/run/delete flows. - Tests diff --git a/docs/updates/115.md b/docs/updates/115.md index cc286985..39e0cb43 100644 --- a/docs/updates/115.md +++ b/docs/updates/115.md @@ -1,7 +1,7 @@ # Intent of the change - Record Codex, Claude Code, and Cursor prompts, responses, and tools in canonical Tilde ChatKit audit storage. -- Keep Tilde MCP server and managed-skill setup in the existing `openbot plugin` workflow. +- Keep Tilde MCP server and managed-skill setup in the existing `tilde plugin` workflow. - Publish small harness-specific wire adapters without rebuilding storage behavior three times. # Architecture changes @@ -12,14 +12,14 @@ flowchart LR Adapter --> Core["@trytilde/sdk coding-agent recorder"] Core --> Session["lookup-key ChatKit session + messages"] Core --> Tools["canonical tool executions"] - CLI["openbot plugin"] --> Native + CLI["tilde plugin"] --> Native CLI --> MCP["Tilde MCP configuration"] CLI --> Skills["managed skills"] ``` - `@trytilde/sdk` owns one normalized coding-agent event union and the ChatKit session/message/tool mapping. - Each new adapter package owns only its harness's hook payload normalization. -- `openbot plugin` stores non-secret API URL, team ID, and agent ID routing. It reuses the existing API-key environment or mode-0600 OAuth token store. +- `tilde plugin` stores non-secret API URL, team ID, and agent ID routing. It reuses the existing API-key environment or mode-0600 OAuth token store. - Codex receives a packaged plugin containing its hooks, a Tilde platform skill, and generated MCP declarations. Claude Code and Cursor receive their native user hook files. - API types are regenerated from trytilde/api#213. @@ -29,7 +29,7 @@ flowchart LR - `@trytilde/sdk-codex`: maps Codex hooks and ships the validated Codex plugin. - `@trytilde/sdk-claude-code`: maps Claude Code session, prompt, tool, failure, stop, and end hooks. - `@trytilde/sdk-cursor`: maps Cursor agent session, prompt, response, and generic tool hooks. -- `openbot`: discovers a visible ChatKit audit agent, installs hooks, persists non-secret routing, and exposes the fail-open hook subprocess command. +- `@trytilde/cli`: discovers a visible ChatKit audit agent, installs hooks, persists non-secret routing, and exposes the fail-open hook subprocess command. - SDK release scripts: validate, publish, pack, install, compile, and run all three new packages in a clean consumer. - End-to-end proof: the three adapters wrote three searchable messages in three canonical ChatKit sessions; repeated Codex hooks reused one session and its @@ -37,4 +37,4 @@ flowchart LR # Critical to apply to forks -yes — merge and deploy trytilde/api#213 before releasing or consuming these adapters. Forks using `openbot plugin` should rerun it for each desired harness so native hooks and the selected ChatKit audit agent are installed. Existing MCP and skill configuration remains compatible. No fork-owned `configuration/`, environment, secret, provider, web, Electron, or Expo migration is required. +yes — merge and deploy trytilde/api#213 before releasing or consuming these adapters. Forks using `tilde plugin` should rerun it for each desired harness so native hooks and the selected ChatKit audit agent are installed. Existing MCP and skill configuration remains compatible. No fork-owned `configuration/`, environment, secret, provider, web, Electron, or Expo migration is required. diff --git a/docs/updates/116.md b/docs/updates/116.md index 6f347f3b..2fe48c0a 100644 --- a/docs/updates/116.md +++ b/docs/updates/116.md @@ -2,23 +2,23 @@ - Finish coding-harness audit coverage. OpenCode and Gemini CLI now match Codex, Claude Code, and Cursor. -- Make one `openbot plugin` command install Tilde MCP servers, Tilde skills, and native ChatKit +- Make one `tilde plugin` command install Tilde MCP servers, Tilde skills, and native ChatKit audit emission for every supported harness. - Keep audit fail-open. Tilde outage must not stop coding work. - Fix native MCP config details found during completion: OpenCode global config path/schema; Gemini Streamable HTTP field. -- Restore Changesets status by removing release notes for removed `@tryopenbot/mobile` package. +- Restore Changesets status by removing release notes for removed `@trytilde/dispatch-mobile` package. # Architecture changes ```mermaid flowchart LR - O[OpenCode stable plugin hooks] --> C[openbot plugin audit] + O[OpenCode stable plugin hooks] --> C[tilde plugin audit] G[Gemini command hooks] --> C C --> A[Dedicated SDK normalizers] A --> S[@trytilde/sdk recorder] S --> K[Tilde ChatKit sessions, messages, tool executions] - P[openbot plugin setup] --> M[Native MCP config] + P[tilde plugin setup] --> M[Native MCP config] P --> L[Native skill directories] P --> O P --> G @@ -40,7 +40,7 @@ flowchart LR - `@trytilde/sdk`: add OpenCode and Gemini CLI to public coding-agent source union and display names. - `@trytilde/sdk-opencode`: add prompt, assistant-text, and tool lifecycle adapters; ship native plugin. - `@trytilde/sdk-gemini-cli`: add session, prompt, response, and terminal tool adapters. -- `openbot`: install and dispatch all five harness audit integrations; fix OpenCode and Gemini MCP +- `@trytilde/cli`: install and dispatch all five harness audit integrations; fix OpenCode and Gemini MCP documents; preserve Gemini settings while installing hooks. - SDK release tooling: build, validate, pack, install, type-check, and execute both new packages in the external-consumer smoke test. @@ -52,8 +52,8 @@ flowchart LR # Critical to apply to forks -yes — forks using OpenCode or Gemini CLI must rerun `openbot plugin --cli opencode` or -`openbot plugin --cli gemini` after updating. This installs native audit hooks and rewrites selected +yes — forks using OpenCode or Gemini CLI must rerun `tilde plugin --cli opencode` or +`tilde plugin --cli gemini` after updating. This installs native audit hooks and rewrites selected Tilde MCP servers using each harness's valid current schema. Forks importing SDKs directly may adopt `@trytilde/sdk-opencode` or `@trytilde/sdk-gemini-cli`; existing Codex, Claude Code, Cursor, and Vercel AI SDK integrations do not require code changes. No environment variable, secret, database, diff --git a/docs/updates/117.md b/docs/updates/117.md index bc88b224..23c983a4 100644 --- a/docs/updates/117.md +++ b/docs/updates/117.md @@ -8,7 +8,7 @@ Make clean repeat deploy switch to exact requested branch safely. Keep dirty tra ```mermaid flowchart LR - CLI[openbot deploy] --> Git[Push named Code Storage branch] + CLI[tilde deploy] --> Git[Push named Code Storage branch] Git --> Fetch[Fetch explicit branch ref] Fetch --> Exists{Local branch exists?} Exists -->|yes| Switch[Switch then fast-forward only] @@ -22,19 +22,19 @@ Provider boundary unchanged. `ExeDevRuntimeServiceProvider` still owns VM source # Summarized package changes -- `@tryopenbot/agent-service-provider` +- `@trytilde/dispatch-agent-service-provider` - Ignore untracked runtime files when deciding whether tracked source is dirty. - Fetch requested Code Storage branch with explicit local remote ref. - Switch existing requested branch before fast-forward. - Create missing branch at fetched ref with no upstream tracking dependency. - Test rendered reconcile script contains every safe branch step. - Changesets - - Patch fixed OpenBot package group. + - Patch fixed Dispatch package group. -Validation: provider 19 tests pass; provider build passes; full `pnpm check` and `pnpm build` pass. Real our-openbot deployment converged and public health, SPA, unsigned-agent rejection, and systemd service passed. +Validation: provider 19 tests pass; provider build passes; full `pnpm check` and `pnpm build` pass. Real our-dispatch deployment converged and public health, SPA, unsigned-agent rejection, and systemd service passed. # Critical to apply to forks yes -Forks using exe.dev must merge this before deploying a different named source branch to an existing VM checkout. No configuration, secret, state, dependency, or manual VM migration is required. Rerun ordinary `openbot deploy --yes`; the provider converges the clean checkout. If tracked VM edits exist, commit or intentionally remove them first because deploy continues preserving them. +Forks using exe.dev must merge this before deploying a different named source branch to an existing VM checkout. No configuration, secret, state, dependency, or manual VM migration is required. Rerun ordinary `tilde deploy --yes`; the provider converges the clean checkout. If tracked VM edits exist, commit or intentionally remove them first because deploy continues preserving them. diff --git a/docs/updates/118.md b/docs/updates/118.md index 3c7c8291..07b0c7b8 100644 --- a/docs/updates/118.md +++ b/docs/updates/118.md @@ -23,9 +23,9 @@ flowchart LR # Summarized package changes -- `@tryopenbot/client-runtime`: add participant identity/event contracts; hydrate and reconcile per-session participant activity; filter old `tilde.chatkit.participant` messages; add focused snapshot, realtime, and filtering tests. -- `@tryopenbot/web`: merge participant activity with message chronology and render simple joined/left rows. -- `@tryopenbot/ui`: add shared styling for quiet participant activity. +- `@trytilde/dispatch-client-runtime`: add participant identity/event contracts; hydrate and reconcile per-session participant activity; filter old `tilde.chatkit.participant` messages; add focused snapshot, realtime, and filtering tests. +- `@trytilde/dispatch-web`: merge participant activity with message chronology and render simple joined/left rows. +- `@trytilde/dispatch-ui`: add shared styling for quiet participant activity. - `@trytilde/api-client` and `@trytilde/sdk`: regenerate from merged Tilde API, including participant activity, personal Memory source bindings, and Wiki grep. - Docs: amend ADR-0014 and client-runtime README. Add two Changesets. - Validation: frozen install; SDK refresh builds/tests; Client Runtime 96 tests; web 3 tests; repository check/build; browser e2e 16 passed and 1 skipped. diff --git a/docs/updates/119.md b/docs/updates/119.md index 420b538a..5f9ce401 100644 --- a/docs/updates/119.md +++ b/docs/updates/119.md @@ -2,7 +2,7 @@ ## Intent of the change -Desktop release workflow install Vite+. Later workflow steps call `pnpm` anyway. Fresh runner may not have that command. Build, publish, or final manifest can stop before OpenBot release command runs. +Desktop release workflow install Vite+. Later workflow steps call `pnpm` anyway. Fresh runner may not have that command. Build, publish, or final manifest can stop before Dispatch release command runs. Change three workflow commands. Call root `release:desktop` task through `vp run`. Keep command arguments, release safety checks, signing secrets, AWS role, artifact paths, and manual dispatch unchanged. @@ -15,7 +15,7 @@ flowchart LR D["Manual release dispatch"] --> P["Vite+ setup and install"] P --> M["Linux x64 / macOS arm64 matrix"] M --> R["vp run release:desktop"] - R --> C["OpenBot desktop release CLI"] + R --> C["Dispatch desktop release CLI"] C --> A["Signed or unsigned artifacts"] A --> V["version.json"] ``` @@ -27,7 +27,7 @@ Before, the matrix crossed from Vite+ setup to a separate command executable. Af - Repository workflow: run desktop build through `vp run release:desktop`. - Repository workflow: run artifact publication through the same task. - Repository workflow: run `version.json` publication through the same task. -- OpenBot CLI: no source change. +- Tilde CLI: no source change. - Desktop package: no source, version, artifact, signing, or update-feed change. - Web and owner clients: no change. - Dependencies and contributor prerequisites: no change. @@ -39,4 +39,4 @@ Validation covers workflow YAML parsing and formatting, all CLI tests, the full yes -Forks using the inherited desktop release workflow should merge this update. No configuration or secret migration is needed. Keep any fork-owned bucket and AWS role variables. After updating, manually dispatch a dry-run desktop release and confirm the selected Linux x64 or macOS arm64 job reaches the OpenBot release command. +Forks using the inherited desktop release workflow should merge this update. No configuration or secret migration is needed. Keep any fork-owned bucket and AWS role variables. After updating, manually dispatch a dry-run desktop release and confirm the selected Linux x64 or macOS arm64 job reaches the Dispatch release command. diff --git a/docs/updates/120.md b/docs/updates/120.md index f046de19..e5c28c7e 100644 --- a/docs/updates/120.md +++ b/docs/updates/120.md @@ -1,7 +1,7 @@ # Intent of the change -- Make durable memory an owner-selectable part of ordinary OpenBot conversations - while keeping both OpenBot and the reusable Tilde SDK default-off. +- Make durable memory an owner-selectable part of ordinary Dispatch conversations + while keeping both Dispatch and the reusable Tilde SDK default-off. - Give opted-in ordinary bots a bounded, provenance-bearing recall projection before inference and provision an owned bank only for `personal_plus_agent`. - Deploy Memory Catcher as an ordinary user-owned background agent with a @@ -14,7 +14,7 @@ # Architecture changes - Tilde remains the authorization, storage, queue, embedding, retrieval, and - synthesis-session authority. OpenBot does not accept a model-supplied bank, + synthesis-session authority. Dispatch does not accept a model-supplied bank, organization, team, or user identifier during automatic recall or synthesis. - The Agent Provider reconciles the installation or per-agent selected memory mode. Only `personal_plus_agent` provisions a bot-owned bank. Memory Catcher @@ -55,14 +55,14 @@ flowchart LR - `@trytilde/sdk-vercel-ai-node`: add the automatic-memory projection controller, request-bound lease-fenced synthesis tools, idempotent background forget, and a strict synthesis tool allowlist. -- `@tryopenbot/agent-provider`: reconcile agent-owned banks and automatic-memory +- `@trytilde/dispatch-agent-provider`: reconcile agent-owned banks and automatic-memory modes from durable fork settings, default off, without giving Memory Catcher recursive memory. -- `openbot`: scaffold Memory Catcher, its managed synthesis skills, required +- `@trytilde/cli`: scaffold Memory Catcher, its managed synthesis skills, required discoverable source files, selected-provider inference adapter, deterministic dependency-first deployment when memory is enabled, and automatic recall in future Factory templates. -- Documentation: record the opt-in SDK/default OpenBot policy in ADR-0034 and +- Documentation: record the opt-in SDK/default Dispatch policy in ADR-0034 and document the SDK, provider, agent, security, and caching behavior. - Validation at the final API #235 contract: 95 core SDK tests, 125 Vercel adapter tests, 15 Agent Provider tests, 19 Agent Service Provider tests, 175 @@ -82,7 +82,7 @@ the changed future-agent template. A customized fork must keep its authored agent edits, add Memory Catcher with its two synthesis skills and restricted tool surface, reconcile it before ordinary bots, and deploy ordinary bots with their intended automatic-memory mode. Persist -`OPENBOT_AUTOMATIC_MEMORY_MODE` (default `none`) or a per-agent +`DISPATCH_AUTOMATIC_MEMORY_MODE` (default `none`) or a per-agent `AGENT__AUTOMATIC_MEMORY_MODE` override in fork environment configuration. Its mutation calls must pass the exact batch, complete evidence set, and lease owner from the current job. No new secret is introduced. Existing fork-owned agents diff --git a/docs/updates/121.md b/docs/updates/121.md index 4e3585a5..e8a99f3e 100644 --- a/docs/updates/121.md +++ b/docs/updates/121.md @@ -9,7 +9,7 @@ Yes or No action. Free-text confirmation is never interpreted as approval. The Tilde API remains authoritative for proposal state, the linked Human Approval, durable execution, receipts, provider setup continuation, and rollback. -OpenBot adds a propose-only agent tool, a stable SDK projection, an +Dispatch adds a propose-only agent tool, a stable SDK projection, an owner-authenticated same-origin decision proxy, and a shared conversation card. ```mermaid @@ -17,7 +17,7 @@ flowchart LR Agent["authored agent"] -->|propose only| Tilde["Tilde durable proposal"] Tilde --> Card["inline Yes / No card"] Owner["authenticated owner"] --> Card - Card -->|exact id + hash + generation| Proxy["OpenBot owner proxy"] + Card -->|exact id + hash + generation| Proxy["Dispatch owner proxy"] Proxy --> Tilde Tilde -->|durable decision and execution| Agent ``` @@ -31,12 +31,12 @@ server-authored. - `@trytilde/sdk` adds `SelfExtensionClient` and camel-case proposal, preview, approval, resource, and provider-continuation types. -- `@tryopenbot/client-runtime` validates supported proposal-tool output and +- `@trytilde/dispatch-client-runtime` validates supported proposal-tool output and strips fields outside its tokenless projection, requires the nested approval to bind the same proposal identifier, submits the exact decision binding, and reloads durable status so a completed card cannot become pending again after navigation or restart. -- `@tryopenbot/ui` renders the proposal impact and Yes/No decision as a distinct +- `@trytilde/dispatch-ui` renders the proposal impact and Yes/No decision as a distinct conversation block rather than a collapsed tool row. - The browser and Electron renderer resume the conversation only after the authenticated decision succeeds, with generic errors that do not expose diff --git a/docs/updates/122.md b/docs/updates/122.md index fb413cdd..c169c1ff 100644 --- a/docs/updates/122.md +++ b/docs/updates/122.md @@ -9,7 +9,7 @@ credential capability in model-visible data or portable configuration. # Architecture changes Tilde remains the authority for room membership, invitations, roles, event -audiences, verified speakers, and delegated personal-tool capabilities. OpenBot +audiences, verified speakers, and delegated personal-tool capabilities. Dispatch adds stable SDK wrappers, a dormant Client Runtime contract, an exact same-origin allowlist, and request-scoped private MCP header forwarding. @@ -33,16 +33,16 @@ dormant framework-neutral contract; Expo remains paused on main. - `@trytilde/sdk` adds `ChatKitRoomsClient`, room/participant/invitation types, create/roster/add/leave/invite/decide/revoke operations, and bounded deterministic group-turn orchestration. -- `@tryopenbot/client-runtime` adds strict room schemas and same-origin methods +- `@trytilde/dispatch-client-runtime` adds strict room schemas and same-origin methods for roster, invitations, decisions, revocation, and departure. -- `@tryopenbot/control-service` allows only the room paths and HTTP methods +- `@trytilde/dispatch-control-service` allows only the room paths and HTTP methods consumed by Client Runtime. -- `@tryopenbot/agent-provider` reconciles the default-off - `OPENBOT_PERSONAL_TOOL_FEDERATION_MODE` into each agent MCP server. +- `@trytilde/dispatch-agent-provider` reconciles the default-off + `DISPATCH_PERSONAL_TOOL_FEDERATION_MODE` into each agent MCP server. - `@trytilde/sdk-vercel-ai-node` privately forwards a verified delegated speaker capability with fresh nonce/protocol-session bindings and strips the delivery header before application code runs. -- `openbot` future-agent templates construct every managed MCP connection from +- `@trytilde/cli` future-agent templates construct every managed MCP connection from `context.mcp.connect(...)`, so the verified request capability reaches the default `agentLoop` path rather than only tool-mode endpoints. - Generated Tilde clients come from merged API #227's exact OpenAPI document. @@ -54,7 +54,7 @@ dormant framework-neutral contract; Expo remains paused on main. yes Forks that want personal tool federation must explicitly set -`OPENBOT_PERSONAL_TOOL_FEDERATION_MODE` to `selected` or `all`; leaving it unset +`DISPATCH_PERSONAL_TOOL_FEDERATION_MODE` to `selected` or `all`; leaving it unset preserves `none`. They must keep signed ChatKit endpoint handling in front of request-scoped MCP construction so the delegated capability remains private and is stripped before agent/application code runs. Forks exposing room APIs diff --git a/docs/updates/123.md b/docs/updates/123.md index d370efb8..0b7bbd72 100644 --- a/docs/updates/123.md +++ b/docs/updates/123.md @@ -1,6 +1,6 @@ # Intent of the change -Give hosted OpenBot inference safe, exact billing without coupling billing to +Give hosted Dispatch inference safe, exact billing without coupling billing to provider initialization. Agents reserve organization AI credits before every managed model call, persist invocation intent and Gateway generation identity through the AgentRun effect ledger, then commit the authoritative receipt or @@ -24,7 +24,7 @@ flowchart LR Flag --> Agent ``` -Tilde remains the billing and authorization boundary. OpenBot stores no billing +Tilde remains the billing and authorization boundary. Dispatch stores no billing ledger or receipt Control State. Inference providers only reconcile one non-secret environment marker and contribute fork-owned template source. They do not gain request-time model factories or billing methods. Request-time @@ -40,8 +40,8 @@ ADR 0004 is amended to preserve that split explicitly. context types, exact receipt commit input, client composition, focused request mapping tests, and Public API documentation. AgentRun effect prepare/finish now send the API-required generation, worker ID, and planned/terminal status. -- `@tryopenbot/inference-provider`: writes - `OPENBOT_HOSTED_INFERENCE_BILLING=1` only for managed Vercel project OIDC, +- `@trytilde/dispatch-inference-provider`: writes + `DISPATCH_HOSTED_INFERENCE_BILLING=1` only for managed Vercel project OIDC, resets it to `0` for direct-key Vercel and Codex subscription inference, accepts optional per-call model IDs in provider-owned templates, and covers the selection rules with provider tests. @@ -50,13 +50,13 @@ ADR 0004 is amended to preserve that split explicitly. settles exact receipts, releases BYOK/provider-failed reservations, and refuses provider replay for planned, uncertain, or committed effects. Every Gateway call reserves first; an authoritative BYOK receipt releases it. -- `openbot`: wires the controller into the generated agent webhook, returns a +- `@trytilde/cli`: wires the controller into the generated agent webhook, returns a clear 402 for exhausted credits, keeps reconciliation fail-closed, reports authoritative hosted cost to AgentRuns, and closes MCP resources on every preflight, stream, abort, and synchronous failure path. A reconciled or uncertain provider call without a recoverable response marks the current run failed, so a later owner request starts a new run explicitly. -- `@tryopenbot/platform-integrations`: forwards the non-secret hosted billing +- `@trytilde/dispatch-platform-integrations`: forwards the non-secret hosted billing marker through the narrow Tilde Cloud runtime allowlist while continuing to exclude Vercel tokens and other control-plane secrets. - `.changeset/add-hosted-inference-metering.md`: requests minor releases for @@ -66,8 +66,8 @@ ADR 0004 is amended to preserve that split explicitly. # Critical to apply to forks -yes — rerun `openbot init` after merging so the selected inference provider -reconciles `OPENBOT_HOSTED_INFERENCE_BILLING` in fork-owned configuration. +yes — rerun `tilde init` after merging so the selected inference provider +reconciles `DISPATCH_HOSTED_INFERENCE_BILLING` in fork-owned configuration. Tilde Cloud hosted releases forward that marker automatically; customized release adapters must preserve it without broadening their secret allowlists. Customized inference templates should adopt the optional third `modelId` diff --git a/docs/updates/124.md b/docs/updates/124.md index b4ffe6f2..d58e2af4 100644 --- a/docs/updates/124.md +++ b/docs/updates/124.md @@ -22,7 +22,7 @@ execute, claim outputs, roll back, or collect credentials through this tool. # Summarized package changes -- `openbot` imports and registers `propose_self_extension` in the default agent +- `@trytilde/cli` imports and registers `propose_self_extension` in the default agent template under its exact wire name. - Scaffold tests prove rendered agents contain the import and registration, and that the rendered tool calls `client.selfExtension.propose` with the diff --git a/docs/updates/125.md b/docs/updates/125.md index e4af8aef..3f7dacfc 100644 --- a/docs/updates/125.md +++ b/docs/updates/125.md @@ -2,9 +2,9 @@ ## Intent of the change -OpenBot agents could answer one request and run a bounded in-memory tool loop, but substantial work had no cohesive durable product. Goals and tasks were not available through the public SDK or default tools, delegated children lacked a complete owner surface, long conversations had no agent-owned compaction checkpoint, and model continuation could not survive an invocation boundary safely. +Dispatch agents could answer one request and run a bounded in-memory tool loop, but substantial work had no cohesive durable product. Goals and tasks were not available through the public SDK or default tools, delegated children lacked a complete owner surface, long conversations had no agent-owned compaction checkpoint, and model continuation could not survive an invocation boundary safely. -Add one end-to-end durable-work slice. Keep Tilde authoritative for persisted work and OpenBot authoritative for authored model behavior, tools, host policy, and presentation. +Add one end-to-end durable-work slice. Keep Tilde authoritative for persisted work and Dispatch authoritative for authored model behavior, tools, host policy, and presentation. ## Architecture changes @@ -13,7 +13,7 @@ flowchart LR U["Owner in web or Electron"] --> R["Client Runtime Work state"] R --> T["Signed same-origin ChatKit bridge"] T --> D["Tilde goals, tasks, jobs, runs, routines"] - D --> H["OpenBot authored agent host"] + D --> H["Dispatch authored agent host"] H --> C["Agent-owned compaction"] H --> M["Model and tool execution"] M --> D @@ -24,8 +24,8 @@ Four accepted boundaries now ship together: - ADR-0032 binds goals, tasks, and background jobs to one agent and ChatKit session. - ADR-0033 keeps model-context compaction in authored agent code while Tilde stores lifecycle evidence and the canonical transcript. -- ADR-0034 gives Tilde durable child-job state while OpenBot owns delegation policy and provider execution. -- ADR-0035 gives Tilde runs, leases, accounting, and effect receipts while OpenBot owns continuation and loop policy. +- ADR-0034 gives Tilde durable child-job state while Dispatch owns delegation policy and provider execution. +- ADR-0035 gives Tilde runs, leases, accounting, and effect receipts while Dispatch owns continuation and loop policy. Client Runtime owns the remote Work snapshot and polling lifecycle. The shared UI package renders it for the web application and packaged Electron client. Renderer-local duplicated network state was deliberately removed during extraction. @@ -33,13 +33,13 @@ The runtime consumes only signed server-authored `tildeAgentRun` and `tildeAgent ## Summarized package changes -- `openbot`: scaffold goal, task, child-job, and routine tools; wire durable runs, trusted job context, and context compaction into generated agents. +- `@trytilde/cli`: scaffold goal, task, child-job, and routine tools; wire durable runs, trusted job context, and context compaction into generated agents. - `@trytilde/sdk`: add typed work, job, routine, run, effect-receipt, and compaction clients. - `@trytilde/sdk-vercel-ai-node`: add the durable run controller, uncertain-effect guard, compaction controller, composed `prepareStep`, and compacted-history session support. -- `@tryopenbot/inference-provider`: allow an explicitly selected child-job model while preserving configured defaults. -- `@tryopenbot/client-runtime`: validate and own Work snapshots, polling, and job-control actions. -- `@tryopenbot/ui`: add the tested Work overview and background-job detail/control surface. -- `@tryopenbot/web`: replace the routines-only details route with the combined Work pane. +- `@trytilde/dispatch-inference-provider`: allow an explicitly selected child-job model while preserving configured defaults. +- `@trytilde/dispatch-client-runtime`: validate and own Work snapshots, polling, and job-control actions. +- `@trytilde/dispatch-ui`: add the tested Work overview and background-job detail/control surface. +- `@trytilde/dispatch-web`: replace the routines-only details route with the combined Work pane. - Generated API client: refresh from the merged Tilde contract through API #229 and validate 663 operations. - Documentation: add ADRs 0032-0035, update ADR-0011, product language, agent guidance, and affected package READMEs. - Release notes: add five focused Changesets for the independently published surfaces. @@ -50,7 +50,7 @@ Validation passed for core SDK (86 tests), Vercel AI adapter (106), Client Runti yes -Forks with customized agents must port the new generated-agent tools and runtime wiring manually; OpenBot never overwrites existing fork-owned agent files. Regenerate or reconcile from the updated future-agent template, preserve the fixed agent ID and session binding, and deploy API #229 or later before the OpenBot update so signed child model/budget metadata is available. +Forks with customized agents must port the new generated-agent tools and runtime wiring manually; Dispatch never overwrites existing fork-owned agent files. Regenerate or reconcile from the updated future-agent template, preserve the fixed agent ID and session binding, and deploy API #229 or later before the Dispatch update so signed child model/budget metadata is available. No database, secret, credential, environment-name, or state-import migration is required. The new optional environment values have safe defaults for run duration/steps, context-window size, and model cost rates. A cost-capped child job fails closed when pricing is unavailable. diff --git a/docs/updates/128.md b/docs/updates/128.md index 39536f20..743ee78a 100644 --- a/docs/updates/128.md +++ b/docs/updates/128.md @@ -1,19 +1,19 @@ # Intent of the change -Prevent OpenBot metadata from becoming an internal Tilde/OpenBot control protocol. Provider-specific extensions remain available, while internal execution, identity, routing, lifecycle, memory, and presentation fields must use typed contracts. +Prevent Dispatch metadata from becoming an internal Tilde/Dispatch control protocol. Provider-specific extensions remain available, while internal execution, identity, routing, lifecycle, memory, and presentation fields must use typed contracts. # Architecture changes ```mermaid flowchart LR API[Typed Tilde OpenAPI] --> SDK[Generated client and stable SDK] - SDK --> Runtime[OpenBot runtime] + SDK --> Runtime[Dispatch runtime] Provider[Provider payload] --> Adapter[Provider adapter] Adapter -->|provider-only remainder| Metadata[Provider metadata] Adapter --> Runtime ``` -ADR 0038 aligns OpenBot with Tilde API ADR 0022. `AGENTS.md` and the PR, pre-commit, API exposure, SDK wrapper, and provider implementation skills now block magic metadata protocols. The audit identifies current template, Signal, UI, credential, and provider catalogue debt. +ADR 0038 aligns Dispatch with Tilde API ADR 0022. `AGENTS.md` and the PR, pre-commit, API exposure, SDK wrapper, and provider implementation skills now block magic metadata protocols. The audit identifies current template, Signal, UI, credential, and provider catalogue debt. # Summarized package changes diff --git a/docs/updates/129.md b/docs/updates/129.md index b77b0f06..a9980406 100644 --- a/docs/updates/129.md +++ b/docs/updates/129.md @@ -59,7 +59,7 @@ receipts are also bound to that fresh lease. - `@trytilde/sdk`: add the hand-authored `MemorySynthesisSessionClient.validateBatch` wrapper for Tilde's exact batch/lease/evidence validation endpoint. -- `openbot`: compose the helper in the materialized Memory Catcher endpoint; +- `@trytilde/cli`: compose the helper in the materialized Memory Catcher endpoint; reserve all managed Gateway calls, release authoritative BYOK receipts, commit authoritative system/fallback receipts, pause on insufficient credits, and fail closed for unsafe reconciliation. Factory now supplies a semantic @@ -91,7 +91,7 @@ authored endpoint: project OIDC enables hosted billing; direct owner Gateway keys and Codex subscription inference remain outside Tilde metering. - Do not copy credentials or fork configuration from upstream. Existing - `OPENBOT_HOSTED_INFERENCE_BILLING` and reserve-size environment behavior is + `DISPATCH_HOSTED_INFERENCE_BILLING` and reserve-size environment behavior is reused; no new environment name or secret is introduced. After adapting materialized templates, run the SDK hosted-billing and synthesis diff --git a/docs/updates/130.md b/docs/updates/130.md index 23fe5e72..cef88ac6 100644 --- a/docs/updates/130.md +++ b/docs/updates/130.md @@ -19,7 +19,7 @@ ADR 0038 governs the boundary. The SDK validates the discriminated `agent_run` a # Summarized package changes - `@trytilde/sdk-vercel-ai-node`: adds typed execution contracts, validation, endpoint context, and request timestamps. -- `openbot`: consumes `context.execution` and typed message timestamps in the generated Factory agent. +- `@trytilde/cli`: consumes `context.execution` and typed message timestamps in the generated Factory agent. - Focused parser tests cover valid delegated-job state, absence from message metadata, and invalid generations. # Critical to apply to forks diff --git a/docs/updates/131.md b/docs/updates/131.md index 05a1fd25..2e3ced12 100644 --- a/docs/updates/131.md +++ b/docs/updates/131.md @@ -1,10 +1,10 @@ # Intent of the change -Update canonical repository identities after GitHub renamed `trytilde/openbot` to `trytilde/dispatch` and its maintained fork to `trytilde/our-dispatch`. +Update canonical repository identities after GitHub renamed `trytilde/dispatch` to `trytilde/dispatch` and its maintained fork to `trytilde/our-dispatch`. # Architecture changes -Repository bootstrap, upstream/publication guards, package metadata, contribution guidance, and development setup now resolve `trytilde/dispatch`. Public fork examples resolve `trytilde/our-dispatch`. Package names, CLI commands, application identifiers, and the separately managed `openbot-computer` image repository do not change. +Repository bootstrap, upstream/publication guards, package metadata, contribution guidance, and development setup now resolve `trytilde/dispatch`. Public fork examples resolve `trytilde/our-dispatch`. Package names, CLI commands, application identifiers, and the separately managed `dispatch-computer` image repository do not change. # Summarized package changes @@ -15,4 +15,4 @@ Repository bootstrap, upstream/publication guards, package metadata, contributio # Critical to apply to forks -yes — update existing fork remotes from `trytilde/openbot` to `trytilde/dispatch`. GitHub redirects old URLs, but publication guards and future bootstrap operations use the new canonical identity. +yes — update existing fork remotes from `trytilde/dispatch` to `trytilde/dispatch`. GitHub redirects old URLs, but publication guards and future bootstrap operations use the new canonical identity. diff --git a/docs/updates/138.md b/docs/updates/138.md index 0540ad35..25ea55b3 100644 --- a/docs/updates/138.md +++ b/docs/updates/138.md @@ -18,8 +18,8 @@ flowchart LR # Summarized package changes -- `openbot` scaffold: generate Memory Catcher with `responseMode: "agentLoop"`. -- `openbot` tests: assert the background mode and forbid conversational tool +- `@trytilde/cli` scaffold: generate Memory Catcher with `responseMode: "agentLoop"`. +- `@trytilde/cli` tests: assert the background mode and forbid conversational tool mode in the generated catcher. # Critical to apply to forks diff --git a/docs/updates/139.md b/docs/updates/139.md index fe052b5c..431c43ab 100644 --- a/docs/updates/139.md +++ b/docs/updates/139.md @@ -17,7 +17,7 @@ flowchart LR # Summarized package changes -- `openbot` Memory Catcher scaffold: log safe inference stream diagnostics. +- `@trytilde/cli` Memory Catcher scaffold: log safe inference stream diagnostics. # Critical to apply to forks diff --git a/docs/updates/140.md b/docs/updates/140.md index 6aae810f..6e76713d 100644 --- a/docs/updates/140.md +++ b/docs/updates/140.md @@ -18,8 +18,8 @@ flowchart LR # Summarized package changes -- `openbot` scaffold: filter system history before Memory Catcher inference. -- `openbot` tests: require the filter in generated agents. +- `@trytilde/cli` scaffold: filter system history before Memory Catcher inference. +- `@trytilde/cli` tests: require the filter in generated agents. # Critical to apply to forks diff --git a/docs/updates/142.md b/docs/updates/142.md index 075478dd..126da95c 100644 --- a/docs/updates/142.md +++ b/docs/updates/142.md @@ -18,8 +18,8 @@ flowchart LR # Summarized package changes -- `openbot` scaffold: remove full synthesis-session history from model context. -- `openbot` tests: require current-batch-only input. +- `@trytilde/cli` scaffold: remove full synthesis-session history from model context. +- `@trytilde/cli` tests: require current-batch-only input. # Critical to apply to forks diff --git a/docs/updates/144.md b/docs/updates/144.md index a6ee59ab..a8e11c93 100644 --- a/docs/updates/144.md +++ b/docs/updates/144.md @@ -29,23 +29,23 @@ No public HTTP, ConnectRPC, OpenAPI, protobuf, client, or metadata contract chan # Summarized package changes -- `@tryopenbot/git-provider` +- `@trytilde/dispatch-git-provider` - sanitizes legacy credential-bearing Code Storage remotes; - configures a Code Storage-host-scoped helper that reads `CODE_STORAGE_REPOSITORY_TOKEN` at execution time; - passes token through child environment for lifecycle push instead of command arguments or remote URL; - strips credentials before preserving an old origin as `upstream`; - adds regressions proving neither current nor legacy JWT enters Git arguments. -- `@tryopenbot/agent-service-provider` +- `@trytilde/dispatch-agent-service-provider` - renders a clean exe.dev source URL; - loads only the repository JWT needed for initial reconciliation from the private environment file; - authenticates initial clone/fetch with a transient reconciliation copy, then unsets that copy; - installs the non-secret host-scoped helper for later supervised background reconciliation. -- `@tryopenbot/computer-service-provider` +- `@trytilde/dispatch-computer-service-provider` - uses the same clean remote and helper boundary when preparing the trusted development checkout. - Documentation - updates provider guidance and the Git Provider package README; - amends ADR 0020 and ADR 0032 with the credential-lifetime decision; - - adds a patch changeset for the fixed OpenBot package group. + - adds a patch changeset for the fixed Dispatch package group. Proof completed on rebased PR head: diff --git a/docs/updates/145.md b/docs/updates/145.md index 106f5050..4b525947 100644 --- a/docs/updates/145.md +++ b/docs/updates/145.md @@ -20,13 +20,13 @@ Architecture does not otherwise change. Remote remains credential-free. Token re # Summarized package changes -- `@tryopenbot/agent-service-provider` +- `@trytilde/dispatch-agent-service-provider` - derives helper host from `source_url` using shell parameter expansion; - validates derived host is non-empty; - removes the undeclared `CODE_STORAGE_ORGANIZATION` read; - adds a rendered-script regression for both facts. - Release - - adds patch changeset for fixed OpenBot package group. + - adds patch changeset for fixed Dispatch package group. Proof: diff --git a/docs/updates/146.md b/docs/updates/146.md index 3b872597..5c2e1fb5 100644 --- a/docs/updates/146.md +++ b/docs/updates/146.md @@ -23,7 +23,7 @@ No public API, metadata, secret, configuration, database, dependency, client, or # Summarized package changes -- `@tryopenbot/agent-provider` +- `@trytilde/dispatch-agent-provider` - recognizes exact `memory bindings are still synchronizing` message after trimming and case normalization; - continues polling within existing 1,200-attempt, 500-millisecond interval; - keeps unknown, empty, and permanent errors on immediate failure path; @@ -32,7 +32,7 @@ No public API, metadata, secret, configuration, database, dependency, client, or - full provisioning regression begins with retryable `ERROR`, observes poll to `ACTIVE`, then completes credential and resource workflow; - existing permanent-error regression remains green. - Release - - patch changeset added for fixed OpenBot package group. + - patch changeset added for fixed Dispatch package group. Proof: all 15 Agent Provider tests and focused package check passed. Diff check and configuration-ownership guard passed. diff --git a/docs/updates/150.md b/docs/updates/150.md new file mode 100644 index 00000000..575e3838 --- /dev/null +++ b/docs/updates/150.md @@ -0,0 +1,116 @@ +# PR 150: Establish Dispatch product identity + +## Intent of the change + +- Dispatch name everywhere. One product identity. +- `trytilde/dispatch` canonical repository. No stale repository owner/name. +- `@trytilde/dispatch-*` application packages. Tilde SDK packages stay `@trytilde/sdk*`. +- `@trytilde/cli` package, `tilde` executable. No product-named CLI. +- Breaking namespace cutover. No silent compatibility aliases. +- Current `main` preserved. No replay of already-merged stale feature work. + +The original dirty checkout predated 78 commits already merged to `main`. Its complete state remains +recoverable in a named local stash. The final branch starts at current `origin/main` and reapplies +only the approved identity migration, so newer memory, work, room, capability, coding-agent, and +exe.dev behavior stays intact. + +## Architecture changes + +Dispatch remains the owner application. Tilde remains the platform, public SDK namespace, and +unified command surface. Repository bootstrap, package publication, generated contracts, desktop +identity, provider assets, runtime paths, persisted client keys, UI tokens, and documentation now +agree on that split. + +```mermaid +flowchart LR + R["trytilde/dispatch"] --> P["@trytilde/dispatch-* packages"] + R --> C["@trytilde/cli"] + C -->|"tilde commands"| D["Dispatch lifecycle"] + S["@trytilde/sdk* packages"] --> D + D --> T["Tilde API"] +``` + +The Computer protobuf package moves to `dispatch.computer.v1`. Dispatch-owned HTTP, OAuth, +hosted-instance, avatar, and generated OpenAPI names also move to Dispatch. This is a coordinated +wire change: the authoritative Tilde API must expose the new identity route and schema namespace +before a deployed Dispatch build can use those flows. + +State classification: + +- Repository configuration: package names, provider templates, repository URLs, and `DISPATCH_*` + environment declarations. +- Secret material: values unchanged; names may move with their owning environment contract; no + plaintext included. +- Control/client state: `.dispatch` paths, storage keys, OAuth audience/scope, and desktop protocol + identity move to Dispatch. +- Ephemeral runtime state: process, image, service, VM, cache, and generated artifact names move to + Dispatch. + +ADR-0021 records the Dispatch UI class/token namespace. ADR-0030 records Dispatch as application +and `@trytilde/cli`/`tilde` as command owner. ADR-0013 continues to own canonical repository +bootstrap. No new provider, storage, authentication, or deployment owner is introduced. + +## Summarized package changes + +- `@trytilde/cli`: replaces the product-named package and binary. Help renders Tilde as command + owner and Dispatch as the operated application. Init, dev, deploy, SDK, plugin, desktop, remote, + and repository workflows use `tilde`. +- Fixed Dispatch package group: moves from the previous scope to `@trytilde/dispatch-*`; imports, + exports, filters, Changesets, READMEs, templates, and package metadata move together. +- `@trytilde/api-client` and `@trytilde/sdk`: regenerated from the renamed Dispatch OpenAPI + contract. `@trytilde/sdk-vercel-ai-node` consumes the renamed hosted identities. +- `@trytilde/dispatch-computer-service-proto`: source and generated output move to + `dispatch/computer/v1` and `dispatch.computer.v1`. +- Web and UI: app module, runtime symbols, owner copy, local state keys, stylesheet export, + `dispatch-*` classes, and `--dispatch-*` design tokens move as one surface. +- Electron: app name, bundle/protocol identity, preload bridge, executable, updater variables, + service assets, and Linux package output move to Dispatch. +- Providers and Computers: service units, desktop launchers, image names, internal directories, + deterministic resource prefixes, source-kind metadata, and fork paths move to Dispatch. +- Skills, ADRs, update records, workflows, examples, tests, provenance, and contributor instructions + use current product, package, command, and repository names. +- Git provider README now documents its exported provider contracts, adapters, constants, and + helper functions. +- Browser regression: the routines E2E now mocks current Work endpoints and asserts the already + merged Work-pane hierarchy instead of a removed standalone panel. +- Release metadata: a dedicated breaking pre-1.0 Changeset covers the fixed Dispatch group and + affected Tilde API/SDK packages. Existing pending Changesets target the new package names. + +Validation completed on Linux: + +- Focused CLI, control-service, agent-service-provider, computer-service-provider, + client-runtime, and desktop tests pass. +- Full `pnpm check`, `pnpm build`, and `pnpm test` pass. +- Full Chromium E2E: 16 passed, 1 intentionally skipped. +- Linux Electron packaging: Dispatch AppImage and Debian artifacts produced outside Git. +- Protobuf/OpenAPI generation, package artifact verification, CLI artifact verification, + Changesets status, formatting, stale-name scan, secret scan, and diff checks pass. +- macOS packaging/signing and production deployment not run. + +Task evidence audit: summaries for all 150 archived tasks returned by the archive API and all 69 +active/pinned tasks returned by the active-task API were reviewed. Full turns were read for the +Dispatch naming decision, earlier Tilde CLI ownership decision, and this implementation task. The +active-task API exposes at most 50 non-pinned tasks and no pagination cursor, so older non-pinned +active tasks could not be enumerated; no claim of complete local task-database coverage is made. +No unrelated private task material is included here. + +## Critical to apply to forks + +yes + +This is a breaking identity and wire migration. Forks must: + +1. Replace product-package dependencies and imports with matching `@trytilde/dispatch-*` names. +2. Install `@trytilde/cli`; replace product-named commands and root delegations with `tilde`. +3. Rename environment declarations to `DISPATCH_*` and local/persisted paths to `.dispatch`. +4. Migrate client storage keys, OAuth audience/scope, desktop protocol and bundle identity, service + names, image/resource names, and any selectors targeting the prior UI prefix. +5. Regenerate Computer protobuf output from `dispatch/computer/v1/computer.proto`. +6. Deploy a matching Tilde API identity/OpenAPI namespace before deploying this Dispatch version; + otherwise auth, hosted-instance, avatar, and release operations address unavailable routes. +7. Re-run `pnpm install`, `pnpm check`, `pnpm build`, `pnpm test`, browser E2E, and the relevant + desktop package on each supported host. + +Fork secret values do not move into Git. Keep `configuration/.env` untracked, migrate encrypted +names through the fork's normal SOPS workflow, and preserve one-time credentials while changing +their owning environment contract. diff --git a/docs/updates/38.md b/docs/updates/38.md index 1f1f9b7a..38bab37c 100644 --- a/docs/updates/38.md +++ b/docs/updates/38.md @@ -1,11 +1,11 @@ -# PR 38: Publish OpenBot packages and standalone CLI +# PR 38: Publish Dispatch packages and standalone CLI ## Intent of the change -- Make every workspace package public. Use `@tryopenbot/*` namespace. -- Keep operator command simple: package and executable both named `openbot`. +- Make every workspace package public. Use `@trytilde/dispatch-*` namespace. +- Keep the operator command simple: package `@trytilde/cli`, executable `tilde`. - Ship real JavaScript, declarations, CSS, Handlebars assets, service binaries, and verified package exports. No source-checkout dependency at runtime. -- Let `openbot init` start in empty directory. Create owned GitHub public fork or private mirror. Support personal account and organization through `name` or `owner/name`. +- Let `tilde init` start in empty directory. Create owned GitHub public fork or private mirror. Support personal account and organization through `name` or `owner/name`. - Make automation first class. JSON answers on stdin. JSON results on stdout. Secret values on stdin, never argv. - Make AWS IAM Identity Center profiles work with SOPS. Export fresh short-lived credentials through AWS CLI and pass only to child process environment. - Keep local computer images local. Build Vercel Sandbox image for `linux/amd64` and publish to configured Vercel Container Registry. @@ -14,7 +14,7 @@ - Package boundary changes from private TypeScript workspace links to dual development/published exports. - Development condition points at `src`. Published condition points at `dist`. Build verifies every declared artifact. -- CLI root changes from install checkout to current working directory. Ordinary commands operate on current OpenBot repository. Init is special: empty destination becomes repository root after verified clone. +- CLI root changes from install checkout to current working directory. Ordinary commands operate on current Dispatch repository. Init is special: empty destination becomes repository root after verified clone. - Repository bootstrap checks empty directory, Git, GitHub auth, SSH, canonical HEAD compatibility, fork or mirror creation, exact cloned revision, and origin/upstream remotes before configuration begins. - Public path remains GitHub fork. Private path remains independent mirrored repository. No false private-fork claim. - SOPS identity metadata may store AWS profile name. It never stores exported access key, secret key, or session token. @@ -22,7 +22,7 @@ ```mermaid flowchart TD - N["npm or npx openbot"] --> E{"Current directory empty?"} + N["npm or npx @trytilde/cli"] --> E{"Current directory empty?"} E -->|"no"| R["Repository commands"] E -->|"yes and init"| P["Verify GitHub and canonical revision"] P --> V{"Visibility"} @@ -36,17 +36,17 @@ flowchart TD ## Summarized package changes -- `openbot`: public executable package; bundled `dist/index.js`; empty-directory repository bootstrap; organization repositories; non-interactive JSON init; JSON agent and secret mutations; stdin secrets; SOPS encryption preflight; fresh AWS profile export; current-directory operation. -- `@tryopenbot/workspace`: public workspace identity; renamed scripts and filters; full artifact and standalone executable verification. -- `@tryopenbot/ui` and `@tryopenbot/web`: published UI JavaScript, declarations, CSS, and corrected Beautiful UI stylesheet resolution. -- `@tryopenbot/control-service` and `@tryopenbot/computer-service`: runnable service artifacts; computer service exposes executable bin; control service publishes declarations and root export. -- `@tryopenbot/control-service-proto` and `@tryopenbot/computer-service-proto`: generated JavaScript/declarations and proto sources included in public packages. -- `@tryopenbot/agent-provider`, `@tryopenbot/inference-model-provider`, `@tryopenbot/skills-provider`, and `@tryopenbot/tools-provider`: public provider exports renamed and built to `dist`. -- `@tryopenbot/agent-service-provider`, `@tryopenbot/control-service-provider`, and `@tryopenbot/computer-provider`: public provider artifacts, templates, declarations, and renamed cross-package imports. -- `@tryopenbot/runtime-provider`: initialization questions may include descriptions for interactive and automated clients. -- `@tryopenbot/configuration`: public typed fork composition contract under new namespace. -- `@tryopenbot/utilities`: public JavaScript/declarations and copied Handlebars assets. -- `@tryopenbot/desktop`: public package metadata and renamed web dependency; Linux AppImage and Debian packaging verified. +- `@trytilde/cli`: public executable package; bundled `dist/index.js`; empty-directory repository bootstrap; organization repositories; non-interactive JSON init; JSON agent and secret mutations; stdin secrets; SOPS encryption preflight; fresh AWS profile export; current-directory operation. +- `@trytilde/dispatch-workspace`: public workspace identity; renamed scripts and filters; full artifact and standalone executable verification. +- `@trytilde/dispatch-ui` and `@trytilde/dispatch-web`: published UI JavaScript, declarations, CSS, and corrected Beautiful UI stylesheet resolution. +- `@trytilde/dispatch-control-service` and `@trytilde/dispatch-computer-service`: runnable service artifacts; computer service exposes executable bin; control service publishes declarations and root export. +- `@trytilde/dispatch-control-service-proto` and `@trytilde/dispatch-computer-service-proto`: generated JavaScript/declarations and proto sources included in public packages. +- `@trytilde/dispatch-agent-provider`, `@trytilde/dispatch-inference-model-provider`, `@trytilde/dispatch-skills-provider`, and `@trytilde/dispatch-tools-provider`: public provider exports renamed and built to `dist`. +- `@trytilde/dispatch-agent-service-provider`, `@trytilde/dispatch-control-service-provider`, and `@trytilde/dispatch-computer-provider`: public provider artifacts, templates, declarations, and renamed cross-package imports. +- `@trytilde/dispatch-runtime-provider`: initialization questions may include descriptions for interactive and automated clients. +- `@trytilde/dispatch-configuration`: public typed fork composition contract under new namespace. +- `@trytilde/dispatch-utilities`: public JavaScript/declarations and copied Handlebars assets. +- `@trytilde/dispatch-desktop`: public package metadata and renamed web dependency; Linux AppImage and Debian packaging verified. - Changesets fixed group and all existing pending changesets now use published package names. New release changeset covers public artifacts, CLI, AWS profile refresh, and automation surface. - Governing ADRs and package READMEs updated. Protobuf schemas and `tilde.state.yaml` unchanged. @@ -54,11 +54,11 @@ flowchart TD yes -- Replace every `@openbot/*` dependency and import with matching `@tryopenbot/*` name. Replace `@openbot/cli` with `openbot`. +- Replace every `@dispatch/*` dependency and import with the matching `@trytilde/dispatch-*` name. Replace `@dispatch/cli` with `@trytilde/cli` and invoke it as `tilde`. - Run `pnpm install`, `pnpm check`, `pnpm build`, and provider-focused tests after namespace migration. Published consumers must import declared exports, not package `src` paths. -- Use `openbot ` or `npx openbot `. Run new initialization only from completely empty destination. Existing initialized forks keep their tracked configuration and do not rerun init in place. +- Use `tilde ` or `npx @trytilde/cli `. Run new initialization only from completely empty destination. Existing initialized forks keep their tracked configuration and do not rerun init in place. - For organization repository creation, answer `owner/name`. Bare name still uses authenticated GitHub account. - AWS KMS owners using a named profile must have AWS CLI credential export working. Profile name remains in `configuration/sops.identity.json`; fresh credentials remain ephemeral. -- Vercel Sandbox forks must provide untagged Vercel Container Registry repository and have Docker Buildx available for `linux/amd64`. Local Microsandbox forks no longer need `OPENBOT_COMPUTER_IMAGE_REPOSITORY`. +- Vercel Sandbox forks must provide untagged Vercel Container Registry repository and have Docker Buildx available for `linux/amd64`. Local Microsandbox forks no longer need `DISPATCH_COMPUTER_IMAGE_REPOSITORY`. - Automation should send init answers as JSON on stdin and secret values through `--stdin`; never put credentials in command arguments. - Keep upstream contribution boundary intact: canonical repository tracks only `configuration/.gitignore`. Forks keep initialized `configuration/` and exclude `configuration/.env`. diff --git a/docs/updates/39.md b/docs/updates/39.md index 9a7a046d..f2475941 100644 --- a/docs/updates/39.md +++ b/docs/updates/39.md @@ -10,15 +10,15 @@ ```mermaid flowchart LR - I["openbot init"] --> C["Clone and configure fork"] + I["tilde init"] --> C["Clone and configure fork"] C --> V["vp install"] - V --> D["openbot dev"] + V --> D["tilde dev"] D --> S["Workspace source exports"] - P["openbot deploy"] --> VP["Create or inspect Vercel projects"] + P["tilde deploy"] --> VP["Create or inspect Vercel projects"] VP --> R["Resolve agent-project VCR namespace"] R --> L["Docker login via token on stdin"] - L --> U["First push creates openbot-computer"] + L --> U["First push creates dispatch-computer"] U --> E["Publish immutable image reference"] ``` @@ -30,15 +30,15 @@ flowchart LR # Summarized package changes -- `openbot` +- `@trytilde/cli` - Remove `computer-image-repository` from Vercel init answers. - Run `vp install` as final successful init action. - Add `--conditions=development` to watched server process while preserving existing `NODE_OPTIONS`. - Add regression coverage for init and source-export resolution. -- `@tryopenbot/computer-provider` +- `@trytilde/dispatch-computer-provider` - Suppress registry prompt for managed Vercel images. - Use local build tag before remote project configuration exists. - - Resolve `vcr.vercel.com///openbot-computer` during deploy. + - Resolve `vcr.vercel.com///dispatch-computer` during deploy. - Authenticate Docker with Vercel token through stdin. - Let first push create repository, then publish immutable content tag. - Documentation @@ -51,7 +51,7 @@ flowchart LR - CLI tests: 32 passed, 2 skipped. - `pnpm check` passed with existing warnings only. - `pnpm build` passed, including package artifacts and standalone CLI smoke test. - - Real `/root/our-openbot` source import passed without package `dist` artifacts. + - Real `/root/our-dispatch` source import passed without package `dist` artifacts. # Critical to apply to forks @@ -59,7 +59,7 @@ yes - Pull this update before initializing a new fork. Init will install dependencies automatically. - Existing initialized forks cannot rerun init. Run `vp install` once after pulling. -- Existing Vercel forks may remove stale `OPENBOT_COMPUTER_IMAGE_REPOSITORY`; it is no longer an init input. +- Existing Vercel forks may remove stale `DISPATCH_COMPUTER_IMAGE_REPOSITORY`; it is no longer an init input. - Ensure the Vercel token can access the configured agent project and VCR. -- Next deploy creates `openbot-computer` inside the agent project's VCR on first push. -- Run `openbot dev` to verify workspace packages resolve from source without a full build. +- Next deploy creates `dispatch-computer` inside the agent project's VCR on first push. +- Run `tilde dev` to verify workspace packages resolve from source without a full build. diff --git a/docs/updates/40.md b/docs/updates/40.md index 7981db23..23ee7c18 100644 --- a/docs/updates/40.md +++ b/docs/updates/40.md @@ -1,14 +1,14 @@ # Intent of the change -- Make standalone `openbot dev` discover agents from the fork repository. -- Stop `pnpm --filter openbot exec` from changing the watched server cwd to `cli/`. +- Make standalone `tilde dev` discover agents from the fork repository. +- Stop `pnpm --filter @trytilde/cli exec` from changing the watched server cwd to `cli/`. - Fix `ENOENT` for `/cli/configuration/agents` on the first development run. # Architecture changes ```mermaid flowchart LR - C["Standalone openbot CLI"] --> P["pnpm exec from fork root"] + C["Standalone Tilde CLI"] --> P["pnpm exec from fork root"] P --> T["tsx watch cli/src/index.tsx _serve"] T --> R["process.cwd = fork root"] R --> A["configuration/agents"] @@ -19,7 +19,7 @@ flowchart LR # Summarized package changes -- `openbot` +- `@trytilde/cli` - Launch the watched server with root-scoped `pnpm exec`. - Keep `cli/src/index.tsx` as the source entrypoint. - Add a regression assertion for the exact command. @@ -28,7 +28,7 @@ flowchart LR - Proof - CLI typecheck passed. - CLI tests passed: 39 passed, 2 skipped. - - Real run from `/root/our-openbot` passed the reported agent discovery failure. + - Real run from `/root/our-dispatch` passed the reported agent discovery failure. # Critical to apply to forks @@ -36,4 +36,4 @@ yes - Pull this fix before running the standalone CLI against a source fork. - No configuration or secret migration is required. -- Retry `openbot dev`; it will read `/configuration/agents` rather than `/cli/configuration/agents`. +- Retry `tilde dev`; it will read `/configuration/agents` rather than `/cli/configuration/agents`. diff --git a/docs/updates/41.md b/docs/updates/41.md index 57693158..bcc9f13a 100644 --- a/docs/updates/41.md +++ b/docs/updates/41.md @@ -30,9 +30,9 @@ flowchart TD ``` - `configuration/index.ts` remains the fork composition root. Concrete providers receive shared platform clients instead of asking the same platform questions repeatedly. -- `@tryopenbot/chat-provider` owns control-facing agent, session, and message data. `@tryopenbot/agent-provider` now owns external authored-agent lifecycle reconciliation. +- `@trytilde/dispatch-chat-provider` owns control-facing agent, session, and message data. `@trytilde/dispatch-agent-provider` now owns external authored-agent lifecycle reconciliation. - Provider contracts expose only operations used by the control service, initialization, provisioning, or lifecycle coordination. Authored agents do not import provider packages. -- `@tryopenbot/platform-integrations` contains shared Tilde and Vercel transport, error, deployment, registry, and AI Gateway helpers. `@tryopenbot/computer-tools` contains the agent-safe typed Computer tools. Instrumentation utilities live in `@tryopenbot/configuration`. +- `@trytilde/dispatch-platform-integrations` contains shared Tilde and Vercel transport, error, deployment, registry, and AI Gateway helpers. `@trytilde/dispatch-computer-tools` contains the agent-safe typed Computer tools. Instrumentation utilities live in `@trytilde/dispatch-configuration`. - The lifecycle coordinator invokes each agent's skills, tools, and agent deployables in order and passes `agentId`, absolute agent path, and `DeploymentContext.devMode`. Providers own drift checks, mutations, persisted values, and named handoff outputs. - Tilde reconciliation uses stable identities and typed API calls. It creates or updates the ChatKit agent, exact skill set, skill registry, dynamic MCP server, Tilde control-plane toolkit, optional Vercel MCP server, and Vercel AI SDK endpoint. Development switches applicable endpoints to tunnel mode. - `tilde.state.yaml` is no longer part of normal operation. Manual Tilde CLI export and import remains the one-time path for moving resources between teams. @@ -42,8 +42,8 @@ flowchart TD # Summarized package changes - CLI and initialization - - Publish the standalone `openbot` executable with built package entrypoints and workspace-source loading for development. - - Use public `@tryopenbot/*` package names while preserving the `openbot` binary name. + - Publish the standalone `tilde` executable with built package entrypoints and workspace-source loading for development. + - Use public `@trytilde/dispatch-*` package names while preserving the `tilde` binary name. - Reject initialization in unrelated non-empty directories, accept `owner/name` GitHub repositories, run `vp install`, and let recognized forks revisit existing answers. - Scaffold the primary agent at `configuration/agent/` and full additional agents at `configuration/agent/subagents//`, using fork-owned templates from `configuration/templates/agent/`. - Validate Tilde MCP tool registries before narrowing them to Vercel AI SDK `ToolSet`, and typecheck the real default scaffold so generated agents cannot fail only during provider build checks. @@ -56,7 +56,7 @@ flowchart TD - Make Vercel service adapters development-safe and make the Vercel Computer adapter use Microsandbox during development. - Import locally built Computer images into the Microsandbox cache and disable registry pulls, preventing repository-derived local tags from being mistaken for Docker Hub images. - Authored-agent runtime - - Remove provider imports from default agent code and templates. Agents use direct AI SDK/vendor integrations plus `@tryopenbot/computer-tools` and `@tryopenbot/configuration` runtime helpers. + - Remove provider imports from default agent code and templates. Agents use direct AI SDK/vendor integrations plus `@trytilde/dispatch-computer-tools` and `@trytilde/dispatch-configuration` runtime helpers. - Give the primary agent and every subagent the same instrumentation, skills, tools, sandbox workspace seed, and ChatKit entrypoint shape. - Build and packaging - Add browser and Node tsdown configurations, public package exports, package artifact verification, and local-package Docker build inputs so fresh workspaces do not depend on prebuilt or unpublished packages. @@ -75,10 +75,10 @@ yes - Pull this update before changing provider composition or creating more agents; package boundaries and lifecycle contracts are breaking. - Move the primary authored agent to `configuration/agent/`. Move every additional full agent to `configuration/agent/subagents//`; nested subagents and the legacy plural layout are unsupported. -- Keep `configuration/templates/agent/` aligned with the current primary/subagent structure so future `openbot new-agent` scaffolds the same integrations. -- Remove provider imports from authored agents. Integrate model, prompt, tool, MCP, and vendor behavior directly; use `@tryopenbot/computer-tools` only for standard Computer tools and `@tryopenbot/configuration` for shared instrumentation helpers. +- Keep `configuration/templates/agent/` aligned with the current primary/subagent structure so future `tilde new-agent` scaffolds the same integrations. +- Remove provider imports from authored agents. Integrate model, prompt, tool, MCP, and vendor behavior directly; use `@trytilde/dispatch-computer-tools` only for standard Computer tools and `@trytilde/dispatch-configuration` for shared instrumentation helpers. - Update custom deployables to accept `DeploymentContext.devMode` instead of `target`, remain idempotent, and own their environment/secrets persistence. Preserve named outputs only for real provider handoffs. - Replace split runtime-provider composition files with explicit concrete providers under `Configuration({ providers: { ... } })`, sharing one platform instance per vendor. -- Delete `tilde.state.yaml` from the fork. Re-run initialization in the recognized workspace to supply missing platform values, then let `openbot dev` or deployment reconcile Tilde resources. Use the Tilde CLI manually only for a one-time team export/import. +- Delete `tilde.state.yaml` from the fork. Re-run initialization in the recognized workspace to supply missing platform values, then let `tilde dev` or deployment reconcile Tilde resources. Use the Tilde CLI manually only for a one-time team export/import. - Treat the trusted development Computer as receiving the entire `configuration/.env` and encrypted secret set. Confirm its SOPS age identity has read permission only for the sandbox Linux user. -- Run `vp install`, then `openbot dev`. Confirm skills, tools, and agent reconciliation completes; local services enter watch mode; and Computer image changes replace the Microsandbox without losing its workspace. +- Run `vp install`, then `tilde dev`. Confirm skills, tools, and agent reconciliation completes; local services enter watch mode; and Computer image changes replace the Microsandbox without losing its workspace. diff --git a/docs/updates/42.md b/docs/updates/42.md index e0eb61a8..54831422 100644 --- a/docs/updates/42.md +++ b/docs/updates/42.md @@ -2,7 +2,7 @@ - Ship the first integrated owner workspace: Tilde-backed chat, continuous streaming, attachments, queued turns, responsive navigation, and one agent workspace with an isolated Computer preview. - Make fork configuration executable and explicit. Provider roles are constructed in `configuration/index.ts`; development and production reconcile provider-owned resources before starting runtimes. -- Protect every owner-facing control route. Tilde Identity issues public-client PKCE credentials bound to one OpenBot installation; browser credentials stay in host-only HttpOnly cookies and Electron credentials stay in the main process. +- Protect every owner-facing control route. Tilde Identity issues public-client PKCE credentials bound to one Dispatch installation; browser credentials stay in host-only HttpOnly cookies and Electron credentials stay in the main process. - Keep the implementation clean-room. Another desktop agent supplied behavioral requirements only; no source, identifiers, or prose are reused. # Architecture changes @@ -10,21 +10,21 @@ ```mermaid flowchart LR O["Owner"] -->|"Tilde SSO and PKCE"| I["Tilde Identity"] - I -->|"exact installation audience"| C["OpenBot control service"] + I -->|"exact installation audience"| C["Dispatch control service"] W["Web app"] -->|"host-only HttpOnly cookie"| C E["Electron main"] -->|"bearer via local proxy"| C C -->|"typed owner principal"| H["Owner HTTP and Connect handlers"] H --> P["Configured providers"] P --> A["Tilde agents and ChatKit"] - P --> X["OpenBot Computer"] + P --> X["Dispatch Computer"] D["Deploy coordinator"] -->|"build, reconcile, deploy"| P ``` -- Adds `@tryopenbot/auth-provider`. Its core contract owns authorization metadata and principal validation; the Tilde adapter performs discovery, installation registration, PKCE token exchange/refresh, and strict JWT verification. +- Adds `@trytilde/dispatch-auth-provider`. Its core contract owns authorization metadata and principal validation; the Tilde adapter performs discovery, installation registration, PKCE token exchange/refresh, and strict JWT verification. - Adds control-service auth middleware and bounded login, callback, refresh, logout, and session routes. Static assets and health remain public. Owner chat, attachment, control RPC, and Computer-preview surfaces require an authenticated principal. - Adds a web auth gate without exposing access or refresh tokens to browser JavaScript. - Adds Electron system-browser authentication, main-process PKCE and refresh handling, OS-protected credential storage, and bearer injection in the existing loopback proxy. The preload bridge exposes only bounded auth state and commands. -- Splits chat behavior into the chat provider and owner-facing control proxy. Tilde remains authoritative for agents, ChatKit sessions, tools, skills, and memory; OpenBot owns installation control and Computer lifecycle. +- Splits chat behavior into the chat provider and owner-facing control proxy. Tilde remains authoritative for agents, ChatKit sessions, tools, skills, and memory; Dispatch owns installation control and Computer lifecycle. - Extends provider deployment reconciliation so owner chat, auth metadata, workspace sources, and service-specific environments reach the correct local or Vercel artifact without leaking build-only credentials into runtime. - Adds agent-centric workspace and Computer tooling. Agent source and one-time workspace seeds are discovered from `configuration/agents//`; typed Computer tools bind the path-derived agent ID outside model-visible schemas. @@ -56,11 +56,11 @@ This PR changes fork composition, public package surfaces, generated protobuf co 1. Re-run `pnpm install` with Node 24 and pnpm 10, then regenerate contracts with `pnpm contracts:generate`. 2. Add an authentication provider to fork composition and reconcile custom provider extensions with the updated runtime, platform-integration, and service-provider contracts. Keep provider contracts in each package's `src/core.ts` or `src/core/index.ts`. 3. Reconcile `configuration/index.ts`, runtime-provider construction, instrumentation, and every configured agent under `configuration/agents//`. Do not copy upstream's `configuration/.gitignore` sentinel over an initialized fork. -4. Re-run `openbot init` or reproduce its new public Tilde metadata and encrypted-secret outputs. Keep `configuration/.env` untracked; keep team API keys, deployment credentials, and Computer service keys only in `configuration/secrets.enc.yaml`. +4. Re-run `tilde init` or reproduce its new public Tilde metadata and encrypted-secret outputs. Keep `configuration/.env` untracked; keep team API keys, deployment credentials, and Computer service keys only in `configuration/secrets.enc.yaml`. 5. Register each installation with Tilde Identity. Configure its exact issuer, client ID, installation audience, team/installation identifiers, and supported web/native redirects. Never encode an installation ID as an OAuth scope. 6. Preserve browser host-only HttpOnly cookie handling and Electron main-process credential storage. Do not expose access or refresh tokens through renderer code, preload APIs, protobuf state, logs, or deployment outputs. 7. Review custom Vercel/local providers against build and deployment contracts, environment allowlists, secret installation, and service-specific deploy behavior. 8. Review custom agents against the Eve-compatible directory subset and fixed-agent Computer tools. Existing deployed workspace seeds are one-time and are not overwritten by later repository edits. -9. Run `pnpm check`, `pnpm build`, `pnpm test:e2e`, and `pnpm --filter @openbot/desktop package`; verify login, refresh, logout, wrong-audience rejection, owner chat, attachments, Computer preview, and deployment dry-run on the customized fork. +9. Run `pnpm check`, `pnpm build`, `pnpm test:e2e`, and `pnpm --filter @dispatch/desktop package`; verify login, refresh, logout, wrong-audience rejection, owner chat, attachments, Computer preview, and deployment dry-run on the customized fork. No database migration is introduced. Existing installation access tokens cannot be revoked immediately and remain valid until their short expiry; unlink and revocation management are deferred. diff --git a/docs/updates/43.md b/docs/updates/43.md index eb89346c..44fe28d2 100644 --- a/docs/updates/43.md +++ b/docs/updates/43.md @@ -2,8 +2,8 @@ - Ship the continuous agent workspace: sidebar, transcript, composer, rich message content, Computer pane, overlays, activity panels. - One continuous conversation per agent. No session picker, no thread list, no conversation switcher. -- Move every reusable surface out of `apps/web` into `@tryopenbot/ui`. The app keeps data fetching, routing, and composition only. -- Ship the workspace stylesheet from the package as `@tryopenbot/ui/openbot-ui.css`. No app-local stylesheet. +- Move every reusable surface out of `apps/web` into `@trytilde/dispatch-ui`. The app keeps data fetching, routing, and composition only. +- Ship the workspace stylesheet from the package as `@trytilde/dispatch-ui/dispatch-ui.css`. No app-local stylesheet. - Make every reusable component inspectable in isolation. Package-owned Storybook, not a separate demo app, not duplicated production components. - Stop treating an owner-cancelled Computer preview as a provider failure. A hidden or unmounted preview is normal lifecycle. @@ -12,7 +12,7 @@ ```mermaid flowchart LR W["apps/web: routing, Tilde fetch, SSE reconciliation, uploads"] -->|"props only"| U["packages/ui: workspace, transcript, content, Computer, overlays, activity"] - W -->|"import"| CSS["@tryopenbot/ui/openbot-ui.css"] + W -->|"import"| CSS["@trytilde/dispatch-ui/dispatch-ui.css"] U --> CSS U --> SB["packages/ui/stories: Storybook catalog, 9 story files"] W -->|"iframe /api/computer/:agentId/preview"| CS["apps/control-service: computer-preview route"] @@ -21,26 +21,26 @@ flowchart LR ``` - Presentation boundary moved. `packages/ui` owns markup, class names, motion, and component state. `apps/web` owns the Tilde data path and application composition. Nothing in `packages/ui` fetches. -- Stylesheet ownership moved with it. `apps/web/src/styles.css` is deleted; `packages/ui/src/openbot-ui.css` is the single workspace stylesheet, exported through a new `./openbot-ui.css` entry in the package `exports` and `publishConfig.exports`. `apps/web/src/main.tsx` imports the package path. +- Stylesheet ownership moved with it. `apps/web/src/styles.css` is deleted; `packages/ui/src/dispatch-ui.css` is the single workspace stylesheet, exported through a new `./dispatch-ui.css` entry in the package `exports` and `publishConfig.exports`. `apps/web/src/main.tsx` imports the package path. - Four modules physically relocated: `agent-workspace-panel.tsx`, `use-workspace-layout.ts`, `message-content.tsx`, `styles.css` → `packages/ui/src/`. Git records them as renames; GitHub's file list shows the CSS and `message-content.tsx` as delete plus add. - Computer preview lifecycle is now two-sided. The panel mounts the iframe only while the pane is visible and re-keys it on retry and monitor switch; the control-service route returns `499` when `context.req.raw.signal.aborted`; `retryComputerServiceStartup` rethrows instead of retrying when `signal?.aborted`. No provider error surfaces from an owner navigating away. - Computer screen focus decoupled from agent identity. `AgentWorkspacePanel` tracks `activeMonitorId` locally and derives `previewUrl`, `previewAgentId`, and `previewAgentName` from the selected monitor, falling back to the agent. Selecting a monitor drops control, resets ready and failure state, and re-keys the iframe. The monitor strip renders only when more than one monitor exists. - Preview failure is a UI state, not a blank frame. `ComputerStagePlaceholder` covers booting and unreachable, with a retry action that bumps the preview key. -- Chat event replay is deduplicated in the app, not the package. `apps/web/src/screens/openbot-app.tsx` keeps a bounded `Set` of seen event ids, evicting the oldest past 1000 entries. -- Storybook is package-owned. `packages/ui/.storybook/main.ts` uses `@storybook/react-vite` plus the Tailwind Vite plugin; `preview.tsx` loads both package stylesheets and wraps stories in `openbot-storybook-root`. Stories import the real exports; no duplicate production components exist. +- Chat event replay is deduplicated in the app, not the package. `apps/web/src/screens/dispatch-app.tsx` keeps a bounded `Set` of seen event ids, evicting the oldest past 1000 entries. +- Storybook is package-owned. `packages/ui/.storybook/main.ts` uses `@storybook/react-vite` plus the Tailwind Vite plugin; `preview.tsx` loads both package stylesheets and wraps stories in `dispatch-storybook-root`. Stories import the real exports; no duplicate production components exist. - Not in this PR: no protobuf, no persisted schema, no deployment resource, no environment name, no secret handling. Streamed chat state, uploads, and preview URLs stay ephemeral runtime data. # Summarized package changes -- `packages/ui` — the bulk of the change. New modules: `workspace-shell.tsx`, `workspace-sidebar.tsx`, `sidebar-components.tsx`, `workspace-icons.tsx`, `chat-components.tsx`, `chat-composer.tsx`, `transcript-components.tsx`, `rich-message-components.tsx`, `content-components.tsx`, `markdown-components.tsx`, `primitive-components.tsx`, `overlay-components.tsx`, `computer-components.tsx`, `computer-stage.tsx`, `activity-panels.tsx`, `agent-activity.tsx`, `agent-avatar.tsx`, `agent-avatar-shapes.ts`, `assets/avatars/{blue,green,red}.svg`. Relocated in: `agent-workspace-panel.tsx`, `use-workspace-layout.ts`, `message-content.tsx`, `openbot-ui.css` (7249 lines). `index.ts` +199 export lines. `README.md` rewritten around the public component surface and the Storybook command. `package.json` gains the `./openbot-ui.css` export, `storybook` and `storybook:build` scripts, Storybook/Tailwind devDependencies, and `react-markdown` + `remark-gfm` dependencies. One unit test file, `computer-components.test.ts`, covering `getComputerRebuildProgress` phase mapping, reset cleanup ordering, the four-step recovery flow, and clamping of image-download progress. +- `packages/ui` — the bulk of the change. New modules: `workspace-shell.tsx`, `workspace-sidebar.tsx`, `sidebar-components.tsx`, `workspace-icons.tsx`, `chat-components.tsx`, `chat-composer.tsx`, `transcript-components.tsx`, `rich-message-components.tsx`, `content-components.tsx`, `markdown-components.tsx`, `primitive-components.tsx`, `overlay-components.tsx`, `computer-components.tsx`, `computer-stage.tsx`, `activity-panels.tsx`, `agent-activity.tsx`, `agent-avatar.tsx`, `agent-avatar-shapes.ts`, `assets/avatars/{blue,green,red}.svg`. Relocated in: `agent-workspace-panel.tsx`, `use-workspace-layout.ts`, `message-content.tsx`, `dispatch-ui.css` (7249 lines). `index.ts` +199 export lines. `README.md` rewritten around the public component surface and the Storybook command. `package.json` gains the `./dispatch-ui.css` export, `storybook` and `storybook:build` scripts, Storybook/Tailwind devDependencies, and `react-markdown` + `remark-gfm` dependencies. One unit test file, `computer-components.test.ts`, covering `getComputerRebuildProgress` phase mapping, reset cleanup ordering, the four-step recovery flow, and clamping of image-download progress. - `packages/ui/stories` — 9 new story files: `Workspace`, `Messages`, `Computer`, `Content`, `Activity`, `Controls`, `Transcript`, `Overlays`, `Primitives`. -- `apps/web` — `screens/openbot-app.tsx` rewritten around the package components (364 added, 559 removed) with the replayed-event dedupe; `main.tsx` swaps `./styles.css` for `@tryopenbot/ui/openbot-ui.css`; `chat-api.ts` adds optional `last_message_preview` and `last_user_message_at` to `ChatAgent` for sidebar preview rows; `styles.css` and `message-content.tsx` removed. +- `apps/web` — `screens/dispatch-app.tsx` rewritten around the package components (364 added, 559 removed) with the replayed-event dedupe; `main.tsx` swaps `./styles.css` for `@trytilde/dispatch-ui/dispatch-ui.css`; `chat-api.ts` adds optional `last_message_preview` and `last_user_message_at` to `ChatAgent` for sidebar preview rows; `styles.css` and `message-content.tsx` removed. - `apps/control-service` — `computer-preview.ts` returns `499` on an aborted request; `app.test.ts` adds a case asserting the aborted preview yields `499` and still calls `previewAgentDesktop` once. - `packages/computer-provider` — `base/index.ts` rethrows on an aborted signal inside `retryComputerServiceStartup`; `base.test.ts` adds a case asserting a caller-aborted request is attempted once and not retried. - `tests/e2e/workspace.spec.ts` — 270 added lines across 6 Chromium tests: owner-session requirement, bare workspace layout metrics, mobile-viewport chat composition, rich streaming plus file upload, queued turn while busy, control-route health. - `scripts/copy-package-assets.mjs` — copied extensions gain `.svg` so packaged avatar artwork ships in `dist`. - `.gitignore` — `storybook-static/`. -- `.changeset/extract-workspace-ui.md`, `.changeset/add-rich-content-surfaces.md` — both minor. The first bumps the whole fixed workspace group; the second is `@tryopenbot/ui` only. +- `.changeset/extract-workspace-ui.md`, `.changeset/add-rich-content-surfaces.md` — both minor. The first bumps the whole fixed workspace group; the second is `@trytilde/dispatch-ui` only. - `pnpm-lock.yaml` — 2221 added lines for the new UI and Storybook dependency graph. - No ADR, no `docs/` change in this PR. @@ -48,13 +48,13 @@ flowchart LR yes -**A fork that styled the web app loses its stylesheet.** `apps/web/src/styles.css` is deleted, 3680 lines, and reappears as `packages/ui/src/openbot-ui.css`. A fork that edited the app stylesheet sees the file vanish on merge. Reapply the edits in `packages/ui/src/openbot-ui.css`, or add a fork-owned stylesheet imported after the package one — do not restore `apps/web/src/styles.css`, because `apps/web/src/main.tsx` no longer imports it. +**A fork that styled the web app loses its stylesheet.** `apps/web/src/styles.css` is deleted, 3680 lines, and reappears as `packages/ui/src/dispatch-ui.css`. A fork that edited the app stylesheet sees the file vanish on merge. Reapply the edits in `packages/ui/src/dispatch-ui.css`, or add a fork-owned stylesheet imported after the package one — do not restore `apps/web/src/styles.css`, because `apps/web/src/main.tsx` no longer imports it. -**Import paths moved.** `apps/web/src/message-content.tsx`, `apps/web/src/agent-workspace-panel.tsx`, and `apps/web/src/use-workspace-layout.ts` are gone. Anything in a fork importing `./message-content.js`, `../agent-workspace-panel.js`, or `./use-workspace-layout.js` from inside `apps/web` fails to resolve. Import `MessageContent`, `AgentWorkspacePanel`, and `useWorkspaceLayout` from `@tryopenbot/ui`. +**Import paths moved.** `apps/web/src/message-content.tsx`, `apps/web/src/agent-workspace-panel.tsx`, and `apps/web/src/use-workspace-layout.ts` are gone. Anything in a fork importing `./message-content.js`, `../agent-workspace-panel.js`, or `./use-workspace-layout.js` from inside `apps/web` fails to resolve. Import `MessageContent`, `AgentWorkspacePanel`, and `useWorkspaceLayout` from `@trytilde/dispatch-ui`. -**`apps/web/src/screens/openbot-app.tsx` was rewritten.** 364 added, 559 removed. A fork carrying local edits to the workspace screen will conflict across most of the file. Rebase by re-expressing the fork's behavior as props into the package components rather than by resolving hunks. +**`apps/web/src/screens/dispatch-app.tsx` was rewritten.** 364 added, 559 removed. A fork carrying local edits to the workspace screen will conflict across most of the file. Rebase by re-expressing the fork's behavior as props into the package components rather than by resolving hunks. -**Install before anything else.** `@tryopenbot/ui` gained runtime and Storybook dependencies and the lockfile changed by 2221 lines. Run `pnpm install`; a stale `node_modules` fails at build, not at typecheck. +**Install before anything else.** `@trytilde/dispatch-ui` gained runtime and Storybook dependencies and the lockfile changed by 2221 lines. Run `pnpm install`; a stale `node_modules` fails at build, not at typecheck. **Packaged asset copying changed.** `scripts/copy-package-assets.mjs` now copies `.svg`. A fork with its own package build or asset pipeline must copy the avatar SVGs under `packages/ui/src/assets/avatars/` or agent identity artwork is missing from `dist` in production builds only. @@ -64,4 +64,4 @@ yes **Additive only on the chat contract.** `ChatAgent` gained optional `last_message_preview` and `last_user_message_at`. No protobuf, persisted schema, environment name, or secret handling changed. No migration. -Run `pnpm install`, then `pnpm check`, `pnpm build`, `pnpm --filter @tryopenbot/ui storybook:build`, and `pnpm test:e2e`. Then open the workspace and confirm the sidebar, transcript, composer, overlays, activity panels, and Computer pane render — the relocation is invisible to static checks once imports resolve. +Run `pnpm install`, then `pnpm check`, `pnpm build`, `pnpm --filter @trytilde/dispatch-ui storybook:build`, and `pnpm test:e2e`. Then open the workspace and confirm the sidebar, transcript, composer, overlays, activity panels, and Computer pane render — the relocation is invisible to static checks once imports resolve. diff --git a/docs/updates/44.md b/docs/updates/44.md index 3bc194f4..321c7de8 100644 --- a/docs/updates/44.md +++ b/docs/updates/44.md @@ -23,7 +23,7 @@ flowchart LR - `TildeAgentProvider` is now the aggregate owner for the complete external Tilde footprint of an authored agent. Internal skill and tool reconcilers remain cohesive modules under `packages/agent-provider/src/tilde/` and run after the agent endpoint/channel exists. - The configuration contract no longer exposes `chat`, `skills`, or `tools` provider roles. CLI initialization and lifecycle scheduling no longer construct or sequence them separately. -- `@tryopenbot/chat-provider`, `@tryopenbot/skills-provider`, `@tryopenbot/tools-provider`, and `@tryopenbot/control-service-proto` are deleted. +- `@trytilde/dispatch-chat-provider`, `@trytilde/dispatch-skills-provider`, `@trytilde/dispatch-tools-provider`, and `@trytilde/dispatch-control-service-proto` are deleted. - The browser keeps Tilde ChatKit's native request and streaming shapes at `/api/chat/*`. The control service constrains the upstream path, injects its server-held credential, strips browser credentials, and removes private upstream response headers. - Local, Electron, Vite, and Vercel routing consistently forwards `/api/*`. The owner `/rpc` route and generated owner protobuf contract are gone. - Installation authentication remains a provider because it owns external OIDC client registration plus initialization/deployment. Its former `/rpc` middleware coverage is removed; it continues to protect the owner REST and Computer-preview routes. @@ -33,7 +33,7 @@ flowchart LR # Summarized package changes - Agent resources - - Move Tilde skill and tool reconciliation implementations and tests under `@tryopenbot/agent-provider`. + - Move Tilde skill and tool reconciliation implementations and tests under `@trytilde/dispatch-agent-provider`. - Add internal skill/tool input types and translate internal reconciliation failures to `AgentProviderError` at the aggregate boundary. - Reconcile endpoint/channel/credentials first, authored skills and registry second, then MCP/tool resources. - Control and frontend transport @@ -42,7 +42,7 @@ flowchart LR - Retain the allowlisted Tilde REST/SSE bridge and route `/api/*` through development, packaged desktop, and Vercel surfaces. - Update installation-auth tests to protect real REST routes rather than the deleted `/rpc` namespace. - Configuration and lifecycle - - Remove the `chat`, `skills`, and `tools` fields from `OpenBotProviders`. + - Remove the `chat`, `skills`, and `tools` fields from `DispatchProviders`. - Remove the deleted providers from initialization, development/deployment scheduling, generated configuration templates, package dependencies, and the workspace lockfile. - Keep `auth`, service, agent, computer, and inference providers because they own initialization/provisioning or build/deploy lifecycles. - Documentation and release @@ -65,5 +65,5 @@ yes - Update custom lifecycle code that assumed skills, tools, and agents were separate deployable participants. Schedule only the aggregate Agent Provider for authored-agent Tilde resources. - Replace owner ConnectRPC clients with the native `/api/chat/*` REST/SSE client. Ensure custom local, desktop, and hosting routes forward `/api/*` to the control service. - Remove dependencies on the four deleted packages and run `pnpm install` to refresh workspace links and the lockfile. -- Leave Computer service clients on `@tryopenbot/computer-service-proto` and ConnectRPC. That internal API did not migrate. +- Leave Computer service clients on `@trytilde/dispatch-computer-service-proto` and ConnectRPC. That internal API did not migrate. - Run `pnpm check`, `pnpm build`, `pnpm test`, and `pnpm test:e2e` after updating fork-owned configuration and routes. diff --git a/docs/updates/45.md b/docs/updates/45.md index ea4203cc..58f131ca 100644 --- a/docs/updates/45.md +++ b/docs/updates/45.md @@ -18,7 +18,7 @@ flowchart LR DO --> OG["Origin check for unsafe cookie requests"] CS -->|"devMode off"| PO["PUBLIC_ORIGIN or request origin (unchanged)"] AP["TildeAuthProvider.configure"] -->|"devMode: add loopback web callbacks"| TR["Tilde client registration"] - TR --> KEEP["Keeps 127.0.0.1:PORT, openbot://, PUBLIC_ORIGIN callbacks"] + TR --> KEEP["Keeps 127.0.0.1:PORT, dispatch://, PUBLIC_ORIGIN callbacks"] ``` - Boundary owners unchanged. Control service owns callback resolution and origin validation. Auth provider owns Tilde OIDC client registration. No new service, no new provider role. @@ -29,27 +29,27 @@ flowchart LR # Summarized package changes -- `@tryopenbot/control-service` +- `@trytilde/dispatch-control-service` - `src/auth.ts`: add `OwnerAuthOptions`, thread options through login, callback, session, logout, middleware, cookie helpers. Add `developmentBrowserOrigin`. `callbackUrl` prefers validated dev browser origin when `devMode`, else `PUBLIC_ORIGIN`, else request origin. - `src/app.ts`: pass app options into `registerOwnerAuth` and `requireOwner`. - `src/auth.test.ts`: two new tests — dev login keeps `redirect_uri` on forwarded `localhost:4173` even with hosted `PUBLIC_ORIGIN` and sets no `Secure` cookie; dev mutation accepts forwarded local origin and rejects `https://evil.test` with `403`. Env stubs cleared in `afterEach`. - `test/e2e-server.ts`: harness app runs with `devMode: true`, and stub `authorizationUrl` echoes `redirect_uri` so browser test can assert it. - `README.md`: document `createApp`, `registerOwnerAuth`, `requireOwner`. -- `@tryopenbot/auth-provider` - - `src/tilde.ts`: `#register` takes `development` from `context.devMode`; when set, adds `http://127.0.0.1:/auth/callback` and `http://localhost:/auth/callback`. Loopback control callback, `openbot://auth/callback`, and `PUBLIC_ORIGIN` callback stay. `deployment_url` untouched. +- `@trytilde/dispatch-auth-provider` + - `src/tilde.ts`: `#register` takes `development` from `context.devMode`; when set, adds `http://127.0.0.1:/auth/callback` and `http://localhost:/auth/callback`. Loopback control callback, `dispatch://auth/callback`, and `PUBLIC_ORIGIN` callback stay. `deployment_url` untouched. - `src/tilde.test.ts`: dev reconciliation registers both loopback web callbacks and keeps hosted callback. - `README.md`: add `Public API` for `AuthProvider`, `OwnerPrincipal`, `OAuthTokens`, `AuthProviderError`, `TildeAuthProvider`. Contracts still defined in `src/core.ts`. -- `@tryopenbot/web` +- `@trytilde/dispatch-web` - `vite.config.ts`: proxy entries for `/healthz`, `/api/chat`, `/api/computer`, `/auth` become objects with `xfwd: true`. - `README.md`: record dev proxy forwarded-origin behavior. - Workspace root - - `playwright.config.ts`: harness env gets `PUBLIC_ORIGIN=https://deployed.openbot.test` and `WEB_PORT`, so the regression is proven against a hosted origin. + - `playwright.config.ts`: harness env gets `PUBLIC_ORIGIN=https://deployed.dispatch.test` and `WEB_PORT`, so the regression is proven against a hosted origin. - `tests/e2e/workspace.spec.ts`: proxied `/auth/login` must return `302` with `redirect_uri=http://127.0.0.1:/auth/callback`. - `.changeset/fix-local-oauth-callbacks.md`: patch for the fixed version group. - Proof - `pnpm check`: 0 errors, 6 pre-existing `unbound-method` warnings in `cli/src/initialization.test.ts`. - `pnpm build`: passed with `verify:packages` and `verify:cli`. - - `@tryopenbot/control-service` tests: 15/15. `@tryopenbot/auth-provider` tests: 4/4. + - `@trytilde/dispatch-control-service` tests: 15/15. `@trytilde/dispatch-auth-provider` tests: 4/4. - `pnpm test:e2e`: 6/6 on idle host. Two earlier runs under heavy concurrent CPU load each flaked one unrelated chat-UI test; both passed on rerun, and an unmodified `upstream/main` baseline run in the same worktree passed 6/6. # Critical to apply to forks @@ -60,7 +60,7 @@ Every fork that keeps a deployed control service and develops locally hits the b Fork action: -- Take this update, then run `openbot dev` once so `TildeAuthProvider` reconciliation registers `http://localhost:/auth/callback` and `http://127.0.0.1:/auth/callback` on the installation's Tilde client. Registration is idempotent and additive; the deployment callback survives. +- Take this update, then run `tilde dev` once so `TildeAuthProvider` reconciliation registers `http://localhost:/auth/callback` and `http://127.0.0.1:/auth/callback` on the installation's Tilde client. Registration is idempotent and additive; the deployment callback survives. - Keep production `PUBLIC_ORIGIN` as is. Do not delete it to work around the old behavior. - Set `WEB_PORT` when the fork's web dev server does not use `4173`. Other ports fall back to the old control-origin callback. - Custom control-service composition must pass `devMode` and `environment` into `createApp`, because `registerOwnerAuth` and `requireOwner` now read them from options instead of `process.env`. Calls with the old two-argument shape still compile, but lose the dev behavior. diff --git a/docs/updates/47.md b/docs/updates/47.md index f49a6b70..199aceed 100644 --- a/docs/updates/47.md +++ b/docs/updates/47.md @@ -1,6 +1,6 @@ # Intent of the change -- Give OpenBot a second owner client without duplicating chat behavior a third time. +- Give Dispatch a second owner client without duplicating chat behavior a third time. - Move Tilde transport, SSE reconciliation, conversation state, and UI-facing wire types out of the web screen into one framework-neutral package every client consumes. - Add an Expo iOS and Android client that selects its control service, authenticates with PKCE, and streams conversations. - Rename `computer-provider` to `computer-service-provider` and remove the `computer-tools` re-export that let callers reach a runtime utility through a provider. @@ -33,10 +33,10 @@ flowchart TD - `packages/client-runtime` — new. Grouped Zod contracts by capability (installation, auth, sidebar, messages, events, queue, attachments, platform), REST/SSE client, pure event reducers, Zustand vanilla store. - `apps/mobile` — new Expo client. Control-service selection, PKCE sign-in, sidebar, streaming chat, send, stop, sign-out. BNA UI components vendored under `src/components/ui` with provenance. `scripts/toolchain.mjs` and `scripts/expo.mjs` resolve the Android SDK and a real Node binary; `scripts/android-emulator.mjs` boots a headless emulator behind Xvfb with loopback VNC. -- `apps/web` — migrated onto the runtime. `src/chat-api.ts` deleted; roughly thirty component-level state variables in `screens/openbot-app.tsx` replaced by runtime state. New `src/runtime.ts` and `src/web-attachments.ts`. +- `apps/web` — migrated onto the runtime. `src/chat-api.ts` deleted; roughly thirty component-level state variables in `screens/dispatch-app.tsx` replaced by runtime state. New `src/runtime.ts` and `src/web-attachments.ts`. - `apps/desktop` — consumes shared authentication and preload bridge contracts. - `apps/control-service` — adds the public `/auth/native-config` endpoint. -- `packages/computer-service-provider` — renamed from `computer-provider`. Root provider API only; `./tools` export and the `@tryopenbot/computer-tools` dependency removed. +- `packages/computer-service-provider` — renamed from `computer-provider`. Root provider API only; `./tools` export and the `@trytilde/dispatch-computer-tools` dependency removed. - `packages/auth-provider` — native PKCE configuration surfaced for the mobile flow. Merged with PR 45: `registerOwnerAuth` keeps that PR's `OwnerAuthOptions` dev-mode callback handling and gains the `/auth/native-config` route, and the browser E2E auth stub keeps its `redirect_uri` echo alongside the native configuration stub. - `docs/adrs/0017` — new. ADR-0004, ADR-0010, ADR-0014, ADR-0016 amended. - `AGENTS.md`, `CONTEXT.md`, `README.md`, `.agents/skills/**` — runtime-mandatory rule, cross-client parity gate in `create-pr`, new `run-expo` skill, vendored `frontend-design`, and the `expo/skills` set tracked in `skills-lock.json`. @@ -47,8 +47,8 @@ yes Two reasons. -**Breaking package rename.** A fork importing `@tryopenbot/computer-provider` will not resolve. Rename the dependency to `@tryopenbot/computer-service-provider` in every `package.json` and import site, including `configuration/index.ts` and any custom provider under `configuration/providers/`. The `./tools` subpath export is gone: import `@tryopenbot/computer-tools` directly wherever a fork reached tools through the provider. Run `pnpm install` and `pnpm check`, then `pnpm build` to confirm no `dist/tools` entry is expected. +**Breaking package rename.** A fork importing `@trytilde/dispatch-computer-provider` will not resolve. Rename the dependency to `@trytilde/dispatch-computer-service-provider` in every `package.json` and import site, including `configuration/index.ts` and any custom provider under `configuration/providers/`. The `./tools` subpath export is gone: import `@trytilde/dispatch-computer-tools` directly wherever a fork reached tools through the provider. Run `pnpm install` and `pnpm check`, then `pnpm build` to confirm no `dist/tools` entry is expected. -**New client boundary.** A fork that customized `apps/web/src/chat-api.ts` or the conversation state in `apps/web/src/screens/openbot-app.tsx` will conflict: the first file is deleted and the second is largely replaced. Port those customizations into `packages/client-runtime` rather than back into the web screen, because web, Electron, and Expo now share that implementation. A fork adding UI state should read `AGENTS.md` first — network-crossing, persisted, or multi-client state belongs in the runtime; presentation-only state stays in the component. +**New client boundary.** A fork that customized `apps/web/src/chat-api.ts` or the conversation state in `apps/web/src/screens/dispatch-app.tsx` will conflict: the first file is deleted and the second is largely replaced. Port those customizations into `packages/client-runtime` rather than back into the web screen, because web, Electron, and Expo now share that implementation. A fork adding UI state should read `AGENTS.md` first — network-crossing, persisted, or multi-client state belongs in the runtime; presentation-only state stays in the component. Forks that only track upstream and do not customize the web client or the computer provider need no action beyond `pnpm install`. diff --git a/docs/updates/48.md b/docs/updates/48.md index 2301f516..b68e45a2 100644 --- a/docs/updates/48.md +++ b/docs/updates/48.md @@ -1,7 +1,7 @@ # Intent of the change - Give the four-target mobile development topology one owner with tests: local mac, local Linux, remote mac, remote Linux. -- Move Expo, emulator, and toolchain logic out of untested `apps/mobile/scripts/*.mjs` into the published `openbot` CLI, so fork developers and sandboxed agents get the same versioned tooling. +- Move Expo, emulator, and toolchain logic out of untested `apps/mobile/scripts/*.mjs` into the published Tilde CLI, so fork developers and sandboxed agents get the same versioned tooling. - Make repository gates commands rather than only root scripts. - Keep development-host identity out of package code. - Record that every future developer workflow lands as a CLI command, and enforce it in `create-pr`. @@ -10,7 +10,7 @@ ```mermaid flowchart LR - R["root scripts: dev:mobile:*, connect, dev:remote, doctor"] --> C["openbot CLI"] + R["root scripts: dev:mobile:*, connect, dev:remote, doctor"] --> C["Tilde CLI"] M["apps/mobile scripts"] --> C C -->|"mobile expo, emulator, avd, setup, screenshot, logs, doctor"| L["this machine: mac or linux"] C -->|"check, build, test, e2e, desktop package"| G["repository gates via root scripts"] @@ -18,7 +18,7 @@ flowchart LR C -->|"connect host"| T["ssh tunnel: VNC 5900, Metro 8081, adb 5555"] ``` -- One CLI owns operator commands and developer workflow. A separate `@tryopenbot/dev-cli` package was built and folded back in before publication; ADR-0018's Updates record the reversal. +- One CLI owns operator commands and developer workflow. A separate `@trytilde/dispatch-dev-cli` package was built and folded back in before publication; ADR-0018's Updates record the reversal. - Gates delegate to the root `package.json` scripts, which stay the single definition of what each gate runs. The CLI never duplicates a `vp` command line. - `cli/src/toolchain.ts` resolves the Android SDK and takes Node from `process.execPath`, because Gradle shells out to `node` while evaluating settings and fails on a version-manager shim. - Host names, addresses, platforms, and paths live in fork-owned `configuration/dev-hosts.json`. Package code carries no machine identity. @@ -27,23 +27,23 @@ flowchart LR # Summarized package changes - `cli` — new modules `toolchain.ts`, `workspace.ts`, `hosts.ts`, `tunnel.ts` and commands `mobile/` (expo, emulator, avd, setup, screenshot, logs, doctor), `connect.ts`, `remote.ts`. Dispatch gains `e2e` and `desktop package`; `delegate` is split so package-filtered scripts can be delegated too. Tests rise from 66 to 77. `README.md` documents the full command surface and the `dev-hosts.json` shape. -- `apps/mobile` — `scripts/*.mjs` deleted; package scripts delegate to `openbot`. No source change. +- `apps/mobile` — `scripts/*.mjs` deleted; package scripts delegate to `tilde`. No source change. - root `package.json` — verb:target taxonomy: `dev:mobile`, `dev:mobile:android`, `dev:mobile:ios`, `dev:mobile:emulator`, `connect`, `dev:remote`, `doctor`. - `docs/adrs/0018-developer-workflow-cli.md` — new decision with its full revision history. - `AGENTS.md`, `README.md`, `apps/mobile/README.md`, `.agents/skills/run-expo/SKILL.md` — rewritten around the CLI commands. - `.agents/skills/create-pr/SKILL.md` — new CLI ownership gate, step 6 of the required order. -- `.changeset/fix-local-oauth-callbacks.md` — repaired: it arrived on `main` with PR 45 naming the pre-rename `@tryopenbot/computer-provider`, which broke `pnpm changeset status` for everyone. +- `.changeset/fix-local-oauth-callbacks.md` — repaired: it arrived on `main` with PR 45 naming the pre-rename `@trytilde/dispatch-computer-provider`, which broke `pnpm changeset status` for everyone. # Critical to apply to forks yes -**A fork that customized the mobile scripts must move that work.** `apps/mobile/scripts/expo.mjs`, `toolchain.mjs`, and `android-emulator.mjs` are deleted. Their behavior now lives in `cli/src/toolchain.ts` and `cli/src/commands/mobile/`. A fork that edited those files — a different SDK path, extra emulator flags, a different AVD — will see the files vanish on merge and must reapply the change in the CLI. `pnpm --filter @tryopenbot/mobile dev`, `android`, `ios`, `build`, and `start` keep working unchanged, because only their script bodies moved. +**A fork that customized the mobile scripts must move that work.** `apps/mobile/scripts/expo.mjs`, `toolchain.mjs`, and `android-emulator.mjs` are deleted. Their behavior now lives in `cli/src/toolchain.ts` and `cli/src/commands/mobile/`. A fork that edited those files — a different SDK path, extra emulator flags, a different AVD — will see the files vanish on merge and must reapply the change in the CLI. `pnpm --filter @trytilde/dispatch-mobile dev`, `android`, `ios`, `build`, and `start` keep working unchanged, because only their script bodies moved. -**Root script names changed.** Anything automating the old `pnpm --filter @tryopenbot/mobile emulator` should call `pnpm dev:mobile:emulator` or `openbot mobile emulator`. CI that shells the mobile scripts directly needs no change. +**Root script names changed.** Anything automating the old `pnpm --filter @trytilde/dispatch-mobile emulator` should call `pnpm dev:mobile:emulator` or `tilde mobile emulator`. CI that shells the mobile scripts directly needs no change. **Remote development hosts are new fork-owned configuration.** A fork that develops on remote machines creates `configuration/dev-hosts.json` with its own `{ "hosts": { "": { "ssh", "platform", "path" } } }`. It stays untracked upstream and must never be committed to `trytilde/dispatch`. Without it, `connect` and `remote` still accept a raw `user@host`. -**Check the changeset repair.** A fork carrying its own copy of `.changeset/fix-local-oauth-callbacks.md` from PR 45 has the same broken package name and the same `pnpm changeset status` failure; rename `@tryopenbot/computer-provider` to `@tryopenbot/computer-service-provider` there too. +**Check the changeset repair.** A fork carrying its own copy of `.changeset/fix-local-oauth-callbacks.md` from PR 45 has the same broken package name and the same `pnpm changeset status` failure; rename `@trytilde/dispatch-computer-provider` to `@trytilde/dispatch-computer-service-provider` there too. Run `pnpm install`, then `pnpm doctor` to confirm the toolchain, then `pnpm check` and `pnpm build`. diff --git a/docs/updates/49.md b/docs/updates/49.md index c1660c47..232c669a 100644 --- a/docs/updates/49.md +++ b/docs/updates/49.md @@ -1,8 +1,8 @@ # Intent of the change -- Make `@tryopenbot/ui` own every identifier and every user-visible string it ships. No naming inherited from the reference build the components were recovered from. -- Move the workspace class families onto the `ob-` prefix already used by the package's `--ob-*` design tokens. One prefix, one owner. -- Reword carried-over interface copy — aria labels, panel titles, status lines, permission dialog text, composer placeholder — into OpenBot wording. +- Make `@trytilde/dispatch-ui` own every identifier and every user-visible string it ships. No naming inherited from the reference build the components were recovered from. +- Move the workspace class families onto the `dispatch-` prefix already used by the package's `--dispatch-*` design tokens. One prefix, one owner. +- Reword carried-over interface copy — aria labels, panel titles, status lines, permission dialog text, composer placeholder — into Dispatch wording. - Remove the hardcoded personal-name account placeholder from the sidebar. - Leave the MIT-licensed `beautiful-ui/upstream/` tree pristine so the per-file SHA-256 values in `packages/ui/src/beautiful-ui/PROVENANCE.md` still verify. - Rename and reword only. No behavior, no markup structure, no component API change. @@ -14,21 +14,21 @@ Boundaries unchanged. Ownership of names and strings changed. ```mermaid flowchart LR A["apps/web and apps/desktop renderer"] --> U["packages/ui authored components"] - U -->|"ob-* class names"| S["openbot-ui.css: ob-* selectors, --ob-* tokens"] - U -->|"OpenBot-authored strings"| C["visible copy: titles, aria labels, placeholders, status text"] + U -->|"dispatch-* class names"| S["dispatch-ui.css: dispatch-* selectors, --dispatch-* tokens"] + U -->|"Dispatch-authored strings"| C["visible copy: titles, aria labels, placeholders, status text"] U -->|"import only, files untouched"| V["beautiful-ui/upstream: MIT, pristine SHAs"] ``` -- `ob-` is now the single class prefix for OpenBot-authored UI. It matches the `--ob-*` custom properties that already existed in `openbot-ui.css`; the file previously mixed `--ob-*` tokens with `ui-*` selectors. +- `dispatch-` is now the single class prefix for Dispatch-authored UI. It matches the `--dispatch-*` custom properties that already existed in `dispatch-ui.css`; the file previously mixed `--dispatch-*` tokens with `ui-*` selectors. - Renamed families: `ui-markdown__*`, `ui-code-block*`, `ui-default-code*`, `ui-default-diff*`, `ui-mermaid-diagram*`, `ui-expandable-node__*`, `ui-dialog*`, `ui-status-badge`, `ui-indicator-dot`, `ui-kbd`, `ui-input-group__*`, `ui-select-*`, `ui-scroll-area__*`, `ui-text-roll__*`, `ui-voice-waveform`, `ui-model-picker__*`. - Not renamed: `ui-sans-serif` and `ui-monospace` in the `--font-sans` / `--font-mono` stacks. Those are CSS generic font-family keywords, not class names. -- Not renamed: structural class names that were already OpenBot-authored — `diagram-card`, `diagram-modal-*`, `dialog-layer`, `dialog-surface`, `agent-row-marker`, `local-tool-permission-dock`, `markdown`, `md-citation-btn`. Several elements keep a structural class plus the renamed `ob-` class. +- Not renamed: structural class names that were already Dispatch-authored — `diagram-card`, `diagram-modal-*`, `dialog-layer`, `dialog-surface`, `agent-row-marker`, `local-tool-permission-dock`, `markdown`, `md-citation-btn`. Several elements keep a structural class plus the renamed `dispatch-` class. - `beautiful-ui/upstream/` is outside this change. Its files carry a third-party MIT license and recorded hashes; renaming inside them would break `PROVENANCE.md` verification. - No DOM structure, no props, no exported symbol, no CSS declaration value changed. Pure identifier and string substitution. # Summarized package changes -- `packages/ui/src/openbot-ui.css` — 100 selector renames `ui-*` → `ob-*` across markdown, code block, diff, badge, dot, kbd, input group, select, scroll area, text roll, voice waveform, and model picker rules. Font-family keywords untouched. +- `packages/ui/src/dispatch-ui.css` — 100 selector renames `ui-*` → `dispatch-*` across markdown, code block, diff, badge, dot, kbd, input group, select, scroll area, text roll, voice waveform, and model picker rules. Font-family keywords untouched. - `packages/ui/src/markdown-components.tsx` — 40 class renames. Full markdown element map (`h1`–`h6`, lists, tables, links, images, inline code, blockquote, hr, task marker) plus code block and diff block shells. - `packages/ui/src/primitive-components.tsx` — 25 class renames: status badge, indicator dot, kbd, input group, select, scroll area, text roll, voice waveform, model picker trigger and menu. - `packages/ui/src/content-components.tsx` — 10 class renames (code block, mermaid diagram, expandable-node modal); copy: computer takeover aria label and button, request-skip tooltip. @@ -46,7 +46,7 @@ flowchart LR yes -**A fork that styles or selects `@tryopenbot/ui` markup breaks silently.** Every `ui-*` class the package renders is now `ob-*`. A fork-owned stylesheet, theme override, snapshot test, Playwright locator, or `querySelector` targeting `.ui-markdown__link`, `.ui-code-block`, `.ui-model-picker__menu`, `.ui-dialog`, `.ui-input-group__input`, `.ui-scroll-area__viewport`, `.ui-status-badge`, `.ui-text-roll__item`, or any sibling name stops matching. This is not a type error and not a lint error — `pnpm typecheck` and `pnpm lint` stay green while the fork's styling silently drops. Rewrite those selectors `ui-` → `ob-`. +**A fork that styles or selects `@trytilde/dispatch-ui` markup breaks silently.** Every `ui-*` class the package renders is now `dispatch-*`. A fork-owned stylesheet, theme override, snapshot test, Playwright locator, or `querySelector` targeting `.ui-markdown__link`, `.ui-code-block`, `.ui-model-picker__menu`, `.ui-dialog`, `.ui-input-group__input`, `.ui-scroll-area__viewport`, `.ui-status-badge`, `.ui-text-roll__item`, or any sibling name stops matching. This is not a type error and not a lint error — `pnpm typecheck` and `pnpm lint` stay green while the fork's styling silently drops. Rewrite those selectors `ui-` → `dispatch-`. **Do not blanket-replace `ui-` in CSS.** `ui-sans-serif` and `ui-monospace` are generic font keywords in the `--font-sans` and `--font-mono` stacks. Renaming them breaks font resolution. Scope the replacement to class selectors. @@ -56,6 +56,6 @@ yes **Sidebar account default changed.** The account name default is `"Your account"`, not a person's name. A fork relying on the old default to render a demo identity must pass its own `name` prop. -**Keep the boundary.** Do not reintroduce reference-build class names or interface copy when merging upstream or reapplying local patches. OpenBot-authored surfaces carry OpenBot-authored names and OpenBot-authored wording. +**Keep the boundary.** Do not reintroduce reference-build class names or interface copy when merging upstream or reapplying local patches. Dispatch-authored surfaces carry Dispatch-authored names and Dispatch-authored wording. Run `pnpm typecheck` and `pnpm lint`, then visually verify the workspace, markdown rendering, code blocks, dialogs, and model picker — the renames are invisible to static checks. diff --git a/docs/updates/50.md b/docs/updates/50.md index dd56d5c0..4d98b29d 100644 --- a/docs/updates/50.md +++ b/docs/updates/50.md @@ -12,23 +12,23 @@ flowchart LR X["index.ts export surface"] --> S["components/ui: shadcn primitives"] X --> A["components/ai-elements: Vercel AI Elements"] X --> U["beautiful-ui/upstream: pristine vendored files"] - X --> T["beautiful-ui/atoms: OpenBot-authored reconstructions"] + X --> T["beautiful-ui/atoms: Dispatch-authored reconstructions"] U -. "per-file SHA-256 + recorded drift" .-> P["beautiful-ui/PROVENANCE.md"] S -. "license + modification record" .-> N["THIRD_PARTY_NOTICES.md"] A -.-> N M["markdown-components.tsx"] --> D["streamdown"] ``` -- Three vendored layers, one discipline. `upstream/` stays pristine except recorded drift (analytics call removed, import paths rewritten); every file's retrieval SHA-256 lives in `PROVENANCE.md`. `atoms/` (Button, GlideMenu, Shimmer, StreamText) are OpenBot-authored reconstructions — upstream never published its atom source. shadcn and AI Elements copies record their modifications in `THIRD_PARTY_NOTICES.md`. +- Three vendored layers, one discipline. `upstream/` stays pristine except recorded drift (analytics call removed, import paths rewritten); every file's retrieval SHA-256 lives in `PROVENANCE.md`. `atoms/` (Button, GlideMenu, Shimmer, StreamText) are Dispatch-authored reconstructions — upstream never published its atom source. shadcn and AI Elements copies record their modifications in `THIRD_PARTY_NOTICES.md`. - `components.json` pins the shadcn registry config (new-york style, lucide, `src/components/ui` alias) so later `shadcn add` pulls land in the same tree. -- shadcn `accent` utilities remapped to `hover`/`ink` tokens because Beautiful UI already owns `--color-accent`. `dialog.tsx`, `command.tsx`, `dropdown-menu.tsx` are OpenBot-authored on Radix/cmdk, not registry copies. +- shadcn `accent` utilities remapped to `hover`/`ink` tokens because Beautiful UI already owns `--color-accent`. `dialog.tsx`, `command.tsx`, `dropdown-menu.tsx` are Dispatch-authored on Radix/cmdk, not registry copies. - Superseded upstream duplicates removed: `chat.tsx` → `chat-composer.tsx`, `thinking.tsx` → `thinking-state.tsx`. - Two modules land here inert, wired later in the stack: `theme.ts` (activated by PR 51) and `agent-avatar-assets.ts` (consumed by PR 52). Stack-split artifact, deliberate. - Not vendored: upstream `insight-cards` and `selection-actions` (extra dependencies). Re-extract the same way if needed. # Summarized package changes -- `packages/ui` — new trees `src/components/ui/` (15 shadcn primitives), `src/components/ai-elements/` (8 chat components), `src/beautiful-ui/upstream/` refreshed from live source plus new `atoms/`. `index.ts` export surface grows (Command/Dialog/DropdownMenu groups, AI Elements groups, atoms, `cn`, theme API module added but unexported here). `markdown-components.tsx` rewritten on Streamdown with token utility classes; `ob-code-block*` class markup gone. Dependencies added: `radix-ui`/`@radix-ui/*`, `cmdk`, `streamdown` + `@streamdown/{cjk,code,math,mermaid}`, `shiki`, `motion`, `class-variance-authority`, `clsx`, `tailwind-merge`, `lucide-react`, `glimm`, `ai`, `nanoid`, `use-stick-to-bottom`. Removed: `react-markdown`, `remark-gfm`. `components.json` new. Stories updated. +- `packages/ui` — new trees `src/components/ui/` (15 shadcn primitives), `src/components/ai-elements/` (8 chat components), `src/beautiful-ui/upstream/` refreshed from live source plus new `atoms/`. `index.ts` export surface grows (Command/Dialog/DropdownMenu groups, AI Elements groups, atoms, `cn`, theme API module added but unexported here). `markdown-components.tsx` rewritten on Streamdown with token utility classes; `dispatch-code-block*` class markup gone. Dependencies added: `radix-ui`/`@radix-ui/*`, `cmdk`, `streamdown` + `@streamdown/{cjk,code,math,mermaid}`, `shiki`, `motion`, `class-variance-authority`, `clsx`, `tailwind-merge`, `lucide-react`, `glimm`, `ai`, `nanoid`, `use-stick-to-bottom`. Removed: `react-markdown`, `remark-gfm`. `components.json` new. Stories updated. - `THIRD_PARTY_NOTICES.md` (root) — Beautiful UI, shadcn/ui, Vercel AI Elements, glimm entries with license and modification records. - `pnpm-lock.yaml` — dependency swap fallout (~4000 lines). @@ -36,11 +36,11 @@ flowchart LR yes -**Renamed public deep imports.** `@tryopenbot/ui/beautiful-ui/*` is an exported wildcard. `beautiful-ui/chat` and `beautiful-ui/thinking` no longer resolve — the files are now `chat-composer.tsx` and `thinking-state.tsx`. Update deep imports; the root exports `BeautifulChatComposer` and `ThinkingState` unchanged. +**Renamed public deep imports.** `@trytilde/dispatch-ui/beautiful-ui/*` is an exported wildcard. `beautiful-ui/chat` and `beautiful-ui/thinking` no longer resolve — the files are now `chat-composer.tsx` and `thinking-state.tsx`. Update deep imports; the root exports `BeautifulChatComposer` and `ThinkingState` unchanged. -**Removed dependencies.** `react-markdown` and `remark-gfm` left `@tryopenbot/ui`. Fork code that imported them transitively must declare its own dependency or move to Streamdown. +**Removed dependencies.** `react-markdown` and `remark-gfm` left `@trytilde/dispatch-ui`. Fork code that imported them transitively must declare its own dependency or move to Streamdown. -**Markdown markup changed.** `CodeBlock` and friends dropped the `ob-code-block*` class names for token utilities. Fork CSS targeting those selectors stops matching. Restyle against the token utilities (PR 51 defines the palette). +**Markdown markup changed.** `CodeBlock` and friends dropped the `dispatch-code-block*` class names for token utilities. Fork CSS targeting those selectors stops matching. Restyle against the token utilities (PR 51 defines the palette). **Vendored-tree discipline.** Do not edit `beautiful-ui/upstream/` in a fork without recording the change in `PROVENANCE.md`; the per-file SHAs are the audit trail. Fork-authored composition belongs outside `upstream/`. diff --git a/docs/updates/51.md b/docs/updates/51.md index 8125b0f4..bb4e2c7c 100644 --- a/docs/updates/51.md +++ b/docs/updates/51.md @@ -1,7 +1,7 @@ # Intent of the change - Give the workspace UI one palette with two schemes. Second PR of the 7-PR stack. Foundation, not surface. -- Own the token *values*. PR 50 vendored the component sources and their `@theme inline` utility mapping; the colours themselves were never OpenBot's. Now they are. +- Own the token *values*. PR 50 vendored the component sources and their `@theme inline` utility mapping; the colours themselves were never Dispatch's. Now they are. - Activate dark mode. `.dark` existed in the vendored `beautiful-ui/upstream/globals.css` and in `theme.ts` (landed inert in PR 50); nothing ever toggled the class. `initTheme()` in the web entry does. - Fix a cascade defect. Bare `button`/`h1` element resets outranked component utilities. `text-[12.5px]` on a `