@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,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure claude stream-json → protocol-v2 mapper. `mapClaudeMessage` folds one
|
|
3
|
+
* parsed NDJSON stdout line into `UiEvent`s plus the next mapper state; the
|
|
4
|
+
* runner calls it ALONGSIDE the v1 path (v1 events keep flowing unchanged).
|
|
5
|
+
*
|
|
6
|
+
* Contract: `.ai/analysis/cockpit-ui-redesign/agent-event-protocols.md` §1
|
|
7
|
+
* (wire format) and §7.1 "Claude (stream-json)" (the mapping). Golden
|
|
8
|
+
* fixtures replaying real wire shapes live in `__fixtures__/claude/`.
|
|
9
|
+
*
|
|
10
|
+
* Robustness rule: input is untrusted wire data — the mapper never throws;
|
|
11
|
+
* unknown message/block types map to zero events.
|
|
12
|
+
*
|
|
13
|
+
* State is explicit and treated as immutable: callers thread the returned
|
|
14
|
+
* `state` into the next call. Item ids are deterministic — tool items reuse
|
|
15
|
+
* the wire `tool_use` id; text/thinking blocks (which have no wire id) get
|
|
16
|
+
* sequential `item_<n>` ids, turns get `turn_<n>` — so replaying a stored
|
|
17
|
+
* transcript reproduces the exact event sequence.
|
|
18
|
+
*/
|
|
19
|
+
import type { UiEvent, UiToolItem } from './ui-events.js';
|
|
20
|
+
export interface ClaudeUiMapperState {
|
|
21
|
+
/** Used when `system/init` lacks `session_id` (the dry-run mock does). */
|
|
22
|
+
readonly fallbackSessionId?: string;
|
|
23
|
+
/** True once `system/init` produced `session.started`. */
|
|
24
|
+
readonly sessionStarted: boolean;
|
|
25
|
+
/** Turns begun before init arrived — their `turn.started` is queued so
|
|
26
|
+
* `session.started` stays the first event on the wire. */
|
|
27
|
+
readonly pendingTurnIds: readonly string[];
|
|
28
|
+
readonly turnSeq: number;
|
|
29
|
+
readonly currentTurnId: string | null;
|
|
30
|
+
readonly itemSeq: number;
|
|
31
|
+
/** `tool_use` items awaiting their `tool_result`, keyed by tool_use id. */
|
|
32
|
+
readonly openTools: ReadonlyMap<string, UiToolItem>;
|
|
33
|
+
}
|
|
34
|
+
export interface ClaudeUiMapping {
|
|
35
|
+
events: UiEvent[];
|
|
36
|
+
state: ClaudeUiMapperState;
|
|
37
|
+
}
|
|
38
|
+
export declare function createClaudeUiState(opts?: {
|
|
39
|
+
fallbackSessionId?: string;
|
|
40
|
+
}): ClaudeUiMapperState;
|
|
41
|
+
/**
|
|
42
|
+
* Claude has no wire-level turn-start — the runner writing a user message to
|
|
43
|
+
* stdin IS the turn boundary, so the runner calls this on each send. Until
|
|
44
|
+
* `init` arrives the event is queued (the seed message is written before the
|
|
45
|
+
* first stdout line is read).
|
|
46
|
+
*/
|
|
47
|
+
export declare function claudeTurnStarted(state: ClaudeUiMapperState): ClaudeUiMapping;
|
|
48
|
+
/** Fold one parsed stream-json message into v2 events. Never throws. */
|
|
49
|
+
export declare function mapClaudeMessage(msg: unknown, state: ClaudeUiMapperState): ClaudeUiMapping;
|
|
50
|
+
/** Flatten a `tool_result.content` (string or block array) to display text.
|
|
51
|
+
* Image blocks become a placeholder — they ride as their own events. */
|
|
52
|
+
export declare function stringifyToolResultContent(content: unknown): string;
|
|
53
|
+
/** base64 image blocks inside a tool_result's content, if any. */
|
|
54
|
+
export declare function toolResultImageBlocks(content: unknown): Array<{
|
|
55
|
+
media_type: string;
|
|
56
|
+
data: string;
|
|
57
|
+
}>;
|
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure claude stream-json → protocol-v2 mapper. `mapClaudeMessage` folds one
|
|
3
|
+
* parsed NDJSON stdout line into `UiEvent`s plus the next mapper state; the
|
|
4
|
+
* runner calls it ALONGSIDE the v1 path (v1 events keep flowing unchanged).
|
|
5
|
+
*
|
|
6
|
+
* Contract: `.ai/analysis/cockpit-ui-redesign/agent-event-protocols.md` §1
|
|
7
|
+
* (wire format) and §7.1 "Claude (stream-json)" (the mapping). Golden
|
|
8
|
+
* fixtures replaying real wire shapes live in `__fixtures__/claude/`.
|
|
9
|
+
*
|
|
10
|
+
* Robustness rule: input is untrusted wire data — the mapper never throws;
|
|
11
|
+
* unknown message/block types map to zero events.
|
|
12
|
+
*
|
|
13
|
+
* State is explicit and treated as immutable: callers thread the returned
|
|
14
|
+
* `state` into the next call. Item ids are deterministic — tool items reuse
|
|
15
|
+
* the wire `tool_use` id; text/thinking blocks (which have no wire id) get
|
|
16
|
+
* sequential `item_<n>` ids, turns get `turn_<n>` — so replaying a stored
|
|
17
|
+
* transcript reproduces the exact event sequence.
|
|
18
|
+
*/
|
|
19
|
+
import { toolDisplay } from './tool-display.js';
|
|
20
|
+
export function createClaudeUiState(opts = {}) {
|
|
21
|
+
return {
|
|
22
|
+
fallbackSessionId: opts.fallbackSessionId,
|
|
23
|
+
sessionStarted: false,
|
|
24
|
+
pendingTurnIds: [],
|
|
25
|
+
turnSeq: 0,
|
|
26
|
+
currentTurnId: null,
|
|
27
|
+
itemSeq: 0,
|
|
28
|
+
openTools: new Map(),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Claude has no wire-level turn-start — the runner writing a user message to
|
|
33
|
+
* stdin IS the turn boundary, so the runner calls this on each send. Until
|
|
34
|
+
* `init` arrives the event is queued (the seed message is written before the
|
|
35
|
+
* first stdout line is read).
|
|
36
|
+
*/
|
|
37
|
+
export function claudeTurnStarted(state) {
|
|
38
|
+
const turnId = `turn_${state.turnSeq + 1}`;
|
|
39
|
+
const next = { ...state, turnSeq: state.turnSeq + 1, currentTurnId: turnId };
|
|
40
|
+
if (!state.sessionStarted) {
|
|
41
|
+
return { events: [], state: { ...next, pendingTurnIds: [...state.pendingTurnIds, turnId] } };
|
|
42
|
+
}
|
|
43
|
+
return { events: [{ type: 'turn.started', turnId }], state: next };
|
|
44
|
+
}
|
|
45
|
+
/** Fold one parsed stream-json message into v2 events. Never throws. */
|
|
46
|
+
export function mapClaudeMessage(msg, state) {
|
|
47
|
+
if (!isRecord(msg))
|
|
48
|
+
return { events: [], state };
|
|
49
|
+
switch (msg.type) {
|
|
50
|
+
case 'system':
|
|
51
|
+
return msg.subtype === 'init' ? mapInit(msg, state) : { events: [], state };
|
|
52
|
+
case 'assistant':
|
|
53
|
+
return mapAssistant(msg, state);
|
|
54
|
+
case 'user':
|
|
55
|
+
return mapToolResults(msg, state);
|
|
56
|
+
case 'result':
|
|
57
|
+
return mapResult(msg, state);
|
|
58
|
+
default:
|
|
59
|
+
// stream_event, control_request, … — nothing to render yet.
|
|
60
|
+
return { events: [], state };
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// ---- system/init → session.started ----------------------------------------
|
|
64
|
+
function mapInit(msg, state) {
|
|
65
|
+
const event = {
|
|
66
|
+
type: 'session.started',
|
|
67
|
+
sessionId: str(msg.session_id) ?? state.fallbackSessionId ?? '',
|
|
68
|
+
backend: 'claude',
|
|
69
|
+
};
|
|
70
|
+
const model = str(msg.model);
|
|
71
|
+
if (model !== undefined)
|
|
72
|
+
event.model = model;
|
|
73
|
+
const cwd = str(msg.cwd);
|
|
74
|
+
if (cwd !== undefined)
|
|
75
|
+
event.cwd = cwd;
|
|
76
|
+
if (Array.isArray(msg.tools)) {
|
|
77
|
+
event.tools = msg.tools.filter((tool) => typeof tool === 'string');
|
|
78
|
+
}
|
|
79
|
+
const events = [event];
|
|
80
|
+
// Flush turns that began before init (the seeded first user message).
|
|
81
|
+
for (const turnId of state.pendingTurnIds)
|
|
82
|
+
events.push({ type: 'turn.started', turnId });
|
|
83
|
+
return { events, state: { ...state, sessionStarted: true, pendingTurnIds: [] } };
|
|
84
|
+
}
|
|
85
|
+
// ---- assistant blocks → message/reasoning/tool items -----------------------
|
|
86
|
+
function mapAssistant(msg, state) {
|
|
87
|
+
const content = messageContent(msg);
|
|
88
|
+
const parentItemId = str(msg.parent_tool_use_id);
|
|
89
|
+
const events = [];
|
|
90
|
+
let itemSeq = state.itemSeq;
|
|
91
|
+
let openTools = null;
|
|
92
|
+
for (const raw of content) {
|
|
93
|
+
if (!isRecord(raw))
|
|
94
|
+
continue;
|
|
95
|
+
if (raw.type === 'text' && typeof raw.text === 'string') {
|
|
96
|
+
// Whole blocks per API round-trip — claude sends no deltas in this
|
|
97
|
+
// mode, so we never fake `item.delta`s: started + completed.
|
|
98
|
+
const item = { kind: 'message', id: `item_${++itemSeq}`, role: 'assistant', text: raw.text };
|
|
99
|
+
if (parentItemId !== undefined)
|
|
100
|
+
item.parentItemId = parentItemId;
|
|
101
|
+
events.push({ type: 'item.started', item }, { type: 'item.completed', item });
|
|
102
|
+
}
|
|
103
|
+
else if (raw.type === 'thinking' && typeof raw.thinking === 'string') {
|
|
104
|
+
const item = { kind: 'reasoning', id: `item_${++itemSeq}`, text: raw.thinking };
|
|
105
|
+
if (parentItemId !== undefined)
|
|
106
|
+
item.parentItemId = parentItemId;
|
|
107
|
+
events.push({ type: 'item.started', item }, { type: 'item.completed', item });
|
|
108
|
+
}
|
|
109
|
+
else if (raw.type === 'tool_use' && typeof raw.id === 'string' && typeof raw.name === 'string') {
|
|
110
|
+
const display = toolDisplay(raw.name, raw.input);
|
|
111
|
+
const item = {
|
|
112
|
+
kind: 'tool',
|
|
113
|
+
id: raw.id,
|
|
114
|
+
name: raw.name,
|
|
115
|
+
toolKind: display.toolKind,
|
|
116
|
+
title: display.title,
|
|
117
|
+
// claude has no pending phase — a tool_use is already executing.
|
|
118
|
+
status: 'running',
|
|
119
|
+
};
|
|
120
|
+
if (raw.input !== undefined)
|
|
121
|
+
item.input = raw.input;
|
|
122
|
+
const edit = editArtifacts(raw.name, raw.input);
|
|
123
|
+
if (edit) {
|
|
124
|
+
if (edit.diffs)
|
|
125
|
+
item.diffs = edit.diffs;
|
|
126
|
+
item.locations = edit.locations;
|
|
127
|
+
}
|
|
128
|
+
if (parentItemId !== undefined)
|
|
129
|
+
item.parentItemId = parentItemId;
|
|
130
|
+
events.push({ type: 'item.started', item });
|
|
131
|
+
if (raw.name === 'TodoWrite') {
|
|
132
|
+
const entries = planEntries(raw.input);
|
|
133
|
+
if (entries)
|
|
134
|
+
events.push({ type: 'plan.updated', entries });
|
|
135
|
+
}
|
|
136
|
+
openTools ??= new Map(state.openTools);
|
|
137
|
+
openTools.set(raw.id, item);
|
|
138
|
+
}
|
|
139
|
+
// Unknown block types (redacted_thinking, server_tool_use, …): ignored.
|
|
140
|
+
}
|
|
141
|
+
if (events.length === 0)
|
|
142
|
+
return { events, state };
|
|
143
|
+
return { events, state: { ...state, itemSeq, openTools: openTools ?? state.openTools } };
|
|
144
|
+
}
|
|
145
|
+
/** claude `Edit`/`Write` inputs carry the diff inline (§7.1). */
|
|
146
|
+
function editArtifacts(name, input) {
|
|
147
|
+
const key = name.toLowerCase();
|
|
148
|
+
if (key !== 'edit' && key !== 'write')
|
|
149
|
+
return undefined;
|
|
150
|
+
if (!isRecord(input) || typeof input.file_path !== 'string' || input.file_path === '')
|
|
151
|
+
return undefined;
|
|
152
|
+
const path = input.file_path;
|
|
153
|
+
const locations = [{ path }];
|
|
154
|
+
if (key === 'edit') {
|
|
155
|
+
if (typeof input.old_string === 'string' && typeof input.new_string === 'string') {
|
|
156
|
+
return { diffs: [{ path, oldText: input.old_string, newText: input.new_string }], locations };
|
|
157
|
+
}
|
|
158
|
+
return { locations };
|
|
159
|
+
}
|
|
160
|
+
// Write: a created (or fully replaced) file — `oldText: null` per FileDiff.
|
|
161
|
+
const diff = { path, oldText: null };
|
|
162
|
+
if (typeof input.content === 'string')
|
|
163
|
+
diff.newText = input.content;
|
|
164
|
+
return { diffs: [diff], locations };
|
|
165
|
+
}
|
|
166
|
+
const PLAN_STATUSES = ['pending', 'in_progress', 'completed'];
|
|
167
|
+
/** TodoWrite input `{todos:[{content,status,activeForm}]}` → plan entries
|
|
168
|
+
* (full-replacement semantics — an empty list is a valid plan). */
|
|
169
|
+
function planEntries(input) {
|
|
170
|
+
if (!isRecord(input) || !Array.isArray(input.todos))
|
|
171
|
+
return undefined;
|
|
172
|
+
const entries = [];
|
|
173
|
+
for (const todo of input.todos) {
|
|
174
|
+
if (!isRecord(todo) || typeof todo.content !== 'string')
|
|
175
|
+
continue;
|
|
176
|
+
const status = PLAN_STATUSES.find((s) => s === todo.status);
|
|
177
|
+
if (status === undefined)
|
|
178
|
+
continue;
|
|
179
|
+
const entry = { content: todo.content, status };
|
|
180
|
+
if (typeof todo.activeForm === 'string')
|
|
181
|
+
entry.activeForm = todo.activeForm;
|
|
182
|
+
entries.push(entry);
|
|
183
|
+
}
|
|
184
|
+
return entries;
|
|
185
|
+
}
|
|
186
|
+
// ---- user tool_result blocks → item.completed (+ image events) -------------
|
|
187
|
+
function mapToolResults(msg, state) {
|
|
188
|
+
const content = messageContent(msg);
|
|
189
|
+
const parentItemId = str(msg.parent_tool_use_id);
|
|
190
|
+
const events = [];
|
|
191
|
+
let openTools = null;
|
|
192
|
+
for (const raw of content) {
|
|
193
|
+
if (!isRecord(raw) || raw.type !== 'tool_result' || typeof raw.tool_use_id !== 'string')
|
|
194
|
+
continue;
|
|
195
|
+
const open = (openTools ?? state.openTools).get(raw.tool_use_id);
|
|
196
|
+
// A result for a tool we never saw start (state loss) still completes an
|
|
197
|
+
// item — consumers upsert by id, so a lone snapshot renders fine.
|
|
198
|
+
const item = open
|
|
199
|
+
? { ...open }
|
|
200
|
+
: { kind: 'tool', id: raw.tool_use_id, name: 'unknown', toolKind: 'other', title: 'Tool', status: 'running' };
|
|
201
|
+
if (!open && parentItemId !== undefined)
|
|
202
|
+
item.parentItemId = parentItemId;
|
|
203
|
+
const text = stringifyToolResultContent(raw.content);
|
|
204
|
+
if (raw.is_error === true) {
|
|
205
|
+
item.status = 'failed';
|
|
206
|
+
item.error = text;
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
item.status = 'completed';
|
|
210
|
+
item.output = text;
|
|
211
|
+
}
|
|
212
|
+
events.push({ type: 'item.completed', item });
|
|
213
|
+
for (const img of toolResultImageBlocks(raw.content)) {
|
|
214
|
+
events.push({ type: 'image', itemId: raw.tool_use_id, mediaType: img.media_type, data: img.data });
|
|
215
|
+
}
|
|
216
|
+
openTools ??= new Map(state.openTools);
|
|
217
|
+
openTools.delete(raw.tool_use_id);
|
|
218
|
+
}
|
|
219
|
+
if (events.length === 0)
|
|
220
|
+
return { events, state };
|
|
221
|
+
return { events, state: { ...state, openTools: openTools ?? state.openTools } };
|
|
222
|
+
}
|
|
223
|
+
// ---- result → declined tools + turn.completed + usage.updated --------------
|
|
224
|
+
function mapResult(msg, state) {
|
|
225
|
+
const events = [];
|
|
226
|
+
let itemSeq = state.itemSeq;
|
|
227
|
+
let turnSeq = state.turnSeq;
|
|
228
|
+
let openTools = null;
|
|
229
|
+
if (Array.isArray(msg.permission_denials)) {
|
|
230
|
+
for (const raw of msg.permission_denials) {
|
|
231
|
+
if (!isRecord(raw) || typeof raw.tool_name !== 'string')
|
|
232
|
+
continue;
|
|
233
|
+
const id = typeof raw.tool_use_id === 'string' ? raw.tool_use_id : `item_${++itemSeq}`;
|
|
234
|
+
const open = (openTools ?? state.openTools).get(id);
|
|
235
|
+
let item;
|
|
236
|
+
if (open) {
|
|
237
|
+
item = { ...open, status: 'declined' };
|
|
238
|
+
openTools ??= new Map(state.openTools);
|
|
239
|
+
openTools.delete(id);
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
const display = toolDisplay(raw.tool_name, raw.tool_input);
|
|
243
|
+
item = {
|
|
244
|
+
kind: 'tool',
|
|
245
|
+
id,
|
|
246
|
+
name: raw.tool_name,
|
|
247
|
+
toolKind: display.toolKind,
|
|
248
|
+
title: display.title,
|
|
249
|
+
status: 'declined',
|
|
250
|
+
};
|
|
251
|
+
if (raw.tool_input !== undefined)
|
|
252
|
+
item.input = raw.tool_input;
|
|
253
|
+
}
|
|
254
|
+
events.push({ type: 'item.completed', item });
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
const turnId = state.currentTurnId ?? `turn_${++turnSeq}`;
|
|
258
|
+
const usage = rawTokenUsage(msg.usage);
|
|
259
|
+
const costUsd = typeof msg.total_cost_usd === 'number' && Number.isFinite(msg.total_cost_usd)
|
|
260
|
+
? msg.total_cost_usd
|
|
261
|
+
: undefined;
|
|
262
|
+
const turnEvent = { type: 'turn.completed', turnId, stopReason: resultStopReason(msg) };
|
|
263
|
+
if (usage)
|
|
264
|
+
turnEvent.usage = usage;
|
|
265
|
+
if (costUsd !== undefined)
|
|
266
|
+
turnEvent.costUsd = costUsd;
|
|
267
|
+
events.push(turnEvent);
|
|
268
|
+
if (usage) {
|
|
269
|
+
const usageEvent = { type: 'usage.updated', usage };
|
|
270
|
+
if (costUsd !== undefined)
|
|
271
|
+
usageEvent.costUsd = costUsd;
|
|
272
|
+
events.push(usageEvent);
|
|
273
|
+
}
|
|
274
|
+
return {
|
|
275
|
+
events,
|
|
276
|
+
state: { ...state, itemSeq, turnSeq, currentTurnId: null, openTools: openTools ?? state.openTools },
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
/** §7.1: success→end_turn, error_max_turns→max_tokens,
|
|
280
|
+
* error_during_execution→error; unknown subtypes fall back on `is_error`. */
|
|
281
|
+
function resultStopReason(msg) {
|
|
282
|
+
switch (msg.subtype) {
|
|
283
|
+
case 'success':
|
|
284
|
+
return 'end_turn';
|
|
285
|
+
case 'error_max_turns':
|
|
286
|
+
return 'max_tokens';
|
|
287
|
+
case 'error_during_execution':
|
|
288
|
+
return 'error';
|
|
289
|
+
default:
|
|
290
|
+
return msg.is_error === true ? 'error' : 'end_turn';
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
/** Raw counts straight off the wire — never cost-weighted (that stays a
|
|
294
|
+
* presentation concern; v1's `token-usage` keeps the weighted number). */
|
|
295
|
+
function rawTokenUsage(usage) {
|
|
296
|
+
if (!isRecord(usage))
|
|
297
|
+
return undefined;
|
|
298
|
+
const input = num(usage.input_tokens) ?? 0;
|
|
299
|
+
const output = num(usage.output_tokens) ?? 0;
|
|
300
|
+
const cacheRead = num(usage.cache_read_input_tokens);
|
|
301
|
+
const cacheWrite = num(usage.cache_creation_input_tokens);
|
|
302
|
+
const result = {
|
|
303
|
+
input,
|
|
304
|
+
output,
|
|
305
|
+
total: input + output + (cacheRead ?? 0) + (cacheWrite ?? 0),
|
|
306
|
+
};
|
|
307
|
+
if (cacheRead !== undefined)
|
|
308
|
+
result.cacheRead = cacheRead;
|
|
309
|
+
if (cacheWrite !== undefined)
|
|
310
|
+
result.cacheWrite = cacheWrite;
|
|
311
|
+
return result;
|
|
312
|
+
}
|
|
313
|
+
// ---- shared wire helpers (also used by the v1 path in the runner) ----------
|
|
314
|
+
/** Flatten a `tool_result.content` (string or block array) to display text.
|
|
315
|
+
* Image blocks become a placeholder — they ride as their own events. */
|
|
316
|
+
export function stringifyToolResultContent(content) {
|
|
317
|
+
if (typeof content === 'string')
|
|
318
|
+
return content;
|
|
319
|
+
if (Array.isArray(content)) {
|
|
320
|
+
return content
|
|
321
|
+
.map((c) => {
|
|
322
|
+
const b = c;
|
|
323
|
+
if (b.type === 'text' && typeof b.text === 'string')
|
|
324
|
+
return b.text;
|
|
325
|
+
if (b.type === 'image')
|
|
326
|
+
return '[screenshot]'; // emitted as its own image event
|
|
327
|
+
try {
|
|
328
|
+
return JSON.stringify(b);
|
|
329
|
+
}
|
|
330
|
+
catch {
|
|
331
|
+
return String(b);
|
|
332
|
+
}
|
|
333
|
+
})
|
|
334
|
+
.join('\n');
|
|
335
|
+
}
|
|
336
|
+
try {
|
|
337
|
+
return JSON.stringify(content);
|
|
338
|
+
}
|
|
339
|
+
catch {
|
|
340
|
+
return String(content);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
/** base64 image blocks inside a tool_result's content, if any. */
|
|
344
|
+
export function toolResultImageBlocks(content) {
|
|
345
|
+
if (!Array.isArray(content))
|
|
346
|
+
return [];
|
|
347
|
+
const out = [];
|
|
348
|
+
for (const c of content) {
|
|
349
|
+
const b = c;
|
|
350
|
+
if (b.type === 'image' && b.source?.type === 'base64' && b.source.media_type && b.source.data) {
|
|
351
|
+
out.push({ media_type: b.source.media_type, data: b.source.data });
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
return out;
|
|
355
|
+
}
|
|
356
|
+
// ---- tiny guards ------------------------------------------------------------
|
|
357
|
+
function isRecord(value) {
|
|
358
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
359
|
+
}
|
|
360
|
+
function messageContent(msg) {
|
|
361
|
+
const message = isRecord(msg.message) ? msg.message : undefined;
|
|
362
|
+
return message && Array.isArray(message.content) ? message.content : [];
|
|
363
|
+
}
|
|
364
|
+
function str(value) {
|
|
365
|
+
return typeof value === 'string' && value !== '' ? value : undefined;
|
|
366
|
+
}
|
|
367
|
+
function num(value) {
|
|
368
|
+
return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
|
|
369
|
+
}
|
|
370
|
+
//# sourceMappingURL=claude-ui-mapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-ui-mapper.js","sourceRoot":"","sources":["../../src/core/claude-ui-mapper.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
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 type { UiEvent } from './ui-events.js';
|
|
25
|
+
export interface CodexUiMapperState {
|
|
26
|
+
/** True once `session.started` was emitted (thread/started notification or
|
|
27
|
+
* the runner's `codexSessionStarted` after the thread/start result —
|
|
28
|
+
* whichever lands first wins; the other is deduplicated). */
|
|
29
|
+
readonly sessionStarted: boolean;
|
|
30
|
+
/** Fallback counter for turn frames that arrive without a wire turn id. */
|
|
31
|
+
readonly turnSeq: number;
|
|
32
|
+
readonly currentTurnId: string | null;
|
|
33
|
+
/** Item ids already introduced — a delta for an unknown id synthesizes an
|
|
34
|
+
* `item.started` first so consumers always have something to upsert. */
|
|
35
|
+
readonly knownItems: ReadonlySet<string>;
|
|
36
|
+
/** Accumulated `outputDelta` text per commandExecution item, attached to
|
|
37
|
+
* the final snapshot when the wire `item/completed` carries no output. */
|
|
38
|
+
readonly outputs: ReadonlyMap<string, string>;
|
|
39
|
+
}
|
|
40
|
+
export interface CodexUiMapping {
|
|
41
|
+
events: UiEvent[];
|
|
42
|
+
state: CodexUiMapperState;
|
|
43
|
+
}
|
|
44
|
+
export declare function createCodexUiState(): CodexUiMapperState;
|
|
45
|
+
/**
|
|
46
|
+
* Codex confirms the thread via the `thread/start`/`thread/resume` RESULT
|
|
47
|
+
* (a response frame the mapper cannot attribute), so the runner calls this
|
|
48
|
+
* once the thread id is known. Deduplicated against the `thread/started`
|
|
49
|
+
* notification — whichever arrives first emits `session.started`.
|
|
50
|
+
*/
|
|
51
|
+
export declare function codexSessionStarted(threadId: string, state: CodexUiMapperState): CodexUiMapping;
|
|
52
|
+
/** Fold one parsed JSON-RPC frame into v2 events. Never throws. */
|
|
53
|
+
export declare function mapCodexNotification(frame: unknown, state: CodexUiMapperState): CodexUiMapping;
|