@pat-lewczuk/cezar 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +249 -45
- package/dist/config.d.ts +8 -0
- package/dist/config.js +6 -0
- package/dist/config.js.map +1 -1
- package/dist/core/agent-runner.d.ts +44 -2
- package/dist/core/agent-runner.js +8 -2
- package/dist/core/agent-runner.js.map +1 -1
- package/dist/core/backend-detect.d.ts +6 -4
- package/dist/core/backend-detect.js +44 -4
- package/dist/core/backend-detect.js.map +1 -1
- package/dist/core/claude-cli-runner.d.ts +3 -25
- package/dist/core/claude-cli-runner.js +2 -19
- package/dist/core/claude-cli-runner.js.map +1 -1
- package/dist/core/claude-ui-mapper.d.ts +57 -0
- package/dist/core/claude-ui-mapper.js +370 -0
- package/dist/core/claude-ui-mapper.js.map +1 -0
- package/dist/core/codex-app-server-runner.d.ts +29 -0
- package/dist/core/codex-app-server-runner.js +452 -0
- package/dist/core/codex-app-server-runner.js.map +1 -0
- package/dist/core/codex-ui-mapper.d.ts +53 -0
- package/dist/core/codex-ui-mapper.js +411 -0
- package/dist/core/codex-ui-mapper.js.map +1 -0
- package/dist/core/ndjson.d.ts +6 -0
- package/dist/core/ndjson.js +23 -0
- package/dist/core/ndjson.js.map +1 -0
- package/dist/core/opencode-server-runner.d.ts +30 -0
- package/dist/core/opencode-server-runner.js +451 -0
- package/dist/core/opencode-server-runner.js.map +1 -0
- package/dist/core/opencode-ui-mapper.d.ts +105 -0
- package/dist/core/opencode-ui-mapper.js +578 -0
- package/dist/core/opencode-ui-mapper.js.map +1 -0
- package/dist/core/process-usage.d.ts +63 -0
- package/dist/core/process-usage.js +181 -0
- package/dist/core/process-usage.js.map +1 -0
- package/dist/core/runner-factory.d.ts +8 -0
- package/dist/core/runner-factory.js +22 -0
- package/dist/core/runner-factory.js.map +1 -0
- package/dist/core/tool-display.d.ts +27 -0
- package/dist/core/tool-display.js +150 -0
- package/dist/core/tool-display.js.map +1 -0
- package/dist/core/ui-events.d.ts +294 -0
- package/dist/core/ui-events.js +25 -0
- package/dist/core/ui-events.js.map +1 -0
- package/dist/index.js +0 -0
- package/dist/pack-check.d.ts +17 -0
- package/dist/pack-check.js +27 -0
- package/dist/pack-check.js.map +1 -0
- package/dist/planner.js +7 -3
- package/dist/planner.js.map +1 -1
- package/dist/runs/store.d.ts +5 -0
- package/dist/runs/store.js +3 -0
- package/dist/runs/store.js.map +1 -1
- package/dist/runs/title-summary.d.ts +15 -0
- package/dist/runs/title-summary.js +84 -0
- package/dist/runs/title-summary.js.map +1 -0
- package/dist/runs/ui-event-sink.d.ts +81 -0
- package/dist/runs/ui-event-sink.js +210 -0
- package/dist/runs/ui-event-sink.js.map +1 -0
- package/dist/server/capabilities.d.ts +18 -0
- package/dist/server/capabilities.js +23 -0
- package/dist/server/capabilities.js.map +1 -0
- package/dist/server/forge/github.d.ts +39 -0
- package/dist/server/forge/github.js +369 -0
- package/dist/server/forge/github.js.map +1 -0
- package/dist/server/forge/index.d.ts +24 -0
- package/dist/server/forge/index.js +45 -0
- package/dist/server/forge/index.js.map +1 -0
- package/dist/server/forge/types.d.ts +80 -0
- package/dist/server/forge/types.js +2 -0
- package/dist/server/forge/types.js.map +1 -0
- package/dist/server/git-changes.d.ts +182 -0
- package/dist/server/git-changes.js +424 -0
- package/dist/server/git-changes.js.map +1 -0
- package/dist/server/open-in-app.d.ts +19 -0
- package/dist/server/open-in-app.js +134 -0
- package/dist/server/open-in-app.js.map +1 -0
- package/dist/server/server.js +34 -10
- package/dist/server/server.js.map +1 -1
- package/dist/server/static-ui.d.ts +49 -0
- package/dist/server/static-ui.js +92 -0
- package/dist/server/static-ui.js.map +1 -0
- package/dist/update-check.d.ts +12 -0
- package/dist/update-check.js +41 -0
- package/dist/update-check.js.map +1 -0
- package/dist/workflows/run.d.ts +3 -0
- package/dist/workflows/run.js +22 -7
- package/dist/workflows/run.js.map +1 -1
- package/dist/workflows/types.d.ts +16 -0
- package/dist/workflows/types.js +3 -1
- package/dist/workflows/types.js.map +1 -1
- package/package.json +1 -1
- package/web/app/node_modules/.vite/vitest/ca84d1343b96baa8137c943ed1860e522cacb238/results.json +1 -0
- package/web/app/src/components/app-shell-container.tsx +76 -0
- package/web/app.js +145 -18
- package/web/dist/assets/arrow-left-BE957rJs.js +1 -0
- package/web/dist/assets/bundle-mjs-DLPpRFyl.js +1 -0
- package/web/dist/assets/chunk-BO2N2NFS-f5igTtpB.js +131 -0
- package/web/dist/assets/compare-variants-D6fPL9cS.js +1 -0
- package/web/dist/assets/core-BuMqAF_1.js +12 -0
- package/web/dist/assets/css-BsVw1vtW.js +1 -0
- package/web/dist/assets/dialog-BEgEWFDS.js +1 -0
- package/web/dist/assets/diff-view-CctnJHWe.js +4 -0
- package/web/dist/assets/diff-woXpYk--.js +1 -0
- package/web/dist/assets/dist-CW7M_Jhs.js +1 -0
- package/web/dist/assets/ellipsis-vertical-DJPAfccS.js +1 -0
- package/web/dist/assets/engine-javascript-FQvzRocB.js +141 -0
- package/web/dist/assets/folder-RbRLfIX-.js +1 -0
- package/web/dist/assets/git-pull-request-DJkAMT0f.js +1 -0
- package/web/dist/assets/git-toolbar-D8OPPqBP.js +1 -0
- package/web/dist/assets/github-BYIHwIJB.js +1 -0
- package/web/dist/assets/go-rLFTqkRN.js +1 -0
- package/web/dist/assets/highlighted-body-OFNGDK62-DGHHie_q.js +1 -0
- package/web/dist/assets/highlighter-BKVEsACy.js +3 -0
- package/web/dist/assets/html-BY76lXLH.js +1 -0
- package/web/dist/assets/index-9qG98Orw.js +11 -0
- package/web/dist/assets/index-Bz_r8Jt3.css +2 -0
- package/web/dist/assets/input-BRsSo4xH.js +1 -0
- package/web/dist/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
- package/web/dist/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
- package/web/dist/assets/javascript-BgS3c2Ky.js +1 -0
- package/web/dist/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
- package/web/dist/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
- package/web/dist/assets/json-qhed-kSA.js +1 -0
- package/web/dist/assets/jsonc-CYpm1nAK.js +1 -0
- package/web/dist/assets/jsx-Bz0zcwM4.js +1 -0
- package/web/dist/assets/lib-CNGa3Dig.js +1 -0
- package/web/dist/assets/loader-circle-BV3DO9mE.js +1 -0
- package/web/dist/assets/markdown-BYOwaDjH.js +1 -0
- package/web/dist/assets/markdown-CR_HLGTs.js +1 -0
- package/web/dist/assets/mermaid-GHXKKRXX-DM2VsGBG.js +1 -0
- package/web/dist/assets/open-mercato-toBr6SOa.svg +11 -0
- package/web/dist/assets/python-gzcpVVnB.js +1 -0
- package/web/dist/assets/react-dom-Ddtik4qM.js +1 -0
- package/web/dist/assets/refresh-cw-DCa-Rlwz.js +1 -0
- package/web/dist/assets/repo-git-XTqlVOl2.js +1 -0
- package/web/dist/assets/run-diff-C7mfxj7f.js +3 -0
- package/web/dist/assets/run-header-CfVeY3uM.js +1 -0
- package/web/dist/assets/rust-Cfkwpbl8.js +1 -0
- package/web/dist/assets/search-x-CoCyl7zT.js +1 -0
- package/web/dist/assets/shellscript-CLZ0U2zV.js +1 -0
- package/web/dist/assets/skill-detail-C9cniyId.js +1 -0
- package/web/dist/assets/skills-DXgY1uXJ.js +1 -0
- package/web/dist/assets/skills-ynuO5oCr.js +1 -0
- package/web/dist/assets/sql-BsFa4tDR.js +1 -0
- package/web/dist/assets/square-terminal-B6PZX4Qp.js +1 -0
- package/web/dist/assets/tab-link-phWEqSBy.js +1 -0
- package/web/dist/assets/task-changes-DYwnPnTN.js +1 -0
- package/web/dist/assets/task-commits-DZzxEzbn.js +1 -0
- package/web/dist/assets/task-files-FOAAz2FB.js +2 -0
- package/web/dist/assets/task-thread-Bncxe8Os.js +5 -0
- package/web/dist/assets/toaster-BS2E1bhz.js +43 -0
- package/web/dist/assets/trash-2-CDtxmmc8.js +1 -0
- package/web/dist/assets/triangle-alert-6su4Js5O.js +1 -0
- package/web/dist/assets/tsx-udAQXfEw.js +1 -0
- package/web/dist/assets/typescript-bsJCZSQ-.js +1 -0
- package/web/dist/assets/upload-Bp7hQxll.js +1 -0
- package/web/dist/assets/use-desktop-eHm2iTXX.js +3 -0
- package/web/dist/assets/utils-rQGbOrwc.js +1 -0
- package/web/dist/assets/workflows-Dg2wQg6i.js +11 -0
- package/web/dist/assets/x-Br_jIDBw.js +1 -0
- package/web/dist/assets/yaml-rwi0_p6S.js +1 -0
- package/web/dist/index.html +67 -0
- package/web/index.html +1 -0
- package/web/style.css +28 -8
|
@@ -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 {};
|
|
@@ -0,0 +1,210 @@
|
|
|
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
|
+
/** Spec guardrail: coalesce `item.delta` at ~30–50 ms boundaries. */
|
|
25
|
+
export const DELTA_FLUSH_MS = 40;
|
|
26
|
+
/** Backstop so one item can never buffer unboundedly within a window. */
|
|
27
|
+
const MAX_DELTA_BUFFER = 64_000;
|
|
28
|
+
/**
|
|
29
|
+
* v2 lines share the NDJSON file and the store's event bus with v1, but ride
|
|
30
|
+
* a DIFFERENT SSE event name (`ui-event` vs `run-event`) so the legacy UI —
|
|
31
|
+
* which knew only `run-event` and JSON-dumped unknown types into the
|
|
32
|
+
* transcript; retired in R7, but the name split stays as wire shape — never
|
|
33
|
+
* saw them. The discriminator is the dotted namespace:
|
|
34
|
+
* every v2 type on the wire is dotted (`item.started`, `turn.completed`, …)
|
|
35
|
+
* and no v1 type is. v2's only undotted type, `image`, never reaches the
|
|
36
|
+
* store: the sink drops it in favor of the v1 image pipeline (which persists
|
|
37
|
+
* the file and re-emits a URL instead of raw base64).
|
|
38
|
+
*/
|
|
39
|
+
export function isV2WireEventType(type) {
|
|
40
|
+
return type.includes('.');
|
|
41
|
+
}
|
|
42
|
+
export class UiEventSink {
|
|
43
|
+
out;
|
|
44
|
+
flushMs;
|
|
45
|
+
/** Pending delta text per open item, per streamed field (insertion order
|
|
46
|
+
* preserved so a flush replays fields in first-arrival order). */
|
|
47
|
+
buffers = new Map();
|
|
48
|
+
timers = new Map();
|
|
49
|
+
/** Last persisted non-streamed shape per item — the `item.updated`
|
|
50
|
+
* meaningful-change filter. */
|
|
51
|
+
shapes = new Map();
|
|
52
|
+
lastUsage = null;
|
|
53
|
+
ended = false;
|
|
54
|
+
constructor(out, flushMs = DELTA_FLUSH_MS) {
|
|
55
|
+
this.out = out;
|
|
56
|
+
this.flushMs = flushMs;
|
|
57
|
+
}
|
|
58
|
+
/** Fold one runner-emitted v2 event into the persist/live outputs. */
|
|
59
|
+
handle(event) {
|
|
60
|
+
if (this.ended)
|
|
61
|
+
return;
|
|
62
|
+
switch (event.type) {
|
|
63
|
+
case 'item.delta':
|
|
64
|
+
this.bufferDelta(event);
|
|
65
|
+
return;
|
|
66
|
+
case 'item.started':
|
|
67
|
+
this.shapes.set(event.item.id, itemShape(event.item));
|
|
68
|
+
this.persist(event);
|
|
69
|
+
return;
|
|
70
|
+
case 'item.updated': {
|
|
71
|
+
// Chronology: the item's buffered deltas reach the live wire before
|
|
72
|
+
// the snapshot that supersedes them.
|
|
73
|
+
this.flushItem(event.item.id);
|
|
74
|
+
const shape = itemShape(event.item);
|
|
75
|
+
if (this.shapes.get(event.item.id) === shape) {
|
|
76
|
+
// Streamed-content-only growth — live consumers still get the
|
|
77
|
+
// snapshot, the disk stays at snapshot-change frequency.
|
|
78
|
+
this.emitLive(event);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
this.shapes.set(event.item.id, shape);
|
|
82
|
+
this.persist(event);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
case 'item.completed':
|
|
86
|
+
this.flushItem(event.item.id);
|
|
87
|
+
this.shapes.delete(event.item.id);
|
|
88
|
+
this.persist(event);
|
|
89
|
+
return;
|
|
90
|
+
case 'turn.completed':
|
|
91
|
+
this.flushAll();
|
|
92
|
+
this.persist(event);
|
|
93
|
+
return;
|
|
94
|
+
case 'usage.updated': {
|
|
95
|
+
if (this.lastUsage !== null &&
|
|
96
|
+
this.lastUsage.total === event.usage.total &&
|
|
97
|
+
this.lastUsage.costUsd === event.costUsd) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
this.lastUsage = { total: event.usage.total, costUsd: event.costUsd };
|
|
101
|
+
this.persist(event);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
case 'image':
|
|
105
|
+
// The v1 image pipeline already persists the screenshot as a file
|
|
106
|
+
// and re-emits a URL — persisting this raw-base64 twin would write
|
|
107
|
+
// the payload to the NDJSON file. Dropped until R3 links images to
|
|
108
|
+
// items by `itemId`.
|
|
109
|
+
return;
|
|
110
|
+
default:
|
|
111
|
+
// session.*, turn.started, plan.updated, permission.* — plain
|
|
112
|
+
// snapshot/lifecycle lines, persisted as they come. (`session.ended`
|
|
113
|
+
// and fatal `session.error` are normally minted by `sessionEnded()`;
|
|
114
|
+
// mapper-emitted ones — e.g. opencode's non-fatal session.error —
|
|
115
|
+
// pass through here.)
|
|
116
|
+
this.persist(event);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Session close, called by the RunManager exactly once when the v1 session
|
|
122
|
+
* settles: flush everything, then persist v2 `session.error` (fatal) when
|
|
123
|
+
* the session failed, and `session.ended` — the v2 counterparts of v1's
|
|
124
|
+
* `done`/`error`, which the mappers deliberately left to the RunManager.
|
|
125
|
+
*/
|
|
126
|
+
sessionEnded(reason, errorMessage) {
|
|
127
|
+
if (this.ended)
|
|
128
|
+
return;
|
|
129
|
+
this.flushAll();
|
|
130
|
+
if (errorMessage !== undefined) {
|
|
131
|
+
this.persist({ type: 'session.error', message: errorMessage, fatal: true });
|
|
132
|
+
this.persist({ type: 'session.ended', reason, message: errorMessage });
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
this.persist({ type: 'session.ended', reason });
|
|
136
|
+
}
|
|
137
|
+
this.ended = true;
|
|
138
|
+
}
|
|
139
|
+
/** Flush every open coalescer now (turn end, session settle). */
|
|
140
|
+
flushAll() {
|
|
141
|
+
for (const itemId of [...this.buffers.keys()])
|
|
142
|
+
this.flushItem(itemId);
|
|
143
|
+
}
|
|
144
|
+
// ---- internals -----------------------------------------------------------
|
|
145
|
+
bufferDelta(event) {
|
|
146
|
+
let fields = this.buffers.get(event.itemId);
|
|
147
|
+
if (!fields) {
|
|
148
|
+
fields = new Map();
|
|
149
|
+
this.buffers.set(event.itemId, fields);
|
|
150
|
+
}
|
|
151
|
+
const pending = (fields.get(event.field) ?? '') + event.delta;
|
|
152
|
+
fields.set(event.field, pending);
|
|
153
|
+
if (pending.length >= MAX_DELTA_BUFFER) {
|
|
154
|
+
this.flushItem(event.itemId);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
if (!this.timers.has(event.itemId)) {
|
|
158
|
+
const timer = setTimeout(() => this.flushItem(event.itemId), this.flushMs);
|
|
159
|
+
timer.unref?.();
|
|
160
|
+
this.timers.set(event.itemId, timer);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
/** Emit one merged `item.delta` per buffered field of the item, live only. */
|
|
164
|
+
flushItem(itemId) {
|
|
165
|
+
const timer = this.timers.get(itemId);
|
|
166
|
+
if (timer !== undefined) {
|
|
167
|
+
clearTimeout(timer);
|
|
168
|
+
this.timers.delete(itemId);
|
|
169
|
+
}
|
|
170
|
+
const fields = this.buffers.get(itemId);
|
|
171
|
+
if (!fields)
|
|
172
|
+
return;
|
|
173
|
+
this.buffers.delete(itemId);
|
|
174
|
+
for (const [field, delta] of fields) {
|
|
175
|
+
if (delta !== '')
|
|
176
|
+
this.emitLive({ type: 'item.delta', itemId, field, delta });
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
// UiEvent members carry no index signature; they are plain JSON objects at
|
|
180
|
+
// runtime, so widening them to the store's loose event shape is safe.
|
|
181
|
+
persist(event) {
|
|
182
|
+
try {
|
|
183
|
+
this.out.persist(event);
|
|
184
|
+
}
|
|
185
|
+
catch {
|
|
186
|
+
// best effort — v2 must never disturb the v1 stream
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
emitLive(event) {
|
|
190
|
+
try {
|
|
191
|
+
this.out.emitLive(event);
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
// best effort
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
/** The item minus its delta-streamed content field — what "meaningful
|
|
199
|
+
* snapshot change" compares. Mappers build items with stable key order, so
|
|
200
|
+
* JSON equality is a faithful (and cheap) identity; a false negative merely
|
|
201
|
+
* persists one extra snapshot. */
|
|
202
|
+
function itemShape(item) {
|
|
203
|
+
if (item.kind === 'tool') {
|
|
204
|
+
const { output: _output, ...rest } = item;
|
|
205
|
+
return JSON.stringify(rest);
|
|
206
|
+
}
|
|
207
|
+
const { text: _text, ...rest } = item;
|
|
208
|
+
return JSON.stringify(rest);
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=ui-event-sink.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui-event-sink.js","sourceRoot":"","sources":["../../src/runs/ui-event-sink.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deployment-mode capabilities (cockpit-ui redesign spec §"Deployment modes —
|
|
3
|
+
* local vs hosted"). The default deployment is `npx cezar-cli` on localhost,
|
|
4
|
+
* where handing a session off to a local terminal/editor makes sense. On a
|
|
5
|
+
* VPS/remote box it doesn't: `CEZ_REMOTE=1` (or binding a non-loopback host)
|
|
6
|
+
* switches to hosted mode — `/api/health` reports `localHandoff:false`, the UI
|
|
7
|
+
* hides every local-machine affordance, and the open-in-* endpoints 409 as
|
|
8
|
+
* defense in depth.
|
|
9
|
+
*/
|
|
10
|
+
export interface Capabilities {
|
|
11
|
+
localHandoff: boolean;
|
|
12
|
+
}
|
|
13
|
+
/** True for hosts that only the local machine can reach. Undefined = the
|
|
14
|
+
* default bind (127.0.0.1). */
|
|
15
|
+
export declare function isLoopbackHost(host: string | undefined): boolean;
|
|
16
|
+
/** `CEZ_REMOTE=1` or a non-loopback bind host ⇒ hosted mode (no local handoff).
|
|
17
|
+
* Read per request — cheap, and tests/ops can flip the env live. */
|
|
18
|
+
export declare function resolveCapabilities(env?: NodeJS.ProcessEnv, bindHost?: string): Capabilities;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deployment-mode capabilities (cockpit-ui redesign spec §"Deployment modes —
|
|
3
|
+
* local vs hosted"). The default deployment is `npx cezar-cli` on localhost,
|
|
4
|
+
* where handing a session off to a local terminal/editor makes sense. On a
|
|
5
|
+
* VPS/remote box it doesn't: `CEZ_REMOTE=1` (or binding a non-loopback host)
|
|
6
|
+
* switches to hosted mode — `/api/health` reports `localHandoff:false`, the UI
|
|
7
|
+
* hides every local-machine affordance, and the open-in-* endpoints 409 as
|
|
8
|
+
* defense in depth.
|
|
9
|
+
*/
|
|
10
|
+
/** True for hosts that only the local machine can reach. Undefined = the
|
|
11
|
+
* default bind (127.0.0.1). */
|
|
12
|
+
export function isLoopbackHost(host) {
|
|
13
|
+
if (!host)
|
|
14
|
+
return true;
|
|
15
|
+
const h = host.toLowerCase().replace(/^\[|\]$/g, '');
|
|
16
|
+
return h === 'localhost' || h === '::1' || h.startsWith('127.');
|
|
17
|
+
}
|
|
18
|
+
/** `CEZ_REMOTE=1` or a non-loopback bind host ⇒ hosted mode (no local handoff).
|
|
19
|
+
* Read per request — cheap, and tests/ops can flip the env live. */
|
|
20
|
+
export function resolveCapabilities(env = process.env, bindHost) {
|
|
21
|
+
return { localHandoff: env.CEZ_REMOTE !== '1' && isLoopbackHost(bindHost) };
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=capabilities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../../src/server/capabilities.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH;gCACgC;AAChC,MAAM,UAAU,cAAc,CAAC,IAAwB;IACrD,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IACrD,OAAO,CAAC,KAAK,WAAW,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;AAClE,CAAC;AAED;qEACqE;AACrE,MAAM,UAAU,mBAAmB,CAAC,MAAyB,OAAO,CAAC,GAAG,EAAE,QAAiB;IACzF,OAAO,EAAE,YAAY,EAAE,GAAG,CAAC,UAAU,KAAK,GAAG,IAAI,cAAc,CAAC,QAAQ,CAAC,EAAE,CAAC;AAC9E,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { DraftPrInput, DraftPrOutcome, ForgeAvailability, ForgeDriver, ForgeItem } from './types.js';
|
|
2
|
+
/** One GitHub issue or pull request, flattened for the cockpit's GitHub tab. */
|
|
3
|
+
export type GithubItem = ForgeItem;
|
|
4
|
+
export interface GithubData {
|
|
5
|
+
available: boolean;
|
|
6
|
+
/** Human-readable hint when unavailable (`gh` missing, no remote, offline…). */
|
|
7
|
+
reason?: string;
|
|
8
|
+
/** owner/name, when known. */
|
|
9
|
+
repo?: string;
|
|
10
|
+
syncedAt?: string;
|
|
11
|
+
issues: GithubItem[];
|
|
12
|
+
prs: GithubItem[];
|
|
13
|
+
/** Repo-wide map of label name → 6-hex color (no `#`), so the UI can tint chips like GitHub
|
|
14
|
+
* does. Additive (BACKWARD_COMPATIBILITY): absent on old payloads, chips fall back to neutral. */
|
|
15
|
+
labelColors?: Record<string, string>;
|
|
16
|
+
}
|
|
17
|
+
export declare const GH_MAX_LIMIT = 1000;
|
|
18
|
+
export declare function fetchGithub(repoRoot: string, refresh?: boolean, limit?: number): Promise<GithubData>;
|
|
19
|
+
export declare function createDraftPr(input: DraftPrInput): Promise<DraftPrOutcome>;
|
|
20
|
+
/**
|
|
21
|
+
* PR body from the handoff journal: the "## Goal" section (task text as
|
|
22
|
+
* fallback) + the first ~10 lines of "## Progress log" (newest first) +
|
|
23
|
+
* the cezar footer.
|
|
24
|
+
*/
|
|
25
|
+
export declare function buildPrBody(handoffText: string, task: string): string;
|
|
26
|
+
/**
|
|
27
|
+
* Non-blocking availability for `GET /api/health` (#major-health-latency): returns the cached
|
|
28
|
+
* probe immediately, or `null` while kicking off a background probe to warm it. It NEVER shells
|
|
29
|
+
* out to `gh` on the request that reads it, so health stays under the bookmarklet's 800 ms port
|
|
30
|
+
* budget (a `gh repo view` round-trip is ~500–650 ms on its own). `null` is contract-safe — the
|
|
31
|
+
* whole `forge` field is additive, so "unknown until warm" is a valid answer.
|
|
32
|
+
*/
|
|
33
|
+
export declare function detectGithubCached(repoRoot: string): ForgeAvailability | null;
|
|
34
|
+
/** owner/repo parsed out of the origin remote — feeds `viewUrl`. */
|
|
35
|
+
export interface GithubRepoRef {
|
|
36
|
+
owner: string;
|
|
37
|
+
repo: string;
|
|
38
|
+
}
|
|
39
|
+
export declare function createGithubDriver(repoRoot: string, repoRef: GithubRepoRef | null): ForgeDriver;
|