Skip to content

Releases: bjb2/omp-deck

v0.6.1 — In-app update notification

29 May 23:31

Choose a tag to compare

Small follow-up to v0.6.0. Adds a passive update-check pill in the StatusBar so future releases (this one and onward) become discoverable from inside the deck instead of requiring users to run npm outdated -g.

Added

  • ↑ X.Y.Z available pill at the bottom-right of the deck chrome whenever the running version is behind what's published on npm. Click → opens the GitHub release notes in a new tab. The user runs npm install -g omp-deck@latest themselves; the deck never auto-updates. (#10)
  • GET /api/version returns { current, latest, updateAvailable, lastCheckedAt, releaseUrl, packageUrl, disabled }. The pill is just a thin renderer over this.
  • 24-hour cached version check against https://registry.npmjs.org/omp-deck. Same destination as npm install; no version-as-fingerprint, no analytics, no extra outbound traffic beyond one ~1 KB request per day.
  • Kill switch: OMP_DECK_DISABLE_UPDATE_CHECK=1 short-circuits the entire feature (no cache read, no network, no pill). Set it in your managed .env if you're on a locked-down network or just don't want the chrome.
  • Cache lives at <dataDir>/update-check.json and is graceful on every failure mode (registry down, parse error, env disabled, malformed cache, version-compare failure) — the pill simply doesn't render.
  • Semver-aware comparison via Bun.semver.order (so 0.10.0 > 0.9.0, prereleases handled correctly).
  • New protocol type: VersionInfo.
  • 10 new tests on the update-check module (33 assertions): disabled-flag handling, cache hits at newer / same / older versions, semver edge cases, registry-error state, first-call empty-state + background refresh, response-shape sanity.

v0.6.0 — First-run onboarding + provider clarity + reliability fixes

29 May 23:31

Choose a tag to compare

Quality-of-life release driven by three live-demo reports plus a deliberate first-run-experience rewrite.

For existing users: see docs/upgrading.md — the onboarding wizard does NOT trigger for installs with existing sessions or a moved welcome task. Everything you have keeps working.

Onboarding wizard (#9)

  • Five-step first-run flow at /onboarding, gated by a server-detected needsOnboarding flag. Brand-new users get walked through: kb scaffold → provider auth (Claude Pro/Max or ChatGPT Plus/Pro OAuth, or OpenRouter API key) → optional /start greeting → handoff to chat.
  • Returning-user detection is silent: any existing session OR a welcome task that's not in backlog marks onboarding settled without ever showing the wizard. Existing installs upgrade cleanly.
  • Welcome task tile on SessionPicker surfaces the seeded T-1 task even if the user never clicks the Tasks tab.
  • Skip-but-remind toast appears on the chat view if onboarding was X-ed out, pointing at /onboarding for a re-run.
  • New server module apps/server/src/onboarding-state.ts + routes at /api/onboarding/{state,complete,seed-kb-system}. Reuses existing endpoints (/api/kb/init, /api/orientation/start, /api/settings/env, /api/auth/oauth/*) for the actual work.
  • The wizard's /start template is static but the AGENT re-fetches live state on every fire (kb files, /api/{tasks,routines,inbox}), so it stays accurate as the deck grows.

Model-picker clarity (#7)

  • subscription badge in the model picker for genuine consumer-subscription providers (Claude Pro/Max, ChatGPT Plus/Pro, GitHub Copilot, Cursor, Perplexity Pro/Max, coding plans). Explicit allowlist — not the SDK's broader getOAuthProviders() which would have falsely badged Ollama / LM Studio / gateway services as "subscription."
  • Placeholder API keys suppressed. OPENAI_API_KEY=sk-your-XXXXhere (and other .env.example leftovers — your-api-key, <your-key>, changeme, length-too-short keys per prefix family) no longer mark API-key providers as authenticated. The picker hides those rows from the default view instead of letting users click them and get back a 401.
  • 401-recovery notification. When a chat call returns auth-shaped error (401, incorrect api key, unauthorized) on an API-key provider AND a subscription provider carries the same model id with a real OAuth credential, the deck fires a warn notification suggesting the switch.

OAuth flow lifecycle (#7)

  • 5-minute server-side timeout per OAuth flow. The SDK's own timeout only fires on the loopback callback listener — flows driven by onPrompt (e.g. Ollama endpoint input) could sit pending forever, blocking subsequent attempts with 409 already-in-flight. Now force-cancelled.
  • Stale-flow eviction on POST /:provider/start. If a duplicate start arrives and the held flow is past the timeout window, evict it inline instead of 409-ing forever.
  • abortFlow helper drains promptResolvers too (latent bug — pre-fix cancel only rejected manualCode, leaving onPrompt deferreds hanging).
  • OAuth consent button now uses variant="primary" instead of inheriting the low-contrast default ghost variant.

Cross-platform reliability (#8)

  • Bun executable resolution falls back to Bun.which("bun") when process.execPath points at a dead path. Fixes a macOS-reported posix_spawn ENOENT '~/.bun/bin/bun' when the user reinstalled Bun via Homebrew / asdf / mise after deck boot. Affects both telegram-bridge spawn and scheduleRestart.

Added

  • docs/upgrading.md — version-by-version migration notes.
  • README "Global install" section rewritten to explicitly call out: omp CLI not required; Bun + Node prereqs; post-boot auth paths (OAuth or API key); and how the deck self-bootstraps ~/.omp/agent/ on first boot.
  • apps/server/src/credential-quality.ts with looksLikePlaceholderKey (44 unit-test assertions).
  • apps/server/src/runtime-bun.ts with resolveBunExecutable (4 tests).
  • apps/server/src/onboarding-state.ts + routes-onboarding.ts (4 tests).
  • apps/server/src/routes-auth-oauth.test.ts — 6 tests for the new abortFlow cleanup helper.
  • ModelInfo.isSubscription field in @omp-deck/protocol.
  • OnboardingState + SeedKbSystem* types in @omp-deck/protocol.

v0.5.0 — Cross-platform CI, Linux container, Mac/Linux launcher

29 May 01:01

Choose a tag to compare

Infrastructure release. v0.4.0 advertised macOS and Linux support but had never been empirically verified — every release shipped "tested on a Windows box, presumed to work elsewhere." v0.5.0 closes that gap: every push to main now runs the gates on all three platforms under the same Bun version, the Docker image actually boots end-to-end, and Mac/Linux users get a launcher with parity to the Windows one.

Two real Linux bugs surfaced during the validation work and are fixed in this release.


Cross-platform CI matrix

.github/workflows/ci.yml runs on every push to main and every pull request:

Job Runner What it runs
ubuntu-latest · bun 1.3.14 Ubuntu bun install --frozen-lockfile, bun run typecheck, bun test, bun --cwd apps/web run build
macos-latest · bun 1.3.14 macOS same
windows-latest · bun 1.3.14 Windows same
docker build + boot smoke Ubuntu docker build, container boot, curl /api/health, curl /api/tasks

The first run was green across all four jobs. The matrix is fail-fast disabled so a regression on one platform doesn't mask issues on the others. Concurrency group cancels in-flight runs on the same ref so rapid pushes don't queue duplicate work.

What this means in practice:

  • No more "should work on Mac/Linux" claims — every release ships with empirical verification.
  • Platform-divergent regressions are caught at PR time instead of at user-install time.
  • The Docker Dockerfile is exercised end-to-end on every push — if anyone breaks the container path, the next push tells them.

Total CI wall-clock on a typical push: about 2.5 minutes.

Fixed: Docker build is now correct end-to-end on Linux

Two regressions were silently broken before this release, even though docs/deployment.md advertised the path:

1. Lockfile workspace mismatch. The Dockerfile copied four workspace manifests (packages/protocol, apps/server, apps/web, root) but the lockfile knows about five — the telegram bridge under apps/bridges/telegram was missing. bun install --frozen-lockfile failed with lockfile had changes, but lockfile is frozen. Fix: both build stages now copy the telegram manifest alongside the rest. The bridge itself is still opt-in at runtime; the manifest just needs to exist for the workspace graph to match the lockfile.

2. Alpine vs glibc. The base image was oven/bun:1.3.14-alpine (musl libc). @oh-my-pi/pi-natives ships prebuilt .node binaries for linux-x64-modern and linux-x64-baseline, both linked against glibc's ld-linux-x86-64.so.2. There is no linux-x64-musl variant, so the container booted, crashed at agent-session init, and exited. Fix: base image switched to oven/bun:1.3.14 (Debian-slim, glibc). The image is about 40 MB larger; the trade is a runtime that actually boots.

Added: Start-OMP-Deck.sh for macOS and Linux

Bash sibling to the Windows Start-OMP-Deck.cmd launcher. Same shape — start the dev server + Vite together, write logs under .logs/, open the deck in the default browser — plus start / stop / status subcommands for "set it and forget it" usage:

chmod +x Start-OMP-Deck.sh         # one-time
./Start-OMP-Deck.sh start          # background, opens browser
./Start-OMP-Deck.sh status         # check
./Start-OMP-Deck.sh stop           # tears down server + vite + child processes
./Start-OMP-Deck.sh                # foreground, same as `bun run dev`

Stop handling kills the whole process group, so vite and the bun server both exit together — no orphan listeners on the dev port.

Added: .gitattributes enforcing LF on POSIX-executed files

Locks *.sh, *.bash, and Dockerfile to LF line endings. Without this, Windows clones with core.autocrlf=true (Git for Windows default) silently convert these to CRLF; the file commits clean, then the shebang lookup fails on POSIX (bash\r: not found). This was a latent landmine and is now defused.

Install / upgrade

Fresh install:

git clone https://github.com/bjb2/omp-deck.git
cd omp-deck
bun install
bun run dev

Upgrade from v0.4.0 — no migrations needed:

git pull
bun install
bun run dev

Docker (now actually works):

docker build -t omp-deck .
docker run --rm -p 127.0.0.1:8787:8787 omp-deck
# → http://127.0.0.1:8787

Full changelog: v0.4.0...v0.5.0 · See CHANGELOG.md for the full detail.

v0.4.0 — Plan mode, queued-prompt editing, todo live-sync

29 May 00:30

Choose a tag to compare

Mid-cycle release focused on user-visible polish to the chat loop. Plan mode brings TUI parity to the deck so the agent can propose work before it executes. Queued prompts you sent mid-stream can now be edited or cancelled. The Inspector's todo panel updates intra-turn instead of waiting for SDK reminder ticks. Session rename failures surface their error instead of silently reverting.


✨ Plan mode (T-105)

Shift+Tab in the composer — or /plan [on|off] from the slash picker — toggles plan mode for the active session. While active, the agent gets the SDK's plan-mode system prompt + the resolve tool, so writes are gated until you approve.

When the agent submits a plan, the chat surfaces an inline PlanApproval card with:

  • Reject — exits plan mode cleanly, no rename, no execute.
  • Approve — renames local://PLAN.md to local://<title>.md and queues a synthetic execute prompt that runs in a new turn with the full tool set restored.
  • Edit & approve — opens an inline textarea pre-filled with the plan body; saves the edited content back to PLAN.md before the rename.

Five discoverability surfaces, all keyboard-/touch-friendly:

Entry point Where
Shift+Tab Composer keyboard (matches TUI muscle memory)
/plan Slash picker — client-virtual, never round-trips to the agent
Header pill Top of session pane
Composer border tint accent-plan color around the textarea
Sidebar badge On the active session row

Robust to reconnect: pending proposals are replayed via the bridge's subscribePlanModeFrames mechanism, so a page reload mid-approval re-renders the card.

15 unit tests covering enter / idempotent re-enter / exit / approve happy path / edit-and-approve / title-override / path-traversal-rejection / reject / double-click CAS / cancel-mid-approval / dispose / snapshot-replay.

✏️ Queued-prompt edit + cancel

Hover any queued bubble to reveal Pencil + X. Edit opens an inline textarea (Enter saves, Esc discards, empty save = cancel). Cancel drops the entry without prompting.

Under the hood, the bridge maintains a shadow queue mirrored from the SDK; cancel/edit rebuild the SDK queue (synchronous popLastQueuedMessage loop + parallel re-enqueue) preserving order + ids so bubbles don't re-key. queue_state event re-broadcasts the canonical queue after every mutation; reducer replaces wholesale.

Session snapshot now carries queuedPrompts, so a page reload subscriber sees the queue immediately.

⚡ Todo panel live-sync (T-106)

The Inspector's TodoPanel was visibly stale between an agent's todo_write call and the SDK's next todo_reminder tick (those fire only on reminder cycles, typically at turn boundaries). For long turns with many todo updates, the panel showed pre-tick state until the cycle caught up.

The bridge now extends the existing session.subscribe listener to detect tool_execution_end with toolName=todo_write and emit a synthetic todo_phases_set event carrying session.getTodoPhases(). Inspector updates intra-turn.

🐛 Session rename — surface failures

The omp SDK's setSessionName performs an atomic-replace on the session journal: write to .jsonl.tmp, fs.rename over the original. On Windows fs.rename fails with EPERM when the destination is held open — and the live session always holds the journal open. So pressing Enter to rename produced a 500 error the store swallowed via console.warn; the input closed; the UI showed the old name with no indication anything had failed.

Now the input stays open on failure and renders an inline danger-toned error span with role=alert + aria-describedby. Successful renames still close as before.

The underlying Windows EPERM bug is in the SDK's atomic-rename helper — to be raised separately upstream.

⌨️ Universal Ctrl+. / Cmd+. abort

Window-level keybinding to abort the active session if it's streaming. Same convention as ChatGPT and VS Code. Composer's Stop button also gains an explicit Ctrl+. hint.

🩹 Fixed

  • Fresh-clone bun run dev no longer fails on missing TELEGRAM_BOT_TOKEN. The root dev script previously fanned out across every workspace (--filter='@omp-deck/*') and brought the standalone telegram bridge along with the deck server + web — the bridge's config validator throws if no bot token is set, so first-run users would hit an error before the UI ever came up. The bridge has always been opt-in; the dev script now restricts itself to @omp-deck/server + @omp-deck/web. (#1)

📚 Docs

  • README rewritten human-forward — leads with the feeling of using the cockpit (track work as work, ask from anywhere, decide carefully, capture without context-switching, remember across sessions) rather than a feature inventory.
  • docs/tui-parity.md: plan mode + ask tool moved from Future to ✓. Themes row adds Horizon. New row for queued-prompt edit/cancel. Todos panel mentions the synthesis.
  • docs/slash-commands.md: /plan section + client-virtual mechanism explanation.
  • docs/architecture.md: synthetic events expanded (todo_phases_set, prompt_queued + queue_state, plan-mode trio, ext_ui_dialog pair). DB tables list fleshed out.
  • docs/themes.md: Horizon documented.
  • docs/configuration.md: OMP_DECK_AUTO_START default corrected from "empty (disabled)" to /start (the actual default — it's opt-OUT, not opt-in).
  • CONTRIBUTING.md: "No unit-test harness" claim retired — 149+ server + 16+ web/reducer tests; coverage is partial but real.

Install / upgrade

Fresh install:

git clone https://github.com/bjb2/omp-deck.git
cd omp-deck
bun install
bun run dev

Upgrade from v0.3.0:

git pull
bun install
bun run dev

No migrations needed beyond the automatic SQLite ones; deck DB is forward-compatible.

Tested fresh install path verified end-to-end on Bun 1.3.14 — see install docs.


Full changelog: v0.3.0...v0.4.0 · See CHANGELOG.md for the section-by-section detail.