@parall/sdk 1.34.0 → 1.36.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/dist/client.d.ts +97 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +177 -8
- package/dist/constants.d.ts +19 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +28 -0
- package/dist/types.d.ts +343 -21
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/client.ts +338 -12
- package/src/constants.ts +41 -0
- package/src/types.ts +398 -20
package/src/client.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ENDPOINTS } from './constants.js';
|
|
1
|
+
import { ENDPOINTS, WIKI_BASE } from './constants.js';
|
|
2
2
|
import type {
|
|
3
3
|
AuthTokens,
|
|
4
4
|
AvatarUploadResponse,
|
|
@@ -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,
|
|
@@ -68,6 +70,19 @@ import type {
|
|
|
68
70
|
UpdateScheduleInput,
|
|
69
71
|
ScheduleFilters,
|
|
70
72
|
ScheduleRunFilters,
|
|
73
|
+
ExternalConnection,
|
|
74
|
+
CreateExternalConnectionInput,
|
|
75
|
+
UpdateExternalConnectionInput,
|
|
76
|
+
ExternalConnectionFilters,
|
|
77
|
+
ExternalIngressEvent,
|
|
78
|
+
ExternalIngressEventFilters,
|
|
79
|
+
ExternalTrigger,
|
|
80
|
+
CreateExternalTriggerInput,
|
|
81
|
+
UpdateExternalTriggerInput,
|
|
82
|
+
ExternalTriggerFilters,
|
|
83
|
+
ExternalTriggerRun,
|
|
84
|
+
ExternalTriggerRunFilters,
|
|
85
|
+
ExternalTriggerSchema,
|
|
71
86
|
AgentSessionDB,
|
|
72
87
|
AgentStep,
|
|
73
88
|
CreateAgentSessionRequest,
|
|
@@ -103,6 +118,8 @@ import type {
|
|
|
103
118
|
CreateWikiChangesetRequest,
|
|
104
119
|
UpdateWikiChangesetRequest,
|
|
105
120
|
CreateWikiPathScopeRequest,
|
|
121
|
+
WikiPathRestriction,
|
|
122
|
+
CreateWikiPathRestrictionRequest,
|
|
106
123
|
CreateWikiAccessRequest,
|
|
107
124
|
Comment,
|
|
108
125
|
CreateCommentRequest,
|
|
@@ -148,6 +165,7 @@ import type {
|
|
|
148
165
|
AgentClip,
|
|
149
166
|
CreateClipRequest,
|
|
150
167
|
UpdateClipRequest,
|
|
168
|
+
BulkUpdateClipMetadataRequest,
|
|
151
169
|
BindAgentClipRequest,
|
|
152
170
|
InvokeClipRequest,
|
|
153
171
|
InvokeClipResponse,
|
|
@@ -155,16 +173,28 @@ import type {
|
|
|
155
173
|
RegistryClipInfo,
|
|
156
174
|
MachineClip,
|
|
157
175
|
BrowserProfile,
|
|
176
|
+
BrowserProfileListItem,
|
|
158
177
|
BrowserProfileStatus,
|
|
159
178
|
BrowserProfileConsent,
|
|
160
179
|
CreateBrowserProfileRequest,
|
|
161
180
|
UpdateBrowserProfileRequest,
|
|
162
181
|
BrowserProfileLifecycleRequest,
|
|
182
|
+
BrowserViewerCommandRequest,
|
|
183
|
+
BrowserViewerCommandResponse,
|
|
163
184
|
GrantBrowserProfileConsentRequest,
|
|
164
185
|
} from './types.js';
|
|
165
186
|
|
|
166
187
|
export interface ParallClientOptions {
|
|
167
188
|
baseUrl?: string;
|
|
189
|
+
/**
|
|
190
|
+
* Base URL for wiki-service endpoints (paths under `/wiki/v1`). Defaults to
|
|
191
|
+
* `baseUrl`. Wiki endpoints are served by a separate service from the rest of
|
|
192
|
+
* the API; in staging/prod one gateway fronts both (so `baseUrl` alone is
|
|
193
|
+
* correct), but local dev runs api-server (:8080) and wiki-service (:8090)
|
|
194
|
+
* separately. Set this so wiki calls reach wiki-service while everything else
|
|
195
|
+
* (chat, tasks, comments, refs) keeps using `baseUrl`.
|
|
196
|
+
*/
|
|
197
|
+
wikiBaseUrl?: string;
|
|
168
198
|
token?: string;
|
|
169
199
|
onTokenExpired?: () => void;
|
|
170
200
|
getRefreshToken?: () => string | null;
|
|
@@ -174,6 +204,7 @@ export interface ParallClientOptions {
|
|
|
174
204
|
|
|
175
205
|
export class ParallClient {
|
|
176
206
|
private baseUrl: string;
|
|
207
|
+
private wikiBaseUrl: string;
|
|
177
208
|
private token: string | null;
|
|
178
209
|
private onTokenExpired?: () => void;
|
|
179
210
|
private getRefreshToken?: () => string | null;
|
|
@@ -235,6 +266,10 @@ export class ParallClient {
|
|
|
235
266
|
|
|
236
267
|
constructor(options: ParallClientOptions = {}) {
|
|
237
268
|
this.baseUrl = options.baseUrl ?? '';
|
|
269
|
+
// Defaults to baseUrl so existing single-origin consumers (web, desktop,
|
|
270
|
+
// hosted agents behind one gateway) are unchanged; only split api/wiki
|
|
271
|
+
// deployments (local dev) need to set it.
|
|
272
|
+
this.wikiBaseUrl = options.wikiBaseUrl ?? this.baseUrl;
|
|
238
273
|
this.token = options.token ?? null;
|
|
239
274
|
this.onTokenExpired = options.onTokenExpired;
|
|
240
275
|
this.getRefreshToken = options.getRefreshToken;
|
|
@@ -242,6 +277,16 @@ export class ParallClient {
|
|
|
242
277
|
this.swimlaneName = options.swimlaneName;
|
|
243
278
|
}
|
|
244
279
|
|
|
280
|
+
/**
|
|
281
|
+
* Pick the origin for a request path: wiki-service base for `/wiki/v1`
|
|
282
|
+
* endpoints, api base for everything else. The path itself (from ENDPOINTS)
|
|
283
|
+
* is authoritative, so wiki vs api routing can't drift from how a caller
|
|
284
|
+
* happens to invoke the client.
|
|
285
|
+
*/
|
|
286
|
+
private baseUrlFor(path: string): string {
|
|
287
|
+
return path.startsWith(WIKI_BASE) ? this.wikiBaseUrl : this.baseUrl;
|
|
288
|
+
}
|
|
289
|
+
|
|
245
290
|
setToken(token: string | null) {
|
|
246
291
|
this.token = token;
|
|
247
292
|
}
|
|
@@ -312,14 +357,14 @@ export class ParallClient {
|
|
|
312
357
|
body?: unknown,
|
|
313
358
|
query?: Record<string, string | number | boolean | undefined>,
|
|
314
359
|
retried = false,
|
|
315
|
-
opts?: { timeoutMs?: number; signal?: AbortSignal },
|
|
360
|
+
opts?: { timeoutMs?: number; signal?: AbortSignal; keepalive?: boolean },
|
|
316
361
|
): Promise<T> {
|
|
317
362
|
// Proactive refresh: block until token is fresh (no-op if still valid)
|
|
318
363
|
if (!retried) {
|
|
319
364
|
await this.ensureFreshToken(path);
|
|
320
365
|
}
|
|
321
366
|
|
|
322
|
-
let url = `${this.
|
|
367
|
+
let url = `${this.baseUrlFor(path)}${path}`;
|
|
323
368
|
|
|
324
369
|
if (query) {
|
|
325
370
|
const params = new URLSearchParams();
|
|
@@ -349,6 +394,9 @@ export class ParallClient {
|
|
|
349
394
|
headers,
|
|
350
395
|
body: body ? JSON.stringify(body) : undefined,
|
|
351
396
|
signal,
|
|
397
|
+
// keepalive lets a request fired during page unload (e.g. the browser
|
|
398
|
+
// viewer's stream.close on pagehide) outlive the document.
|
|
399
|
+
keepalive: opts?.keepalive,
|
|
352
400
|
});
|
|
353
401
|
} catch (err) {
|
|
354
402
|
throw ParallClient.normalizeFetchError(err);
|
|
@@ -409,7 +457,7 @@ export class ParallClient {
|
|
|
409
457
|
|
|
410
458
|
let res: Response;
|
|
411
459
|
try {
|
|
412
|
-
res = await fetch(`${this.
|
|
460
|
+
res = await fetch(`${this.baseUrlFor(path)}${path}`, {
|
|
413
461
|
method,
|
|
414
462
|
headers,
|
|
415
463
|
body,
|
|
@@ -580,6 +628,11 @@ export class ParallClient {
|
|
|
580
628
|
return res.data;
|
|
581
629
|
}
|
|
582
630
|
|
|
631
|
+
async getTeams(orgId: string): Promise<Team[]> {
|
|
632
|
+
const res = await this.request<{ data: Team[] }>('GET', ENDPOINTS.TEAMS(orgId));
|
|
633
|
+
return res.data;
|
|
634
|
+
}
|
|
635
|
+
|
|
583
636
|
async getOnlineMembers(orgId: string): Promise<string[]> {
|
|
584
637
|
const res = await this.request<{ user_ids: string[] }>(
|
|
585
638
|
'GET',
|
|
@@ -639,6 +692,22 @@ export class ParallClient {
|
|
|
639
692
|
);
|
|
640
693
|
}
|
|
641
694
|
|
|
695
|
+
// Auto-paginated variant of getMemberTasks: fetches ALL pending tasks
|
|
696
|
+
// (todo + in_progress) assigned to a member, including subtasks (the
|
|
697
|
+
// endpoint does not filter parent_id). Powers the CLI `tasks assigned`
|
|
698
|
+
// command so an agent answering "what's on X's plate" sees the full
|
|
699
|
+
// backlog, not just the first page.
|
|
700
|
+
async getMemberTasksAll(orgId: string, memberId: string): Promise<Task[]> {
|
|
701
|
+
const all: Task[] = [];
|
|
702
|
+
let cursor: string | undefined;
|
|
703
|
+
do {
|
|
704
|
+
const res = await this.getMemberTasks(orgId, memberId, { cursor, limit: 100 });
|
|
705
|
+
all.push(...res.data);
|
|
706
|
+
cursor = res.has_more ? res.next_cursor : undefined;
|
|
707
|
+
} while (cursor);
|
|
708
|
+
return all;
|
|
709
|
+
}
|
|
710
|
+
|
|
642
711
|
// ---- Invitations ----
|
|
643
712
|
|
|
644
713
|
async createInvitation(
|
|
@@ -1007,6 +1076,11 @@ export class ParallClient {
|
|
|
1007
1076
|
return this.request('POST', ENDPOINTS.AGENT_API_KEYS(orgId, agentId));
|
|
1008
1077
|
}
|
|
1009
1078
|
|
|
1079
|
+
/** Revokes all of the agent's active API keys and mints a replacement. */
|
|
1080
|
+
async regenerateAgentApiKey(orgId: string, agentId: string): Promise<ApiKey> {
|
|
1081
|
+
return this.request('POST', ENDPOINTS.AGENT_API_KEY_REGENERATE(orgId, agentId));
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1010
1084
|
async revokeAgentApiKey(orgId: string, agentId: string, key: string): Promise<void> {
|
|
1011
1085
|
return this.request('DELETE', ENDPOINTS.AGENT_API_KEY(orgId, agentId, key));
|
|
1012
1086
|
}
|
|
@@ -1254,7 +1328,15 @@ export class ParallClient {
|
|
|
1254
1328
|
*/
|
|
1255
1329
|
async createMachine(
|
|
1256
1330
|
orgId: string,
|
|
1257
|
-
opts: {
|
|
1331
|
+
opts: {
|
|
1332
|
+
label?: string;
|
|
1333
|
+
compute_mode: 'local';
|
|
1334
|
+
llm_source?: 'parall' | 'runtime_auth';
|
|
1335
|
+
// Omit for the default BYOC daemon (agent_host + browser_provider). Pass an
|
|
1336
|
+
// explicit set for a single-purpose host, e.g. ['browser_provider'] for a
|
|
1337
|
+
// platform-hosted bb-browser + Chromium provider.
|
|
1338
|
+
capabilities?: MachineCapability[];
|
|
1339
|
+
},
|
|
1258
1340
|
): Promise<{
|
|
1259
1341
|
machine: Machine;
|
|
1260
1342
|
machine_key: string;
|
|
@@ -1338,6 +1420,22 @@ export class ParallClient {
|
|
|
1338
1420
|
});
|
|
1339
1421
|
}
|
|
1340
1422
|
|
|
1423
|
+
/**
|
|
1424
|
+
* Replace the machine's capability set (admin). Primary use: healing a
|
|
1425
|
+
* machine that registered without `browser_provider` during the capability
|
|
1426
|
+
* migration's rolling-deploy window. Removing `agent_host` is rejected by the
|
|
1427
|
+
* server while agents are attached (409 AGENTS_STILL_ATTACHED).
|
|
1428
|
+
*/
|
|
1429
|
+
async patchMachineCapabilities(
|
|
1430
|
+
orgId: string,
|
|
1431
|
+
machineId: string,
|
|
1432
|
+
capabilities: MachineCapability[],
|
|
1433
|
+
): Promise<Machine> {
|
|
1434
|
+
return this.request('PATCH', ENDPOINTS.MACHINE_CAPABILITIES(orgId, machineId), {
|
|
1435
|
+
capabilities,
|
|
1436
|
+
});
|
|
1437
|
+
}
|
|
1438
|
+
|
|
1341
1439
|
/** Get machine-level runtime auth state. */
|
|
1342
1440
|
async getMachineRuntimeAuth(orgId: string, machineId: string): Promise<MachineRuntimeAuthState> {
|
|
1343
1441
|
return this.request('GET', ENDPOINTS.MACHINE_RUNTIME_AUTH(orgId, machineId));
|
|
@@ -1483,6 +1581,43 @@ export class ParallClient {
|
|
|
1483
1581
|
return this.request('POST', ENDPOINTS.MACHINES_ME_BROWSE_RESPONSE(requestId), response);
|
|
1484
1582
|
}
|
|
1485
1583
|
|
|
1584
|
+
/**
|
|
1585
|
+
* `POST /machines/me/browser-profiles/viewer-response/{requestId}` — daemon
|
|
1586
|
+
* reply to a `machine.browser_profile.viewer` control command. Wakes the
|
|
1587
|
+
* api-server request/reply bridge (mirrors {@link postBrowseResponse}).
|
|
1588
|
+
*/
|
|
1589
|
+
async postBrowserProfileViewerResponse(
|
|
1590
|
+
requestId: string,
|
|
1591
|
+
response: { result?: Record<string, unknown>; error?: { message: string } },
|
|
1592
|
+
): Promise<void> {
|
|
1593
|
+
return this.request(
|
|
1594
|
+
'POST',
|
|
1595
|
+
ENDPOINTS.MACHINES_ME_BROWSER_PROFILE_VIEWER_RESPONSE(requestId),
|
|
1596
|
+
response,
|
|
1597
|
+
);
|
|
1598
|
+
}
|
|
1599
|
+
|
|
1600
|
+
/**
|
|
1601
|
+
* `POST /orgs/{orgId}/browser-profiles/{profileId}/viewer/command` — drive the
|
|
1602
|
+
* hosted browser live viewer (WebRTC signaling + tab nav). Authz: profile
|
|
1603
|
+
* owner or org admin. api-server brokers the command to the host daemon.
|
|
1604
|
+
*/
|
|
1605
|
+
async browserViewerCommand(
|
|
1606
|
+
orgId: string,
|
|
1607
|
+
profileId: string,
|
|
1608
|
+
req: BrowserViewerCommandRequest,
|
|
1609
|
+
opts?: { timeoutMs?: number; keepalive?: boolean },
|
|
1610
|
+
): Promise<BrowserViewerCommandResponse> {
|
|
1611
|
+
return this.request(
|
|
1612
|
+
'POST',
|
|
1613
|
+
ENDPOINTS.BROWSER_PROFILE_VIEWER_COMMAND(orgId, profileId),
|
|
1614
|
+
req,
|
|
1615
|
+
undefined,
|
|
1616
|
+
false,
|
|
1617
|
+
opts,
|
|
1618
|
+
);
|
|
1619
|
+
}
|
|
1620
|
+
|
|
1486
1621
|
async resizeMachine(
|
|
1487
1622
|
orgId: string,
|
|
1488
1623
|
machineId: string,
|
|
@@ -1666,7 +1801,7 @@ export class ParallClient {
|
|
|
1666
1801
|
* Returns null when the server responds with 304 (config unchanged).
|
|
1667
1802
|
*/
|
|
1668
1803
|
async getPlatformConfig(currentVersion?: string): Promise<PlatformConfigResponse | null> {
|
|
1669
|
-
const url = `${this.
|
|
1804
|
+
const url = `${this.baseUrlFor(ENDPOINTS.PLATFORM_CONFIG)}${ENDPOINTS.PLATFORM_CONFIG}`;
|
|
1670
1805
|
const extra: Record<string, string> = {};
|
|
1671
1806
|
if (currentVersion !== undefined) {
|
|
1672
1807
|
extra['If-None-Match'] = currentVersion;
|
|
@@ -1977,6 +2112,127 @@ export class ParallClient {
|
|
|
1977
2112
|
return this.request('GET', ENDPOINTS.SCHEDULE_RUN(orgId, runId));
|
|
1978
2113
|
}
|
|
1979
2114
|
|
|
2115
|
+
// ---- External triggers (org-scoped) ----
|
|
2116
|
+
|
|
2117
|
+
async createExternalConnection(
|
|
2118
|
+
orgId: string,
|
|
2119
|
+
input: CreateExternalConnectionInput,
|
|
2120
|
+
): Promise<ExternalConnection> {
|
|
2121
|
+
return this.request('POST', ENDPOINTS.EXTERNAL_CONNECTIONS(orgId), input);
|
|
2122
|
+
}
|
|
2123
|
+
|
|
2124
|
+
async listExternalConnections(
|
|
2125
|
+
orgId: string,
|
|
2126
|
+
filters?: ExternalConnectionFilters,
|
|
2127
|
+
): Promise<PaginatedResponse<ExternalConnection>> {
|
|
2128
|
+
return this.request(
|
|
2129
|
+
'GET',
|
|
2130
|
+
ENDPOINTS.EXTERNAL_CONNECTIONS(orgId),
|
|
2131
|
+
undefined,
|
|
2132
|
+
filters as Record<string, string | number | undefined>,
|
|
2133
|
+
);
|
|
2134
|
+
}
|
|
2135
|
+
|
|
2136
|
+
async getExternalConnection(orgId: string, connectionId: string): Promise<ExternalConnection> {
|
|
2137
|
+
return this.request('GET', ENDPOINTS.EXTERNAL_CONNECTION(orgId, connectionId));
|
|
2138
|
+
}
|
|
2139
|
+
|
|
2140
|
+
async updateExternalConnection(
|
|
2141
|
+
orgId: string,
|
|
2142
|
+
connectionId: string,
|
|
2143
|
+
patch: UpdateExternalConnectionInput,
|
|
2144
|
+
): Promise<ExternalConnection> {
|
|
2145
|
+
return this.request('PATCH', ENDPOINTS.EXTERNAL_CONNECTION(orgId, connectionId), patch);
|
|
2146
|
+
}
|
|
2147
|
+
|
|
2148
|
+
async regenerateExternalConnectionIngressToken(
|
|
2149
|
+
orgId: string,
|
|
2150
|
+
connectionId: string,
|
|
2151
|
+
): Promise<ExternalConnection> {
|
|
2152
|
+
return this.request(
|
|
2153
|
+
'POST',
|
|
2154
|
+
ENDPOINTS.EXTERNAL_CONNECTION_INGRESS_TOKEN_REGENERATE(orgId, connectionId),
|
|
2155
|
+
);
|
|
2156
|
+
}
|
|
2157
|
+
|
|
2158
|
+
async deleteExternalConnection(orgId: string, connectionId: string): Promise<void> {
|
|
2159
|
+
return this.request('DELETE', ENDPOINTS.EXTERNAL_CONNECTION(orgId, connectionId));
|
|
2160
|
+
}
|
|
2161
|
+
|
|
2162
|
+
async getExternalTriggerSchema(
|
|
2163
|
+
orgId: string,
|
|
2164
|
+
connectionId: string,
|
|
2165
|
+
): Promise<ExternalTriggerSchema> {
|
|
2166
|
+
return this.request('GET', ENDPOINTS.EXTERNAL_TRIGGER_SCHEMA(orgId, connectionId));
|
|
2167
|
+
}
|
|
2168
|
+
|
|
2169
|
+
async listExternalIngressEvents(
|
|
2170
|
+
orgId: string,
|
|
2171
|
+
filters?: ExternalIngressEventFilters,
|
|
2172
|
+
): Promise<PaginatedResponse<ExternalIngressEvent>> {
|
|
2173
|
+
return this.request(
|
|
2174
|
+
'GET',
|
|
2175
|
+
ENDPOINTS.EXTERNAL_INGRESS_EVENTS(orgId),
|
|
2176
|
+
undefined,
|
|
2177
|
+
filters as Record<string, string | number | undefined>,
|
|
2178
|
+
);
|
|
2179
|
+
}
|
|
2180
|
+
|
|
2181
|
+
async getExternalIngressEvent(orgId: string, eventId: string): Promise<ExternalIngressEvent> {
|
|
2182
|
+
return this.request('GET', ENDPOINTS.EXTERNAL_INGRESS_EVENT(orgId, eventId));
|
|
2183
|
+
}
|
|
2184
|
+
|
|
2185
|
+
async createExternalTrigger(
|
|
2186
|
+
orgId: string,
|
|
2187
|
+
input: CreateExternalTriggerInput,
|
|
2188
|
+
): Promise<ExternalTrigger> {
|
|
2189
|
+
return this.request('POST', ENDPOINTS.EXTERNAL_TRIGGERS(orgId), input);
|
|
2190
|
+
}
|
|
2191
|
+
|
|
2192
|
+
async listExternalTriggers(
|
|
2193
|
+
orgId: string,
|
|
2194
|
+
filters?: ExternalTriggerFilters,
|
|
2195
|
+
): Promise<PaginatedResponse<ExternalTrigger>> {
|
|
2196
|
+
return this.request(
|
|
2197
|
+
'GET',
|
|
2198
|
+
ENDPOINTS.EXTERNAL_TRIGGERS(orgId),
|
|
2199
|
+
undefined,
|
|
2200
|
+
filters as Record<string, string | number | undefined>,
|
|
2201
|
+
);
|
|
2202
|
+
}
|
|
2203
|
+
|
|
2204
|
+
async getExternalTrigger(orgId: string, triggerId: string): Promise<ExternalTrigger> {
|
|
2205
|
+
return this.request('GET', ENDPOINTS.EXTERNAL_TRIGGER(orgId, triggerId));
|
|
2206
|
+
}
|
|
2207
|
+
|
|
2208
|
+
async updateExternalTrigger(
|
|
2209
|
+
orgId: string,
|
|
2210
|
+
triggerId: string,
|
|
2211
|
+
patch: UpdateExternalTriggerInput,
|
|
2212
|
+
): Promise<ExternalTrigger> {
|
|
2213
|
+
return this.request('PATCH', ENDPOINTS.EXTERNAL_TRIGGER(orgId, triggerId), patch);
|
|
2214
|
+
}
|
|
2215
|
+
|
|
2216
|
+
async deleteExternalTrigger(orgId: string, triggerId: string): Promise<void> {
|
|
2217
|
+
return this.request('DELETE', ENDPOINTS.EXTERNAL_TRIGGER(orgId, triggerId));
|
|
2218
|
+
}
|
|
2219
|
+
|
|
2220
|
+
async listExternalTriggerRuns(
|
|
2221
|
+
orgId: string,
|
|
2222
|
+
filters?: ExternalTriggerRunFilters,
|
|
2223
|
+
): Promise<PaginatedResponse<ExternalTriggerRun>> {
|
|
2224
|
+
return this.request(
|
|
2225
|
+
'GET',
|
|
2226
|
+
ENDPOINTS.EXTERNAL_TRIGGER_RUNS(orgId),
|
|
2227
|
+
undefined,
|
|
2228
|
+
filters as Record<string, string | number | undefined>,
|
|
2229
|
+
);
|
|
2230
|
+
}
|
|
2231
|
+
|
|
2232
|
+
async getExternalTriggerRun(orgId: string, runId: string): Promise<ExternalTriggerRun> {
|
|
2233
|
+
return this.request('GET', ENDPOINTS.EXTERNAL_TRIGGER_RUN(orgId, runId));
|
|
2234
|
+
}
|
|
2235
|
+
|
|
1980
2236
|
// ---- Wikis (org-scoped) ----
|
|
1981
2237
|
|
|
1982
2238
|
async createWiki(orgId: string, data: CreateWikiRequest): Promise<Wiki> {
|
|
@@ -2000,12 +2256,43 @@ export class ParallClient {
|
|
|
2000
2256
|
return this.request('GET', ENDPOINTS.WIKI_TREE(orgId, wikiId), undefined, params);
|
|
2001
2257
|
}
|
|
2002
2258
|
|
|
2259
|
+
/**
|
|
2260
|
+
* Resolve a server-returned, host-relative media URL (a wiki `signed_url`
|
|
2261
|
+
* like `/wiki/v1/signed/files?token=...`) against this client's base origin,
|
|
2262
|
+
* so it can be dropped straight into a browser `<img>`/`<video>`/`<iframe>`
|
|
2263
|
+
* `src`.
|
|
2264
|
+
*
|
|
2265
|
+
* wiki-service returns these relative on purpose — it doesn't know its own
|
|
2266
|
+
* public origin. A relative `src` resolves against the *page* origin, which
|
|
2267
|
+
* only works when the page and wiki-service share an origin (local dev:
|
|
2268
|
+
* same-origin + Next.js `/wiki/*` proxy). In deployed envs the app
|
|
2269
|
+
* (app.parall.com) and wiki-service (api.parall.com) are different origins,
|
|
2270
|
+
* so `app.parall.com/wiki/v1/signed/files` hits the SPA's own `/wiki/[...]`
|
|
2271
|
+
* catch-all route — an `<iframe>` then recursively renders the whole app
|
|
2272
|
+
* instead of the file. Prefixing with the wiki base (the exact origin every
|
|
2273
|
+
* wiki API request already uses — `baseUrlFor` resolves `/wiki/v1` paths to
|
|
2274
|
+
* `wikiBaseUrl`) makes the URL absolute against the origin that actually
|
|
2275
|
+
* serves the bytes. An empty base (local dev, same-origin proxy) leaves it
|
|
2276
|
+
* relative, preserving the proxy path.
|
|
2277
|
+
*/
|
|
2278
|
+
private absoluteMediaUrl(url: string): string {
|
|
2279
|
+
if (/^https?:\/\//i.test(url)) return url; // already absolute — leave as-is
|
|
2280
|
+
return `${this.baseUrlFor(url)}${url}`;
|
|
2281
|
+
}
|
|
2282
|
+
|
|
2003
2283
|
async getWikiBlob(
|
|
2004
2284
|
orgId: string,
|
|
2005
2285
|
wikiId: string,
|
|
2006
2286
|
params: { path: string; ref?: string },
|
|
2007
2287
|
): Promise<WikiBlob> {
|
|
2008
|
-
|
|
2288
|
+
const blob = await this.request<WikiBlob>(
|
|
2289
|
+
'GET',
|
|
2290
|
+
ENDPOINTS.WIKI_BLOB(orgId, wikiId),
|
|
2291
|
+
undefined,
|
|
2292
|
+
params,
|
|
2293
|
+
);
|
|
2294
|
+
if (blob.signed_url) blob.signed_url = this.absoluteMediaUrl(blob.signed_url);
|
|
2295
|
+
return blob;
|
|
2009
2296
|
}
|
|
2010
2297
|
|
|
2011
2298
|
async getWikiNodeSections(
|
|
@@ -2018,7 +2305,9 @@ export class ParallClient {
|
|
|
2018
2305
|
|
|
2019
2306
|
async search(
|
|
2020
2307
|
orgId: string,
|
|
2021
|
-
|
|
2308
|
+
// `types` selects entities (message/task/wiki); `wiki_type` is the distinct
|
|
2309
|
+
// wiki document-type facet (frontmatter `type`) — the two never overlap.
|
|
2310
|
+
params: { q: string; types?: string; chat_id?: string; limit?: number; wiki_type?: string },
|
|
2022
2311
|
opts?: { signal?: AbortSignal },
|
|
2023
2312
|
): Promise<SearchResponse> {
|
|
2024
2313
|
return this.request('GET', ENDPOINTS.SEARCH(orgId), undefined, params, false, opts);
|
|
@@ -2027,7 +2316,8 @@ export class ParallClient {
|
|
|
2027
2316
|
async searchWiki(
|
|
2028
2317
|
orgId: string,
|
|
2029
2318
|
wikiId: string,
|
|
2030
|
-
|
|
2319
|
+
// `type` is the wiki document-type facet (frontmatter `type`).
|
|
2320
|
+
params: { q: string; limit?: number; path_prefix?: string; ref?: string; type?: string },
|
|
2031
2321
|
): Promise<WikiSearchResponse> {
|
|
2032
2322
|
return this.request('GET', ENDPOINTS.WIKI_SEARCH(orgId, wikiId), undefined, params);
|
|
2033
2323
|
}
|
|
@@ -2203,7 +2493,13 @@ export class ParallClient {
|
|
|
2203
2493
|
wikiId: string,
|
|
2204
2494
|
params: { path: string; ref?: string },
|
|
2205
2495
|
): Promise<WikiFilePreviewUrlResponse> {
|
|
2206
|
-
|
|
2496
|
+
const res = await this.request<WikiFilePreviewUrlResponse>(
|
|
2497
|
+
'POST',
|
|
2498
|
+
ENDPOINTS.WIKI_FILE_PREVIEW_URL(orgId, wikiId),
|
|
2499
|
+
params,
|
|
2500
|
+
);
|
|
2501
|
+
if (res.url) res.url = this.absoluteMediaUrl(res.url);
|
|
2502
|
+
return res;
|
|
2207
2503
|
}
|
|
2208
2504
|
|
|
2209
2505
|
// ---- Wiki Path Scopes (AFCS ACL) ----
|
|
@@ -2228,6 +2524,28 @@ export class ParallClient {
|
|
|
2228
2524
|
await this.request('DELETE', ENDPOINTS.WIKI_PATH_SCOPE(orgId, wikiId, scopeId));
|
|
2229
2525
|
}
|
|
2230
2526
|
|
|
2527
|
+
// ---- Wiki Path Restrictions (narrowing ACL — private subtrees) ----
|
|
2528
|
+
|
|
2529
|
+
async getWikiRestrictions(orgId: string, wikiId: string): Promise<WikiPathRestriction[]> {
|
|
2530
|
+
const res = await this.request<{ data: WikiPathRestriction[] }>(
|
|
2531
|
+
'GET',
|
|
2532
|
+
ENDPOINTS.WIKI_RESTRICTIONS(orgId, wikiId),
|
|
2533
|
+
);
|
|
2534
|
+
return res.data;
|
|
2535
|
+
}
|
|
2536
|
+
|
|
2537
|
+
async createWikiRestriction(
|
|
2538
|
+
orgId: string,
|
|
2539
|
+
wikiId: string,
|
|
2540
|
+
data: CreateWikiPathRestrictionRequest,
|
|
2541
|
+
): Promise<WikiPathRestriction> {
|
|
2542
|
+
return this.request('POST', ENDPOINTS.WIKI_RESTRICTIONS(orgId, wikiId), data);
|
|
2543
|
+
}
|
|
2544
|
+
|
|
2545
|
+
async deleteWikiRestriction(orgId: string, wikiId: string, restrictionId: string): Promise<void> {
|
|
2546
|
+
await this.request('DELETE', ENDPOINTS.WIKI_RESTRICTION(orgId, wikiId, restrictionId));
|
|
2547
|
+
}
|
|
2548
|
+
|
|
2231
2549
|
async getWikiAccessStatus(
|
|
2232
2550
|
orgId: string,
|
|
2233
2551
|
wikiId: string,
|
|
@@ -2511,6 +2829,11 @@ export class ParallClient {
|
|
|
2511
2829
|
return this.request('PATCH', ENDPOINTS.CLIP(orgId, clipId), req);
|
|
2512
2830
|
}
|
|
2513
2831
|
|
|
2832
|
+
/** Atomically set display_name and/or description on multiple clip instances (application metadata). */
|
|
2833
|
+
async bulkUpdateClipMetadata(orgId: string, req: BulkUpdateClipMetadataRequest): Promise<Clip[]> {
|
|
2834
|
+
return this.request('POST', ENDPOINTS.CLIPS_BULK_METADATA(orgId), req);
|
|
2835
|
+
}
|
|
2836
|
+
|
|
2514
2837
|
async deleteClip(orgId: string, clipId: string): Promise<void> {
|
|
2515
2838
|
await this.request('DELETE', ENDPOINTS.CLIP(orgId, clipId));
|
|
2516
2839
|
}
|
|
@@ -2554,8 +2877,11 @@ export class ParallClient {
|
|
|
2554
2877
|
return resp.data;
|
|
2555
2878
|
}
|
|
2556
2879
|
|
|
2557
|
-
|
|
2558
|
-
|
|
2880
|
+
/** Org-wide browser-profile discovery list. Returns the sanitized
|
|
2881
|
+
* {@link BrowserProfileListItem} shape (not the full domain model), each row
|
|
2882
|
+
* carrying a per-viewer `can_open` control hint. */
|
|
2883
|
+
async listBrowserProfiles(orgId: string): Promise<BrowserProfileListItem[]> {
|
|
2884
|
+
const resp = await this.request<{ data: BrowserProfileListItem[] }>(
|
|
2559
2885
|
'GET',
|
|
2560
2886
|
ENDPOINTS.BROWSER_PROFILES(orgId),
|
|
2561
2887
|
);
|
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`,
|
|
@@ -554,6 +566,24 @@ export const ENDPOINTS = {
|
|
|
554
566
|
SCHEDULE_RUN: (orgId: string, runId: string) =>
|
|
555
567
|
`${API_BASE}/orgs/${orgId}/schedule_runs/${runId}`,
|
|
556
568
|
|
|
569
|
+
// External triggers (org-scoped incoming integration primitive)
|
|
570
|
+
EXTERNAL_CONNECTIONS: (orgId: string) => `${API_BASE}/orgs/${orgId}/external-connections`,
|
|
571
|
+
EXTERNAL_CONNECTION: (orgId: string, connectionId: string) =>
|
|
572
|
+
`${API_BASE}/orgs/${orgId}/external-connections/${connectionId}`,
|
|
573
|
+
EXTERNAL_CONNECTION_INGRESS_TOKEN_REGENERATE: (orgId: string, connectionId: string) =>
|
|
574
|
+
`${API_BASE}/orgs/${orgId}/external-connections/${connectionId}/ingress-token/regenerate`,
|
|
575
|
+
EXTERNAL_TRIGGER_SCHEMA: (orgId: string, connectionId: string) =>
|
|
576
|
+
`${API_BASE}/orgs/${orgId}/external-connections/${connectionId}/trigger-schema`,
|
|
577
|
+
EXTERNAL_INGRESS_EVENTS: (orgId: string) => `${API_BASE}/orgs/${orgId}/external-ingress-events`,
|
|
578
|
+
EXTERNAL_INGRESS_EVENT: (orgId: string, eventId: string) =>
|
|
579
|
+
`${API_BASE}/orgs/${orgId}/external-ingress-events/${eventId}`,
|
|
580
|
+
EXTERNAL_TRIGGERS: (orgId: string) => `${API_BASE}/orgs/${orgId}/external-triggers`,
|
|
581
|
+
EXTERNAL_TRIGGER: (orgId: string, triggerId: string) =>
|
|
582
|
+
`${API_BASE}/orgs/${orgId}/external-triggers/${triggerId}`,
|
|
583
|
+
EXTERNAL_TRIGGER_RUNS: (orgId: string) => `${API_BASE}/orgs/${orgId}/external-trigger-runs`,
|
|
584
|
+
EXTERNAL_TRIGGER_RUN: (orgId: string, runId: string) =>
|
|
585
|
+
`${API_BASE}/orgs/${orgId}/external-trigger-runs/${runId}`,
|
|
586
|
+
|
|
557
587
|
// Invitations (org-scoped, admin)
|
|
558
588
|
ORG_INVITATIONS: (orgId: string) => `${API_BASE}/orgs/${orgId}/invitations`,
|
|
559
589
|
ORG_INVITATION: (orgId: string, invId: string) =>
|
|
@@ -617,6 +647,11 @@ export const ENDPOINTS = {
|
|
|
617
647
|
`${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/path-scopes`,
|
|
618
648
|
WIKI_PATH_SCOPE: (orgId: string, wikiId: string, scopeId: string) =>
|
|
619
649
|
`${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/path-scopes/${scopeId}`,
|
|
650
|
+
// Wiki Path Restrictions (AFCS narrowing ACL — private subtrees)
|
|
651
|
+
WIKI_RESTRICTIONS: (orgId: string, wikiId: string) =>
|
|
652
|
+
`${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/restrictions`,
|
|
653
|
+
WIKI_RESTRICTION: (orgId: string, wikiId: string, restrictionId: string) =>
|
|
654
|
+
`${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/restrictions/${restrictionId}`,
|
|
620
655
|
WIKI_ACCESS_STATUS: (orgId: string, wikiId: string) =>
|
|
621
656
|
`${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/access-status`,
|
|
622
657
|
WIKI_ACCESS_REQUESTS: (orgId: string, wikiId: string) =>
|
|
@@ -705,6 +740,7 @@ export const ENDPOINTS = {
|
|
|
705
740
|
// Clips (org-scoped, served by clip-service)
|
|
706
741
|
CLIPS: (orgId: string) => `${CLIP_BASE}/orgs/${orgId}/clips`,
|
|
707
742
|
CLIP: (orgId: string, clipId: string) => `${CLIP_BASE}/orgs/${orgId}/clips/${clipId}`,
|
|
743
|
+
CLIPS_BULK_METADATA: (orgId: string) => `${CLIP_BASE}/orgs/${orgId}/clips/bulk-metadata`,
|
|
708
744
|
CLIP_AGENTS: (orgId: string, clipId: string) =>
|
|
709
745
|
`${CLIP_BASE}/orgs/${orgId}/clips/${clipId}/agents`,
|
|
710
746
|
AGENT_CLIPS: (orgId: string, agentId: string) =>
|
|
@@ -726,6 +762,10 @@ export const ENDPOINTS = {
|
|
|
726
762
|
`${CLIP_BASE}/orgs/${orgId}/browser-profiles/${profileId}/consents`,
|
|
727
763
|
BROWSER_PROFILE_CONSENT: (orgId: string, profileId: string, clipId: string) =>
|
|
728
764
|
`${CLIP_BASE}/orgs/${orgId}/browser-profiles/${profileId}/consents/${clipId}`,
|
|
765
|
+
// Live viewer command — on api-server (API_BASE), not clip-service: it rides
|
|
766
|
+
// the machine control-plane request/reply bridge that lives in api-server.
|
|
767
|
+
BROWSER_PROFILE_VIEWER_COMMAND: (orgId: string, profileId: string) =>
|
|
768
|
+
`${API_BASE}/orgs/${orgId}/browser-profiles/${profileId}/viewer/command`,
|
|
729
769
|
|
|
730
770
|
// Clip registry (global, served by clip-service → Pinix Hub proxy)
|
|
731
771
|
CLIP_REGISTRY: () => `${CLIP_BASE}/registry/clips`,
|
|
@@ -805,6 +845,7 @@ export const WS_EVENTS = {
|
|
|
805
845
|
MACHINE_CONFIG_UPDATED: 'machine.config.updated',
|
|
806
846
|
MACHINE_CLIP_SYNC: 'machine.clip.sync',
|
|
807
847
|
MACHINE_BROWSER_PROFILE_LIFECYCLE: 'machine.browser_profile.lifecycle',
|
|
848
|
+
MACHINE_BROWSER_PROFILE_VIEWER: 'machine.browser_profile.viewer',
|
|
808
849
|
AGENT_NEW_SESSION: 'agent.new_session',
|
|
809
850
|
CLIP_CREATED: 'clip.created',
|
|
810
851
|
CLIP_REMOVED: 'clip.removed',
|