@pat-lewczuk/cezar 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +249 -45
- package/dist/config.d.ts +8 -0
- package/dist/config.js +6 -0
- package/dist/config.js.map +1 -1
- package/dist/core/agent-runner.d.ts +44 -2
- package/dist/core/agent-runner.js +8 -2
- package/dist/core/agent-runner.js.map +1 -1
- package/dist/core/backend-detect.d.ts +6 -4
- package/dist/core/backend-detect.js +44 -4
- package/dist/core/backend-detect.js.map +1 -1
- package/dist/core/claude-cli-runner.d.ts +3 -25
- package/dist/core/claude-cli-runner.js +2 -19
- package/dist/core/claude-cli-runner.js.map +1 -1
- package/dist/core/claude-ui-mapper.d.ts +57 -0
- package/dist/core/claude-ui-mapper.js +370 -0
- package/dist/core/claude-ui-mapper.js.map +1 -0
- package/dist/core/codex-app-server-runner.d.ts +29 -0
- package/dist/core/codex-app-server-runner.js +452 -0
- package/dist/core/codex-app-server-runner.js.map +1 -0
- package/dist/core/codex-ui-mapper.d.ts +53 -0
- package/dist/core/codex-ui-mapper.js +411 -0
- package/dist/core/codex-ui-mapper.js.map +1 -0
- package/dist/core/ndjson.d.ts +6 -0
- package/dist/core/ndjson.js +23 -0
- package/dist/core/ndjson.js.map +1 -0
- package/dist/core/opencode-server-runner.d.ts +30 -0
- package/dist/core/opencode-server-runner.js +451 -0
- package/dist/core/opencode-server-runner.js.map +1 -0
- package/dist/core/opencode-ui-mapper.d.ts +105 -0
- package/dist/core/opencode-ui-mapper.js +578 -0
- package/dist/core/opencode-ui-mapper.js.map +1 -0
- package/dist/core/process-usage.d.ts +63 -0
- package/dist/core/process-usage.js +181 -0
- package/dist/core/process-usage.js.map +1 -0
- package/dist/core/runner-factory.d.ts +8 -0
- package/dist/core/runner-factory.js +22 -0
- package/dist/core/runner-factory.js.map +1 -0
- package/dist/core/tool-display.d.ts +27 -0
- package/dist/core/tool-display.js +150 -0
- package/dist/core/tool-display.js.map +1 -0
- package/dist/core/ui-events.d.ts +294 -0
- package/dist/core/ui-events.js +25 -0
- package/dist/core/ui-events.js.map +1 -0
- package/dist/index.js +0 -0
- package/dist/pack-check.d.ts +17 -0
- package/dist/pack-check.js +27 -0
- package/dist/pack-check.js.map +1 -0
- package/dist/planner.js +7 -3
- package/dist/planner.js.map +1 -1
- package/dist/runs/store.d.ts +5 -0
- package/dist/runs/store.js +3 -0
- package/dist/runs/store.js.map +1 -1
- package/dist/runs/title-summary.d.ts +15 -0
- package/dist/runs/title-summary.js +84 -0
- package/dist/runs/title-summary.js.map +1 -0
- package/dist/runs/ui-event-sink.d.ts +81 -0
- package/dist/runs/ui-event-sink.js +210 -0
- package/dist/runs/ui-event-sink.js.map +1 -0
- package/dist/server/capabilities.d.ts +18 -0
- package/dist/server/capabilities.js +23 -0
- package/dist/server/capabilities.js.map +1 -0
- package/dist/server/forge/github.d.ts +39 -0
- package/dist/server/forge/github.js +369 -0
- package/dist/server/forge/github.js.map +1 -0
- package/dist/server/forge/index.d.ts +24 -0
- package/dist/server/forge/index.js +45 -0
- package/dist/server/forge/index.js.map +1 -0
- package/dist/server/forge/types.d.ts +80 -0
- package/dist/server/forge/types.js +2 -0
- package/dist/server/forge/types.js.map +1 -0
- package/dist/server/git-changes.d.ts +182 -0
- package/dist/server/git-changes.js +424 -0
- package/dist/server/git-changes.js.map +1 -0
- package/dist/server/open-in-app.d.ts +19 -0
- package/dist/server/open-in-app.js +134 -0
- package/dist/server/open-in-app.js.map +1 -0
- package/dist/server/server.js +34 -10
- package/dist/server/server.js.map +1 -1
- package/dist/server/static-ui.d.ts +49 -0
- package/dist/server/static-ui.js +92 -0
- package/dist/server/static-ui.js.map +1 -0
- package/dist/update-check.d.ts +12 -0
- package/dist/update-check.js +41 -0
- package/dist/update-check.js.map +1 -0
- package/dist/workflows/run.d.ts +3 -0
- package/dist/workflows/run.js +22 -7
- package/dist/workflows/run.js.map +1 -1
- package/dist/workflows/types.d.ts +16 -0
- package/dist/workflows/types.js +3 -1
- package/dist/workflows/types.js.map +1 -1
- package/package.json +1 -1
- package/web/app/node_modules/.vite/vitest/ca84d1343b96baa8137c943ed1860e522cacb238/results.json +1 -0
- package/web/app/src/components/app-shell-container.tsx +76 -0
- package/web/app.js +145 -18
- package/web/dist/assets/arrow-left-BE957rJs.js +1 -0
- package/web/dist/assets/bundle-mjs-DLPpRFyl.js +1 -0
- package/web/dist/assets/chunk-BO2N2NFS-f5igTtpB.js +131 -0
- package/web/dist/assets/compare-variants-D6fPL9cS.js +1 -0
- package/web/dist/assets/core-BuMqAF_1.js +12 -0
- package/web/dist/assets/css-BsVw1vtW.js +1 -0
- package/web/dist/assets/dialog-BEgEWFDS.js +1 -0
- package/web/dist/assets/diff-view-CctnJHWe.js +4 -0
- package/web/dist/assets/diff-woXpYk--.js +1 -0
- package/web/dist/assets/dist-CW7M_Jhs.js +1 -0
- package/web/dist/assets/ellipsis-vertical-DJPAfccS.js +1 -0
- package/web/dist/assets/engine-javascript-FQvzRocB.js +141 -0
- package/web/dist/assets/folder-RbRLfIX-.js +1 -0
- package/web/dist/assets/git-pull-request-DJkAMT0f.js +1 -0
- package/web/dist/assets/git-toolbar-D8OPPqBP.js +1 -0
- package/web/dist/assets/github-BYIHwIJB.js +1 -0
- package/web/dist/assets/go-rLFTqkRN.js +1 -0
- package/web/dist/assets/highlighted-body-OFNGDK62-DGHHie_q.js +1 -0
- package/web/dist/assets/highlighter-BKVEsACy.js +3 -0
- package/web/dist/assets/html-BY76lXLH.js +1 -0
- package/web/dist/assets/index-9qG98Orw.js +11 -0
- package/web/dist/assets/index-Bz_r8Jt3.css +2 -0
- package/web/dist/assets/input-BRsSo4xH.js +1 -0
- package/web/dist/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
- package/web/dist/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
- package/web/dist/assets/javascript-BgS3c2Ky.js +1 -0
- package/web/dist/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
- package/web/dist/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
- package/web/dist/assets/json-qhed-kSA.js +1 -0
- package/web/dist/assets/jsonc-CYpm1nAK.js +1 -0
- package/web/dist/assets/jsx-Bz0zcwM4.js +1 -0
- package/web/dist/assets/lib-CNGa3Dig.js +1 -0
- package/web/dist/assets/loader-circle-BV3DO9mE.js +1 -0
- package/web/dist/assets/markdown-BYOwaDjH.js +1 -0
- package/web/dist/assets/markdown-CR_HLGTs.js +1 -0
- package/web/dist/assets/mermaid-GHXKKRXX-DM2VsGBG.js +1 -0
- package/web/dist/assets/open-mercato-toBr6SOa.svg +11 -0
- package/web/dist/assets/python-gzcpVVnB.js +1 -0
- package/web/dist/assets/react-dom-Ddtik4qM.js +1 -0
- package/web/dist/assets/refresh-cw-DCa-Rlwz.js +1 -0
- package/web/dist/assets/repo-git-XTqlVOl2.js +1 -0
- package/web/dist/assets/run-diff-C7mfxj7f.js +3 -0
- package/web/dist/assets/run-header-CfVeY3uM.js +1 -0
- package/web/dist/assets/rust-Cfkwpbl8.js +1 -0
- package/web/dist/assets/search-x-CoCyl7zT.js +1 -0
- package/web/dist/assets/shellscript-CLZ0U2zV.js +1 -0
- package/web/dist/assets/skill-detail-C9cniyId.js +1 -0
- package/web/dist/assets/skills-DXgY1uXJ.js +1 -0
- package/web/dist/assets/skills-ynuO5oCr.js +1 -0
- package/web/dist/assets/sql-BsFa4tDR.js +1 -0
- package/web/dist/assets/square-terminal-B6PZX4Qp.js +1 -0
- package/web/dist/assets/tab-link-phWEqSBy.js +1 -0
- package/web/dist/assets/task-changes-DYwnPnTN.js +1 -0
- package/web/dist/assets/task-commits-DZzxEzbn.js +1 -0
- package/web/dist/assets/task-files-FOAAz2FB.js +2 -0
- package/web/dist/assets/task-thread-Bncxe8Os.js +5 -0
- package/web/dist/assets/toaster-BS2E1bhz.js +43 -0
- package/web/dist/assets/trash-2-CDtxmmc8.js +1 -0
- package/web/dist/assets/triangle-alert-6su4Js5O.js +1 -0
- package/web/dist/assets/tsx-udAQXfEw.js +1 -0
- package/web/dist/assets/typescript-bsJCZSQ-.js +1 -0
- package/web/dist/assets/upload-Bp7hQxll.js +1 -0
- package/web/dist/assets/use-desktop-eHm2iTXX.js +3 -0
- package/web/dist/assets/utils-rQGbOrwc.js +1 -0
- package/web/dist/assets/workflows-Dg2wQg6i.js +11 -0
- package/web/dist/assets/x-Br_jIDBw.js +1 -0
- package/web/dist/assets/yaml-rwi0_p6S.js +1 -0
- package/web/dist/index.html +67 -0
- package/web/index.html +1 -0
- package/web/style.css +28 -8
package/README.md
CHANGED
|
@@ -1,90 +1,294 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
1
3
|
# cezar ⚡
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
+
**A local cockpit for running and tracking AI coding-agent tasks in your repo.**
|
|
6
|
+
|
|
7
|
+
Type a task, pick a workflow, watch the agent work live — steps, tool calls,
|
|
8
|
+
tokens, diffs — in a browser cockpit that runs entirely on your machine.
|
|
9
|
+
Your `claude` login, your `gh`, your files. No accounts, no database, no cloud.
|
|
10
|
+
|
|
11
|
+
[What it solves](#what-it-solves) · [Who it's for](#who-its-for) · [Quick start](#quick-start) · [How it works](#how-it-works) · [Core concepts](#core-concepts) · [Cockpit tour](#cockpit-tour)
|
|
12
|
+
|
|
13
|
+
[](#license)
|
|
14
|
+

|
|
15
|
+

|
|
16
|
+

|
|
17
|
+

|
|
18
|
+
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
---
|
|
5
22
|
|
|
6
23
|
```bash
|
|
7
24
|
cd your-repo
|
|
8
|
-
npx cezar
|
|
25
|
+
npx cezar-cli # → cockpit at http://localhost:4321
|
|
9
26
|
```
|
|
10
27
|
|
|
11
|
-
That's
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
28
|
+
That's the whole setup. If your `claude` CLI is logged in (Pro/Max) and `gh` is
|
|
29
|
+
authenticated, there is nothing else to configure. State lives in `.ai/cezar/`
|
|
30
|
+
inside your repo — plain JSON, NDJSON and Markdown you can `cat` and fix by hand.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## What it solves
|
|
35
|
+
|
|
36
|
+
Most "AI coding agent" tooling makes you choose between a **terminal** you can't
|
|
37
|
+
see into once it's running, and a **cloud product** that wants your API key, your
|
|
38
|
+
code on their servers, and an account. cezar is the third option: the agent runs
|
|
39
|
+
locally under *your* subscription, and a cockpit shows you exactly what it's doing.
|
|
40
|
+
|
|
41
|
+
- **No visibility into a running agent.** A headless `claude` run is a black box
|
|
42
|
+
until it finishes. cezar streams every step — agent text, each tool call and
|
|
43
|
+
its result, tokens and cost per step — live, and keeps the full replay.
|
|
44
|
+
- **One agent, one working tree, one thing at a time.** Kick off a second task and
|
|
45
|
+
it fights the first over your files. cezar runs each task in its **own git
|
|
46
|
+
worktree**, so two (or three) agents work in parallel without stepping on
|
|
47
|
+
each other — or on the branch you're editing.
|
|
48
|
+
- **The agent finishes and you have to trust it.** cezar ends non-trivial runs at
|
|
49
|
+
a **review gate**: inspect the diff, send notes back into the same session, or
|
|
50
|
+
push a **draft PR** — never an auto-merge.
|
|
51
|
+
- **Losing a session when it fails.** Every run records its `claude` session id.
|
|
52
|
+
Take it over interactively in one click (`claude --resume <id>`), or continue it
|
|
53
|
+
in-process from the cockpit.
|
|
54
|
+
- **Setup tax.** No wizard, no env vars, no schema. Skills are Markdown, workflows
|
|
55
|
+
are short YAML, and everything degrades: no `gh` → works without PRs, no network
|
|
56
|
+
→ local skills still load, no `.ai/skills` → the bare prompt still runs.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Who it's for
|
|
61
|
+
|
|
62
|
+
- **Solo devs and small teams** who want the leverage of coding agents without
|
|
63
|
+
handing their code and keys to a SaaS — the agent runs on your subscription,
|
|
64
|
+
on your machine.
|
|
65
|
+
- **`claude` CLI power users** who love headless runs but want to *see* them,
|
|
66
|
+
compare a few attempts side by side, and review a diff before it lands.
|
|
67
|
+
- **Anyone with a backlog** who'd rather queue three tasks into isolated worktrees
|
|
68
|
+
and pick the winners than babysit one terminal.
|
|
69
|
+
- **Teams with shared conventions** who want their playbooks (skills) pulled from
|
|
70
|
+
a git repo, applied consistently, with zero per-project setup.
|
|
71
|
+
|
|
72
|
+
---
|
|
16
73
|
|
|
17
|
-
|
|
74
|
+
## Quick start
|
|
18
75
|
|
|
19
|
-
|
|
76
|
+
**Prerequisites:** Node 20+, the [`claude` CLI](https://github.com/anthropics/claude-code)
|
|
77
|
+
logged in (Pro/Max subscription), and — optionally — `git` and the `gh` CLI.
|
|
20
78
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
retry loops (`onFail: retry`). The built-in `quick-task` workflow (one agent
|
|
27
|
-
step) works with zero setup.
|
|
28
|
-
- **Skills** — Markdown files in `.ai/skills/` or `.ai/cezar/skills/`; a workflow
|
|
29
|
-
step references one via `skill: <name>` and its body becomes the agent's
|
|
30
|
-
extra system prompt.
|
|
31
|
-
- **Repo view** — branch, working-tree status, diff vs HEAD, recent commits.
|
|
79
|
+
```bash
|
|
80
|
+
cd your-repo
|
|
81
|
+
npx cezar-cli # start the cockpit for the current repo
|
|
82
|
+
# or: npx @pat-lewczuk/cezar
|
|
83
|
+
```
|
|
32
84
|
|
|
33
|
-
|
|
85
|
+
The cockpit opens at `http://localhost:4321` (auto-picks the next free port if
|
|
86
|
+
busy). Type a task, pick a workflow, hit **Start**. That's it.
|
|
34
87
|
|
|
35
88
|
```bash
|
|
36
|
-
npx cezar
|
|
37
|
-
npx cezar
|
|
38
|
-
npx cezar init # scaffold .ai/cezar/ with an example workflow + skill
|
|
89
|
+
npx cezar-cli run "add a --json flag to the export command" # headless, CI-friendly
|
|
90
|
+
npx cezar-cli init # scaffold .ai/cezar/
|
|
39
91
|
```
|
|
40
92
|
|
|
93
|
+
Both the `cezar` and `cez` commands are installed, so once it's on your PATH you
|
|
94
|
+
can run either. No API key is ever used — cezar shells out to your logged-in
|
|
95
|
+
`claude` CLI.
|
|
96
|
+
|
|
97
|
+
> **Just kicking the tires?** Set `CEZ_DRY_RUN=1` to run against a bundled mock
|
|
98
|
+
> instead of the real CLI — the whole cockpit works with no `claude` login, so
|
|
99
|
+
> you can explore runs, diffs, variants and the review gate offline.
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## How it works
|
|
104
|
+
|
|
105
|
+
You describe a task. cezar runs it as a **workflow** — an ordered list of agent
|
|
106
|
+
steps and shell checks — shelling out to your `claude` CLI in headless
|
|
107
|
+
stream-json mode. Each task gets its own git worktree; the cockpit streams every
|
|
108
|
+
event live and parks the run at a review gate when there's a diff to inspect.
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
you type a task
|
|
112
|
+
│
|
|
113
|
+
▼
|
|
114
|
+
┌─────────────┐ optional: Plan → AI drafts a chain of steps you approve
|
|
115
|
+
│ workflow │ (agent steps + shell checks, with bounded onFail retries)
|
|
116
|
+
└─────────────┘
|
|
117
|
+
│
|
|
118
|
+
▼
|
|
119
|
+
┌──────────────────────────────┐ ┌───────────────────────────────┐
|
|
120
|
+
│ git worktree per task │ │ claude CLI (your login) │
|
|
121
|
+
│ (isolated branch, parallel) │◄───►│ stream-json · default-deny │
|
|
122
|
+
└──────────────────────────────┘ │ tools · acceptEdits in-repo │
|
|
123
|
+
│ └───────────────────────────────┘
|
|
124
|
+
│ agent text · tool calls · tool results · tokens · cost
|
|
125
|
+
▼
|
|
126
|
+
┌─────────────┐ SSE (replay + live) ┌──────────────────────────┐
|
|
127
|
+
│ .ai/cezar/ │ ──────────────────────► │ cockpit localhost:4321 │
|
|
128
|
+
│ JSON·NDJSON │ │ Runs · Repo · GitHub · │
|
|
129
|
+
│ ·Markdown │ │ Skills · Workflows │
|
|
130
|
+
└─────────────┘ └──────────────────────────┘
|
|
131
|
+
│
|
|
132
|
+
review gate: read the diff →
|
|
133
|
+
send notes back · draft PR · finish
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
When a check fails, the workflow can loop back to an earlier step (bounded by
|
|
137
|
+
`max`) with the failing output appended to the retried agent's prompt. Nothing
|
|
138
|
+
auto-merges: a run with changes rests in `review` until you act on it.
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Core concepts
|
|
143
|
+
|
|
144
|
+
Three words, no jargon — **task**, **skill**, **chain**:
|
|
145
|
+
|
|
146
|
+
- **Tasks** are the unit of work. Every task is a **run**: `queued → running →
|
|
147
|
+
review / done / failed / cancelled`, with a live event log, per-step token and
|
|
148
|
+
cost usage, cancel/delete, and — for anything with a diff — a review gate. Paste
|
|
149
|
+
screenshots into the task, or send follow-up messages into the live session
|
|
150
|
+
while it works.
|
|
151
|
+
- **Skills** are Markdown playbooks. Drop them in `.ai/skills/` or
|
|
152
|
+
`.ai/cezar/skills/`, or pull them from a shared **team skills repo** (a bare
|
|
153
|
+
git clone cached globally in `~/.cache/cez/`). A workflow step references one by
|
|
154
|
+
`skill: <name>` and its body becomes the agent's extra system prompt — so you
|
|
155
|
+
shape *how* the agent reasons without touching code.
|
|
156
|
+
- **Chains (workflows)** stitch steps into a pipeline: agent steps plus shell
|
|
157
|
+
checks, with bounded `onFail` retry loops. Write the YAML yourself, build one by
|
|
158
|
+
drag-ordering skills in the **Workflows** tab, or press **Plan** and let the AI
|
|
159
|
+
draft a chain for your task that you review, trim and start. The built-in
|
|
160
|
+
`quick-task` (one agent step) works with zero setup.
|
|
161
|
+
|
|
162
|
+
Two moves that make the cockpit worth the browser tab:
|
|
163
|
+
|
|
164
|
+
- **Parallel variants (×2 / ×3).** Run the same task as competing agents in
|
|
165
|
+
separate worktrees, then compare their diffs side by side and **pick** one —
|
|
166
|
+
the losers are archived and their worktrees cleaned up.
|
|
167
|
+
- **Review gate.** A finished run with changes waits in `review`. Read the diff,
|
|
168
|
+
type notes that go straight back into the agent's session, or push a
|
|
169
|
+
`gh pr create --draft`. You stay the merge button.
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Cockpit tour
|
|
174
|
+
|
|
175
|
+
Six tabs, one browser window, all live over Server-Sent Events:
|
|
176
|
+
|
|
177
|
+
| Tab | What's in it |
|
|
178
|
+
|---|---|
|
|
179
|
+
| **Runs** | Every task with its status, live event stream (agent text · tool calls · tool results · pasted/generated screenshots), tokens and cost. Continue, cancel, open in terminal (`claude --resume`), review the diff, or push a draft PR. |
|
|
180
|
+
| **Inbox** | Follow-ups an agent left behind (`todos.json`) — one click turns a suggestion into the next task, pre-wired to its suggested skill. |
|
|
181
|
+
| **Repo** | Branch, working-tree status, diff vs HEAD, recent commits (click one for its inline patch + GitHub link), and the configurable base branch that worktrees fork from and PRs target. |
|
|
182
|
+
| **GitHub** | Open issues and PRs of the repo's origin, read through your logged-in `gh`. Drag an issue onto the task box to prefill the prompt. |
|
|
183
|
+
| **Skills** | Local skills plus the team skills repo, with a rendered body + prompt preview. Refresh pulls the latest from the remote. |
|
|
184
|
+
| **Workflows** | Build a chain by drag-ordering skills, save it as portable YAML, import/export, or delete. Built-ins always come back. |
|
|
185
|
+
|
|
186
|
+
The whole GUI is dependency-free vanilla JS with no build step, a dark/light
|
|
187
|
+
theme toggle, and bookmarklets that launch a task straight from a GitHub page.
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
41
191
|
## Workflow format
|
|
42
192
|
|
|
43
|
-
`.ai/cezar/workflows
|
|
193
|
+
A workflow is a small YAML file in `.ai/cezar/workflows/`:
|
|
44
194
|
|
|
45
195
|
```yaml
|
|
46
196
|
name: fix-and-verify
|
|
47
|
-
description: Implement, then verify; retry with failing output on red.
|
|
197
|
+
description: Implement the task, then verify; retry with failing output on red.
|
|
48
198
|
steps:
|
|
49
199
|
- id: implement
|
|
50
200
|
name: Implement
|
|
51
201
|
prompt: "{{task}}"
|
|
52
|
-
skill: project-conventions # optional
|
|
53
|
-
# model: opus # optional per-step override
|
|
202
|
+
skill: project-conventions # optional — from .ai/skills or .ai/cezar/skills
|
|
203
|
+
# model: opus # optional per-step model override
|
|
54
204
|
# allowedTools: [Read, Edit, Write, Grep, Glob, Bash]
|
|
55
205
|
- id: verify
|
|
56
206
|
name: Verify
|
|
57
|
-
command: "npm test"
|
|
207
|
+
command: "npm test" # a check step: exit 0 passes
|
|
58
208
|
onFail:
|
|
59
|
-
retry: implement # loop back
|
|
60
|
-
max: 2
|
|
209
|
+
retry: implement # loop back to an earlier step…
|
|
210
|
+
max: 2 # …at most twice
|
|
61
211
|
```
|
|
62
212
|
|
|
63
|
-
`{{task}}` is replaced with the task you typed. When a check fails and loops
|
|
64
|
-
back,
|
|
213
|
+
`{{task}}` is replaced with the task text you typed. When a check fails and loops
|
|
214
|
+
back, its failing output is appended to the retried agent's prompt so the next
|
|
215
|
+
attempt can see what broke.
|
|
216
|
+
|
|
217
|
+
Prefer skills over steps? A workflow can also be written in the portable
|
|
218
|
+
shorthand — an ordered list of skill names, each becoming one agent step:
|
|
219
|
+
|
|
220
|
+
```yaml
|
|
221
|
+
name: triage-and-fix
|
|
222
|
+
skills: [reproduce, root-cause, implement, self-review]
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
---
|
|
65
226
|
|
|
66
227
|
## How it runs agents
|
|
67
228
|
|
|
68
|
-
|
|
69
|
-
stream-json mode — your subscription, no API key
|
|
70
|
-
default-deny via `--allowedTools
|
|
71
|
-
(`--permission-mode acceptEdits`) inside the
|
|
229
|
+
cezar shells out to your locally installed, logged-in `claude` CLI in headless
|
|
230
|
+
`stream-json` mode — **your subscription, no API key**. Tool access is
|
|
231
|
+
default-deny via `--allowedTools`, and edits are auto-accepted
|
|
232
|
+
(`--permission-mode acceptEdits`) inside the task's worktree. Nothing runs on a
|
|
233
|
+
server you don't own.
|
|
234
|
+
|
|
235
|
+
Useful environment variables:
|
|
236
|
+
|
|
237
|
+
| Var | Effect |
|
|
238
|
+
|---|---|
|
|
239
|
+
| `CEZ_DRY_RUN=1` | Use the bundled mock instead of the real `claude` CLI — the entire cockpit works offline, for demos and development. |
|
|
240
|
+
| `CEZ_CLAUDE_BIN=/path/to/claude` | Override which `claude` binary is used. |
|
|
241
|
+
| `GITHUB_TOKEN` | Fallback for GitHub reads/PRs when `gh` isn't authenticated. |
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## Configuration (optional)
|
|
246
|
+
|
|
247
|
+
Zero config is the default — everything below is opt-in via
|
|
248
|
+
`.ai/cezar/config.json` (a missing or invalid file simply uses the defaults, and
|
|
249
|
+
never blocks startup):
|
|
250
|
+
|
|
251
|
+
```jsonc
|
|
252
|
+
{
|
|
253
|
+
"skillsRepos": [{ "repo": "open-mercato/skills", "ref": "main" }], // team skills; [] disables
|
|
254
|
+
"maxParallel": 2, // how many tasks may run at once (non-git dirs always run 1)
|
|
255
|
+
"plannerModel": "sonnet", // model the Plan button uses to draft chains
|
|
256
|
+
"baseBranch": "develop" // branch worktrees fork from + PRs target (also settable in the Repo tab)
|
|
257
|
+
}
|
|
258
|
+
```
|
|
72
259
|
|
|
73
|
-
|
|
260
|
+
Run data (`runs.json`, NDJSON event logs, worktrees, `todos.json`) is
|
|
261
|
+
git-ignored automatically; your workflows and skills stay committable.
|
|
74
262
|
|
|
75
|
-
|
|
76
|
-
- `CEZ_CLAUDE_BIN=/path/to/claude` — override the binary.
|
|
263
|
+
---
|
|
77
264
|
|
|
78
265
|
## Development
|
|
79
266
|
|
|
80
267
|
```bash
|
|
81
268
|
npm install
|
|
82
|
-
npm run dev
|
|
83
|
-
npm run build
|
|
269
|
+
npm run dev # tsx src/index.ts — the cockpit, live-reloaded
|
|
270
|
+
npm run build # tsc → dist/
|
|
271
|
+
npm run typecheck # tsc --noEmit
|
|
84
272
|
```
|
|
85
273
|
|
|
274
|
+
The stack is deliberately small: **TypeScript** (strict, ESM), **Hono** + SSE for
|
|
275
|
+
the server, **Zod** at every boundary, **YAML** for workflows, and **vanilla JS**
|
|
276
|
+
for the GUI (no framework, no bundler). Every module is meant to be read in one
|
|
277
|
+
sitting.
|
|
278
|
+
|
|
86
279
|
---
|
|
87
280
|
|
|
281
|
+
## Relationship to cezar (the SaaS)
|
|
282
|
+
|
|
88
283
|
cez is the radically-simple, single-user sibling of
|
|
89
|
-
[cezar](https://github.com
|
|
90
|
-
|
|
284
|
+
[**cezar**](https://github.com/comerito/cezar) — the team SaaS cockpit for
|
|
285
|
+
running agents across the whole GitHub issue lifecycle (auto-triage, webhooks,
|
|
286
|
+
Supabase, multi-repo). Same core ideas — agent runner, skills, declarative
|
|
287
|
+
workflows, a live run cockpit — with none of the accounts, database or cloud.
|
|
288
|
+
Start here; graduate to cezar when a team needs shared visibility.
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## License
|
|
293
|
+
|
|
294
|
+
**MIT** © Patryk Lewczuk
|
package/dist/config.d.ts
CHANGED
|
@@ -32,6 +32,12 @@ declare const configSchema: z.ZodObject<{
|
|
|
32
32
|
}>, "many">>;
|
|
33
33
|
/** How many tasks may run at once (spec 006). Non-git dirs always run 1. */
|
|
34
34
|
maxParallel: z.ZodDefault<z.ZodNumber>;
|
|
35
|
+
/**
|
|
36
|
+
* Which agent backend a task uses unless overridden per task (GUI) or per
|
|
37
|
+
* step (workflow). The GUI only offers runners actually installed; this is
|
|
38
|
+
* the preselected default. Also the runner the chain planner uses.
|
|
39
|
+
*/
|
|
40
|
+
defaultRunner: z.ZodDefault<z.ZodEnum<["claude", "codex", "opencode"]>>;
|
|
35
41
|
/** Model for the chain planner (spec 008) — cheap but reliable at JSON. */
|
|
36
42
|
plannerModel: z.ZodDefault<z.ZodString>;
|
|
37
43
|
/**
|
|
@@ -45,6 +51,7 @@ declare const configSchema: z.ZodObject<{
|
|
|
45
51
|
ref: string;
|
|
46
52
|
}[];
|
|
47
53
|
maxParallel: number;
|
|
54
|
+
defaultRunner: "claude" | "codex" | "opencode";
|
|
48
55
|
plannerModel: string;
|
|
49
56
|
baseBranch?: string | undefined;
|
|
50
57
|
}, {
|
|
@@ -53,6 +60,7 @@ declare const configSchema: z.ZodObject<{
|
|
|
53
60
|
ref?: string | undefined;
|
|
54
61
|
}[] | undefined;
|
|
55
62
|
maxParallel?: number | undefined;
|
|
63
|
+
defaultRunner?: "claude" | "codex" | "opencode" | undefined;
|
|
56
64
|
plannerModel?: string | undefined;
|
|
57
65
|
baseBranch?: string | undefined;
|
|
58
66
|
}>;
|
package/dist/config.js
CHANGED
|
@@ -19,6 +19,12 @@ const configSchema = z.object({
|
|
|
19
19
|
skillsRepos: z.array(skillsRepoSchema).default(DEFAULT_SKILLS_REPOS),
|
|
20
20
|
/** How many tasks may run at once (spec 006). Non-git dirs always run 1. */
|
|
21
21
|
maxParallel: z.number().int().min(1).max(16).default(2),
|
|
22
|
+
/**
|
|
23
|
+
* Which agent backend a task uses unless overridden per task (GUI) or per
|
|
24
|
+
* step (workflow). The GUI only offers runners actually installed; this is
|
|
25
|
+
* the preselected default. Also the runner the chain planner uses.
|
|
26
|
+
*/
|
|
27
|
+
defaultRunner: z.enum(['claude', 'codex', 'opencode']).default('claude'),
|
|
22
28
|
/** Model for the chain planner (spec 008) — cheap but reliable at JSON. */
|
|
23
29
|
plannerModel: z.string().min(1).default('sonnet'),
|
|
24
30
|
/**
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;GAKG;AACH,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChC,gFAAgF;IAChF,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;CACvC,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,oBAAoB,GAAuB;IACtD,EAAE,IAAI,EAAE,qBAAqB,EAAE,GAAG,EAAE,MAAM,EAAE;CAC7C,CAAC;AAEF,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5B,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC;IACpE,4EAA4E;IAC5E,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IACvD,2EAA2E;IAC3E,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;IACjD;;;OAGG;IACH,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;CAChD,CAAC,CAAC;AAIH,2EAA2E;AAC3E,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,QAAgB;IAC/C,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,aAAa,CAAC,EAAE,MAAM,CAAC,CAAC;IAC3E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAChC,CAAC;IACD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,YAAY,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;QACvD,IAAI,MAAM,CAAC,OAAO;YAAE,OAAO,MAAM,CAAC,IAAI,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,wDAAwD;IAC1D,CAAC;IACD,OAAO,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AAChC,CAAC"}
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;GAKG;AACH,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChC,gFAAgF;IAChF,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;CACvC,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,oBAAoB,GAAuB;IACtD,EAAE,IAAI,EAAE,qBAAqB,EAAE,GAAG,EAAE,MAAM,EAAE;CAC7C,CAAC;AAEF,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5B,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC;IACpE,4EAA4E;IAC5E,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IACvD;;;;OAIG;IACH,aAAa,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;IACxE,2EAA2E;IAC3E,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;IACjD;;;OAGG;IACH,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;CAChD,CAAC,CAAC;AAIH,2EAA2E;AAC3E,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,QAAgB;IAC/C,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,aAAa,CAAC,EAAE,MAAM,CAAC,CAAC;IAC3E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAChC,CAAC;IACD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,YAAY,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;QACvD,IAAI,MAAM,CAAC,OAAO;YAAE,OAAO,MAAM,CAAC,IAAI,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,wDAAwD;IAC1D,CAAC;IACD,OAAO,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AAChC,CAAC"}
|
|
@@ -2,9 +2,19 @@
|
|
|
2
2
|
* The backend-agnostic seam for running one agent task. Adapted from
|
|
3
3
|
* @cezar/core's `agents/agent-runner.ts`, trimmed for single-user local use:
|
|
4
4
|
* no token-budget circuit breaker, no zod response schemas — one run is one
|
|
5
|
-
*
|
|
5
|
+
* agent-CLI session streaming normalized events.
|
|
6
|
+
*
|
|
7
|
+
* Three interchangeable backends implement this seam, each as a persistent
|
|
8
|
+
* process so multi-turn follow-ups, `waiting`, interrupt and resume all work:
|
|
9
|
+
* - `claude` — Claude Code CLI, stream-json over stdin/stdout;
|
|
10
|
+
* - `codex` — `codex app-server`, JSON-RPC 2.0 (JSONL) over stdin/stdout;
|
|
11
|
+
* - `opencode` — `opencode serve`, HTTP + SSE.
|
|
6
12
|
*/
|
|
7
|
-
|
|
13
|
+
/** `claude-cli` is the legacy id kept so old run records still parse. */
|
|
14
|
+
export type AgentBackend = 'claude' | 'codex' | 'opencode' | 'claude-cli';
|
|
15
|
+
/** The user-selectable runners (what config/GUI expose). */
|
|
16
|
+
export type RunnerId = 'claude' | 'codex' | 'opencode';
|
|
17
|
+
export declare const RUNNER_IDS: readonly RunnerId[];
|
|
8
18
|
export interface AgentRunSpec {
|
|
9
19
|
/** Appended to the CLI's default system prompt (`--append-system-prompt`). */
|
|
10
20
|
systemPrompt?: string;
|
|
@@ -77,6 +87,13 @@ export type AgentEvent = {
|
|
|
77
87
|
} | {
|
|
78
88
|
type: 'cost';
|
|
79
89
|
usd: number;
|
|
90
|
+
}
|
|
91
|
+
/** The backend's real session id, once known — codex threads and opencode
|
|
92
|
+
* sessions mint their own id, so the run manager persists this to enable
|
|
93
|
+
* resume ("Continue") and "open in CLI". Claude's equals `spec.sessionId`. */
|
|
94
|
+
| {
|
|
95
|
+
type: 'session';
|
|
96
|
+
sessionId: string;
|
|
80
97
|
} | {
|
|
81
98
|
type: 'turn-end';
|
|
82
99
|
} | {
|
|
@@ -101,8 +118,33 @@ export interface AgentRunResult {
|
|
|
101
118
|
tokensUsed: number;
|
|
102
119
|
sessionId?: string;
|
|
103
120
|
}
|
|
121
|
+
export interface SessionOptions {
|
|
122
|
+
/** Close the session shortly after the first turn ends (single-turn
|
|
123
|
+
* behavior, used for non-interactive workflow steps). Interactive
|
|
124
|
+
* sessions omit this and control `end()` themselves. */
|
|
125
|
+
autoEndAfterFirstTurn?: boolean;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* A live agent session over one spawned backend process. The process stays
|
|
129
|
+
* alive between turns and reads further user messages — that's what makes
|
|
130
|
+
* mid-task follow-ups possible. Implemented identically by every backend
|
|
131
|
+
* (claude stdin, codex app-server, opencode serve).
|
|
132
|
+
*/
|
|
133
|
+
export interface AgentSession {
|
|
134
|
+
/** Resolves when the backend process exits — the session is fully over. */
|
|
135
|
+
result: Promise<AgentRunResult>;
|
|
136
|
+
/** Write a user message into the live session. False when it is closed. */
|
|
137
|
+
sendMessage(content: ContentBlock[]): boolean;
|
|
138
|
+
/** Graceful close: end input, then a SIGTERM→SIGKILL watchdog. */
|
|
139
|
+
end(): void;
|
|
140
|
+
/** Hard stop (used by cancel). */
|
|
141
|
+
interrupt(): void;
|
|
142
|
+
/** True while the session still accepts messages. */
|
|
143
|
+
readonly open: boolean;
|
|
144
|
+
}
|
|
104
145
|
export interface AgentRunner {
|
|
105
146
|
readonly backend: AgentBackend;
|
|
106
147
|
run(spec: AgentRunSpec, onEvent?: (event: AgentEvent) => void): Promise<AgentRunResult>;
|
|
148
|
+
startSession(spec: AgentRunSpec, onEvent?: (event: AgentEvent) => void, opts?: SessionOptions): AgentSession;
|
|
107
149
|
interrupt(): Promise<void>;
|
|
108
150
|
}
|
|
@@ -2,7 +2,13 @@
|
|
|
2
2
|
* The backend-agnostic seam for running one agent task. Adapted from
|
|
3
3
|
* @cezar/core's `agents/agent-runner.ts`, trimmed for single-user local use:
|
|
4
4
|
* no token-budget circuit breaker, no zod response schemas — one run is one
|
|
5
|
-
*
|
|
5
|
+
* agent-CLI session streaming normalized events.
|
|
6
|
+
*
|
|
7
|
+
* Three interchangeable backends implement this seam, each as a persistent
|
|
8
|
+
* process so multi-turn follow-ups, `waiting`, interrupt and resume all work:
|
|
9
|
+
* - `claude` — Claude Code CLI, stream-json over stdin/stdout;
|
|
10
|
+
* - `codex` — `codex app-server`, JSON-RPC 2.0 (JSONL) over stdin/stdout;
|
|
11
|
+
* - `opencode` — `opencode serve`, HTTP + SSE.
|
|
6
12
|
*/
|
|
7
|
-
export
|
|
13
|
+
export const RUNNER_IDS = ['claude', 'codex', 'opencode'];
|
|
8
14
|
//# sourceMappingURL=agent-runner.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-runner.js","sourceRoot":"","sources":["../../src/core/agent-runner.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"agent-runner.js","sourceRoot":"","sources":["../../src/core/agent-runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH,MAAM,CAAC,MAAM,UAAU,GAAwB,CAAC,QAAQ,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC"}
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
export interface BackendCheck {
|
|
2
|
-
name: 'claude' | 'gh' | 'git';
|
|
2
|
+
name: 'claude' | 'codex' | 'opencode' | 'gh' | 'git';
|
|
3
3
|
available: boolean;
|
|
4
4
|
version?: string;
|
|
5
5
|
hint?: string;
|
|
6
6
|
}
|
|
7
7
|
/**
|
|
8
|
-
* Probe the host for everything cez leans on: the
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* Probe the host for everything cez leans on: the agent CLIs (`claude`, and
|
|
9
|
+
* the optional `codex` / `opencode` alternatives), `gh` (GitHub auth for PR
|
|
10
|
+
* creation) and `git`. Nothing is required except at least one agent CLI — the
|
|
11
|
+
* GUI degrades gracefully, only offers the runners that are present, and shows
|
|
12
|
+
* the hints for the rest.
|
|
11
13
|
*/
|
|
12
14
|
export declare function detectEnvironment(): Promise<BackendCheck[]>;
|
|
13
15
|
/** The host's GitHub token: logged-in `gh` first, `GITHUB_TOKEN` fallback. */
|
|
@@ -2,12 +2,14 @@ import { execFile } from 'node:child_process';
|
|
|
2
2
|
import { promisify } from 'node:util';
|
|
3
3
|
const exec = promisify(execFile);
|
|
4
4
|
/**
|
|
5
|
-
* Probe the host for everything cez leans on: the
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* Probe the host for everything cez leans on: the agent CLIs (`claude`, and
|
|
6
|
+
* the optional `codex` / `opencode` alternatives), `gh` (GitHub auth for PR
|
|
7
|
+
* creation) and `git`. Nothing is required except at least one agent CLI — the
|
|
8
|
+
* GUI degrades gracefully, only offers the runners that are present, and shows
|
|
9
|
+
* the hints for the rest.
|
|
8
10
|
*/
|
|
9
11
|
export async function detectEnvironment() {
|
|
10
|
-
return Promise.all([probeClaude(), probeGh(), probeGit()]);
|
|
12
|
+
return Promise.all([probeClaude(), probeCodex(), probeOpencode(), probeGh(), probeGit()]);
|
|
11
13
|
}
|
|
12
14
|
async function probeClaude() {
|
|
13
15
|
if (process.env.CEZ_DRY_RUN === '1') {
|
|
@@ -40,6 +42,44 @@ async function probeClaude() {
|
|
|
40
42
|
};
|
|
41
43
|
}
|
|
42
44
|
}
|
|
45
|
+
async function probeCodex() {
|
|
46
|
+
const bin = process.env.CEZ_CODEX_BIN ?? 'codex';
|
|
47
|
+
try {
|
|
48
|
+
const { stdout } = await exec(bin, ['--version'], { timeout: 10_000 });
|
|
49
|
+
return {
|
|
50
|
+
name: 'codex',
|
|
51
|
+
available: true,
|
|
52
|
+
version: stdout.trim(),
|
|
53
|
+
hint: 'if not authenticated, run `codex` once and log in',
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return {
|
|
58
|
+
name: 'codex',
|
|
59
|
+
available: false,
|
|
60
|
+
hint: 'optional: install the Codex CLI (npm i -g @openai/codex) and log in to use the Codex runner',
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
async function probeOpencode() {
|
|
65
|
+
const bin = process.env.CEZ_OPENCODE_BIN ?? 'opencode';
|
|
66
|
+
try {
|
|
67
|
+
const { stdout } = await exec(bin, ['--version'], { timeout: 10_000 });
|
|
68
|
+
return {
|
|
69
|
+
name: 'opencode',
|
|
70
|
+
available: true,
|
|
71
|
+
version: stdout.trim(),
|
|
72
|
+
hint: 'if no provider is configured, run `opencode` once to set one up',
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return {
|
|
77
|
+
name: 'opencode',
|
|
78
|
+
available: false,
|
|
79
|
+
hint: 'optional: install OpenCode (https://opencode.ai) and configure a provider to use the OpenCode runner',
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
43
83
|
async function probeGh() {
|
|
44
84
|
try {
|
|
45
85
|
const { stdout } = await exec('gh', ['auth', 'token'], { timeout: 10_000 });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backend-detect.js","sourceRoot":"","sources":["../../src/core/backend-detect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,IAAI,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AASjC
|
|
1
|
+
{"version":3,"file":"backend-detect.js","sourceRoot":"","sources":["../../src/core/backend-detect.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { AgentEvent, AgentRunResult, AgentRunSpec, AgentRunner,
|
|
1
|
+
import type { AgentEvent, AgentRunResult, AgentRunSpec, AgentRunner, AgentSession, SessionOptions } from './agent-runner.js';
|
|
2
|
+
export type { AgentSession, SessionOptions } from './agent-runner.js';
|
|
2
3
|
/** Default wall-clock cap for a single run before SIGTERM → SIGKILL.
|
|
3
4
|
* Interactive sessions pass `timeoutMs: 0` to disable it entirely. */
|
|
4
5
|
export declare const DEFAULT_RUN_TIMEOUT_MS: number;
|
|
@@ -16,29 +17,6 @@ export interface ClaudeCliRunnerOptions {
|
|
|
16
17
|
/** Wall-clock timeout for a run (ms); per-spec `timeoutMs` still wins. */
|
|
17
18
|
timeoutMs?: number;
|
|
18
19
|
}
|
|
19
|
-
export interface SessionOptions {
|
|
20
|
-
/** Close the session shortly after the first turn ends (single-turn
|
|
21
|
-
* behavior, used for non-interactive workflow steps). Interactive
|
|
22
|
-
* sessions omit this and control `end()` themselves. */
|
|
23
|
-
autoEndAfterFirstTurn?: boolean;
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* A live agent session over one spawned claude process. The process stays
|
|
27
|
-
* alive between turns (no `-p`) and reads further user messages from stdin —
|
|
28
|
-
* that's what makes mid-task follow-ups and pasted screenshots possible.
|
|
29
|
-
*/
|
|
30
|
-
export interface AgentSession {
|
|
31
|
-
/** Resolves when the claude process exits — the session is fully over. */
|
|
32
|
-
result: Promise<AgentRunResult>;
|
|
33
|
-
/** Write a user message into the live session. False when stdin is closed. */
|
|
34
|
-
sendMessage(content: ContentBlock[]): boolean;
|
|
35
|
-
/** Graceful close: EOF on stdin, then the SIGTERM→SIGKILL watchdog. */
|
|
36
|
-
end(): void;
|
|
37
|
-
/** Hard stop (used by cancel). */
|
|
38
|
-
interrupt(): void;
|
|
39
|
-
/** True while the session still accepts messages. */
|
|
40
|
-
readonly open: boolean;
|
|
41
|
-
}
|
|
42
20
|
/**
|
|
43
21
|
* `AgentRunner` over the Claude Code CLI in headless stream-json mode. Auth =
|
|
44
22
|
* the host's logged-in Pro/Max subscription (no API key needed). Sandboxing is
|
|
@@ -50,7 +28,7 @@ export interface AgentSession {
|
|
|
50
28
|
* came from @cezar/core's `ClaudeCodeCliRunner`.
|
|
51
29
|
*/
|
|
52
30
|
export declare class ClaudeCliRunner implements AgentRunner {
|
|
53
|
-
readonly backend: "claude
|
|
31
|
+
readonly backend: "claude";
|
|
54
32
|
private readonly bin;
|
|
55
33
|
private readonly timeoutMs;
|
|
56
34
|
private lastSession;
|