@thinkai/tai-api-contract 2.171.0 → 2.173.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.
@@ -1,7 +1,7 @@
1
1
  openapi: 3.0.3
2
2
  info:
3
3
  title: ThinkAI API
4
- version: 2.171.0
4
+ version: 2.173.0
5
5
  description: >
6
6
  Contract surface for the AI Driven SDLC backend used by ThinkAI.
7
7
  Workspace-scoped routes use `/workspaces/{workspaceId}/...`.
@@ -92,6 +92,12 @@ tags:
92
92
  classified test-file inventory (unit, integration, acceptance/BDD, contract, E2E)
93
93
  with count-based presence and advisory 70/20/10 shape. Distinct from Agentic
94
94
  Foundation readiness `/readiness/test-pyramid*` (signal-inclusive presence).
95
+ - name: Evals
96
+ description: >
97
+ Workspace prompt/model eval suites (`/evals/*`) — authored golden cases with
98
+ deterministic expected-signal scoring, async runs (never scored on the request
99
+ path), and an Insights surface for regressions and token efficiency. Distinct
100
+ from AI Usage & Spend ingest and Agentic Foundation Token Efficiency (rubric I).
95
101
 
96
102
  paths:
97
103
  /admin/users/{userId}:
@@ -8829,7 +8835,8 @@ paths:
8829
8835
  `status` is `indexing`, `generating_agent_md`, `failed`, or `ready`. Chat stays closed
8830
8836
  until `ready`: create thread and post message return `409 chat_not_ready` with
8831
8837
  `progressMessage` when status is not ready. An open index wave reports `indexing` until
8832
- every job in that wave is terminal.
8838
+ every job in that wave is terminal. When ready, includes `activeProvider` and
8839
+ `attachmentLimits` for Conversations file uploads.
8833
8840
  operationId: getCodeChatReadiness
8834
8841
  x-test-coverage-skip: thin HTTP over deriveCodeChatReadiness; covered by code-chat-readiness unit tests
8835
8842
  parameters:
@@ -8853,6 +8860,58 @@ paths:
8853
8860
  error: Code Intelligence is disabled for this workspace
8854
8861
  code: code_intelligence_disabled
8855
8862
 
8863
+ /workspaces/{workspaceId}/code-chat/attachments:
8864
+ post:
8865
+ tags: [CodeChat]
8866
+ summary: Upload a Conversations attachment
8867
+ description: >
8868
+ Any workspace member when chat is ready. Validates size/type against the active
8869
+ provider profile (`attachmentLimits` from readiness). Returns metadata; pass `id`
8870
+ as `attachmentIds` on the next POST message. Max 5 MB per file.
8871
+ operationId: postCodeChatAttachment
8872
+ x-test-coverage-skip: thin HTTP over validateAttachment + store insert
8873
+ parameters:
8874
+ - $ref: "#/components/parameters/WorkspaceId"
8875
+ requestBody:
8876
+ required: true
8877
+ content:
8878
+ application/json:
8879
+ schema:
8880
+ $ref: "#/components/schemas/CodeChatUploadAttachmentBodyDto"
8881
+ responses:
8882
+ "201":
8883
+ description: Attachment stored
8884
+ content:
8885
+ application/json:
8886
+ schema:
8887
+ $ref: "#/components/schemas/CodeChatAttachmentMetaDto"
8888
+ "400":
8889
+ description: Validation failed (size, type, totals)
8890
+ content:
8891
+ application/json:
8892
+ schema:
8893
+ $ref: "#/components/schemas/ErrorMessageDto"
8894
+ "401":
8895
+ $ref: "#/components/responses/Unauthorized"
8896
+ "403":
8897
+ description: Engineering Context Graph is off
8898
+ content:
8899
+ application/json:
8900
+ schema:
8901
+ $ref: "#/components/schemas/ErrorMessageDto"
8902
+ "409":
8903
+ description: Chat not ready
8904
+ content:
8905
+ application/json:
8906
+ schema:
8907
+ $ref: "#/components/schemas/ErrorMessageDto"
8908
+ "422":
8909
+ description: Could not process the file
8910
+ content:
8911
+ application/json:
8912
+ schema:
8913
+ $ref: "#/components/schemas/ErrorMessageDto"
8914
+
8856
8915
  /workspaces/{workspaceId}/code-chat/indexes/{indexId}:
8857
8916
  get:
8858
8917
  tags: [CodeChat]
@@ -11939,6 +11998,350 @@ paths:
11939
11998
  "403":
11940
11999
  $ref: "#/components/responses/Forbidden"
11941
12000
 
12001
+ /workspaces/{workspaceId}/evals/suites:
12002
+ get:
12003
+ tags: [Evals]
12004
+ summary: List eval suites for a workspace
12005
+ description: >
12006
+ Returns the latest version of each eval suite in the workspace (max 50 suites).
12007
+ Requires workspace membership (`requireWorkspaceMember`). Empty workspace →
12008
+ `{ "suites": [] }`.
12009
+ operationId: listEvalSuites
12010
+ parameters:
12011
+ - $ref: "#/components/parameters/WorkspaceId"
12012
+ responses:
12013
+ "200":
12014
+ description: Suite list (latest version per suite)
12015
+ content:
12016
+ application/json:
12017
+ schema:
12018
+ $ref: "#/components/schemas/EvalSuiteListDto"
12019
+ example:
12020
+ suites: []
12021
+ "401":
12022
+ $ref: "#/components/responses/Unauthorized"
12023
+ "403":
12024
+ $ref: "#/components/responses/Forbidden"
12025
+ "404":
12026
+ description: Workspace not found
12027
+ content:
12028
+ application/json:
12029
+ schema:
12030
+ $ref: "#/components/schemas/ErrorMessageDto"
12031
+ post:
12032
+ tags: [Evals]
12033
+ summary: Create an eval suite
12034
+ description: >
12035
+ Creates a suite at `version: 1`. Requires workspace editor or admin
12036
+ (`requireWorkspaceEditor`). Rejects when both `target.promptBody` is empty
12037
+ and model fields are missing; when `cases` is empty (`400`
12038
+ `eval_suite_cases_required`); or when the workspace already has 50 suites.
12039
+ Each case must include at least one expected signal.
12040
+ operationId: createEvalSuite
12041
+ parameters:
12042
+ - $ref: "#/components/parameters/WorkspaceId"
12043
+ requestBody:
12044
+ required: true
12045
+ content:
12046
+ application/json:
12047
+ schema:
12048
+ $ref: "#/components/schemas/CreateEvalSuiteBodyDto"
12049
+ example:
12050
+ name: Greeting quality
12051
+ description: Fixture-backed smoke suite for the support greeting prompt
12052
+ target:
12053
+ promptBody: "You are a support agent. Greet the user by name."
12054
+ promptKey: support-greeting
12055
+ provider: cursor
12056
+ modelName: gpt-4.1-mini
12057
+ cases:
12058
+ - id: case-hello
12059
+ name: Hello Alice
12060
+ input: '{"name":"Alice"}'
12061
+ fixtureCompletion: "Hello Alice, how can I help you today?"
12062
+ expectedSignals:
12063
+ - id: sig-contains-hello
12064
+ kind: contains
12065
+ value: "Hello Alice"
12066
+ - id: sig-not-sorry
12067
+ kind: not_contains
12068
+ value: "I cannot"
12069
+ responses:
12070
+ "201":
12071
+ description: Suite created
12072
+ content:
12073
+ application/json:
12074
+ schema:
12075
+ $ref: "#/components/schemas/EvalSuiteDto"
12076
+ "400":
12077
+ description: >
12078
+ Validation failed — empty cases (`eval_suite_cases_required`), missing
12079
+ target (prompt and model), invalid name/description lengths, case/signal
12080
+ bounds, or malformed body.
12081
+ content:
12082
+ application/json:
12083
+ schema:
12084
+ $ref: "#/components/schemas/ErrorMessageDto"
12085
+ examples:
12086
+ cases_required:
12087
+ value:
12088
+ error: At least one case is required
12089
+ code: eval_suite_cases_required
12090
+ target_required:
12091
+ value:
12092
+ error: Suite target requires promptBody or provider+modelName
12093
+ code: eval_suite_target_required
12094
+ "401":
12095
+ $ref: "#/components/responses/Unauthorized"
12096
+ "403":
12097
+ description: Authenticated but not a workspace editor/admin
12098
+ content:
12099
+ application/json:
12100
+ schema:
12101
+ $ref: "#/components/schemas/ErrorMessageDto"
12102
+ example:
12103
+ error: Workspace editor role required
12104
+ code: workspace_editor_required
12105
+ "404":
12106
+ description: Workspace not found
12107
+ content:
12108
+ application/json:
12109
+ schema:
12110
+ $ref: "#/components/schemas/ErrorMessageDto"
12111
+ "409":
12112
+ description: Workspace already has the maximum of 50 suites
12113
+ content:
12114
+ application/json:
12115
+ schema:
12116
+ $ref: "#/components/schemas/ErrorMessageDto"
12117
+ example:
12118
+ error: Maximum of 50 eval suites per workspace
12119
+ code: eval_suite_limit_reached
12120
+
12121
+ /workspaces/{workspaceId}/evals/suites/{suiteId}:
12122
+ get:
12123
+ tags: [Evals]
12124
+ summary: Get an eval suite (latest version)
12125
+ description: >
12126
+ Returns the latest version of the suite. Historical versions are retained for
12127
+ runs via `suiteVersion` + snapshot on each run; this endpoint does not expose
12128
+ prior versions. Requires workspace membership.
12129
+ operationId: getEvalSuite
12130
+ parameters:
12131
+ - $ref: "#/components/parameters/WorkspaceId"
12132
+ - $ref: "#/components/parameters/EvalSuiteId"
12133
+ responses:
12134
+ "200":
12135
+ description: Suite (latest version)
12136
+ content:
12137
+ application/json:
12138
+ schema:
12139
+ $ref: "#/components/schemas/EvalSuiteDto"
12140
+ "401":
12141
+ $ref: "#/components/responses/Unauthorized"
12142
+ "403":
12143
+ $ref: "#/components/responses/Forbidden"
12144
+ "404":
12145
+ description: Workspace or suite not found
12146
+ content:
12147
+ application/json:
12148
+ schema:
12149
+ $ref: "#/components/schemas/ErrorMessageDto"
12150
+ put:
12151
+ tags: [Evals]
12152
+ summary: Update an eval suite
12153
+ description: >
12154
+ Replaces mutable suite fields. Requires workspace editor or admin.
12155
+ Changing `target`, `cases`, or `promptBody` increments `version` by 1 and
12156
+ keeps prior versions immutable for historical runs. Cosmetic
12157
+ name/description-only updates do not bump `version`. Same validation rules
12158
+ as create (cases required, target required, bounds).
12159
+ operationId: updateEvalSuite
12160
+ parameters:
12161
+ - $ref: "#/components/parameters/WorkspaceId"
12162
+ - $ref: "#/components/parameters/EvalSuiteId"
12163
+ requestBody:
12164
+ required: true
12165
+ content:
12166
+ application/json:
12167
+ schema:
12168
+ $ref: "#/components/schemas/UpdateEvalSuiteBodyDto"
12169
+ responses:
12170
+ "200":
12171
+ description: Suite updated (possibly with bumped version)
12172
+ content:
12173
+ application/json:
12174
+ schema:
12175
+ $ref: "#/components/schemas/EvalSuiteDto"
12176
+ "400":
12177
+ description: Validation failed (same codes as create)
12178
+ content:
12179
+ application/json:
12180
+ schema:
12181
+ $ref: "#/components/schemas/ErrorMessageDto"
12182
+ "401":
12183
+ $ref: "#/components/responses/Unauthorized"
12184
+ "403":
12185
+ description: Authenticated but not a workspace editor/admin
12186
+ content:
12187
+ application/json:
12188
+ schema:
12189
+ $ref: "#/components/schemas/ErrorMessageDto"
12190
+ example:
12191
+ error: Workspace editor role required
12192
+ code: workspace_editor_required
12193
+ "404":
12194
+ description: Workspace or suite not found
12195
+ content:
12196
+ application/json:
12197
+ schema:
12198
+ $ref: "#/components/schemas/ErrorMessageDto"
12199
+
12200
+ /workspaces/{workspaceId}/evals/suites/{suiteId}/runs:
12201
+ get:
12202
+ tags: [Evals]
12203
+ summary: List recent eval runs for a suite
12204
+ description: >
12205
+ Returns the last 50 runs for the suite (newest first). Empty → `{ "runs": [] }`.
12206
+ Requires workspace membership. Does not trigger scoring.
12207
+ operationId: listEvalRuns
12208
+ parameters:
12209
+ - $ref: "#/components/parameters/WorkspaceId"
12210
+ - $ref: "#/components/parameters/EvalSuiteId"
12211
+ responses:
12212
+ "200":
12213
+ description: Run history (max 50)
12214
+ content:
12215
+ application/json:
12216
+ schema:
12217
+ $ref: "#/components/schemas/EvalRunListDto"
12218
+ example:
12219
+ runs: []
12220
+ "401":
12221
+ $ref: "#/components/responses/Unauthorized"
12222
+ "403":
12223
+ $ref: "#/components/responses/Forbidden"
12224
+ "404":
12225
+ description: Workspace or suite not found
12226
+ content:
12227
+ application/json:
12228
+ schema:
12229
+ $ref: "#/components/schemas/ErrorMessageDto"
12230
+ post:
12231
+ tags: [Evals]
12232
+ summary: Enqueue an eval suite run
12233
+ description: >
12234
+ Enqueues an async eval run. Returns `202` with `{ runId, status: "queued" }`.
12235
+ Never scores on the request path — a worker claims the run, uses
12236
+ `fixtureCompletion` when present (or live completion when provider credentials
12237
+ exist), applies deterministic expected-signal scoring, and persists results.
12238
+ Requires workspace editor or admin. At most one active (`queued`|`running`)
12239
+ run per suite; a second POST returns `409` `eval_run_in_progress`.
12240
+ operationId: enqueueEvalRun
12241
+ parameters:
12242
+ - $ref: "#/components/parameters/WorkspaceId"
12243
+ - $ref: "#/components/parameters/EvalSuiteId"
12244
+ responses:
12245
+ "202":
12246
+ description: Run queued
12247
+ content:
12248
+ application/json:
12249
+ schema:
12250
+ $ref: "#/components/schemas/EvalRunEnqueueResponseDto"
12251
+ example:
12252
+ runId: "22222222-2222-4222-8222-222222222222"
12253
+ status: queued
12254
+ "401":
12255
+ $ref: "#/components/responses/Unauthorized"
12256
+ "403":
12257
+ description: Authenticated but not a workspace editor/admin
12258
+ content:
12259
+ application/json:
12260
+ schema:
12261
+ $ref: "#/components/schemas/ErrorMessageDto"
12262
+ example:
12263
+ error: Workspace editor role required
12264
+ code: workspace_editor_required
12265
+ "404":
12266
+ description: Workspace or suite not found
12267
+ content:
12268
+ application/json:
12269
+ schema:
12270
+ $ref: "#/components/schemas/ErrorMessageDto"
12271
+ "409":
12272
+ description: An active queued or running eval already exists for this suite
12273
+ content:
12274
+ application/json:
12275
+ schema:
12276
+ $ref: "#/components/schemas/ErrorMessageDto"
12277
+ example:
12278
+ error: An eval run is already in progress for this suite
12279
+ code: eval_run_in_progress
12280
+
12281
+ /workspaces/{workspaceId}/evals/suites/{suiteId}/runs/{runId}:
12282
+ get:
12283
+ tags: [Evals]
12284
+ summary: Get an eval run with case results
12285
+ description: >
12286
+ Returns persisted run status and case results. While `queued` or `running`,
12287
+ `caseResults` may be empty and `score` null. Requires workspace membership.
12288
+ Does not trigger scoring.
12289
+ operationId: getEvalRun
12290
+ parameters:
12291
+ - $ref: "#/components/parameters/WorkspaceId"
12292
+ - $ref: "#/components/parameters/EvalSuiteId"
12293
+ - $ref: "#/components/parameters/EvalRunId"
12294
+ responses:
12295
+ "200":
12296
+ description: Run detail
12297
+ content:
12298
+ application/json:
12299
+ schema:
12300
+ $ref: "#/components/schemas/EvalRunDto"
12301
+ "401":
12302
+ $ref: "#/components/responses/Unauthorized"
12303
+ "403":
12304
+ $ref: "#/components/responses/Forbidden"
12305
+ "404":
12306
+ description: Workspace, suite, or run not found
12307
+ content:
12308
+ application/json:
12309
+ schema:
12310
+ $ref: "#/components/schemas/ErrorMessageDto"
12311
+
12312
+ /workspaces/{workspaceId}/evals/insights:
12313
+ get:
12314
+ tags: [Evals]
12315
+ summary: Eval insights (regressions, tips, efficiency, model comparison)
12316
+ description: >
12317
+ Workspace-level Insights for prompt/model evals. Computes regressions when
12318
+ prior score − current score ≥ 0.10 on the same suiteId+suiteVersion case set
12319
+ (or suite score drop ≥ 0.10); prompt tips from failed signal notes / case
12320
+ names; token efficiency averages over successful cases in the last succeeded
12321
+ run per suite; and model comparison rollups. No succeeded runs → empty arrays
12322
+ and null `tokenEfficiency`. Requires workspace membership. Distinct from
12323
+ `/insights-recommendations` and AI Usage & Spend.
12324
+ operationId: getEvalInsights
12325
+ parameters:
12326
+ - $ref: "#/components/parameters/WorkspaceId"
12327
+ responses:
12328
+ "200":
12329
+ description: Insights payload
12330
+ content:
12331
+ application/json:
12332
+ schema:
12333
+ $ref: "#/components/schemas/EvalInsightsDto"
12334
+ "401":
12335
+ $ref: "#/components/responses/Unauthorized"
12336
+ "403":
12337
+ $ref: "#/components/responses/Forbidden"
12338
+ "404":
12339
+ description: Workspace not found
12340
+ content:
12341
+ application/json:
12342
+ schema:
12343
+ $ref: "#/components/schemas/ErrorMessageDto"
12344
+
11942
12345
  components:
11943
12346
  securitySchemes:
11944
12347
  bearerAuth:
@@ -11954,6 +12357,22 @@ components:
11954
12357
  required: true
11955
12358
  schema:
11956
12359
  type: string
12360
+ EvalSuiteId:
12361
+ name: suiteId
12362
+ in: path
12363
+ required: true
12364
+ schema:
12365
+ type: string
12366
+ format: uuid
12367
+ description: Eval suite id (`tai_workspace_eval_suites.id`).
12368
+ EvalRunId:
12369
+ name: runId
12370
+ in: path
12371
+ required: true
12372
+ schema:
12373
+ type: string
12374
+ format: uuid
12375
+ description: Eval run id (`tai_workspace_eval_runs.id`).
11957
12376
  RepoId:
11958
12377
  name: repoId
11959
12378
  in: path
@@ -13666,7 +14085,44 @@ components:
13666
14085
  format: date-time
13667
14086
  nullable: true
13668
14087
 
13669
- CodeChatReadinessDto:
14088
+ CodeChatAttachmentLimitsDto:
14089
+ type: object
14090
+ required:
14091
+ - maxFiles
14092
+ - maxBytesPerFile
14093
+ - maxTotalBytes
14094
+ - maxTextChars
14095
+ - maxPdfPages
14096
+ - allowedMimeTypes
14097
+ - allowedExtensions
14098
+ - supportsImages
14099
+ - supportsPdf
14100
+ properties:
14101
+ maxFiles: { type: integer, minimum: 1 }
14102
+ maxBytesPerFile: { type: integer, minimum: 1 }
14103
+ maxTotalBytes: { type: integer, minimum: 1 }
14104
+ maxTextChars: { type: integer, minimum: 1 }
14105
+ maxPdfPages: { type: integer, minimum: 1 }
14106
+ allowedMimeTypes:
14107
+ type: array
14108
+ items: { type: string }
14109
+ allowedExtensions:
14110
+ type: array
14111
+ items: { type: string }
14112
+ supportsImages: { type: boolean }
14113
+ supportsPdf: { type: boolean }
14114
+
14115
+ CodeChatAttachmentMetaDto:
14116
+ type: object
14117
+ required: [id, filename, mimeType, sizeBytes, createdAt]
14118
+ properties:
14119
+ id: { type: string, format: uuid }
14120
+ filename: { type: string }
14121
+ mimeType: { type: string }
14122
+ sizeBytes: { type: integer, minimum: 1 }
14123
+ createdAt: { type: string, format: date-time }
14124
+
14125
+ CodeChatReadinessDto:
13670
14126
  type: object
13671
14127
  required:
13672
14128
  - status
@@ -13705,6 +14161,13 @@ components:
13705
14161
  type: string
13706
14162
  nullable: true
13707
14163
  enum: [generated, admin]
14164
+ activeProvider:
14165
+ type: string
14166
+ nullable: true
14167
+ enum: [claude, cursor]
14168
+ description: Active Ask synthesizer for attachment limit profiles
14169
+ attachmentLimits:
14170
+ $ref: "#/components/schemas/CodeChatAttachmentLimitsDto"
13708
14171
 
13709
14172
  CodeWikiGuidanceDto:
13710
14173
  type: object
@@ -23515,6 +23978,10 @@ components:
23515
23978
  type: array
23516
23979
  items: { $ref: "#/components/schemas/CodeChatCitationDto" }
23517
23980
  createdAt: { type: string, format: date-time }
23981
+ attachments:
23982
+ type: array
23983
+ items: { $ref: "#/components/schemas/CodeChatAttachmentMetaDto" }
23984
+ description: Present on user turns that included uploaded files
23518
23985
 
23519
23986
  CodeChatThreadDetailDto:
23520
23987
  allOf:
@@ -23541,6 +24008,24 @@ components:
23541
24008
  description: >
23542
24009
  Optional force deterministic inventory catalog instead of LLM synthesis.
23543
24010
  When omitted, the server classifies listing-style API/module questions automatically.
24011
+ attachmentIds:
24012
+ type: array
24013
+ maxItems: 5
24014
+ items: { type: string, format: uuid }
24015
+ description: Previously uploaded attachment ids to bind to this user turn
24016
+
24017
+ CodeChatUploadAttachmentBodyDto:
24018
+ type: object
24019
+ required: [filename, mimeType, contentBase64]
24020
+ properties:
24021
+ filename: { type: string, minLength: 1, maxLength: 255 }
24022
+ mimeType: { type: string, minLength: 1, maxLength: 255 }
24023
+ contentBase64:
24024
+ type: string
24025
+ minLength: 1
24026
+ description: Base64-encoded file bytes (no data-URL prefix required)
24027
+ threadId: { type: string, format: uuid, nullable: true }
24028
+ pdfPageCount: { type: integer, minimum: 1, nullable: true }
23544
24029
 
23545
24030
  CodeChatMessageReplyDto:
23546
24031
  allOf:
@@ -25489,3 +25974,539 @@ components:
25489
25974
  total: { type: integer, minimum: 0 }
25490
25975
  limit: { type: integer, minimum: 1 }
25491
25976
  offset: { type: integer, minimum: 0 }
25977
+ EvalExpectedSignalKindDto:
25978
+ type: string
25979
+ description: >
25980
+ Deterministic scorer kinds for golden-case expected signals. Case pass =
25981
+ all signals pass. No LLM-as-judge in v1.
25982
+ enum: [contains, not_contains, regex, json_path_equals]
25983
+
25984
+ EvalAiProviderDto:
25985
+ type: string
25986
+ description: >
25987
+ Model provider vocabulary aligned with AI Usage `modelName` surfaces
25988
+ (`cursor` | `claude`).
25989
+ enum: [cursor, claude]
25990
+
25991
+ EvalExpectedSignalDto:
25992
+ type: object
25993
+ additionalProperties: false
25994
+ required: [id, kind]
25995
+ description: >
25996
+ One expected signal on a golden case. Use `value` for `contains` /
25997
+ `not_contains` (substring) and for `json_path_equals` (expected value as
25998
+ string). Use `pattern` for `regex`. Use `path` (JSONPath) for
25999
+ `json_path_equals`.
26000
+ properties:
26001
+ id:
26002
+ type: string
26003
+ minLength: 1
26004
+ maxLength: 64
26005
+ kind:
26006
+ $ref: "#/components/schemas/EvalExpectedSignalKindDto"
26007
+ value:
26008
+ type: string
26009
+ maxLength: 8000
26010
+ description: >
26011
+ Substring for `contains` / `not_contains`, or expected value for
26012
+ `json_path_equals`.
26013
+ pattern:
26014
+ type: string
26015
+ maxLength: 2000
26016
+ description: Regular expression source for `regex`.
26017
+ path:
26018
+ type: string
26019
+ maxLength: 500
26020
+ description: JSONPath expression for `json_path_equals`.
26021
+
26022
+ EvalCaseDto:
26023
+ type: object
26024
+ additionalProperties: false
26025
+ required: [id, name, input, expectedSignals]
26026
+ description: >
26027
+ One golden case in a suite. 1–20 cases per suite; each case requires ≥1
26028
+ expected signal. When `fixtureCompletion` is set, the worker scores that
26029
+ text without calling a live model (CI/demo path).
26030
+ properties:
26031
+ id:
26032
+ type: string
26033
+ minLength: 1
26034
+ maxLength: 64
26035
+ name:
26036
+ type: string
26037
+ minLength: 1
26038
+ maxLength: 200
26039
+ input:
26040
+ type: string
26041
+ minLength: 1
26042
+ maxLength: 20000
26043
+ description: Case input payload (opaque string; often JSON text).
26044
+ fixtureCompletion:
26045
+ type: string
26046
+ maxLength: 100000
26047
+ description: >
26048
+ Optional fixture completion. When present, the worker uses it instead
26049
+ of a live provider call.
26050
+ expectedSignals:
26051
+ type: array
26052
+ minItems: 1
26053
+ maxItems: 20
26054
+ items:
26055
+ $ref: "#/components/schemas/EvalExpectedSignalDto"
26056
+
26057
+ EvalSuiteTargetDto:
26058
+ type: object
26059
+ additionalProperties: false
26060
+ description: >
26061
+ Suite target — at least one of prompt or model. Prompt path requires
26062
+ non-empty `promptBody` (text snapshot) and may include optional `promptKey`
26063
+ slug. Model path requires `provider` + `modelName` (vendor string, same
26064
+ vocabulary as AI Usage `modelName`). Create/update reject when both
26065
+ prompt body is empty and model fields are missing. No separate
26066
+ prompt-template registry in v1; versioning is the suite `version`.
26067
+ properties:
26068
+ promptBody:
26069
+ type: string
26070
+ maxLength: 100000
26071
+ description: Prompt text snapshot. Empty string allowed only when model fields are set.
26072
+ promptKey:
26073
+ type: string
26074
+ maxLength: 120
26075
+ nullable: true
26076
+ description: Optional slug for the prompt (not a registry foreign key in v1).
26077
+ provider:
26078
+ type: string
26079
+ nullable: true
26080
+ enum: [cursor, claude]
26081
+ description: Model provider; null when suite is prompt-only.
26082
+ modelName:
26083
+ type: string
26084
+ maxLength: 200
26085
+ nullable: true
26086
+ description: Vendor model id string (aligned with AI Usage `modelName`).
26087
+
26088
+ EvalSuiteDto:
26089
+ type: object
26090
+ additionalProperties: false
26091
+ required:
26092
+ - id
26093
+ - name
26094
+ - description
26095
+ - version
26096
+ - createdAt
26097
+ - updatedAt
26098
+ - createdByUserId
26099
+ - target
26100
+ - cases
26101
+ description: >
26102
+ Latest version of a workspace eval suite. Max 50 suites per workspace.
26103
+ Name 1–120 chars; description ≤ 2000; version starts at 1.
26104
+ properties:
26105
+ id:
26106
+ type: string
26107
+ format: uuid
26108
+ name:
26109
+ type: string
26110
+ minLength: 1
26111
+ maxLength: 120
26112
+ description:
26113
+ type: string
26114
+ maxLength: 2000
26115
+ version:
26116
+ type: integer
26117
+ minimum: 1
26118
+ description: Monotonic suite version; bumps when target/cases/promptBody change.
26119
+ createdAt:
26120
+ type: string
26121
+ format: date-time
26122
+ updatedAt:
26123
+ type: string
26124
+ format: date-time
26125
+ createdByUserId:
26126
+ type: string
26127
+ format: uuid
26128
+ target:
26129
+ $ref: "#/components/schemas/EvalSuiteTargetDto"
26130
+ cases:
26131
+ type: array
26132
+ minItems: 1
26133
+ maxItems: 20
26134
+ items:
26135
+ $ref: "#/components/schemas/EvalCaseDto"
26136
+
26137
+ EvalSuiteListDto:
26138
+ type: object
26139
+ additionalProperties: false
26140
+ required: [suites]
26141
+ properties:
26142
+ suites:
26143
+ type: array
26144
+ maxItems: 50
26145
+ items:
26146
+ $ref: "#/components/schemas/EvalSuiteDto"
26147
+
26148
+ CreateEvalSuiteBodyDto:
26149
+ type: object
26150
+ additionalProperties: false
26151
+ required: [name, target, cases]
26152
+ properties:
26153
+ name:
26154
+ type: string
26155
+ minLength: 1
26156
+ maxLength: 120
26157
+ description:
26158
+ type: string
26159
+ maxLength: 2000
26160
+ default: ""
26161
+ target:
26162
+ $ref: "#/components/schemas/EvalSuiteTargetDto"
26163
+ cases:
26164
+ type: array
26165
+ minItems: 1
26166
+ maxItems: 20
26167
+ items:
26168
+ $ref: "#/components/schemas/EvalCaseDto"
26169
+
26170
+ UpdateEvalSuiteBodyDto:
26171
+ type: object
26172
+ additionalProperties: false
26173
+ required: [name, target, cases]
26174
+ description: >
26175
+ Full replace of mutable suite fields. Version bumps only when `target`,
26176
+ `cases`, or `promptBody` change versus the stored latest version.
26177
+ properties:
26178
+ name:
26179
+ type: string
26180
+ minLength: 1
26181
+ maxLength: 120
26182
+ description:
26183
+ type: string
26184
+ maxLength: 2000
26185
+ default: ""
26186
+ target:
26187
+ $ref: "#/components/schemas/EvalSuiteTargetDto"
26188
+ cases:
26189
+ type: array
26190
+ minItems: 1
26191
+ maxItems: 20
26192
+ items:
26193
+ $ref: "#/components/schemas/EvalCaseDto"
26194
+
26195
+ EvalRunStatusDto:
26196
+ type: string
26197
+ enum: [queued, running, succeeded, failed, cancelled]
26198
+
26199
+ EvalCaseResultStatusDto:
26200
+ type: string
26201
+ description: >
26202
+ Per-case outcome. `error` is used when completion is unavailable
26203
+ (`code: completion_unavailable`) or another non-score failure occurs.
26204
+ enum: [passed, failed, error]
26205
+
26206
+ EvalCaseResultDto:
26207
+ type: object
26208
+ additionalProperties: false
26209
+ required:
26210
+ - caseId
26211
+ - name
26212
+ - status
26213
+ - pass
26214
+ - failedSignalIds
26215
+ description: >
26216
+ Persisted result for one case. `pass` is true only when `status` is
26217
+ `passed` (all expected signals matched). On signal failure, `pass` is
26218
+ false and `failedSignalIds` lists the failing signal ids. On
26219
+ `completion_unavailable`, `status` is `error` and `code` is set.
26220
+ properties:
26221
+ caseId:
26222
+ type: string
26223
+ name:
26224
+ type: string
26225
+ status:
26226
+ $ref: "#/components/schemas/EvalCaseResultStatusDto"
26227
+ pass:
26228
+ type: boolean
26229
+ failedSignalIds:
26230
+ type: array
26231
+ items:
26232
+ type: string
26233
+ completion:
26234
+ type: string
26235
+ nullable: true
26236
+ description: Completion text used for scoring (fixture or live).
26237
+ inputTokens:
26238
+ type: integer
26239
+ nullable: true
26240
+ minimum: 0
26241
+ outputTokens:
26242
+ type: integer
26243
+ nullable: true
26244
+ minimum: 0
26245
+ costCents:
26246
+ type: number
26247
+ nullable: true
26248
+ minimum: 0
26249
+ description: Provider-reported cost in cents when available.
26250
+ code:
26251
+ type: string
26252
+ nullable: true
26253
+ description: >
26254
+ Machine-readable error when `status` is `error`
26255
+ (e.g. `completion_unavailable`).
26256
+ error:
26257
+ type: string
26258
+ nullable: true
26259
+ description: Human-readable error detail when `status` is `error`.
26260
+
26261
+ EvalSuiteSnapshotDto:
26262
+ type: object
26263
+ additionalProperties: false
26264
+ required: [name, description, version, target, cases]
26265
+ description: >
26266
+ Immutable suite snapshot pinned on a run (`suiteVersion` + JSON). Used so
26267
+ historical runs stay interpretable after later suite edits.
26268
+ properties:
26269
+ name:
26270
+ type: string
26271
+ description:
26272
+ type: string
26273
+ version:
26274
+ type: integer
26275
+ minimum: 1
26276
+ target:
26277
+ $ref: "#/components/schemas/EvalSuiteTargetDto"
26278
+ cases:
26279
+ type: array
26280
+ items:
26281
+ $ref: "#/components/schemas/EvalCaseDto"
26282
+
26283
+ EvalRunDto:
26284
+ type: object
26285
+ additionalProperties: false
26286
+ required:
26287
+ - id
26288
+ - suiteId
26289
+ - suiteVersion
26290
+ - status
26291
+ - startedAt
26292
+ - finishedAt
26293
+ - passCount
26294
+ - failCount
26295
+ - errorCount
26296
+ - score
26297
+ - caseResults
26298
+ description: >
26299
+ Persisted eval run. Suite score = `passedCases / scoredCases` in [0,1]
26300
+ when at least one case was scored; `null` when the run ends with all
26301
+ cases in `error` (status `failed`). List endpoints return at most the
26302
+ last 50 runs per suite.
26303
+ properties:
26304
+ id:
26305
+ type: string
26306
+ format: uuid
26307
+ suiteId:
26308
+ type: string
26309
+ format: uuid
26310
+ suiteVersion:
26311
+ type: integer
26312
+ minimum: 1
26313
+ status:
26314
+ $ref: "#/components/schemas/EvalRunStatusDto"
26315
+ startedAt:
26316
+ type: string
26317
+ format: date-time
26318
+ nullable: true
26319
+ description: Set when the worker claims the run (`running`).
26320
+ finishedAt:
26321
+ type: string
26322
+ format: date-time
26323
+ nullable: true
26324
+ passCount:
26325
+ type: integer
26326
+ minimum: 0
26327
+ failCount:
26328
+ type: integer
26329
+ minimum: 0
26330
+ errorCount:
26331
+ type: integer
26332
+ minimum: 0
26333
+ score:
26334
+ type: number
26335
+ nullable: true
26336
+ minimum: 0
26337
+ maximum: 1
26338
+ description: >
26339
+ `passedCases / scoredCases` in [0,1], or null when no case was scored
26340
+ (all-error run).
26341
+ caseResults:
26342
+ type: array
26343
+ items:
26344
+ $ref: "#/components/schemas/EvalCaseResultDto"
26345
+ suiteSnapshot:
26346
+ type: object
26347
+ nullable: true
26348
+ allOf:
26349
+ - $ref: "#/components/schemas/EvalSuiteSnapshotDto"
26350
+ description: Pinned suite snapshot for this run (present on persisted runs).
26351
+
26352
+ EvalRunListDto:
26353
+ type: object
26354
+ additionalProperties: false
26355
+ required: [runs]
26356
+ properties:
26357
+ runs:
26358
+ type: array
26359
+ maxItems: 50
26360
+ items:
26361
+ $ref: "#/components/schemas/EvalRunDto"
26362
+
26363
+ EvalRunEnqueueResponseDto:
26364
+ type: object
26365
+ additionalProperties: false
26366
+ required: [runId, status]
26367
+ properties:
26368
+ runId:
26369
+ type: string
26370
+ format: uuid
26371
+ status:
26372
+ type: string
26373
+ enum: [queued]
26374
+ description: Always `queued` on enqueue; poll GET run for progress.
26375
+
26376
+ EvalRegressionDto:
26377
+ type: object
26378
+ additionalProperties: false
26379
+ required:
26380
+ - suiteId
26381
+ - suiteVersion
26382
+ - priorScore
26383
+ - currentScore
26384
+ - scoreDrop
26385
+ description: >
26386
+ Regression when prior score − current score ≥ 0.10 on the same
26387
+ suiteId+suiteVersion case set, or suite score drop ≥ 0.10.
26388
+ properties:
26389
+ suiteId:
26390
+ type: string
26391
+ format: uuid
26392
+ suiteName:
26393
+ type: string
26394
+ suiteVersion:
26395
+ type: integer
26396
+ minimum: 1
26397
+ caseId:
26398
+ type: string
26399
+ nullable: true
26400
+ description: Set for case-level regressions; null for suite-level score drops.
26401
+ caseName:
26402
+ type: string
26403
+ nullable: true
26404
+ priorRunId:
26405
+ type: string
26406
+ format: uuid
26407
+ currentRunId:
26408
+ type: string
26409
+ format: uuid
26410
+ priorScore:
26411
+ type: number
26412
+ minimum: 0
26413
+ maximum: 1
26414
+ currentScore:
26415
+ type: number
26416
+ minimum: 0
26417
+ maximum: 1
26418
+ scoreDrop:
26419
+ type: number
26420
+ minimum: 0
26421
+ maximum: 1
26422
+ description: priorScore − currentScore (always ≥ 0.10 for listed items).
26423
+
26424
+ EvalPromptTipDto:
26425
+ type: object
26426
+ additionalProperties: false
26427
+ required: [suiteId, message]
26428
+ description: Tip derived from failed signal notes / case names on recent runs.
26429
+ properties:
26430
+ suiteId:
26431
+ type: string
26432
+ format: uuid
26433
+ suiteName:
26434
+ type: string
26435
+ caseId:
26436
+ type: string
26437
+ nullable: true
26438
+ caseName:
26439
+ type: string
26440
+ nullable: true
26441
+ signalId:
26442
+ type: string
26443
+ nullable: true
26444
+ message:
26445
+ type: string
26446
+ maxLength: 2000
26447
+
26448
+ EvalTokenEfficiencyDto:
26449
+ type: object
26450
+ additionalProperties: false
26451
+ required: [avgInputTokens, avgOutputTokens, avgCostCents]
26452
+ description: >
26453
+ Averages over successful cases in the last succeeded run per suite
26454
+ (workspace rollup). Nullables when token/cost fields were not returned.
26455
+ properties:
26456
+ avgInputTokens:
26457
+ type: number
26458
+ nullable: true
26459
+ minimum: 0
26460
+ avgOutputTokens:
26461
+ type: number
26462
+ nullable: true
26463
+ minimum: 0
26464
+ avgCostCents:
26465
+ type: number
26466
+ nullable: true
26467
+ minimum: 0
26468
+
26469
+ EvalModelComparisonDto:
26470
+ type: object
26471
+ additionalProperties: false
26472
+ required: [provider, modelName, suiteCount, avgScore]
26473
+ properties:
26474
+ provider:
26475
+ $ref: "#/components/schemas/EvalAiProviderDto"
26476
+ modelName:
26477
+ type: string
26478
+ suiteCount:
26479
+ type: integer
26480
+ minimum: 0
26481
+ avgScore:
26482
+ type: number
26483
+ nullable: true
26484
+ minimum: 0
26485
+ maximum: 1
26486
+ description: Average suite score across succeeded runs for this model; null when none.
26487
+
26488
+ EvalInsightsDto:
26489
+ type: object
26490
+ additionalProperties: false
26491
+ required: [regressions, promptTips, tokenEfficiency, modelComparison]
26492
+ description: >
26493
+ Insights hub payload for Prompt & model evals. Empty succeeded-run history
26494
+ → empty arrays and null `tokenEfficiency`.
26495
+ properties:
26496
+ regressions:
26497
+ type: array
26498
+ items:
26499
+ $ref: "#/components/schemas/EvalRegressionDto"
26500
+ promptTips:
26501
+ type: array
26502
+ items:
26503
+ $ref: "#/components/schemas/EvalPromptTipDto"
26504
+ tokenEfficiency:
26505
+ type: object
26506
+ nullable: true
26507
+ allOf:
26508
+ - $ref: "#/components/schemas/EvalTokenEfficiencyDto"
26509
+ modelComparison:
26510
+ type: array
26511
+ items:
26512
+ $ref: "#/components/schemas/EvalModelComparisonDto"