@pasko70/pibo 1.16.6 → 2.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 (145) hide show
  1. package/dist/agent-runtime/auth.js +28 -0
  2. package/dist/agent-runtime/capabilities.js +221 -0
  3. package/dist/agent-runtime/context-build.js +313 -0
  4. package/dist/agent-runtime/contract.js +45 -0
  5. package/dist/agent-runtime/errors.js +57 -0
  6. package/dist/agent-runtime/events.js +1 -0
  7. package/dist/agent-runtime/history.js +1 -0
  8. package/dist/agent-runtime/profile-validation.js +109 -0
  9. package/dist/agent-runtime/registry.js +608 -0
  10. package/dist/agent-runtime/resource-files.js +87 -0
  11. package/dist/agent-runtime/resource-service.js +635 -0
  12. package/dist/agent-runtime/resources.js +1 -0
  13. package/dist/agent-runtime/routed-session.js +931 -0
  14. package/dist/agent-runtime/testing/contract.js +51 -0
  15. package/dist/agent-runtime/testing/fake-adapter.js +192 -0
  16. package/dist/agent-runtime/types.js +3 -0
  17. package/dist/agent-runtimes/codex-native/adapter.js +905 -0
  18. package/dist/agent-runtimes/codex-native/auth.js +476 -0
  19. package/dist/agent-runtimes/codex-native/client.js +734 -0
  20. package/dist/agent-runtimes/codex-native/config.js +152 -0
  21. package/dist/agent-runtimes/codex-native/history.js +283 -0
  22. package/dist/agent-runtimes/codex-native/mcp-stdio-launcher.js +89 -0
  23. package/dist/agent-runtimes/codex-native/models.js +581 -0
  24. package/dist/agent-runtimes/codex-native/process.js +459 -0
  25. package/dist/agent-runtimes/codex-native/protocol-types.js +1 -0
  26. package/dist/agent-runtimes/codex-native/protocol-version.js +7 -0
  27. package/dist/agent-runtimes/codex-native/redaction.js +31 -0
  28. package/dist/agent-runtimes/codex-native/requests.js +378 -0
  29. package/dist/agent-runtimes/codex-native/resource-delivery.js +445 -0
  30. package/dist/agent-runtimes/codex-native/thread.js +388 -0
  31. package/dist/agent-runtimes/codex-native/turn.js +849 -0
  32. package/dist/agent-runtimes/pi/adapter.js +653 -0
  33. package/dist/agent-runtimes/pi/auth.js +455 -0
  34. package/dist/agent-runtimes/pi/history.js +640 -0
  35. package/dist/agent-runtimes/pi/model-catalog.js +87 -0
  36. package/dist/agent-runtimes/pi/routed-session.js +1464 -0
  37. package/dist/agent-runtimes/pi/runtime.js +534 -0
  38. package/dist/agent-runtimes/pi/tool-compiler.js +69 -0
  39. package/dist/apps/chat/agent-profiles.js +40 -23
  40. package/dist/apps/chat/agent-store.js +111 -64
  41. package/dist/apps/chat/chat-api-routes.js +1 -1
  42. package/dist/apps/chat/chat-request-normalizers.js +47 -0
  43. package/dist/apps/chat/data/chat-data-mappers.js +25 -9
  44. package/dist/apps/chat/data/history-query-service.js +108 -0
  45. package/dist/apps/chat/data/session-query-service.js +24 -3
  46. package/dist/apps/chat/data/timeline-query-service.js +3 -3
  47. package/dist/apps/chat/model-catalog.js +1 -55
  48. package/dist/apps/chat/provider-auth-actions.js +171 -23
  49. package/dist/apps/chat/stream.js +12 -0
  50. package/dist/apps/chat/trace-v2.js +1 -0
  51. package/dist/apps/chat/trace.js +126 -415
  52. package/dist/apps/chat/web-app.js +582 -157
  53. package/dist/apps/chat-ui/assets/{dist-BTLtT_Vf.js → dist-9v2ZXT6V.js} +1 -1
  54. package/dist/apps/chat-ui/assets/{dist-CMk1aPug.js → dist-B1LVAytl.js} +1 -1
  55. package/dist/apps/chat-ui/assets/{dist-CcwA_IWN.js → dist-C6LPDFXU.js} +1 -1
  56. package/dist/apps/chat-ui/assets/{dist-DKOthbxr.js → dist-DVtXxfHc.js} +1 -1
  57. package/dist/apps/chat-ui/assets/{dist-ls2I6BIw.js → dist-DW4Qrfbd.js} +1 -1
  58. package/dist/apps/chat-ui/assets/{dist-D1rAtRWs.js → dist-DmbsHdMC.js} +1 -1
  59. package/dist/apps/chat-ui/assets/{dist-C1JQRskW.js → dist-DyvwuSFO.js} +1 -1
  60. package/dist/apps/chat-ui/assets/{dist-DfpaylQ-.js → dist-I26VB0QO.js} +1 -1
  61. package/dist/apps/chat-ui/assets/{dist-D10bTFD5.js → dist-RtHbJRPV.js} +1 -1
  62. package/dist/apps/chat-ui/assets/{dist-5KpmmBBZ.js → dist-sZgJkWZb.js} +1 -1
  63. package/dist/apps/chat-ui/assets/index-BPbNvcZe.css +1 -0
  64. package/dist/apps/chat-ui/assets/index-CIOf2uL2.js +237 -0
  65. package/dist/apps/chat-ui/index.html +2 -2
  66. package/dist/apps/chat-vscode-web/assets/index-1ivRyjFs.js +41 -0
  67. package/dist/apps/chat-vscode-web/index.html +1 -1
  68. package/dist/apps/vscode-artifacts/latest.vsix +0 -0
  69. package/dist/apps/vscode-artifacts/pibo-vscode-ext-2.0.0.vsix +0 -0
  70. package/dist/auth/login-actions.js +5 -251
  71. package/dist/cli-session/localSessionSource.js +8 -1
  72. package/dist/core/context-build.js +124 -20
  73. package/dist/core/default-profile.js +8 -0
  74. package/dist/core/profiles.js +30 -3
  75. package/dist/core/routed-session.js +5 -1446
  76. package/dist/core/runtime.js +5 -561
  77. package/dist/core/session-router.js +637 -83
  78. package/dist/data/cli.js +20 -3
  79. package/dist/data/schema.js +104 -1
  80. package/dist/data/session-store.js +24 -1
  81. package/dist/debug/events.js +25 -10
  82. package/dist/debug/failures.js +23 -3
  83. package/dist/debug/index.js +24 -6
  84. package/dist/debug/messages.js +87 -7
  85. package/dist/debug/persisted-payloads.js +31 -0
  86. package/dist/debug/pty.js +7 -6
  87. package/dist/debug/runtime-binding.js +29 -0
  88. package/dist/debug/session.js +137 -0
  89. package/dist/debug/summary.js +12 -0
  90. package/dist/debug/telemetry.js +28 -0
  91. package/dist/debug/tools.js +12 -2
  92. package/dist/debug/trace.js +154 -76
  93. package/dist/gateway/server.js +87 -2
  94. package/dist/gateway/tool.js +5 -5
  95. package/dist/index.js +21 -2
  96. package/dist/loops/tools.js +13 -12
  97. package/dist/mcp/agent-context.js +13 -4
  98. package/dist/mcp/client.js +10 -6
  99. package/dist/mcp/config.js +5 -2
  100. package/dist/mcp/runtime-session.js +166 -0
  101. package/dist/plugins/builtin.js +191 -53
  102. package/dist/plugins/codex-native.js +29 -0
  103. package/dist/plugins/registry.js +66 -2
  104. package/dist/runs/tools.js +26 -25
  105. package/dist/session-ui/terminalRows.js +2 -2
  106. package/dist/sessions/pibo-data-store.js +125 -16
  107. package/dist/sessions/runtime-binding.js +107 -0
  108. package/dist/sessions/sqlite-store.js +239 -18
  109. package/dist/sessions/store.js +86 -7
  110. package/dist/shared/trace-engine.js +18 -9
  111. package/dist/shared/trace-event-projection.js +29 -11
  112. package/dist/shared/{trace-transcript.js → trace-history.js} +193 -195
  113. package/dist/shared/trace-order.js +9 -4
  114. package/dist/shared/trace-page-merge.js +1 -1
  115. package/dist/signals/projector.js +20 -2
  116. package/dist/signals/registry.js +11 -0
  117. package/dist/subagents/tool.js +8 -6
  118. package/dist/tools/codex-browser.js +20 -19
  119. package/dist/tools/codex-compat.js +10 -9
  120. package/dist/tools/codex-image-generation.js +8 -6
  121. package/dist/tools/contract.js +45 -0
  122. package/dist/tools/credential-registry.js +182 -0
  123. package/dist/tools/mcp-bridge.js +511 -0
  124. package/dist/tools/payload-writer.js +17 -0
  125. package/dist/tools/runtime/tool.js +10 -9
  126. package/dist/tools/schema.js +9 -0
  127. package/dist/tools/session-service.js +193 -0
  128. package/dist/tools/session-tool-set.js +85 -0
  129. package/dist/web-annotations/tools.js +17 -16
  130. package/docs/README.md +11 -0
  131. package/package.json +3 -2
  132. package/skills/builtin/pibo-agent-runtime-adapter/SKILL.md +183 -0
  133. package/skills/builtin/pibo-agent-runtime-adapter/evals/README.md +10 -0
  134. package/skills/builtin/pibo-agent-runtime-adapter/evals/evals.json +45 -0
  135. package/skills/builtin/pibo-agent-runtime-adapter/evals/fixtures/orion-full-harness.md +60 -0
  136. package/skills/builtin/pibo-agent-runtime-adapter/evals/fixtures/relay-partial-harness.md +52 -0
  137. package/skills/builtin/pibo-agent-runtime-adapter/references/capabilities-and-designer.md +194 -0
  138. package/skills/builtin/pibo-agent-runtime-adapter/references/history-debug-and-security.md +213 -0
  139. package/skills/builtin/pibo-agent-runtime-adapter/references/interfaces-and-registration.md +214 -0
  140. package/skills/builtin/pibo-agent-runtime-adapter/references/lifecycle-bindings-and-events.md +193 -0
  141. package/skills/builtin/pibo-agent-runtime-adapter/references/portable-delivery-and-native-behavior.md +226 -0
  142. package/skills/builtin/pibo-agent-runtime-adapter/references/testing-migration-and-validation.md +256 -0
  143. package/dist/apps/chat-ui/assets/index-C2YI0xfw.js +0 -237
  144. package/dist/apps/chat-ui/assets/index-E0RmuCkY.css +0 -1
  145. package/dist/apps/chat-vscode-web/assets/index-D-tSsXLG.js +0 -41
@@ -0,0 +1,653 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { SessionManager } from "@earendil-works/pi-coding-agent";
3
+ import { InitialSessionContext, } from "../../core/profiles.js";
4
+ import { createPiboRuntime, } from "./runtime.js";
5
+ import { PiboPluginRegistry } from "../../plugins/registry.js";
6
+ import { unsupportedAgentRuntimeCapability, } from "../../agent-runtime/capabilities.js";
7
+ import { RoutedSession as PiRoutedSession } from "./routed-session.js";
8
+ import { loadModelCatalog as loadPiModelCatalog, piAgentRuntimeModelCatalog, } from "./model-catalog.js";
9
+ import { inspectPiAgentRuntimeHistory, readPiAgentRuntimeHistory, } from "./history.js";
10
+ import { PiAgentRuntimeAuthController } from "./auth.js";
11
+ const PI_ADAPTER_ID = "pi";
12
+ const PI_PROTOCOL_VERSION = "0.80.6";
13
+ export const PI_AGENT_RUNTIME_CAPABILITIES = {
14
+ lifecycle: {
15
+ persistent: true,
16
+ lazyBinding: false,
17
+ resume: true,
18
+ attach: true,
19
+ listNativeSessions: true,
20
+ fork: true,
21
+ clone: true,
22
+ tree: true,
23
+ },
24
+ input: {
25
+ text: true,
26
+ images: true,
27
+ audio: false,
28
+ steering: true,
29
+ structuredOutput: false,
30
+ },
31
+ output: {
32
+ assistantDeltas: true,
33
+ reasoning: true,
34
+ toolEvents: true,
35
+ usage: true,
36
+ plans: false,
37
+ diffs: false,
38
+ rawNativeEvents: true,
39
+ },
40
+ tools: {
41
+ piboManaged: { support: "direct" },
42
+ nativeToolInspection: { support: "native" },
43
+ nativeToolYielding: { support: "native" },
44
+ },
45
+ mcp: {
46
+ externalServers: { support: "materialized", modes: ["isolated-pibo-mcp-config"] },
47
+ statusInspection: true,
48
+ },
49
+ skills: { support: "native" },
50
+ context: { support: "native" },
51
+ auth: {
52
+ status: true,
53
+ methods: [
54
+ { id: "device_code", completion: "explicit" },
55
+ { id: "browser_oauth", completion: "explicit" },
56
+ { id: "api_key", completion: "immediate" },
57
+ ],
58
+ cancel: true,
59
+ logout: true,
60
+ credentialScope: "adapter-shared",
61
+ },
62
+ models: {
63
+ catalog: true,
64
+ switchInSession: true,
65
+ },
66
+ reasoning: {
67
+ supported: true,
68
+ values: ["off", "minimal", "low", "medium", "high", "xhigh", "max"],
69
+ },
70
+ approvals: {
71
+ supported: false,
72
+ structuredUserInput: false,
73
+ },
74
+ maintenance: {
75
+ compaction: true,
76
+ contextUsage: true,
77
+ history: true,
78
+ health: true,
79
+ },
80
+ };
81
+ function cloneProfileForPiSession(input) {
82
+ const profile = input.profile;
83
+ const nativeSessionId = input.binding?.nativeSessionId ?? input.piboSession.piSessionId;
84
+ return new InitialSessionContext({
85
+ profileName: profile.profileName,
86
+ runtimeInstanceId: profile.runtimeInstanceId,
87
+ runtimeOptions: profile.runtimeOptions,
88
+ sessionId: nativeSessionId,
89
+ parentSessionId: profile.parentSessionId,
90
+ model: profile.model,
91
+ mainModel: profile.mainModel,
92
+ subagentModel: profile.subagentModel,
93
+ thinkingLevel: profile.thinkingLevel,
94
+ mainThinkingLevel: profile.mainThinkingLevel,
95
+ subagentThinkingLevel: profile.subagentThinkingLevel,
96
+ fast: profile.fast,
97
+ mainFast: profile.mainFast,
98
+ subagentFast: profile.subagentFast,
99
+ skills: profile.skills,
100
+ tools: profile.tools,
101
+ subagents: profile.subagents,
102
+ mcpServers: profile.mcpServers,
103
+ piPackages: profile.piPackages,
104
+ contextFiles: profile.contextFiles,
105
+ builtinTools: profile.builtinTools,
106
+ builtinToolNames: profile.builtinToolNames,
107
+ autoContextFiles: profile.autoContextFiles,
108
+ toolPackages: profile.toolPackages,
109
+ });
110
+ }
111
+ function nativeSnapshotFromPi(runtimeInstanceId, snapshot) {
112
+ return {
113
+ adapterId: PI_ADAPTER_ID,
114
+ runtimeInstanceId,
115
+ nativeSessionId: snapshot.piSessionId,
116
+ locator: snapshot.sessionFile ? { kind: "local-file", value: snapshot.sessionFile } : undefined,
117
+ leafId: snapshot.leafId,
118
+ cwd: snapshot.cwd,
119
+ name: snapshot.sessionName,
120
+ parentLocator: snapshot.parentSessionFile
121
+ ? { kind: "local-file", value: snapshot.parentSessionFile }
122
+ : undefined,
123
+ };
124
+ }
125
+ function nativeOperationFromPi(runtimeInstanceId, result) {
126
+ return {
127
+ previous: nativeSnapshotFromPi(runtimeInstanceId, result.previous),
128
+ current: nativeSnapshotFromPi(runtimeInstanceId, result.current),
129
+ cancelled: result.cancelled,
130
+ selectedText: result.selectedText,
131
+ editorText: result.editorText,
132
+ summaryEntryId: result.summaryEntryId,
133
+ };
134
+ }
135
+ function nativeSessionInfoFromPi(runtimeInstanceId, info) {
136
+ return {
137
+ adapterId: PI_ADAPTER_ID,
138
+ runtimeInstanceId,
139
+ nativeSessionId: info.id,
140
+ locator: { kind: "local-file", value: info.path },
141
+ cwd: info.cwd,
142
+ name: info.name,
143
+ parentLocator: info.parentSessionPath
144
+ ? { kind: "local-file", value: info.parentSessionPath }
145
+ : undefined,
146
+ createdAt: info.created,
147
+ updatedAt: info.modified,
148
+ messageCount: info.messageCount,
149
+ firstMessage: info.firstMessage,
150
+ };
151
+ }
152
+ function semanticEventFromPibo(event) {
153
+ switch (event.type) {
154
+ case "message_started":
155
+ return { type: "turn_started", turnId: event.eventId };
156
+ case "message_finished":
157
+ return { type: "turn_completed", turnId: event.eventId, status: "completed" };
158
+ case "assistant_delta":
159
+ return { type: "assistant_delta", text: event.text, contentIndex: event.contentIndex };
160
+ case "assistant_message":
161
+ return { type: "assistant_message", text: event.text, contentIndex: event.contentIndex };
162
+ case "thinking_started":
163
+ return { type: "reasoning_started", contentIndex: event.contentIndex };
164
+ case "thinking_delta":
165
+ return { type: "reasoning_delta", text: event.text, contentIndex: event.contentIndex };
166
+ case "thinking_finished":
167
+ return { type: "reasoning_finished", text: event.text, contentIndex: event.contentIndex };
168
+ case "tool_call":
169
+ return {
170
+ type: "tool_call",
171
+ toolCallId: event.toolCallId,
172
+ toolName: event.toolName,
173
+ args: event.args,
174
+ argsComplete: event.argsComplete,
175
+ };
176
+ case "tool_execution_started":
177
+ return { ...event, type: "tool_execution_started" };
178
+ case "tool_execution_updated":
179
+ return { ...event, type: "tool_execution_updated" };
180
+ case "tool_execution_finished":
181
+ return { ...event, type: "tool_execution_finished" };
182
+ case "assistant_usage":
183
+ return {
184
+ type: "usage",
185
+ usage: {
186
+ inputTokens: event.inputTokens,
187
+ outputTokens: event.outputTokens,
188
+ cacheReadTokens: event.cacheReadTokens,
189
+ cacheWriteTokens: event.cacheWriteTokens,
190
+ totalTokens: event.totalTokens,
191
+ },
192
+ };
193
+ case "compaction_start":
194
+ return { type: "compaction_start", reason: event.reason };
195
+ case "compaction_end":
196
+ return {
197
+ type: "compaction_end",
198
+ reason: event.reason,
199
+ result: event.result,
200
+ aborted: event.aborted,
201
+ errorMessage: event.errorMessage,
202
+ };
203
+ case "session_error":
204
+ return { type: "error", message: event.error, details: event.errorDetails };
205
+ case "pi_event":
206
+ return { type: "native_event", event: event.event };
207
+ default:
208
+ return undefined;
209
+ }
210
+ }
211
+ class PiAgentRuntimeSession {
212
+ runtimeInstanceId;
213
+ piboSessionId;
214
+ runtime;
215
+ binding;
216
+ adapterId = PI_ADAPTER_ID;
217
+ cwd;
218
+ capabilities = PI_AGENT_RUNTIME_CAPABILITIES;
219
+ compatibility = { productRawEventType: "pi_event" };
220
+ controls;
221
+ listeners = new Set();
222
+ routed;
223
+ compatibilityHandle;
224
+ pendingPrompt;
225
+ engineProcessing = false;
226
+ bindingNativeSessionId;
227
+ nativePresenceExpected;
228
+ disposed = false;
229
+ constructor(runtimeInstanceId, piboSessionId, runtime, binding, initialFastMode) {
230
+ this.runtimeInstanceId = runtimeInstanceId;
231
+ this.piboSessionId = piboSessionId;
232
+ this.runtime = runtime;
233
+ this.binding = binding;
234
+ this.cwd = runtime.cwd;
235
+ this.bindingNativeSessionId = runtime.session.sessionId;
236
+ this.nativePresenceExpected = runtime.session.sessionManager.buildSessionContext().messages.length > 0;
237
+ this.routed = new PiRoutedSession(piboSessionId, runtime, (event) => this.handlePiboEvent(event), PiboPluginRegistry.create(), true, undefined, initialFastMode, undefined, undefined, (state) => this.handleEngineState(state));
238
+ this.controls = this.createControls();
239
+ this.compatibilityHandle = this.createCompatibilityHandle();
240
+ }
241
+ getBinding() {
242
+ const persistent = this.binding.metadata?.persistent !== false;
243
+ if (this.bindingNativeSessionId !== this.runtime.session.sessionId) {
244
+ this.bindingNativeSessionId = this.runtime.session.sessionId;
245
+ this.nativePresenceExpected = this.runtime.session.sessionManager.buildSessionContext().messages.length > 0;
246
+ }
247
+ return {
248
+ ...structuredClone(this.binding),
249
+ nativeSessionId: this.runtime.session.sessionId,
250
+ state: "bound",
251
+ locator: this.runtime.session.sessionFile
252
+ ? { kind: "local-file", value: this.runtime.session.sessionFile }
253
+ : undefined,
254
+ metadata: {
255
+ ...(this.binding.metadata ?? {}),
256
+ nativePresenceExpected: persistent && this.nativePresenceExpected,
257
+ },
258
+ };
259
+ }
260
+ subscribe(listener) {
261
+ this.listeners.add(listener);
262
+ return () => this.listeners.delete(listener);
263
+ }
264
+ async prompt(input) {
265
+ this.assertActive();
266
+ if (this.pendingPrompt)
267
+ throw new Error(`Pi runtime session "${this.piboSessionId}" already has an active prompt.`);
268
+ const id = randomUUID();
269
+ await new Promise((resolve, reject) => {
270
+ this.pendingPrompt = { id, terminal: false, resolve, reject };
271
+ try {
272
+ this.routed.enqueueMessage({
273
+ type: "message",
274
+ piboSessionId: this.piboSessionId,
275
+ id,
276
+ text: input.text,
277
+ source: input.source === "interactive" ? "user" : "service",
278
+ capabilityScope: input.capabilityScope === "run-reminder" ? "run-reminder" : undefined,
279
+ });
280
+ }
281
+ catch (error) {
282
+ this.pendingPrompt = undefined;
283
+ reject(error);
284
+ }
285
+ });
286
+ }
287
+ async steer(input) {
288
+ this.assertActive();
289
+ await this.routed.steerMessage({
290
+ type: "message",
291
+ piboSessionId: this.piboSessionId,
292
+ id: randomUUID(),
293
+ text: input.text,
294
+ delivery: "steer",
295
+ source: input.source === "interactive" ? "user" : "service",
296
+ });
297
+ }
298
+ async abort() {
299
+ const pending = this.pendingPrompt;
300
+ if (pending) {
301
+ const cancelled = await this.routed.cancelMessage(pending.id);
302
+ if (!cancelled)
303
+ await this.runtime.session.abort();
304
+ pending.terminal = true;
305
+ this.settlePromptIfReady();
306
+ return;
307
+ }
308
+ await this.runtime.session.abort();
309
+ }
310
+ async dispose() {
311
+ if (this.disposed)
312
+ return;
313
+ this.disposed = true;
314
+ await this.routed.dispose();
315
+ const pending = this.pendingPrompt;
316
+ this.pendingPrompt = undefined;
317
+ pending?.resolve();
318
+ this.listeners.clear();
319
+ }
320
+ getStatus() {
321
+ const status = this.routed.getStatus();
322
+ return {
323
+ streaming: status.streaming,
324
+ enabledTools: status.enabledTools,
325
+ cwd: status.cwd,
326
+ activeModel: this.routed.getActiveModel(),
327
+ reasoning: {
328
+ value: status.thinkingLevel,
329
+ availableValues: this.runtime.session.getAvailableThinkingLevels(),
330
+ supported: this.runtime.session.supportsThinking(),
331
+ },
332
+ fastMode: this.routed.getFastMode(),
333
+ retry: status.retry ? structuredClone(status.retry) : undefined,
334
+ warnings: status.warnings,
335
+ errors: status.errors,
336
+ };
337
+ }
338
+ async getStatusSnapshot() {
339
+ const status = await this.routed.getStatusSnapshot();
340
+ return {
341
+ ...this.getStatus(),
342
+ activeModel: status.activeModel,
343
+ contextUsage: status.contextUsage,
344
+ providerUsage: status.providerUsage,
345
+ };
346
+ }
347
+ getNativeCompatibilityHandle() {
348
+ return this.compatibilityHandle;
349
+ }
350
+ handlePiboEvent(event) {
351
+ if (event.type === "message_started")
352
+ this.nativePresenceExpected = true;
353
+ const eventId = "eventId" in event ? event.eventId : undefined;
354
+ const pending = this.pendingPrompt;
355
+ if (pending && eventId === pending.id) {
356
+ if (event.type === "message_finished" || event.type === "session_error")
357
+ pending.terminal = true;
358
+ }
359
+ const semantic = semanticEventFromPibo(event);
360
+ if (semantic)
361
+ this.emit(semantic);
362
+ if (event.type === "session_error") {
363
+ this.emit({
364
+ type: "turn_failed",
365
+ turnId: event.eventId,
366
+ message: event.error,
367
+ details: event.errorDetails,
368
+ });
369
+ }
370
+ this.settlePromptIfReady();
371
+ }
372
+ handleEngineState(state) {
373
+ this.engineProcessing = state.processing;
374
+ this.settlePromptIfReady();
375
+ }
376
+ settlePromptIfReady() {
377
+ const pending = this.pendingPrompt;
378
+ if (!pending || !pending.terminal || this.engineProcessing)
379
+ return;
380
+ this.pendingPrompt = undefined;
381
+ pending.resolve();
382
+ }
383
+ createControls() {
384
+ return {
385
+ getCurrentSession: () => nativeSnapshotFromPi(this.runtimeInstanceId, this.routed.getCurrentSession()),
386
+ listSessions: async () => (await this.routed.listSessions()).map((info) => nativeSessionInfoFromPi(this.runtimeInstanceId, info)),
387
+ getForkCandidates: () => this.routed.getForkCandidates(),
388
+ forkSession: async (entryId) => nativeOperationFromPi(this.runtimeInstanceId, await this.routed.forkSession(entryId)),
389
+ cloneSession: async () => nativeOperationFromPi(this.runtimeInstanceId, await this.routed.cloneSession()),
390
+ getSessionTree: () => {
391
+ const result = this.routed.getSessionTree();
392
+ return {
393
+ current: nativeSnapshotFromPi(this.runtimeInstanceId, result.current),
394
+ tree: result.tree,
395
+ };
396
+ },
397
+ navigateSessionTree: async (params) => nativeOperationFromPi(this.runtimeInstanceId, await this.routed.navigateSessionTree({
398
+ entryId: String(params.entryId ?? ""),
399
+ summarize: typeof params.summarize === "boolean" ? params.summarize : undefined,
400
+ customInstructions: typeof params.customInstructions === "string" ? params.customInstructions : undefined,
401
+ replaceInstructions: typeof params.replaceInstructions === "boolean" ? params.replaceInstructions : undefined,
402
+ label: typeof params.label === "string" ? params.label : undefined,
403
+ })),
404
+ switchSession: async (params) => nativeOperationFromPi(this.runtimeInstanceId, await this.routed.switchSession({
405
+ sessionFile: String(params.sessionFile ?? ""),
406
+ cwdOverride: typeof params.cwdOverride === "string" ? params.cwdOverride : undefined,
407
+ })),
408
+ getReasoning: () => ({
409
+ value: this.runtime.session.thinkingLevel,
410
+ availableValues: this.runtime.session.getAvailableThinkingLevels(),
411
+ supported: this.runtime.session.supportsThinking(),
412
+ }),
413
+ setReasoning: (value) => {
414
+ const result = this.routed.setThinkingLevel(value);
415
+ return { value: result.level, availableValues: result.availableLevels, supported: result.supported };
416
+ },
417
+ cycleReasoning: () => {
418
+ const result = this.routed.cycleThinkingLevel();
419
+ return { value: result.level, availableValues: result.availableLevels, supported: result.supported };
420
+ },
421
+ getFastMode: () => this.routed.getFastMode(),
422
+ setFastMode: (enabled) => this.routed.setFastMode(enabled),
423
+ setModel: async (model) => await this.routed.setModel(model),
424
+ compact: async (customInstructions) => await this.routed.compact(customInstructions),
425
+ };
426
+ }
427
+ createCompatibilityHandle() {
428
+ return new Proxy(this.runtime, {
429
+ get: (target, property, receiver) => {
430
+ if (property === "dispose")
431
+ return () => this.dispose();
432
+ const value = Reflect.get(target, property, receiver);
433
+ return typeof value === "function" ? value.bind(target) : value;
434
+ },
435
+ });
436
+ }
437
+ emit(event) {
438
+ for (const listener of this.listeners)
439
+ listener(event);
440
+ }
441
+ assertActive() {
442
+ if (this.disposed)
443
+ throw new Error(`Pi runtime session "${this.piboSessionId}" is disposed.`);
444
+ }
445
+ }
446
+ class PiAgentRuntimeAdapter {
447
+ instanceId;
448
+ enabled;
449
+ descriptor = PI_AGENT_RUNTIME_DRIVER.descriptor;
450
+ config;
451
+ displayName;
452
+ modelCatalogCache;
453
+ authController;
454
+ constructor(instanceId, config, displayName, enabled) {
455
+ this.instanceId = instanceId;
456
+ this.enabled = enabled;
457
+ this.config = structuredClone(config);
458
+ this.displayName = displayName ?? this.descriptor.displayName;
459
+ this.authController = new PiAgentRuntimeAuthController(() => this.loadModelCatalog(), () => {
460
+ this.modelCatalogCache = undefined;
461
+ });
462
+ }
463
+ async diagnose() {
464
+ return [{
465
+ severity: "info",
466
+ code: "pi_runtime_available",
467
+ message: `Pi Coding Agent SDK ${PI_PROTOCOL_VERSION} is available in-process.`,
468
+ }];
469
+ }
470
+ async listModels() {
471
+ return piAgentRuntimeModelCatalog(this.instanceId, await this.loadModelCatalog());
472
+ }
473
+ async getAuthStatus() {
474
+ return await this.authController.getStatus();
475
+ }
476
+ async startAuth(input) {
477
+ return await this.authController.start(input);
478
+ }
479
+ async completeAuth(input) {
480
+ return await this.authController.complete(input);
481
+ }
482
+ async cancelAuth(input) {
483
+ return await this.authController.cancel(input);
484
+ }
485
+ async logoutAuth(input) {
486
+ return await this.authController.logout(input);
487
+ }
488
+ async disposeAuth() {
489
+ await this.authController.dispose();
490
+ }
491
+ async inspectHistory(input) {
492
+ return await inspectPiAgentRuntimeHistory(this.instanceId, input);
493
+ }
494
+ async readHistory(input) {
495
+ return await readPiAgentRuntimeHistory(this.instanceId, input);
496
+ }
497
+ validateProfile(input) {
498
+ const diagnostics = [];
499
+ if (input.profile.runtimeInstanceId !== this.instanceId) {
500
+ diagnostics.push({
501
+ severity: "error",
502
+ code: "runtime_instance_mismatch",
503
+ message: `Profile "${input.profile.profileName}" selects runtime instance "${input.profile.runtimeInstanceId}", not "${this.instanceId}".`,
504
+ });
505
+ }
506
+ if (Object.keys(input.profile.runtimeOptions).length > 0) {
507
+ diagnostics.push({
508
+ severity: "error",
509
+ code: "pi_runtime_options_unsupported",
510
+ message: "The Pi runtime does not accept adapter-specific profile options.",
511
+ path: "runtimeOptions",
512
+ });
513
+ }
514
+ const profileProvidesBash = input.profile.toolPackages.runControl === true
515
+ || (input.profile.builtinTools !== "disabled" && input.profile.builtinToolNames.includes("bash"));
516
+ if (input.profile.mcpServers.length > 0 && !profileProvidesBash) {
517
+ diagnostics.push({
518
+ severity: "error",
519
+ code: "pi_mcp_bash_required",
520
+ message: "Pi delivers selected external MCP servers through the session-scoped Pibo MCP CLI configuration, which requires the Bash tool.",
521
+ path: "mcpServers",
522
+ });
523
+ }
524
+ return diagnostics;
525
+ }
526
+ async resolveBinding(input) {
527
+ const binding = structuredClone(input.binding);
528
+ if (binding.state !== "bound" || binding.metadata?.persistent === false)
529
+ return binding;
530
+ if (!binding.nativeSessionId) {
531
+ return {
532
+ ...binding,
533
+ state: "error",
534
+ metadata: {
535
+ ...(binding.metadata ?? {}),
536
+ diagnosticCode: "pi_binding_native_id_missing",
537
+ diagnosticMessage: "The persisted Pi binding is bound but has no native session id.",
538
+ },
539
+ };
540
+ }
541
+ const existing = (await SessionManager.list(input.workspace)).find((session) => session.id === binding.nativeSessionId);
542
+ if (existing) {
543
+ return {
544
+ ...binding,
545
+ locator: { kind: "local-file", value: existing.path },
546
+ metadata: {
547
+ ...(binding.metadata ?? {}),
548
+ nativePresenceExpected: existing.messageCount > 0,
549
+ },
550
+ };
551
+ }
552
+ if (binding.metadata?.nativePresenceExpected === false)
553
+ return binding;
554
+ return {
555
+ ...binding,
556
+ state: "missing",
557
+ metadata: {
558
+ ...(binding.metadata ?? {}),
559
+ diagnosticCode: "pi_session_missing",
560
+ diagnosticMessage: `Pi session "${binding.nativeSessionId}" was not found for workspace "${input.workspace}".`,
561
+ },
562
+ };
563
+ }
564
+ async openSession(input) {
565
+ const compatibility = input.services?.compatibility;
566
+ const runtime = await createPiboRuntime({
567
+ cwd: input.workspace,
568
+ persistSession: compatibility?.persistSession,
569
+ profile: cloneProfileForPiSession(input),
570
+ thinkingLevel: compatibility?.thinkingLevel,
571
+ retryDefaults: compatibility?.retryDefaults,
572
+ extensionFactories: compatibility?.extensionFactories,
573
+ subagentRunner: input.services?.subagentRunner,
574
+ runToolController: input.services?.runToolController,
575
+ runtimeToolController: input.services?.codeRuntimeToolController,
576
+ portableTools: input.services?.portableTools,
577
+ resources: input.services?.resources,
578
+ modelDefaults: compatibility?.modelDefaults,
579
+ activeModel: input.activeModel,
580
+ sessionContext: {
581
+ piboSessionId: input.productContext.piboSessionId,
582
+ piboRoomId: input.productContext.piboRoomId,
583
+ timezone: input.productContext.timezone,
584
+ getActiveMessage: input.productContext.getActiveMessage,
585
+ },
586
+ contextGuardTuiQueueOrdering: compatibility?.contextGuardTuiQueueOrdering,
587
+ });
588
+ const binding = {
589
+ ...(input.binding ? structuredClone(input.binding) : {}),
590
+ piboSessionId: input.piboSession.id,
591
+ runtimeInstanceId: this.instanceId,
592
+ adapterId: this.descriptor.id,
593
+ nativeSessionId: runtime.session.sessionId,
594
+ state: "bound",
595
+ protocol: "pi-sdk",
596
+ protocolVersion: PI_PROTOCOL_VERSION,
597
+ locator: runtime.session.sessionFile
598
+ ? { kind: "local-file", value: runtime.session.sessionFile }
599
+ : undefined,
600
+ metadata: {
601
+ ...(input.binding?.metadata ?? {}),
602
+ persistent: compatibility?.persistSession !== false,
603
+ nativePresenceExpected: compatibility?.persistSession !== false
604
+ && runtime.session.sessionManager.buildSessionContext().messages.length > 0,
605
+ },
606
+ };
607
+ return new PiAgentRuntimeSession(this.instanceId, input.piboSession.id, runtime, binding, compatibility?.initialFastMode ?? false);
608
+ }
609
+ loadModelCatalog() {
610
+ const now = Date.now();
611
+ if (this.modelCatalogCache && this.modelCatalogCache.expiresAt > now)
612
+ return this.modelCatalogCache.value;
613
+ const value = loadPiModelCatalog(process.cwd());
614
+ this.modelCatalogCache = { expiresAt: now + 5_000, value };
615
+ value.catch(() => {
616
+ if (this.modelCatalogCache?.value === value)
617
+ this.modelCatalogCache = undefined;
618
+ });
619
+ return value;
620
+ }
621
+ }
622
+ export const PI_AGENT_RUNTIME_DRIVER = {
623
+ descriptor: {
624
+ id: PI_ADAPTER_ID,
625
+ displayName: "Pi Coding Agent",
626
+ transport: "embedded",
627
+ configSchema: {
628
+ type: "object",
629
+ additionalProperties: false,
630
+ },
631
+ capabilities: PI_AGENT_RUNTIME_CAPABILITIES,
632
+ protocol: {
633
+ name: "pi-sdk",
634
+ supportedRange: PI_PROTOCOL_VERSION,
635
+ },
636
+ supportsMultipleInstances: true,
637
+ },
638
+ defaultConfig: () => ({}),
639
+ parseConfig(value) {
640
+ if (Object.keys(value).length > 0)
641
+ throw new Error("Pi runtime config does not accept instance fields yet.");
642
+ return {};
643
+ },
644
+ create(input) {
645
+ return new PiAgentRuntimeAdapter(input.instanceId, input.config, input.displayName, input.enabled);
646
+ },
647
+ };
648
+ export function getPiAgentRuntimeCompatibilityHandle(session) {
649
+ if (session.adapterId !== PI_ADAPTER_ID)
650
+ return undefined;
651
+ return session.getNativeCompatibilityHandle?.();
652
+ }
653
+ export const PI_NATIVE_TOOL_YIELDING_LIMITATION = unsupportedAgentRuntimeCapability("Only Pi direct tools can be wrapped natively. External harness-native tools require an explicit host-tool capability.");