@soat/cli 0.20.5 → 0.21.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.
Files changed (2) hide show
  1. package/dist/index.mjs +637 -341
  2. package/package.json +2 -2
package/dist/index.mjs CHANGED
@@ -13,7 +13,7 @@ import { load } from "js-yaml";
13
13
  import * as os from "node:os";
14
14
 
15
15
  //#region package.json
16
- var version = "0.20.5";
16
+ var version = "0.21.0";
17
17
 
18
18
  //#endregion
19
19
  //#region src/cli-wrappers/wrappers/formations.ts
@@ -1184,17 +1184,23 @@ var routes = {
1184
1184
  "create-agent-generation": {
1185
1185
  serviceClass: "Agents",
1186
1186
  operationId: "createAgentGeneration",
1187
- description: "Sends messages to the agent, resolves its tools, and runs the AI model loop. Supports streaming via `stream: true`. Client tools pause the generation and return `requires_action`.",
1187
+ description: "Sends messages to the agent, resolves its tools, and runs the AI model loop. Background by default: returns `202 Accepted` with a `generation_id` to poll via `GET /api/v1/generations/{generation_id}`. Pass `?wait=true` to block and receive the result inline, where client tools pause the generation and return `requires_action`. Streaming (`stream: true`) implies waiting.",
1188
1188
  moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/agents",
1189
1189
  httpMethod: "post",
1190
1190
  pathParams: ["agent_id"],
1191
- queryParams: [],
1191
+ queryParams: ["wait"],
1192
1192
  flags: [{
1193
1193
  "name": "agent_id",
1194
1194
  "description": "",
1195
1195
  "required": true,
1196
1196
  "type": "string",
1197
1197
  "in": "path"
1198
+ }, {
1199
+ "name": "wait",
1200
+ "description": "When omitted or `false` (default), the generation runs in the background and `202 Accepted` is returned immediately with a `generation_id` to poll. Pass `true` to block until the generation settles and receive the result. Mutually exclusive with `stream: true`. A `soat` tool call always waits.",
1201
+ "required": false,
1202
+ "type": "boolean",
1203
+ "in": "query"
1198
1204
  }, {
1199
1205
  "name": "messages",
1200
1206
  "description": "",
@@ -1407,12 +1413,18 @@ var routes = {
1407
1413
  "required": true,
1408
1414
  "type": "integer",
1409
1415
  "in": "body"
1416
+ }, {
1417
+ "name": "promotion_gate",
1418
+ "description": "Eval to gate promotion on. It must belong to this project and evaluate this agent; anything else is a `400`. Omit it, or send null, for a rollout that can be promoted at will.",
1419
+ "required": false,
1420
+ "type": "string",
1421
+ "in": "body"
1410
1422
  }]
1411
1423
  },
1412
1424
  "promote-agent-release": {
1413
1425
  serviceClass: "AgentVersions",
1414
1426
  operationId: "promoteAgentRelease",
1415
- description: "Makes the canary version's config the agent's live config and clears the release. The canary is pinned by version, so an edit that landed mid-rollout is not promoted in its place — it stays an unreleased draft in the version history.",
1427
+ description: "Makes the canary version's config the agent's live config and clears the release. The canary is pinned by version, so an edit that landed mid-rollout is not promoted in its place — it stays an unreleased draft in the version history. When the release carries a `promotion_gate`, the eval it names must have a run that finished `completed` with `passed: true` **and** was pinned to the canary version (`agent_version`); otherwise the call is a `409` and the rollout is left running untouched. The run that cleared the gate is recorded as `eval_run_id` on the version that goes live.",
1416
1428
  moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/agents",
1417
1429
  httpMethod: "post",
1418
1430
  pathParams: ["agent_id"],
@@ -1592,7 +1604,7 @@ var routes = {
1592
1604
  "delete-ai-provider": {
1593
1605
  serviceClass: "AIProviders",
1594
1606
  operationId: "deleteAiProvider",
1595
- description: "Deletes an AI provider configuration. Live references — chats, agents, discussions, and model routes whose targets name this provider — always block deletion with `409 AI_PROVIDER_HAS_DEPENDENTS`; `force` does not override them, so delete or repoint those resources first. Soft dependents — price overrides, usage/generation records, and discussion participants — also block with `409` unless `force=true`, which deletes the provider's price overrides and unlinks (nulls) its usage and participant history, preserving those rows. The `409` body's `error.meta` reports the counts, a sample of offending IDs, and a `forcible` flag that is `true` when a `force=true` retry would succeed.",
1607
+ description: "Deletes an AI provider configuration. Live references — chats, agents, and model routes whose targets name this provider — always block deletion with `409 AI_PROVIDER_HAS_DEPENDENTS`; `force` does not override them, so delete or repoint those resources first. Soft dependents — price overrides and usage/generation records — also block with `409` unless `force=true`, which deletes the provider's price overrides and unlinks (nulls) its usage history, preserving those rows. The `409` body's `error.meta` reports the counts, a sample of offending IDs, and a `forcible` flag that is `true` when a `force=true` retry would succeed.",
1596
1608
  moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/ai-providers",
1597
1609
  httpMethod: "delete",
1598
1610
  pathParams: ["ai_provider_id"],
@@ -1605,7 +1617,7 @@ var routes = {
1605
1617
  "in": "path"
1606
1618
  }, {
1607
1619
  "name": "force",
1608
- "description": "When `true`, delete the provider's price overrides and unlink its usage/participant history so a provider with only soft dependents can be removed. Has no effect on live references (chats, agents, discussions, model routes), which always block deletion.\n",
1620
+ "description": "When `true`, delete the provider's price overrides and unlink its usage history so a provider with only soft dependents can be removed. Has no effect on live references (chats, agents, model routes), which always block deletion.\n",
1609
1621
  "required": false,
1610
1622
  "type": "boolean",
1611
1623
  "in": "query"
@@ -2432,17 +2444,23 @@ var routes = {
2432
2444
  "generate-conversation-message": {
2433
2445
  serviceClass: "Conversations",
2434
2446
  operationId: "generateConversationMessage",
2435
- description: "Generates the next message using the specified actor's linked agent or chat. On `completed`, the reply is persisted as a new ConversationMessage authored by that actor. On `requires_action`, nothing is persisted; the caller must submit tool outputs via the Agents module and re-invoke generate.",
2447
+ description: "Generates the next message using the specified actor's linked agent or chat. Background by default: returns `202 Accepted` immediately and the reply lands as a new ConversationMessage when it completes — poll `GET /api/v1/conversations/{conversation_id}/messages` for it. Pass `?wait=true` to block and receive the result inline. On `completed`, the reply is persisted as a new ConversationMessage authored by that actor. On `requires_action`, nothing is persisted; the caller must submit tool outputs via the Agents module and re-invoke generate — so a flow using client tools should pass `?wait=true`.",
2436
2448
  moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/conversations",
2437
2449
  httpMethod: "post",
2438
2450
  pathParams: ["conversation_id"],
2439
- queryParams: [],
2451
+ queryParams: ["wait"],
2440
2452
  flags: [{
2441
2453
  "name": "conversation_id",
2442
2454
  "description": "",
2443
2455
  "required": true,
2444
2456
  "type": "string",
2445
2457
  "in": "path"
2458
+ }, {
2459
+ "name": "wait",
2460
+ "description": "When omitted or `false` (default), the generation runs in the background and `202 Accepted` is returned immediately. Pass `true` to block until the generation settles and receive the result. A `soat` tool call always waits.",
2461
+ "required": false,
2462
+ "type": "boolean",
2463
+ "in": "query"
2446
2464
  }, {
2447
2465
  "name": "agent_id",
2448
2466
  "description": "ID of the agent that will produce the next message.",
@@ -2539,11 +2557,11 @@ var routes = {
2539
2557
  "in": "path"
2540
2558
  }]
2541
2559
  },
2542
- "list-discussions": {
2543
- serviceClass: "Discussions",
2544
- operationId: "listDiscussions",
2545
- description: "Returns all discussions the caller has access to. If project_id is provided, returns only discussions in that project.",
2546
- moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/discussions",
2560
+ "list-documents": {
2561
+ serviceClass: "Documents",
2562
+ operationId: "listDocuments",
2563
+ description: "Returns all documents the caller has access to. If projectId is provided, returns only documents in that project. project keys are scoped to a single project automatically. JWT users without projectId receive documents across all their accessible projects.",
2564
+ moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/documents",
2547
2565
  httpMethod: "get",
2548
2566
  pathParams: [],
2549
2567
  queryParams: ["project_id", "limit", "offset"],
@@ -2567,243 +2585,383 @@ var routes = {
2567
2585
  "in": "query"
2568
2586
  }]
2569
2587
  },
2570
- "create-discussion": {
2571
- serviceClass: "Discussions",
2572
- operationId: "createDiscussion",
2573
- description: "Creates a new discussion config. project keys infer the project from the key's scope; JWT callers must supply project_id.",
2574
- moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/discussions",
2588
+ "create-document": {
2589
+ serviceClass: "Documents",
2590
+ operationId: "createDocument",
2591
+ description: "Creates a new text document and generates an embedding vector for semantic search. project keys automatically infer the project from the key's scope; JWT callers must supply projectId.",
2592
+ moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/documents",
2575
2593
  httpMethod: "post",
2576
2594
  pathParams: [],
2577
2595
  queryParams: [],
2578
2596
  flags: [{
2579
2597
  "name": "project_id",
2580
- "description": "Project ID. Required for JWT auth; omit when using a project key.",
2598
+ "description": "Project ID. Required for JWT auth; omit when using an project key.",
2581
2599
  "required": false,
2582
2600
  "type": "string",
2583
2601
  "in": "body"
2584
2602
  }, {
2585
- "name": "name",
2603
+ "name": "content",
2586
2604
  "description": "",
2587
2605
  "required": true,
2588
2606
  "type": "string",
2589
2607
  "in": "body"
2590
2608
  }, {
2591
- "name": "description",
2592
- "description": "",
2609
+ "name": "path",
2610
+ "description": "Logical path within the project (e.g. /reports/q1.txt). Defaults to /filename if omitted.",
2593
2611
  "required": false,
2594
2612
  "type": "string",
2595
2613
  "in": "body"
2596
2614
  }, {
2597
- "name": "ai_provider_id",
2598
- "description": "Default AI provider participants and synthesis fall back to. Optional: omit it to inherit the project's `default_model_route_id`, which gives every turn provider failover. Omitting it returns `400` when the project has no default.",
2615
+ "name": "filename",
2616
+ "description": "",
2599
2617
  "required": false,
2600
2618
  "type": "string",
2601
2619
  "in": "body"
2602
2620
  }, {
2603
- "name": "model",
2604
- "description": "Default model (falls back to the provider's default_model).",
2621
+ "name": "title",
2622
+ "description": "Document title",
2605
2623
  "required": false,
2606
2624
  "type": "string",
2607
2625
  "in": "body"
2608
2626
  }, {
2609
- "name": "max_rounds",
2610
- "description": "",
2627
+ "name": "metadata",
2628
+ "description": "Arbitrary metadata object. Unlike other body fields, keys are stored and returned verbatim in the casing supplied — they are not converted between snake_case and camelCase.",
2611
2629
  "required": false,
2612
- "type": "integer",
2630
+ "type": "object",
2613
2631
  "in": "body"
2614
2632
  }, {
2615
- "name": "synthesis",
2616
- "description": "Override for the final synthesis pass that weighs the deliberation into a single outcome.",
2633
+ "name": "tags",
2634
+ "description": "Key-value tags",
2617
2635
  "required": false,
2618
2636
  "type": "object",
2619
2637
  "in": "body"
2620
2638
  }, {
2621
- "name": "tags",
2622
- "description": "",
2639
+ "name": "chunk_strategy",
2640
+ "description": "How to split the content into embeddable chunks. `whole` (default) stores the content as a single chunk; `size` splits into fixed-size character windows with overlap. `page` is equivalent to `whole` for plain text.",
2623
2641
  "required": false,
2624
- "type": "object",
2642
+ "type": "string",
2625
2643
  "in": "body"
2626
2644
  }, {
2627
- "name": "participants",
2628
- "description": "",
2645
+ "name": "chunk_size",
2646
+ "description": "Window size in characters when `chunk_strategy=size`. Defaults to 1000.",
2629
2647
  "required": false,
2630
- "type": "array",
2648
+ "type": "integer",
2649
+ "in": "body"
2650
+ }, {
2651
+ "name": "chunk_overlap",
2652
+ "description": "Overlap in characters between consecutive windows when `chunk_strategy=size`. Defaults to 200.",
2653
+ "required": false,
2654
+ "type": "integer",
2631
2655
  "in": "body"
2632
2656
  }]
2633
2657
  },
2634
- "get-discussion-run": {
2635
- serviceClass: "Discussions",
2636
- operationId: "getDiscussionRun",
2637
- description: "Returns a single discussion run, including its outcome, transcript conversation, and outcome document.",
2638
- moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/discussions",
2639
- httpMethod: "get",
2640
- pathParams: ["run_id"],
2641
- queryParams: [],
2658
+ "ingest-document": {
2659
+ serviceClass: "Documents",
2660
+ operationId: "ingestDocument",
2661
+ description: "Parses an already-uploaded file and creates one Document split into one or more embedded chunks. The source format is detected from the file's content type: PDFs are parsed page-by-page; `text/plain` and `text/markdown` files are read as a single source. How the source is chunked is controlled by `chunk_strategy`. A file can only back one Document — a second call with the same `file_id` returns `409 FILE_ALREADY_INGESTED`. To re-process an already-ingested file (e.g. with a different `chunk_strategy`), use `POST /documents/{document_id}/ingest`; to ingest the same source under a different path, upload a new copy of the file first.",
2662
+ moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/documents",
2663
+ httpMethod: "post",
2664
+ pathParams: [],
2665
+ queryParams: ["wait"],
2642
2666
  flags: [{
2643
- "name": "run_id",
2644
- "description": "Discussion run ID",
2667
+ "name": "wait",
2668
+ "description": "When omitted or `false` (default), processing runs in the background and `202 Accepted` is returned immediately with `status=pending`. Pass `true` to block until processing completes and receive `201 Created` with `status=ready`.",
2669
+ "required": false,
2670
+ "type": "boolean",
2671
+ "in": "query"
2672
+ }, {
2673
+ "name": "file_id",
2674
+ "description": "ID of the uploaded file. Must be one of application/pdf, text/plain, text/markdown.",
2645
2675
  "required": true,
2646
2676
  "type": "string",
2647
- "in": "path"
2677
+ "in": "body"
2678
+ }, {
2679
+ "name": "project_id",
2680
+ "description": "Project ID. Required for JWT auth; omit when using a project key.",
2681
+ "required": false,
2682
+ "type": "string",
2683
+ "in": "body"
2684
+ }, {
2685
+ "name": "path_prefix",
2686
+ "description": "Path prefix under which to store the document (e.g. /docs/). The filename is appended automatically.",
2687
+ "required": false,
2688
+ "type": "string",
2689
+ "in": "body"
2690
+ }, {
2691
+ "name": "tags",
2692
+ "description": "Key-value tags to attach to the document.",
2693
+ "required": false,
2694
+ "type": "object",
2695
+ "in": "body"
2696
+ }, {
2697
+ "name": "chunk_strategy",
2698
+ "description": "How to split the source into chunks. `page` (default) creates one chunk per non-empty page (PDF); for non-paged sources it yields a single chunk. `whole` joins everything into one chunk. `size` splits into fixed-size character windows with overlap.",
2699
+ "required": false,
2700
+ "type": "string",
2701
+ "in": "body"
2702
+ }, {
2703
+ "name": "chunk_size",
2704
+ "description": "Window size in characters when `chunk_strategy=size`. Defaults to 1000.",
2705
+ "required": false,
2706
+ "type": "integer",
2707
+ "in": "body"
2708
+ }, {
2709
+ "name": "chunk_overlap",
2710
+ "description": "Overlap in characters between consecutive windows when `chunk_strategy=size`. Defaults to 200.",
2711
+ "required": false,
2712
+ "type": "integer",
2713
+ "in": "body"
2648
2714
  }]
2649
2715
  },
2650
- "get-discussion": {
2651
- serviceClass: "Discussions",
2652
- operationId: "getDiscussion",
2653
- description: "Returns a discussion config with its participants.",
2654
- moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/discussions",
2716
+ "get-document": {
2717
+ serviceClass: "Documents",
2718
+ operationId: "getDocument",
2719
+ description: "Returns a document with its text content",
2720
+ moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/documents",
2655
2721
  httpMethod: "get",
2656
- pathParams: ["discussion_id"],
2722
+ pathParams: ["document_id"],
2657
2723
  queryParams: [],
2658
2724
  flags: [{
2659
- "name": "discussion_id",
2660
- "description": "Discussion ID",
2725
+ "name": "document_id",
2726
+ "description": "Document ID",
2661
2727
  "required": true,
2662
2728
  "type": "string",
2663
2729
  "in": "path"
2664
2730
  }]
2665
2731
  },
2666
- "update-discussion": {
2667
- serviceClass: "Discussions",
2668
- operationId: "updateDiscussion",
2669
- description: "Updates a discussion. Providing participants replaces the full set (not merged).",
2670
- moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/discussions",
2732
+ "update-document": {
2733
+ serviceClass: "Documents",
2734
+ operationId: "updateDocument",
2735
+ description: "Updates document content, title, path, metadata, or tags. Supplying `path` moves the document to a new logical path within the project.",
2736
+ moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/documents",
2671
2737
  httpMethod: "patch",
2672
- pathParams: ["discussion_id"],
2738
+ pathParams: ["document_id"],
2673
2739
  queryParams: [],
2674
2740
  flags: [{
2675
- "name": "discussion_id",
2676
- "description": "Discussion ID",
2741
+ "name": "document_id",
2742
+ "description": "Document ID",
2677
2743
  "required": true,
2678
2744
  "type": "string",
2679
2745
  "in": "path"
2680
2746
  }, {
2681
- "name": "name",
2682
- "description": "",
2683
- "required": false,
2684
- "type": "string",
2685
- "in": "body"
2686
- }, {
2687
- "name": "description",
2688
- "description": "",
2747
+ "name": "content",
2748
+ "description": "New text content",
2689
2749
  "required": false,
2690
2750
  "type": "string",
2691
2751
  "in": "body"
2692
2752
  }, {
2693
- "name": "ai_provider_id",
2694
- "description": "Repins the default AI provider. An explicit `null` unpins the discussion onto the project's `default_model_route_id`, and returns `400` when the project has no default.",
2753
+ "name": "title",
2754
+ "description": "New title",
2695
2755
  "required": false,
2696
2756
  "type": "string",
2697
2757
  "in": "body"
2698
2758
  }, {
2699
- "name": "model",
2700
- "description": "",
2759
+ "name": "path",
2760
+ "description": "Logical path within the project (e.g. /reports/q1.txt). Pass null to clear.",
2701
2761
  "required": false,
2702
2762
  "type": "string",
2703
2763
  "in": "body"
2704
2764
  }, {
2705
- "name": "max_rounds",
2706
- "description": "",
2707
- "required": false,
2708
- "type": "integer",
2709
- "in": "body"
2710
- }, {
2711
- "name": "synthesis",
2712
- "description": "Override for the final synthesis pass that weighs the deliberation into a single outcome.",
2765
+ "name": "metadata",
2766
+ "description": "Arbitrary metadata object. Unlike other body fields, keys are stored and returned verbatim in the casing supplied — they are not converted between snake_case and camelCase.",
2713
2767
  "required": false,
2714
2768
  "type": "object",
2715
2769
  "in": "body"
2716
2770
  }, {
2717
2771
  "name": "tags",
2718
- "description": "",
2772
+ "description": "Key-value tags",
2719
2773
  "required": false,
2720
2774
  "type": "object",
2721
2775
  "in": "body"
2722
- }, {
2723
- "name": "participants",
2724
- "description": "",
2725
- "required": false,
2726
- "type": "array",
2727
- "in": "body"
2728
2776
  }]
2729
2777
  },
2730
- "delete-discussion": {
2731
- serviceClass: "Discussions",
2732
- operationId: "deleteDiscussion",
2733
- description: "Deletes a discussion config and its participants.",
2734
- moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/discussions",
2778
+ "delete-document": {
2779
+ serviceClass: "Documents",
2780
+ operationId: "deleteDocument",
2781
+ description: "Deletes a document and its underlying file",
2782
+ moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/documents",
2735
2783
  httpMethod: "delete",
2736
- pathParams: ["discussion_id"],
2784
+ pathParams: ["document_id"],
2737
2785
  queryParams: [],
2738
2786
  flags: [{
2739
- "name": "discussion_id",
2740
- "description": "Discussion ID",
2787
+ "name": "document_id",
2788
+ "description": "Document ID",
2741
2789
  "required": true,
2742
2790
  "type": "string",
2743
2791
  "in": "path"
2744
2792
  }]
2745
2793
  },
2746
- "list-discussion-runs": {
2747
- serviceClass: "Discussions",
2748
- operationId: "listDiscussionRuns",
2749
- description: "Returns the run history of a discussion, most recent first.",
2750
- moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/discussions",
2794
+ "get-document-status": {
2795
+ serviceClass: "Documents",
2796
+ operationId: "getDocumentStatus",
2797
+ description: "Returns a lightweight ingestion status payload for polling — `status`, `chunk_count`, `total_pages`, and (when failed) `error`. Unlike `GET /documents/{document_id}`, it never returns the assembled chunk content, so it is cheap to poll on large documents. A document whose ingestion has stalled (no progress past the configured timeout) is transitioned to `failed` with `error=INGESTION_TIMEOUT` on read.",
2798
+ moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/documents",
2751
2799
  httpMethod: "get",
2752
- pathParams: ["discussion_id"],
2753
- queryParams: ["limit", "offset"],
2800
+ pathParams: ["document_id"],
2801
+ queryParams: [],
2802
+ flags: [{
2803
+ "name": "document_id",
2804
+ "description": "Document ID",
2805
+ "required": true,
2806
+ "type": "string",
2807
+ "in": "path"
2808
+ }]
2809
+ },
2810
+ "reingest-document": {
2811
+ serviceClass: "Documents",
2812
+ operationId: "reingestDocument",
2813
+ description: "Re-runs ingestion for an existing document against its already-stored source file. Existing chunks are discarded and the document is reset to `status=pending` before re-processing. Use this to recover a document stuck in `processing`/`failed` or to re-chunk with a different strategy without re-uploading the file. Background by default (`202`); pass `?wait=true` to run synchronously (`201`).",
2814
+ moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/documents",
2815
+ httpMethod: "post",
2816
+ pathParams: ["document_id"],
2817
+ queryParams: ["wait"],
2754
2818
  flags: [{
2755
- "name": "discussion_id",
2756
- "description": "Discussion ID",
2819
+ "name": "document_id",
2820
+ "description": "Document ID",
2757
2821
  "required": true,
2758
2822
  "type": "string",
2759
2823
  "in": "path"
2760
2824
  }, {
2761
- "name": "limit",
2762
- "description": "",
2825
+ "name": "wait",
2826
+ "description": "When omitted or `false` (default), processing runs in the background and `202 Accepted` is returned immediately with `status=pending`. Pass `true` to block until processing completes and receive `201 Created` with `status=ready`.",
2763
2827
  "required": false,
2764
- "type": "integer",
2828
+ "type": "boolean",
2765
2829
  "in": "query"
2766
2830
  }, {
2767
- "name": "offset",
2768
- "description": "",
2831
+ "name": "chunk_strategy",
2832
+ "description": "How to split the source into chunks. Defaults to `page`.",
2833
+ "required": false,
2834
+ "type": "string",
2835
+ "in": "body"
2836
+ }, {
2837
+ "name": "chunk_size",
2838
+ "description": "Window size in characters when `chunk_strategy=size`. Defaults to 1000.",
2769
2839
  "required": false,
2770
2840
  "type": "integer",
2771
- "in": "query"
2841
+ "in": "body"
2842
+ }, {
2843
+ "name": "chunk_overlap",
2844
+ "description": "Overlap in characters between consecutive windows when `chunk_strategy=size`. Defaults to 200.",
2845
+ "required": false,
2846
+ "type": "integer",
2847
+ "in": "body"
2772
2848
  }]
2773
2849
  },
2774
- "create-discussion-run": {
2775
- serviceClass: "Discussions",
2776
- operationId: "createDiscussionRun",
2777
- description: "Runs the discussion synchronously over the given topic and returns the completed run, whose outcome inlines the synthesized text. The run's transcript is persisted as a conversation and the outcome as a document.",
2778
- moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/discussions",
2850
+ "complete-ingestion-callback": {
2851
+ serviceClass: "Documents",
2852
+ operationId: "completeIngestionCallback",
2853
+ description: "Token-authed callback for a tool converter that deferred conversion by returning `{ \"status\": \"pending\" }` (see the Ingestion Rules module docs). Not IAM-gated — the external converter is not a SOAT principal, so it authenticates with the single-use token minted for this document and ingestion attempt (delivered as `callback.token` / embedded in `callback.url` in the original converter invocation). Accepted only while the document is still awaiting that exact attempt; rejected with `409` if the attempt already completed, timed out, or was superseded by a re-ingest.",
2854
+ moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/documents",
2779
2855
  httpMethod: "post",
2780
- pathParams: ["discussion_id"],
2781
- queryParams: [],
2856
+ pathParams: ["document_id"],
2857
+ queryParams: ["token"],
2782
2858
  flags: [{
2783
- "name": "discussion_id",
2784
- "description": "Discussion ID",
2859
+ "name": "document_id",
2860
+ "description": "Document ID",
2785
2861
  "required": true,
2786
2862
  "type": "string",
2787
2863
  "in": "path"
2788
2864
  }, {
2789
- "name": "topic",
2790
- "description": "The question or subject the participants deliberate on.",
2865
+ "name": "token",
2866
+ "description": "Single-use signed token from the original `callback.token`",
2791
2867
  "required": true,
2792
2868
  "type": "string",
2869
+ "in": "query"
2870
+ }, {
2871
+ "name": "text",
2872
+ "description": "",
2873
+ "required": false,
2874
+ "type": "string",
2875
+ "in": "body"
2876
+ }, {
2877
+ "name": "pages",
2878
+ "description": "",
2879
+ "required": false,
2880
+ "type": "array",
2793
2881
  "in": "body"
2794
2882
  }]
2795
2883
  },
2796
- "list-documents": {
2884
+ "get-document-tags": {
2797
2885
  serviceClass: "Documents",
2798
- operationId: "listDocuments",
2799
- description: "Returns all documents the caller has access to. If projectId is provided, returns only documents in that project. project keys are scoped to a single project automatically. JWT users without projectId receive documents across all their accessible projects.",
2886
+ operationId: "getDocumentTags",
2887
+ description: "Returns all tags attached to the document",
2800
2888
  moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/documents",
2801
2889
  httpMethod: "get",
2890
+ pathParams: ["document_id"],
2891
+ queryParams: [],
2892
+ flags: [{
2893
+ "name": "document_id",
2894
+ "description": "Document ID",
2895
+ "required": true,
2896
+ "type": "string",
2897
+ "in": "path"
2898
+ }]
2899
+ },
2900
+ "replace-document-tags": {
2901
+ serviceClass: "Documents",
2902
+ operationId: "replaceDocumentTags",
2903
+ description: "Replaces all tags on the document with the provided tags (not merged)",
2904
+ moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/documents",
2905
+ httpMethod: "put",
2906
+ pathParams: ["document_id"],
2907
+ queryParams: [],
2908
+ flags: [{
2909
+ "name": "document_id",
2910
+ "description": "Document ID",
2911
+ "required": true,
2912
+ "type": "string",
2913
+ "in": "path"
2914
+ }]
2915
+ },
2916
+ "merge-document-tags": {
2917
+ serviceClass: "Documents",
2918
+ operationId: "mergeDocumentTags",
2919
+ description: "Merges provided tags with existing tags (existing tags are preserved unless overridden)",
2920
+ moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/documents",
2921
+ httpMethod: "patch",
2922
+ pathParams: ["document_id"],
2923
+ queryParams: [],
2924
+ flags: [{
2925
+ "name": "document_id",
2926
+ "description": "Document ID",
2927
+ "required": true,
2928
+ "type": "string",
2929
+ "in": "path"
2930
+ }]
2931
+ },
2932
+ "create-embeddings": {
2933
+ serviceClass: "Embeddings",
2934
+ operationId: "createEmbeddings",
2935
+ description: "Generates embedding vectors for one or more text inputs using the server's configured embedding model. Provide `input` for a single text or `inputs` for a batch. At least one is required. Returns `embedding` when `input` is used, and `embeddings` when `inputs` is used.",
2936
+ moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/embeddings",
2937
+ httpMethod: "post",
2938
+ pathParams: [],
2939
+ queryParams: [],
2940
+ flags: [{
2941
+ "name": "input",
2942
+ "description": "Single text to embed.",
2943
+ "required": false,
2944
+ "type": "string",
2945
+ "in": "body"
2946
+ }, {
2947
+ "name": "inputs",
2948
+ "description": "Batch of texts to embed.",
2949
+ "required": false,
2950
+ "type": "array",
2951
+ "in": "body"
2952
+ }]
2953
+ },
2954
+ "list-datasets": {
2955
+ serviceClass: "Evaluations",
2956
+ operationId: "listDatasets",
2957
+ description: "Returns the datasets defined in a project",
2958
+ moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/evaluations",
2959
+ httpMethod: "get",
2802
2960
  pathParams: [],
2803
2961
  queryParams: ["project_id", "limit", "offset"],
2804
2962
  flags: [{
2805
2963
  "name": "project_id",
2806
- "description": "Project ID (optional)",
2964
+ "description": "Project ID (required if not using project key auth)",
2807
2965
  "required": false,
2808
2966
  "type": "string",
2809
2967
  "in": "query"
@@ -2821,370 +2979,508 @@ var routes = {
2821
2979
  "in": "query"
2822
2980
  }]
2823
2981
  },
2824
- "create-document": {
2825
- serviceClass: "Documents",
2826
- operationId: "createDocument",
2827
- description: "Creates a new text document and generates an embedding vector for semantic search. project keys automatically infer the project from the key's scope; JWT callers must supply projectId.",
2828
- moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/documents",
2982
+ "create-dataset": {
2983
+ serviceClass: "Evaluations",
2984
+ operationId: "createDataset",
2985
+ description: "Creates a project-scoped dataset a named collection of test cases an eval runs an agent against. Names are unique per project. Datasets are operator-owned **fixtures**. The platform's content purge never deletes or mutates a dataset item, so erasing a generation cannot silently stop a test suite from being runnable.",
2986
+ moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/evaluations",
2829
2987
  httpMethod: "post",
2830
2988
  pathParams: [],
2831
2989
  queryParams: [],
2832
2990
  flags: [{
2833
2991
  "name": "project_id",
2834
- "description": "Project ID. Required for JWT auth; omit when using an project key.",
2992
+ "description": "Project ID (required if not using project key auth)",
2835
2993
  "required": false,
2836
2994
  "type": "string",
2837
2995
  "in": "body"
2838
2996
  }, {
2839
- "name": "content",
2840
- "description": "",
2997
+ "name": "name",
2998
+ "description": "Unique name within the project",
2841
2999
  "required": true,
2842
3000
  "type": "string",
2843
3001
  "in": "body"
2844
3002
  }, {
2845
- "name": "path",
2846
- "description": "Logical path within the project (e.g. /reports/q1.txt). Defaults to /filename if omitted.",
3003
+ "name": "description",
3004
+ "description": "What this suite covers",
2847
3005
  "required": false,
2848
3006
  "type": "string",
2849
3007
  "in": "body"
3008
+ }]
3009
+ },
3010
+ "get-dataset": {
3011
+ serviceClass: "Evaluations",
3012
+ operationId: "getDataset",
3013
+ description: "Returns a specific dataset",
3014
+ moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/evaluations",
3015
+ httpMethod: "get",
3016
+ pathParams: ["dataset_id"],
3017
+ queryParams: [],
3018
+ flags: [{
3019
+ "name": "dataset_id",
3020
+ "description": "Dataset ID",
3021
+ "required": true,
3022
+ "type": "string",
3023
+ "in": "path"
3024
+ }]
3025
+ },
3026
+ "update-dataset": {
3027
+ serviceClass: "Evaluations",
3028
+ operationId: "updateDataset",
3029
+ description: "Updates a dataset's name and/or description",
3030
+ moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/evaluations",
3031
+ httpMethod: "put",
3032
+ pathParams: ["dataset_id"],
3033
+ queryParams: [],
3034
+ flags: [{
3035
+ "name": "dataset_id",
3036
+ "description": "Dataset ID",
3037
+ "required": true,
3038
+ "type": "string",
3039
+ "in": "path"
2850
3040
  }, {
2851
- "name": "filename",
3041
+ "name": "name",
2852
3042
  "description": "",
2853
3043
  "required": false,
2854
3044
  "type": "string",
2855
3045
  "in": "body"
2856
3046
  }, {
2857
- "name": "title",
2858
- "description": "Document title",
3047
+ "name": "description",
3048
+ "description": "",
3049
+ "required": false,
3050
+ "type": "string",
3051
+ "in": "body"
3052
+ }]
3053
+ },
3054
+ "delete-dataset": {
3055
+ serviceClass: "Evaluations",
3056
+ operationId: "deleteDataset",
3057
+ description: "Deletes a dataset, its items, and every eval bound to it. Results of runs that already scored those items keep their frozen copies of the input and expected output.",
3058
+ moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/evaluations",
3059
+ httpMethod: "delete",
3060
+ pathParams: ["dataset_id"],
3061
+ queryParams: [],
3062
+ flags: [{
3063
+ "name": "dataset_id",
3064
+ "description": "Dataset ID",
3065
+ "required": true,
3066
+ "type": "string",
3067
+ "in": "path"
3068
+ }]
3069
+ },
3070
+ "list-dataset-items": {
3071
+ serviceClass: "Evaluations",
3072
+ operationId: "listDatasetItems",
3073
+ description: "Returns the test cases in a dataset, oldest first",
3074
+ moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/evaluations",
3075
+ httpMethod: "get",
3076
+ pathParams: ["dataset_id"],
3077
+ queryParams: ["limit", "offset"],
3078
+ flags: [{
3079
+ "name": "dataset_id",
3080
+ "description": "Dataset ID",
3081
+ "required": true,
3082
+ "type": "string",
3083
+ "in": "path"
3084
+ }, {
3085
+ "name": "limit",
3086
+ "description": "Maximum number of results to return",
3087
+ "required": false,
3088
+ "type": "integer",
3089
+ "in": "query"
3090
+ }, {
3091
+ "name": "offset",
3092
+ "description": "Number of results to skip",
3093
+ "required": false,
3094
+ "type": "integer",
3095
+ "in": "query"
3096
+ }]
3097
+ },
3098
+ "create-dataset-item": {
3099
+ serviceClass: "Evaluations",
3100
+ operationId: "createDatasetItem",
3101
+ description: "Adds one test case. `input` is replayed verbatim as the generation's messages, so it must be a non-empty array of `{ role, content }`.",
3102
+ moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/evaluations",
3103
+ httpMethod: "post",
3104
+ pathParams: ["dataset_id"],
3105
+ queryParams: [],
3106
+ flags: [{
3107
+ "name": "dataset_id",
3108
+ "description": "Dataset ID",
3109
+ "required": true,
3110
+ "type": "string",
3111
+ "in": "path"
3112
+ }, {
3113
+ "name": "input",
3114
+ "description": "Messages replayed verbatim as the generation's input",
3115
+ "required": true,
3116
+ "type": "array",
3117
+ "in": "body"
3118
+ }, {
3119
+ "name": "expected_output",
3120
+ "description": "Reference answer for exact_match / llm_judge scorers",
2859
3121
  "required": false,
2860
3122
  "type": "string",
2861
3123
  "in": "body"
2862
3124
  }, {
2863
3125
  "name": "metadata",
2864
- "description": "Arbitrary metadata object. Unlike other body fields, keys are stored and returned verbatim in the casing supplied — they are not converted between snake_case and camelCase.",
3126
+ "description": "Free-form tags, opaque to the platform",
2865
3127
  "required": false,
2866
3128
  "type": "object",
2867
3129
  "in": "body"
3130
+ }]
3131
+ },
3132
+ "update-dataset-item": {
3133
+ serviceClass: "Evaluations",
3134
+ operationId: "updateDatasetItem",
3135
+ description: "Updates a test case. Runs that already scored it are unaffected — each result carries its own frozen copy of the input and expected output.",
3136
+ moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/evaluations",
3137
+ httpMethod: "put",
3138
+ pathParams: ["dataset_id", "item_id"],
3139
+ queryParams: [],
3140
+ flags: [{
3141
+ "name": "dataset_id",
3142
+ "description": "Dataset ID",
3143
+ "required": true,
3144
+ "type": "string",
3145
+ "in": "path"
2868
3146
  }, {
2869
- "name": "tags",
2870
- "description": "Key-value tags",
3147
+ "name": "item_id",
3148
+ "description": "Dataset item ID",
3149
+ "required": true,
3150
+ "type": "string",
3151
+ "in": "path"
3152
+ }, {
3153
+ "name": "input",
3154
+ "description": "Messages replayed verbatim as the generation's input",
3155
+ "required": false,
3156
+ "type": "array",
3157
+ "in": "body"
3158
+ }, {
3159
+ "name": "expected_output",
3160
+ "description": "",
3161
+ "required": false,
3162
+ "type": "string",
3163
+ "in": "body"
3164
+ }, {
3165
+ "name": "metadata",
3166
+ "description": "",
2871
3167
  "required": false,
2872
3168
  "type": "object",
2873
3169
  "in": "body"
3170
+ }]
3171
+ },
3172
+ "delete-dataset-item": {
3173
+ serviceClass: "Evaluations",
3174
+ operationId: "deleteDatasetItem",
3175
+ description: "Deletes a test case. Results of runs that already scored it stay readable; their `dataset_item_id` becomes null.",
3176
+ moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/evaluations",
3177
+ httpMethod: "delete",
3178
+ pathParams: ["dataset_id", "item_id"],
3179
+ queryParams: [],
3180
+ flags: [{
3181
+ "name": "dataset_id",
3182
+ "description": "Dataset ID",
3183
+ "required": true,
3184
+ "type": "string",
3185
+ "in": "path"
2874
3186
  }, {
2875
- "name": "chunk_strategy",
2876
- "description": "How to split the content into embeddable chunks. `whole` (default) stores the content as a single chunk; `size` splits into fixed-size character windows with overlap. `page` is equivalent to `whole` for plain text.",
3187
+ "name": "item_id",
3188
+ "description": "Dataset item ID",
3189
+ "required": true,
3190
+ "type": "string",
3191
+ "in": "path"
3192
+ }]
3193
+ },
3194
+ "list-evals": {
3195
+ serviceClass: "Evaluations",
3196
+ operationId: "listEvals",
3197
+ description: "Returns the evals defined in a project",
3198
+ moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/evaluations",
3199
+ httpMethod: "get",
3200
+ pathParams: [],
3201
+ queryParams: ["project_id", "limit", "offset"],
3202
+ flags: [{
3203
+ "name": "project_id",
3204
+ "description": "Project ID (required if not using project key auth)",
2877
3205
  "required": false,
2878
3206
  "type": "string",
2879
- "in": "body"
3207
+ "in": "query"
2880
3208
  }, {
2881
- "name": "chunk_size",
2882
- "description": "Window size in characters when `chunk_strategy=size`. Defaults to 1000.",
3209
+ "name": "limit",
3210
+ "description": "Maximum number of results to return",
2883
3211
  "required": false,
2884
3212
  "type": "integer",
2885
- "in": "body"
3213
+ "in": "query"
2886
3214
  }, {
2887
- "name": "chunk_overlap",
2888
- "description": "Overlap in characters between consecutive windows when `chunk_strategy=size`. Defaults to 200.",
3215
+ "name": "offset",
3216
+ "description": "Number of results to skip",
2889
3217
  "required": false,
2890
3218
  "type": "integer",
2891
- "in": "body"
3219
+ "in": "query"
2892
3220
  }]
2893
3221
  },
2894
- "ingest-document": {
2895
- serviceClass: "Documents",
2896
- operationId: "ingestDocument",
2897
- description: "Parses an already-uploaded file and creates one Document split into one or more embedded chunks. The source format is detected from the file's content type: PDFs are parsed page-by-page; `text/plain` and `text/markdown` files are read as a single source. How the source is chunked is controlled by `chunk_strategy`. A file can only back one Document a second call with the same `file_id` returns `409 FILE_ALREADY_INGESTED`. To re-process an already-ingested file (e.g. with a different `chunk_strategy`), use `POST /documents/{document_id}/ingest`; to ingest the same source under a different path, upload a new copy of the file first.",
2898
- moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/documents",
3222
+ "create-eval": {
3223
+ serviceClass: "Evaluations",
3224
+ operationId: "createEval",
3225
+ description: "Binds an agent under test to a dataset and a list of scorers. The agent and the dataset must belong to the same project as the eval; a cross-project reference is rejected with 400. Scorer config is frozen here rather than read from the agent at run time, so two runs of the same eval are always judged by the same criteria and their comparison measures the agent instead of the config drifting underneath it. Each scorer `type` may appear at most once.",
3226
+ moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/evaluations",
2899
3227
  httpMethod: "post",
2900
3228
  pathParams: [],
2901
- queryParams: ["async"],
3229
+ queryParams: [],
2902
3230
  flags: [{
2903
- "name": "async",
2904
- "description": "When omitted or `true` (default), processing runs in the background and `202 Accepted` is returned immediately with `status=pending`. Pass `false` to run synchronously and receive `201 Created` with `status=ready`.",
2905
- "required": false,
2906
- "type": "boolean",
2907
- "in": "query"
2908
- }, {
2909
- "name": "file_id",
2910
- "description": "ID of the uploaded file. Must be one of application/pdf, text/plain, text/markdown.",
2911
- "required": true,
2912
- "type": "string",
2913
- "in": "body"
2914
- }, {
2915
3231
  "name": "project_id",
2916
- "description": "Project ID. Required for JWT auth; omit when using a project key.",
3232
+ "description": "Project ID (required if not using project key auth)",
2917
3233
  "required": false,
2918
3234
  "type": "string",
2919
3235
  "in": "body"
2920
3236
  }, {
2921
- "name": "path_prefix",
2922
- "description": "Path prefix under which to store the document (e.g. /docs/). The filename is appended automatically.",
2923
- "required": false,
3237
+ "name": "name",
3238
+ "description": "Unique name within the project",
3239
+ "required": true,
2924
3240
  "type": "string",
2925
3241
  "in": "body"
2926
3242
  }, {
2927
- "name": "tags",
2928
- "description": "Key-value tags to attach to the document.",
2929
- "required": false,
2930
- "type": "object",
3243
+ "name": "agent_id",
3244
+ "description": "The agent under test",
3245
+ "required": true,
3246
+ "type": "string",
2931
3247
  "in": "body"
2932
3248
  }, {
2933
- "name": "chunk_strategy",
2934
- "description": "How to split the source into chunks. `page` (default) creates one chunk per non-empty page (PDF); for non-paged sources it yields a single chunk. `whole` joins everything into one chunk. `size` splits into fixed-size character windows with overlap.",
2935
- "required": false,
3249
+ "name": "dataset_id",
3250
+ "description": "The dataset to run it against",
3251
+ "required": true,
2936
3252
  "type": "string",
2937
3253
  "in": "body"
2938
3254
  }, {
2939
- "name": "chunk_size",
2940
- "description": "Window size in characters when `chunk_strategy=size`. Defaults to 1000.",
2941
- "required": false,
2942
- "type": "integer",
3255
+ "name": "scorers",
3256
+ "description": "Scorer configs, a discriminated union on `type`. Each type may appear at most once. Every scorer produces `{ score: 0–1, passed: boolean }`; binary scorers emit 0 or 1.\n\n`exact_match` compares the trimmed output text to `expected_output`. `contains` looks for `value` in the output text. `json_logic` evaluates `expression` over `{ input, output, object, expected, item.metadata }`, where `object` is the structured output (absent when the agent has no `output_schema`). `output_schema` validates the structured output against the scorer's own `schema`, falling back to the agent's; it requires the agent to carry an `output_schema`, because without one the platform emits no structured output and every item would score 0.\n\n`llm_judge` grades the output with a model completion, returning a continuous score plus its `reasoning`. Its `pass_threshold` is required: a continuous score says nothing about where \"good enough\" is, and a defaulted cutoff would silently decide the gate.",
3257
+ "required": true,
3258
+ "type": "array",
2943
3259
  "in": "body"
2944
3260
  }, {
2945
- "name": "chunk_overlap",
2946
- "description": "Overlap in characters between consecutive windows when `chunk_strategy=size`. Defaults to 200.",
3261
+ "name": "pass_threshold",
3262
+ "description": "0–1. The run passes iff its pass rate passed items over non-errored items — is at least this. Null reports scores without gating on them.",
2947
3263
  "required": false,
2948
- "type": "integer",
3264
+ "type": "number",
2949
3265
  "in": "body"
2950
3266
  }]
2951
3267
  },
2952
- "get-document": {
2953
- serviceClass: "Documents",
2954
- operationId: "getDocument",
2955
- description: "Returns a document with its text content",
2956
- moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/documents",
3268
+ "get-eval": {
3269
+ serviceClass: "Evaluations",
3270
+ operationId: "getEval",
3271
+ description: "Returns a specific eval",
3272
+ moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/evaluations",
2957
3273
  httpMethod: "get",
2958
- pathParams: ["document_id"],
3274
+ pathParams: ["eval_id"],
2959
3275
  queryParams: [],
2960
3276
  flags: [{
2961
- "name": "document_id",
2962
- "description": "Document ID",
3277
+ "name": "eval_id",
3278
+ "description": "Eval ID",
2963
3279
  "required": true,
2964
3280
  "type": "string",
2965
3281
  "in": "path"
2966
3282
  }]
2967
3283
  },
2968
- "update-document": {
2969
- serviceClass: "Documents",
2970
- operationId: "updateDocument",
2971
- description: "Updates document content, title, path, metadata, or tags. Supplying `path` moves the document to a new logical path within the project.",
2972
- moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/documents",
2973
- httpMethod: "patch",
2974
- pathParams: ["document_id"],
3284
+ "update-eval": {
3285
+ serviceClass: "Evaluations",
3286
+ operationId: "updateEval",
3287
+ description: "Updates an eval. Changing `agent_id` re-validates the scorers against the new agent, since an `output_schema` scorer that was legal against the old one may not be.",
3288
+ moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/evaluations",
3289
+ httpMethod: "put",
3290
+ pathParams: ["eval_id"],
2975
3291
  queryParams: [],
2976
3292
  flags: [{
2977
- "name": "document_id",
2978
- "description": "Document ID",
3293
+ "name": "eval_id",
3294
+ "description": "Eval ID",
2979
3295
  "required": true,
2980
3296
  "type": "string",
2981
3297
  "in": "path"
2982
3298
  }, {
2983
- "name": "content",
2984
- "description": "New text content",
3299
+ "name": "name",
3300
+ "description": "",
2985
3301
  "required": false,
2986
3302
  "type": "string",
2987
3303
  "in": "body"
2988
3304
  }, {
2989
- "name": "title",
2990
- "description": "New title",
3305
+ "name": "agent_id",
3306
+ "description": "",
2991
3307
  "required": false,
2992
3308
  "type": "string",
2993
3309
  "in": "body"
2994
3310
  }, {
2995
- "name": "path",
2996
- "description": "Logical path within the project (e.g. /reports/q1.txt). Pass null to clear.",
3311
+ "name": "dataset_id",
3312
+ "description": "",
2997
3313
  "required": false,
2998
3314
  "type": "string",
2999
3315
  "in": "body"
3000
3316
  }, {
3001
- "name": "metadata",
3002
- "description": "Arbitrary metadata object. Unlike other body fields, keys are stored and returned verbatim in the casing supplied they are not converted between snake_case and camelCase.",
3317
+ "name": "scorers",
3318
+ "description": "Scorer configs, a discriminated union on `type`. Each type may appear at most once. Every scorer produces `{ score: 0–1, passed: boolean }`; binary scorers emit 0 or 1.\n\n`exact_match` compares the trimmed output text to `expected_output`. `contains` looks for `value` in the output text. `json_logic` evaluates `expression` over `{ input, output, object, expected, item.metadata }`, where `object` is the structured output (absent when the agent has no `output_schema`). `output_schema` validates the structured output against the scorer's own `schema`, falling back to the agent's; it requires the agent to carry an `output_schema`, because without one the platform emits no structured output and every item would score 0.\n\n`llm_judge` grades the output with a model completion, returning a continuous score plus its `reasoning`. Its `pass_threshold` is required: a continuous score says nothing about where \"good enough\" is, and a defaulted cutoff would silently decide the gate.",
3003
3319
  "required": false,
3004
- "type": "object",
3320
+ "type": "array",
3005
3321
  "in": "body"
3006
3322
  }, {
3007
- "name": "tags",
3008
- "description": "Key-value tags",
3323
+ "name": "pass_threshold",
3324
+ "description": "",
3009
3325
  "required": false,
3010
- "type": "object",
3326
+ "type": "number",
3011
3327
  "in": "body"
3012
3328
  }]
3013
3329
  },
3014
- "delete-document": {
3015
- serviceClass: "Documents",
3016
- operationId: "deleteDocument",
3017
- description: "Deletes a document and its underlying file",
3018
- moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/documents",
3330
+ "delete-eval": {
3331
+ serviceClass: "Evaluations",
3332
+ operationId: "deleteEval",
3333
+ description: "Deletes an eval, its runs, and their results",
3334
+ moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/evaluations",
3019
3335
  httpMethod: "delete",
3020
- pathParams: ["document_id"],
3336
+ pathParams: ["eval_id"],
3021
3337
  queryParams: [],
3022
3338
  flags: [{
3023
- "name": "document_id",
3024
- "description": "Document ID",
3339
+ "name": "eval_id",
3340
+ "description": "Eval ID",
3025
3341
  "required": true,
3026
3342
  "type": "string",
3027
3343
  "in": "path"
3028
3344
  }]
3029
3345
  },
3030
- "get-document-status": {
3031
- serviceClass: "Documents",
3032
- operationId: "getDocumentStatus",
3033
- description: "Returns a lightweight ingestion status payload for polling — `status`, `chunk_count`, `total_pages`, and (when failed) `error`. Unlike `GET /documents/{document_id}`, it never returns the assembled chunk content, so it is cheap to poll on large documents. A document whose ingestion has stalled (no progress past the configured timeout) is transitioned to `failed` with `error=INGESTION_TIMEOUT` on read.",
3034
- moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/documents",
3346
+ "list-eval-runs": {
3347
+ serviceClass: "Evaluations",
3348
+ operationId: "listEvalRuns",
3349
+ description: "Returns an eval's runs, newest first",
3350
+ moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/evaluations",
3035
3351
  httpMethod: "get",
3036
- pathParams: ["document_id"],
3037
- queryParams: [],
3352
+ pathParams: ["eval_id"],
3353
+ queryParams: ["limit", "offset"],
3038
3354
  flags: [{
3039
- "name": "document_id",
3040
- "description": "Document ID",
3355
+ "name": "eval_id",
3356
+ "description": "Eval ID",
3041
3357
  "required": true,
3042
3358
  "type": "string",
3043
3359
  "in": "path"
3360
+ }, {
3361
+ "name": "limit",
3362
+ "description": "Maximum number of results to return",
3363
+ "required": false,
3364
+ "type": "integer",
3365
+ "in": "query"
3366
+ }, {
3367
+ "name": "offset",
3368
+ "description": "Number of results to skip",
3369
+ "required": false,
3370
+ "type": "integer",
3371
+ "in": "query"
3044
3372
  }]
3045
3373
  },
3046
- "reingest-document": {
3047
- serviceClass: "Documents",
3048
- operationId: "reingestDocument",
3049
- description: "Re-runs ingestion for an existing document against its already-stored source file. Existing chunks are discarded and the document is reset to `status=pending` before re-processing. Use this to recover a document stuck in `processing`/`failed` or to re-chunk with a different strategy without re-uploading the file. Async by default (`202`); pass `?async=false` to run synchronously (`201`).",
3050
- moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/documents",
3374
+ "start-eval-run": {
3375
+ serviceClass: "Evaluations",
3376
+ operationId: "startEvalRun",
3377
+ description: "Runs the eval against its dataset, creating one real agent generation per item and scoring the outputs. `wait: true` executes the run synchronously and returns it terminal, with its scores. The dataset is capped at 25 items for a synchronous run; a larger one is rejected with 400 rather than partially scored. `wait: false` (the default) enqueues one task per item and returns immediately with `status: \"queued\"`. A worker executes the items and the run settles itself; poll `GET /evals/{eval_id}/runs/{eval_run_id}` for the terminal status, or subscribe to the `eval_run.completed` webhook. There is no item cap on a queued run. The whole run is pinned to **one** agent version, stamped on `agent_version`: pass one explicitly to evaluate a canary before promoting it, or omit it to use the active release's stable version (or the live draft when no release is in effect). Without the pin, release assignment would bucket each item independently and blend two configs into a single score. With `baseline_run_id`, the finished run's `aggregate_scores.baseline` carries per-scorer deltas against that run, computed over the items present and scorable in **both** runs, with the divergence counted. A delta over a shifted dataset is therefore never presented as a clean comparison.",
3378
+ moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/evaluations",
3051
3379
  httpMethod: "post",
3052
- pathParams: ["document_id"],
3053
- queryParams: ["async"],
3380
+ pathParams: ["eval_id"],
3381
+ queryParams: [],
3054
3382
  flags: [{
3055
- "name": "document_id",
3056
- "description": "Document ID",
3383
+ "name": "eval_id",
3384
+ "description": "Eval ID",
3057
3385
  "required": true,
3058
3386
  "type": "string",
3059
3387
  "in": "path"
3060
3388
  }, {
3061
- "name": "async",
3062
- "description": "When omitted or `true` (default), processing runs in the background and `202 Accepted` is returned immediately with `status=pending`. Pass `false` to run synchronously and receive `201 Created` with `status=ready`.",
3389
+ "name": "wait",
3390
+ "description": "True runs the eval synchronously (25-item cap) and returns a terminal run with its scores. False the default enqueues the items and returns a `queued` run immediately.",
3063
3391
  "required": false,
3064
3392
  "type": "boolean",
3065
- "in": "query"
3066
- }, {
3067
- "name": "chunk_strategy",
3068
- "description": "How to split the source into chunks. Defaults to `page`.",
3069
- "required": false,
3070
- "type": "string",
3071
3393
  "in": "body"
3072
3394
  }, {
3073
- "name": "chunk_size",
3074
- "description": "Window size in characters when `chunk_strategy=size`. Defaults to 1000.",
3395
+ "name": "agent_version",
3396
+ "description": "An archived agent version to evaluate. Defaults to the active release's stable version, or the live draft version when no release is in effect.",
3075
3397
  "required": false,
3076
3398
  "type": "integer",
3077
3399
  "in": "body"
3078
3400
  }, {
3079
- "name": "chunk_overlap",
3080
- "description": "Overlap in characters between consecutive windows when `chunk_strategy=size`. Defaults to 200.",
3401
+ "name": "baseline_run_id",
3402
+ "description": "A terminal run of the same eval to compare against. The finished run's `aggregate_scores.baseline` reports per-scorer deltas over the item intersection. A run of a different eval is rejected with 400.",
3081
3403
  "required": false,
3082
- "type": "integer",
3404
+ "type": "string",
3083
3405
  "in": "body"
3084
3406
  }]
3085
3407
  },
3086
- "complete-ingestion-callback": {
3087
- serviceClass: "Documents",
3088
- operationId: "completeIngestionCallback",
3089
- description: "Token-authed callback for a tool converter that deferred conversion by returning `{ \"status\": \"pending\" }` (see the Ingestion Rules module docs). Not IAM-gated — the external converter is not a SOAT principal, so it authenticates with the single-use token minted for this document and ingestion attempt (delivered as `callback.token` / embedded in `callback.url` in the original converter invocation). Accepted only while the document is still awaiting that exact attempt; rejected with `409` if the attempt already completed, timed out, or was superseded by a re-ingest.",
3090
- moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/documents",
3091
- httpMethod: "post",
3092
- pathParams: ["document_id"],
3093
- queryParams: ["token"],
3408
+ "get-eval-run": {
3409
+ serviceClass: "Evaluations",
3410
+ operationId: "getEvalRun",
3411
+ description: "Returns a run's status, counts, and aggregate scores",
3412
+ moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/evaluations",
3413
+ httpMethod: "get",
3414
+ pathParams: ["eval_id", "eval_run_id"],
3415
+ queryParams: [],
3094
3416
  flags: [{
3095
- "name": "document_id",
3096
- "description": "Document ID",
3417
+ "name": "eval_id",
3418
+ "description": "Eval ID",
3097
3419
  "required": true,
3098
3420
  "type": "string",
3099
3421
  "in": "path"
3100
3422
  }, {
3101
- "name": "token",
3102
- "description": "Single-use signed token from the original `callback.token`",
3423
+ "name": "eval_run_id",
3424
+ "description": "Eval run ID",
3103
3425
  "required": true,
3104
3426
  "type": "string",
3105
- "in": "query"
3106
- }, {
3107
- "name": "text",
3108
- "description": "",
3109
- "required": false,
3110
- "type": "string",
3111
- "in": "body"
3112
- }, {
3113
- "name": "pages",
3114
- "description": "",
3115
- "required": false,
3116
- "type": "array",
3117
- "in": "body"
3427
+ "in": "path"
3118
3428
  }]
3119
3429
  },
3120
- "get-document-tags": {
3121
- serviceClass: "Documents",
3122
- operationId: "getDocumentTags",
3123
- description: "Returns all tags attached to the document",
3124
- moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/documents",
3430
+ "list-eval-results": {
3431
+ serviceClass: "Evaluations",
3432
+ operationId: "listEvalResults",
3433
+ description: "Returns the per-item results of a run, oldest first",
3434
+ moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/evaluations",
3125
3435
  httpMethod: "get",
3126
- pathParams: ["document_id"],
3127
- queryParams: [],
3436
+ pathParams: ["eval_id", "eval_run_id"],
3437
+ queryParams: ["limit", "offset"],
3128
3438
  flags: [{
3129
- "name": "document_id",
3130
- "description": "Document ID",
3439
+ "name": "eval_id",
3440
+ "description": "Eval ID",
3131
3441
  "required": true,
3132
3442
  "type": "string",
3133
3443
  "in": "path"
3134
- }]
3135
- },
3136
- "replace-document-tags": {
3137
- serviceClass: "Documents",
3138
- operationId: "replaceDocumentTags",
3139
- description: "Replaces all tags on the document with the provided tags (not merged)",
3140
- moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/documents",
3141
- httpMethod: "put",
3142
- pathParams: ["document_id"],
3143
- queryParams: [],
3144
- flags: [{
3145
- "name": "document_id",
3146
- "description": "Document ID",
3444
+ }, {
3445
+ "name": "eval_run_id",
3446
+ "description": "Eval run ID",
3147
3447
  "required": true,
3148
3448
  "type": "string",
3149
3449
  "in": "path"
3450
+ }, {
3451
+ "name": "limit",
3452
+ "description": "Maximum number of results to return",
3453
+ "required": false,
3454
+ "type": "integer",
3455
+ "in": "query"
3456
+ }, {
3457
+ "name": "offset",
3458
+ "description": "Number of results to skip",
3459
+ "required": false,
3460
+ "type": "integer",
3461
+ "in": "query"
3150
3462
  }]
3151
3463
  },
3152
- "merge-document-tags": {
3153
- serviceClass: "Documents",
3154
- operationId: "mergeDocumentTags",
3155
- description: "Merges provided tags with existing tags (existing tags are preserved unless overridden)",
3156
- moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/documents",
3157
- httpMethod: "patch",
3158
- pathParams: ["document_id"],
3464
+ "cancel-eval-run": {
3465
+ serviceClass: "Evaluations",
3466
+ operationId: "cancelEvalRun",
3467
+ description: "Cancels a queued or running run: its outstanding item tasks are dropped so it stops consuming provider budget, and the run settles as `canceled`. Results already written are kept — they are real measurements of generations that were really paid for — and `completed_count` / `errored_count` report what ran. `aggregate_scores` is deliberately left null: a partial roll-up in the same field a completed run uses would read as a whole-dataset verdict. A run that has already finished is rejected with 400.",
3468
+ moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/evaluations",
3469
+ httpMethod: "post",
3470
+ pathParams: ["eval_id", "eval_run_id"],
3159
3471
  queryParams: [],
3160
3472
  flags: [{
3161
- "name": "document_id",
3162
- "description": "Document ID",
3473
+ "name": "eval_id",
3474
+ "description": "Eval ID",
3163
3475
  "required": true,
3164
3476
  "type": "string",
3165
3477
  "in": "path"
3166
- }]
3167
- },
3168
- "create-embeddings": {
3169
- serviceClass: "Embeddings",
3170
- operationId: "createEmbeddings",
3171
- description: "Generates embedding vectors for one or more text inputs using the server's configured embedding model. Provide `input` for a single text or `inputs` for a batch. At least one is required. Returns `embedding` when `input` is used, and `embeddings` when `inputs` is used.",
3172
- moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/embeddings",
3173
- httpMethod: "post",
3174
- pathParams: [],
3175
- queryParams: [],
3176
- flags: [{
3177
- "name": "input",
3178
- "description": "Single text to embed.",
3179
- "required": false,
3180
- "type": "string",
3181
- "in": "body"
3182
3478
  }, {
3183
- "name": "inputs",
3184
- "description": "Batch of texts to embed.",
3185
- "required": false,
3186
- "type": "array",
3187
- "in": "body"
3479
+ "name": "eval_run_id",
3480
+ "description": "Eval run ID",
3481
+ "required": true,
3482
+ "type": "string",
3483
+ "in": "path"
3188
3484
  }]
3189
3485
  },
3190
3486
  "list-exceptions": {
@@ -6144,11 +6440,11 @@ var routes = {
6144
6440
  "generate-session-response": {
6145
6441
  serviceClass: "Sessions",
6146
6442
  operationId: "generateSessionResponse",
6147
- description: "Triggers the agent to generate a response based on the current conversation. Returns the assistant reply or a requires_action status if the agent needs client tool outputs. Pass ?async=true for a 202 accepted response when you do not need to wait for the result.",
6443
+ description: "Triggers the agent to generate a response based on the current conversation. Background by default: returns `202 Accepted` immediately while the generation runs. Pass ?wait=true to block and receive the assistant reply (or a requires_action status if the agent needs client tool outputs) in the response.",
6148
6444
  moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/sessions",
6149
6445
  httpMethod: "post",
6150
6446
  pathParams: ["session_id"],
6151
- queryParams: ["async"],
6447
+ queryParams: ["wait"],
6152
6448
  flags: [{
6153
6449
  "name": "session_id",
6154
6450
  "description": "Session public ID",
@@ -6156,8 +6452,8 @@ var routes = {
6156
6452
  "type": "string",
6157
6453
  "in": "path"
6158
6454
  }, {
6159
- "name": "async",
6160
- "description": "When true, generation runs in the background and 202 is returned immediately",
6455
+ "name": "wait",
6456
+ "description": "When omitted or `false` (default), generation runs in the background and `202 Accepted` is returned immediately. Pass `true` to block until the generation settles and receive the result.",
6161
6457
  "required": false,
6162
6458
  "type": "boolean",
6163
6459
  "in": "query"
@@ -7050,7 +7346,7 @@ var routes = {
7050
7346
  "fire-trigger": {
7051
7347
  serviceClass: "Triggers",
7052
7348
  operationId: "fireTrigger",
7053
- description: "Fires a trigger synchronously and returns the terminal firing record.",
7349
+ description: "Fires a trigger synchronously and returns the terminal firing record. The firing itself always settles here; an `eval` target's run is queued rather than executed inline, so the record names a `queued` run to poll.",
7054
7350
  moduleDocsUrl: "https://soat.ttoss.dev/docs/modules/triggers",
7055
7351
  httpMethod: "post",
7056
7352
  pathParams: ["trigger_id"],
@@ -7063,7 +7359,7 @@ var routes = {
7063
7359
  "in": "path"
7064
7360
  }, {
7065
7361
  "name": "input",
7066
- "description": "Fire-time input, shallow-merged over the trigger's static input",
7362
+ "description": "Fire-time input, shallow-merged over the trigger's static input. For `eval` targets it may carry `agent_version` and `baseline_run_id`.",
7067
7363
  "required": false,
7068
7364
  "type": "object",
7069
7365
  "in": "body"