@gitterm/sdk 0.1.3 → 0.2.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.
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,47 @@ 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
+ /**
321
+ * A free-text answer outside `options` is accepted.
322
+ * Defaults to true, matching OpenCode; false only when the agent sets it.
323
+ */
324
+ custom: boolean;
325
+ };
326
+ /** The agent called OpenCode's `question` tool. Answer every question in one reply. */
327
+ export type AgentQuestionRequest = {
314
328
  id: string;
315
329
  kind: "question";
316
- createdAt: string;
330
+ createdAt: string | null;
317
331
  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
- }>;
332
+ questions: AgentQuestion[];
332
333
  };
334
+ /** A prompt the agent is blocked on. */
335
+ export type AgentRunInputRequest = AgentPermissionRequest | AgentQuestionRequest;
333
336
  export type AgentRunReply = {
334
337
  type: "permission";
335
338
  response: "once" | "always" | "reject";
336
339
  }
337
- /** One entry per question, each the selected option labels (or a custom answer when allowed). */
340
+ /**
341
+ * Keyed by `AgentQuestion.key`, each the selected option labels (or a single
342
+ * custom answer when the question allows one). Every question needs a key.
343
+ */
338
344
  | {
339
345
  type: "question";
340
- answers: string[][];
346
+ answers: Record<string, string[]>;
341
347
  } | {
342
348
  type: "question";
343
349
  reject: true;
@@ -349,7 +355,11 @@ export type AgentRun = {
349
355
  status: AgentRunStatus;
350
356
  error: string | null;
351
357
  finalText: string | null;
352
- /** Non-empty exactly while `status` is `awaiting_input`. */
358
+ /**
359
+ * Non-empty exactly while `status` is `awaiting_input`. Usually one request;
360
+ * several when the agent issued parallel tool calls that each need approval.
361
+ * Answer each with `runs.respond()`; the run resumes once none remain.
362
+ */
353
363
  pendingInputs: AgentRunInputRequest[];
354
364
  context: {
355
365
  type: "isolated";
@@ -379,7 +389,7 @@ export type AgentRunListResult = {
379
389
  };
380
390
  };
381
391
  export type AgentRunCreateInput = {
382
- workspaceId: string;
392
+ workspace: WorkspaceRef;
383
393
  /**
384
394
  * Stable key used to return the same run when a request is retried.
385
395
  * Defaults to a random UUID, which gives no retry protection; pass your own
@@ -396,7 +406,7 @@ export type AgentRunCreateInput = {
396
406
  type: "isolated";
397
407
  } | {
398
408
  type: "continue";
399
- runId: string;
409
+ run: RunRef;
400
410
  };
401
411
  /**
402
412
  * Wait for the `afterAgent` setup phase to succeed before submitting the
@@ -430,17 +440,53 @@ export type AgentRunMessagePart = {
430
440
  startedAt: string | null;
431
441
  completedAt: string | null;
432
442
  };
433
- export type RunWaitOptions = {
434
- /** Default 30 minutes. */
435
- timeoutMs?: number;
436
- /** Abort the wait early; the promise rejects with code `ABORTED`. */
443
+ export type RunWatchOptions = {
444
+ /** Stop the stream early; the iterator throws with code `ABORTED`. */
437
445
  signal?: AbortSignal;
446
+ };
447
+ export type RunWaitOptions = RunWatchOptions & {
448
+ /** Default 30 minutes. When it elapses the promise rejects with code `TIMEOUT`. */
449
+ timeoutMs?: number;
438
450
  /**
439
451
  * `input-or-terminal` (default) also returns when the run is `awaiting_input`
440
452
  * so the caller can answer with `runs.respond()`; `terminal` keeps waiting.
441
453
  */
442
454
  until?: "input-or-terminal" | "terminal";
443
455
  };
456
+ export type AgentRunResult<T extends AgentRun = AgentRun> = T & {
457
+ status: "completed";
458
+ };
459
+ export type RunResultOptions = RunWatchOptions & {
460
+ /** Total deadline, including time spent in human-input handlers. Default 30 minutes. */
461
+ timeoutMs?: number;
462
+ onPermission?: (request: AgentPermissionRequest, options: {
463
+ signal: AbortSignal;
464
+ }) => AgentRunReplyPermission | Promise<AgentRunReplyPermission>;
465
+ onQuestion?: (request: AgentQuestionRequest, options: {
466
+ signal: AbortSignal;
467
+ }) => AgentRunReplyQuestion | Promise<AgentRunReplyQuestion>;
468
+ };
469
+ export type AgentRunReplyPermission = "once" | "always" | "reject";
470
+ export type AgentRunReplyQuestion = {
471
+ answers: Record<string, string[]>;
472
+ } | {
473
+ reject: true;
474
+ };
475
+ export type AgentRunEvent<T extends AgentRun = AgentRun> = {
476
+ type: "run.status";
477
+ run: T;
478
+ } | {
479
+ type: "input.required";
480
+ run: T;
481
+ request: AgentRunInputRequest;
482
+ } | {
483
+ type: "input.resolved";
484
+ run: T;
485
+ requestId: string;
486
+ } | {
487
+ type: "run.completed" | "run.failed" | "run.cancelled";
488
+ run: T;
489
+ };
444
490
  export type AgentRunMessage = {
445
491
  id: string;
446
492
  role: "user" | "assistant";
@@ -473,31 +519,48 @@ export type WorkspaceSetupStatus = {
473
519
  export type ModelProviderInfo = {
474
520
  id: string;
475
521
  name: string;
522
+ /** Use this key in models.providers and provider/model references. */
523
+ logicalProviderKey: string;
476
524
  displayName: string;
477
525
  authType: string;
478
526
  isRecommended: boolean;
479
527
  };
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;
528
+ export type ModelInfo = {
529
+ /** Full provider/model identifier accepted by runs.create(). */
530
+ id: string;
531
+ name: string;
532
+ provider: string;
533
+ isFree: boolean;
534
+ isRecommended: boolean;
535
+ };
536
+ /** Control-plane configuration, not a live authentication check. */
537
+ export type WorkspaceModelAccess = {
538
+ providers: Array<{
539
+ provider: string;
540
+ source: "saved" | "apiKey";
541
+ label: string | null;
542
+ active: boolean;
543
+ }>;
544
+ /** Known catalog models whose provider is configured, plus free models. */
545
+ models: ModelInfo[];
546
+ };
547
+ /** Explicit credential intent. Saved sources use dashboard labels, never credential IDs. */
548
+ export type ModelCredentialSource = {
549
+ source: "saved";
550
+ label: string;
497
551
  } | {
498
- providerName: string;
499
- label?: string;
500
- apiKey?: never;
552
+ source: "default";
553
+ } | {
554
+ source: "apiKey";
555
+ apiKey: string;
556
+ };
557
+ export type WorkspaceModelsInput = {
558
+ /** Workspace default, overridden by runs.create({ model }). */
559
+ default?: string;
560
+ /** Default for an explicit block is none. */
561
+ inherit?: "defaults" | "none";
562
+ /** Keys are model provider names (e.g. openai for API keys AND ChatGPT subscriptions). */
563
+ providers?: Record<string, ModelCredentialSource>;
501
564
  };
502
565
  /** Safe dashboard credential metadata. Secret material is never returned by the SDK. */
503
566
  export type ModelCredential = {
@@ -507,7 +570,7 @@ export type ModelCredential = {
507
570
  providerDisplayName: string;
508
571
  logicalProviderKey: string;
509
572
  authType: string;
510
- /** Unique per provider; use it in `modelCredentials: [{ providerName, label }]`. */
573
+ /** Select with models.providers[logicalProviderKey] = { source: "saved", label }. */
511
574
  label: string;
512
575
  keyHash: string;
513
576
  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.1",
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",