@kindgi/api 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +2 -1
- package/dist/app.js.map +1 -1
- package/dist/cost-binding.d.ts +81 -5
- package/dist/cost-binding.d.ts.map +1 -1
- package/dist/cost-binding.js +6 -0
- package/dist/cost-binding.js.map +1 -1
- package/dist/hitl-binding.d.ts +20 -5
- package/dist/hitl-binding.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/middleware/auth.d.ts +3 -2
- package/dist/middleware/auth.d.ts.map +1 -1
- package/dist/middleware/auth.js.map +1 -1
- package/dist/middleware/idempotency.d.ts +5 -1
- package/dist/middleware/idempotency.d.ts.map +1 -1
- package/dist/middleware/idempotency.js +8 -1
- package/dist/middleware/idempotency.js.map +1 -1
- package/dist/openapi/operations.d.ts.map +1 -1
- package/dist/openapi/operations.js +83 -18
- package/dist/openapi/operations.js.map +1 -1
- package/dist/openapi/schemas.d.ts +18 -0
- package/dist/openapi/schemas.d.ts.map +1 -1
- package/dist/openapi/schemas.js +202 -7
- package/dist/openapi/schemas.js.map +1 -1
- package/dist/provenance-binding.d.ts +27 -1
- package/dist/provenance-binding.d.ts.map +1 -1
- package/dist/provenance-binding.js.map +1 -1
- package/dist/reviewer-binding.d.ts +10 -2
- package/dist/reviewer-binding.d.ts.map +1 -1
- package/dist/reviewer-role.d.ts +13 -0
- package/dist/reviewer-role.d.ts.map +1 -0
- package/dist/reviewer-role.js +27 -0
- package/dist/reviewer-role.js.map +1 -0
- package/dist/routes/approvals.d.ts +5 -4
- package/dist/routes/approvals.d.ts.map +1 -1
- package/dist/routes/approvals.js +52 -16
- package/dist/routes/approvals.js.map +1 -1
- package/dist/routes/conversations.d.ts +7 -1
- package/dist/routes/conversations.d.ts.map +1 -1
- package/dist/routes/conversations.js +41 -1
- package/dist/routes/conversations.js.map +1 -1
- package/dist/routes/cost.d.ts.map +1 -1
- package/dist/routes/cost.js +95 -9
- package/dist/routes/cost.js.map +1 -1
- package/dist/routes/identity.d.ts +7 -0
- package/dist/routes/identity.d.ts.map +1 -1
- package/dist/routes/identity.js +3 -2
- package/dist/routes/identity.js.map +1 -1
- package/dist/routes/provenance.d.ts.map +1 -1
- package/dist/routes/provenance.js +32 -1
- package/dist/routes/provenance.js.map +1 -1
- package/dist/routes/runs.d.ts +0 -7
- package/dist/routes/runs.d.ts.map +1 -1
- package/dist/routes/runs.js +44 -20
- package/dist/routes/runs.js.map +1 -1
- package/dist/routes/scope-params.d.ts +16 -1
- package/dist/routes/scope-params.d.ts.map +1 -1
- package/dist/routes/scope-params.js +28 -0
- package/dist/routes/scope-params.js.map +1 -1
- package/dist/routes/sse.d.ts +2 -2
- package/dist/routes/sse.js +1 -1
- package/dist/types.d.ts +4 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/webhook-endpoint-binding.d.ts +11 -0
- package/dist/webhook-endpoint-binding.d.ts.map +1 -1
- package/dist/webhook-endpoint-binding.js.map +1 -1
- package/openapi.json +599 -24
- package/package.json +24 -24
- package/src/app.ts +5 -1
- package/src/cost-binding.ts +96 -5
- package/src/hitl-binding.ts +20 -4
- package/src/index.ts +3 -0
- package/src/middleware/auth.ts +3 -2
- package/src/middleware/idempotency.ts +7 -1
- package/src/openapi/operations.ts +93 -18
- package/src/openapi/schemas.ts +221 -7
- package/src/provenance-binding.ts +42 -1
- package/src/reviewer-binding.ts +10 -2
- package/src/reviewer-role.ts +35 -0
- package/src/routes/approvals.ts +70 -19
- package/src/routes/conversations.ts +57 -1
- package/src/routes/cost.ts +104 -20
- package/src/routes/identity.ts +10 -2
- package/src/routes/provenance.ts +48 -1
- package/src/routes/runs.ts +54 -22
- package/src/routes/scope-params.ts +35 -1
- package/src/routes/sse.ts +2 -2
- package/src/types.ts +4 -3
- package/src/webhook-endpoint-binding.ts +11 -0
package/src/openapi/schemas.ts
CHANGED
|
@@ -128,6 +128,23 @@ export const RunStatusSchema: JsonSchema = {
|
|
|
128
128
|
enum: ['pending', 'running', 'suspended', 'completed', 'failed', 'cancelled'],
|
|
129
129
|
};
|
|
130
130
|
|
|
131
|
+
/**
|
|
132
|
+
* The agent a run is a turn of. A component of its own, so generated
|
|
133
|
+
* clients name it `RunAgent` (not after the `agent` property).
|
|
134
|
+
*/
|
|
135
|
+
export const RunAgentSchema: JsonSchema = {
|
|
136
|
+
type: 'object',
|
|
137
|
+
additionalProperties: false,
|
|
138
|
+
required: ['id', 'version', 'conversationId'],
|
|
139
|
+
description:
|
|
140
|
+
"Set on an agent's turn (an agent run, or the turn a flow's agent step started): the agent, the version that ran and the conversation. Absent on other runs, and on turns that ran before Kindgi 0.1.3.",
|
|
141
|
+
properties: {
|
|
142
|
+
id: { type: 'string', description: 'The agent id.' },
|
|
143
|
+
version: { type: 'string', description: 'The agent version that ran (semver).' },
|
|
144
|
+
conversationId: { type: 'string', format: 'uuid' },
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
|
|
131
148
|
export const RunSchema: JsonSchema = {
|
|
132
149
|
type: 'object',
|
|
133
150
|
additionalProperties: false,
|
|
@@ -167,6 +184,7 @@ export const RunSchema: JsonSchema = {
|
|
|
167
184
|
type: 'string',
|
|
168
185
|
description: 'Set on a child run: the node in the parent run that started it.',
|
|
169
186
|
},
|
|
187
|
+
agent: { $ref: '#/components/schemas/RunAgent' },
|
|
170
188
|
publicAccessToken: {
|
|
171
189
|
type: 'string',
|
|
172
190
|
description:
|
|
@@ -557,6 +575,29 @@ export const ApprovalSchema: JsonSchema = {
|
|
|
557
575
|
updatedAt: { type: 'string', format: 'date-time' },
|
|
558
576
|
decidedAt: { type: 'string', format: 'date-time' },
|
|
559
577
|
expiresAt: { type: 'string', format: 'date-time' },
|
|
578
|
+
decision: {
|
|
579
|
+
description:
|
|
580
|
+
"The reviewer's decision, once one is recorded. Absent while the approval is open, and when it ended without one (it expired, or a timeout escalated it).",
|
|
581
|
+
$ref: '#/components/schemas/ApprovalDecisionRecord',
|
|
582
|
+
},
|
|
583
|
+
},
|
|
584
|
+
};
|
|
585
|
+
|
|
586
|
+
export const ApprovalDecisionRecordSchema: JsonSchema = {
|
|
587
|
+
type: 'object',
|
|
588
|
+
additionalProperties: false,
|
|
589
|
+
required: ['decision', 'reviewerId', 'reviewerRoleAtDecision', 'decidedAt'],
|
|
590
|
+
properties: {
|
|
591
|
+
decision: ReviewDecisionKindSchema,
|
|
592
|
+
decidedBy: {
|
|
593
|
+
type: 'string',
|
|
594
|
+
description:
|
|
595
|
+
"Who decided, as an actor: `user:<userId>`, the reviewer's user. The run's journal and provenance name the decider the same way. The Kindgi runtime always records it; a deployment whose HITL binding doesn't leaves it out.",
|
|
596
|
+
},
|
|
597
|
+
reviewerId: { type: 'string', format: 'uuid' },
|
|
598
|
+
reviewerRoleAtDecision: ReviewerRoleSchema,
|
|
599
|
+
decidedAt: { type: 'string', format: 'date-time' },
|
|
600
|
+
rationale: { type: 'string' },
|
|
560
601
|
},
|
|
561
602
|
};
|
|
562
603
|
|
|
@@ -599,7 +640,7 @@ export const CompleteApprovalBodySchema: JsonSchema = {
|
|
|
599
640
|
rationale: { type: 'string' },
|
|
600
641
|
value: {
|
|
601
642
|
description:
|
|
602
|
-
|
|
643
|
+
"Payload passed to the run waitpoint (`RunBinding.completeToken`) when the approval is linked to a suspended run and the decision is `approve` or `reject`. Refused (400 `bad-input`) for an agent's tool-call or session gate (`tool-call:pending`, `agent-turn:session-hitl-gate`): those resume on the decision alone.",
|
|
603
644
|
},
|
|
604
645
|
},
|
|
605
646
|
};
|
|
@@ -1652,6 +1693,12 @@ export const ConversationSchema: JsonSchema = {
|
|
|
1652
1693
|
agentVersion: { type: 'string', description: 'Semver.' },
|
|
1653
1694
|
title: { type: 'string' },
|
|
1654
1695
|
participantId: { type: 'string' },
|
|
1696
|
+
projectId: {
|
|
1697
|
+
type: 'string',
|
|
1698
|
+
format: 'uuid',
|
|
1699
|
+
description:
|
|
1700
|
+
"The project the conversation is in: the project of the run that opened it, or `projectId` on open (the tenant's Default project when omitted). Absent on conversations from before Kindgi 0.1.3; those are listed only without a scope.",
|
|
1701
|
+
},
|
|
1655
1702
|
scope: {
|
|
1656
1703
|
type: 'object',
|
|
1657
1704
|
additionalProperties: true,
|
|
@@ -1706,6 +1753,12 @@ export const OpenConversationBodySchema: JsonSchema = {
|
|
|
1706
1753
|
type: 'string',
|
|
1707
1754
|
description: 'Optional. Defaults to `"Untitled conversation"` when omitted.',
|
|
1708
1755
|
},
|
|
1756
|
+
projectId: {
|
|
1757
|
+
type: 'string',
|
|
1758
|
+
format: 'uuid',
|
|
1759
|
+
description:
|
|
1760
|
+
"The project the conversation is in; `GET /v1/conversations?scopeKind=project&scopeId=…` lists it. A project of the caller's tenant, else `400 bad-input`. Omitted: the tenant's Default project, as for a run.",
|
|
1761
|
+
},
|
|
1709
1762
|
scope: {
|
|
1710
1763
|
type: 'object',
|
|
1711
1764
|
additionalProperties: true,
|
|
@@ -2483,6 +2536,12 @@ export const ProvenanceRecordMetadataSchema: JsonSchema = {
|
|
|
2483
2536
|
'True when the emission-time signature is present. Independent of whether the export route can produce a signed bundle.',
|
|
2484
2537
|
},
|
|
2485
2538
|
createdAt: { type: 'string', format: 'date-time' },
|
|
2539
|
+
projectId: {
|
|
2540
|
+
type: 'string',
|
|
2541
|
+
format: 'uuid',
|
|
2542
|
+
description:
|
|
2543
|
+
"The project of the record's run. Absent on records from before Kindgi 0.1.3; those are listed only without a scope.",
|
|
2544
|
+
},
|
|
2486
2545
|
},
|
|
2487
2546
|
};
|
|
2488
2547
|
|
|
@@ -2508,6 +2567,22 @@ export const ProvenanceRecordSchema: JsonSchema = {
|
|
|
2508
2567
|
},
|
|
2509
2568
|
signature: ProvenanceSignatureSchema,
|
|
2510
2569
|
createdAt: { type: 'string', format: 'date-time' },
|
|
2570
|
+
callUsage: {
|
|
2571
|
+
type: 'object',
|
|
2572
|
+
description:
|
|
2573
|
+
"Each model call's usage from the cost ledger, by the `callId` in its `model-call` node's attributes. Joined when read: not part of the signed DAG. A signed export includes it, as it stood when signed.",
|
|
2574
|
+
additionalProperties: {
|
|
2575
|
+
type: 'object',
|
|
2576
|
+
additionalProperties: false,
|
|
2577
|
+
required: ['usage'],
|
|
2578
|
+
properties: {
|
|
2579
|
+
usage: { $ref: '#/components/schemas/ModelCallTokens' },
|
|
2580
|
+
costUsd: { type: 'number', minimum: 0 },
|
|
2581
|
+
durationMs: { type: 'integer', minimum: 0 },
|
|
2582
|
+
servedModel: { type: 'string' },
|
|
2583
|
+
},
|
|
2584
|
+
},
|
|
2585
|
+
},
|
|
2511
2586
|
},
|
|
2512
2587
|
};
|
|
2513
2588
|
|
|
@@ -2544,7 +2619,7 @@ export const ExportProvenanceBodySchema: JsonSchema = {
|
|
|
2544
2619
|
|
|
2545
2620
|
export const ExportProvenanceResultSchema: JsonSchema = {
|
|
2546
2621
|
description:
|
|
2547
|
-
'Signed exportable bundle. `bundle` is base64 of the exact bytes that were signed (sorted-key canonical JSON, no whitespace); verifiers can pass those bytes directly to `verifyEd25519`. The bundle body itself includes `bundleSchemaVersion`, `runId`, `tenantId`, `dag: { nodes, edges }`, `messages?` (if requested), etc. See `canonicalization` for the deterministic serialization algorithm.',
|
|
2622
|
+
'Signed exportable bundle. `bundle` is base64 of the exact bytes that were signed (sorted-key canonical JSON, no whitespace); verifiers can pass those bytes directly to `verifyEd25519`. The bundle body itself includes `bundleSchemaVersion`, `runId`, `tenantId`, `dag: { nodes, edges }`, `messages?` (if requested), `callUsage?` (the usage of the model calls, from the cost ledger), etc. See `canonicalization` for the deterministic serialization algorithm.',
|
|
2548
2623
|
type: 'object',
|
|
2549
2624
|
additionalProperties: false,
|
|
2550
2625
|
required: [
|
|
@@ -2566,7 +2641,8 @@ export const ExportProvenanceResultSchema: JsonSchema = {
|
|
|
2566
2641
|
},
|
|
2567
2642
|
bundleSchemaVersion: {
|
|
2568
2643
|
type: 'string',
|
|
2569
|
-
description:
|
|
2644
|
+
description:
|
|
2645
|
+
"Semver for the shape of the bundle body. Currently `1.1.0`, which adds `callUsage`: each model call's usage from the cost ledger, by call id, as it stood when signed.",
|
|
2570
2646
|
},
|
|
2571
2647
|
algorithm: { type: 'string', const: 'ed25519' },
|
|
2572
2648
|
signingKeyId: { type: 'string' },
|
|
@@ -3243,7 +3319,65 @@ export const GetMCPPromptResultSchema: JsonSchema = {
|
|
|
3243
3319
|
*/
|
|
3244
3320
|
export const CostGroupDimensionSchema: JsonSchema = {
|
|
3245
3321
|
type: 'string',
|
|
3246
|
-
enum: [
|
|
3322
|
+
enum: [
|
|
3323
|
+
'agentId',
|
|
3324
|
+
'runId',
|
|
3325
|
+
'category',
|
|
3326
|
+
'providerId',
|
|
3327
|
+
'day',
|
|
3328
|
+
'month',
|
|
3329
|
+
'tenant',
|
|
3330
|
+
'conversationId',
|
|
3331
|
+
'model',
|
|
3332
|
+
'servedModel',
|
|
3333
|
+
'projectId',
|
|
3334
|
+
'orgId',
|
|
3335
|
+
'rootRunId',
|
|
3336
|
+
'flowId',
|
|
3337
|
+
],
|
|
3338
|
+
};
|
|
3339
|
+
|
|
3340
|
+
/** Why a model call failed, as its cost record carries it. */
|
|
3341
|
+
export const ModelCallErrorSchema: JsonSchema = {
|
|
3342
|
+
type: 'object',
|
|
3343
|
+
additionalProperties: false,
|
|
3344
|
+
required: ['message'],
|
|
3345
|
+
description: 'Why a model call failed (`status: failed`).',
|
|
3346
|
+
properties: { message: { type: 'string' } },
|
|
3347
|
+
};
|
|
3348
|
+
|
|
3349
|
+
/** A model call's tokens, as a cost record and a provenance record carry them. */
|
|
3350
|
+
export const ModelCallTokensSchema: JsonSchema = {
|
|
3351
|
+
type: 'object',
|
|
3352
|
+
additionalProperties: false,
|
|
3353
|
+
required: ['promptTokens', 'completionTokens'],
|
|
3354
|
+
description:
|
|
3355
|
+
"The call's tokens. `promptTokens` / `completionTokens` are the totals; `cacheReadTokens` / `cacheWriteTokens` are parts of `promptTokens`, `reasoningTokens` of `completionTokens`, present when the provider reports them.",
|
|
3356
|
+
properties: {
|
|
3357
|
+
promptTokens: { type: 'integer', minimum: 0 },
|
|
3358
|
+
completionTokens: { type: 'integer', minimum: 0 },
|
|
3359
|
+
cacheReadTokens: { type: 'integer', minimum: 0 },
|
|
3360
|
+
cacheWriteTokens: { type: 'integer', minimum: 0 },
|
|
3361
|
+
reasoningTokens: { type: 'integer', minimum: 0 },
|
|
3362
|
+
},
|
|
3363
|
+
};
|
|
3364
|
+
|
|
3365
|
+
/**
|
|
3366
|
+
* Token sums of an aggregate. `prompt` / `completion` are the totals;
|
|
3367
|
+
* `cacheRead` / `cacheWrite` are parts of `prompt`, `reasoning` of
|
|
3368
|
+
* `completion` (`0` where providers didn't report them).
|
|
3369
|
+
*/
|
|
3370
|
+
export const CostTokenTotalsSchema: JsonSchema = {
|
|
3371
|
+
type: 'object',
|
|
3372
|
+
additionalProperties: false,
|
|
3373
|
+
required: ['prompt', 'completion', 'cacheRead', 'cacheWrite', 'reasoning'],
|
|
3374
|
+
properties: {
|
|
3375
|
+
prompt: { type: 'integer', minimum: 0 },
|
|
3376
|
+
completion: { type: 'integer', minimum: 0 },
|
|
3377
|
+
cacheRead: { type: 'integer', minimum: 0 },
|
|
3378
|
+
cacheWrite: { type: 'integer', minimum: 0 },
|
|
3379
|
+
reasoning: { type: 'integer', minimum: 0 },
|
|
3380
|
+
},
|
|
3247
3381
|
};
|
|
3248
3382
|
|
|
3249
3383
|
/**
|
|
@@ -3283,6 +3417,63 @@ export const CostRecordSchema: JsonSchema = {
|
|
|
3283
3417
|
additionalProperties: true,
|
|
3284
3418
|
description: 'Free-form filter/display tags — never counters.',
|
|
3285
3419
|
},
|
|
3420
|
+
callId: {
|
|
3421
|
+
type: 'string',
|
|
3422
|
+
description:
|
|
3423
|
+
"A model call's id (`category` `llm.inference`); its provenance `model-call` node carries it too.",
|
|
3424
|
+
},
|
|
3425
|
+
projectId: { type: 'string', format: 'uuid' },
|
|
3426
|
+
rootRunId: {
|
|
3427
|
+
type: 'string',
|
|
3428
|
+
format: 'uuid',
|
|
3429
|
+
description: "The root of the record's run tree (a flow run, for its agent turns).",
|
|
3430
|
+
},
|
|
3431
|
+
parentRunId: { type: 'string', format: 'uuid' },
|
|
3432
|
+
agentVersion: { type: 'string' },
|
|
3433
|
+
flowId: { type: 'string', description: "The flow of the run tree's root." },
|
|
3434
|
+
nodeId: { type: 'string', description: 'The step that made the call.' },
|
|
3435
|
+
step: { type: 'integer', minimum: 1, description: "The turn's step number." },
|
|
3436
|
+
purpose: {
|
|
3437
|
+
type: 'string',
|
|
3438
|
+
description:
|
|
3439
|
+
"What the call was for, beyond the turn's own model step: `guardrail-judge:<guardrail id>`.",
|
|
3440
|
+
},
|
|
3441
|
+
model: { type: 'string', description: 'The model actually called.' },
|
|
3442
|
+
servedModel: {
|
|
3443
|
+
type: 'string',
|
|
3444
|
+
description: 'The exact model version the vendor reported (vendors alias).',
|
|
3445
|
+
},
|
|
3446
|
+
fallback: {
|
|
3447
|
+
type: 'boolean',
|
|
3448
|
+
description: 'The router picked a fallback provider for the turn.',
|
|
3449
|
+
},
|
|
3450
|
+
status: {
|
|
3451
|
+
type: 'string',
|
|
3452
|
+
enum: ['ok', 'failed'],
|
|
3453
|
+
description: '`ok`: the provider answered. `failed`: the call threw.',
|
|
3454
|
+
},
|
|
3455
|
+
usage: { $ref: '#/components/schemas/ModelCallTokens' },
|
|
3456
|
+
durationMs: { type: 'integer', minimum: 0 },
|
|
3457
|
+
finishReason: { type: 'string' },
|
|
3458
|
+
providerRequestId: { type: 'string', description: "The vendor's id for the request." },
|
|
3459
|
+
attempts: {
|
|
3460
|
+
type: 'integer',
|
|
3461
|
+
minimum: 1,
|
|
3462
|
+
description: "HTTP attempts the call took, the client's retries included.",
|
|
3463
|
+
},
|
|
3464
|
+
error: { $ref: '#/components/schemas/ModelCallError' },
|
|
3465
|
+
rawUsage: {
|
|
3466
|
+
type: 'object',
|
|
3467
|
+
additionalProperties: false,
|
|
3468
|
+
required: ['provider', 'model', 'usage'],
|
|
3469
|
+
description:
|
|
3470
|
+
"The vendor's own usage object, exactly as it reported it. Only with `include=rawUsage`.",
|
|
3471
|
+
properties: {
|
|
3472
|
+
provider: { type: 'string' },
|
|
3473
|
+
model: { type: 'string' },
|
|
3474
|
+
usage: { type: 'object', additionalProperties: true },
|
|
3475
|
+
},
|
|
3476
|
+
},
|
|
3286
3477
|
},
|
|
3287
3478
|
};
|
|
3288
3479
|
|
|
@@ -3303,7 +3494,7 @@ export const CostRecordCollectionPageSchema: JsonSchema = {
|
|
|
3303
3494
|
export const CostAggregateGroupSchema: JsonSchema = {
|
|
3304
3495
|
type: 'object',
|
|
3305
3496
|
additionalProperties: false,
|
|
3306
|
-
required: ['key', 'count', 'totalUsd'],
|
|
3497
|
+
required: ['key', 'count', 'totalUsd', 'tokens'],
|
|
3307
3498
|
properties: {
|
|
3308
3499
|
key: {
|
|
3309
3500
|
type: 'object',
|
|
@@ -3313,13 +3504,14 @@ export const CostAggregateGroupSchema: JsonSchema = {
|
|
|
3313
3504
|
},
|
|
3314
3505
|
count: { type: 'integer', minimum: 0 },
|
|
3315
3506
|
totalUsd: { type: 'number', minimum: 0 },
|
|
3507
|
+
tokens: { $ref: '#/components/schemas/CostTokenTotals' },
|
|
3316
3508
|
},
|
|
3317
3509
|
};
|
|
3318
3510
|
|
|
3319
3511
|
export const CostAggregateResultSchema: JsonSchema = {
|
|
3320
3512
|
type: 'object',
|
|
3321
3513
|
additionalProperties: false,
|
|
3322
|
-
required: ['groups', 'totalUsd', 'totalRecords', 'timeRange', 'groupBy'],
|
|
3514
|
+
required: ['groups', 'totalUsd', 'totalRecords', 'tokens', 'timeRange', 'groupBy'],
|
|
3323
3515
|
properties: {
|
|
3324
3516
|
groups: {
|
|
3325
3517
|
type: 'array',
|
|
@@ -3327,6 +3519,7 @@ export const CostAggregateResultSchema: JsonSchema = {
|
|
|
3327
3519
|
},
|
|
3328
3520
|
totalUsd: { type: 'number', minimum: 0 },
|
|
3329
3521
|
totalRecords: { type: 'integer', minimum: 0 },
|
|
3522
|
+
tokens: { $ref: '#/components/schemas/CostTokenTotals' },
|
|
3330
3523
|
timeRange: {
|
|
3331
3524
|
type: 'object',
|
|
3332
3525
|
additionalProperties: false,
|
|
@@ -3980,7 +4173,7 @@ export const LogoutResultSchema: JsonSchema = {
|
|
|
3980
4173
|
|
|
3981
4174
|
export const WhoamiResultSchema: JsonSchema = {
|
|
3982
4175
|
description:
|
|
3983
|
-
"Introspection of the caller's current authentication context. Always carries `tenantId` and `scopes` (empty for static bearer tokens), plus `userId` when the token carries one; session-token callers additionally see `sessionId`, `providerId`, and `expiresAt`. `user` is the caller's directory record, present when the deployment wires an identity directory and it knows the `userId`. `reviewerRole` is set when the token carries a reviewer role — clients can
|
|
4176
|
+
"Introspection of the caller's current authentication context. Always carries `tenantId` and `scopes` (empty for static bearer tokens), plus `userId` when the token carries one; session-token callers additionally see `sessionId`, `providerId`, and `expiresAt`. `user` is the caller's directory record, present when the deployment wires an identity directory and it knows the `userId`. `reviewerRole` is set when the caller is a reviewer — its token carries a reviewer role, or its user is a registered reviewer — so clients can gate reviewer-only UI (the approvals surface) without a second round trip.",
|
|
3984
4177
|
type: 'object',
|
|
3985
4178
|
additionalProperties: false,
|
|
3986
4179
|
required: ['tenantId', 'scopes'],
|
|
@@ -5844,6 +6037,20 @@ export const WebhookEndpointUnregisterResultSchema: JsonSchema = {
|
|
|
5844
6037
|
},
|
|
5845
6038
|
};
|
|
5846
6039
|
|
|
6040
|
+
/** A run tree's model calls, as `run.finished` carries them. */
|
|
6041
|
+
export const RunTreeUsageSchema: JsonSchema = {
|
|
6042
|
+
type: 'object',
|
|
6043
|
+
additionalProperties: false,
|
|
6044
|
+
required: ['calls', 'costUsd', 'tokens'],
|
|
6045
|
+
description:
|
|
6046
|
+
"The model calls of the run tree (this run and every run it started) that the cost ledger had recorded when this run finished: a child run still running then isn't in it. `calls` counts failed calls too. Absent when the runtime records no usage.",
|
|
6047
|
+
properties: {
|
|
6048
|
+
calls: { type: 'integer', minimum: 0 },
|
|
6049
|
+
costUsd: { type: 'number', minimum: 0 },
|
|
6050
|
+
tokens: { $ref: '#/components/schemas/CostTokenTotals' },
|
|
6051
|
+
},
|
|
6052
|
+
};
|
|
6053
|
+
|
|
5847
6054
|
export const FinishedRunSchema: JsonSchema = {
|
|
5848
6055
|
type: 'object',
|
|
5849
6056
|
additionalProperties: false,
|
|
@@ -5873,6 +6080,7 @@ export const FinishedRunSchema: JsonSchema = {
|
|
|
5873
6080
|
},
|
|
5874
6081
|
createdAt: { type: 'string', format: 'date-time' },
|
|
5875
6082
|
completedAt: { type: 'string', format: 'date-time' },
|
|
6083
|
+
usage: { $ref: '#/components/schemas/RunTreeUsage' },
|
|
5876
6084
|
},
|
|
5877
6085
|
};
|
|
5878
6086
|
|
|
@@ -6020,6 +6228,7 @@ export const COMPONENT_SCHEMAS: ReadonlyArray<readonly [string, JsonSchema]> = [
|
|
|
6020
6228
|
['WireError', WireErrorSchema],
|
|
6021
6229
|
['HealthResult', HealthResultSchema],
|
|
6022
6230
|
['RunStatus', RunStatusSchema],
|
|
6231
|
+
['RunAgent', RunAgentSchema],
|
|
6023
6232
|
['Run', RunSchema],
|
|
6024
6233
|
['StartRunOptions', StartRunOptionsSchema],
|
|
6025
6234
|
['StartRunBody', StartRunBodySchema],
|
|
@@ -6047,6 +6256,7 @@ export const COMPONENT_SCHEMAS: ReadonlyArray<readonly [string, JsonSchema]> = [
|
|
|
6047
6256
|
['ApprovalStatus', ApprovalStatusSchema],
|
|
6048
6257
|
['ReviewDecisionKind', ReviewDecisionKindSchema],
|
|
6049
6258
|
['Approval', ApprovalSchema],
|
|
6259
|
+
['ApprovalDecisionRecord', ApprovalDecisionRecordSchema],
|
|
6050
6260
|
['ReviewDecision', ReviewDecisionSchema],
|
|
6051
6261
|
['ApprovalCollectionPage', ApprovalCollectionPageSchema],
|
|
6052
6262
|
['CompleteApprovalBody', CompleteApprovalBodySchema],
|
|
@@ -6190,6 +6400,9 @@ export const COMPONENT_SCHEMAS: ReadonlyArray<readonly [string, JsonSchema]> = [
|
|
|
6190
6400
|
['GetMCPPromptResult', GetMCPPromptResultSchema],
|
|
6191
6401
|
['CostGroupDimension', CostGroupDimensionSchema],
|
|
6192
6402
|
['CostRecord', CostRecordSchema],
|
|
6403
|
+
['ModelCallTokens', ModelCallTokensSchema],
|
|
6404
|
+
['ModelCallError', ModelCallErrorSchema],
|
|
6405
|
+
['CostTokenTotals', CostTokenTotalsSchema],
|
|
6193
6406
|
['CostRecordCollectionPage', CostRecordCollectionPageSchema],
|
|
6194
6407
|
['CostAggregateGroup', CostAggregateGroupSchema],
|
|
6195
6408
|
['CostAggregateResult', CostAggregateResultSchema],
|
|
@@ -6348,6 +6561,7 @@ export const COMPONENT_SCHEMAS: ReadonlyArray<readonly [string, JsonSchema]> = [
|
|
|
6348
6561
|
['CreateWebhookEndpointBody', CreateWebhookEndpointBodySchema],
|
|
6349
6562
|
['PatchWebhookEndpointBody', PatchWebhookEndpointBodySchema],
|
|
6350
6563
|
['WebhookEndpointUnregisterResult', WebhookEndpointUnregisterResultSchema],
|
|
6564
|
+
['RunTreeUsage', RunTreeUsageSchema],
|
|
6351
6565
|
['FinishedRun', FinishedRunSchema],
|
|
6352
6566
|
['RunFinishedEvent', RunFinishedEventSchema],
|
|
6353
6567
|
['WebhookTestEvent', WebhookTestEventSchema],
|
|
@@ -8,7 +8,16 @@
|
|
|
8
8
|
// touches provenance storage directly.
|
|
9
9
|
//
|
|
10
10
|
|
|
11
|
-
import type {
|
|
11
|
+
import type {
|
|
12
|
+
FlowId,
|
|
13
|
+
ListScope,
|
|
14
|
+
ProjectId,
|
|
15
|
+
ProvenanceId,
|
|
16
|
+
Result,
|
|
17
|
+
RunId,
|
|
18
|
+
TenantId,
|
|
19
|
+
Timestamp,
|
|
20
|
+
} from '@kindgi/types';
|
|
12
21
|
|
|
13
22
|
// ---------- domain type surface ----------
|
|
14
23
|
|
|
@@ -98,6 +107,8 @@ export interface ProvenanceListCursor {
|
|
|
98
107
|
export interface ListProvenanceRecordsInput {
|
|
99
108
|
readonly tenantId: TenantId;
|
|
100
109
|
readonly limit: number;
|
|
110
|
+
/** Only one project's records, or every project's in an org. Absent: the tenant's. */
|
|
111
|
+
readonly scope?: ListScope;
|
|
101
112
|
readonly runId?: RunId;
|
|
102
113
|
readonly agentId?: string;
|
|
103
114
|
readonly createdAfter?: Date;
|
|
@@ -117,6 +128,8 @@ export interface ProvenanceRecordSummary {
|
|
|
117
128
|
readonly createdAt: Timestamp;
|
|
118
129
|
readonly flowRef?: { readonly id: FlowId; readonly version: string };
|
|
119
130
|
readonly signed: boolean;
|
|
131
|
+
/** The project of the record's run; absent on records from before it was stored. */
|
|
132
|
+
readonly projectId?: ProjectId;
|
|
120
133
|
}
|
|
121
134
|
|
|
122
135
|
export interface ListProvenanceRecordsResult {
|
|
@@ -166,4 +179,32 @@ export interface ProvenanceBinding {
|
|
|
166
179
|
* tenant/run pair.
|
|
167
180
|
*/
|
|
168
181
|
getByRunId(tenantId: TenantId, runId: RunId): Promise<Result<Provenance, ProvenanceBindingError>>;
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* The cost ledger's usage of each model call in the run's provenance,
|
|
185
|
+
* by the `callId` in its `model-call` node's attributes. Optional: a
|
|
186
|
+
* deployment without a cost ledger omits it. The routes add it to a
|
|
187
|
+
* read as `callUsage`, outside the signed DAG; a signed export
|
|
188
|
+
* includes it as it stood when signed.
|
|
189
|
+
*/
|
|
190
|
+
getCallUsage?(
|
|
191
|
+
tenantId: TenantId,
|
|
192
|
+
runId: RunId,
|
|
193
|
+
): Promise<Result<CallUsageByCallId, ProvenanceBindingError>>;
|
|
169
194
|
}
|
|
195
|
+
|
|
196
|
+
/** One model call's usage, as the cost ledger has it. */
|
|
197
|
+
export interface CallUsage {
|
|
198
|
+
readonly usage: {
|
|
199
|
+
readonly promptTokens: number;
|
|
200
|
+
readonly completionTokens: number;
|
|
201
|
+
readonly cacheReadTokens?: number;
|
|
202
|
+
readonly cacheWriteTokens?: number;
|
|
203
|
+
readonly reasoningTokens?: number;
|
|
204
|
+
};
|
|
205
|
+
readonly costUsd?: number;
|
|
206
|
+
readonly durationMs?: number;
|
|
207
|
+
readonly servedModel?: string;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export type CallUsageByCallId = Readonly<Record<string, CallUsage>>;
|
package/src/reviewer-binding.ts
CHANGED
|
@@ -6,16 +6,24 @@ import type { Cursor, ReviewerId, TenantId, Timestamp, UserId } from '@kindgi/ty
|
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Translates the bearer-token identity (`UserId`) into the `ReviewerId`
|
|
9
|
-
* that `HitlBinding.submitReview` needs
|
|
9
|
+
* that `HitlBinding.submitReview` needs, and the reviewer role the
|
|
10
|
+
* approvals surface is scoped by. The API package intentionally does
|
|
10
11
|
* NOT own the `user ↔ reviewer` mapping — deployments plug that in via
|
|
11
12
|
* this binding, same pattern as `TokenResolver` (for auth read) and
|
|
12
13
|
* `TokenAdmin` (for mint/revoke).
|
|
13
14
|
*
|
|
14
|
-
*
|
|
15
|
+
* Both return `null` when the user has no active reviewer row for the
|
|
15
16
|
* tenant (leads to `403 permission-denied` from the approvals route).
|
|
16
17
|
*/
|
|
17
18
|
export interface ReviewerBinding {
|
|
18
19
|
resolveReviewer(input: ReviewerLookupInput): Promise<ReviewerId | null>;
|
|
20
|
+
/**
|
|
21
|
+
* The user's reviewer role in the tenant. Consulted for a token that
|
|
22
|
+
* carries no `reviewerRole` of its own (a session or API key of a
|
|
23
|
+
* registered reviewer), so the roster, not the token, says who reviews.
|
|
24
|
+
* A binding without it: only a token that carries its role reviews.
|
|
25
|
+
*/
|
|
26
|
+
resolveReviewerRole?(input: ReviewerLookupInput): Promise<ReviewerRole | null>;
|
|
19
27
|
}
|
|
20
28
|
|
|
21
29
|
export interface ReviewerLookupInput {
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (C) 2026 Kindgi Inc.
|
|
3
|
+
|
|
4
|
+
import type { ReviewerRole } from '@kindgi/authz';
|
|
5
|
+
import type { TenantId, UserId } from '@kindgi/types';
|
|
6
|
+
import type { Context } from 'hono';
|
|
7
|
+
|
|
8
|
+
import type { ReviewerBinding } from './reviewer-binding.js';
|
|
9
|
+
import type { AppEnv } from './types.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The caller's reviewer role: the one its token carries, else the one the
|
|
13
|
+
* roster gives its user (`ReviewerBinding.resolveReviewerRole`, when the
|
|
14
|
+
* binding has it), kept on the request. `undefined` for a caller that
|
|
15
|
+
* isn't a reviewer: a token with neither a role nor a user, or a user the
|
|
16
|
+
* roster doesn't know.
|
|
17
|
+
*/
|
|
18
|
+
export async function callerReviewerRole(
|
|
19
|
+
c: Context<AppEnv>,
|
|
20
|
+
reviewerBinding: ReviewerBinding | undefined,
|
|
21
|
+
): Promise<ReviewerRole | undefined> {
|
|
22
|
+
const carried = c.get('reviewerRole');
|
|
23
|
+
if (carried !== undefined) return carried;
|
|
24
|
+
const userId = c.get('userId') as UserId | undefined;
|
|
25
|
+
if (userId === undefined || reviewerBinding?.resolveReviewerRole === undefined) {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
const role = await reviewerBinding.resolveReviewerRole({
|
|
29
|
+
tenantId: c.get('tenantId') as TenantId,
|
|
30
|
+
userId,
|
|
31
|
+
});
|
|
32
|
+
if (role === null) return undefined;
|
|
33
|
+
c.set('reviewerRole', role);
|
|
34
|
+
return role;
|
|
35
|
+
}
|