@parall/sdk 1.56.1 → 1.57.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.
Files changed (40) hide show
  1. package/dist/attachment-client.d.ts +2 -2
  2. package/dist/attachment-client.d.ts.map +1 -1
  3. package/dist/attachment-client.js +2 -2
  4. package/dist/browser-use.d.ts +288 -0
  5. package/dist/browser-use.d.ts.map +1 -0
  6. package/dist/browser-use.js +6 -0
  7. package/dist/client.d.ts +14 -17
  8. package/dist/client.d.ts.map +1 -1
  9. package/dist/client.js +35 -29
  10. package/dist/constants.d.ts +12 -0
  11. package/dist/constants.d.ts.map +1 -1
  12. package/dist/constants.js +22 -0
  13. package/dist/index.d.ts +3 -0
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +2 -0
  16. package/dist/llm-provider-client.d.ts +38 -0
  17. package/dist/llm-provider-client.d.ts.map +1 -0
  18. package/dist/llm-provider-client.js +57 -0
  19. package/dist/llm-provider-types.d.ts +97 -0
  20. package/dist/llm-provider-types.d.ts.map +1 -0
  21. package/dist/llm-provider-types.js +6 -0
  22. package/dist/types.d.ts +56 -70
  23. package/dist/types.d.ts.map +1 -1
  24. package/dist/wiki-changeset.d.ts +4 -0
  25. package/dist/wiki-changeset.d.ts.map +1 -0
  26. package/dist/wiki-changeset.js +11 -0
  27. package/dist/wiki-upload.d.ts +43 -0
  28. package/dist/wiki-upload.d.ts.map +1 -0
  29. package/dist/wiki-upload.js +87 -0
  30. package/package.json +1 -1
  31. package/src/attachment-client.ts +2 -2
  32. package/src/browser-use.ts +217 -0
  33. package/src/client.ts +60 -30
  34. package/src/constants.ts +22 -0
  35. package/src/index.ts +8 -0
  36. package/src/llm-provider-client.ts +96 -0
  37. package/src/llm-provider-types.ts +104 -0
  38. package/src/types.ts +83 -101
  39. package/src/wiki-changeset.ts +13 -0
  40. package/src/wiki-upload.ts +142 -0
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Org-configured model providers (BYOK) and the model rows bound to them.
3
+ *
4
+ * Design: docs/engineering-design/org-llm-provider-byok-design.md
5
+ */
6
+
7
+ /** Inbound protocol a provider can serve. */
8
+ export type LLMProviderEndpoint = 'chat_completions' | 'messages' | 'responses';
9
+
10
+ export type LLMProviderStatus = 'active' | 'disabled';
11
+
12
+ /**
13
+ * A provider as the server returns it. The credential is never echoed back —
14
+ * `api_key_set` is the only thing a client learns about it.
15
+ */
16
+ export interface LLMProvider {
17
+ id: string;
18
+ name: string;
19
+ base_url: string;
20
+ api_key_set: boolean;
21
+ endpoints: LLMProviderEndpoint[];
22
+ status: LLMProviderStatus;
23
+ is_platform: boolean;
24
+ /**
25
+ * Runtime types whose protocol this provider can actually serve. Anything
26
+ * absent here silently uses the platform provider — surface this, or an
27
+ * operator will assume their credential covers every agent.
28
+ */
29
+ runtimes: string[];
30
+ /** Most recent fallback-worthy failure, if any. */
31
+ last_error_at?: string | null;
32
+ last_error_status?: number | null;
33
+ created_at: string;
34
+ updated_at: string;
35
+ }
36
+
37
+ export interface CreateLLMProviderRequest {
38
+ name: string;
39
+ base_url: string;
40
+ api_key: string;
41
+ endpoints: LLMProviderEndpoint[];
42
+ }
43
+
44
+ /** Omitting `api_key` leaves the stored credential untouched. */
45
+ export interface UpdateLLMProviderRequest {
46
+ name?: string;
47
+ base_url?: string;
48
+ api_key?: string;
49
+ endpoints?: LLMProviderEndpoint[];
50
+ status?: LLMProviderStatus;
51
+ }
52
+
53
+ /**
54
+ * One org's row for a model. Overriding a platform model and adding a new one
55
+ * are the same shape: `overrides_platform` is derived by the server from
56
+ * whether the platform catalog knows this id, never stored.
57
+ */
58
+ export interface OrgLLMModel {
59
+ id: string;
60
+ model_id: string;
61
+ provider_id: string;
62
+ upstream_model_id: string;
63
+ display_name?: string | null;
64
+ context_window?: number | null;
65
+ max_tokens?: number | null;
66
+ overrides_platform: boolean;
67
+ created_at: string;
68
+ updated_at: string;
69
+ }
70
+
71
+ export interface CreateOrgLLMModelRequest {
72
+ model_id: string;
73
+ provider_id: string;
74
+ /** The name to send to this provider, which differs per provider. */
75
+ upstream_model_id: string;
76
+ /** Required when `model_id` is not in the platform catalog. */
77
+ display_name?: string;
78
+ context_window?: number;
79
+ max_tokens?: number;
80
+ effort_levels?: string[];
81
+ input_modalities?: string[];
82
+ }
83
+
84
+ /**
85
+ * Everything about a model row except its identity. `model_id` is what agents
86
+ * pin to, so changing it is a delete-and-recreate the operator performs
87
+ * deliberately; the server rejects it here.
88
+ */
89
+ export interface UpdateOrgLLMModelRequest {
90
+ provider_id?: string;
91
+ upstream_model_id?: string;
92
+ /**
93
+ * Metadata fields accept `null` to clear the org's value and go back to
94
+ * inheriting the platform entry's. Omitting a field leaves it as it is —
95
+ * the two are different requests, so do not send `undefined` meaning
96
+ * "clear". A model the platform does not have cannot clear these: it has
97
+ * nothing to inherit from, and the server rejects it.
98
+ */
99
+ display_name?: string | null;
100
+ context_window?: number | null;
101
+ max_tokens?: number | null;
102
+ effort_levels?: string[] | null;
103
+ input_modalities?: string[] | null;
104
+ }
package/src/types.ts CHANGED
@@ -481,6 +481,25 @@ export interface Organization {
481
481
  onboarding_agent_id: string | null;
482
482
  /** Org-level IANA timezone (e.g. "America/New_York"). Defaults to "UTC". */
483
483
  timezone: string;
484
+ /**
485
+ * Whether this org may configure its own LLM providers (BYOK). Absent means
486
+ * it inherits the platform default, which is off.
487
+ *
488
+ * An entitlement, not a feature flag: only a platform admin changes it, and
489
+ * it is expected to become plan-driven. Turning it off also stops existing
490
+ * provider configuration from taking effect.
491
+ */
492
+ llm_byok_enabled?: boolean | null;
493
+ /**
494
+ * When an org's own model provider fails at run time, retry once on the
495
+ * platform provider — billed to this org's credit balance. Defaults to off,
496
+ * so "no fallback" is the default state and fallback is opted into.
497
+ * Does NOT gate the capability fallback: a provider that cannot serve a
498
+ * runtime's protocol always defers to the platform regardless.
499
+ * Current servers populate this field; it remains optional for source
500
+ * compatibility with cached and rolling-upgrade organization payloads.
501
+ */
502
+ llm_byok_fallback_enabled?: boolean;
484
503
  created_at: string;
485
504
  /** Per-member flag: true when the user has dismissed the onboarding popup for this org. */
486
505
  onboarding_dismissed: boolean;
@@ -710,11 +729,35 @@ export interface CreateInvitationRequest {
710
729
  role?: OrgMemberRole;
711
730
  }
712
731
 
713
- // Response of agent API key create/regenerate. The plaintext `api_key` is
714
- // returned exactly once at mint time and can never be fetched again.
732
+ // Response of API key create/regenerate (agent keys and personal keys alike).
733
+ // The plaintext `api_key` is returned exactly once at mint time and can never
734
+ // be fetched again. Personal keys additionally echo the org they are bound to.
715
735
  export interface ApiKey {
716
736
  id: string;
717
737
  api_key: string;
738
+ org_id?: string;
739
+ }
740
+
741
+ // A personal API key row as listed by GET /users/me/api-keys. Personal keys
742
+ // are org-scoped ("org_full"): the user's permissions inside org_id only.
743
+ // Managed Clip keys have their own surface; the key hash never leaves the
744
+ // server.
745
+ export interface PersonalApiKey {
746
+ id: string;
747
+ user_id: string;
748
+ name?: string;
749
+ org_id: string;
750
+ last_used_at?: string;
751
+ expires_at?: string;
752
+ created_at: string;
753
+ }
754
+
755
+ export interface CreatePersonalApiKeyRequest {
756
+ name?: string;
757
+ /** The org this key is bound to; the caller must be a member. */
758
+ org_id: string;
759
+ /** RFC3339; must be in the future. Omit for a non-expiring key. */
760
+ expires_at?: string;
718
761
  }
719
762
 
720
763
  export interface CreateAgentResponse {
@@ -1057,10 +1100,8 @@ export interface MessageDispatchSource {
1057
1100
  source_type: string;
1058
1101
  source_id: string;
1059
1102
  /**
1060
- * Conversation generation of the sending execution (parel v2 invocation
1061
- * context). Required by the server for agents on the direct_session_v2
1062
- * transport; a value older than the current New Session barrier is
1063
- * rejected (STALE_GENERATION).
1103
+ * @deprecated Ignored by current servers. Retained so clients compiled
1104
+ * against older SDKs can upgrade without source changes.
1064
1105
  */
1065
1106
  generation?: number;
1066
1107
  }
@@ -1797,8 +1838,8 @@ export interface UpdateTaskRequest {
1797
1838
  * Lane-bound form (v1 consumers): dispatch_lane + dispatch_event_id bind
1798
1839
  * the update to the claimed typed lane (incumbency-checked).
1799
1840
  * By-id form (parel v2 converged consumers — no lane exists):
1800
- * dispatch_event_id + dispatch_generation bind the update to the WorkItem
1801
- * directly under the conversation-generation fence.
1841
+ * dispatch_event_id alone binds the update to the WorkItem; the server
1842
+ * admits it on the binding's transport and deletion state alone.
1802
1843
  * In both forms dispatch_effect_key additionally commits the update as
1803
1844
  * the dispatch's idempotent Effect and resolves the WorkItem in the same
1804
1845
  * transaction. Lane-bound: exactly "task_update:<dispatch_event_id>" —
@@ -1811,6 +1852,10 @@ export interface UpdateTaskRequest {
1811
1852
  dispatch_lane?: string;
1812
1853
  dispatch_event_id?: string;
1813
1854
  dispatch_effect_key?: string;
1855
+ /**
1856
+ * @deprecated Ignored by current servers. Retained so clients compiled
1857
+ * against older SDKs can upgrade without source changes.
1858
+ */
1814
1859
  dispatch_generation?: number;
1815
1860
  }
1816
1861
 
@@ -2391,6 +2436,10 @@ export interface WikiChangeset {
2391
2436
  title: string;
2392
2437
  message: string | null;
2393
2438
  status: WikiChangesetStatus;
2439
+ /** Present on current servers; optional keeps older mocked/client data source-compatible. */
2440
+ head_branch?: string | null;
2441
+ /** Present on current servers; optional keeps older mocked/client data source-compatible. */
2442
+ base_commit?: string | null;
2394
2443
  merge_commit: string | null;
2395
2444
  file_changes: WikiFileChange[];
2396
2445
  changed_paths: string[];
@@ -2658,6 +2707,8 @@ export interface CreateWikiChangesetRequest {
2658
2707
  title: string;
2659
2708
  message?: string;
2660
2709
  file_changes: WikiFileChangeInput[];
2710
+ /** Omit for the server default (`proposed`); pass `draft` for staged uploads. */
2711
+ status?: 'draft' | 'proposed';
2661
2712
  source_chat_id?: string;
2662
2713
  source_message_id?: string;
2663
2714
  source_run_id?: string;
@@ -2667,6 +2718,8 @@ export interface UpdateWikiChangesetRequest {
2667
2718
  title?: string;
2668
2719
  message?: string;
2669
2720
  file_changes?: WikiFileChangeInput[];
2721
+ /** Author-settable transitions currently include `proposed` and `closed`. */
2722
+ status?: 'proposed' | 'closed';
2670
2723
  /**
2671
2724
  * When true, file_changes define the changeset's FULL content: the server
2672
2725
  * resets the feature branch to the current default-branch HEAD before
@@ -2832,17 +2885,6 @@ export interface WikiBlob {
2832
2885
  signed_url_expires_at?: string;
2833
2886
  }
2834
2887
 
2835
- export type WikiStoredAs = 'git_blob' | 'lfs_pointer';
2836
-
2837
- /** Response from POST /uploads or POST /changesets/{csId}/files. */
2838
- export interface WikiFileUploadResponse {
2839
- path: string;
2840
- size: number;
2841
- stored_as: WikiStoredAs;
2842
- commit_sha: string;
2843
- content_sha: string;
2844
- }
2845
-
2846
2888
  /** Response from POST /files/preview-url — short-lived signed URL for
2847
2889
  * browser `<img>`/`<video>`/`<iframe>` src. TTL is 5 minutes by default. */
2848
2890
  export interface WikiFilePreviewUrlResponse {
@@ -3365,6 +3407,7 @@ export interface ChannelConversation {
3365
3407
  agent_id: string;
3366
3408
  agent_session_id?: string | null;
3367
3409
  external_conversation_id: string;
3410
+ external_conversation_name?: string;
3368
3411
  external_thread_id: string;
3369
3412
  conversation_type: string;
3370
3413
  external_user_id: string;
@@ -4161,6 +4204,8 @@ export interface ResolvedRef {
4161
4204
  type: string;
4162
4205
  exists: boolean;
4163
4206
  restricted?: boolean;
4207
+ /** The target could not be resolved because a dependency failed temporarily. */
4208
+ unavailable?: boolean;
4164
4209
 
4165
4210
  // User fields
4166
4211
  display_name?: string;
@@ -5496,88 +5541,25 @@ export interface BrowserAliasExecutionReceipt {
5496
5541
  updated_at: string;
5497
5542
  }
5498
5543
 
5499
- export type BrowserUseAction =
5500
- | 'read'
5501
- | 'tabs'
5502
- | 'wait'
5503
- | 'snapshot'
5504
- | 'get'
5505
- | 'screenshot'
5506
- | 'open'
5507
- | 'navigate'
5508
- | 'viewport'
5509
- | 'click'
5510
- | 'fill'
5511
- | 'type'
5512
- | 'press'
5513
- | 'scroll'
5514
- | 'close'
5515
- | 'recover'
5516
- | 'eval';
5517
-
5518
- export interface BrowserUseTarget {
5519
- tab_id?: string;
5520
- browser_generation?: number;
5521
- document_generation?: number;
5522
- snapshot_id?: string;
5523
- ref?: string;
5524
- }
5525
-
5526
- export interface BrowserUseOperationRequest {
5527
- contract_version: 'browser-use-operation-v1';
5528
- request_id: string;
5529
- profile_id: string;
5530
- action: BrowserUseAction;
5531
- target?: BrowserUseTarget;
5532
- params: Record<string, unknown>;
5533
- /** Canonical RFC3339 UTC instant, no more than two minutes in the future. */
5534
- deadline: string;
5535
- }
5536
-
5537
- export type BrowserUseOperationPhase =
5538
- | 'accepted'
5539
- | 'started'
5540
- | 'succeeded'
5541
- | 'failed'
5542
- | 'outcome_unknown';
5543
-
5544
- export interface BrowserUseOperationError {
5545
- code: string;
5546
- message?: string;
5547
- hint?: string;
5548
- }
5549
-
5550
- /** Durable Browser Use proof. `data` is encrypted/transient: it is present
5551
- * only while result_available is true and disappears after result_expires_at;
5552
- * the terminal receipt and result_digest remain durable. */
5553
- export interface BrowserUseOperationReceipt {
5554
- contract_version: 'browser-use-operation-v1';
5555
- operation_id: string;
5556
- request_id: string;
5557
- profile_id: string;
5558
- profile_version: number;
5559
- profile_config_revision: number;
5560
- action: BrowserUseAction;
5561
- required_grant: 'browser.read' | 'browser.interact' | 'browser.advanced';
5562
- phase: BrowserUseOperationPhase;
5563
- dispatched?: boolean;
5564
- receipt_id?: string;
5565
- receipt_digest?: string;
5566
- occurred_at?: string;
5567
- tab_id?: string;
5568
- browser_generation?: number;
5569
- duration_ms?: number;
5570
- result_digest?: string;
5571
- result_available: boolean;
5572
- result_expires_at?: string;
5573
- data?: unknown;
5574
- error?: BrowserUseOperationError;
5575
- deadline: string;
5576
- accepted_at: string;
5577
- started_at?: string;
5578
- terminal_at?: string;
5579
- updated_at: string;
5580
- }
5544
+ export type {
5545
+ BrowserUseAction,
5546
+ BrowserUseActionRequest,
5547
+ BrowserUseArticle,
5548
+ BrowserUseGrant,
5549
+ BrowserUseOperationError,
5550
+ BrowserUseOperationPhase,
5551
+ BrowserUseOperationReceipt,
5552
+ BrowserUseOperationReceiptBase,
5553
+ BrowserUseOperationReceiptFor,
5554
+ BrowserUseOperationRequest,
5555
+ BrowserUseRefTarget,
5556
+ BrowserUseSuccessDataMap,
5557
+ BrowserUseTabState,
5558
+ BrowserUseTabSummary,
5559
+ BrowserUseTabTarget,
5560
+ BrowserUseTarget,
5561
+ BrowserUseViewport,
5562
+ } from './browser-use.js';
5581
5563
 
5582
5564
  /**
5583
5565
  * Sanitized per-profile egress proxy status (hosted Cloud Profiles) — the GET
@@ -0,0 +1,13 @@
1
+ import type { WikiChangeset } from './types.js';
2
+
3
+ /** Normalize fields that older wiki-service responses may omit. */
4
+ export function normalizeWikiChangeset(changeset: WikiChangeset): WikiChangeset {
5
+ return {
6
+ ...changeset,
7
+ head_branch: changeset.head_branch ?? null,
8
+ base_commit: changeset.base_commit ?? null,
9
+ merge_commit: changeset.merge_commit ?? null,
10
+ changed_paths: changeset.changed_paths ?? [],
11
+ file_changes: changeset.file_changes ?? [],
12
+ };
13
+ }
@@ -0,0 +1,142 @@
1
+ interface WikiFileUploadParamsBase {
2
+ path: string;
3
+ file: Blob;
4
+ message?: string;
5
+ /** Stable per-file retry key; replays return the original successful path. */
6
+ uploadId?: string;
7
+ /** Preserve the legacy 409 by default, or atomically choose `name (N).ext`. */
8
+ conflict?: 'error' | 'rename';
9
+ signal?: AbortSignal;
10
+ onProgress?: (uploadedBytes: number, totalBytes: number) => void;
11
+ }
12
+
13
+ export type WikiStoredAs = 'git_blob' | 'lfs_pointer';
14
+
15
+ /** Response from POST /uploads or POST /changesets/{csId}/files. */
16
+ export interface WikiFileUploadResponse {
17
+ path: string;
18
+ size: number;
19
+ stored_as: WikiStoredAs;
20
+ commit_sha: string;
21
+ content_sha: string;
22
+ }
23
+
24
+ /** Parameters for the maintain-only direct upload endpoint. */
25
+ export type WikiFileUploadParams = WikiFileUploadParamsBase;
26
+
27
+ /** Parameters for a changeset-scoped multipart upload. */
28
+ export interface WikiChangesetFileUploadParams extends WikiFileUploadParamsBase {
29
+ /** `auto` accepts reviewable text as a Git blob on the changeset branch. */
30
+ contentRoute?: 'binary' | 'auto';
31
+ }
32
+
33
+ export function createWikiUploadFormData(
34
+ params: WikiFileUploadParams | WikiChangesetFileUploadParams,
35
+ ): FormData {
36
+ const form = new FormData();
37
+ form.append('path', params.path);
38
+ form.append('file', params.file);
39
+ if (params.message) form.append('message', params.message);
40
+ if (params.uploadId) form.append('upload_id', params.uploadId);
41
+ if (params.conflict) form.append('conflict', params.conflict);
42
+ if ('contentRoute' in params && params.contentRoute) {
43
+ form.append('content_route', params.contentRoute);
44
+ }
45
+ return form;
46
+ }
47
+
48
+ interface MultipartTransportOptions {
49
+ method: string;
50
+ url: string;
51
+ headers: Record<string, string>;
52
+ body: FormData;
53
+ timeoutMs: number;
54
+ signal?: AbortSignal;
55
+ onProgress?: (uploadedBytes: number, totalBytes: number) => void;
56
+ }
57
+
58
+ /** Send one multipart request. XHR is used only when a browser caller asks
59
+ * for upload progress; fetch remains the transport everywhere else. Auth
60
+ * refresh and API error decoding stay in ParallClient above this boundary. */
61
+ export function sendMultipartRequest(options: MultipartTransportOptions): Promise<Response> {
62
+ if (options.onProgress && typeof XMLHttpRequest !== 'undefined') {
63
+ return multipartXHR(options, options.onProgress);
64
+ }
65
+ const timeoutSignal = AbortSignal.timeout(options.timeoutMs);
66
+ const signal = options.signal ? AbortSignal.any([options.signal, timeoutSignal]) : timeoutSignal;
67
+ return fetch(options.url, {
68
+ method: options.method,
69
+ headers: options.headers,
70
+ body: options.body,
71
+ signal,
72
+ });
73
+ }
74
+
75
+ function multipartXHR(
76
+ options: MultipartTransportOptions,
77
+ onProgress: (uploadedBytes: number, totalBytes: number) => void,
78
+ ): Promise<Response> {
79
+ return new Promise((resolve, reject) => {
80
+ const xhr = new XMLHttpRequest();
81
+ let settled = false;
82
+
83
+ const finish = (fn: () => void) => {
84
+ if (settled) return;
85
+ settled = true;
86
+ options.signal?.removeEventListener('abort', abortFromSignal);
87
+ fn();
88
+ };
89
+ const abortFromSignal = () => xhr.abort();
90
+
91
+ xhr.open(options.method, options.url, true);
92
+ xhr.timeout = options.timeoutMs;
93
+ for (const [name, value] of Object.entries(options.headers)) {
94
+ xhr.setRequestHeader(name, value);
95
+ }
96
+
97
+ xhr.upload.onprogress = (event) => {
98
+ try {
99
+ onProgress(event.loaded, event.lengthComputable ? event.total : 0);
100
+ } catch {
101
+ // Observer failures must not cancel an otherwise healthy upload.
102
+ }
103
+ };
104
+ xhr.onload = () =>
105
+ finish(() => {
106
+ const responseHeaders = new Headers();
107
+ for (const line of xhr
108
+ .getAllResponseHeaders()
109
+ .trim()
110
+ .split(/[\r\n]+/)) {
111
+ if (!line) continue;
112
+ const separator = line.indexOf(':');
113
+ if (separator > 0) {
114
+ responseHeaders.append(
115
+ line.slice(0, separator).trim(),
116
+ line.slice(separator + 1).trim(),
117
+ );
118
+ }
119
+ }
120
+ const responseBody =
121
+ xhr.status === 204 || xhr.responseText === '' ? null : xhr.responseText;
122
+ resolve(
123
+ new Response(responseBody, {
124
+ status: xhr.status,
125
+ statusText: xhr.statusText,
126
+ headers: responseHeaders,
127
+ }),
128
+ );
129
+ });
130
+ xhr.onerror = () => finish(() => reject(new TypeError('Network request failed')));
131
+ xhr.ontimeout = () =>
132
+ finish(() => reject(new DOMException('Request timed out', 'TimeoutError')));
133
+ xhr.onabort = () => finish(() => reject(new DOMException('Request aborted', 'AbortError')));
134
+
135
+ if (options.signal?.aborted) {
136
+ finish(() => reject(new DOMException('Request aborted', 'AbortError')));
137
+ return;
138
+ }
139
+ options.signal?.addEventListener('abort', abortFromSignal, { once: true });
140
+ xhr.send(options.body);
141
+ });
142
+ }