@sixb/core 0.1.6 → 0.1.7
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/actions/index.js +37 -33
- package/dist/actions/index.js.map +1 -1
- package/dist/actions/worker.js +3 -3
- package/dist/agents/adapters.d.ts +33 -76
- package/dist/agents/adapters.d.ts.map +1 -1
- package/dist/agents/authority.d.ts +22 -6
- package/dist/agents/authority.d.ts.map +1 -1
- package/dist/agents/builders.d.ts +3 -11
- package/dist/agents/builders.d.ts.map +1 -1
- package/dist/agents/context.js +2 -2
- package/dist/agents/dispatch.d.ts +9 -1
- package/dist/agents/dispatch.d.ts.map +1 -1
- package/dist/agents/errors.d.ts +2 -2
- package/dist/agents/errors.d.ts.map +1 -1
- package/dist/agents/execution.d.ts +9 -10
- package/dist/agents/execution.d.ts.map +1 -1
- package/dist/agents/ids.d.ts +4 -0
- package/dist/agents/ids.d.ts.map +1 -1
- package/dist/agents/index.d.ts +13 -9
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js +80 -68
- package/dist/agents/index.js.map +1 -1
- package/dist/agents/message.d.ts +17 -10
- package/dist/agents/message.d.ts.map +1 -1
- package/dist/agents/model-loop.d.ts +56 -0
- package/dist/agents/model-loop.d.ts.map +1 -0
- package/dist/agents/reference.d.ts +4 -0
- package/dist/agents/reference.d.ts.map +1 -0
- package/dist/agents/request.d.ts +10 -8
- package/dist/agents/request.d.ts.map +1 -1
- package/dist/agents/retired-config.d.ts +4 -0
- package/dist/agents/retired-config.d.ts.map +1 -0
- package/dist/agents/streams.d.ts +13 -8
- package/dist/agents/streams.d.ts.map +1 -1
- package/dist/agents/streams.js +7 -5
- package/dist/agents/streams.js.map +1 -1
- package/dist/agents/tool-catalog.d.ts +9 -0
- package/dist/agents/tool-catalog.d.ts.map +1 -0
- package/dist/agents/tool-definition.d.ts +1 -0
- package/dist/agents/tool-definition.d.ts.map +1 -1
- package/dist/agents/types.d.ts +31 -68
- package/dist/agents/types.d.ts.map +1 -1
- package/dist/agents/validation.d.ts +4 -10
- package/dist/agents/validation.d.ts.map +1 -1
- package/dist/ai-usage/execution.d.ts +53 -0
- package/dist/ai-usage/execution.d.ts.map +1 -0
- package/dist/ai-usage/index.d.ts +3 -0
- package/dist/ai-usage/index.d.ts.map +1 -0
- package/dist/auth/index.js +7 -7
- package/dist/authorization/decision.d.ts +5 -2
- package/dist/authorization/decision.d.ts.map +1 -1
- package/dist/authorization/grant-kinds.d.ts +24 -8
- package/dist/authorization/grant-kinds.d.ts.map +1 -1
- package/dist/authorization/index.d.ts +1 -1
- package/dist/authorization/index.d.ts.map +1 -1
- package/dist/authorization/index.js +8 -6
- package/dist/authorization/index.js.map +1 -1
- package/dist/authorization/resolve.d.ts +3 -3
- package/dist/authorization/resolve.d.ts.map +1 -1
- package/dist/authorization/types.d.ts +7 -5
- package/dist/authorization/types.d.ts.map +1 -1
- package/dist/blob-storage/browser.js +2 -2
- package/dist/blob-storage/index.js +3 -3
- package/dist/bootstrap/discovery.d.ts +1 -7
- package/dist/bootstrap/discovery.d.ts.map +1 -1
- package/dist/bootstrap/index.js +52 -48
- package/dist/bootstrap/index.js.map +1 -1
- package/dist/broker/index.js +2 -2
- package/dist/{chunk-zqysyfjt.js → chunk-08m3b6w8.js} +1 -1
- package/dist/{chunk-1g8negke.js → chunk-08twe8m6.js} +93 -8
- package/dist/chunk-08twe8m6.js.map +12 -0
- package/dist/{chunk-xkthy56g.js → chunk-1kamz6j0.js} +1 -1
- package/dist/{chunk-dy311asx.js → chunk-2b5qtban.js} +12 -12
- package/dist/{chunk-dy311asx.js.map → chunk-2b5qtban.js.map} +3 -3
- package/dist/{chunk-0172wgm9.js → chunk-2xns679x.js} +10 -2
- package/dist/{chunk-0172wgm9.js.map → chunk-2xns679x.js.map} +3 -3
- package/dist/{chunk-f83ka50g.js → chunk-37wk412q.js} +86 -28
- package/dist/{chunk-f83ka50g.js.map → chunk-37wk412q.js.map} +8 -8
- package/dist/{chunk-md8k0r54.js → chunk-3fqt22c4.js} +4 -4
- package/dist/{chunk-t9xghkva.js → chunk-3kv70xwp.js} +3 -2
- package/dist/{chunk-t9xghkva.js.map → chunk-3kv70xwp.js.map} +3 -3
- package/dist/{chunk-z3zp0bj1.js → chunk-407j3msh.js} +1 -1
- package/dist/{chunk-rhrbz7d4.js → chunk-4a849fr1.js} +1 -1
- package/dist/{chunk-62c7t4jc.js → chunk-4nxeacx7.js} +1 -1
- package/dist/{chunk-cy0n5dms.js → chunk-5jcdmjam.js} +1 -1
- package/dist/{chunk-819wnjz8.js → chunk-64sr682n.js} +7 -7
- package/dist/{chunk-t624af60.js → chunk-6ed5bwnd.js} +646 -67
- package/dist/{chunk-t624af60.js.map → chunk-6ed5bwnd.js.map} +10 -9
- package/dist/{chunk-x2yw73hy.js → chunk-7ds9620f.js} +1 -1
- package/dist/{chunk-dm72y8wt.js → chunk-7y0f6rf1.js} +29 -16
- package/dist/chunk-7y0f6rf1.js.map +10 -0
- package/dist/{chunk-72q2y8hn.js → chunk-8tsf6dmc.js} +2 -2
- package/dist/{chunk-nkbfrt0c.js → chunk-9aehf39w.js} +7 -7
- package/dist/{chunk-ezake7g1.js → chunk-agsvg9ar.js} +1 -1
- package/dist/{chunk-rdeagz6b.js → chunk-atmkaf60.js} +1 -1
- package/dist/{chunk-rdeagz6b.js.map → chunk-atmkaf60.js.map} +2 -2
- package/dist/chunk-c15dr03f.js +43 -0
- package/dist/chunk-c15dr03f.js.map +10 -0
- package/dist/{chunk-0hc5j867.js → chunk-d2ndstdf.js} +8 -6
- package/dist/{chunk-0hc5j867.js.map → chunk-d2ndstdf.js.map} +2 -2
- package/dist/{chunk-rnshztfq.js → chunk-d63tybny.js} +2 -2
- package/dist/{chunk-t0jjkep3.js → chunk-d8qkxt2v.js} +4 -2
- package/dist/chunk-d8qkxt2v.js.map +10 -0
- package/dist/{chunk-vybf6pkp.js → chunk-dbc80ad7.js} +1 -1
- package/dist/{chunk-4gz41why.js → chunk-dqn23610.js} +1 -1
- package/dist/{chunk-5sxb1168.js → chunk-e4rvtvpw.js} +13 -11
- package/dist/{chunk-5sxb1168.js.map → chunk-e4rvtvpw.js.map} +2 -2
- package/dist/{chunk-h9kxd41f.js → chunk-gbrpsx4m.js} +19 -6
- package/dist/chunk-gbrpsx4m.js.map +11 -0
- package/dist/{chunk-nva1xkjz.js → chunk-h0knpbz5.js} +468 -1236
- package/dist/chunk-h0knpbz5.js.map +38 -0
- package/dist/{chunk-tg5mee00.js → chunk-ha58tjtt.js} +6 -6
- package/dist/{chunk-f6erf2vv.js → chunk-hdz94br2.js} +2 -2
- package/dist/chunk-jecn6t54.js +307 -0
- package/dist/chunk-jecn6t54.js.map +12 -0
- package/dist/{chunk-dsrkgtnh.js → chunk-jq43kdvk.js} +1 -1
- package/dist/{chunk-wtmzkcht.js → chunk-k34z5rvh.js} +1 -1
- package/dist/{chunk-htq0qh7z.js → chunk-ka3a2ft3.js} +2 -2
- package/dist/{chunk-znagycq7.js → chunk-kt81c11h.js} +2 -2
- package/dist/chunk-n2arzn6e.js +1745 -0
- package/dist/chunk-n2arzn6e.js.map +20 -0
- package/dist/{chunk-f2rt4vkh.js → chunk-n2w475r0.js} +3 -3
- package/dist/{chunk-t8t39h7v.js → chunk-n6jxh8sw.js} +10 -2
- package/dist/chunk-n6jxh8sw.js.map +10 -0
- package/dist/{chunk-drjqm1aa.js → chunk-p03r0h5s.js} +310 -28
- package/dist/chunk-p03r0h5s.js.map +16 -0
- package/dist/chunk-p2vqaxkc.js +528 -0
- package/dist/chunk-p2vqaxkc.js.map +15 -0
- package/dist/{chunk-n4spznws.js → chunk-qjycjdj6.js} +84 -11
- package/dist/chunk-qjycjdj6.js.map +12 -0
- package/dist/chunk-qjzp9xyb.js +286 -0
- package/dist/chunk-qjzp9xyb.js.map +12 -0
- package/dist/{chunk-5gynx4xn.js → chunk-qv38twt8.js} +50 -69
- package/dist/{chunk-5gynx4xn.js.map → chunk-qv38twt8.js.map} +8 -8
- package/dist/{chunk-bhxaq2nn.js → chunk-qw9gvjv5.js} +1 -1
- package/dist/{chunk-8gv5z0zm.js → chunk-rp1mvzb4.js} +6 -6
- package/dist/{chunk-1e8m6yn3.js → chunk-rre42skh.js} +182 -18
- package/dist/chunk-rre42skh.js.map +39 -0
- package/dist/{chunk-ghteq96b.js → chunk-s5y30bc9.js} +2 -2
- package/dist/{chunk-a31h57d5.js → chunk-tn7xcs2n.js} +2 -2
- package/dist/{chunk-6gjqgd3d.js → chunk-tpnd31c1.js} +2 -1
- package/dist/chunk-tpnd31c1.js.map +11 -0
- package/dist/chunk-trxxmgnf.js +68 -0
- package/dist/chunk-trxxmgnf.js.map +11 -0
- package/dist/{chunk-e42bc6m3.js → chunk-vjjv9mrb.js} +2 -2
- package/dist/{chunk-8b55ygje.js → chunk-w3e09qqk.js} +1 -1
- package/dist/{chunk-ckxfnx7f.js → chunk-wjgm6jjt.js} +2 -2
- package/dist/{chunk-3j7573mj.js → chunk-x0qhkqje.js} +2 -2
- package/dist/{chunk-dysw7nsm.js → chunk-xdpwpkha.js} +2 -2
- package/dist/{chunk-a44d5zgd.js → chunk-y35ma3mj.js} +11 -16
- package/dist/{chunk-a44d5zgd.js.map → chunk-y35ma3mj.js.map} +3 -4
- package/dist/{chunk-qewtks41.js → chunk-z2sery1b.js} +64 -1
- package/dist/{chunk-qewtks41.js.map → chunk-z2sery1b.js.map} +3 -3
- package/dist/error-reporting/internal.js +4 -4
- package/dist/error-reporting/types.d.ts +7 -2
- package/dist/error-reporting/types.d.ts.map +1 -1
- package/dist/errors/catalog.d.ts +8 -0
- package/dist/errors/catalog.d.ts.map +1 -1
- package/dist/errors/internal.js +2 -2
- package/dist/events/index.js +4 -4
- package/dist/execution/agent.d.ts +18 -9
- package/dist/execution/agent.d.ts.map +1 -1
- package/dist/execution/agent.js +52 -43
- package/dist/execution/agent.js.map +1 -1
- package/dist/execution/authorization.d.ts +14 -4
- package/dist/execution/authorization.d.ts.map +1 -1
- package/dist/execution/primitive.js +45 -43
- package/dist/execution/primitive.js.map +2 -2
- package/dist/execution/request.d.ts +3 -1
- package/dist/execution/request.d.ts.map +1 -1
- package/dist/execution/request.js +46 -44
- package/dist/execution/request.js.map +3 -3
- package/dist/execution/types.d.ts +1 -1
- package/dist/execution/types.d.ts.map +1 -1
- package/dist/http/api-routes.d.ts.map +1 -1
- package/dist/http/index.js +1 -1
- package/dist/index.d.ts +9 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +82 -77
- package/dist/index.js.map +1 -1
- package/dist/json.d.ts +2 -0
- package/dist/json.d.ts.map +1 -1
- package/dist/lake-storage/index.js +5 -5
- package/dist/logging/index.js +3 -3
- package/dist/logging/types.js +2 -2
- package/dist/materialization/index.js +2 -2
- package/dist/materializer/index.js +33 -29
- package/dist/materializer/index.js.map +1 -1
- package/dist/models/catalog.d.ts +40 -0
- package/dist/models/catalog.d.ts.map +1 -0
- package/dist/models/definitions.d.ts +25 -0
- package/dist/models/definitions.d.ts.map +1 -0
- package/dist/models/errors.d.ts +52 -0
- package/dist/models/errors.d.ts.map +1 -0
- package/dist/models/events.d.ts +192 -0
- package/dist/models/events.d.ts.map +1 -0
- package/dist/models/index.d.ts +17 -39
- package/dist/models/index.d.ts.map +1 -1
- package/dist/models/index.js +50 -0
- package/dist/models/index.js.map +9 -0
- package/dist/models/language-model.d.ts +90 -0
- package/dist/models/language-model.d.ts.map +1 -0
- package/dist/models/messages.d.ts +74 -0
- package/dist/models/messages.d.ts.map +1 -0
- package/dist/models/pricing.d.ts +69 -0
- package/dist/models/pricing.d.ts.map +1 -0
- package/dist/models/rate-card.d.ts +24 -0
- package/dist/models/rate-card.d.ts.map +1 -0
- package/dist/models/tools.d.ts +24 -0
- package/dist/models/tools.d.ts.map +1 -0
- package/dist/objects/index.js +38 -34
- package/dist/objects/index.js.map +1 -1
- package/dist/objects/query/index.js +32 -28
- package/dist/objects/query/index.js.map +1 -1
- package/dist/ontology/index.js +5 -5
- package/dist/ontology/internal.js +4 -4
- package/dist/pipelines/index.js +37 -35
- package/dist/pipelines/index.js.map +1 -1
- package/dist/projections/internal.js +35 -31
- package/dist/projections/internal.js.map +1 -1
- package/dist/queues/in-memory.d.ts +3 -2
- package/dist/queues/in-memory.d.ts.map +1 -1
- package/dist/queues/index.d.ts +3 -1
- package/dist/queues/index.d.ts.map +1 -1
- package/dist/queues/index.js +1 -1
- package/dist/queues/types.d.ts +15 -3
- package/dist/queues/types.d.ts.map +1 -1
- package/dist/runtime/create.d.ts +4 -4
- package/dist/runtime/create.d.ts.map +1 -1
- package/dist/runtime/definitions.d.ts +2 -2
- package/dist/runtime/definitions.d.ts.map +1 -1
- package/dist/runtime/host.d.ts +3 -2
- package/dist/runtime/host.d.ts.map +1 -1
- package/dist/runtime/resolve-definitions.d.ts +2 -2
- package/dist/runtime/resolve-definitions.d.ts.map +1 -1
- package/dist/runtime/sixb.d.ts +4 -2
- package/dist/runtime/sixb.d.ts.map +1 -1
- package/dist/security/every.d.ts +1 -4
- package/dist/security/every.d.ts.map +1 -1
- package/dist/security/grants.d.ts +6 -5
- package/dist/security/grants.d.ts.map +1 -1
- package/dist/security/index.d.ts +1 -1
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/registry.d.ts +1 -1
- package/dist/security/registry.d.ts.map +1 -1
- package/dist/security/types.d.ts +13 -5
- package/dist/security/types.d.ts.map +1 -1
- package/dist/security/validation.d.ts +4 -2
- package/dist/security/validation.d.ts.map +1 -1
- package/dist/storage/action-runs/failure.js +3 -3
- package/dist/storage/action-runs/provider.js +2 -2
- package/dist/storage/agents/errors.d.ts +1 -1
- package/dist/storage/agents/errors.d.ts.map +1 -1
- package/dist/storage/agents/in-memory.d.ts +3 -2
- package/dist/storage/agents/in-memory.d.ts.map +1 -1
- package/dist/storage/agents/index.d.ts +1 -1
- package/dist/storage/agents/index.d.ts.map +1 -1
- package/dist/storage/agents/provider.d.ts +11 -4
- package/dist/storage/agents/provider.d.ts.map +1 -1
- package/dist/storage/agents/provider.js +18 -15
- package/dist/storage/agents/provider.js.map +1 -1
- package/dist/storage/agents/types.d.ts +65 -17
- package/dist/storage/agents/types.d.ts.map +1 -1
- package/dist/storage/ai-cost/analytics.d.ts +2 -1
- package/dist/storage/ai-cost/analytics.d.ts.map +1 -1
- package/dist/storage/ai-cost/codec.d.ts +3 -2
- package/dist/storage/ai-cost/codec.d.ts.map +1 -1
- package/dist/storage/ai-cost/groups.d.ts +51 -0
- package/dist/storage/ai-cost/groups.d.ts.map +1 -0
- package/dist/storage/ai-cost/in-memory.d.ts +11 -1
- package/dist/storage/ai-cost/in-memory.d.ts.map +1 -1
- package/dist/storage/ai-cost/index.d.ts +1 -1
- package/dist/storage/ai-cost/index.d.ts.map +1 -1
- package/dist/storage/ai-cost/provider.d.ts +2 -0
- package/dist/storage/ai-cost/provider.d.ts.map +1 -1
- package/dist/storage/ai-cost/provider.js +29 -13
- package/dist/storage/ai-cost/provider.js.map +3 -3
- package/dist/storage/ai-cost/types.d.ts +64 -15
- package/dist/storage/ai-cost/types.d.ts.map +1 -1
- package/dist/storage/ai-cost/validation.d.ts +2 -1
- package/dist/storage/ai-cost/validation.d.ts.map +1 -1
- package/dist/storage/ai-limits/enforcement.d.ts +14 -0
- package/dist/storage/ai-limits/enforcement.d.ts.map +1 -0
- package/dist/storage/ai-limits/enforcement.js +21 -0
- package/dist/storage/ai-limits/enforcement.js.map +9 -0
- package/dist/storage/ai-limits/errors.d.ts +8 -0
- package/dist/storage/ai-limits/errors.d.ts.map +1 -0
- package/dist/storage/ai-limits/in-memory.d.ts +78 -0
- package/dist/storage/ai-limits/in-memory.d.ts.map +1 -0
- package/dist/storage/ai-limits/index.d.ts +7 -0
- package/dist/storage/ai-limits/index.d.ts.map +1 -0
- package/dist/storage/ai-limits/period.d.ts +4 -0
- package/dist/storage/ai-limits/period.d.ts.map +1 -0
- package/dist/storage/ai-limits/provider.d.ts +85 -0
- package/dist/storage/ai-limits/provider.d.ts.map +1 -0
- package/dist/storage/ai-limits/provider.js +62 -0
- package/dist/storage/ai-limits/provider.js.map +9 -0
- package/dist/storage/ai-limits/types.d.ts +175 -0
- package/dist/storage/ai-limits/types.d.ts.map +1 -0
- package/dist/storage/ai-usage/in-memory.d.ts +4 -0
- package/dist/storage/ai-usage/in-memory.d.ts.map +1 -1
- package/dist/storage/ai-usage/record.d.ts.map +1 -1
- package/dist/storage/ai-usage/types.d.ts +6 -2
- package/dist/storage/ai-usage/types.d.ts.map +1 -1
- package/dist/storage/auth/errors.d.ts +1 -1
- package/dist/storage/auth/errors.d.ts.map +1 -1
- package/dist/storage/auth/in-memory/auth-storage.d.ts +4 -1
- package/dist/storage/auth/in-memory/auth-storage.d.ts.map +1 -1
- package/dist/storage/auth/in-memory/device-authorizations.d.ts +29 -0
- package/dist/storage/auth/in-memory/device-authorizations.d.ts.map +1 -0
- package/dist/storage/auth/in-memory/shared.d.ts +3 -1
- package/dist/storage/auth/in-memory/shared.d.ts.map +1 -1
- package/dist/storage/auth/index.d.ts +2 -1
- package/dist/storage/auth/index.d.ts.map +1 -1
- package/dist/storage/auth/types.d.ts +66 -0
- package/dist/storage/auth/types.d.ts.map +1 -1
- package/dist/storage/connector-connections/provider.js +2 -2
- package/dist/storage/executions/provider.js +1 -1
- package/dist/storage/executions/run-link.d.ts +7 -2
- package/dist/storage/executions/run-link.d.ts.map +1 -1
- package/dist/storage/executions/validation.d.ts.map +1 -1
- package/dist/storage/in-memory/index.d.ts +4 -0
- package/dist/storage/in-memory/index.d.ts.map +1 -1
- package/dist/storage/index.d.ts +7 -4
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/index.js +51 -38
- package/dist/storage/index.js.map +1 -1
- package/dist/storage/ontology/provider.js +3 -3
- package/dist/storage/pipeline-runs/provider.js +2 -2
- package/dist/storage/projection-runs/provider.js +4 -4
- package/dist/storage/sync-runs/provider.js +2 -2
- package/dist/storage/types.d.ts +5 -1
- package/dist/storage/types.d.ts.map +1 -1
- package/dist/storage/webhook-runs/provider.js +2 -2
- package/dist/storage/workflow-runs/provider.d.ts +1 -1
- package/dist/storage/workflow-runs/provider.js +10 -11
- package/dist/storage/workflow-runs/provider.js.map +1 -1
- package/dist/storage/workflow-runs/types.d.ts +5 -4
- package/dist/storage/workflow-runs/types.d.ts.map +1 -1
- package/dist/syncs/index.js +37 -35
- package/dist/syncs/index.js.map +1 -1
- package/dist/testing/agent-execution.d.ts +3 -1
- package/dist/testing/agent-execution.d.ts.map +1 -1
- package/dist/testing/agent-storage-contract.d.ts.map +1 -1
- package/dist/testing/ai-cost-storage-contract.d.ts.map +1 -1
- package/dist/testing/ai-limit-storage-contract.d.ts +18 -0
- package/dist/testing/ai-limit-storage-contract.d.ts.map +1 -0
- package/dist/testing/ai-model-call-groups-contract.d.ts +6 -0
- package/dist/testing/ai-model-call-groups-contract.d.ts.map +1 -0
- package/dist/testing/ai-usage-storage-contract.d.ts.map +1 -1
- package/dist/testing/auth-storage-contract.d.ts.map +1 -1
- package/dist/testing/index.d.ts +2 -0
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +3637 -1962
- package/dist/testing/index.js.map +14 -12
- package/dist/testing/queues-contract.d.ts.map +1 -1
- package/dist/webhooks/internal.js +32 -28
- package/dist/webhooks/internal.js.map +2 -2
- package/dist/workers/index.js +2 -2
- package/dist/workflows/agent-step-identity.d.ts +3 -0
- package/dist/workflows/agent-step-identity.d.ts.map +1 -0
- package/dist/workflows/builders.d.ts +2 -3
- package/dist/workflows/builders.d.ts.map +1 -1
- package/dist/workflows/execution.d.ts +1 -1
- package/dist/workflows/execution.d.ts.map +1 -1
- package/dist/workflows/failure.d.ts +1 -1
- package/dist/workflows/failure.d.ts.map +1 -1
- package/dist/workflows/index.d.ts +3 -2
- package/dist/workflows/index.d.ts.map +1 -1
- package/dist/workflows/index.js +53 -45
- package/dist/workflows/index.js.map +1 -1
- package/dist/workflows/types.d.ts +26 -11
- package/dist/workflows/types.d.ts.map +1 -1
- package/dist/workflows/validation.d.ts +7 -1
- package/dist/workflows/validation.d.ts.map +1 -1
- package/package.json +19 -4
- package/src/agents/adapters.ts +109 -115
- package/src/agents/authority.ts +214 -32
- package/src/agents/builders.ts +3 -50
- package/src/agents/context-compaction.ts +4 -0
- package/src/agents/dispatch.ts +59 -2
- package/src/agents/errors.ts +5 -2
- package/src/agents/execution.ts +53 -52
- package/src/agents/ids.ts +16 -1
- package/src/agents/index.ts +23 -11
- package/src/agents/message.ts +18 -9
- package/src/agents/model-loop.ts +1023 -0
- package/src/agents/reference.ts +7 -0
- package/src/agents/request.ts +141 -74
- package/src/agents/retired-config.ts +20 -0
- package/src/agents/streams.ts +45 -19
- package/src/agents/tool-catalog.ts +21 -0
- package/src/agents/tool-definition.ts +23 -0
- package/src/agents/types.ts +39 -81
- package/src/agents/validation.ts +34 -180
- package/src/ai-usage/execution.ts +196 -0
- package/src/ai-usage/index.ts +15 -0
- package/src/authorization/decision.ts +27 -10
- package/src/authorization/grant-kinds.ts +62 -15
- package/src/authorization/index.ts +1 -0
- package/src/authorization/resolve.ts +12 -5
- package/src/authorization/types.ts +7 -5
- package/src/bootstrap/discovery.ts +0 -3
- package/src/error-reporting/types.ts +4 -2
- package/src/errors/catalog.ts +8 -0
- package/src/execution/agent.ts +129 -22
- package/src/execution/authorization.ts +48 -18
- package/src/execution/request.ts +4 -1
- package/src/execution/types.ts +1 -1
- package/src/http/api-routes.ts +63 -0
- package/src/index.ts +36 -7
- package/src/json.ts +9 -0
- package/src/models/catalog.ts +137 -0
- package/src/models/definitions.ts +202 -0
- package/src/models/errors.ts +83 -0
- package/src/models/events.ts +198 -0
- package/src/models/index.ts +89 -71
- package/src/models/language-model.ts +143 -0
- package/src/models/messages.ts +78 -0
- package/src/models/pricing.ts +390 -0
- package/src/models/rate-card.ts +101 -0
- package/src/models/tools.ts +29 -0
- package/src/queues/in-memory.ts +5 -0
- package/src/queues/index.ts +11 -0
- package/src/queues/types.ts +20 -3
- package/src/runtime/create.ts +7 -5
- package/src/runtime/definitions.ts +2 -2
- package/src/runtime/host.ts +3 -2
- package/src/runtime/resolve-definitions.ts +13 -36
- package/src/runtime/sixb.ts +6 -8
- package/src/security/every.ts +0 -4
- package/src/security/grants.ts +55 -11
- package/src/security/index.ts +2 -0
- package/src/security/registry.ts +6 -5
- package/src/security/types.ts +15 -4
- package/src/security/validation.ts +30 -9
- package/src/storage/agents/errors.ts +1 -0
- package/src/storage/agents/in-memory.ts +121 -11
- package/src/storage/agents/index.ts +7 -0
- package/src/storage/agents/provider.ts +150 -6
- package/src/storage/agents/types.ts +73 -16
- package/src/storage/ai-cost/analytics.ts +63 -6
- package/src/storage/ai-cost/codec.ts +37 -12
- package/src/storage/ai-cost/groups.ts +248 -0
- package/src/storage/ai-cost/in-memory.ts +42 -0
- package/src/storage/ai-cost/index.ts +6 -0
- package/src/storage/ai-cost/provider.ts +7 -0
- package/src/storage/ai-cost/types.ts +76 -14
- package/src/storage/ai-cost/validation.ts +147 -17
- package/src/storage/ai-limits/enforcement.ts +68 -0
- package/src/storage/ai-limits/errors.ts +23 -0
- package/src/storage/ai-limits/in-memory.ts +671 -0
- package/src/storage/ai-limits/index.ts +31 -0
- package/src/storage/ai-limits/period.ts +11 -0
- package/src/storage/ai-limits/provider.ts +430 -0
- package/src/storage/ai-limits/types.ts +195 -0
- package/src/storage/ai-usage/in-memory.ts +13 -0
- package/src/storage/ai-usage/record.ts +17 -0
- package/src/storage/ai-usage/types.ts +6 -2
- package/src/storage/auth/errors.ts +6 -0
- package/src/storage/auth/in-memory/auth-storage.ts +69 -0
- package/src/storage/auth/in-memory/device-authorizations.ts +145 -0
- package/src/storage/auth/in-memory/shared.ts +7 -0
- package/src/storage/auth/index.ts +7 -0
- package/src/storage/auth/types.ts +73 -0
- package/src/storage/executions/run-link.ts +16 -6
- package/src/storage/executions/validation.ts +36 -6
- package/src/storage/in-memory/index.ts +48 -4
- package/src/storage/index.ts +51 -1
- package/src/storage/types.ts +37 -0
- package/src/storage/workflow-runs/in-memory.ts +3 -3
- package/src/storage/workflow-runs/provider.ts +2 -2
- package/src/storage/workflow-runs/types.ts +6 -3
- package/src/testing/agent-execution.ts +40 -28
- package/src/testing/agent-storage-contract.ts +249 -28
- package/src/testing/ai-cost-storage-contract.ts +96 -8
- package/src/testing/ai-limit-storage-contract.ts +1134 -0
- package/src/testing/ai-model-call-groups-contract.ts +353 -0
- package/src/testing/ai-usage-storage-contract.ts +31 -0
- package/src/testing/auth-storage-contract.ts +85 -0
- package/src/testing/execution-storage-contract.ts +2 -2
- package/src/testing/index.ts +10 -0
- package/src/testing/queues-contract.ts +36 -1
- package/src/workflows/agent-step-identity.ts +4 -0
- package/src/workflows/builders.ts +95 -9
- package/src/workflows/execution.ts +2 -2
- package/src/workflows/failure.ts +2 -2
- package/src/workflows/index.ts +3 -0
- package/src/workflows/types.ts +23 -11
- package/src/workflows/validation.ts +100 -7
- package/dist/chunk-1e8m6yn3.js.map +0 -37
- package/dist/chunk-1g8negke.js.map +0 -11
- package/dist/chunk-6gjqgd3d.js.map +0 -11
- package/dist/chunk-dm72y8wt.js.map +0 -10
- package/dist/chunk-drjqm1aa.js.map +0 -15
- package/dist/chunk-fe5ev6mr.js +0 -55
- package/dist/chunk-fe5ev6mr.js.map +0 -11
- package/dist/chunk-h9kxd41f.js.map +0 -11
- package/dist/chunk-hceck7dq.js +0 -137
- package/dist/chunk-hceck7dq.js.map +0 -10
- package/dist/chunk-n4spznws.js.map +0 -11
- package/dist/chunk-nva1xkjz.js.map +0 -46
- package/dist/chunk-t0jjkep3.js.map +0 -10
- package/dist/chunk-t8t39h7v.js.map +0 -10
- /package/dist/{chunk-zqysyfjt.js.map → chunk-08m3b6w8.js.map} +0 -0
- /package/dist/{chunk-xkthy56g.js.map → chunk-1kamz6j0.js.map} +0 -0
- /package/dist/{chunk-md8k0r54.js.map → chunk-3fqt22c4.js.map} +0 -0
- /package/dist/{chunk-z3zp0bj1.js.map → chunk-407j3msh.js.map} +0 -0
- /package/dist/{chunk-rhrbz7d4.js.map → chunk-4a849fr1.js.map} +0 -0
- /package/dist/{chunk-62c7t4jc.js.map → chunk-4nxeacx7.js.map} +0 -0
- /package/dist/{chunk-cy0n5dms.js.map → chunk-5jcdmjam.js.map} +0 -0
- /package/dist/{chunk-819wnjz8.js.map → chunk-64sr682n.js.map} +0 -0
- /package/dist/{chunk-x2yw73hy.js.map → chunk-7ds9620f.js.map} +0 -0
- /package/dist/{chunk-72q2y8hn.js.map → chunk-8tsf6dmc.js.map} +0 -0
- /package/dist/{chunk-nkbfrt0c.js.map → chunk-9aehf39w.js.map} +0 -0
- /package/dist/{chunk-ezake7g1.js.map → chunk-agsvg9ar.js.map} +0 -0
- /package/dist/{chunk-rnshztfq.js.map → chunk-d63tybny.js.map} +0 -0
- /package/dist/{chunk-vybf6pkp.js.map → chunk-dbc80ad7.js.map} +0 -0
- /package/dist/{chunk-4gz41why.js.map → chunk-dqn23610.js.map} +0 -0
- /package/dist/{chunk-tg5mee00.js.map → chunk-ha58tjtt.js.map} +0 -0
- /package/dist/{chunk-f6erf2vv.js.map → chunk-hdz94br2.js.map} +0 -0
- /package/dist/{chunk-dsrkgtnh.js.map → chunk-jq43kdvk.js.map} +0 -0
- /package/dist/{chunk-wtmzkcht.js.map → chunk-k34z5rvh.js.map} +0 -0
- /package/dist/{chunk-htq0qh7z.js.map → chunk-ka3a2ft3.js.map} +0 -0
- /package/dist/{chunk-znagycq7.js.map → chunk-kt81c11h.js.map} +0 -0
- /package/dist/{chunk-f2rt4vkh.js.map → chunk-n2w475r0.js.map} +0 -0
- /package/dist/{chunk-bhxaq2nn.js.map → chunk-qw9gvjv5.js.map} +0 -0
- /package/dist/{chunk-8gv5z0zm.js.map → chunk-rp1mvzb4.js.map} +0 -0
- /package/dist/{chunk-ghteq96b.js.map → chunk-s5y30bc9.js.map} +0 -0
- /package/dist/{chunk-a31h57d5.js.map → chunk-tn7xcs2n.js.map} +0 -0
- /package/dist/{chunk-e42bc6m3.js.map → chunk-vjjv9mrb.js.map} +0 -0
- /package/dist/{chunk-8b55ygje.js.map → chunk-w3e09qqk.js.map} +0 -0
- /package/dist/{chunk-ckxfnx7f.js.map → chunk-wjgm6jjt.js.map} +0 -0
- /package/dist/{chunk-3j7573mj.js.map → chunk-x0qhkqje.js.map} +0 -0
- /package/dist/{chunk-dysw7nsm.js.map → chunk-xdpwpkha.js.map} +0 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { AiLimitPeriod } from "./types"
|
|
2
|
+
|
|
3
|
+
/** Return the UTC calendar month containing `at`, with an inclusive start and exclusive end. */
|
|
4
|
+
export function aiLimitCalendarMonth(at: Date): AiLimitPeriod {
|
|
5
|
+
if (!(at instanceof Date) || !Number.isFinite(at.getTime())) {
|
|
6
|
+
throw new TypeError("[Sixb] AI limit period date must be a valid Date.")
|
|
7
|
+
}
|
|
8
|
+
const start = new Date(Date.UTC(at.getUTCFullYear(), at.getUTCMonth(), 1))
|
|
9
|
+
const end = new Date(Date.UTC(at.getUTCFullYear(), at.getUTCMonth() + 1, 1))
|
|
10
|
+
return { kind: "calendarMonth", start, end, resetAt: new Date(end) }
|
|
11
|
+
}
|
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
import type { AiMoney } from "../ai-cost"
|
|
2
|
+
import { AiLimitStorageError } from "./errors"
|
|
3
|
+
import { aiLimitCalendarMonth } from "./period"
|
|
4
|
+
import type {
|
|
5
|
+
AiLimitPeriod,
|
|
6
|
+
AiLimitPolicy,
|
|
7
|
+
AiLimitQuantity,
|
|
8
|
+
AiLimitReservationBucket,
|
|
9
|
+
AiLimitSubject,
|
|
10
|
+
AiModelCallReservation,
|
|
11
|
+
AiModelCallReservationIdentity,
|
|
12
|
+
CreateAiLimitPolicyInput,
|
|
13
|
+
ReserveAiModelCallInput,
|
|
14
|
+
UpdateAiLimitPolicyInput,
|
|
15
|
+
} from "./types"
|
|
16
|
+
|
|
17
|
+
const SIGNED_INT64_MAX = 9_223_372_036_854_775_807n
|
|
18
|
+
|
|
19
|
+
/** @internal Serialize compound limit operations, including within an existing transaction. */
|
|
20
|
+
export class AiLimitOperationLock {
|
|
21
|
+
private tail: Promise<void> = Promise.resolve()
|
|
22
|
+
|
|
23
|
+
/** Wait for already queued operations before the owning transaction commits or rolls back. */
|
|
24
|
+
settle(): Promise<void> {
|
|
25
|
+
return this.tail
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async run<T>(operation: () => Promise<T> | T): Promise<T> {
|
|
29
|
+
const previous = this.tail
|
|
30
|
+
let release!: () => void
|
|
31
|
+
this.tail = new Promise<void>((resolve) => {
|
|
32
|
+
release = resolve
|
|
33
|
+
})
|
|
34
|
+
await previous
|
|
35
|
+
try {
|
|
36
|
+
return await operation()
|
|
37
|
+
} finally {
|
|
38
|
+
release()
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** @internal Canonical integer quantity used by storage providers. */
|
|
44
|
+
export interface NormalizedAiLimitAmount {
|
|
45
|
+
readonly meter: AiLimitQuantity["meter"]
|
|
46
|
+
readonly currency: string
|
|
47
|
+
readonly amount: bigint
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** @internal Minimal immutable accounting facts consumed by limit providers. */
|
|
51
|
+
export interface AiLimitAccountingEntry {
|
|
52
|
+
readonly projectId: string
|
|
53
|
+
readonly usageRecordId: string
|
|
54
|
+
readonly executionId: string
|
|
55
|
+
readonly attempt: number
|
|
56
|
+
readonly callId: string
|
|
57
|
+
readonly occurredAt: Date
|
|
58
|
+
readonly totalTokens?: number
|
|
59
|
+
readonly requesterGroupIds: readonly string[]
|
|
60
|
+
readonly requester?:
|
|
61
|
+
| { readonly type: "user"; readonly id: string }
|
|
62
|
+
| { readonly type: "serviceAccount"; readonly id: string }
|
|
63
|
+
readonly valuation?:
|
|
64
|
+
| { readonly status: "rated"; readonly money: AiMoney }
|
|
65
|
+
| { readonly status: "unavailable" }
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface ResolvedAiLimitActual {
|
|
69
|
+
readonly amount: bigint
|
|
70
|
+
readonly accountingStatus: "complete" | "unavailable"
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function normalizeAiLimitSubject(subject: AiLimitSubject): AiLimitSubject {
|
|
74
|
+
if (!subject || typeof subject !== "object") {
|
|
75
|
+
throw new TypeError("[Sixb] AI limit subject must be an object.")
|
|
76
|
+
}
|
|
77
|
+
if (subject.type === "project") return { type: "project" }
|
|
78
|
+
if (subject.type === "group" || subject.type === "user" || subject.type === "serviceAccount") {
|
|
79
|
+
assertNonBlank(subject.id, "subject id")
|
|
80
|
+
return { type: subject.type, id: subject.id }
|
|
81
|
+
}
|
|
82
|
+
throw new TypeError("[Sixb] AI limit subject type is unsupported.")
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function normalizeAiLimitSubjects(
|
|
86
|
+
subjects: readonly AiLimitSubject[]
|
|
87
|
+
): readonly AiLimitSubject[] {
|
|
88
|
+
if (!Array.isArray(subjects)) {
|
|
89
|
+
throw new TypeError("[Sixb] AI limit subjects must be an array.")
|
|
90
|
+
}
|
|
91
|
+
const normalized = [
|
|
92
|
+
normalizeAiLimitSubject({ type: "project" }),
|
|
93
|
+
...subjects.map(normalizeAiLimitSubject),
|
|
94
|
+
]
|
|
95
|
+
const byKey = new Map(normalized.map((subject) => [aiLimitSubjectKey(subject), subject]))
|
|
96
|
+
return [...byKey.values()].sort((left, right) =>
|
|
97
|
+
aiLimitSubjectKey(left).localeCompare(aiLimitSubjectKey(right))
|
|
98
|
+
)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function aiLimitSubjectKey(subject: AiLimitSubject): string {
|
|
102
|
+
return subject.type === "project" ? "project:" : `${subject.type}:${subject.id}`
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function aiLimitSubjectParts(subject: AiLimitSubject): {
|
|
106
|
+
readonly type: AiLimitSubject["type"]
|
|
107
|
+
readonly id: string
|
|
108
|
+
} {
|
|
109
|
+
return { type: subject.type, id: subject.type === "project" ? "" : subject.id }
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function aiLimitSubjectFromParts(type: AiLimitSubject["type"], id: string): AiLimitSubject {
|
|
113
|
+
return normalizeAiLimitSubject(type === "project" ? { type } : { type, id })
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function normalizeAiLimitQuantity(quantity: AiLimitQuantity): AiLimitQuantity {
|
|
117
|
+
const normalized = normalizeAiLimitAmount(quantity)
|
|
118
|
+
return aiLimitQuantityFromAmount(normalized)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function normalizeAiLimitQuantities(
|
|
122
|
+
quantities: readonly AiLimitQuantity[],
|
|
123
|
+
label: string
|
|
124
|
+
): readonly AiLimitQuantity[] {
|
|
125
|
+
if (!Array.isArray(quantities) || quantities.length === 0) {
|
|
126
|
+
throw new TypeError(`[Sixb] AI limit ${label} must contain at least one quantity.`)
|
|
127
|
+
}
|
|
128
|
+
const byKey = new Map<string, AiLimitQuantity>()
|
|
129
|
+
for (const quantity of quantities) {
|
|
130
|
+
const normalized = normalizeAiLimitQuantity(quantity)
|
|
131
|
+
const key = aiLimitAmountKey(normalizeAiLimitAmount(normalized))
|
|
132
|
+
if (byKey.has(key)) {
|
|
133
|
+
throw new TypeError(`[Sixb] AI limit ${label} contains duplicate meter '${key}'.`)
|
|
134
|
+
}
|
|
135
|
+
byKey.set(key, normalized)
|
|
136
|
+
}
|
|
137
|
+
return [...byKey.values()].sort((left, right) =>
|
|
138
|
+
aiLimitAmountKey(normalizeAiLimitAmount(left)).localeCompare(
|
|
139
|
+
aiLimitAmountKey(normalizeAiLimitAmount(right))
|
|
140
|
+
)
|
|
141
|
+
)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function normalizeAiLimitAmount(quantity: AiLimitQuantity): NormalizedAiLimitAmount {
|
|
145
|
+
if (!quantity || typeof quantity !== "object") {
|
|
146
|
+
throw new TypeError("[Sixb] AI limit quantity must be an object.")
|
|
147
|
+
}
|
|
148
|
+
if (quantity.meter === "tokens.total") {
|
|
149
|
+
if (!Number.isSafeInteger(quantity.amount) || quantity.amount < 0) {
|
|
150
|
+
throw new TypeError("[Sixb] AI limit token amount must be a non-negative safe integer.")
|
|
151
|
+
}
|
|
152
|
+
return { meter: quantity.meter, currency: "", amount: BigInt(quantity.amount) }
|
|
153
|
+
}
|
|
154
|
+
if (quantity.meter === "cost.catalogEstimated") {
|
|
155
|
+
const money = normalizeAiMoney(quantity.amount)
|
|
156
|
+
return { meter: quantity.meter, currency: money.currency, amount: BigInt(money.amountNanos) }
|
|
157
|
+
}
|
|
158
|
+
throw new TypeError("[Sixb] AI limit meter is unsupported.")
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export function aiLimitQuantityFromAmount(amount: NormalizedAiLimitAmount): AiLimitQuantity {
|
|
162
|
+
if (amount.amount < 0n) {
|
|
163
|
+
throw new TypeError("[Sixb] AI limit amount cannot be negative.")
|
|
164
|
+
}
|
|
165
|
+
if (amount.meter === "tokens.total") {
|
|
166
|
+
const tokens = Number(amount.amount)
|
|
167
|
+
if (!Number.isSafeInteger(tokens)) {
|
|
168
|
+
throw new RangeError("[Sixb] AI limit token amount exceeds JavaScript's safe integer range.")
|
|
169
|
+
}
|
|
170
|
+
return { meter: amount.meter, amount: tokens }
|
|
171
|
+
}
|
|
172
|
+
if (amount.currency !== "USD") {
|
|
173
|
+
throw new TypeError("[Sixb] AI limit catalog-estimated cost currency must be 'USD'.")
|
|
174
|
+
}
|
|
175
|
+
return {
|
|
176
|
+
meter: amount.meter,
|
|
177
|
+
amount: { currency: "USD", amountNanos: amount.amount.toString() },
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export function aiLimitAmountKey(
|
|
182
|
+
amount: Pick<NormalizedAiLimitAmount, "meter" | "currency">
|
|
183
|
+
): string {
|
|
184
|
+
return `${amount.meter}:${amount.currency}`
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export function normalizeCreateAiLimitPolicy(input: CreateAiLimitPolicyInput): AiLimitPolicy {
|
|
188
|
+
assertNonBlank(input.id, "policy id")
|
|
189
|
+
assertNonBlank(input.projectId, "projectId")
|
|
190
|
+
const createdAt = cloneValidDate(input.createdAt ?? new Date(), "createdAt")
|
|
191
|
+
return {
|
|
192
|
+
id: input.id,
|
|
193
|
+
projectId: input.projectId,
|
|
194
|
+
subject: normalizeAiLimitSubject(input.subject),
|
|
195
|
+
limit: normalizeAiLimitQuantity(input.limit),
|
|
196
|
+
period: "calendarMonth",
|
|
197
|
+
enabled: input.enabled ?? true,
|
|
198
|
+
createdAt,
|
|
199
|
+
updatedAt: new Date(createdAt),
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export function normalizeUpdateAiLimitPolicy(input: UpdateAiLimitPolicyInput): {
|
|
204
|
+
readonly projectId: string
|
|
205
|
+
readonly id: string
|
|
206
|
+
readonly limit?: AiLimitQuantity
|
|
207
|
+
readonly enabled?: boolean
|
|
208
|
+
readonly updatedAt: Date
|
|
209
|
+
} {
|
|
210
|
+
assertNonBlank(input.projectId, "projectId")
|
|
211
|
+
assertNonBlank(input.id, "policy id")
|
|
212
|
+
if (input.limit === undefined && input.enabled === undefined) {
|
|
213
|
+
throw new TypeError("[Sixb] AI limit policy update must change limit or enabled.")
|
|
214
|
+
}
|
|
215
|
+
if (input.enabled !== undefined && typeof input.enabled !== "boolean") {
|
|
216
|
+
throw new TypeError("[Sixb] AI limit enabled must be a boolean.")
|
|
217
|
+
}
|
|
218
|
+
return {
|
|
219
|
+
projectId: input.projectId,
|
|
220
|
+
id: input.id,
|
|
221
|
+
...(input.limit === undefined ? {} : { limit: normalizeAiLimitQuantity(input.limit) }),
|
|
222
|
+
...(input.enabled === undefined ? {} : { enabled: input.enabled }),
|
|
223
|
+
updatedAt: cloneValidDate(input.updatedAt ?? new Date(), "updatedAt"),
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export function normalizeReserveAiModelCall(input: ReserveAiModelCallInput): {
|
|
228
|
+
readonly identity: AiModelCallReservationIdentity
|
|
229
|
+
readonly subjects: readonly AiLimitSubject[]
|
|
230
|
+
readonly estimates: readonly AiLimitQuantity[]
|
|
231
|
+
readonly period: AiLimitPeriod
|
|
232
|
+
readonly reservedAt: Date
|
|
233
|
+
} {
|
|
234
|
+
const identity = normalizeAiModelCallReservationIdentity(input)
|
|
235
|
+
const reservedAt = cloneValidDate(input.reservedAt ?? new Date(), "reservedAt")
|
|
236
|
+
return {
|
|
237
|
+
identity,
|
|
238
|
+
subjects: normalizeAiLimitSubjects(input.subjects),
|
|
239
|
+
estimates: normalizeAiLimitQuantities(input.estimates, "estimates"),
|
|
240
|
+
period: aiLimitCalendarMonth(reservedAt),
|
|
241
|
+
reservedAt,
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export function normalizeAiModelCallReservationIdentity(
|
|
246
|
+
input: AiModelCallReservationIdentity
|
|
247
|
+
): AiModelCallReservationIdentity {
|
|
248
|
+
assertNonBlank(input.projectId, "projectId")
|
|
249
|
+
assertNonBlank(input.executionId, "executionId")
|
|
250
|
+
if (!Number.isSafeInteger(input.attempt) || input.attempt <= 0) {
|
|
251
|
+
throw new TypeError("[Sixb] AI limit reservation attempt must be a positive safe integer.")
|
|
252
|
+
}
|
|
253
|
+
assertNonBlank(input.callId, "callId")
|
|
254
|
+
return {
|
|
255
|
+
projectId: input.projectId,
|
|
256
|
+
executionId: input.executionId,
|
|
257
|
+
attempt: input.attempt,
|
|
258
|
+
callId: input.callId,
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export function aiModelCallReservationKey(identity: AiModelCallReservationIdentity): string {
|
|
263
|
+
return JSON.stringify([
|
|
264
|
+
identity.projectId,
|
|
265
|
+
identity.executionId,
|
|
266
|
+
identity.attempt,
|
|
267
|
+
identity.callId,
|
|
268
|
+
])
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
export function aiLimitPolicyDimensionKey(
|
|
272
|
+
policy: Pick<AiLimitPolicy, "projectId" | "subject" | "limit">
|
|
273
|
+
): string {
|
|
274
|
+
const amount = normalizeAiLimitAmount(policy.limit)
|
|
275
|
+
return JSON.stringify([
|
|
276
|
+
policy.projectId,
|
|
277
|
+
aiLimitSubjectKey(policy.subject),
|
|
278
|
+
amount.meter,
|
|
279
|
+
amount.currency,
|
|
280
|
+
])
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
export function aiLimitReservationRequestMatches(
|
|
284
|
+
reservation: AiModelCallReservation,
|
|
285
|
+
request: ReturnType<typeof normalizeReserveAiModelCall>
|
|
286
|
+
): boolean {
|
|
287
|
+
return reservation.requestKey === aiLimitReservationRequestKey(request)
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
export function aiLimitReservationRequestKey(
|
|
291
|
+
request: ReturnType<typeof normalizeReserveAiModelCall>
|
|
292
|
+
): string {
|
|
293
|
+
return JSON.stringify([
|
|
294
|
+
request.period.start.toISOString(),
|
|
295
|
+
request.subjects.map(aiLimitSubjectKey),
|
|
296
|
+
request.estimates.map((quantity) => {
|
|
297
|
+
const amount = normalizeAiLimitAmount(quantity)
|
|
298
|
+
return [amount.meter, amount.currency, amount.amount.toString()]
|
|
299
|
+
}),
|
|
300
|
+
])
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
export function aiLimitReservationBuckets(
|
|
304
|
+
policies: readonly AiLimitPolicy[],
|
|
305
|
+
subjects: readonly AiLimitSubject[],
|
|
306
|
+
estimates: readonly AiLimitQuantity[]
|
|
307
|
+
): readonly AiLimitReservationBucket[] {
|
|
308
|
+
const subjectKeys = new Set(subjects.map(aiLimitSubjectKey))
|
|
309
|
+
const estimatesByDimension = new Map(
|
|
310
|
+
estimates.map((estimate) => {
|
|
311
|
+
const amount = normalizeAiLimitAmount(estimate)
|
|
312
|
+
return [aiLimitAmountKey(amount), estimate] as const
|
|
313
|
+
})
|
|
314
|
+
)
|
|
315
|
+
return policies
|
|
316
|
+
.filter((policy) => subjectKeys.has(aiLimitSubjectKey(policy.subject)))
|
|
317
|
+
.flatMap((policy) => {
|
|
318
|
+
const estimate = estimatesByDimension.get(
|
|
319
|
+
aiLimitAmountKey(normalizeAiLimitAmount(policy.limit))
|
|
320
|
+
)
|
|
321
|
+
return estimate ? [{ subject: policy.subject, estimate }] : []
|
|
322
|
+
})
|
|
323
|
+
.sort((left, right) => {
|
|
324
|
+
const subject = aiLimitSubjectKey(left.subject).localeCompare(
|
|
325
|
+
aiLimitSubjectKey(right.subject)
|
|
326
|
+
)
|
|
327
|
+
if (subject !== 0) return subject
|
|
328
|
+
return aiLimitAmountKey(normalizeAiLimitAmount(left.estimate)).localeCompare(
|
|
329
|
+
aiLimitAmountKey(normalizeAiLimitAmount(right.estimate))
|
|
330
|
+
)
|
|
331
|
+
})
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
export function aiLimitAccountingEntryAppliesToSubject(
|
|
335
|
+
entry: AiLimitAccountingEntry,
|
|
336
|
+
subject: AiLimitSubject
|
|
337
|
+
): boolean {
|
|
338
|
+
if (subject.type === "project") return true
|
|
339
|
+
if (subject.type === "group") return entry.requesterGroupIds.includes(subject.id)
|
|
340
|
+
return entry.requester?.type === subject.type && entry.requester.id === subject.id
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
export function aiLimitSubjectsFromAccountingEntry(
|
|
344
|
+
entry: AiLimitAccountingEntry
|
|
345
|
+
): readonly AiLimitSubject[] {
|
|
346
|
+
return normalizeAiLimitSubjects([
|
|
347
|
+
...entry.requesterGroupIds.map((id) => ({ type: "group" as const, id })),
|
|
348
|
+
...(entry.requester ? [entry.requester] : []),
|
|
349
|
+
])
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
export function resolveAiLimitActual(
|
|
353
|
+
entries: readonly AiLimitAccountingEntry[],
|
|
354
|
+
dimension: Pick<NormalizedAiLimitAmount, "meter" | "currency">
|
|
355
|
+
): ResolvedAiLimitActual {
|
|
356
|
+
let amount = 0n
|
|
357
|
+
let accountingStatus: ResolvedAiLimitActual["accountingStatus"] = "complete"
|
|
358
|
+
for (const entry of entries) {
|
|
359
|
+
if (dimension.meter === "tokens.total") {
|
|
360
|
+
if (entry.totalTokens === undefined) {
|
|
361
|
+
accountingStatus = "unavailable"
|
|
362
|
+
} else {
|
|
363
|
+
amount += BigInt(entry.totalTokens)
|
|
364
|
+
}
|
|
365
|
+
continue
|
|
366
|
+
}
|
|
367
|
+
if (
|
|
368
|
+
entry.valuation?.status !== "rated" ||
|
|
369
|
+
entry.valuation.money.currency !== dimension.currency
|
|
370
|
+
) {
|
|
371
|
+
accountingStatus = "unavailable"
|
|
372
|
+
continue
|
|
373
|
+
}
|
|
374
|
+
amount += BigInt(entry.valuation.money.amountNanos)
|
|
375
|
+
}
|
|
376
|
+
return { amount, accountingStatus }
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
export function assertAiLimitAccountingMatchesReservation(
|
|
380
|
+
reservation: AiModelCallReservation,
|
|
381
|
+
entry: AiLimitAccountingEntry
|
|
382
|
+
): void {
|
|
383
|
+
if (
|
|
384
|
+
entry.projectId !== reservation.projectId ||
|
|
385
|
+
entry.executionId !== reservation.executionId ||
|
|
386
|
+
entry.attempt !== reservation.attempt ||
|
|
387
|
+
entry.callId !== reservation.callId
|
|
388
|
+
) {
|
|
389
|
+
throw new AiLimitStorageError(
|
|
390
|
+
"usage_mismatch",
|
|
391
|
+
`[Sixb] AI usage record '${entry.usageRecordId}' does not belong to reservation '${reservation.callId}'.`
|
|
392
|
+
)
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
export function cloneAiLimitPolicy(policy: AiLimitPolicy): AiLimitPolicy {
|
|
397
|
+
return structuredClone(policy)
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
function normalizeAiMoney(money: AiMoney): AiMoney & { readonly currency: "USD" } {
|
|
401
|
+
if (!money || typeof money !== "object") {
|
|
402
|
+
throw new TypeError("[Sixb] AI limit cost amount must be AiMoney.")
|
|
403
|
+
}
|
|
404
|
+
assertNonBlank(money.currency, "cost currency")
|
|
405
|
+
if (money.currency !== "USD") {
|
|
406
|
+
throw new TypeError("[Sixb] AI limit catalog-estimated cost currency must be 'USD'.")
|
|
407
|
+
}
|
|
408
|
+
if (!/^(0|[1-9][0-9]*)$/.test(money.amountNanos)) {
|
|
409
|
+
throw new TypeError(
|
|
410
|
+
"[Sixb] AI limit cost amountNanos must be a canonical non-negative integer string."
|
|
411
|
+
)
|
|
412
|
+
}
|
|
413
|
+
if (BigInt(money.amountNanos) > SIGNED_INT64_MAX) {
|
|
414
|
+
throw new RangeError("[Sixb] AI limit cost amountNanos exceeds the supported range.")
|
|
415
|
+
}
|
|
416
|
+
return { currency: "USD", amountNanos: money.amountNanos }
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
export function assertNonBlank(value: string, label: string): void {
|
|
420
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
421
|
+
throw new TypeError(`[Sixb] AI limit ${label} must be nonblank.`)
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
export function cloneValidDate(value: Date, label: string): Date {
|
|
426
|
+
if (!(value instanceof Date) || !Number.isFinite(value.getTime())) {
|
|
427
|
+
throw new TypeError(`[Sixb] AI limit ${label} must be a valid Date.`)
|
|
428
|
+
}
|
|
429
|
+
return new Date(value)
|
|
430
|
+
}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import type { AiMoney } from "../ai-cost"
|
|
2
|
+
|
|
3
|
+
/** A project-wide, group, or durable requester identity charged for AI model calls. */
|
|
4
|
+
export type AiLimitSubject =
|
|
5
|
+
| { readonly type: "project" }
|
|
6
|
+
| { readonly type: "group"; readonly id: string }
|
|
7
|
+
| { readonly type: "user"; readonly id: string }
|
|
8
|
+
| { readonly type: "serviceAccount"; readonly id: string }
|
|
9
|
+
|
|
10
|
+
/** Aggregate meters supported by the first AI usage-limit release. */
|
|
11
|
+
export type AiLimitMeter = "tokens.total" | "cost.catalogEstimated"
|
|
12
|
+
|
|
13
|
+
/** An exact quantity for one supported meter. */
|
|
14
|
+
export type AiLimitQuantity =
|
|
15
|
+
| { readonly meter: "tokens.total"; readonly amount: number }
|
|
16
|
+
| {
|
|
17
|
+
readonly meter: "cost.catalogEstimated"
|
|
18
|
+
readonly amount: AiMoney & { readonly currency: "USD" }
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type AiLimitPeriodKind = "calendarMonth"
|
|
22
|
+
|
|
23
|
+
/** Inclusive start and exclusive end of one UTC accounting period. */
|
|
24
|
+
export interface AiLimitPeriod {
|
|
25
|
+
readonly kind: AiLimitPeriodKind
|
|
26
|
+
readonly start: Date
|
|
27
|
+
readonly end: Date
|
|
28
|
+
/** The first instant at which a denied call may be admitted in the next period. */
|
|
29
|
+
readonly resetAt: Date
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Editable policy. Consumption is intentionally stored independently from this record. */
|
|
33
|
+
export interface AiLimitPolicy {
|
|
34
|
+
readonly id: string
|
|
35
|
+
readonly projectId: string
|
|
36
|
+
readonly subject: AiLimitSubject
|
|
37
|
+
readonly limit: AiLimitQuantity
|
|
38
|
+
readonly period: AiLimitPeriodKind
|
|
39
|
+
readonly enabled: boolean
|
|
40
|
+
readonly createdAt: Date
|
|
41
|
+
readonly updatedAt: Date
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface CreateAiLimitPolicyInput {
|
|
45
|
+
readonly id: string
|
|
46
|
+
readonly projectId: string
|
|
47
|
+
readonly subject: AiLimitSubject
|
|
48
|
+
readonly limit: AiLimitQuantity
|
|
49
|
+
readonly enabled?: boolean
|
|
50
|
+
readonly createdAt?: Date
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface UpdateAiLimitPolicyInput {
|
|
54
|
+
readonly projectId: string
|
|
55
|
+
readonly id: string
|
|
56
|
+
/** The meter and cost currency are immutable; only the amount may change. */
|
|
57
|
+
readonly limit?: AiLimitQuantity
|
|
58
|
+
readonly enabled?: boolean
|
|
59
|
+
readonly updatedAt?: Date
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface GetAiLimitPolicyInput {
|
|
63
|
+
readonly projectId: string
|
|
64
|
+
readonly id: string
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface DeleteAiLimitPolicyInput extends GetAiLimitPolicyInput {}
|
|
68
|
+
|
|
69
|
+
export interface ListAiLimitPoliciesInput {
|
|
70
|
+
readonly projectId: string
|
|
71
|
+
readonly includeDisabled?: boolean
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Current-period consumption for one policy, all expressed in the policy's meter. */
|
|
75
|
+
export interface AiLimitConsumption {
|
|
76
|
+
readonly actual: AiLimitQuantity
|
|
77
|
+
readonly reserved: AiLimitQuantity
|
|
78
|
+
readonly unknown: AiLimitQuantity
|
|
79
|
+
readonly remaining: AiLimitQuantity
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export interface AiLimitPolicyStatus {
|
|
83
|
+
readonly policy: AiLimitPolicy
|
|
84
|
+
readonly period: AiLimitPeriod
|
|
85
|
+
readonly consumption: AiLimitConsumption
|
|
86
|
+
/** Whether every applicable immutable ledger record could be measured for this policy. */
|
|
87
|
+
readonly accountingStatus: "complete" | "unavailable"
|
|
88
|
+
readonly exhausted: boolean
|
|
89
|
+
/** True only when the caller supplied the current group set and this group is absent. */
|
|
90
|
+
readonly orphaned: boolean
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export interface ListAiLimitPolicyStatusesInput {
|
|
94
|
+
readonly projectId: string
|
|
95
|
+
readonly at?: Date
|
|
96
|
+
readonly includeDisabled?: boolean
|
|
97
|
+
/** Optional current group IDs used to report policies whose snapshotted group disappeared. */
|
|
98
|
+
readonly existingGroupIds?: readonly string[]
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export interface AiModelCallReservationIdentity {
|
|
102
|
+
readonly projectId: string
|
|
103
|
+
readonly executionId: string
|
|
104
|
+
readonly attempt: number
|
|
105
|
+
readonly callId: string
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export interface AiLimitReservationBucket {
|
|
109
|
+
readonly subject: AiLimitSubject
|
|
110
|
+
readonly estimate: AiLimitQuantity
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export type AiModelCallReservationState = "active" | "reconciled" | "unknown"
|
|
114
|
+
|
|
115
|
+
/** Durable reservation for one Sixb-owned provider attempt. */
|
|
116
|
+
export interface AiModelCallReservation extends AiModelCallReservationIdentity {
|
|
117
|
+
/** Only policy dimensions that were applicable at admission time. */
|
|
118
|
+
readonly buckets: readonly AiLimitReservationBucket[]
|
|
119
|
+
/** Canonical admission request used to reject conflicting idempotent replays. */
|
|
120
|
+
readonly requestKey: string
|
|
121
|
+
readonly period: AiLimitPeriod
|
|
122
|
+
readonly state: AiModelCallReservationState
|
|
123
|
+
readonly usageRecordId?: string
|
|
124
|
+
readonly reservedAt: Date
|
|
125
|
+
readonly updatedAt: Date
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export interface ReserveAiModelCallInput extends AiModelCallReservationIdentity {
|
|
129
|
+
/** The project subject is always added, even when omitted here. */
|
|
130
|
+
readonly subjects: readonly AiLimitSubject[]
|
|
131
|
+
readonly estimates: readonly AiLimitQuantity[]
|
|
132
|
+
readonly reservedAt?: Date
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export type ReserveAiModelCallResult =
|
|
136
|
+
| {
|
|
137
|
+
readonly status: "reserved"
|
|
138
|
+
readonly reservation: AiModelCallReservation
|
|
139
|
+
/** False when the exact reservation identity and request were replayed. */
|
|
140
|
+
readonly created: boolean
|
|
141
|
+
}
|
|
142
|
+
| {
|
|
143
|
+
/** No enabled policy matched a supplied subject and estimate. */
|
|
144
|
+
readonly status: "notRequired"
|
|
145
|
+
}
|
|
146
|
+
| {
|
|
147
|
+
/** Exact replay of a reservation that can no longer authorize a provider call. */
|
|
148
|
+
readonly status: "terminal"
|
|
149
|
+
readonly reservation: AiModelCallReservation
|
|
150
|
+
readonly created: false
|
|
151
|
+
}
|
|
152
|
+
| {
|
|
153
|
+
readonly status: "denied"
|
|
154
|
+
/** Every applicable policy that the proposed reservation would exceed. */
|
|
155
|
+
readonly exhaustedPolicies: readonly AiLimitPolicyStatus[]
|
|
156
|
+
readonly resetAt: Date
|
|
157
|
+
}
|
|
158
|
+
| {
|
|
159
|
+
/** Admission failed closed because an applicable policy could not be measured safely. */
|
|
160
|
+
readonly status: "unavailable"
|
|
161
|
+
readonly unavailablePolicies: readonly AiLimitPolicyStatus[]
|
|
162
|
+
readonly reasons: readonly ("missingEstimate" | "incompleteAccounting")[]
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export interface ReconcileAiModelCallInput extends AiModelCallReservationIdentity {
|
|
166
|
+
readonly usageRecordId: string
|
|
167
|
+
readonly reconciledAt?: Date
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export interface MarkAiModelCallReservationUnknownInput extends AiModelCallReservationIdentity {
|
|
171
|
+
readonly markedAt?: Date
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export interface RecordAiModelCallLimitActualsInput {
|
|
175
|
+
readonly projectId: string
|
|
176
|
+
readonly usageRecordId: string
|
|
177
|
+
readonly recordedAt?: Date
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export interface AiLimitStorage {
|
|
181
|
+
createPolicy(input: CreateAiLimitPolicyInput): Promise<AiLimitPolicy>
|
|
182
|
+
updatePolicy(input: UpdateAiLimitPolicyInput): Promise<AiLimitPolicy>
|
|
183
|
+
deletePolicy(input: DeleteAiLimitPolicyInput): Promise<boolean>
|
|
184
|
+
getPolicy(input: GetAiLimitPolicyInput): Promise<AiLimitPolicy | null>
|
|
185
|
+
listPolicies(input: ListAiLimitPoliciesInput): Promise<readonly AiLimitPolicy[]>
|
|
186
|
+
listPolicyStatuses(input: ListAiLimitPolicyStatusesInput): Promise<readonly AiLimitPolicyStatus[]>
|
|
187
|
+
|
|
188
|
+
reserveModelCall(input: ReserveAiModelCallInput): Promise<ReserveAiModelCallResult>
|
|
189
|
+
/** Applies a newly-created immutable usage record to initialized period counters. */
|
|
190
|
+
recordModelCallActuals(input: RecordAiModelCallLimitActualsInput): Promise<void>
|
|
191
|
+
reconcileModelCall(input: ReconcileAiModelCallInput): Promise<AiModelCallReservation>
|
|
192
|
+
markReservationUnknown(
|
|
193
|
+
input: MarkAiModelCallReservationUnknownInput
|
|
194
|
+
): Promise<AiModelCallReservation>
|
|
195
|
+
}
|
|
@@ -144,6 +144,19 @@ export class InMemoryAiUsageStorage implements AiUsageStorage {
|
|
|
144
144
|
replaceMap(this.groupRows, snapshot.groupRows)
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
+
/** @internal Immutable accounting source used by in-memory AI limit enforcement. */
|
|
148
|
+
getRecord(projectId: string, id: string): AiModelCallUsageRecord | null {
|
|
149
|
+
const record = this.records.get(modelCallRecordKey(projectId, id))
|
|
150
|
+
return record ? structuredClone(record) : null
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/** @internal Immutable accounting source used by in-memory AI limit status reads. */
|
|
154
|
+
listRecords(projectId: string): readonly AiModelCallUsageRecord[] {
|
|
155
|
+
return [...this.records.values()]
|
|
156
|
+
.filter((record) => record.projectId === projectId)
|
|
157
|
+
.map((record) => structuredClone(record))
|
|
158
|
+
}
|
|
159
|
+
|
|
147
160
|
private async assertExecutionExists(projectId: string, executionId: string): Promise<void> {
|
|
148
161
|
const execution = await this.executions.getById({ projectId, id: executionId })
|
|
149
162
|
if (execution) return
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { normalizeRequesterGroupIds } from "../../auth/attribution"
|
|
2
2
|
import { assertJsonValue, isPlainRecord } from "../../json"
|
|
3
|
+
import { normalizeModelProviderIds } from "../../models/events"
|
|
4
|
+
import { isModelReasoning } from "../../models/language-model"
|
|
3
5
|
import type { AiModelCallUsageRecord, RecordAiModelCallInput } from "./types"
|
|
4
6
|
import { normalizeAiModelCallUsage } from "./usage"
|
|
5
7
|
|
|
@@ -20,6 +22,7 @@ export function normalizeAiModelCallRecord(input: RecordAiModelCallInput): AiMod
|
|
|
20
22
|
const occurredAt = cloneValidDate(input.occurredAt, "occurredAt")
|
|
21
23
|
const recordedAt = cloneValidDate(input.recordedAt ?? new Date(), "recordedAt")
|
|
22
24
|
const requesterGroupIds = normalizeRequesterGroupIds(input.requesterGroupIds)
|
|
25
|
+
const requestedReasoning = cloneRequestedReasoning(input.requestedReasoning)
|
|
23
26
|
const rawUsage = cloneRawUsage(input.rawUsage)
|
|
24
27
|
|
|
25
28
|
return {
|
|
@@ -30,7 +33,11 @@ export function normalizeAiModelCallRecord(input: RecordAiModelCallInput): AiMod
|
|
|
30
33
|
callId: input.callId,
|
|
31
34
|
requesterGroupIds,
|
|
32
35
|
providerId: input.providerId,
|
|
36
|
+
...(input.providerIds === undefined
|
|
37
|
+
? {}
|
|
38
|
+
: { providerIds: normalizeModelProviderIds(input.providerIds) }),
|
|
33
39
|
requestedModelId: input.requestedModelId,
|
|
40
|
+
...(requestedReasoning === undefined ? {} : { requestedReasoning }),
|
|
34
41
|
...(input.responseModelId === undefined ? {} : { responseModelId: input.responseModelId }),
|
|
35
42
|
responseId: input.responseId,
|
|
36
43
|
usage: normalizeAiModelCallUsage(input.usage),
|
|
@@ -40,6 +47,16 @@ export function normalizeAiModelCallRecord(input: RecordAiModelCallInput): AiMod
|
|
|
40
47
|
}
|
|
41
48
|
}
|
|
42
49
|
|
|
50
|
+
function cloneRequestedReasoning(
|
|
51
|
+
reasoning: RecordAiModelCallInput["requestedReasoning"]
|
|
52
|
+
): RecordAiModelCallInput["requestedReasoning"] {
|
|
53
|
+
if (reasoning === undefined) return undefined
|
|
54
|
+
if (!isModelReasoning(reasoning)) {
|
|
55
|
+
throw new TypeError("[Sixb] AI usage requestedReasoning is invalid.")
|
|
56
|
+
}
|
|
57
|
+
return typeof reasoning === "string" ? reasoning : { budgetTokens: reasoning.budgetTokens }
|
|
58
|
+
}
|
|
59
|
+
|
|
43
60
|
/** Validate a durable execution reference at storage and query boundaries. */
|
|
44
61
|
export function assertAiUsageExecutionId(executionId: string): void {
|
|
45
62
|
assertNonBlank(executionId, "executionId")
|