@parall/sdk 1.36.1 → 1.38.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 -4
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +158 -3
- package/dist/constants.d.ts +71 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +105 -8
- package/dist/types.d.ts +399 -6
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/client.ts +287 -3
- package/src/constants.ts +122 -8
- package/src/types.ts +453 -6
package/src/client.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { ENDPOINTS, WIKI_BASE } from './constants.js';
|
|
2
2
|
import type {
|
|
3
|
+
ClaimDispatchRequest,
|
|
4
|
+
ClaimDispatchResponse,
|
|
5
|
+
SteerDispatchRequest,
|
|
6
|
+
SteerDispatchResponse,
|
|
7
|
+
CompleteDispatchRequest,
|
|
8
|
+
CompleteDispatchResult,
|
|
3
9
|
AuthTokens,
|
|
4
10
|
AvatarUploadResponse,
|
|
5
11
|
RegisterRequest,
|
|
@@ -41,6 +47,7 @@ import type {
|
|
|
41
47
|
MachineRuntimeAuthState,
|
|
42
48
|
AgentWorkspaceState,
|
|
43
49
|
AgentWorkspaceReportStatus,
|
|
50
|
+
DetectedRuntime,
|
|
44
51
|
BrowseMachineFilesystemResponse,
|
|
45
52
|
FilesystemEntry,
|
|
46
53
|
DaemonAgentConfig,
|
|
@@ -74,6 +81,14 @@ import type {
|
|
|
74
81
|
CreateExternalConnectionInput,
|
|
75
82
|
UpdateExternalConnectionInput,
|
|
76
83
|
ExternalConnectionFilters,
|
|
84
|
+
ChannelConnection,
|
|
85
|
+
ChannelConversation,
|
|
86
|
+
ChannelMessage,
|
|
87
|
+
ChannelCredentialsInput,
|
|
88
|
+
ChannelProvisioningSession,
|
|
89
|
+
CreateChannelConnectionInput,
|
|
90
|
+
InitiateChannelProvisioningInput,
|
|
91
|
+
UpdateChannelConnectionInput,
|
|
77
92
|
ExternalIngressEvent,
|
|
78
93
|
ExternalIngressEventFilters,
|
|
79
94
|
ExternalTrigger,
|
|
@@ -97,6 +112,8 @@ import type {
|
|
|
97
112
|
PlatformConfigResponse,
|
|
98
113
|
Wiki,
|
|
99
114
|
WikiBlob,
|
|
115
|
+
CopyWikiFileRequest,
|
|
116
|
+
CopyWikiFileResponse,
|
|
100
117
|
WikiChangeset,
|
|
101
118
|
WikiFileUploadResponse,
|
|
102
119
|
WikiFilePreviewUrlResponse,
|
|
@@ -163,6 +180,8 @@ import type {
|
|
|
163
180
|
UpdateAutoReloadRequest,
|
|
164
181
|
ComputePricing,
|
|
165
182
|
ComputePricingResponse,
|
|
183
|
+
RuntimeCapability,
|
|
184
|
+
PlatformModelsResponse,
|
|
166
185
|
Clip,
|
|
167
186
|
AgentClip,
|
|
168
187
|
CreateClipRequest,
|
|
@@ -178,6 +197,7 @@ import type {
|
|
|
178
197
|
MachineBrowserProfile,
|
|
179
198
|
BrowserProfileListItem,
|
|
180
199
|
BrowserProfileStatus,
|
|
200
|
+
BrowserRuntimeStatus,
|
|
181
201
|
BrowserProfileConsent,
|
|
182
202
|
CreateBrowserProfileRequest,
|
|
183
203
|
UpdateBrowserProfileRequest,
|
|
@@ -360,7 +380,13 @@ export class ParallClient {
|
|
|
360
380
|
body?: unknown,
|
|
361
381
|
query?: Record<string, string | number | boolean | undefined>,
|
|
362
382
|
retried = false,
|
|
363
|
-
opts?: {
|
|
383
|
+
opts?: {
|
|
384
|
+
timeoutMs?: number;
|
|
385
|
+
signal?: AbortSignal;
|
|
386
|
+
keepalive?: boolean;
|
|
387
|
+
/** Observes the final HTTP status of a successful request (e.g. 200-idempotent-replay vs 201-created). */
|
|
388
|
+
onStatus?: (status: number) => void;
|
|
389
|
+
},
|
|
364
390
|
): Promise<T> {
|
|
365
391
|
// Proactive refresh: block until token is fresh (no-op if still valid)
|
|
366
392
|
if (!retried) {
|
|
@@ -427,6 +453,7 @@ export class ParallClient {
|
|
|
427
453
|
throw buildApiError(res, rawErrorBody);
|
|
428
454
|
}
|
|
429
455
|
|
|
456
|
+
opts?.onStatus?.(res.status);
|
|
430
457
|
if (res.status === 204) return undefined as T;
|
|
431
458
|
// 202 Accepted may have an empty body (e.g., async restart) or a JSON body.
|
|
432
459
|
if (res.status === 202) {
|
|
@@ -631,6 +658,17 @@ export class ParallClient {
|
|
|
631
658
|
return res.data;
|
|
632
659
|
}
|
|
633
660
|
|
|
661
|
+
/** User IDs of soft-removed (former) org members — for marking their avatar /
|
|
662
|
+
* name as "left" where dormant relations still surface them (DMs, task
|
|
663
|
+
* assignees, message history). */
|
|
664
|
+
async getFormerMemberIds(orgId: string): Promise<string[]> {
|
|
665
|
+
const res = await this.request<{ user_ids: string[] }>(
|
|
666
|
+
'GET',
|
|
667
|
+
ENDPOINTS.ORG_MEMBERS_FORMER(orgId),
|
|
668
|
+
);
|
|
669
|
+
return res.user_ids ?? [];
|
|
670
|
+
}
|
|
671
|
+
|
|
634
672
|
async getTeams(orgId: string): Promise<Team[]> {
|
|
635
673
|
const res = await this.request<{ data: Team[] }>('GET', ENDPOINTS.TEAMS(orgId));
|
|
636
674
|
return res.data;
|
|
@@ -944,6 +982,33 @@ export class ParallClient {
|
|
|
944
982
|
return this.request('POST', ENDPOINTS.CHAT_MESSAGES(orgId, chatId), req);
|
|
945
983
|
}
|
|
946
984
|
|
|
985
|
+
/**
|
|
986
|
+
* sendMessage variant that also reports whether the server answered with an
|
|
987
|
+
* idempotent replay (HTTP 200 — the message already existed for this
|
|
988
|
+
* idempotency/effect key) instead of a fresh create (201). Used by the CLI
|
|
989
|
+
* to surface "already sent by a previous run (deduplicated)".
|
|
990
|
+
*/
|
|
991
|
+
async sendMessageDetailed(
|
|
992
|
+
orgId: string,
|
|
993
|
+
chatId: string,
|
|
994
|
+
req: SendMessageRequest,
|
|
995
|
+
): Promise<{ message: Message; deduplicated: boolean }> {
|
|
996
|
+
let status = 0;
|
|
997
|
+
const message = await this.request<Message>(
|
|
998
|
+
'POST',
|
|
999
|
+
ENDPOINTS.CHAT_MESSAGES(orgId, chatId),
|
|
1000
|
+
req,
|
|
1001
|
+
undefined,
|
|
1002
|
+
false,
|
|
1003
|
+
{
|
|
1004
|
+
onStatus: (s) => {
|
|
1005
|
+
status = s;
|
|
1006
|
+
},
|
|
1007
|
+
},
|
|
1008
|
+
);
|
|
1009
|
+
return { message, deduplicated: status === 200 };
|
|
1010
|
+
}
|
|
1011
|
+
|
|
947
1012
|
async getMessages(
|
|
948
1013
|
orgId: string,
|
|
949
1014
|
chatId: string,
|
|
@@ -1515,29 +1580,40 @@ export class ParallClient {
|
|
|
1515
1580
|
profileId: string,
|
|
1516
1581
|
status: BrowserProfileStatus,
|
|
1517
1582
|
errorMsg?: string,
|
|
1583
|
+
// The lifecycle generation this report was issued under (captured at op start,
|
|
1584
|
+
// PR #1650). Omitted by pre-generation callers; the server then falls back to
|
|
1585
|
+
// safe-state compatibility. The server no-ops a report older than the row's.
|
|
1586
|
+
generation?: number,
|
|
1518
1587
|
): Promise<void> {
|
|
1519
1588
|
await this.request('POST', ENDPOINTS.MACHINES_ME_BROWSER_PROFILE_STATUS(profileId), {
|
|
1520
1589
|
status,
|
|
1521
1590
|
...(errorMsg ? { error_msg: errorMsg } : {}),
|
|
1591
|
+
...(generation !== undefined ? { generation } : {}),
|
|
1522
1592
|
});
|
|
1523
1593
|
}
|
|
1524
1594
|
|
|
1525
1595
|
/**
|
|
1526
1596
|
* `POST /machines/me/health` — bump the Machine's `updated_at` to now and
|
|
1527
|
-
* report daemon state. The daemon
|
|
1528
|
-
*
|
|
1597
|
+
* report daemon state. The daemon calls this on startup and again whenever
|
|
1598
|
+
* periodic runtime re-detection produces a CHANGED result (there is no
|
|
1599
|
+
* fixed-cadence keepalive loop today — steady state posts nothing). All
|
|
1529
1600
|
* fields are optional and only persisted when changed:
|
|
1530
1601
|
* - `daemonVersion` — the running bundle/launcher version.
|
|
1531
1602
|
* - `selfUpdateCapable` — whether the daemon can act on a machine.update
|
|
1532
1603
|
* signal (true under a service manager, false for bare `npx` foreground).
|
|
1604
|
+
* - `detectedRuntimes` — runtime CLIs found on the host. Omitted = no
|
|
1605
|
+
* report this beat (server keeps the stored value); [] = detection ran
|
|
1606
|
+
* and found nothing (server clears to empty).
|
|
1533
1607
|
*/
|
|
1534
1608
|
async postMachineHeartbeat(opts?: {
|
|
1535
1609
|
daemonVersion?: string;
|
|
1536
1610
|
selfUpdateCapable?: boolean;
|
|
1611
|
+
detectedRuntimes?: DetectedRuntime[];
|
|
1537
1612
|
}): Promise<void> {
|
|
1538
1613
|
const body: Record<string, unknown> = {};
|
|
1539
1614
|
if (opts?.daemonVersion) body.daemon_version = opts.daemonVersion;
|
|
1540
1615
|
if (opts?.selfUpdateCapable !== undefined) body.self_update_capable = opts.selfUpdateCapable;
|
|
1616
|
+
if (opts?.detectedRuntimes !== undefined) body.detected_runtimes = opts.detectedRuntimes;
|
|
1541
1617
|
return this.request(
|
|
1542
1618
|
'POST',
|
|
1543
1619
|
ENDPOINTS.MACHINES_ME_HEALTH,
|
|
@@ -1785,6 +1861,41 @@ export class ParallClient {
|
|
|
1785
1861
|
return this.request('POST', ENDPOINTS.DISPATCH_EXPIRE(orgId), undefined, params);
|
|
1786
1862
|
}
|
|
1787
1863
|
|
|
1864
|
+
/**
|
|
1865
|
+
* Claim a dispatch lane (explicit consume endpoint). Occupies the
|
|
1866
|
+
* (agent, target, thread) lane and folds claimable WorkItems into it;
|
|
1867
|
+
* `claimed: false` means a healthy incumbent holds the lane.
|
|
1868
|
+
*/
|
|
1869
|
+
async claimDispatch(orgId: string, req: ClaimDispatchRequest): Promise<ClaimDispatchResponse> {
|
|
1870
|
+
return this.request('POST', ENDPOINTS.DISPATCH_CLAIM(orgId), req);
|
|
1871
|
+
}
|
|
1872
|
+
|
|
1873
|
+
/** Fold a pending same-target WorkItem into a live lane (409 STALE_LANE when dethroned). */
|
|
1874
|
+
async steerDispatch(orgId: string, req: SteerDispatchRequest): Promise<SteerDispatchResponse> {
|
|
1875
|
+
return this.request('POST', ENDPOINTS.DISPATCH_STEER(orgId), req);
|
|
1876
|
+
}
|
|
1877
|
+
|
|
1878
|
+
/** End a turn: no_action sweep of the lane's members + lane release + re-drive check. */
|
|
1879
|
+
async completeDispatch(
|
|
1880
|
+
orgId: string,
|
|
1881
|
+
req: CompleteDispatchRequest,
|
|
1882
|
+
): Promise<CompleteDispatchResult> {
|
|
1883
|
+
return this.request('POST', ENDPOINTS.DISPATCH_COMPLETE(orgId), req);
|
|
1884
|
+
}
|
|
1885
|
+
|
|
1886
|
+
/** Release a lane on graceful shutdown — members return to pending immediately. */
|
|
1887
|
+
async releaseDispatchLane(orgId: string, lane: string): Promise<void> {
|
|
1888
|
+
return this.request('POST', ENDPOINTS.DISPATCH_RELEASE(orgId), { lane });
|
|
1889
|
+
}
|
|
1890
|
+
|
|
1891
|
+
/** Renew a live lane's lease (long-turn keepalive). 409 STALE_LANE when dethroned. */
|
|
1892
|
+
async heartbeatDispatchLane(
|
|
1893
|
+
orgId: string,
|
|
1894
|
+
req: { lane: string; target_uri: string; thread_root_id?: string },
|
|
1895
|
+
): Promise<{ lease_until?: string }> {
|
|
1896
|
+
return this.request('POST', ENDPOINTS.DISPATCH_HEARTBEAT(orgId), req);
|
|
1897
|
+
}
|
|
1898
|
+
|
|
1788
1899
|
async getDispatchByMessages(
|
|
1789
1900
|
orgId: string,
|
|
1790
1901
|
chatId: string,
|
|
@@ -2165,6 +2276,124 @@ export class ParallClient {
|
|
|
2165
2276
|
return this.request('DELETE', ENDPOINTS.EXTERNAL_CONNECTION(orgId, connectionId));
|
|
2166
2277
|
}
|
|
2167
2278
|
|
|
2279
|
+
// ---- External IM channel (org-scoped) ----
|
|
2280
|
+
|
|
2281
|
+
async createChannelConnection(
|
|
2282
|
+
orgId: string,
|
|
2283
|
+
input: CreateChannelConnectionInput,
|
|
2284
|
+
): Promise<ChannelConnection> {
|
|
2285
|
+
return this.request('POST', ENDPOINTS.CHANNEL_CONNECTIONS(orgId), input);
|
|
2286
|
+
}
|
|
2287
|
+
|
|
2288
|
+
async listChannelConnections(orgId: string): Promise<{ connections: ChannelConnection[] }> {
|
|
2289
|
+
return this.request('GET', ENDPOINTS.CHANNEL_CONNECTIONS(orgId));
|
|
2290
|
+
}
|
|
2291
|
+
|
|
2292
|
+
async getChannelConnection(orgId: string, connectionId: string): Promise<ChannelConnection> {
|
|
2293
|
+
return this.request('GET', ENDPOINTS.CHANNEL_CONNECTION(orgId, connectionId));
|
|
2294
|
+
}
|
|
2295
|
+
|
|
2296
|
+
async updateChannelConnection(
|
|
2297
|
+
orgId: string,
|
|
2298
|
+
connectionId: string,
|
|
2299
|
+
patch: UpdateChannelConnectionInput,
|
|
2300
|
+
): Promise<ChannelConnection> {
|
|
2301
|
+
return this.request('PATCH', ENDPOINTS.CHANNEL_CONNECTION(orgId, connectionId), patch);
|
|
2302
|
+
}
|
|
2303
|
+
|
|
2304
|
+
async archiveChannelConnection(orgId: string, connectionId: string): Promise<ChannelConnection> {
|
|
2305
|
+
return this.request('DELETE', ENDPOINTS.CHANNEL_CONNECTION(orgId, connectionId));
|
|
2306
|
+
}
|
|
2307
|
+
|
|
2308
|
+
async deliverChannelCredentials(
|
|
2309
|
+
orgId: string,
|
|
2310
|
+
connectionId: string,
|
|
2311
|
+
credentials: ChannelCredentialsInput,
|
|
2312
|
+
): Promise<ChannelConnection> {
|
|
2313
|
+
return this.request(
|
|
2314
|
+
'POST',
|
|
2315
|
+
ENDPOINTS.CHANNEL_CONNECTION_CREDENTIALS(orgId, connectionId),
|
|
2316
|
+
credentials,
|
|
2317
|
+
);
|
|
2318
|
+
}
|
|
2319
|
+
|
|
2320
|
+
async regenerateChannelIngressToken(
|
|
2321
|
+
orgId: string,
|
|
2322
|
+
connectionId: string,
|
|
2323
|
+
): Promise<ChannelConnection> {
|
|
2324
|
+
return this.request(
|
|
2325
|
+
'POST',
|
|
2326
|
+
ENDPOINTS.CHANNEL_CONNECTION_INGRESS_TOKEN_REGENERATE(orgId, connectionId),
|
|
2327
|
+
);
|
|
2328
|
+
}
|
|
2329
|
+
|
|
2330
|
+
/** Start a Feishu one-click provisioning session (device flow QR). */
|
|
2331
|
+
async initiateChannelProvisioning(
|
|
2332
|
+
orgId: string,
|
|
2333
|
+
input: InitiateChannelProvisioningInput,
|
|
2334
|
+
): Promise<ChannelProvisioningSession> {
|
|
2335
|
+
return this.request('POST', ENDPOINTS.CHANNEL_PROVISIONING(orgId), input);
|
|
2336
|
+
}
|
|
2337
|
+
|
|
2338
|
+
/**
|
|
2339
|
+
* Lazy status poll — server-side this may forward one provider poll, so
|
|
2340
|
+
* call it at the session's `poll_interval_seconds` cadence, not faster.
|
|
2341
|
+
*/
|
|
2342
|
+
async getChannelProvisioningSession(
|
|
2343
|
+
orgId: string,
|
|
2344
|
+
sessionId: string,
|
|
2345
|
+
): Promise<ChannelProvisioningSession> {
|
|
2346
|
+
return this.request('GET', ENDPOINTS.CHANNEL_PROVISIONING_SESSION(orgId, sessionId));
|
|
2347
|
+
}
|
|
2348
|
+
|
|
2349
|
+
async cancelChannelProvisioning(
|
|
2350
|
+
orgId: string,
|
|
2351
|
+
sessionId: string,
|
|
2352
|
+
): Promise<ChannelProvisioningSession> {
|
|
2353
|
+
return this.request('POST', ENDPOINTS.CHANNEL_PROVISIONING_CANCEL(orgId, sessionId));
|
|
2354
|
+
}
|
|
2355
|
+
|
|
2356
|
+
async listChannelConversations(
|
|
2357
|
+
orgId: string,
|
|
2358
|
+
connectionId: string,
|
|
2359
|
+
): Promise<{ conversations: ChannelConversation[] }> {
|
|
2360
|
+
return this.request('GET', ENDPOINTS.CHANNEL_CONNECTION_CONVERSATIONS(orgId, connectionId));
|
|
2361
|
+
}
|
|
2362
|
+
|
|
2363
|
+
async getChannelConversation(
|
|
2364
|
+
orgId: string,
|
|
2365
|
+
conversationId: string,
|
|
2366
|
+
): Promise<ChannelConversation> {
|
|
2367
|
+
return this.request('GET', ENDPOINTS.CHANNEL_CONVERSATION(orgId, conversationId));
|
|
2368
|
+
}
|
|
2369
|
+
|
|
2370
|
+
async listChannelConversationMessages(
|
|
2371
|
+
orgId: string,
|
|
2372
|
+
conversationId: string,
|
|
2373
|
+
limit?: number,
|
|
2374
|
+
): Promise<{ messages: ChannelMessage[] }> {
|
|
2375
|
+
return this.request(
|
|
2376
|
+
'GET',
|
|
2377
|
+
ENDPOINTS.CHANNEL_CONVERSATION_MESSAGES(orgId, conversationId),
|
|
2378
|
+
undefined,
|
|
2379
|
+
{ limit },
|
|
2380
|
+
);
|
|
2381
|
+
}
|
|
2382
|
+
|
|
2383
|
+
async setChannelConversationSession(
|
|
2384
|
+
orgId: string,
|
|
2385
|
+
conversationId: string,
|
|
2386
|
+
agentSessionId: string,
|
|
2387
|
+
): Promise<ChannelConversation> {
|
|
2388
|
+
return this.request('PATCH', ENDPOINTS.CHANNEL_CONVERSATION_SESSION(orgId, conversationId), {
|
|
2389
|
+
agent_session_id: agentSessionId,
|
|
2390
|
+
});
|
|
2391
|
+
}
|
|
2392
|
+
|
|
2393
|
+
async getChannelMessage(orgId: string, messageId: string): Promise<ChannelMessage> {
|
|
2394
|
+
return this.request('GET', ENDPOINTS.CHANNEL_MESSAGE(orgId, messageId));
|
|
2395
|
+
}
|
|
2396
|
+
|
|
2168
2397
|
async getExternalTriggerSchema(
|
|
2169
2398
|
orgId: string,
|
|
2170
2399
|
connectionId: string,
|
|
@@ -2254,6 +2483,26 @@ export class ParallClient {
|
|
|
2254
2483
|
return this.request('GET', ENDPOINTS.WIKI(orgId, wikiId));
|
|
2255
2484
|
}
|
|
2256
2485
|
|
|
2486
|
+
/** Soft-delete an entire wiki (org owner only; the default wiki is
|
|
2487
|
+
* protected → 403 WIKI_PROTECTED). Returns the deleted wiki. Recoverable
|
|
2488
|
+
* via restoreWiki within the retention window. */
|
|
2489
|
+
async deleteWiki(orgId: string, wikiId: string): Promise<Wiki> {
|
|
2490
|
+
return this.request('DELETE', ENDPOINTS.WIKI(orgId, wikiId));
|
|
2491
|
+
}
|
|
2492
|
+
|
|
2493
|
+
/** Restore a soft-deleted wiki (org owner only). 409 WIKI_PURGE_STARTED once
|
|
2494
|
+
* purge has been claimed (no longer restorable), or 404 once the row is gone.
|
|
2495
|
+
* Returns the restored wiki. */
|
|
2496
|
+
async restoreWiki(orgId: string, wikiId: string): Promise<Wiki> {
|
|
2497
|
+
return this.request('POST', ENDPOINTS.WIKI_RESTORE(orgId, wikiId));
|
|
2498
|
+
}
|
|
2499
|
+
|
|
2500
|
+
/** Recycle bin — list soft-deleted wikis for the org (owner only). */
|
|
2501
|
+
async getDeletedWikis(orgId: string): Promise<Wiki[]> {
|
|
2502
|
+
const res = await this.request<{ data: Wiki[] }>('GET', ENDPOINTS.WIKIS_DELETED(orgId));
|
|
2503
|
+
return res.data;
|
|
2504
|
+
}
|
|
2505
|
+
|
|
2257
2506
|
async getWikiTree(
|
|
2258
2507
|
orgId: string,
|
|
2259
2508
|
wikiId: string,
|
|
@@ -2301,6 +2550,20 @@ export class ParallClient {
|
|
|
2301
2550
|
return blob;
|
|
2302
2551
|
}
|
|
2303
2552
|
|
|
2553
|
+
/**
|
|
2554
|
+
* Copy one wiki file to another path as an independent snapshot (no sync).
|
|
2555
|
+
* Used to "share a private file out": copy a file from the caller's personal
|
|
2556
|
+
* namespace (`users/{userId}/…`) into the public wiki, leaving the original
|
|
2557
|
+
* untouched. 409 `FILE_EXISTS` if `dest_path` already exists.
|
|
2558
|
+
*/
|
|
2559
|
+
async copyWikiFile(
|
|
2560
|
+
orgId: string,
|
|
2561
|
+
wikiId: string,
|
|
2562
|
+
req: CopyWikiFileRequest,
|
|
2563
|
+
): Promise<CopyWikiFileResponse> {
|
|
2564
|
+
return this.request('POST', ENDPOINTS.WIKI_COPY(orgId, wikiId), req);
|
|
2565
|
+
}
|
|
2566
|
+
|
|
2304
2567
|
async getWikiNodeSections(
|
|
2305
2568
|
orgId: string,
|
|
2306
2569
|
wikiId: string,
|
|
@@ -2828,6 +3091,21 @@ export class ParallClient {
|
|
|
2828
3091
|
return resp.data;
|
|
2829
3092
|
}
|
|
2830
3093
|
|
|
3094
|
+
/** Runtime capability table (public) — SSOT for the create/settings interlock. */
|
|
3095
|
+
async getRuntimes(): Promise<RuntimeCapability[]> {
|
|
3096
|
+
const resp = await this.request<{ data: RuntimeCapability[] }>('GET', ENDPOINTS.RUNTIMES());
|
|
3097
|
+
return resp.data;
|
|
3098
|
+
}
|
|
3099
|
+
|
|
3100
|
+
/**
|
|
3101
|
+
* Platform model catalog (public) — DB-backed, replaces the compile-time
|
|
3102
|
+
* PLATFORM_MODELS constant. Pass includeModel to keep an agent's pinned
|
|
3103
|
+
* hidden legacy model representable (settings picker).
|
|
3104
|
+
*/
|
|
3105
|
+
async getModels(includeModel?: string): Promise<PlatformModelsResponse> {
|
|
3106
|
+
return this.request<PlatformModelsResponse>('GET', ENDPOINTS.MODELS(includeModel));
|
|
3107
|
+
}
|
|
3108
|
+
|
|
2831
3109
|
// ---- Clips ----
|
|
2832
3110
|
|
|
2833
3111
|
async listClips(orgId: string): Promise<Clip[]> {
|
|
@@ -2895,6 +3173,12 @@ export class ParallClient {
|
|
|
2895
3173
|
return resp.data;
|
|
2896
3174
|
}
|
|
2897
3175
|
|
|
3176
|
+
/** Deployment-wide hosted browser runtime availability — drives whether the
|
|
3177
|
+
* create UI offers the platform-hosted placement. Fail-closed server-side. */
|
|
3178
|
+
async getBrowserRuntimeStatus(orgId: string): Promise<BrowserRuntimeStatus> {
|
|
3179
|
+
return this.request('GET', ENDPOINTS.BROWSER_RUNTIME_STATUS(orgId));
|
|
3180
|
+
}
|
|
3181
|
+
|
|
2898
3182
|
/** Org-wide browser-profile discovery list. Returns the sanitized
|
|
2899
3183
|
* {@link BrowserProfileListItem} shape (not the full domain model), each row
|
|
2900
3184
|
* carrying a per-viewer `can_open` control hint. */
|
package/src/constants.ts
CHANGED
|
@@ -7,11 +7,17 @@ export const WIKI_BASE = '/wiki/v1';
|
|
|
7
7
|
// Clip-service base path (served by clip-service, routed via LB path rules)
|
|
8
8
|
export const CLIP_BASE = '/clip/v1';
|
|
9
9
|
|
|
10
|
-
// LLM model catalog —
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
|
|
10
|
+
// LLM model catalog — frozen compile-time mirror of the catalog at the time
|
|
11
|
+
// the DB-backed source shipped (docs/engineering-design/model-catalog-design.md).
|
|
12
|
+
// Kept ONLY as the offline/degraded fallback for pickers; it is NOT updated
|
|
13
|
+
// when models are added through the admin catalog.
|
|
14
|
+
/**
|
|
15
|
+
* @deprecated The catalog is DB-backed — fetch it via `client.getModels()`
|
|
16
|
+
* (GET /api/v1/models). This constant is a frozen degraded-mode fallback and
|
|
17
|
+
* will be removed after one release cycle. Still structurally consumed by
|
|
18
|
+
* FALLBACK_CATALOG (`@parall/app` agent-interlock) — do not delete before
|
|
19
|
+
* that fallback strategy changes (PR-3).
|
|
20
|
+
*/
|
|
15
21
|
export const PLATFORM_MODELS = [
|
|
16
22
|
// Fable 5 rejects an explicit thinking "disabled" param (400) — bridges must
|
|
17
23
|
// omit the thinking config entirely instead of disabling it.
|
|
@@ -211,6 +217,12 @@ export const PLATFORM_MODELS = [
|
|
|
211
217
|
|
|
212
218
|
// Hidden from new-agent pickers, but available to editors so persisted Beta
|
|
213
219
|
// agent defaults remain representable.
|
|
220
|
+
/**
|
|
221
|
+
* @deprecated Fetch via `client.getModels(currentModelId)` — the include_model
|
|
222
|
+
* parameter serves the legacy-pin case. Frozen degraded-mode fallback only.
|
|
223
|
+
* Still structurally consumed by FALLBACK_CATALOG (`@parall/app`
|
|
224
|
+
* agent-interlock) — do not delete before that fallback changes (PR-3).
|
|
225
|
+
*/
|
|
214
226
|
export const PLATFORM_LEGACY_MODELS = [
|
|
215
227
|
{
|
|
216
228
|
id: 'openai/gpt-5.4-mini',
|
|
@@ -284,9 +296,13 @@ export const PLATFORM_LEGACY_MODELS = [
|
|
|
284
296
|
},
|
|
285
297
|
] as const;
|
|
286
298
|
|
|
287
|
-
//
|
|
288
|
-
//
|
|
289
|
-
//
|
|
299
|
+
// Frozen mirror of the per-runtime defaults at ship time of the DB-backed
|
|
300
|
+
// catalog (llm_runtime_defaults). Live values arrive as recommended_model on
|
|
301
|
+
// GET /runtimes.
|
|
302
|
+
/**
|
|
303
|
+
* @deprecated Read `recommended_model` from `client.getRuntimes()` instead.
|
|
304
|
+
* Frozen degraded-mode fallback only.
|
|
305
|
+
*/
|
|
290
306
|
export const PLATFORM_DEFAULT_MODEL_BY_RUNTIME = {
|
|
291
307
|
openclaw: 'anthropic/claude-sonnet-4.6',
|
|
292
308
|
'claude-code': 'anthropic/claude-sonnet-4.6',
|
|
@@ -312,6 +328,11 @@ export function platformDefaultModelForRuntime(runtime: string | null | undefine
|
|
|
312
328
|
case '':
|
|
313
329
|
case 'openclaw':
|
|
314
330
|
case 'claude-code':
|
|
331
|
+
// hermes / parel route through the Parall proxy and accept any model; the
|
|
332
|
+
// server (DefaultModelIDForRuntime) recommends the platform default, so
|
|
333
|
+
// mirror it.
|
|
334
|
+
case 'hermes':
|
|
335
|
+
case 'parel':
|
|
315
336
|
return PLATFORM_DEFAULT_MODEL_BY_RUNTIME.openclaw;
|
|
316
337
|
case 'codex':
|
|
317
338
|
return PLATFORM_DEFAULT_MODEL_BY_RUNTIME.codex;
|
|
@@ -347,6 +368,7 @@ export const ENDPOINTS = {
|
|
|
347
368
|
// Org-scoped
|
|
348
369
|
ORG: (orgId: string) => `${API_BASE}/orgs/${orgId}`,
|
|
349
370
|
ORG_MEMBERS: (orgId: string) => `${API_BASE}/orgs/${orgId}/members`,
|
|
371
|
+
ORG_MEMBERS_FORMER: (orgId: string) => `${API_BASE}/orgs/${orgId}/members/former`,
|
|
350
372
|
TEAMS: (orgId: string) => `${API_BASE}/orgs/${orgId}/teams`,
|
|
351
373
|
ORG_MEMBERS_ONLINE: (orgId: string) => `${API_BASE}/orgs/${orgId}/members/online`,
|
|
352
374
|
ORG_MEMBER: (orgId: string, userId: string) => `${API_BASE}/orgs/${orgId}/members/${userId}`,
|
|
@@ -584,6 +606,30 @@ export const ENDPOINTS = {
|
|
|
584
606
|
EXTERNAL_TRIGGER_RUN: (orgId: string, runId: string) =>
|
|
585
607
|
`${API_BASE}/orgs/${orgId}/external-trigger-runs/${runId}`,
|
|
586
608
|
|
|
609
|
+
// External IM channel (org-scoped, platform-mediated Feishu/Slack)
|
|
610
|
+
CHANNEL_CONNECTIONS: (orgId: string) => `${API_BASE}/orgs/${orgId}/channel-connections`,
|
|
611
|
+
CHANNEL_CONNECTION: (orgId: string, connectionId: string) =>
|
|
612
|
+
`${API_BASE}/orgs/${orgId}/channel-connections/${connectionId}`,
|
|
613
|
+
CHANNEL_CONNECTION_CREDENTIALS: (orgId: string, connectionId: string) =>
|
|
614
|
+
`${API_BASE}/orgs/${orgId}/channel-connections/${connectionId}/credentials`,
|
|
615
|
+
CHANNEL_CONNECTION_INGRESS_TOKEN_REGENERATE: (orgId: string, connectionId: string) =>
|
|
616
|
+
`${API_BASE}/orgs/${orgId}/channel-connections/${connectionId}/ingress-token/regenerate`,
|
|
617
|
+
CHANNEL_CONNECTION_CONVERSATIONS: (orgId: string, connectionId: string) =>
|
|
618
|
+
`${API_BASE}/orgs/${orgId}/channel-connections/${connectionId}/conversations`,
|
|
619
|
+
CHANNEL_CONVERSATION: (orgId: string, conversationId: string) =>
|
|
620
|
+
`${API_BASE}/orgs/${orgId}/channel-conversations/${conversationId}`,
|
|
621
|
+
CHANNEL_CONVERSATION_MESSAGES: (orgId: string, conversationId: string) =>
|
|
622
|
+
`${API_BASE}/orgs/${orgId}/channel-conversations/${conversationId}/messages`,
|
|
623
|
+
CHANNEL_CONVERSATION_SESSION: (orgId: string, conversationId: string) =>
|
|
624
|
+
`${API_BASE}/orgs/${orgId}/channel-conversations/${conversationId}/session`,
|
|
625
|
+
CHANNEL_MESSAGE: (orgId: string, messageId: string) =>
|
|
626
|
+
`${API_BASE}/orgs/${orgId}/channel-messages/${messageId}`,
|
|
627
|
+
CHANNEL_PROVISIONING: (orgId: string) => `${API_BASE}/orgs/${orgId}/channel-provisioning`,
|
|
628
|
+
CHANNEL_PROVISIONING_SESSION: (orgId: string, sessionId: string) =>
|
|
629
|
+
`${API_BASE}/orgs/${orgId}/channel-provisioning/${sessionId}`,
|
|
630
|
+
CHANNEL_PROVISIONING_CANCEL: (orgId: string, sessionId: string) =>
|
|
631
|
+
`${API_BASE}/orgs/${orgId}/channel-provisioning/${sessionId}/cancel`,
|
|
632
|
+
|
|
587
633
|
// Invitations (org-scoped, admin)
|
|
588
634
|
ORG_INVITATIONS: (orgId: string) => `${API_BASE}/orgs/${orgId}/invitations`,
|
|
589
635
|
ORG_INVITATION: (orgId: string, invId: string) =>
|
|
@@ -608,9 +654,17 @@ export const ENDPOINTS = {
|
|
|
608
654
|
|
|
609
655
|
// Wikis (org-scoped, served by wiki-service)
|
|
610
656
|
WIKIS: (orgId: string) => `${WIKI_BASE}/orgs/${orgId}/wikis`,
|
|
657
|
+
// Recycle bin — soft-deleted wikis (owner only). Must precede WIKI in the
|
|
658
|
+
// backend router so `deleted` isn't captured as a {wikiId}; the SDK builder
|
|
659
|
+
// is just a string.
|
|
660
|
+
WIKIS_DELETED: (orgId: string) => `${WIKI_BASE}/orgs/${orgId}/wikis/deleted`,
|
|
661
|
+
// Detail URL — also reused for DELETE (soft-delete) and `${WIKI}/restore`.
|
|
611
662
|
WIKI: (orgId: string, wikiId: string) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}`,
|
|
663
|
+
WIKI_RESTORE: (orgId: string, wikiId: string) =>
|
|
664
|
+
`${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/restore`,
|
|
612
665
|
WIKI_TREE: (orgId: string, wikiId: string) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/tree`,
|
|
613
666
|
WIKI_BLOB: (orgId: string, wikiId: string) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/blob`,
|
|
667
|
+
WIKI_COPY: (orgId: string, wikiId: string) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/copy`,
|
|
614
668
|
WIKI_NODE_SECTIONS: (orgId: string, wikiId: string) =>
|
|
615
669
|
`${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/node-sections`,
|
|
616
670
|
WIKI_SEARCH: (orgId: string, wikiId: string) =>
|
|
@@ -695,6 +749,11 @@ export const ENDPOINTS = {
|
|
|
695
749
|
DISPATCH_ACK_BY_ID: (orgId: string, id: string) => `${API_BASE}/orgs/${orgId}/dispatch/${id}/ack`,
|
|
696
750
|
DISPATCH_EXPIRE: (orgId: string) => `${API_BASE}/orgs/${orgId}/dispatch/expire`,
|
|
697
751
|
DISPATCH_BY_MESSAGES: (orgId: string) => `${API_BASE}/orgs/${orgId}/dispatch/by-messages`,
|
|
752
|
+
DISPATCH_CLAIM: (orgId: string) => `${API_BASE}/orgs/${orgId}/dispatch/claim`,
|
|
753
|
+
DISPATCH_STEER: (orgId: string) => `${API_BASE}/orgs/${orgId}/dispatch/steer`,
|
|
754
|
+
DISPATCH_COMPLETE: (orgId: string) => `${API_BASE}/orgs/${orgId}/dispatch/complete`,
|
|
755
|
+
DISPATCH_RELEASE: (orgId: string) => `${API_BASE}/orgs/${orgId}/dispatch/release`,
|
|
756
|
+
DISPATCH_HEARTBEAT: (orgId: string) => `${API_BASE}/orgs/${orgId}/dispatch/heartbeat`,
|
|
698
757
|
|
|
699
758
|
// Unread
|
|
700
759
|
UNREAD: `${API_BASE}/me/unread`,
|
|
@@ -734,6 +793,19 @@ export const ENDPOINTS = {
|
|
|
734
793
|
BILLING_SETUP_INTENT: (orgId: string) => `${API_BASE}/orgs/${orgId}/billing/setup-intent`,
|
|
735
794
|
COMPUTE_PRICING: () => `${API_BASE}/billing/compute-pricing`,
|
|
736
795
|
|
|
796
|
+
// Runtime capability table (public, no auth) — SSOT for the create/settings
|
|
797
|
+
// interlock: per-runtime compute modes, native model family, cross-family
|
|
798
|
+
// availability, and recommended model.
|
|
799
|
+
RUNTIMES: () => `${API_BASE}/runtimes`,
|
|
800
|
+
|
|
801
|
+
// Model catalog (public, no auth) — served from the server's DB-backed
|
|
802
|
+
// snapshot. Optional include_model keeps an agent's pinned hidden legacy
|
|
803
|
+
// model representable in settings pickers.
|
|
804
|
+
MODELS: (includeModel?: string) =>
|
|
805
|
+
includeModel
|
|
806
|
+
? `${API_BASE}/models?include_model=${encodeURIComponent(includeModel)}`
|
|
807
|
+
: `${API_BASE}/models`,
|
|
808
|
+
|
|
737
809
|
// ADMIN_GRANTS intentionally NOT exported here — it sits under the
|
|
738
810
|
// unauthenticated `/internal/admin/*` surface and must not bleed into the
|
|
739
811
|
// public SDK. Admin dashboard hits the URL directly from its own client.
|
|
@@ -750,6 +822,7 @@ export const ENDPOINTS = {
|
|
|
750
822
|
`${CLIP_BASE}/orgs/${orgId}/agents/${agentId}/clips/${clipId}`,
|
|
751
823
|
CLIP_INVOKE: (orgId: string) => `${CLIP_BASE}/orgs/${orgId}/invoke`,
|
|
752
824
|
CLIP_ONLINE: (orgId: string) => `${CLIP_BASE}/orgs/${orgId}/online`,
|
|
825
|
+
BROWSER_RUNTIME_STATUS: (orgId: string) => `${CLIP_BASE}/orgs/${orgId}/browser-runtime/status`,
|
|
753
826
|
BROWSER_PROFILES: (orgId: string) => `${CLIP_BASE}/orgs/${orgId}/browser-profiles`,
|
|
754
827
|
BROWSER_PROFILE: (orgId: string, profileId: string) =>
|
|
755
828
|
`${CLIP_BASE}/orgs/${orgId}/browser-profiles/${profileId}`,
|
|
@@ -772,6 +845,42 @@ export const ENDPOINTS = {
|
|
|
772
845
|
CLIP_REGISTRY: () => `${CLIP_BASE}/registry/clips`,
|
|
773
846
|
} as const;
|
|
774
847
|
|
|
848
|
+
/**
|
|
849
|
+
* Wiki personal-namespace prefix — the path subtree a member owns for
|
|
850
|
+
* self-service private spaces: `users/{userId}/`. SSOT mirror of the
|
|
851
|
+
* wiki-service `personalNamespacePrefix` (server/internal/wiki/handler/acl.go):
|
|
852
|
+
* a member may create/manage path restrictions anywhere under this prefix
|
|
853
|
+
* without org/path admin. The trailing slash is load-bearing — it keeps a user
|
|
854
|
+
* ID that is a string prefix of another from matching across namespaces.
|
|
855
|
+
*/
|
|
856
|
+
export function wikiPersonalNamespacePrefix(userId: string): string {
|
|
857
|
+
return `users/${userId}/`;
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
/**
|
|
861
|
+
* Whether `path` falls inside `userId`'s personal namespace (the namespace root
|
|
862
|
+
* itself or any descendant). Mirrors the server's `ownsPersonalNamespacePath`;
|
|
863
|
+
* use it for UI affordance gating only — the wiki-service stays the security
|
|
864
|
+
* SSOT and re-checks on every mutation.
|
|
865
|
+
*/
|
|
866
|
+
export function isInWikiPersonalNamespace(userId: string, path: string): boolean {
|
|
867
|
+
if (!userId) return false;
|
|
868
|
+
const prefix = wikiPersonalNamespacePrefix(userId);
|
|
869
|
+
return path === prefix || path.startsWith(prefix);
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
/**
|
|
873
|
+
* Whether `path` falls inside ANY user's personal namespace (`users/{id}/…`),
|
|
874
|
+
* regardless of whose. UI affordance helper — e.g. badging member personal-space
|
|
875
|
+
* restriction rows in the admin Access tab, or keeping "copy to shared wiki"
|
|
876
|
+
* destinations out of personal namespaces. Matches by shape (`users/<segment>/`
|
|
877
|
+
* or the bare `users/<segment>`), deliberately broader than
|
|
878
|
+
* `isInWikiPersonalNamespace`.
|
|
879
|
+
*/
|
|
880
|
+
export function isWikiPersonalNamespacePath(path: string): boolean {
|
|
881
|
+
return /^users\/[^/]+(\/|$)/.test(path);
|
|
882
|
+
}
|
|
883
|
+
|
|
775
884
|
// WebSocket event types
|
|
776
885
|
export const WS_EVENTS = {
|
|
777
886
|
// Client -> Server
|
|
@@ -813,10 +922,13 @@ export const WS_EVENTS = {
|
|
|
813
922
|
INVITATION_REVOKED: 'invitation.revoked',
|
|
814
923
|
ORG_JOIN_REQUEST_NEW: 'org.join_request.new',
|
|
815
924
|
ORG_INVITE_LINK_JOINED: 'org.invite_link.joined',
|
|
925
|
+
ORG_MEMBER_REMOVED: 'org.member.removed',
|
|
816
926
|
AGENT_CONFIG_UPDATE: 'agent_config.update',
|
|
817
927
|
PRESENCE_UPDATE: 'presence.update',
|
|
818
928
|
WIKI_CHANGESET_CREATED: 'wiki.changeset.created',
|
|
819
929
|
WIKI_CHANGESET_UPDATED: 'wiki.changeset.updated',
|
|
930
|
+
WIKI_DELETED: 'wiki.deleted',
|
|
931
|
+
WIKI_RESTORED: 'wiki.restored',
|
|
820
932
|
COMMENT_CREATED: 'comment.created',
|
|
821
933
|
COMMENT_UPDATED: 'comment.updated',
|
|
822
934
|
COMMENT_DELETED: 'comment.deleted',
|
|
@@ -827,6 +939,7 @@ export const WS_EVENTS = {
|
|
|
827
939
|
READ_POSITION_UPDATED: 'read_position.updated',
|
|
828
940
|
DISPATCH_NEW: 'dispatch.new',
|
|
829
941
|
DISPATCH_RECEIVED: 'dispatch.received',
|
|
942
|
+
DISPATCH_RESOLVED: 'dispatch.resolved',
|
|
830
943
|
SCHEDULE_CREATED: 'schedule.created',
|
|
831
944
|
SCHEDULE_UPDATED: 'schedule.updated',
|
|
832
945
|
SCHEDULE_DELETED: 'schedule.deleted',
|
|
@@ -844,6 +957,7 @@ export const WS_EVENTS = {
|
|
|
844
957
|
MACHINE_FILESYSTEM_BROWSE: 'machine.filesystem.browse',
|
|
845
958
|
MACHINE_UPDATE: 'machine.update',
|
|
846
959
|
MACHINE_CONFIG_UPDATED: 'machine.config.updated',
|
|
960
|
+
MACHINE_AGENT_CONFIG_UPDATED: 'machine.agent_config.updated',
|
|
847
961
|
MACHINE_CLIP_SYNC: 'machine.clip.sync',
|
|
848
962
|
MACHINE_BROWSER_PROFILE_LIFECYCLE: 'machine.browser_profile.lifecycle',
|
|
849
963
|
MACHINE_BROWSER_PROFILE_VIEWER: 'machine.browser_profile.viewer',
|