summaryrefslogtreecommitdiffhomepage
path: root/bin
AgeCommit message (Collapse)Author
3 daysfix(install): restart service instead of start (no-op when already running)devAdam Malczewski
3 daysfix(install): run build as user, sudo only on privileged linesAdam Malczewski
The script previously required sudo for the entire script (id -u check), which meant bin/build ran as root and created root-owned dist/ files. On the next build, the normal user couldn't overwrite them (EACCES). Now the script runs without a sudo prefix: the build step runs as the normal user (dist/ files are user-owned), and sudo is used only on the specific lines that write to system directories (/usr/bin, /etc, /usr/share) or call systemctl.
3 daysfix(build): run tsc --build before bun build --compileAdam Malczewski
bin/build was compiling the binary directly from stale dist/*.js files without first recompiling the TypeScript packages. Since package.json main fields point to dist/index.js, source edits to .ts files were silently lost in the compiled binary. Now tsc --build runs first (composite project references rebuild all packages in dependency order), then bun build --compile bundles the fresh dist/ output.
4 daysfix(bin): pin dev ports in bin/up so shell BACKEND_PORT can't override .envAdam Malczewski
bin/up ran `bun --watch main.ts` without setting BACKEND_PORT, so a shell-exported BACKEND_PORT (e.g. 24991 in ~/.bashrc, set so the Dispatch CLI hits the prod server) overrode .env's dev value 24203 — Bun lets shell env win over .env — binding the dev server onto the production port and colliding with the active dispatch-server systemd service. transport-http then failed to activate (Bun.serve "port in use"), so the HTTP server never came up and the frontend got "Failed to fetch". Force BACKEND_PORT=24203 + SURFACE_WS_PORT=24205 in the setsid invocation so the dev stack is deterministic regardless of the shell environment.
5 daysfix(kernel+tool-shell): abort hanging tool calls without bricking the ↵Adam Malczewski
conversation kernel: executeToolCall now races tool.execute against the abort signal via Promise.race; on abort resolves (not rejects) with an "Aborted" result so the step completes normally → finishReason "aborted" → turn seals cleanly (done event) → finally clears activeTurns → conversation freed, next message accepted. run-turn strips tool-call chunks from the assistant message on abort (keeps text/thinking) and omits tool-result messages to avoid persisting dangling tool calls that would 400 the provider next turn. tool-shell: realSpawn spawns detached (own process group); on abort AND timeout kills the entire group (process.kill(-pgid, SIGKILL)) and resolves immediately — no child.on("close") dependency, so a grandchild holding the pipes can't stall the spawn promise or leak. Also: ORCHESTRATOR.md migrated to dispatch CLI summon mechanism; .skills summary; bin/sync-env PATH injection; frontend handoff docs. 1453 vitest pass · tsc -b EXIT 0 · biome clean.
7 daysdocs: mark roadmap items 9 (tab persistence) + 10 (compacting) as DONEAdam Malczewski
Also adds bin/sync-env script for updating system env keys.
8 daysfix(install): write service file directly instead of sed (slashes broke it)Adam Malczewski
The sed substitution failed because the comment line contained '/' chars. Now writes the service file via heredoc with User=/Group= patched in. Also removes any previous masked service file first.
8 daysfeat(install): run dispatch service as user, not rootAdam Malczewski
systemd service: User= and Group= patched by bin/install from SUDO_USER. bin/setup-env: chowns data dirs to the real user. Since the service runs as the user, os.homedir() resolves correctly for skills discovery — no separate HOME env var needed.
8 daysfix(setup-env): set HOME so skills discovery works under systemdAdam Malczewski
The skills extension scans ~/.skills/ via os.homedir(). Under systemd as root, this resolves to /root — no skills there. setup-env now resolves the real user's home via SUDO_USER and writes HOME=<user home> to /etc/dispatch/env.
8 daysfeat: standalone build + systemd install (Arch Linux)Adam Malczewski
bin/build: compiles standalone binaries (dispatch-server + dispatch CLI) via bun build --compile, builds the frontend static bundle with VITE_HTTP_PORT=24991 + VITE_WS_PORT=24990, copies to dist/web/. bin/install: installs binaries to /usr/bin/, frontend to /usr/share/dispatch/web/, systemd service to /etc/systemd/system/, config to /etc/dispatch/env, data dirs to /var/lib/dispatch/ + /var/log/dispatch/. Enables + starts the dispatch systemd service. Supports --uninstall and --no-build flags. systemd/dispatch.service: Type=simple, reads /etc/dispatch/env, restarts on failure, logs to journald. systemd/dispatch.env: template config (ports 24991 HTTP + 24990 WS, DISPATCH_WEB_DIR, API key, data paths). transport-http: optional webDir static file serving — unmatched GET requests fall through to Bun.file() serving with SPA index.html fallback. Gated on DISPATCH_WEB_DIR env var (backward compatible).
2026-06-06feat(frontend,wire): surface system (FE slice 1) + @dispatch/wire types-only ↵Adam Malczewski
split (B2) FE slice 1 — backend-declared, frontend-agnostic surface system (verified live): new types-only @dispatch/ui-contract (SurfaceSpec / field kinds / region / ActionRef / catalog), surface-registry (typed service handle), transport-ws (Bun WS :24205, path-agnostic upgrade), surface-loaded-extensions (first real surface); kernel HostAPI.getExtensions; host-bin wiring; bin/up. Harness: retire AGENTS 'backend only', ORCHESTRATOR §3/§7/§8, frontend-design.md locked. B2 — wire-types split (chat-slice prerequisite): new types-only @dispatch/wire single-sources the wire ABI (AgentEvent + 11 variants; conversation model Chunk/ChatMessage/Role/TurnId/StepId + 6 chunk variants; Usage) with zero @dispatch/* deps. @dispatch/kernel re-exports via shims so its public surface is byte-identical (zero consumer blast radius). transport-contract re-exports AgentEvent from @dispatch/wire and drops its @dispatch/kernel dependency, so HTTP clients (the web frontend) consume the wire without the kernel runtime. tsc -b + biome clean; 460 vitest + 77 bun pass.
2026-06-04chore: genesis — remove all files to rebuild from scratch (arch rewrite)Adam Malczewski
2026-06-03chore(bin/up): DEBUG=1 writes LLM debug logs to /app/logging (host: logging/)Adam Malczewski
Add a DEBUG=1 convenience flag to bin/up that turns on full LLM debug logging (DISPATCH_DEBUG_LLM) plus the per-step usage/cache split (DISPATCH_DEBUG_USAGE) and routes the JSON request/response files into the container's /app/logging, which maps to the project-root logging/ dir on the host via the existing .:/app bind mount. This makes it easy to verify cache hits (including the prompt-cache warming replay) without docker exec. - bin/up: DEBUG=1 sets DISPATCH_DEBUG_LLM/_USAGE=1 and DISPATCH_DEBUG_LLM_DIR= /app/logging as DEFAULTS (explicit DISPATCH_DEBUG_* still win). Pre-creates the host log dir; /app/* targets are already host-owned so no sudo chown, while the /tmp fallback keeps its ownership fix. - docker-compose.yml: forward DISPATCH_DEBUG_LLM_DIR into the api container. - .gitignore: ignore logging/.
2026-06-02Fix build scripts and deployment port issueAdam Malczewski
2026-06-02build(pkg): provision cs for native installs via a 'code-search' split packageAdam Malczewski
The Docker path (bin/up) already builds and bundles cs, but the native package path (bin/service install -> bin/build-pkg -> makepkg) did not, so search_code would have no cs binary under a systemd/s6 install and fall back to its 'cs not found' error. - packaging/PKGBUILD: add 'code-search' to the split pkgname array; add go+git to makedepends; build the patched, statically-linked cs (pinned v3.1.0 commit + docker/cs/luau-declarations.patch) in build(); install it to /usr/bin/cs via a dedicated package_code-search() (with the upstream MIT LICENSE). Pin kept in lockstep with the Dockerfiles. - bin/install-pkg: install code-search alongside dispatch + dispatch-systemd by default (and under --all). Verified: full run produces code-search-0.0.1-1-x86_64.pkg.tar.zst containing a working /usr/bin/cs (v3.1.0, static) with Luau declaration detection; the dispatch package no longer contains cs. Tests (598) + biome still pass.
2026-05-31feat(debug): wire LLM debug logger end-to-endAdam Malczewski
The debug-logger.ts module existed but was completely orphaned — none of its functions had any callsites, so DISPATCH_DEBUG_LLM=1 did nothing. Wires it in across the stack: - llm/debug-logger.ts: add wrapFetchWithLogging() that tees SSE bodies via TransformStream + response.clone() so we capture every chunk without draining the body the AI SDK consumes. Redacts authorization / x-api-key / cookie headers in logs. Also exports nextDebugSeq() so requests and log files share an id. - llm/provider.ts: all 3 factories (Claude OAuth, plain-API-key Anthropic, OpenAI-compatible) now pass fetch: wrapFetchWithLogging(globalThis.fetch). For Claude OAuth the wrap goes on the inner base fetch so logged bodies reflect the post-transform shape + Claude-Code session headers. Added tabId to ProviderConfig for log labelling. - agent/agent.ts: threads tabId through createProvider and emits logAgentLoop / logStepLifecycle / logStreamEvent at every meaningful point in the run loop — step start/end, tool count, every fullStream event. All are no-ops when DISPATCH_DEBUG_LLM is unset. - core/index.ts: re-exports the debug helpers. - tests/llm/provider.test.ts: switch one full-object equality assertion to property assertions so the test survives the new fetch: wrapper. Plumbing the env var into the container required three more fixes: - bin/up: re-export DISPATCH_DEBUG_LLM* so docker compose forwards them (compose only forwards vars referenced in the environment: block). Also pre-creates /tmp/dispatch/llm-debug and chowns it on first run so the container's UID-1000 bun process can write into it without EACCES. - docker-compose.yml: declare the debug vars on api.environment and bind-mount /tmp/dispatch/llm-debug:/tmp/dispatch/llm-debug so logs are inspectable from the host without docker exec. - docker/entrypoint.dev.sh: explicitly forward DISPATCH_DEBUG_* through the 'su -' login-shell barrier — su - resets the environment to TERM/ PATH/HOME/SHELL/USER/LOGNAME only, silently stripping everything else. This is why the vars appeared via 'docker exec env' (which spawns a new process inheriting the container env) but were absent from the actual bun process's /proc/<pid>/environ. bin/build: drop stray sudo for consistency with bin/up and bin/down.
2026-05-29fix(packaging): convert dispatch-systemd from user units to system template ↵Adam Malczewski
units (User=%i) The per-user systemd manager ([email protected]) fails to start on WSL (kernel 6.6.87.2, microsoft/WSL#13186 — 'Failed to spawn executor: Device or resource busy'), which breaks pacman's 30-systemd-daemon-reload-user.hook on install. Changes: - New [email protected] + [email protected] system template units with User=%i (run as the named instance user) - Remove old user-scope dispatch-api.service / dispatch-frontend.service - Install to /usr/lib/systemd/system/ instead of .../systemd/user/ - Update PKGBUILD, .install hints, and bin/service to use sudo systemctl dispatch-api@<user>
2026-05-28feat: add agent status indicator in chat input, db tabs tests, and service ↵Adam Malczewski
management script
2026-05-27refactor(packaging): split into dispatch/dispatch-systemd/dispatch-s6, ↵Adam Malczewski
separate dispatch-electron, add bun-based frontend serve PKGBUILD is now a split package producing three .pkg.tar.zst files in one makepkg run: - dispatch base application files (/opt/dispatch), CLI wrappers (dispatch-api, dispatch-frontend), env configs (/etc/dispatch/dispatch-api.conf, /etc/dispatch/dispatch-frontend.conf) - dispatch-systemd systemd user units for dispatch-api + dispatch-frontend (conflicts with dispatch-s6) - dispatch-s6 s6-rc service pipelines (-srv + -log) for both services (conflicts with dispatch-systemd) The Electron desktop wrapper moved to its own self-contained PKGBUILD at packaging/electron/, producing dispatch-electron. It bundles its own copy of the frontend dist + electron entry points under /opt/dispatch-electron and does not depend on the base dispatch package, so users can install it standalone and point VITE_API_URL at any backend at build time. Files under packaging/ are now read directly from ${_projectdir}/packaging/ rather than via source=(); the two s6 service dirs share basenames (run, type) which would collide inside ${srcdir}. New frontend static server: packages/frontend/serve.ts uses Bun's built-in HTTP server (no extra runtime deps) with SPA fallback to index.html and path-traversal protection. PORT/HOST/DIST_DIR overridable via env. Exposed as 'bun run --cwd packages/frontend serve' and via /usr/bin/dispatch-frontend. Build scripts: - bin/build-pkg now prints the freshest built packages - bin/install-pkg installs dispatch + dispatch-systemd by default; accepts package names or --all; searches both packaging/ and packaging/electron/ - bin/build-pkg-electron new, builds the electron split - bin/build-pkg-windows replaces bin/windows-pkg; drops the hard-coded WSL copy step, just prints the win-unpacked path .gitignore extended to cover packaging/*.tar.zst and packaging/electron/{src,pkg,*.pkg.tar.zst,*.tar.zst}.
2026-05-23feat: add is_subagent flag to agents, fix all lint/type/test issuesAdam Malczewski
- Add is_subagent checkbox to agent editor; subagents are hidden from Chat Settings - Add is_subagent field to AgentDefinition type, TOML serialization, and API route - Filter subagents from ModelSelector agent list - Fix all biome lint/format errors across codebase (useLiteralKeys, noNonNullAssertion, noExplicitAny, formatting, import sorting) - Fix svelte-check errors (type narrowing in SkillsBrowser, ToolPermissions, SidebarPanel) - Fix a11y warnings in App.svelte (label-control associations) - Fix test mocks missing BackgroundShellStore, BackgroundTranscriptStore, createWebSearchTool, createYoutubeTranscribeTool - Update stale 409 test to match current message-queuing behavior - Exclude packaging/ and release/ dirs from biome to avoid linting stale build artifacts
2026-05-22feat: Arch Linux packaging with Electron frontend, systemd backend service, ↵Adam Malczewski
and Windows exe build - Add Electron wrapper (main.cjs, preload.cjs) for desktop frontend - Add systemd service unit, env config, and sysusers for backend API - Add PKGBUILD and .install for Arch package (makepkg -si) - Add desktop entry, SVG/PNG icon, and wrapper scripts - Add bin/build-pkg, bin/install-pkg, bin/windows-pkg scripts - Make API port configurable via PORT env var (default 3000, prod 18390) - Add electron-builder config for Windows exe cross-compilation - Set vite base to './' for Electron file:// loading
2026-05-22feat: agent builder, CWD support, auto-save, UI polish, unavailable tool ↵Adam Malczewski
handling - Agent Builder: full CRUD with card grid, drag-and-drop model reorder, edit/delete - Auto-save on edit with 600ms debounce, AbortController for concurrency, fieldset disabled until name entered - Agent definitions stored as TOML with cwd field, loaded from global/project dirs - Working directory: per-tab CWD override in Chat Settings, agent default CWD, auto-create on first message - CWD validation: check-dir endpoint with ~ expansion, real-time validity indicator - Subagent CWD validated against parent's effective CWD using path.relative - Unavailable tool calls: caught gracefully, shown as tool call with error badge, model retries - UI: tab bar border radius, sidebar border removed, chat input ghost style, scroll-to-bottom rectangle - Skills dir collapse uses CSS rotation, Model Choice renamed to Chat Settings, System Prompt view removed - Reusable SkillsBrowser/ToolPermissions with external mode for Agent Builder - ModelSelector: Agent/Manual toggle, agent list, Agent Settings link - Page router, skills recursive scanning, bin/up gopass removed, docker volume mounts
2026-05-21refactor: gut model/tag/fallback/agent-template system, fix Docker setupAdam Malczewski
- Remove ModelResolver, model definitions, model tags, fallback order, agent templates - Remove all [[models]], [agents], and fallback from dispatch.toml and config schema - ModelRegistry is now a pure key-state manager - dispatch.toml reduced to keys + permissions only - Docker: fix entrypoint for existing UID, skip bun install in frontend container - Docker: scoped build cache prune in bin/clean
2026-05-21feat: SQLite database for all credentials, keys, wake schedule, and usage cacheAdam Malczewski
- Add SQLite database at ~/.local/share/dispatch/dispatch.db with tables: credentials, api_keys, wake_schedule, usage_cache - Store Claude OAuth credentials in DB with import button in Model Status UI - Store OpenCode/Copilot API keys in DB with paste-to-import modal - Store OpenCode cookie and workspace IDs in DB - Migrate wake schedule from .wake-schedule.json to DB - Migrate usage cache from in-memory Map + localStorage to DB - Remove all env var and file fallbacks — DB is the single source of truth - Add seed scripts: bin/import-credentials.ts, bin/seed-opencode-keys.ts - Docker: container runs as host UID/GID with matching home directory - Clean up dispatch.toml: remove env fields, update comments - Progress bar time markers for usage cycle tracking
2026-05-20feat: claude max oauth support with multi-account switching, reasoning ↵Adam Malczewski
effort, and dynamic model listing
2026-05-20fix: sidebar layout, copilot auth script, config setupAdam Malczewski
- Sidebar uses absolute inset-0 with overflow-y-auto for proper scrolling - Border moved to inner div so it hides with sidebar - Copilot auth script uses portable sed instead of grep -P (macOS compat) - dispatch.toml with 3 keys, 4 models, fallback order - .env.dispatch with key placeholders and script reference - docker-compose loads .env.dispatch via env_file
2026-05-19fix: DeepSeek reasoning_content dropped on multi-step tool callsAdam Malczewski
- Base URL corrected: zen/v1 -> zen/go/v1 (opencode-go provider) - Model changed: deepseek-v4-flash-free -> deepseek-v4-flash - Added wrapLanguageModel middleware to inject reasoning_content via providerMetadata.openaiCompatible before each stream call - Fixed test mocks: removed vi.importActual (unsupported in Bun), added tool factory mocks, preserved real tool export in ai mock - Added 11 tests for the normalizeMessages middleware
2026-05-19Phase 1: single agent + basic UIHEADmainAdam Malczewski
- Bun monorepo with @dispatch/core, @dispatch/api, @dispatch/frontend - Agent runtime with Vercel AI SDK, streaming via WebSocket - Tools: read_file, write_file, list_files (scoped to working directory) - Hono API server with POST /chat, GET /status, GET /health, WS /ws - Svelte 5 + DaisyUI frontend with chat UI, theme switcher, copy button - OpenCode Go (Zen) as LLM provider, deepseek-v4-flash-free model - Docker setup (dev + prod) with bin/ scripts and gopass secrets - Biome v2 linting/formatting, Vitest tests (44 passing) - Debug info attached to error messages for diagnostics