@pasko70/pibo 1.16.5 → 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 (146) 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-QXwINWYY.js → dist-9v2ZXT6V.js} +1 -1
  54. package/dist/apps/chat-ui/assets/{dist-CvZNkkOi.js → dist-B1LVAytl.js} +1 -1
  55. package/dist/apps/chat-ui/assets/{dist-_SP-MjLq.js → dist-C6LPDFXU.js} +1 -1
  56. package/dist/apps/chat-ui/assets/{dist-Bad4Yz4P.js → dist-DVtXxfHc.js} +1 -1
  57. package/dist/apps/chat-ui/assets/{dist-xy-zomwl.js → dist-DW4Qrfbd.js} +1 -1
  58. package/dist/apps/chat-ui/assets/{dist-DI4i80O2.js → dist-DmbsHdMC.js} +1 -1
  59. package/dist/apps/chat-ui/assets/{dist-D17yAUqp.js → dist-DyvwuSFO.js} +1 -1
  60. package/dist/apps/chat-ui/assets/{dist-Bc3Vbgjh.js → dist-I26VB0QO.js} +1 -1
  61. package/dist/apps/chat-ui/assets/{dist-BzqH7w58.js → dist-RtHbJRPV.js} +1 -1
  62. package/dist/apps/chat-ui/assets/{dist-CMDJ-WZm.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-C45B0rw7.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
  146. package/dist/apps/vscode-artifacts/pibo-vscode-ext-1.16.5.vsix +0 -0
@@ -5,7 +5,7 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <meta name="theme-color" content="#101d22" />
7
7
  <title>Pibo</title>
8
- <script type="module" crossorigin src="/apps/chat-vscode/assets/index-D-tSsXLG.js"></script>
8
+ <script type="module" crossorigin src="/apps/chat-vscode/assets/index-1ivRyjFs.js"></script>
9
9
  <link rel="stylesheet" crossorigin href="/apps/chat-vscode/assets/index-Dupu1DzQ.css">
10
10
  </head>
11
11
  <body>
@@ -1,251 +1,5 @@
1
- import { AuthStorage } from "@earendil-works/pi-coding-agent";
2
- import { randomBytes } from "node:crypto";
3
- const OPENAI_CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
4
- const OPENAI_AUTHORIZE_URL = "https://auth.openai.com/oauth/authorize";
5
- const OPENAI_ISSUER_URL = "https://auth.openai.com";
6
- const OPENAI_DEVICE_USER_CODE_URL = `${OPENAI_ISSUER_URL}/api/accounts/deviceauth/usercode`;
7
- const OPENAI_DEVICE_TOKEN_URL = `${OPENAI_ISSUER_URL}/api/accounts/deviceauth/token`;
8
- const OPENAI_DEVICE_VERIFICATION_URL = `${OPENAI_ISSUER_URL}/codex/device`;
9
- const OPENAI_TOKEN_URL = "https://auth.openai.com/oauth/token";
10
- const OPENAI_REDIRECT_URI = "http://localhost:1455/auth/callback";
11
- const OPENAI_DEVICE_REDIRECT_URI = `${OPENAI_ISSUER_URL}/deviceauth/callback`;
12
- const OPENAI_SCOPE = "openid profile email offline_access";
13
- const OPENAI_JWT_CLAIM_PATH = "https://api.openai.com/auth";
14
- const OPENAI_DEVICE_LOGIN_TIMEOUT_MS = 15 * 60 * 1000;
15
- function base64urlEncode(bytes) {
16
- let binary = "";
17
- for (const byte of bytes) {
18
- binary += String.fromCharCode(byte);
19
- }
20
- return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
21
- }
22
- async function generatePKCE() {
23
- const verifierBytes = new Uint8Array(32);
24
- crypto.getRandomValues(verifierBytes);
25
- const verifier = base64urlEncode(verifierBytes);
26
- const encoder = new TextEncoder();
27
- const data = encoder.encode(verifier);
28
- const hashBuffer = await crypto.subtle.digest("SHA-256", data);
29
- const challenge = base64urlEncode(new Uint8Array(hashBuffer));
30
- return { verifier, challenge };
31
- }
32
- const pendingLogins = new Map();
33
- function createAuthStorage() {
34
- return AuthStorage.create();
35
- }
36
- function decodeJwt(token) {
37
- try {
38
- const parts = token.split(".");
39
- if (parts.length !== 3)
40
- return null;
41
- const payload = parts[1] ?? "";
42
- const decoded = atob(payload);
43
- return JSON.parse(decoded);
44
- }
45
- catch {
46
- return null;
47
- }
48
- }
49
- function getOpenAiAccountId(accessToken) {
50
- const payload = decodeJwt(accessToken);
51
- const auth = payload?.[OPENAI_JWT_CLAIM_PATH];
52
- const accountId = auth?.chatgpt_account_id;
53
- return typeof accountId === "string" && accountId.length > 0 ? accountId : null;
54
- }
55
- function requirePendingLogin(state, provider) {
56
- const pending = pendingLogins.get(state);
57
- if (!pending) {
58
- throw new Error("Invalid or expired login state. Start a new login flow with /login-start.");
59
- }
60
- if (pending.provider !== provider) {
61
- throw new Error(`Login state mismatch: expected provider "${pending.provider}", got "${provider}".`);
62
- }
63
- // Expire after 10 minutes
64
- if (Date.now() - pending.createdAt > 10 * 60 * 1000) {
65
- pendingLogins.delete(state);
66
- throw new Error("Login state expired. Start a new login flow with /login-start.");
67
- }
68
- return pending;
69
- }
70
- async function readResponseText(response) {
71
- return await response.text().catch(() => "");
72
- }
73
- function parseDeviceIntervalMs(value) {
74
- const parsed = typeof value === "number" ? value : Number.parseInt(value ?? "", 10);
75
- return Number.isFinite(parsed) && parsed > 0 ? parsed * 1000 : 5000;
76
- }
77
- async function startOpenAiDeviceLogin(provider) {
78
- const response = await fetch(OPENAI_DEVICE_USER_CODE_URL, {
79
- method: "POST",
80
- headers: { "Content-Type": "application/json" },
81
- body: JSON.stringify({ client_id: OPENAI_CLIENT_ID }),
82
- });
83
- if (!response.ok) {
84
- const text = await readResponseText(response);
85
- const suffix = text ? ` ${text}` : "";
86
- if (response.status === 404) {
87
- throw new Error(`OpenAI device code login is not enabled for this account or Codex server.${suffix}`);
88
- }
89
- throw new Error(`OpenAI device code request failed: ${response.status}${suffix}`);
90
- }
91
- const json = (await response.json());
92
- const deviceAuthId = json.device_auth_id;
93
- const userCode = json.user_code ?? json.usercode;
94
- if (!deviceAuthId || !userCode) {
95
- throw new Error("Invalid device code response from OpenAI");
96
- }
97
- const state = randomBytes(16).toString("hex");
98
- pendingLogins.set(state, {
99
- type: "device",
100
- deviceAuthId,
101
- userCode,
102
- intervalMs: parseDeviceIntervalMs(json.interval),
103
- state,
104
- provider,
105
- createdAt: Date.now(),
106
- });
107
- return {
108
- type: "device_code",
109
- url: OPENAI_DEVICE_VERIFICATION_URL,
110
- verificationUrl: OPENAI_DEVICE_VERIFICATION_URL,
111
- userCode,
112
- state,
113
- provider,
114
- instructions: "Open the URL in any browser, enter the one-time code, finish sign-in, then return here and complete login.",
115
- };
116
- }
117
- async function pollOpenAiDeviceAuthorization(pending) {
118
- const startedAt = Date.now();
119
- while (Date.now() - startedAt < OPENAI_DEVICE_LOGIN_TIMEOUT_MS) {
120
- const response = await fetch(OPENAI_DEVICE_TOKEN_URL, {
121
- method: "POST",
122
- headers: { "Content-Type": "application/json" },
123
- body: JSON.stringify({
124
- device_auth_id: pending.deviceAuthId,
125
- user_code: pending.userCode,
126
- }),
127
- });
128
- if (response.ok) {
129
- const json = (await response.json());
130
- if (!json.authorization_code || !json.code_verifier) {
131
- throw new Error("Invalid device authorization response from OpenAI");
132
- }
133
- return json;
134
- }
135
- if (response.status !== 403 && response.status !== 404) {
136
- const text = await readResponseText(response);
137
- throw new Error(`OpenAI device authorization failed: ${response.status}${text ? ` ${text}` : ""}`);
138
- }
139
- await new Promise((resolve) => setTimeout(resolve, pending.intervalMs));
140
- }
141
- throw new Error("OpenAI device authorization timed out after 15 minutes.");
142
- }
143
- async function exchangeOpenAiAuthorizationCode(code, verifier, redirectUri) {
144
- const response = await fetch(OPENAI_TOKEN_URL, {
145
- method: "POST",
146
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
147
- body: new URLSearchParams({
148
- grant_type: "authorization_code",
149
- client_id: OPENAI_CLIENT_ID,
150
- code,
151
- code_verifier: verifier,
152
- redirect_uri: redirectUri,
153
- }),
154
- });
155
- if (!response.ok) {
156
- const text = await readResponseText(response);
157
- throw new Error(`Token exchange failed: ${response.status} ${text}`);
158
- }
159
- const json = (await response.json());
160
- if (!json.access_token || !json.refresh_token || typeof json.expires_in !== "number") {
161
- throw new Error("Invalid token response from OpenAI");
162
- }
163
- return { accessToken: json.access_token, refreshToken: json.refresh_token, expiresIn: json.expires_in };
164
- }
165
- export async function startLogin(provider) {
166
- if (provider === "openai-codex") {
167
- return await startOpenAiDeviceLogin(provider);
168
- }
169
- if (provider === "openai-codex-browser") {
170
- const { verifier, challenge } = await generatePKCE();
171
- const state = randomBytes(16).toString("hex");
172
- const url = new URL(OPENAI_AUTHORIZE_URL);
173
- url.searchParams.set("response_type", "code");
174
- url.searchParams.set("client_id", OPENAI_CLIENT_ID);
175
- url.searchParams.set("redirect_uri", OPENAI_REDIRECT_URI);
176
- url.searchParams.set("scope", OPENAI_SCOPE);
177
- url.searchParams.set("code_challenge", challenge);
178
- url.searchParams.set("code_challenge_method", "S256");
179
- url.searchParams.set("state", state);
180
- url.searchParams.set("id_token_add_organizations", "true");
181
- url.searchParams.set("codex_cli_simplified_flow", "true");
182
- url.searchParams.set("originator", "pibo");
183
- pendingLogins.set(state, { type: "browser", verifier, state, provider, createdAt: Date.now() });
184
- return {
185
- url: url.toString(),
186
- state,
187
- provider,
188
- instructions: "Open the URL in your browser, complete login, then paste the authorization code (or full redirect URL) via /login-complete.",
189
- };
190
- }
191
- throw new Error(`OAuth login start not supported for provider "${provider}". Supported: openai-codex.`);
192
- }
193
- export async function completeLogin(provider, code, state) {
194
- if (provider === "openai-codex") {
195
- const pending = requirePendingLogin(state, provider);
196
- if (pending.type !== "device") {
197
- throw new Error("Login flow mismatch. Start a new OpenAI device login.");
198
- }
199
- const deviceResult = await pollOpenAiDeviceAuthorization(pending);
200
- const tokenResult = await exchangeOpenAiAuthorizationCode(deviceResult.authorization_code, deviceResult.code_verifier, OPENAI_DEVICE_REDIRECT_URI);
201
- const accountId = getOpenAiAccountId(tokenResult.accessToken);
202
- const authStorage = createAuthStorage();
203
- authStorage.set(provider, {
204
- type: "oauth",
205
- access: tokenResult.accessToken,
206
- refresh: tokenResult.refreshToken,
207
- expires: Date.now() + tokenResult.expiresIn * 1000,
208
- accountId: accountId ?? undefined,
209
- });
210
- pendingLogins.delete(state);
211
- return { success: true, provider, accountId };
212
- }
213
- if (provider === "openai-codex-browser") {
214
- if (!code)
215
- throw new Error("login.complete requires params.code");
216
- const pending = requirePendingLogin(state, provider);
217
- pendingLogins.delete(state);
218
- if (pending.type !== "browser") {
219
- throw new Error("Login flow mismatch. Start a new OpenAI browser login.");
220
- }
221
- const tokenResult = await exchangeOpenAiAuthorizationCode(code, pending.verifier, OPENAI_REDIRECT_URI);
222
- const accountId = getOpenAiAccountId(tokenResult.accessToken);
223
- const authStorage = createAuthStorage();
224
- authStorage.set("openai-codex", {
225
- type: "oauth",
226
- access: tokenResult.accessToken,
227
- refresh: tokenResult.refreshToken,
228
- expires: Date.now() + tokenResult.expiresIn * 1000,
229
- accountId: accountId ?? undefined,
230
- });
231
- return { success: true, provider: "openai-codex", accountId };
232
- }
233
- throw new Error(`OAuth login complete not supported for provider "${provider}". Supported: openai-codex.`);
234
- }
235
- export function setApiKey(provider, apiKey) {
236
- const authStorage = createAuthStorage();
237
- authStorage.set(provider, { type: "api_key", key: apiKey });
238
- return { success: true, provider };
239
- }
240
- export function getLoginStatus(provider) {
241
- const authStorage = createAuthStorage();
242
- if (provider) {
243
- return [{ id: provider, provider, ...authStorage.getAuthStatus(provider) }];
244
- }
245
- return authStorage.list().map((p) => ({ id: p, provider: p, ...authStorage.getAuthStatus(p) }));
246
- }
247
- export function removeLogin(provider) {
248
- const authStorage = createAuthStorage();
249
- authStorage.logout(provider);
250
- return { success: true, provider };
251
- }
1
+ /**
2
+ * @deprecated Pi-specific compatibility exports. Product auth routing must use
3
+ * the selected Agent Runtime Adapter instead of importing these helpers.
4
+ */
5
+ export { cancelLogin, completeLogin, getLoginStatus, removeLogin, setApiKey, startLogin, } from "../agent-runtimes/pi/auth.js";
@@ -6,6 +6,7 @@ import { buildTraceView } from "../apps/chat/trace.js";
6
6
  import { storedPiboEventFromV2Row, } from "../apps/chat/data/chat-data-mappers.js";
7
7
  import { ChatDataIngestService } from "../data/ingest-service.js";
8
8
  import { ChatRoomService } from "../apps/chat/data/room-service.js";
9
+ import { ChatHistoryQueryService } from "../apps/chat/data/history-query-service.js";
9
10
  import { buildSlashCommandCatalog, normalizeCommandErrorDescriptor, normalizeCommandResultDescriptor, } from "../session-ui/index.js";
10
11
  import { CliSourceError, } from "./sessionSource.js";
11
12
  export const CLI_LOCAL_RECOVERY_SOURCE_ID = "local:root";
@@ -729,13 +730,18 @@ export class LocalCliSessionSource {
729
730
  limit: 500,
730
731
  });
731
732
  const events = rows
732
- .map((row) => storedPiboEventFromV2Row(eventLogRowToV2MapperRow(row)))
733
+ .map((row) => storedPiboEventFromV2Row(eventLogRowToV2MapperRow(row), this.dataStore?.payloads))
733
734
  .filter((event) => event !== undefined)
734
735
  .map(normalizeStoredEventForCliTrace);
736
+ const historyEntries = new ChatHistoryQueryService(this.dataStore).listProductHistoryEntries({
737
+ piboSessionId: session.id,
738
+ limit: 500,
739
+ });
735
740
  return await buildTraceView({
736
741
  session,
737
742
  sessions: this.readSessions(),
738
743
  events,
744
+ historyEntries,
739
745
  status: statusFromSession(session) === "running"
740
746
  ? "running"
741
747
  : statusFromSession(session) === "error"
@@ -943,6 +949,7 @@ function eventLogRowToV2MapperRow(row) {
943
949
  event_id: row.eventId ?? null,
944
950
  idempotency_key: row.idempotencyKey ?? null,
945
951
  retention_class: row.retentionClass,
952
+ payload_ref: row.payloadRef ?? null,
946
953
  preview_text: row.previewText ?? null,
947
954
  attributes_json: JSON.stringify(row.attributes ?? {}),
948
955
  created_at: row.createdAt,
@@ -1,7 +1,8 @@
1
1
  import { readFile } from "node:fs/promises";
2
2
  import { resolve } from "node:path";
3
- import { createDefaultPiboProfile } from "../plugins/builtin.js";
3
+ import { createDefaultPiboProfile } from "./default-profile.js";
4
4
  import { getMcpAgentContextFile } from "../mcp/agent-context.js";
5
+ import { PIBO_GOAL_TOOL_NAMES } from "../loops/tools.js";
5
6
  import { getInstalledCliToolContextFile } from "../tools/registry.js";
6
7
  import { WEB_SEARCH_PROMPT_CONTRIBUTION, isWebSearchProviderTool, normalizeOpenAiWebSearchConfig, } from "../tools/web-search.js";
7
8
  import { buildPiboAvailableTools, buildPiboGuidelines, hasPiboSystemPromptTemplateMarkers, } from "./system-prompt-template.js";
@@ -198,6 +199,8 @@ function generatedOriginForTool(name, profile) {
198
199
  return "Generated subagent tool from the profile's subagent list.";
199
200
  if (name.startsWith("pibo_run_"))
200
201
  return "Generated run-control tool from the pibo-run-control capability package.";
202
+ if (PIBO_GOAL_TOOL_NAMES.includes(name))
203
+ return "Generated goal-control tool from the pibo-goal-control capability package.";
201
204
  if (name === "apply_patch" || name === "view_image")
202
205
  return "Generated Codex-compatible tool from the codex-compat package.";
203
206
  if (profile.builtinToolNames.includes(name) || DEFAULT_BUILTIN_TOOL_NAMES.includes(name))
@@ -227,6 +230,8 @@ function badgesForSource(source) {
227
230
  return ["MANAGED"];
228
231
  case "plugin":
229
232
  return ["PLUGIN"];
233
+ case "pibo":
234
+ return ["PIBO"];
230
235
  case "pi":
231
236
  return ["PI"];
232
237
  case "provider":
@@ -315,10 +320,18 @@ export async function inspectPiboContextBuild(options = {}) {
315
320
  if (definition?.promptGuidelines?.length)
316
321
  promptGuidelines.push(...definition.promptGuidelines);
317
322
  }
318
- const diagnostics = runtime.diagnostics.map((diagnostic) => ({
319
- type: diagnostic.type,
320
- message: diagnostic.message,
321
- }));
323
+ const resourceInspection = options.resources?.getInspection();
324
+ const resourceDelivery = new Map(resourceInspection?.delivery.map((report) => [report.contributionId, report]) ?? []);
325
+ const diagnostics = [
326
+ ...runtime.diagnostics.map((diagnostic) => ({
327
+ type: diagnostic.type,
328
+ message: diagnostic.message,
329
+ })),
330
+ ...(resourceInspection?.diagnostics ?? []).map((diagnostic) => ({
331
+ type: diagnostic.severity,
332
+ message: diagnostic.message,
333
+ })),
334
+ ];
322
335
  if (profile.autoContextFiles === false) {
323
336
  diagnostics.push({ type: "info", message: "Pi automatic context files are disabled for this profile." });
324
337
  }
@@ -405,6 +418,15 @@ export async function inspectPiboContextBuild(options = {}) {
405
418
  }
406
419
  const toolChildren = toolNames.map((name) => {
407
420
  const providerTool = providerTools.find((tool) => tool.name === name);
421
+ const profileTool = profile.tools.find((tool) => tool.name === name);
422
+ const generatedOrigin = generatedOriginForTool(name, profile);
423
+ const toolSource = providerTool
424
+ ? "provider"
425
+ : generatedOrigin
426
+ ? "generated"
427
+ : profileTool
428
+ ? "pibo"
429
+ : "pi";
408
430
  const definition = runtime.session.getToolDefinition(name);
409
431
  const info = toolInfoByName.get(name);
410
432
  const children = [];
@@ -413,7 +435,7 @@ export async function inspectPiboContextBuild(options = {}) {
413
435
  id: `tools/${name}/prompt-snippet`,
414
436
  kind: "tool_prompt_snippet",
415
437
  title: "Prompt Snippet",
416
- source: providerTool ? "provider" : "pi",
438
+ source: toolSource,
417
439
  state: "active",
418
440
  hydratedText: definition.promptSnippet,
419
441
  });
@@ -423,7 +445,7 @@ export async function inspectPiboContextBuild(options = {}) {
423
445
  id: `tools/${name}/prompt-guidelines`,
424
446
  kind: "tool_prompt_guidelines",
425
447
  title: "Prompt Guidelines",
426
- source: providerTool ? "provider" : "pi",
448
+ source: toolSource,
427
449
  state: "active",
428
450
  hydratedText: definition.promptGuidelines.map((guideline) => `- ${guideline}`).join("\n"),
429
451
  metadata: { guidelineCount: definition.promptGuidelines.length },
@@ -435,16 +457,16 @@ export async function inspectPiboContextBuild(options = {}) {
435
457
  id: `tools/${name}/definition`,
436
458
  kind: "tool_definition",
437
459
  title: "Tool Definition / Schema",
438
- source: providerTool ? "provider" : "pi",
460
+ source: toolSource,
439
461
  state: "active",
440
462
  schemaJson: {
441
463
  name,
442
464
  description: definition?.description ?? info?.description,
465
+ inputSchema: schema,
443
466
  parameters: schema,
444
467
  },
445
468
  });
446
469
  }
447
- const generatedOrigin = generatedOriginForTool(name, profile);
448
470
  if (generatedOrigin) {
449
471
  children.push({
450
472
  id: `tools/${name}/generated-origin`,
@@ -452,7 +474,7 @@ export async function inspectPiboContextBuild(options = {}) {
452
474
  title: "Generated Origin",
453
475
  source: "generated",
454
476
  state: "active",
455
- badges: ["GENERATED"],
477
+ badges: ["GENERATED", "PIBO"],
456
478
  hydratedText: generatedOrigin,
457
479
  });
458
480
  }
@@ -485,23 +507,24 @@ export async function inspectPiboContextBuild(options = {}) {
485
507
  id: `tools/${name}/no-prompt-text`,
486
508
  kind: "metadata",
487
509
  title: "No Prompt Text",
488
- source: providerTool ? "provider" : "pi",
510
+ source: toolSource,
489
511
  state: "active",
490
- hydratedText: "This tool has no separate prompt snippet or guideline exposed by Pi. Its callable schema is the model-visible contribution.",
512
+ hydratedText: "This tool has no separate prompt snippet or guideline. Its callable JSON Schema is the model-visible contribution.",
491
513
  approximate: true,
492
514
  });
493
515
  }
494
516
  const badges = [
495
517
  "ACTIVE",
496
518
  ...(providerTool ? ["PROVIDER-BACKED"] : []),
497
- ...(generatedOrigin ? ["GENERATED"] : []),
519
+ ...(generatedOrigin ? ["GENERATED", "PIBO"] : []),
520
+ ...(toolSource === "pibo" ? ["PIBO"] : []),
498
521
  ...(profile.builtinToolNames.includes(name) || DEFAULT_BUILTIN_TOOL_NAMES.includes(name) ? ["PI"] : []),
499
522
  ];
500
523
  return {
501
524
  id: `tools/${name}`,
502
525
  kind: "tool",
503
526
  title: name,
504
- source: providerTool ? "provider" : generatedOrigin ? "generated" : "pi",
527
+ source: toolSource,
505
528
  state: "active",
506
529
  provider: providerTool?.providerTool.provider,
507
530
  badges,
@@ -509,29 +532,49 @@ export async function inspectPiboContextBuild(options = {}) {
509
532
  registered: Boolean(info || providerTool),
510
533
  hasDefinition: Boolean(definition || info),
511
534
  description: definition?.description ?? info?.description ?? providerTool?.description,
535
+ ...(toolSource === "pibo" || toolSource === "generated" ? { owner: "pibo", deliveryMode: "direct" } : {}),
512
536
  },
513
537
  children,
514
538
  };
515
539
  });
516
540
  const agentsFiles = resourceLoader.getAgentsFiles().agentsFiles;
517
541
  const installedToolContextFile = getInstalledCliToolContextFile();
518
- const mcpAgentContextFile = await getMcpAgentContextFile(profile.mcpServers);
542
+ const mcpAgentContextFile = options.resources
543
+ ? options.resources.getContextContributions().find((contribution) => contribution.id === "context:enabled-mcp-servers")
544
+ : await getMcpAgentContextFile(profile.mcpServers);
519
545
  const contextChildren = agentsFiles.map((contextFile) => {
520
546
  const source = contextFile.path === installedToolContextFile?.path
521
547
  ? "generated"
522
548
  : contextFile.path === mcpAgentContextFile?.path
523
549
  ? "generated"
524
550
  : sourceForContextFile(contextFile.path, profile, cwd);
551
+ const contribution = resourceInspection?.context.find((candidate) => candidate.path === contextFile.path
552
+ || candidate.sourcePath === contextFile.path
553
+ || candidate.materializedPath === contextFile.path);
554
+ const delivery = contribution ? resourceDelivery.get(contribution.id) : undefined;
525
555
  return {
526
556
  id: `context-files/${contextFile.path}`,
527
557
  kind: "context_file",
528
558
  title: contextFile.path.split("/").pop() || contextFile.path,
529
559
  source,
530
- state: "active",
560
+ state: delivery?.status === "failed" || delivery?.status === "unsupported"
561
+ ? "error"
562
+ : delivery?.status === "degraded"
563
+ ? "warning"
564
+ : "active",
531
565
  path: contextFile.path,
532
566
  bytes: byteLength(contextFile.content),
533
- badges: [...badgesForSource(source), ...(contextFile.path === "pibo://runtime/session-context.md" ? ["LOCKED"] : [])],
534
- metadata: { path: contextFile.path },
567
+ badges: [
568
+ ...badgesForSource(source),
569
+ ...(contextFile.path === "pibo://runtime/session-context.md" ? ["LOCKED"] : []),
570
+ ...(delivery ? [delivery.status.toUpperCase(), delivery.mode.toUpperCase(), delivery.fidelity.toUpperCase()] : []),
571
+ ],
572
+ metadata: {
573
+ path: contextFile.path,
574
+ ...(contribution ? { contributionId: contribution.id, intent: contribution.intent, required: contribution.required } : {}),
575
+ ...(delivery ? { deliveryStatus: delivery.status, deliveryMode: delivery.mode, fidelity: delivery.fidelity, target: delivery.target } : {}),
576
+ },
577
+ notes: delivery?.diagnostic ? [delivery.diagnostic] : undefined,
535
578
  hydratedText: contextFile.content,
536
579
  };
537
580
  });
@@ -540,6 +583,8 @@ export async function inspectPiboContextBuild(options = {}) {
540
583
  for (const skill of skills) {
541
584
  const markdown = await readSkillMarkdown(skill.filePath);
542
585
  const promptEntry = formatSkillEntryForPrompt(skill);
586
+ const resourceSkill = resourceInspection?.skills.find((candidate) => candidate.name === skill.name);
587
+ const delivery = resourceSkill ? resourceDelivery.get(resourceSkill.contributionId) : undefined;
543
588
  // The skill node reports only what is actually part of the model
544
589
  // prompt: the formatted <skill>...</skill> entry. The full
545
590
  // SKILL.md body is loaded lazily by the model via the read tool
@@ -553,20 +598,62 @@ export async function inspectPiboContextBuild(options = {}) {
553
598
  source: "plugin",
554
599
  path: skill.filePath,
555
600
  bytes: byteLength(promptEntry),
556
- badges: ["ACTIVE"],
601
+ badges: [
602
+ "ACTIVE",
603
+ ...(delivery ? [delivery.status.toUpperCase(), delivery.mode.toUpperCase(), delivery.fidelity.toUpperCase()] : []),
604
+ ],
557
605
  metadata: {
558
606
  description: skill.description,
559
607
  filePath: skill.filePath,
560
608
  disableModelInvocation: skill.disableModelInvocation,
561
609
  fullFileBytes: markdown ? byteLength(markdown) : undefined,
562
610
  fullFileLoadableBy: "read tool, /skill:name command, $skill-name inline expansion",
611
+ ...(resourceSkill ? { contributionId: resourceSkill.contributionId, kind: resourceSkill.kind } : {}),
612
+ ...(delivery ? { deliveryStatus: delivery.status, deliveryMode: delivery.mode, fidelity: delivery.fidelity, target: delivery.target } : {}),
563
613
  },
564
614
  hydratedText: markdown === undefined
565
615
  ? `Skill metadata is loaded, but ${skill.filePath} could not be read for inspection.`
566
616
  : promptEntry,
567
- state: markdown ? "active" : "warning",
617
+ state: delivery?.status === "failed" || delivery?.status === "unsupported"
618
+ ? "error"
619
+ : delivery?.status === "degraded" || markdown === undefined
620
+ ? "warning"
621
+ : "active",
622
+ notes: delivery?.diagnostic ? [delivery.diagnostic] : undefined,
568
623
  });
569
624
  }
625
+ const mcpChildren = (resourceInspection?.mcpServers ?? []).map((server) => {
626
+ const delivery = resourceDelivery.get(server.contributionId);
627
+ return {
628
+ id: `mcp/${server.name}`,
629
+ kind: "runtime_extension",
630
+ title: server.name,
631
+ source: "profile",
632
+ state: server.status === "failed" || delivery?.status === "failed" || delivery?.status === "unsupported"
633
+ ? "error"
634
+ : delivery?.status === "degraded"
635
+ ? "warning"
636
+ : "active",
637
+ badges: [
638
+ server.status.toUpperCase(),
639
+ ...(delivery ? [delivery.mode.toUpperCase(), delivery.fidelity.toUpperCase()] : []),
640
+ ],
641
+ metadata: {
642
+ contributionId: server.contributionId,
643
+ transport: server.transport,
644
+ serverName: server.serverName,
645
+ serverVersion: server.serverVersion,
646
+ protocolVersion: server.protocolVersion,
647
+ toolNames: server.tools.map((tool) => tool.name),
648
+ resourceUris: server.resources.map((resource) => resource.uri),
649
+ resourceTemplates: server.resourceTemplates.map((resource) => resource.uriTemplate),
650
+ secretEnvironmentKeys: server.secretEnvironmentKeys,
651
+ ...(delivery ? { deliveryStatus: delivery.status, deliveryMode: delivery.mode, fidelity: delivery.fidelity, target: delivery.target } : {}),
652
+ },
653
+ hydratedText: server.instructions,
654
+ notes: [server.diagnostic, delivery?.diagnostic].filter((value) => Boolean(value)),
655
+ };
656
+ });
570
657
  const extensionChildren = [];
571
658
  if (providerTools.length > 0) {
572
659
  extensionChildren.push(...providerTools.map((tool) => ({
@@ -645,6 +732,23 @@ export async function inspectPiboContextBuild(options = {}) {
645
732
  metadata: { childCount: skillChildren.length },
646
733
  children: skillChildren,
647
734
  },
735
+ ...(mcpChildren.length > 0 ? [{
736
+ id: "mcp",
737
+ kind: "runtime_extension",
738
+ title: "External MCP Servers",
739
+ source: "runtime",
740
+ state: mcpChildren.some((node) => node.state === "error")
741
+ ? "error"
742
+ : mcpChildren.some((node) => node.state === "warning")
743
+ ? "warning"
744
+ : "active",
745
+ badges: [mcpChildren.every((node) => node.state === "active") ? "CONNECTED" : "DIAGNOSTICS"],
746
+ metadata: {
747
+ selectedServers: mcpChildren.length,
748
+ connectedServers: mcpChildren.filter((node) => node.badges?.includes("CONNECTED")).length,
749
+ },
750
+ children: mcpChildren,
751
+ }] : []),
648
752
  {
649
753
  id: "runtime-extensions",
650
754
  kind: "runtime_extension",
@@ -0,0 +1,8 @@
1
+ import { InitialSessionContextBuilder } from "./profiles.js";
2
+ export const DEFAULT_PIBO_PROFILE_NAME = "base";
3
+ export function createDefaultPiboProfile() {
4
+ return new InitialSessionContextBuilder(DEFAULT_PIBO_PROFILE_NAME)
5
+ .withBuiltinToolNames(["read", "bash", "edit", "write"])
6
+ .withToolPackages({ goalControl: true })
7
+ .createSession();
8
+ }