koneck 2.106.0 → 2.107.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.
@@ -0,0 +1,107 @@
1
+ /**
2
+ * A diagnostic report somebody can send you, with nothing in it they would not want to send.
3
+ *
4
+ * Two questions prompted this. "A tiny task took 31 minutes and 1,207,341 tokens — how come?" and
5
+ * "there must be a way to get details of all the KONECK running by people, so we can debug easily
6
+ * and know how heavy their systems are."
7
+ *
8
+ * The first is answerable already: KONECK records a trajectory with a timing for every request and
9
+ * every tool call, and it knew exactly where those 31 minutes went. Nobody could read it, which is
10
+ * the actual gap — the data existed and had no way out of the machine.
11
+ *
12
+ * ## Why this is a file and not a phone-home
13
+ *
14
+ * The second question asks for something that cannot be built the way it was asked. "Details of what
15
+ * they are working on" is their source code, their prompts, and their file paths. A KONECK session
16
+ * transcript routinely contains API keys people paste, database passwords, internal addresses and
17
+ * proprietary code. Uploading that from a published npm package — silently, because nobody would be
18
+ * asked — is not telemetry, it is exfiltration, and it would be true whatever the intention behind
19
+ * it. It would also be the first thing a security review of KONECK found.
20
+ *
21
+ * So: a report the person generates, reads, and chooses to send. It carries what is needed to debug
22
+ * a slow or stuck run and nothing that identifies the work:
23
+ *
24
+ * - what KONECK and the machine are: version, platform, arch, cores, memory, Node
25
+ * - what it was talking to: provider, whether local, the window, and how that was learned
26
+ * - where the time went: model, tools, waiting, and the shape of the turns
27
+ * - which of KONECK's own failure modes fired: lean mode, truncation, empty turns, loops
28
+ * - tool counts by name, and the slowest of each kind
29
+ *
30
+ * and never: prompts, replies, reasoning, file contents, absolute paths, credentials, hostnames,
31
+ * repository names, or a machine identifier. There is nothing here to correlate back to a person,
32
+ * which is deliberate: a report that cannot be traced to somebody is a report they will actually
33
+ * send.
34
+ */
35
+ import type { TrajectoryEvent, TrajectorySummary } from './trajectory.js';
36
+ export interface ReportMachine {
37
+ koneck: string;
38
+ node: string;
39
+ platform: string;
40
+ arch: string;
41
+ cores: number;
42
+ memoryGb: number;
43
+ /** Load average as a share of the cores, which is the number that says "this machine is busy". */
44
+ loadPerCore: number | null;
45
+ }
46
+ export interface ReportRun {
47
+ provider: string;
48
+ /** The model family, not the exact tag: "qwen3-coder" rather than a private deployment name. */
49
+ modelFamily: string;
50
+ local: boolean;
51
+ contextTokens: number | null;
52
+ windowSource: string | null;
53
+ leanMode: boolean;
54
+ truncationSeen: boolean;
55
+ }
56
+ export interface ToolTally {
57
+ name: string;
58
+ calls: number;
59
+ failed: number;
60
+ totalMs: number;
61
+ slowestMs: number;
62
+ }
63
+ export interface Report {
64
+ kind: 'koneck-report';
65
+ version: 1;
66
+ at: string;
67
+ machine: ReportMachine;
68
+ run: ReportRun;
69
+ timing: TrajectorySummary & {
70
+ wallMs: number;
71
+ unaccountedMs: number;
72
+ };
73
+ tools: ToolTally[];
74
+ /** Counts of the conditions KONECK detects itself, which is what makes a run explicable. */
75
+ signals: Record<string, number>;
76
+ }
77
+ export declare function modelFamily(model: string): string;
78
+ /** Machine facts, and none that identify a machine. Deliberately no hostname and no username. */
79
+ export declare function machineFacts(koneckVersion: string): ReportMachine;
80
+ /**
81
+ * Every tool, how often, how long, and how often it failed.
82
+ *
83
+ * The shape that answers "why did a sidebar take half an hour": 140 read_files and 3 write_file is
84
+ * a different story from 12 read_files and 40 execute_command, and neither needs a single line of
85
+ * anybody's code to tell.
86
+ */
87
+ export declare function tallyTools(events: readonly TrajectoryEvent[]): ToolTally[];
88
+ export declare function buildReport(input: {
89
+ koneckVersion: string;
90
+ events: readonly TrajectoryEvent[];
91
+ provider: string;
92
+ model: string;
93
+ local: boolean;
94
+ contextTokens?: number | undefined;
95
+ windowSource?: string | undefined;
96
+ leanMode?: boolean;
97
+ truncationSeen?: boolean;
98
+ signals?: Record<string, number>;
99
+ }): Report;
100
+ /**
101
+ * The report as a person reads it before deciding to send it.
102
+ *
103
+ * Readable on purpose. Somebody asked to send a diagnostic file should be able to see there is
104
+ * nothing of theirs in it, and a wall of JSON does not let them see that.
105
+ */
106
+ export declare function renderReport(r: Report): string;
107
+ //# sourceMappingURL=report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAG1E,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,kGAAkG;IAClG,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,gGAAgG;IAChG,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;IACf,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,QAAQ,EAAE,OAAO,CAAC;IAClB,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,eAAe,CAAC;IACtB,OAAO,EAAE,CAAC,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,aAAa,CAAC;IACvB,GAAG,EAAE,SAAS,CAAC;IACf,MAAM,EAAE,iBAAiB,GAAG;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC;IACtE,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,4FAA4F;IAC5F,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAaD,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIjD;AAED,iGAAiG;AACjG,wBAAgB,YAAY,CAAC,aAAa,EAAE,MAAM,GAAG,aAAa,CAajE;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,SAAS,eAAe,EAAE,GAAG,SAAS,EAAE,CAa1E;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,SAAS,eAAe,EAAE,CAAC;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC,GAAG,MAAM,CAkCT;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CA8C9C"}
package/dist/report.js ADDED
@@ -0,0 +1,174 @@
1
+ /**
2
+ * A diagnostic report somebody can send you, with nothing in it they would not want to send.
3
+ *
4
+ * Two questions prompted this. "A tiny task took 31 minutes and 1,207,341 tokens — how come?" and
5
+ * "there must be a way to get details of all the KONECK running by people, so we can debug easily
6
+ * and know how heavy their systems are."
7
+ *
8
+ * The first is answerable already: KONECK records a trajectory with a timing for every request and
9
+ * every tool call, and it knew exactly where those 31 minutes went. Nobody could read it, which is
10
+ * the actual gap — the data existed and had no way out of the machine.
11
+ *
12
+ * ## Why this is a file and not a phone-home
13
+ *
14
+ * The second question asks for something that cannot be built the way it was asked. "Details of what
15
+ * they are working on" is their source code, their prompts, and their file paths. A KONECK session
16
+ * transcript routinely contains API keys people paste, database passwords, internal addresses and
17
+ * proprietary code. Uploading that from a published npm package — silently, because nobody would be
18
+ * asked — is not telemetry, it is exfiltration, and it would be true whatever the intention behind
19
+ * it. It would also be the first thing a security review of KONECK found.
20
+ *
21
+ * So: a report the person generates, reads, and chooses to send. It carries what is needed to debug
22
+ * a slow or stuck run and nothing that identifies the work:
23
+ *
24
+ * - what KONECK and the machine are: version, platform, arch, cores, memory, Node
25
+ * - what it was talking to: provider, whether local, the window, and how that was learned
26
+ * - where the time went: model, tools, waiting, and the shape of the turns
27
+ * - which of KONECK's own failure modes fired: lean mode, truncation, empty turns, loops
28
+ * - tool counts by name, and the slowest of each kind
29
+ *
30
+ * and never: prompts, replies, reasoning, file contents, absolute paths, credentials, hostnames,
31
+ * repository names, or a machine identifier. There is nothing here to correlate back to a person,
32
+ * which is deliberate: a report that cannot be traced to somebody is a report they will actually
33
+ * send.
34
+ */
35
+ import os from 'os';
36
+ import { summarise } from './trajectory.js';
37
+ /*
38
+ * A model's family, not its name.
39
+ *
40
+ * "qwen3-coder:30b" and "gpt-4o" say something useful about behaviour, and the size suffix does
41
+ * not, so it goes. An org prefix does say something about the company running it — "acme-internal/
42
+ * house-model" — so the part before the slash is dropped and the model's own name kept.
43
+ *
44
+ * What it does NOT do is judge whether a name is public. A private model called "house-model" comes
45
+ * through as "house-model"; only a string with characters no model name has is replaced. Claiming
46
+ * otherwise in this comment would be worse than the behaviour, because somebody would rely on it.
47
+ */
48
+ export function modelFamily(model) {
49
+ const bare = model.trim().toLowerCase().split('/').pop() ?? '';
50
+ const cut = bare.split(':')[0] ?? bare;
51
+ return /^[a-z][a-z0-9.\-]{0,40}$/.test(cut) ? cut : 'unrecognised';
52
+ }
53
+ /** Machine facts, and none that identify a machine. Deliberately no hostname and no username. */
54
+ export function machineFacts(koneckVersion) {
55
+ const cores = os.cpus().length || 1;
56
+ // Windows has no load average, and reports zeros rather than failing.
57
+ const load = os.loadavg()[0] ?? 0;
58
+ return {
59
+ koneck: koneckVersion,
60
+ node: process.version,
61
+ platform: process.platform,
62
+ arch: process.arch,
63
+ cores,
64
+ memoryGb: Math.round(os.totalmem() / 1e9 * 10) / 10,
65
+ loadPerCore: load > 0 ? Math.round(load / cores * 100) / 100 : null,
66
+ };
67
+ }
68
+ /**
69
+ * Every tool, how often, how long, and how often it failed.
70
+ *
71
+ * The shape that answers "why did a sidebar take half an hour": 140 read_files and 3 write_file is
72
+ * a different story from 12 read_files and 40 execute_command, and neither needs a single line of
73
+ * anybody's code to tell.
74
+ */
75
+ export function tallyTools(events) {
76
+ const by = new Map();
77
+ for (const e of events) {
78
+ if (e.t !== 'tool')
79
+ continue;
80
+ const row = by.get(e.name)
81
+ ?? { name: e.name, calls: 0, failed: 0, totalMs: 0, slowestMs: 0 };
82
+ row.calls++;
83
+ if (!e.ok)
84
+ row.failed++;
85
+ row.totalMs += e.ms;
86
+ row.slowestMs = Math.max(row.slowestMs, e.ms);
87
+ by.set(e.name, row);
88
+ }
89
+ return [...by.values()].sort((a, b) => b.totalMs - a.totalMs);
90
+ }
91
+ export function buildReport(input) {
92
+ const timing = summarise(input.events);
93
+ const first = input.events[0]?.at ?? 0;
94
+ const last = input.events[input.events.length - 1]?.at ?? first;
95
+ const wallMs = Math.max(0, last - first);
96
+ return {
97
+ kind: 'koneck-report',
98
+ version: 1,
99
+ at: new Date().toISOString(),
100
+ machine: machineFacts(input.koneckVersion),
101
+ run: {
102
+ provider: input.provider,
103
+ modelFamily: modelFamily(input.model),
104
+ local: input.local,
105
+ contextTokens: input.contextTokens ?? null,
106
+ windowSource: input.windowSource ?? null,
107
+ leanMode: !!input.leanMode,
108
+ truncationSeen: !!input.truncationSeen,
109
+ },
110
+ timing: {
111
+ ...timing,
112
+ wallMs,
113
+ /*
114
+ * The gap, stated rather than left to subtraction.
115
+ *
116
+ * A real session could not be accounted for: 48 minutes of wall clock against 14.5 in the
117
+ * model and 16.1 in tools. Thirteen minutes were invisible, and the only way to find them was
118
+ * to notice they were missing. Naming the gap is what makes somebody go looking.
119
+ */
120
+ unaccountedMs: Math.max(0, wallMs - timing.modelMs - timing.toolMs),
121
+ },
122
+ tools: tallyTools(input.events),
123
+ signals: input.signals ?? {},
124
+ };
125
+ }
126
+ /**
127
+ * The report as a person reads it before deciding to send it.
128
+ *
129
+ * Readable on purpose. Somebody asked to send a diagnostic file should be able to see there is
130
+ * nothing of theirs in it, and a wall of JSON does not let them see that.
131
+ */
132
+ export function renderReport(r) {
133
+ const s = (ms) => ms >= 60_000
134
+ ? `${Math.floor(ms / 60_000)}m ${Math.round(ms % 60_000 / 1000)}s`
135
+ : `${(ms / 1000).toFixed(1)}s`;
136
+ const pc = (ms) => r.timing.wallMs > 0
137
+ ? ` (${Math.round(ms / r.timing.wallMs * 100)}%)` : '';
138
+ const lines = [
139
+ `KONECK ${r.machine.koneck} · ${r.machine.platform}/${r.machine.arch} · `
140
+ + `${r.machine.cores} cores · ${r.machine.memoryGb}GB · Node ${r.machine.node}`
141
+ + (r.machine.loadPerCore !== null ? ` · load ${r.machine.loadPerCore} per core` : ''),
142
+ `${r.run.provider} · ${r.run.modelFamily}${r.run.local ? ' (local)' : ''}`
143
+ + (r.run.contextTokens ? ` · ${(r.run.contextTokens / 1000).toFixed(1)}k window` : '')
144
+ + (r.run.windowSource ? ` (${r.run.windowSource})` : '')
145
+ + (r.run.leanMode ? ' · reduced tool set' : '')
146
+ + (r.run.truncationSeen ? ' · prompt was being truncated' : ''),
147
+ '',
148
+ `Where ${s(r.timing.wallMs)} went:`,
149
+ ` waiting for the model ${s(r.timing.modelMs)}${pc(r.timing.modelMs)} `
150
+ + `across ${r.timing.requests} requests`,
151
+ ` running tools ${s(r.timing.toolMs)}${pc(r.timing.toolMs)}`,
152
+ ` unaccounted ${s(r.timing.unaccountedMs)}${pc(r.timing.unaccountedMs)}`,
153
+ ` ${r.timing.turns} turns · ${r.timing.promptTokens.toLocaleString()} in / `
154
+ + `${r.timing.completionTokens.toLocaleString()} out · `
155
+ + `${r.timing.compactions} compactions · ${r.timing.failedTools} failed tool calls`,
156
+ ];
157
+ if (r.tools.length > 0) {
158
+ lines.push('', 'Tools:');
159
+ for (const t of r.tools.slice(0, 10)) {
160
+ lines.push(` ${t.name.padEnd(18)} ${String(t.calls).padStart(4)} calls `
161
+ + `${s(t.totalMs).padStart(7)} slowest ${s(t.slowestMs)}`
162
+ + (t.failed > 0 ? ` ${t.failed} failed` : ''));
163
+ }
164
+ }
165
+ const fired = Object.entries(r.signals).filter(([, n]) => n > 0);
166
+ if (fired.length > 0) {
167
+ lines.push('', 'What KONECK noticed:');
168
+ for (const [name, n] of fired)
169
+ lines.push(` ${name.padEnd(24)} ${n}`);
170
+ }
171
+ lines.push('', 'Nothing above names a file, a directory, a host or a person, and no prompt, reply or line of', 'code is in it. Read it, then send it if you are happy to.');
172
+ return lines.join('\n');
173
+ }
174
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/web/api.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AASH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAiC/C,eAAO,MAAM,gBAAgB,OAAO,CAAC;AAYrC,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4EAA4E;IAC5E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oFAAoF;IACpF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mCAAmC;IACnC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AA6BD,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B;AAED,wBAAsB,QAAQ,CAC5B,YAAY,EAAE,WAAW,EAAE,OAAO,GAAE,UAAe,GAClD,OAAO,CAAC,SAAS,CAAC,CAosDpB"}
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/web/api.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AASH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAiC/C,eAAO,MAAM,gBAAgB,OAAO,CAAC;AAYrC,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4EAA4E;IAC5E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oFAAoF;IACpF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mCAAmC;IACnC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AA6BD,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B;AAED,wBAAsB,QAAQ,CAC5B,YAAY,EAAE,WAAW,EAAE,OAAO,GAAE,UAAe,GAClD,OAAO,CAAC,SAAS,CAAC,CAotDpB"}
package/dist/web/api.js CHANGED
@@ -573,6 +573,23 @@ export async function startWeb(baseConfigIn, options = {}) {
573
573
  });
574
574
  }
575
575
  // Where the time went. The live session's own record, or a past one's from its file.
576
+ /*
577
+ * A diagnostic report for one session, carrying nothing of the work.
578
+ *
579
+ * The same thing /report writes in the terminal. Both exist because the timings were already
580
+ * recorded and unreadable: asked why a small task took 31 minutes and 1.2 million tokens, the
581
+ * answer was in the trajectory with no way out of the machine.
582
+ */
583
+ if (route === '/api/report' && req.method === 'GET') {
584
+ if (!mayRead)
585
+ return json(res, 401, { error: 'token required' });
586
+ const session = registry.get(url.searchParams.get('session') ?? '');
587
+ if (!session)
588
+ return json(res, 404, { error: 'no such session' });
589
+ const { renderReport } = await import('../report.js');
590
+ const report = session.report();
591
+ return json(res, 200, { report, text: renderReport(report) });
592
+ }
576
593
  if (route === '/api/timing' && req.method === 'GET') {
577
594
  if (!mayRead)
578
595
  return json(res, 401, { error: 'token required' });