@parall/sdk 1.23.0 → 1.24.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/src/client.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { ENDPOINTS } from './constants.js';
2
2
  import type {
3
3
  AuthTokens,
4
+ AvatarUploadResponse,
4
5
  RegisterRequest,
5
6
  RegisterResponse,
6
7
  LoginRequest,
@@ -22,6 +23,7 @@ import type {
22
23
  PatchMessageRequest,
23
24
  PaginatedResponse,
24
25
  Approval,
26
+ CreateApprovalRequest,
25
27
  PresignResponse,
26
28
  PresignUploadRequest,
27
29
  FileUrlResponse,
@@ -110,6 +112,15 @@ import type {
110
112
  UpdateAgentRequest,
111
113
  UpdateChatMemberRequest,
112
114
  UnreadEntry,
115
+ BillingSummary,
116
+ CreditTransaction,
117
+ CreateCheckoutRequest,
118
+ CreateCheckoutResponse,
119
+ CreateSetupIntentResponse,
120
+ AutoReloadSettings,
121
+ UpdateAutoReloadRequest,
122
+ ComputePricing,
123
+ ComputePricingResponse,
113
124
  } from './types.js';
114
125
 
115
126
  export interface ParallClientOptions {
@@ -416,6 +427,30 @@ export class ParallClient {
416
427
  return this.request('PATCH', ENDPOINTS.USERS_ME, data);
417
428
  }
418
429
 
430
+ async deleteAccount(): Promise<void> {
431
+ return this.request('DELETE', ENDPOINTS.USERS_ME);
432
+ }
433
+
434
+ async uploadAvatar(file: File | Blob): Promise<AvatarUploadResponse> {
435
+ const fd = new FormData();
436
+ fd.append('file', file);
437
+ return this.multipartRequest('POST', ENDPOINTS.USER_AVATAR, fd);
438
+ }
439
+
440
+ async deleteAvatar(): Promise<void> {
441
+ return this.request('DELETE', ENDPOINTS.USER_AVATAR);
442
+ }
443
+
444
+ async uploadAgentAvatar(orgId: string, agentId: string, file: File | Blob): Promise<AvatarUploadResponse> {
445
+ const fd = new FormData();
446
+ fd.append('file', file);
447
+ return this.multipartRequest('POST', ENDPOINTS.AGENT_AVATAR(orgId, agentId), fd);
448
+ }
449
+
450
+ async deleteAgentAvatar(orgId: string, agentId: string): Promise<void> {
451
+ return this.request('DELETE', ENDPOINTS.AGENT_AVATAR(orgId, agentId));
452
+ }
453
+
419
454
  async getUser(id: string): Promise<User> {
420
455
  return this.request('GET', ENDPOINTS.USER(id));
421
456
  }
@@ -680,10 +715,22 @@ export class ParallClient {
680
715
 
681
716
  // ---- Approvals ----
682
717
 
718
+ async getApproval(id: string): Promise<Approval> {
719
+ return this.request('GET', ENDPOINTS.APPROVAL(id));
720
+ }
721
+
722
+ async requestApproval(orgId: string, req: CreateApprovalRequest): Promise<Approval> {
723
+ return this.request('POST', ENDPOINTS.APPROVAL_REQUESTS(orgId), req);
724
+ }
725
+
683
726
  async decideApproval(id: string, decision: 'approve' | 'reject'): Promise<Approval> {
684
727
  return this.request('POST', ENDPOINTS.APPROVAL_DECIDE(id), { decision });
685
728
  }
686
729
 
730
+ async cancelApproval(id: string): Promise<void> {
731
+ return this.request('POST', ENDPOINTS.APPROVAL_CANCEL(id));
732
+ }
733
+
687
734
  async getPendingApprovals(): Promise<Approval[]> {
688
735
  const res = await this.request<{ data: Approval[] }>('GET', ENDPOINTS.APPROVALS_PENDING);
689
736
  return res.data;
@@ -1523,6 +1570,61 @@ export class ParallClient {
1523
1570
  async getFeatureFlags(orgId: string): Promise<FeatureFlagsResponse> {
1524
1571
  return this.request('GET', ENDPOINTS.FEATURE_FLAGS(orgId));
1525
1572
  }
1573
+
1574
+ // ---- Billing & Credits (org-scoped) ----
1575
+
1576
+ async getBilling(orgId: string): Promise<BillingSummary> {
1577
+ return this.request('GET', ENDPOINTS.BILLING(orgId));
1578
+ }
1579
+
1580
+ async listBillingTransactions(orgId: string, opts?: { cursor?: string; limit?: number; types?: string[] }): Promise<{ items: CreditTransaction[]; next_cursor: string | null }> {
1581
+ const params = new URLSearchParams();
1582
+ if (opts?.cursor) params.set('cursor', opts.cursor);
1583
+ if (opts?.limit) params.set('limit', String(opts.limit));
1584
+ if (opts?.types?.length) params.set('types', opts.types.join(','));
1585
+ const qs = params.toString();
1586
+ return this.request('GET', `${ENDPOINTS.BILLING_TRANSACTIONS(orgId)}${qs ? `?${qs}` : ''}`);
1587
+ }
1588
+
1589
+ async createCheckout(orgId: string, req: CreateCheckoutRequest): Promise<CreateCheckoutResponse> {
1590
+ return this.request('POST', ENDPOINTS.BILLING_CHECKOUT(orgId), req);
1591
+ }
1592
+
1593
+ /**
1594
+ * Creates a Stripe-hosted card-collection session (Checkout in mode=setup)
1595
+ * and returns the redirect URL. The frontend navigates to `setup_url` and
1596
+ * Stripe handles the card form; the resulting payment_method is recorded
1597
+ * server-side via the `setup_intent.succeeded` webhook. Mirrors
1598
+ * `POST /billing/setup-intent`.
1599
+ */
1600
+ async createSetupIntent(orgId: string): Promise<CreateSetupIntentResponse> {
1601
+ return this.request('POST', ENDPOINTS.BILLING_SETUP_INTENT(orgId));
1602
+ }
1603
+
1604
+ async getAutoReloadSettings(orgId: string): Promise<AutoReloadSettings> {
1605
+ return this.request('GET', ENDPOINTS.BILLING_AUTO_RELOAD(orgId));
1606
+ }
1607
+
1608
+ async updateAutoReloadSettings(orgId: string, req: UpdateAutoReloadRequest): Promise<AutoReloadSettings> {
1609
+ return this.request('PUT', ENDPOINTS.BILLING_AUTO_RELOAD(orgId), req);
1610
+ }
1611
+
1612
+ // NOTE: `resizeMachine` was intentionally removed before merge — the
1613
+ // matching `PATCH /api/v1/orgs/{orgId}/machines/{machineId}/spec` route
1614
+ // is not yet wired on the server, so exposing the method shipped a
1615
+ // method that always 404'd. Reintroduce together with the server route
1616
+ // when machine in-place resize lands.
1617
+ //
1618
+ // Similarly, the admin grant endpoints (POST/GET /internal/admin/orgs/
1619
+ // {id}/grants) intentionally do NOT live on this public client — they
1620
+ // are mounted on the unauthenticated `/internal/*` surface and reachable
1621
+ // only via internal network paths. The admin dashboard maintains its
1622
+ // own thin client (`ts/admin/lib/api.ts`) that hits these directly.
1623
+
1624
+ async getComputePricing(): Promise<ComputePricingResponse> {
1625
+ const resp = await this.request<{ data: ComputePricingResponse }>('GET', ENDPOINTS.COMPUTE_PRICING());
1626
+ return resp.data;
1627
+ }
1526
1628
  }
1527
1629
 
1528
1630
  function normalizeWikiChangeset(changeset: WikiChangeset): WikiChangeset {
package/src/constants.ts CHANGED
@@ -5,19 +5,24 @@ export const API_BASE = '/api/v1';
5
5
  export const WIKI_BASE = '/wiki/v1';
6
6
 
7
7
  // LLM model catalog — mirrors server/pkg/llmproxy/models.go DefaultModels.
8
- // SSOT is the Go side; keep this list in sync when models change.
8
+ // SSOT is the Go side; keep this list in sync when models change. `provider`
9
+ // is used by clients to filter runtime-specific pickers.
9
10
  export const PLATFORM_MODELS = [
10
- { id: 'anthropic/claude-opus-4.6', name: 'Claude Opus 4.6' },
11
- { id: 'anthropic/claude-sonnet-4.6', name: 'Claude Sonnet 4.6' },
12
- { id: 'anthropic/claude-sonnet-4.5', name: 'Claude Sonnet 4.5' },
13
- { id: 'openai/gpt-5.4', name: 'GPT-5.4' },
14
- { id: 'openai/o4-mini', name: 'o4 Mini' },
15
- { id: 'openai/gpt-4.1', name: 'GPT-4.1' },
16
- { id: 'google/gemini-2.5-pro', name: 'Gemini 2.5 Pro' },
17
- { id: 'google/gemini-2.5-flash', name: 'Gemini 2.5 Flash' },
18
- { id: 'moonshotai/kimi-k2.5', name: 'Kimi K2.5' },
19
- { id: 'z-ai/glm-5', name: 'GLM 5' },
20
- { id: 'qwen/qwen3.5-plus-02-15', name: 'Qwen3.5 Plus' },
11
+ { id: 'anthropic/claude-opus-4.7', name: 'Claude Opus 4.7', provider: 'anthropic' },
12
+ { id: 'anthropic/claude-opus-4.6', name: 'Claude Opus 4.6', provider: 'anthropic' },
13
+ { id: 'anthropic/claude-sonnet-4.6', name: 'Claude Sonnet 4.6', provider: 'anthropic' },
14
+ { id: 'anthropic/claude-sonnet-4.5', name: 'Claude Sonnet 4.5', provider: 'anthropic' },
15
+ { id: 'openai/gpt-5-codex', name: 'GPT-5 Codex', provider: 'openai' },
16
+ { id: 'openai/gpt-5.4', name: 'GPT-5.4', provider: 'openai' },
17
+ { id: 'openai/o4-mini', name: 'o4 Mini', provider: 'openai' },
18
+ { id: 'openai/gpt-4.1', name: 'GPT-4.1', provider: 'openai' },
19
+ { id: 'google/gemini-2.5-pro', name: 'Gemini 2.5 Pro', provider: 'google' },
20
+ { id: 'google/gemini-2.5-flash', name: 'Gemini 2.5 Flash', provider: 'google' },
21
+ { id: 'moonshotai/kimi-k2.5', name: 'Kimi K2.5', provider: 'moonshotai' },
22
+ { id: 'z-ai/glm-5', name: 'GLM 5', provider: 'z-ai' },
23
+ { id: 'deepseek/deepseek-v4-pro', name: 'DeepSeek V4 Pro', provider: 'deepseek' },
24
+ { id: 'deepseek/deepseek-v4-flash', name: 'DeepSeek V4 Flash', provider: 'deepseek' },
25
+ { id: 'qwen/qwen3.5-plus-02-15', name: 'Qwen3.5 Plus', provider: 'qwen' },
21
26
  ] as const;
22
27
 
23
28
  // REST endpoints
@@ -34,6 +39,7 @@ export const ENDPOINTS = {
34
39
 
35
40
  // Users
36
41
  USERS_ME: `${API_BASE}/users/me`,
42
+ USER_AVATAR: `${API_BASE}/users/me/avatar`,
37
43
  USER: (id: string) => `${API_BASE}/users/${id}`,
38
44
 
39
45
  // WebSocket ticket
@@ -81,8 +87,13 @@ export const ENDPOINTS = {
81
87
  UPLOAD_COMPLETE: (orgId: string) => `${API_BASE}/orgs/${orgId}/upload/complete`,
82
88
  FILE: (id: string) => `${API_BASE}/files/${id}`,
83
89
 
90
+ // Approval requests (org-scoped)
91
+ APPROVAL_REQUESTS: (orgId: string) => `${API_BASE}/orgs/${orgId}/approval-requests`,
92
+
84
93
  // Approvals (global)
94
+ APPROVAL: (id: string) => `${API_BASE}/approvals/${id}`,
85
95
  APPROVAL_DECIDE: (id: string) => `${API_BASE}/approvals/${id}/decide`,
96
+ APPROVAL_CANCEL: (id: string) => `${API_BASE}/approvals/${id}/cancel`,
86
97
  APPROVALS_PENDING: `${API_BASE}/approvals/pending`,
87
98
 
88
99
  // Agents (org-scoped)
@@ -92,6 +103,8 @@ export const ENDPOINTS = {
92
103
  `${API_BASE}/orgs/${orgId}/agents/${agentId}/api-keys`,
93
104
  AGENT_API_KEY: (orgId: string, agentId: string, key: string) =>
94
105
  `${API_BASE}/orgs/${orgId}/agents/${agentId}/api-keys/${key}`,
106
+ AGENT_AVATAR: (orgId: string, agentId: string) =>
107
+ `${API_BASE}/orgs/${orgId}/agents/${agentId}/avatar`,
95
108
  AGENT_ACTIVITY: (orgId: string, agentId: string) =>
96
109
  `${API_BASE}/orgs/${orgId}/agents/${agentId}/activity`,
97
110
  AGENT_MONITOR: (orgId: string, agentId: string) =>
@@ -296,6 +309,21 @@ export const ENDPOINTS = {
296
309
  // Feature flags (org-scoped, server-evaluated)
297
310
  FEATURE_FLAGS: (orgId: string) => `${API_BASE}/orgs/${orgId}/feature-flags`,
298
311
 
312
+ // Billing & Credits (org-scoped)
313
+ BILLING: (orgId: string) => `${API_BASE}/orgs/${orgId}/billing`,
314
+ BILLING_TRANSACTIONS: (orgId: string) => `${API_BASE}/orgs/${orgId}/billing/transactions`,
315
+ BILLING_CHECKOUT: (orgId: string) => `${API_BASE}/orgs/${orgId}/billing/checkout`,
316
+ BILLING_AUTO_RELOAD: (orgId: string) => `${API_BASE}/orgs/${orgId}/billing/auto-reload`,
317
+ BILLING_SETUP_INTENT: (orgId: string) => `${API_BASE}/orgs/${orgId}/billing/setup-intent`,
318
+ // MACHINE_SPEC is intentionally absent until the server registers
319
+ // `PATCH /machines/{machineId}/spec`. Reintroduce with ParallClient.resizeMachine
320
+ // once the in-place resize endpoint lands.
321
+ COMPUTE_PRICING: () => `${API_BASE}/billing/compute-pricing`,
322
+
323
+ // ADMIN_GRANTS intentionally NOT exported here — it sits under the
324
+ // unauthenticated `/internal/admin/*` surface and must not bleed into the
325
+ // public SDK. Admin dashboard hits the URL directly from its own client.
326
+
299
327
  } as const;
300
328
 
301
329
  // WebSocket event types
@@ -354,6 +382,11 @@ export const WS_EVENTS = {
354
382
  SCHEDULE_UPDATED: 'schedule.updated',
355
383
  SCHEDULE_DELETED: 'schedule.deleted',
356
384
  SCHEDULE_FIRED: 'schedule.fired',
385
+ BILLING_BALANCE_UPDATED: 'billing.balance_updated',
386
+ BILLING_LOW_BALANCE: 'billing.low_balance',
387
+ BILLING_MACHINE_STOPPED: 'billing.machine_stopped',
388
+ BILLING_INSUFFICIENT: 'billing.insufficient',
389
+ USER_UPDATED: 'user.updated',
357
390
  } as const;
358
391
 
359
392
  // Canonical target URI builders for unified comments.