@neta-art/cohub 7.0.0 → 8.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/http.d.ts +328 -226
- package/dist/chunks/http.js +227 -194
- package/dist/chunks/transport.js +2 -1
- package/dist/chunks/websocket.d.ts +96 -77
- package/dist/http.d.ts +3 -3
- package/dist/index.d.ts +165 -119
- package/dist/index.js +409 -286
- package/dist/protocol/dist/index.d.ts +1 -1
- package/dist/protocol/dist/realtime/types.d.ts +1 -1
- package/package.json +1 -1
- /package/dist/protocol/dist/{work.d.ts → app.d.ts} +0 -0
package/dist/chunks/http.js
CHANGED
|
@@ -1296,39 +1296,43 @@ z.object({
|
|
|
1296
1296
|
}).optional()
|
|
1297
1297
|
}).strict();
|
|
1298
1298
|
//#endregion
|
|
1299
|
-
//#region ../protocol/dist/
|
|
1299
|
+
//#region ../protocol/dist/desktop-command.js
|
|
1300
1300
|
/**
|
|
1301
|
-
* Lets an agent drive the Cohub
|
|
1301
|
+
* Lets an agent drive the Cohub desktop that originated the app. Routing comes
|
|
1302
1302
|
* from request provenance, never a caller-supplied target, so a command only
|
|
1303
1303
|
* reaches the actor's own instances.
|
|
1304
|
+
*
|
|
1305
|
+
* The canonical command is `desktop.open`. The legacy `preview.show` shape is
|
|
1306
|
+
* accepted on input and normalized, so older clients keep working, but commands
|
|
1307
|
+
* are always stored and dispatched in the canonical form.
|
|
1304
1308
|
*/
|
|
1305
|
-
const
|
|
1309
|
+
const DESKTOP_COMMAND_VERSION = 1;
|
|
1306
1310
|
/** Persisted and broadcast, so every field is capped; MAX_BYTES bounds the whole. */
|
|
1307
|
-
const
|
|
1308
|
-
const
|
|
1309
|
-
const
|
|
1310
|
-
const
|
|
1311
|
-
const
|
|
1312
|
-
const
|
|
1311
|
+
const DESKTOP_COMMAND_PAYLOAD_MAX_BYTES = 32 * 1024;
|
|
1312
|
+
const DESKTOP_COMMAND_MAX_BYTES = 40 * 1024;
|
|
1313
|
+
const DESKTOP_COMMAND_LAUNCH_MAX_LENGTH = 2048;
|
|
1314
|
+
const DESKTOP_COMMAND_DEFAULT_TIMEOUT_MS = 600 * 1e3;
|
|
1315
|
+
const DESKTOP_COMMAND_MAX_TIMEOUT_MS = 720 * 60 * 1e3;
|
|
1316
|
+
const DESKTOP_COMMAND_SETTLEMENT_GRACE_SECONDS = 600;
|
|
1313
1317
|
/** Keeps pending commands reportable for the full wait window plus settlement grace. */
|
|
1314
|
-
const
|
|
1315
|
-
const
|
|
1316
|
-
const
|
|
1318
|
+
const DESKTOP_COMMAND_PENDING_TTL_SECONDS = 43800;
|
|
1319
|
+
const DESKTOP_COMMAND_TERMINAL_TTL_SECONDS = 1800;
|
|
1320
|
+
const DESKTOP_COMMAND_TERMINAL_STATUSES = [
|
|
1317
1321
|
"applied",
|
|
1318
1322
|
"no_active_client",
|
|
1319
|
-
"
|
|
1323
|
+
"desktop_host_unavailable",
|
|
1320
1324
|
"rejected",
|
|
1321
1325
|
"unsupported",
|
|
1322
1326
|
"timeout"
|
|
1323
1327
|
];
|
|
1324
|
-
const
|
|
1328
|
+
const isTerminalDesktopCommandStatus = (status) => DESKTOP_COMMAND_TERMINAL_STATUSES.includes(status);
|
|
1325
1329
|
const METHOD_RE = /^[A-Za-z][A-Za-z0-9_.:-]{0,63}$/;
|
|
1326
|
-
const
|
|
1327
|
-
const
|
|
1328
|
-
const
|
|
1330
|
+
const isDesktopCallMethod = (value) => typeof value === "string" && METHOD_RE.test(value);
|
|
1331
|
+
const DESKTOP_COMMAND_ID_RE = /^[A-Za-z0-9_-]{1,64}$/;
|
|
1332
|
+
const parseDesktopCommandId = (value) => {
|
|
1329
1333
|
if (typeof value !== "string") return null;
|
|
1330
1334
|
const trimmed = value.trim();
|
|
1331
|
-
return
|
|
1335
|
+
return DESKTOP_COMMAND_ID_RE.test(trimmed) ? trimmed : null;
|
|
1332
1336
|
};
|
|
1333
1337
|
const isRecord$1 = (value) => Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
1334
1338
|
const asTrimmed = (value) => {
|
|
@@ -1346,7 +1350,7 @@ const parseLaunch = (value) => {
|
|
|
1346
1350
|
...hash ? { hash: hash.startsWith("#") ? hash : `#${hash}` } : {}
|
|
1347
1351
|
};
|
|
1348
1352
|
};
|
|
1349
|
-
const
|
|
1353
|
+
const measureDesktopCommandPayload = (value) => {
|
|
1350
1354
|
if (value === void 0) return 0;
|
|
1351
1355
|
try {
|
|
1352
1356
|
return new TextEncoder().encode(JSON.stringify(value) ?? "").length;
|
|
@@ -1354,118 +1358,131 @@ const measureUiCommandPayload = (value) => {
|
|
|
1354
1358
|
return null;
|
|
1355
1359
|
}
|
|
1356
1360
|
};
|
|
1357
|
-
|
|
1361
|
+
/**
|
|
1362
|
+
* Parse a desktop command from untrusted input.
|
|
1363
|
+
*
|
|
1364
|
+
* Accepts both the canonical `desktop.open` shape (`target` / `call`) and the
|
|
1365
|
+
* legacy `preview.show` shape (`preview` / `request`); the result is always
|
|
1366
|
+
* canonical so every later stage handles a single form.
|
|
1367
|
+
*/
|
|
1368
|
+
const parseDesktopCommand = (input) => {
|
|
1358
1369
|
if (!isRecord$1(input)) return {
|
|
1359
1370
|
command: null,
|
|
1360
1371
|
error: "command must be an object"
|
|
1361
1372
|
};
|
|
1362
|
-
|
|
1373
|
+
const legacy = input.type === "preview.show";
|
|
1374
|
+
if (input.type !== "desktop.open" && !legacy) return {
|
|
1363
1375
|
command: null,
|
|
1364
|
-
error: "command.type must be one of:
|
|
1376
|
+
error: "command.type must be one of: desktop.open"
|
|
1365
1377
|
};
|
|
1366
|
-
const
|
|
1367
|
-
if (!
|
|
1378
|
+
const target = isRecord$1(input.target) ? input.target : isRecord$1(input.preview) ? input.preview : null;
|
|
1379
|
+
if (!target) return {
|
|
1368
1380
|
command: null,
|
|
1369
|
-
error: "command.
|
|
1381
|
+
error: "command.target is required"
|
|
1370
1382
|
};
|
|
1371
|
-
|
|
1383
|
+
const kind = target.kind === "app" || legacy && target.kind === "work" ? "app" : target.kind === "file" ? "file" : null;
|
|
1384
|
+
if (!kind) return {
|
|
1372
1385
|
command: null,
|
|
1373
|
-
error: "command.
|
|
1386
|
+
error: "command.target.kind must be one of: app, file"
|
|
1374
1387
|
};
|
|
1375
|
-
if (
|
|
1376
|
-
const path = asTrimmed(
|
|
1388
|
+
if (kind === "file") {
|
|
1389
|
+
const path = asTrimmed(target.path);
|
|
1377
1390
|
if (!path) return {
|
|
1378
1391
|
command: null,
|
|
1379
|
-
error: "command.
|
|
1392
|
+
error: "command.target.path is required"
|
|
1380
1393
|
};
|
|
1381
1394
|
if (path.length > 2048 || path.startsWith("/") || path.includes("\0") || path.includes("\\") || path.split("/").some((segment) => segment === "..")) return {
|
|
1382
1395
|
command: null,
|
|
1383
|
-
error: "command.
|
|
1396
|
+
error: "command.target.path must be a relative Space file path"
|
|
1384
1397
|
};
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
kind: "file",
|
|
1389
|
-
path
|
|
1390
|
-
}
|
|
1398
|
+
if (input.call !== void 0 && input.call !== null) return {
|
|
1399
|
+
command: null,
|
|
1400
|
+
error: "command.call is only supported for app targets"
|
|
1391
1401
|
};
|
|
1392
|
-
if (input.request !== void 0 && input.request !== null) return {
|
|
1402
|
+
if (legacy && input.request !== void 0 && input.request !== null) return {
|
|
1393
1403
|
command: null,
|
|
1394
|
-
error: "command.
|
|
1404
|
+
error: "command.call is only supported for app targets"
|
|
1395
1405
|
};
|
|
1396
1406
|
return {
|
|
1397
|
-
command
|
|
1407
|
+
command: {
|
|
1408
|
+
type: "desktop.open",
|
|
1409
|
+
target: {
|
|
1410
|
+
kind: "file",
|
|
1411
|
+
path
|
|
1412
|
+
}
|
|
1413
|
+
},
|
|
1398
1414
|
error: null
|
|
1399
1415
|
};
|
|
1400
1416
|
}
|
|
1401
|
-
const
|
|
1402
|
-
if (!
|
|
1417
|
+
const appId = asTrimmed(target.appId ?? target.workId);
|
|
1418
|
+
if (!appId) return {
|
|
1403
1419
|
command: null,
|
|
1404
|
-
error: "command.
|
|
1420
|
+
error: "command.target.appId is required"
|
|
1405
1421
|
};
|
|
1406
|
-
if (!isUuid(
|
|
1422
|
+
if (!isUuid(appId)) return {
|
|
1407
1423
|
command: null,
|
|
1408
|
-
error: "command.
|
|
1424
|
+
error: "command.target.appId must be an App id"
|
|
1409
1425
|
};
|
|
1410
|
-
const label = asTrimmed(
|
|
1426
|
+
const label = asTrimmed(target.label);
|
|
1411
1427
|
if (label && label.length > 200) return {
|
|
1412
1428
|
command: null,
|
|
1413
|
-
error: `command.
|
|
1429
|
+
error: `command.target.label exceeds 200 characters`
|
|
1414
1430
|
};
|
|
1415
|
-
const launch = parseLaunch(
|
|
1431
|
+
const launch = parseLaunch(target.launch);
|
|
1416
1432
|
if (launch) {
|
|
1417
1433
|
for (const [field, value] of [["search", launch.search], ["hash", launch.hash]]) if (value && value.length > 2048) return {
|
|
1418
1434
|
command: null,
|
|
1419
|
-
error: `command.
|
|
1435
|
+
error: `command.target.launch.${field} exceeds ${DESKTOP_COMMAND_LAUNCH_MAX_LENGTH} characters`
|
|
1420
1436
|
};
|
|
1421
1437
|
}
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1438
|
+
const callSource = input.call !== void 0 ? input.call : input.request;
|
|
1439
|
+
let call;
|
|
1440
|
+
if (callSource !== void 0 && callSource !== null) {
|
|
1441
|
+
if (!isRecord$1(callSource)) return {
|
|
1425
1442
|
command: null,
|
|
1426
|
-
error: "command.
|
|
1443
|
+
error: "command.call must be an object"
|
|
1427
1444
|
};
|
|
1428
|
-
const method = asTrimmed(
|
|
1445
|
+
const method = asTrimmed(callSource.method);
|
|
1429
1446
|
if (!method) return {
|
|
1430
1447
|
command: null,
|
|
1431
|
-
error: "command.
|
|
1448
|
+
error: "command.call.method is required"
|
|
1432
1449
|
};
|
|
1433
|
-
if (!
|
|
1450
|
+
if (!isDesktopCallMethod(method)) return {
|
|
1434
1451
|
command: null,
|
|
1435
|
-
error: "command.
|
|
1452
|
+
error: "command.call.method has an unsupported format"
|
|
1436
1453
|
};
|
|
1437
|
-
const size =
|
|
1454
|
+
const size = measureDesktopCommandPayload(callSource.input);
|
|
1438
1455
|
if (size === null) return {
|
|
1439
1456
|
command: null,
|
|
1440
|
-
error: "command.
|
|
1457
|
+
error: "command.call.input must be JSON-serializable"
|
|
1441
1458
|
};
|
|
1442
1459
|
if (size > 32768) return {
|
|
1443
1460
|
command: null,
|
|
1444
|
-
error: `command.
|
|
1461
|
+
error: `command.call.input exceeds ${DESKTOP_COMMAND_PAYLOAD_MAX_BYTES} bytes`
|
|
1445
1462
|
};
|
|
1446
|
-
|
|
1463
|
+
call = {
|
|
1447
1464
|
method,
|
|
1448
|
-
...
|
|
1465
|
+
...callSource.input === void 0 ? {} : { input: callSource.input }
|
|
1449
1466
|
};
|
|
1450
1467
|
}
|
|
1451
1468
|
const command = {
|
|
1452
|
-
type: "
|
|
1453
|
-
|
|
1454
|
-
kind: "
|
|
1455
|
-
|
|
1469
|
+
type: "desktop.open",
|
|
1470
|
+
target: {
|
|
1471
|
+
kind: "app",
|
|
1472
|
+
appId,
|
|
1456
1473
|
...label ? { label } : {},
|
|
1457
1474
|
...launch ? { launch } : {}
|
|
1458
1475
|
},
|
|
1459
|
-
...
|
|
1476
|
+
...call ? { call } : {}
|
|
1460
1477
|
};
|
|
1461
|
-
const totalSize =
|
|
1478
|
+
const totalSize = measureDesktopCommandPayload(command);
|
|
1462
1479
|
if (totalSize === null) return {
|
|
1463
1480
|
command: null,
|
|
1464
1481
|
error: "command must be JSON-serializable"
|
|
1465
1482
|
};
|
|
1466
1483
|
if (totalSize > 40960) return {
|
|
1467
1484
|
command: null,
|
|
1468
|
-
error: `command exceeds ${
|
|
1485
|
+
error: `command exceeds ${DESKTOP_COMMAND_MAX_BYTES} bytes`
|
|
1469
1486
|
};
|
|
1470
1487
|
return {
|
|
1471
1488
|
command,
|
|
@@ -3113,7 +3130,7 @@ var SpaceEventsApi = class {
|
|
|
3113
3130
|
handler(event);
|
|
3114
3131
|
return;
|
|
3115
3132
|
}
|
|
3116
|
-
if (type === "
|
|
3133
|
+
if (type === "app.version.published" && event.type === "app.version.published") {
|
|
3117
3134
|
handler(event);
|
|
3118
3135
|
return;
|
|
3119
3136
|
}
|
|
@@ -4000,79 +4017,6 @@ var TasksApi = class {
|
|
|
4000
4017
|
}
|
|
4001
4018
|
};
|
|
4002
4019
|
//#endregion
|
|
4003
|
-
//#region src/apis/ui-commands.ts
|
|
4004
|
-
const DEFAULT_POLL_INTERVAL_MS = 300;
|
|
4005
|
-
const resolveTimeoutMs = (timeoutMs) => {
|
|
4006
|
-
const value = timeoutMs ?? 6e5;
|
|
4007
|
-
if (!Number.isFinite(value) || value <= 0 || value > 432e5) throw new RangeError(`timeoutMs must be between 1 and ${UI_COMMAND_MAX_TIMEOUT_MS} milliseconds`);
|
|
4008
|
-
return value;
|
|
4009
|
-
};
|
|
4010
|
-
const sleep = (ms, signal) => new Promise((resolve, reject) => {
|
|
4011
|
-
if (signal?.aborted) {
|
|
4012
|
-
reject(/* @__PURE__ */ new Error("aborted"));
|
|
4013
|
-
return;
|
|
4014
|
-
}
|
|
4015
|
-
const timer = setTimeout(() => {
|
|
4016
|
-
signal?.removeEventListener("abort", onAbort);
|
|
4017
|
-
resolve();
|
|
4018
|
-
}, ms);
|
|
4019
|
-
const onAbort = () => {
|
|
4020
|
-
clearTimeout(timer);
|
|
4021
|
-
reject(/* @__PURE__ */ new Error("aborted"));
|
|
4022
|
-
};
|
|
4023
|
-
signal?.addEventListener("abort", onAbort, { once: true });
|
|
4024
|
-
});
|
|
4025
|
-
var UiCommandsApi = class {
|
|
4026
|
-
transport;
|
|
4027
|
-
constructor(transport) {
|
|
4028
|
-
this.transport = transport;
|
|
4029
|
-
}
|
|
4030
|
-
create(input) {
|
|
4031
|
-
return this.transport.request("/api/ui/commands", {
|
|
4032
|
-
method: "POST",
|
|
4033
|
-
headers: { "Content-Type": "application/json" },
|
|
4034
|
-
body: JSON.stringify(input)
|
|
4035
|
-
});
|
|
4036
|
-
}
|
|
4037
|
-
get(commandId) {
|
|
4038
|
-
return this.transport.request(`/api/ui/commands/${encodeURIComponent(commandId)}`);
|
|
4039
|
-
}
|
|
4040
|
-
reportResult(commandId, input) {
|
|
4041
|
-
return this.transport.request(`/api/ui/commands/${encodeURIComponent(commandId)}/result`, {
|
|
4042
|
-
method: "POST",
|
|
4043
|
-
headers: { "Content-Type": "application/json" },
|
|
4044
|
-
body: JSON.stringify(input)
|
|
4045
|
-
});
|
|
4046
|
-
}
|
|
4047
|
-
async run(input, options = {}) {
|
|
4048
|
-
const { command } = await this.create(input);
|
|
4049
|
-
if (isTerminalUiCommandStatus(command.status)) return command;
|
|
4050
|
-
return this.wait(command.commandId, options);
|
|
4051
|
-
}
|
|
4052
|
-
async wait(commandId, options = {}) {
|
|
4053
|
-
const timeoutMs = resolveTimeoutMs(options.timeoutMs);
|
|
4054
|
-
const pollIntervalMs = Math.max(50, options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS);
|
|
4055
|
-
const deadline = Date.now() + timeoutMs;
|
|
4056
|
-
let latest = (await this.get(commandId)).command;
|
|
4057
|
-
while (!isTerminalUiCommandStatus(latest.status)) {
|
|
4058
|
-
const remaining = deadline - Date.now();
|
|
4059
|
-
if (remaining <= 0) break;
|
|
4060
|
-
await sleep(Math.min(pollIntervalMs, remaining), options.signal);
|
|
4061
|
-
latest = (await this.get(commandId)).command;
|
|
4062
|
-
}
|
|
4063
|
-
if (isTerminalUiCommandStatus(latest.status)) return latest;
|
|
4064
|
-
return {
|
|
4065
|
-
...latest,
|
|
4066
|
-
status: "timeout",
|
|
4067
|
-
error: {
|
|
4068
|
-
code: "timeout",
|
|
4069
|
-
message: "No Cohub frontend reported a result before the timeout."
|
|
4070
|
-
},
|
|
4071
|
-
settledAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
4072
|
-
};
|
|
4073
|
-
}
|
|
4074
|
-
};
|
|
4075
|
-
//#endregion
|
|
4076
4020
|
//#region src/apis/user.ts
|
|
4077
4021
|
const usageDate = (value) => value instanceof Date ? value.toISOString() : value;
|
|
4078
4022
|
var UserApi = class {
|
|
@@ -4200,131 +4144,208 @@ var ReferralsApi = class {
|
|
|
4200
4144
|
}
|
|
4201
4145
|
};
|
|
4202
4146
|
//#endregion
|
|
4203
|
-
//#region src/apis/
|
|
4204
|
-
var
|
|
4147
|
+
//#region src/apis/apps.ts
|
|
4148
|
+
var AppsApi = class {
|
|
4205
4149
|
transport;
|
|
4206
4150
|
constructor(transport) {
|
|
4207
4151
|
this.transport = transport;
|
|
4208
4152
|
}
|
|
4209
4153
|
listBySpace(spaceId) {
|
|
4210
|
-
return this.transport.request(`/api/
|
|
4154
|
+
return this.transport.request(`/api/apps/space/${spaceId}`);
|
|
4211
4155
|
}
|
|
4212
4156
|
get(id) {
|
|
4213
|
-
return this.transport.request(`/api/
|
|
4157
|
+
return this.transport.request(`/api/apps/${id}`);
|
|
4214
4158
|
}
|
|
4215
4159
|
/**
|
|
4216
|
-
* Loads a published
|
|
4217
|
-
* Used by the standalone
|
|
4160
|
+
* Loads a published app's metadata + owner info by id (public access model).
|
|
4161
|
+
* Used by the standalone app auth broker page.
|
|
4218
4162
|
*/
|
|
4219
4163
|
getPublicById(id) {
|
|
4220
|
-
return this.transport.request(`/api/
|
|
4164
|
+
return this.transport.request(`/api/apps/${id}/public`);
|
|
4221
4165
|
}
|
|
4222
|
-
getBySlug(username, spaceSlug,
|
|
4223
|
-
return this.transport.request(`/api/
|
|
4166
|
+
getBySlug(username, spaceSlug, appSlug, options) {
|
|
4167
|
+
return this.transport.request(`/api/apps/by-slug/${encodeURIComponent(username)}/${encodeURIComponent(spaceSlug)}/${encodeURIComponent(appSlug)}`, options?.signal ? { signal: options.signal } : void 0);
|
|
4224
4168
|
}
|
|
4225
4169
|
create(input) {
|
|
4226
|
-
return this.transport.request("/api/
|
|
4170
|
+
return this.transport.request("/api/apps", {
|
|
4227
4171
|
method: "POST",
|
|
4228
4172
|
headers: { "Content-Type": "application/json" },
|
|
4229
4173
|
body: JSON.stringify(input)
|
|
4230
4174
|
});
|
|
4231
4175
|
}
|
|
4232
4176
|
update(id, input) {
|
|
4233
|
-
return this.transport.request(`/api/
|
|
4177
|
+
return this.transport.request(`/api/apps/${id}`, {
|
|
4234
4178
|
method: "PATCH",
|
|
4235
4179
|
headers: { "Content-Type": "application/json" },
|
|
4236
4180
|
body: JSON.stringify(input)
|
|
4237
4181
|
});
|
|
4238
4182
|
}
|
|
4239
4183
|
delete(id) {
|
|
4240
|
-
return this.transport.request(`/api/
|
|
4184
|
+
return this.transport.request(`/api/apps/${id}`, { method: "DELETE" });
|
|
4241
4185
|
}
|
|
4242
|
-
getStats(
|
|
4243
|
-
return this.transport.request(`/api/
|
|
4186
|
+
getStats(appId) {
|
|
4187
|
+
return this.transport.request(`/api/apps/${appId}/stats`);
|
|
4244
4188
|
}
|
|
4245
|
-
listPromotions(
|
|
4246
|
-
return this.transport.request(`/api/
|
|
4189
|
+
listPromotions(appId) {
|
|
4190
|
+
return this.transport.request(`/api/apps/${appId}/promotions`);
|
|
4247
4191
|
}
|
|
4248
|
-
createPromotion(
|
|
4249
|
-
return this.transport.request(`/api/
|
|
4192
|
+
createPromotion(appId, input) {
|
|
4193
|
+
return this.transport.request(`/api/apps/${appId}/promotions`, {
|
|
4250
4194
|
method: "POST",
|
|
4251
4195
|
headers: { "Content-Type": "application/json" },
|
|
4252
4196
|
body: JSON.stringify(input)
|
|
4253
4197
|
});
|
|
4254
4198
|
}
|
|
4255
|
-
getPromotionStats(
|
|
4256
|
-
return this.transport.request(`/api/
|
|
4199
|
+
getPromotionStats(appId, promotionId) {
|
|
4200
|
+
return this.transport.request(`/api/apps/${appId}/promotions/${promotionId}/stats`);
|
|
4257
4201
|
}
|
|
4258
|
-
recordPromotionEvent(
|
|
4259
|
-
return this.transport.request(`/api/
|
|
4202
|
+
recordPromotionEvent(appId, promotionId, input) {
|
|
4203
|
+
return this.transport.request(`/api/apps/${appId}/promotions/${promotionId}/events`, {
|
|
4260
4204
|
method: "POST",
|
|
4261
4205
|
headers: { "Content-Type": "application/json" },
|
|
4262
4206
|
body: JSON.stringify(input)
|
|
4263
4207
|
});
|
|
4264
4208
|
}
|
|
4265
|
-
recordPromotionRegistration(
|
|
4266
|
-
return this.transport.request(`/api/
|
|
4209
|
+
recordPromotionRegistration(appId, promotionId, input) {
|
|
4210
|
+
return this.transport.request(`/api/apps/${appId}/promotions/${promotionId}/registration`, {
|
|
4267
4211
|
method: "POST",
|
|
4268
4212
|
headers: input ? { "Content-Type": "application/json" } : void 0,
|
|
4269
4213
|
body: input ? JSON.stringify(input) : void 0
|
|
4270
4214
|
});
|
|
4271
4215
|
}
|
|
4272
|
-
listVersions(
|
|
4273
|
-
return this.transport.request(`/api/
|
|
4216
|
+
listVersions(appId) {
|
|
4217
|
+
return this.transport.request(`/api/apps/${appId}/versions`);
|
|
4274
4218
|
}
|
|
4275
|
-
publishVersion(
|
|
4276
|
-
return this.transport.request(`/api/
|
|
4219
|
+
publishVersion(appId, input) {
|
|
4220
|
+
return this.transport.request(`/api/apps/${appId}/versions`, {
|
|
4277
4221
|
method: "POST",
|
|
4278
4222
|
headers: input ? { "Content-Type": "application/json" } : void 0,
|
|
4279
4223
|
body: input ? JSON.stringify(input) : void 0
|
|
4280
4224
|
});
|
|
4281
4225
|
}
|
|
4282
|
-
createSession(
|
|
4283
|
-
return this.transport.request(`/api/
|
|
4226
|
+
createSession(appId) {
|
|
4227
|
+
return this.transport.request(`/api/apps/${appId}/session`, { method: "POST" });
|
|
4228
|
+
}
|
|
4229
|
+
authorize(appId, input) {
|
|
4230
|
+
return this.transport.request(`/api/apps/${appId}/authorize`, {
|
|
4231
|
+
method: "POST",
|
|
4232
|
+
headers: { "Content-Type": "application/json" },
|
|
4233
|
+
body: JSON.stringify(input)
|
|
4234
|
+
});
|
|
4235
|
+
}
|
|
4236
|
+
};
|
|
4237
|
+
//#endregion
|
|
4238
|
+
//#region src/apis/desktop-commands.ts
|
|
4239
|
+
const DEFAULT_POLL_INTERVAL_MS = 300;
|
|
4240
|
+
const resolveTimeoutMs = (timeoutMs) => {
|
|
4241
|
+
const value = timeoutMs ?? 6e5;
|
|
4242
|
+
if (!Number.isFinite(value) || value <= 0 || value > 432e5) throw new RangeError(`timeoutMs must be between 1 and ${DESKTOP_COMMAND_MAX_TIMEOUT_MS} milliseconds`);
|
|
4243
|
+
return value;
|
|
4244
|
+
};
|
|
4245
|
+
const sleep = (ms, signal) => new Promise((resolve, reject) => {
|
|
4246
|
+
if (signal?.aborted) {
|
|
4247
|
+
reject(/* @__PURE__ */ new Error("aborted"));
|
|
4248
|
+
return;
|
|
4249
|
+
}
|
|
4250
|
+
const timer = setTimeout(() => {
|
|
4251
|
+
signal?.removeEventListener("abort", onAbort);
|
|
4252
|
+
resolve();
|
|
4253
|
+
}, ms);
|
|
4254
|
+
const onAbort = () => {
|
|
4255
|
+
clearTimeout(timer);
|
|
4256
|
+
reject(/* @__PURE__ */ new Error("aborted"));
|
|
4257
|
+
};
|
|
4258
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
4259
|
+
});
|
|
4260
|
+
var DesktopCommandsApi = class {
|
|
4261
|
+
transport;
|
|
4262
|
+
constructor(transport) {
|
|
4263
|
+
this.transport = transport;
|
|
4264
|
+
}
|
|
4265
|
+
create(input) {
|
|
4266
|
+
return this.transport.request("/api/desktop/commands", {
|
|
4267
|
+
method: "POST",
|
|
4268
|
+
headers: { "Content-Type": "application/json" },
|
|
4269
|
+
body: JSON.stringify(input)
|
|
4270
|
+
});
|
|
4271
|
+
}
|
|
4272
|
+
get(commandId) {
|
|
4273
|
+
return this.transport.request(`/api/desktop/commands/${encodeURIComponent(commandId)}`);
|
|
4284
4274
|
}
|
|
4285
|
-
|
|
4286
|
-
return this.transport.request(`/api/
|
|
4275
|
+
reportResult(commandId, input) {
|
|
4276
|
+
return this.transport.request(`/api/desktop/commands/${encodeURIComponent(commandId)}/result`, {
|
|
4287
4277
|
method: "POST",
|
|
4288
4278
|
headers: { "Content-Type": "application/json" },
|
|
4289
4279
|
body: JSON.stringify(input)
|
|
4290
4280
|
});
|
|
4291
4281
|
}
|
|
4282
|
+
async run(input, options = {}) {
|
|
4283
|
+
const { command } = await this.create(input);
|
|
4284
|
+
if (isTerminalDesktopCommandStatus(command.status)) return command;
|
|
4285
|
+
return this.wait(command.commandId, options);
|
|
4286
|
+
}
|
|
4287
|
+
async wait(commandId, options = {}) {
|
|
4288
|
+
const timeoutMs = resolveTimeoutMs(options.timeoutMs);
|
|
4289
|
+
const pollIntervalMs = Math.max(50, options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS);
|
|
4290
|
+
const deadline = Date.now() + timeoutMs;
|
|
4291
|
+
let latest = (await this.get(commandId)).command;
|
|
4292
|
+
while (!isTerminalDesktopCommandStatus(latest.status)) {
|
|
4293
|
+
const remaining = deadline - Date.now();
|
|
4294
|
+
if (remaining <= 0) break;
|
|
4295
|
+
await sleep(Math.min(pollIntervalMs, remaining), options.signal);
|
|
4296
|
+
latest = (await this.get(commandId)).command;
|
|
4297
|
+
}
|
|
4298
|
+
if (isTerminalDesktopCommandStatus(latest.status)) return latest;
|
|
4299
|
+
return {
|
|
4300
|
+
...latest,
|
|
4301
|
+
status: "timeout",
|
|
4302
|
+
error: {
|
|
4303
|
+
code: "timeout",
|
|
4304
|
+
message: "No Cohub desktop reported a result before the timeout."
|
|
4305
|
+
},
|
|
4306
|
+
settledAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
4307
|
+
};
|
|
4308
|
+
}
|
|
4292
4309
|
};
|
|
4310
|
+
/** @deprecated Use `DesktopCommandsApi`. */
|
|
4311
|
+
var UiCommandsApi = class extends DesktopCommandsApi {};
|
|
4293
4312
|
//#endregion
|
|
4294
|
-
//#region src/apis/
|
|
4295
|
-
var
|
|
4313
|
+
//#region src/apis/app-commerce.ts
|
|
4314
|
+
var AppCommerceApi = class {
|
|
4296
4315
|
transport;
|
|
4297
4316
|
constructor(transport) {
|
|
4298
4317
|
this.transport = transport;
|
|
4299
4318
|
}
|
|
4300
|
-
resolveProducts(
|
|
4301
|
-
return this.transport.request(`/api/
|
|
4319
|
+
resolveProducts(appId, input) {
|
|
4320
|
+
return this.transport.request(`/api/apps/${encodeURIComponent(appId)}/commerce/products/resolve`, {
|
|
4302
4321
|
method: "POST",
|
|
4303
4322
|
headers: { "Content-Type": "application/json" },
|
|
4304
4323
|
body: JSON.stringify(input)
|
|
4305
4324
|
});
|
|
4306
4325
|
}
|
|
4307
|
-
getEntitlements(
|
|
4308
|
-
return this.transport.request(`/api/
|
|
4326
|
+
getEntitlements(appId) {
|
|
4327
|
+
return this.transport.request(`/api/apps/${encodeURIComponent(appId)}/commerce/entitlements`);
|
|
4309
4328
|
}
|
|
4310
|
-
consumeCredits(
|
|
4311
|
-
return this.transport.request(`/api/
|
|
4329
|
+
consumeCredits(appId, input) {
|
|
4330
|
+
return this.transport.request(`/api/apps/${encodeURIComponent(appId)}/commerce/credits/consume`, {
|
|
4312
4331
|
method: "POST",
|
|
4313
4332
|
headers: { "Content-Type": "application/json" },
|
|
4314
4333
|
body: JSON.stringify(input)
|
|
4315
4334
|
});
|
|
4316
4335
|
}
|
|
4317
|
-
purchase(
|
|
4318
|
-
return this.transport.request(`/api/
|
|
4336
|
+
purchase(appId, input) {
|
|
4337
|
+
return this.transport.request(`/api/apps/${encodeURIComponent(appId)}/commerce/purchase`, {
|
|
4319
4338
|
method: "POST",
|
|
4320
4339
|
headers: { "Content-Type": "application/json" },
|
|
4321
4340
|
body: JSON.stringify(input)
|
|
4322
4341
|
});
|
|
4323
4342
|
}
|
|
4324
|
-
getOrder(
|
|
4325
|
-
return this.transport.request(`/api/
|
|
4343
|
+
getOrder(appId, orderId) {
|
|
4344
|
+
return this.transport.request(`/api/apps/${encodeURIComponent(appId)}/commerce/orders/${encodeURIComponent(orderId)}`);
|
|
4326
4345
|
}
|
|
4327
4346
|
};
|
|
4347
|
+
/** @deprecated Use `AppCommerceApi`. */
|
|
4348
|
+
var WorkCommerceApi = class extends AppCommerceApi {};
|
|
4328
4349
|
//#endregion
|
|
4329
4350
|
//#region src/http.ts
|
|
4330
4351
|
var CohubHttpClient = class {
|
|
@@ -4344,9 +4365,21 @@ var CohubHttpClient = class {
|
|
|
4344
4365
|
cronJobs;
|
|
4345
4366
|
invite;
|
|
4346
4367
|
referrals;
|
|
4347
|
-
|
|
4348
|
-
|
|
4349
|
-
|
|
4368
|
+
apps;
|
|
4369
|
+
appCommerce;
|
|
4370
|
+
/** @deprecated Use `apps`. */
|
|
4371
|
+
get works() {
|
|
4372
|
+
return this.apps;
|
|
4373
|
+
}
|
|
4374
|
+
/** @deprecated Use `appCommerce`. */
|
|
4375
|
+
get workCommerce() {
|
|
4376
|
+
return this.appCommerce;
|
|
4377
|
+
}
|
|
4378
|
+
desktop;
|
|
4379
|
+
/** @deprecated Use `desktop`. */
|
|
4380
|
+
get ui() {
|
|
4381
|
+
return this.desktop;
|
|
4382
|
+
}
|
|
4350
4383
|
transport;
|
|
4351
4384
|
constructor(options = {}) {
|
|
4352
4385
|
const apiBaseUrl = resolveApiBaseUrl(options);
|
|
@@ -4367,9 +4400,9 @@ var CohubHttpClient = class {
|
|
|
4367
4400
|
this.cronJobs = new CronJobsApi(this.transport);
|
|
4368
4401
|
this.invite = new PublicInviteApi(this.transport);
|
|
4369
4402
|
this.referrals = new ReferralsApi(this.transport);
|
|
4370
|
-
this.
|
|
4371
|
-
this.
|
|
4372
|
-
this.
|
|
4403
|
+
this.apps = new AppsApi(this.transport);
|
|
4404
|
+
this.appCommerce = new AppCommerceApi(this.transport);
|
|
4405
|
+
this.desktop = new DesktopCommandsApi(this.transport);
|
|
4373
4406
|
}
|
|
4374
4407
|
space(spaceId) {
|
|
4375
4408
|
return new SpaceClient(spaceId, this.transport, null);
|
|
@@ -4377,4 +4410,4 @@ var CohubHttpClient = class {
|
|
|
4377
4410
|
};
|
|
4378
4411
|
const createHttpClient = (options) => new CohubHttpClient(options);
|
|
4379
4412
|
//#endregion
|
|
4380
|
-
export {
|
|
4413
|
+
export { BOARD_BUILTIN_EFFECT_KINDS as $, DESKTOP_COMMAND_TERMINAL_TTL_SECONDS as A, BoardEffectSchema as B, createSessionPatchReducer as C, DESKTOP_COMMAND_PAYLOAD_MAX_BYTES as D, DESKTOP_COMMAND_MAX_TIMEOUT_MS as E, parseDesktopCommandId as F, BoardCompositionSchema as G, BOARD_ANIMATION_CHANNELS as H, BoardAuthoringItemSchema as I, parseBoardCompositionInput as J, BoardProceduralClipSchema as K, BoardItemPatchSchema as L, isDesktopCallMethod as M, isTerminalDesktopCommandStatus as N, DESKTOP_COMMAND_PENDING_TTL_SECONDS as O, parseDesktopCommand as P, BOARD_BUILTIN_CLIP_KINDS as Q, BoardSemanticMutationSchema as R, SessionPatchReducer as S, DESKTOP_COMMAND_DEFAULT_TIMEOUT_MS as T, BOARD_ANIMATION_CHANNEL_CAPABILITIES as U, parseBoardEffectInput as V, BoardCompositionInputSchema as W, BOARD_ARROW_STROKE_SIZE as X, BoardConnectionSchema as Y, BOARD_BUILTIN_CAPABILITIES as Z, buildSpaceInvitePath as _, DesktopCommandsApi as a, SkillsApi as at, createSessionGenerationStreamClient as b, ReferralsApi as c, GenerationsApi as ct, TasksApi as d, DEFAULT_BOARD_RENDER_LIMITS as et, BoardClient as f, PublicInviteApi as g, SpacesApi as h, WorkCommerceApi as i, PublicAssetsApi as it, DESKTOP_COMMAND_VERSION as j, DESKTOP_COMMAND_SETTLEMENT_GRACE_SECONDS as k, UsersApi as l, CronJobsApi as lt, SpacePublicFilesApi as m, createHttpClient as n, ReferencesApi as nt, UiCommandsApi as o, PromptsApi as ot, SpaceClient as p, BoardTrackSchema as q, AppCommerceApi as r, SearchApi as rt, AppsApi as s, ModelsApi as st, CohubHttpClient as t, SessionAccessApi as tt, UserApi as u, ChannelsApi as ut, buildSpacePath as v, ensureRealtimeConnected as w, parseAssistantMessageCommit as x, SessionGenerationStreamClient as y, BoardEffectInputSchema as z };
|
package/dist/chunks/transport.js
CHANGED
|
@@ -10,7 +10,8 @@ const REALTIME_DOMAINS = [
|
|
|
10
10
|
"space",
|
|
11
11
|
"label",
|
|
12
12
|
"room",
|
|
13
|
-
"ui"
|
|
13
|
+
"ui",
|
|
14
|
+
"desktop"
|
|
14
15
|
];
|
|
15
16
|
const isRealtimeDomain = (value) => typeof value === "string" && REALTIME_DOMAINS.some((domain) => domain === value);
|
|
16
17
|
/** Accepted room event names. Shared so a client can reject one before sending. */
|