@pasko70/pibo 1.9.11 → 1.9.13

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 (111) hide show
  1. package/README.md +183 -183
  2. package/context/codex-base-prompt.md +148 -148
  3. package/context/compute-worker.md +23 -23
  4. package/context/pibo-compaction-prompt.md +100 -100
  5. package/context/pibo-native-tooling.md +18 -18
  6. package/context/pibo-system-prompt.md +77 -77
  7. package/dist/apps/chat/agent-store.js +248 -248
  8. package/dist/apps/chat/data/project-service.js +168 -168
  9. package/dist/apps/chat/data/read-state-service.js +18 -18
  10. package/dist/apps/chat/data/session-query-service.js +25 -25
  11. package/dist/apps/chat/data/timeline-query-service.js +25 -14
  12. package/dist/apps/chat/static-assets.js +854 -854
  13. package/dist/apps/chat/trace.js +2 -0
  14. package/dist/apps/chat/web-app.js +7 -0
  15. package/dist/apps/chat/workflow-persistence.js +255 -255
  16. package/dist/apps/chat-ui/index.html +16 -16
  17. package/dist/apps/chat-ui/manifest.webmanifest +25 -25
  18. package/dist/apps/chat-ui/sw.js +47 -47
  19. package/dist/apps/chat-vscode-web/index.html +12 -12
  20. package/dist/apps/cli-ui/cliSessionsCommand.js +23 -23
  21. package/dist/apps/context-files-ui/index.html +11 -11
  22. package/dist/apps/vscode-artifacts/latest.vsix +0 -0
  23. package/dist/apps/vscode-artifacts/pibo-vscode-ext-1.9.13.vsix +0 -0
  24. package/dist/cli.js +39 -39
  25. package/dist/compute/cli.js +54 -54
  26. package/dist/cron/cli.js +15 -15
  27. package/dist/cron/store.js +49 -49
  28. package/dist/data/cli.js +23 -23
  29. package/dist/data/event-log.js +23 -23
  30. package/dist/data/ingest-service.js +7 -0
  31. package/dist/data/message-store.js +31 -20
  32. package/dist/data/navigation-store.js +9 -9
  33. package/dist/data/observation-store.js +4 -4
  34. package/dist/data/payload-store.js +17 -17
  35. package/dist/data/schema.js +433 -431
  36. package/dist/data/session-store.js +4 -4
  37. package/dist/data/telemetry-queries.js +54 -54
  38. package/dist/data/telemetry.js +197 -197
  39. package/dist/debug/events.js +12 -12
  40. package/dist/debug/failures.js +6 -6
  41. package/dist/debug/index.js +227 -227
  42. package/dist/debug/messages.js +6 -6
  43. package/dist/debug/pty.js +124 -124
  44. package/dist/debug/session.js +29 -29
  45. package/dist/debug/tools.js +5 -5
  46. package/dist/debug/web-snapshot-browser-scripts.js +294 -294
  47. package/dist/debug/web-streaming-browser-library.js +925 -925
  48. package/dist/debug/web-streaming-browser-scripts.js +232 -232
  49. package/dist/debug/web-streaming-provider-telemetry.js +4 -4
  50. package/dist/debug/web.js +93 -93
  51. package/dist/gateway/cli.js +19 -19
  52. package/dist/mcp/config-command.js +53 -53
  53. package/dist/mcp/index.js +21 -21
  54. package/dist/mcp/registry.js +11 -11
  55. package/dist/pi-packages/cli.js +11 -11
  56. package/dist/plugins/context-files-store.js +110 -110
  57. package/dist/plugins/context-files.js +4 -4
  58. package/dist/ralph/cli.js +18 -18
  59. package/dist/ralph/templates.js +140 -140
  60. package/dist/reliability/store.js +226 -226
  61. package/dist/resources/lifecycle.js +4 -6
  62. package/dist/resources/reaper-state.js +30 -3
  63. package/dist/resources/reaper.js +43 -15
  64. package/dist/sessions/pibo-data-store.js +16 -16
  65. package/dist/sessions/sqlite-store.js +53 -53
  66. package/dist/setup/cli.js +58 -58
  67. package/dist/shared/trace-engine.js +3 -2
  68. package/dist/shared/trace-event-projection.js +26 -0
  69. package/dist/tools/agent-browser-wrapper.js +80 -80
  70. package/dist/tools/browser-use-cdp.js +12 -12
  71. package/dist/tools/browser-use-wrapper.js +762 -762
  72. package/dist/tools/guides.js +538 -538
  73. package/dist/tools/index.js +99 -99
  74. package/dist/tools/runtime/node-worker-source.js +205 -205
  75. package/dist/tools/runtime/python-worker-source.js +177 -177
  76. package/dist/vscode/cli.js +9 -9
  77. package/dist/web-annotations/cdp.js +900 -900
  78. package/dist/web-annotations/store.js +96 -96
  79. package/docs/README.md +23 -23
  80. package/docs/ops/install-developer-host.md +112 -112
  81. package/docs/ops/install-user-host.md +96 -96
  82. package/docs/ops/upgrade-user-to-developer-host.md +69 -69
  83. package/docs/ops/vscode-extension-release.md +160 -160
  84. package/package.json +95 -95
  85. package/skills/builtin/graphify/SKILL.md +52 -52
  86. package/skills/builtin/pi-agent-harness/SKILL.md +319 -319
  87. package/skills/builtin/pi-agent-harness/agents/openai.yaml +4 -4
  88. package/skills/builtin/pibo-docker-system/SKILL.md +170 -170
  89. package/skills/builtin/pibo-spec-writing/SKILL.md +330 -330
  90. package/skills/builtin/prd/SKILL.md +143 -143
  91. package/skills/builtin/ralph-loop/SKILL.md +359 -359
  92. package/skills/builtin/ralph-prd-json/SKILL.md +123 -123
  93. package/skills/builtin/skill-creator/LICENSE.txt +201 -201
  94. package/skills/builtin/skill-creator/SKILL.md +513 -513
  95. package/skills/builtin/skill-creator/agents/analyzer.md +274 -274
  96. package/skills/builtin/skill-creator/agents/comparator.md +202 -202
  97. package/skills/builtin/skill-creator/agents/grader.md +223 -223
  98. package/skills/builtin/skill-creator/assets/eval_review.html +146 -146
  99. package/skills/builtin/skill-creator/eval-viewer/generate_review.py +471 -471
  100. package/skills/builtin/skill-creator/eval-viewer/viewer.html +1325 -1325
  101. package/skills/builtin/skill-creator/references/schemas.md +430 -430
  102. package/skills/builtin/skill-creator/scripts/aggregate_benchmark.py +401 -401
  103. package/skills/builtin/skill-creator/scripts/generate_report.py +326 -326
  104. package/skills/builtin/skill-creator/scripts/improve_description.py +247 -247
  105. package/skills/builtin/skill-creator/scripts/package_skill.py +136 -136
  106. package/skills/builtin/skill-creator/scripts/quick_validate.py +102 -102
  107. package/skills/builtin/skill-creator/scripts/run_eval.py +310 -310
  108. package/skills/builtin/skill-creator/scripts/run_loop.py +328 -328
  109. package/skills/builtin/skill-creator/scripts/utils.py +47 -47
  110. package/skills/builtin/web-annotations/SKILL.md +93 -93
  111. package/src/mcp/LICENSE.mcp-cli +21 -21
@@ -1,242 +1,242 @@
1
1
  import { browserStreamingBenchmarkLibrary } from "./web-streaming-browser-library.js";
2
2
  export function streamingBenchmarkEventSourceProbeScript() {
3
- return String.raw `
4
- (() => {
5
- if (window.__piboStreamingBenchmarkEventSourceProbeInstalled || typeof window.EventSource !== 'function') return;
6
- const OriginalEventSource = window.EventSource;
7
- const probe = {
8
- createdAt: new Date().toISOString(),
9
- openCount: 0,
10
- errorCount: 0,
11
- closeCount: 0,
12
- forcedCloseCount: 0,
13
- textDropRequested: false,
14
- textDropDurationMs: undefined,
15
- textDropUntil: 0,
16
- textDropCount: 0,
17
- textDropTextEventCount: 0,
18
- events: [],
19
- connections: [],
20
- };
21
- Object.defineProperty(probe, '_instances', { value: [], enumerable: false, configurable: false });
22
- function at() { return typeof performance === 'undefined' ? Date.now() : performance.now(); }
23
- function isChatEventsUrl(url) { return String(url || '').includes('/api/chat/events'); }
24
- function pushConnection(kind, info, extra) {
25
- probe.connections.push({ t: at(), kind, url: info.url, ...(extra || {}) });
26
- if (probe.connections.length > 200) probe.connections.splice(0, probe.connections.length - 200);
27
- }
28
- function WrappedEventSource(url, init) {
29
- const events = new OriginalEventSource(url, init);
30
- const info = { url: String(url), createdAt: at(), closed: false, forcedClosing: false };
31
- probe._instances.push({ events, info });
32
- events.addEventListener('open', () => {
33
- probe.openCount += 1;
34
- pushConnection('open', info, { readyState: events.readyState });
35
- });
36
- events.addEventListener('error', () => {
37
- probe.errorCount += 1;
38
- pushConnection('error', info, { readyState: events.readyState });
39
- });
40
- events.addEventListener('pibo', (message) => {
41
- let payload;
42
- try { payload = JSON.parse(message.data); } catch {}
43
- const type = payload && typeof payload.type === 'string' ? payload.type : undefined;
44
- const record = {
45
- t: at(),
46
- url: info.url,
47
- lastEventId: message.lastEventId || '',
48
- type: typeof type === 'string' ? type : undefined,
49
- liveReplayId: payload && typeof payload.liveReplayId === 'number' && Number.isFinite(payload.liveReplayId) ? payload.liveReplayId : undefined,
50
- liveReplayReplayed: payload && payload.liveReplay && typeof payload.liveReplay.replayed === 'number' && Number.isFinite(payload.liveReplay.replayed) ? payload.liveReplay.replayed : undefined,
51
- liveReplayMissed: Boolean(payload && payload.liveReplay && payload.liveReplay.missed === true),
52
- liveReplayEvictedBefore: payload && payload.liveReplay && typeof payload.liveReplay.evictedBefore === 'number' && Number.isFinite(payload.liveReplay.evictedBefore) ? payload.liveReplay.evictedBefore : undefined,
53
- liveReplayRequestedAfter: payload && payload.liveReplay && typeof payload.liveReplay.requestedAfter === 'number' && Number.isFinite(payload.liveReplay.requestedAfter) ? payload.liveReplay.requestedAfter : undefined,
54
- liveReplayNewestAvailable: payload && payload.liveReplay && typeof payload.liveReplay.newestAvailable === 'number' && Number.isFinite(payload.liveReplay.newestAvailable) ? payload.liveReplay.newestAvailable : undefined,
55
- };
56
- probe.events.push(record);
57
- if (probe.events.length > 1000) probe.events.splice(0, probe.events.length - 1000);
58
- });
59
- const originalClose = events.close.bind(events);
60
- events.close = () => {
61
- if (!info.closed) {
62
- info.closed = true;
63
- probe.closeCount += 1;
64
- pushConnection('close', info, { forced: Boolean(info.forcedClosing), readyState: events.readyState });
65
- }
66
- return originalClose();
67
- };
68
- return events;
69
- }
70
- WrappedEventSource.prototype = OriginalEventSource.prototype;
71
- Object.setPrototypeOf(WrappedEventSource, OriginalEventSource);
72
- window.EventSource = WrappedEventSource;
73
- window.__piboStreamingBenchmarkMarkTextDropRequested = (durationMs) => {
74
- const duration = Math.max(0, Number(durationMs || 0));
75
- probe.textDropRequested = true;
76
- probe.textDropDurationMs = duration;
77
- probe.textDropUntil = at() + duration;
78
- probe.textDropCount = 0;
79
- probe.textDropTextEventCount = 0;
80
- return { durationMs: duration };
81
- };
82
- window.__piboStreamingBenchmarkForceReconnect = () => {
83
- let closed = 0;
84
- for (const entry of probe._instances) {
85
- if (!entry || !entry.events || !isChatEventsUrl(entry.info && entry.info.url)) continue;
86
- if (entry.events.readyState === 2) continue;
87
- entry.info.forcedClosing = true;
88
- probe.forcedCloseCount += 1;
89
- entry.events.close();
90
- closed += 1;
91
- }
92
- window.dispatchEvent(new Event('online'));
93
- window.dispatchEvent(new Event('focus'));
94
- return closed;
95
- };
96
- window.__piboStreamingBenchmarkEventSourceProbe = probe;
97
- window.__piboStreamingBenchmarkEventSourceProbeInstalled = true;
98
- })();
3
+ return String.raw `
4
+ (() => {
5
+ if (window.__piboStreamingBenchmarkEventSourceProbeInstalled || typeof window.EventSource !== 'function') return;
6
+ const OriginalEventSource = window.EventSource;
7
+ const probe = {
8
+ createdAt: new Date().toISOString(),
9
+ openCount: 0,
10
+ errorCount: 0,
11
+ closeCount: 0,
12
+ forcedCloseCount: 0,
13
+ textDropRequested: false,
14
+ textDropDurationMs: undefined,
15
+ textDropUntil: 0,
16
+ textDropCount: 0,
17
+ textDropTextEventCount: 0,
18
+ events: [],
19
+ connections: [],
20
+ };
21
+ Object.defineProperty(probe, '_instances', { value: [], enumerable: false, configurable: false });
22
+ function at() { return typeof performance === 'undefined' ? Date.now() : performance.now(); }
23
+ function isChatEventsUrl(url) { return String(url || '').includes('/api/chat/events'); }
24
+ function pushConnection(kind, info, extra) {
25
+ probe.connections.push({ t: at(), kind, url: info.url, ...(extra || {}) });
26
+ if (probe.connections.length > 200) probe.connections.splice(0, probe.connections.length - 200);
27
+ }
28
+ function WrappedEventSource(url, init) {
29
+ const events = new OriginalEventSource(url, init);
30
+ const info = { url: String(url), createdAt: at(), closed: false, forcedClosing: false };
31
+ probe._instances.push({ events, info });
32
+ events.addEventListener('open', () => {
33
+ probe.openCount += 1;
34
+ pushConnection('open', info, { readyState: events.readyState });
35
+ });
36
+ events.addEventListener('error', () => {
37
+ probe.errorCount += 1;
38
+ pushConnection('error', info, { readyState: events.readyState });
39
+ });
40
+ events.addEventListener('pibo', (message) => {
41
+ let payload;
42
+ try { payload = JSON.parse(message.data); } catch {}
43
+ const type = payload && typeof payload.type === 'string' ? payload.type : undefined;
44
+ const record = {
45
+ t: at(),
46
+ url: info.url,
47
+ lastEventId: message.lastEventId || '',
48
+ type: typeof type === 'string' ? type : undefined,
49
+ liveReplayId: payload && typeof payload.liveReplayId === 'number' && Number.isFinite(payload.liveReplayId) ? payload.liveReplayId : undefined,
50
+ liveReplayReplayed: payload && payload.liveReplay && typeof payload.liveReplay.replayed === 'number' && Number.isFinite(payload.liveReplay.replayed) ? payload.liveReplay.replayed : undefined,
51
+ liveReplayMissed: Boolean(payload && payload.liveReplay && payload.liveReplay.missed === true),
52
+ liveReplayEvictedBefore: payload && payload.liveReplay && typeof payload.liveReplay.evictedBefore === 'number' && Number.isFinite(payload.liveReplay.evictedBefore) ? payload.liveReplay.evictedBefore : undefined,
53
+ liveReplayRequestedAfter: payload && payload.liveReplay && typeof payload.liveReplay.requestedAfter === 'number' && Number.isFinite(payload.liveReplay.requestedAfter) ? payload.liveReplay.requestedAfter : undefined,
54
+ liveReplayNewestAvailable: payload && payload.liveReplay && typeof payload.liveReplay.newestAvailable === 'number' && Number.isFinite(payload.liveReplay.newestAvailable) ? payload.liveReplay.newestAvailable : undefined,
55
+ };
56
+ probe.events.push(record);
57
+ if (probe.events.length > 1000) probe.events.splice(0, probe.events.length - 1000);
58
+ });
59
+ const originalClose = events.close.bind(events);
60
+ events.close = () => {
61
+ if (!info.closed) {
62
+ info.closed = true;
63
+ probe.closeCount += 1;
64
+ pushConnection('close', info, { forced: Boolean(info.forcedClosing), readyState: events.readyState });
65
+ }
66
+ return originalClose();
67
+ };
68
+ return events;
69
+ }
70
+ WrappedEventSource.prototype = OriginalEventSource.prototype;
71
+ Object.setPrototypeOf(WrappedEventSource, OriginalEventSource);
72
+ window.EventSource = WrappedEventSource;
73
+ window.__piboStreamingBenchmarkMarkTextDropRequested = (durationMs) => {
74
+ const duration = Math.max(0, Number(durationMs || 0));
75
+ probe.textDropRequested = true;
76
+ probe.textDropDurationMs = duration;
77
+ probe.textDropUntil = at() + duration;
78
+ probe.textDropCount = 0;
79
+ probe.textDropTextEventCount = 0;
80
+ return { durationMs: duration };
81
+ };
82
+ window.__piboStreamingBenchmarkForceReconnect = () => {
83
+ let closed = 0;
84
+ for (const entry of probe._instances) {
85
+ if (!entry || !entry.events || !isChatEventsUrl(entry.info && entry.info.url)) continue;
86
+ if (entry.events.readyState === 2) continue;
87
+ entry.info.forcedClosing = true;
88
+ probe.forcedCloseCount += 1;
89
+ entry.events.close();
90
+ closed += 1;
91
+ }
92
+ window.dispatchEvent(new Event('online'));
93
+ window.dispatchEvent(new Event('focus'));
94
+ return closed;
95
+ };
96
+ window.__piboStreamingBenchmarkEventSourceProbe = probe;
97
+ window.__piboStreamingBenchmarkEventSourceProbeInstalled = true;
98
+ })();
99
99
  `;
100
100
  }
101
101
  export function streamingBenchmarkFixtureHtml(fixtureProfile, fixtureMix) {
102
- return `<!doctype html>
103
- <html>
104
- <head>
105
- <meta charset="utf-8">
106
- <title>Streaming Benchmark Fixture</title>
107
- <style>body{font-family:system-ui,sans-serif;margin:24px;line-height:1.4} [data-pibo-component]{white-space:pre-wrap}</style>
108
- </head>
109
- <body data-pibo-debug="chat-app">
110
- <h1>Streaming Benchmark Fixture</h1>
111
- <div data-pibo-component="MarkdownRendererHost" data-pibo-markdown-kind="assistant-message">hello</div>
112
- <script>
113
- (() => {
114
- function nowIso() { return new Date().toISOString(); }
115
- const target = document.querySelector('[data-pibo-component="MarkdownRendererHost"]');
116
- const textDeltas = [' a', ' b', ' c', ' d', ' e', ' f', ' g', ' h', ' i', ' j', ' k', ' l'];
117
- const markdownDeltas = [' **a**', ' **b**', ' **c**', ' **d**', ' **e**', ' **f**', ' **g**', ' **h**', ' **i**', ' **j**', ' **k**', ' **l**'];
118
- const gfmMarkdownDeltas = [' ~~a~~', ' ~~b~~', ' ~~c~~', ' ~~d~~', ' ~~e~~', ' ~~f~~', ' ~~g~~', ' ~~h~~', ' ~~i~~', ' ~~j~~', ' ~~k~~', ' ~~l~~'];
119
- const gfmTaskMarkdownDeltas = ['- [ ] [_**a**_](https://e.co/a)', ' [_**b**_](https://e.co/b)', ' [_**c**_](https://e.co/c)', ' [_**d**_](https://e.co/d)', ' [_**e**_](https://e.co/e)', ' [_**f**_](https://e.co/f)', ' [_**g**_](https://e.co/g)', ' [_**h**_](https://e.co/h)', ' [_**i**_](https://e.co/i)', ' [_**j**_](https://e.co/j)', ' [_**k**_](https://e.co/k)', ' [_**l**_](https://e.co/l)'];
120
- const gfmFullMarkdownDeltas = ['- [ ] [_~~a~~_](https://e.co/a)', ' [_~~b~~_](https://e.co/b)', ' [_~~c~~_](https://e.co/c)', ' [_~~d~~_](https://e.co/d)', ' [_~~e~~_](https://e.co/e)', ' [_~~f~~_](https://e.co/f)', ' [_~~g~~_](https://e.co/g)', ' [_~~h~~_](https://e.co/h)', ' [_~~i~~_](https://e.co/i)', ' [_~~j~~_](https://e.co/j)', ' [_~~k~~_](https://e.co/k)', ' [_~~l~~_](https://e.co/l)'];
121
- const cadenceMs = 100;
122
- const profile = ${JSON.stringify(fixtureProfile)};
123
- const mix = ${JSON.stringify(fixtureMix)};
124
- const deltas = mix === 'markdown' ? markdownDeltas : (mix === 'gfm-markdown' ? gfmMarkdownDeltas : (mix === 'gfm-task-markdown' ? gfmTaskMarkdownDeltas : (mix === 'gfm-full-markdown' ? gfmFullMarkdownDeltas : textDeltas)));
125
- const reasoningDeltas = mix === 'reasoning-text' ? [' think', ' plan', ' check', ' answer'] : [];
126
- const scheduleMs = buildSchedule(deltas.length, cadenceMs, profile);
127
- const reasoningScheduleMs = reasoningDeltas.map((_, index) => Math.max(10, Math.round((index + 1) * cadenceMs / 2)));
128
- let timers = [];
129
- function buildSchedule(count, cadence, timingProfile) {
130
- const delays = [];
131
- let elapsed = 0;
132
- for (let index = 0; index < count; index += 1) {
133
- let gap = cadence;
134
- if (timingProfile === 'jitter') {
135
- const jitter = [-30, 50, -20, 30, -40, 60, -10, 40, -50, 70, -20, 30][index % 12];
136
- gap = Math.max(10, cadence + jitter);
137
- } else if (timingProfile === 'burst') {
138
- gap = index > 0 && index % 3 !== 0 ? Math.max(10, Math.round(cadence / 5)) : Math.max(cadence, Math.round(cadence * 2.5));
139
- } else if (timingProfile === 'batch') {
140
- gap = index % 4 === 0 ? Math.max(cadence, Math.round(cadence * 3)) : 0;
141
- }
142
- elapsed += gap;
143
- delays.push(elapsed);
144
- }
145
- return delays;
146
- }
147
- function snapshot() {
148
- const now = nowIso();
149
- return {
150
- startedAt: now,
151
- updatedAt: now,
152
- eventCount: 0,
153
- textDeltaCount: 0,
154
- textDeltaBytes: 0,
155
- reasoningDeltaCount: 0,
156
- reasoningDeltaBytes: 0,
157
- enqueueCount: 0,
158
- flushCount: 0,
159
- flushedEventCount: 0,
160
- overlayUpdateCount: 0,
161
- overlayEventCount: 0,
162
- traceRefreshStartedCount: 0,
163
- traceRefreshCompletedCount: 0,
164
- traceRefreshFailedCount: 0,
165
- traceBaseUpdateCount: 0,
166
- traceBaseOutputLength: 0,
167
- currentOutputLength: target.textContent.length,
168
- lastDurableCursor: undefined,
169
- lastTransientLiveId: 'live:-1',
170
- };
171
- }
172
- window.__piboStreamingDebugReset = () => {
173
- for (const timer of timers) clearTimeout(timer);
174
- timers = [];
175
- target.textContent = 'hello';
176
- window.__piboStreamingDebug = snapshot();
177
- return window.__piboStreamingDebug;
178
- };
179
- window.__piboStreamingFixtureConfig = { deltaCount: deltas.length, reasoningDeltaCount: reasoningDeltas.length, cadenceMs, profile, mix, scheduleMs, reasoningScheduleMs, textBytes: deltas.join('').length, reasoningBytes: reasoningDeltas.join('').length };
180
- window.__piboStreamingFixtureStart = () => {
181
- window.__piboStreamingDebugReset();
182
- reasoningDeltas.forEach((delta, index) => {
183
- timers.push(setTimeout(() => {
184
- const debug = window.__piboStreamingDebug;
185
- const at = nowIso();
186
- debug.eventCount += 1;
187
- debug.firstEventAt ??= at;
188
- debug.firstReasoningDeltaAt ??= at;
189
- debug.reasoningDeltaCount += 1;
190
- debug.reasoningDeltaBytes += delta.length;
191
- debug.firstEnqueueAt ??= at;
192
- debug.enqueueCount += 1;
193
- debug.firstFlushAt ??= at;
194
- debug.flushCount += 1;
195
- debug.flushedEventCount += 1;
196
- debug.firstOverlayUpdateAt ??= at;
197
- debug.overlayUpdateCount += 1;
198
- debug.overlayEventCount += 1;
199
- debug.lastEventAt = at;
200
- debug.updatedAt = at;
201
- debug.lastTransientLiveId = 'live:reasoning-' + index;
202
- }, reasoningScheduleMs[index]));
203
- });
204
- deltas.forEach((delta, index) => {
205
- timers.push(setTimeout(() => {
206
- target.textContent += delta;
207
- const debug = window.__piboStreamingDebug;
208
- const at = nowIso();
209
- debug.eventCount += 1;
210
- debug.firstEventAt ??= at;
211
- debug.firstTextDeltaAt ??= at;
212
- debug.textDeltaCount += 1;
213
- debug.textDeltaBytes += delta.length;
214
- debug.firstEnqueueAt ??= at;
215
- debug.enqueueCount += 1;
216
- debug.firstFlushAt ??= at;
217
- debug.flushCount += 1;
218
- debug.flushedEventCount += 1;
219
- debug.firstOverlayUpdateAt ??= at;
220
- debug.overlayUpdateCount += 1;
221
- debug.overlayEventCount += 1;
222
- debug.currentOutputLength = target.textContent.length;
223
- debug.lastEventAt = at;
224
- debug.updatedAt = at;
225
- debug.lastTransientLiveId = 'live:' + index;
226
- }, scheduleMs[index]));
227
- });
228
- return window.__piboStreamingFixtureConfig;
229
- };
230
- window.__piboStreamingDebugReset();
231
- })();
232
- </script>
233
- </body>
102
+ return `<!doctype html>
103
+ <html>
104
+ <head>
105
+ <meta charset="utf-8">
106
+ <title>Streaming Benchmark Fixture</title>
107
+ <style>body{font-family:system-ui,sans-serif;margin:24px;line-height:1.4} [data-pibo-component]{white-space:pre-wrap}</style>
108
+ </head>
109
+ <body data-pibo-debug="chat-app">
110
+ <h1>Streaming Benchmark Fixture</h1>
111
+ <div data-pibo-component="MarkdownRendererHost" data-pibo-markdown-kind="assistant-message">hello</div>
112
+ <script>
113
+ (() => {
114
+ function nowIso() { return new Date().toISOString(); }
115
+ const target = document.querySelector('[data-pibo-component="MarkdownRendererHost"]');
116
+ const textDeltas = [' a', ' b', ' c', ' d', ' e', ' f', ' g', ' h', ' i', ' j', ' k', ' l'];
117
+ const markdownDeltas = [' **a**', ' **b**', ' **c**', ' **d**', ' **e**', ' **f**', ' **g**', ' **h**', ' **i**', ' **j**', ' **k**', ' **l**'];
118
+ const gfmMarkdownDeltas = [' ~~a~~', ' ~~b~~', ' ~~c~~', ' ~~d~~', ' ~~e~~', ' ~~f~~', ' ~~g~~', ' ~~h~~', ' ~~i~~', ' ~~j~~', ' ~~k~~', ' ~~l~~'];
119
+ const gfmTaskMarkdownDeltas = ['- [ ] [_**a**_](https://e.co/a)', ' [_**b**_](https://e.co/b)', ' [_**c**_](https://e.co/c)', ' [_**d**_](https://e.co/d)', ' [_**e**_](https://e.co/e)', ' [_**f**_](https://e.co/f)', ' [_**g**_](https://e.co/g)', ' [_**h**_](https://e.co/h)', ' [_**i**_](https://e.co/i)', ' [_**j**_](https://e.co/j)', ' [_**k**_](https://e.co/k)', ' [_**l**_](https://e.co/l)'];
120
+ const gfmFullMarkdownDeltas = ['- [ ] [_~~a~~_](https://e.co/a)', ' [_~~b~~_](https://e.co/b)', ' [_~~c~~_](https://e.co/c)', ' [_~~d~~_](https://e.co/d)', ' [_~~e~~_](https://e.co/e)', ' [_~~f~~_](https://e.co/f)', ' [_~~g~~_](https://e.co/g)', ' [_~~h~~_](https://e.co/h)', ' [_~~i~~_](https://e.co/i)', ' [_~~j~~_](https://e.co/j)', ' [_~~k~~_](https://e.co/k)', ' [_~~l~~_](https://e.co/l)'];
121
+ const cadenceMs = 100;
122
+ const profile = ${JSON.stringify(fixtureProfile)};
123
+ const mix = ${JSON.stringify(fixtureMix)};
124
+ const deltas = mix === 'markdown' ? markdownDeltas : (mix === 'gfm-markdown' ? gfmMarkdownDeltas : (mix === 'gfm-task-markdown' ? gfmTaskMarkdownDeltas : (mix === 'gfm-full-markdown' ? gfmFullMarkdownDeltas : textDeltas)));
125
+ const reasoningDeltas = mix === 'reasoning-text' ? [' think', ' plan', ' check', ' answer'] : [];
126
+ const scheduleMs = buildSchedule(deltas.length, cadenceMs, profile);
127
+ const reasoningScheduleMs = reasoningDeltas.map((_, index) => Math.max(10, Math.round((index + 1) * cadenceMs / 2)));
128
+ let timers = [];
129
+ function buildSchedule(count, cadence, timingProfile) {
130
+ const delays = [];
131
+ let elapsed = 0;
132
+ for (let index = 0; index < count; index += 1) {
133
+ let gap = cadence;
134
+ if (timingProfile === 'jitter') {
135
+ const jitter = [-30, 50, -20, 30, -40, 60, -10, 40, -50, 70, -20, 30][index % 12];
136
+ gap = Math.max(10, cadence + jitter);
137
+ } else if (timingProfile === 'burst') {
138
+ gap = index > 0 && index % 3 !== 0 ? Math.max(10, Math.round(cadence / 5)) : Math.max(cadence, Math.round(cadence * 2.5));
139
+ } else if (timingProfile === 'batch') {
140
+ gap = index % 4 === 0 ? Math.max(cadence, Math.round(cadence * 3)) : 0;
141
+ }
142
+ elapsed += gap;
143
+ delays.push(elapsed);
144
+ }
145
+ return delays;
146
+ }
147
+ function snapshot() {
148
+ const now = nowIso();
149
+ return {
150
+ startedAt: now,
151
+ updatedAt: now,
152
+ eventCount: 0,
153
+ textDeltaCount: 0,
154
+ textDeltaBytes: 0,
155
+ reasoningDeltaCount: 0,
156
+ reasoningDeltaBytes: 0,
157
+ enqueueCount: 0,
158
+ flushCount: 0,
159
+ flushedEventCount: 0,
160
+ overlayUpdateCount: 0,
161
+ overlayEventCount: 0,
162
+ traceRefreshStartedCount: 0,
163
+ traceRefreshCompletedCount: 0,
164
+ traceRefreshFailedCount: 0,
165
+ traceBaseUpdateCount: 0,
166
+ traceBaseOutputLength: 0,
167
+ currentOutputLength: target.textContent.length,
168
+ lastDurableCursor: undefined,
169
+ lastTransientLiveId: 'live:-1',
170
+ };
171
+ }
172
+ window.__piboStreamingDebugReset = () => {
173
+ for (const timer of timers) clearTimeout(timer);
174
+ timers = [];
175
+ target.textContent = 'hello';
176
+ window.__piboStreamingDebug = snapshot();
177
+ return window.__piboStreamingDebug;
178
+ };
179
+ window.__piboStreamingFixtureConfig = { deltaCount: deltas.length, reasoningDeltaCount: reasoningDeltas.length, cadenceMs, profile, mix, scheduleMs, reasoningScheduleMs, textBytes: deltas.join('').length, reasoningBytes: reasoningDeltas.join('').length };
180
+ window.__piboStreamingFixtureStart = () => {
181
+ window.__piboStreamingDebugReset();
182
+ reasoningDeltas.forEach((delta, index) => {
183
+ timers.push(setTimeout(() => {
184
+ const debug = window.__piboStreamingDebug;
185
+ const at = nowIso();
186
+ debug.eventCount += 1;
187
+ debug.firstEventAt ??= at;
188
+ debug.firstReasoningDeltaAt ??= at;
189
+ debug.reasoningDeltaCount += 1;
190
+ debug.reasoningDeltaBytes += delta.length;
191
+ debug.firstEnqueueAt ??= at;
192
+ debug.enqueueCount += 1;
193
+ debug.firstFlushAt ??= at;
194
+ debug.flushCount += 1;
195
+ debug.flushedEventCount += 1;
196
+ debug.firstOverlayUpdateAt ??= at;
197
+ debug.overlayUpdateCount += 1;
198
+ debug.overlayEventCount += 1;
199
+ debug.lastEventAt = at;
200
+ debug.updatedAt = at;
201
+ debug.lastTransientLiveId = 'live:reasoning-' + index;
202
+ }, reasoningScheduleMs[index]));
203
+ });
204
+ deltas.forEach((delta, index) => {
205
+ timers.push(setTimeout(() => {
206
+ target.textContent += delta;
207
+ const debug = window.__piboStreamingDebug;
208
+ const at = nowIso();
209
+ debug.eventCount += 1;
210
+ debug.firstEventAt ??= at;
211
+ debug.firstTextDeltaAt ??= at;
212
+ debug.textDeltaCount += 1;
213
+ debug.textDeltaBytes += delta.length;
214
+ debug.firstEnqueueAt ??= at;
215
+ debug.enqueueCount += 1;
216
+ debug.firstFlushAt ??= at;
217
+ debug.flushCount += 1;
218
+ debug.flushedEventCount += 1;
219
+ debug.firstOverlayUpdateAt ??= at;
220
+ debug.overlayUpdateCount += 1;
221
+ debug.overlayEventCount += 1;
222
+ debug.currentOutputLength = target.textContent.length;
223
+ debug.lastEventAt = at;
224
+ debug.updatedAt = at;
225
+ debug.lastTransientLiveId = 'live:' + index;
226
+ }, scheduleMs[index]));
227
+ });
228
+ return window.__piboStreamingFixtureConfig;
229
+ };
230
+ window.__piboStreamingDebugReset();
231
+ })();
232
+ </script>
233
+ </body>
234
234
  </html>`;
235
235
  }
236
236
  export function buildStreamingBenchmarkExpression(durationMs, input = {}) {
237
- return `(async () => {
238
- const options = ${JSON.stringify({ durationMs, startFixture: Boolean(input.startFixture), startBackendFixture: Boolean(input.startBackendFixture), fixtureProfile: input.fixtureProfile ?? "steady", fixtureMix: input.fixtureMix ?? "text", fixturePreludeMessages: input.fixturePreludeMessages ?? 0, simulateReconnect: Boolean(input.simulateReconnect), simulateTraceCatchup: Boolean(input.simulateTraceCatchup), simulateOverlayDrop: Boolean(input.simulateOverlayDrop), reconnectAtMs: input.simulateReconnect ? 325 : undefined, traceCatchupDropMs: input.simulateTraceCatchup ? 1300 : undefined })};
239
- ${browserStreamingBenchmarkLibrary()}
240
- return await runStreamingBenchmark(options);
237
+ return `(async () => {
238
+ const options = ${JSON.stringify({ durationMs, startFixture: Boolean(input.startFixture), startBackendFixture: Boolean(input.startBackendFixture), fixtureProfile: input.fixtureProfile ?? "steady", fixtureMix: input.fixtureMix ?? "text", fixturePreludeMessages: input.fixturePreludeMessages ?? 0, simulateReconnect: Boolean(input.simulateReconnect), simulateTraceCatchup: Boolean(input.simulateTraceCatchup), simulateOverlayDrop: Boolean(input.simulateOverlayDrop), reconnectAtMs: input.simulateReconnect ? 325 : undefined, traceCatchupDropMs: input.simulateTraceCatchup ? 1300 : undefined })};
239
+ ${browserStreamingBenchmarkLibrary()}
240
+ return await runStreamingBenchmark(options);
241
241
  })()`;
242
242
  }
@@ -41,10 +41,10 @@ export function summarizeStreamingProviderTelemetry(input) {
41
41
  };
42
42
  }
43
43
  export async function collectStreamingProviderTelemetryFromSelectedBrowserSession(client) {
44
- const selected = await client.evaluate(`(() => ({
45
- piboSessionId: document.querySelector('[data-pibo-debug="chat-shell"]')?.getAttribute('data-pibo-session-id')
46
- || document.querySelector('[data-pibo-selected-session-id]')?.getAttribute('data-pibo-selected-session-id')
47
- || undefined,
44
+ const selected = await client.evaluate(`(() => ({
45
+ piboSessionId: document.querySelector('[data-pibo-debug="chat-shell"]')?.getAttribute('data-pibo-session-id')
46
+ || document.querySelector('[data-pibo-selected-session-id]')?.getAttribute('data-pibo-selected-session-id')
47
+ || undefined,
48
48
  }))()`, 5_000).catch(() => ({}));
49
49
  const piboSessionId = isRecord(selected) && typeof selected.piboSessionId === "string" ? selected.piboSessionId : undefined;
50
50
  if (!piboSessionId)