@gitterm/sdk 0.1.3 → 0.2.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.
package/dist/types.d.ts CHANGED
@@ -58,13 +58,10 @@ export type Workspace = {
58
58
  export type WorkspaceRef = string | {
59
59
  id: string;
60
60
  };
61
- /** A run id pair, or any object carrying one (e.g. an `AgentRun`). */
61
+ /** An `AgentRun`, or any object carrying its `workspaceId` and `id`. */
62
62
  export type RunRef = {
63
63
  workspaceId: string;
64
64
  id: string;
65
- } | {
66
- workspaceId: string;
67
- runId: string;
68
65
  };
69
66
  /** `v1` = OpenCode 1.x (`/event`, `/session/*`); `v2` = OpenCode 2 (`/api/*`), experimental until 2.0 ships. */
70
67
  export type OpencodeApi = "v1" | "v2";
@@ -234,12 +231,8 @@ export type WorkspaceCreateInput = {
234
231
  /** Defaults from the selected provider. */
235
232
  persistent?: boolean;
236
233
  workspaceProfile?: "standard" | "ssh-enabled";
237
- /**
238
- * One entry per provider. Omit entirely to inject the dashboard defaults.
239
- * Naming any dashboard credential (an entry without `apiKey`) turns off the
240
- * implicit defaults, so list every provider the workspace needs.
241
- */
242
- modelCredentials?: WorkspaceModelCredentialInput[];
234
+ /** Omit to use dashboard defaults. An explicit block inherits nothing unless requested. */
235
+ models?: WorkspaceModelsInput;
243
236
  /** Ephemeral environment variables injected into this workspace only. */
244
237
  environmentVariables?: Record<string, string>;
245
238
  /**
@@ -297,11 +290,11 @@ export type WorkspaceEnsureRunningResult = {
297
290
  export type AgentRunStatus = "pending" | "running" | "retrying"
298
291
  /** Blocked on a permission prompt or agent question; answer with `runs.respond()`. */
299
292
  | "awaiting_input" | "completed" | "failed" | "cancelled";
300
- /** A prompt the agent is blocked on. `permission` = OpenCode tool approval; `question` = the agent's `question` tool. */
301
- export type AgentRunInputRequest = {
293
+ /** OpenCode asked to run a tool your `permission` config does not pre-approve. */
294
+ export type AgentPermissionRequest = {
302
295
  id: string;
303
296
  kind: "permission";
304
- createdAt: string;
297
+ createdAt: string | null;
305
298
  toolCallId: string | null;
306
299
  /** Permission action, e.g. "bash" or "edit". */
307
300
  permission: string;
@@ -310,34 +303,44 @@ export type AgentRunInputRequest = {
310
303
  /** Patterns OpenCode remembers when answered with "always". */
311
304
  always: string[];
312
305
  title: string;
313
- } | {
306
+ };
307
+ /** One choice to show the user. Answer with the `label`. */
308
+ export type AgentQuestionOption = {
309
+ label: string;
310
+ description: string;
311
+ };
312
+ export type AgentQuestion = {
313
+ /** Identifies this question in `AgentRunReply.answers`. Unique within a request. */
314
+ key: string;
315
+ header: string;
316
+ question: string;
317
+ options: AgentQuestionOption[];
318
+ /** More than one option may be selected. */
319
+ multiple: boolean;
320
+ /** A free-text answer outside `options` is accepted. */
321
+ custom: boolean;
322
+ };
323
+ /** The agent called OpenCode's `question` tool. Answer every question in one reply. */
324
+ export type AgentQuestionRequest = {
314
325
  id: string;
315
326
  kind: "question";
316
- createdAt: string;
327
+ createdAt: string | null;
317
328
  toolCallId: string | null;
318
- questions: Array<{
319
- key: string;
320
- header: string;
321
- question: string;
322
- options: Array<{
323
- label: string;
324
- description: string;
325
- value?: string;
326
- }>;
327
- /** More than one option may be selected. */
328
- multiple: boolean;
329
- /** A free-text answer outside `options` is accepted. */
330
- custom: boolean;
331
- }>;
329
+ questions: AgentQuestion[];
332
330
  };
331
+ /** A prompt the agent is blocked on. */
332
+ export type AgentRunInputRequest = AgentPermissionRequest | AgentQuestionRequest;
333
333
  export type AgentRunReply = {
334
334
  type: "permission";
335
335
  response: "once" | "always" | "reject";
336
336
  }
337
- /** One entry per question, each the selected option labels (or a custom answer when allowed). */
337
+ /**
338
+ * Keyed by `AgentQuestion.key`, each the selected option labels (or a single
339
+ * custom answer when the question allows one). Every question needs a key.
340
+ */
338
341
  | {
339
342
  type: "question";
340
- answers: string[][];
343
+ answers: Record<string, string[]>;
341
344
  } | {
342
345
  type: "question";
343
346
  reject: true;
@@ -349,7 +352,11 @@ export type AgentRun = {
349
352
  status: AgentRunStatus;
350
353
  error: string | null;
351
354
  finalText: string | null;
352
- /** Non-empty exactly while `status` is `awaiting_input`. */
355
+ /**
356
+ * Non-empty exactly while `status` is `awaiting_input`. Usually one request;
357
+ * several when the agent issued parallel tool calls that each need approval.
358
+ * Answer each with `runs.respond()`; the run resumes once none remain.
359
+ */
353
360
  pendingInputs: AgentRunInputRequest[];
354
361
  context: {
355
362
  type: "isolated";
@@ -379,7 +386,7 @@ export type AgentRunListResult = {
379
386
  };
380
387
  };
381
388
  export type AgentRunCreateInput = {
382
- workspaceId: string;
389
+ workspace: WorkspaceRef;
383
390
  /**
384
391
  * Stable key used to return the same run when a request is retried.
385
392
  * Defaults to a random UUID, which gives no retry protection; pass your own
@@ -396,7 +403,7 @@ export type AgentRunCreateInput = {
396
403
  type: "isolated";
397
404
  } | {
398
405
  type: "continue";
399
- runId: string;
406
+ run: RunRef;
400
407
  };
401
408
  /**
402
409
  * Wait for the `afterAgent` setup phase to succeed before submitting the
@@ -430,17 +437,53 @@ export type AgentRunMessagePart = {
430
437
  startedAt: string | null;
431
438
  completedAt: string | null;
432
439
  };
433
- export type RunWaitOptions = {
434
- /** Default 30 minutes. */
435
- timeoutMs?: number;
436
- /** Abort the wait early; the promise rejects with code `ABORTED`. */
440
+ export type RunWatchOptions = {
441
+ /** Stop the stream early; the iterator throws with code `ABORTED`. */
437
442
  signal?: AbortSignal;
443
+ };
444
+ export type RunWaitOptions = RunWatchOptions & {
445
+ /** Default 30 minutes. When it elapses the promise rejects with code `TIMEOUT`. */
446
+ timeoutMs?: number;
438
447
  /**
439
448
  * `input-or-terminal` (default) also returns when the run is `awaiting_input`
440
449
  * so the caller can answer with `runs.respond()`; `terminal` keeps waiting.
441
450
  */
442
451
  until?: "input-or-terminal" | "terminal";
443
452
  };
453
+ export type AgentRunResult<T extends AgentRun = AgentRun> = T & {
454
+ status: "completed";
455
+ };
456
+ export type RunResultOptions = RunWatchOptions & {
457
+ /** Total deadline, including time spent in human-input handlers. Default 30 minutes. */
458
+ timeoutMs?: number;
459
+ onPermission?: (request: AgentPermissionRequest, options: {
460
+ signal: AbortSignal;
461
+ }) => AgentRunReplyPermission | Promise<AgentRunReplyPermission>;
462
+ onQuestion?: (request: AgentQuestionRequest, options: {
463
+ signal: AbortSignal;
464
+ }) => AgentRunReplyQuestion | Promise<AgentRunReplyQuestion>;
465
+ };
466
+ export type AgentRunReplyPermission = "once" | "always" | "reject";
467
+ export type AgentRunReplyQuestion = {
468
+ answers: Record<string, string[]>;
469
+ } | {
470
+ reject: true;
471
+ };
472
+ export type AgentRunEvent<T extends AgentRun = AgentRun> = {
473
+ type: "run.status";
474
+ run: T;
475
+ } | {
476
+ type: "input.required";
477
+ run: T;
478
+ request: AgentRunInputRequest;
479
+ } | {
480
+ type: "input.resolved";
481
+ run: T;
482
+ requestId: string;
483
+ } | {
484
+ type: "run.completed" | "run.failed" | "run.cancelled";
485
+ run: T;
486
+ };
444
487
  export type AgentRunMessage = {
445
488
  id: string;
446
489
  role: "user" | "assistant";
@@ -473,31 +516,48 @@ export type WorkspaceSetupStatus = {
473
516
  export type ModelProviderInfo = {
474
517
  id: string;
475
518
  name: string;
519
+ /** Use this key in models.providers and provider/model references. */
520
+ logicalProviderKey: string;
476
521
  displayName: string;
477
522
  authType: string;
478
523
  isRecommended: boolean;
479
524
  };
480
- /**
481
- * Selects the credential for one provider on workspaces.create().
482
- * `providerName` comes from credentials.listProviders(), e.g. "anthropic" or
483
- * "openai"; unknown providers throw MODEL_CREDENTIAL_INVALID.
484
- *
485
- * - `{ providerName, apiKey }` — inline key for this workspace only, never
486
- * stored. Overrides any dashboard credential for the same provider.
487
- * OAuth-only providers throw MODEL_CREDENTIAL_INVALID.
488
- * - `{ providerName, label }` — the dashboard credential with that label.
489
- * Unknown labels throw MODEL_CREDENTIAL_UNAVAILABLE listing the labels
490
- * that exist.
491
- * - `{ providerName }` — that provider's dashboard default credential.
492
- */
493
- export type WorkspaceModelCredentialInput = {
494
- providerName: string;
495
- apiKey: string;
496
- label?: never;
525
+ export type ModelInfo = {
526
+ /** Full provider/model identifier accepted by runs.create(). */
527
+ id: string;
528
+ name: string;
529
+ provider: string;
530
+ isFree: boolean;
531
+ isRecommended: boolean;
532
+ };
533
+ /** Control-plane configuration, not a live authentication check. */
534
+ export type WorkspaceModelAccess = {
535
+ providers: Array<{
536
+ provider: string;
537
+ source: "saved" | "apiKey";
538
+ label: string | null;
539
+ active: boolean;
540
+ }>;
541
+ /** Known catalog models whose provider is configured, plus free models. */
542
+ models: ModelInfo[];
543
+ };
544
+ /** Explicit credential intent. Saved sources use dashboard labels, never credential IDs. */
545
+ export type ModelCredentialSource = {
546
+ source: "saved";
547
+ label: string;
497
548
  } | {
498
- providerName: string;
499
- label?: string;
500
- apiKey?: never;
549
+ source: "default";
550
+ } | {
551
+ source: "apiKey";
552
+ apiKey: string;
553
+ };
554
+ export type WorkspaceModelsInput = {
555
+ /** Workspace default, overridden by runs.create({ model }). */
556
+ default?: string;
557
+ /** Default for an explicit block is none. */
558
+ inherit?: "defaults" | "none";
559
+ /** Keys are model provider names (e.g. openai for API keys AND ChatGPT subscriptions). */
560
+ providers?: Record<string, ModelCredentialSource>;
501
561
  };
502
562
  /** Safe dashboard credential metadata. Secret material is never returned by the SDK. */
503
563
  export type ModelCredential = {
@@ -507,7 +567,7 @@ export type ModelCredential = {
507
567
  providerDisplayName: string;
508
568
  logicalProviderKey: string;
509
569
  authType: string;
510
- /** Unique per provider; use it in `modelCredentials: [{ providerName, label }]`. */
570
+ /** Select with models.providers[logicalProviderKey] = { source: "saved", label }. */
511
571
  label: string;
512
572
  keyHash: string;
513
573
  isActive: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitterm/sdk",
3
- "version": "0.1.3",
3
+ "version": "0.2.0",
4
4
  "files": [
5
5
  "dist"
6
6
  ],
@@ -39,6 +39,7 @@
39
39
  "eventsource": "^5.1.1"
40
40
  },
41
41
  "devDependencies": {
42
+ "@gitterm/agent-runtime": "workspace:*",
42
43
  "@gitterm/api": "workspace:*",
43
44
  "@trpc/server": "catalog:",
44
45
  "@types/bun": "^1.2.6",