@pasko70/pibo 2.5.2 → 3.0.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.
Files changed (100) hide show
  1. package/context/pibo-native-tooling.md +1 -0
  2. package/dist/agent-runtime/contract.js +2 -1
  3. package/dist/agent-runtime/history.js +53 -1
  4. package/dist/agent-runtime/routed-session.js +100 -26
  5. package/dist/agent-runtimes/codex-native/adapter.js +304 -30
  6. package/dist/agent-runtimes/codex-native/client.js +22 -3
  7. package/dist/agent-runtimes/codex-native/first-use.js +294 -0
  8. package/dist/agent-runtimes/codex-native/history.js +26 -7
  9. package/dist/agent-runtimes/codex-native/process.js +14 -0
  10. package/dist/agent-runtimes/codex-native/thread.js +59 -25
  11. package/dist/agent-runtimes/codex-native/turn.js +27 -0
  12. package/dist/agent-runtimes/history-proof.js +8 -0
  13. package/dist/agent-runtimes/omp/adapter.js +61 -14
  14. package/dist/agent-runtimes/omp/history.js +189 -34
  15. package/dist/agent-runtimes/omp/thread.js +82 -36
  16. package/dist/agent-runtimes/pi/adapter.js +30 -3
  17. package/dist/agent-runtimes/pi/history.js +66 -5
  18. package/dist/agent-runtimes/pi/openai-response-observer.js +102 -0
  19. package/dist/agent-runtimes/pi/routed-session.js +344 -37
  20. package/dist/apps/chat/chat-api-routes.js +1 -1
  21. package/dist/apps/chat/chat-files.js +130 -9
  22. package/dist/apps/chat/chat-settings-routes.js +27 -2
  23. package/dist/apps/chat/chat-speech.js +100 -0
  24. package/dist/apps/chat/data/chat-data-mappers.js +25 -5
  25. package/dist/apps/chat/data/timeline-query-service.js +89 -1
  26. package/dist/apps/chat/trace-v2.js +210 -8
  27. package/dist/apps/chat/trace.js +3 -0
  28. package/dist/apps/chat/web-app.js +108 -3
  29. package/dist/apps/chat-ui/assets/{dist-DTWJf37A.js → dist-BBDMeU5-.js} +1 -1
  30. package/dist/apps/chat-ui/assets/{dist-CkYWKnvy.js → dist-BDIATCQt.js} +1 -1
  31. package/dist/apps/chat-ui/assets/{dist-DZ8Wpj-H.js → dist-JnW4v8UE.js} +1 -1
  32. package/dist/apps/chat-ui/assets/{dist-Dmblz15N.js → dist-lRiLP9rr.js} +1 -1
  33. package/dist/apps/chat-ui/assets/{dist-DjcwoyNY.js → dist-mqCviI-c.js} +1 -1
  34. package/dist/apps/chat-ui/assets/index-0XOOVxLP.js +228 -0
  35. package/dist/apps/chat-ui/assets/index-DV7_CgsC.css +1 -0
  36. package/dist/apps/chat-ui/index.html +2 -2
  37. package/dist/apps/chat-vscode-web/assets/index-Dtw2Z7jz.js +43 -0
  38. package/dist/apps/chat-vscode-web/assets/{index-CF1-9PKU.css → index-SluZr_-r.css} +1 -1
  39. package/dist/apps/chat-vscode-web/index.html +2 -2
  40. package/dist/apps/vscode-artifacts/latest.vsix +0 -0
  41. package/dist/apps/vscode-artifacts/pibo-vscode-ext-3.0.0.vsix +0 -0
  42. package/dist/cli.js +49 -5
  43. package/dist/config/config.js +59 -8
  44. package/dist/core/preview-server-settings.js +20 -0
  45. package/dist/core/session-router.js +457 -37
  46. package/dist/core/user-settings.js +10 -0
  47. package/dist/data/payload-store.js +57 -1
  48. package/dist/data/schema.js +18 -1
  49. package/dist/debug/trace.js +5 -0
  50. package/dist/gateway/client.js +368 -65
  51. package/dist/gateway/protocol.js +2 -0
  52. package/dist/gateway/server.js +8 -0
  53. package/dist/gateway/web.js +2 -0
  54. package/dist/index.js +1 -1
  55. package/dist/loops/store.js +6 -4
  56. package/dist/mcp/config.js +89 -17
  57. package/dist/mcp/daemon-client.js +473 -153
  58. package/dist/mcp/daemon.js +401 -37
  59. package/dist/plugins/builtin.js +2 -2
  60. package/dist/plugins/codex-native.js +2 -0
  61. package/dist/plugins/registry.js +259 -1
  62. package/dist/previews/cli.js +345 -0
  63. package/dist/previews/config.js +61 -0
  64. package/dist/previews/manager.js +644 -0
  65. package/dist/previews/network.js +198 -0
  66. package/dist/previews/plugin.js +11 -0
  67. package/dist/previews/process-supervisor.js +38 -0
  68. package/dist/previews/proxy.js +387 -0
  69. package/dist/previews/store.js +750 -0
  70. package/dist/previews/types.js +1 -0
  71. package/dist/previews/web-app.js +446 -0
  72. package/dist/runs/registry.js +22 -0
  73. package/dist/runs/tools.js +46 -7
  74. package/dist/session-ui/terminalRows.js +187 -13
  75. package/dist/sessions/pibo-data-store.js +37 -0
  76. package/dist/sessions/runtime-binding-persistence.js +34 -0
  77. package/dist/sessions/runtime-binding.js +6 -0
  78. package/dist/sessions/sqlite-store.js +37 -0
  79. package/dist/shared/trace-engine.js +12 -64
  80. package/dist/shared/trace-event-projection.js +16 -0
  81. package/dist/shared/trace-history.js +684 -184
  82. package/dist/shared/trace-limits.js +7 -0
  83. package/dist/shared/trace-live-patch.js +61 -0
  84. package/dist/shared/trace-tool-identity.js +43 -0
  85. package/dist/speech/openai-codex-realtime-call-proxy.js +248 -0
  86. package/dist/speech/openai-codex.js +407 -0
  87. package/dist/speech/types.js +8 -0
  88. package/dist/subagents/context.js +5 -3
  89. package/dist/subagents/observations.js +94 -6
  90. package/dist/subagents/tool.js +103 -20
  91. package/dist/tools/codex-image-artifacts.js +24 -0
  92. package/dist/tools/codex-image-generation.js +4 -22
  93. package/dist/web/channel.js +88 -4
  94. package/dist/web/http.js +2 -1
  95. package/npm-shrinkwrap.json +2 -2
  96. package/package.json +1 -1
  97. package/dist/apps/chat-ui/assets/index-0WZI2phJ.css +0 -1
  98. package/dist/apps/chat-ui/assets/index-DsgTm1Aw.js +0 -228
  99. package/dist/apps/chat-vscode-web/assets/index-DvTSSvzN.js +0 -43
  100. package/dist/apps/vscode-artifacts/pibo-vscode-ext-2.5.2.vsix +0 -0
@@ -3,6 +3,8 @@ import { closeSync, existsSync, openSync, readFileSync, readSync, readdirSync, s
3
3
  import { homedir } from "node:os";
4
4
  import { join } from "node:path";
5
5
  import { parseSessionEntries, SessionManager } from "@earendil-works/pi-coding-agent";
6
+ import { historyReconciliationDigest } from "../../agent-runtime/history.js";
7
+ import { TRACE_RECONCILIATION_ENTRY_CAP } from "../../shared/trace-limits.js";
6
8
  export const PI_HISTORY_TAIL_MAX_BYTES = 2 * 1024 * 1024;
7
9
  export const PI_HISTORY_PAGE_MAX_BYTES = 512 * 1024;
8
10
  export const PI_HISTORY_SCAN_MAX_BYTES = 16 * 1024 * 1024;
@@ -76,11 +78,35 @@ export async function readPiAgentRuntimeHistory(runtimeInstanceId, input) {
76
78
  beforeTimestamp: input.beforeTimestamp ?? decoded.beforeTimestamp,
77
79
  limit: input.limit,
78
80
  });
81
+ const historyScopeId = `pi:${runtimeInstanceId}:${input.binding.nativeSessionId ?? "unbound"}`;
82
+ const completeProof = inspection.sizeBytes !== undefined && inspection.sizeBytes <= PI_HISTORY_SCAN_MAX_BYTES
83
+ ? readPiTranscriptEntriesWithPositions(inspection.locator.value, PI_HISTORY_SCAN_MAX_BYTES, TRACE_RECONCILIATION_ENTRY_CAP)
84
+ : undefined;
85
+ const proofEntries = completeProof
86
+ ? piSessionEntriesToAgentRuntimeHistoryEntries(completeProof.entries, completeProof.entryPositions, historyScopeId)
87
+ : undefined;
88
+ const proofEntriesByPosition = proofEntries
89
+ ? new Map(proofEntries.map((entry) => [entry.historyPosition, entry]))
90
+ : undefined;
91
+ const entries = proofEntriesByPosition
92
+ ? page.entryPositions.flatMap((position) => {
93
+ const entry = proofEntriesByPosition.get(position);
94
+ return entry ? [entry] : [];
95
+ })
96
+ : piSessionEntriesToAgentRuntimeHistoryEntries(page.entries, page.entryPositions, historyScopeId);
79
97
  return {
80
98
  runtimeInstanceId,
81
99
  adapterId: "pi",
82
100
  source: "native",
83
- entries: piSessionEntriesToAgentRuntimeHistoryEntries(page.entries),
101
+ entries,
102
+ reconciliationProof: completeProof && proofEntries
103
+ ? {
104
+ complete: true,
105
+ scopeId: historyScopeId,
106
+ fullScope: { entryCount: proofEntries.length, digest: historyReconciliationDigest(proofEntries) },
107
+ entries: proofEntries,
108
+ }
109
+ : { complete: false, scopeId: historyScopeId, entries },
84
110
  orderOffset: page.startByte,
85
111
  nextCursor: page.hasOlder && page.nextBeforeByte !== undefined
86
112
  ? encodePiHistoryCursor({ beforeByte: page.nextBeforeByte, beforeTimestamp: input.beforeTimestamp ?? decoded.beforeTimestamp })
@@ -89,11 +115,12 @@ export async function readPiAgentRuntimeHistory(runtimeInstanceId, input) {
89
115
  inspection,
90
116
  };
91
117
  }
92
- export function piSessionEntriesToAgentRuntimeHistoryEntries(entries) {
118
+ export function piSessionEntriesToAgentRuntimeHistoryEntries(entries, historyPositions = [], historyScopeId) {
93
119
  const normalized = [];
94
120
  let nativeTurnId;
95
121
  for (let sequence = 0; sequence < entries.length; sequence += 1) {
96
122
  const entry = entries[sequence];
123
+ const historyPosition = historyPositions[sequence];
97
124
  if (entry.type === "session_info" && entry.name) {
98
125
  normalized.push({
99
126
  id: `pi:${entry.id}`,
@@ -101,6 +128,8 @@ export function piSessionEntriesToAgentRuntimeHistoryEntries(entries) {
101
128
  source: "native",
102
129
  createdAt: entry.timestamp,
103
130
  sequence,
131
+ ...(historyPosition ? { historyPosition } : {}),
132
+ ...(historyScopeId ? { historyScopeId } : {}),
104
133
  nativeEntryId: entry.id,
105
134
  name: entry.name,
106
135
  });
@@ -117,6 +146,8 @@ export function piSessionEntriesToAgentRuntimeHistoryEntries(entries) {
117
146
  source: "native",
118
147
  createdAt: entry.timestamp,
119
148
  sequence,
149
+ ...(historyPosition ? { historyPosition } : {}),
150
+ ...(historyScopeId ? { historyScopeId } : {}),
120
151
  nativeTurnId,
121
152
  nativeEntryId: entry.id,
122
153
  role: "user",
@@ -132,6 +163,8 @@ export function piSessionEntriesToAgentRuntimeHistoryEntries(entries) {
132
163
  source: "native",
133
164
  createdAt: entry.timestamp,
134
165
  sequence,
166
+ ...(historyPosition ? { historyPosition } : {}),
167
+ ...(historyScopeId ? { historyScopeId } : {}),
135
168
  nativeTurnId,
136
169
  nativeEntryId: entry.id,
137
170
  role: "assistant",
@@ -153,6 +186,8 @@ export function piSessionEntriesToAgentRuntimeHistoryEntries(entries) {
153
186
  source: "native",
154
187
  createdAt: entry.timestamp,
155
188
  sequence,
189
+ ...(historyPosition ? { historyPosition } : {}),
190
+ ...(historyScopeId ? { historyScopeId } : {}),
156
191
  nativeTurnId,
157
192
  nativeEntryId: entry.id,
158
193
  role: "tool",
@@ -228,7 +263,7 @@ export function readPiTranscriptTailEntries(path, maxBytes = PI_HISTORY_TAIL_MAX
228
263
  }
229
264
  export function readPiTranscriptHistoryPage(path, input = {}) {
230
265
  if (!existsSync(path))
231
- return { entries: [], hasOlder: false, scannedBytes: 0, startByte: 0, endByte: 0 };
266
+ return { entries: [], entryPositions: [], hasOlder: false, scannedBytes: 0, startByte: 0, endByte: 0 };
232
267
  const stats = statSync(path);
233
268
  const fileSize = Math.max(0, stats.size);
234
269
  const initialEnd = input.beforeByte === undefined
@@ -261,7 +296,7 @@ export function readPiTranscriptHistoryPage(path, input = {}) {
261
296
  const entry = parsed[entryIndex];
262
297
  if (beforeTime !== undefined && entryTimestampMs(entry) >= beforeTime)
263
298
  continue;
264
- entries.push({ entry, startByte: record.startByte });
299
+ entries.push({ entry, startByte: record.startByte, parsedIndex: entryIndex });
265
300
  if (entries.length >= limit)
266
301
  break;
267
302
  }
@@ -271,8 +306,10 @@ export function readPiTranscriptHistoryPage(path, input = {}) {
271
306
  closeSync(fd);
272
307
  }
273
308
  const nextBeforeByte = cursorEnd > 0 ? cursorEnd : undefined;
309
+ const orderedEntries = entries.reverse();
274
310
  return {
275
- entries: entries.reverse().map((item) => item.entry),
311
+ entries: orderedEntries.map((item) => item.entry),
312
+ entryPositions: orderedEntries.map((item) => `pi-byte:${item.startByte}:${item.parsedIndex}`),
276
313
  nextBeforeByte,
277
314
  hasOlder: nextBeforeByte !== undefined,
278
315
  scannedBytes,
@@ -280,6 +317,30 @@ export function readPiTranscriptHistoryPage(path, input = {}) {
280
317
  endByte: initialEnd,
281
318
  };
282
319
  }
320
+ function readPiTranscriptEntriesWithPositions(path, maxBytes, maxEntries) {
321
+ if (statSync(path).size > maxBytes)
322
+ return undefined;
323
+ const content = readFileSync(path);
324
+ if (content.length > maxBytes)
325
+ return undefined;
326
+ const entries = [];
327
+ const entryPositions = [];
328
+ let lineStart = 0;
329
+ for (let cursor = 0; cursor <= content.length; cursor += 1) {
330
+ if (cursor < content.length && content[cursor] !== 0x0a)
331
+ continue;
332
+ const line = content.subarray(lineStart, cursor).toString("utf8");
333
+ const parsed = parseTranscriptLine(line);
334
+ for (let parsedIndex = 0; parsedIndex < parsed.length; parsedIndex += 1) {
335
+ if (entries.length >= maxEntries)
336
+ return undefined;
337
+ entries.push(parsed[parsedIndex]);
338
+ entryPositions.push(`pi-byte:${lineStart}:${parsedIndex}`);
339
+ }
340
+ lineStart = cursor + 1;
341
+ }
342
+ return { entries, entryPositions };
343
+ }
283
344
  function normalizePiAssistantContent(content) {
284
345
  if (typeof content === "string")
285
346
  return [{ type: "text", text: content }];
@@ -0,0 +1,102 @@
1
+ export function withOpenAiResponseEventObserver(options, observer) {
2
+ const fetchImpl = options?.fetch ?? globalThis.fetch;
3
+ return {
4
+ ...(options ?? {}),
5
+ // Pi does not expose raw events from its shared Codex WebSocket transport.
6
+ // SSE keeps observation request-scoped instead of replacing global constructors.
7
+ transport: "sse",
8
+ fetch: async (input, init) => observeOpenAiSseResponse(await fetchImpl(input, init), observer),
9
+ };
10
+ }
11
+ export function observeOpenAiSseResponse(response, observer) {
12
+ if (!response.body || !response.headers.get("content-type")?.toLowerCase().includes("text/event-stream")) {
13
+ return response;
14
+ }
15
+ const reader = response.body.getReader();
16
+ const parser = new OpenAiSseParser(observer);
17
+ let cancelled = false;
18
+ const body = new ReadableStream({
19
+ async pull(controller) {
20
+ try {
21
+ const chunk = await reader.read();
22
+ if (cancelled)
23
+ return;
24
+ if (chunk.done) {
25
+ parser.finish();
26
+ reader.releaseLock();
27
+ controller.close();
28
+ return;
29
+ }
30
+ parser.push(chunk.value);
31
+ controller.enqueue(chunk.value);
32
+ }
33
+ catch (error) {
34
+ if (cancelled)
35
+ return;
36
+ reader.releaseLock();
37
+ controller.error(error);
38
+ }
39
+ },
40
+ async cancel(reason) {
41
+ cancelled = true;
42
+ try {
43
+ await reader.cancel(reason);
44
+ }
45
+ finally {
46
+ reader.releaseLock();
47
+ }
48
+ },
49
+ }, { highWaterMark: 0 });
50
+ return new Response(body, {
51
+ status: response.status,
52
+ statusText: response.statusText,
53
+ headers: response.headers,
54
+ });
55
+ }
56
+ class OpenAiSseParser {
57
+ observer;
58
+ decoder = new TextDecoder();
59
+ buffer = "";
60
+ constructor(observer) {
61
+ this.observer = observer;
62
+ }
63
+ push(chunk) {
64
+ this.buffer += this.decoder.decode(chunk, { stream: true });
65
+ this.drain();
66
+ }
67
+ finish() {
68
+ this.buffer += this.decoder.decode();
69
+ this.drain(true);
70
+ }
71
+ drain(final = false) {
72
+ this.buffer = this.buffer.replaceAll("\r\n", "\n");
73
+ let separator = this.buffer.indexOf("\n\n");
74
+ while (separator >= 0) {
75
+ this.observeBlock(this.buffer.slice(0, separator));
76
+ this.buffer = this.buffer.slice(separator + 2);
77
+ separator = this.buffer.indexOf("\n\n");
78
+ }
79
+ if (final && this.buffer.trim()) {
80
+ this.observeBlock(this.buffer);
81
+ this.buffer = "";
82
+ }
83
+ }
84
+ observeBlock(block) {
85
+ const data = block
86
+ .split("\n")
87
+ .filter((line) => line.startsWith("data:"))
88
+ .map((line) => line.slice(5).trim())
89
+ .join("\n")
90
+ .trim();
91
+ if (data && data !== "[DONE]")
92
+ observeJson(data, this.observer);
93
+ }
94
+ }
95
+ function observeJson(value, observer) {
96
+ try {
97
+ observer(JSON.parse(value));
98
+ }
99
+ catch {
100
+ // Provider observation must never interfere with the provider stream.
101
+ }
102
+ }