@pat-lewczuk/cezar 0.1.3 → 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/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-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/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/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/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/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/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/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
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure codex app-server JSON-RPC → protocol-v2 mapper. `mapCodexNotification`
|
|
3
|
+
* folds one parsed JSONL frame into `UiEvent`s plus the next mapper state;
|
|
4
|
+
* the runner calls it ALONGSIDE the v1 path (v1 events keep flowing
|
|
5
|
+
* unchanged).
|
|
6
|
+
*
|
|
7
|
+
* Contract: `.ai/analysis/cockpit-ui-redesign/agent-event-protocols.md` §3
|
|
8
|
+
* (wire format) and §7.1 "Codex (app-server)" (the mapping). Golden fixtures
|
|
9
|
+
* replaying wire-faithful frame sequences live in `__fixtures__/codex/`.
|
|
10
|
+
*
|
|
11
|
+
* Robustness rule: input is untrusted wire data — the mapper never throws;
|
|
12
|
+
* responses, server→client requests (approval prompts — reserved for the
|
|
13
|
+
* `permission.*` events later) and unknown methods map to zero events.
|
|
14
|
+
*
|
|
15
|
+
* State is explicit and treated as immutable: callers thread the returned
|
|
16
|
+
* `state` into the next call. Ids are deterministic — codex items and turns
|
|
17
|
+
* carry stable wire ids which are reused verbatim (`turn_<n>` is minted only
|
|
18
|
+
* when a turn frame arrives without one) — so replaying a stored transcript
|
|
19
|
+
* reproduces the exact event sequence.
|
|
20
|
+
*
|
|
21
|
+
* Status map (§7.1, kills v1's regex-on-status hack): `inProgress→running`,
|
|
22
|
+
* `completed→completed`, `failed→failed`, `declined→declined`.
|
|
23
|
+
*/
|
|
24
|
+
import { toolDisplay } from './tool-display.js';
|
|
25
|
+
export function createCodexUiState() {
|
|
26
|
+
return {
|
|
27
|
+
sessionStarted: false,
|
|
28
|
+
turnSeq: 0,
|
|
29
|
+
currentTurnId: null,
|
|
30
|
+
knownItems: new Set(),
|
|
31
|
+
outputs: new Map(),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Codex confirms the thread via the `thread/start`/`thread/resume` RESULT
|
|
36
|
+
* (a response frame the mapper cannot attribute), so the runner calls this
|
|
37
|
+
* once the thread id is known. Deduplicated against the `thread/started`
|
|
38
|
+
* notification — whichever arrives first emits `session.started`.
|
|
39
|
+
*/
|
|
40
|
+
export function codexSessionStarted(threadId, state) {
|
|
41
|
+
if (state.sessionStarted || threadId === '')
|
|
42
|
+
return { events: [], state };
|
|
43
|
+
return {
|
|
44
|
+
events: [{ type: 'session.started', sessionId: threadId, backend: 'codex' }],
|
|
45
|
+
state: { ...state, sessionStarted: true },
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/** Fold one parsed JSON-RPC frame into v2 events. Never throws. */
|
|
49
|
+
export function mapCodexNotification(frame, state) {
|
|
50
|
+
if (!isRecord(frame) || typeof frame.method !== 'string')
|
|
51
|
+
return { events: [], state };
|
|
52
|
+
// A frame with both `method` and `id` is a server→client REQUEST (the
|
|
53
|
+
// approval prompts) — reserved for `permission.requested` later.
|
|
54
|
+
if (frame.id !== undefined)
|
|
55
|
+
return { events: [], state };
|
|
56
|
+
const params = isRecord(frame.params) ? frame.params : {};
|
|
57
|
+
switch (frame.method) {
|
|
58
|
+
case 'thread/started':
|
|
59
|
+
return codexSessionStarted(threadIdOf(params) ?? '', state);
|
|
60
|
+
case 'turn/started':
|
|
61
|
+
return mapTurnStarted(params, state);
|
|
62
|
+
case 'turn/completed':
|
|
63
|
+
return mapTurnEnd(params, state, /* failed */ false);
|
|
64
|
+
case 'turn/failed':
|
|
65
|
+
return mapTurnEnd(params, state, /* failed */ true);
|
|
66
|
+
case 'item/started':
|
|
67
|
+
return mapItemLifecycle(params, state, 'item.started');
|
|
68
|
+
case 'item/updated':
|
|
69
|
+
return mapItemLifecycle(params, state, 'item.updated');
|
|
70
|
+
case 'item/completed':
|
|
71
|
+
return mapItemLifecycle(params, state, 'item.completed');
|
|
72
|
+
case 'item/agentMessage/delta':
|
|
73
|
+
return mapDelta(params, state, 'text');
|
|
74
|
+
case 'item/reasoning/textDelta':
|
|
75
|
+
case 'item/reasoning/summaryDelta':
|
|
76
|
+
case 'item/reasoning/summaryTextDelta':
|
|
77
|
+
return mapDelta(params, state, 'reasoning');
|
|
78
|
+
case 'item/commandExecution/outputDelta':
|
|
79
|
+
return mapDelta(params, state, 'output');
|
|
80
|
+
case 'thread/tokenUsage/updated':
|
|
81
|
+
return mapTokenUsage(params, state);
|
|
82
|
+
default:
|
|
83
|
+
// thread/status/changed, thread/closed, … — nothing to render yet.
|
|
84
|
+
return { events: [], state };
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// ---- turn lifecycle ---------------------------------------------------------
|
|
88
|
+
function mapTurnStarted(params, state) {
|
|
89
|
+
const turnSeq = state.turnSeq + 1;
|
|
90
|
+
const turnId = turnIdOf(params) ?? `turn_${turnSeq}`;
|
|
91
|
+
return {
|
|
92
|
+
events: [{ type: 'turn.started', turnId }],
|
|
93
|
+
state: { ...state, turnSeq, currentTurnId: turnId },
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
function mapTurnEnd(params, state, failed) {
|
|
97
|
+
let turnSeq = state.turnSeq;
|
|
98
|
+
const turnId = turnIdOf(params) ?? state.currentTurnId ?? `turn_${++turnSeq}`;
|
|
99
|
+
return {
|
|
100
|
+
events: [{ type: 'turn.completed', turnId, stopReason: turnStopReason(params, failed) }],
|
|
101
|
+
state: { ...state, turnSeq, currentTurnId: null },
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
/** §7.1: turn/completed→end_turn, turn/failed→error — except an interrupted
|
|
105
|
+
* turn (turn.status `interrupted`, or an interrupt-shaped error message,
|
|
106
|
+
* the only wire signals codex gives us) → cancelled. */
|
|
107
|
+
function turnStopReason(params, failed) {
|
|
108
|
+
const turn = isRecord(params.turn) ? params.turn : {};
|
|
109
|
+
if (turn.status === 'interrupted')
|
|
110
|
+
return 'cancelled';
|
|
111
|
+
if (!failed)
|
|
112
|
+
return 'end_turn';
|
|
113
|
+
return /interrupt/i.test(errorMessage(params.error) ?? '') ? 'cancelled' : 'error';
|
|
114
|
+
}
|
|
115
|
+
function mapItemLifecycle(params, state, eventType) {
|
|
116
|
+
const raw = isRecord(params.item) ? params.item : undefined;
|
|
117
|
+
if (!raw || typeof raw.type !== 'string')
|
|
118
|
+
return { events: [], state };
|
|
119
|
+
const type = raw.type;
|
|
120
|
+
// todoList / plan items never render as items — they ARE the plan
|
|
121
|
+
// (full-replacement semantics on every lifecycle phase, §7.1).
|
|
122
|
+
if (type === 'todoList' || type === 'plan') {
|
|
123
|
+
const entries = planEntriesOf(raw);
|
|
124
|
+
if (!entries)
|
|
125
|
+
return { events: [], state };
|
|
126
|
+
return { events: [{ type: 'plan.updated', entries }], state };
|
|
127
|
+
}
|
|
128
|
+
// The user's own message echoed back — the client already rendered what it
|
|
129
|
+
// sent, so it maps to zero events (matching the claude mapper).
|
|
130
|
+
if (type === 'userMessage')
|
|
131
|
+
return { events: [], state };
|
|
132
|
+
const id = str(raw.id);
|
|
133
|
+
if (id === undefined)
|
|
134
|
+
return { events: [], state };
|
|
135
|
+
const item = type === 'agentMessage'
|
|
136
|
+
? messageItem(raw, id)
|
|
137
|
+
: type === 'reasoning'
|
|
138
|
+
? reasoningItem(raw, id)
|
|
139
|
+
: toolItem(raw, id, type, eventType, state);
|
|
140
|
+
const events = [{ type: eventType, item }];
|
|
141
|
+
// Track live ids (for delta synthesis) and drop bookkeeping on completion.
|
|
142
|
+
if (eventType === 'item.completed') {
|
|
143
|
+
if (!state.knownItems.has(id) && !state.outputs.has(id))
|
|
144
|
+
return { events, state };
|
|
145
|
+
const knownItems = new Set(state.knownItems);
|
|
146
|
+
knownItems.delete(id);
|
|
147
|
+
const outputs = new Map(state.outputs);
|
|
148
|
+
outputs.delete(id);
|
|
149
|
+
return { events, state: { ...state, knownItems, outputs } };
|
|
150
|
+
}
|
|
151
|
+
if (state.knownItems.has(id))
|
|
152
|
+
return { events, state };
|
|
153
|
+
return { events, state: { ...state, knownItems: new Set(state.knownItems).add(id) } };
|
|
154
|
+
}
|
|
155
|
+
/** `agentMessage` → message item; `phase` commentary|final_answer→'commentary'|'final'. */
|
|
156
|
+
function messageItem(raw, id) {
|
|
157
|
+
const item = {
|
|
158
|
+
kind: 'message',
|
|
159
|
+
id,
|
|
160
|
+
role: 'assistant',
|
|
161
|
+
text: typeof raw.text === 'string' ? raw.text : '',
|
|
162
|
+
};
|
|
163
|
+
if (raw.phase === 'commentary')
|
|
164
|
+
item.phase = 'commentary';
|
|
165
|
+
else if (raw.phase === 'final_answer')
|
|
166
|
+
item.phase = 'final';
|
|
167
|
+
return item;
|
|
168
|
+
}
|
|
169
|
+
/** `reasoning` → reasoning item — full `content` when present, else the summary. */
|
|
170
|
+
function reasoningItem(raw, id) {
|
|
171
|
+
return { kind: 'reasoning', id, text: str(raw.content) ?? str(raw.summary) ?? '' };
|
|
172
|
+
}
|
|
173
|
+
/** The §7.1 status map — the wire word wins; an item without one derives its
|
|
174
|
+
* status from the lifecycle phase it arrived in. */
|
|
175
|
+
const STATUS_MAP = {
|
|
176
|
+
inProgress: 'running',
|
|
177
|
+
completed: 'completed',
|
|
178
|
+
failed: 'failed',
|
|
179
|
+
declined: 'declined',
|
|
180
|
+
};
|
|
181
|
+
function toolStatus(raw, eventType) {
|
|
182
|
+
const mapped = typeof raw.status === 'string' ? STATUS_MAP[raw.status] : undefined;
|
|
183
|
+
return mapped ?? (eventType === 'item.completed' ? 'completed' : 'running');
|
|
184
|
+
}
|
|
185
|
+
function toolItem(raw, id, type, eventType, state) {
|
|
186
|
+
const status = toolStatus(raw, eventType);
|
|
187
|
+
let item;
|
|
188
|
+
switch (type) {
|
|
189
|
+
case 'commandExecution': {
|
|
190
|
+
const display = toolDisplay('commandExecution', raw);
|
|
191
|
+
item = { kind: 'tool', id, name: type, toolKind: display.toolKind, title: display.title, status };
|
|
192
|
+
if (raw.command !== undefined)
|
|
193
|
+
item.input = { command: raw.command };
|
|
194
|
+
// Wire output wins; else the final snapshot carries what outputDelta streamed.
|
|
195
|
+
const output = str(raw.aggregatedOutput) ??
|
|
196
|
+
str(raw.output) ??
|
|
197
|
+
(eventType === 'item.completed' ? state.outputs.get(id) : undefined);
|
|
198
|
+
if (output !== undefined)
|
|
199
|
+
item.output = output;
|
|
200
|
+
const exitCode = num(raw.exitCode);
|
|
201
|
+
if (exitCode !== undefined)
|
|
202
|
+
item.exitCode = exitCode;
|
|
203
|
+
break;
|
|
204
|
+
}
|
|
205
|
+
case 'fileChange': {
|
|
206
|
+
const display = toolDisplay('fileChange', raw);
|
|
207
|
+
item = { kind: 'tool', id, name: type, toolKind: display.toolKind, title: display.title, status };
|
|
208
|
+
const artifacts = changeArtifacts(raw.changes);
|
|
209
|
+
if (artifacts) {
|
|
210
|
+
item.diffs = artifacts.diffs;
|
|
211
|
+
item.locations = artifacts.locations;
|
|
212
|
+
}
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
215
|
+
case 'mcpToolCall': {
|
|
216
|
+
const server = str(raw.server);
|
|
217
|
+
const tool = str(raw.tool);
|
|
218
|
+
const display = toolDisplay('mcpToolCall', raw);
|
|
219
|
+
item = {
|
|
220
|
+
kind: 'tool',
|
|
221
|
+
id,
|
|
222
|
+
// §7.1: the item is named after what it called, `server.tool`.
|
|
223
|
+
name: server && tool ? `${server}.${tool}` : type,
|
|
224
|
+
toolKind: display.toolKind,
|
|
225
|
+
title: display.title,
|
|
226
|
+
status,
|
|
227
|
+
};
|
|
228
|
+
if (raw.arguments !== undefined)
|
|
229
|
+
item.input = raw.arguments;
|
|
230
|
+
const result = raw.result;
|
|
231
|
+
if (typeof result === 'string')
|
|
232
|
+
item.output = result;
|
|
233
|
+
else if (result !== undefined)
|
|
234
|
+
item.output = safeStringify(result);
|
|
235
|
+
break;
|
|
236
|
+
}
|
|
237
|
+
case 'webSearch': {
|
|
238
|
+
const display = toolDisplay('webSearch', raw);
|
|
239
|
+
item = { kind: 'tool', id, name: type, toolKind: display.toolKind, title: display.title, status };
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
case 'enteredReviewMode':
|
|
243
|
+
case 'exitedReviewMode':
|
|
244
|
+
// §7.1: review-mode items → tool(kind task).
|
|
245
|
+
item = {
|
|
246
|
+
kind: 'tool',
|
|
247
|
+
id,
|
|
248
|
+
name: type,
|
|
249
|
+
toolKind: 'task',
|
|
250
|
+
title: type === 'enteredReviewMode' ? 'Entered review mode' : 'Exited review mode',
|
|
251
|
+
status,
|
|
252
|
+
};
|
|
253
|
+
break;
|
|
254
|
+
default: {
|
|
255
|
+
// Unknown item types stay visible as generic tool cards (v1 parity —
|
|
256
|
+
// a future codex tool must not silently vanish from the thread).
|
|
257
|
+
const display = toolDisplay(type, raw);
|
|
258
|
+
item = { kind: 'tool', id, name: type, toolKind: display.toolKind, title: display.title, status, input: raw };
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
const error = errorMessage(raw.error);
|
|
262
|
+
if (error !== undefined)
|
|
263
|
+
item.error = error;
|
|
264
|
+
return item;
|
|
265
|
+
}
|
|
266
|
+
/** `fileChange.changes[]` `{path, kind, diff}` → `diffs[]` (unified) + locations. */
|
|
267
|
+
function changeArtifacts(changes) {
|
|
268
|
+
if (!Array.isArray(changes))
|
|
269
|
+
return undefined;
|
|
270
|
+
const diffs = [];
|
|
271
|
+
const locations = [];
|
|
272
|
+
for (const change of changes) {
|
|
273
|
+
if (!isRecord(change) || typeof change.path !== 'string' || change.path === '')
|
|
274
|
+
continue;
|
|
275
|
+
// Codex sends unified diffs only — the old text is unknown, not "empty".
|
|
276
|
+
const diff = { path: change.path, oldText: null };
|
|
277
|
+
const unified = str(change.diff);
|
|
278
|
+
if (unified !== undefined)
|
|
279
|
+
diff.unified = unified;
|
|
280
|
+
diffs.push(diff);
|
|
281
|
+
locations.push({ path: change.path });
|
|
282
|
+
}
|
|
283
|
+
if (diffs.length === 0)
|
|
284
|
+
return undefined;
|
|
285
|
+
return { diffs, locations };
|
|
286
|
+
}
|
|
287
|
+
/** `todoList` items `{text, completed}` (and plan step arrays) → plan entries;
|
|
288
|
+
* a text-only `plan` item becomes the single entry the agent is executing. */
|
|
289
|
+
function planEntriesOf(raw) {
|
|
290
|
+
const list = Array.isArray(raw.items) ? raw.items : Array.isArray(raw.plan) ? raw.plan : undefined;
|
|
291
|
+
if (list) {
|
|
292
|
+
const entries = [];
|
|
293
|
+
for (const entry of list) {
|
|
294
|
+
if (!isRecord(entry))
|
|
295
|
+
continue;
|
|
296
|
+
const content = str(entry.text) ?? str(entry.step) ?? str(entry.content);
|
|
297
|
+
if (content === undefined)
|
|
298
|
+
continue;
|
|
299
|
+
if (typeof entry.completed === 'boolean') {
|
|
300
|
+
entries.push({ content, status: entry.completed ? 'completed' : 'pending' });
|
|
301
|
+
}
|
|
302
|
+
else if (entry.status === 'pending' || entry.status === 'completed') {
|
|
303
|
+
entries.push({ content, status: entry.status });
|
|
304
|
+
}
|
|
305
|
+
else if (entry.status === 'inProgress' || entry.status === 'in_progress') {
|
|
306
|
+
entries.push({ content, status: 'in_progress' });
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
entries.push({ content, status: 'pending' });
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
return entries;
|
|
313
|
+
}
|
|
314
|
+
const text = str(raw.text);
|
|
315
|
+
if (text === undefined)
|
|
316
|
+
return undefined;
|
|
317
|
+
return [{ content: text, status: 'in_progress' }];
|
|
318
|
+
}
|
|
319
|
+
// ---- streaming deltas -------------------------------------------------------
|
|
320
|
+
/** Minimal item synthesized when a delta outruns its `item/started` — gives
|
|
321
|
+
* consumers a valid target to upsert; the completed snapshot reconciles. */
|
|
322
|
+
function synthesizedItem(itemId, field) {
|
|
323
|
+
if (field === 'text')
|
|
324
|
+
return { kind: 'message', id: itemId, role: 'assistant', text: '' };
|
|
325
|
+
if (field === 'reasoning')
|
|
326
|
+
return { kind: 'reasoning', id: itemId, text: '' };
|
|
327
|
+
const display = toolDisplay('commandExecution');
|
|
328
|
+
return { kind: 'tool', id: itemId, name: 'commandExecution', toolKind: display.toolKind, title: display.title, status: 'running' };
|
|
329
|
+
}
|
|
330
|
+
function mapDelta(params, state, field) {
|
|
331
|
+
const itemId = str(params.itemId);
|
|
332
|
+
const delta = typeof params.delta === 'string' ? params.delta : '';
|
|
333
|
+
if (itemId === undefined || delta === '')
|
|
334
|
+
return { events: [], state };
|
|
335
|
+
const events = [];
|
|
336
|
+
let knownItems = state.knownItems;
|
|
337
|
+
if (!knownItems.has(itemId)) {
|
|
338
|
+
events.push({ type: 'item.started', item: synthesizedItem(itemId, field) });
|
|
339
|
+
knownItems = new Set(knownItems).add(itemId);
|
|
340
|
+
}
|
|
341
|
+
events.push({ type: 'item.delta', itemId, field, delta });
|
|
342
|
+
let outputs = state.outputs;
|
|
343
|
+
if (field === 'output') {
|
|
344
|
+
const next = new Map(state.outputs);
|
|
345
|
+
next.set(itemId, (next.get(itemId) ?? '') + delta);
|
|
346
|
+
outputs = next;
|
|
347
|
+
}
|
|
348
|
+
return { events, state: { ...state, knownItems, outputs } };
|
|
349
|
+
}
|
|
350
|
+
// ---- telemetry ---------------------------------------------------------------
|
|
351
|
+
/** `thread/tokenUsage/updated` → usage.updated. Raw CUMULATIVE totals from
|
|
352
|
+
* `tokenUsage.total`; codex reports no USD cost, so none is ever fabricated. */
|
|
353
|
+
function mapTokenUsage(params, state) {
|
|
354
|
+
if (!isRecord(params.tokenUsage))
|
|
355
|
+
return { events: [], state };
|
|
356
|
+
const tokenUsage = params.tokenUsage;
|
|
357
|
+
const total = isRecord(tokenUsage.total) ? tokenUsage.total : undefined;
|
|
358
|
+
if (!total)
|
|
359
|
+
return { events: [], state };
|
|
360
|
+
const input = num(total.inputTokens) ?? 0;
|
|
361
|
+
const output = num(total.outputTokens) ?? 0;
|
|
362
|
+
const cacheRead = num(total.cachedInputTokens);
|
|
363
|
+
const reasoning = num(total.reasoningOutputTokens);
|
|
364
|
+
const usage = {
|
|
365
|
+
input,
|
|
366
|
+
output,
|
|
367
|
+
total: num(total.totalTokens) ?? input + output,
|
|
368
|
+
};
|
|
369
|
+
if (cacheRead !== undefined)
|
|
370
|
+
usage.cacheRead = cacheRead;
|
|
371
|
+
if (reasoning !== undefined)
|
|
372
|
+
usage.reasoning = reasoning;
|
|
373
|
+
const contextWindow = num(tokenUsage.modelContextWindow);
|
|
374
|
+
if (contextWindow !== undefined)
|
|
375
|
+
usage.contextWindow = contextWindow;
|
|
376
|
+
return { events: [{ type: 'usage.updated', usage }], state };
|
|
377
|
+
}
|
|
378
|
+
// ---- tiny guards --------------------------------------------------------------
|
|
379
|
+
function isRecord(value) {
|
|
380
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
381
|
+
}
|
|
382
|
+
function str(value) {
|
|
383
|
+
return typeof value === 'string' && value !== '' ? value : undefined;
|
|
384
|
+
}
|
|
385
|
+
function num(value) {
|
|
386
|
+
return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
|
|
387
|
+
}
|
|
388
|
+
function turnIdOf(params) {
|
|
389
|
+
const turn = isRecord(params.turn) ? params.turn : undefined;
|
|
390
|
+
return (turn && str(turn.id)) ?? str(params.turnId);
|
|
391
|
+
}
|
|
392
|
+
function threadIdOf(params) {
|
|
393
|
+
const thread = isRecord(params.thread) ? params.thread : undefined;
|
|
394
|
+
return (thread && str(thread.id)) ?? str(params.threadId);
|
|
395
|
+
}
|
|
396
|
+
function errorMessage(error) {
|
|
397
|
+
if (typeof error === 'string')
|
|
398
|
+
return str(error);
|
|
399
|
+
if (isRecord(error))
|
|
400
|
+
return str(error.message);
|
|
401
|
+
return undefined;
|
|
402
|
+
}
|
|
403
|
+
function safeStringify(value) {
|
|
404
|
+
try {
|
|
405
|
+
return JSON.stringify(value);
|
|
406
|
+
}
|
|
407
|
+
catch {
|
|
408
|
+
return String(value);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
//# sourceMappingURL=codex-ui-mapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex-ui-mapper.js","sourceRoot":"","sources":["../../src/core/codex-ui-mapper.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure opencode SSE-bus → protocol-v2 mapper. `mapOpencodeEvent` folds one
|
|
3
|
+
* parsed `{type, properties}` bus event into `UiEvent`s plus the next mapper
|
|
4
|
+
* state; the runner calls it ALONGSIDE the v1 path (v1 events keep flowing
|
|
5
|
+
* unchanged — including v1's HTTP-response-synthesized `turn-end`; only the
|
|
6
|
+
* v2 stream uses the correct `session.idle` signal, fixing gap §5.9).
|
|
7
|
+
*
|
|
8
|
+
* Contract: `.ai/analysis/cockpit-ui-redesign/agent-event-protocols.md` §4
|
|
9
|
+
* (wire format: Message/Part model, ToolState lifecycle) and §7.1
|
|
10
|
+
* "OpenCode (SSE)" (the mapping). Golden fixtures replaying wire-faithful
|
|
11
|
+
* bus-event sequences live in `__fixtures__/opencode/`.
|
|
12
|
+
*
|
|
13
|
+
* Robustness rule: input is untrusted wire data — the mapper never throws;
|
|
14
|
+
* unknown event/part types map to zero events.
|
|
15
|
+
*
|
|
16
|
+
* State is explicit and treated as immutable: callers thread the returned
|
|
17
|
+
* `state` into the next call. Ids are deterministic — items reuse the wire
|
|
18
|
+
* part ids, turns get `turn_<n>` minted at each prompt POST — so replaying
|
|
19
|
+
* a stored transcript reproduces the exact event sequence.
|
|
20
|
+
*
|
|
21
|
+
* Opencode-specific mechanics baked in:
|
|
22
|
+
* - text/reasoning parts carry the FULL accumulated text on every update;
|
|
23
|
+
* a per-part cursor diffs it into true `item.delta`s (a server-provided
|
|
24
|
+
* `delta` field wins when present — newer servers send it);
|
|
25
|
+
* - tool parts have the ONLY real `pending` phase of the three backends
|
|
26
|
+
* (`pending→pending`, `running→running`, `completed→completed`,
|
|
27
|
+
* `error→failed`);
|
|
28
|
+
* - the SSE bus is server-wide: parts from a foreign session id are the
|
|
29
|
+
* active subtask's child session and nest via `parentItemId` (§7.1);
|
|
30
|
+
* anything foreign outside a subtask scope is dropped.
|
|
31
|
+
*/
|
|
32
|
+
import type { TokenUsage, ToolStatus, UiEvent } from './ui-events.js';
|
|
33
|
+
/** Per-message telemetry: `message.updated` snapshots (cumulative per
|
|
34
|
+
* message) and summed `step-finish` increments are tracked separately —
|
|
35
|
+
* they describe the same accumulation, so the larger total wins and
|
|
36
|
+
* nothing is double-counted. */
|
|
37
|
+
interface MessageUsage {
|
|
38
|
+
readonly info: TokenUsage | null;
|
|
39
|
+
readonly infoCost: number | null;
|
|
40
|
+
readonly steps: TokenUsage | null;
|
|
41
|
+
readonly stepsCost: number | null;
|
|
42
|
+
}
|
|
43
|
+
export interface OpencodeUiMapperState {
|
|
44
|
+
/** The main session id (from POST /session) — the SSE bus is server-wide,
|
|
45
|
+
* so this is what separates our events from a subtask's child session. */
|
|
46
|
+
readonly sessionId: string | null;
|
|
47
|
+
/** True once `opencodeSessionStarted` emitted `session.started`. */
|
|
48
|
+
readonly sessionStarted: boolean;
|
|
49
|
+
readonly turnSeq: number;
|
|
50
|
+
readonly currentTurnId: string | null;
|
|
51
|
+
/** A `session.error` arrived since the turn started → `session.idle`
|
|
52
|
+
* closes the turn with stopReason 'error' (§7.1). */
|
|
53
|
+
readonly turnErrored: boolean;
|
|
54
|
+
/** messageID → role. Parts carry no role; only assistant parts surface
|
|
55
|
+
* (the user's own prompt streams as parts over the same feed). */
|
|
56
|
+
readonly msgRoles: ReadonlyMap<string, string>;
|
|
57
|
+
/** Text/reasoning part id → chars already emitted as deltas. */
|
|
58
|
+
readonly cursors: ReadonlyMap<string, number>;
|
|
59
|
+
/** Part ids whose `item.started` was emitted. */
|
|
60
|
+
readonly startedItems: ReadonlySet<string>;
|
|
61
|
+
/** Text/reasoning/patch part ids whose `item.completed` was emitted. */
|
|
62
|
+
readonly endedItems: ReadonlySet<string>;
|
|
63
|
+
/** Tool part id → last emitted status/title (flip + live-title detection). */
|
|
64
|
+
readonly tools: ReadonlyMap<string, {
|
|
65
|
+
status: ToolStatus;
|
|
66
|
+
title: string;
|
|
67
|
+
}>;
|
|
68
|
+
/** Serialized last plan — todowrite snapshots are idempotent, so identical
|
|
69
|
+
* replacements emit no duplicate `plan.updated`. */
|
|
70
|
+
readonly lastPlanJson: string | null;
|
|
71
|
+
/** Active subtask scope: its id becomes `parentItemId` for child-session
|
|
72
|
+
* items; the child's `session.idle` completes it. */
|
|
73
|
+
readonly subtask: {
|
|
74
|
+
id: string;
|
|
75
|
+
title: string;
|
|
76
|
+
input?: unknown;
|
|
77
|
+
} | null;
|
|
78
|
+
readonly usageByMessage: ReadonlyMap<string, MessageUsage>;
|
|
79
|
+
/** Last emitted session totals — usage.updated fires only on change. */
|
|
80
|
+
readonly lastUsage: {
|
|
81
|
+
total: number;
|
|
82
|
+
cost: number | null;
|
|
83
|
+
} | null;
|
|
84
|
+
}
|
|
85
|
+
export interface OpencodeUiMapping {
|
|
86
|
+
events: UiEvent[];
|
|
87
|
+
state: OpencodeUiMapperState;
|
|
88
|
+
}
|
|
89
|
+
export declare function createOpencodeUiState(): OpencodeUiMapperState;
|
|
90
|
+
/**
|
|
91
|
+
* Opencode has no wire-level session-start event — the session is created by
|
|
92
|
+
* the runner's `POST /session`, so the runner calls this once the response
|
|
93
|
+
* carries the id (like codex's out-of-band thread/start result).
|
|
94
|
+
*/
|
|
95
|
+
export declare function opencodeSessionStarted(sessionId: string, state: OpencodeUiMapperState): OpencodeUiMapping;
|
|
96
|
+
/**
|
|
97
|
+
* Opencode has no wire-level turn-start either — the runner POSTing a prompt
|
|
98
|
+
* IS the turn boundary, so the runner calls this on each prompt POST. The
|
|
99
|
+
* matching `turn.completed` comes from the wire `session.idle` (never from
|
|
100
|
+
* the HTTP prompt response — that is v1's known fidelity gap).
|
|
101
|
+
*/
|
|
102
|
+
export declare function opencodeTurnStarted(state: OpencodeUiMapperState): OpencodeUiMapping;
|
|
103
|
+
/** Fold one parsed SSE bus event into v2 events. Never throws. */
|
|
104
|
+
export declare function mapOpencodeEvent(evt: unknown, state: OpencodeUiMapperState): OpencodeUiMapping;
|
|
105
|
+
export {};
|