@parall/sdk 1.34.0 → 1.35.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
@@ -11,6 +11,7 @@ import type {
11
11
  Organization,
12
12
  OrgMember,
13
13
  OrgMemberRole,
14
+ Team,
14
15
  Chat,
15
16
  ChatMember,
16
17
  ChatMemberRole,
@@ -34,6 +35,7 @@ import type {
34
35
  ApiKey,
35
36
  WsTicketResponse,
36
37
  Machine,
38
+ MachineCapability,
37
39
  ResizeMachineRequest,
38
40
  MachineKey,
39
41
  MachineRuntimeAuthState,
@@ -103,6 +105,8 @@ import type {
103
105
  CreateWikiChangesetRequest,
104
106
  UpdateWikiChangesetRequest,
105
107
  CreateWikiPathScopeRequest,
108
+ WikiPathRestriction,
109
+ CreateWikiPathRestrictionRequest,
106
110
  CreateWikiAccessRequest,
107
111
  Comment,
108
112
  CreateCommentRequest,
@@ -148,6 +152,7 @@ import type {
148
152
  AgentClip,
149
153
  CreateClipRequest,
150
154
  UpdateClipRequest,
155
+ BulkUpdateClipMetadataRequest,
151
156
  BindAgentClipRequest,
152
157
  InvokeClipRequest,
153
158
  InvokeClipResponse,
@@ -160,6 +165,8 @@ import type {
160
165
  CreateBrowserProfileRequest,
161
166
  UpdateBrowserProfileRequest,
162
167
  BrowserProfileLifecycleRequest,
168
+ BrowserViewerCommandRequest,
169
+ BrowserViewerCommandResponse,
163
170
  GrantBrowserProfileConsentRequest,
164
171
  } from './types.js';
165
172
 
@@ -312,7 +319,7 @@ export class ParallClient {
312
319
  body?: unknown,
313
320
  query?: Record<string, string | number | boolean | undefined>,
314
321
  retried = false,
315
- opts?: { timeoutMs?: number; signal?: AbortSignal },
322
+ opts?: { timeoutMs?: number; signal?: AbortSignal; keepalive?: boolean },
316
323
  ): Promise<T> {
317
324
  // Proactive refresh: block until token is fresh (no-op if still valid)
318
325
  if (!retried) {
@@ -349,6 +356,9 @@ export class ParallClient {
349
356
  headers,
350
357
  body: body ? JSON.stringify(body) : undefined,
351
358
  signal,
359
+ // keepalive lets a request fired during page unload (e.g. the browser
360
+ // viewer's stream.close on pagehide) outlive the document.
361
+ keepalive: opts?.keepalive,
352
362
  });
353
363
  } catch (err) {
354
364
  throw ParallClient.normalizeFetchError(err);
@@ -580,6 +590,11 @@ export class ParallClient {
580
590
  return res.data;
581
591
  }
582
592
 
593
+ async getTeams(orgId: string): Promise<Team[]> {
594
+ const res = await this.request<{ data: Team[] }>('GET', ENDPOINTS.TEAMS(orgId));
595
+ return res.data;
596
+ }
597
+
583
598
  async getOnlineMembers(orgId: string): Promise<string[]> {
584
599
  const res = await this.request<{ user_ids: string[] }>(
585
600
  'GET',
@@ -1007,6 +1022,11 @@ export class ParallClient {
1007
1022
  return this.request('POST', ENDPOINTS.AGENT_API_KEYS(orgId, agentId));
1008
1023
  }
1009
1024
 
1025
+ /** Revokes all of the agent's active API keys and mints a replacement. */
1026
+ async regenerateAgentApiKey(orgId: string, agentId: string): Promise<ApiKey> {
1027
+ return this.request('POST', ENDPOINTS.AGENT_API_KEY_REGENERATE(orgId, agentId));
1028
+ }
1029
+
1010
1030
  async revokeAgentApiKey(orgId: string, agentId: string, key: string): Promise<void> {
1011
1031
  return this.request('DELETE', ENDPOINTS.AGENT_API_KEY(orgId, agentId, key));
1012
1032
  }
@@ -1254,7 +1274,15 @@ export class ParallClient {
1254
1274
  */
1255
1275
  async createMachine(
1256
1276
  orgId: string,
1257
- opts: { label?: string; compute_mode: 'local'; llm_source?: 'parall' | 'runtime_auth' },
1277
+ opts: {
1278
+ label?: string;
1279
+ compute_mode: 'local';
1280
+ llm_source?: 'parall' | 'runtime_auth';
1281
+ // Omit for the default BYOC daemon (agent_host + browser_provider). Pass an
1282
+ // explicit set for a single-purpose host, e.g. ['browser_provider'] for a
1283
+ // platform-hosted bb-browser + Chromium provider.
1284
+ capabilities?: MachineCapability[];
1285
+ },
1258
1286
  ): Promise<{
1259
1287
  machine: Machine;
1260
1288
  machine_key: string;
@@ -1338,6 +1366,22 @@ export class ParallClient {
1338
1366
  });
1339
1367
  }
1340
1368
 
1369
+ /**
1370
+ * Replace the machine's capability set (admin). Primary use: healing a
1371
+ * machine that registered without `browser_provider` during the capability
1372
+ * migration's rolling-deploy window. Removing `agent_host` is rejected by the
1373
+ * server while agents are attached (409 AGENTS_STILL_ATTACHED).
1374
+ */
1375
+ async patchMachineCapabilities(
1376
+ orgId: string,
1377
+ machineId: string,
1378
+ capabilities: MachineCapability[],
1379
+ ): Promise<Machine> {
1380
+ return this.request('PATCH', ENDPOINTS.MACHINE_CAPABILITIES(orgId, machineId), {
1381
+ capabilities,
1382
+ });
1383
+ }
1384
+
1341
1385
  /** Get machine-level runtime auth state. */
1342
1386
  async getMachineRuntimeAuth(orgId: string, machineId: string): Promise<MachineRuntimeAuthState> {
1343
1387
  return this.request('GET', ENDPOINTS.MACHINE_RUNTIME_AUTH(orgId, machineId));
@@ -1483,6 +1527,43 @@ export class ParallClient {
1483
1527
  return this.request('POST', ENDPOINTS.MACHINES_ME_BROWSE_RESPONSE(requestId), response);
1484
1528
  }
1485
1529
 
1530
+ /**
1531
+ * `POST /machines/me/browser-profiles/viewer-response/{requestId}` — daemon
1532
+ * reply to a `machine.browser_profile.viewer` control command. Wakes the
1533
+ * api-server request/reply bridge (mirrors {@link postBrowseResponse}).
1534
+ */
1535
+ async postBrowserProfileViewerResponse(
1536
+ requestId: string,
1537
+ response: { result?: Record<string, unknown>; error?: { message: string } },
1538
+ ): Promise<void> {
1539
+ return this.request(
1540
+ 'POST',
1541
+ ENDPOINTS.MACHINES_ME_BROWSER_PROFILE_VIEWER_RESPONSE(requestId),
1542
+ response,
1543
+ );
1544
+ }
1545
+
1546
+ /**
1547
+ * `POST /orgs/{orgId}/browser-profiles/{profileId}/viewer/command` — drive the
1548
+ * hosted browser live viewer (WebRTC signaling + tab nav). Authz: profile
1549
+ * owner or org admin. api-server brokers the command to the host daemon.
1550
+ */
1551
+ async browserViewerCommand(
1552
+ orgId: string,
1553
+ profileId: string,
1554
+ req: BrowserViewerCommandRequest,
1555
+ opts?: { timeoutMs?: number; keepalive?: boolean },
1556
+ ): Promise<BrowserViewerCommandResponse> {
1557
+ return this.request(
1558
+ 'POST',
1559
+ ENDPOINTS.BROWSER_PROFILE_VIEWER_COMMAND(orgId, profileId),
1560
+ req,
1561
+ undefined,
1562
+ false,
1563
+ opts,
1564
+ );
1565
+ }
1566
+
1486
1567
  async resizeMachine(
1487
1568
  orgId: string,
1488
1569
  machineId: string,
@@ -2018,7 +2099,9 @@ export class ParallClient {
2018
2099
 
2019
2100
  async search(
2020
2101
  orgId: string,
2021
- params: { q: string; types?: string; chat_id?: string; limit?: number },
2102
+ // `types` selects entities (message/task/wiki); `wiki_type` is the distinct
2103
+ // wiki document-type facet (frontmatter `type`) — the two never overlap.
2104
+ params: { q: string; types?: string; chat_id?: string; limit?: number; wiki_type?: string },
2022
2105
  opts?: { signal?: AbortSignal },
2023
2106
  ): Promise<SearchResponse> {
2024
2107
  return this.request('GET', ENDPOINTS.SEARCH(orgId), undefined, params, false, opts);
@@ -2027,7 +2110,8 @@ export class ParallClient {
2027
2110
  async searchWiki(
2028
2111
  orgId: string,
2029
2112
  wikiId: string,
2030
- params: { q: string; limit?: number; path_prefix?: string; ref?: string },
2113
+ // `type` is the wiki document-type facet (frontmatter `type`).
2114
+ params: { q: string; limit?: number; path_prefix?: string; ref?: string; type?: string },
2031
2115
  ): Promise<WikiSearchResponse> {
2032
2116
  return this.request('GET', ENDPOINTS.WIKI_SEARCH(orgId, wikiId), undefined, params);
2033
2117
  }
@@ -2228,6 +2312,28 @@ export class ParallClient {
2228
2312
  await this.request('DELETE', ENDPOINTS.WIKI_PATH_SCOPE(orgId, wikiId, scopeId));
2229
2313
  }
2230
2314
 
2315
+ // ---- Wiki Path Restrictions (narrowing ACL — private subtrees) ----
2316
+
2317
+ async getWikiRestrictions(orgId: string, wikiId: string): Promise<WikiPathRestriction[]> {
2318
+ const res = await this.request<{ data: WikiPathRestriction[] }>(
2319
+ 'GET',
2320
+ ENDPOINTS.WIKI_RESTRICTIONS(orgId, wikiId),
2321
+ );
2322
+ return res.data;
2323
+ }
2324
+
2325
+ async createWikiRestriction(
2326
+ orgId: string,
2327
+ wikiId: string,
2328
+ data: CreateWikiPathRestrictionRequest,
2329
+ ): Promise<WikiPathRestriction> {
2330
+ return this.request('POST', ENDPOINTS.WIKI_RESTRICTIONS(orgId, wikiId), data);
2331
+ }
2332
+
2333
+ async deleteWikiRestriction(orgId: string, wikiId: string, restrictionId: string): Promise<void> {
2334
+ await this.request('DELETE', ENDPOINTS.WIKI_RESTRICTION(orgId, wikiId, restrictionId));
2335
+ }
2336
+
2231
2337
  async getWikiAccessStatus(
2232
2338
  orgId: string,
2233
2339
  wikiId: string,
@@ -2511,6 +2617,11 @@ export class ParallClient {
2511
2617
  return this.request('PATCH', ENDPOINTS.CLIP(orgId, clipId), req);
2512
2618
  }
2513
2619
 
2620
+ /** Atomically set display_name and/or description on multiple clip instances (application metadata). */
2621
+ async bulkUpdateClipMetadata(orgId: string, req: BulkUpdateClipMetadataRequest): Promise<Clip[]> {
2622
+ return this.request('POST', ENDPOINTS.CLIPS_BULK_METADATA(orgId), req);
2623
+ }
2624
+
2514
2625
  async deleteClip(orgId: string, clipId: string): Promise<void> {
2515
2626
  await this.request('DELETE', ENDPOINTS.CLIP(orgId, clipId));
2516
2627
  }
package/src/constants.ts CHANGED
@@ -347,6 +347,7 @@ export const ENDPOINTS = {
347
347
  // Org-scoped
348
348
  ORG: (orgId: string) => `${API_BASE}/orgs/${orgId}`,
349
349
  ORG_MEMBERS: (orgId: string) => `${API_BASE}/orgs/${orgId}/members`,
350
+ TEAMS: (orgId: string) => `${API_BASE}/orgs/${orgId}/teams`,
350
351
  ORG_MEMBERS_ONLINE: (orgId: string) => `${API_BASE}/orgs/${orgId}/members/online`,
351
352
  ORG_MEMBER: (orgId: string, userId: string) => `${API_BASE}/orgs/${orgId}/members/${userId}`,
352
353
  ORG_MEMBER_CHATS: (orgId: string, memberId: string) =>
@@ -409,6 +410,8 @@ export const ENDPOINTS = {
409
410
  `${API_BASE}/orgs/${orgId}/agents/${agentId}/api-keys`,
410
411
  AGENT_API_KEY: (orgId: string, agentId: string, key: string) =>
411
412
  `${API_BASE}/orgs/${orgId}/agents/${agentId}/api-keys/${key}`,
413
+ AGENT_API_KEY_REGENERATE: (orgId: string, agentId: string) =>
414
+ `${API_BASE}/orgs/${orgId}/agents/${agentId}/api-keys/regenerate`,
412
415
  AGENT_AVATAR: (orgId: string, agentId: string) =>
413
416
  `${API_BASE}/orgs/${orgId}/agents/${agentId}/avatar`,
414
417
  AGENT_ACTIVITY: (orgId: string, agentId: string) =>
@@ -479,6 +482,8 @@ export const ENDPOINTS = {
479
482
  `${API_BASE}/orgs/${orgId}/machines/${machineId}/llm-source`,
480
483
  MACHINE_PROVIDER_ENABLED: (orgId: string, machineId: string) =>
481
484
  `${API_BASE}/orgs/${orgId}/machines/${machineId}/provider-enabled`,
485
+ MACHINE_CAPABILITIES: (orgId: string, machineId: string) =>
486
+ `${API_BASE}/orgs/${orgId}/machines/${machineId}/capabilities`,
482
487
  MACHINE_RUNTIME_AUTH: (orgId: string, machineId: string) =>
483
488
  `${API_BASE}/orgs/${orgId}/machines/${machineId}/runtime-auth`,
484
489
  MACHINE_KEYS: (orgId: string, machineId: string) =>
@@ -511,6 +516,13 @@ export const ENDPOINTS = {
511
516
  MACHINES_ME_WS_TICKET: `${API_BASE}/machines/me/ws/ticket`,
512
517
  MACHINES_ME_BROWSE_RESPONSE: (requestId: string) =>
513
518
  `${API_BASE}/machines/me/browse-response/${requestId}`,
519
+ // Hosted browser live-viewer control plane (api-server, NOT clip-service):
520
+ // the web client drives WebRTC signaling + tab nav through VIEWER_COMMAND;
521
+ // api-server brokers each command to the host daemon via the machine:{id}
522
+ // request/reply bridge (mirrors filesystem browse), and the daemon replies on
523
+ // VIEWER_RESPONSE. See docs/engineering-design/hosted-browser-provider-design.md.
524
+ MACHINES_ME_BROWSER_PROFILE_VIEWER_RESPONSE: (requestId: string) =>
525
+ `${API_BASE}/machines/me/browser-profiles/viewer-response/${requestId}`,
514
526
 
515
527
  // Tasks (org-scoped)
516
528
  TASKS: (orgId: string) => `${API_BASE}/orgs/${orgId}/tasks`,
@@ -617,6 +629,11 @@ export const ENDPOINTS = {
617
629
  `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/path-scopes`,
618
630
  WIKI_PATH_SCOPE: (orgId: string, wikiId: string, scopeId: string) =>
619
631
  `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/path-scopes/${scopeId}`,
632
+ // Wiki Path Restrictions (AFCS narrowing ACL — private subtrees)
633
+ WIKI_RESTRICTIONS: (orgId: string, wikiId: string) =>
634
+ `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/restrictions`,
635
+ WIKI_RESTRICTION: (orgId: string, wikiId: string, restrictionId: string) =>
636
+ `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/restrictions/${restrictionId}`,
620
637
  WIKI_ACCESS_STATUS: (orgId: string, wikiId: string) =>
621
638
  `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/access-status`,
622
639
  WIKI_ACCESS_REQUESTS: (orgId: string, wikiId: string) =>
@@ -705,6 +722,7 @@ export const ENDPOINTS = {
705
722
  // Clips (org-scoped, served by clip-service)
706
723
  CLIPS: (orgId: string) => `${CLIP_BASE}/orgs/${orgId}/clips`,
707
724
  CLIP: (orgId: string, clipId: string) => `${CLIP_BASE}/orgs/${orgId}/clips/${clipId}`,
725
+ CLIPS_BULK_METADATA: (orgId: string) => `${CLIP_BASE}/orgs/${orgId}/clips/bulk-metadata`,
708
726
  CLIP_AGENTS: (orgId: string, clipId: string) =>
709
727
  `${CLIP_BASE}/orgs/${orgId}/clips/${clipId}/agents`,
710
728
  AGENT_CLIPS: (orgId: string, agentId: string) =>
@@ -726,6 +744,10 @@ export const ENDPOINTS = {
726
744
  `${CLIP_BASE}/orgs/${orgId}/browser-profiles/${profileId}/consents`,
727
745
  BROWSER_PROFILE_CONSENT: (orgId: string, profileId: string, clipId: string) =>
728
746
  `${CLIP_BASE}/orgs/${orgId}/browser-profiles/${profileId}/consents/${clipId}`,
747
+ // Live viewer command — on api-server (API_BASE), not clip-service: it rides
748
+ // the machine control-plane request/reply bridge that lives in api-server.
749
+ BROWSER_PROFILE_VIEWER_COMMAND: (orgId: string, profileId: string) =>
750
+ `${API_BASE}/orgs/${orgId}/browser-profiles/${profileId}/viewer/command`,
729
751
 
730
752
  // Clip registry (global, served by clip-service → Pinix Hub proxy)
731
753
  CLIP_REGISTRY: () => `${CLIP_BASE}/registry/clips`,
@@ -805,6 +827,7 @@ export const WS_EVENTS = {
805
827
  MACHINE_CONFIG_UPDATED: 'machine.config.updated',
806
828
  MACHINE_CLIP_SYNC: 'machine.clip.sync',
807
829
  MACHINE_BROWSER_PROFILE_LIFECYCLE: 'machine.browser_profile.lifecycle',
830
+ MACHINE_BROWSER_PROFILE_VIEWER: 'machine.browser_profile.viewer',
808
831
  AGENT_NEW_SESSION: 'agent.new_session',
809
832
  CLIP_CREATED: 'clip.created',
810
833
  CLIP_REMOVED: 'clip.removed',
package/src/types.ts CHANGED
@@ -362,6 +362,17 @@ export interface OrgMember {
362
362
  user?: User;
363
363
  }
364
364
 
365
+ // Team — a named group of org members, referenced in wiki ACLs as `@slug`.
366
+ export interface Team {
367
+ id: string;
368
+ org_id: string;
369
+ name: string;
370
+ slug: string;
371
+ created_by: string;
372
+ created_at: string;
373
+ updated_at: string;
374
+ }
375
+
365
376
  // Invitation
366
377
 
367
378
  export type InvitationStatus = 'pending' | 'accepted' | 'declined' | 'revoked';
@@ -441,11 +452,11 @@ export interface CreateInvitationRequest {
441
452
  role?: OrgMemberRole;
442
453
  }
443
454
 
455
+ // Response of agent API key create/regenerate. The plaintext `api_key` is
456
+ // returned exactly once at mint time and can never be fetched again.
444
457
  export interface ApiKey {
445
458
  id: string;
446
- key: string;
447
- agent_id: string;
448
- created_at: string;
459
+ api_key: string;
449
460
  }
450
461
 
451
462
  export interface CreateAgentResponse {
@@ -708,6 +719,10 @@ export type MachineStatus =
708
719
  | 'error'
709
720
  | 'terminated';
710
721
 
722
+ // What a Machine can provide. Composable (a BYOC daemon is typically both) and
723
+ // orthogonal to compute_mode. See hosted-browser-provider-design.md.
724
+ export type MachineCapability = 'agent_host' | 'browser_provider';
725
+
711
726
  export interface Machine {
712
727
  id: string;
713
728
  org_id: string;
@@ -725,6 +740,13 @@ export interface Machine {
725
740
  daemon_mode: boolean;
726
741
  llm_source?: string;
727
742
  compute_mode: 'hosted' | 'local';
743
+ // What this machine can provide — composable and orthogonal to compute_mode
744
+ // (which is lifecycle handoff, not BYOC/role). A BYOC daemon is typically
745
+ // agent_host + browser_provider; a hosted browser provider pod is browser-only.
746
+ // Filter agent-host pickers by includes('agent_host') — never by excluding
747
+ // 'browser_provider'. Absent on servers predating the field. See
748
+ // docs/engineering-design/hosted-browser-provider-design.md.
749
+ capabilities?: MachineCapability[];
728
750
  // Whether the machine contributes its local clips as a hub provider
729
751
  // (org-admin-toggleable via PATCH /machines/{id}/provider-enabled). Absent on
730
752
  // servers predating the field → treat as true (default-on). See
@@ -929,6 +951,21 @@ export interface MachineBrowserProfileLifecycleData {
929
951
  start_url?: string;
930
952
  }
931
953
 
954
+ /**
955
+ * Live-viewer control command relayed to the host daemon over `machine:{id}`.
956
+ * One command per WebRTC signaling / tab-nav step; the daemon replies via
957
+ * `POST /machines/me/browser-profiles/viewer-response/{request_id}`.
958
+ */
959
+ export interface MachineBrowserProfileViewerData {
960
+ request_id: string;
961
+ profile_id: string;
962
+ session_id: string;
963
+ command: string;
964
+ input?: Record<string, unknown>;
965
+ /** Short-lived managed TURN/ICE credentials, minted server-side per stream.start. */
966
+ turn?: { url: string; username?: string; credential?: string };
967
+ }
968
+
932
969
  export interface AgentNewSessionData {
933
970
  previous_session_id?: string;
934
971
  }
@@ -1370,6 +1407,10 @@ export interface WikiNodeSection {
1370
1407
  start_line: number;
1371
1408
  end_line: number;
1372
1409
  content: string;
1410
+ /** Frontmatter metadata (OKF-inspired, file-level, all optional). */
1411
+ type?: string;
1412
+ description?: string;
1413
+ tags?: string[];
1373
1414
  }
1374
1415
 
1375
1416
  export interface WikiNodeSectionArtifact {
@@ -1506,15 +1547,24 @@ export interface CreateWikiRequest {
1506
1547
  default_branch?: string;
1507
1548
  }
1508
1549
 
1550
+ export interface WikiFileChangeInput {
1551
+ path: string;
1552
+ action: 'create' | 'update' | 'delete';
1553
+ content_base64?: string;
1554
+ base_version?: number;
1555
+ /**
1556
+ * Git blob SHA of the default-branch version this change was authored
1557
+ * against. When set on update/delete, the server rejects the changeset
1558
+ * with 409 STALE_BASE if the file has since changed on the default branch
1559
+ * (prevents silently overwriting concurrent edits).
1560
+ */
1561
+ base_sha?: string;
1562
+ }
1563
+
1509
1564
  export interface CreateWikiChangesetRequest {
1510
1565
  title: string;
1511
1566
  message?: string;
1512
- file_changes: Array<{
1513
- path: string;
1514
- action: 'create' | 'update' | 'delete';
1515
- content_base64?: string;
1516
- base_version?: number;
1517
- }>;
1567
+ file_changes: WikiFileChangeInput[];
1518
1568
  source_chat_id?: string;
1519
1569
  source_message_id?: string;
1520
1570
  source_run_id?: string;
@@ -1523,12 +1573,15 @@ export interface CreateWikiChangesetRequest {
1523
1573
  export interface UpdateWikiChangesetRequest {
1524
1574
  title?: string;
1525
1575
  message?: string;
1526
- file_changes?: Array<{
1527
- path: string;
1528
- action: 'create' | 'update' | 'delete';
1529
- content_base64?: string;
1530
- base_version?: number;
1531
- }>;
1576
+ file_changes?: WikiFileChangeInput[];
1577
+ /**
1578
+ * When true, file_changes define the changeset's FULL content: the server
1579
+ * resets the feature branch to the current default-branch HEAD before
1580
+ * applying, so previously-proposed changes that are not re-sent are
1581
+ * dropped. Used by CLI re-propose (`changeset create --update`). Default
1582
+ * false preserves incremental merge semantics (binary-upload flow).
1583
+ */
1584
+ replace_files?: boolean;
1532
1585
  }
1533
1586
 
1534
1587
  export interface WikiCommit {
@@ -1572,11 +1625,42 @@ export interface CreateWikiPathScopeRequest {
1572
1625
  admins?: unknown;
1573
1626
  }
1574
1627
 
1628
+ // Narrowing ACL layer — gates a path subtree to `subjects`. Org owners/admins
1629
+ // are bound for CONTENT access too, and must be listed to view/edit restricted
1630
+ // content. They always keep rule management so they can add themselves, edit, or
1631
+ // delete the rule. `apply_to_admins` is retained for wire/data compatibility.
1632
+ // `level: read` = fully private folder. See authorization-design.md § Wiki.
1633
+ export interface WikiPathRestriction {
1634
+ id: string;
1635
+ wiki_id: string;
1636
+ path: string;
1637
+ level: 'read' | 'maintain' | 'admin';
1638
+ subjects: string[];
1639
+ apply_to_admins: boolean;
1640
+ created_by: string;
1641
+ created_at: string;
1642
+ }
1643
+
1644
+ export interface CreateWikiPathRestrictionRequest {
1645
+ path: string;
1646
+ level?: 'read' | 'maintain' | 'admin';
1647
+ subjects: string[];
1648
+ apply_to_admins?: boolean;
1649
+ }
1650
+
1575
1651
  export interface WikiAccessStatus {
1576
1652
  path: string;
1577
1653
  read: boolean;
1578
1654
  maintain: boolean;
1579
1655
  admin: boolean;
1656
+ // Management-surface capability on the requested path: true for org
1657
+ // owners/admins regardless of content restrictions (which narrow content
1658
+ // access above, never rule management). Gates the Activity tab (root-scoped
1659
+ // operation log).
1660
+ acl_manage: boolean;
1661
+ // True when the caller can administer at least one path in the wiki —
1662
+ // includes delegated sub-tree admins. Gates the Access tab.
1663
+ acl_manage_any: boolean;
1580
1664
  }
1581
1665
 
1582
1666
  export interface CreateWikiAccessRequest {
@@ -2157,6 +2241,7 @@ export type WsEventMap = {
2157
2241
  'machine.update': MachineUpdateData;
2158
2242
  'machine.clip.sync': MachineClipSyncData;
2159
2243
  'machine.browser_profile.lifecycle': MachineBrowserProfileLifecycleData;
2244
+ 'machine.browser_profile.viewer': MachineBrowserProfileViewerData;
2160
2245
  'clip.created': ClipCreatedData;
2161
2246
  'clip.removed': ClipRemovedData;
2162
2247
  'clip.updated': ClipUpdatedData;
@@ -2648,6 +2733,8 @@ export interface CreateClipRequest {
2648
2733
  }
2649
2734
 
2650
2735
  export interface UpdateClipRequest {
2736
+ /** Rename the clip's org-local alias; uniqueness enforced per org. */
2737
+ alias?: string;
2651
2738
  name?: string;
2652
2739
  display_name?: string;
2653
2740
  description?: string;
@@ -2659,6 +2746,18 @@ export interface UpdateClipRequest {
2659
2746
  browser_profile_id?: string;
2660
2747
  }
2661
2748
 
2749
+ /**
2750
+ * Atomically set application-level metadata (`display_name` and/or
2751
+ * `description`) on every clip instance of an application. All-or-nothing on the
2752
+ * server (one transaction). At least one field must be present; omitted leaves
2753
+ * it unchanged, an empty `description` clears it.
2754
+ */
2755
+ export interface BulkUpdateClipMetadataRequest {
2756
+ clip_ids: string[];
2757
+ display_name?: string;
2758
+ description?: string;
2759
+ }
2760
+
2662
2761
  export interface BindAgentClipRequest {
2663
2762
  clip_id: string;
2664
2763
  config?: Record<string, unknown>;
@@ -2722,6 +2821,44 @@ export interface BrowserProfileLifecycleRequest {
2722
2821
  start_url?: string;
2723
2822
  }
2724
2823
 
2824
+ /** A WebRTC ICE server (STUN/TURN) for the live-viewer peer connection. */
2825
+ export interface BrowserViewerIceServer {
2826
+ urls: string[];
2827
+ username?: string;
2828
+ credential?: string;
2829
+ }
2830
+
2831
+ /** A serialized ICE candidate exchanged during live-viewer signaling. */
2832
+ export interface BrowserViewerIceCandidate {
2833
+ candidate: string;
2834
+ sdpMLineIndex?: number | null;
2835
+ sdpMid?: string | null;
2836
+ }
2837
+
2838
+ /**
2839
+ * One live-viewer control command. The web client drives the WebRTC handshake
2840
+ * (`stream.start` → `stream.answer` → `stream.close`/`stream.switch`) and tab
2841
+ * navigation (`tab_list`/`tab_new`/`open`/`reload`/`back`/`forward`) through a
2842
+ * single endpoint; api-server forwards `command` to the host daemon.
2843
+ */
2844
+ export interface BrowserViewerCommandRequest {
2845
+ /** Correlates a viewer session. Omit on `stream.start`; the server returns one. */
2846
+ session_id?: string;
2847
+ command: string;
2848
+ input?: Record<string, unknown>;
2849
+ }
2850
+
2851
+ export interface BrowserViewerCommandResponse {
2852
+ session_id: string;
2853
+ /**
2854
+ * Command-specific result. For `stream.start`:
2855
+ * `{ offer_sdp: string, candidates: BrowserViewerIceCandidate[], ice_servers: BrowserViewerIceServer[] }`.
2856
+ * May be `null` on the wire — a nil Go result map serializes as JSON null; the
2857
+ * viewer client coalesces it to `{}`.
2858
+ */
2859
+ result: Record<string, unknown> | null;
2860
+ }
2861
+
2725
2862
  export interface GrantBrowserProfileConsentRequest {
2726
2863
  clip_id: string;
2727
2864
  }
@@ -2820,6 +2957,10 @@ export interface SearchWikiResult {
2820
2957
  heading_path: string[];
2821
2958
  content_snippet: string;
2822
2959
  score: number;
2960
+ /** Frontmatter document type (OKF facet label), when the file declares one. */
2961
+ type?: string;
2962
+ /** Frontmatter summary; clients may prefer it over content_snippet. */
2963
+ description?: string;
2823
2964
  }
2824
2965
 
2825
2966
  export interface SearchResponse {