@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.
Files changed (123) hide show
  1. package/dist/core/claude-ui-mapper.d.ts +57 -0
  2. package/dist/core/claude-ui-mapper.js +370 -0
  3. package/dist/core/claude-ui-mapper.js.map +1 -0
  4. package/dist/core/codex-ui-mapper.d.ts +53 -0
  5. package/dist/core/codex-ui-mapper.js +411 -0
  6. package/dist/core/codex-ui-mapper.js.map +1 -0
  7. package/dist/core/opencode-ui-mapper.d.ts +105 -0
  8. package/dist/core/opencode-ui-mapper.js +578 -0
  9. package/dist/core/opencode-ui-mapper.js.map +1 -0
  10. package/dist/core/process-usage.d.ts +63 -0
  11. package/dist/core/process-usage.js +181 -0
  12. package/dist/core/process-usage.js.map +1 -0
  13. package/dist/core/tool-display.d.ts +27 -0
  14. package/dist/core/tool-display.js +150 -0
  15. package/dist/core/tool-display.js.map +1 -0
  16. package/dist/core/ui-events.d.ts +294 -0
  17. package/dist/core/ui-events.js +25 -0
  18. package/dist/core/ui-events.js.map +1 -0
  19. package/dist/index.js +0 -0
  20. package/dist/pack-check.d.ts +17 -0
  21. package/dist/pack-check.js +27 -0
  22. package/dist/pack-check.js.map +1 -0
  23. package/dist/runs/title-summary.d.ts +15 -0
  24. package/dist/runs/title-summary.js +84 -0
  25. package/dist/runs/title-summary.js.map +1 -0
  26. package/dist/runs/ui-event-sink.d.ts +81 -0
  27. package/dist/runs/ui-event-sink.js +210 -0
  28. package/dist/runs/ui-event-sink.js.map +1 -0
  29. package/dist/server/capabilities.d.ts +18 -0
  30. package/dist/server/capabilities.js +23 -0
  31. package/dist/server/capabilities.js.map +1 -0
  32. package/dist/server/forge/github.d.ts +39 -0
  33. package/dist/server/forge/github.js +369 -0
  34. package/dist/server/forge/github.js.map +1 -0
  35. package/dist/server/forge/index.d.ts +24 -0
  36. package/dist/server/forge/index.js +45 -0
  37. package/dist/server/forge/index.js.map +1 -0
  38. package/dist/server/forge/types.d.ts +80 -0
  39. package/dist/server/forge/types.js +2 -0
  40. package/dist/server/forge/types.js.map +1 -0
  41. package/dist/server/git-changes.d.ts +182 -0
  42. package/dist/server/git-changes.js +424 -0
  43. package/dist/server/git-changes.js.map +1 -0
  44. package/dist/server/open-in-app.d.ts +19 -0
  45. package/dist/server/open-in-app.js +134 -0
  46. package/dist/server/open-in-app.js.map +1 -0
  47. package/dist/server/static-ui.d.ts +49 -0
  48. package/dist/server/static-ui.js +92 -0
  49. package/dist/server/static-ui.js.map +1 -0
  50. package/dist/update-check.d.ts +12 -0
  51. package/dist/update-check.js +41 -0
  52. package/dist/update-check.js.map +1 -0
  53. package/package.json +1 -1
  54. package/web/app/node_modules/.vite/vitest/ca84d1343b96baa8137c943ed1860e522cacb238/results.json +1 -0
  55. package/web/app/src/components/app-shell-container.tsx +76 -0
  56. package/web/dist/assets/arrow-left-BE957rJs.js +1 -0
  57. package/web/dist/assets/bundle-mjs-DLPpRFyl.js +1 -0
  58. package/web/dist/assets/chunk-BO2N2NFS-f5igTtpB.js +131 -0
  59. package/web/dist/assets/compare-variants-D6fPL9cS.js +1 -0
  60. package/web/dist/assets/core-BuMqAF_1.js +12 -0
  61. package/web/dist/assets/css-BsVw1vtW.js +1 -0
  62. package/web/dist/assets/dialog-BEgEWFDS.js +1 -0
  63. package/web/dist/assets/diff-view-CctnJHWe.js +4 -0
  64. package/web/dist/assets/diff-woXpYk--.js +1 -0
  65. package/web/dist/assets/dist-CW7M_Jhs.js +1 -0
  66. package/web/dist/assets/ellipsis-vertical-DJPAfccS.js +1 -0
  67. package/web/dist/assets/engine-javascript-FQvzRocB.js +141 -0
  68. package/web/dist/assets/folder-RbRLfIX-.js +1 -0
  69. package/web/dist/assets/git-pull-request-DJkAMT0f.js +1 -0
  70. package/web/dist/assets/git-toolbar-D8OPPqBP.js +1 -0
  71. package/web/dist/assets/github-BYIHwIJB.js +1 -0
  72. package/web/dist/assets/go-rLFTqkRN.js +1 -0
  73. package/web/dist/assets/highlighted-body-OFNGDK62-DGHHie_q.js +1 -0
  74. package/web/dist/assets/highlighter-BKVEsACy.js +3 -0
  75. package/web/dist/assets/html-BY76lXLH.js +1 -0
  76. package/web/dist/assets/index-9qG98Orw.js +11 -0
  77. package/web/dist/assets/index-Bz_r8Jt3.css +2 -0
  78. package/web/dist/assets/input-BRsSo4xH.js +1 -0
  79. package/web/dist/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
  80. package/web/dist/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
  81. package/web/dist/assets/javascript-BgS3c2Ky.js +1 -0
  82. package/web/dist/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
  83. package/web/dist/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
  84. package/web/dist/assets/json-qhed-kSA.js +1 -0
  85. package/web/dist/assets/jsonc-CYpm1nAK.js +1 -0
  86. package/web/dist/assets/jsx-Bz0zcwM4.js +1 -0
  87. package/web/dist/assets/lib-CNGa3Dig.js +1 -0
  88. package/web/dist/assets/loader-circle-BV3DO9mE.js +1 -0
  89. package/web/dist/assets/markdown-BYOwaDjH.js +1 -0
  90. package/web/dist/assets/markdown-CR_HLGTs.js +1 -0
  91. package/web/dist/assets/mermaid-GHXKKRXX-DM2VsGBG.js +1 -0
  92. package/web/dist/assets/open-mercato-toBr6SOa.svg +11 -0
  93. package/web/dist/assets/python-gzcpVVnB.js +1 -0
  94. package/web/dist/assets/react-dom-Ddtik4qM.js +1 -0
  95. package/web/dist/assets/refresh-cw-DCa-Rlwz.js +1 -0
  96. package/web/dist/assets/repo-git-XTqlVOl2.js +1 -0
  97. package/web/dist/assets/run-diff-C7mfxj7f.js +3 -0
  98. package/web/dist/assets/run-header-CfVeY3uM.js +1 -0
  99. package/web/dist/assets/rust-Cfkwpbl8.js +1 -0
  100. package/web/dist/assets/search-x-CoCyl7zT.js +1 -0
  101. package/web/dist/assets/shellscript-CLZ0U2zV.js +1 -0
  102. package/web/dist/assets/skill-detail-C9cniyId.js +1 -0
  103. package/web/dist/assets/skills-DXgY1uXJ.js +1 -0
  104. package/web/dist/assets/skills-ynuO5oCr.js +1 -0
  105. package/web/dist/assets/sql-BsFa4tDR.js +1 -0
  106. package/web/dist/assets/square-terminal-B6PZX4Qp.js +1 -0
  107. package/web/dist/assets/tab-link-phWEqSBy.js +1 -0
  108. package/web/dist/assets/task-changes-DYwnPnTN.js +1 -0
  109. package/web/dist/assets/task-commits-DZzxEzbn.js +1 -0
  110. package/web/dist/assets/task-files-FOAAz2FB.js +2 -0
  111. package/web/dist/assets/task-thread-Bncxe8Os.js +5 -0
  112. package/web/dist/assets/toaster-BS2E1bhz.js +43 -0
  113. package/web/dist/assets/trash-2-CDtxmmc8.js +1 -0
  114. package/web/dist/assets/triangle-alert-6su4Js5O.js +1 -0
  115. package/web/dist/assets/tsx-udAQXfEw.js +1 -0
  116. package/web/dist/assets/typescript-bsJCZSQ-.js +1 -0
  117. package/web/dist/assets/upload-Bp7hQxll.js +1 -0
  118. package/web/dist/assets/use-desktop-eHm2iTXX.js +3 -0
  119. package/web/dist/assets/utils-rQGbOrwc.js +1 -0
  120. package/web/dist/assets/workflows-Dg2wQg6i.js +11 -0
  121. package/web/dist/assets/x-Br_jIDBw.js +1 -0
  122. package/web/dist/assets/yaml-rwi0_p6S.js +1 -0
  123. package/web/dist/index.html +67 -0
@@ -0,0 +1,294 @@
1
+ /**
2
+ * Normalized agent-event protocol v2 — the shared vocabulary every runner
3
+ * emits ALONGSIDE the v1 `AgentEvent` stream (never replacing it; mixed
4
+ * NDJSON files stay valid — old recordings must keep replaying).
5
+ *
6
+ * Contract sources (authoritative, in this order):
7
+ * - `.ai/analysis/cockpit-ui-redesign/agent-event-protocols.md` §7 (schema)
8
+ * and §7.1 (per-backend mapping tables);
9
+ * - the spec `.ai/specs/2026-07-14-cockpit-ui-redesign.md`
10
+ * §"Normalized agent-event protocol v2".
11
+ *
12
+ * Design rules baked in:
13
+ * 1. Item-lifecycle model (Codex/ACP style): one stable `id` per item with
14
+ * started/delta/updated/completed phases — two of the three backends are
15
+ * natively item-shaped and claude maps trivially.
16
+ * 2. ACP vocabulary wherever a choice is arbitrary (tool status/kind, plan
17
+ * entries, diff shape, stop reasons) for ecosystem alignment.
18
+ * 3. Every v1 `AgentEvent` stays derivable from this stream, so consumers
19
+ * can migrate one panel at a time.
20
+ *
21
+ * This module is pure vocabulary: no runtime imports, no runner coupling.
22
+ * Step 2.4 mirrors it into `web/app/src/protocol/`.
23
+ */
24
+ /** The backend that produced a session — mirrors `RunnerId` in
25
+ * `agent-runner.ts` (kept structurally identical; a type-level test
26
+ * guards against drift so this module stays dependency-free). */
27
+ export type UiBackend = 'claude' | 'codex' | 'opencode';
28
+ /**
29
+ * Tool lifecycle status (ACP: pending/in_progress/completed/failed).
30
+ * `running` ≡ ACP `in_progress` (opencode's word — reads better in code);
31
+ * `declined` covers codex approval declines and claude `permission_denials`.
32
+ *
33
+ * Per backend: claude has no pending phase (`tool_use` arrives already
34
+ * running); codex maps `inProgress→running`, `completed/failed/declined`
35
+ * verbatim; opencode maps `pending/running` verbatim and `error→failed`.
36
+ */
37
+ export type ToolStatus = 'pending' | 'running' | 'completed' | 'failed' | 'declined';
38
+ /**
39
+ * Icon/verb hint for a tool item — a superset of ACP's ToolKind.
40
+ * `task` = subagent spawn (claude Task / opencode subtask / codex review).
41
+ */
42
+ export type ToolKind = 'read' | 'edit' | 'delete' | 'move' | 'search' | 'execute' | 'think' | 'fetch' | 'task' | 'plan' | 'other';
43
+ /**
44
+ * Why a turn (or the session) stopped.
45
+ *
46
+ * Per backend: claude `result` subtype success→`end_turn`,
47
+ * error_max_turns→`max_tokens`, error_during_execution→`error`; codex
48
+ * turn/completed→`end_turn`, turn/failed→`error`, interrupt→`cancelled`;
49
+ * opencode `session.idle`→`end_turn` (or `error` when a session.error
50
+ * preceded it).
51
+ */
52
+ export type StopReason = 'end_turn' | 'max_tokens' | 'refusal' | 'cancelled' | 'timeout' | 'error';
53
+ /** Status of one plan/todo entry (claude TodoWrite uses these words verbatim;
54
+ * codex todoList and opencode todowrite map 1:1). */
55
+ export type PlanStatus = 'pending' | 'in_progress' | 'completed';
56
+ /** One entry of the session plan — full-replacement semantics (ACP style). */
57
+ export interface PlanEntry {
58
+ content: string;
59
+ status: PlanStatus;
60
+ priority?: 'high' | 'medium' | 'low';
61
+ /** Present-continuous label shown while the entry is in progress
62
+ * (claude TodoWrite's `activeForm`). */
63
+ activeForm?: string;
64
+ }
65
+ /**
66
+ * Raw token counts — never pre-weighted (cost weighting is a presentation
67
+ * concern, not a wire concern).
68
+ *
69
+ * Per backend: claude `result.usage` (+ `total_cost_usd` as `costUsd` on the
70
+ * carrying event); codex `thread/tokenUsage/updated` (no USD); opencode
71
+ * `message.updated` info.tokens/cost and `step-finish` parts.
72
+ */
73
+ export interface TokenUsage {
74
+ input: number;
75
+ output: number;
76
+ cacheRead?: number;
77
+ cacheWrite?: number;
78
+ reasoning?: number;
79
+ /** The backend's own total when given, else the sum of the parts. */
80
+ total: number;
81
+ /** Model context-window size when known — feeds the fill gauge. */
82
+ contextWindow?: number;
83
+ }
84
+ /**
85
+ * One file change carried by an edit-tool item.
86
+ * claude `Edit`/`Write` input → `oldText`/`newText`; codex
87
+ * `fileChange.changes[]` → `unified`; opencode `patch` parts → `unified`.
88
+ * `oldText: null` means the file is newly created.
89
+ */
90
+ export interface FileDiff {
91
+ path: string;
92
+ oldText: string | null;
93
+ newText?: string;
94
+ unified?: string;
95
+ }
96
+ /** A file location a tool touched (feeds "jump to file" affordances). */
97
+ export interface ToolLocation {
98
+ path: string;
99
+ line?: number;
100
+ }
101
+ /** A choice offered by a permission request (ACP option kinds). */
102
+ export type PermissionOptionKind = 'allow_once' | 'allow_always' | 'reject_once' | 'reject_always';
103
+ export interface PermissionOption {
104
+ id: string;
105
+ label: string;
106
+ kind: PermissionOptionKind;
107
+ }
108
+ /**
109
+ * A chat message.
110
+ * claude: `assistant` `text` blocks (whole-block, or true deltas via
111
+ * `--include-partial-messages`); codex: `agentMessage` items (`phase` from
112
+ * the item's own phase field); opencode: text parts of a message.
113
+ */
114
+ export interface UiMessageItem {
115
+ kind: 'message';
116
+ id: string;
117
+ role: 'assistant' | 'user';
118
+ text: string;
119
+ phase?: 'commentary' | 'final';
120
+ parentItemId?: string;
121
+ }
122
+ /**
123
+ * Extended thinking / reasoning summary.
124
+ * claude: `thinking` blocks; codex: `reasoning` items (+ textDelta);
125
+ * opencode: `reasoning` parts.
126
+ */
127
+ export interface UiReasoningItem {
128
+ kind: 'reasoning';
129
+ id: string;
130
+ text: string;
131
+ parentItemId?: string;
132
+ }
133
+ /**
134
+ * One tool invocation with its full lifecycle.
135
+ * claude: `tool_use` (started, status `running`) + `tool_result`
136
+ * (completed/failed; `permission_denials` → `declined`); codex: typed items
137
+ * (`commandExecution`→execute with `exitCode`, `fileChange`→edit with
138
+ * `diffs`, `mcpToolCall`→other, `webSearch`→fetch); opencode: tool parts
139
+ * (state pending/running/completed/error, `patch` parts → `diffs`).
140
+ *
141
+ * `parentItemId` nests subagent work under its spawning task item —
142
+ * claude `parent_tool_use_id`, opencode `subtask` parts, codex review items.
143
+ */
144
+ export interface UiToolItem {
145
+ kind: 'tool';
146
+ id: string;
147
+ /** The backend's tool name / item type (e.g. `Bash`, `commandExecution`). */
148
+ name: string;
149
+ /** ACP-style icon/verb hint — see `toolDisplay()` in `tool-display.ts`. */
150
+ toolKind: ToolKind;
151
+ /** Human line, computed once in the protocol layer: "Ran npm test". */
152
+ title: string;
153
+ status: ToolStatus;
154
+ /** Raw input — may arrive incrementally. */
155
+ input?: unknown;
156
+ output?: string;
157
+ error?: string;
158
+ diffs?: FileDiff[];
159
+ locations?: ToolLocation[];
160
+ /** commandExecution / bash exit code, when the backend reports one. */
161
+ exitCode?: number;
162
+ parentItemId?: string;
163
+ }
164
+ export type UiItem = UiMessageItem | UiReasoningItem | UiToolItem;
165
+ /**
166
+ * Session opened.
167
+ * claude: `system/init` (model, tools, cwd); codex: `thread/started` or the
168
+ * `thread/start` result; opencode: `POST /session` response.
169
+ */
170
+ export interface UiSessionStartedEvent {
171
+ type: 'session.started';
172
+ sessionId: string;
173
+ backend: UiBackend;
174
+ model?: string;
175
+ cwd?: string;
176
+ tools?: string[];
177
+ }
178
+ /** Session over (replaces v1 `done` / fatal `error`). */
179
+ export interface UiSessionEndedEvent {
180
+ type: 'session.ended';
181
+ reason: StopReason;
182
+ message?: string;
183
+ }
184
+ /** v1 `note` + `error` unified — severity explicit instead of implied. */
185
+ export interface UiSessionErrorEvent {
186
+ type: 'session.error';
187
+ message: string;
188
+ fatal: boolean;
189
+ }
190
+ /**
191
+ * A turn began.
192
+ * claude: on each stdin user message; codex: `turn/started`;
193
+ * opencode: on each prompt POST.
194
+ */
195
+ export interface UiTurnStartedEvent {
196
+ type: 'turn.started';
197
+ turnId: string;
198
+ }
199
+ /**
200
+ * A turn finished.
201
+ * claude: `result` (usage + `total_cost_usd`); codex: `turn/completed` /
202
+ * `turn/failed`; opencode: `session.idle`.
203
+ */
204
+ export interface UiTurnCompletedEvent {
205
+ type: 'turn.completed';
206
+ turnId: string;
207
+ stopReason: StopReason;
208
+ usage?: TokenUsage;
209
+ costUsd?: number;
210
+ }
211
+ /** An item entered the stream (tools usually with status pending/running). */
212
+ export interface UiItemStartedEvent {
213
+ type: 'item.started';
214
+ item: UiItem;
215
+ }
216
+ /**
217
+ * Streaming append to one field of a live item.
218
+ * claude: partial-message text deltas; codex: `item/agentMessage/delta`
219
+ * (`text`), `item/reasoning/textDelta` (`reasoning`),
220
+ * `item/commandExecution/outputDelta` (`output` — live terminal); opencode:
221
+ * text/reasoning part cursor deltas, running-state metadata for `output`.
222
+ * claude has no live command output — the tool card fills on completion
223
+ * (per-capability degradation, never per-backend).
224
+ */
225
+ export interface UiItemDeltaEvent {
226
+ type: 'item.delta';
227
+ itemId: string;
228
+ field: 'text' | 'reasoning' | 'output';
229
+ delta: string;
230
+ }
231
+ /** Status flips and streamed-content snapshots (codex `item/updated`,
232
+ * opencode part-state flips such as pending→running). */
233
+ export interface UiItemUpdatedEvent {
234
+ type: 'item.updated';
235
+ item: UiItem;
236
+ }
237
+ /** Final snapshot of an item — safe to persist (snapshots, not deltas). */
238
+ export interface UiItemCompletedEvent {
239
+ type: 'item.completed';
240
+ item: UiItem;
241
+ }
242
+ /**
243
+ * Full-replacement plan snapshot (ACP semantics).
244
+ * claude: `TodoWrite` tool input; codex: `todoList`/`plan` items;
245
+ * opencode: `todowrite` tool — identical semantics across all three.
246
+ */
247
+ export interface UiPlanUpdatedEvent {
248
+ type: 'plan.updated';
249
+ entries: PlanEntry[];
250
+ }
251
+ /**
252
+ * RESERVED — wired when auto-approve becomes optional. Types only for now.
253
+ * claude: `control_request can_use_tool`; codex: the per-item
254
+ * `requestApproval` JSON-RPC requests; opencode: `permission.updated`.
255
+ */
256
+ export interface UiPermissionRequestedEvent {
257
+ type: 'permission.requested';
258
+ requestId: string;
259
+ itemId?: string;
260
+ title: string;
261
+ options: PermissionOption[];
262
+ }
263
+ /** RESERVED — the counterpart resolution (see `permission.requested`). */
264
+ export interface UiPermissionResolvedEvent {
265
+ type: 'permission.resolved';
266
+ requestId: string;
267
+ optionId: string;
268
+ }
269
+ /**
270
+ * Cumulative-for-session raw telemetry.
271
+ * claude: `result.usage` + `total_cost_usd`; codex:
272
+ * `thread/tokenUsage/updated` (cost stays absent); opencode:
273
+ * `message.updated` tokens/cost + `step-finish` increments.
274
+ */
275
+ export interface UiUsageUpdatedEvent {
276
+ type: 'usage.updated';
277
+ usage: TokenUsage;
278
+ costUsd?: number;
279
+ }
280
+ /**
281
+ * An image emitted mid-stream (kept from v1) — raw base64 on the wire here;
282
+ * the run manager persists it and re-emits a URL. claude: image blocks in
283
+ * `tool_result` (with `itemId` linking back to the tool item).
284
+ */
285
+ export interface UiImageEvent {
286
+ type: 'image';
287
+ itemId?: string;
288
+ mediaType: string;
289
+ data: string;
290
+ }
291
+ export type UiEvent = UiSessionStartedEvent | UiSessionEndedEvent | UiSessionErrorEvent | UiTurnStartedEvent | UiTurnCompletedEvent | UiItemStartedEvent | UiItemDeltaEvent | UiItemUpdatedEvent | UiItemCompletedEvent | UiPlanUpdatedEvent | UiPermissionRequestedEvent | UiPermissionResolvedEvent | UiUsageUpdatedEvent | UiImageEvent;
292
+ /** Every v2 event discriminator — `satisfies Record<UiEventType, …>` maps
293
+ * downstream keep new event types honest at compile time. */
294
+ export type UiEventType = UiEvent['type'];
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Normalized agent-event protocol v2 — the shared vocabulary every runner
3
+ * emits ALONGSIDE the v1 `AgentEvent` stream (never replacing it; mixed
4
+ * NDJSON files stay valid — old recordings must keep replaying).
5
+ *
6
+ * Contract sources (authoritative, in this order):
7
+ * - `.ai/analysis/cockpit-ui-redesign/agent-event-protocols.md` §7 (schema)
8
+ * and §7.1 (per-backend mapping tables);
9
+ * - the spec `.ai/specs/2026-07-14-cockpit-ui-redesign.md`
10
+ * §"Normalized agent-event protocol v2".
11
+ *
12
+ * Design rules baked in:
13
+ * 1. Item-lifecycle model (Codex/ACP style): one stable `id` per item with
14
+ * started/delta/updated/completed phases — two of the three backends are
15
+ * natively item-shaped and claude maps trivially.
16
+ * 2. ACP vocabulary wherever a choice is arbitrary (tool status/kind, plan
17
+ * entries, diff shape, stop reasons) for ecosystem alignment.
18
+ * 3. Every v1 `AgentEvent` stays derivable from this stream, so consumers
19
+ * can migrate one panel at a time.
20
+ *
21
+ * This module is pure vocabulary: no runtime imports, no runner coupling.
22
+ * Step 2.4 mirrors it into `web/app/src/protocol/`.
23
+ */
24
+ export {};
25
+ //# sourceMappingURL=ui-events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-events.js","sourceRoot":"","sources":["../../src/core/ui-events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG"}
package/dist/index.js CHANGED
File without changes
@@ -0,0 +1,17 @@
1
+ /** Tarball bundle check — the pure half of `scripts/check-pack.mjs`.
2
+ *
3
+ * Phase R1 of the cockpit redesign shipped an npm tarball with no UI in it
4
+ * (`files` listed the sources, not the Vite build). This module pins that bug
5
+ * class: given the file list `npm pack --dry-run --json` reports, decide
6
+ * whether the package would ship a working cockpit. Kept dependency-free and
7
+ * side-effect-free so the decision is unit-testable; the script owns the
8
+ * `npm pack` invocation and the exit code.
9
+ */
10
+ /** Human-readable problems with a would-be tarball; empty array = publishable.
11
+ *
12
+ * Requirements (spec `.ai/specs/2026-07-14-cockpit-ui-redesign.md`, Serving):
13
+ * - `web/dist/index.html` — the built shell every GET serves.
14
+ * - at least one `web/dist/assets/*` file — the hashed JS/CSS bundles; an
15
+ * index.html alone renders a blank page.
16
+ */
17
+ export declare function findPackGaps(packedFiles: readonly string[]): string[];
@@ -0,0 +1,27 @@
1
+ /** Tarball bundle check — the pure half of `scripts/check-pack.mjs`.
2
+ *
3
+ * Phase R1 of the cockpit redesign shipped an npm tarball with no UI in it
4
+ * (`files` listed the sources, not the Vite build). This module pins that bug
5
+ * class: given the file list `npm pack --dry-run --json` reports, decide
6
+ * whether the package would ship a working cockpit. Kept dependency-free and
7
+ * side-effect-free so the decision is unit-testable; the script owns the
8
+ * `npm pack` invocation and the exit code.
9
+ */
10
+ /** Human-readable problems with a would-be tarball; empty array = publishable.
11
+ *
12
+ * Requirements (spec `.ai/specs/2026-07-14-cockpit-ui-redesign.md`, Serving):
13
+ * - `web/dist/index.html` — the built shell every GET serves.
14
+ * - at least one `web/dist/assets/*` file — the hashed JS/CSS bundles; an
15
+ * index.html alone renders a blank page.
16
+ */
17
+ export function findPackGaps(packedFiles) {
18
+ const gaps = [];
19
+ if (!packedFiles.includes('web/dist/index.html')) {
20
+ gaps.push('web/dist/index.html is missing — the tarball would ship no UI shell (run `npm run build:web`)');
21
+ }
22
+ if (!packedFiles.some((f) => f.startsWith('web/dist/assets/') && f.length > 'web/dist/assets/'.length)) {
23
+ gaps.push('no web/dist/assets/* bundle in the tarball — the shell would load with no JS/CSS');
24
+ }
25
+ return gaps;
26
+ }
27
+ //# sourceMappingURL=pack-check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pack-check.js","sourceRoot":"","sources":["../src/pack-check.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,WAA8B;IACzD,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,qBAAqB,CAAC,EAAE,CAAC;QACjD,IAAI,CAAC,IAAI,CAAC,+FAA+F,CAAC,CAAC;IAC7G,CAAC;IACD,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAC;QACvG,IAAI,CAAC,IAAI,CAAC,kFAAkF,CAAC,CAAC;IAChG,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Auto-summary titles (#389): derive a short display title for a run from the
3
+ * text of an agent turn. Pure by design — the RunManager calls this on
4
+ * turn-end and stores the first informative answer as `RunRecord.titleSummary`.
5
+ *
6
+ * Honest absence beats a garbage title: when the turn text yields nothing
7
+ * better than the raw task's first line (too short, markdown noise only,
8
+ * or a verbatim echo of the task), the answer is `undefined` and the UI
9
+ * keeps showing the raw `title`.
10
+ */
11
+ /**
12
+ * Derive a display title from an agent turn's text, or `undefined` when the
13
+ * text yields nothing more informative than the task itself.
14
+ */
15
+ export declare function deriveTitleSummary(text: string, task: string): string | undefined;
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Auto-summary titles (#389): derive a short display title for a run from the
3
+ * text of an agent turn. Pure by design — the RunManager calls this on
4
+ * turn-end and stores the first informative answer as `RunRecord.titleSummary`.
5
+ *
6
+ * Honest absence beats a garbage title: when the turn text yields nothing
7
+ * better than the raw task's first line (too short, markdown noise only,
8
+ * or a verbatim echo of the task), the answer is `undefined` and the UI
9
+ * keeps showing the raw `title`.
10
+ */
11
+ /** Display cap, in code points — matches `makeTitle`'s 80-char convention. */
12
+ const MAX_LEN = 80;
13
+ /** A summary shorter than this many words says nothing — skip it. */
14
+ const MIN_WORDS = 4;
15
+ /** Conversational lead-ins that carry no information about the task. Applied
16
+ * repeatedly, so "Sure! I'll go ahead and fix …" strips down to "fix …". */
17
+ const FLUFF_RES = [
18
+ /^(?:sure|okay|ok|alright|great|certainly|understood|got it|sounds good|of course)[,.!:]*\s+/i,
19
+ /^(?:i(?:'|’)?ll|i will|i(?:'|’)?m going to|i(?:'|’)?m about to|let me|let(?:'|’)?s|first,?|now,?)\s+/i,
20
+ /^(?:go ahead and|start by|begin by)\s+/i,
21
+ ];
22
+ /** Strip inline markdown emphasis/code from one line. */
23
+ function stripInlineMarkdown(line) {
24
+ return line
25
+ .replace(/^#{1,6}\s+/, '') // heading marker
26
+ .replace(/^(?:[-*+]|\d+[.)])\s+/, '') // list marker
27
+ .replace(/^>\s+/, '') // blockquote marker
28
+ .replace(/\*\*([^*]+)\*\*/g, '$1')
29
+ .replace(/__([^_]+)__/g, '$1')
30
+ .replace(/\*([^*]+)\*/g, '$1')
31
+ .replace(/(^|[\s(])_([^_]+)_(?=[\s).,;:!?]|$)/g, '$1$2') // word-bound _emphasis_, not snake_case
32
+ .replace(/`([^`]*)`/g, '$1')
33
+ .replace(/\[([^\]]+)\]\([^)]*\)/g, '$1') // [text](url) → text
34
+ .trim();
35
+ }
36
+ /**
37
+ * First sentence of `s`. Sentence end = `.`/`!`/`?` followed by whitespace or
38
+ * end of string — so dots inside paths (`src/store.ts`) don't cut it short.
39
+ */
40
+ function firstSentence(s) {
41
+ const match = /^(.*?[.!?])(?:\s|$)/.exec(s);
42
+ return (match?.[1] ?? s).replace(/[.!?]+$/, '').trim();
43
+ }
44
+ /**
45
+ * Derive a display title from an agent turn's text, or `undefined` when the
46
+ * text yields nothing more informative than the task itself.
47
+ */
48
+ export function deriveTitleSummary(text, task) {
49
+ // Fenced code blocks are never titles — drop them (incl. an unclosed one).
50
+ const withoutFences = text.replace(/```[\s\S]*?(?:```|$)/g, '\n');
51
+ const line = withoutFences
52
+ .split('\n')
53
+ .map((l) => stripInlineMarkdown(l))
54
+ .find((l) => l.length > 0);
55
+ if (!line)
56
+ return undefined;
57
+ // Fluff first, sentence second: "Sure! I'll fix …" — the fluff IS the
58
+ // first sentence, so stripping after extraction would keep only "Sure".
59
+ let s = line;
60
+ for (let stripped = true; stripped;) {
61
+ stripped = false;
62
+ for (const re of FLUFF_RES) {
63
+ const next = s.replace(re, '');
64
+ if (next !== s) {
65
+ s = next;
66
+ stripped = true;
67
+ }
68
+ }
69
+ }
70
+ s = firstSentence(s.trim());
71
+ // Cap by code points, not UTF-16 units — no split surrogate pairs.
72
+ const chars = [...s];
73
+ if (chars.length > MAX_LEN)
74
+ s = `${chars.slice(0, MAX_LEN - 1).join('').trimEnd()}…`;
75
+ // Informative? More than a few words, and not an echo of the task.
76
+ if (s.split(/\s+/).filter(Boolean).length < MIN_WORDS)
77
+ return undefined;
78
+ const taskFirstLine = (task.trim().split('\n')[0] ?? '').trim().toLowerCase();
79
+ if (s.toLowerCase() === taskFirstLine)
80
+ return undefined;
81
+ const first = [...s][0] ?? '';
82
+ return first.toUpperCase() + s.slice(first.length);
83
+ }
84
+ //# sourceMappingURL=title-summary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"title-summary.js","sourceRoot":"","sources":["../../src/runs/title-summary.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Protocol-v2 persistence + fan-out policy for one agent session — the
3
+ * RunManager feeds every `UiEvent` a runner emits (`SessionOptions.onUiEvent`)
4
+ * through one sink instance and the sink decides, per the spec's performance
5
+ * guardrails (§"Normalized agent-event protocol v2" and
6
+ * `.ai/analysis/cockpit-ui-redesign/protocol-rationale-and-performance.md` §5):
7
+ *
8
+ * - `item.delta` is COALESCED per item (~40 ms flush) onto the live wire
9
+ * only — raw deltas NEVER hit the NDJSON file; replay needs no delta
10
+ * reduction because every item's final state rides `item.completed`.
11
+ * - Everything else persists as snapshots via `persist()` (the store stamps
12
+ * `seq`/`ts`, and `appendEvent` already fans persisted lines out live, so
13
+ * a persisted event is never double-emitted here).
14
+ * - `item.updated` hits disk only on a meaningful change (status flip, new
15
+ * diffs/title/…) — streamed-content-only growth goes to the live wire
16
+ * ephemerally, mirroring what the deltas already carry.
17
+ * - `usage.updated` is cumulative per session: persisted only when the
18
+ * total (or cost) actually moved, mirroring v1's token-usage cadence.
19
+ *
20
+ * Output errors are swallowed: v2 is additive and best-effort — a persist
21
+ * failure (e.g. the run was deleted mid-flush) must never disturb the v1
22
+ * stream or crash a timer callback.
23
+ */
24
+ import type { StopReason, UiEvent } from '../core/ui-events.js';
25
+ /** Spec guardrail: coalesce `item.delta` at ~30–50 ms boundaries. */
26
+ export declare const DELTA_FLUSH_MS = 40;
27
+ /**
28
+ * v2 lines share the NDJSON file and the store's event bus with v1, but ride
29
+ * a DIFFERENT SSE event name (`ui-event` vs `run-event`) so the legacy UI —
30
+ * which knew only `run-event` and JSON-dumped unknown types into the
31
+ * transcript; retired in R7, but the name split stays as wire shape — never
32
+ * saw them. The discriminator is the dotted namespace:
33
+ * every v2 type on the wire is dotted (`item.started`, `turn.completed`, …)
34
+ * and no v1 type is. v2's only undotted type, `image`, never reaches the
35
+ * store: the sink drops it in favor of the v1 image pipeline (which persists
36
+ * the file and re-emits a URL instead of raw base64).
37
+ */
38
+ export declare function isV2WireEventType(type: string): boolean;
39
+ /** A loose event as the store consumes it (the sink adds no seq/ts — the
40
+ * store stamps those). */
41
+ type WireEvent = {
42
+ type: string;
43
+ [key: string]: unknown;
44
+ };
45
+ export interface UiEventSinkOutput {
46
+ /** Append to the run's NDJSON file (which also fans out live). */
47
+ persist(event: WireEvent): void;
48
+ /** Fan out live only — never written to disk (coalesced deltas). */
49
+ emitLive(event: WireEvent): void;
50
+ }
51
+ export declare class UiEventSink {
52
+ private readonly out;
53
+ private readonly flushMs;
54
+ /** Pending delta text per open item, per streamed field (insertion order
55
+ * preserved so a flush replays fields in first-arrival order). */
56
+ private readonly buffers;
57
+ private readonly timers;
58
+ /** Last persisted non-streamed shape per item — the `item.updated`
59
+ * meaningful-change filter. */
60
+ private readonly shapes;
61
+ private lastUsage;
62
+ private ended;
63
+ constructor(out: UiEventSinkOutput, flushMs?: number);
64
+ /** Fold one runner-emitted v2 event into the persist/live outputs. */
65
+ handle(event: UiEvent): void;
66
+ /**
67
+ * Session close, called by the RunManager exactly once when the v1 session
68
+ * settles: flush everything, then persist v2 `session.error` (fatal) when
69
+ * the session failed, and `session.ended` — the v2 counterparts of v1's
70
+ * `done`/`error`, which the mappers deliberately left to the RunManager.
71
+ */
72
+ sessionEnded(reason: StopReason, errorMessage?: string): void;
73
+ /** Flush every open coalescer now (turn end, session settle). */
74
+ flushAll(): void;
75
+ private bufferDelta;
76
+ /** Emit one merged `item.delta` per buffered field of the item, live only. */
77
+ private flushItem;
78
+ private persist;
79
+ private emitLive;
80
+ }
81
+ export {};