@pat-lewczuk/cezar 0.1.2 → 0.1.3
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/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/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/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/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/server/server.js +34 -10
- package/dist/server/server.js.map +1 -1
- 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.js +145 -18
- package/web/index.html +1 -0
- package/web/style.css +28 -8
|
@@ -14,6 +14,8 @@ export declare const workflowStepSchema: z.ZodEffects<z.ZodObject<{
|
|
|
14
14
|
prompt: z.ZodOptional<z.ZodString>;
|
|
15
15
|
skill: z.ZodOptional<z.ZodString>;
|
|
16
16
|
model: z.ZodOptional<z.ZodString>;
|
|
17
|
+
/** Per-step agent backend override (falls back to the task / config default). */
|
|
18
|
+
runner: z.ZodOptional<z.ZodEnum<["claude", "codex", "opencode"]>>;
|
|
17
19
|
allowedTools: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
18
20
|
bashAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
19
21
|
command: z.ZodOptional<z.ZodString>;
|
|
@@ -31,6 +33,7 @@ export declare const workflowStepSchema: z.ZodEffects<z.ZodObject<{
|
|
|
31
33
|
id: string;
|
|
32
34
|
name?: string | undefined;
|
|
33
35
|
model?: string | undefined;
|
|
36
|
+
runner?: "claude" | "codex" | "opencode" | undefined;
|
|
34
37
|
skill?: string | undefined;
|
|
35
38
|
command?: string | undefined;
|
|
36
39
|
prompt?: string | undefined;
|
|
@@ -44,6 +47,7 @@ export declare const workflowStepSchema: z.ZodEffects<z.ZodObject<{
|
|
|
44
47
|
id: string;
|
|
45
48
|
name?: string | undefined;
|
|
46
49
|
model?: string | undefined;
|
|
50
|
+
runner?: "claude" | "codex" | "opencode" | undefined;
|
|
47
51
|
skill?: string | undefined;
|
|
48
52
|
command?: string | undefined;
|
|
49
53
|
prompt?: string | undefined;
|
|
@@ -57,6 +61,7 @@ export declare const workflowStepSchema: z.ZodEffects<z.ZodObject<{
|
|
|
57
61
|
id: string;
|
|
58
62
|
name?: string | undefined;
|
|
59
63
|
model?: string | undefined;
|
|
64
|
+
runner?: "claude" | "codex" | "opencode" | undefined;
|
|
60
65
|
skill?: string | undefined;
|
|
61
66
|
command?: string | undefined;
|
|
62
67
|
prompt?: string | undefined;
|
|
@@ -70,6 +75,7 @@ export declare const workflowStepSchema: z.ZodEffects<z.ZodObject<{
|
|
|
70
75
|
id: string;
|
|
71
76
|
name?: string | undefined;
|
|
72
77
|
model?: string | undefined;
|
|
78
|
+
runner?: "claude" | "codex" | "opencode" | undefined;
|
|
73
79
|
skill?: string | undefined;
|
|
74
80
|
command?: string | undefined;
|
|
75
81
|
prompt?: string | undefined;
|
|
@@ -94,6 +100,8 @@ export declare const workflowFileSchema: z.ZodEffects<z.ZodObject<{
|
|
|
94
100
|
prompt: z.ZodOptional<z.ZodString>;
|
|
95
101
|
skill: z.ZodOptional<z.ZodString>;
|
|
96
102
|
model: z.ZodOptional<z.ZodString>;
|
|
103
|
+
/** Per-step agent backend override (falls back to the task / config default). */
|
|
104
|
+
runner: z.ZodOptional<z.ZodEnum<["claude", "codex", "opencode"]>>;
|
|
97
105
|
allowedTools: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
98
106
|
bashAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
99
107
|
command: z.ZodOptional<z.ZodString>;
|
|
@@ -111,6 +119,7 @@ export declare const workflowFileSchema: z.ZodEffects<z.ZodObject<{
|
|
|
111
119
|
id: string;
|
|
112
120
|
name?: string | undefined;
|
|
113
121
|
model?: string | undefined;
|
|
122
|
+
runner?: "claude" | "codex" | "opencode" | undefined;
|
|
114
123
|
skill?: string | undefined;
|
|
115
124
|
command?: string | undefined;
|
|
116
125
|
prompt?: string | undefined;
|
|
@@ -124,6 +133,7 @@ export declare const workflowFileSchema: z.ZodEffects<z.ZodObject<{
|
|
|
124
133
|
id: string;
|
|
125
134
|
name?: string | undefined;
|
|
126
135
|
model?: string | undefined;
|
|
136
|
+
runner?: "claude" | "codex" | "opencode" | undefined;
|
|
127
137
|
skill?: string | undefined;
|
|
128
138
|
command?: string | undefined;
|
|
129
139
|
prompt?: string | undefined;
|
|
@@ -137,6 +147,7 @@ export declare const workflowFileSchema: z.ZodEffects<z.ZodObject<{
|
|
|
137
147
|
id: string;
|
|
138
148
|
name?: string | undefined;
|
|
139
149
|
model?: string | undefined;
|
|
150
|
+
runner?: "claude" | "codex" | "opencode" | undefined;
|
|
140
151
|
skill?: string | undefined;
|
|
141
152
|
command?: string | undefined;
|
|
142
153
|
prompt?: string | undefined;
|
|
@@ -150,6 +161,7 @@ export declare const workflowFileSchema: z.ZodEffects<z.ZodObject<{
|
|
|
150
161
|
id: string;
|
|
151
162
|
name?: string | undefined;
|
|
152
163
|
model?: string | undefined;
|
|
164
|
+
runner?: "claude" | "codex" | "opencode" | undefined;
|
|
153
165
|
skill?: string | undefined;
|
|
154
166
|
command?: string | undefined;
|
|
155
167
|
prompt?: string | undefined;
|
|
@@ -167,6 +179,7 @@ export declare const workflowFileSchema: z.ZodEffects<z.ZodObject<{
|
|
|
167
179
|
id: string;
|
|
168
180
|
name?: string | undefined;
|
|
169
181
|
model?: string | undefined;
|
|
182
|
+
runner?: "claude" | "codex" | "opencode" | undefined;
|
|
170
183
|
skill?: string | undefined;
|
|
171
184
|
command?: string | undefined;
|
|
172
185
|
prompt?: string | undefined;
|
|
@@ -185,6 +198,7 @@ export declare const workflowFileSchema: z.ZodEffects<z.ZodObject<{
|
|
|
185
198
|
id: string;
|
|
186
199
|
name?: string | undefined;
|
|
187
200
|
model?: string | undefined;
|
|
201
|
+
runner?: "claude" | "codex" | "opencode" | undefined;
|
|
188
202
|
skill?: string | undefined;
|
|
189
203
|
command?: string | undefined;
|
|
190
204
|
prompt?: string | undefined;
|
|
@@ -203,6 +217,7 @@ export declare const workflowFileSchema: z.ZodEffects<z.ZodObject<{
|
|
|
203
217
|
id: string;
|
|
204
218
|
name?: string | undefined;
|
|
205
219
|
model?: string | undefined;
|
|
220
|
+
runner?: "claude" | "codex" | "opencode" | undefined;
|
|
206
221
|
skill?: string | undefined;
|
|
207
222
|
command?: string | undefined;
|
|
208
223
|
prompt?: string | undefined;
|
|
@@ -221,6 +236,7 @@ export declare const workflowFileSchema: z.ZodEffects<z.ZodObject<{
|
|
|
221
236
|
id: string;
|
|
222
237
|
name?: string | undefined;
|
|
223
238
|
model?: string | undefined;
|
|
239
|
+
runner?: "claude" | "codex" | "opencode" | undefined;
|
|
224
240
|
skill?: string | undefined;
|
|
225
241
|
command?: string | undefined;
|
|
226
242
|
prompt?: string | undefined;
|
package/dist/workflows/types.js
CHANGED
|
@@ -16,6 +16,8 @@ export const workflowStepSchema = z
|
|
|
16
16
|
prompt: z.string().optional(),
|
|
17
17
|
skill: z.string().optional(),
|
|
18
18
|
model: z.string().optional(),
|
|
19
|
+
/** Per-step agent backend override (falls back to the task / config default). */
|
|
20
|
+
runner: z.enum(['claude', 'codex', 'opencode']).optional(),
|
|
19
21
|
allowedTools: z.array(z.string()).optional(),
|
|
20
22
|
bashAllowlist: z.array(z.string()).optional(),
|
|
21
23
|
// check step
|
|
@@ -79,7 +81,7 @@ export function skillStackOf(steps) {
|
|
|
79
81
|
return null;
|
|
80
82
|
if (s.name !== undefined && s.name !== s.skill)
|
|
81
83
|
return null;
|
|
82
|
-
if (s.model || s.allowedTools || s.bashAllowlist || s.onFail)
|
|
84
|
+
if (s.model || s.runner || s.allowedTools || s.bashAllowlist || s.onFail)
|
|
83
85
|
return null;
|
|
84
86
|
skills.push(s.skill);
|
|
85
87
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/workflows/types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/workflows/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pat-lewczuk/cezar",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Local cockpit for running and tracking AI agent tasks in your repo. Uses your logged-in `claude` CLI and `gh` — zero config, zero database.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
package/web/app.js
CHANGED
|
@@ -16,7 +16,9 @@ const state = {
|
|
|
16
16
|
taskSource: 'workflow', // 'workflow' (a chain) | 'skill' — what taskRef names
|
|
17
17
|
taskRef: null, // selected chain/skill name (the "≡ fix-and-verify" pill)
|
|
18
18
|
taskModel: '', // model override ('' = auto; the "⊞ auto" pill)
|
|
19
|
-
modelsAvailable: false, //
|
|
19
|
+
modelsAvailable: false, // agent CLI detected → model menu lists that runner's models
|
|
20
|
+
taskRunner: 'claude', // selected agent backend (the "⚙ claude" pill)
|
|
21
|
+
runnersAvailable: ['claude'], // runner ids detected on the host (from /api/health)
|
|
20
22
|
srcMenuTab: 'workflow', // Workflows | Skills tab inside the source pill menu
|
|
21
23
|
srcMenuQuery: '', // search box inside the source pill menu
|
|
22
24
|
pendingImages: [], // [{mediaType, data, preview}] queued for the next message
|
|
@@ -437,6 +439,7 @@ const PILL_ICONS = {
|
|
|
437
439
|
chain: 'M4 6h16M4 12h16M4 18h10', // ≡ list
|
|
438
440
|
skill: 'M4 19.5A2.5 2.5 0 016.5 17H20M6.5 2H20v20H6.5A2.5 2.5 0 014 19.5v-15A2.5 2.5 0 016.5 2z', // book
|
|
439
441
|
model: 'M9 3v3M15 3v3M9 18v3M15 18v3M3 9h3M3 15h3M18 9h3M18 15h3M6 6h12v12H6z', // chip
|
|
442
|
+
runner: 'M12 2l9 5v10l-9 5-9-5V7l9-5zM12 2v20M3 7l9 5 9-5', // 3D box (backend/engine)
|
|
440
443
|
};
|
|
441
444
|
|
|
442
445
|
/* Small inline icons for the run-detail action bar (design: every action has
|
|
@@ -526,7 +529,33 @@ function renderTaskPills() {
|
|
|
526
529
|
srcMenu,
|
|
527
530
|
);
|
|
528
531
|
|
|
529
|
-
|
|
532
|
+
// Runner pill — only shown when more than one backend is installed, so a
|
|
533
|
+
// single-runner (claude-only) host stays as simple as before.
|
|
534
|
+
const runnerPill = $('#runner-pill');
|
|
535
|
+
if (runnerPill) {
|
|
536
|
+
const runners = RUNNERS.filter((r) => state.runnersAvailable.includes(r.id));
|
|
537
|
+
if (runners.length > 1) {
|
|
538
|
+
runnerPill.hidden = false;
|
|
539
|
+
const selected = runners.find((r) => r.id === state.taskRunner) ?? runners[0];
|
|
540
|
+
const runnerMenu = runners
|
|
541
|
+
.map((r) =>
|
|
542
|
+
menuItemHtml(
|
|
543
|
+
`data-mi="runner" data-value="${esc(r.id)}"`,
|
|
544
|
+
r.label,
|
|
545
|
+
r.desc,
|
|
546
|
+
r.id === selected.id,
|
|
547
|
+
PILL_ICONS.runner,
|
|
548
|
+
),
|
|
549
|
+
)
|
|
550
|
+
.join('');
|
|
551
|
+
runnerPill.innerHTML = pillHtml(PILL_ICONS.runner, selected.label, runnerMenu);
|
|
552
|
+
} else {
|
|
553
|
+
runnerPill.hidden = true;
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
const all = modelsForRunner(state.taskRunner);
|
|
558
|
+
const models = state.modelsAvailable ? all : all.slice(0, 1);
|
|
530
559
|
const selectedModel = models.find((m) => m.id === state.taskModel) ?? models[0];
|
|
531
560
|
const modelMenu = models
|
|
532
561
|
.map((m) =>
|
|
@@ -564,25 +593,64 @@ function renderChrome(health) {
|
|
|
564
593
|
)
|
|
565
594
|
.join('');
|
|
566
595
|
|
|
567
|
-
//
|
|
568
|
-
|
|
569
|
-
|
|
596
|
+
// Which agent backends are installed → which runners the pill offers.
|
|
597
|
+
const available = RUNNERS.map((r) => r.id).filter((id) =>
|
|
598
|
+
health.checks.some((c) => c.name === id && c.available),
|
|
599
|
+
);
|
|
600
|
+
state.runnersAvailable = available.length ? available : ['claude'];
|
|
601
|
+
// Preselect the configured default when it's installed, else the first
|
|
602
|
+
// available runner.
|
|
603
|
+
const preferred = health.defaultRunner;
|
|
604
|
+
if (preferred && state.runnersAvailable.includes(preferred)) {
|
|
605
|
+
state.taskRunner = preferred;
|
|
606
|
+
} else if (!state.runnersAvailable.includes(state.taskRunner)) {
|
|
607
|
+
state.taskRunner = state.runnersAvailable[0];
|
|
608
|
+
}
|
|
609
|
+
// Model pill is populated only when the selected runner's CLI is present;
|
|
610
|
+
// otherwise it collapses to "auto".
|
|
611
|
+
state.modelsAvailable = state.runnersAvailable.includes(state.taskRunner);
|
|
570
612
|
renderTaskPills();
|
|
571
613
|
}
|
|
572
614
|
|
|
573
|
-
/*
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
{ id: '', label: '
|
|
578
|
-
{ id: '
|
|
579
|
-
{ id: 'sonnet', label: 'sonnet', desc: 'Fast and cheap' },
|
|
580
|
-
{ id: 'haiku', label: 'haiku', desc: 'Fastest — simple, scoped tasks' },
|
|
581
|
-
{ id: 'claude-opus-4-8', label: 'Opus 4.8', desc: 'Pinned version' },
|
|
582
|
-
{ id: 'claude-sonnet-5', label: 'Sonnet 5', desc: 'Pinned version' },
|
|
583
|
-
{ id: 'claude-haiku-4-5', label: 'Haiku 4.5', desc: 'Pinned version' },
|
|
615
|
+
/* The selectable agent backends. Only those actually installed on the host
|
|
616
|
+
(detected via /api/health checks) are offered in the pill. */
|
|
617
|
+
const RUNNERS = [
|
|
618
|
+
{ id: 'claude', label: 'claude', desc: 'Claude Code CLI' },
|
|
619
|
+
{ id: 'codex', label: 'codex', desc: 'OpenAI Codex (app-server)' },
|
|
620
|
+
{ id: 'opencode', label: 'opencode', desc: 'OpenCode (serve)' },
|
|
584
621
|
];
|
|
585
622
|
|
|
623
|
+
/* Model presets per runner. `id: ''` is always "auto" — no model flag, the
|
|
624
|
+
runner decides. Claude takes tier aliases + pinned versions; Codex takes
|
|
625
|
+
gpt-*-codex ids; OpenCode takes `provider/model` ids. */
|
|
626
|
+
const MODELS_BY_RUNNER = {
|
|
627
|
+
claude: [
|
|
628
|
+
{ id: '', label: 'auto', desc: 'Pick the best model per step' },
|
|
629
|
+
{ id: 'opus', label: 'opus', desc: 'Deep reasoning for hard tasks' },
|
|
630
|
+
{ id: 'sonnet', label: 'sonnet', desc: 'Fast and cheap' },
|
|
631
|
+
{ id: 'haiku', label: 'haiku', desc: 'Fastest — simple, scoped tasks' },
|
|
632
|
+
{ id: 'claude-opus-4-8', label: 'Opus 4.8', desc: 'Pinned version' },
|
|
633
|
+
{ id: 'claude-sonnet-5', label: 'Sonnet 5', desc: 'Pinned version' },
|
|
634
|
+
{ id: 'claude-haiku-4-5', label: 'Haiku 4.5', desc: 'Pinned version' },
|
|
635
|
+
],
|
|
636
|
+
codex: [
|
|
637
|
+
{ id: '', label: 'auto', desc: 'Use your Codex default model' },
|
|
638
|
+
{ id: 'gpt-5.1-codex', label: 'gpt-5.1-codex', desc: 'Codex-tuned' },
|
|
639
|
+
{ id: 'gpt-5.1-codex-mini', label: 'gpt-5.1-codex-mini', desc: 'Faster, cheaper' },
|
|
640
|
+
{ id: 'gpt-5-codex', label: 'gpt-5-codex', desc: 'Previous generation' },
|
|
641
|
+
],
|
|
642
|
+
opencode: [
|
|
643
|
+
{ id: '', label: 'auto', desc: 'Use your OpenCode default model' },
|
|
644
|
+
{ id: 'anthropic/claude-sonnet-4-5', label: 'claude-sonnet-4.5', desc: 'via Anthropic' },
|
|
645
|
+
{ id: 'openai/gpt-5.1', label: 'gpt-5.1', desc: 'via OpenAI' },
|
|
646
|
+
{ id: 'openai/gpt-5.1-codex', label: 'gpt-5.1-codex', desc: 'via OpenAI' },
|
|
647
|
+
],
|
|
648
|
+
};
|
|
649
|
+
|
|
650
|
+
function modelsForRunner(runner) {
|
|
651
|
+
return MODELS_BY_RUNNER[runner] ?? MODELS_BY_RUNNER.claude;
|
|
652
|
+
}
|
|
653
|
+
|
|
586
654
|
/* The global stream replays nothing after a drop (laptop sleep, server
|
|
587
655
|
restart) — a missed `run` event would leave a stale status in the sidebar
|
|
588
656
|
forever (seen live: a run resting at `review` still listed under Working).
|
|
@@ -720,6 +788,10 @@ function bindUi() {
|
|
|
720
788
|
state.taskRef = item.dataset.value;
|
|
721
789
|
} else if (item.dataset.mi === 'model') {
|
|
722
790
|
state.taskModel = item.dataset.value;
|
|
791
|
+
} else if (item.dataset.mi === 'runner') {
|
|
792
|
+
// Switching backend invalidates the model list — reset to auto.
|
|
793
|
+
state.taskRunner = item.dataset.value;
|
|
794
|
+
state.taskModel = '';
|
|
723
795
|
}
|
|
724
796
|
closePillMenus();
|
|
725
797
|
renderTaskPills();
|
|
@@ -864,6 +936,7 @@ function bindUi() {
|
|
|
864
936
|
const body = {
|
|
865
937
|
task: form.task.value.trim(),
|
|
866
938
|
model: state.taskModel || undefined,
|
|
939
|
+
runner: state.runnersAvailable.length > 1 ? state.taskRunner : undefined,
|
|
867
940
|
variants: state.variants > 1 ? state.variants : undefined,
|
|
868
941
|
images: state.taskImages.length
|
|
869
942
|
? state.taskImages.map((i) => ({ mediaType: i.mediaType, data: i.data }))
|
|
@@ -1649,6 +1722,7 @@ function updateDetail(run) {
|
|
|
1649
1722
|
run.costUsd ? esc(fmtCost(run.costUsd)) : null,
|
|
1650
1723
|
`started ${esc(timeAgo(run.startedAt ?? run.createdAt))}`,
|
|
1651
1724
|
run.finishedAt ? `finished ${esc(timeAgo(run.finishedAt))}` : null,
|
|
1725
|
+
run.runner && run.runner !== 'claude' ? `runner ${esc(run.runner)}` : null,
|
|
1652
1726
|
run.model ? `model ${esc(run.model)}` : null,
|
|
1653
1727
|
run.branch ? esc(run.branch) : null,
|
|
1654
1728
|
prLink(run) || null,
|
|
@@ -1892,6 +1966,53 @@ function toolArg(input) {
|
|
|
1892
1966
|
return null;
|
|
1893
1967
|
}
|
|
1894
1968
|
|
|
1969
|
+
/* Claude-Code-style collapsing for tool streaks: consecutive tool calls /
|
|
1970
|
+
results stack in one group — the last few stay visible, older ones fold
|
|
1971
|
+
under a "\u25b8 N earlier tool calls" toggle. Any other event breaks the
|
|
1972
|
+
streak. Selecting another run clears the log, which disconnects the group —
|
|
1973
|
+
the isConnected check below then starts a fresh one. */
|
|
1974
|
+
const STREAK_TAIL = 3;
|
|
1975
|
+
let toolStreak = null; // { wrap, toggle, hiddenBox, tailBox }
|
|
1976
|
+
|
|
1977
|
+
function streakLabel(hiddenBox) {
|
|
1978
|
+
const n = hiddenBox.children.length;
|
|
1979
|
+
return `${hiddenBox.hidden ? '\u25b8' : '\u25be'} ${n} earlier tool call${n === 1 ? '' : 's'}`;
|
|
1980
|
+
}
|
|
1981
|
+
|
|
1982
|
+
function newToolStreak(inner) {
|
|
1983
|
+
const wrap = document.createElement('div');
|
|
1984
|
+
wrap.className = 'ev tool-streak';
|
|
1985
|
+
const toggle = document.createElement('button');
|
|
1986
|
+
toggle.type = 'button';
|
|
1987
|
+
toggle.className = 'streak-toggle';
|
|
1988
|
+
toggle.hidden = true;
|
|
1989
|
+
const hiddenBox = document.createElement('div');
|
|
1990
|
+
hiddenBox.className = 'streak-box';
|
|
1991
|
+
hiddenBox.hidden = true;
|
|
1992
|
+
const tailBox = document.createElement('div');
|
|
1993
|
+
tailBox.className = 'streak-box';
|
|
1994
|
+
toggle.addEventListener('click', () => {
|
|
1995
|
+
hiddenBox.hidden = !hiddenBox.hidden;
|
|
1996
|
+
toggle.textContent = streakLabel(hiddenBox);
|
|
1997
|
+
});
|
|
1998
|
+
wrap.append(toggle, hiddenBox, tailBox);
|
|
1999
|
+
inner.appendChild(wrap);
|
|
2000
|
+
return { wrap, toggle, hiddenBox, tailBox };
|
|
2001
|
+
}
|
|
2002
|
+
|
|
2003
|
+
function appendToStreak(inner, el) {
|
|
2004
|
+
if (!toolStreak || !toolStreak.wrap.isConnected) toolStreak = newToolStreak(inner);
|
|
2005
|
+
toolStreak.tailBox.appendChild(el);
|
|
2006
|
+
// Overflow rolls the oldest visible chip into the folded box (order kept).
|
|
2007
|
+
while (toolStreak.tailBox.children.length > STREAK_TAIL) {
|
|
2008
|
+
toolStreak.hiddenBox.appendChild(toolStreak.tailBox.firstElementChild);
|
|
2009
|
+
}
|
|
2010
|
+
if (toolStreak.hiddenBox.children.length > 0) {
|
|
2011
|
+
toolStreak.toggle.hidden = false;
|
|
2012
|
+
toolStreak.toggle.textContent = streakLabel(toolStreak.hiddenBox);
|
|
2013
|
+
}
|
|
2014
|
+
}
|
|
2015
|
+
|
|
1895
2016
|
function appendLog(evt) {
|
|
1896
2017
|
const inner = $('#log-inner');
|
|
1897
2018
|
const log = $('#log');
|
|
@@ -1985,7 +2106,12 @@ function appendLog(evt) {
|
|
|
1985
2106
|
el.textContent = JSON.stringify(evt);
|
|
1986
2107
|
}
|
|
1987
2108
|
|
|
1988
|
-
|
|
2109
|
+
if (evt.type === 'tool-call' || evt.type === 'tool-result') {
|
|
2110
|
+
appendToStreak(inner, el);
|
|
2111
|
+
} else {
|
|
2112
|
+
toolStreak = null; // anything else breaks the streak
|
|
2113
|
+
inner.appendChild(el);
|
|
2114
|
+
}
|
|
1989
2115
|
if (state.autoScroll) log.scrollTop = log.scrollHeight;
|
|
1990
2116
|
}
|
|
1991
2117
|
|
|
@@ -2725,7 +2851,7 @@ function wbSkillStack(steps) {
|
|
|
2725
2851
|
if (s.command || !s.skill) return null;
|
|
2726
2852
|
if (s.prompt !== undefined && s.prompt !== '{{task}}') return null;
|
|
2727
2853
|
if (s.name !== undefined && s.name !== s.skill) return null;
|
|
2728
|
-
if (s.model || s.allowedTools || s.bashAllowlist || s.onFail) return null;
|
|
2854
|
+
if (s.model || s.runner || s.allowedTools || s.bashAllowlist || s.onFail) return null;
|
|
2729
2855
|
skills.push(s.skill);
|
|
2730
2856
|
}
|
|
2731
2857
|
return skills.length ? skills : null;
|
|
@@ -2764,6 +2890,7 @@ function wbYamlText() {
|
|
|
2764
2890
|
if (s.skill) lines.push(` skill: ${yamlScalar(s.skill)}`);
|
|
2765
2891
|
if (s.prompt) lines.push(...yamlBlock('prompt', s.prompt, 4));
|
|
2766
2892
|
if (s.model) lines.push(` model: ${yamlScalar(s.model)}`);
|
|
2893
|
+
if (s.runner) lines.push(` runner: ${yamlScalar(s.runner)}`);
|
|
2767
2894
|
if (s.allowedTools) lines.push(` allowedTools: [${s.allowedTools.map(yamlScalar).join(', ')}]`);
|
|
2768
2895
|
if (s.bashAllowlist) lines.push(` bashAllowlist: [${s.bashAllowlist.map(yamlScalar).join(', ')}]`);
|
|
2769
2896
|
if (s.command) lines.push(...yamlBlock('command', s.command, 4));
|
package/web/index.html
CHANGED
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"><path d="M12 3l2 5.5L19.5 10 14 12l-2 5.5L10 12l-5.5-2L10 8.5 12 3z"/></svg>
|
|
37
37
|
Plan
|
|
38
38
|
</button>
|
|
39
|
+
<div class="pill-select" id="runner-pill" data-pill="runner" hidden></div>
|
|
39
40
|
<div class="pill-select" id="model-pill" data-pill="model"></div>
|
|
40
41
|
<button type="submit" id="run-btn" class="tip-right" data-tip="Run the task (⌘↵)">
|
|
41
42
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><path d="M12 19V5M6 11l6-6 6 6"/></svg>
|
package/web/style.css
CHANGED
|
@@ -229,8 +229,8 @@ summary::-webkit-details-marker { display: none; }
|
|
|
229
229
|
/* ---- sidebar ---- */
|
|
230
230
|
|
|
231
231
|
#sidebar {
|
|
232
|
-
width:
|
|
233
|
-
min-width:
|
|
232
|
+
width: 318px;
|
|
233
|
+
min-width: 318px;
|
|
234
234
|
display: flex;
|
|
235
235
|
flex-direction: column;
|
|
236
236
|
min-height: 0;
|
|
@@ -291,11 +291,11 @@ summary::-webkit-details-marker { display: none; }
|
|
|
291
291
|
#task-thumbs img { height: 38px; border-radius: 7px; border: 1px solid var(--line2); display: block; }
|
|
292
292
|
#task-thumbs .thumb:hover img { border-color: var(--red); opacity: 0.7; }
|
|
293
293
|
#new-task .row { display: flex; gap: 7px; align-items: center; }
|
|
294
|
+
#new-task .row.actions { flex-wrap: wrap; row-gap: 6px; }
|
|
294
295
|
|
|
295
296
|
/* pill dropdowns — "≡ fix-and-verify ⌄" / "⊞ auto ⌄" */
|
|
296
297
|
.pill-select { position: relative; min-width: 0; }
|
|
297
|
-
#src-pill { flex: 0 1 auto; min-width: 0; }
|
|
298
|
-
#model-pill { flex: 0 1 auto; min-width: 0; }
|
|
298
|
+
#src-pill, #model-pill, #runner-pill { flex: 0 1 auto; min-width: 0; }
|
|
299
299
|
.pill-btn {
|
|
300
300
|
display: inline-flex;
|
|
301
301
|
align-items: center;
|
|
@@ -677,10 +677,10 @@ summary::-webkit-details-marker { display: none; }
|
|
|
677
677
|
border-top: 1px solid var(--line);
|
|
678
678
|
padding: 11px 16px;
|
|
679
679
|
display: flex;
|
|
680
|
-
align-items:
|
|
681
|
-
gap:
|
|
680
|
+
align-items: flex-end;
|
|
681
|
+
gap: 8px;
|
|
682
682
|
}
|
|
683
|
-
#env-chips { display: flex; gap:
|
|
683
|
+
#env-chips { display: flex; flex-wrap: wrap; gap: 6px 9px; min-width: 0; flex: 1 1 auto; }
|
|
684
684
|
.env-chip {
|
|
685
685
|
display: flex;
|
|
686
686
|
align-items: center;
|
|
@@ -694,6 +694,8 @@ summary::-webkit-details-marker { display: none; }
|
|
|
694
694
|
.env-chip.bad .led { background: var(--red); }
|
|
695
695
|
#theme-toggle {
|
|
696
696
|
margin-left: auto;
|
|
697
|
+
align-self: flex-end;
|
|
698
|
+
flex: none;
|
|
697
699
|
border: none;
|
|
698
700
|
background: transparent;
|
|
699
701
|
color: var(--text3);
|
|
@@ -906,6 +908,24 @@ main { flex: 1; min-width: 0; display: flex; min-height: 0; background: var(--bg
|
|
|
906
908
|
white-space: nowrap;
|
|
907
909
|
max-width: 46ch;
|
|
908
910
|
}
|
|
911
|
+
/* collapsed tool streaks (Claude-Code style) */
|
|
912
|
+
.ev.tool-streak { min-width: 0; margin: 4px 0; }
|
|
913
|
+
.streak-box { display: flex; flex-direction: column; align-items: flex-start; min-width: 0; }
|
|
914
|
+
.streak-box[hidden] { display: none; }
|
|
915
|
+
.streak-toggle {
|
|
916
|
+
display: inline-flex;
|
|
917
|
+
align-items: center;
|
|
918
|
+
border: none;
|
|
919
|
+
background: transparent;
|
|
920
|
+
color: var(--text3);
|
|
921
|
+
font-family: var(--mono);
|
|
922
|
+
font-size: 10.5px;
|
|
923
|
+
cursor: pointer;
|
|
924
|
+
padding: 3px 2px;
|
|
925
|
+
margin: 1px 0;
|
|
926
|
+
}
|
|
927
|
+
.streak-toggle:hover { color: var(--text2); }
|
|
928
|
+
|
|
909
929
|
.ev.result { margin: 4px 0; }
|
|
910
930
|
.ev.result summary { cursor: pointer; }
|
|
911
931
|
.ev.result summary:hover { border-color: var(--line2); }
|
|
@@ -1739,7 +1759,7 @@ a.bm:hover { border-color: var(--accent-line); color: var(--accent); text-decora
|
|
|
1739
1759
|
|
|
1740
1760
|
/* narrow screens: sidebar shrinks, splits stack */
|
|
1741
1761
|
@media (max-width: 900px) {
|
|
1742
|
-
#sidebar { width:
|
|
1762
|
+
#sidebar { width: 258px; min-width: 258px; }
|
|
1743
1763
|
.split { grid-template-columns: 1fr; grid-template-rows: minmax(0, 45%) minmax(0, 1fr); }
|
|
1744
1764
|
.split-list { border-right: none; border-bottom: 1px solid var(--line); }
|
|
1745
1765
|
.wb-grid { grid-template-columns: 1fr; grid-template-rows: minmax(0, 1fr) minmax(0, 45%); }
|