@parall/sdk 1.55.5 → 1.56.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
@@ -41,6 +41,8 @@ import type {
41
41
  BrowserAliasExecutionReceipt,
42
42
  BrowserAliasGrantReplaceRequest,
43
43
  BrowserAliasGrantSet,
44
+ BrowserUseOperationRequest,
45
+ BrowserUseOperationReceipt,
44
46
  BrowserRuntimeStatus,
45
47
  BrowserViewerCommandRequest,
46
48
  BrowserViewerCommandResponse,
@@ -3091,6 +3093,19 @@ export class ParallClient extends AttachmentClient {
3091
3093
  await this.request('DELETE', ENDPOINTS.WIKI_MEMBERSHIP_SELF(orgId, wikiId));
3092
3094
  }
3093
3095
 
3096
+ /** Star a library for the caller (sidebar Starred group). Idempotent —
3097
+ * re-starring is a 204 no-op. Requires read access; hidden private
3098
+ * libraries answer 404 like absent IDs. */
3099
+ async starWiki(orgId: string, wikiId: string): Promise<void> {
3100
+ await this.request('POST', ENDPOINTS.WIKI_STARS_SELF(orgId, wikiId));
3101
+ }
3102
+
3103
+ /** Remove the caller's star. Idempotent — unstarring a never-starred
3104
+ * library is a 204 no-op. */
3105
+ async unstarWiki(orgId: string, wikiId: string): Promise<void> {
3106
+ await this.request('DELETE', ENDPOINTS.WIKI_STARS_SELF(orgId, wikiId));
3107
+ }
3108
+
3094
3109
  async getWikiMembers(orgId: string, wikiId: string): Promise<WikiAccessPolicyMember[]> {
3095
3110
  const res = await this.request<{ data: WikiAccessPolicyMember[] | null }>(
3096
3111
  'GET',
@@ -3674,8 +3689,12 @@ export class ParallClient extends AttachmentClient {
3674
3689
  * connections operate on.
3675
3690
  */
3676
3691
  async listOrgRegistryClips(orgId: string): Promise<ClipRegistryEntry[]> {
3677
- // Server default page is 50 (max 100); one max-size page covers today's
3678
- // catalogs revisit with real pagination if registries outgrow it.
3692
+ // ONE page (server max 100), name-ordered a browse surface, not a
3693
+ // resolution surface. The catalog includes every public+approved clip
3694
+ // platform-wide, so "fetch it all" cannot scale; anything that needs a
3695
+ // SPECIFIC clip must point-query instead: `resolveRegistryClip` for an
3696
+ // exact <publisher org, name>, `getRegistryClip` for a `crg_` id, and
3697
+ // `searchOrgRegistryClips` for discovery.
3679
3698
  const resp = await this.request<ClipRegistryEntry[] | null>(
3680
3699
  'GET',
3681
3700
  `${ENDPOINTS.ORG_CLIP_REGISTRY(orgId)}?limit=100`,
@@ -3683,6 +3702,42 @@ export class ParallClient extends AttachmentClient {
3683
3702
  return resp ?? [];
3684
3703
  }
3685
3704
 
3705
+ /**
3706
+ * Resolve an exact `<publisher org, name>` reference to its registry entry —
3707
+ * the npm-style point read. Deliberately independent of catalog size: no
3708
+ * Search, no pagination, same read-visibility boundary as `getRegistryClip`
3709
+ * (cross-org requires public + approved). 404 `NOT_FOUND` when the publisher
3710
+ * org has no visible clip of that exact name.
3711
+ */
3712
+ async resolveRegistryClip(
3713
+ orgId: string,
3714
+ publisherOrgId: string,
3715
+ name: string,
3716
+ ): Promise<ClipRegistryEntry> {
3717
+ const params = new URLSearchParams({ org_id: publisherOrgId, name });
3718
+ return this.request('GET', `${ENDPOINTS.ORG_CLIP_REGISTRY_RESOLVE(orgId)}?${params}`);
3719
+ }
3720
+
3721
+ /**
3722
+ * Server-side fuzzy discovery over the visible registry (name/description
3723
+ * substring match), paginated. The discovery verb: rows carry the `crg_` id
3724
+ * that {@link installRegistryClip} takes.
3725
+ */
3726
+ async searchOrgRegistryClips(
3727
+ orgId: string,
3728
+ query: string,
3729
+ opts?: { limit?: number; offset?: number },
3730
+ ): Promise<ClipRegistryEntry[]> {
3731
+ const params = new URLSearchParams({ q: query });
3732
+ if (opts?.limit !== undefined) params.set('limit', String(opts.limit));
3733
+ if (opts?.offset !== undefined) params.set('offset', String(opts.offset));
3734
+ const resp = await this.request<ClipRegistryEntry[] | null>(
3735
+ 'GET',
3736
+ `${ENDPOINTS.ORG_CLIP_REGISTRY_SEARCH(orgId)}?${params}`,
3737
+ );
3738
+ return resp ?? [];
3739
+ }
3740
+
3686
3741
  /**
3687
3742
  * Install a registry clip into the org (a reference in `clip_installs`, not a
3688
3743
  * copy). Idempotent: installing an already-installed clip returns the same
@@ -3990,6 +4045,24 @@ export class ParallClient extends AttachmentClient {
3990
4045
  return this.request('GET', ENDPOINTS.ORG_BROWSER_ALIAS_EXECUTION(orgId, requestId));
3991
4046
  }
3992
4047
 
4048
+ /** Accept one idempotent Browser Use operation for an explicit Profile.
4049
+ * The Server resolves Profile→Edge; callers never select an Edge directly. */
4050
+ async createBrowserUseOperation(
4051
+ orgId: string,
4052
+ request: BrowserUseOperationRequest,
4053
+ ): Promise<BrowserUseOperationReceipt> {
4054
+ return this.request('POST', ENDPOINTS.ORG_BROWSER_USE_OPERATIONS(orgId), request);
4055
+ }
4056
+
4057
+ /** Recover the durable receipt. Successful data is present only inside the
4058
+ * Server's short encrypted result TTL; terminal proof remains afterwards. */
4059
+ async getBrowserUseOperation(
4060
+ orgId: string,
4061
+ operationId: string,
4062
+ ): Promise<BrowserUseOperationReceipt> {
4063
+ return this.request('GET', ENDPOINTS.ORG_BROWSER_USE_OPERATION(orgId, operationId));
4064
+ }
4065
+
3993
4066
  /**
3994
4067
  * Read a hosted Cloud Profile's egress-proxy status (manager-only: hosted
3995
4068
  * human maintainer or org admin). Sanitized — the password never comes back.
package/src/constants.ts CHANGED
@@ -573,6 +573,7 @@ export const ENDPOINTS = {
573
573
  TASKS: (orgId: string) => `${API_BASE}/orgs/${orgId}/tasks`,
574
574
  TASK_SUBTASK_SUMMARY: (orgId: string) => `${API_BASE}/orgs/${orgId}/tasks/subtask-summary`,
575
575
  TASK: (orgId: string, taskId: string) => `${API_BASE}/orgs/${orgId}/tasks/${taskId}`,
576
+ TASK_MOVE: (orgId: string, taskId: string) => `${API_BASE}/orgs/${orgId}/tasks/${taskId}/move`,
576
577
  TASK_ARCHIVE: (orgId: string, taskId: string) =>
577
578
  `${API_BASE}/orgs/${orgId}/tasks/${taskId}/archive`,
578
579
  TASK_RESTORE: (orgId: string, taskId: string) =>
@@ -776,6 +777,9 @@ export const ENDPOINTS = {
776
777
  `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/access-policy/members`,
777
778
  WIKI_MEMBERSHIP_SELF: (orgId: string, wikiId: string) =>
778
779
  `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/membership/self`,
780
+ // Library-level star (self-scoped bookmark; POST = star, DELETE = unstar).
781
+ WIKI_STARS_SELF: (orgId: string, wikiId: string) =>
782
+ `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/stars/self`,
779
783
  WIKI_MEMBERS: (orgId: string, wikiId: string) =>
780
784
  `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/members`,
781
785
  WIKI_ACCESS_STATUS: (orgId: string, wikiId: string) =>
@@ -972,6 +976,9 @@ export const ENDPOINTS = {
972
976
  ORG_BROWSER_ALIAS_EXECUTIONS: (orgId: string) => `/api/v1/orgs/${orgId}/executions`,
973
977
  ORG_BROWSER_ALIAS_EXECUTION: (orgId: string, requestId: string) =>
974
978
  `/api/v1/orgs/${orgId}/executions/${encodeURIComponent(requestId)}`,
979
+ ORG_BROWSER_USE_OPERATIONS: (orgId: string) => `/api/v1/orgs/${orgId}/browser-use/operations`,
980
+ ORG_BROWSER_USE_OPERATION: (orgId: string, operationId: string) =>
981
+ `/api/v1/orgs/${orgId}/browser-use/operations/${encodeURIComponent(operationId)}`,
975
982
  // Per-profile egress proxy (hosted Cloud Profiles; manager-only, human-only).
976
983
  ORG_EDGE_PROFILE_PROXY: (orgId: string, edgeId: string, profileName: string) =>
977
984
  `/api/v1/orgs/${orgId}/edge/${edgeId}/profiles/${encodeURIComponent(profileName)}/proxy`,
@@ -992,6 +999,8 @@ export const ENDPOINTS = {
992
999
 
993
1000
  // Clip registry (v3, org-scoped, served by api-server — `crg_` entries)
994
1001
  ORG_CLIP_REGISTRY: (orgId: string) => `/api/v1/orgs/${orgId}/clip-registry`,
1002
+ ORG_CLIP_REGISTRY_RESOLVE: (orgId: string) => `/api/v1/orgs/${orgId}/clip-registry/resolve`,
1003
+ ORG_CLIP_REGISTRY_SEARCH: (orgId: string) => `/api/v1/orgs/${orgId}/clip-registry/search`,
995
1004
  ORG_CLIP_REGISTRY_CLIP: (orgId: string, clipId: string) =>
996
1005
  `/api/v1/orgs/${orgId}/clip-registry/${clipId}`,
997
1006
  ORG_CLIP_REGISTRY_PUBLISH: (orgId: string) => `/api/v1/orgs/${orgId}/clip-registry/publish`,
@@ -23,6 +23,7 @@ import type {
23
23
  UpdateProjectMemberRequest,
24
24
  UpdateProjectRequest,
25
25
  UpdateTaskCommentRequest,
26
+ MoveTaskRequest,
26
27
  UpdateTaskRequest,
27
28
  } from './types.js';
28
29
 
@@ -84,6 +85,16 @@ export abstract class ProjectTaskClient {
84
85
  );
85
86
  }
86
87
 
88
+ /**
89
+ * Moves a task and its whole subtree into another project (renumbering it
90
+ * there; old identifiers stay resolvable as aliases). The caller needs
91
+ * update access on the task (source project membership) and read access to
92
+ * the target project.
93
+ */
94
+ async moveTask(orgId: string, taskId: string, data: MoveTaskRequest): Promise<Task> {
95
+ return this.request('POST', ENDPOINTS.TASK_MOVE(orgId, taskId), data);
96
+ }
97
+
87
98
  async archiveTask(orgId: string, taskId: string): Promise<void> {
88
99
  return this.request('POST', ENDPOINTS.TASK_ARCHIVE(orgId, taskId));
89
100
  }
package/src/types.ts CHANGED
@@ -4,6 +4,7 @@ import type {
4
4
  LabelDeletedData,
5
5
  LabelUpdatedData,
6
6
  } from './task-label-types.js';
7
+
7
8
  export type {
8
9
  CompletedUploadPart,
9
10
  FileUrlResponse,
@@ -63,7 +64,11 @@ export interface Chat {
63
64
  created_at: string;
64
65
  updated_at: string;
65
66
  archived_at?: string | null;
67
+ archived_by?: string | null;
66
68
  deleted_at?: string | null;
69
+ deleted_by?: string | null;
70
+ member_count?: number;
71
+ my_role?: ChatMemberRole;
67
72
  pinned: boolean;
68
73
  hidden: boolean;
69
74
  my_notification_level?: NotificationLevel;
@@ -365,10 +370,18 @@ export interface Message {
365
370
  recent_repliers?: User[];
366
371
  /**
367
372
  * Per-viewer count of thread replies newer than the viewer's thread read
368
- * cursor, excluding the viewer's own replies (root only). Populated on
369
- * top-level list responses; omitted when zero.
373
+ * cursor, excluding the viewer's own replies (root only). Watcher-scoped:
374
+ * only threads the viewer watches accrue unread. Populated on top-level
375
+ * list responses; omitted when zero.
370
376
  */
371
377
  unread_reply_count?: number;
378
+ /**
379
+ * Per-viewer thread watch state (root only): true when the viewer watches
380
+ * this root's thread. Populated on top-level list responses for roots with
381
+ * replies; omitted means not watching. Seeds the client's live unread
382
+ * mirror.
383
+ */
384
+ watching?: boolean;
372
385
  edited_at: string | null;
373
386
  deleted_at: string | null;
374
387
  created_at: string;
@@ -1636,7 +1649,9 @@ export interface Task {
1636
1649
  completed_at: string | null;
1637
1650
  canceled_at: string | null;
1638
1651
  archived_at?: string | null;
1652
+ archived_by?: string | null;
1639
1653
  deleted_at?: string | null;
1654
+ deleted_by?: string | null;
1640
1655
  /**
1641
1656
  * Per-viewer: whether the requesting user may manage OTHER members' comment
1642
1657
  * subscriptions for this task (creator / assignee / project manager / org
@@ -1731,6 +1746,20 @@ export interface CreateTaskRequest {
1731
1746
  label_ids?: string[];
1732
1747
  }
1733
1748
 
1749
+ /**
1750
+ * Moves a task (and its whole subtree) into another project via
1751
+ * POST /tasks/{taskId}/move — the only path that changes the binding; PATCH
1752
+ * keeps refusing project_id changes. Every subtree node is renumbered from the
1753
+ * target project's counter and its old KEY-N identifier stays resolvable as a
1754
+ * permanent alias. parent_id (must belong to the target project) attaches the
1755
+ * moved root under a parent there; same-project calls with a parent degrade to
1756
+ * a reparent, without one they are an idempotent no-op.
1757
+ */
1758
+ export interface MoveTaskRequest {
1759
+ project_id: string;
1760
+ parent_id?: string;
1761
+ }
1762
+
1734
1763
  export interface UpdateTaskRequest {
1735
1764
  title?: string;
1736
1765
  description?: string;
@@ -1738,9 +1767,10 @@ export interface UpdateTaskRequest {
1738
1767
  priority?: TaskPriority;
1739
1768
  assignee_id?: string | null;
1740
1769
  parent_id?: string | null;
1741
- // project_id is deliberately absent: a Task's Project is immutable after
1742
- // creation (server answers 400 PROJECT_IMMUTABLE; resubmitting the current
1743
- // value is an idempotent no-op).
1770
+ // project_id is deliberately absent: PATCH cannot change a Task's Project
1771
+ // (server answers 400 PROJECT_IMMUTABLE; resubmitting the current value is
1772
+ // an idempotent no-op). Moving between projects is its own explicit
1773
+ // operation — see MoveTaskRequest / moveTask().
1744
1774
  sort_order?: number;
1745
1775
  /**
1746
1776
  * Ordering intent resolved server-side in the update transaction:
@@ -1818,6 +1848,8 @@ export interface Project {
1818
1848
  sort_order: number;
1819
1849
  created_at: string;
1820
1850
  updated_at: string;
1851
+ archived_at?: string | null;
1852
+ archived_by?: string | null;
1821
1853
  /** The requesting user's own role, computed per request rather than stored.
1822
1854
  * Absent means they hold no membership (direct or team-derived). */
1823
1855
  my_role?: ProjectRole;
@@ -2338,11 +2370,19 @@ export interface Wiki {
2338
2370
  * access_tier are populated — enough to request to join, nothing else.
2339
2371
  * Degraded entries must not be mounted, synced or treated as content. */
2340
2372
  degraded?: boolean;
2373
+ /** Caller's library-level star (the sidebar Starred group). Carried on full
2374
+ * list/get projections only — degraded entries never have it. */
2375
+ starred?: boolean;
2341
2376
  }
2342
2377
 
2343
2378
  export interface WikiFileChange {
2344
2379
  path: string;
2345
- action: 'create' | 'update' | 'delete';
2380
+ action: 'create' | 'update' | 'delete' | 'rename';
2381
+ /**
2382
+ * Rename source; present only when action is "rename" (path is the rename
2383
+ * target). Additive key — older changesets never carry it.
2384
+ */
2385
+ from_path?: string;
2346
2386
  }
2347
2387
 
2348
2388
  export interface WikiChangeset {
@@ -2558,7 +2598,9 @@ export interface WikiRefsCheckResponse {
2558
2598
 
2559
2599
  export interface WikiDiffFile {
2560
2600
  path: string;
2561
- action?: string; // "create" | "update" | "delete"
2601
+ action?: string; // "create" | "update" | "delete" | "rename"
2602
+ /** Rename source when action is "rename" (path is the target). */
2603
+ from_path?: string;
2562
2604
  additions: number;
2563
2605
  deletions: number;
2564
2606
  }
@@ -2574,20 +2616,44 @@ export interface CreateWikiRequest {
2574
2616
  default_branch?: string;
2575
2617
  }
2576
2618
 
2577
- export interface WikiFileChangeInput {
2619
+ interface WikiFileChangeInputCommon {
2578
2620
  path: string;
2579
- action: 'create' | 'update' | 'delete';
2580
- content_base64?: string;
2581
2621
  base_version?: number;
2582
2622
  /**
2583
2623
  * Git blob SHA of the default-branch version this change was authored
2584
2624
  * against. When set on update/delete, the server rejects the changeset
2585
2625
  * with 409 STALE_BASE if the file has since changed on the default branch
2586
- * (prevents silently overwriting concurrent edits).
2626
+ * (prevents silently overwriting concurrent edits). For rename it guards
2627
+ * the from_path side.
2587
2628
  */
2588
2629
  base_sha?: string;
2589
2630
  }
2590
2631
 
2632
+ export interface WikiFileChangeWriteInput extends WikiFileChangeInputCommon {
2633
+ action: 'create' | 'update' | 'delete';
2634
+ content_base64?: string;
2635
+ /** Only valid with action "rename" — the server rejects it elsewhere. */
2636
+ from_path?: never;
2637
+ }
2638
+
2639
+ /**
2640
+ * Rename is a discriminated variant: `from_path` (the source; `path` is the
2641
+ * target) and `content_base64` are both REQUIRED. The content must be sent —
2642
+ * the server rejects a rename without the content_base64 key
2643
+ * (400 MISSING_FIELDS) because the single-commit move always writes content
2644
+ * and an omitted key would otherwise erase the file; an explicitly empty
2645
+ * string (an empty file) is legal. Requires the server capability
2646
+ * `cap:wiki-rename` — while it is off the server answers 422 RENAME_DISABLED
2647
+ * (older servers answer 400 INVALID_ACTION).
2648
+ */
2649
+ export interface WikiFileChangeRenameInput extends WikiFileChangeInputCommon {
2650
+ action: 'rename';
2651
+ from_path: string;
2652
+ content_base64: string;
2653
+ }
2654
+
2655
+ export type WikiFileChangeInput = WikiFileChangeWriteInput | WikiFileChangeRenameInput;
2656
+
2591
2657
  export interface CreateWikiChangesetRequest {
2592
2658
  title: string;
2593
2659
  message?: string;
@@ -5430,6 +5496,89 @@ export interface BrowserAliasExecutionReceipt {
5430
5496
  updated_at: string;
5431
5497
  }
5432
5498
 
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
+ }
5581
+
5433
5582
  /**
5434
5583
  * Sanitized per-profile egress proxy status (hosted Cloud Profiles) — the GET
5435
5584
  * response and the PUT/DELETE result. NEVER carries the password; `password_set`