koneck 2.25.76 → 2.27.0
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/doctor.d.ts +15 -0
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +28 -8
- package/dist/doctor.js.map +1 -1
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +4 -1
- package/dist/engine.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +51 -4
- package/dist/index.js.map +1 -1
- package/dist/ink-chat.d.ts +10 -0
- package/dist/ink-chat.d.ts.map +1 -1
- package/dist/ink-chat.js +156 -22
- package/dist/ink-chat.js.map +1 -1
- package/dist/quality-gate.d.ts +5 -1
- package/dist/quality-gate.d.ts.map +1 -1
- package/dist/quality-gate.js +8 -6
- package/dist/quality-gate.js.map +1 -1
- package/dist/session.d.ts +10 -1
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +12 -1
- package/dist/session.js.map +1 -1
- package/dist/types.d.ts +4 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/web/api.d.ts +31 -0
- package/dist/web/api.d.ts.map +1 -0
- package/dist/web/api.js +295 -0
- package/dist/web/api.js.map +1 -0
- package/dist/web/changes.d.ts +55 -0
- package/dist/web/changes.d.ts.map +1 -0
- package/dist/web/changes.js +215 -0
- package/dist/web/changes.js.map +1 -0
- package/dist/web/events.d.ts +172 -0
- package/dist/web/events.d.ts.map +1 -0
- package/dist/web/events.js +52 -0
- package/dist/web/events.js.map +1 -0
- package/dist/web/history.d.ts +61 -0
- package/dist/web/history.d.ts.map +1 -0
- package/dist/web/history.js +197 -0
- package/dist/web/history.js.map +1 -0
- package/dist/web/mark.d.ts +15 -0
- package/dist/web/mark.d.ts.map +1 -0
- package/dist/web/mark.js +15 -0
- package/dist/web/mark.js.map +1 -0
- package/dist/web/sessions.d.ts +82 -0
- package/dist/web/sessions.d.ts.map +1 -0
- package/dist/web/sessions.js +197 -0
- package/dist/web/sessions.js.map +1 -0
- package/dist/web/ui-client.d.ts +14 -0
- package/dist/web/ui-client.d.ts.map +1 -0
- package/dist/web/ui-client.js +0 -0
- package/dist/web/ui-client.js.map +1 -0
- package/dist/web/ui-css.d.ts +15 -0
- package/dist/web/ui-css.d.ts.map +1 -0
- package/dist/web/ui-css.js +284 -0
- package/dist/web/ui-css.js.map +1 -0
- package/dist/web/ui.d.ts +11 -0
- package/dist/web/ui.d.ts.map +1 -0
- package/dist/web/ui.js +116 -0
- package/dist/web/ui.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"changes.d.ts","sourceRoot":"","sources":["../../src/web/changes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAYH,6FAA6F;AAC7F,eAAO,MAAM,cAAc,QAAa,CAAC;AACzC,wFAAwF;AACxF,eAAO,MAAM,SAAS,OAAQ,CAAC;AAY/B,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAO9C;;;;;GAKG;AACH,wBAAsB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAgC7D;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,CAAC;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,oEAAoE;IACpE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACd;AAuCD,6EAA6E;AAC7E,wBAAgB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAsBvG;AAED,oEAAoE;AACpE,wBAAgB,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,GAAG,UAAU,EAAE,CAqCvE;AAED,gCAAgC;AAChC,wBAAgB,SAAS,CAAC,OAAO,EAAE,SAAS,UAAU,EAAE,GAAG;IACzD,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;CAC/C,CAMA"}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a session changed on disk, and what the change was.
|
|
3
|
+
*
|
|
4
|
+
* KONECK has a git-based checkpoint already, and it is the right thing when there is a repository:
|
|
5
|
+
* `git write-tree` is cheap and exact. But it needs one, and the workspace this was asked for has
|
|
6
|
+
* no repository of its own — the enclosing directory has one, which is a tree full of other
|
|
7
|
+
* projects and precisely what the git tools are now withheld from touching. A diff view that only
|
|
8
|
+
* works in a git repo is a diff view that does not work.
|
|
9
|
+
*
|
|
10
|
+
* So the workspace is read directly: a snapshot of the text files before a turn, another after, and
|
|
11
|
+
* the difference between them. Bounded in every direction, because a workspace can contain a
|
|
12
|
+
* node_modules and a build output and a database.
|
|
13
|
+
*/
|
|
14
|
+
import { readdir, readFile, stat } from 'fs/promises';
|
|
15
|
+
import path from 'path';
|
|
16
|
+
/** Directories never worth reading: generated, enormous, or not the user's work. */
|
|
17
|
+
const SKIP_DIRS = new Set([
|
|
18
|
+
'node_modules', '.git', '.svn', '.hg', 'dist', 'build', 'out', 'target',
|
|
19
|
+
'.next', '.nuxt', '.venv', 'venv', '__pycache__', '.cache', '.turbo',
|
|
20
|
+
'coverage', '.pytest_cache', '.mypy_cache', '.gradle', 'vendor', '.koneck',
|
|
21
|
+
]);
|
|
22
|
+
/** A file larger than this is recorded by size alone: no diff is readable at that length. */
|
|
23
|
+
export const MAX_DIFF_BYTES = 512 * 1024;
|
|
24
|
+
/** A cap on how many files are held, so a snapshot cannot become the memory problem. */
|
|
25
|
+
export const MAX_FILES = 4_000;
|
|
26
|
+
/** Anything that is plainly not text does not get diffed. */
|
|
27
|
+
const BINARY_EXT = new Set([
|
|
28
|
+
'.png', '.jpg', '.jpeg', '.gif', '.webp', '.avif', '.ico', '.bmp', '.svgz',
|
|
29
|
+
'.pdf', '.zip', '.gz', '.tgz', '.bz2', '.xz', '.7z', '.rar', '.jar',
|
|
30
|
+
'.mp3', '.mp4', '.mov', '.avi', '.mkv', '.wav', '.flac', '.ogg',
|
|
31
|
+
'.woff', '.woff2', '.ttf', '.otf', '.eot',
|
|
32
|
+
'.so', '.dylib', '.dll', '.exe', '.bin', '.wasm', '.db', '.sqlite', '.sqlite3',
|
|
33
|
+
'.pyc', '.class', '.o', '.a', '.node',
|
|
34
|
+
]);
|
|
35
|
+
const looksBinary = (name) => BINARY_EXT.has(path.extname(name).toLowerCase());
|
|
36
|
+
/** Written as a code point so no source file needs to contain the byte itself. */
|
|
37
|
+
const NUL = String.fromCharCode(0);
|
|
38
|
+
/**
|
|
39
|
+
* Every text file under a workspace, with its contents.
|
|
40
|
+
*
|
|
41
|
+
* Content is read rather than hashed because the diff needs it anyway, and a workspace that fits
|
|
42
|
+
* in the caps above is small enough that reading it is faster than deciding not to.
|
|
43
|
+
*/
|
|
44
|
+
export async function snapshot(cwd) {
|
|
45
|
+
const out = new Map();
|
|
46
|
+
async function walk(dir, depth) {
|
|
47
|
+
if (out.size >= MAX_FILES || depth > 12)
|
|
48
|
+
return;
|
|
49
|
+
let entries;
|
|
50
|
+
try {
|
|
51
|
+
entries = await readdir(dir, { withFileTypes: true });
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
for (const entry of entries) {
|
|
57
|
+
if (out.size >= MAX_FILES)
|
|
58
|
+
return;
|
|
59
|
+
const full = path.join(dir, entry.name);
|
|
60
|
+
if (entry.isDirectory()) {
|
|
61
|
+
if (SKIP_DIRS.has(entry.name) || entry.name.startsWith('.'))
|
|
62
|
+
continue;
|
|
63
|
+
await walk(full, depth + 1);
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
if (!entry.isFile())
|
|
67
|
+
continue; // a socket or a symlink loop
|
|
68
|
+
const rel = path.relative(cwd, full);
|
|
69
|
+
try {
|
|
70
|
+
const info = await stat(full);
|
|
71
|
+
const state = { size: info.size, mtimeMs: info.mtimeMs };
|
|
72
|
+
if (!looksBinary(entry.name) && info.size <= MAX_DIFF_BYTES) {
|
|
73
|
+
const text = await readFile(full, 'utf8');
|
|
74
|
+
// A NUL byte in the first stretch means it is binary whatever the extension says.
|
|
75
|
+
if (!text.slice(0, 4_000).includes(NUL))
|
|
76
|
+
state.text = text;
|
|
77
|
+
}
|
|
78
|
+
out.set(rel, state);
|
|
79
|
+
}
|
|
80
|
+
catch { /* vanished between readdir and stat, or unreadable */ }
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
await walk(cwd, 0);
|
|
84
|
+
return out;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* The longest common subsequence of two line arrays, as an edit script.
|
|
88
|
+
*
|
|
89
|
+
* Written out rather than pulled in: a diff is forty lines of Myers and the dependency would be
|
|
90
|
+
* another thing to keep current. Bounded by area, and above the bound it reports a whole-file
|
|
91
|
+
* replacement rather than spending a second on a file nobody will read the diff of.
|
|
92
|
+
*/
|
|
93
|
+
function diffLines(before, after) {
|
|
94
|
+
const n = before.length, m = after.length;
|
|
95
|
+
if (n * m > 4_000_000) {
|
|
96
|
+
return [...before.map(l => ['-', l]),
|
|
97
|
+
...after.map(l => ['+', l])];
|
|
98
|
+
}
|
|
99
|
+
// Classic LCS table. Memory is the reason for the area bound above.
|
|
100
|
+
const lcs = Array.from({ length: n + 1 }, () => new Array(m + 1).fill(0));
|
|
101
|
+
for (let i = n - 1; i >= 0; i--) {
|
|
102
|
+
for (let j = m - 1; j >= 0; j--) {
|
|
103
|
+
lcs[i][j] = before[i] === after[j]
|
|
104
|
+
? lcs[i + 1][j + 1] + 1
|
|
105
|
+
: Math.max(lcs[i + 1][j], lcs[i][j + 1]);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
const script = [];
|
|
109
|
+
let i = 0, j = 0;
|
|
110
|
+
while (i < n && j < m) {
|
|
111
|
+
if (before[i] === after[j]) {
|
|
112
|
+
script.push([' ', before[i]]);
|
|
113
|
+
i++;
|
|
114
|
+
j++;
|
|
115
|
+
}
|
|
116
|
+
else if (lcs[i + 1][j] >= lcs[i][j + 1]) {
|
|
117
|
+
script.push(['-', before[i]]);
|
|
118
|
+
i++;
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
script.push(['+', after[j]]);
|
|
122
|
+
j++;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
while (i < n)
|
|
126
|
+
script.push(['-', before[i++]]);
|
|
127
|
+
while (j < m)
|
|
128
|
+
script.push(['+', after[j++]]);
|
|
129
|
+
return script;
|
|
130
|
+
}
|
|
131
|
+
/** Context lines either side of a change. Three is what everybody's diff shows. */
|
|
132
|
+
const CONTEXT = 3;
|
|
133
|
+
/** The edit script as a unified diff, with untouched stretches collapsed. */
|
|
134
|
+
export function unified(before, after) {
|
|
135
|
+
const script = diffLines(before.split('\n'), after.split('\n'));
|
|
136
|
+
let added = 0, removed = 0;
|
|
137
|
+
for (const [kind] of script) {
|
|
138
|
+
if (kind === '+')
|
|
139
|
+
added++;
|
|
140
|
+
else if (kind === '-')
|
|
141
|
+
removed++;
|
|
142
|
+
}
|
|
143
|
+
// Which lines to keep: any change, plus context around it.
|
|
144
|
+
const keep = new Array(script.length).fill(false);
|
|
145
|
+
for (let k = 0; k < script.length; k++) {
|
|
146
|
+
if (script[k][0] === ' ')
|
|
147
|
+
continue;
|
|
148
|
+
for (let c = Math.max(0, k - CONTEXT); c <= Math.min(script.length - 1, k + CONTEXT); c++) {
|
|
149
|
+
keep[c] = true;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
const lines = [];
|
|
153
|
+
let gap = false;
|
|
154
|
+
for (let k = 0; k < script.length; k++) {
|
|
155
|
+
if (!keep[k]) {
|
|
156
|
+
gap = true;
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
if (gap) {
|
|
160
|
+
lines.push('@@');
|
|
161
|
+
gap = false;
|
|
162
|
+
}
|
|
163
|
+
lines.push(script[k][0] + script[k][1]);
|
|
164
|
+
}
|
|
165
|
+
return { diff: lines.join('\n'), added, removed };
|
|
166
|
+
}
|
|
167
|
+
/** What changed between two snapshots, newest interesting first. */
|
|
168
|
+
export function compare(before, after) {
|
|
169
|
+
const changes = [];
|
|
170
|
+
for (const [file, now] of after) {
|
|
171
|
+
const was = before.get(file);
|
|
172
|
+
if (!was) {
|
|
173
|
+
const lines = now.text ? now.text.split('\n').length : 0;
|
|
174
|
+
changes.push({
|
|
175
|
+
path: file, kind: 'added', added: lines, removed: 0, size: now.size,
|
|
176
|
+
diff: now.text === undefined ? null
|
|
177
|
+
: now.text.split('\n').map(l => '+' + l).join('\n'),
|
|
178
|
+
});
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
// mtime alone is not evidence: a tool can rewrite a file with identical contents.
|
|
182
|
+
if (was.size === now.size && was.text !== undefined && was.text === now.text)
|
|
183
|
+
continue;
|
|
184
|
+
if (was.text === undefined || now.text === undefined) {
|
|
185
|
+
if (was.size === now.size && was.mtimeMs === now.mtimeMs)
|
|
186
|
+
continue;
|
|
187
|
+
changes.push({ path: file, kind: 'modified', added: 0, removed: 0, diff: null, size: now.size });
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
if (was.text === now.text)
|
|
191
|
+
continue;
|
|
192
|
+
const { diff, added, removed } = unified(was.text, now.text);
|
|
193
|
+
changes.push({ path: file, kind: 'modified', added, removed, diff, size: now.size });
|
|
194
|
+
}
|
|
195
|
+
for (const [file, was] of before) {
|
|
196
|
+
if (after.has(file))
|
|
197
|
+
continue;
|
|
198
|
+
changes.push({
|
|
199
|
+
path: file, kind: 'deleted', added: 0,
|
|
200
|
+
removed: was.text ? was.text.split('\n').length : 0, size: 0,
|
|
201
|
+
diff: was.text === undefined ? null : was.text.split('\n').map(l => '-' + l).join('\n'),
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
// Most changed first, since that is what anybody looks at.
|
|
205
|
+
return changes.sort((a, b) => (b.added + b.removed) - (a.added + a.removed));
|
|
206
|
+
}
|
|
207
|
+
/** Totals for a header line. */
|
|
208
|
+
export function summarise(changes) {
|
|
209
|
+
return {
|
|
210
|
+
files: changes.length,
|
|
211
|
+
added: changes.reduce((n, c) => n + c.added, 0),
|
|
212
|
+
removed: changes.reduce((n, c) => n + c.removed, 0),
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=changes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"changes.js","sourceRoot":"","sources":["../../src/web/changes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a session does, as events a browser can render.
|
|
3
|
+
*
|
|
4
|
+
* The existing /run route shelled out to the CLI and forwarded stdout line by line, so the web side
|
|
5
|
+
* received text that had already been formatted for a terminal — no way to tell a tool call from a
|
|
6
|
+
* sentence, no timings, no plan, nothing to lay out. Everything needed was already there: the
|
|
7
|
+
* engine takes twenty-one callbacks, and each one is an event with a shape.
|
|
8
|
+
*
|
|
9
|
+
* Typed as a discriminated union so the client can switch on `t` and the compiler checks both ends.
|
|
10
|
+
* Every event carries `at` because when things happened is most of what anyone wants to know
|
|
11
|
+
* afterwards, and `seq` so a client that reconnects can say what it already has.
|
|
12
|
+
*/
|
|
13
|
+
export type WebEvent =
|
|
14
|
+
/** A session was created or adopted. */
|
|
15
|
+
{
|
|
16
|
+
t: 'session';
|
|
17
|
+
at: number;
|
|
18
|
+
seq: number;
|
|
19
|
+
sessionId: string;
|
|
20
|
+
cwd: string;
|
|
21
|
+
provider: string;
|
|
22
|
+
model: string;
|
|
23
|
+
}
|
|
24
|
+
/** The user's message, echoed back so every client sees the same transcript. */
|
|
25
|
+
| {
|
|
26
|
+
t: 'user';
|
|
27
|
+
at: number;
|
|
28
|
+
seq: number;
|
|
29
|
+
text: string;
|
|
30
|
+
}
|
|
31
|
+
/** A piece of the reply as it streams. */
|
|
32
|
+
| {
|
|
33
|
+
t: 'chunk';
|
|
34
|
+
at: number;
|
|
35
|
+
seq: number;
|
|
36
|
+
text: string;
|
|
37
|
+
}
|
|
38
|
+
/** Reasoning, where the model exposes it. */
|
|
39
|
+
| {
|
|
40
|
+
t: 'thinking';
|
|
41
|
+
at: number;
|
|
42
|
+
seq: number;
|
|
43
|
+
text: string;
|
|
44
|
+
chars: number;
|
|
45
|
+
}
|
|
46
|
+
/** A tool is about to run. */
|
|
47
|
+
| {
|
|
48
|
+
t: 'tool';
|
|
49
|
+
at: number;
|
|
50
|
+
seq: number;
|
|
51
|
+
callId: string;
|
|
52
|
+
name: string;
|
|
53
|
+
detail: string;
|
|
54
|
+
}
|
|
55
|
+
/** Output from a tool while it runs — a dev server's log, a test's progress. */
|
|
56
|
+
| {
|
|
57
|
+
t: 'tool-output';
|
|
58
|
+
at: number;
|
|
59
|
+
seq: number;
|
|
60
|
+
name: string;
|
|
61
|
+
line: string;
|
|
62
|
+
}
|
|
63
|
+
/** A tool finished. */
|
|
64
|
+
| {
|
|
65
|
+
t: 'tool-done';
|
|
66
|
+
at: number;
|
|
67
|
+
seq: number;
|
|
68
|
+
callId: string;
|
|
69
|
+
name: string;
|
|
70
|
+
ok: boolean;
|
|
71
|
+
ms: number;
|
|
72
|
+
detail: string;
|
|
73
|
+
}
|
|
74
|
+
/** The plan, whenever it changes. */
|
|
75
|
+
| {
|
|
76
|
+
t: 'plan';
|
|
77
|
+
at: number;
|
|
78
|
+
seq: number;
|
|
79
|
+
steps: Array<{
|
|
80
|
+
text: string;
|
|
81
|
+
state: string;
|
|
82
|
+
}>;
|
|
83
|
+
}
|
|
84
|
+
/** Token counts, as the provider reports them. */
|
|
85
|
+
| {
|
|
86
|
+
t: 'tokens';
|
|
87
|
+
at: number;
|
|
88
|
+
seq: number;
|
|
89
|
+
prompt: number;
|
|
90
|
+
completion: number;
|
|
91
|
+
total: number;
|
|
92
|
+
cost: number;
|
|
93
|
+
}
|
|
94
|
+
/** Permission is needed before a tool runs. Answered by POST /api/answer. */
|
|
95
|
+
| {
|
|
96
|
+
t: 'ask';
|
|
97
|
+
at: number;
|
|
98
|
+
seq: number;
|
|
99
|
+
askId: string;
|
|
100
|
+
tool: string;
|
|
101
|
+
args: string;
|
|
102
|
+
waiting: number;
|
|
103
|
+
}
|
|
104
|
+
/** A permission request was resolved, by anyone. */
|
|
105
|
+
| {
|
|
106
|
+
t: 'ask-done';
|
|
107
|
+
at: number;
|
|
108
|
+
seq: number;
|
|
109
|
+
askId: string;
|
|
110
|
+
allowed: boolean;
|
|
111
|
+
}
|
|
112
|
+
/** Something worth telling the user that is not the model talking. */
|
|
113
|
+
| {
|
|
114
|
+
t: 'notice';
|
|
115
|
+
at: number;
|
|
116
|
+
seq: number;
|
|
117
|
+
level: 'info' | 'warn';
|
|
118
|
+
text: string;
|
|
119
|
+
}
|
|
120
|
+
/** The turn ended. */
|
|
121
|
+
| {
|
|
122
|
+
t: 'turn-end';
|
|
123
|
+
at: number;
|
|
124
|
+
seq: number;
|
|
125
|
+
ms: number;
|
|
126
|
+
completed: boolean;
|
|
127
|
+
}
|
|
128
|
+
/** The run failed. */
|
|
129
|
+
| {
|
|
130
|
+
t: 'error';
|
|
131
|
+
at: number;
|
|
132
|
+
seq: number;
|
|
133
|
+
text: string;
|
|
134
|
+
}
|
|
135
|
+
/** Sent periodically so a proxy does not close an idle stream. */
|
|
136
|
+
| {
|
|
137
|
+
t: 'ping';
|
|
138
|
+
at: number;
|
|
139
|
+
seq: number;
|
|
140
|
+
};
|
|
141
|
+
/**
|
|
142
|
+
* A bounded log of everything one session has emitted, and the clients watching it.
|
|
143
|
+
*
|
|
144
|
+
* Kept so a browser that arrives late — or reloads, which is the common case — sees the whole
|
|
145
|
+
* conversation rather than whatever happens next. Bounded because a session that runs for an hour
|
|
146
|
+
* should not be able to fill memory with its own history; the transcript on disk is the permanent
|
|
147
|
+
* record and this is only what the live view needs.
|
|
148
|
+
*/
|
|
149
|
+
export declare const MAX_BUFFERED = 5000;
|
|
150
|
+
/**
|
|
151
|
+
* One event minus the fields the bus fills in.
|
|
152
|
+
*
|
|
153
|
+
* Written to distribute over the union. A plain `Omit<WebEvent, 'at' | 'seq'>` collapses a union to
|
|
154
|
+
* the keys every member shares — which is `t` alone — so every field of every event was rejected
|
|
155
|
+
* as unknown. The conditional forces TypeScript to apply the Omit to each member separately.
|
|
156
|
+
*/
|
|
157
|
+
export type Emitted<T = WebEvent> = T extends unknown ? Omit<T, 'at' | 'seq'> & {
|
|
158
|
+
at?: number;
|
|
159
|
+
} : never;
|
|
160
|
+
export declare class EventBus {
|
|
161
|
+
private readonly log;
|
|
162
|
+
private readonly clients;
|
|
163
|
+
private seq;
|
|
164
|
+
/** Stamps and records an event, then hands it to every listener. */
|
|
165
|
+
emit(event: Emitted): WebEvent;
|
|
166
|
+
/** Everything since `after`, for a client that is catching up. */
|
|
167
|
+
since(after?: number): WebEvent[];
|
|
168
|
+
subscribe(fn: (e: WebEvent) => void): () => void;
|
|
169
|
+
get watchers(): number;
|
|
170
|
+
get lastSeq(): number;
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/web/events.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a session does, as events a browser can render.
|
|
3
|
+
*
|
|
4
|
+
* The existing /run route shelled out to the CLI and forwarded stdout line by line, so the web side
|
|
5
|
+
* received text that had already been formatted for a terminal — no way to tell a tool call from a
|
|
6
|
+
* sentence, no timings, no plan, nothing to lay out. Everything needed was already there: the
|
|
7
|
+
* engine takes twenty-one callbacks, and each one is an event with a shape.
|
|
8
|
+
*
|
|
9
|
+
* Typed as a discriminated union so the client can switch on `t` and the compiler checks both ends.
|
|
10
|
+
* Every event carries `at` because when things happened is most of what anyone wants to know
|
|
11
|
+
* afterwards, and `seq` so a client that reconnects can say what it already has.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* A bounded log of everything one session has emitted, and the clients watching it.
|
|
15
|
+
*
|
|
16
|
+
* Kept so a browser that arrives late — or reloads, which is the common case — sees the whole
|
|
17
|
+
* conversation rather than whatever happens next. Bounded because a session that runs for an hour
|
|
18
|
+
* should not be able to fill memory with its own history; the transcript on disk is the permanent
|
|
19
|
+
* record and this is only what the live view needs.
|
|
20
|
+
*/
|
|
21
|
+
export const MAX_BUFFERED = 5_000;
|
|
22
|
+
export class EventBus {
|
|
23
|
+
log = [];
|
|
24
|
+
clients = new Set();
|
|
25
|
+
seq = 0;
|
|
26
|
+
/** Stamps and records an event, then hands it to every listener. */
|
|
27
|
+
emit(event) {
|
|
28
|
+
const full = { ...event, at: event.at ?? Date.now(), seq: ++this.seq };
|
|
29
|
+
this.log.push(full);
|
|
30
|
+
if (this.log.length > MAX_BUFFERED)
|
|
31
|
+
this.log.shift();
|
|
32
|
+
for (const client of this.clients) {
|
|
33
|
+
// One client's failure is not the others' problem, and never the session's.
|
|
34
|
+
try {
|
|
35
|
+
client(full);
|
|
36
|
+
}
|
|
37
|
+
catch { /* a disconnected socket, mid-write */ }
|
|
38
|
+
}
|
|
39
|
+
return full;
|
|
40
|
+
}
|
|
41
|
+
/** Everything since `after`, for a client that is catching up. */
|
|
42
|
+
since(after = 0) {
|
|
43
|
+
return after <= 0 ? [...this.log] : this.log.filter(e => e.seq > after);
|
|
44
|
+
}
|
|
45
|
+
subscribe(fn) {
|
|
46
|
+
this.clients.add(fn);
|
|
47
|
+
return () => { this.clients.delete(fn); };
|
|
48
|
+
}
|
|
49
|
+
get watchers() { return this.clients.size; }
|
|
50
|
+
get lastSeq() { return this.seq; }
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/web/events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAkCH;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,CAAC;AAalC,MAAM,OAAO,QAAQ;IACF,GAAG,GAAe,EAAE,CAAC;IACrB,OAAO,GAAG,IAAI,GAAG,EAAyB,CAAC;IACpD,GAAG,GAAG,CAAC,CAAC;IAEhB,oEAAoE;IACpE,IAAI,CAAC,KAAc;QACjB,MAAM,IAAI,GAAG,EAAE,GAAG,KAAK,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,EAAE,IAAI,CAAC,GAAG,EAAc,CAAC;QACnF,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpB,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,YAAY;YAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;QACrD,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAClC,4EAA4E;YAC5E,IAAI,CAAC;gBAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,sCAAsC,CAAC,CAAC;QACxE,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,kEAAkE;IAClE,KAAK,CAAC,KAAK,GAAG,CAAC;QACb,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC,CAAC;IAC1E,CAAC;IAED,SAAS,CAAC,EAAyB;QACjC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACrB,OAAO,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5C,CAAC;IAED,IAAI,QAAQ,KAAa,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACpD,IAAI,OAAO,KAAa,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;CAC3C"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sessions already on disk, read back as something a browser can show.
|
|
3
|
+
*
|
|
4
|
+
* Every CLI run writes a JSONL transcript into `.koneck/sessions`, and until now the web side
|
|
5
|
+
* listed their titles and could do nothing with them. That is the larger half of what a harness is
|
|
6
|
+
* for: most of the value is in looking at a run that has already happened — what it did, in what
|
|
7
|
+
* order, and where the time went — and none of that needs an agent to be running.
|
|
8
|
+
*
|
|
9
|
+
* The file is the record, so this only reads. A past session cannot be resumed from the browser
|
|
10
|
+
* because resuming is what the CLI does, and pretending otherwise would produce a second live
|
|
11
|
+
* session pointed at the same transcript.
|
|
12
|
+
*/
|
|
13
|
+
import { type TrajectoryEvent, type TrajectorySummary } from '../trajectory.js';
|
|
14
|
+
export interface PastSessionMeta {
|
|
15
|
+
file: string;
|
|
16
|
+
id: string;
|
|
17
|
+
task: string;
|
|
18
|
+
model: string;
|
|
19
|
+
provider: string;
|
|
20
|
+
turns: number;
|
|
21
|
+
totalTokens: number;
|
|
22
|
+
at: number;
|
|
23
|
+
bytes: number;
|
|
24
|
+
}
|
|
25
|
+
/** One entry in a rendered transcript. */
|
|
26
|
+
export type PastEntry = {
|
|
27
|
+
kind: 'user';
|
|
28
|
+
text: string;
|
|
29
|
+
} | {
|
|
30
|
+
kind: 'assistant';
|
|
31
|
+
text: string;
|
|
32
|
+
} | {
|
|
33
|
+
kind: 'tool';
|
|
34
|
+
name: string;
|
|
35
|
+
args: string;
|
|
36
|
+
result: string;
|
|
37
|
+
ok: boolean;
|
|
38
|
+
} | {
|
|
39
|
+
kind: 'system';
|
|
40
|
+
text: string;
|
|
41
|
+
};
|
|
42
|
+
export interface PastSession {
|
|
43
|
+
meta: PastSessionMeta;
|
|
44
|
+
entries: PastEntry[];
|
|
45
|
+
trajectory: TrajectoryEvent[];
|
|
46
|
+
summary: TrajectorySummary | null;
|
|
47
|
+
/** True when the file held more than was read, so the view can say so. */
|
|
48
|
+
truncated: boolean;
|
|
49
|
+
}
|
|
50
|
+
/** A transcript longer than this is read to here and the rest reported as omitted. */
|
|
51
|
+
export declare const MAX_ENTRIES = 600;
|
|
52
|
+
/** Only the first line of each file is read: it holds the metadata. */
|
|
53
|
+
export declare function listPast(cwd: string, limit?: number): Promise<PastSessionMeta[]>;
|
|
54
|
+
/**
|
|
55
|
+
* One session, read into entries.
|
|
56
|
+
*
|
|
57
|
+
* The file is a sequence of records; older KONECK versions wrote slightly different shapes, so this
|
|
58
|
+
* accepts what it recognises and ignores the rest rather than refusing to open an old transcript.
|
|
59
|
+
*/
|
|
60
|
+
export declare function readPast(cwd: string, file: string): Promise<PastSession | null>;
|
|
61
|
+
//# sourceMappingURL=history.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../src/web/history.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH,OAAO,EAAa,KAAK,eAAe,EAAE,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE3F,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACf;AAED,0CAA0C;AAC1C,MAAM,MAAM,SAAS,GACjB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,OAAO,CAAA;CAAE,GACzE;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAErC,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,eAAe,CAAC;IACtB,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAClC,0EAA0E;IAC1E,SAAS,EAAE,OAAO,CAAC;CACpB;AAID,sFAAsF;AACtF,eAAO,MAAM,WAAW,MAAM,CAAC;AAE/B,uEAAuE;AACvE,wBAAsB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAkClF;AAmBD;;;;;GAKG;AACH,wBAAsB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAgGrF"}
|