@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,635 @@
1
+ import { chmod, readFile, rm, stat, writeFile, } from "node:fs/promises";
2
+ import { basename, isAbsolute, join, resolve } from "node:path";
3
+ import { PIBO_APP_CONTEXT } from "../app-context.js";
4
+ import { piboHomePath } from "../core/pibo-home.js";
5
+ import { DEFAULT_USER_TIMEZONE } from "../core/user-settings.js";
6
+ import { isHttpServer, loadConfigUnresolved, } from "../mcp/config.js";
7
+ import { redactMcpRuntimeError as redactResourceError, scopePiboMcpServerConfig, verifyPiboMcpServer, } from "../mcp/runtime-session.js";
8
+ import { getMcpAgentContextFileFromConfig } from "../mcp/agent-context.js";
9
+ import { getInstalledCliToolContextFile } from "../tools/registry.js";
10
+ import { copyAgentRuntimeSkillDirectory, createAgentRuntimeResourcePaths, } from "./resource-files.js";
11
+ const DEFAULT_MCP_VERIFY_TIMEOUT_MS = 15_000;
12
+ const DEFAULT_MAX_SKILL_FILES = 2_048;
13
+ const DEFAULT_MAX_SKILL_BYTES = 64 * 1024 * 1024;
14
+ const MCP_CONFIG_FILE = "mcp-servers.json";
15
+ const ENABLED_MCP_CONTEXT_ID = "context:enabled-mcp-servers";
16
+ export class PiboRuntimeResourceError extends Error {
17
+ diagnostics;
18
+ constructor(message, diagnostics) {
19
+ super(message);
20
+ this.diagnostics = diagnostics;
21
+ this.name = "PiboRuntimeResourceError";
22
+ }
23
+ }
24
+ function positiveInteger(value, fallback, label) {
25
+ const resolved = value ?? fallback;
26
+ if (!Number.isSafeInteger(resolved) || resolved <= 0)
27
+ throw new Error(`${label} must be a positive integer`);
28
+ return resolved;
29
+ }
30
+ function normalizeIdentifier(value, label) {
31
+ const normalized = value.trim();
32
+ if (!normalized)
33
+ throw new Error(`${label} is required`);
34
+ return normalized;
35
+ }
36
+ function slug(value) {
37
+ return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64) || "resource";
38
+ }
39
+ function resolveProfilePath(cwd, path) {
40
+ return isAbsolute(path) ? path : resolve(cwd, path);
41
+ }
42
+ function deliveryMode(delivery) {
43
+ if (delivery.support === "mcp")
44
+ return `mcp:${delivery.transports.join(",")}`;
45
+ if (delivery.support === "materialized")
46
+ return `materialized:${delivery.modes.join(",")}`;
47
+ if (delivery.support === "degraded")
48
+ return `degraded:${delivery.mode}`;
49
+ return delivery.support;
50
+ }
51
+ function deliveryFor(input) {
52
+ if (input.failure) {
53
+ return {
54
+ contributionId: input.contributionId,
55
+ status: "failed",
56
+ mode: input.modeOverride ?? deliveryMode(input.delivery),
57
+ fidelity: "none",
58
+ diagnostic: input.failure,
59
+ };
60
+ }
61
+ if (input.delivery.support === "unsupported") {
62
+ return {
63
+ contributionId: input.contributionId,
64
+ status: "unsupported",
65
+ mode: "unsupported",
66
+ fidelity: "none",
67
+ diagnostic: input.delivery.reason,
68
+ };
69
+ }
70
+ if (input.delivery.support === "degraded") {
71
+ return {
72
+ contributionId: input.contributionId,
73
+ status: "degraded",
74
+ mode: input.modeOverride ?? input.delivery.mode,
75
+ fidelity: input.fidelity ?? "lossy",
76
+ ...(input.target ? { target: input.target } : {}),
77
+ diagnostic: input.delivery.reason,
78
+ };
79
+ }
80
+ return {
81
+ contributionId: input.contributionId,
82
+ status: "delivered",
83
+ mode: input.modeOverride ?? deliveryMode(input.delivery),
84
+ fidelity: input.fidelity ?? "exact",
85
+ ...(input.target ? { target: input.target } : {}),
86
+ };
87
+ }
88
+ function sessionContextContribution(input) {
89
+ const piboRoomId = input.piboRoomId?.trim() || "unknown";
90
+ const timezone = input.timezone?.trim() || DEFAULT_USER_TIMEZONE;
91
+ return {
92
+ id: "context:pibo-session",
93
+ kind: "product",
94
+ source: "pibo-product",
95
+ intent: "session",
96
+ label: "Pibo Runtime Context",
97
+ required: false,
98
+ order: 100,
99
+ path: "pibo://runtime/session-context.md",
100
+ content: [
101
+ "# Pibo Runtime Context",
102
+ "",
103
+ `- App context: ${PIBO_APP_CONTEXT.id}`,
104
+ `- Pibo Session ID: ${input.piboSessionId}`,
105
+ `- Pibo Room ID: ${piboRoomId}`,
106
+ `- User timezone: ${timezone}`,
107
+ "",
108
+ "Login identity gates app access only. Use the Pibo Session ID or Room ID when scheduling jobs, correlating events, or referring to the current session or room.",
109
+ ].join("\n"),
110
+ };
111
+ }
112
+ function contextSource(file) {
113
+ if (file.source === "managed")
114
+ return "managed";
115
+ if (file.source === "plugin")
116
+ return "plugin";
117
+ return "profile";
118
+ }
119
+ class RuntimeResourceSession {
120
+ input;
121
+ options;
122
+ onDispose;
123
+ piboSessionId;
124
+ runtimeInstanceId;
125
+ adapterId;
126
+ sessionGeneration;
127
+ context = [];
128
+ skills = [];
129
+ mcpServers = [];
130
+ delivery = [];
131
+ diagnostics = [];
132
+ requiredContributionIds = new Set();
133
+ paths;
134
+ adapterEnvironment = {};
135
+ resolvedMcpConfigs = {};
136
+ disposed = false;
137
+ constructor(input, options, onDispose) {
138
+ this.input = input;
139
+ this.options = options;
140
+ this.onDispose = onDispose;
141
+ this.piboSessionId = input.piboSessionId;
142
+ this.runtimeInstanceId = input.runtimeInstanceId;
143
+ this.adapterId = input.adapterId;
144
+ this.sessionGeneration = input.sessionGeneration;
145
+ }
146
+ async prepare() {
147
+ await this.prepareMcpServers();
148
+ await this.prepareContext();
149
+ await this.prepareSkills();
150
+ try {
151
+ await this.materialize();
152
+ }
153
+ catch (error) {
154
+ const message = `Runtime generation directory could not be materialized: ${redactResourceError(error)}`;
155
+ const contributionIds = [
156
+ ...(this.input.capabilities.skills.support === "materialized" ? this.skills.map((skill) => skill.contributionId) : []),
157
+ ...(this.input.capabilities.context.support === "materialized" ? this.context.filter((item) => item.content !== undefined).map((item) => item.id) : []),
158
+ ...this.mcpServers.filter((server) => server.scoped).map((server) => server.contributionId),
159
+ ];
160
+ for (const contributionId of contributionIds) {
161
+ if (this.diagnostics.some((diagnostic) => diagnostic.contributionId === contributionId && diagnostic.severity === "error"))
162
+ continue;
163
+ this.diagnostics.push({ severity: "error", code: "runtime_resource_materialization_failed", message, contributionId });
164
+ }
165
+ }
166
+ await this.verifyMcpServers();
167
+ this.buildDeliveryReports();
168
+ const blocking = this.delivery.filter((report) => this.requiredContributionIds.has(report.contributionId)
169
+ && (report.status === "failed" || report.status === "unsupported"));
170
+ if (this.input.strict !== false && blocking.length > 0) {
171
+ throw new PiboRuntimeResourceError(`Runtime resource preparation failed: ${blocking.map((report) => report.diagnostic ?? report.contributionId).join("; ")}`, this.diagnostics);
172
+ }
173
+ }
174
+ getContextContributions() {
175
+ this.assertActive();
176
+ return this.context.map((contribution) => ({ ...contribution }));
177
+ }
178
+ getSkillPaths(mode = "source") {
179
+ this.assertActive();
180
+ return this.skills.flatMap((skill) => {
181
+ const path = mode === "materialized" ? skill.materializedPath : skill.sourcePath;
182
+ return path ? [path] : [];
183
+ });
184
+ }
185
+ getMcpConfigPath() {
186
+ this.assertActive();
187
+ return this.paths && Object.keys(this.resolvedMcpConfigs).length > 0
188
+ ? join(this.paths.config, MCP_CONFIG_FILE)
189
+ : undefined;
190
+ }
191
+ getAdapterEnvironment() {
192
+ this.assertActive();
193
+ return { ...this.adapterEnvironment };
194
+ }
195
+ getExternalMcpServerConfigs() {
196
+ this.assertActive();
197
+ return structuredClone(this.resolvedMcpConfigs);
198
+ }
199
+ getInspection() {
200
+ this.assertActive();
201
+ return {
202
+ piboSessionId: this.piboSessionId,
203
+ runtimeInstanceId: this.runtimeInstanceId,
204
+ adapterId: this.adapterId,
205
+ sessionGeneration: this.sessionGeneration,
206
+ ...(this.paths ? { paths: { ...this.paths } } : {}),
207
+ skills: this.skills.map((skill) => ({ ...skill })),
208
+ context: this.context.map(({ content: _content, ...contribution }) => ({ ...contribution })),
209
+ mcpServers: this.mcpServers.map((server) => structuredClone(server.inspection)),
210
+ delivery: this.delivery.map((report) => ({ ...report })),
211
+ diagnostics: this.diagnostics.map((diagnostic) => ({ ...diagnostic })),
212
+ };
213
+ }
214
+ async dispose() {
215
+ if (this.disposed)
216
+ return;
217
+ this.disposed = true;
218
+ this.adapterEnvironment = {};
219
+ this.resolvedMcpConfigs = {};
220
+ try {
221
+ if (this.paths)
222
+ await rm(this.paths.root, { recursive: true, force: true });
223
+ }
224
+ finally {
225
+ this.onDispose();
226
+ }
227
+ }
228
+ async prepareMcpServers() {
229
+ const selected = [...new Set(this.input.profile.mcpServers.map((name) => name.trim()).filter(Boolean))];
230
+ for (const name of selected)
231
+ this.requiredContributionIds.add(`mcp:${name}`);
232
+ if (selected.length === 0)
233
+ return;
234
+ let config;
235
+ try {
236
+ config = await loadConfigUnresolved(this.options.mcpConfigPath);
237
+ }
238
+ catch (error) {
239
+ const message = redactResourceError(error);
240
+ for (const name of selected)
241
+ this.addFailedMcp(name, message);
242
+ return;
243
+ }
244
+ for (const name of selected) {
245
+ const serverConfig = config.mcpServers[name];
246
+ if (!serverConfig) {
247
+ this.addFailedMcp(name, `Selected MCP server "${name}" is not present in the merged MCP configuration.`);
248
+ continue;
249
+ }
250
+ try {
251
+ const scoped = scopePiboMcpServerConfig(name, serverConfig, this.options.environment);
252
+ this.mcpServers.push({
253
+ name,
254
+ contributionId: `mcp:${name}`,
255
+ transport: isHttpServer(serverConfig) ? "http" : "stdio",
256
+ scoped,
257
+ inspection: {
258
+ contributionId: `mcp:${name}`,
259
+ name,
260
+ transport: isHttpServer(serverConfig) ? "http" : "stdio",
261
+ status: "configured",
262
+ tools: [],
263
+ resources: [],
264
+ resourceTemplates: [],
265
+ secretEnvironmentKeys: scoped.secretEnvironmentKeys,
266
+ },
267
+ });
268
+ }
269
+ catch (error) {
270
+ this.addFailedMcp(name, redactResourceError(error));
271
+ }
272
+ }
273
+ const mcpContext = getMcpAgentContextFileFromConfig(selected, {
274
+ mcpServers: Object.fromEntries(selected.flatMap((name) => config.mcpServers[name] ? [[name, config.mcpServers[name]]] : [])),
275
+ });
276
+ if (mcpContext) {
277
+ this.context.push({
278
+ id: ENABLED_MCP_CONTEXT_ID,
279
+ kind: "generated",
280
+ source: "generated",
281
+ intent: "developer",
282
+ label: "Enabled MCP Servers",
283
+ required: false,
284
+ order: 400,
285
+ path: mcpContext.path,
286
+ content: mcpContext.content,
287
+ });
288
+ }
289
+ }
290
+ addFailedMcp(name, message) {
291
+ const contributionId = `mcp:${name}`;
292
+ this.mcpServers.push({
293
+ name,
294
+ contributionId,
295
+ transport: "stdio",
296
+ error: message,
297
+ inspection: {
298
+ contributionId,
299
+ name,
300
+ transport: "stdio",
301
+ status: "failed",
302
+ tools: [],
303
+ resources: [],
304
+ resourceTemplates: [],
305
+ secretEnvironmentKeys: [],
306
+ diagnostic: message,
307
+ },
308
+ });
309
+ this.diagnostics.push({ severity: "error", code: "runtime_mcp_configuration_failed", message, contributionId });
310
+ }
311
+ async prepareContext() {
312
+ if (this.input.profile.autoContextFiles) {
313
+ this.requiredContributionIds.add("context:automatic-project-files");
314
+ this.context.push({
315
+ id: "context:automatic-project-files",
316
+ kind: "automatic",
317
+ source: "profile",
318
+ intent: "project",
319
+ label: "Automatic AGENTS.md / CLAUDE.md discovery",
320
+ required: false,
321
+ order: 0,
322
+ });
323
+ }
324
+ this.context.push(sessionContextContribution(this.input));
325
+ for (const [index, file] of this.input.profile.contextFiles.entries()) {
326
+ if (file.enabled === false)
327
+ continue;
328
+ const id = `context:${file.key ?? file.path}`;
329
+ this.requiredContributionIds.add(id);
330
+ const sourcePath = resolveProfilePath(this.input.cwd, file.path);
331
+ try {
332
+ const content = await readFile(sourcePath, "utf8");
333
+ this.context.push({
334
+ id,
335
+ kind: "context-file",
336
+ source: contextSource(file),
337
+ intent: file.scope === "agent" ? "developer" : "project",
338
+ label: file.label ?? file.key ?? basename(file.path),
339
+ required: true,
340
+ order: 200 + index,
341
+ path: sourcePath,
342
+ sourcePath,
343
+ content,
344
+ });
345
+ }
346
+ catch (error) {
347
+ const message = `Context file "${file.key ?? file.path}" could not be loaded: ${redactResourceError(error)}`;
348
+ this.context.push({
349
+ id,
350
+ kind: "context-file",
351
+ source: contextSource(file),
352
+ intent: file.scope === "agent" ? "developer" : "project",
353
+ label: file.label ?? file.key ?? basename(file.path),
354
+ required: true,
355
+ order: 200 + index,
356
+ path: sourcePath,
357
+ sourcePath,
358
+ });
359
+ this.diagnostics.push({ severity: "error", code: "runtime_context_file_failed", message, contributionId: id });
360
+ }
361
+ }
362
+ const installedTools = getInstalledCliToolContextFile();
363
+ if (installedTools) {
364
+ this.context.push({
365
+ id: "context:installed-pibo-tools",
366
+ kind: "generated",
367
+ source: "generated",
368
+ intent: "developer",
369
+ label: "Installed Pibo Tools",
370
+ required: false,
371
+ order: 300,
372
+ path: installedTools.path,
373
+ content: installedTools.content,
374
+ });
375
+ }
376
+ for (const contribution of this.context) {
377
+ if (contribution.content !== undefined)
378
+ contribution.byteSize = Buffer.byteLength(contribution.content, "utf8");
379
+ }
380
+ this.context.sort((left, right) => left.order - right.order || left.id.localeCompare(right.id));
381
+ }
382
+ async prepareSkills() {
383
+ for (const skill of this.input.profile.skills) {
384
+ if (skill.enabled === false)
385
+ continue;
386
+ const contributionId = `skill:${skill.name}`;
387
+ this.requiredContributionIds.add(contributionId);
388
+ const sourcePath = resolveProfilePath(this.input.cwd, skill.path);
389
+ const resource = {
390
+ contributionId,
391
+ name: skill.name,
392
+ kind: skill.kind ?? "plugin",
393
+ required: true,
394
+ sourcePath,
395
+ };
396
+ this.skills.push(resource);
397
+ try {
398
+ const metadata = await stat(sourcePath);
399
+ if (!metadata.isFile())
400
+ throw new Error("skill path is not a file");
401
+ }
402
+ catch (error) {
403
+ const message = `Skill "${skill.name}" could not be loaded: ${redactResourceError(error)}`;
404
+ this.diagnostics.push({ severity: "error", code: "runtime_skill_failed", message, contributionId });
405
+ }
406
+ }
407
+ }
408
+ async materialize() {
409
+ const materializeSkills = this.input.capabilities.skills.support === "materialized" && this.skills.length > 0;
410
+ const materializeContext = this.input.capabilities.context.support === "materialized" && this.context.some((item) => item.content !== undefined);
411
+ const materializeMcp = this.mcpServers.some((server) => server.scoped !== undefined);
412
+ if (!materializeSkills && !materializeContext && !materializeMcp)
413
+ return;
414
+ this.paths = await createAgentRuntimeResourcePaths(this.options.rootDir, this.input);
415
+ if (materializeSkills) {
416
+ for (const skill of this.skills) {
417
+ if (this.diagnostics.some((diagnostic) => diagnostic.contributionId === skill.contributionId && diagnostic.severity === "error"))
418
+ continue;
419
+ try {
420
+ skill.materializedPath = await copyAgentRuntimeSkillDirectory(skill, this.paths.skills, {
421
+ maxFiles: this.options.maxSkillFiles,
422
+ maxBytes: this.options.maxSkillBytes,
423
+ });
424
+ }
425
+ catch (error) {
426
+ const message = `Skill "${skill.name}" could not be materialized: ${redactResourceError(error)}`;
427
+ this.diagnostics.push({ severity: "error", code: "runtime_skill_materialization_failed", message, contributionId: skill.contributionId });
428
+ }
429
+ }
430
+ }
431
+ if (materializeContext) {
432
+ let materializedIndex = 0;
433
+ for (const contribution of this.context) {
434
+ if (contribution.content === undefined)
435
+ continue;
436
+ const target = join(this.paths.context, `${String(materializedIndex++).padStart(3, "0")}-${slug(contribution.label)}.md`);
437
+ try {
438
+ await writeFile(target, contribution.content, { encoding: "utf8", mode: 0o600 });
439
+ await chmod(target, 0o600);
440
+ contribution.materializedPath = target;
441
+ }
442
+ catch (error) {
443
+ const message = `Context contribution "${contribution.label}" could not be materialized: ${redactResourceError(error)}`;
444
+ this.diagnostics.push({ severity: "error", code: "runtime_context_materialization_failed", message, contributionId: contribution.id });
445
+ }
446
+ }
447
+ }
448
+ if (materializeMcp) {
449
+ const materializedConfigs = {};
450
+ for (const server of this.mcpServers) {
451
+ if (!server.scoped)
452
+ continue;
453
+ materializedConfigs[server.name] = server.scoped.materialized;
454
+ this.resolvedMcpConfigs[server.name] = server.scoped.resolved;
455
+ Object.assign(this.adapterEnvironment, server.scoped.secretEnvironment);
456
+ }
457
+ const configPath = join(this.paths.config, MCP_CONFIG_FILE);
458
+ await writeFile(configPath, `${JSON.stringify({ mcpServers: materializedConfigs }, null, 2)}\n`, { encoding: "utf8", mode: 0o600 });
459
+ await chmod(configPath, 0o600);
460
+ this.adapterEnvironment.MCP_CONFIG_PATH = configPath;
461
+ this.adapterEnvironment.MCP_NO_DAEMON = "1";
462
+ this.adapterEnvironment.MCP_STRICT_ENV = "true";
463
+ this.adapterEnvironment.PIBO_MCP_ISOLATED_ENV = "1";
464
+ }
465
+ }
466
+ async verifyMcpServers() {
467
+ const shouldVerify = this.input.verifyMcp !== false;
468
+ if (!shouldVerify)
469
+ return;
470
+ for (const server of this.mcpServers) {
471
+ if (!server.scoped || server.error)
472
+ continue;
473
+ const delivery = this.input.capabilities.mcp.externalServers;
474
+ const transport = server.transport === "http" ? "streamable-http" : "stdio";
475
+ if (delivery.support === "mcp" && !delivery.transports.includes(transport))
476
+ continue;
477
+ try {
478
+ const result = await this.options.verifyMcpServer(server.name, server.scoped.resolved, {
479
+ timeoutMs: this.options.mcpVerifyTimeoutMs,
480
+ });
481
+ server.inspection = {
482
+ ...server.inspection,
483
+ ...result,
484
+ status: "connected",
485
+ };
486
+ }
487
+ catch (error) {
488
+ const message = redactResourceError(error, Object.values(server.scoped.secretEnvironment));
489
+ server.error = message;
490
+ server.inspection = { ...server.inspection, status: "failed", diagnostic: message };
491
+ this.diagnostics.push({ severity: "error", code: "runtime_mcp_verification_failed", message, contributionId: server.contributionId });
492
+ }
493
+ }
494
+ }
495
+ buildDeliveryReports() {
496
+ for (const skill of this.skills) {
497
+ const failure = this.diagnosticFor(skill.contributionId);
498
+ this.delivery.push(deliveryFor({
499
+ contributionId: skill.contributionId,
500
+ delivery: this.input.capabilities.skills,
501
+ target: this.input.capabilities.skills.support === "materialized" ? skill.materializedPath : skill.sourcePath,
502
+ failure,
503
+ }));
504
+ }
505
+ for (const contribution of this.context) {
506
+ const failure = this.diagnosticFor(contribution.id);
507
+ if (contribution.id === ENABLED_MCP_CONTEXT_ID
508
+ && this.input.capabilities.mcp.externalServers.support === "mcp") {
509
+ this.delivery.push({
510
+ contributionId: contribution.id,
511
+ status: failure ? "failed" : "delivered",
512
+ mode: "native-mcp-inventory",
513
+ fidelity: failure ? "none" : "equivalent",
514
+ ...(this.getMcpConfigPath() ? { target: this.getMcpConfigPath() } : {}),
515
+ ...(failure ? { diagnostic: failure } : {}),
516
+ });
517
+ continue;
518
+ }
519
+ if (contribution.kind === "automatic" && this.input.capabilities.context.support === "materialized") {
520
+ const supportsNativeDiscovery = this.input.capabilities.context.modes.includes("native-project-discovery");
521
+ this.delivery.push(supportsNativeDiscovery
522
+ ? {
523
+ contributionId: contribution.id,
524
+ status: "delivered",
525
+ mode: "native-project-discovery",
526
+ fidelity: "equivalent",
527
+ target: this.input.cwd,
528
+ }
529
+ : {
530
+ contributionId: contribution.id,
531
+ status: "unsupported",
532
+ mode: "unsupported:auto-context-discovery",
533
+ fidelity: "none",
534
+ diagnostic: "This runtime materializes explicit context but does not declare native-project-discovery for automatic AGENTS.md / CLAUDE.md context.",
535
+ });
536
+ continue;
537
+ }
538
+ this.delivery.push(deliveryFor({
539
+ contributionId: contribution.id,
540
+ delivery: this.input.capabilities.context,
541
+ target: this.input.capabilities.context.support === "materialized"
542
+ ? contribution.materializedPath
543
+ : contribution.path ?? contribution.sourcePath ?? this.input.cwd,
544
+ failure,
545
+ fidelity: contribution.kind === "automatic" ? "equivalent" : "exact",
546
+ modeOverride: contribution.kind === "automatic" ? "native-discovery" : undefined,
547
+ }));
548
+ }
549
+ for (const server of this.mcpServers) {
550
+ const delivery = this.input.capabilities.mcp.externalServers;
551
+ const transport = server.transport === "http" ? "streamable-http" : "stdio";
552
+ if (delivery.support === "mcp" && !delivery.transports.includes(transport)) {
553
+ const diagnostic = `This runtime does not support selected MCP transport "${transport}".`;
554
+ this.diagnostics.push({
555
+ severity: "error",
556
+ code: "runtime_mcp_transport_unsupported",
557
+ message: diagnostic,
558
+ contributionId: server.contributionId,
559
+ });
560
+ this.delivery.push({
561
+ contributionId: server.contributionId,
562
+ status: "unsupported",
563
+ mode: `unsupported:mcp:${transport}`,
564
+ fidelity: "none",
565
+ diagnostic,
566
+ });
567
+ continue;
568
+ }
569
+ const requiresInspection = this.input.verifyMcp !== false;
570
+ const unverified = requiresInspection && server.inspection.status !== "connected" && !server.error
571
+ ? `MCP server "${server.name}" was not verified as connected.`
572
+ : undefined;
573
+ this.delivery.push(deliveryFor({
574
+ contributionId: server.contributionId,
575
+ delivery,
576
+ target: this.getMcpConfigPath(),
577
+ failure: server.error ?? unverified,
578
+ fidelity: "exact",
579
+ }));
580
+ }
581
+ }
582
+ diagnosticFor(contributionId) {
583
+ return this.diagnostics.find((diagnostic) => diagnostic.contributionId === contributionId && diagnostic.severity === "error")?.message;
584
+ }
585
+ assertActive() {
586
+ if (this.disposed)
587
+ throw new Error(`Runtime resources for Pibo session "${this.piboSessionId}" are disposed.`);
588
+ }
589
+ }
590
+ export class PiboRuntimeResourceService {
591
+ sessions = new Map();
592
+ options;
593
+ constructor(options = {}) {
594
+ this.options = {
595
+ rootDir: options.rootDir ?? piboHomePath("agent-runtimes"),
596
+ mcpConfigPath: options.mcpConfigPath ?? options.environment?.MCP_CONFIG_PATH,
597
+ environment: { ...(options.environment ?? process.env) },
598
+ verifyMcpServer: options.verifyMcpServer ?? verifyPiboMcpServer,
599
+ mcpVerifyTimeoutMs: positiveInteger(options.mcpVerifyTimeoutMs, DEFAULT_MCP_VERIFY_TIMEOUT_MS, "mcpVerifyTimeoutMs"),
600
+ maxSkillFiles: positiveInteger(options.maxSkillFiles, DEFAULT_MAX_SKILL_FILES, "maxSkillFiles"),
601
+ maxSkillBytes: positiveInteger(options.maxSkillBytes, DEFAULT_MAX_SKILL_BYTES, "maxSkillBytes"),
602
+ };
603
+ }
604
+ async createSession(input) {
605
+ const normalized = {
606
+ ...input,
607
+ piboSessionId: normalizeIdentifier(input.piboSessionId, "piboSessionId"),
608
+ runtimeInstanceId: normalizeIdentifier(input.runtimeInstanceId, "runtimeInstanceId"),
609
+ adapterId: normalizeIdentifier(input.adapterId, "adapterId"),
610
+ sessionGeneration: normalizeIdentifier(input.sessionGeneration, "sessionGeneration"),
611
+ cwd: normalizeIdentifier(input.cwd, "cwd"),
612
+ };
613
+ const key = `${normalized.piboSessionId}\0${normalized.sessionGeneration}`;
614
+ if (this.sessions.has(key))
615
+ throw new Error(`Runtime resource session already exists for generation "${normalized.sessionGeneration}".`);
616
+ const session = new RuntimeResourceSession(normalized, this.options, () => {
617
+ if (this.sessions.get(key) === session)
618
+ this.sessions.delete(key);
619
+ });
620
+ try {
621
+ await session.prepare();
622
+ this.sessions.set(key, session);
623
+ return session;
624
+ }
625
+ catch (error) {
626
+ await session.dispose().catch(() => { });
627
+ throw error;
628
+ }
629
+ }
630
+ async dispose() {
631
+ const sessions = [...this.sessions.values()];
632
+ this.sessions.clear();
633
+ await Promise.allSettled(sessions.map((session) => session.dispose()));
634
+ }
635
+ }
@@ -0,0 +1 @@
1
+ export {};