@pasko70/pibo 1.16.6 → 2.1.1

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 (156) 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/omp/adapter.js +581 -0
  33. package/dist/agent-runtimes/omp/auth.js +109 -0
  34. package/dist/agent-runtimes/omp/client.js +460 -0
  35. package/dist/agent-runtimes/omp/config.js +188 -0
  36. package/dist/agent-runtimes/omp/history.js +108 -0
  37. package/dist/agent-runtimes/omp/host-tools.js +201 -0
  38. package/dist/agent-runtimes/omp/models.js +86 -0
  39. package/dist/agent-runtimes/omp/process.js +283 -0
  40. package/dist/agent-runtimes/omp/protocol-types.js +17 -0
  41. package/dist/agent-runtimes/omp/resource-delivery.js +162 -0
  42. package/dist/agent-runtimes/omp/thread.js +141 -0
  43. package/dist/agent-runtimes/omp/turn.js +325 -0
  44. package/dist/agent-runtimes/pi/adapter.js +653 -0
  45. package/dist/agent-runtimes/pi/auth.js +455 -0
  46. package/dist/agent-runtimes/pi/history.js +640 -0
  47. package/dist/agent-runtimes/pi/model-catalog.js +87 -0
  48. package/dist/agent-runtimes/pi/routed-session.js +1464 -0
  49. package/dist/agent-runtimes/pi/runtime.js +534 -0
  50. package/dist/agent-runtimes/pi/tool-compiler.js +69 -0
  51. package/dist/apps/chat/agent-profiles.js +40 -23
  52. package/dist/apps/chat/agent-store.js +111 -64
  53. package/dist/apps/chat/chat-api-routes.js +1 -1
  54. package/dist/apps/chat/chat-request-normalizers.js +47 -0
  55. package/dist/apps/chat/data/chat-data-mappers.js +25 -9
  56. package/dist/apps/chat/data/history-query-service.js +108 -0
  57. package/dist/apps/chat/data/session-query-service.js +24 -3
  58. package/dist/apps/chat/data/timeline-query-service.js +3 -3
  59. package/dist/apps/chat/model-catalog.js +1 -55
  60. package/dist/apps/chat/provider-auth-actions.js +171 -23
  61. package/dist/apps/chat/stream.js +12 -0
  62. package/dist/apps/chat/trace-v2.js +1 -0
  63. package/dist/apps/chat/trace.js +126 -415
  64. package/dist/apps/chat/web-app.js +582 -157
  65. package/dist/apps/chat-ui/assets/{dist-BTLtT_Vf.js → dist-9v2ZXT6V.js} +1 -1
  66. package/dist/apps/chat-ui/assets/{dist-CMk1aPug.js → dist-B1LVAytl.js} +1 -1
  67. package/dist/apps/chat-ui/assets/{dist-CcwA_IWN.js → dist-C6LPDFXU.js} +1 -1
  68. package/dist/apps/chat-ui/assets/{dist-DKOthbxr.js → dist-DVtXxfHc.js} +1 -1
  69. package/dist/apps/chat-ui/assets/{dist-ls2I6BIw.js → dist-DW4Qrfbd.js} +1 -1
  70. package/dist/apps/chat-ui/assets/{dist-D1rAtRWs.js → dist-DmbsHdMC.js} +1 -1
  71. package/dist/apps/chat-ui/assets/{dist-C1JQRskW.js → dist-DyvwuSFO.js} +1 -1
  72. package/dist/apps/chat-ui/assets/{dist-DfpaylQ-.js → dist-I26VB0QO.js} +1 -1
  73. package/dist/apps/chat-ui/assets/{dist-D10bTFD5.js → dist-RtHbJRPV.js} +1 -1
  74. package/dist/apps/chat-ui/assets/{dist-5KpmmBBZ.js → dist-sZgJkWZb.js} +1 -1
  75. package/dist/apps/chat-ui/assets/index-BPbNvcZe.css +1 -0
  76. package/dist/apps/chat-ui/assets/index-CIOf2uL2.js +237 -0
  77. package/dist/apps/chat-ui/index.html +2 -2
  78. package/dist/apps/chat-vscode-web/assets/index-1ivRyjFs.js +41 -0
  79. package/dist/apps/chat-vscode-web/index.html +1 -1
  80. package/dist/auth/login-actions.js +5 -251
  81. package/dist/cli-session/localSessionSource.js +8 -1
  82. package/dist/core/context-build.js +124 -20
  83. package/dist/core/default-profile.js +8 -0
  84. package/dist/core/profiles.js +30 -3
  85. package/dist/core/routed-session.js +5 -1446
  86. package/dist/core/runtime.js +5 -561
  87. package/dist/core/session-router.js +637 -83
  88. package/dist/data/cli.js +20 -3
  89. package/dist/data/schema.js +104 -1
  90. package/dist/data/session-store.js +24 -1
  91. package/dist/debug/events.js +25 -10
  92. package/dist/debug/failures.js +23 -3
  93. package/dist/debug/index.js +24 -6
  94. package/dist/debug/messages.js +87 -7
  95. package/dist/debug/persisted-payloads.js +31 -0
  96. package/dist/debug/pty.js +7 -6
  97. package/dist/debug/runtime-binding.js +29 -0
  98. package/dist/debug/session.js +137 -0
  99. package/dist/debug/summary.js +12 -0
  100. package/dist/debug/telemetry.js +28 -0
  101. package/dist/debug/tools.js +12 -2
  102. package/dist/debug/trace.js +154 -76
  103. package/dist/gateway/server.js +87 -2
  104. package/dist/gateway/tool.js +5 -5
  105. package/dist/index.js +21 -2
  106. package/dist/loops/tools.js +13 -12
  107. package/dist/mcp/agent-context.js +13 -4
  108. package/dist/mcp/client.js +10 -6
  109. package/dist/mcp/config.js +5 -2
  110. package/dist/mcp/runtime-session.js +166 -0
  111. package/dist/plugins/builtin.js +193 -53
  112. package/dist/plugins/codex-native.js +29 -0
  113. package/dist/plugins/omp.js +57 -0
  114. package/dist/plugins/registry.js +66 -2
  115. package/dist/runs/tools.js +26 -25
  116. package/dist/session-ui/terminalRows.js +2 -2
  117. package/dist/sessions/pibo-data-store.js +125 -16
  118. package/dist/sessions/runtime-binding.js +107 -0
  119. package/dist/sessions/sqlite-store.js +239 -18
  120. package/dist/sessions/store.js +86 -7
  121. package/dist/shared/trace-engine.js +18 -9
  122. package/dist/shared/trace-event-projection.js +29 -11
  123. package/dist/shared/{trace-transcript.js → trace-history.js} +193 -195
  124. package/dist/shared/trace-order.js +9 -4
  125. package/dist/shared/trace-page-merge.js +1 -1
  126. package/dist/signals/projector.js +20 -2
  127. package/dist/signals/registry.js +11 -0
  128. package/dist/subagents/tool.js +8 -6
  129. package/dist/tools/codex-browser.js +20 -19
  130. package/dist/tools/codex-compat.js +10 -9
  131. package/dist/tools/codex-image-generation.js +8 -6
  132. package/dist/tools/contract.js +45 -0
  133. package/dist/tools/credential-registry.js +182 -0
  134. package/dist/tools/mcp-bridge.js +511 -0
  135. package/dist/tools/payload-writer.js +17 -0
  136. package/dist/tools/runtime/tool.js +10 -9
  137. package/dist/tools/schema.js +9 -0
  138. package/dist/tools/session-service.js +193 -0
  139. package/dist/tools/session-tool-set.js +85 -0
  140. package/dist/web-annotations/tools.js +17 -16
  141. package/docs/README.md +11 -0
  142. package/package.json +3 -2
  143. package/skills/builtin/pibo-agent-runtime-adapter/SKILL.md +183 -0
  144. package/skills/builtin/pibo-agent-runtime-adapter/evals/README.md +10 -0
  145. package/skills/builtin/pibo-agent-runtime-adapter/evals/evals.json +45 -0
  146. package/skills/builtin/pibo-agent-runtime-adapter/evals/fixtures/orion-full-harness.md +60 -0
  147. package/skills/builtin/pibo-agent-runtime-adapter/evals/fixtures/relay-partial-harness.md +52 -0
  148. package/skills/builtin/pibo-agent-runtime-adapter/references/capabilities-and-designer.md +194 -0
  149. package/skills/builtin/pibo-agent-runtime-adapter/references/history-debug-and-security.md +213 -0
  150. package/skills/builtin/pibo-agent-runtime-adapter/references/interfaces-and-registration.md +214 -0
  151. package/skills/builtin/pibo-agent-runtime-adapter/references/lifecycle-bindings-and-events.md +193 -0
  152. package/skills/builtin/pibo-agent-runtime-adapter/references/portable-delivery-and-native-behavior.md +226 -0
  153. package/skills/builtin/pibo-agent-runtime-adapter/references/testing-migration-and-validation.md +256 -0
  154. package/dist/apps/chat-ui/assets/index-C2YI0xfw.js +0 -237
  155. package/dist/apps/chat-ui/assets/index-E0RmuCkY.css +0 -1
  156. package/dist/apps/chat-vscode-web/assets/index-D-tSsXLG.js +0 -41
@@ -0,0 +1,166 @@
1
+ import { createHash } from "node:crypto";
2
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
3
+ import { getDefaultEnvironment, StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
4
+ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
5
+ import { filterTools, isHttpServer, } from "./config.js";
6
+ const SECRET_KEY_RE = /(api[_-]?key|authorization|bearer|cookie|credential|oauth|password|secret|token)/i;
7
+ const ENV_REFERENCE_RE = /\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g;
8
+ function resolveEnvironmentString(value, environment) {
9
+ const missing = new Set();
10
+ const resolved = value.replace(ENV_REFERENCE_RE, (_match, name) => {
11
+ const replacement = environment[name];
12
+ if (replacement === undefined) {
13
+ missing.add(name);
14
+ return "";
15
+ }
16
+ return replacement;
17
+ });
18
+ if (missing.size > 0)
19
+ throw new Error(`Missing environment variables: ${[...missing].sort().join(", ")}`);
20
+ return resolved;
21
+ }
22
+ function generatedSecretName(serverName, path, value) {
23
+ const readable = [serverName, ...path]
24
+ .join("_")
25
+ .toUpperCase()
26
+ .replace(/[^A-Z0-9_]+/g, "_")
27
+ .replace(/^_+|_+$/g, "")
28
+ .slice(0, 72);
29
+ const hash = createHash("sha256").update(`${serverName}\0${path.join(".")}\0${value}`).digest("hex").slice(0, 12).toUpperCase();
30
+ return `PIBO_RUNTIME_MCP_${readable || "VALUE"}_${hash}`;
31
+ }
32
+ function urlLooksSensitive(value) {
33
+ try {
34
+ const url = new URL(value);
35
+ if (url.username || url.password)
36
+ return true;
37
+ for (const key of url.searchParams.keys()) {
38
+ if (SECRET_KEY_RE.test(key))
39
+ return true;
40
+ }
41
+ }
42
+ catch {
43
+ return false;
44
+ }
45
+ return false;
46
+ }
47
+ function scopeConfigValue(serverName, value, path, environment, secretEnvironment, forceSecret = false) {
48
+ if (typeof value === "string") {
49
+ const hasReference = ENV_REFERENCE_RE.test(value);
50
+ ENV_REFERENCE_RE.lastIndex = 0;
51
+ const secret = forceSecret || hasReference || SECRET_KEY_RE.test(path.at(-1) ?? "") || (path.at(-1) === "url" && urlLooksSensitive(value));
52
+ if (!secret)
53
+ return { materialized: value, resolved: value };
54
+ const resolved = resolveEnvironmentString(value, environment);
55
+ const environmentName = generatedSecretName(serverName, path, value);
56
+ secretEnvironment[environmentName] = resolved;
57
+ return { materialized: `\${${environmentName}}`, resolved };
58
+ }
59
+ if (Array.isArray(value)) {
60
+ const materialized = [];
61
+ const resolved = [];
62
+ for (const [index, item] of value.entries()) {
63
+ const scoped = scopeConfigValue(serverName, item, [...path, String(index)], environment, secretEnvironment, forceSecret);
64
+ materialized.push(scoped.materialized);
65
+ resolved.push(scoped.resolved);
66
+ }
67
+ return { materialized, resolved };
68
+ }
69
+ if (value && typeof value === "object") {
70
+ const materialized = {};
71
+ const resolved = {};
72
+ for (const [key, item] of Object.entries(value)) {
73
+ const scoped = scopeConfigValue(serverName, item, [...path, key], environment, secretEnvironment, forceSecret || path.at(-1) === "env" || path.at(-1) === "headers" || path.at(-1) === "args");
74
+ materialized[key] = scoped.materialized;
75
+ resolved[key] = scoped.resolved;
76
+ }
77
+ return { materialized, resolved };
78
+ }
79
+ return { materialized: value, resolved: value };
80
+ }
81
+ export function scopePiboMcpServerConfig(serverName, config, environment) {
82
+ const secretEnvironment = {};
83
+ const scoped = scopeConfigValue(serverName, config, [], environment, secretEnvironment);
84
+ return {
85
+ materialized: scoped.materialized,
86
+ resolved: scoped.resolved,
87
+ secretEnvironment,
88
+ secretEnvironmentKeys: Object.keys(secretEnvironment).sort(),
89
+ };
90
+ }
91
+ export function redactMcpRuntimeError(error, secretValues = []) {
92
+ let message = error instanceof Error ? error.message : String(error);
93
+ for (const value of secretValues) {
94
+ if (value)
95
+ message = message.split(value).join("[REDACTED]");
96
+ }
97
+ return message.replace(/Bearer\s+\S+/gi, "Bearer [REDACTED]");
98
+ }
99
+ export async function verifyPiboMcpServer(serverName, config, options) {
100
+ const client = new Client({ name: "pibo-runtime-resource-verifier", version: "1.0.0" }, { capabilities: {} });
101
+ let transport;
102
+ if (isHttpServer(config)) {
103
+ transport = new StreamableHTTPClientTransport(new URL(config.url), {
104
+ requestInit: { headers: config.headers },
105
+ });
106
+ }
107
+ else {
108
+ const env = {
109
+ ...getDefaultEnvironment(),
110
+ ...(config.env ?? {}),
111
+ };
112
+ transport = new StdioClientTransport({
113
+ command: config.command,
114
+ args: config.args,
115
+ env,
116
+ cwd: config.cwd,
117
+ stderr: "pipe",
118
+ });
119
+ }
120
+ const signal = AbortSignal.timeout(options.timeoutMs);
121
+ try {
122
+ await client.connect(transport, { signal, timeout: options.timeoutMs, maxTotalTimeout: options.timeoutMs });
123
+ const capabilities = client.getServerCapabilities();
124
+ const listedTools = capabilities?.tools
125
+ ? (await client.listTools(undefined, { signal, timeout: options.timeoutMs, maxTotalTimeout: options.timeoutMs })).tools
126
+ : [];
127
+ const tools = filterTools(listedTools.map((tool) => ({
128
+ name: tool.name,
129
+ ...(tool.description ? { description: tool.description } : {}),
130
+ })), config);
131
+ let resources = [];
132
+ let resourceTemplates = [];
133
+ if (capabilities?.resources) {
134
+ const listed = await client.listResources(undefined, { signal, timeout: options.timeoutMs, maxTotalTimeout: options.timeoutMs });
135
+ resources = listed.resources.map((resource) => ({
136
+ uri: resource.uri,
137
+ ...(resource.name ? { name: resource.name } : {}),
138
+ ...(resource.description ? { description: resource.description } : {}),
139
+ ...(resource.mimeType ? { mimeType: resource.mimeType } : {}),
140
+ }));
141
+ const templates = await client.listResourceTemplates(undefined, { signal, timeout: options.timeoutMs, maxTotalTimeout: options.timeoutMs });
142
+ resourceTemplates = templates.resourceTemplates.map((template) => ({
143
+ uriTemplate: template.uriTemplate,
144
+ ...(template.name ? { name: template.name } : {}),
145
+ ...(template.description ? { description: template.description } : {}),
146
+ ...(template.mimeType ? { mimeType: template.mimeType } : {}),
147
+ }));
148
+ }
149
+ const version = client.getServerVersion();
150
+ return {
151
+ status: "connected",
152
+ ...(version?.name ? { serverName: version.name } : {}),
153
+ ...(version?.version ? { serverVersion: version.version } : {}),
154
+ ...(client.getInstructions() ? { instructions: client.getInstructions() } : {}),
155
+ tools,
156
+ resources,
157
+ resourceTemplates,
158
+ };
159
+ }
160
+ catch (error) {
161
+ throw new Error(`MCP server "${serverName}" verification failed: ${redactMcpRuntimeError(error)}`);
162
+ }
163
+ finally {
164
+ await client.close().catch(async () => transport.close().catch(() => { }));
165
+ }
166
+ }
@@ -2,32 +2,27 @@ import { dirname, resolve } from "node:path";
2
2
  import { fileURLToPath } from "node:url";
3
3
  import { createPiboGatewayToolProfiles } from "../gateway/tool.js";
4
4
  import { InitialSessionContextBuilder } from "../core/profiles.js";
5
+ import { createDefaultPiboProfile, DEFAULT_PIBO_PROFILE_NAME } from "../core/default-profile.js";
5
6
  import { parsePiboThinkingLevel } from "../core/thinking.js";
6
7
  import { createWebSearchToolProfile } from "../tools/web-search.js";
7
8
  import { CODEX_BROWSER_TOOL_NAMES, createCodexBrowserToolProfiles } from "../tools/codex-browser.js";
8
9
  import { createRuntimeToolProfile } from "../tools/runtime/tool.js";
9
- import { completeLogin, getLoginStatus, removeLogin, setApiKey, startLogin } from "../auth/login-actions.js";
10
10
  import { loadModelCatalog } from "../apps/chat/model-catalog.js";
11
11
  import { piboCodexCompatPlugin } from "./codex-compat.js";
12
+ import { piboCodexNativePlugin } from "./codex-native.js";
12
13
  import { addPiboNativeToolingContext, registerPiboNativeTooling } from "./native-tooling.js";
13
14
  import { piboWebAnnotationsPlugin } from "./web-annotations.js";
15
+ import { piboOmpPlugin } from "./omp.js";
14
16
  import { definePiboPlugin, PiboPluginRegistry } from "./registry.js";
15
- export const DEFAULT_PIBO_PROFILE_NAME = "base";
17
+ import { PI_AGENT_RUNTIME_DRIVER } from "../agent-runtimes/pi/adapter.js";
18
+ export { createDefaultPiboProfile, DEFAULT_PIBO_PROFILE_NAME } from "../core/default-profile.js";
19
+ export { CODEX_NATIVE_PROFILE_NAME, CODEX_NATIVE_RUNTIME_INSTANCE_ID, piboCodexNativePlugin, } from "./codex-native.js";
20
+ export { OMP_PROFILE_NAME, OMP_RUNTIME_INSTANCE_ID, piboOmpPlugin, } from "./omp.js";
16
21
  const GATEWAY_PROFILE_TOOLS = ["pibo_gateway_send"];
17
22
  const PIBO_PACKAGE_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "../..");
18
23
  function builtinSkillPath(name) {
19
24
  return resolve(PIBO_PACKAGE_ROOT, "skills", "builtin", name, "SKILL.md");
20
25
  }
21
- const LOGIN_PROVIDERS = [
22
- { id: "openai-codex", name: "OpenAI (ChatGPT Plus/Pro)", authMethods: ["device_code"] },
23
- { id: "openai", name: "OpenAI API", authMethods: ["api_key"] },
24
- { id: "anthropic", name: "Anthropic", authMethods: ["api_key"] },
25
- { id: "qwen-token-plan", name: "Qwen Token Plan", authMethods: ["api_key"] },
26
- { id: "kimi-coding", name: "Kimi for Coding", authMethods: ["api_key"] },
27
- { id: "google", name: "Google Gemini", authMethods: ["api_key"] },
28
- { id: "groq", name: "Groq", authMethods: ["api_key"] },
29
- { id: "ollama", name: "Ollama", authMethods: ["api_key"] },
30
- ];
31
26
  function getObjectParams(event) {
32
27
  const params = "params" in event ? event.params : undefined;
33
28
  if (!params || typeof params !== "object" || Array.isArray(params))
@@ -75,12 +70,35 @@ function getThinkingParams(event) {
75
70
  throw new Error("thinking requires params.level to be a string");
76
71
  return { level: parsePiboThinkingLevel(raw.level) };
77
72
  }
73
+ function requireApprovalResponseParams(event) {
74
+ const params = getObjectParams(event);
75
+ if (!params || typeof params.requestId !== "string" || !params.requestId.trim()) {
76
+ throw new Error("runtime.approval.respond requires params.requestId");
77
+ }
78
+ if (typeof params.decision !== "string" || !params.decision.trim()) {
79
+ throw new Error("runtime.approval.respond requires params.decision");
80
+ }
81
+ return { requestId: params.requestId, decision: params.decision };
82
+ }
83
+ function requireUserInputResponseParams(event) {
84
+ const params = getObjectParams(event);
85
+ if (!params || typeof params.requestId !== "string" || !params.requestId.trim()) {
86
+ throw new Error("runtime.user_input.respond requires params.requestId");
87
+ }
88
+ if (!params.answers || typeof params.answers !== "object" || Array.isArray(params.answers)) {
89
+ throw new Error("runtime.user_input.respond requires params.answers");
90
+ }
91
+ return { requestId: params.requestId, answers: params.answers };
92
+ }
78
93
  function requireLoginStartParams(event) {
79
94
  const params = getObjectParams(event);
80
95
  if (!params || typeof params.provider !== "string" || params.provider.length === 0) {
81
96
  throw new Error("login.start requires params.provider");
82
97
  }
83
- return { provider: params.provider };
98
+ if (params.method !== undefined && params.method !== "device_code" && params.method !== "browser_oauth") {
99
+ throw new Error("login.start params.method must be device_code or browser_oauth");
100
+ }
101
+ return { provider: params.provider, method: params.method };
84
102
  }
85
103
  function requireLoginCompleteParams(event) {
86
104
  const params = getObjectParams(event);
@@ -90,10 +108,28 @@ function requireLoginCompleteParams(event) {
90
108
  if (params.code !== undefined && typeof params.code !== "string") {
91
109
  throw new Error("login.complete params.code must be a string when provided");
92
110
  }
93
- if (typeof params.state !== "string" || params.state.length === 0) {
94
- throw new Error("login.complete requires params.state");
111
+ const flowId = typeof params.flowId === "string" && params.flowId.length > 0
112
+ ? params.flowId
113
+ : typeof params.state === "string" && params.state.length > 0
114
+ ? params.state
115
+ : undefined;
116
+ if (!flowId)
117
+ throw new Error("login.complete requires params.flowId");
118
+ return { provider: params.provider, code: params.code, flowId };
119
+ }
120
+ function requireLoginCancelParams(event) {
121
+ const params = getObjectParams(event);
122
+ if (!params || typeof params.provider !== "string" || params.provider.length === 0) {
123
+ throw new Error("login.cancel requires params.provider");
95
124
  }
96
- return { provider: params.provider, code: params.code, state: params.state };
125
+ const flowId = typeof params.flowId === "string" && params.flowId.length > 0
126
+ ? params.flowId
127
+ : typeof params.state === "string" && params.state.length > 0
128
+ ? params.state
129
+ : undefined;
130
+ if (!flowId)
131
+ throw new Error("login.cancel requires params.flowId");
132
+ return { provider: params.provider, flowId };
97
133
  }
98
134
  function requireLoginApiKeyParams(event) {
99
135
  const params = getObjectParams(event);
@@ -121,11 +157,18 @@ export const piboCorePlugin = definePiboPlugin({
121
157
  id: "pibo.core",
122
158
  name: "Pibo Core",
123
159
  register(api) {
160
+ api.registerAgentRuntimeDriver(PI_AGENT_RUNTIME_DRIVER);
161
+ api.registerAgentRuntimeInstance({ id: "pi", adapterId: "pi", displayName: "Pi Coding Agent" });
124
162
  api.registerSkill({
125
163
  name: "pi-agent-harness",
126
164
  path: builtinSkillPath("pi-agent-harness"),
127
165
  kind: "builtin",
128
166
  });
167
+ api.registerSkill({
168
+ name: "pibo-agent-runtime-adapter",
169
+ path: builtinSkillPath("pibo-agent-runtime-adapter"),
170
+ kind: "builtin",
171
+ });
129
172
  api.registerSkill({
130
173
  name: "pibo-spec-writing",
131
174
  path: builtinSkillPath("pibo-spec-writing"),
@@ -203,6 +246,26 @@ export const piboCorePlugin = definePiboPlugin({
203
246
  return await context.compact(customInstructions);
204
247
  },
205
248
  });
249
+ api.registerGatewayAction({
250
+ name: "runtime.approval.respond",
251
+ description: "Respond to a pending runtime approval request.",
252
+ hidden: true,
253
+ async execute(context, event) {
254
+ const params = requireApprovalResponseParams(event);
255
+ await context.respondToApproval(params.requestId, params.decision);
256
+ return { requestId: params.requestId, responded: true };
257
+ },
258
+ });
259
+ api.registerGatewayAction({
260
+ name: "runtime.user_input.respond",
261
+ description: "Respond to a pending structured runtime user-input request.",
262
+ hidden: true,
263
+ async execute(context, event) {
264
+ const params = requireUserInputResponseParams(event);
265
+ await context.respondToUserInput(params.requestId, params.answers);
266
+ return { requestId: params.requestId, responded: true };
267
+ },
268
+ });
206
269
  api.registerGatewayAction({
207
270
  name: "session_id",
208
271
  description: "Return the routed Pibo session id.",
@@ -255,7 +318,7 @@ export const piboCorePlugin = definePiboPlugin({
255
318
  });
256
319
  api.registerGatewayAction({
257
320
  name: "thinking",
258
- description: "Show or set the routed Pi thinking level.",
321
+ description: "Show or set the active runtime reasoning level.",
259
322
  slashCommands: ["thinking"],
260
323
  execute(context, event) {
261
324
  const params = getThinkingParams(event);
@@ -346,81 +409,164 @@ export const piboCorePlugin = definePiboPlugin({
346
409
  });
347
410
  api.registerGatewayAction({
348
411
  name: "login",
349
- description: "Open the interactive provider login menu.",
412
+ description: "Open the interactive provider login menu for the active runtime.",
350
413
  slashCommands: ["login"],
351
- execute() {
352
- const statuses = new Map(getLoginStatus().map((status) => [status.id, status.configured]));
414
+ async execute(context) {
415
+ const statuses = await context.getRuntimeAuthStatus();
353
416
  return {
354
417
  action: "show_login_menu",
355
- providers: LOGIN_PROVIDERS.map((provider) => ({
356
- ...provider,
357
- authMethods: [...provider.authMethods],
358
- configured: statuses.get(provider.id) ?? false,
418
+ runtimeInstanceId: context.runtimeInstanceId,
419
+ providers: statuses.map((status) => ({
420
+ id: status.id,
421
+ name: status.displayName ?? status.id,
422
+ authMethods: status.methods.map((method) => method.id),
423
+ configured: status.configured,
424
+ state: status.state,
425
+ message: status.message,
359
426
  })),
360
427
  };
361
428
  },
362
429
  });
363
430
  api.registerGatewayAction({
364
431
  name: "model",
365
- description: "Open the interactive model selector for authenticated providers.",
432
+ description: "Open the interactive model selector for the active runtime.",
366
433
  slashCommands: ["model"],
367
- async execute() {
434
+ async execute(context) {
435
+ const runtimeCatalog = await context.getModelCatalog();
436
+ if (runtimeCatalog) {
437
+ let authStatusAvailable = false;
438
+ let authStatuses = new Map();
439
+ try {
440
+ const statuses = await context.getRuntimeAuthStatus();
441
+ authStatusAvailable = true;
442
+ authStatuses = new Map(statuses.map((status) => [status.id, status.configured]));
443
+ }
444
+ catch {
445
+ // Runtimes that do not declare auth may use model-catalog compatibility metadata.
446
+ }
447
+ const providers = new Map();
448
+ for (const model of runtimeCatalog.models) {
449
+ const providerId = model.provider ?? runtimeCatalog.runtimeInstanceId;
450
+ const providerLabel = typeof model.options?.providerDisplayName === "string"
451
+ ? model.options.providerDisplayName
452
+ : providerId;
453
+ const authConfigured = authStatuses.get(providerId)
454
+ ?? (authStatusAvailable
455
+ ? false
456
+ : typeof model.options?.authConfigured === "boolean"
457
+ ? model.options.authConfigured
458
+ : !context.runtimeAuthRequired);
459
+ let provider = providers.get(providerId);
460
+ if (!provider) {
461
+ provider = { id: providerId, label: providerLabel, authConfigured, models: [] };
462
+ providers.set(providerId, provider);
463
+ }
464
+ provider.models.push({
465
+ provider: providerId,
466
+ id: model.id,
467
+ label: model.displayName ?? model.id,
468
+ ...(model.reasoningOptions ? { supportsReasoning: model.reasoningOptions.length > 0 } : {}),
469
+ });
470
+ }
471
+ return { action: "show_model_menu", providers: [...providers.values()] };
472
+ }
368
473
  const catalog = await loadModelCatalog(process.cwd());
369
474
  return {
370
475
  action: "show_model_menu",
371
- providers: catalog.providers
372
- .filter((provider) => provider.authConfigured)
373
- .map((provider) => ({
476
+ providers: catalog.providers.map((provider) => ({
374
477
  ...provider,
375
- models: provider.models.filter((model) => model.authConfigured !== false),
478
+ models: provider.models,
376
479
  })),
377
480
  };
378
481
  },
379
482
  });
380
483
  api.registerGatewayAction({
381
484
  name: "login.start",
382
- description: "Start an OAuth login flow for a provider. Returns a URL to open in a browser.",
485
+ description: "Start a provider login flow for the active runtime.",
383
486
  slashCommands: [],
384
- async execute(_context, event) {
487
+ async execute(context, event) {
385
488
  const params = requireLoginStartParams(event);
386
- return await startLogin(params.provider);
489
+ const status = (await context.getRuntimeAuthStatus()).find((candidate) => candidate.id === params.provider);
490
+ const method = params.method ?? status?.methods.find((candidate) => candidate.id !== "api_key")?.id;
491
+ if (method !== "device_code" && method !== "browser_oauth") {
492
+ throw new Error(`Provider "${params.provider}" does not expose an interactive login method.`);
493
+ }
494
+ const result = await context.startRuntimeAuth({ providerId: params.provider, method });
495
+ return {
496
+ ...result,
497
+ runtimeInstanceId: context.runtimeInstanceId,
498
+ ...(result.flow ? {
499
+ type: result.flow.method,
500
+ url: result.flow.verificationUrl,
501
+ verificationUrl: result.flow.verificationUrl,
502
+ userCode: result.flow.userCode,
503
+ instructions: result.flow.instructions,
504
+ flowId: result.flow.flowId,
505
+ state: result.flow.flowId,
506
+ } : {}),
507
+ };
387
508
  },
388
509
  });
389
510
  api.registerGatewayAction({
390
511
  name: "login.complete",
391
- description: "Complete an OAuth login flow with the authorization code from the provider callback.",
512
+ description: "Read or complete a provider login flow for the active runtime.",
392
513
  slashCommands: [],
393
- async execute(_context, event) {
514
+ async execute(context, event) {
394
515
  const params = requireLoginCompleteParams(event);
395
- return await completeLogin(params.provider, params.code, params.state);
516
+ return {
517
+ ...(await context.completeRuntimeAuth({ providerId: params.provider, flowId: params.flowId, code: params.code })),
518
+ runtimeInstanceId: context.runtimeInstanceId,
519
+ };
396
520
  },
397
521
  });
398
522
  api.registerGatewayAction({
399
523
  name: "login.apikey",
400
- description: "Set an API key directly for a provider.",
524
+ description: "Set an API key for a provider on the active runtime.",
401
525
  slashCommands: [],
402
- execute(_context, event) {
526
+ async execute(context, event) {
403
527
  const params = requireLoginApiKeyParams(event);
404
- return setApiKey(params.provider, params.apiKey);
528
+ return {
529
+ ...(await context.startRuntimeAuth({ providerId: params.provider, method: "api_key", apiKey: params.apiKey })),
530
+ runtimeInstanceId: context.runtimeInstanceId,
531
+ };
532
+ },
533
+ });
534
+ api.registerGatewayAction({
535
+ name: "login.cancel",
536
+ description: "Cancel a pending provider login for the active runtime.",
537
+ slashCommands: [],
538
+ async execute(context, event) {
539
+ const params = requireLoginCancelParams(event);
540
+ return {
541
+ ...(await context.cancelRuntimeAuth({ providerId: params.provider, flowId: params.flowId })),
542
+ runtimeInstanceId: context.runtimeInstanceId,
543
+ };
405
544
  },
406
545
  });
407
546
  api.registerGatewayAction({
408
547
  name: "login.status",
409
- description: "Check the authentication status for providers.",
548
+ description: "Check provider authentication status for the active runtime.",
410
549
  slashCommands: [],
411
- execute(_context, event) {
550
+ async execute(context, event) {
412
551
  const params = getObjectParams(event);
413
552
  const provider = typeof params?.provider === "string" ? params.provider : undefined;
414
- return { providers: getLoginStatus(provider) };
553
+ const providers = await context.getRuntimeAuthStatus();
554
+ return {
555
+ runtimeInstanceId: context.runtimeInstanceId,
556
+ providers: provider ? providers.filter((status) => status.id === provider) : providers,
557
+ };
415
558
  },
416
559
  });
417
560
  api.registerGatewayAction({
418
561
  name: "logout",
419
- description: "Remove stored credentials for a provider.",
562
+ description: "Remove stored credentials for a provider on the active runtime.",
420
563
  slashCommands: [],
421
- execute(_context, event) {
564
+ async execute(context, event) {
422
565
  const params = requireLogoutParams(event);
423
- return removeLogin(params.provider);
566
+ return {
567
+ ...(await context.logoutRuntimeAuth({ providerId: params.provider })),
568
+ runtimeInstanceId: context.runtimeInstanceId,
569
+ };
424
570
  },
425
571
  });
426
572
  },
@@ -443,11 +589,11 @@ export const piboGatewayProducerPlugin = definePiboPlugin({
443
589
  },
444
590
  });
445
591
  export function createDefaultPiboPlugins() {
446
- return [piboCorePlugin, piboCodexCompatPlugin, piboWebAnnotationsPlugin];
592
+ return [piboCorePlugin, piboCodexNativePlugin, piboCodexCompatPlugin, piboWebAnnotationsPlugin, piboOmpPlugin];
447
593
  }
448
594
  export function createGatewayProducerPiboPluginRegistry() {
449
595
  return PiboPluginRegistry.create({
450
- plugins: [piboCorePlugin, piboGatewayProducerPlugin, piboCodexCompatPlugin, piboWebAnnotationsPlugin],
596
+ plugins: [piboCorePlugin, piboCodexNativePlugin, piboGatewayProducerPlugin, piboCodexCompatPlugin, piboWebAnnotationsPlugin, piboOmpPlugin],
451
597
  });
452
598
  }
453
599
  export function createDefaultPiboPluginRegistry() {
@@ -457,12 +603,6 @@ export function selectDefaultPiboProfileName(registry) {
457
603
  const names = registry.getProfileNames();
458
604
  return names.includes(DEFAULT_PIBO_PROFILE_NAME) ? DEFAULT_PIBO_PROFILE_NAME : names[0] ?? DEFAULT_PIBO_PROFILE_NAME;
459
605
  }
460
- export function createDefaultPiboProfile() {
461
- return new InitialSessionContextBuilder(DEFAULT_PIBO_PROFILE_NAME)
462
- .withBuiltinToolNames(["read", "bash", "edit", "write"])
463
- .withToolPackages({ goalControl: true })
464
- .createSession();
465
- }
466
606
  export function resolvePiboProfileNameFromRegistryOrDefault(registry, profileName) {
467
607
  const requestedProfileName = profileName ?? selectDefaultPiboProfileName(registry);
468
608
  try {
@@ -0,0 +1,29 @@
1
+ import { CODEX_NATIVE_ADAPTER_ID, CODEX_NATIVE_AGENT_RUNTIME_DRIVER, } from "../agent-runtimes/codex-native/adapter.js";
2
+ import { InitialSessionContextBuilder } from "../core/profiles.js";
3
+ import { definePiboPlugin } from "./registry.js";
4
+ export const CODEX_NATIVE_RUNTIME_INSTANCE_ID = "codex-native";
5
+ export const CODEX_NATIVE_PROFILE_NAME = "codex-native";
6
+ export const piboCodexNativePlugin = definePiboPlugin({
7
+ id: "pibo.codex-native",
8
+ name: "Pibo Native Codex",
9
+ register(api) {
10
+ api.registerAgentRuntimeDriver(CODEX_NATIVE_AGENT_RUNTIME_DRIVER);
11
+ api.registerAgentRuntimeInstance({
12
+ id: CODEX_NATIVE_RUNTIME_INSTANCE_ID,
13
+ adapterId: CODEX_NATIVE_ADAPTER_ID,
14
+ displayName: "Native Codex App Server",
15
+ });
16
+ api.registerProfile({
17
+ name: CODEX_NATIVE_PROFILE_NAME,
18
+ description: "Native Codex App Server profile. Distinct from the Pi-backed Codex compatibility profile.",
19
+ create() {
20
+ return new InitialSessionContextBuilder(CODEX_NATIVE_PROFILE_NAME)
21
+ .withAgentRuntime(CODEX_NATIVE_RUNTIME_INSTANCE_ID)
22
+ .withBuiltinTools("disabled")
23
+ .withBuiltinToolNames([])
24
+ .withToolPackages({ goalControl: true })
25
+ .createSession();
26
+ },
27
+ });
28
+ },
29
+ });
@@ -0,0 +1,57 @@
1
+ import { OMP_AGENT_RUNTIME_DRIVER } from "../agent-runtimes/omp/adapter.js";
2
+ import { InitialSessionContextBuilder } from "../core/profiles.js";
3
+ import { definePiboPlugin } from "./registry.js";
4
+ export const OMP_RUNTIME_INSTANCE_ID = "omp-native";
5
+ export const OMP_PROFILE_NAME = "orp";
6
+ /**
7
+ * Resolve the OMP CLI entry for the default configured instance.
8
+ *
9
+ * The operator must point Pibo at an Oh My Pi install. We honour (in order):
10
+ * PIBO_OMP_CLI absolute path to the OMP CLI entry (clover cli.ts / dist/cli.js)
11
+ * OMP_HOME absolute directory containing `src/cli.ts`
12
+ * If neither is set, ompEntry stays empty and `diagnose` reports it clearly; the
13
+ * adapter refuses to spawn until configured. We never invent a workspace-relative
14
+ * default.
15
+ */
16
+ function defaultOmpEntry() {
17
+ const cli = process.env.PIBO_OMP_CLI;
18
+ if (cli && (cli.startsWith("/") || /^[a-zA-Z]:[\\/]/.test(cli)))
19
+ return cli.trim();
20
+ const home = process.env.OMP_HOME;
21
+ if (home && (home.startsWith("/") || /^[a-zA-Z]:[\\/]/.test(home))) {
22
+ return `${home.replace(/[\\/]+$/, "")}${process.platform === "win32" ? "\\" : "/"}packages/coding-agent/src/cli.ts`;
23
+ }
24
+ return "";
25
+ }
26
+ export const piboOmpPlugin = definePiboPlugin({
27
+ id: "pibo.orp",
28
+ name: "Pibo Oh My Pi",
29
+ register(api) {
30
+ api.registerAgentRuntimeDriver(OMP_AGENT_RUNTIME_DRIVER);
31
+ api.registerAgentRuntimeInstance({
32
+ id: OMP_RUNTIME_INSTANCE_ID,
33
+ adapterId: OMP_AGENT_RUNTIME_DRIVER.descriptor.id,
34
+ displayName: "Oh My Pi Native",
35
+ config: {
36
+ bunExecutable: "bun",
37
+ ompEntry: defaultOmpEntry(),
38
+ defaultProvider: "alibaba-token-plan",
39
+ defaultModel: "deepseek-v4-flash-0731",
40
+ environmentAllowlist: ["PATH", "SystemRoot", "WINDIR", "TZ", "HTTP_PROXY", "HTTPS_PROXY", "NO_PROXY", "ALL_PROXY"],
41
+ apiKeyEnvironment: ["OPENAI_API_KEY", "ANTHROPIC_API_KEY", "GEMINI_API_KEY", "DEEPSEEK_API_KEY", "ALIBABA_TOKEN_PLAN_API_KEY", "BAILIAN_TOKEN_PLAN_API_KEY"],
42
+ },
43
+ });
44
+ api.registerProfile({
45
+ name: OMP_PROFILE_NAME,
46
+ description: "Oh My Pi native runtime profile. Uses the OMP engine (can1357/oh-my-pi) via its RPC bridge; OMP owns its native tools, base prompt, and sessions; Pibo delivers selected portable tools, skills, and context files.",
47
+ create() {
48
+ return new InitialSessionContextBuilder(OMP_PROFILE_NAME)
49
+ .withAgentRuntime(OMP_RUNTIME_INSTANCE_ID)
50
+ .withBuiltinTools("disabled")
51
+ .withBuiltinToolNames([])
52
+ .withToolPackages({ goalControl: true })
53
+ .createSession();
54
+ },
55
+ });
56
+ },
57
+ });