@alvera-ai/platform-sdk 0.17.0-next.g97c2ef9 → 0.17.0-next.gae2995f

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.
@@ -42,6 +42,7 @@
42
42
  "identifiers": [
43
43
  {
44
44
  "system": "{{ p.source_uri | json_escape }}",
45
+ "type": "digital_identifier",
45
46
  "value": "{{ p.email | json_escape }}"
46
47
  }
47
48
  ]
@@ -16,9 +16,10 @@
16
16
  workflow's — a filter that had to know about `"3 - checked out"` would
17
17
  be coupled to one vendor's export format.
18
18
 
19
- `legal_entity_id` is NEVER written here. Contract B's
19
+ `legal_entity_id` is NEVER declared or written here. Contract B's
20
20
  `mdm_input_config` resolves the patient and the platform stamps the
21
- subject's id onto the row; a column of that name would shadow it.
21
+ subject's id onto the row; the name is reserved, so declaring a column
22
+ of it 422s this create rather than shadowing the stamp.
22
23
 
23
24
  GT columns:
24
25
  * `appointment_id` — the vendor's id (unique, so a re-ingest updates)
@@ -7,8 +7,8 @@
7
7
  Contract B also carries an `mdm_input_config` (separate template), so
8
8
  the platform resolves each row's subject and stamps `legal_entity_id`
9
9
  onto the row. `legal_entity_id` is NEVER declared as a column and
10
- never written here — the stamp is the platform's, and a column of the
11
- same name would shadow it.
10
+ never written here — the stamp is the platform's, and the name is
11
+ reserved, so declaring it 422s this create rather than shadowing it.
12
12
 
13
13
  GT columns:
14
14
  * `customer_number` — Stripe's customer id (the unique column, so a
@@ -488,7 +488,7 @@ const ENRICHMENT_OUTPUT_SCHEMA = {
488
488
  }
489
489
 
490
490
  const OLLAMA_BASE_BODY =
491
- '{"model": "{{ model }}", "messages": [{"role": "user", "content": "{{ rendered_prompt | json_escape }}", "images": [{% for img in images %}{% unless forloop.first %}, {% endunless %}"{{ img.data }}"{% endfor %}]}], "stream": false, "think": false, "options": {"temperature": 0, "num_ctx": 40960}, "format": {{ schema | to_json }}}'
491
+ '{"model": "{{ model }}", "messages": [{"role": "user", "content": "{{ rendered_prompt | json_escape }}", "images": [{% for img in images %}{% unless forloop.first %}, {% endunless %}"{{ img.data }}"{% endfor %}]}], "stream": false, "think": false, "options": {"temperature": {{ temperature }}, "num_predict": {{ max_tokens }}, "num_ctx": 40960}, "format": {{ schema | to_json }}}'
492
492
 
493
493
  const OLLAMA_EXTRACTOR =
494
494
  '{"output_json": "{{ msg.message.content | json_escape }}", "explanation": "{{ msg.message.thinking | json_escape }}", "input_tokens": {{ msg.prompt_eval_count | default: 0 }}, "output_tokens": {{ msg.eval_count | default: 0 }}, "total_tokens": {{ msg.prompt_eval_count | default: 0 | plus: msg.eval_count }}}'
@@ -547,7 +547,7 @@ const ENRICHMENT_OUTPUT_SCHEMA = {
547
547
  }
548
548
 
549
549
  const OLLAMA_BASE_BODY =
550
- '{"model": "{{ model }}", "messages": [{"role": "user", "content": "{{ rendered_prompt | json_escape }}", "images": [{% for img in images %}{% unless forloop.first %}, {% endunless %}"{{ img.data }}"{% endfor %}]}], "stream": false, "think": false, "options": {"temperature": 0, "num_ctx": 40960}, "format": {{ schema | to_json }}}'
550
+ '{"model": "{{ model }}", "messages": [{"role": "user", "content": "{{ rendered_prompt | json_escape }}", "images": [{% for img in images %}{% unless forloop.first %}, {% endunless %}"{{ img.data }}"{% endfor %}]}], "stream": false, "think": false, "options": {"temperature": {{ temperature }}, "num_predict": {{ max_tokens }}, "num_ctx": 40960}, "format": {{ schema | to_json }}}'
551
551
 
552
552
  const OLLAMA_EXTRACTOR =
553
553
  '{"output_json": "{{ msg.message.content | json_escape }}", "explanation": "{{ msg.message.thinking | json_escape }}", "input_tokens": {{ msg.prompt_eval_count | default: 0 }}, "output_tokens": {{ msg.eval_count | default: 0 }}, "total_tokens": {{ msg.prompt_eval_count | default: 0 | plus: msg.eval_count }}}'
@@ -828,8 +828,8 @@ ingesting a JSON array into it is refused per row —
828
828
  still reports a row received.
829
829
 
830
830
  Do **not** declare a `legal_entity_id` column. The platform stamps it from
831
- Contract B's MDM resolve in §019, and a column of that name shadows the
832
- stamp silently.
831
+ Contract B's MDM resolve in §019, and the name is reserved — declaring it
832
+ does not shadow the stamp silently, it 422s the create.
833
833
 
834
834
  ```typescript
835
835
  const screenings = await ctx.ensure(
@@ -2177,4 +2177,4 @@ Running this walk again reuses all of it.
2177
2177
  - `datalakes.md` — the create body, and what the derived pair is for
2178
2178
  - `workflows.md` — scheduling versus firing, and the accessor tables
2179
2179
  - `interoperability_contracts.md` — the contract pair, and the
2180
- `legal_entity_id` stamp you must not shadow
2180
+ reserved `legal_entity_id` stamp you must not declare
@@ -591,8 +591,8 @@ here is. Each half matters:
591
591
  gaps that actually have entries in them.
592
592
 
593
593
  Do **not** declare a `legal_entity_id` column. The platform stamps it from
594
- Contract B's resolve, and a column of that name shadows the stamp — which
595
- would leave the review link minted against nothing.
594
+ Contract B's resolve, and the name is reserved — declaring it does not shadow
595
+ the stamp, it 422s the create, so you lose the table until you drop it.
596
596
 
597
597
  ```typescript
598
598
  const appointments = await ctx.ensure(
@@ -1366,7 +1366,7 @@ const ENRICHMENT_OUTPUT_SCHEMA = {
1366
1366
  const OLLAMA_BASE_BODY =
1367
1367
  '{"model": "{{ model }}", "messages": [{"role": "user", "content": "{{ rendered_prompt | json_escape }}", ' +
1368
1368
  '"images": [{% for img in images %}{% unless forloop.first %}, {% endunless %}"{{ img.data }}"{% endfor %}]}], ' +
1369
- '"stream": false, "think": false, "options": {"temperature": 0, "num_ctx": 40960}, "format": {{ schema | to_json }}}'
1369
+ '"stream": false, "think": false, "options": {"temperature": {{ temperature }}, "num_predict": {{ max_tokens }}, "num_ctx": 40960}, "format": {{ schema | to_json }}}'
1370
1370
 
1371
1371
  const OLLAMA_EXTRACTOR =
1372
1372
  '{"output_json": "{{ msg.message.content | json_escape }}", ' +
@@ -509,8 +509,8 @@ here, and the declaration goes live the moment someone calls
509
509
  call rather than being remembered afterwards.
510
510
 
511
511
  Do **not** declare a `legal_entity_id` column. The platform stamps it from
512
- the MDM resolve in §012, and a column of that name shadows the stamp — which
513
- would leave every connected-app link minted against nothing.
512
+ the MDM resolve in §012, and the name is reserved — declaring it does not
513
+ shadow the stamp, it 422s the create, so you lose the table until you drop it.
514
514
 
515
515
  ```typescript
516
516
  const customers = await ctx.ensure(
@@ -1457,7 +1457,7 @@ const ENRICHMENT_OUTPUT_SCHEMA = {
1457
1457
  const OLLAMA_BASE_BODY =
1458
1458
  '{"model": "{{ model }}", "messages": [{"role": "user", "content": "{{ rendered_prompt | json_escape }}", ' +
1459
1459
  '"images": [{% for img in images %}{% unless forloop.first %}, {% endunless %}"{{ img.data }}"{% endfor %}]}], ' +
1460
- '"stream": false, "think": false, "options": {"temperature": 0, "num_ctx": 40960}, "format": {{ schema | to_json }}}'
1460
+ '"stream": false, "think": false, "options": {"temperature": {{ temperature }}, "num_predict": {{ max_tokens }}, "num_ctx": 40960}, "format": {{ schema | to_json }}}'
1461
1461
 
1462
1462
  const OLLAMA_EXTRACTOR =
1463
1463
  '{"output_json": "{{ msg.message.content | json_escape }}", ' +
@@ -521,7 +521,9 @@ const { data: search } = await api.datasets.createUserSearch(
521
521
  },
522
522
  )
523
523
  // search.id — UUID of the materialised result set
524
- // search.status — 'completed' on success; 'failed' surfaces error_message
524
+ // search.status — 'new' | 'in_progress' | 'completed' | 'error'.
525
+ // The failure member is 'error', NOT 'failed' — and it is
526
+ // 'error' that carries error_message. There is no 'failed'.
525
527
  // search.results_count — ALWAYS null on the POST response (see Gotcha 5)
526
528
 
527
529
  // (2) GET paginates rows from the materialised result set.
@@ -529,6 +531,13 @@ const { data: search } = await api.datasets.createUserSearch(
529
531
  // 'raw' — real values verbatim
530
532
  // 'tokenized' — masked columns return a stable tok_<hash>
531
533
  // 'redacted' — masked columns return an unjoinable placeholder
534
+ // `search.id` is `string | undefined` on the response type, and
535
+ // `DatasetSearchOptions.userSearchId` is declared `?: string` — optional, but
536
+ // NOT `| undefined`. So an app with `exactOptionalPropertyTypes` will not
537
+ // compile the shorthand, and an app without it gets a runtime 404 that reads
538
+ // like a wrong path. Narrow it first.
539
+ if (!search.id) throw new Error(`createUserSearch returned no id (status ${search.status})`)
540
+
532
541
  const { data: page } = await api.datasets.search(
533
542
  tenantSlug,
534
543
  datalakeSlug,
@@ -752,6 +752,24 @@ the SQL between the two calls.
752
752
  live — e.g. `WHERE some_boolean = 1` 422s on Postgres (booleans compare to
753
753
  `true`/`false`, never `1`). Surface the SQL to a human (or a checking step)
754
754
  and expect to edit before `executeSql`.
755
+ - **`executeSql` returns rows as POSITIONAL ARRAYS, not objects keyed by
756
+ column.** `data` is `unknown[][]`; the column names are in `meta.columns`, in
757
+ the same order. So `row.legal_entity_id` is silently `undefined` — not an
758
+ error, just absent — and a probe written against it fails with a message
759
+ built from its own bug while the data is perfectly correct. Zip them:
760
+
761
+ ```ts
762
+ const { data: res } = await api.datalakes.executeSql(tenantSlug, datalakeSlug, {
763
+ sql, mode: 'raw',
764
+ })
765
+ const cols = res.meta.columns
766
+ const rows = res.data.map((r) => Object.fromEntries(cols.map((c, i) => [c, r[i]])))
767
+ // now rows[0].legal_entity_id is real
768
+ ```
769
+
770
+ Worth knowing before you write a richer check than the scaffolds ship: their
771
+ seeded example only asserts `data.length > 0`, which behaves identically for
772
+ both shapes, so nothing in the example reveals this.
755
773
  - **`executeSql`** body is `{ sql, mode, page?, page_size? }`. It runs the SQL
756
774
  **read-only** (INSERT/UPDATE/DELETE/DDL are rejected) against the
757
775
  mode-selected lake tier, with Flop-inspired pagination (`page_size` capped server-side). The JSON
@@ -283,9 +283,14 @@ and they are yours to read but never to declare:
283
283
  **`legal_entity_id` is the one that catches people.** It is not a
284
284
  column you declare and fill — a contract's `mdm_input_config`
285
285
  resolves the subject and the platform stamps it. Declaring a column
286
- of that name shadows the stamp, and the symptom is not an error: the
287
- row lands, the batch reports green, and every connected-app link
288
- minted from that row points at nobody.
286
+ of that name does not shadow the stamp silently: the create is
287
+ REJECTED with 422, and the message names the offending column
288
+ (`contain reserved system column names: legal_entity_id`). You lose
289
+ the create, not the linkage — so read the 422 as the platform telling
290
+ you the column is already there, and drop it from your definition.
291
+ There is correspondingly **nothing to guard against in a contract
292
+ hook**: a table that declares the column is never created, so an
293
+ `assert` on its absence can never fire.
289
294
 
290
295
  There is no longer a per-domain reserved list. GH-859 removed the
291
296
  industry datalakes and their MDM foreign keys, so names like
@@ -356,11 +361,25 @@ Standard JSON:API envelopes per `errors.md`. Common rejections:
356
361
  | `source.pointer` | Cause |
357
362
  |----------------------------------|----------------------------------------------------|
358
363
  | `/title` | empty; generates a name colliding with existing; or starts with `alvera_system` prefix |
359
- | `/columns` | empty array; duplicate `column.name`; or zero columns marked `is_unique: true` |
360
- | `/columns/0/name` | reserved column name (infrastructure column or the industry's MDM FK; see §2) |
364
+ | `/columns` | empty array; duplicate `column.name`; zero columns marked `is_unique: true`; or a RESERVED column name (see §2) |
365
+ | `/columns/0/name` | too short/long, or not matching `[a-z][a-z0-9_]*` |
361
366
  | `/columns/0/type` | value not in supported type enum (see §2 column types) |
362
367
  | `/columns/0/privacy_requirement` | value not in enum, OR `tokenize` on a `jsonb` column |
363
368
 
369
+ **Reserved names point at `/columns`, not at the offending index** —
370
+ measured, not inferred. The check runs on the parent changeset
371
+ (`add_error(changeset, :columns, …)`), so it names *every* offending
372
+ column at once rather than the first it meets:
373
+
374
+ ```
375
+ alvera: plan halted at generic_table "lead-submissions": server rejected request:
376
+ /columns: contain reserved system column names: legal_entity_id
377
+ ```
378
+
379
+ Note where that halted: at **plan**, not apply — the server answering
380
+ during plan's refresh, before any mutation. The per-column rows above
381
+ are indexed because those validations run on the column embed itself.
382
+
364
383
  All of these come back as a 422 `AlveraApiError` thrown from the
365
384
  SDK on submit — structural cases (Layer 1) and semantic conflicts
366
385
  like name collision / deployed-name reuse (Layer 2). The SDK does
@@ -134,8 +134,11 @@ they converge on one legal entity and the platform stamps
134
134
  `legal_entity_id` onto the generic-table row.
135
135
 
136
136
  **Never declare `legal_entity_id` as a column on that table.**
137
- Declaring it shadows the stamp, and it fails silently — the
138
- column simply stays empty.
137
+ The name is reserved, so declaring it does not shadow the stamp —
138
+ the create is REJECTED with 422 (`contain reserved system column
139
+ names: legal_entity_id`). You lose the table, not the linkage.
140
+ Drop it from your definition; the platform adds the column itself
141
+ and you read the stamp back off the row.
139
142
 
140
143
  ### `filter_template` has INVERTED semantics
141
144
 
package/.agent/tools.md CHANGED
@@ -637,13 +637,34 @@ await api.tools.testInvocation(
637
637
  inlines the value verbatim; `type: 'system'` references a
638
638
  platform-shipped template (see `templates.md`).
639
639
 
640
- **Test-invocation accepts exactly FIVE `tool_call_type` variants** —
641
- the interactive ones. Its request casts into a `ManualToolInvocation`
642
- embed (`on_type_not_found: :raise`) whose polymorphic set is
643
- `sms_request`, `mms_request`, `email_request`, `restapi_request`,
644
- `aws_lambda_request`. A tool whose body is SFTP / S3 / SQL /
645
- SharePoint has **no** test-invocation variant and cannot be exercised
646
- through this endpoint (same shape as the `status_poller` case below).
640
+ **Test-invocation accepts SIX `tool_call_type` variants** — the
641
+ interactive ones. Its request casts into a `ManualToolInvocation` embed
642
+ (`on_type_not_found: :raise`) whose polymorphic set is `sms_request`,
643
+ `mms_request`, `email_request`, `restapi_request`, `aws_lambda_request`
644
+ and `sql_query`.
645
+
646
+ THREE LISTS LIVE HERE and conflating them is the mistake this paragraph
647
+ used to make. `tool_body_type` says what a tool IS (12 variants — `sns`,
648
+ `twilio`, `s3`, `sql_database`, `sftp`, `sharepoint`, `manual_upload`, …).
649
+ `tool_call_type` says how a CALL is shaped (9). Test-invocation accepts a
650
+ subset of the call types (6). They do not map one-to-one: `sns` and
651
+ `twilio` are both bodies that send SMS, so both call through
652
+ `sms_request`; the `sql_database` body calls through `sql_query`.
653
+
654
+ So a tool whose body is **S3, SFTP or SharePoint** has no test-invocation
655
+ variant and cannot be exercised through this endpoint (same shape as the
656
+ `status_poller` case below). SFTP and SharePoint are coming; S3 is not
657
+ currently reachable this way either.
658
+
659
+ **`manual_upload` is the exception worth knowing.** It is excluded from
660
+ test-invocation, but it is NOT unexecutable — it has a real executor
661
+ (`Platform.Tools.ManualUpload`, protocols.ex:105) which routes to the
662
+ `ingest_json` path rather than the automated fetch pipeline. There is
663
+ nothing to dial interactively because the input is a file someone
664
+ supplies; the tool still runs. A born-red contract that demands a
665
+ test-invocation smoke for a manual-upload tool is therefore asking for
666
+ something that cannot exist, and the cure is to assert the tool's
667
+ configuration and its provenance binding instead.
647
668
  Those config shapes still exist — but on the broader **workflow-action
648
669
  `ToolCallConfig`** surface (see `tool-call-configs.md`), not here. The
649
670
  per-branch required-list for the five test-invocable variants:
@@ -671,10 +692,18 @@ per-branch required-list for the five test-invocable variants:
671
692
 
672
693
  tool_call_type: 'restapi_request'
673
694
  required: path, method, pagination_context_template
674
- enums: method ∈ HTTP methods (GET, POST, PUT, PATCH, DELETE,
675
- HEAD, OPTIONS)
676
- optional: body, params (each TemplateConfig — 'identity' or
677
- 'custom' both accepted)
695
+ enums: method ∈ 'head' | 'get' | 'put' | 'post' | 'delete' |
696
+ 'patch' — LOWERCASE. 'POST' is rejected as
697
+ `/tool_call/method — Invalid value for enum`.
698
+ optional: body, params
699
+ shapes: path, body, params and pagination_context_template are
700
+ EACH a TemplateConfig ({ type, body }) — 'identity' or
701
+ 'custom' both accepted. `path` is NOT a plain string;
702
+ passing one is `/tool_call/path — Invalid value: Invalid
703
+ object. Got: string`. It is an envelope so a path can be
704
+ interpolated per row.
705
+ pagination_context_template is required even with nothing
706
+ to paginate — `{ type: 'null' }` is how you say so.
678
707
 
679
708
  tool_call_type: 'aws_lambda_request'
680
709
  required: payload (TemplateConfig — 'identity' acceptable)
@@ -789,16 +789,14 @@ Each log carries:
789
789
  - `error_message` — coarse failure summary (e.g.
790
790
  `"AI enrichment failed: <agent_name>"`); rich detail lives
791
791
  in `error.json` (§ Per-step artifacts below)
792
- - `action_execution_logs` — nested rows, one per action that fired
793
- (`message_body` virtual field is rendered when read via
794
- `dataAccessMode: 'raw'`)
792
+ - `action_execution_logs` — nested rows, one per action that fired,
793
+ carrying the `message_body` virtual field
795
794
 
796
795
  Methods:
797
796
 
798
797
  ```
799
798
  .list(tenantSlug, datalakeSlug, workflowSlug, query?) Paged
800
- .get(tenantSlug, datalakeSlug, workflowSlug, logId,
801
- { dataAccessMode? }) One row
799
+ .get(tenantSlug, datalakeSlug, workflowSlug, logId) One row
802
800
  .download(tenantSlug, datalakeSlug, workflowSlug, logId) The run's artifact
803
801
  ```
804
802
 
@@ -818,13 +816,14 @@ await api.workflows.workflowLogs.list(tenantSlug, datalakeSlug, slug, {
818
816
  `filters` uses the Flop empty-bracket serialization on the wire —
819
817
  the SDK's serializer handles it; never hand-roll the query string.
820
818
 
821
- The `dataAccessMode` query parameter on `.get` controls how
822
- `message_body` is rendered:
823
- - `'raw'` — the real rendered body, with the resolved short path
824
- `/t/<token>`
825
- - `'tokenized'` — masked display body, with each masked column as a
826
- stable `tok_<hash>`
827
- - `'redacted'` — masked display body with unjoinable placeholders
819
+ `.get` takes NO `dataAccessMode`. It used to; the platform removed the
820
+ `data_access_mode` query from this endpoint, and the generated type is now
821
+ `query?: never`, so passing one no longer compiles.
822
+
823
+ An execution log is workflow bookkeeping rather than lake rows, so there is
824
+ no tier to select. Choosing a tier belongs to the reads that return data —
825
+ `datasets.search` and `datalakes.executeSql` both take a mode, and that is
826
+ where `'raw' | 'tokenized' | 'redacted'` still applies.
828
827
 
829
828
  ### Per-step artifacts (event, filter, enrichment, error)
830
829
 
package/dist/index.d.mts CHANGED
@@ -290,7 +290,7 @@ type AgenticWorkflowResponse = {
290
290
  readonly context_datasets?: Array<ContextDatasetResponse>;
291
291
  datalake?: DatalakeResponse;
292
292
  /**
293
- * Dataset type the workflow listens on (e.g. patient, appointment, generic_table)
293
+ * Dataset type the workflow listens on (e.g. legal_entity, document, generic_table)
294
294
  */
295
295
  dataset_type: string;
296
296
  decision_config?: ComplexTemplateConfigResponse | null;
@@ -526,7 +526,7 @@ type DataActivationClientLogResponse = {
526
526
  */
527
527
  readonly client_id: string;
528
528
  /**
529
- * Target dataset table for this slice (e.g. patients, observations)
529
+ * Target dataset table for this slice (e.g. legal_entities, documents)
530
530
  */
531
531
  dataset_table: string;
532
532
  /**
@@ -866,7 +866,7 @@ type ExecuteActionRequest = {
866
866
  */
867
867
  dataset_id: string;
868
868
  /**
869
- * Decision key identifying which action to execute (e.g. 'cahps_survey')
869
+ * Decision key identifying which action to execute (e.g. 'send_welcome_email')
870
870
  */
871
871
  decision_key: string;
872
872
  /**
@@ -1025,7 +1025,7 @@ type ResolvePageResponse = {
1025
1025
  subject?: string | null;
1026
1026
  } | null;
1027
1027
  /**
1028
- * Route path within the connected app (e.g. /forms/cahps)
1028
+ * Route path within the connected app (e.g. /forms/onboarding)
1029
1029
  */
1030
1030
  route_path: string;
1031
1031
  /**
@@ -1877,11 +1877,11 @@ type WorkflowLogListResponse = {
1877
1877
  /**
1878
1878
  * SystemDatasetListResponse
1879
1879
  *
1880
- * Industry-registered dataset name strings for the datalake's data domain.
1880
+ * The dataset name strings the platform registers. Identical for every datalake.
1881
1881
  */
1882
1882
  type SystemDatasetListResponse = {
1883
1883
  /**
1884
- * Sorted unique dataset name strings (e.g. `patient`, `appointment`, `legal_entity`).
1884
+ * Sorted unique dataset name strings (e.g. `legal_entity`, `document`, `action_log`).
1885
1885
  */
1886
1886
  datasets: Array<string>;
1887
1887
  };
@@ -1980,9 +1980,9 @@ type SharePointExcelCallRequest = {
1980
1980
  */
1981
1981
  type DacRawLogFileResponse = {
1982
1982
  /**
1983
- * Bucket the archive lives in — raw or tokenized
1983
+ * Bucket the archive lives in. One archive is written per log, and it is raw.
1984
1984
  */
1985
- mode: 'raw' | 'tokenized' | 'redacted';
1985
+ mode: 'raw';
1986
1986
  /**
1987
1987
  * Cloud-storage object key of the merged NDJSON archive
1988
1988
  */
@@ -2238,7 +2238,7 @@ type WorkflowRunListResponse = {
2238
2238
  */
2239
2239
  type MinimalAiAgentResponse = {
2240
2240
  /**
2241
- * Data access level
2241
+ * Which lake the agent reads. `tokenized` means the agent's context is read from the tokenized copy, so it never sees a real identifier. It is enforced, not advisory: an agent set to `tokenized` in an environment with no tokenized lake fails its enrichment step rather than falling back to raw.
2242
2242
  */
2243
2243
  data_access: 'raw' | 'tokenized';
2244
2244
  /**
@@ -3284,11 +3284,16 @@ type DatalakeMigrateResponse = {
3284
3284
  */
3285
3285
  enqueued_at: string;
3286
3286
  /**
3287
- * Oban job ID for tracking
3287
+ * Oban job ID for tracking. This datalake's own job — the first of the batch. The derived lakes are migrated by their own jobs, which are not reported here.
3288
3288
  */
3289
3289
  job_id: number;
3290
3290
  /**
3291
- * Job status (always 'enqueued' at creation)
3291
+ * Always the literal `enqueued` — a constant in the response body, not a
3292
+ * reading of the job's state. A repeat call while a job for this datalake
3293
+ * is still incomplete is deduplicated onto the existing job, so `job_id`
3294
+ * and `enqueued_at` can describe an earlier request while this field
3295
+ * still reads `enqueued`. Poll `GET /datalakes/:id` for real progress.
3296
+ *
3292
3297
  */
3293
3298
  status: 'enqueued';
3294
3299
  };
@@ -4292,9 +4297,10 @@ type ToolSftpResponse = SftpResponse & {
4292
4297
  */
4293
4298
  type ResyncTableResponse = {
4294
4299
  /**
4295
- * Every table this actually emptied — the one asked for, plus anything that
4296
- * points at it. All of them are copied again by the same run. Returned rather
4297
- * than assumed, because a caller that emptied nine tables should be told nine.
4300
+ * Every table the repair emptied — the one asked for, plus anything that
4301
+ * points at it, read from the catalog for this call. All of them are copied
4302
+ * again by the same run. Returned in full because a caller that emptied nine
4303
+ * tables should be told nine.
4298
4304
  *
4299
4305
  */
4300
4306
  emptied: Array<string>;
@@ -4303,7 +4309,13 @@ type ResyncTableResponse = {
4303
4309
  */
4304
4310
  mode: 'tokenized' | 'redacted';
4305
4311
  /**
4306
- * Always `copying` — the repair starts a first pass that finishes later
4312
+ * Always the literal `copying` — a constant written once the repair's last
4313
+ * statement succeeded, not a reading of the copy. Nothing here queries the
4314
+ * subscription. `copying` is *also* one of the real table states
4315
+ * `GET .../tables` reports, and the two are unrelated: a table that has just
4316
+ * been put back on the subscription usually reads `waiting_to_start` for a
4317
+ * moment first. Poll `GET .../tables` for the state the copy is actually in.
4318
+ *
4307
4319
  */
4308
4320
  status: 'copying';
4309
4321
  /**
@@ -4373,7 +4385,7 @@ type AiAgentResponse = {
4373
4385
  */
4374
4386
  readonly checksum?: string;
4375
4387
  /**
4376
- * Data access level
4388
+ * Which lake the agent reads. `tokenized` means the agent's context is read from the tokenized copy, so it never sees a real identifier. It is enforced, not advisory: an agent set to `tokenized` in an environment with no tokenized lake fails its enrichment step rather than falling back to raw.
4377
4389
  */
4378
4390
  data_access: 'raw' | 'tokenized';
4379
4391
  datalake?: DatalakeResponse;
@@ -4760,7 +4772,7 @@ type AgenticWorkflowRequestWritable = {
4760
4772
  */
4761
4773
  context_datasets?: Array<ContextDatasetRequestWritable>;
4762
4774
  /**
4763
- * Dataset type the workflow listens on (e.g. patient, appointment, generic_table)
4775
+ * Dataset type the workflow listens on (e.g. legal_entity, document, generic_table)
4764
4776
  */
4765
4777
  dataset_type: string;
4766
4778
  decision_config?: ComplexTemplateConfigRequest;
@@ -5109,7 +5121,7 @@ type WorkflowAiAgentRequestWritable = {
5109
5121
  */
5110
5122
  type AiAgentRequestWritable = {
5111
5123
  /**
5112
- * Data access level
5124
+ * Which lake the agent reads. `tokenized` means the agent's context is read from the tokenized copy, so it never sees a real identifier. It is enforced, not advisory: an agent set to `tokenized` in an environment with no tokenized lake fails its enrichment step rather than falling back to raw.
5113
5125
  */
5114
5126
  data_access: 'raw' | 'tokenized';
5115
5127
  /**
@@ -7014,6 +7026,51 @@ type PlatformApiAgenticWorkflowOperationsControllerBatchLogsIndexData = {
7014
7026
  };
7015
7027
  url: '/api/v1/tenants/{tenant_slug}/datalakes/{datalake_slug}/agentic-workflows/{workflow_slug}/batch-logs';
7016
7028
  };
7029
+ type PlatformApiDatalakeControllerMetadataData = {
7030
+ body?: never;
7031
+ path: {
7032
+ /**
7033
+ * Tenant slug
7034
+ */
7035
+ tenant_slug: string;
7036
+ };
7037
+ query?: {
7038
+ /**
7039
+ * Page number (1-indexed). Defaults to 1 when omitted.
7040
+ */
7041
+ page?: number;
7042
+ /**
7043
+ * Items per page (1-100). Defaults to the resource's Flop default when omitted.
7044
+ */
7045
+ page_size?: number;
7046
+ /**
7047
+ * Fields to sort by, in order of precedence. Must appear in the resource schema's Flop `sortable:` list — unknown fields return 422.
7048
+ */
7049
+ order_by?: Array<string>;
7050
+ /**
7051
+ * Sort direction(s), pair-wise with `order_by`. `asc` or `desc`. Defaults to `asc` per unpaired `order_by` entry.
7052
+ */
7053
+ order_directions?: Array<'asc' | 'desc'>;
7054
+ /**
7055
+ * Flop-native filter array. URL shape: `?filters[][field]=status&filters[][op]=%3D%3D&filters[][value]=pending` (empty brackets — consecutive `[]` entries group into one filter object per element; indexed brackets parse as a map and fail the array cast with 422). `op` is the symbol, percent-encoded — `%3D%3D` for `==`, `%3E%3D` for `>=` — not a word like `equal`; anything outside the enum above is a 422 before the request reaches Flop. Omit `op` entirely for equality. Unknown fields return 422 via Flop validation at the context layer.
7056
+ */
7057
+ filters?: Array<{
7058
+ /**
7059
+ * Filterable field name (must be in the resource's `filterable:`)
7060
+ */
7061
+ field: string;
7062
+ /**
7063
+ * Comparison operator. Defaults to `==` when omitted.
7064
+ */
7065
+ op?: '==' | '!=' | '<' | '<=' | '>' | '>=' | 'empty' | 'not_empty' | 'like' | 'ilike' | 'like_and' | 'like_or' | 'ilike_and' | 'ilike_or' | 'in' | 'not_in' | 'contains' | 'not_contains';
7066
+ /**
7067
+ * Filter value — shape depends on `field` and `op`.
7068
+ */
7069
+ value: unknown;
7070
+ }>;
7071
+ };
7072
+ url: '/api/v1/tenants/{tenant_slug}/datalakes/metadata';
7073
+ };
7017
7074
  type PlatformApiDataActivationClientControllerIndexData = {
7018
7075
  body?: never;
7019
7076
  path: {
@@ -7777,10 +7834,7 @@ declare function _buildApi(myClient: Client): {
7777
7834
  request: Request;
7778
7835
  response: Response;
7779
7836
  }>;
7780
- metadata: (tenantSlug: string, query?: {
7781
- page?: number;
7782
- page_size?: number;
7783
- }) => Promise<{
7837
+ metadata: (tenantSlug: string, query?: PlatformApiDatalakeControllerMetadataData["query"]) => Promise<{
7784
7838
  data: string;
7785
7839
  request: Request;
7786
7840
  response: Response;
@@ -8424,9 +8478,7 @@ declare function _buildApi(myClient: Client): {
8424
8478
  request: Request;
8425
8479
  response: Response;
8426
8480
  }>;
8427
- get: (tenantSlug: string, datalakeSlug: string, workflowSlug: string, id: string, opts?: {
8428
- dataAccessMode?: "raw" | "tokenized" | "redacted";
8429
- }) => Promise<{
8481
+ get: (tenantSlug: string, datalakeSlug: string, workflowSlug: string, id: string) => Promise<{
8430
8482
  data: WorkflowLogResponse;
8431
8483
  request: Request;
8432
8484
  response: Response;