@parall/sdk 1.28.1 → 1.29.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/src/client.ts CHANGED
@@ -20,7 +20,6 @@ import type {
20
20
  SendMessageRequest,
21
21
  SendDirectMessageRequest,
22
22
  DirectMessageResponse,
23
- PatchMessageRequest,
24
23
  PaginatedResponse,
25
24
  Approval,
26
25
  CreateApprovalRequest,
@@ -38,6 +37,9 @@ import type {
38
37
  ResizeMachineRequest,
39
38
  MachineKey,
40
39
  MachineRuntimeAuthState,
40
+ AgentWorkspaceState,
41
+ AgentWorkspaceReportStatus,
42
+ DaemonAgentConfig,
41
43
  AttachedAgent,
42
44
  AttachAgentRequest,
43
45
  AttachedAgentsResponse,
@@ -48,6 +50,7 @@ import type {
48
50
  TaskRelation,
49
51
  TaskRelationTargetType,
50
52
  TaskWatcher,
53
+ ThreadWatcher,
51
54
  CreateTaskRelationRequest,
52
55
  TaskComment,
53
56
  CreateTaskCommentRequest,
@@ -155,6 +158,7 @@ export class ParallClient {
155
158
  private static readonly AUTH_PATHS = new Set([
156
159
  '/auth/login', '/auth/register', '/auth/refresh', '/auth/logout',
157
160
  '/auth/verify-email', '/auth/resend-code', '/auth/check-email',
161
+ '/auth/forgot-password', '/auth/reset-password',
158
162
  ]);
159
163
 
160
164
  /** Proactive refresh when token expires within this window (seconds). */
@@ -438,6 +442,14 @@ export class ParallClient {
438
442
  return this.request('POST', ENDPOINTS.AUTH_RESEND_CODE, { email });
439
443
  }
440
444
 
445
+ async forgotPassword(email: string): Promise<{ message: string }> {
446
+ return this.request('POST', ENDPOINTS.AUTH_FORGOT_PASSWORD, { email });
447
+ }
448
+
449
+ async resetPassword(token: string, newPassword: string): Promise<AuthTokens> {
450
+ return this.request('POST', ENDPOINTS.AUTH_RESET_PASSWORD, { token, new_password: newPassword });
451
+ }
452
+
441
453
  // ---- WebSocket ----
442
454
 
443
455
  async getWsTicket(): Promise<WsTicketResponse> {
@@ -732,10 +744,6 @@ export class ParallClient {
732
744
  return this.request('DELETE', ENDPOINTS.MESSAGE(id));
733
745
  }
734
746
 
735
- async patchMessage(id: string, req: PatchMessageRequest): Promise<void> {
736
- return this.request('POST', ENDPOINTS.MESSAGE_PATCHES(id), req);
737
- }
738
-
739
747
  async getMessageReplies(
740
748
  id: string,
741
749
  params?: { limit?: number; before?: string; after?: string },
@@ -753,8 +761,8 @@ export class ParallClient {
753
761
  return this.request('POST', ENDPOINTS.UPLOAD_COMPLETE(orgId), { attachment_id: attachmentId });
754
762
  }
755
763
 
756
- async getFileUrl(id: string): Promise<FileUrlResponse> {
757
- return this.request('GET', ENDPOINTS.FILE(id));
764
+ async getFileUrl(id: string, opts?: { download?: boolean }): Promise<FileUrlResponse> {
765
+ return this.request('GET', ENDPOINTS.FILE(id), undefined, opts?.download ? { download: true } : undefined);
758
766
  }
759
767
 
760
768
  // ---- Approvals ----
@@ -864,9 +872,8 @@ export class ParallClient {
864
872
  * List agent sessions.
865
873
  * @param params.status - Comma-separated status filter (e.g., `'open'`).
866
874
  */
867
- async getAgentSessions(orgId: string, agentId: string, params?: { limit?: number; status?: string }): Promise<AgentSessionDB[]> {
868
- const res = await this.request<{ data: AgentSessionDB[] }>('GET', ENDPOINTS.AGENT_SESSIONS(orgId, agentId), undefined, params);
869
- return res.data;
875
+ async getAgentSessions(orgId: string, agentId: string, params?: { limit?: number; status?: string; cursor?: string }): Promise<PaginatedResponse<AgentSessionDB>> {
876
+ return this.request('GET', ENDPOINTS.AGENT_SESSIONS(orgId, agentId), undefined, params);
870
877
  }
871
878
 
872
879
  async getAgentSession(orgId: string, agentId: string, sessionId: string): Promise<AgentSessionDB> {
@@ -881,15 +888,18 @@ export class ParallClient {
881
888
  return this.request('POST', ENDPOINTS.AGENT_SESSION_STEPS(orgId, agentId, sessionId), req);
882
889
  }
883
890
 
884
- async getAgentSessionSteps(orgId: string, agentId: string, sessionId: string, params?: { limit?: number }): Promise<AgentStep[]> {
885
- const res = await this.request<{ data: AgentStep[] }>('GET', ENDPOINTS.AGENT_SESSION_STEPS(orgId, agentId, sessionId), undefined, params);
886
- return res.data;
891
+ async getAgentSessionSteps(orgId: string, agentId: string, sessionId: string, params?: { limit?: number; cursor?: string }): Promise<PaginatedResponse<AgentStep>> {
892
+ return this.request('GET', ENDPOINTS.AGENT_SESSION_STEPS(orgId, agentId, sessionId), undefined, params);
887
893
  }
888
894
 
889
895
  async getAgentSessionStep(orgId: string, agentId: string, sessionId: string, stepId: string): Promise<AgentStep> {
890
896
  return this.request('GET', ENDPOINTS.AGENT_SESSION_STEP(orgId, agentId, sessionId, stepId));
891
897
  }
892
898
 
899
+ async getAgentStepById(orgId: string, stepId: string): Promise<AgentStep> {
900
+ return this.request('GET', ENDPOINTS.AGENT_STEP_BY_ID(orgId, stepId));
901
+ }
902
+
893
903
  // ---- Agent runtime auth (hosted Claude OAuth) ----
894
904
 
895
905
  async getAgentRuntimeAuth(orgId: string, agentId: string): Promise<RuntimeAuthConnectedState> {
@@ -1017,7 +1027,7 @@ export class ParallClient {
1017
1027
  * Create a new daemon-mode Machine. Returns the Machine row + one-shot
1018
1028
  * mck_ token. The UI uses this when the user clicks "Create Workspace".
1019
1029
  */
1020
- async createMachine(orgId: string, opts: { label?: string; tier?: string; compute_mode?: 'hosted' | 'local' }): Promise<{
1030
+ async createMachine(orgId: string, opts: { label?: string; tier?: string; llm_source?: string; compute_mode?: 'hosted' | 'local' }): Promise<{
1021
1031
  machine: Machine;
1022
1032
  machine_key: string;
1023
1033
  key_id: string;
@@ -1044,11 +1054,49 @@ export class ParallClient {
1044
1054
  return this.request('DELETE', ENDPOINTS.MACHINE_DETACH_AGENT(orgId, machineId, agentId));
1045
1055
  }
1046
1056
 
1057
+ async listAgentWorkspaceStates(orgId: string, machineId: string): Promise<AgentWorkspaceState[]> {
1058
+ const res = await this.request<{ data: AgentWorkspaceState[] }>('GET', ENDPOINTS.MACHINE_WORKSPACE_STATES(orgId, machineId));
1059
+ return res.data;
1060
+ }
1061
+
1062
+ async patchAgentDaemonConfig(orgId: string, machineId: string, agentId: string, daemonConfig: DaemonAgentConfig): Promise<void> {
1063
+ return this.request('PATCH', ENDPOINTS.MACHINE_AGENT_DAEMON_CONFIG(orgId, machineId, agentId), { daemon_config: daemonConfig });
1064
+ }
1065
+
1066
+ async retryAgentWorkspaceSetup(orgId: string, machineId: string, agentId: string): Promise<void> {
1067
+ return this.request('POST', ENDPOINTS.MACHINE_AGENT_WORKSPACE_SETUP(orgId, machineId, agentId));
1068
+ }
1069
+
1070
+ async patchMachineLLMSource(orgId: string, machineId: string, llmSource: string): Promise<Machine> {
1071
+ return this.request('PATCH', ENDPOINTS.MACHINE_LLM_SOURCE(orgId, machineId), { llm_source: llmSource });
1072
+ }
1073
+
1047
1074
  /** Get machine-level runtime auth state. */
1048
1075
  async getMachineRuntimeAuth(orgId: string, machineId: string): Promise<MachineRuntimeAuthState> {
1049
1076
  return this.request('GET', ENDPOINTS.MACHINE_RUNTIME_AUTH(orgId, machineId));
1050
1077
  }
1051
1078
 
1079
+ async startMachineRuntimeAuthSession(
1080
+ orgId: string,
1081
+ machineId: string,
1082
+ req: StartRuntimeAuthSessionRequest = {},
1083
+ ): Promise<RuntimeAuthSession> {
1084
+ return this.request('POST', ENDPOINTS.MACHINE_RUNTIME_AUTH_SESSIONS(orgId, machineId), req);
1085
+ }
1086
+
1087
+ async completeMachineRuntimeAuthSession(
1088
+ orgId: string,
1089
+ machineId: string,
1090
+ sessionId: string,
1091
+ req: CompleteRuntimeAuthSessionRequest,
1092
+ ): Promise<RuntimeAuthSession> {
1093
+ return this.request('POST', ENDPOINTS.MACHINE_RUNTIME_AUTH_SESSION_COMPLETE(orgId, machineId, sessionId), req);
1094
+ }
1095
+
1096
+ async disconnectMachineRuntimeAuth(orgId: string, machineId: string): Promise<void> {
1097
+ return this.request('DELETE', ENDPOINTS.MACHINE_RUNTIME_AUTH(orgId, machineId));
1098
+ }
1099
+
1052
1100
  // ---- Machine self-control-plane (mck_-scoped) ----
1053
1101
  //
1054
1102
  // The four methods below are intended to be called from a daemon-mode
@@ -1082,6 +1130,18 @@ export class ParallClient {
1082
1130
  return this.request('POST', ENDPOINTS.MACHINES_ME_HEALTH);
1083
1131
  }
1084
1132
 
1133
+ async reportAgentWorkspaceState(agentId: string, state: {
1134
+ config_hash: string;
1135
+ status: AgentWorkspaceReportStatus;
1136
+ last_error?: string | null;
1137
+ output_tail?: string | null;
1138
+ }): Promise<void> {
1139
+ const res = await this.request<{ status?: string }>('PUT', ENDPOINTS.MACHINES_ME_AGENT_WORKSPACE_STATE(agentId), state);
1140
+ if (res?.status === 'ignored_stale') {
1141
+ throw new ApiError(409, 'Workspace state report ignored as stale', 'STALE_WORKSPACE_STATE');
1142
+ }
1143
+ }
1144
+
1085
1145
  /**
1086
1146
  * `POST /machines/me/agents/{agentId}/launch-credential` — mint a
1087
1147
  * short-lived `agk_*` for one of this Machine's attached agents. The
@@ -1287,6 +1347,24 @@ export class ParallClient {
1287
1347
  return res.data;
1288
1348
  }
1289
1349
 
1350
+ async watchThread(threadRootId: string): Promise<void> {
1351
+ return this.request('POST', ENDPOINTS.MESSAGE_WATCH(threadRootId));
1352
+ }
1353
+
1354
+ async unwatchThread(threadRootId: string): Promise<void> {
1355
+ return this.request('DELETE', ENDPOINTS.MESSAGE_WATCH(threadRootId));
1356
+ }
1357
+
1358
+ async getThreadWatchers(threadRootId: string): Promise<ThreadWatcher[]> {
1359
+ const res = await this.request<{ data: ThreadWatcher[] }>('GET', ENDPOINTS.MESSAGE_WATCHERS(threadRootId));
1360
+ return res.data;
1361
+ }
1362
+
1363
+ async isWatchingThread(threadRootId: string): Promise<boolean> {
1364
+ const res = await this.request<{ watching: boolean }>('GET', ENDPOINTS.MESSAGE_WATCHING(threadRootId));
1365
+ return res.watching;
1366
+ }
1367
+
1290
1368
  async getSubtasks(orgId: string, taskId: string): Promise<Task[]> {
1291
1369
  const res = await this.request<PaginatedResponse<Task>>('GET', ENDPOINTS.TASK_SUBTASKS(orgId, taskId));
1292
1370
  return res.data;
@@ -1745,7 +1823,7 @@ export class ParallClient {
1745
1823
  return this.request('GET', ENDPOINTS.BILLING(orgId));
1746
1824
  }
1747
1825
 
1748
- async listBillingTransactions(orgId: string, opts?: { cursor?: string; limit?: number; types?: string[]; user_id?: string; unresolved_actor?: boolean; machine_id?: string; unresolved_machine?: boolean }): Promise<{ items: CreditTransaction[]; next_cursor: string | null }> {
1826
+ async listBillingTransactions(orgId: string, opts?: { cursor?: string; limit?: number; types?: string[]; user_id?: string; unresolved_actor?: boolean; machine_id?: string; unresolved_machine?: boolean; from?: string; to?: string }): Promise<{ items: CreditTransaction[]; next_cursor: string | null }> {
1749
1827
  const params = new URLSearchParams();
1750
1828
  if (opts?.cursor) params.set('cursor', opts.cursor);
1751
1829
  if (opts?.limit) params.set('limit', String(opts.limit));
@@ -1754,16 +1832,24 @@ export class ParallClient {
1754
1832
  if (opts?.unresolved_actor) params.set('unresolved_actor', 'true');
1755
1833
  if (opts?.machine_id) params.set('machine_id', opts.machine_id);
1756
1834
  if (opts?.unresolved_machine) params.set('unresolved_machine', 'true');
1835
+ if (opts?.from) params.set('from', opts.from);
1836
+ if (opts?.to) params.set('to', opts.to);
1757
1837
  const qs = params.toString();
1758
1838
  return this.request('GET', `${ENDPOINTS.BILLING_TRANSACTIONS(orgId)}${qs ? `?${qs}` : ''}`);
1759
1839
  }
1760
1840
 
1761
- async listBillingTransactionAgentGroups(orgId: string): Promise<{ groups: CreditTransactionAgentGroup[] }> {
1762
- return this.request('GET', `${ENDPOINTS.BILLING_TRANSACTIONS(orgId)}?group_by=agent`);
1841
+ async listBillingTransactionAgentGroups(orgId: string, opts?: { from?: string; to?: string }): Promise<{ groups: CreditTransactionAgentGroup[] }> {
1842
+ const params = new URLSearchParams({ group_by: 'agent' });
1843
+ if (opts?.from) params.set('from', opts.from);
1844
+ if (opts?.to) params.set('to', opts.to);
1845
+ return this.request('GET', `${ENDPOINTS.BILLING_TRANSACTIONS(orgId)}?${params}`);
1763
1846
  }
1764
1847
 
1765
- async listBillingTransactionMachineGroups(orgId: string): Promise<{ groups: CreditTransactionMachineGroup[] }> {
1766
- return this.request('GET', `${ENDPOINTS.BILLING_TRANSACTIONS(orgId)}?group_by=machine`);
1848
+ async listBillingTransactionMachineGroups(orgId: string, opts?: { from?: string; to?: string }): Promise<{ groups: CreditTransactionMachineGroup[] }> {
1849
+ const params = new URLSearchParams({ group_by: 'machine' });
1850
+ if (opts?.from) params.set('from', opts.from);
1851
+ if (opts?.to) params.set('to', opts.to);
1852
+ return this.request('GET', `${ENDPOINTS.BILLING_TRANSACTIONS(orgId)}?${params}`);
1767
1853
  }
1768
1854
 
1769
1855
  async createCheckout(orgId: string, req: CreateCheckoutRequest): Promise<CreateCheckoutResponse> {
package/src/constants.ts CHANGED
@@ -93,6 +93,8 @@ export const ENDPOINTS = {
93
93
  AUTH_CHECK_EMAIL: `${API_BASE}/auth/check-email`,
94
94
  AUTH_VERIFY_EMAIL: `${API_BASE}/auth/verify-email`,
95
95
  AUTH_RESEND_CODE: `${API_BASE}/auth/resend-code`,
96
+ AUTH_FORGOT_PASSWORD: `${API_BASE}/auth/forgot-password`,
97
+ AUTH_RESET_PASSWORD: `${API_BASE}/auth/reset-password`,
96
98
 
97
99
  // Users
98
100
  USERS_ME: `${API_BASE}/users/me`,
@@ -142,8 +144,10 @@ export const ENDPOINTS = {
142
144
 
143
145
  // Messages (global, by message ID)
144
146
  MESSAGE: (id: string) => `${API_BASE}/messages/${id}`,
145
- MESSAGE_PATCHES: (id: string) => `${API_BASE}/messages/${id}/patches`,
146
147
  MESSAGE_REPLIES: (id: string) => `${API_BASE}/messages/${id}/replies`,
148
+ MESSAGE_WATCH: (id: string) => `${API_BASE}/messages/${id}/watch`,
149
+ MESSAGE_WATCHERS: (id: string) => `${API_BASE}/messages/${id}/watchers`,
150
+ MESSAGE_WATCHING: (id: string) => `${API_BASE}/messages/${id}/watching`,
147
151
 
148
152
  // Upload (org-scoped)
149
153
  UPLOAD_PRESIGN: (orgId: string) => `${API_BASE}/orgs/${orgId}/upload/presign`,
@@ -183,6 +187,8 @@ export const ENDPOINTS = {
183
187
  `${API_BASE}/orgs/${orgId}/agents/${agentId}/sessions/${sessionId}/steps`,
184
188
  AGENT_SESSION_STEP: (orgId: string, agentId: string, sessionId: string, stepId: string) =>
185
189
  `${API_BASE}/orgs/${orgId}/agents/${agentId}/sessions/${sessionId}/steps/${stepId}`,
190
+ AGENT_STEP_BY_ID: (orgId: string, stepId: string) =>
191
+ `${API_BASE}/orgs/${orgId}/agent-steps/${stepId}`,
186
192
  AGENT_TASKS: (orgId: string, agentId: string) =>
187
193
  `${API_BASE}/orgs/${orgId}/agents/${agentId}/tasks`,
188
194
  AGENT_RUNTIME_AUTH: (orgId: string, agentId: string) =>
@@ -230,12 +236,24 @@ export const ENDPOINTS = {
230
236
  `${API_BASE}/orgs/${orgId}/machines/${machineId}/agents/${agentId}`,
231
237
  MACHINE_DETACH_AGENT: (orgId: string, machineId: string, agentId: string) =>
232
238
  `${API_BASE}/orgs/${orgId}/machines/${machineId}/agents/${agentId}`,
239
+ MACHINE_WORKSPACE_STATES: (orgId: string, machineId: string) =>
240
+ `${API_BASE}/orgs/${orgId}/machines/${machineId}/workspace-states`,
241
+ MACHINE_AGENT_DAEMON_CONFIG: (orgId: string, machineId: string, agentId: string) =>
242
+ `${API_BASE}/orgs/${orgId}/machines/${machineId}/agents/${agentId}/daemon-config`,
243
+ MACHINE_AGENT_WORKSPACE_SETUP: (orgId: string, machineId: string, agentId: string) =>
244
+ `${API_BASE}/orgs/${orgId}/machines/${machineId}/agents/${agentId}/workspace/setup`,
245
+ MACHINE_LLM_SOURCE: (orgId: string, machineId: string) =>
246
+ `${API_BASE}/orgs/${orgId}/machines/${machineId}/llm-source`,
233
247
  MACHINE_RUNTIME_AUTH: (orgId: string, machineId: string) =>
234
248
  `${API_BASE}/orgs/${orgId}/machines/${machineId}/runtime-auth`,
235
249
  MACHINE_KEYS: (orgId: string, machineId: string) =>
236
250
  `${API_BASE}/orgs/${orgId}/machines/${machineId}/keys`,
237
251
  MACHINE_KEY: (orgId: string, machineId: string, keyId: string) =>
238
252
  `${API_BASE}/orgs/${orgId}/machines/${machineId}/keys/${keyId}`,
253
+ MACHINE_RUNTIME_AUTH_SESSIONS: (orgId: string, machineId: string) =>
254
+ `${API_BASE}/orgs/${orgId}/machines/${machineId}/runtime-auth-sessions`,
255
+ MACHINE_RUNTIME_AUTH_SESSION_COMPLETE: (orgId: string, machineId: string, sessionId: string) =>
256
+ `${API_BASE}/orgs/${orgId}/machines/${machineId}/runtime-auth-sessions/${sessionId}/complete`,
239
257
 
240
258
  // Machine self-control-plane (mck_-scoped). The bearer token implicitly
241
259
  // identifies the Machine, so there is no `:mid` URL parameter — these are
@@ -245,6 +263,8 @@ export const ENDPOINTS = {
245
263
  MACHINES_ME_HEALTH: `${API_BASE}/machines/me/health`,
246
264
  MACHINES_ME_AGENT_LAUNCH_CREDENTIAL: (agentId: string) =>
247
265
  `${API_BASE}/machines/me/agents/${agentId}/launch-credential`,
266
+ MACHINES_ME_AGENT_WORKSPACE_STATE: (agentId: string) =>
267
+ `${API_BASE}/machines/me/agents/${agentId}/workspace-state`,
248
268
  MACHINES_ME_WS_TICKET: `${API_BASE}/machines/me/ws/ticket`,
249
269
 
250
270
  // Tasks (org-scoped)
@@ -480,6 +500,7 @@ export const WS_EVENTS = {
480
500
  MACHINE_AGENT_ATTACHED: 'machine.agent.attached',
481
501
  MACHINE_AGENT_DETACHED: 'machine.agent.detached',
482
502
  MACHINE_STOP: 'machine.stop',
503
+ MACHINE_WORKSPACE_SETUP_REQUESTED: 'machine.workspace.setup.requested',
483
504
  } as const;
484
505
 
485
506
  // Canonical target URI builders for unified comments.
package/src/types.ts CHANGED
@@ -249,6 +249,7 @@ export interface Message {
249
249
  created_at: string;
250
250
  idempotency_key: string | null;
251
251
  agent_step_id?: string | null;
252
+ agent_session_id?: string | null;
252
253
  hints?: MessageHints | null;
253
254
  attachments?: Attachment[];
254
255
  }
@@ -510,11 +511,6 @@ export interface DirectMessageResponse {
510
511
  message: Message;
511
512
  }
512
513
 
513
- export interface PatchMessageRequest {
514
- version: number;
515
- ops: JsonPatchOp[];
516
- }
517
-
518
514
  export interface JsonPatchOp {
519
515
  op: 'replace' | 'add';
520
516
  path: string;
@@ -544,6 +540,7 @@ export interface CreateAgentRequest {
544
540
  memory_mb?: number;
545
541
  storage_gb?: number;
546
542
  provider_config?: AgentProviderConfig;
543
+ daemon_config?: DaemonAgentConfig;
547
544
  /**
548
545
  * When true, marks this create as a candidate for the org's onboarding
549
546
  * agent. The server will atomically claim `org.onboarding_agent_id`;
@@ -649,6 +646,7 @@ export interface Machine {
649
646
  compute_provider: string;
650
647
  runtime_type: string;
651
648
  daemon_mode: boolean;
649
+ llm_source?: string;
652
650
  compute_mode: 'hosted' | 'local';
653
651
  region: string | null;
654
652
  created_by: string;
@@ -656,9 +654,53 @@ export interface Machine {
656
654
  updated_at: string;
657
655
  }
658
656
 
657
+ export type DaemonWorkspaceMode = 'default' | 'local_path' | 'git';
658
+ export type DaemonWorkspaceSetupRunOn = 'first_attach' | 'config_change';
659
+
660
+ export interface DaemonWorkspaceGitConfig {
661
+ remote?: string;
662
+ ref?: string;
663
+ target_path?: string;
664
+ }
665
+
666
+ export interface DaemonWorkspaceSetup {
667
+ command?: string;
668
+ timeout_sec?: number;
669
+ run_on?: DaemonWorkspaceSetupRunOn;
670
+ }
671
+
672
+ export interface DaemonWorkspaceConfig {
673
+ mode?: DaemonWorkspaceMode;
674
+ path?: string;
675
+ git?: DaemonWorkspaceGitConfig;
676
+ setup?: DaemonWorkspaceSetup;
677
+ }
678
+
679
+ export interface DaemonAgentConfig {
680
+ /** Legacy shorthand for workspace.mode="local_path". */
681
+ workspace_path?: string;
682
+ workspace?: DaemonWorkspaceConfig;
683
+ }
684
+
659
685
  /** Body for `POST /orgs/{orgId}/machines/{machineId}/agents/{agentId}`. */
660
686
  export interface AttachAgentRequest {
661
687
  workspace_path?: string;
688
+ daemon_config?: DaemonAgentConfig;
689
+ }
690
+
691
+ export type AgentWorkspaceStatus = 'pending' | 'preparing' | 'ready' | 'failed';
692
+ export type AgentWorkspaceReportStatus = Exclude<AgentWorkspaceStatus, 'pending'>;
693
+
694
+ export interface AgentWorkspaceState {
695
+ machine_id: string;
696
+ agent_id: string;
697
+ config_hash: string;
698
+ status: AgentWorkspaceStatus;
699
+ last_error?: string | null;
700
+ output_tail?: string | null;
701
+ prepared_at?: string | null;
702
+ created_at: string;
703
+ updated_at: string;
662
704
  }
663
705
 
664
706
  /** Response from `GET /orgs/{orgId}/machines/{machineId}/runtime-auth`. */
@@ -722,7 +764,9 @@ export interface AgentWithRuntime extends User {
722
764
  export interface AttachedAgent {
723
765
  user: User | null;
724
766
  profile: AgentProfile;
725
- daemon_config?: { workspace_path?: string };
767
+ daemon_config?: DaemonAgentConfig;
768
+ provider_config?: AgentProviderConfig;
769
+ workspace_state?: AgentWorkspaceState;
726
770
  }
727
771
 
728
772
  // ---- Machine WS event data (daemon control plane) ----
@@ -744,6 +788,16 @@ export interface MachineAgentDetachedData {
744
788
  agent_id: string;
745
789
  }
746
790
 
791
+ export interface MachineConfigUpdatedData {
792
+ machine_id: string;
793
+ llm_source?: string;
794
+ }
795
+
796
+ export interface MachineWorkspaceSetupRequestedData {
797
+ machine_id: string;
798
+ agent_id: string;
799
+ }
800
+
747
801
  export interface MachineStopData {
748
802
  machine_id: string;
749
803
  reason?: string;
@@ -826,6 +880,14 @@ export interface TaskWatcher {
826
880
  user?: User;
827
881
  }
828
882
 
883
+ export interface ThreadWatcher {
884
+ thread_root_id: string;
885
+ chat_id: string;
886
+ user_id: string;
887
+ created_at: string;
888
+ user?: User;
889
+ }
890
+
829
891
  /** Content shape for system messages that project issue operations into chat. */
830
892
  export interface IssueProjectionContent {
831
893
  event: 'issue_created' | 'issue_status_changed' | 'issue_assigned';
@@ -1432,6 +1494,7 @@ export interface MessageNewData {
1432
1494
  deleted_at?: string | null;
1433
1495
  idempotency_key?: string | null;
1434
1496
  agent_step_id?: string | null;
1497
+ agent_session_id?: string | null;
1435
1498
  hints?: MessageHints | null;
1436
1499
  attachments?: Attachment[];
1437
1500
  }
@@ -1700,6 +1763,9 @@ export interface InboxItem {
1700
1763
  task_id: string | null;
1701
1764
  title: string;
1702
1765
  body: string;
1766
+ grouping_priority: number;
1767
+ /** Number of events in this group. Populated by the grouped list query. */
1768
+ group_count: number;
1703
1769
  read_at: string | null;
1704
1770
  archived_at: string | null;
1705
1771
  snoozed_until: string | null;
@@ -1833,6 +1899,8 @@ export type WsEventMap = {
1833
1899
  'machine.hello': MachineHelloData;
1834
1900
  'machine.agent.attached': MachineAgentAttachedData;
1835
1901
  'machine.agent.detached': MachineAgentDetachedData;
1902
+ 'machine.config.updated': MachineConfigUpdatedData;
1903
+ 'machine.workspace.setup.requested': MachineWorkspaceSetupRequestedData;
1836
1904
  'machine.stop': MachineStopData;
1837
1905
  };
1838
1906
 
package/src/ws.ts CHANGED
@@ -24,6 +24,19 @@ export interface ParallWsOptions {
24
24
  maxReconnectInterval?: number;
25
25
  }
26
26
 
27
+ function isRetryableNetworkError(err: unknown): boolean {
28
+ return (
29
+ err instanceof Error
30
+ && err.name === 'ApiError'
31
+ && 'status' in err
32
+ && (err as { status?: unknown }).status === 0
33
+ );
34
+ }
35
+
36
+ function isBrowserRuntime(): boolean {
37
+ return typeof window !== 'undefined';
38
+ }
39
+
27
40
  export class ParallWs {
28
41
  private ws: WebSocket | null = null;
29
42
  private options: ParallWsOptions & { reconnect: boolean; reconnectInterval: number; maxReconnectInterval: number };
@@ -63,7 +76,11 @@ export class ParallWs {
63
76
  try {
64
77
  ticket = await this.options.getTicket();
65
78
  } catch (err) {
66
- console.error('Failed to get WS ticket:', err);
79
+ if (isBrowserRuntime() && isRetryableNetworkError(err)) {
80
+ console.warn('Failed to get WS ticket:', err);
81
+ } else {
82
+ console.error('Failed to get WS ticket:', err);
83
+ }
67
84
  if (this.options.reconnect) {
68
85
  this.scheduleReconnect();
69
86
  } else {