@getpaseo/server 0.9.2 → 0.10.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 (148) hide show
  1. package/dist/scripts/supervisor.js +51 -21
  2. package/dist/server/server/agent/agent-manager.js +22 -2
  3. package/dist/server/server/agent/agent-prompt.js +12 -0
  4. package/dist/server/server/agent/agent-sdk-types.d.ts +3 -0
  5. package/dist/server/server/agent/mcp-shared.d.ts +5 -1
  6. package/dist/server/server/agent/mcp-shared.js +2 -1
  7. package/dist/server/server/agent/provider-launch-config.d.ts +2 -2
  8. package/dist/server/server/agent/provider-launch-config.js +1 -1
  9. package/dist/server/server/agent/provider-registry.js +2 -2
  10. package/dist/server/server/agent/providers/acp-agent.js +20 -11
  11. package/dist/server/server/agent/providers/claude/agent.d.ts +1 -2
  12. package/dist/server/server/agent/providers/claude/agent.js +10 -9
  13. package/dist/server/server/agent/providers/claude/models.d.ts +1 -1
  14. package/dist/server/server/agent/providers/claude/models.js +1 -5
  15. package/dist/server/server/agent/providers/claude/project-dir.d.ts +1 -0
  16. package/dist/server/server/agent/providers/claude/project-dir.js +5 -1
  17. package/dist/server/server/agent/providers/codex-app-server-agent.d.ts +6 -1
  18. package/dist/server/server/agent/providers/codex-app-server-agent.js +10 -1
  19. package/dist/server/server/agent/providers/generic-acp-agent.js +3 -1
  20. package/dist/server/server/agent/providers/omp/agent.js +23 -6
  21. package/dist/server/server/agent/providers/omp/rpc-types.d.ts +1 -0
  22. package/dist/server/server/agent/providers/omp/rpc-types.js +1 -0
  23. package/dist/server/server/agent/providers/opencode/bridge.d.ts +5 -1
  24. package/dist/server/server/agent/providers/opencode/bridge.js +56 -5
  25. package/dist/server/server/agent/providers/opencode/http-error.d.ts +8 -0
  26. package/dist/server/server/agent/providers/opencode/http-error.js +13 -0
  27. package/dist/server/server/agent/providers/opencode/runtime-client.d.ts +38 -0
  28. package/dist/server/server/agent/providers/opencode/runtime-client.js +131 -0
  29. package/dist/server/server/agent/providers/opencode/runtime-notice.d.ts +3 -0
  30. package/dist/server/server/agent/providers/opencode/runtime-notice.js +47 -0
  31. package/dist/server/server/agent/providers/opencode/server-manager.js +19 -8
  32. package/dist/server/server/agent/providers/opencode/v2/agent.d.ts +36 -0
  33. package/dist/server/server/agent/providers/opencode/v2/agent.js +211 -0
  34. package/dist/server/server/agent/providers/opencode/v2/api.d.ts +18 -0
  35. package/dist/server/server/agent/providers/opencode/v2/api.js +2 -0
  36. package/dist/server/server/agent/providers/opencode/v2/bridge-plugin.bundle.mjs +6693 -0
  37. package/dist/server/server/agent/providers/opencode/v2/capabilities.d.ts +3 -0
  38. package/dist/server/server/agent/providers/opencode/v2/capabilities.js +13 -0
  39. package/dist/server/server/agent/providers/opencode/v2/children.d.ts +20 -0
  40. package/dist/server/server/agent/providers/opencode/v2/children.js +75 -0
  41. package/dist/server/server/agent/providers/opencode/v2/commands.d.ts +4 -0
  42. package/dist/server/server/agent/providers/opencode/v2/commands.js +36 -0
  43. package/dist/server/server/agent/providers/opencode/v2/configuration.d.ts +8 -0
  44. package/dist/server/server/agent/providers/opencode/v2/configuration.js +64 -0
  45. package/dist/server/server/agent/providers/opencode/v2/history.d.ts +4 -0
  46. package/dist/server/server/agent/providers/opencode/v2/history.js +15 -0
  47. package/dist/server/server/agent/providers/opencode/v2/mapping.d.ts +7 -0
  48. package/dist/server/server/agent/providers/opencode/v2/mapping.js +42 -0
  49. package/dist/server/server/agent/providers/opencode/v2/permissions.d.ts +18 -0
  50. package/dist/server/server/agent/providers/opencode/v2/permissions.js +157 -0
  51. package/dist/server/server/agent/providers/opencode/v2/readiness.d.ts +18 -0
  52. package/dist/server/server/agent/providers/opencode/v2/readiness.js +51 -0
  53. package/dist/server/server/agent/providers/opencode/v2/runtime.d.ts +36 -0
  54. package/dist/server/server/agent/providers/opencode/v2/runtime.js +230 -0
  55. package/dist/server/server/agent/providers/opencode/v2/session.d.ts +84 -0
  56. package/dist/server/server/agent/providers/opencode/v2/session.js +468 -0
  57. package/dist/server/server/agent/providers/opencode/v2/structured-output.d.ts +8 -0
  58. package/dist/server/server/agent/providers/opencode/v2/structured-output.js +32 -0
  59. package/dist/server/server/agent/providers/opencode/v2/timeline.d.ts +28 -0
  60. package/dist/server/server/agent/providers/opencode/v2/timeline.js +154 -0
  61. package/dist/server/server/agent/providers/opencode/v2/turns.d.ts +40 -0
  62. package/dist/server/server/agent/providers/opencode/v2/turns.js +226 -0
  63. package/dist/server/server/agent/providers/opencode-agent.d.ts +26 -7
  64. package/dist/server/server/agent/providers/opencode-agent.js +100 -40
  65. package/dist/server/server/agent/providers/pi/agent.d.ts +6 -6
  66. package/dist/server/server/agent/providers/pi/agent.js +114 -165
  67. package/dist/server/server/agent/providers/pi/extensions/child-session.d.ts +4 -0
  68. package/dist/server/server/agent/providers/pi/extensions/child-session.js +59 -0
  69. package/dist/server/server/agent/providers/pi/extensions/contract.d.ts +68 -0
  70. package/dist/server/server/agent/providers/pi/extensions/contract.js +2 -0
  71. package/dist/server/server/agent/providers/pi/extensions/gotgenes-pi-subagents/index.d.ts +3 -0
  72. package/dist/server/server/agent/providers/pi/extensions/gotgenes-pi-subagents/index.js +159 -0
  73. package/dist/server/server/agent/providers/pi/extensions/host.d.ts +28 -0
  74. package/dist/server/server/agent/providers/pi/extensions/host.js +94 -0
  75. package/dist/server/server/agent/providers/pi/extensions/index.d.ts +7 -0
  76. package/dist/server/server/agent/providers/pi/extensions/index.js +6 -0
  77. package/dist/server/server/agent/providers/pi/extensions/pi-ask-user/index.d.ts +3 -0
  78. package/dist/server/server/agent/providers/pi/extensions/pi-ask-user/index.js +138 -0
  79. package/dist/server/server/agent/providers/pi/extensions/pi-example-todo/index.d.ts +3 -0
  80. package/dist/server/server/agent/providers/pi/extensions/pi-example-todo/index.js +38 -0
  81. package/dist/server/server/agent/providers/pi/extensions/pi-goal-x/index.d.ts +3 -0
  82. package/dist/server/server/agent/providers/pi/extensions/pi-goal-x/index.js +63 -0
  83. package/dist/server/server/agent/providers/pi/extensions/pi-mcp-adapter/index.d.ts +3 -0
  84. package/dist/server/server/agent/providers/pi/extensions/pi-mcp-adapter/index.js +48 -0
  85. package/dist/server/server/agent/providers/pi/extensions/pi-subagents/index.d.ts +3 -0
  86. package/dist/server/server/agent/providers/pi/extensions/pi-subagents/index.js +131 -0
  87. package/dist/server/server/agent/providers/pi/extensions/registry.d.ts +2 -0
  88. package/dist/server/server/agent/providers/pi/extensions/registry.js +21 -0
  89. package/dist/server/server/agent/providers/pi/extensions/rpiv-ask-user-question/index.d.ts +3 -0
  90. package/dist/server/server/agent/providers/pi/extensions/rpiv-ask-user-question/index.js +180 -0
  91. package/dist/server/server/agent/providers/pi/extensions/rpiv-todo/index.d.ts +3 -0
  92. package/dist/server/server/agent/providers/pi/extensions/rpiv-todo/index.js +51 -0
  93. package/dist/server/server/agent/providers/pi/extensions/subagent-fixture-test.d.ts +22 -0
  94. package/dist/server/server/agent/providers/pi/extensions/subagent-fixture-test.js +66 -0
  95. package/dist/server/server/agent/providers/pi/extensions/task-fixture-test.d.ts +4 -0
  96. package/dist/server/server/agent/providers/pi/extensions/task-fixture-test.js +79 -0
  97. package/dist/server/server/agent/providers/pi/extensions/tintinweb-pi-subagents/index.d.ts +3 -0
  98. package/dist/server/server/agent/providers/pi/extensions/tintinweb-pi-subagents/index.js +149 -0
  99. package/dist/server/server/agent/providers/pi/history-mapper.d.ts +7 -2
  100. package/dist/server/server/agent/providers/pi/history-mapper.js +78 -35
  101. package/dist/server/server/agent/providers/pi/rpc-types.d.ts +3 -0
  102. package/dist/server/server/agent/providers/pi/test-utils/fake-pi.d.ts +170 -0
  103. package/dist/server/server/agent/providers/pi/test-utils/fake-pi.js +355 -0
  104. package/dist/server/server/agent/providers/pi/tool-call-mapper.d.ts +1 -6
  105. package/dist/server/server/agent/providers/pi/tool-call-mapper.js +1 -97
  106. package/dist/server/server/agent/tools/paseo-tools.js +22 -15
  107. package/dist/server/server/auth.d.ts +1 -2
  108. package/dist/server/server/auth.js +8 -14
  109. package/dist/server/server/bootstrap.js +10 -2
  110. package/dist/server/server/daemon-instance.d.ts +1 -0
  111. package/dist/server/server/daemon-instance.js +1 -0
  112. package/dist/server/server/exports.d.ts +1 -1
  113. package/dist/server/server/exports.js +1 -1
  114. package/dist/server/server/local-credential.d.ts +6 -0
  115. package/dist/server/server/local-credential.js +82 -0
  116. package/dist/server/server/session-admission-auth.d.ts +16 -0
  117. package/dist/server/server/session-admission-auth.js +26 -0
  118. package/dist/server/server/websocket-server.d.ts +6 -1
  119. package/dist/server/server/websocket-server.js +132 -55
  120. package/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-bridge-f41bce08c3c4ac2de0652d20234d19e9.js → desktop-attachment-bridge-9da07adb97f5e0eb726f7762afee43f5.js} +1 -1
  121. package/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-bridge-f41bce08c3c4ac2de0652d20234d19e9.js.br → desktop-attachment-bridge-9da07adb97f5e0eb726f7762afee43f5.js.br} +0 -0
  122. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-9da07adb97f5e0eb726f7762afee43f5.js.gz +0 -0
  123. package/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-store-9e271e161480b0d1dd35e58616a37341.js → desktop-attachment-store-d5d3402a752965d3037191484127123b.js} +1 -1
  124. package/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-store-9e271e161480b0d1dd35e58616a37341.js.br → desktop-attachment-store-d5d3402a752965d3037191484127123b.js.br} +0 -0
  125. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-d5d3402a752965d3037191484127123b.js.gz +0 -0
  126. package/dist/server/web-ui/_expo/static/js/web/{index-8868523fc6d311c5da524c067d1cd426.js → index-136fa41d4adb7ec5c6392839cc354136.js} +1580 -1576
  127. package/dist/server/web-ui/_expo/static/js/web/index-136fa41d4adb7ec5c6392839cc354136.js.br +0 -0
  128. package/dist/server/web-ui/_expo/static/js/web/index-136fa41d4adb7ec5c6392839cc354136.js.gz +0 -0
  129. package/dist/server/web-ui/_expo/static/js/web/{indexeddb-attachment-store-369cdb67f5856fd2c72d640df0b7b79e.js → indexeddb-attachment-store-3afc19e43c8152bd3c6d71b3ea8776dc.js} +1 -1
  130. package/dist/server/web-ui/_expo/static/js/web/{indexeddb-attachment-store-369cdb67f5856fd2c72d640df0b7b79e.js.br → indexeddb-attachment-store-3afc19e43c8152bd3c6d71b3ea8776dc.js.br} +0 -0
  131. package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-3afc19e43c8152bd3c6d71b3ea8776dc.js.gz +0 -0
  132. package/dist/server/web-ui/_expo/static/js/web/{native-file-attachment-store-bcd89f6ce714279a8f4fa0e024f3a610.js → native-file-attachment-store-187a9d5c32188f357dbbf037a0f89073.js} +3 -3
  133. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-187a9d5c32188f357dbbf037a0f89073.js.br +0 -0
  134. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-187a9d5c32188f357dbbf037a0f89073.js.gz +0 -0
  135. package/dist/server/web-ui/index.html +1 -1
  136. package/dist/server/web-ui/index.html.br +0 -0
  137. package/dist/server/web-ui/index.html.gz +0 -0
  138. package/dist/src/server/agent/provider-launch-config.js +1 -1
  139. package/dist/src/server/daemon-instance.js +1 -0
  140. package/dist/src/server/local-credential.js +82 -0
  141. package/package.json +8 -7
  142. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-f41bce08c3c4ac2de0652d20234d19e9.js.gz +0 -0
  143. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-9e271e161480b0d1dd35e58616a37341.js.gz +0 -0
  144. package/dist/server/web-ui/_expo/static/js/web/index-8868523fc6d311c5da524c067d1cd426.js.br +0 -0
  145. package/dist/server/web-ui/_expo/static/js/web/index-8868523fc6d311c5da524c067d1cd426.js.gz +0 -0
  146. package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-369cdb67f5856fd2c72d640df0b7b79e.js.gz +0 -0
  147. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-bcd89f6ce714279a8f4fa0e024f3a610.js.br +0 -0
  148. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-bcd89f6ce714279a8f4fa0e024f3a610.js.gz +0 -0
@@ -1325,6 +1325,7 @@ export declare const OmpRuntimeEventSchema: z.ZodDiscriminatedUnion<[z.ZodObject
1325
1325
  title: z.ZodOptional<z.ZodString>;
1326
1326
  message: z.ZodOptional<z.ZodString>;
1327
1327
  options: z.ZodOptional<z.ZodArray<z.ZodString>>;
1328
+ optionDetails: z.ZodOptional<z.ZodUnknown>;
1328
1329
  placeholder: z.ZodOptional<z.ZodString>;
1329
1330
  url: z.ZodOptional<z.ZodString>;
1330
1331
  launchUrl: z.ZodOptional<z.ZodString>;
@@ -425,6 +425,7 @@ const OmpExtensionUiRequestSchema = z
425
425
  title: z.string().optional(),
426
426
  message: z.string().optional(),
427
427
  options: z.array(z.string()).optional(),
428
+ optionDetails: z.unknown().optional(),
428
429
  placeholder: z.string().optional(),
429
430
  url: z.string().optional(),
430
431
  launchUrl: z.string().optional(),
@@ -19,12 +19,14 @@ export declare class OpenCodeBridge {
19
19
  private server;
20
20
  private baseUrl;
21
21
  private pluginUrl;
22
+ private v2PluginUrl;
22
23
  private manifestCatalog;
23
24
  constructor(options: OpenCodeBridgeOptions);
24
25
  start(): Promise<void>;
25
26
  setManifestCatalog(catalog: PaseoToolCatalog | null): void;
26
27
  bindSession(input: BindOpenCodeSessionInput): () => void;
27
28
  decorateServerEnv(env: Record<string, string>): Record<string, string>;
29
+ decorateV2ServerEnv(env: Record<string, string>): Promise<Record<string, string>>;
28
30
  close(): Promise<void>;
29
31
  private materializePlugin;
30
32
  private route;
@@ -33,7 +35,9 @@ export declare class OpenCodeBridge {
33
35
  private requireBaseUrl;
34
36
  private requirePluginUrl;
35
37
  }
38
+ export declare function materializeOpenCodeV2Plugin(paseoHome: string): Promise<string>;
39
+ export declare function decorateOpenCodeV2Env(env: Record<string, string>, pluginUrl: string, options?: Record<string, string>): Record<string, string>;
36
40
  type CompileOpenCodeBridgePlugin = (sourcePath: string) => Promise<Uint8Array>;
37
- export declare function loadOpenCodeBridgePluginArtifact(moduleUrl: string, compileSource?: CompileOpenCodeBridgePlugin): Promise<Uint8Array>;
41
+ export declare function loadOpenCodeBridgePluginArtifact(moduleUrl: string, compileSource?: CompileOpenCodeBridgePlugin, version?: 1 | 2): Promise<Uint8Array>;
38
42
  export {};
39
43
  //# sourceMappingURL=bridge.d.ts.map
@@ -14,6 +14,7 @@ export class OpenCodeBridge {
14
14
  this.server = null;
15
15
  this.baseUrl = null;
16
16
  this.pluginUrl = null;
17
+ this.v2PluginUrl = null;
17
18
  this.manifestCatalog = null;
18
19
  this.paseoHome = options.paseoHome;
19
20
  this.logger = options.logger.child({ module: "agent", component: "opencode-bridge" });
@@ -75,6 +76,13 @@ export class OpenCodeBridge {
75
76
  }),
76
77
  };
77
78
  }
79
+ async decorateV2ServerEnv(env) {
80
+ this.v2PluginUrl ?? (this.v2PluginUrl = await this.materializePlugin(2));
81
+ return decorateOpenCodeV2Env(env, this.v2PluginUrl, {
82
+ baseUrl: this.requireBaseUrl(),
83
+ token: this.token,
84
+ });
85
+ }
78
86
  async close() {
79
87
  const server = this.server;
80
88
  this.server = null;
@@ -83,7 +91,9 @@ export class OpenCodeBridge {
83
91
  if (server)
84
92
  await closeServer(server);
85
93
  }
86
- async materializePlugin() {
94
+ async materializePlugin(version = 1) {
95
+ if (version === 2)
96
+ return materializeOpenCodeV2Plugin(this.paseoHome);
87
97
  const artifact = await loadOpenCodeBridgePluginArtifact(import.meta.url);
88
98
  const digest = createHash("sha256").update(artifact).digest("hex");
89
99
  const destination = path.join(this.paseoHome, "runtime", "opencode", `paseo-${digest}.mjs`);
@@ -108,7 +118,12 @@ export class OpenCodeBridge {
108
118
  sendJson(response, 404, { error: "OpenCode session is not bound to a Paseo agent" });
109
119
  return;
110
120
  }
111
- sendJson(response, 200, { env: binding.env });
121
+ sendJson(response, 200, {
122
+ env: binding.env,
123
+ ...(url.searchParams.has("tools")
124
+ ? { tools: [...(binding.tools?.tools.keys() ?? [])] }
125
+ : {}),
126
+ });
112
127
  return;
113
128
  }
114
129
  const toolMatch = url.pathname.match(new RegExp(`^${INTERNAL_PREFIX}/sessions/([^/]+)/tools/([^/]+)$`));
@@ -177,8 +192,43 @@ export class OpenCodeBridge {
177
192
  return this.pluginUrl;
178
193
  }
179
194
  }
180
- export async function loadOpenCodeBridgePluginArtifact(moduleUrl, compileSource = compileOpenCodeBridgePlugin) {
181
- const bundleUrl = new URL("./bridge-plugin.bundle.mjs", moduleUrl);
195
+ export async function materializeOpenCodeV2Plugin(paseoHome) {
196
+ const artifact = await loadOpenCodeBridgePluginArtifact(import.meta.url, undefined, 2);
197
+ const digest = createHash("sha256").update(artifact).digest("hex");
198
+ // V2 ignores configured file paths; it loads a package directory's server entry point.
199
+ const directory = path.join(paseoHome, "runtime", "opencode", `paseo-v2-${digest}`);
200
+ await writeFileAtomic(path.join(directory, "server.js"), artifact);
201
+ await writeFileAtomic(path.join(directory, "package.json"), JSON.stringify({
202
+ name: "paseo-opencode-bridge",
203
+ private: true,
204
+ type: "module",
205
+ exports: { "./server": "./server.js" },
206
+ }));
207
+ return pathToFileURL(directory).href;
208
+ }
209
+ export function decorateOpenCodeV2Env(env, pluginUrl, options = {}) {
210
+ const config = parseOpenCodeConfig(env.OPENCODE_CONFIG_CONTENT);
211
+ const plugins = config.plugins;
212
+ if (plugins !== undefined && !Array.isArray(plugins))
213
+ throw new Error("OpenCode v2 plugins must be an array");
214
+ return {
215
+ ...env,
216
+ OPENCODE_CONFIG_CONTENT: JSON.stringify({
217
+ ...config,
218
+ plugins: [
219
+ ...(plugins ?? []).filter((plugin) => plugin !== pluginUrl &&
220
+ !(typeof plugin === "object" &&
221
+ plugin !== null &&
222
+ "package" in plugin &&
223
+ plugin.package === pluginUrl)),
224
+ { package: pluginUrl, options },
225
+ ],
226
+ }),
227
+ };
228
+ }
229
+ export async function loadOpenCodeBridgePluginArtifact(moduleUrl, compileSource = compileOpenCodeBridgePlugin, version = 1) {
230
+ const directory = version === 2 ? "./v2/" : "./";
231
+ const bundleUrl = new URL(`${directory}bridge-plugin.bundle.mjs`, moduleUrl);
182
232
  try {
183
233
  return await readFile(bundleUrl);
184
234
  }
@@ -187,7 +237,7 @@ export async function loadOpenCodeBridgePluginArtifact(moduleUrl, compileSource
187
237
  throw new Error("Bundled OpenCode bridge plugin artifact is missing", { cause: error });
188
238
  }
189
239
  }
190
- return compileSource(fileURLToPath(new URL("./bridge-plugin.mjs", moduleUrl)));
240
+ return compileSource(fileURLToPath(new URL(`${directory}bridge-plugin.mjs`, moduleUrl)));
191
241
  }
192
242
  async function compileOpenCodeBridgePlugin(sourcePath) {
193
243
  const source = await readFile(sourcePath, "utf8");
@@ -201,6 +251,7 @@ async function compileOpenCodeBridgePlugin(sourcePath) {
201
251
  bundle: true,
202
252
  format: "esm",
203
253
  platform: "neutral",
254
+ mainFields: ["module", "main"],
204
255
  target: "es2022",
205
256
  write: false,
206
257
  });
@@ -0,0 +1,8 @@
1
+ export declare class OpenCodeHttpError extends Error {
2
+ readonly operation: string;
3
+ readonly status: number | undefined;
4
+ readonly html: boolean;
5
+ readonly name = "OpenCodeHttpError";
6
+ constructor(operation: string, status: number | undefined, html: boolean);
7
+ }
8
+ //# sourceMappingURL=http-error.d.ts.map
@@ -0,0 +1,13 @@
1
+ export class OpenCodeHttpError extends Error {
2
+ constructor(operation, status, html) {
3
+ const statusLabel = status === undefined ? "" : ` (HTTP ${status})`;
4
+ super(html
5
+ ? `OpenCode ${operation} returned HTML instead of JSON; incompatible OpenCode API${statusLabel}`
6
+ : `OpenCode ${operation} failed${statusLabel}`);
7
+ this.operation = operation;
8
+ this.status = status;
9
+ this.html = html;
10
+ this.name = "OpenCodeHttpError";
11
+ }
12
+ }
13
+ //# sourceMappingURL=http-error.js.map
@@ -0,0 +1,38 @@
1
+ import type { Logger } from "pino";
2
+ import type { AgentClient, AgentSessionConfig, AgentLaunchContext, AgentCreateSessionOptions, AgentPersistenceHandle, FetchCatalogOptions, ProviderRefreshContext, ListImportableSessionsOptions, ImportProviderSessionInput, ImportProviderSessionContext } from "../../agent-sdk-types.js";
3
+ import { type ProviderRuntimeSettings } from "../../provider-launch-config.js";
4
+ import { OpenCodeAgentClient } from "../opencode-agent.js";
5
+ export declare function openCodeMajorVersion(output: string): 1 | 2;
6
+ export type OpenCodeRuntimeClientOptions = NonNullable<ConstructorParameters<typeof OpenCodeAgentClient>[2]>;
7
+ export declare class OpenCodeRuntimeClient implements AgentClient {
8
+ private readonly logger;
9
+ private readonly settings?;
10
+ private readonly options;
11
+ readonly provider = "opencode";
12
+ readonly capabilities: import("../../agent-sdk-types.js").AgentCapabilityFlags;
13
+ readonly resolveCreateConfig: (input: import("../../agent-sdk-types.js").ResolveAgentCreateConfigInput) => import("../../agent-sdk-types.js").ResolveAgentCreateConfigResult;
14
+ readonly isCreateConfigUnattended: (input: Parameters<typeof import("../../create-agent-mode.js").isDefaultAgentCreateConfigUnattended>[0]) => boolean;
15
+ private selected;
16
+ private legacySelected;
17
+ private readonly legacy;
18
+ constructor(logger: Logger, settings?: ProviderRuntimeSettings | undefined, options?: OpenCodeRuntimeClientOptions);
19
+ private client;
20
+ isAvailable(): Promise<boolean>;
21
+ getDiagnostic(): Promise<{
22
+ diagnostic: string;
23
+ }>;
24
+ createSession(config: AgentSessionConfig, launch?: AgentLaunchContext, options?: AgentCreateSessionOptions): Promise<import("../../agent-sdk-types.js").AgentSession>;
25
+ resumeSession(handle: AgentPersistenceHandle, config?: Partial<AgentSessionConfig>, launch?: AgentLaunchContext): Promise<import("../../agent-sdk-types.js").AgentSession>;
26
+ fetchCatalog(options: FetchCatalogOptions, context?: ProviderRefreshContext): Promise<{
27
+ models: import("../../agent-sdk-types.js").AgentModelDefinition[];
28
+ modes: import("../../agent-sdk-types.js").AgentMode[];
29
+ }>;
30
+ listCommands(config: AgentSessionConfig): Promise<import("../../agent-sdk-types.js").AgentSlashCommand[]>;
31
+ listFeatures(config: AgentSessionConfig): Promise<import("../../agent-sdk-types.js").AgentFeature[]>;
32
+ listImportableSessions(options?: ListImportableSessionsOptions): Promise<import("../../agent-sdk-types.js").ImportableProviderSession[]>;
33
+ importSession(input: ImportProviderSessionInput, context: ImportProviderSessionContext): Promise<import("../../agent-sdk-types.js").ImportedProviderSession>;
34
+ archiveNativeSession(handle: AgentPersistenceHandle): Promise<void>;
35
+ unarchiveNativeSession(handle: AgentPersistenceHandle): Promise<void>;
36
+ shutdown(): Promise<void>;
37
+ }
38
+ //# sourceMappingURL=runtime-client.d.ts.map
@@ -0,0 +1,131 @@
1
+ import { createProviderEnvSpec, resolveProviderLaunch, } from "../../provider-launch-config.js";
2
+ import { execCommand } from "../../../../utils/spawn.js";
3
+ import { OpenCodeAgentClient } from "../opencode-agent.js";
4
+ import { withOpenCodeRuntimeNotice } from "./runtime-notice.js";
5
+ // Keep the minimum aligned with the SDK and binary exercised by CI.
6
+ const MINIMUM_V2 = [0, 10];
7
+ const VERSION_PATTERN = /^(?:opencode\s+)?v?(\d+)\.(\d+)\.(\d+)(?:[-+][\w.-]+)?$/i;
8
+ export function openCodeMajorVersion(output) {
9
+ const version = output.trim().match(VERSION_PATTERN);
10
+ if (!version)
11
+ return 1;
12
+ if (version[1] === "1")
13
+ return 1;
14
+ if (version[1] === "2") {
15
+ const [minimumMinor, minimumPatch] = MINIMUM_V2;
16
+ const minor = Number(version[2]);
17
+ const patch = Number(version[3]);
18
+ if (minor < minimumMinor || (minor === minimumMinor && patch < minimumPatch))
19
+ throw new Error(`OpenCode ${version[1]}.${version[2]}.${version[3]} is too old for this Paseo integration. Update OpenCode to 2.${minimumMinor}.${minimumPatch} or newer, then refresh the provider in Paseo.`);
20
+ return 2;
21
+ }
22
+ throw new Error(`Unsupported OpenCode major version ${version[1]}; supported versions are 1 and 2`);
23
+ }
24
+ // Selection belongs to the configured client, which provider reload replaces.
25
+ export class OpenCodeRuntimeClient {
26
+ constructor(logger, settings, options = {}) {
27
+ this.logger = logger;
28
+ this.settings = settings;
29
+ this.options = options;
30
+ this.provider = "opencode";
31
+ this.selected = null;
32
+ this.legacySelected = false;
33
+ this.legacy = new OpenCodeAgentClient(logger, settings, options);
34
+ this.capabilities = this.legacy.capabilities;
35
+ this.resolveCreateConfig = this.legacy.resolveCreateConfig;
36
+ this.isCreateConfigUnattended = this.legacy.isCreateConfigUnattended;
37
+ }
38
+ client() {
39
+ this.selected ?? (this.selected = (async () => {
40
+ let output;
41
+ try {
42
+ const launch = await resolveProviderLaunch({
43
+ commandConfig: this.settings?.command,
44
+ defaultBinary: "opencode",
45
+ });
46
+ const result = await execCommand(launch.command, [...launch.args, "--version"], {
47
+ ...createProviderEnvSpec({ runtimeSettings: this.settings }),
48
+ timeout: 5000,
49
+ });
50
+ output = result.stdout;
51
+ }
52
+ catch {
53
+ // Version discovery is additive: legacy wrappers need not support --version.
54
+ this.selected = null;
55
+ this.legacySelected = true;
56
+ return this.legacy;
57
+ }
58
+ if (!VERSION_PATTERN.test(output.trim()))
59
+ this.selected = null;
60
+ if (openCodeMajorVersion(output) === 1) {
61
+ this.legacySelected = true;
62
+ return this.legacy;
63
+ }
64
+ const { OpenCodeV2AgentClient } = await import("./v2/agent.js");
65
+ return new OpenCodeV2AgentClient({
66
+ logger: this.logger,
67
+ settings: this.settings,
68
+ managedProcesses: this.options.managedProcesses,
69
+ bridge: this.options.bridge,
70
+ });
71
+ })().catch((error) => {
72
+ // A failed probe must not poison refresh after the user updates the binary.
73
+ this.selected = null;
74
+ throw error;
75
+ }));
76
+ return this.selected;
77
+ }
78
+ async isAvailable() {
79
+ return this.legacy.isAvailable();
80
+ }
81
+ async getDiagnostic() {
82
+ return this.legacy.getDiagnostic();
83
+ }
84
+ async createSession(config, launch, options) {
85
+ const client = await this.client();
86
+ const session = await client.createSession(config, launch, options);
87
+ return client === this.legacy ? session : withOpenCodeRuntimeNotice(session, 2);
88
+ }
89
+ async resumeSession(handle, config, launch) {
90
+ const client = await this.client();
91
+ const session = await client.resumeSession(handle, config, launch);
92
+ return client === this.legacy ? session : withOpenCodeRuntimeNotice(session, 2, handle);
93
+ }
94
+ async fetchCatalog(options, context) {
95
+ return (await this.client()).fetchCatalog(options, context);
96
+ }
97
+ async listCommands(config) {
98
+ return (await this.client()).listCommands(config);
99
+ }
100
+ async listFeatures(config) {
101
+ return (await this.client()).listFeatures(config);
102
+ }
103
+ async listImportableSessions(options) {
104
+ return (await this.client()).listImportableSessions(options);
105
+ }
106
+ async importSession(input, context) {
107
+ const client = await this.client();
108
+ const imported = await client.importSession(input, context);
109
+ return client === this.legacy
110
+ ? imported
111
+ : { ...imported, session: withOpenCodeRuntimeNotice(imported.session, 2) };
112
+ }
113
+ async archiveNativeSession(handle) {
114
+ const client = await this.client();
115
+ if (client instanceof OpenCodeAgentClient)
116
+ await client.archiveNativeSession(handle);
117
+ }
118
+ async unarchiveNativeSession(handle) {
119
+ const client = await this.client();
120
+ if (client instanceof OpenCodeAgentClient)
121
+ await client.unarchiveNativeSession(handle);
122
+ }
123
+ async shutdown() {
124
+ const selected = await this.selected?.catch(() => null);
125
+ if (this.legacySelected)
126
+ await this.legacy.shutdown();
127
+ if (selected && selected !== this.legacy)
128
+ await selected.shutdown();
129
+ }
130
+ }
131
+ //# sourceMappingURL=runtime-client.js.map
@@ -0,0 +1,3 @@
1
+ import type { AgentPersistenceHandle, AgentSession } from "../../agent-sdk-types.js";
2
+ export declare function withOpenCodeRuntimeNotice(session: AgentSession, major: 1 | 2, previous?: AgentPersistenceHandle): AgentSession;
3
+ //# sourceMappingURL=runtime-notice.d.ts.map
@@ -0,0 +1,47 @@
1
+ import { z } from "zod";
2
+ const Notices = z.array(z.object({ major: z.union([z.literal(1), z.literal(2)]), timestamp: z.string().datetime() }));
3
+ // These rows belong to Paseo, not OpenCode's conversation. Keep their original
4
+ // timestamps in the persistence handle so history rebuilds preserve placement.
5
+ export function withOpenCodeRuntimeNotice(session, major, previous) {
6
+ const notices = Notices.parse(previous?.metadata?.openCodeRuntimeNotices ?? []);
7
+ const added = notices.at(-1)?.major !== major;
8
+ if (added)
9
+ notices.push({ major, timestamp: new Date().toISOString() });
10
+ const entries = notices.map(({ major: recordedMajor, timestamp }) => ({
11
+ timestamp,
12
+ item: {
13
+ type: "notification",
14
+ level: "info",
15
+ message: `This chat uses OpenCode v${recordedMajor}.`,
16
+ },
17
+ }));
18
+ const describePersistence = session.describePersistence.bind(session);
19
+ const streamHistory = session.streamHistory.bind(session);
20
+ return Object.assign(session, {
21
+ initialTimeline: added ? entries.slice(-1) : [],
22
+ describePersistence() {
23
+ const handle = describePersistence();
24
+ return (handle && { ...handle, metadata: { ...handle.metadata, openCodeRuntimeNotices: notices } });
25
+ },
26
+ async *streamHistory() {
27
+ const pending = [...entries];
28
+ const event = (entry) => ({
29
+ type: "timeline",
30
+ provider: "opencode",
31
+ ...entry,
32
+ });
33
+ for await (const row of streamHistory()) {
34
+ while (row.type === "timeline" &&
35
+ row.timestamp &&
36
+ pending[0]?.timestamp &&
37
+ pending[0].timestamp <= row.timestamp) {
38
+ yield event(pending.shift());
39
+ }
40
+ yield row;
41
+ }
42
+ for (const entry of pending)
43
+ yield event(entry);
44
+ },
45
+ });
46
+ }
47
+ //# sourceMappingURL=runtime-notice.js.map
@@ -1,6 +1,7 @@
1
1
  import { mkdirSync } from "node:fs";
2
2
  import { stat } from "node:fs/promises";
3
3
  import net from "node:net";
4
+ import { createRequire } from "node:module";
4
5
  import path from "node:path";
5
6
  import { findExecutable } from "../../../../executable-resolution/executable-resolution.js";
6
7
  import { spawnProcess } from "../../../../utils/spawn.js";
@@ -471,14 +472,24 @@ async function resolveOpenCodeBinary() {
471
472
  throw new Error("OpenCode binary not found. Install OpenCode (https://github.com/opencode-ai/opencode) and ensure it is available in your shell PATH.");
472
473
  }
473
474
  if (process.platform === "win32" && path.extname(found).toLowerCase() === ".cmd") {
474
- // Global npm: <prefix>/opencode.cmd → <prefix>/node_modules/opencode-ai/bin/opencode.exe
475
- const globalCandidate = path.join(path.dirname(found), "node_modules", "opencode-ai", "bin", "opencode.exe");
476
- if (await pathExists(globalCandidate))
477
- return globalCandidate;
478
- // Local/pnpm: <project>/node_modules/.bin/opencode.cmd → <project>/node_modules/opencode-ai/bin/opencode.exe
479
- const localCandidate = path.join(path.dirname(found), "..", "opencode-ai", "bin", "opencode.exe");
480
- if (await pathExists(localCandidate))
481
- return localCandidate;
475
+ const packageDirectories = [
476
+ path.join(path.dirname(found), "node_modules", "opencode-ai"),
477
+ path.join(path.dirname(found), "..", "opencode-ai"),
478
+ ];
479
+ for (const packageDirectory of packageDirectories) {
480
+ const bundledBinary = path.join(packageDirectory, "bin", "opencode.exe");
481
+ if (await pathExists(bundledBinary))
482
+ return bundledBinary;
483
+ // Newer npm releases keep the executable in a platform dependency.
484
+ // Resolve from the CLI package so nested installs and pnpm both work.
485
+ try {
486
+ const require = createRequire(path.join(packageDirectory, "package.json"));
487
+ return require.resolve(`opencode-windows-${process.arch}/bin/opencode.exe`);
488
+ }
489
+ catch {
490
+ // Try the other npm layout before retaining the original command.
491
+ }
492
+ }
482
493
  console.warn("[opencode-server] Found opencode.cmd but could not resolve the real opencode.exe. " +
483
494
  "The process may not be properly terminated on exit. Path: %s", found);
484
495
  }
@@ -0,0 +1,36 @@
1
+ import type { Logger } from "pino";
2
+ import type { AgentCapabilityFlags, AgentClient, AgentCreateSessionOptions, AgentFeature, AgentLaunchContext, AgentPersistenceHandle, AgentSession, AgentSessionConfig, FetchCatalogOptions, ImportableProviderSession, ImportProviderSessionInput, ImportProviderSessionContext, ListImportableSessionsOptions, ProviderRefreshContext } from "../../../agent-sdk-types.js";
3
+ import { type ProviderRuntimeSettings } from "../../../provider-launch-config.js";
4
+ import type { ManagedProcessRegistry } from "../../../../managed-processes/managed-processes.js";
5
+ import type { OpenCodeBridge } from "../bridge.js";
6
+ import { V2Runtime } from "./runtime.js";
7
+ interface V2AgentOptions {
8
+ logger: Logger;
9
+ settings?: ProviderRuntimeSettings;
10
+ managedProcesses?: ManagedProcessRegistry;
11
+ bridge?: OpenCodeBridge;
12
+ runtime?: Pick<V2Runtime, "acquire" | "shutdown">;
13
+ }
14
+ export declare class OpenCodeV2AgentClient implements AgentClient {
15
+ private readonly options;
16
+ readonly provider = "opencode";
17
+ readonly capabilities: AgentCapabilityFlags;
18
+ private readonly runtime;
19
+ private readonly connections;
20
+ constructor(options: V2AgentOptions);
21
+ isAvailable(): Promise<boolean>;
22
+ shutdown(): Promise<void>;
23
+ fetchCatalog(options: FetchCatalogOptions, context?: ProviderRefreshContext): Promise<{
24
+ models: import("../../../agent-sdk-types.js").AgentModelDefinition[];
25
+ modes: import("../../../agent-sdk-types.js").AgentMode[];
26
+ }>;
27
+ createSession(config: AgentSessionConfig, launch?: AgentLaunchContext, options?: AgentCreateSessionOptions): Promise<AgentSession>;
28
+ resumeSession(handle: AgentPersistenceHandle, overrides?: Partial<AgentSessionConfig>, launch?: AgentLaunchContext): Promise<AgentSession>;
29
+ private attach;
30
+ listFeatures(config: AgentSessionConfig): Promise<AgentFeature[]>;
31
+ listCommands(config: AgentSessionConfig): Promise<import("../../../agent-sdk-types.js").AgentSlashCommand[]>;
32
+ listImportableSessions(options?: ListImportableSessionsOptions): Promise<ImportableProviderSession[]>;
33
+ importSession(input: ImportProviderSessionInput, context: ImportProviderSessionContext): Promise<import("../../../agent-sdk-types.js").ImportedProviderSession>;
34
+ }
35
+ export {};
36
+ //# sourceMappingURL=agent.d.ts.map