primitive-admin 1.2.0-alpha.2 → 1.2.0-alpha.4

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.
Files changed (57) hide show
  1. package/dist/src/commands/agent-sessions.js +4 -0
  2. package/dist/src/commands/agent-sessions.js.map +1 -1
  3. package/dist/src/commands/databases.js +13 -38
  4. package/dist/src/commands/databases.js.map +1 -1
  5. package/dist/src/commands/documents.d.ts +1 -1
  6. package/dist/src/commands/documents.js +70 -33
  7. package/dist/src/commands/documents.js.map +1 -1
  8. package/dist/src/commands/prompts.d.ts +7 -0
  9. package/dist/src/commands/prompts.js +44 -0
  10. package/dist/src/commands/prompts.js.map +1 -1
  11. package/dist/src/commands/sync.d.ts +12 -29
  12. package/dist/src/commands/sync.js +128 -138
  13. package/dist/src/commands/sync.js.map +1 -1
  14. package/dist/src/lib/aggregate-output.d.ts +25 -0
  15. package/dist/src/lib/aggregate-output.js +53 -0
  16. package/dist/src/lib/aggregate-output.js.map +1 -0
  17. package/dist/src/lib/api-client.d.ts +29 -16
  18. package/dist/src/lib/api-client.js +30 -28
  19. package/dist/src/lib/api-client.js.map +1 -1
  20. package/dist/src/lib/config-object-descriptor.js +14 -5
  21. package/dist/src/lib/config-object-descriptor.js.map +1 -1
  22. package/dist/src/lib/db-codegen/dbGenerator.js +5 -16
  23. package/dist/src/lib/db-codegen/dbGenerator.js.map +1 -1
  24. package/dist/src/lib/db-codegen/dbNaming.d.ts +3 -12
  25. package/dist/src/lib/db-codegen/dbNaming.js +3 -16
  26. package/dist/src/lib/db-codegen/dbNaming.js.map +1 -1
  27. package/dist/src/lib/db-codegen/dbTemplates.d.ts +7 -56
  28. package/dist/src/lib/db-codegen/dbTemplates.js +25 -125
  29. package/dist/src/lib/db-codegen/dbTemplates.js.map +1 -1
  30. package/dist/src/lib/db-codegen/dbTypeIR.d.ts +1 -1
  31. package/dist/src/lib/function-sync.d.ts +3 -16
  32. package/dist/src/lib/function-sync.js +14 -18
  33. package/dist/src/lib/function-sync.js.map +1 -1
  34. package/dist/src/lib/generated-config-surfaces.d.ts +172 -47
  35. package/dist/src/lib/generated-config-surfaces.js +599 -90
  36. package/dist/src/lib/generated-config-surfaces.js.map +1 -1
  37. package/dist/src/lib/generated-sdk-types.d.ts +1 -1
  38. package/dist/src/lib/generated-sdk-types.js +1 -1
  39. package/dist/src/lib/generated-sdk-types.js.map +1 -1
  40. package/dist/src/lib/prompt-schema-codegen.js +5 -2
  41. package/dist/src/lib/prompt-schema-codegen.js.map +1 -1
  42. package/dist/src/lib/swift-codegen/dbGenerator.d.ts +4 -3
  43. package/dist/src/lib/swift-codegen/dbGenerator.js +14 -117
  44. package/dist/src/lib/swift-codegen/dbGenerator.js.map +1 -1
  45. package/dist/src/lib/swift-codegen/generator.d.ts +5 -5
  46. package/dist/src/lib/swift-codegen/generator.js +8 -13
  47. package/dist/src/lib/swift-codegen/generator.js.map +1 -1
  48. package/dist/src/lib/workflow-codegen/generator.d.ts +7 -7
  49. package/dist/src/lib/workflow-codegen/generator.js +16 -23
  50. package/dist/src/lib/workflow-codegen/generator.js.map +1 -1
  51. package/dist/src/lib/workflow-codegen/invokerIR.d.ts +6 -12
  52. package/dist/src/lib/workflow-codegen/invokerIR.js +4 -5
  53. package/dist/src/lib/workflow-codegen/invokerIR.js.map +1 -1
  54. package/dist/src/lib/workflow-toml-validator.d.ts +2 -0
  55. package/dist/src/lib/workflow-toml-validator.js +13 -0
  56. package/dist/src/lib/workflow-toml-validator.js.map +1 -1
  57. package/package.json +2 -2
@@ -0,0 +1,25 @@
1
+ /** One aggregate row as the routes answer it. */
2
+ export interface AggregateOutputRow {
3
+ group?: Record<string, unknown>;
4
+ [operationKey: string]: unknown;
5
+ }
6
+ /** What the command asked for: the group levels and its one operation. */
7
+ export interface AggregateOutputRequest {
8
+ groupBy: string[];
9
+ op: string;
10
+ field?: string;
11
+ }
12
+ /** A rendered aggregate: a key/value line, or a ready-to-print table. */
13
+ export type RenderedAggregate = {
14
+ kind: "scalar";
15
+ label: string;
16
+ value: string;
17
+ } | {
18
+ kind: "table";
19
+ text: string;
20
+ };
21
+ /**
22
+ * Render an aggregate's rows for a terminal. `rows` is the route body's
23
+ * `result`; anything that is not an array renders as no rows.
24
+ */
25
+ export declare function renderAggregateResult(rows: unknown, request: AggregateOutputRequest): RenderedAggregate;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Human output for `databases records aggregate` and
3
+ * `documents records aggregate`, shared so the two print alike.
4
+ *
5
+ * Both routes answer rows, `{ group, ...operationValues }`. Ungrouped, the one
6
+ * row's value is printed as a key/value line; grouped, as a table with one
7
+ * column per row group key and one value column. A `null` group value prints
8
+ * as `null` so it stays distinct from an empty string (an empty cell); a
9
+ * `null` operation value prints `—`.
10
+ */
11
+ import { formatTable } from "./output.js";
12
+ const display = (value) => value === null || value === undefined ? "—" : String(value);
13
+ /**
14
+ * Render an aggregate's rows for a terminal. `rows` is the route body's
15
+ * `result`; anything that is not an array renders as no rows.
16
+ */
17
+ export function renderAggregateResult(rows, request) {
18
+ const list = Array.isArray(rows) ? rows : [];
19
+ const operationKey = request.op === "count" ? "count" : `${request.op}_${request.field}`;
20
+ if (request.groupBy.length === 0) {
21
+ // The field name is reproduced verbatim in both labels — it is a
22
+ // user-supplied identifier, and case-folding it produced
23
+ // `avg(lastvalue)` for `--field lastValue` (issue #2357).
24
+ return {
25
+ kind: "scalar",
26
+ label: request.op === "count"
27
+ ? "count"
28
+ : `${request.op.toLowerCase()}(${request.field})`,
29
+ value: display(list[0]?.[operationKey]),
30
+ };
31
+ }
32
+ const groupKeys = list.length > 0 ? Object.keys(list[0].group ?? {}) : request.groupBy;
33
+ const valueLabel = request.op === "count"
34
+ ? "COUNT"
35
+ : `${request.op.toUpperCase()}(${request.field})`;
36
+ const table = list.map((row) => {
37
+ const cells = {};
38
+ groupKeys.forEach((key, index) => {
39
+ const value = row.group?.[key];
40
+ cells[`g${index}`] = value === null || value === undefined ? "null" : String(value);
41
+ });
42
+ cells.value = display(row[operationKey]);
43
+ return cells;
44
+ });
45
+ return {
46
+ kind: "table",
47
+ text: formatTable(table, [
48
+ ...groupKeys.map((key, index) => ({ header: key.toUpperCase(), key: `g${index}` })),
49
+ { header: valueLabel, key: "value" },
50
+ ]),
51
+ };
52
+ }
53
+ //# sourceMappingURL=aggregate-output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aggregate-output.js","sourceRoot":"","sources":["../../../src/lib/aggregate-output.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAoB1C,MAAM,OAAO,GAAG,CAAC,KAAc,EAAU,EAAE,CACzC,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAE9D;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CACnC,IAAa,EACb,OAA+B;IAE/B,MAAM,IAAI,GAAyB,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IACnE,MAAM,YAAY,GAChB,OAAO,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,EAAE,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;IAEtE,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,iEAAiE;QACjE,yDAAyD;QACzD,0DAA0D;QAC1D,OAAO;YACL,IAAI,EAAE,QAAQ;YACd,KAAK,EACH,OAAO,CAAC,EAAE,KAAK,OAAO;gBACpB,CAAC,CAAC,OAAO;gBACT,CAAC,CAAC,GAAG,OAAO,CAAC,EAAE,CAAC,WAAW,EAAE,IAAI,OAAO,CAAC,KAAK,GAAG;YACrD,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC;SACxC,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;IACvF,MAAM,UAAU,GACd,OAAO,CAAC,EAAE,KAAK,OAAO;QACpB,CAAC,CAAC,OAAO;QACT,CAAC,CAAC,GAAG,OAAO,CAAC,EAAE,CAAC,WAAW,EAAE,IAAI,OAAO,CAAC,KAAK,GAAG,CAAC;IACtD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QAC7B,MAAM,KAAK,GAA2B,EAAE,CAAC;QACzC,SAAS,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;YAC/B,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC;YAC/B,KAAK,CAAC,IAAI,KAAK,EAAE,CAAC,GAAG,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACtF,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC;QACzC,OAAO,KAAK,CAAC;IACf,CAAC,CAAC,CAAC;IACH,OAAO;QACL,IAAI,EAAE,OAAO;QACb,IAAI,EAAE,WAAW,CAAC,KAAK,EAAE;YACvB,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,WAAW,EAAE,EAAE,GAAG,EAAE,IAAI,KAAK,EAAE,EAAE,CAAC,CAAC;YACnF,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,OAAO,EAAE;SACrC,CAAC;KACH,CAAC;AACJ,CAAC"}
@@ -1,5 +1,17 @@
1
1
  import { type ListEnvelope } from "./paginate.js";
2
2
  import { type GlobalAppRef, type WorkflowUsageReport } from "./workflow-usage.js";
3
+ /**
4
+ * #4262 — an agent prompt's test case: its `[test.agent]` block on the wire.
5
+ * `agentHistory` is JSON text; context and the expected call are parsed.
6
+ */
7
+ export interface AgentTestCaseWireFields {
8
+ agentHistory?: string | null;
9
+ agentContext?: Record<string, any> | null;
10
+ agentTimezone?: string | null;
11
+ agentLocale?: string | null;
12
+ agentExpectedToolCall?: Record<string, any> | null;
13
+ agentExpectedNoToolCall?: boolean | null;
14
+ }
3
15
  /**
4
16
  * Metadata for a single bucket blob, as returned by the metadata endpoint
5
17
  * `GET blob-buckets/:bucketId/blobs/:blobId/metadata`. Mirrors the published
@@ -1358,7 +1370,7 @@ export declare class ApiClient {
1358
1370
  evaluatorConfigId?: string;
1359
1371
  /** The sidecar's file name — the case's identity (#2896). */
1360
1372
  key?: string;
1361
- }): Promise<any>;
1373
+ } & AgentTestCaseWireFields): Promise<any>;
1362
1374
  updateTestCase(appId: string, blockType: "prompt" | "integration" | "workflow" | "script", blockId: string, testCaseId: string, payload: {
1363
1375
  name?: string;
1364
1376
  description?: string | null;
@@ -1371,7 +1383,7 @@ export declare class ApiClient {
1371
1383
  evaluatorConfigId?: string | null;
1372
1384
  /** The sidecar's file name, on a create-or-rename backfill (#2896). */
1373
1385
  key?: string;
1374
- }): Promise<any>;
1386
+ } & AgentTestCaseWireFields): Promise<any>;
1375
1387
  deleteTestCase(appId: string, blockType: "prompt" | "integration" | "workflow" | "script", blockId: string, testCaseId: string): Promise<void>;
1376
1388
  listTestCaseAttachments(appId: string, blockType: "prompt" | "integration" | "workflow" | "script", blockId: string, testCaseId: string): Promise<{
1377
1389
  attachments: Array<{
@@ -1863,7 +1875,7 @@ export declare class ApiClient {
1863
1875
  limit?: number;
1864
1876
  cursor?: string;
1865
1877
  direction?: number;
1866
- }, token?: string, options?: {
1878
+ }, options?: {
1867
1879
  timing?: boolean;
1868
1880
  }): Promise<any>;
1869
1881
  /**
@@ -1881,11 +1893,6 @@ export declare class ApiClient {
1881
1893
  imported: number;
1882
1894
  failed: number;
1883
1895
  }>;
1884
- /**
1885
- * Make a request using a specific JWT token instead of the CLI's credentials.
1886
- * Used for executing operations as a different user.
1887
- */
1888
- requestWithToken<T = any>(path: string, token: string, options?: RequestInit): Promise<T>;
1889
1896
  listDatabaseIndexes(appId: string, databaseId: string, modelName?: string): Promise<any>;
1890
1897
  registerDatabaseIndex(appId: string, databaseId: string, data: {
1891
1898
  modelName: string;
@@ -2285,14 +2292,14 @@ export declare class ApiClient {
2285
2292
  limit?: number;
2286
2293
  cursor?: string;
2287
2294
  /** #3764 — the format the caller believes this document has. */
2288
- documentFormat?: 1 | 2;
2295
+ documentFormat?: 1 | 2 | 3;
2289
2296
  }): Promise<ListEnvelope>;
2290
2297
  /**
2291
2298
  * Count records in a document model (issue #1964 Phase 3). Returns `{ count }`.
2292
2299
  */
2293
2300
  countDocumentRecords(appId: string, documentId: string, modelName: string, queryOptions?: {
2294
2301
  filter?: Record<string, any>;
2295
- documentFormat?: 1 | 2;
2302
+ documentFormat?: 1 | 2 | 3;
2296
2303
  }): Promise<{
2297
2304
  count: number;
2298
2305
  }>;
@@ -2314,7 +2321,7 @@ export declare class ApiClient {
2314
2321
  groupBy?: string[];
2315
2322
  filter?: Record<string, any>;
2316
2323
  }, extra?: {
2317
- documentFormat?: 1 | 2;
2324
+ documentFormat?: 1 | 2 | 3;
2318
2325
  }): Promise<{
2319
2326
  result: unknown;
2320
2327
  }>;
@@ -2323,6 +2330,12 @@ export declare class ApiClient {
2323
2330
  * record/model/blob counts, approximate size, and last-modified timestamp.
2324
2331
  */
2325
2332
  getDocumentStats(appId: string, documentId: string): Promise<any>;
2333
+ /**
2334
+ * A record-log document's room (#4306): `GET documents/:id/room` →
2335
+ * `{ ok, appId, documentId, documentFormat, room }`, `room` null for a
2336
+ * format that has no record room. App admins only.
2337
+ */
2338
+ getDocumentRoom(appId: string, documentId: string): Promise<any>;
2326
2339
  /**
2327
2340
  * A large document's snapshot builds, newest first, one page (#3432).
2328
2341
  * `GET documents/:id/snapshots` → `{ items, hasMore, nextCursor? }`.
@@ -2399,7 +2412,7 @@ export declare class ApiClient {
2399
2412
  data: Record<string, unknown>;
2400
2413
  options?: Record<string, unknown>;
2401
2414
  }, extra?: {
2402
- documentFormat?: 1 | 2;
2415
+ documentFormat?: 1 | 2 | 3;
2403
2416
  }): Promise<{
2404
2417
  record: unknown;
2405
2418
  }>;
@@ -2412,7 +2425,7 @@ export declare class ApiClient {
2412
2425
  data: Record<string, unknown>;
2413
2426
  options?: Record<string, unknown>;
2414
2427
  }, extra?: {
2415
- documentFormat?: 1 | 2;
2428
+ documentFormat?: 1 | 2 | 3;
2416
2429
  }): Promise<{
2417
2430
  record: unknown;
2418
2431
  }>;
@@ -2422,7 +2435,7 @@ export declare class ApiClient {
2422
2435
  * a silent no-op per the facade contract. Returns `{ deleted: true }`.
2423
2436
  */
2424
2437
  deleteDocumentRecord(appId: string, documentId: string, modelName: string, recordId: string, extra?: {
2425
- documentFormat?: 1 | 2;
2438
+ documentFormat?: 1 | 2 | 3;
2426
2439
  }): Promise<{
2427
2440
  deleted: boolean;
2428
2441
  }>;
@@ -2433,7 +2446,7 @@ export declare class ApiClient {
2433
2446
  * `{ applied, added, updated, deleted }`.
2434
2447
  */
2435
2448
  bulkDocumentRecords(appId: string, documentId: string, operations: Array<Record<string, unknown>>, extra?: {
2436
- documentFormat?: 1 | 2;
2449
+ documentFormat?: 1 | 2 | 3;
2437
2450
  }): Promise<{
2438
2451
  applied: number;
2439
2452
  added: Array<{
@@ -2457,7 +2470,7 @@ export declare class ApiClient {
2457
2470
  documentId?: string;
2458
2471
  tags?: string[];
2459
2472
  createdBy?: string;
2460
- documentFormat?: 1 | 2;
2473
+ documentFormat?: 1 | 2 | 3;
2461
2474
  }): Promise<any>;
2462
2475
  listDocumentPermissions(appId: string, documentId: string): Promise<any[]>;
2463
2476
  grantDocumentPermission(appId: string, documentId: string, permissions: Array<{
@@ -11,6 +11,15 @@ import { drainAppsUntilConverged, } from "./workflow-usage.js";
11
11
  * fewest round trips the contract allows; a larger value is clamped there.
12
12
  */
13
13
  const ADMIN_INVENTORY_PAGE_SIZE = 100;
14
+ /** The agent block's wire keys, in the surface's order. */
15
+ const AGENT_TEST_CASE_WIRE_KEYS = [
16
+ "agentHistory",
17
+ "agentContext",
18
+ "agentTimezone",
19
+ "agentLocale",
20
+ "agentExpectedToolCall",
21
+ "agentExpectedNoToolCall",
22
+ ];
14
23
  export class ApiError extends Error {
15
24
  statusCode;
16
25
  code;
@@ -1529,6 +1538,13 @@ export class ApiClient {
1529
1538
  if (payload.expectedJsonSubset) {
1530
1539
  serverPayload.expectedJsonSubset = payload.expectedJsonSubset;
1531
1540
  }
1541
+ // #4262 — an agent case's `[test.agent]` keys, each when the caller set it:
1542
+ // presence, not truthiness, so `agentExpectedNoToolCall: false` travels. A
1543
+ // chat case sets none, and its body is unchanged.
1544
+ for (const key of AGENT_TEST_CASE_WIRE_KEYS) {
1545
+ if (payload[key] !== undefined)
1546
+ serverPayload[key] = payload[key];
1547
+ }
1532
1548
  return this.post(`/admin/api/apps/${appId}/blocks/${blockType}/${blockId}/test-cases`, serverPayload);
1533
1549
  }
1534
1550
  async updateTestCase(appId, blockType, blockId, testCaseId, payload) {
@@ -1563,6 +1579,11 @@ export class ApiClient {
1563
1579
  }
1564
1580
  if (payload.key !== undefined)
1565
1581
  serverPayload.key = payload.key;
1582
+ // #4262 — as on create; an explicit `null` clears the field.
1583
+ for (const key of AGENT_TEST_CASE_WIRE_KEYS) {
1584
+ if (payload[key] !== undefined)
1585
+ serverPayload[key] = payload[key];
1586
+ }
1566
1587
  return this.patch(`/admin/api/apps/${appId}/blocks/${blockType}/${blockId}/test-cases/${testCaseId}`, serverPayload);
1567
1588
  }
1568
1589
  async deleteTestCase(appId, blockType, blockId, testCaseId) {
@@ -2140,19 +2161,12 @@ export class ApiClient {
2140
2161
  * else (a `count`, an `aggregate`, a mutation, a `returnField: "all"`
2141
2162
  * pipeline) is returned exactly as the server sent it.
2142
2163
  */
2143
- async executeDatabaseOperation(appId, databaseId, operationName, data, token, options) {
2164
+ async executeDatabaseOperation(appId, databaseId, operationName, data, options) {
2144
2165
  const path = `/app/${appId}/api/databases/${databaseId}/operations/${encodeURIComponent(operationName)}/execute`;
2145
2166
  const extraHeaders = {};
2146
2167
  if (options?.timing) {
2147
2168
  extraHeaders["X-Timing"] = "true";
2148
2169
  }
2149
- if (token) {
2150
- return normalizeDatabaseOperationResult(await this.requestWithToken(path, token, {
2151
- method: "POST",
2152
- body: JSON.stringify(data || {}),
2153
- headers: extraHeaders,
2154
- }));
2155
- }
2156
2170
  return normalizeDatabaseOperationResult(await this.request(path, {
2157
2171
  method: "POST",
2158
2172
  body: JSON.stringify(data || {}),
@@ -2171,26 +2185,6 @@ export class ApiClient {
2171
2185
  async executeBatch(appId, databaseId, operationName, batch) {
2172
2186
  return this.post(`/app/${appId}/api/databases/${databaseId}/operations/${encodeURIComponent(operationName)}/batch`, { batch });
2173
2187
  }
2174
- /**
2175
- * Make a request using a specific JWT token instead of the CLI's credentials.
2176
- * Used for executing operations as a different user.
2177
- */
2178
- async requestWithToken(path, token, options = {}) {
2179
- const credentials = await this.ensureAuthenticated();
2180
- const url = `${credentials.serverUrl}${path}`;
2181
- const headers = {
2182
- Authorization: `Bearer ${token}`,
2183
- "Content-Type": "application/json",
2184
- ...(options.headers || {}),
2185
- };
2186
- const response = await fetchWithTLS(url, { ...options, headers });
2187
- const text = await response.text();
2188
- if (!response.ok) {
2189
- const parsed = parseErrorResponse(response, text, path);
2190
- throw new ApiError(parsed.message, response.status, parsed.code, parsed.details);
2191
- }
2192
- return text ? JSON.parse(text) : null;
2193
- }
2194
2188
  // ============================================
2195
2189
  // DATABASE INDEXES
2196
2190
  // ============================================
@@ -2796,6 +2790,14 @@ export class ApiClient {
2796
2790
  async getDocumentStats(appId, documentId) {
2797
2791
  return this.get(`/app/${appId}/api/documents/${documentId}/stats`);
2798
2792
  }
2793
+ /**
2794
+ * A record-log document's room (#4306): `GET documents/:id/room` →
2795
+ * `{ ok, appId, documentId, documentFormat, room }`, `room` null for a
2796
+ * format that has no record room. App admins only.
2797
+ */
2798
+ async getDocumentRoom(appId, documentId) {
2799
+ return this.get(`/app/${appId}/api/documents/${documentId}/room`);
2800
+ }
2799
2801
  /**
2800
2802
  * A large document's snapshot builds, newest first, one page (#3432).
2801
2803
  * `GET documents/:id/snapshots` → `{ items, hasMore, nextCursor? }`.