@llmsafespaces/sdk 0.30.0 → 0.31.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/index.cjs CHANGED
@@ -205,7 +205,8 @@ var LLMSafeSpaces = class {
205
205
  throw new RateLimitError(msg);
206
206
  case 503: {
207
207
  const reason = errBody.reason;
208
- const retryAfter = errBody.retryAfter;
208
+ const headerAfter = Number(res.headers.get("Retry-After"));
209
+ const retryAfter = errBody.retryAfter ?? (Number.isFinite(headerAfter) && headerAfter > 0 ? headerAfter : void 0);
209
210
  const apiMessage = errBody.message ?? msg;
210
211
  throw new ServiceUnavailableError(apiMessage, reason, retryAfter);
211
212
  }
@@ -418,13 +419,17 @@ var SessionsAPI = class {
418
419
  abort(workspaceId, sessionId) {
419
420
  return this.client.request("POST", `/workspaces/${workspaceId}/sessions/${sessionId}/abort`);
420
421
  }
422
+ /** Gets one session in contract shape (pkg/session Session). */
421
423
  get(workspaceId, sessionId) {
422
424
  return this.client.request("GET", `/workspaces/${workspaceId}/sessions/${sessionId}`);
423
425
  }
424
426
  /**
425
- * Sends a prompt asynchronously (202; the reply arrives on the workspace
426
- * SSE stream). Optional `files` (Epic 68) are upload-namespace paths
427
- * the API composes the v1 attachment manifest into the dispatched text.
427
+ * Sends a prompt asynchronously into the delivery outbox (202) and
428
+ * returns the accepted-entry receipt; the agent's reply arrives on the
429
+ * workspace SSE stream. A retried clientMessageID answers 200 with the
430
+ * ORIGINAL accepted entry (status "duplicate"). Optional `files`
431
+ * (Epic 68) are upload-namespace paths — the API composes the v1
432
+ * attachment manifest into the dispatched text.
428
433
  */
429
434
  sendPromptAsync(workspaceId, sessionId, message, files) {
430
435
  const body = { parts: [{ type: "text", text: message }] };
@@ -623,25 +628,57 @@ var UsageAPI = class {
623
628
  return this.client.request("GET", "/usage/quota");
624
629
  }
625
630
  };
631
+ function lateAnswerOnly(late) {
632
+ return late?.status === "queued" ? late : void 0;
633
+ }
626
634
  var InputRequestsAPI = class {
627
635
  constructor(client) {
628
636
  this.client = client;
629
637
  }
630
638
  client;
639
+ /** Pending questions as contract InputRequest values (kind=question). */
631
640
  listQuestions(workspaceId) {
632
641
  return this.client.request("GET", `/workspaces/${workspaceId}/question`);
633
642
  }
634
- replyQuestion(workspaceId, requestId, body) {
635
- return this.client.request("POST", `/workspaces/${workspaceId}/question/${requestId}/reply`, body);
643
+ /**
644
+ * Answers a live question. When the ask is no longer live but its
645
+ * unanswered-question inbox record is pending (#1313), the server
646
+ * accepts the answer as a late answer through the delivery outbox
647
+ * (202) and the resolved value carries the outbox entry; a live
648
+ * answer (200) resolves to undefined.
649
+ */
650
+ replyQuestion(workspaceId, requestId, answers) {
651
+ return this.client.request("POST", `/workspaces/${workspaceId}/question/${requestId}/reply`, { answers }).then(lateAnswerOnly);
636
652
  }
653
+ /** Rejects (dismisses) a pending question. */
637
654
  rejectQuestion(workspaceId, requestId) {
638
655
  return this.client.request("POST", `/workspaces/${workspaceId}/question/${requestId}/reject`);
639
656
  }
657
+ /** Pending permissions as contract InputRequest values (kind=permission). */
640
658
  listPermissions(workspaceId) {
641
659
  return this.client.request("GET", `/workspaces/${workspaceId}/permission`);
642
660
  }
643
- replyPermission(workspaceId, requestId, body) {
644
- return this.client.request("POST", `/workspaces/${workspaceId}/permission/${requestId}/reply`, body);
661
+ /**
662
+ * Answers a live permission with the reply vocabulary
663
+ * ("once" | "always" | "reject") and an optional message. A late
664
+ * decision (ask no longer live, inbox record pending) resolves to the
665
+ * 202 outbox entry; a live answer (200) resolves to undefined.
666
+ */
667
+ replyPermission(workspaceId, requestId, reply, message) {
668
+ const body = { reply };
669
+ if (message !== void 0 && message !== "") body.message = message;
670
+ return this.client.request("POST", `/workspaces/${workspaceId}/permission/${requestId}/reply`, body).then(lateAnswerOnly);
671
+ }
672
+ /**
673
+ * Dismisses an unanswered-question inbox record (#1313): the record
674
+ * becomes dismissed; a still-live ask is rejected first server-side.
675
+ */
676
+ dismissInboxRecord(workspaceId, sessionId, requestId) {
677
+ return this.client.request("DELETE", `/workspaces/${workspaceId}/sessions/${sessionId}/inbox/${requestId}`);
678
+ }
679
+ /** Triggers an input-snapshot flight (202; events arrive on the event streams). */
680
+ requestInputSnapshot(workspaceId) {
681
+ return this.client.request("POST", `/workspaces/${workspaceId}/input-snapshot`);
645
682
  }
646
683
  };
647
684
  var ProbeAPI = class {
package/dist/index.d.cts CHANGED
@@ -103,6 +103,44 @@ interface SessionListItem {
103
103
  messageCount: number;
104
104
  status: string;
105
105
  }
106
+ /**
107
+ * The platform-owned view of one agent session (pkg/session contract,
108
+ * design 0049) — the getSession response shape.
109
+ */
110
+ interface Session {
111
+ id: string;
112
+ workspaceId: string;
113
+ parentId?: string;
114
+ title?: string;
115
+ agentId?: string;
116
+ model?: ModelRef;
117
+ status: "unknown" | "idle" | "busy" | "error" | "compacting" | "archived";
118
+ cost?: Cost;
119
+ contextUsage?: ContextUsage;
120
+ time?: TimeRange;
121
+ summary?: string;
122
+ archived?: boolean;
123
+ }
124
+ /** The session's live context occupancy (non-monotonic: compaction resets it). */
125
+ interface ContextUsage {
126
+ used: number;
127
+ window?: number;
128
+ }
129
+ /** Bounds a session or message. completedAt is absent while busy. */
130
+ interface TimeRange {
131
+ startedAt: string;
132
+ completedAt?: string;
133
+ }
134
+ /**
135
+ * The delivery-outbox receipt for an async prompt: the 202 body of a
136
+ * fresh accept, and the 200 body of a retried clientMessageID (which
137
+ * echoes the ORIGINAL accepted entry with status "duplicate").
138
+ */
139
+ interface PromptAccepted {
140
+ messageID: string;
141
+ clientMessageID?: string;
142
+ status: "queued" | "duplicate";
143
+ }
106
144
  interface ActiveSessionsResponse {
107
145
  active: string[];
108
146
  maxActive: number;
@@ -136,7 +174,7 @@ interface Message {
136
174
  }
137
175
  /** One renderable part of a message — the closed 5-type union. */
138
176
  interface Part {
139
- type: "text" | "reasoning" | "tool" | "file-change" | "custom";
177
+ type: "text" | "reasoning" | "tool" | "file_change" | "custom";
140
178
  id?: string;
141
179
  text?: string;
142
180
  reasoning?: string;
@@ -194,6 +232,20 @@ interface ToolRef {
194
232
  messageId?: string;
195
233
  callId?: string;
196
234
  }
235
+ /**
236
+ * The 202 body for a reply that landed as a late answer through the
237
+ * delivery outbox (#1313): the ask was no longer live, so the answer
238
+ * rides a Q&A user message instead of the live ask.
239
+ */
240
+ interface InboxLateAnswerAccepted {
241
+ status: "queued";
242
+ /** Ask-scoped dedupe key (`inbox-{requestID}-answer`); duplicate clicks return the original. */
243
+ clientMessageID: string;
244
+ /** The outbox entry ID (202) or the original accepted entry (duplicate). */
245
+ messageID: string;
246
+ /** Present and true when the ask-scoped key was already accepted. */
247
+ duplicate?: boolean;
248
+ }
197
249
  interface ModelRef {
198
250
  id: string;
199
251
  provider?: string;
@@ -463,13 +515,17 @@ declare class SessionsAPI {
463
515
  nextCursor: string;
464
516
  }>;
465
517
  abort(workspaceId: string, sessionId: string): Promise<void>;
466
- get(workspaceId: string, sessionId: string): Promise<Record<string, unknown>>;
518
+ /** Gets one session in contract shape (pkg/session Session). */
519
+ get(workspaceId: string, sessionId: string): Promise<Session>;
467
520
  /**
468
- * Sends a prompt asynchronously (202; the reply arrives on the workspace
469
- * SSE stream). Optional `files` (Epic 68) are upload-namespace paths
470
- * the API composes the v1 attachment manifest into the dispatched text.
521
+ * Sends a prompt asynchronously into the delivery outbox (202) and
522
+ * returns the accepted-entry receipt; the agent's reply arrives on the
523
+ * workspace SSE stream. A retried clientMessageID answers 200 with the
524
+ * ORIGINAL accepted entry (status "duplicate"). Optional `files`
525
+ * (Epic 68) are upload-namespace paths — the API composes the v1
526
+ * attachment manifest into the dispatched text.
471
527
  */
472
- sendPromptAsync(workspaceId: string, sessionId: string, message: string, files?: string[]): Promise<void>;
528
+ sendPromptAsync(workspaceId: string, sessionId: string, message: string, files?: string[]): Promise<PromptAccepted>;
473
529
  delete(workspaceId: string, sessionId: string): Promise<void>;
474
530
  /** Enqueues a message for a busy session; optional `files` as in sendPromptAsync. */
475
531
  enqueue(workspaceId: string, sessionId: string, text: string, files?: string[]): Promise<{
@@ -587,11 +643,34 @@ declare class UsageAPI {
587
643
  declare class InputRequestsAPI {
588
644
  private client;
589
645
  constructor(client: LLMSafeSpaces);
590
- listQuestions(workspaceId: string): Promise<unknown[]>;
591
- replyQuestion(workspaceId: string, requestId: string, body: Record<string, unknown>): Promise<void>;
646
+ /** Pending questions as contract InputRequest values (kind=question). */
647
+ listQuestions(workspaceId: string): Promise<InputRequest[]>;
648
+ /**
649
+ * Answers a live question. When the ask is no longer live but its
650
+ * unanswered-question inbox record is pending (#1313), the server
651
+ * accepts the answer as a late answer through the delivery outbox
652
+ * (202) and the resolved value carries the outbox entry; a live
653
+ * answer (200) resolves to undefined.
654
+ */
655
+ replyQuestion(workspaceId: string, requestId: string, answers: string[][]): Promise<InboxLateAnswerAccepted | undefined>;
656
+ /** Rejects (dismisses) a pending question. */
592
657
  rejectQuestion(workspaceId: string, requestId: string): Promise<void>;
593
- listPermissions(workspaceId: string): Promise<unknown[]>;
594
- replyPermission(workspaceId: string, requestId: string, body: Record<string, unknown>): Promise<void>;
658
+ /** Pending permissions as contract InputRequest values (kind=permission). */
659
+ listPermissions(workspaceId: string): Promise<InputRequest[]>;
660
+ /**
661
+ * Answers a live permission with the reply vocabulary
662
+ * ("once" | "always" | "reject") and an optional message. A late
663
+ * decision (ask no longer live, inbox record pending) resolves to the
664
+ * 202 outbox entry; a live answer (200) resolves to undefined.
665
+ */
666
+ replyPermission(workspaceId: string, requestId: string, reply: "once" | "always" | "reject", message?: string): Promise<InboxLateAnswerAccepted | undefined>;
667
+ /**
668
+ * Dismisses an unanswered-question inbox record (#1313): the record
669
+ * becomes dismissed; a still-live ask is rejected first server-side.
670
+ */
671
+ dismissInboxRecord(workspaceId: string, sessionId: string, requestId: string): Promise<void>;
672
+ /** Triggers an input-snapshot flight (202; events arrive on the event streams). */
673
+ requestInputSnapshot(workspaceId: string): Promise<void>;
595
674
  }
596
675
  declare class ProbeAPI {
597
676
  private client;
@@ -814,4 +893,4 @@ declare class ServiceUnavailableError extends LLMSafeSpacesError {
814
893
  constructor(message?: string, reason?: string, retryAfter?: number);
815
894
  }
816
895
 
817
- export { type APIKey, type ActivateWorkspaceResponse, type ActiveSessionsResponse, AuthError, type AuthResponse, type ClientOptions, ConflictError, type Cost, type CreateMcpServerRequest, type CreateProviderCredentialRequest, type CreateSecretRequest, type CreateWorkspaceRequest, type EnsureSessionResponse, type FetchFn, type FileDiff, type FileUpload, type InputOption, type InputRequest, LLMSafeSpaces, LLMSafeSpacesError, type McpAutoApplyRule, type McpServer, type Message, type ModelRef, NotFoundError, type PaginationMetadata, type Part, type ProviderCredential, type QueuedMessage, RateLimitError, type RefreshWorkspaceResult, SECRET_NAME_PATTERN, type SecretResponse, ServiceUnavailableError, type SessionListItem, type TerminalTicket, TimeoutError, type ToolPart, type ToolRef, type UpdateMcpServerRequest, type UpdateProviderCredentialRequest, type User, type Workspace, type WorkspaceCondition, type WorkspaceListItem, type WorkspaceListResult, type WorkspaceStatusResult };
896
+ export { type APIKey, type ActivateWorkspaceResponse, type ActiveSessionsResponse, AuthError, type AuthResponse, type ClientOptions, ConflictError, type ContextUsage, type Cost, type CreateMcpServerRequest, type CreateProviderCredentialRequest, type CreateSecretRequest, type CreateWorkspaceRequest, type EnsureSessionResponse, type FetchFn, type FileDiff, type FileUpload, type InboxLateAnswerAccepted, type InputOption, type InputRequest, LLMSafeSpaces, LLMSafeSpacesError, type McpAutoApplyRule, type McpServer, type Message, type ModelRef, NotFoundError, type PaginationMetadata, type Part, type PromptAccepted, type ProviderCredential, type QueuedMessage, RateLimitError, type RefreshWorkspaceResult, SECRET_NAME_PATTERN, type SecretResponse, ServiceUnavailableError, type Session, type SessionListItem, type TerminalTicket, type TimeRange, TimeoutError, type ToolPart, type ToolRef, type UpdateMcpServerRequest, type UpdateProviderCredentialRequest, type User, type Workspace, type WorkspaceCondition, type WorkspaceListItem, type WorkspaceListResult, type WorkspaceStatusResult };
package/dist/index.d.ts CHANGED
@@ -103,6 +103,44 @@ interface SessionListItem {
103
103
  messageCount: number;
104
104
  status: string;
105
105
  }
106
+ /**
107
+ * The platform-owned view of one agent session (pkg/session contract,
108
+ * design 0049) — the getSession response shape.
109
+ */
110
+ interface Session {
111
+ id: string;
112
+ workspaceId: string;
113
+ parentId?: string;
114
+ title?: string;
115
+ agentId?: string;
116
+ model?: ModelRef;
117
+ status: "unknown" | "idle" | "busy" | "error" | "compacting" | "archived";
118
+ cost?: Cost;
119
+ contextUsage?: ContextUsage;
120
+ time?: TimeRange;
121
+ summary?: string;
122
+ archived?: boolean;
123
+ }
124
+ /** The session's live context occupancy (non-monotonic: compaction resets it). */
125
+ interface ContextUsage {
126
+ used: number;
127
+ window?: number;
128
+ }
129
+ /** Bounds a session or message. completedAt is absent while busy. */
130
+ interface TimeRange {
131
+ startedAt: string;
132
+ completedAt?: string;
133
+ }
134
+ /**
135
+ * The delivery-outbox receipt for an async prompt: the 202 body of a
136
+ * fresh accept, and the 200 body of a retried clientMessageID (which
137
+ * echoes the ORIGINAL accepted entry with status "duplicate").
138
+ */
139
+ interface PromptAccepted {
140
+ messageID: string;
141
+ clientMessageID?: string;
142
+ status: "queued" | "duplicate";
143
+ }
106
144
  interface ActiveSessionsResponse {
107
145
  active: string[];
108
146
  maxActive: number;
@@ -136,7 +174,7 @@ interface Message {
136
174
  }
137
175
  /** One renderable part of a message — the closed 5-type union. */
138
176
  interface Part {
139
- type: "text" | "reasoning" | "tool" | "file-change" | "custom";
177
+ type: "text" | "reasoning" | "tool" | "file_change" | "custom";
140
178
  id?: string;
141
179
  text?: string;
142
180
  reasoning?: string;
@@ -194,6 +232,20 @@ interface ToolRef {
194
232
  messageId?: string;
195
233
  callId?: string;
196
234
  }
235
+ /**
236
+ * The 202 body for a reply that landed as a late answer through the
237
+ * delivery outbox (#1313): the ask was no longer live, so the answer
238
+ * rides a Q&A user message instead of the live ask.
239
+ */
240
+ interface InboxLateAnswerAccepted {
241
+ status: "queued";
242
+ /** Ask-scoped dedupe key (`inbox-{requestID}-answer`); duplicate clicks return the original. */
243
+ clientMessageID: string;
244
+ /** The outbox entry ID (202) or the original accepted entry (duplicate). */
245
+ messageID: string;
246
+ /** Present and true when the ask-scoped key was already accepted. */
247
+ duplicate?: boolean;
248
+ }
197
249
  interface ModelRef {
198
250
  id: string;
199
251
  provider?: string;
@@ -463,13 +515,17 @@ declare class SessionsAPI {
463
515
  nextCursor: string;
464
516
  }>;
465
517
  abort(workspaceId: string, sessionId: string): Promise<void>;
466
- get(workspaceId: string, sessionId: string): Promise<Record<string, unknown>>;
518
+ /** Gets one session in contract shape (pkg/session Session). */
519
+ get(workspaceId: string, sessionId: string): Promise<Session>;
467
520
  /**
468
- * Sends a prompt asynchronously (202; the reply arrives on the workspace
469
- * SSE stream). Optional `files` (Epic 68) are upload-namespace paths
470
- * the API composes the v1 attachment manifest into the dispatched text.
521
+ * Sends a prompt asynchronously into the delivery outbox (202) and
522
+ * returns the accepted-entry receipt; the agent's reply arrives on the
523
+ * workspace SSE stream. A retried clientMessageID answers 200 with the
524
+ * ORIGINAL accepted entry (status "duplicate"). Optional `files`
525
+ * (Epic 68) are upload-namespace paths — the API composes the v1
526
+ * attachment manifest into the dispatched text.
471
527
  */
472
- sendPromptAsync(workspaceId: string, sessionId: string, message: string, files?: string[]): Promise<void>;
528
+ sendPromptAsync(workspaceId: string, sessionId: string, message: string, files?: string[]): Promise<PromptAccepted>;
473
529
  delete(workspaceId: string, sessionId: string): Promise<void>;
474
530
  /** Enqueues a message for a busy session; optional `files` as in sendPromptAsync. */
475
531
  enqueue(workspaceId: string, sessionId: string, text: string, files?: string[]): Promise<{
@@ -587,11 +643,34 @@ declare class UsageAPI {
587
643
  declare class InputRequestsAPI {
588
644
  private client;
589
645
  constructor(client: LLMSafeSpaces);
590
- listQuestions(workspaceId: string): Promise<unknown[]>;
591
- replyQuestion(workspaceId: string, requestId: string, body: Record<string, unknown>): Promise<void>;
646
+ /** Pending questions as contract InputRequest values (kind=question). */
647
+ listQuestions(workspaceId: string): Promise<InputRequest[]>;
648
+ /**
649
+ * Answers a live question. When the ask is no longer live but its
650
+ * unanswered-question inbox record is pending (#1313), the server
651
+ * accepts the answer as a late answer through the delivery outbox
652
+ * (202) and the resolved value carries the outbox entry; a live
653
+ * answer (200) resolves to undefined.
654
+ */
655
+ replyQuestion(workspaceId: string, requestId: string, answers: string[][]): Promise<InboxLateAnswerAccepted | undefined>;
656
+ /** Rejects (dismisses) a pending question. */
592
657
  rejectQuestion(workspaceId: string, requestId: string): Promise<void>;
593
- listPermissions(workspaceId: string): Promise<unknown[]>;
594
- replyPermission(workspaceId: string, requestId: string, body: Record<string, unknown>): Promise<void>;
658
+ /** Pending permissions as contract InputRequest values (kind=permission). */
659
+ listPermissions(workspaceId: string): Promise<InputRequest[]>;
660
+ /**
661
+ * Answers a live permission with the reply vocabulary
662
+ * ("once" | "always" | "reject") and an optional message. A late
663
+ * decision (ask no longer live, inbox record pending) resolves to the
664
+ * 202 outbox entry; a live answer (200) resolves to undefined.
665
+ */
666
+ replyPermission(workspaceId: string, requestId: string, reply: "once" | "always" | "reject", message?: string): Promise<InboxLateAnswerAccepted | undefined>;
667
+ /**
668
+ * Dismisses an unanswered-question inbox record (#1313): the record
669
+ * becomes dismissed; a still-live ask is rejected first server-side.
670
+ */
671
+ dismissInboxRecord(workspaceId: string, sessionId: string, requestId: string): Promise<void>;
672
+ /** Triggers an input-snapshot flight (202; events arrive on the event streams). */
673
+ requestInputSnapshot(workspaceId: string): Promise<void>;
595
674
  }
596
675
  declare class ProbeAPI {
597
676
  private client;
@@ -814,4 +893,4 @@ declare class ServiceUnavailableError extends LLMSafeSpacesError {
814
893
  constructor(message?: string, reason?: string, retryAfter?: number);
815
894
  }
816
895
 
817
- export { type APIKey, type ActivateWorkspaceResponse, type ActiveSessionsResponse, AuthError, type AuthResponse, type ClientOptions, ConflictError, type Cost, type CreateMcpServerRequest, type CreateProviderCredentialRequest, type CreateSecretRequest, type CreateWorkspaceRequest, type EnsureSessionResponse, type FetchFn, type FileDiff, type FileUpload, type InputOption, type InputRequest, LLMSafeSpaces, LLMSafeSpacesError, type McpAutoApplyRule, type McpServer, type Message, type ModelRef, NotFoundError, type PaginationMetadata, type Part, type ProviderCredential, type QueuedMessage, RateLimitError, type RefreshWorkspaceResult, SECRET_NAME_PATTERN, type SecretResponse, ServiceUnavailableError, type SessionListItem, type TerminalTicket, TimeoutError, type ToolPart, type ToolRef, type UpdateMcpServerRequest, type UpdateProviderCredentialRequest, type User, type Workspace, type WorkspaceCondition, type WorkspaceListItem, type WorkspaceListResult, type WorkspaceStatusResult };
896
+ export { type APIKey, type ActivateWorkspaceResponse, type ActiveSessionsResponse, AuthError, type AuthResponse, type ClientOptions, ConflictError, type ContextUsage, type Cost, type CreateMcpServerRequest, type CreateProviderCredentialRequest, type CreateSecretRequest, type CreateWorkspaceRequest, type EnsureSessionResponse, type FetchFn, type FileDiff, type FileUpload, type InboxLateAnswerAccepted, type InputOption, type InputRequest, LLMSafeSpaces, LLMSafeSpacesError, type McpAutoApplyRule, type McpServer, type Message, type ModelRef, NotFoundError, type PaginationMetadata, type Part, type PromptAccepted, type ProviderCredential, type QueuedMessage, RateLimitError, type RefreshWorkspaceResult, SECRET_NAME_PATTERN, type SecretResponse, ServiceUnavailableError, type Session, type SessionListItem, type TerminalTicket, type TimeRange, TimeoutError, type ToolPart, type ToolRef, type UpdateMcpServerRequest, type UpdateProviderCredentialRequest, type User, type Workspace, type WorkspaceCondition, type WorkspaceListItem, type WorkspaceListResult, type WorkspaceStatusResult };
package/dist/index.js CHANGED
@@ -171,7 +171,8 @@ var LLMSafeSpaces = class {
171
171
  throw new RateLimitError(msg);
172
172
  case 503: {
173
173
  const reason = errBody.reason;
174
- const retryAfter = errBody.retryAfter;
174
+ const headerAfter = Number(res.headers.get("Retry-After"));
175
+ const retryAfter = errBody.retryAfter ?? (Number.isFinite(headerAfter) && headerAfter > 0 ? headerAfter : void 0);
175
176
  const apiMessage = errBody.message ?? msg;
176
177
  throw new ServiceUnavailableError(apiMessage, reason, retryAfter);
177
178
  }
@@ -384,13 +385,17 @@ var SessionsAPI = class {
384
385
  abort(workspaceId, sessionId) {
385
386
  return this.client.request("POST", `/workspaces/${workspaceId}/sessions/${sessionId}/abort`);
386
387
  }
388
+ /** Gets one session in contract shape (pkg/session Session). */
387
389
  get(workspaceId, sessionId) {
388
390
  return this.client.request("GET", `/workspaces/${workspaceId}/sessions/${sessionId}`);
389
391
  }
390
392
  /**
391
- * Sends a prompt asynchronously (202; the reply arrives on the workspace
392
- * SSE stream). Optional `files` (Epic 68) are upload-namespace paths
393
- * the API composes the v1 attachment manifest into the dispatched text.
393
+ * Sends a prompt asynchronously into the delivery outbox (202) and
394
+ * returns the accepted-entry receipt; the agent's reply arrives on the
395
+ * workspace SSE stream. A retried clientMessageID answers 200 with the
396
+ * ORIGINAL accepted entry (status "duplicate"). Optional `files`
397
+ * (Epic 68) are upload-namespace paths — the API composes the v1
398
+ * attachment manifest into the dispatched text.
394
399
  */
395
400
  sendPromptAsync(workspaceId, sessionId, message, files) {
396
401
  const body = { parts: [{ type: "text", text: message }] };
@@ -589,25 +594,57 @@ var UsageAPI = class {
589
594
  return this.client.request("GET", "/usage/quota");
590
595
  }
591
596
  };
597
+ function lateAnswerOnly(late) {
598
+ return late?.status === "queued" ? late : void 0;
599
+ }
592
600
  var InputRequestsAPI = class {
593
601
  constructor(client) {
594
602
  this.client = client;
595
603
  }
596
604
  client;
605
+ /** Pending questions as contract InputRequest values (kind=question). */
597
606
  listQuestions(workspaceId) {
598
607
  return this.client.request("GET", `/workspaces/${workspaceId}/question`);
599
608
  }
600
- replyQuestion(workspaceId, requestId, body) {
601
- return this.client.request("POST", `/workspaces/${workspaceId}/question/${requestId}/reply`, body);
609
+ /**
610
+ * Answers a live question. When the ask is no longer live but its
611
+ * unanswered-question inbox record is pending (#1313), the server
612
+ * accepts the answer as a late answer through the delivery outbox
613
+ * (202) and the resolved value carries the outbox entry; a live
614
+ * answer (200) resolves to undefined.
615
+ */
616
+ replyQuestion(workspaceId, requestId, answers) {
617
+ return this.client.request("POST", `/workspaces/${workspaceId}/question/${requestId}/reply`, { answers }).then(lateAnswerOnly);
602
618
  }
619
+ /** Rejects (dismisses) a pending question. */
603
620
  rejectQuestion(workspaceId, requestId) {
604
621
  return this.client.request("POST", `/workspaces/${workspaceId}/question/${requestId}/reject`);
605
622
  }
623
+ /** Pending permissions as contract InputRequest values (kind=permission). */
606
624
  listPermissions(workspaceId) {
607
625
  return this.client.request("GET", `/workspaces/${workspaceId}/permission`);
608
626
  }
609
- replyPermission(workspaceId, requestId, body) {
610
- return this.client.request("POST", `/workspaces/${workspaceId}/permission/${requestId}/reply`, body);
627
+ /**
628
+ * Answers a live permission with the reply vocabulary
629
+ * ("once" | "always" | "reject") and an optional message. A late
630
+ * decision (ask no longer live, inbox record pending) resolves to the
631
+ * 202 outbox entry; a live answer (200) resolves to undefined.
632
+ */
633
+ replyPermission(workspaceId, requestId, reply, message) {
634
+ const body = { reply };
635
+ if (message !== void 0 && message !== "") body.message = message;
636
+ return this.client.request("POST", `/workspaces/${workspaceId}/permission/${requestId}/reply`, body).then(lateAnswerOnly);
637
+ }
638
+ /**
639
+ * Dismisses an unanswered-question inbox record (#1313): the record
640
+ * becomes dismissed; a still-live ask is rejected first server-side.
641
+ */
642
+ dismissInboxRecord(workspaceId, sessionId, requestId) {
643
+ return this.client.request("DELETE", `/workspaces/${workspaceId}/sessions/${sessionId}/inbox/${requestId}`);
644
+ }
645
+ /** Triggers an input-snapshot flight (202; events arrive on the event streams). */
646
+ requestInputSnapshot(workspaceId) {
647
+ return this.client.request("POST", `/workspaces/${workspaceId}/input-snapshot`);
611
648
  }
612
649
  };
613
650
  var ProbeAPI = class {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@llmsafespaces/sdk",
3
- "version": "0.30.0",
3
+ "version": "0.31.0",
4
4
  "description": "TypeScript SDK for LLMSafeSpaces API",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",