Skip to content

feat: add experimental app server - #188

Merged
oratis merged 13 commits into
mainfrom
codex/app-server
Aug 2, 2026
Merged

feat: add experimental app server#188
oratis merged 13 commits into
mainfrom
codex/app-server

Conversation

@oratis

@oratis oratis commented Aug 1, 2026

Copy link
Copy Markdown
Owner

Summary

  • add a single-owner line-delimited JSON app-server backed by the experimental lifecycle protocol
  • persist thread snapshots atomically and normalize orphaned in-progress turns to interrupted on resume
  • adapt RuntimeHost history and streaming events without exposing credentials to clients
  • propagate real cancellation on interrupt and client EOF
  • serialize output with backpressure; only transient deltas may be dropped under saturation
  • expose the same handler through deepcode app-server

Validation

  • pnpm typecheck
  • pnpm lint (0 errors, 3 pre-existing warnings)
  • pnpm test (945 passed, 12 skipped)
  • pnpm build
  • pnpm docs:check
  • process handshake: printf ... | node apps/cli/dist/cli.js app-server
  • CI=1 pnpm install --frozen-lockfile --lockfile-only --ignore-scripts

Scope notes

  • v1 is single-client stdio, not a shared daemon
  • approval/user-input RPC and production CommonJS sidecar bundling remain follow-up work
  • existing REPL/headless output contracts are unchanged

Stack

Depends on #187.

@oratis
oratis changed the base branch from codex/desktop-runtime-adr to main August 2, 2026 06:36
@oratis
oratis marked this pull request as ready for review August 2, 2026 06:40
@oratis

oratis commented Aug 2, 2026

Copy link
Copy Markdown
Owner Author

Review: approved ✅

The app-server is the load-bearing piece of the whole stack, and the design choices here are the ones I'd want.

What I checked

  • Single-owner matches Sessions: canonical v1 writer and cross-process ownership #185's writer lock and docs: decide desktop runtime packaging #187's single-client decision. All three agree, so there's one ownership story rather than three.
  • Orphaned in-progress turns normalize to interrupted on resume. This is the crash-recovery case that otherwise leaves a thread permanently stuck "running" with no process behind it — a state users can't clear without deleting the session. Handling it at resume is the right place.
  • Atomic thread snapshot persistence — partial snapshot writes on a kill would otherwise corrupt exactly the state needed to recover.
  • Credentials are not exposed to clients; the RuntimeHost adapter projects history and streaming events only. This is the property feat: move desktop runtime behind app server #192 depends on, so it needed to be true here first.
  • Cancellation propagates on both interrupt and client EOF. EOF is the one people forget: a client that dies without sending interrupt would otherwise leave the turn burning tokens against a provider with nobody listening.
  • Backpressure where only transient deltas may be dropped. Exactly the right invariant — under saturation you lose typing animation, never a completed item. Dropping durable items would silently corrupt threads; unbounded buffering would OOM. This picks the correct third option.

Note: exposing the same handler via deepcode app-server means the CLI can be used as a debugging entry point without launching the desktop bundle. Useful, and it's how the #208 release gate can exercise the real protocol.

Validation: CI green; apps/server 41 tests pass locally at the stack tip.

@oratis
oratis merged commit ff39dde into main Aug 2, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant