@opencode-ai/sdk 1.3.13 → 1.3.15

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.
@@ -0,0 +1,3 @@
1
+ import { type ChildProcess } from "node:child_process";
2
+ export declare function stop(proc: ChildProcess): void;
3
+ export declare function bindAbort(proc: ChildProcess, signal?: AbortSignal, onAbort?: () => void): () => void;
@@ -0,0 +1,33 @@
1
+ import { spawnSync } from "node:child_process";
2
+ // Duplicated from `packages/opencode/src/util/process.ts` because the SDK cannot
3
+ // import `opencode` without creating a cycle (`opencode` depends on `@opencode-ai/sdk`).
4
+ export function stop(proc) {
5
+ if (proc.exitCode !== null || proc.signalCode !== null)
6
+ return;
7
+ if (process.platform === "win32" && proc.pid) {
8
+ const out = spawnSync("taskkill", ["/pid", String(proc.pid), "/T", "/F"], { windowsHide: true });
9
+ if (!out.error && out.status === 0)
10
+ return;
11
+ }
12
+ proc.kill();
13
+ }
14
+ export function bindAbort(proc, signal, onAbort) {
15
+ if (!signal)
16
+ return () => { };
17
+ const abort = () => {
18
+ clear();
19
+ stop(proc);
20
+ onAbort?.();
21
+ };
22
+ const clear = () => {
23
+ signal.removeEventListener("abort", abort);
24
+ proc.off("exit", clear);
25
+ proc.off("error", clear);
26
+ };
27
+ signal.addEventListener("abort", abort, { once: true });
28
+ proc.on("exit", clear);
29
+ proc.on("error", clear);
30
+ if (signal.aborted)
31
+ abort();
32
+ return clear;
33
+ }
package/dist/server.js CHANGED
@@ -1,4 +1,5 @@
1
- import { spawn } from "node:child_process";
1
+ import launch from "cross-spawn";
2
+ import { stop, bindAbort } from "./process.js";
2
3
  export async function createOpencodeServer(options) {
3
4
  options = Object.assign({
4
5
  hostname: "127.0.0.1",
@@ -8,28 +9,38 @@ export async function createOpencodeServer(options) {
8
9
  const args = [`serve`, `--hostname=${options.hostname}`, `--port=${options.port}`];
9
10
  if (options.config?.logLevel)
10
11
  args.push(`--log-level=${options.config.logLevel}`);
11
- const proc = spawn(`opencode`, args, {
12
- signal: options.signal,
12
+ const proc = launch(`opencode`, args, {
13
13
  env: {
14
14
  ...process.env,
15
15
  OPENCODE_CONFIG_CONTENT: JSON.stringify(options.config ?? {}),
16
16
  },
17
17
  });
18
+ let clear = () => { };
18
19
  const url = await new Promise((resolve, reject) => {
19
20
  const id = setTimeout(() => {
21
+ clear();
22
+ stop(proc);
20
23
  reject(new Error(`Timeout waiting for server to start after ${options.timeout}ms`));
21
24
  }, options.timeout);
22
25
  let output = "";
26
+ let resolved = false;
23
27
  proc.stdout?.on("data", (chunk) => {
28
+ if (resolved)
29
+ return;
24
30
  output += chunk.toString();
25
31
  const lines = output.split("\n");
26
32
  for (const line of lines) {
27
33
  if (line.startsWith("opencode server listening")) {
28
34
  const match = line.match(/on\s+(https?:\/\/[^\s]+)/);
29
35
  if (!match) {
30
- throw new Error(`Failed to parse server url from output: ${line}`);
36
+ clear();
37
+ stop(proc);
38
+ clearTimeout(id);
39
+ reject(new Error(`Failed to parse server url from output: ${line}`));
40
+ return;
31
41
  }
32
42
  clearTimeout(id);
43
+ resolved = true;
33
44
  resolve(match[1]);
34
45
  return;
35
46
  }
@@ -50,17 +61,16 @@ export async function createOpencodeServer(options) {
50
61
  clearTimeout(id);
51
62
  reject(error);
52
63
  });
53
- if (options.signal) {
54
- options.signal.addEventListener("abort", () => {
55
- clearTimeout(id);
56
- reject(new Error("Aborted"));
57
- });
58
- }
64
+ clear = bindAbort(proc, options.signal, () => {
65
+ clearTimeout(id);
66
+ reject(options.signal?.reason);
67
+ });
59
68
  });
60
69
  return {
61
70
  url,
62
71
  close() {
63
- proc.kill();
72
+ clear();
73
+ stop(proc);
64
74
  },
65
75
  };
66
76
  }
@@ -78,17 +88,18 @@ export function createOpencodeTui(options) {
78
88
  if (options?.agent) {
79
89
  args.push(`--agent=${options.agent}`);
80
90
  }
81
- const proc = spawn(`opencode`, args, {
82
- signal: options?.signal,
91
+ const proc = launch(`opencode`, args, {
83
92
  stdio: "inherit",
84
93
  env: {
85
94
  ...process.env,
86
95
  OPENCODE_CONFIG_CONTENT: JSON.stringify(options?.config ?? {}),
87
96
  },
88
97
  });
98
+ const clear = bindAbort(proc, options?.signal);
89
99
  return {
90
100
  close() {
91
- proc.kill();
101
+ clear();
102
+ stop(proc);
92
103
  },
93
104
  };
94
105
  }
@@ -1,5 +1,5 @@
1
1
  import { type Client, type Options as Options2, type TDataShape } from "./client/index.js";
2
- import type { AgentPartInput, AppAgentsResponses, AppLogErrors, AppLogResponses, AppSkillsResponses, Auth as Auth3, AuthRemoveErrors, AuthRemoveResponses, AuthSetErrors, AuthSetResponses, CommandListResponses, Config as Config3, ConfigGetResponses, ConfigProvidersResponses, ConfigUpdateErrors, ConfigUpdateResponses, EventSubscribeResponses, EventTuiCommandExecute, EventTuiPromptAppend, EventTuiSessionSelect, EventTuiToastShow, ExperimentalResourceListResponses, ExperimentalSessionListResponses, ExperimentalWorkspaceCreateErrors, ExperimentalWorkspaceCreateResponses, ExperimentalWorkspaceListResponses, ExperimentalWorkspaceRemoveErrors, ExperimentalWorkspaceRemoveResponses, FileListResponses, FilePartInput, FilePartSource, FileReadResponses, FileStatusResponses, FindFilesResponses, FindSymbolsResponses, FindTextResponses, FormatterStatusResponses, GlobalConfigGetResponses, GlobalConfigUpdateErrors, GlobalConfigUpdateResponses, GlobalDisposeResponses, GlobalEventResponses, GlobalHealthResponses, GlobalSyncEventSubscribeResponses, GlobalUpgradeErrors, GlobalUpgradeResponses, InstanceDisposeResponses, LspStatusResponses, McpAddErrors, McpAddResponses, McpAuthAuthenticateErrors, McpAuthAuthenticateResponses, McpAuthCallbackErrors, McpAuthCallbackResponses, McpAuthRemoveErrors, McpAuthRemoveResponses, McpAuthStartErrors, McpAuthStartResponses, McpConnectResponses, McpDisconnectResponses, McpLocalConfig, McpRemoteConfig, McpStatusResponses, OutputFormat, Part as Part2, PartDeleteErrors, PartDeleteResponses, PartUpdateErrors, PartUpdateResponses, PathGetResponses, PermissionListResponses, PermissionReplyErrors, PermissionReplyResponses, PermissionRespondErrors, PermissionRespondResponses, PermissionRuleset, ProjectCurrentResponses, ProjectInitGitResponses, ProjectListResponses, ProjectUpdateErrors, ProjectUpdateResponses, ProviderAuthResponses, ProviderListResponses, ProviderOauthAuthorizeErrors, ProviderOauthAuthorizeResponses, ProviderOauthCallbackErrors, ProviderOauthCallbackResponses, PtyConnectErrors, PtyConnectResponses, PtyCreateErrors, PtyCreateResponses, PtyGetErrors, PtyGetResponses, PtyListResponses, PtyRemoveErrors, PtyRemoveResponses, PtyUpdateErrors, PtyUpdateResponses, QuestionAnswer, QuestionListResponses, QuestionRejectErrors, QuestionRejectResponses, QuestionReplyErrors, QuestionReplyResponses, SessionAbortErrors, SessionAbortResponses, SessionChildrenErrors, SessionChildrenResponses, SessionCommandErrors, SessionCommandResponses, SessionCreateErrors, SessionCreateResponses, SessionDeleteErrors, SessionDeleteMessageErrors, SessionDeleteMessageResponses, SessionDeleteResponses, SessionDiffResponses, SessionForkResponses, SessionGetErrors, SessionGetResponses, SessionInitErrors, SessionInitResponses, SessionListResponses, SessionMessageErrors, SessionMessageResponses, SessionMessagesErrors, SessionMessagesResponses, SessionPromptAsyncErrors, SessionPromptAsyncResponses, SessionPromptErrors, SessionPromptResponses, SessionRevertErrors, SessionRevertResponses, SessionShareErrors, SessionShareResponses, SessionShellErrors, SessionShellResponses, SessionStatusErrors, SessionStatusResponses, SessionSummarizeErrors, SessionSummarizeResponses, SessionTodoErrors, SessionTodoResponses, SessionUnrevertErrors, SessionUnrevertResponses, SessionUnshareErrors, SessionUnshareResponses, SessionUpdateErrors, SessionUpdateResponses, SubtaskPartInput, TextPartInput, ToolIdsErrors, ToolIdsResponses, ToolListErrors, ToolListResponses, TuiAppendPromptErrors, TuiAppendPromptResponses, TuiClearPromptResponses, TuiControlNextResponses, TuiControlResponseResponses, TuiExecuteCommandErrors, TuiExecuteCommandResponses, TuiOpenHelpResponses, TuiOpenModelsResponses, TuiOpenSessionsResponses, TuiOpenThemesResponses, TuiPublishErrors, TuiPublishResponses, TuiSelectSessionErrors, TuiSelectSessionResponses, TuiShowToastResponses, TuiSubmitPromptResponses, VcsGetResponses, WorktreeCreateErrors, WorktreeCreateInput, WorktreeCreateResponses, WorktreeListResponses, WorktreeRemoveErrors, WorktreeRemoveInput, WorktreeRemoveResponses, WorktreeResetErrors, WorktreeResetInput, WorktreeResetResponses } from "./types.gen.js";
2
+ import type { AgentPartInput, AppAgentsResponses, AppLogErrors, AppLogResponses, AppSkillsResponses, Auth as Auth3, AuthRemoveErrors, AuthRemoveResponses, AuthSetErrors, AuthSetResponses, CommandListResponses, Config as Config3, ConfigGetResponses, ConfigProvidersResponses, ConfigUpdateErrors, ConfigUpdateResponses, EventSubscribeResponses, EventTuiCommandExecute, EventTuiPromptAppend, EventTuiSessionSelect, EventTuiToastShow, ExperimentalResourceListResponses, ExperimentalSessionListResponses, ExperimentalWorkspaceCreateErrors, ExperimentalWorkspaceCreateResponses, ExperimentalWorkspaceListResponses, ExperimentalWorkspaceRemoveErrors, ExperimentalWorkspaceRemoveResponses, FileListResponses, FilePartInput, FilePartSource, FileReadResponses, FileStatusResponses, FindFilesResponses, FindSymbolsResponses, FindTextResponses, FormatterStatusResponses, GlobalConfigGetResponses, GlobalConfigUpdateErrors, GlobalConfigUpdateResponses, GlobalDisposeResponses, GlobalEventResponses, GlobalHealthResponses, GlobalSyncEventSubscribeResponses, GlobalUpgradeErrors, GlobalUpgradeResponses, InstanceDisposeResponses, LspStatusResponses, McpAddErrors, McpAddResponses, McpAuthAuthenticateErrors, McpAuthAuthenticateResponses, McpAuthCallbackErrors, McpAuthCallbackResponses, McpAuthRemoveErrors, McpAuthRemoveResponses, McpAuthStartErrors, McpAuthStartResponses, McpConnectResponses, McpDisconnectResponses, McpLocalConfig, McpRemoteConfig, McpStatusResponses, OutputFormat, Part as Part2, PartDeleteErrors, PartDeleteResponses, PartUpdateErrors, PartUpdateResponses, PathGetResponses, PermissionListResponses, PermissionReplyErrors, PermissionReplyResponses, PermissionRespondErrors, PermissionRespondResponses, PermissionRuleset, ProjectCurrentResponses, ProjectInitGitResponses, ProjectListResponses, ProjectUpdateErrors, ProjectUpdateResponses, ProviderAuthResponses, ProviderListResponses, ProviderOauthAuthorizeErrors, ProviderOauthAuthorizeResponses, ProviderOauthCallbackErrors, ProviderOauthCallbackResponses, PtyConnectErrors, PtyConnectResponses, PtyCreateErrors, PtyCreateResponses, PtyGetErrors, PtyGetResponses, PtyListResponses, PtyRemoveErrors, PtyRemoveResponses, PtyUpdateErrors, PtyUpdateResponses, QuestionAnswer, QuestionListResponses, QuestionRejectErrors, QuestionRejectResponses, QuestionReplyErrors, QuestionReplyResponses, SessionAbortErrors, SessionAbortResponses, SessionChildrenErrors, SessionChildrenResponses, SessionCommandErrors, SessionCommandResponses, SessionCreateErrors, SessionCreateResponses, SessionDeleteErrors, SessionDeleteMessageErrors, SessionDeleteMessageResponses, SessionDeleteResponses, SessionDiffResponses, SessionForkResponses, SessionGetErrors, SessionGetResponses, SessionInitErrors, SessionInitResponses, SessionListResponses, SessionMessageErrors, SessionMessageResponses, SessionMessagesErrors, SessionMessagesResponses, SessionPromptAsyncErrors, SessionPromptAsyncResponses, SessionPromptErrors, SessionPromptResponses, SessionRevertErrors, SessionRevertResponses, SessionShareErrors, SessionShareResponses, SessionShellErrors, SessionShellResponses, SessionStatusErrors, SessionStatusResponses, SessionSummarizeErrors, SessionSummarizeResponses, SessionTodoErrors, SessionTodoResponses, SessionUnrevertErrors, SessionUnrevertResponses, SessionUnshareErrors, SessionUnshareResponses, SessionUpdateErrors, SessionUpdateResponses, SubtaskPartInput, TextPartInput, ToolIdsErrors, ToolIdsResponses, ToolListErrors, ToolListResponses, TuiAppendPromptErrors, TuiAppendPromptResponses, TuiClearPromptResponses, TuiControlNextResponses, TuiControlResponseResponses, TuiExecuteCommandErrors, TuiExecuteCommandResponses, TuiOpenHelpResponses, TuiOpenModelsResponses, TuiOpenSessionsResponses, TuiOpenThemesResponses, TuiPublishErrors, TuiPublishResponses, TuiSelectSessionErrors, TuiSelectSessionResponses, TuiShowToastResponses, TuiSubmitPromptResponses, VcsDiffResponses, VcsGetResponses, WorktreeCreateErrors, WorktreeCreateInput, WorktreeCreateResponses, WorktreeListResponses, WorktreeRemoveErrors, WorktreeRemoveInput, WorktreeRemoveResponses, WorktreeResetErrors, WorktreeResetInput, WorktreeResetResponses } from "./types.gen.js";
3
3
  export type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean> = Options2<TData, ThrowOnError> & {
4
4
  /**
5
5
  * You can provide a client instance returned by `createClient()` instead of
@@ -704,6 +704,7 @@ export declare class Session2 extends HeyApiClient {
704
704
  sessionID: string;
705
705
  directory?: string;
706
706
  workspace?: string;
707
+ messageID?: string;
707
708
  agent?: string;
708
709
  model?: {
709
710
  providerID: string;
@@ -1200,6 +1201,16 @@ export declare class Vcs extends HeyApiClient {
1200
1201
  directory?: string;
1201
1202
  workspace?: string;
1202
1203
  }, options?: Options<never, ThrowOnError>): import("./client/types.gen.js").RequestResult<VcsGetResponses, unknown, ThrowOnError, "fields">;
1204
+ /**
1205
+ * Get VCS diff
1206
+ *
1207
+ * Retrieve the current git diff for the working tree or against the default branch.
1208
+ */
1209
+ diff<ThrowOnError extends boolean = false>(parameters: {
1210
+ directory?: string;
1211
+ workspace?: string;
1212
+ mode: "git" | "branch";
1213
+ }, options?: Options<never, ThrowOnError>): import("./client/types.gen.js").RequestResult<VcsDiffResponses, unknown, ThrowOnError, "fields">;
1203
1214
  }
1204
1215
  export declare class Command extends HeyApiClient {
1205
1216
  /**
@@ -1357,6 +1357,7 @@ export class Session2 extends HeyApiClient {
1357
1357
  { in: "path", key: "sessionID" },
1358
1358
  { in: "query", key: "directory" },
1359
1359
  { in: "query", key: "workspace" },
1360
+ { in: "body", key: "messageID" },
1360
1361
  { in: "body", key: "agent" },
1361
1362
  { in: "body", key: "model" },
1362
1363
  { in: "body", key: "command" },
@@ -2437,6 +2438,27 @@ export class Vcs extends HeyApiClient {
2437
2438
  ...params,
2438
2439
  });
2439
2440
  }
2441
+ /**
2442
+ * Get VCS diff
2443
+ *
2444
+ * Retrieve the current git diff for the working tree or against the default branch.
2445
+ */
2446
+ diff(parameters, options) {
2447
+ const params = buildClientParams([parameters], [
2448
+ {
2449
+ args: [
2450
+ { in: "query", key: "directory" },
2451
+ { in: "query", key: "workspace" },
2452
+ { in: "query", key: "mode" },
2453
+ ],
2454
+ },
2455
+ ]);
2456
+ return (options?.client ?? this.client).get({
2457
+ url: "/vcs/diff",
2458
+ ...options,
2459
+ ...params,
2460
+ });
2461
+ }
2440
2462
  }
2441
2463
  export class Command extends HeyApiClient {
2442
2464
  /**
@@ -1707,6 +1707,7 @@ export type Path = {
1707
1707
  };
1708
1708
  export type VcsInfo = {
1709
1709
  branch?: string;
1710
+ default_branch?: string;
1710
1711
  };
1711
1712
  export type Command = {
1712
1713
  name: string;
@@ -3256,6 +3257,7 @@ export type SessionCommandResponses = {
3256
3257
  export type SessionCommandResponse = SessionCommandResponses[keyof SessionCommandResponses];
3257
3258
  export type SessionShellData = {
3258
3259
  body?: {
3260
+ messageID?: string;
3259
3261
  agent: string;
3260
3262
  model?: {
3261
3263
  providerID: string;
@@ -4335,6 +4337,23 @@ export type VcsGetResponses = {
4335
4337
  200: VcsInfo;
4336
4338
  };
4337
4339
  export type VcsGetResponse = VcsGetResponses[keyof VcsGetResponses];
4340
+ export type VcsDiffData = {
4341
+ body?: never;
4342
+ path?: never;
4343
+ query: {
4344
+ directory?: string;
4345
+ workspace?: string;
4346
+ mode: "git" | "branch";
4347
+ };
4348
+ url: "/vcs/diff";
4349
+ };
4350
+ export type VcsDiffResponses = {
4351
+ /**
4352
+ * VCS diff
4353
+ */
4354
+ 200: Array<FileDiff>;
4355
+ };
4356
+ export type VcsDiffResponse = VcsDiffResponses[keyof VcsDiffResponses];
4338
4357
  export type CommandListData = {
4339
4358
  body?: never;
4340
4359
  path?: never;
package/dist/v2/server.js CHANGED
@@ -1,4 +1,5 @@
1
- import { spawn } from "node:child_process";
1
+ import launch from "cross-spawn";
2
+ import { stop, bindAbort } from "../process.js";
2
3
  export async function createOpencodeServer(options) {
3
4
  options = Object.assign({
4
5
  hostname: "127.0.0.1",
@@ -8,28 +9,38 @@ export async function createOpencodeServer(options) {
8
9
  const args = [`serve`, `--hostname=${options.hostname}`, `--port=${options.port}`];
9
10
  if (options.config?.logLevel)
10
11
  args.push(`--log-level=${options.config.logLevel}`);
11
- const proc = spawn(`opencode`, args, {
12
- signal: options.signal,
12
+ const proc = launch(`opencode`, args, {
13
13
  env: {
14
14
  ...process.env,
15
15
  OPENCODE_CONFIG_CONTENT: JSON.stringify(options.config ?? {}),
16
16
  },
17
17
  });
18
+ let clear = () => { };
18
19
  const url = await new Promise((resolve, reject) => {
19
20
  const id = setTimeout(() => {
21
+ clear();
22
+ stop(proc);
20
23
  reject(new Error(`Timeout waiting for server to start after ${options.timeout}ms`));
21
24
  }, options.timeout);
22
25
  let output = "";
26
+ let resolved = false;
23
27
  proc.stdout?.on("data", (chunk) => {
28
+ if (resolved)
29
+ return;
24
30
  output += chunk.toString();
25
31
  const lines = output.split("\n");
26
32
  for (const line of lines) {
27
33
  if (line.startsWith("opencode server listening")) {
28
34
  const match = line.match(/on\s+(https?:\/\/[^\s]+)/);
29
35
  if (!match) {
30
- throw new Error(`Failed to parse server url from output: ${line}`);
36
+ clear();
37
+ stop(proc);
38
+ clearTimeout(id);
39
+ reject(new Error(`Failed to parse server url from output: ${line}`));
40
+ return;
31
41
  }
32
42
  clearTimeout(id);
43
+ resolved = true;
33
44
  resolve(match[1]);
34
45
  return;
35
46
  }
@@ -50,17 +61,16 @@ export async function createOpencodeServer(options) {
50
61
  clearTimeout(id);
51
62
  reject(error);
52
63
  });
53
- if (options.signal) {
54
- options.signal.addEventListener("abort", () => {
55
- clearTimeout(id);
56
- reject(new Error("Aborted"));
57
- });
58
- }
64
+ clear = bindAbort(proc, options.signal, () => {
65
+ clearTimeout(id);
66
+ reject(options.signal?.reason);
67
+ });
59
68
  });
60
69
  return {
61
70
  url,
62
71
  close() {
63
- proc.kill();
72
+ clear();
73
+ stop(proc);
64
74
  },
65
75
  };
66
76
  }
@@ -78,17 +88,18 @@ export function createOpencodeTui(options) {
78
88
  if (options?.agent) {
79
89
  args.push(`--agent=${options.agent}`);
80
90
  }
81
- const proc = spawn(`opencode`, args, {
82
- signal: options?.signal,
91
+ const proc = launch(`opencode`, args, {
83
92
  stdio: "inherit",
84
93
  env: {
85
94
  ...process.env,
86
95
  OPENCODE_CONFIG_CONTENT: JSON.stringify(options?.config ?? {}),
87
96
  },
88
97
  });
98
+ const clear = bindAbort(proc, options?.signal);
89
99
  return {
90
100
  close() {
91
- proc.kill();
101
+ clear();
102
+ stop(proc);
92
103
  },
93
104
  };
94
105
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
3
  "name": "@opencode-ai/sdk",
4
- "version": "1.3.13",
4
+ "version": "1.3.15",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "scripts": {
@@ -44,9 +44,12 @@
44
44
  "devDependencies": {
45
45
  "@hey-api/openapi-ts": "0.90.10",
46
46
  "@tsconfig/node22": "22.0.2",
47
+ "@types/cross-spawn": "6.0.6",
47
48
  "@types/node": "22.13.9",
48
- "typescript": "5.8.2",
49
- "@typescript/native-preview": "7.0.0-dev.20251207.1"
49
+ "@typescript/native-preview": "7.0.0-dev.20251207.1",
50
+ "typescript": "5.8.2"
50
51
  },
51
- "dependencies": {}
52
+ "dependencies": {
53
+ "cross-spawn": "7.0.6"
54
+ }
52
55
  }