@gitterm/sdk 0.6.0 → 0.7.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.
@@ -31,51 +31,88 @@ export type DirectOAuthModelCredential = {
31
31
  enterpriseUrl?: string;
32
32
  };
33
33
  export type DirectModelCredential = DirectApiModelCredential | DirectOAuthModelCredential;
34
- export type DirectAuthPrompt = {
35
- type: "text";
34
+ type DirectAuthPromptBase = {
36
35
  key: string;
37
- message: string;
38
- placeholder?: string;
39
- when?: {
36
+ title?: string;
37
+ description?: string;
38
+ required?: boolean;
39
+ hidden?: boolean;
40
+ /** Show the field only when every condition holds for an earlier answer. */
41
+ when?: Array<{
40
42
  key: string;
41
43
  op: "eq" | "neq";
42
- value: string;
43
- };
44
- } | {
45
- type: "select";
46
- key: string;
47
- message: string;
48
- options: Array<{
49
- label: string;
50
- value: string;
51
- hint?: string;
44
+ value: string | number | boolean;
52
45
  }>;
53
- when?: {
54
- key: string;
55
- op: "eq" | "neq";
56
- value: string;
57
- };
58
46
  };
47
+ type DirectAuthPromptOption = {
48
+ value: string;
49
+ label: string;
50
+ description?: string;
51
+ };
52
+ type DirectAuthPromptNumber = number | "Infinity" | "-Infinity" | "NaN";
53
+ /** A field an OAuth or key method asks for (OpenCode 2 `FormField`); answer it with `connectOAuth({ inputs })`. */
54
+ export type DirectAuthPrompt = (DirectAuthPromptBase & {
55
+ type: "string";
56
+ format?: "email" | "uri" | "date" | "date-time";
57
+ minLength?: number;
58
+ maxLength?: number;
59
+ pattern?: string;
60
+ placeholder?: string;
61
+ default?: string;
62
+ options?: DirectAuthPromptOption[];
63
+ custom?: boolean;
64
+ }) | (DirectAuthPromptBase & {
65
+ type: "number" | "integer";
66
+ minimum?: DirectAuthPromptNumber;
67
+ maximum?: DirectAuthPromptNumber;
68
+ default?: DirectAuthPromptNumber;
69
+ }) | (DirectAuthPromptBase & {
70
+ type: "boolean";
71
+ default?: boolean;
72
+ }) | (DirectAuthPromptBase & {
73
+ type: "multiselect";
74
+ options: DirectAuthPromptOption[];
75
+ minItems?: number;
76
+ maxItems?: number;
77
+ custom?: boolean;
78
+ default?: string[];
79
+ }) | {
80
+ key: string;
81
+ type: "external";
82
+ url: string;
83
+ title?: string;
84
+ description?: string;
85
+ };
86
+ /** OpenCode 2 `IntegrationMethod`. */
59
87
  export type DirectAuthMethod = {
60
88
  type: "oauth";
61
89
  id: string;
62
90
  label: string;
63
- prompts?: DirectAuthPrompt[];
91
+ form?: DirectAuthPrompt[];
92
+ } | {
93
+ type: "command";
94
+ id: string;
95
+ label: string;
96
+ command: string[];
64
97
  } | {
65
98
  type: "key";
66
99
  label?: string;
100
+ form?: DirectAuthPrompt[];
67
101
  } | {
68
102
  type: "env";
69
103
  names: string[];
70
104
  };
105
+ /** OpenCode 2 `IntegrationInfo`. */
71
106
  export type DirectAuthIntegration = {
72
107
  id: string;
73
108
  name: string;
109
+ metadata?: Record<string, unknown>;
74
110
  methods: DirectAuthMethod[];
75
111
  connections: Array<{
76
112
  type: "credential";
77
113
  id: string;
78
114
  label: string;
115
+ method: "key" | "oauth";
79
116
  } | {
80
117
  type: "env";
81
118
  name: string;
@@ -321,3 +358,4 @@ export type DirectRun = AgentRun & {
321
358
  };
322
359
  export type DirectRunMessage = AgentRunMessage;
323
360
  export type DirectRunWaitOptions = RunWaitOptions;
361
+ export {};
package/dist/index.js CHANGED
@@ -112,6 +112,23 @@ function normalizeServerUrl(value) {
112
112
  url.search = "";
113
113
  return url.toString().replace(/\/$/, "");
114
114
  }
115
+ function withPath(serverUrl, pathname) {
116
+ const url = new URL(serverUrl);
117
+ url.pathname = pathname;
118
+ return url.toString();
119
+ }
120
+ function basePath(serverUrl) {
121
+ return new URL(serverUrl).pathname.replace(/\/+$/, "");
122
+ }
123
+ function trpcEndpoint(serverUrl) {
124
+ const base = basePath(serverUrl);
125
+ return withPath(serverUrl, base.endsWith("/trpc") ? base : `${base}/trpc`);
126
+ }
127
+ function apiEndpoint(serverUrl, route) {
128
+ const base = basePath(serverUrl);
129
+ const apiBase = base.endsWith("/api") ? base : `${base}/api`;
130
+ return withPath(serverUrl, `${apiBase}/${route.replace(/^\/+/, "")}`);
131
+ }
115
132
  function createNoRedirectFetch(fetchImpl = fetch) {
116
133
  return async (input, init) => {
117
134
  const response = await fetchImpl(input, { ...init, redirect: "manual" });
@@ -286,9 +303,6 @@ function resolveCredentials(options) {
286
303
  }
287
304
  return { serverUrl: normalizeServerUrl(serverUrl), token };
288
305
  }
289
- function toTrpcUrl(serverUrl) {
290
- return new URL("/trpc", serverUrl).toString();
291
- }
292
306
  function toIso(value) {
293
307
  if (!value)
294
308
  return null;
@@ -492,14 +506,14 @@ function createGittermClient(options = {}) {
492
506
  splitLink({
493
507
  condition: (operation) => operation.type === "subscription",
494
508
  true: httpSubscriptionLink({
495
- url: toTrpcUrl(credentials.serverUrl),
509
+ url: trpcEndpoint(credentials.serverUrl),
496
510
  EventSource,
497
511
  eventSourceOptions: {
498
512
  fetch: (url, init) => fetchImpl(url, { ...init, headers: { ...init.headers, authorization } })
499
513
  }
500
514
  }),
501
515
  false: httpBatchLink({
502
- url: toTrpcUrl(credentials.serverUrl),
516
+ url: trpcEndpoint(credentials.serverUrl),
503
517
  fetch: fetchImpl,
504
518
  headers: () => ({ authorization })
505
519
  })
@@ -747,7 +761,7 @@ function sleep2(ms) {
747
761
  async function loginWithDeviceCode(serverUrl, options = {}) {
748
762
  const normalizedServerUrl = normalizeServerUrl(serverUrl);
749
763
  const fetchImpl = createNoRedirectFetch(options.fetch);
750
- const codeRes = await fetchImpl(new URL("/api/device/code", normalizedServerUrl), {
764
+ const codeRes = await fetchImpl(apiEndpoint(normalizedServerUrl, "device/code"), {
751
765
  method: "POST",
752
766
  headers: { "content-type": "application/json" },
753
767
  body: JSON.stringify({ clientName: options.clientName ?? "gitterm" })
@@ -763,7 +777,7 @@ async function loginWithDeviceCode(serverUrl, options = {}) {
763
777
  });
764
778
  const deadline = Date.now() + codeJson.expiresInSeconds * 1000;
765
779
  while (Date.now() < deadline) {
766
- const tokenRes = await fetchImpl(new URL("/api/device/token", normalizedServerUrl), {
780
+ const tokenRes = await fetchImpl(apiEndpoint(normalizedServerUrl, "device/token"), {
767
781
  method: "POST",
768
782
  headers: { "content-type": "application/json" },
769
783
  body: JSON.stringify({ deviceCode: codeJson.deviceCode })
@@ -802,10 +816,6 @@ function errorCode(code) {
802
816
  return code;
803
817
  return "SERVER_ERROR";
804
818
  }
805
- function toWorkspaceTrpcUrl(serverUrl) {
806
- const url = new URL(serverUrl);
807
- return url.pathname.endsWith("/trpc") ? serverUrl : new URL("/trpc", url).toString();
808
- }
809
819
  function createGittermWorkspaceClient(options = {}) {
810
820
  const detected = options.serverUrl && options.token && options.workspaceId ? null : getWorkspaceEnvironment();
811
821
  const rawServerUrl = options.serverUrl ?? detected?.serverUrl;
@@ -818,7 +828,7 @@ function createGittermWorkspaceClient(options = {}) {
818
828
  const trpc = createTRPCClient2({
819
829
  links: [
820
830
  httpBatchLink2({
821
- url: toWorkspaceTrpcUrl(serverUrl),
831
+ url: trpcEndpoint(serverUrl),
822
832
  fetch: createNoRedirectFetch(options.fetch),
823
833
  headers: () => ({ authorization: `Bearer ${token}` })
824
834
  })
@@ -1,2 +1,9 @@
1
1
  export declare function normalizeServerUrl(value: string): string;
2
+ /**
3
+ * Resolve the tRPC endpoint relative to the server URL's path, so a base like
4
+ * `https://host/api` (path-routing proxy) maps to `https://host/api/trpc`.
5
+ */
6
+ export declare function trpcEndpoint(serverUrl: string): string;
7
+ /** Resolve a server `/api/*` route, adding `/api` only when the base doesn't already end in it. */
8
+ export declare function apiEndpoint(serverUrl: string, route: string): string;
2
9
  export declare function createNoRedirectFetch(fetchImpl?: typeof fetch): typeof fetch;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitterm/sdk",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "files": [
5
5
  "dist"
6
6
  ],
@@ -25,14 +25,13 @@
25
25
  "access": "public"
26
26
  },
27
27
  "scripts": {
28
- "build": "rm -rf dist && bun build src/index.ts src/direct/index.ts --outdir dist --target node --format esm --external @trpc/client --external eventsource --external @opencode-ai/sdk --external @opencode-ai/sdk/v2 --external e2b --external @asciidev/box-sdk --external @daytonaio/sdk --external @vercel/sandbox && tsc -p tsconfig.build.json",
28
+ "build": "rm -rf dist && bun build src/index.ts src/direct/index.ts --outdir dist --target node --format esm --external @trpc/client --external eventsource --external e2b --external @asciidev/box-sdk --external @daytonaio/sdk --external @vercel/sandbox && tsc -p tsconfig.build.json",
29
29
  "prepublishOnly": "bun run check-types && bun run build",
30
30
  "check-types": "tsc --noEmit"
31
31
  },
32
32
  "dependencies": {
33
33
  "@asciidev/box-sdk": "^0.0.34",
34
34
  "@daytonaio/sdk": "^0.207.0",
35
- "@opencode-ai/sdk": "^1.18.25",
36
35
  "@trpc/client": "^11.8.1",
37
36
  "@vercel/sandbox": "^3.2.1",
38
37
  "e2b": "^2.46.1",
@@ -41,6 +40,7 @@
41
40
  "devDependencies": {
42
41
  "@gitterm/agent-runtime": "workspace:*",
43
42
  "@gitterm/api": "workspace:*",
43
+ "@opencode/client": "^2.0.19",
44
44
  "@trpc/server": "catalog:",
45
45
  "@types/bun": "^1.2.6",
46
46
  "typescript": "^5.8.2"