@opengeni/sdk 0.11.0 → 0.15.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/README.md +34 -12
- package/dist/index.d.ts +658 -83
- package/dist/index.js +1043 -304
- package/dist/index.js.map +1 -1
- package/package.json +9 -9
- package/src/client.ts +1367 -352
- package/src/errors.ts +20 -1
- package/src/index.ts +80 -6
- package/src/proxy.ts +1 -1
- package/src/sse.ts +11 -8
- package/src/stream.ts +9 -2
- package/src/types.ts +892 -102
- package/src/workspace-control-stream.ts +101 -0
package/dist/index.js
CHANGED
|
@@ -9,6 +9,16 @@ var OpenGeniApiError = class extends Error {
|
|
|
9
9
|
this.body = body;
|
|
10
10
|
}
|
|
11
11
|
};
|
|
12
|
+
var OpenGeniApiContractMismatchError = class extends Error {
|
|
13
|
+
expected;
|
|
14
|
+
actual;
|
|
15
|
+
constructor(expected, actual) {
|
|
16
|
+
super(`OpenGeni API contract mismatch: client expects ${expected}, API serves ${actual}`);
|
|
17
|
+
this.name = "OpenGeniApiContractMismatchError";
|
|
18
|
+
this.expected = expected;
|
|
19
|
+
this.actual = actual;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
12
22
|
var OpenGeniStreamError = class extends Error {
|
|
13
23
|
constructor(message) {
|
|
14
24
|
super(message);
|
|
@@ -105,7 +115,8 @@ async function* streamSessionEvents(transport, options = {}) {
|
|
|
105
115
|
let failedAttempts = 0;
|
|
106
116
|
let delayMs = baseDelayMs;
|
|
107
117
|
let everConnected = false;
|
|
108
|
-
while (
|
|
118
|
+
while (true) {
|
|
119
|
+
if (signal?.aborted) break;
|
|
109
120
|
options.onStateChange?.(everConnected || failedAttempts > 0 ? "reconnecting" : "connecting");
|
|
110
121
|
const cursorAtOpen = cursor;
|
|
111
122
|
try {
|
|
@@ -113,6 +124,7 @@ async function* streamSessionEvents(transport, options = {}) {
|
|
|
113
124
|
everConnected = true;
|
|
114
125
|
failedAttempts = 0;
|
|
115
126
|
delayMs = baseDelayMs;
|
|
127
|
+
await options.beforeLive?.();
|
|
116
128
|
options.onStateChange?.("live");
|
|
117
129
|
for await (const message of parseSseStream(body)) {
|
|
118
130
|
if (signal?.aborted) {
|
|
@@ -207,6 +219,246 @@ async function sleep(delayMs, signal) {
|
|
|
207
219
|
});
|
|
208
220
|
}
|
|
209
221
|
|
|
222
|
+
// src/workspace-control-stream.ts
|
|
223
|
+
async function* streamWorkspaceControlEvents(transport, options = {}) {
|
|
224
|
+
const signal = options.signal;
|
|
225
|
+
const reconnect = options.reconnect ?? true;
|
|
226
|
+
const baseDelayMs = options.reconnectDelayMs ?? 500;
|
|
227
|
+
const maxDelayMs = options.maxReconnectDelayMs ?? 1e4;
|
|
228
|
+
const maxAttempts = options.maxReconnectAttempts ?? Number.POSITIVE_INFINITY;
|
|
229
|
+
let cursor = options.after ?? 0;
|
|
230
|
+
let failures = 0;
|
|
231
|
+
let delayMs = baseDelayMs;
|
|
232
|
+
let everConnected = false;
|
|
233
|
+
for (; ; ) {
|
|
234
|
+
if (signal?.aborted) return;
|
|
235
|
+
options.onStateChange?.(everConnected || failures > 0 ? "reconnecting" : "connecting");
|
|
236
|
+
const cursorAtOpen = cursor;
|
|
237
|
+
try {
|
|
238
|
+
const body = await transport.openStream(cursor, signal);
|
|
239
|
+
everConnected = true;
|
|
240
|
+
failures = 0;
|
|
241
|
+
delayMs = baseDelayMs;
|
|
242
|
+
await options.beforeLive?.();
|
|
243
|
+
options.onStateChange?.("live");
|
|
244
|
+
for await (const message of parseSseStream(body)) {
|
|
245
|
+
if (signal?.aborted) return;
|
|
246
|
+
const event = parseWorkspaceControlEvent(message.data);
|
|
247
|
+
if (!event || event.sequence <= cursor) continue;
|
|
248
|
+
cursor = event.sequence;
|
|
249
|
+
yield event;
|
|
250
|
+
}
|
|
251
|
+
if (!reconnect) return;
|
|
252
|
+
if (cursor === cursorAtOpen) await sleep2(baseDelayMs, signal);
|
|
253
|
+
continue;
|
|
254
|
+
} catch (error) {
|
|
255
|
+
if (signal?.aborted || isAbortError(error)) return;
|
|
256
|
+
if (!reconnect || !isRetryableStreamError(error)) throw error;
|
|
257
|
+
failures += 1;
|
|
258
|
+
if (failures > maxAttempts) {
|
|
259
|
+
throw new OpenGeniStreamError(
|
|
260
|
+
`workspace control stream gave up after ${maxAttempts} reconnect attempts: ${error instanceof Error ? error.message : String(error)}`
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
await sleep2(delayMs, signal);
|
|
265
|
+
delayMs = Math.min(Math.max(delayMs * 2, baseDelayMs), maxDelayMs);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
function parseWorkspaceControlEvent(data) {
|
|
269
|
+
let value;
|
|
270
|
+
try {
|
|
271
|
+
value = JSON.parse(data);
|
|
272
|
+
} catch {
|
|
273
|
+
return null;
|
|
274
|
+
}
|
|
275
|
+
if (typeof value !== "object" || value === null || value.type !== "workspace.control.changed" || typeof value.id !== "string" || typeof value.sequence !== "number") {
|
|
276
|
+
return null;
|
|
277
|
+
}
|
|
278
|
+
return value;
|
|
279
|
+
}
|
|
280
|
+
async function sleep2(delayMs, signal) {
|
|
281
|
+
if (signal?.aborted || delayMs <= 0) return;
|
|
282
|
+
await new Promise((resolve) => {
|
|
283
|
+
const timer = setTimeout(done, delayMs);
|
|
284
|
+
function done() {
|
|
285
|
+
clearTimeout(timer);
|
|
286
|
+
signal?.removeEventListener("abort", done);
|
|
287
|
+
resolve();
|
|
288
|
+
}
|
|
289
|
+
signal?.addEventListener("abort", done, { once: true });
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// src/types.ts
|
|
294
|
+
var SESSION_EVENT_TYPES = [
|
|
295
|
+
"session.created",
|
|
296
|
+
"session.status.changed",
|
|
297
|
+
"session.requiresAction",
|
|
298
|
+
"session.context.compaction.requested",
|
|
299
|
+
"session.context.compacted",
|
|
300
|
+
"session.context.compaction.skipped",
|
|
301
|
+
"session.context.cleared",
|
|
302
|
+
"user.message",
|
|
303
|
+
"user.pause",
|
|
304
|
+
"user.approvalDecision",
|
|
305
|
+
"turn.queued",
|
|
306
|
+
"turn.started",
|
|
307
|
+
"turn.completed",
|
|
308
|
+
"turn.failed",
|
|
309
|
+
"turn.cancelled",
|
|
310
|
+
"turn.superseded",
|
|
311
|
+
"turn.recovery.requested",
|
|
312
|
+
"turn.capacity_waiting",
|
|
313
|
+
"agent.message.delta",
|
|
314
|
+
"agent.message.completed",
|
|
315
|
+
"agent.reasoning.delta",
|
|
316
|
+
"agent.toolCall.created",
|
|
317
|
+
"agent.toolCall.output",
|
|
318
|
+
"agent.model.usage",
|
|
319
|
+
"tool.auth_needed",
|
|
320
|
+
"agent.updated",
|
|
321
|
+
"rig.setup.started",
|
|
322
|
+
"rig.setup.completed",
|
|
323
|
+
"rig.setup.skipped",
|
|
324
|
+
"rig.setup.failed",
|
|
325
|
+
"sandbox.operation.started",
|
|
326
|
+
"sandbox.operation.completed",
|
|
327
|
+
"sandbox.operation.failed",
|
|
328
|
+
"sandbox.command.output.delta",
|
|
329
|
+
"artifact.created",
|
|
330
|
+
"goal.set",
|
|
331
|
+
"goal.updated",
|
|
332
|
+
"goal.completed",
|
|
333
|
+
"goal.paused",
|
|
334
|
+
"goal.resumed",
|
|
335
|
+
"goal.cleared",
|
|
336
|
+
"goal.continuation",
|
|
337
|
+
"system.update.pending",
|
|
338
|
+
"system.update.delivered",
|
|
339
|
+
"session.control.paused",
|
|
340
|
+
"session.control.resumed",
|
|
341
|
+
"session.control.steer_requested",
|
|
342
|
+
"workspace.inference.paused",
|
|
343
|
+
"workspace.inference.resumed",
|
|
344
|
+
"session.queue.changed",
|
|
345
|
+
"session.queue.prompt.cancelled",
|
|
346
|
+
"session.queue.history",
|
|
347
|
+
"turn.event.rejected_late",
|
|
348
|
+
"memory.saved",
|
|
349
|
+
"memory.corrected",
|
|
350
|
+
// Channel-B desktop pixel-plane signals (mirror of contracts SessionEventType;
|
|
351
|
+
// the contract-parity test asserts sorted equality).
|
|
352
|
+
"stream.url.rotated",
|
|
353
|
+
"stream.opened",
|
|
354
|
+
"stream.closed",
|
|
355
|
+
"stream.revoked",
|
|
356
|
+
// Channel-B recording signals (P4.3 — "agent films itself proving the fix").
|
|
357
|
+
"recording.started",
|
|
358
|
+
"recording.available",
|
|
359
|
+
"recording.failed",
|
|
360
|
+
// Channel-A structured-service notifications (P4.4; mirror of contracts
|
|
361
|
+
// SessionEventType — the contract-parity test asserts sorted equality).
|
|
362
|
+
"fs.changed",
|
|
363
|
+
"git.changed",
|
|
364
|
+
"terminal.pty.started",
|
|
365
|
+
"terminal.pty.output.delta",
|
|
366
|
+
"terminal.pty.exited",
|
|
367
|
+
"session.title_set",
|
|
368
|
+
// Multi-account Codex (P1): the session's inference account changed.
|
|
369
|
+
"codex.account.switched",
|
|
370
|
+
// OPE-21 metadata-only per-turn credential selection audit.
|
|
371
|
+
"codex.credential.selected",
|
|
372
|
+
// OPE-21 durable zero-capacity wait lifecycle. These are system/runtime
|
|
373
|
+
// events, never synthetic user messages.
|
|
374
|
+
"codex.capacity.waiting",
|
|
375
|
+
"codex.capacity.resumed",
|
|
376
|
+
"codex.capacity.superseded",
|
|
377
|
+
// Sandbox durability observability (mirror of contracts SessionEventType):
|
|
378
|
+
// box lifecycle + manifest-env drift, attributable from the DB alone.
|
|
379
|
+
"sandbox.box.created",
|
|
380
|
+
"sandbox.box.lost",
|
|
381
|
+
"sandbox.box.terminated",
|
|
382
|
+
"sandbox.box.snapshot",
|
|
383
|
+
"sandbox.env.drift",
|
|
384
|
+
// Active-sandbox pointer reconcile (issue #341; announce-only; mirror of contracts
|
|
385
|
+
// SessionEventType — the contract-parity test asserts sorted equality).
|
|
386
|
+
"session.route.reconciled",
|
|
387
|
+
// Workbench v2 turn-end workspace capture (announce-only; mirror of contracts
|
|
388
|
+
// SessionEventType — the contract-parity test asserts sorted equality).
|
|
389
|
+
"workspace.revision.captured",
|
|
390
|
+
"workspace.revision.degraded",
|
|
391
|
+
// Connected Machine op-outcome observability (announce-only, quiet; mirror of
|
|
392
|
+
// contracts SessionEventType — the contract-parity test asserts sorted equality).
|
|
393
|
+
"machine.op.failed",
|
|
394
|
+
"machine.op.recovered",
|
|
395
|
+
// Connected Machine link-plane observability (announce-only, quiet; mirror of
|
|
396
|
+
// contracts SessionEventType — the contract-parity test asserts sorted equality).
|
|
397
|
+
"machine.link.lost",
|
|
398
|
+
"machine.link.restored",
|
|
399
|
+
"machine.runner.restarted"
|
|
400
|
+
];
|
|
401
|
+
var KNOWN_PERMISSIONS = [
|
|
402
|
+
"account:read",
|
|
403
|
+
"account:admin",
|
|
404
|
+
"members:manage",
|
|
405
|
+
"workspace:create",
|
|
406
|
+
"billing:read",
|
|
407
|
+
"billing:manage",
|
|
408
|
+
"workspace:read",
|
|
409
|
+
"workspace:admin",
|
|
410
|
+
"sessions:create",
|
|
411
|
+
"sessions:read",
|
|
412
|
+
"sessions:control",
|
|
413
|
+
// Sandbox-surfacing (mirror of @opengeni/contracts Permission). stream:view is
|
|
414
|
+
// strictly broader than sessions:read (un-redacted pixels); stream:control is
|
|
415
|
+
// the never-granted-v1 raw-input plane; stream:acknowledge is the secret-leak
|
|
416
|
+
// consent gate.
|
|
417
|
+
"stream:view",
|
|
418
|
+
"stream:control",
|
|
419
|
+
"stream:acknowledge",
|
|
420
|
+
"files:upload",
|
|
421
|
+
"files:read",
|
|
422
|
+
"files:write",
|
|
423
|
+
"terminal:attach",
|
|
424
|
+
"documents:manage",
|
|
425
|
+
"documents:search",
|
|
426
|
+
"scheduled_tasks:manage",
|
|
427
|
+
"scheduled_tasks:run",
|
|
428
|
+
"github:manage",
|
|
429
|
+
"github:use",
|
|
430
|
+
"api_keys:manage",
|
|
431
|
+
"connections:read",
|
|
432
|
+
"connections:write",
|
|
433
|
+
"environments:manage",
|
|
434
|
+
"environments:use",
|
|
435
|
+
"variable-sets:manage",
|
|
436
|
+
"variable-sets:use",
|
|
437
|
+
"mcp_servers:attach",
|
|
438
|
+
"toolspace:call",
|
|
439
|
+
"goals:manage",
|
|
440
|
+
"enrollments:read",
|
|
441
|
+
"enrollments:manage",
|
|
442
|
+
"rigs:use",
|
|
443
|
+
"rigs:manage"
|
|
444
|
+
];
|
|
445
|
+
var OPENGENI_API_CONTRACT_REVISION = "2026-07-session-control-v1";
|
|
446
|
+
var OPENGENI_API_CONTRACT_HEADER = "x-opengeni-api-contract";
|
|
447
|
+
var KNOWN_USAGE_EVENT_TYPES = [
|
|
448
|
+
"agent_run.created",
|
|
449
|
+
"agent_run.completed",
|
|
450
|
+
"model.tokens",
|
|
451
|
+
"model.cost",
|
|
452
|
+
"file.uploaded",
|
|
453
|
+
"file.deleted",
|
|
454
|
+
"document.indexed",
|
|
455
|
+
"scheduled_task.fired",
|
|
456
|
+
"api_key.request",
|
|
457
|
+
// sandbox warm-time metering (P2.1) — mirrors contracts UsageEventType.
|
|
458
|
+
"sandbox.warm_seconds",
|
|
459
|
+
"sandbox.warm_cost"
|
|
460
|
+
];
|
|
461
|
+
|
|
210
462
|
// src/client.ts
|
|
211
463
|
var OpenGeniClient = class {
|
|
212
464
|
baseUrl;
|
|
@@ -219,23 +471,79 @@ var OpenGeniClient = class {
|
|
|
219
471
|
}
|
|
220
472
|
// --- Session lifecycle ---------------------------------------------------
|
|
221
473
|
async createSession(workspaceId, request) {
|
|
222
|
-
return await this.requestJson(
|
|
474
|
+
return await this.requestJson(
|
|
475
|
+
"POST",
|
|
476
|
+
`/v1/workspaces/${workspaceId}/sessions`,
|
|
477
|
+
request
|
|
478
|
+
);
|
|
223
479
|
}
|
|
224
480
|
async getSession(workspaceId, sessionId) {
|
|
225
|
-
return await this.requestJson(
|
|
481
|
+
return await this.requestJson(
|
|
482
|
+
"GET",
|
|
483
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}`
|
|
484
|
+
);
|
|
226
485
|
}
|
|
227
486
|
async updateSession(workspaceId, sessionId, request) {
|
|
228
|
-
return await this.requestJson(
|
|
487
|
+
return await this.requestJson(
|
|
488
|
+
"PATCH",
|
|
489
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}`,
|
|
490
|
+
request
|
|
491
|
+
);
|
|
229
492
|
}
|
|
230
493
|
async listSessions(workspaceId, options = {}) {
|
|
231
|
-
return await this.requestJson(
|
|
232
|
-
|
|
233
|
-
|
|
494
|
+
return await this.requestJson(
|
|
495
|
+
"GET",
|
|
496
|
+
`/v1/workspaces/${workspaceId}/sessions`,
|
|
497
|
+
void 0,
|
|
498
|
+
{
|
|
499
|
+
...options.limit !== void 0 ? { limit: String(options.limit) } : {},
|
|
500
|
+
...options.search?.trim() ? { search: options.search.trim() } : {},
|
|
501
|
+
...Object.prototype.hasOwnProperty.call(options, "parentSessionId") && options.parentSessionId !== void 0 ? {
|
|
502
|
+
parentSessionId: options.parentSessionId === null ? "null" : String(options.parentSessionId)
|
|
503
|
+
} : {}
|
|
504
|
+
}
|
|
505
|
+
);
|
|
506
|
+
}
|
|
507
|
+
/** Pin-aware ordinary-session page with a stable keyset cursor. */
|
|
508
|
+
async listSessionPage(workspaceId, options = {}) {
|
|
509
|
+
return await this.requestJson(
|
|
510
|
+
"GET",
|
|
511
|
+
`/v1/workspaces/${workspaceId}/sessions`,
|
|
512
|
+
void 0,
|
|
513
|
+
{
|
|
514
|
+
view: "page",
|
|
515
|
+
...options.limit !== void 0 ? { limit: String(options.limit) } : {},
|
|
516
|
+
...options.cursor !== void 0 ? { cursor: options.cursor } : {},
|
|
517
|
+
...options.search?.trim() ? { search: options.search.trim() } : {},
|
|
518
|
+
...Object.prototype.hasOwnProperty.call(options, "parentSessionId") && options.parentSessionId !== void 0 ? {
|
|
519
|
+
parentSessionId: options.parentSessionId === null ? "null" : String(options.parentSessionId)
|
|
520
|
+
} : {}
|
|
521
|
+
}
|
|
522
|
+
);
|
|
523
|
+
}
|
|
524
|
+
/** Set this authenticated member's personal workspace pin for a session. */
|
|
525
|
+
async updateSessionPin(workspaceId, sessionId, request) {
|
|
526
|
+
return await this.requestJson(
|
|
527
|
+
"PUT",
|
|
528
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/pin`,
|
|
529
|
+
request
|
|
530
|
+
);
|
|
531
|
+
}
|
|
532
|
+
async getSessionLineage(workspaceId, sessionId) {
|
|
533
|
+
return await this.requestJson(
|
|
534
|
+
"GET",
|
|
535
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/lineage`
|
|
536
|
+
);
|
|
234
537
|
}
|
|
235
538
|
async listTurns(workspaceId, sessionId, options = {}) {
|
|
236
|
-
return await this.requestJson(
|
|
237
|
-
|
|
238
|
-
|
|
539
|
+
return await this.requestJson(
|
|
540
|
+
"GET",
|
|
541
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/turns`,
|
|
542
|
+
void 0,
|
|
543
|
+
{
|
|
544
|
+
...options.limit !== void 0 ? { limit: String(options.limit) } : {}
|
|
545
|
+
}
|
|
546
|
+
);
|
|
239
547
|
}
|
|
240
548
|
// --- Bring-your-own-compute: Machines dashboard + metrics (M10) ------------
|
|
241
549
|
/**
|
|
@@ -245,9 +553,14 @@ var OpenGeniClient = class {
|
|
|
245
553
|
* session's synthetic Modal group box + the active-sandbox pointer.
|
|
246
554
|
*/
|
|
247
555
|
async listMachines(workspaceId, options = {}) {
|
|
248
|
-
return await this.requestJson(
|
|
249
|
-
|
|
250
|
-
|
|
556
|
+
return await this.requestJson(
|
|
557
|
+
"GET",
|
|
558
|
+
`/v1/workspaces/${workspaceId}/machines`,
|
|
559
|
+
void 0,
|
|
560
|
+
{
|
|
561
|
+
...options.sessionId !== void 0 ? { sessionId: options.sessionId } : {}
|
|
562
|
+
}
|
|
563
|
+
);
|
|
251
564
|
}
|
|
252
565
|
/**
|
|
253
566
|
* Read the downsampled (~1/min) metrics series for ONE machine over a time
|
|
@@ -273,7 +586,11 @@ var OpenGeniClient = class {
|
|
|
273
586
|
* the request.
|
|
274
587
|
*/
|
|
275
588
|
async lookupDeviceEnrollment(userCode) {
|
|
276
|
-
return await this.requestJson(
|
|
589
|
+
return await this.requestJson(
|
|
590
|
+
"POST",
|
|
591
|
+
"/v1/enrollments/device/lookup",
|
|
592
|
+
{ userCode }
|
|
593
|
+
);
|
|
277
594
|
}
|
|
278
595
|
/**
|
|
279
596
|
* Approve a pending device-enrollment flow (the LOUD consent step). `allowScreenControl`
|
|
@@ -325,12 +642,20 @@ var OpenGeniClient = class {
|
|
|
325
642
|
}
|
|
326
643
|
// --- Scheduled tasks -------------------------------------------------------
|
|
327
644
|
async listScheduledTasks(workspaceId, options = {}) {
|
|
328
|
-
return await this.requestJson(
|
|
329
|
-
|
|
330
|
-
|
|
645
|
+
return await this.requestJson(
|
|
646
|
+
"GET",
|
|
647
|
+
`/v1/workspaces/${workspaceId}/scheduled-tasks`,
|
|
648
|
+
void 0,
|
|
649
|
+
{
|
|
650
|
+
...options.limit !== void 0 ? { limit: String(options.limit) } : {}
|
|
651
|
+
}
|
|
652
|
+
);
|
|
331
653
|
}
|
|
332
654
|
async getScheduledTask(workspaceId, taskId) {
|
|
333
|
-
return await this.requestJson(
|
|
655
|
+
return await this.requestJson(
|
|
656
|
+
"GET",
|
|
657
|
+
`/v1/workspaces/${workspaceId}/scheduled-tasks/${taskId}`
|
|
658
|
+
);
|
|
334
659
|
}
|
|
335
660
|
// --- Events: replay, send, stream ----------------------------------------
|
|
336
661
|
/**
|
|
@@ -340,16 +665,25 @@ var OpenGeniClient = class {
|
|
|
340
665
|
* for resume cursors.
|
|
341
666
|
*/
|
|
342
667
|
async listEvents(workspaceId, sessionId, options = {}) {
|
|
343
|
-
return await this.requestJson(
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
668
|
+
return await this.requestJson(
|
|
669
|
+
"GET",
|
|
670
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/events`,
|
|
671
|
+
void 0,
|
|
672
|
+
{
|
|
673
|
+
...options.after !== void 0 ? { after: String(options.after) } : {},
|
|
674
|
+
...options.before !== void 0 ? { before: String(options.before) } : {},
|
|
675
|
+
...options.limit !== void 0 ? { limit: String(options.limit) } : {},
|
|
676
|
+
...options.compact ? { compact: "1" } : {}
|
|
677
|
+
}
|
|
678
|
+
);
|
|
349
679
|
}
|
|
350
680
|
/** POST a user/control event to the session. Returns the accepted event. */
|
|
351
681
|
async sendEvent(workspaceId, sessionId, event) {
|
|
352
|
-
return await this.requestJson(
|
|
682
|
+
return await this.requestJson(
|
|
683
|
+
"POST",
|
|
684
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/events`,
|
|
685
|
+
event
|
|
686
|
+
);
|
|
353
687
|
}
|
|
354
688
|
async sendMessage(workspaceId, sessionId, message) {
|
|
355
689
|
const input = typeof message === "string" ? { text: message } : message;
|
|
@@ -360,11 +694,12 @@ var OpenGeniClient = class {
|
|
|
360
694
|
payload
|
|
361
695
|
});
|
|
362
696
|
}
|
|
363
|
-
async
|
|
364
|
-
return await this.
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
697
|
+
async pauseSession(workspaceId, sessionId, options = {}) {
|
|
698
|
+
return await this.controlSession(workspaceId, sessionId, {
|
|
699
|
+
action: "pause",
|
|
700
|
+
clientEventId: options.clientEventId ?? crypto.randomUUID(),
|
|
701
|
+
...options.reason ? { reason: options.reason } : {},
|
|
702
|
+
...options.expectedControlEtag ? { expectedControlEtag: options.expectedControlEtag } : {}
|
|
368
703
|
});
|
|
369
704
|
}
|
|
370
705
|
async sendApprovalDecision(workspaceId, sessionId, decision) {
|
|
@@ -386,7 +721,10 @@ var OpenGeniClient = class {
|
|
|
386
721
|
/** The transport `streamEvents` runs on; useful for custom streaming layers. */
|
|
387
722
|
eventStreamTransport(workspaceId, sessionId) {
|
|
388
723
|
return {
|
|
389
|
-
openStream: async (after, signal) => await this.openEventStream(workspaceId, sessionId, {
|
|
724
|
+
openStream: async (after, signal) => await this.openEventStream(workspaceId, sessionId, {
|
|
725
|
+
after,
|
|
726
|
+
...signal ? { signal } : {}
|
|
727
|
+
}),
|
|
390
728
|
listEvents: async (after, limit) => await this.listEvents(workspaceId, sessionId, { after, limit })
|
|
391
729
|
};
|
|
392
730
|
}
|
|
@@ -400,6 +738,7 @@ var OpenGeniClient = class {
|
|
|
400
738
|
headers: { ...this.headers(), Accept: "text/event-stream" },
|
|
401
739
|
...options.signal ? { signal: options.signal } : {}
|
|
402
740
|
});
|
|
741
|
+
assertApiContractResponse(response);
|
|
403
742
|
if (!response.ok) {
|
|
404
743
|
throw new OpenGeniApiError(response.status, await safeText(response));
|
|
405
744
|
}
|
|
@@ -409,87 +748,144 @@ var OpenGeniClient = class {
|
|
|
409
748
|
return response.body;
|
|
410
749
|
}
|
|
411
750
|
// --- Turn queue ------------------------------------------------------------
|
|
412
|
-
|
|
413
|
-
async updateQueuedTurn(workspaceId, sessionId, turnId, update) {
|
|
751
|
+
async getQueue(workspaceId, sessionId) {
|
|
414
752
|
return await this.requestJson(
|
|
415
|
-
"
|
|
416
|
-
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/
|
|
417
|
-
update
|
|
753
|
+
"GET",
|
|
754
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/queue`
|
|
418
755
|
);
|
|
419
756
|
}
|
|
420
|
-
|
|
421
|
-
* Reorder the queued turns. `turnIds` must all reference queued turns; the
|
|
422
|
-
* server assigns positions in the given order and returns the queue.
|
|
423
|
-
*/
|
|
424
|
-
async reorderQueuedTurns(workspaceId, sessionId, turnIds) {
|
|
757
|
+
async moveQueueItem(workspaceId, sessionId, turnId, request) {
|
|
425
758
|
return await this.requestJson(
|
|
426
759
|
"POST",
|
|
427
|
-
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/
|
|
428
|
-
|
|
760
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/queue/${turnId}/move`,
|
|
761
|
+
request
|
|
429
762
|
);
|
|
430
763
|
}
|
|
431
|
-
|
|
432
|
-
async deleteQueuedTurn(workspaceId, sessionId, turnId) {
|
|
764
|
+
async editQueueItem(workspaceId, sessionId, turnId, request) {
|
|
433
765
|
return await this.requestJson(
|
|
434
|
-
"
|
|
435
|
-
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/
|
|
766
|
+
"POST",
|
|
767
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/queue/${turnId}/edit`,
|
|
768
|
+
request
|
|
436
769
|
);
|
|
437
770
|
}
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
771
|
+
async steerQueueItem(workspaceId, sessionId, turnId, request) {
|
|
772
|
+
return await this.requestJson(
|
|
773
|
+
"POST",
|
|
774
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/queue/${turnId}/steer`,
|
|
775
|
+
request
|
|
776
|
+
);
|
|
777
|
+
}
|
|
778
|
+
async deleteQueueItem(workspaceId, sessionId, turnId, request) {
|
|
779
|
+
return await this.requestJson(
|
|
780
|
+
"POST",
|
|
781
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/queue/${turnId}/delete`,
|
|
782
|
+
request
|
|
783
|
+
);
|
|
784
|
+
}
|
|
785
|
+
async getComposerDraft(workspaceId, sessionId) {
|
|
786
|
+
return await this.requestJson(
|
|
787
|
+
"GET",
|
|
788
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/composer-draft`
|
|
789
|
+
);
|
|
790
|
+
}
|
|
791
|
+
async saveComposerDraft(workspaceId, sessionId, request) {
|
|
792
|
+
return await this.requestJson(
|
|
793
|
+
"PUT",
|
|
794
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/composer-draft`,
|
|
795
|
+
request
|
|
796
|
+
);
|
|
797
|
+
}
|
|
798
|
+
async controlSession(workspaceId, sessionId, request) {
|
|
799
|
+
return await this.requestJson(
|
|
800
|
+
"POST",
|
|
801
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/control`,
|
|
802
|
+
request
|
|
803
|
+
);
|
|
804
|
+
}
|
|
805
|
+
async resumeSession(workspaceId, sessionId, options = {}) {
|
|
806
|
+
return await this.controlSession(workspaceId, sessionId, {
|
|
807
|
+
action: "resume",
|
|
808
|
+
clientEventId: options.clientEventId ?? crypto.randomUUID(),
|
|
809
|
+
...options.reason ? { reason: options.reason } : {},
|
|
810
|
+
...options.expectedControlEtag ? { expectedControlEtag: options.expectedControlEtag } : {}
|
|
811
|
+
});
|
|
812
|
+
}
|
|
813
|
+
async setWorkspaceInferenceState(workspaceId, request) {
|
|
814
|
+
return await this.requestJson(
|
|
815
|
+
"POST",
|
|
816
|
+
`/v1/workspaces/${workspaceId}/inference-control`,
|
|
817
|
+
request
|
|
818
|
+
);
|
|
819
|
+
}
|
|
820
|
+
async listWorkspaceControlEvents(workspaceId, options = {}) {
|
|
821
|
+
return await this.requestJson(
|
|
822
|
+
"GET",
|
|
823
|
+
`/v1/workspaces/${workspaceId}/control-events`,
|
|
824
|
+
void 0,
|
|
825
|
+
{
|
|
826
|
+
...options.after !== void 0 ? { after: String(options.after) } : {},
|
|
827
|
+
...options.limit !== void 0 ? { limit: String(options.limit) } : {}
|
|
828
|
+
}
|
|
829
|
+
);
|
|
830
|
+
}
|
|
831
|
+
streamWorkspaceControlEvents(workspaceId, options = {}) {
|
|
832
|
+
return streamWorkspaceControlEvents(this.workspaceControlStreamTransport(workspaceId), options);
|
|
833
|
+
}
|
|
834
|
+
workspaceControlStreamTransport(workspaceId) {
|
|
835
|
+
return {
|
|
836
|
+
openStream: async (after, signal) => await this.openWorkspaceControlEventStream(workspaceId, {
|
|
837
|
+
after,
|
|
838
|
+
...signal ? { signal } : {}
|
|
839
|
+
})
|
|
840
|
+
};
|
|
841
|
+
}
|
|
842
|
+
async openWorkspaceControlEventStream(workspaceId, options = {}) {
|
|
843
|
+
const response = await this.fetchImpl(
|
|
844
|
+
this.url(`/v1/workspaces/${workspaceId}/control-events/stream`, {
|
|
845
|
+
after: String(options.after ?? 0)
|
|
846
|
+
}),
|
|
847
|
+
{
|
|
848
|
+
method: "GET",
|
|
849
|
+
headers: { ...this.headers(), Accept: "text/event-stream" },
|
|
850
|
+
...options.signal ? { signal: options.signal } : {}
|
|
851
|
+
}
|
|
852
|
+
);
|
|
853
|
+
assertApiContractResponse(response);
|
|
854
|
+
if (!response.ok) throw new OpenGeniApiError(response.status, await safeText(response));
|
|
855
|
+
if (!response.body) {
|
|
856
|
+
throw new OpenGeniApiError(response.status, "SSE response did not include a readable body");
|
|
857
|
+
}
|
|
858
|
+
return response.body;
|
|
859
|
+
}
|
|
860
|
+
/**
|
|
861
|
+
* Steer: atomically put this prompt at the head and supersede the current
|
|
862
|
+
* inference. The client performs one request and renders server order.
|
|
863
|
+
*/
|
|
864
|
+
async steerMessage(workspaceId, sessionId, message) {
|
|
865
|
+
const input = typeof message === "string" ? { text: message } : message;
|
|
866
|
+
return await this.requestJson(
|
|
867
|
+
"POST",
|
|
868
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/steer`,
|
|
869
|
+
input
|
|
870
|
+
);
|
|
871
|
+
}
|
|
872
|
+
// --- Goals -------------------------------------------------------------------
|
|
873
|
+
/** The session's goal. 404s when the session never had one. */
|
|
874
|
+
async getGoal(workspaceId, sessionId) {
|
|
875
|
+
return await this.requestJson(
|
|
876
|
+
"GET",
|
|
877
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/goal`
|
|
878
|
+
);
|
|
879
|
+
}
|
|
880
|
+
async updateGoal(workspaceId, sessionId, request) {
|
|
881
|
+
return await this.requestJson(
|
|
882
|
+
"PATCH",
|
|
883
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/goal`,
|
|
884
|
+
request
|
|
885
|
+
);
|
|
886
|
+
}
|
|
887
|
+
async deleteGoal(workspaceId, sessionId) {
|
|
888
|
+
await this.requestVoid("DELETE", `/v1/workspaces/${workspaceId}/sessions/${sessionId}/goal`);
|
|
493
889
|
}
|
|
494
890
|
/** Pause the goal loop: the session stops self-continuing until resumed. */
|
|
495
891
|
async pauseGoal(workspaceId, sessionId, options = {}) {
|
|
@@ -511,16 +907,19 @@ var OpenGeniClient = class {
|
|
|
511
907
|
* context — the destructive intent is explicit on the wire.
|
|
512
908
|
*/
|
|
513
909
|
async clearSessionContext(workspaceId, sessionId) {
|
|
514
|
-
await this.requestVoid(
|
|
910
|
+
await this.requestVoid(
|
|
911
|
+
"POST",
|
|
912
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/context/clear`,
|
|
913
|
+
{ confirm: true }
|
|
914
|
+
);
|
|
515
915
|
}
|
|
516
|
-
/**
|
|
517
|
-
* Trigger conversation compaction now. On the client-managed (Azure) path this
|
|
518
|
-
* queues a forced compaction the worker honors before the next turn
|
|
519
|
-
* (`status:"queued"`); on a server-managed provider or when compaction is off
|
|
520
|
-
* it is a no-op (`status:"noop"`) with an explanatory message.
|
|
521
|
-
*/
|
|
916
|
+
/** Request one durable portable compaction at the next safe model boundary. */
|
|
522
917
|
async compactSessionContext(workspaceId, sessionId) {
|
|
523
|
-
return await this.requestJson(
|
|
918
|
+
return await this.requestJson(
|
|
919
|
+
"POST",
|
|
920
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/context/compact`,
|
|
921
|
+
{}
|
|
922
|
+
);
|
|
524
923
|
}
|
|
525
924
|
// --- Channel-A structured services (P4.4) ------------------------------------
|
|
526
925
|
// FileSystem (Pierre tree), Git (Pierre diff), Terminal (exec + PTY). Each is a
|
|
@@ -528,64 +927,147 @@ var OpenGeniClient = class {
|
|
|
528
927
|
// notifications + the PTY output stream arrive on the existing event SSE.
|
|
529
928
|
/** FileSystem: list a directory tree (feeds the Pierre file tree). */
|
|
530
929
|
async fsList(workspaceId, sessionId, request = {}) {
|
|
531
|
-
return await this.requestJson(
|
|
930
|
+
return await this.requestJson(
|
|
931
|
+
"POST",
|
|
932
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/fs/list`,
|
|
933
|
+
request
|
|
934
|
+
);
|
|
532
935
|
}
|
|
533
936
|
/** FileSystem: read a file (text or base64; binary-safe, size-capped). */
|
|
534
937
|
async fsRead(workspaceId, sessionId, request) {
|
|
535
|
-
return await this.requestJson(
|
|
938
|
+
return await this.requestJson(
|
|
939
|
+
"POST",
|
|
940
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/fs/read`,
|
|
941
|
+
request
|
|
942
|
+
);
|
|
536
943
|
}
|
|
537
944
|
/** FileSystem: write a file (last-writer-wins; emits fs.changed). */
|
|
538
945
|
async fsWrite(workspaceId, sessionId, request) {
|
|
539
|
-
return await this.requestJson(
|
|
946
|
+
return await this.requestJson(
|
|
947
|
+
"POST",
|
|
948
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/fs/write`,
|
|
949
|
+
request
|
|
950
|
+
);
|
|
540
951
|
}
|
|
541
952
|
/** FileSystem: delete a path (emits fs.changed). */
|
|
542
953
|
async fsDelete(workspaceId, sessionId, request) {
|
|
543
|
-
return await this.requestJson(
|
|
954
|
+
return await this.requestJson(
|
|
955
|
+
"POST",
|
|
956
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/fs/delete`,
|
|
957
|
+
request
|
|
958
|
+
);
|
|
544
959
|
}
|
|
545
960
|
/** FileSystem: move/rename a path (emits fs.changed; 409 if destination exists and overwrite is false). */
|
|
546
961
|
async fsMove(workspaceId, sessionId, request) {
|
|
547
|
-
return await this.requestJson(
|
|
962
|
+
return await this.requestJson(
|
|
963
|
+
"POST",
|
|
964
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/fs/move`,
|
|
965
|
+
request
|
|
966
|
+
);
|
|
548
967
|
}
|
|
549
968
|
/** FileSystem: create a directory (emits fs.changed; recursive defaults to true). */
|
|
550
969
|
async fsMkdir(workspaceId, sessionId, request) {
|
|
551
|
-
return await this.requestJson(
|
|
970
|
+
return await this.requestJson(
|
|
971
|
+
"POST",
|
|
972
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/fs/mkdir`,
|
|
973
|
+
request
|
|
974
|
+
);
|
|
552
975
|
}
|
|
553
976
|
/** Git: working-tree/index status (the Pierre file-status feed). */
|
|
554
977
|
async gitStatus(workspaceId, sessionId, request = {}) {
|
|
555
|
-
return await this.requestJson(
|
|
978
|
+
return await this.requestJson(
|
|
979
|
+
"POST",
|
|
980
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/git/status`,
|
|
981
|
+
request
|
|
982
|
+
);
|
|
556
983
|
}
|
|
557
984
|
/** Git: structured diff hunks (the Pierre diff feed). */
|
|
558
985
|
async gitDiff(workspaceId, sessionId, request = {}) {
|
|
559
|
-
return await this.requestJson(
|
|
986
|
+
return await this.requestJson(
|
|
987
|
+
"POST",
|
|
988
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/git/diff`,
|
|
989
|
+
request
|
|
990
|
+
);
|
|
560
991
|
}
|
|
561
992
|
/** Git: commit log. */
|
|
562
993
|
async gitLog(workspaceId, sessionId, request = {}) {
|
|
563
|
-
return await this.requestJson(
|
|
994
|
+
return await this.requestJson(
|
|
995
|
+
"POST",
|
|
996
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/git/log`,
|
|
997
|
+
request
|
|
998
|
+
);
|
|
564
999
|
}
|
|
565
1000
|
/** Git: show a commit (diff vs first parent) or fetch a raw blob at a ref. */
|
|
566
1001
|
async gitShow(workspaceId, sessionId, request) {
|
|
567
|
-
return await this.requestJson(
|
|
1002
|
+
return await this.requestJson(
|
|
1003
|
+
"POST",
|
|
1004
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/git/show`,
|
|
1005
|
+
request
|
|
1006
|
+
);
|
|
1007
|
+
}
|
|
1008
|
+
/** Workspace capture: the latest turn-end snapshot of the session's workspace
|
|
1009
|
+
* (tree + per-repo diff + file after-image refs), served from durable storage
|
|
1010
|
+
* WITHOUT warming a machine — the workbench cold-paint source. Returns
|
|
1011
|
+
* `{available:false}` when no capture exists yet (fall back to the live path). */
|
|
1012
|
+
async getWorkspaceCapture(workspaceId, sessionId) {
|
|
1013
|
+
return await this.requestJson(
|
|
1014
|
+
"GET",
|
|
1015
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/workspace/capture`
|
|
1016
|
+
);
|
|
1017
|
+
}
|
|
1018
|
+
/** Workspace capture: a single file's after-image from the capture (revision
|
|
1019
|
+
* pins a specific one; omitted → latest). Content is inline for small files,
|
|
1020
|
+
* else a short-TTL signed URL; a tooLarge file returns metadata only. */
|
|
1021
|
+
async getWorkspaceCaptureFile(workspaceId, sessionId, path, revision) {
|
|
1022
|
+
const query = { path };
|
|
1023
|
+
if (revision !== void 0) query.revision = String(revision);
|
|
1024
|
+
return await this.requestJson(
|
|
1025
|
+
"GET",
|
|
1026
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/workspace/capture/file`,
|
|
1027
|
+
void 0,
|
|
1028
|
+
query
|
|
1029
|
+
);
|
|
568
1030
|
}
|
|
569
1031
|
/** Terminal: run a bounded command, returning buffered stdout/stderr inline. */
|
|
570
1032
|
async terminalExec(workspaceId, sessionId, request) {
|
|
571
|
-
return await this.requestJson(
|
|
1033
|
+
return await this.requestJson(
|
|
1034
|
+
"POST",
|
|
1035
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/terminal/exec`,
|
|
1036
|
+
request
|
|
1037
|
+
);
|
|
572
1038
|
}
|
|
573
1039
|
/** Terminal: open an interactive PTY. Output streams on the event SSE as
|
|
574
1040
|
* terminal.pty.output.delta; drive it with terminalPtyWrite. */
|
|
575
1041
|
async terminalPtyOpen(workspaceId, sessionId, request = {}) {
|
|
576
|
-
return await this.requestJson(
|
|
1042
|
+
return await this.requestJson(
|
|
1043
|
+
"POST",
|
|
1044
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/terminal/pty`,
|
|
1045
|
+
request
|
|
1046
|
+
);
|
|
577
1047
|
}
|
|
578
1048
|
/** Terminal: send stdin to an open PTY (output rides A1). */
|
|
579
1049
|
async terminalPtyWrite(workspaceId, sessionId, request) {
|
|
580
|
-
await this.requestVoid(
|
|
1050
|
+
await this.requestVoid(
|
|
1051
|
+
"POST",
|
|
1052
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/terminal/pty/write`,
|
|
1053
|
+
request
|
|
1054
|
+
);
|
|
581
1055
|
}
|
|
582
1056
|
/** Terminal: resize an open PTY. */
|
|
583
1057
|
async terminalPtyResize(workspaceId, sessionId, request) {
|
|
584
|
-
await this.requestVoid(
|
|
1058
|
+
await this.requestVoid(
|
|
1059
|
+
"POST",
|
|
1060
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/terminal/pty/resize`,
|
|
1061
|
+
request
|
|
1062
|
+
);
|
|
585
1063
|
}
|
|
586
1064
|
/** Terminal: close an open PTY (idempotent). */
|
|
587
1065
|
async terminalPtyClose(workspaceId, sessionId, request) {
|
|
588
|
-
await this.requestVoid(
|
|
1066
|
+
await this.requestVoid(
|
|
1067
|
+
"POST",
|
|
1068
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/terminal/pty/close`,
|
|
1069
|
+
request
|
|
1070
|
+
);
|
|
589
1071
|
}
|
|
590
1072
|
// --- Stream surfacing: capability negotiation + viewer lifecycle (Phase 5) ---
|
|
591
1073
|
// The capability doc is the single source of UI truth (degradation is always a
|
|
@@ -641,7 +1123,10 @@ var OpenGeniClient = class {
|
|
|
641
1123
|
}
|
|
642
1124
|
/** Detach a viewer (delete this holder; idempotent delete-my-row). */
|
|
643
1125
|
async detachViewer(workspaceId, sessionId, viewerId) {
|
|
644
|
-
await this.requestVoid(
|
|
1126
|
+
await this.requestVoid(
|
|
1127
|
+
"DELETE",
|
|
1128
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/viewers/${viewerId}`
|
|
1129
|
+
);
|
|
645
1130
|
}
|
|
646
1131
|
// --- Access + workspaces -----------------------------------------------------
|
|
647
1132
|
/**
|
|
@@ -652,7 +1137,14 @@ var OpenGeniClient = class {
|
|
|
652
1137
|
* knowledge of the host setup; safe to call before any auth is established.
|
|
653
1138
|
*/
|
|
654
1139
|
async getClientConfig() {
|
|
655
|
-
|
|
1140
|
+
const config = await this.requestJson("GET", "/v1/config/client");
|
|
1141
|
+
if (config.apiContractRevision !== OPENGENI_API_CONTRACT_REVISION) {
|
|
1142
|
+
throw new OpenGeniApiContractMismatchError(
|
|
1143
|
+
OPENGENI_API_CONTRACT_REVISION,
|
|
1144
|
+
String(config.apiContractRevision || "(missing)")
|
|
1145
|
+
);
|
|
1146
|
+
}
|
|
1147
|
+
return config;
|
|
656
1148
|
}
|
|
657
1149
|
/** The caller's access context: subject, account + workspace grants, defaults. */
|
|
658
1150
|
async getAccessContext() {
|
|
@@ -680,7 +1172,10 @@ var OpenGeniClient = class {
|
|
|
680
1172
|
// --- Members ("People with access") -------------------------------------------
|
|
681
1173
|
/** The workspace's members (user + api_key subjects). */
|
|
682
1174
|
async listWorkspaceMembers(workspaceId) {
|
|
683
|
-
const response = await this.requestJson(
|
|
1175
|
+
const response = await this.requestJson(
|
|
1176
|
+
"GET",
|
|
1177
|
+
`/v1/workspaces/${workspaceId}/members`
|
|
1178
|
+
);
|
|
684
1179
|
return response.members;
|
|
685
1180
|
}
|
|
686
1181
|
/**
|
|
@@ -688,7 +1183,11 @@ var OpenGeniClient = class {
|
|
|
688
1183
|
* exists (email invites for unknown users are deferred).
|
|
689
1184
|
*/
|
|
690
1185
|
async addWorkspaceMember(workspaceId, request) {
|
|
691
|
-
return await this.requestJson(
|
|
1186
|
+
return await this.requestJson(
|
|
1187
|
+
"POST",
|
|
1188
|
+
`/v1/workspaces/${workspaceId}/members`,
|
|
1189
|
+
request
|
|
1190
|
+
);
|
|
692
1191
|
}
|
|
693
1192
|
async updateWorkspaceMember(workspaceId, subjectId, request) {
|
|
694
1193
|
return await this.requestJson(
|
|
@@ -702,20 +1201,37 @@ var OpenGeniClient = class {
|
|
|
702
1201
|
* member who can still manage the workspace.
|
|
703
1202
|
*/
|
|
704
1203
|
async removeWorkspaceMember(workspaceId, subjectId) {
|
|
705
|
-
await this.requestVoid(
|
|
1204
|
+
await this.requestVoid(
|
|
1205
|
+
"DELETE",
|
|
1206
|
+
`/v1/workspaces/${workspaceId}/members/${encodeURIComponent(subjectId)}`
|
|
1207
|
+
);
|
|
706
1208
|
}
|
|
707
1209
|
// --- Scheduled tasks (write + runs) -------------------------------------------
|
|
708
1210
|
async createScheduledTask(workspaceId, request) {
|
|
709
|
-
return await this.requestJson(
|
|
1211
|
+
return await this.requestJson(
|
|
1212
|
+
"POST",
|
|
1213
|
+
`/v1/workspaces/${workspaceId}/scheduled-tasks`,
|
|
1214
|
+
request
|
|
1215
|
+
);
|
|
710
1216
|
}
|
|
711
1217
|
async updateScheduledTask(workspaceId, taskId, request) {
|
|
712
|
-
return await this.requestJson(
|
|
1218
|
+
return await this.requestJson(
|
|
1219
|
+
"PATCH",
|
|
1220
|
+
`/v1/workspaces/${workspaceId}/scheduled-tasks/${taskId}`,
|
|
1221
|
+
request
|
|
1222
|
+
);
|
|
713
1223
|
}
|
|
714
1224
|
async pauseScheduledTask(workspaceId, taskId) {
|
|
715
|
-
return await this.requestJson(
|
|
1225
|
+
return await this.requestJson(
|
|
1226
|
+
"POST",
|
|
1227
|
+
`/v1/workspaces/${workspaceId}/scheduled-tasks/${taskId}/pause`
|
|
1228
|
+
);
|
|
716
1229
|
}
|
|
717
1230
|
async resumeScheduledTask(workspaceId, taskId) {
|
|
718
|
-
return await this.requestJson(
|
|
1231
|
+
return await this.requestJson(
|
|
1232
|
+
"POST",
|
|
1233
|
+
`/v1/workspaces/${workspaceId}/scheduled-tasks/${taskId}/resume`
|
|
1234
|
+
);
|
|
719
1235
|
}
|
|
720
1236
|
/**
|
|
721
1237
|
* Fire the task immediately (manual trigger), independent of its schedule.
|
|
@@ -730,7 +1246,10 @@ var OpenGeniClient = class {
|
|
|
730
1246
|
);
|
|
731
1247
|
}
|
|
732
1248
|
async deleteScheduledTask(workspaceId, taskId) {
|
|
733
|
-
await this.requestJson(
|
|
1249
|
+
await this.requestJson(
|
|
1250
|
+
"DELETE",
|
|
1251
|
+
`/v1/workspaces/${workspaceId}/scheduled-tasks/${taskId}`
|
|
1252
|
+
);
|
|
734
1253
|
}
|
|
735
1254
|
async listScheduledTaskRuns(workspaceId, taskId, options = {}) {
|
|
736
1255
|
return await this.requestJson(
|
|
@@ -740,45 +1259,178 @@ var OpenGeniClient = class {
|
|
|
740
1259
|
{ ...options.limit !== void 0 ? { limit: String(options.limit) } : {} }
|
|
741
1260
|
);
|
|
742
1261
|
}
|
|
743
|
-
// ---
|
|
1262
|
+
// --- VariableSets --------------------------------------------------------------
|
|
744
1263
|
// Variable values are write-only: reads return name/version metadata only.
|
|
745
|
-
async
|
|
746
|
-
return await this.requestJson(
|
|
1264
|
+
async listVariableSets(workspaceId) {
|
|
1265
|
+
return await this.requestJson(
|
|
1266
|
+
"GET",
|
|
1267
|
+
`/v1/workspaces/${workspaceId}/variable-sets`
|
|
1268
|
+
);
|
|
747
1269
|
}
|
|
748
|
-
async
|
|
749
|
-
return await this.requestJson(
|
|
1270
|
+
async createVariableSet(workspaceId, request) {
|
|
1271
|
+
return await this.requestJson(
|
|
1272
|
+
"POST",
|
|
1273
|
+
`/v1/workspaces/${workspaceId}/variable-sets`,
|
|
1274
|
+
request
|
|
1275
|
+
);
|
|
750
1276
|
}
|
|
751
|
-
async
|
|
752
|
-
return await this.requestJson(
|
|
1277
|
+
async getVariableSet(workspaceId, variableSetId) {
|
|
1278
|
+
return await this.requestJson(
|
|
1279
|
+
"GET",
|
|
1280
|
+
`/v1/workspaces/${workspaceId}/variable-sets/${variableSetId}`
|
|
1281
|
+
);
|
|
753
1282
|
}
|
|
754
|
-
async
|
|
1283
|
+
async updateVariableSet(workspaceId, variableSetId, request) {
|
|
755
1284
|
return await this.requestJson(
|
|
756
1285
|
"PATCH",
|
|
757
|
-
`/v1/workspaces/${workspaceId}/
|
|
1286
|
+
`/v1/workspaces/${workspaceId}/variable-sets/${variableSetId}`,
|
|
758
1287
|
request
|
|
759
1288
|
);
|
|
760
1289
|
}
|
|
761
|
-
async
|
|
762
|
-
await this.requestJson(
|
|
1290
|
+
async deleteVariableSet(workspaceId, variableSetId) {
|
|
1291
|
+
await this.requestJson(
|
|
1292
|
+
"DELETE",
|
|
1293
|
+
`/v1/workspaces/${workspaceId}/variable-sets/${variableSetId}`
|
|
1294
|
+
);
|
|
763
1295
|
}
|
|
764
1296
|
/** Create or rotate a variable. The value never comes back on any read. */
|
|
765
|
-
async
|
|
1297
|
+
async setVariableSetVariable(workspaceId, variableSetId, name, value) {
|
|
766
1298
|
return await this.requestJson(
|
|
767
1299
|
"PUT",
|
|
768
|
-
`/v1/workspaces/${workspaceId}/
|
|
1300
|
+
`/v1/workspaces/${workspaceId}/variable-sets/${variableSetId}/variables/${encodeURIComponent(name)}`,
|
|
769
1301
|
{ value }
|
|
770
1302
|
);
|
|
771
1303
|
}
|
|
772
|
-
async
|
|
1304
|
+
async deleteVariableSetVariable(workspaceId, variableSetId, name) {
|
|
773
1305
|
await this.requestJson(
|
|
774
1306
|
"DELETE",
|
|
775
|
-
`/v1/workspaces/${workspaceId}/
|
|
1307
|
+
`/v1/workspaces/${workspaceId}/variable-sets/${variableSetId}/variables/${encodeURIComponent(name)}`
|
|
776
1308
|
);
|
|
777
1309
|
}
|
|
1310
|
+
// --- Rigs ------------------------------------------------------------------
|
|
1311
|
+
// Workspace-scoped, versioned sandbox machine definitions. rigs:use gates read
|
|
1312
|
+
// + proposeRigChange; rigs:manage gates create / update / delete / activate.
|
|
1313
|
+
async listRigs(workspaceId) {
|
|
1314
|
+
return await this.requestJson("GET", `/v1/workspaces/${workspaceId}/rigs`);
|
|
1315
|
+
}
|
|
1316
|
+
async createRig(workspaceId, request) {
|
|
1317
|
+
return await this.requestJson("POST", `/v1/workspaces/${workspaceId}/rigs`, request);
|
|
1318
|
+
}
|
|
1319
|
+
async getRig(workspaceId, rigId) {
|
|
1320
|
+
return await this.requestJson("GET", `/v1/workspaces/${workspaceId}/rigs/${rigId}`);
|
|
1321
|
+
}
|
|
1322
|
+
async updateRig(workspaceId, rigId, request) {
|
|
1323
|
+
return await this.requestJson(
|
|
1324
|
+
"PATCH",
|
|
1325
|
+
`/v1/workspaces/${workspaceId}/rigs/${rigId}`,
|
|
1326
|
+
request
|
|
1327
|
+
);
|
|
1328
|
+
}
|
|
1329
|
+
async deleteRig(workspaceId, rigId) {
|
|
1330
|
+
await this.requestJson("DELETE", `/v1/workspaces/${workspaceId}/rigs/${rigId}`);
|
|
1331
|
+
}
|
|
1332
|
+
async listRigVersions(workspaceId, rigId) {
|
|
1333
|
+
return await this.requestJson(
|
|
1334
|
+
"GET",
|
|
1335
|
+
`/v1/workspaces/${workspaceId}/rigs/${rigId}/versions`
|
|
1336
|
+
);
|
|
1337
|
+
}
|
|
1338
|
+
/** Roll the active version to an existing one (rollback / promote-activate). */
|
|
1339
|
+
async activateRigVersion(workspaceId, rigId, versionId) {
|
|
1340
|
+
return await this.requestJson(
|
|
1341
|
+
"POST",
|
|
1342
|
+
`/v1/workspaces/${workspaceId}/rigs/${rigId}/versions/${versionId}/activate`
|
|
1343
|
+
);
|
|
1344
|
+
}
|
|
1345
|
+
async listRigChanges(workspaceId, rigId) {
|
|
1346
|
+
return await this.requestJson(
|
|
1347
|
+
"GET",
|
|
1348
|
+
`/v1/workspaces/${workspaceId}/rigs/${rigId}/changes`
|
|
1349
|
+
);
|
|
1350
|
+
}
|
|
1351
|
+
/** Propose a change against the rig's active version (rigs:use). */
|
|
1352
|
+
async proposeRigChange(workspaceId, rigId, request) {
|
|
1353
|
+
return await this.requestJson(
|
|
1354
|
+
"POST",
|
|
1355
|
+
`/v1/workspaces/${workspaceId}/rigs/${rigId}/changes`,
|
|
1356
|
+
request
|
|
1357
|
+
);
|
|
1358
|
+
}
|
|
1359
|
+
async getRigChange(workspaceId, rigId, changeId) {
|
|
1360
|
+
return await this.requestJson(
|
|
1361
|
+
"GET",
|
|
1362
|
+
`/v1/workspaces/${workspaceId}/rigs/${rigId}/changes/${changeId}`
|
|
1363
|
+
);
|
|
1364
|
+
}
|
|
1365
|
+
/**
|
|
1366
|
+
* Re-run verification for a change (rigs:use). Verification is asynchronous:
|
|
1367
|
+
* this returns the change immediately with status `verifying`; poll
|
|
1368
|
+
* `getRigChange`/`listRigChanges` for the terminal outcome + logs.
|
|
1369
|
+
*/
|
|
1370
|
+
async verifyRigChange(workspaceId, rigId, changeId) {
|
|
1371
|
+
return await this.requestJson(
|
|
1372
|
+
"POST",
|
|
1373
|
+
`/v1/workspaces/${workspaceId}/rigs/${rigId}/changes/${changeId}/verify`
|
|
1374
|
+
);
|
|
1375
|
+
}
|
|
1376
|
+
/**
|
|
1377
|
+
* Promote a verified `definition_edit` change into a new active rig version
|
|
1378
|
+
* (rigs:manage). Only valid once the change's verification passed; returns the
|
|
1379
|
+
* newly minted version.
|
|
1380
|
+
*/
|
|
1381
|
+
async promoteRigChange(workspaceId, rigId, changeId) {
|
|
1382
|
+
return await this.requestJson(
|
|
1383
|
+
"POST",
|
|
1384
|
+
`/v1/workspaces/${workspaceId}/rigs/${rigId}/changes/${changeId}/promote`
|
|
1385
|
+
);
|
|
1386
|
+
}
|
|
1387
|
+
/**
|
|
1388
|
+
* Re-run the active version's checks in a clean throwaway sandbox (rigs:use).
|
|
1389
|
+
* Asynchronous — returns the version id being verified; the outcome lands on
|
|
1390
|
+
* the version's audit trail.
|
|
1391
|
+
*/
|
|
1392
|
+
async verifyRig(workspaceId, rigId) {
|
|
1393
|
+
return await this.requestJson(
|
|
1394
|
+
"POST",
|
|
1395
|
+
`/v1/workspaces/${workspaceId}/rigs/${rigId}/verify`
|
|
1396
|
+
);
|
|
1397
|
+
}
|
|
1398
|
+
/** @deprecated use listVariableSets */
|
|
1399
|
+
async listEnvironments(workspaceId) {
|
|
1400
|
+
return await this.listVariableSets(workspaceId);
|
|
1401
|
+
}
|
|
1402
|
+
/** @deprecated use createVariableSet */
|
|
1403
|
+
async createEnvironment(workspaceId, request) {
|
|
1404
|
+
return await this.createVariableSet(workspaceId, request);
|
|
1405
|
+
}
|
|
1406
|
+
/** @deprecated use getVariableSet */
|
|
1407
|
+
async getEnvironment(workspaceId, environmentId) {
|
|
1408
|
+
return await this.getVariableSet(workspaceId, environmentId);
|
|
1409
|
+
}
|
|
1410
|
+
/** @deprecated use updateVariableSet */
|
|
1411
|
+
async updateEnvironment(workspaceId, environmentId, request) {
|
|
1412
|
+
return await this.updateVariableSet(workspaceId, environmentId, request);
|
|
1413
|
+
}
|
|
1414
|
+
/** @deprecated use deleteVariableSet */
|
|
1415
|
+
async deleteEnvironment(workspaceId, environmentId) {
|
|
1416
|
+
await this.deleteVariableSet(workspaceId, environmentId);
|
|
1417
|
+
}
|
|
1418
|
+
/** @deprecated use setVariableSetVariable */
|
|
1419
|
+
async setEnvironmentVariable(workspaceId, environmentId, name, value) {
|
|
1420
|
+
return await this.setVariableSetVariable(workspaceId, environmentId, name, value);
|
|
1421
|
+
}
|
|
1422
|
+
/** @deprecated use deleteVariableSetVariable */
|
|
1423
|
+
async deleteEnvironmentVariable(workspaceId, environmentId, name) {
|
|
1424
|
+
await this.deleteVariableSetVariable(workspaceId, environmentId, name);
|
|
1425
|
+
}
|
|
778
1426
|
// --- Files -----------------------------------------------------------------------
|
|
779
1427
|
/** Step 1 of the upload flow: returns the pre-signed PUT target. */
|
|
780
1428
|
async beginFileUpload(workspaceId, request) {
|
|
781
|
-
return await this.requestJson(
|
|
1429
|
+
return await this.requestJson(
|
|
1430
|
+
"POST",
|
|
1431
|
+
`/v1/workspaces/${workspaceId}/files/uploads`,
|
|
1432
|
+
request
|
|
1433
|
+
);
|
|
782
1434
|
}
|
|
783
1435
|
/** Step 3 of the upload flow: server verifies the object and marks it ready. */
|
|
784
1436
|
async completeFileUpload(workspaceId, uploadId) {
|
|
@@ -819,28 +1471,51 @@ var OpenGeniClient = class {
|
|
|
819
1471
|
return await this.completeFileUpload(workspaceId, upload.uploadId);
|
|
820
1472
|
}
|
|
821
1473
|
async getFile(workspaceId, fileId) {
|
|
822
|
-
return await this.requestJson(
|
|
1474
|
+
return await this.requestJson(
|
|
1475
|
+
"GET",
|
|
1476
|
+
`/v1/workspaces/${workspaceId}/files/${fileId}`
|
|
1477
|
+
);
|
|
823
1478
|
}
|
|
824
1479
|
/** Mint a short-lived signed download URL for a ready file. */
|
|
825
1480
|
async createFileDownloadUrl(workspaceId, fileId) {
|
|
826
|
-
return await this.requestJson(
|
|
1481
|
+
return await this.requestJson(
|
|
1482
|
+
"POST",
|
|
1483
|
+
`/v1/workspaces/${workspaceId}/files/${fileId}/download-url`
|
|
1484
|
+
);
|
|
827
1485
|
}
|
|
828
1486
|
// --- Documents ----------------------------------------------------------------------
|
|
829
1487
|
async createDocumentBase(workspaceId, request) {
|
|
830
|
-
return await this.requestJson(
|
|
1488
|
+
return await this.requestJson(
|
|
1489
|
+
"POST",
|
|
1490
|
+
`/v1/workspaces/${workspaceId}/document-bases`,
|
|
1491
|
+
request
|
|
1492
|
+
);
|
|
831
1493
|
}
|
|
832
1494
|
async listDocumentBases(workspaceId) {
|
|
833
|
-
return await this.requestJson(
|
|
1495
|
+
return await this.requestJson(
|
|
1496
|
+
"GET",
|
|
1497
|
+
`/v1/workspaces/${workspaceId}/document-bases`
|
|
1498
|
+
);
|
|
834
1499
|
}
|
|
835
1500
|
async getDocumentBase(workspaceId, baseId) {
|
|
836
|
-
return await this.requestJson(
|
|
1501
|
+
return await this.requestJson(
|
|
1502
|
+
"GET",
|
|
1503
|
+
`/v1/workspaces/${workspaceId}/document-bases/${baseId}`
|
|
1504
|
+
);
|
|
837
1505
|
}
|
|
838
1506
|
/** Index an uploaded file into the base. The file must be `ready`. */
|
|
839
1507
|
async addDocument(workspaceId, baseId, request) {
|
|
840
|
-
return await this.requestJson(
|
|
1508
|
+
return await this.requestJson(
|
|
1509
|
+
"POST",
|
|
1510
|
+
`/v1/workspaces/${workspaceId}/document-bases/${baseId}/documents`,
|
|
1511
|
+
request
|
|
1512
|
+
);
|
|
841
1513
|
}
|
|
842
1514
|
async listDocuments(workspaceId, baseId) {
|
|
843
|
-
return await this.requestJson(
|
|
1515
|
+
return await this.requestJson(
|
|
1516
|
+
"GET",
|
|
1517
|
+
`/v1/workspaces/${workspaceId}/document-bases/${baseId}/documents`
|
|
1518
|
+
);
|
|
844
1519
|
}
|
|
845
1520
|
/** Retry indexing for a failed document. */
|
|
846
1521
|
async reindexDocument(workspaceId, baseId, documentId) {
|
|
@@ -867,7 +1542,11 @@ var OpenGeniClient = class {
|
|
|
867
1542
|
);
|
|
868
1543
|
}
|
|
869
1544
|
async searchKnowledge(workspaceId, request) {
|
|
870
|
-
return await this.requestJson(
|
|
1545
|
+
return await this.requestJson(
|
|
1546
|
+
"POST",
|
|
1547
|
+
`/v1/workspaces/${workspaceId}/knowledge/search`,
|
|
1548
|
+
request
|
|
1549
|
+
);
|
|
871
1550
|
}
|
|
872
1551
|
async listKnowledgeMemories(workspaceId, request = {}) {
|
|
873
1552
|
const params = new URLSearchParams();
|
|
@@ -877,16 +1556,53 @@ var OpenGeniClient = class {
|
|
|
877
1556
|
if (request.scope) params.set("scope", request.scope);
|
|
878
1557
|
if (request.limit) params.set("limit", String(request.limit));
|
|
879
1558
|
const query = params.toString();
|
|
880
|
-
return await this.requestJson(
|
|
1559
|
+
return await this.requestJson(
|
|
1560
|
+
"GET",
|
|
1561
|
+
`/v1/workspaces/${workspaceId}/knowledge/memories${query ? `?${query}` : ""}`
|
|
1562
|
+
);
|
|
881
1563
|
}
|
|
882
1564
|
async getKnowledgeMemory(workspaceId, memoryId) {
|
|
883
|
-
return await this.requestJson(
|
|
1565
|
+
return await this.requestJson(
|
|
1566
|
+
"GET",
|
|
1567
|
+
`/v1/workspaces/${workspaceId}/knowledge/memories/${memoryId}`
|
|
1568
|
+
);
|
|
884
1569
|
}
|
|
885
1570
|
async createKnowledgeMemory(workspaceId, request) {
|
|
886
|
-
return await this.requestJson(
|
|
1571
|
+
return await this.requestJson(
|
|
1572
|
+
"POST",
|
|
1573
|
+
`/v1/workspaces/${workspaceId}/knowledge/memories`,
|
|
1574
|
+
request
|
|
1575
|
+
);
|
|
887
1576
|
}
|
|
888
1577
|
async updateKnowledgeMemory(workspaceId, memoryId, request) {
|
|
889
|
-
return await this.requestJson(
|
|
1578
|
+
return await this.requestJson(
|
|
1579
|
+
"PATCH",
|
|
1580
|
+
`/v1/workspaces/${workspaceId}/knowledge/memories/${memoryId}`,
|
|
1581
|
+
request
|
|
1582
|
+
);
|
|
1583
|
+
}
|
|
1584
|
+
/** Hybrid (semantic + keyword) search over the workspace's agent-visible memory. */
|
|
1585
|
+
async searchWorkspaceMemories(workspaceId, request) {
|
|
1586
|
+
return await this.requestJson(
|
|
1587
|
+
"POST",
|
|
1588
|
+
`/v1/workspaces/${workspaceId}/knowledge/memories/search`,
|
|
1589
|
+
request
|
|
1590
|
+
);
|
|
1591
|
+
}
|
|
1592
|
+
/** Deep-merge a settings patch into the workspace (preserves unknown keys). */
|
|
1593
|
+
async updateWorkspaceSettings(workspaceId, request) {
|
|
1594
|
+
return await this.requestJson(
|
|
1595
|
+
"PATCH",
|
|
1596
|
+
`/v1/workspaces/${workspaceId}/settings`,
|
|
1597
|
+
request
|
|
1598
|
+
);
|
|
1599
|
+
}
|
|
1600
|
+
async setWorkspaceDefaultRig(workspaceId, request) {
|
|
1601
|
+
return await this.requestJson(
|
|
1602
|
+
"PUT",
|
|
1603
|
+
`/v1/workspaces/${workspaceId}/default-rig`,
|
|
1604
|
+
request
|
|
1605
|
+
);
|
|
890
1606
|
}
|
|
891
1607
|
// --- Capability packs ------------------------------------------------------------------
|
|
892
1608
|
/** Built-in + registered packs, with the workspace's installations. */
|
|
@@ -895,10 +1611,17 @@ var OpenGeniClient = class {
|
|
|
895
1611
|
}
|
|
896
1612
|
/** Register (or replace) a workspace-scoped pack from a manifest. */
|
|
897
1613
|
async registerPack(workspaceId, manifest) {
|
|
898
|
-
return await this.requestJson(
|
|
1614
|
+
return await this.requestJson(
|
|
1615
|
+
"POST",
|
|
1616
|
+
`/v1/workspaces/${workspaceId}/packs`,
|
|
1617
|
+
manifest
|
|
1618
|
+
);
|
|
899
1619
|
}
|
|
900
1620
|
async getPack(workspaceId, packId) {
|
|
901
|
-
return await this.requestJson(
|
|
1621
|
+
return await this.requestJson(
|
|
1622
|
+
"GET",
|
|
1623
|
+
`/v1/workspaces/${workspaceId}/packs/${encodeURIComponent(packId)}`
|
|
1624
|
+
);
|
|
902
1625
|
}
|
|
903
1626
|
async enablePack(workspaceId, packId, request = {}) {
|
|
904
1627
|
return await this.requestJson(
|
|
@@ -909,18 +1632,31 @@ var OpenGeniClient = class {
|
|
|
909
1632
|
}
|
|
910
1633
|
/** Unregister a workspace-scoped pack (built-in packs cannot be deleted). */
|
|
911
1634
|
async deletePack(workspaceId, packId) {
|
|
912
|
-
await this.requestVoid(
|
|
1635
|
+
await this.requestVoid(
|
|
1636
|
+
"DELETE",
|
|
1637
|
+
`/v1/workspaces/${workspaceId}/packs/${encodeURIComponent(packId)}`
|
|
1638
|
+
);
|
|
913
1639
|
}
|
|
914
1640
|
async listPackInstallations(workspaceId) {
|
|
915
|
-
return await this.requestJson(
|
|
1641
|
+
return await this.requestJson(
|
|
1642
|
+
"GET",
|
|
1643
|
+
`/v1/workspaces/${workspaceId}/packs/installations`
|
|
1644
|
+
);
|
|
916
1645
|
}
|
|
917
1646
|
// --- Capabilities -------------------------------------------------------------------------
|
|
918
1647
|
async listCapabilities(workspaceId) {
|
|
919
|
-
return await this.requestJson(
|
|
1648
|
+
return await this.requestJson(
|
|
1649
|
+
"GET",
|
|
1650
|
+
`/v1/workspaces/${workspaceId}/capabilities`
|
|
1651
|
+
);
|
|
920
1652
|
}
|
|
921
1653
|
/** Add a manual capability catalog item (e.g. a remote MCP server). */
|
|
922
1654
|
async createCapability(workspaceId, request) {
|
|
923
|
-
return await this.requestJson(
|
|
1655
|
+
return await this.requestJson(
|
|
1656
|
+
"POST",
|
|
1657
|
+
`/v1/workspaces/${workspaceId}/capabilities`,
|
|
1658
|
+
request
|
|
1659
|
+
);
|
|
924
1660
|
}
|
|
925
1661
|
async enableCapability(workspaceId, capabilityId, request = {}) {
|
|
926
1662
|
return await this.requestJson(
|
|
@@ -947,6 +1683,49 @@ var OpenGeniClient = class {
|
|
|
947
1683
|
}
|
|
948
1684
|
);
|
|
949
1685
|
}
|
|
1686
|
+
// --- Connections -------------------------------------------------------------------------------
|
|
1687
|
+
async listConnections(workspaceId) {
|
|
1688
|
+
const response = await this.requestJson(
|
|
1689
|
+
"GET",
|
|
1690
|
+
`/v1/workspaces/${workspaceId}/connections`
|
|
1691
|
+
);
|
|
1692
|
+
return response.connections;
|
|
1693
|
+
}
|
|
1694
|
+
async createConnection(workspaceId, request) {
|
|
1695
|
+
const response = await this.requestJson(
|
|
1696
|
+
"POST",
|
|
1697
|
+
`/v1/workspaces/${workspaceId}/connections`,
|
|
1698
|
+
request
|
|
1699
|
+
);
|
|
1700
|
+
return response.connection;
|
|
1701
|
+
}
|
|
1702
|
+
async updateConnection(workspaceId, connectionId, request) {
|
|
1703
|
+
const response = await this.requestJson(
|
|
1704
|
+
"PATCH",
|
|
1705
|
+
`/v1/workspaces/${workspaceId}/connections/${connectionId}`,
|
|
1706
|
+
request
|
|
1707
|
+
);
|
|
1708
|
+
return response.connection;
|
|
1709
|
+
}
|
|
1710
|
+
async deleteConnection(workspaceId, connectionId) {
|
|
1711
|
+
const response = await this.requestJson(
|
|
1712
|
+
"DELETE",
|
|
1713
|
+
`/v1/workspaces/${workspaceId}/connections/${connectionId}`
|
|
1714
|
+
);
|
|
1715
|
+
return response.connection;
|
|
1716
|
+
}
|
|
1717
|
+
/** Start an OAuth connection flow; redirect the user to the returned `authorizationUrl`. */
|
|
1718
|
+
async startConnectionOAuth(workspaceId, request) {
|
|
1719
|
+
return await this.requestJson(
|
|
1720
|
+
"POST",
|
|
1721
|
+
`/v1/workspaces/${workspaceId}/connections/oauth/start`,
|
|
1722
|
+
request
|
|
1723
|
+
);
|
|
1724
|
+
}
|
|
1725
|
+
/** Public, immutably-cached URL for a catalog item's logo, or null when the item has none. */
|
|
1726
|
+
catalogAssetUrl(logoAssetPath) {
|
|
1727
|
+
return logoAssetPath ? `${this.baseUrl}/v1/${logoAssetPath}` : null;
|
|
1728
|
+
}
|
|
950
1729
|
// --- GitHub ----------------------------------------------------------------------------------
|
|
951
1730
|
/** GitHub App configuration status + a signed install URL when configured. */
|
|
952
1731
|
async getGitHubApp(workspaceId) {
|
|
@@ -961,11 +1740,17 @@ var OpenGeniClient = class {
|
|
|
961
1740
|
return this.url(`/v1/workspaces/${workspaceId}/github/connect`, { state });
|
|
962
1741
|
}
|
|
963
1742
|
async listGitHubRepositories(workspaceId) {
|
|
964
|
-
return await this.requestJson(
|
|
1743
|
+
return await this.requestJson(
|
|
1744
|
+
"GET",
|
|
1745
|
+
`/v1/workspaces/${workspaceId}/github/repositories`
|
|
1746
|
+
);
|
|
965
1747
|
}
|
|
966
1748
|
/** Re-sync the installation's repository list from GitHub. */
|
|
967
1749
|
async syncGitHubRepositories(workspaceId) {
|
|
968
|
-
return await this.requestJson(
|
|
1750
|
+
return await this.requestJson(
|
|
1751
|
+
"POST",
|
|
1752
|
+
`/v1/workspaces/${workspaceId}/github/repositories/sync`
|
|
1753
|
+
);
|
|
969
1754
|
}
|
|
970
1755
|
/** Build a GitHub App manifest + the GitHub URL to submit it to. */
|
|
971
1756
|
async createGitHubAppManifest(workspaceId, request = {}) {
|
|
@@ -977,16 +1762,26 @@ var OpenGeniClient = class {
|
|
|
977
1762
|
}
|
|
978
1763
|
// --- API keys ----------------------------------------------------------------------------------
|
|
979
1764
|
async listApiKeys(workspaceId) {
|
|
980
|
-
const response = await this.requestJson(
|
|
1765
|
+
const response = await this.requestJson(
|
|
1766
|
+
"GET",
|
|
1767
|
+
`/v1/workspaces/${workspaceId}/api-keys`
|
|
1768
|
+
);
|
|
981
1769
|
return response.apiKeys;
|
|
982
1770
|
}
|
|
983
1771
|
/** The returned `token` is shown once; only its prefix is stored. */
|
|
984
1772
|
async createApiKey(workspaceId, request) {
|
|
985
|
-
return await this.requestJson(
|
|
1773
|
+
return await this.requestJson(
|
|
1774
|
+
"POST",
|
|
1775
|
+
`/v1/workspaces/${workspaceId}/api-keys`,
|
|
1776
|
+
request
|
|
1777
|
+
);
|
|
986
1778
|
}
|
|
987
1779
|
/** Revoke an API key. Returns the revoked key. */
|
|
988
1780
|
async deleteApiKey(workspaceId, apiKeyId) {
|
|
989
|
-
return await this.requestJson(
|
|
1781
|
+
return await this.requestJson(
|
|
1782
|
+
"DELETE",
|
|
1783
|
+
`/v1/workspaces/${workspaceId}/api-keys/${apiKeyId}`
|
|
1784
|
+
);
|
|
990
1785
|
}
|
|
991
1786
|
// --- Billing (account-scoped) --------------------------------------------------------------------
|
|
992
1787
|
async getBilling(options = {}) {
|
|
@@ -1001,9 +1796,14 @@ var OpenGeniClient = class {
|
|
|
1001
1796
|
});
|
|
1002
1797
|
}
|
|
1003
1798
|
async getBillingEntitlements(options = {}) {
|
|
1004
|
-
return await this.requestJson(
|
|
1005
|
-
|
|
1006
|
-
|
|
1799
|
+
return await this.requestJson(
|
|
1800
|
+
"GET",
|
|
1801
|
+
"/v1/billing/entitlements",
|
|
1802
|
+
void 0,
|
|
1803
|
+
{
|
|
1804
|
+
...options.accountId !== void 0 ? { accountId: options.accountId } : {}
|
|
1805
|
+
}
|
|
1806
|
+
);
|
|
1007
1807
|
}
|
|
1008
1808
|
/** Start a Stripe checkout for prepaid credits. */
|
|
1009
1809
|
async createBillingCheckout(request) {
|
|
@@ -1014,7 +1814,8 @@ var OpenGeniClient = class {
|
|
|
1014
1814
|
const extra = typeof this.options.headers === "function" ? this.options.headers() : this.options.headers;
|
|
1015
1815
|
return {
|
|
1016
1816
|
...this.options.apiKey ? { Authorization: `Bearer ${this.options.apiKey}` } : {},
|
|
1017
|
-
...extra
|
|
1817
|
+
...extra,
|
|
1818
|
+
[OPENGENI_API_CONTRACT_HEADER]: OPENGENI_API_CONTRACT_REVISION
|
|
1018
1819
|
};
|
|
1019
1820
|
}
|
|
1020
1821
|
url(path, query = {}) {
|
|
@@ -1024,15 +1825,25 @@ var OpenGeniClient = class {
|
|
|
1024
1825
|
// --- Codex (ChatGPT) subscription (workspace-scoped) --------------------------------------------
|
|
1025
1826
|
/** Connection state + the codex models the workspace may select (empty until connected). */
|
|
1026
1827
|
async codexStatus(workspaceId) {
|
|
1027
|
-
return await this.requestJson(
|
|
1828
|
+
return await this.requestJson(
|
|
1829
|
+
"GET",
|
|
1830
|
+
`/v1/workspaces/${workspaceId}/codex/status`
|
|
1831
|
+
);
|
|
1028
1832
|
}
|
|
1029
1833
|
/** Begin device-code login: show `userCode` at `verificationUri`, then poll with `state`. */
|
|
1030
1834
|
async codexConnectStart(workspaceId) {
|
|
1031
|
-
return await this.requestJson(
|
|
1835
|
+
return await this.requestJson(
|
|
1836
|
+
"POST",
|
|
1837
|
+
`/v1/workspaces/${workspaceId}/codex/connect/start`
|
|
1838
|
+
);
|
|
1032
1839
|
}
|
|
1033
1840
|
/** Poll device-code authorization with the `state` from {@link codexConnectStart}. */
|
|
1034
1841
|
async codexConnectPoll(workspaceId, state) {
|
|
1035
|
-
return await this.requestJson(
|
|
1842
|
+
return await this.requestJson(
|
|
1843
|
+
"POST",
|
|
1844
|
+
`/v1/workspaces/${workspaceId}/codex/connect/poll`,
|
|
1845
|
+
{ state }
|
|
1846
|
+
);
|
|
1036
1847
|
}
|
|
1037
1848
|
/** Remaining usage / limits for the connected (ACTIVE) subscription. Back-compat. */
|
|
1038
1849
|
async codexUsage(workspaceId) {
|
|
@@ -1040,39 +1851,69 @@ var OpenGeniClient = class {
|
|
|
1040
1851
|
}
|
|
1041
1852
|
/** Live per-account usage read (refreshes THIS account's bearer; writes the cache). */
|
|
1042
1853
|
async codexAccountUsage(workspaceId, accountId) {
|
|
1043
|
-
return await this.requestJson(
|
|
1854
|
+
return await this.requestJson(
|
|
1855
|
+
"GET",
|
|
1856
|
+
`/v1/workspaces/${workspaceId}/codex/accounts/${accountId}/usage`
|
|
1857
|
+
);
|
|
1044
1858
|
}
|
|
1045
1859
|
/** Batched live refresh across every connected account, keyed by credential id. */
|
|
1046
1860
|
async refreshCodexUsage(workspaceId) {
|
|
1047
|
-
return await this.requestJson(
|
|
1861
|
+
return await this.requestJson(
|
|
1862
|
+
"POST",
|
|
1863
|
+
`/v1/workspaces/${workspaceId}/codex/usage/refresh`
|
|
1864
|
+
);
|
|
1048
1865
|
}
|
|
1049
1866
|
/** Disconnect ALL accounts (legacy workspace-wide). Prefer `disconnectCodexAccount`. */
|
|
1050
1867
|
async codexDisconnect(workspaceId) {
|
|
1051
|
-
return await this.requestJson(
|
|
1868
|
+
return await this.requestJson(
|
|
1869
|
+
"DELETE",
|
|
1870
|
+
`/v1/workspaces/${workspaceId}/codex`
|
|
1871
|
+
);
|
|
1052
1872
|
}
|
|
1053
1873
|
/** List every connected Codex account + the workspace active pointer + settings. */
|
|
1054
1874
|
async listCodexAccounts(workspaceId) {
|
|
1055
|
-
return await this.requestJson(
|
|
1875
|
+
return await this.requestJson(
|
|
1876
|
+
"GET",
|
|
1877
|
+
`/v1/workspaces/${workspaceId}/codex/accounts`
|
|
1878
|
+
);
|
|
1056
1879
|
}
|
|
1057
1880
|
/** Switch the workspace ACTIVE Codex account (the one unpinned sessions use). */
|
|
1058
1881
|
async activateCodexAccount(workspaceId, accountId) {
|
|
1059
|
-
return await this.requestJson(
|
|
1882
|
+
return await this.requestJson(
|
|
1883
|
+
"POST",
|
|
1884
|
+
`/v1/workspaces/${workspaceId}/codex/accounts/${accountId}/activate`
|
|
1885
|
+
);
|
|
1060
1886
|
}
|
|
1061
1887
|
/** P3: enable/disable Codex auto-rotation and/or pick the strategy. Returns the effective settings. */
|
|
1062
1888
|
async setCodexRotationSettings(workspaceId, patch) {
|
|
1063
|
-
return await this.requestJson(
|
|
1889
|
+
return await this.requestJson(
|
|
1890
|
+
"PATCH",
|
|
1891
|
+
`/v1/workspaces/${workspaceId}/codex/settings`,
|
|
1892
|
+
patch
|
|
1893
|
+
);
|
|
1064
1894
|
}
|
|
1065
1895
|
/** Disconnect ONE Codex account by id (re-picks active when the removed one was active). */
|
|
1066
1896
|
async disconnectCodexAccount(workspaceId, accountId) {
|
|
1067
|
-
return await this.requestJson(
|
|
1897
|
+
return await this.requestJson(
|
|
1898
|
+
"DELETE",
|
|
1899
|
+
`/v1/workspaces/${workspaceId}/codex/accounts/${accountId}`
|
|
1900
|
+
);
|
|
1068
1901
|
}
|
|
1069
1902
|
/** Rename a Codex account (label only in P1). */
|
|
1070
1903
|
async renameCodexAccount(workspaceId, accountId, label) {
|
|
1071
|
-
return await this.requestJson(
|
|
1904
|
+
return await this.requestJson(
|
|
1905
|
+
"PATCH",
|
|
1906
|
+
`/v1/workspaces/${workspaceId}/codex/accounts/${accountId}`,
|
|
1907
|
+
{ label }
|
|
1908
|
+
);
|
|
1072
1909
|
}
|
|
1073
1910
|
/** Pin (or unpin via "auto") a session's Codex account. Applies on the next turn. */
|
|
1074
1911
|
async pinSessionCodexAccount(workspaceId, sessionId, target) {
|
|
1075
|
-
return await this.requestJson(
|
|
1912
|
+
return await this.requestJson(
|
|
1913
|
+
"POST",
|
|
1914
|
+
`/v1/workspaces/${workspaceId}/sessions/${sessionId}/codex-account`,
|
|
1915
|
+
{ target }
|
|
1916
|
+
);
|
|
1076
1917
|
}
|
|
1077
1918
|
async requestJson(method, path, body, query = {}) {
|
|
1078
1919
|
const response = await this.fetchImpl(this.url(path, query), {
|
|
@@ -1084,6 +1925,7 @@ var OpenGeniClient = class {
|
|
|
1084
1925
|
},
|
|
1085
1926
|
...body !== void 0 ? { body: JSON.stringify(body) } : {}
|
|
1086
1927
|
});
|
|
1928
|
+
assertApiContractResponse(response);
|
|
1087
1929
|
if (!response.ok) {
|
|
1088
1930
|
throw new OpenGeniApiError(response.status, await safeText(response));
|
|
1089
1931
|
}
|
|
@@ -1100,11 +1942,18 @@ var OpenGeniClient = class {
|
|
|
1100
1942
|
},
|
|
1101
1943
|
...body !== void 0 ? { body: JSON.stringify(body) } : {}
|
|
1102
1944
|
});
|
|
1945
|
+
assertApiContractResponse(response);
|
|
1103
1946
|
if (!response.ok) {
|
|
1104
1947
|
throw new OpenGeniApiError(response.status, await safeText(response));
|
|
1105
1948
|
}
|
|
1106
1949
|
}
|
|
1107
1950
|
};
|
|
1951
|
+
function assertApiContractResponse(response) {
|
|
1952
|
+
const actual = response.headers.get(OPENGENI_API_CONTRACT_HEADER);
|
|
1953
|
+
if (actual && actual !== OPENGENI_API_CONTRACT_REVISION) {
|
|
1954
|
+
throw new OpenGeniApiContractMismatchError(OPENGENI_API_CONTRACT_REVISION, actual);
|
|
1955
|
+
}
|
|
1956
|
+
}
|
|
1108
1957
|
async function safeText(response) {
|
|
1109
1958
|
try {
|
|
1110
1959
|
return await response.text();
|
|
@@ -1112,9 +1961,6 @@ async function safeText(response) {
|
|
|
1112
1961
|
return "";
|
|
1113
1962
|
}
|
|
1114
1963
|
}
|
|
1115
|
-
function delay(ms) {
|
|
1116
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1117
|
-
}
|
|
1118
1964
|
|
|
1119
1965
|
// src/proxy.ts
|
|
1120
1966
|
function formatSseEvent(event) {
|
|
@@ -1298,120 +2144,12 @@ function ttydInputFrame(data) {
|
|
|
1298
2144
|
function ttydResizeFrame(columns, rows) {
|
|
1299
2145
|
return TtydClientCommand.RESIZE + JSON.stringify({ columns, rows });
|
|
1300
2146
|
}
|
|
1301
|
-
|
|
1302
|
-
// src/types.ts
|
|
1303
|
-
var SESSION_EVENT_TYPES = [
|
|
1304
|
-
"session.created",
|
|
1305
|
-
"session.status.changed",
|
|
1306
|
-
"session.requiresAction",
|
|
1307
|
-
"session.context.compacted",
|
|
1308
|
-
"session.context.cleared",
|
|
1309
|
-
"user.message",
|
|
1310
|
-
"user.interrupt",
|
|
1311
|
-
"user.approvalDecision",
|
|
1312
|
-
"turn.queued",
|
|
1313
|
-
"turn.updated",
|
|
1314
|
-
"turn.started",
|
|
1315
|
-
"turn.completed",
|
|
1316
|
-
"turn.failed",
|
|
1317
|
-
"turn.cancelled",
|
|
1318
|
-
"turn.preempted",
|
|
1319
|
-
"agent.message.delta",
|
|
1320
|
-
"agent.message.completed",
|
|
1321
|
-
"agent.reasoning.delta",
|
|
1322
|
-
"agent.toolCall.created",
|
|
1323
|
-
"agent.toolCall.output",
|
|
1324
|
-
"tool.auth_needed",
|
|
1325
|
-
"agent.updated",
|
|
1326
|
-
"sandbox.operation.started",
|
|
1327
|
-
"sandbox.operation.completed",
|
|
1328
|
-
"sandbox.operation.failed",
|
|
1329
|
-
"sandbox.command.output.delta",
|
|
1330
|
-
"artifact.created",
|
|
1331
|
-
"goal.set",
|
|
1332
|
-
"goal.updated",
|
|
1333
|
-
"goal.completed",
|
|
1334
|
-
"goal.paused",
|
|
1335
|
-
"goal.resumed",
|
|
1336
|
-
"goal.continuation",
|
|
1337
|
-
// Channel-B desktop pixel-plane signals (mirror of contracts SessionEventType;
|
|
1338
|
-
// the contract-parity test asserts sorted equality).
|
|
1339
|
-
"stream.url.rotated",
|
|
1340
|
-
"stream.opened",
|
|
1341
|
-
"stream.closed",
|
|
1342
|
-
"stream.revoked",
|
|
1343
|
-
// Channel-B recording signals (P4.3 — "agent films itself proving the fix").
|
|
1344
|
-
"recording.started",
|
|
1345
|
-
"recording.available",
|
|
1346
|
-
"recording.failed",
|
|
1347
|
-
// Channel-A structured-service notifications (P4.4; mirror of contracts
|
|
1348
|
-
// SessionEventType — the contract-parity test asserts sorted equality).
|
|
1349
|
-
"fs.changed",
|
|
1350
|
-
"git.changed",
|
|
1351
|
-
"terminal.pty.started",
|
|
1352
|
-
"terminal.pty.output.delta",
|
|
1353
|
-
"terminal.pty.exited",
|
|
1354
|
-
"session.title_set",
|
|
1355
|
-
// Multi-account Codex (P1): the session's inference account changed.
|
|
1356
|
-
"codex.account.switched"
|
|
1357
|
-
];
|
|
1358
|
-
var KNOWN_PERMISSIONS = [
|
|
1359
|
-
"account:read",
|
|
1360
|
-
"account:admin",
|
|
1361
|
-
"members:manage",
|
|
1362
|
-
"workspace:create",
|
|
1363
|
-
"billing:read",
|
|
1364
|
-
"billing:manage",
|
|
1365
|
-
"workspace:read",
|
|
1366
|
-
"workspace:admin",
|
|
1367
|
-
"sessions:create",
|
|
1368
|
-
"sessions:read",
|
|
1369
|
-
"sessions:control",
|
|
1370
|
-
// Sandbox-surfacing (mirror of @opengeni/contracts Permission). stream:view is
|
|
1371
|
-
// strictly broader than sessions:read (un-redacted pixels); stream:control is
|
|
1372
|
-
// the never-granted-v1 raw-input plane; stream:acknowledge is the secret-leak
|
|
1373
|
-
// consent gate.
|
|
1374
|
-
"stream:view",
|
|
1375
|
-
"stream:control",
|
|
1376
|
-
"stream:acknowledge",
|
|
1377
|
-
"files:upload",
|
|
1378
|
-
"files:read",
|
|
1379
|
-
"files:write",
|
|
1380
|
-
"terminal:attach",
|
|
1381
|
-
"documents:manage",
|
|
1382
|
-
"documents:search",
|
|
1383
|
-
"scheduled_tasks:manage",
|
|
1384
|
-
"scheduled_tasks:run",
|
|
1385
|
-
"github:manage",
|
|
1386
|
-
"github:use",
|
|
1387
|
-
"api_keys:manage",
|
|
1388
|
-
"connections:read",
|
|
1389
|
-
"connections:write",
|
|
1390
|
-
"environments:manage",
|
|
1391
|
-
"environments:use",
|
|
1392
|
-
"mcp_servers:attach",
|
|
1393
|
-
"toolspace:call",
|
|
1394
|
-
"goals:manage",
|
|
1395
|
-
"enrollments:read",
|
|
1396
|
-
"enrollments:manage"
|
|
1397
|
-
];
|
|
1398
|
-
var KNOWN_USAGE_EVENT_TYPES = [
|
|
1399
|
-
"agent_run.created",
|
|
1400
|
-
"agent_run.completed",
|
|
1401
|
-
"model.tokens",
|
|
1402
|
-
"model.cost",
|
|
1403
|
-
"file.uploaded",
|
|
1404
|
-
"file.deleted",
|
|
1405
|
-
"document.indexed",
|
|
1406
|
-
"scheduled_task.fired",
|
|
1407
|
-
"api_key.request",
|
|
1408
|
-
// sandbox warm-time metering (P2.1) — mirrors contracts UsageEventType.
|
|
1409
|
-
"sandbox.warm_seconds",
|
|
1410
|
-
"sandbox.warm_cost"
|
|
1411
|
-
];
|
|
1412
2147
|
export {
|
|
1413
2148
|
KNOWN_PERMISSIONS,
|
|
1414
2149
|
KNOWN_USAGE_EVENT_TYPES,
|
|
2150
|
+
OPENGENI_API_CONTRACT_HEADER,
|
|
2151
|
+
OPENGENI_API_CONTRACT_REVISION,
|
|
2152
|
+
OpenGeniApiContractMismatchError,
|
|
1415
2153
|
OpenGeniApiError,
|
|
1416
2154
|
OpenGeniClient,
|
|
1417
2155
|
OpenGeniStreamError,
|
|
@@ -1430,6 +2168,7 @@ export {
|
|
|
1430
2168
|
sessionEventsToSseResponse,
|
|
1431
2169
|
sessionEventsToSseStream,
|
|
1432
2170
|
streamSessionEvents,
|
|
2171
|
+
streamWorkspaceControlEvents,
|
|
1433
2172
|
terminalSocketUrl,
|
|
1434
2173
|
ttydAuthFrame,
|
|
1435
2174
|
ttydInputFrame,
|