@alneas/eaos-server 0.0.0-stage → 0.2.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.
- package/CHANGELOG.md +41 -0
- package/LICENSE +21 -0
- package/README.ja.md +49 -0
- package/README.md +46 -2
- package/dist/agentic/agent-jobs.d.ts +333 -0
- package/dist/agentic/agent-jobs.js +15 -0
- package/dist/agentic/agent-jobs.js.map +1 -0
- package/dist/agentic/agent-node.d.ts +40 -0
- package/dist/agentic/agent-node.js +7 -0
- package/dist/agentic/agent-node.js.map +1 -0
- package/dist/agentic/agent-runner.d.ts +33 -0
- package/dist/agentic/agent-runner.js +7 -0
- package/dist/agentic/agent-runner.js.map +1 -0
- package/dist/agentic/ai-broker.d.ts +169 -0
- package/dist/agentic/ai-broker.js +8 -0
- package/dist/agentic/ai-broker.js.map +1 -0
- package/dist/agentic/atomic-checkpointer.d.ts +137 -0
- package/dist/agentic/atomic-checkpointer.js +9 -0
- package/dist/agentic/atomic-checkpointer.js.map +1 -0
- package/dist/agentic/autonomous-worker.d.ts +122 -0
- package/dist/agentic/autonomous-worker.js +10 -0
- package/dist/agentic/autonomous-worker.js.map +1 -0
- package/dist/agentic/event-bridge.d.ts +350 -0
- package/dist/agentic/event-bridge.js +9 -0
- package/dist/agentic/event-bridge.js.map +1 -0
- package/dist/agentic/executor.d.ts +91 -0
- package/dist/agentic/executor.js +12 -0
- package/dist/agentic/executor.js.map +1 -0
- package/dist/agentic/graph-projection.d.ts +119 -0
- package/dist/agentic/graph-projection.js +7 -0
- package/dist/agentic/graph-projection.js.map +1 -0
- package/dist/agentic/graph.d.ts +524 -0
- package/dist/agentic/graph.js +7 -0
- package/dist/agentic/graph.js.map +1 -0
- package/dist/agentic/index.d.ts +28 -0
- package/dist/agentic/index.js +87 -0
- package/dist/agentic/index.js.map +1 -0
- package/dist/agentic/local-runner.d.ts +106 -0
- package/dist/agentic/local-runner.js +7 -0
- package/dist/agentic/local-runner.js.map +1 -0
- package/dist/agentic/remote-executor.d.ts +67 -0
- package/dist/agentic/remote-executor.js +8 -0
- package/dist/agentic/remote-executor.js.map +1 -0
- package/dist/agentic/types.d.ts +157 -0
- package/dist/agentic/types.js +7 -0
- package/dist/agentic/types.js.map +1 -0
- package/dist/agentic/workflow-catalog.d.ts +152 -0
- package/dist/agentic/workflow-catalog.js +7 -0
- package/dist/agentic/workflow-catalog.js.map +1 -0
- package/dist/agentic/workflow-compiler.d.ts +44 -0
- package/dist/agentic/workflow-compiler.js +8 -0
- package/dist/agentic/workflow-compiler.js.map +1 -0
- package/dist/agentic/workflow-coordinator.d.ts +170 -0
- package/dist/agentic/workflow-coordinator.js +8 -0
- package/dist/agentic/workflow-coordinator.js.map +1 -0
- package/dist/agentic/workflow-manager.d.ts +91 -0
- package/dist/agentic/workflow-manager.js +7 -0
- package/dist/agentic/workflow-manager.js.map +1 -0
- package/dist/agentic/workflow-registry.d.ts +334 -0
- package/dist/agentic/workflow-registry.js +7 -0
- package/dist/agentic/workflow-registry.js.map +1 -0
- package/dist/artifacts-CteHmCMI.d.ts +614 -0
- package/dist/auth-hooks/api-key.d.ts +75 -0
- package/dist/auth-hooks/api-key.js +7 -0
- package/dist/auth-hooks/api-key.js.map +1 -0
- package/dist/auth-hooks/index.d.ts +80 -0
- package/dist/auth-hooks/index.js +28 -0
- package/dist/auth-hooks/index.js.map +1 -0
- package/dist/browser-auth/account-memberships.d.ts +213 -0
- package/dist/browser-auth/account-memberships.js +13 -0
- package/dist/browser-auth/account-memberships.js.map +1 -0
- package/dist/browser-auth/index.d.ts +8 -0
- package/dist/browser-auth/index.js +59 -0
- package/dist/browser-auth/index.js.map +1 -0
- package/dist/browser-auth/kratos-session.d.ts +37 -0
- package/dist/browser-auth/kratos-session.js +7 -0
- package/dist/browser-auth/kratos-session.js.map +1 -0
- package/dist/browser-auth/platform-session.d.ts +120 -0
- package/dist/browser-auth/platform-session.js +7 -0
- package/dist/browser-auth/platform-session.js.map +1 -0
- package/dist/browser-auth/public-memberships.d.ts +22 -0
- package/dist/browser-auth/public-memberships.js +7 -0
- package/dist/browser-auth/public-memberships.js.map +1 -0
- package/dist/cache/index.d.ts +181 -0
- package/dist/cache/index.js +197 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/chunk-32746UQZ.js +131 -0
- package/dist/chunk-32746UQZ.js.map +1 -0
- package/dist/chunk-3NLSWP2Y.js +223 -0
- package/dist/chunk-3NLSWP2Y.js.map +1 -0
- package/dist/chunk-3P4XTTQH.js +346 -0
- package/dist/chunk-3P4XTTQH.js.map +1 -0
- package/dist/chunk-3VITSHN3.js +15 -0
- package/dist/chunk-3VITSHN3.js.map +1 -0
- package/dist/chunk-46UWPEW2.js +226 -0
- package/dist/chunk-46UWPEW2.js.map +1 -0
- package/dist/chunk-4BARRLJR.js +180 -0
- package/dist/chunk-4BARRLJR.js.map +1 -0
- package/dist/chunk-4VORUFKR.js +45 -0
- package/dist/chunk-4VORUFKR.js.map +1 -0
- package/dist/chunk-55D4ERWO.js +1 -0
- package/dist/chunk-55D4ERWO.js.map +1 -0
- package/dist/chunk-5TBBZIND.js +18 -0
- package/dist/chunk-5TBBZIND.js.map +1 -0
- package/dist/chunk-5WOZWPZA.js +211 -0
- package/dist/chunk-5WOZWPZA.js.map +1 -0
- package/dist/chunk-6CBVZ6CT.js +168 -0
- package/dist/chunk-6CBVZ6CT.js.map +1 -0
- package/dist/chunk-6XZXYNJR.js +74 -0
- package/dist/chunk-6XZXYNJR.js.map +1 -0
- package/dist/chunk-753HWDSC.js +222 -0
- package/dist/chunk-753HWDSC.js.map +1 -0
- package/dist/chunk-7AHSS7SO.js +81 -0
- package/dist/chunk-7AHSS7SO.js.map +1 -0
- package/dist/chunk-7FTJN4SA.js +1 -0
- package/dist/chunk-7FTJN4SA.js.map +1 -0
- package/dist/chunk-AVDMLTPF.js +24 -0
- package/dist/chunk-AVDMLTPF.js.map +1 -0
- package/dist/chunk-BKAHUEIT.js +95 -0
- package/dist/chunk-BKAHUEIT.js.map +1 -0
- package/dist/chunk-CJ7OFEF7.js +134 -0
- package/dist/chunk-CJ7OFEF7.js.map +1 -0
- package/dist/chunk-EJKWDZIU.js +111 -0
- package/dist/chunk-EJKWDZIU.js.map +1 -0
- package/dist/chunk-F2J6IQ6I.js +247 -0
- package/dist/chunk-F2J6IQ6I.js.map +1 -0
- package/dist/chunk-F3O7CELI.js +23 -0
- package/dist/chunk-F3O7CELI.js.map +1 -0
- package/dist/chunk-F4IITPGX.js +221 -0
- package/dist/chunk-F4IITPGX.js.map +1 -0
- package/dist/chunk-FD6VC2NA.js +66 -0
- package/dist/chunk-FD6VC2NA.js.map +1 -0
- package/dist/chunk-FRRRWAHO.js +14 -0
- package/dist/chunk-FRRRWAHO.js.map +1 -0
- package/dist/chunk-HCKAGLLB.js +17 -0
- package/dist/chunk-HCKAGLLB.js.map +1 -0
- package/dist/chunk-HVC7FG6B.js +191 -0
- package/dist/chunk-HVC7FG6B.js.map +1 -0
- package/dist/chunk-HXFVOR7Z.js +496 -0
- package/dist/chunk-HXFVOR7Z.js.map +1 -0
- package/dist/chunk-IJWYS2PF.js +122 -0
- package/dist/chunk-IJWYS2PF.js.map +1 -0
- package/dist/chunk-INCHXAFK.js +1395 -0
- package/dist/chunk-INCHXAFK.js.map +1 -0
- package/dist/chunk-JT6BRGQM.js +1 -0
- package/dist/chunk-JT6BRGQM.js.map +1 -0
- package/dist/chunk-L6PMAEMB.js +115 -0
- package/dist/chunk-L6PMAEMB.js.map +1 -0
- package/dist/chunk-LOUGW6MU.js +126 -0
- package/dist/chunk-LOUGW6MU.js.map +1 -0
- package/dist/chunk-LYPZPE53.js +129 -0
- package/dist/chunk-LYPZPE53.js.map +1 -0
- package/dist/chunk-NNCCN7JP.js +186 -0
- package/dist/chunk-NNCCN7JP.js.map +1 -0
- package/dist/chunk-PBC3MZUL.js +212 -0
- package/dist/chunk-PBC3MZUL.js.map +1 -0
- package/dist/chunk-R4ADP2DC.js +20 -0
- package/dist/chunk-R4ADP2DC.js.map +1 -0
- package/dist/chunk-RHN4Y6VS.js +44 -0
- package/dist/chunk-RHN4Y6VS.js.map +1 -0
- package/dist/chunk-SDJNYPYK.js +770 -0
- package/dist/chunk-SDJNYPYK.js.map +1 -0
- package/dist/chunk-UGNTCOVR.js +28 -0
- package/dist/chunk-UGNTCOVR.js.map +1 -0
- package/dist/chunk-VC2PCK2S.js +31 -0
- package/dist/chunk-VC2PCK2S.js.map +1 -0
- package/dist/chunk-VF5YDZJC.js +305 -0
- package/dist/chunk-VF5YDZJC.js.map +1 -0
- package/dist/chunk-VISRDVTK.js +675 -0
- package/dist/chunk-VISRDVTK.js.map +1 -0
- package/dist/chunk-W6O3LVBY.js +102 -0
- package/dist/chunk-W6O3LVBY.js.map +1 -0
- package/dist/chunk-WFEAKJLR.js +47 -0
- package/dist/chunk-WFEAKJLR.js.map +1 -0
- package/dist/chunk-XIEY2OF4.js +67 -0
- package/dist/chunk-XIEY2OF4.js.map +1 -0
- package/dist/chunk-XITLHDG3.js +37 -0
- package/dist/chunk-XITLHDG3.js.map +1 -0
- package/dist/chunk-XMWPYZWZ.js +61 -0
- package/dist/chunk-XMWPYZWZ.js.map +1 -0
- package/dist/chunk-XUP6CNOM.js +34 -0
- package/dist/chunk-XUP6CNOM.js.map +1 -0
- package/dist/chunk-YABTQZDJ.js +25 -0
- package/dist/chunk-YABTQZDJ.js.map +1 -0
- package/dist/chunk-YMHVRBUU.js +199 -0
- package/dist/chunk-YMHVRBUU.js.map +1 -0
- package/dist/chunk-YMJ7BRKU.js +510 -0
- package/dist/chunk-YMJ7BRKU.js.map +1 -0
- package/dist/chunk-ZC3XWU7B.js +28 -0
- package/dist/chunk-ZC3XWU7B.js.map +1 -0
- package/dist/chunk-ZHMTD5KV.js +90 -0
- package/dist/chunk-ZHMTD5KV.js.map +1 -0
- package/dist/chunk-ZWZDLOE7.js +160 -0
- package/dist/chunk-ZWZDLOE7.js.map +1 -0
- package/dist/db-package/db/local-first-sqlite-adapter.d.ts +432 -0
- package/dist/db-package/db/local-first-sqlite-adapter.js +7 -0
- package/dist/db-package/db/local-first-sqlite-adapter.js.map +1 -0
- package/dist/db-package/index.d.ts +7 -0
- package/dist/db-package/index.js +16 -0
- package/dist/db-package/index.js.map +1 -0
- package/dist/db-package/migration/aggregator.d.ts +86 -0
- package/dist/db-package/migration/aggregator.js +7 -0
- package/dist/db-package/migration/aggregator.js.map +1 -0
- package/dist/db-package/migration/index.d.ts +3 -0
- package/dist/db-package/migration/index.js +8 -0
- package/dist/db-package/migration/index.js.map +1 -0
- package/dist/engine.d.ts +205 -0
- package/dist/engine.js +20 -0
- package/dist/engine.js.map +1 -0
- package/dist/entitlements/index.d.ts +313 -0
- package/dist/entitlements/index.js +23 -0
- package/dist/entitlements/index.js.map +1 -0
- package/dist/execution/chat.d.ts +7 -0
- package/dist/execution/chat.js +7 -0
- package/dist/execution/chat.js.map +1 -0
- package/dist/execution/index.d.ts +342 -0
- package/dist/execution/index.js +66 -0
- package/dist/execution/index.js.map +1 -0
- package/dist/execution/tool-agent.d.ts +7 -0
- package/dist/execution/tool-agent.js +8 -0
- package/dist/execution/tool-agent.js.map +1 -0
- package/dist/extensions/index.d.ts +172 -0
- package/dist/extensions/index.js +95 -0
- package/dist/extensions/index.js.map +1 -0
- package/dist/health/index.d.ts +35 -0
- package/dist/health/index.js +7 -0
- package/dist/health/index.js.map +1 -0
- package/dist/index.d.ts +43 -0
- package/dist/index.js +161 -0
- package/dist/index.js.map +1 -0
- package/dist/lifecycle/index.d.ts +133 -0
- package/dist/lifecycle/index.js +13 -0
- package/dist/lifecycle/index.js.map +1 -0
- package/dist/lifecycle-engine/backend-migration.d.ts +2 -0
- package/dist/lifecycle-engine/backend-migration.js +11 -0
- package/dist/lifecycle-engine/backend-migration.js.map +1 -0
- package/dist/lifecycle-engine/baseline.d.ts +2 -0
- package/dist/lifecycle-engine/baseline.js +9 -0
- package/dist/lifecycle-engine/baseline.js.map +1 -0
- package/dist/lifecycle-engine/index.d.ts +1497 -0
- package/dist/lifecycle-engine/index.js +41 -0
- package/dist/lifecycle-engine/index.js.map +1 -0
- package/dist/lifecycle-engine/platform/artifacts.d.ts +4 -0
- package/dist/lifecycle-engine/platform/artifacts.js +7 -0
- package/dist/lifecycle-engine/platform/artifacts.js.map +1 -0
- package/dist/lifecycle-engine/platform/control-plane.d.ts +12 -0
- package/dist/lifecycle-engine/platform/control-plane.js +2 -0
- package/dist/lifecycle-engine/platform/control-plane.js.map +1 -0
- package/dist/lifecycle-engine/platform/database-router.d.ts +118 -0
- package/dist/lifecycle-engine/platform/database-router.js +7 -0
- package/dist/lifecycle-engine/platform/database-router.js.map +1 -0
- package/dist/lifecycle-engine/platform/deployment-placements.d.ts +464 -0
- package/dist/lifecycle-engine/platform/deployment-placements.js +16 -0
- package/dist/lifecycle-engine/platform/deployment-placements.js.map +1 -0
- package/dist/lifecycle-engine/platform/deployment.d.ts +4 -0
- package/dist/lifecycle-engine/platform/deployment.js +17 -0
- package/dist/lifecycle-engine/platform/deployment.js.map +1 -0
- package/dist/lifecycle-engine/platform/index.d.ts +737 -0
- package/dist/lifecycle-engine/platform/index.js +60 -0
- package/dist/lifecycle-engine/platform/index.js.map +1 -0
- package/dist/lifecycle-engine/platform/runtime.d.ts +80 -0
- package/dist/lifecycle-engine/platform/runtime.js +11 -0
- package/dist/lifecycle-engine/platform/runtime.js.map +1 -0
- package/dist/lifecycle-engine/platform/site-publication.d.ts +102 -0
- package/dist/lifecycle-engine/platform/site-publication.js +7 -0
- package/dist/lifecycle-engine/platform/site-publication.js.map +1 -0
- package/dist/lifecycle-engine/platform/user-directory.d.ts +139 -0
- package/dist/lifecycle-engine/platform/user-directory.js +13 -0
- package/dist/lifecycle-engine/platform/user-directory.js.map +1 -0
- package/dist/mcp.d.ts +92 -0
- package/dist/mcp.js +10 -0
- package/dist/mcp.js.map +1 -0
- package/dist/middleware/auth.d.ts +118 -0
- package/dist/middleware/auth.js +7 -0
- package/dist/middleware/auth.js.map +1 -0
- package/dist/middleware/error-handler.d.ts +35 -0
- package/dist/middleware/error-handler.js +7 -0
- package/dist/middleware/error-handler.js.map +1 -0
- package/dist/middleware/module-guard.d.ts +33 -0
- package/dist/middleware/module-guard.js +7 -0
- package/dist/middleware/module-guard.js.map +1 -0
- package/dist/platform-admin/index.d.ts +37 -0
- package/dist/platform-admin/index.js +11 -0
- package/dist/platform-admin/index.js.map +1 -0
- package/dist/platform-admin/store.d.ts +346 -0
- package/dist/platform-admin/store.js +7 -0
- package/dist/platform-admin/store.js.map +1 -0
- package/dist/plugin-data/annotations.d.ts +6 -0
- package/dist/plugin-data/annotations.js +12 -0
- package/dist/plugin-data/annotations.js.map +1 -0
- package/dist/plugin-data/atomic-context.d.ts +41 -0
- package/dist/plugin-data/atomic-context.js +9 -0
- package/dist/plugin-data/atomic-context.js.map +1 -0
- package/dist/plugin-data/atomic.d.ts +6 -0
- package/dist/plugin-data/atomic.js +26 -0
- package/dist/plugin-data/atomic.js.map +1 -0
- package/dist/plugin-data/audit.d.ts +6 -0
- package/dist/plugin-data/audit.js +12 -0
- package/dist/plugin-data/audit.js.map +1 -0
- package/dist/plugin-data/commands.d.ts +6 -0
- package/dist/plugin-data/commands.js +8 -0
- package/dist/plugin-data/commands.js.map +1 -0
- package/dist/plugin-data/composite.d.ts +6 -0
- package/dist/plugin-data/composite.js +8 -0
- package/dist/plugin-data/composite.js.map +1 -0
- package/dist/plugin-data/delivery.d.ts +6 -0
- package/dist/plugin-data/delivery.js +16 -0
- package/dist/plugin-data/delivery.js.map +1 -0
- package/dist/plugin-data/index.d.ts +2798 -0
- package/dist/plugin-data/index.js +102 -0
- package/dist/plugin-data/index.js.map +1 -0
- package/dist/plugin-data/json-documents.d.ts +6 -0
- package/dist/plugin-data/json-documents.js +16 -0
- package/dist/plugin-data/json-documents.js.map +1 -0
- package/dist/plugin-data/outbox.d.ts +6 -0
- package/dist/plugin-data/outbox.js +16 -0
- package/dist/plugin-data/outbox.js.map +1 -0
- package/dist/plugin-data/scoped-records.d.ts +6 -0
- package/dist/plugin-data/scoped-records.js +10 -0
- package/dist/plugin-data/scoped-records.js.map +1 -0
- package/dist/plugin-sdk.d.ts +41 -0
- package/dist/plugin-sdk.js +10 -0
- package/dist/plugin-sdk.js.map +1 -0
- package/dist/sql-lifecycle/index.d.ts +138 -0
- package/dist/sql-lifecycle/index.js +167 -0
- package/dist/sql-lifecycle/index.js.map +1 -0
- package/dist/storage/index.d.ts +2 -0
- package/dist/storage/index.js +13 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/s3-compatible.d.ts +139 -0
- package/dist/storage/s3-compatible.js +11 -0
- package/dist/storage/s3-compatible.js.map +1 -0
- package/dist/tenant.d.ts +108 -0
- package/dist/tenant.js +9 -0
- package/dist/tenant.js.map +1 -0
- package/dist/workspace-context.d.ts +119 -0
- package/dist/workspace-context.js +9 -0
- package/dist/workspace-context.js.map +1 -0
- package/docs/api.md +30560 -0
- package/docs/db/README.md +49 -0
- package/docs/db/docs/api.md +1613 -0
- package/docs/db/docs/guide.md +47 -0
- package/docs/entitlements.md +60 -0
- package/docs/guide.md +92 -0
- package/docs/index.md +57 -0
- package/docs/ja/db/README.md +46 -0
- package/docs/ja/db/docs/guide.md +53 -0
- package/docs/ja/guide.md +46 -0
- package/docs/ja/lifecycle/README.md +46 -0
- package/docs/ja/lifecycle/docs/guide.md +45 -0
- package/docs/ja/storage/README.md +46 -0
- package/docs/ja/storage/docs/guide.md +43 -0
- package/docs/lifecycle/README.md +49 -0
- package/docs/lifecycle/docs/api.md +3770 -0
- package/docs/lifecycle/docs/baseline.md +50 -0
- package/docs/lifecycle/docs/guide.md +47 -0
- package/docs/storage/README.md +49 -0
- package/docs/storage/docs/api.md +470 -0
- package/docs/storage/docs/guide.md +47 -0
- package/package.json +354 -4
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// src/browser-auth/platform-session.ts
|
|
2
|
+
function createPlatformSessionResolver(options) {
|
|
3
|
+
const requests = /* @__PURE__ */ new WeakMap();
|
|
4
|
+
return (context, resolution) => {
|
|
5
|
+
const cached = requests.get(context);
|
|
6
|
+
if (cached && !resolution?.refresh) return cached;
|
|
7
|
+
const result = (async () => {
|
|
8
|
+
const bearer = context.req.header("Authorization");
|
|
9
|
+
if (bearer && !/^Bearer [^\s]+$/.test(bearer)) return null;
|
|
10
|
+
const identity = await options.verify({ cookie: context.req.header("Cookie"), sessionToken: bearer?.slice(7) ?? context.req.header("X-Session-Token") });
|
|
11
|
+
if (!identity) return null;
|
|
12
|
+
const tenantId = context.req.header("X-Tenant-Id");
|
|
13
|
+
if (tenantId && !/^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/.test(tenantId)) return null;
|
|
14
|
+
const matches = await options.memberships(identity.userId, tenantId, identity.identity);
|
|
15
|
+
if (matches.length !== 1) return null;
|
|
16
|
+
const member = matches[0];
|
|
17
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/.test(member.tenantId) || tenantId && member.tenantId !== tenantId) return null;
|
|
18
|
+
if (!Array.isArray(member.roles) || !Array.isArray(member.enabledModules)) throw new Error("Invalid membership");
|
|
19
|
+
if (![...member.roles, ...member.enabledModules].every((x) => typeof x === "string" && x.length > 0)) throw new Error("Invalid membership");
|
|
20
|
+
const state = await options.store.read();
|
|
21
|
+
if (!state.platform.tenants[member.tenantId]?.active) return null;
|
|
22
|
+
const expected = options.targetFor(member.tenantId);
|
|
23
|
+
if (state.platform.placements[member.tenantId]?.backendId !== expected.id) throw new Error("Tenant backend placement mismatch");
|
|
24
|
+
return { userId: identity.userId, tenantId: member.tenantId, roles: [...member.roles], enabledModules: [...member.enabledModules] };
|
|
25
|
+
})();
|
|
26
|
+
requests.set(context, result);
|
|
27
|
+
return result;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export {
|
|
32
|
+
createPlatformSessionResolver
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=chunk-XUP6CNOM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/browser-auth/platform-session.ts"],"sourcesContent":["import type { Context } from 'hono'\nimport { createKratosSessionVerifier, type BrowserSession } from './index'\nimport type { LifecycleStore, BackendTarget } from '@alneas/eaos-server/lifecycle-engine'\n\n/**\n * Verified tenant membership candidate supplied to {@link createPlatformSessionResolver}.\n */\nexport interface Membership {\n /** Tenant ID matching the selected header, if provided; validated as a 1–128-character scope identifier. */\n tenantId: string\n /** Verified role names, each a nonempty string. */\n roles: string[]\n /** Verified entitlement names, each a nonempty string. */\n enabledModules: string[]\n}\n/**\n * Combines a verified Kratos identity, unambiguous membership, active tenant, and expected backend placement.\n * @param options - verify checks credentials; memberships receives verified userId, optional selected tenant ID, and provider identity and resolves candidate memberships; store supplies lifecycle state; targetFor synchronously resolves the expected backend for a selected tenant.\n * @returns A resolver accepting Hono context and optional refresh flag. It resolves a BrowserSession or null for invalid credentials/selection, ambiguous membership, or inactive tenant. Each context caches the in-flight/result Promise unless refresh is true.\n * @throws The resolver rejects verifier, membership, store, and targetFor errors, malformed membership fields, or backend placement mismatch. Rejected Promises are cached until refresh.\n * @remarks Authorization accepts only the exact Bearer syntax with one space and a nonwhitespace token. Bearer token takes precedence over X-Session-Token; the verifier gives session tokens precedence over cookies. X-Tenant-Id selects a candidate but never grants membership. No default tenant or role is invented. The WeakMap cache is per resolver/context; refresh starts another lookup without cancelling previous work.\n * @example\n * ```typescript\n * import { createPlatformSessionResolver } from \"@alneas/eaos-server/browser-auth/platform-session\";\n * export function hostSessionResolver(options: Parameters<typeof createPlatformSessionResolver>[0]) {\n * // Supply verified membership reads, lifecycle store, and backend routing.\n * return createPlatformSessionResolver(options);\n * }\n * ```\n */\nexport function createPlatformSessionResolver(options: {\n /**\n * Server whoami verifier receiving cookie/session-token credentials; token transport takes precedence over cookies.\n */\n verify: ReturnType<typeof createKratosSessionVerifier>\n /**\n * Host callback receiving verified user ID, optional requested tenant, and provider identity; must resolve exactly one authorized membership or resolution returns null.\n */\n memberships: (userId: string, tenantId: string | undefined, identity: Record<string, unknown>) => Promise<Membership[]>\n /**\n * Authoritative lifecycle store used to require an active tenant and its expected backend placement.\n */\n store: LifecycleStore\n /**\n * Synchronous host backend selector for the verified membership tenant; an ID differing from lifecycle placement rejects resolution.\n */\n targetFor: (tenantId: string) => BackendTarget\n}) {\n const requests = new WeakMap<Context, Promise<BrowserSession | null>>()\n return (context: Context, resolution?: { refresh?: boolean }): Promise<BrowserSession | null> => {\n const cached = requests.get(context)\n if (cached && !resolution?.refresh) return cached\n const result = (async () => {\n const bearer = context.req.header('Authorization')\n if (bearer && !/^Bearer [^\\s]+$/.test(bearer)) return null\n const identity = await options.verify({ cookie: context.req.header('Cookie'), sessionToken: bearer?.slice(7) ?? context.req.header('X-Session-Token') })\n if (!identity) return null\n const tenantId = context.req.header('X-Tenant-Id')\n if (tenantId && !/^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/.test(tenantId)) return null\n const matches = await options.memberships(identity.userId, tenantId, identity.identity)\n if (matches.length !== 1) return null // No default tenant or role for ambiguous/unregistered users.\n const member = matches[0]\n if (!/^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/.test(member.tenantId) || (tenantId && member.tenantId !== tenantId)) return null\n if (!Array.isArray(member.roles) || !Array.isArray(member.enabledModules)) throw new Error('Invalid membership')\n if (![...member.roles, ...member.enabledModules].every(x => typeof x === 'string' && x.length > 0)) throw new Error('Invalid membership')\n const state = await options.store.read()\n if (!state.platform.tenants[member.tenantId]?.active) return null\n const expected = options.targetFor(member.tenantId)\n if (state.platform.placements[member.tenantId]?.backendId !== expected.id) throw new Error('Tenant backend placement mismatch')\n return { userId: identity.userId, tenantId: member.tenantId, roles: [...member.roles], enabledModules: [...member.enabledModules] }\n })()\n requests.set(context, result)\n return result\n }\n}\n"],"mappings":";AA8BO,SAAS,8BAA8B,SAiB3C;AACD,QAAM,WAAW,oBAAI,QAAiD;AACtE,SAAO,CAAC,SAAkB,eAAuE;AAC/F,UAAM,SAAS,SAAS,IAAI,OAAO;AACnC,QAAI,UAAU,CAAC,YAAY,QAAS,QAAO;AAC3C,UAAM,UAAU,YAAY;AAC1B,YAAM,SAAS,QAAQ,IAAI,OAAO,eAAe;AACjD,UAAI,UAAU,CAAC,kBAAkB,KAAK,MAAM,EAAG,QAAO;AACtD,YAAM,WAAW,MAAM,QAAQ,OAAO,EAAE,QAAQ,QAAQ,IAAI,OAAO,QAAQ,GAAG,cAAc,QAAQ,MAAM,CAAC,KAAK,QAAQ,IAAI,OAAO,iBAAiB,EAAE,CAAC;AACvJ,UAAI,CAAC,SAAU,QAAO;AACtB,YAAM,WAAW,QAAQ,IAAI,OAAO,aAAa;AACjD,UAAI,YAAY,CAAC,oCAAoC,KAAK,QAAQ,EAAG,QAAO;AAC5E,YAAM,UAAU,MAAM,QAAQ,YAAY,SAAS,QAAQ,UAAU,SAAS,QAAQ;AACtF,UAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,YAAM,SAAS,QAAQ,CAAC;AACxB,UAAI,CAAC,oCAAoC,KAAK,OAAO,QAAQ,KAAM,YAAY,OAAO,aAAa,SAAW,QAAO;AACrH,UAAI,CAAC,MAAM,QAAQ,OAAO,KAAK,KAAK,CAAC,MAAM,QAAQ,OAAO,cAAc,EAAG,OAAM,IAAI,MAAM,oBAAoB;AAC/G,UAAI,CAAC,CAAC,GAAG,OAAO,OAAO,GAAG,OAAO,cAAc,EAAE,MAAM,OAAK,OAAO,MAAM,YAAY,EAAE,SAAS,CAAC,EAAG,OAAM,IAAI,MAAM,oBAAoB;AACxI,YAAM,QAAQ,MAAM,QAAQ,MAAM,KAAK;AACvC,UAAI,CAAC,MAAM,SAAS,QAAQ,OAAO,QAAQ,GAAG,OAAQ,QAAO;AAC7D,YAAM,WAAW,QAAQ,UAAU,OAAO,QAAQ;AAClD,UAAI,MAAM,SAAS,WAAW,OAAO,QAAQ,GAAG,cAAc,SAAS,GAAI,OAAM,IAAI,MAAM,mCAAmC;AAC9H,aAAO,EAAE,QAAQ,SAAS,QAAQ,UAAU,OAAO,UAAU,OAAO,CAAC,GAAG,OAAO,KAAK,GAAG,gBAAgB,CAAC,GAAG,OAAO,cAAc,EAAE;AAAA,IACpI,GAAG;AACH,aAAS,IAAI,SAAS,MAAM;AAC5B,WAAO;AAAA,EACT;AACF;","names":[]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// src/agentic/types.ts
|
|
2
|
+
var ServerAgentExecutionError = class extends Error {
|
|
3
|
+
/** Classification used by runner normalization and durable retry handling. */
|
|
4
|
+
failureCode;
|
|
5
|
+
/** Host retry advice; true does not itself retry or make execution idempotent. */
|
|
6
|
+
retryable;
|
|
7
|
+
/**
|
|
8
|
+
* Creates a runtime failure retaining an optional underlying cause.
|
|
9
|
+
* @param message - Human-readable failure description.
|
|
10
|
+
* @param failureCode - Stable classification for caller retry policy.
|
|
11
|
+
* @param retryable - Whether the caller may consider retrying this failure.
|
|
12
|
+
* @param options - Optional cause; omission does not attach an error cause.
|
|
13
|
+
*/
|
|
14
|
+
constructor(message, failureCode, retryable, options) {
|
|
15
|
+
super(message, options?.cause === void 0 ? void 0 : { cause: options.cause });
|
|
16
|
+
this.name = "ServerAgentExecutionError";
|
|
17
|
+
this.failureCode = failureCode;
|
|
18
|
+
this.retryable = retryable;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export {
|
|
23
|
+
ServerAgentExecutionError
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=chunk-YABTQZDJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/agentic/types.ts"],"sourcesContent":["import type { AgentJobKind, AgentRuntimeResourcePolicy, ApprovalLevel, RiskLevel, WorkflowAgentFailureCode, WorkflowAgentToolMode } from '@alneas/eaos-core'\n\n/**\n * Runtime selector used to dispatch server tasks to built-in or host-provided executors.\n * @see ServerAgentExecutor for the host adapter contract.\n */\nexport type ServerAgentWorkerType = 'goose' | 'hermes_agent' | 'litellm' | 'local_cli' | 'local_mlx' | 'external_no_training' | 'custom'\n/**\n * Selects server-side queue execution or authenticated local runner pull delivery.\n * @see ServerAgentExecutionContext.\n */\nexport type ServerAgentDispatchMode = 'server-queue' | 'local-pull'\n\n/**\n * Host-admitted task passed to an agent runtime; tenant/user claims must already be verified.\n * @see ServerAgentExecutor for a complete adapter example.\n */\nexport interface ServerAgentTaskRequest {\n /** Stable task identifier used for result and checkpoint binding. */\n id: string\n /** Verified tenant ID; never accepted directly as an authenticated request-body claim. */\n tenantId: string\n /** Verified submitting user ID. */\n userId: string\n /** Nonblank task label; ServerAutonomousWorker limits this to 500 characters. */\n title: string\n /** Nonblank runtime instructions; ServerAutonomousWorker limits this to 1000000 characters. */\n instructions: string\n /** Selected built-in or host runtime adapter key. */\n workerType: ServerAgentWorkerType\n /** Why the agent is running; not limited to task-graph workflows. */\n jobKind?: AgentJobKind\n /** Optional domain context; interpretation belongs to the executor. */\n context?: Record<string, unknown>\n /** Host-verified workflow context propagated to the external runtime. */\n executionContext?: ServerAgentExecutionContext\n /** Framework-selected resource policy. Callers cannot loosen this policy. */\n runtimePolicy?: AgentRuntimeResourcePolicy\n /** Optional execution timeout in milliseconds; built-in executors default to 60000 and accept safe integers from 1 to 3600000. */\n timeoutMs?: number\n}\n\n/**\n * Host-selected workflow, correlation, tool scope, and local-runner bindings sent to the runtime.\n * @see ServerAgentTaskRequest.\n */\nexport interface ServerAgentExecutionContext {\n /** Optional workflow/session association. */\n workflowId?: string\n /** Optional host tracing identifier. */\n correlationId?: string\n /** Optional host deduplication key; propagation alone does not enforce idempotency. */\n idempotencyKey?: string\n /** Optional workflow tool-execution mode admitted by the host. */\n toolMode?: WorkflowAgentToolMode\n /** Optional allowlisted tool names; runtime adapters must enforce the intended boundary. */\n allowedToolNames?: readonly string[]\n /** Selected by the server broker; clients cannot override it. */\n routeId?: string\n /** Optional delivery mode; local-pull jobs are claimed by authenticated local runners. */\n dispatchMode?: ServerAgentDispatchMode\n /** User/runner binding for local subscription or MLX execution. */\n runnerId?: string\n}\n\n/**\n * Normalized runtime outcome; FAILED and PENDING_APPROVAL are returned data rather than successful output.\n * @see ServerAgentExecutor.\n */\nexport interface ServerAgentTaskResult {\n /** Task identifier to which this result belongs. */\n taskId: string\n /** COMPLETED has runtime output; PENDING_APPROVAL awaits a host decision; FAILED records a rejected or failed run. */\n status: 'COMPLETED' | 'PENDING_APPROVAL' | 'FAILED'\n /** Runtime text when available; omitted on failures and pending approval. */\n output?: string\n /** Optional failure message for FAILED results. */\n error?: string\n /** Stable failure classification for durable retry/circuit-breaker handling. */\n failureCode?: WorkflowAgentFailureCode\n /** Optional retry advice; absence leaves retry policy to the caller. */\n retryable?: boolean\n /** Optional generated approval binding for PENDING_APPROVAL. */\n approvalTicketId?: string\n /** Optional human-approval level returned by the gatekeeper. */\n approvalLevel?: ApprovalLevel\n /** Optional risk classification returned by the gatekeeper. */\n riskLevel?: RiskLevel\n /** Elapsed wall-clock milliseconds for this attempt. */\n durationMs: number\n}\n\n/**\n * Carries stable failure classification and retry advice from runtime adapters to queue coordination.\n * @example\n * ```typescript\n * import { ServerAgentExecutionError } from \"@alneas/eaos-server/agentic/types\";\n * const error = new ServerAgentExecutionError(\"Runtime unavailable\", \"AGENT_UNAVAILABLE\", true);\n * console.log(error.failureCode, error.retryable);\n * ```\n */\nexport class ServerAgentExecutionError extends Error {\n /** Classification used by runner normalization and durable retry handling. */\n readonly failureCode: WorkflowAgentFailureCode\n /** Host retry advice; true does not itself retry or make execution idempotent. */\n readonly retryable: boolean\n\n /**\n * Creates a runtime failure retaining an optional underlying cause.\n * @param message - Human-readable failure description.\n * @param failureCode - Stable classification for caller retry policy.\n * @param retryable - Whether the caller may consider retrying this failure.\n * @param options - Optional cause; omission does not attach an error cause.\n */\n constructor(message: string, failureCode: WorkflowAgentFailureCode, retryable: boolean, options?: { \n /**\n * Optional underlying error attached through the standard Error cause option; omission leaves the cause unset.\n */\n cause?: unknown }) {\n super(message, options?.cause === undefined ? undefined : { cause: options.cause })\n this.name = 'ServerAgentExecutionError'\n this.failureCode = failureCode\n this.retryable = retryable\n }\n}\n\n/**\n * Host- or plugin-owned agent execution adapter.\n *\n * The server owns admission, authorization and result normalization; the\n * adapter owns the configured runtime (OpenCode, Codex, Goose, LiteLLM, etc.).\n * @param request - Verified task and execution context; adapters must enforce host runtime/tool boundaries.\n * @returns Runtime text output, which is not permission to perform business side effects.\n * @throws Reject for unavailable, failed, timed-out, or invalid runtime work; ServerAgentExecutionError preserves classification and retry advice.\n * @example\n * ```typescript\n * import type { ServerAgentExecutor } from \"@alneas/eaos-server/agentic/types\";\n * export function instrument(execute: ServerAgentExecutor): ServerAgentExecutor {\n * return async request => execute(structuredClone(request));\n * }\n * ```\n */\nexport type ServerAgentExecutor = (request: ServerAgentTaskRequest) => Promise<string>\n\n/**\n * Host-verified approval decision submitted against a pending task checkpoint.\n * @remarks The host authenticates the approver and verifies role authority before passing this payload to a coordinator.\n * @see ServerAgentTaskResult.\n */\nexport interface ServerApprovalCallbackPayload {\n /** Task checkpoint identifier whose approval is being decided. */\n taskId: string\n /** Optional external ticket binding; when supplied it must match the checkpoint. */\n approvalId?: string\n /** Optional binding hash for clients that persist the approval payload. */\n bindingHash?: string\n /** True to approve; false to reject the pending work. */\n approved: boolean\n /** Authenticated host approver identifier. */\n approverId: string\n /** Verified role used for approval authorization. */\n approverRole: string\n /** Optional human decision note. */\n comment?: string\n}\n"],"mappings":";AAqGO,IAAM,4BAAN,cAAwC,MAAM;AAAA;AAAA,EAE1C;AAAA;AAAA,EAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAST,YAAY,SAAiB,aAAuC,WAAoB,SAIrE;AACjB,UAAM,SAAS,SAAS,UAAU,SAAY,SAAY,EAAE,OAAO,QAAQ,MAAM,CAAC;AAClF,SAAK,OAAO;AACZ,SAAK,cAAc;AACnB,SAAK,YAAY;AAAA,EACnB;AACF;","names":[]}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
// src/execution/chat.ts
|
|
2
|
+
function createChatClient(options) {
|
|
3
|
+
const adapter = options.adapter, authorize = options.authorize, tools = options.tools;
|
|
4
|
+
const parameters = structuredClone(options.parameters), governance = options.governance, registry = options.modelRegistry;
|
|
5
|
+
const modelAdapters = Object.freeze(Object.fromEntries(Object.entries(options.modelAdapters ?? {}).map(([model, transport]) => {
|
|
6
|
+
if (typeof transport?.stream !== "function") throw new Error("Invalid AI model adapter binding");
|
|
7
|
+
return [model, Object.freeze({ id: transport.id, capabilities: Object.freeze({ ...transport.capabilities }), stream: transport.stream.bind(transport) })];
|
|
8
|
+
})));
|
|
9
|
+
if (registry && !options.modelAdapters) throw new Error("AI model adapter bindings required");
|
|
10
|
+
if (parameters !== void 0 && (!parameters || typeof parameters !== "object" || Array.isArray(parameters) || Object.keys(parameters).some((key) => ["model", "messages", "tools", "stream"].includes(key)))) throw new Error("Invalid or reserved chat parameters");
|
|
11
|
+
const timeout = options.timeoutMs ?? 3e4, maxInput = options.maxInputChars ?? 2e5, maxOutput = options.maxOutputChars ?? 1e5, maxEvents = options.maxEvents ?? 1e4;
|
|
12
|
+
for (const [value, max] of [[timeout, 36e5], [maxInput, 7e6], [maxOutput, 1e7], [maxEvents, 1e5]]) if (!Number.isSafeInteger(value) || value < 1 || value > max) throw new Error("Invalid chat limit");
|
|
13
|
+
if (typeof adapter?.stream !== "function" || typeof authorize !== "function" || tools !== void 0 && typeof tools !== "function") throw new Error("Chat adapter and authorization required");
|
|
14
|
+
return {
|
|
15
|
+
/**
|
|
16
|
+
* Request one bounded completion for the current actor.
|
|
17
|
+
* @param principal - Verified nonblank tenant/user identity; copied before invoking host callbacks.
|
|
18
|
+
* @param input - One to 1000 messages, optional cancellation, and explicit none/catalog tool disclosure.
|
|
19
|
+
* @returns Assistant data only after final live authorization; tools remain unexecuted requests.
|
|
20
|
+
* @throws Rejects invalid requests, governance/provider failure, revocation, limits or cancellation.
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* import { createChatClient } from '@alneas/eaos-server/execution/chat';
|
|
24
|
+
* export function complete(client: ReturnType<typeof createChatClient>, ...args: Parameters<typeof client.complete>) {
|
|
25
|
+
* return client.complete(...args);
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
async complete(principal, input) {
|
|
30
|
+
const p = structuredClone(principal);
|
|
31
|
+
if (!p || [p.tenantId, p.userId].some((v) => typeof v !== "string" || !v.trim())) throw new Error("Chat access denied");
|
|
32
|
+
if (!Array.isArray(input?.messages) || !input.messages.length || input.messages.length > 1e3 || Object.keys(input).some((k) => !["messages", "signal", "tools"].includes(k)) || input.tools !== void 0 && !["none", "catalog"].includes(input.tools)) throw new Error("Invalid chat history or options");
|
|
33
|
+
let messages = structuredClone(input.messages);
|
|
34
|
+
const toolMode = input.tools, traceId = crypto.randomUUID();
|
|
35
|
+
let sensitivityLevel, usage, selectedModelId;
|
|
36
|
+
let attemptStarted = false, usageRecord;
|
|
37
|
+
const context = () => ({ tenantId: p.tenantId, userId: p.userId, operation: governance?.operation ?? "model:chat", traceId, ...governance?.sessionId ? { sessionId: governance.sessionId } : {}, ...selectedModelId ?? governance?.model ? { model: selectedModelId ?? governance?.model } : {}, ...sensitivityLevel ? { sensitivityLevel } : {} });
|
|
38
|
+
const observe = async (phase, extra = {}) => {
|
|
39
|
+
try {
|
|
40
|
+
await governance?.observability?.record({ phase, context: context(), ...extra });
|
|
41
|
+
} catch {
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
const controller = new AbortController();
|
|
45
|
+
let iterator, timer;
|
|
46
|
+
const abort = () => controller.abort();
|
|
47
|
+
input.signal?.addEventListener("abort", abort, { once: true });
|
|
48
|
+
if (input.signal?.aborted) abort();
|
|
49
|
+
const check = () => {
|
|
50
|
+
if (controller.signal.aborted) throw new Error("Chat cancelled or timed out");
|
|
51
|
+
};
|
|
52
|
+
const allow = async () => {
|
|
53
|
+
check();
|
|
54
|
+
if (await authorize(structuredClone(p), "model:chat") !== true) throw new Error("Chat access denied");
|
|
55
|
+
check();
|
|
56
|
+
};
|
|
57
|
+
const recordAttemptUsage = () => {
|
|
58
|
+
if (!attemptStarted || !governance?.budget?.recordUsage) return Promise.resolve();
|
|
59
|
+
return usageRecord ??= Promise.resolve().then(() => governance.budget.recordUsage({ context: context(), usage: usage && structuredClone(usage) }));
|
|
60
|
+
};
|
|
61
|
+
const work = async () => {
|
|
62
|
+
await allow();
|
|
63
|
+
const catalog = toolMode === "catalog" ? structuredClone(await tools?.(structuredClone(p)) ?? []) : [];
|
|
64
|
+
await allow();
|
|
65
|
+
if (catalog.length > 100 || new Set(catalog.map((t) => t.name)).size !== catalog.length) throw new Error("Invalid chat tool catalog");
|
|
66
|
+
if (JSON.stringify({ messages, tools: catalog, parameters }).length > maxInput) throw new Error("Chat input limit");
|
|
67
|
+
if (governance?.guard?.before) {
|
|
68
|
+
const guarded = await governance.guard.before({ context: context(), messages, toolNames: catalog.map((tool) => tool.name) });
|
|
69
|
+
if (!guarded.allowed) throw new Error(`Chat blocked${guarded.reason ? `: ${guarded.reason}` : ""}`);
|
|
70
|
+
if (guarded.messages !== void 0) messages = structuredClone(guarded.messages);
|
|
71
|
+
sensitivityLevel = guarded.sensitivityLevel;
|
|
72
|
+
}
|
|
73
|
+
await allow();
|
|
74
|
+
const route = registry?.resolve({ context: context(), capability: "chat", ...governance?.model ? { modelId: governance.model } : {}, ...sensitivityLevel ? { sensitivityLevel } : {} });
|
|
75
|
+
let selectedAdapter = adapter;
|
|
76
|
+
if (route) {
|
|
77
|
+
selectedModelId = route.modelId;
|
|
78
|
+
if (!Object.hasOwn(modelAdapters, route.modelId) || typeof modelAdapters[route.modelId]?.stream !== "function") throw new Error("AI model adapter binding missing");
|
|
79
|
+
selectedAdapter = modelAdapters[route.modelId];
|
|
80
|
+
if (selectedAdapter.id !== route.adapterId) throw new Error("AI model adapter does not match the approved route");
|
|
81
|
+
if (toolMode === "catalog" && !route.capabilities.includes("tools")) throw new Error("AI model route does not support tools");
|
|
82
|
+
}
|
|
83
|
+
if (catalog.length && !selectedAdapter.capabilities.tools) throw new Error("Invalid chat tool catalog");
|
|
84
|
+
const inputLimit = Math.min(maxInput, route?.maxInputChars ?? maxInput), outputLimit = Math.min(maxOutput, route?.maxOutputChars ?? maxOutput);
|
|
85
|
+
if (JSON.stringify({ messages, tools: catalog, parameters }).length > inputLimit) throw new Error("Chat input limit");
|
|
86
|
+
await allow();
|
|
87
|
+
if (governance?.budget) {
|
|
88
|
+
const decision = await governance.budget.authorize({ context: context() });
|
|
89
|
+
if (!decision.allowed) throw new Error(`Chat budget denied${decision.reason ? `: ${decision.reason}` : ""}`);
|
|
90
|
+
}
|
|
91
|
+
await allow();
|
|
92
|
+
await observe("started", { input: { messageCount: messages.length, toolCount: catalog.length }, metadata: { adapter: selectedAdapter.id, ...route ? { modelId: route.modelId } : {} } });
|
|
93
|
+
await allow();
|
|
94
|
+
attemptStarted = true;
|
|
95
|
+
iterator = selectedAdapter.stream({ messages, ...catalog.length ? { tools: catalog } : {}, parameters: structuredClone(parameters), signal: controller.signal })[Symbol.asyncIterator]();
|
|
96
|
+
const parts = [], calls = /* @__PURE__ */ new Set(), names = new Set(catalog.map((t) => t.name));
|
|
97
|
+
let size = 0, events = 0;
|
|
98
|
+
while (true) {
|
|
99
|
+
check();
|
|
100
|
+
const next = await iterator.next();
|
|
101
|
+
check();
|
|
102
|
+
if (next.done) throw new Error("Chat stream ended without completion");
|
|
103
|
+
await allow();
|
|
104
|
+
const event = next.value;
|
|
105
|
+
await observe("event", { eventType: event.type });
|
|
106
|
+
if (++events > maxEvents || (size += JSON.stringify(event).length) > outputLimit) throw new Error("Chat output limit");
|
|
107
|
+
if (event.type === "metadata") usage = mergeUsage(usage, readUsage(event.metadata));
|
|
108
|
+
if (event.type === "finish") {
|
|
109
|
+
if (!["stop", "tool-calls"].includes(event.reason) || event.reason === "tool-calls" !== calls.size > 0) throw new Error("Chat response incomplete or inconsistent");
|
|
110
|
+
let message = { id: crypto.randomUUID(), role: "assistant", parts };
|
|
111
|
+
if (governance?.guard?.after) {
|
|
112
|
+
const guarded = await governance.guard.after({ context: context(), message });
|
|
113
|
+
if (!guarded.allowed) throw new Error(`Chat output blocked${guarded.reason ? `: ${guarded.reason}` : ""}`);
|
|
114
|
+
if (guarded.messages !== void 0) {
|
|
115
|
+
if (guarded.messages.length !== 1) throw new Error("Chat output guard returned invalid message count");
|
|
116
|
+
message = structuredClone(guarded.messages[0]);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (JSON.stringify(message).length > outputLimit) throw new Error("Chat output limit after guard");
|
|
120
|
+
await allow();
|
|
121
|
+
return { message, finishReason: event.reason, traceId, usage, sensitivityLevel };
|
|
122
|
+
}
|
|
123
|
+
if (event.type === "text-delta") {
|
|
124
|
+
if (typeof event.text !== "string") throw new Error("Invalid chat text");
|
|
125
|
+
const previous = parts.at(-1);
|
|
126
|
+
if (previous?.type === "text") parts[parts.length - 1] = { type: "text", text: previous.text + event.text };
|
|
127
|
+
else parts.push({ type: "text", text: event.text });
|
|
128
|
+
} else if (event.type === "tool-call") {
|
|
129
|
+
if (!names.has(event.name) || typeof event.callId !== "string" || !event.callId.trim() || calls.has(event.callId) || calls.size >= 100 || !event.input || typeof event.input !== "object" || Array.isArray(event.input)) throw new Error("Invalid or unregistered chat tool call");
|
|
130
|
+
calls.add(event.callId);
|
|
131
|
+
parts.push(structuredClone(event));
|
|
132
|
+
} else if (event.type === "data") parts.push(structuredClone(event));
|
|
133
|
+
else if (event.type !== "metadata") throw new Error("Unexpected chat event");
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
let rejectAbort;
|
|
137
|
+
const stopped = new Promise((_resolve, reject) => {
|
|
138
|
+
rejectAbort = () => reject(new Error("Chat cancelled or timed out"));
|
|
139
|
+
controller.signal.addEventListener("abort", rejectAbort, { once: true });
|
|
140
|
+
if (controller.signal.aborted) rejectAbort();
|
|
141
|
+
timer = setTimeout(abort, timeout);
|
|
142
|
+
});
|
|
143
|
+
const accountedWork = async () => {
|
|
144
|
+
let result;
|
|
145
|
+
try {
|
|
146
|
+
result = await work();
|
|
147
|
+
} catch (error) {
|
|
148
|
+
await recordAttemptUsage();
|
|
149
|
+
throw error;
|
|
150
|
+
}
|
|
151
|
+
await recordAttemptUsage();
|
|
152
|
+
await allow();
|
|
153
|
+
await observe("completed", { output: result.message, usage });
|
|
154
|
+
await allow();
|
|
155
|
+
return result;
|
|
156
|
+
};
|
|
157
|
+
try {
|
|
158
|
+
return await Promise.race([accountedWork(), stopped]);
|
|
159
|
+
} catch (error) {
|
|
160
|
+
let failure = error;
|
|
161
|
+
try {
|
|
162
|
+
await Promise.race([recordAttemptUsage(), stopped]);
|
|
163
|
+
} catch (accountingError) {
|
|
164
|
+
if (!controller.signal.aborted) failure = accountingError;
|
|
165
|
+
}
|
|
166
|
+
void observe("failed", { error: failure instanceof Error ? failure.message : String(failure), usage });
|
|
167
|
+
throw failure;
|
|
168
|
+
} finally {
|
|
169
|
+
clearTimeout(timer);
|
|
170
|
+
input.signal?.removeEventListener("abort", abort);
|
|
171
|
+
if (rejectAbort) controller.signal.removeEventListener("abort", rejectAbort);
|
|
172
|
+
controller.abort();
|
|
173
|
+
try {
|
|
174
|
+
void Promise.resolve(iterator?.return?.()).catch(() => {
|
|
175
|
+
});
|
|
176
|
+
} catch {
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
function readUsage(value) {
|
|
183
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
184
|
+
const record = value, raw = record.usage && typeof record.usage === "object" && !Array.isArray(record.usage) ? record.usage : record;
|
|
185
|
+
const inputTokens = number(raw.inputTokens ?? raw.promptTokens ?? raw.input_tokens), outputTokens = number(raw.outputTokens ?? raw.completionTokens ?? raw.output_tokens), totalTokens = number(raw.totalTokens ?? raw.total_tokens), cost = number(raw.cost), currency = typeof raw.currency === "string" ? raw.currency : void 0;
|
|
186
|
+
if (inputTokens === void 0 && outputTokens === void 0 && totalTokens === void 0 && cost === void 0) return void 0;
|
|
187
|
+
return { ...inputTokens === void 0 ? {} : { inputTokens }, ...outputTokens === void 0 ? {} : { outputTokens }, ...totalTokens === void 0 ? {} : { totalTokens }, ...cost === void 0 ? {} : { cost }, ...currency ? { currency } : {} };
|
|
188
|
+
}
|
|
189
|
+
function number(value) {
|
|
190
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : void 0;
|
|
191
|
+
}
|
|
192
|
+
function mergeUsage(previous, next) {
|
|
193
|
+
return next ? { ...previous ?? {}, ...next } : previous;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export {
|
|
197
|
+
createChatClient
|
|
198
|
+
};
|
|
199
|
+
//# sourceMappingURL=chunk-YMHVRBUU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/execution/chat.ts"],"sourcesContent":["import type { AIChatAdapter, AIChatMessage, AIChatPart, AIChatEvent } from '@alneas/appkit-core/ai/ai-chat'\nimport type { ActionToolDescriptor, ActionToolObject } from '@alneas/appkit-core/ai/action'\nimport type { AIBudgetGate, AIGuard, AIExecutionContext, AIModelRegistry, AIObservabilitySink, AIUsage } from '@alneas/eaos-core'\nimport type { ExecutionPolicy, ExecutionPrincipal } from './index'\n\n/** Host-injected model guards, usage budgets and telemetry.\n * @see createChatClient\n */\nexport interface ChatGovernanceOptions {\n /** Optional pre-input and post-output checks; replacement messages remain host-owned. */\n guard?: AIGuard\n /** Optional request admission and once-per-started-attempt accounting; accounting failures propagate. */\n budget?: AIBudgetGate\n /** Awaited started/event/completed telemetry within the deadline; sink errors are ignored. */\n observability?: AIObservabilitySink\n /** Telemetry operation label; authorization always checks model:chat. */\n operation?: string\n /** Host-selected registry model ID; without a registry this is metadata, not provider selection. */\n model?: string\n /** Optional host session identity recorded in governance context. */\n sessionId?: string\n}\n/** Host-configured adapter, current admission and bounded chat policy.\n * @see createChatClient\n */\nexport interface ChatClientOptions extends ExecutionPolicy {\n /** Existing Appkit transport configured with the host endpoint, model and credentials. */\n adapter: AIChatAdapter\n /** Host-owned provider parameters cloned at creation; model/messages/tools/stream keys are reserved and rejected. */\n parameters?: ActionToolObject\n /**\n * Resolve descriptors only when the caller explicitly requests tools: catalog.\n * @param principal - Copied verified actor whose current disclosure permission the host must check.\n * @returns At most 100 unique descriptors; omission advertises no tools.\n * @throws Host resolution failures reject completion before the provider starts.\n * @example\n * ```typescript\n * import type { ChatClientOptions } from '@alneas/eaos-server/execution/chat';\n * export function disclosedTools(resolve: NonNullable<ChatClientOptions['tools']>) { return resolve; }\n * ```\n */\n tools?(principal: ExecutionPrincipal): Promise<readonly ActionToolDescriptor[]>\n /** Positive integer deadline in milliseconds; default 30000, maximum 3600000. */\n timeoutMs?: number\n /** Serialized request character ceiling; default 200000, maximum 7000000. */\n maxInputChars?: number\n /** Serialized event and final assistant-message character ceiling; default 100000, maximum 10000000. */\n maxOutputChars?: number\n /** Maximum stream event count; default 10000, maximum 100000. */\n maxEvents?: number\n /** Host-approved route registry; requests cannot select a model or bypass sensitivity limits. */\n modelRegistry?: AIModelRegistry\n /** Required with modelRegistry: host-approved logical model to configured adapter bindings, snapshotted at creation. */\n modelAdapters?: Readonly<Record<string, AIChatAdapter>>\n /** Optional host guards, budgets and telemetry; final current authorization follows their completion. */\n governance?: ChatGovernanceOptions\n}\n/** Completed assistant message and optional host-governance metadata.\n * @see createChatClient\n */\nexport interface ChatCompletion {\n /** Detached assistant response; tool-call parts are unexecuted requests. */\n message: AIChatMessage\n /** Successful provider finish reason; truncated or inconsistent streams reject. */\n finishReason: 'stop' | 'tool-calls'\n /** Unique request trace identity generated before governance callbacks. */\n traceId?: string\n /** Recognized nonnegative adapter metadata; undefined means unknown, including Appkit OpenAI SSE without usage events. */\n usage?: AIUsage\n /** Sensitivity label supplied by the input guard. */\n sensitivityLevel?: AIExecutionContext['sensitivityLevel']\n}\n/**\n * Complete scoped chat through the existing Appkit adapter with live admission and host governance.\n * @param options - Trusted adapter, current authorization, optional routes/governance and bounded limits.\n * @returns A client whose complete method returns detached, finally authorized assistant data.\n * @throws Rejects invalid limits or missing adapter/policy during construction. Completion rejects\n * invalid histories/catalogs, denied or revoked admission, guard/budget/route denial, provider failures,\n * incomplete streams, exceeded limits, cancellation, deadline expiry and host accounting failure. Telemetry errors are ignored.\n * @remarks Every completion authorizes model:chat before disclosure, between events and after awaited\n * output guard, usage recording and completion telemetry. This client never executes model tool calls.\n * The host must configure real endpoint credentials in the Appkit adapter. Abort is cooperative for a\n * custom transport; the request promise remains bounded even if its iterator ignores cancellation.\n * With modelRegistry, provide modelAdapters mapping each approved logical model to its host-configured\n * Appkit adapter; generic adapter IDs alone do not select or prove the provider model. Binding entries\n * and stream methods are snapshotted at creation. Reserved transport parameters are rejected in 0.2.\n * Accounting runs once after each started adapter attempt, including output blocks, revocation and provider\n * failure. Unknown usage is passed as undefined, never zero. Appkit's OpenAI SSE adapter currently emits\n * no usage metadata event even for provider include_usage chunks; hosts must reconcile measured usage\n * through their existing accounting port using trace/session context. Accounting callback errors reject\n * completion in 0.2; a stalled callback remains bounded by the request deadline.\n * @example\n * ```typescript\n * import { createChatClient, type ChatClientOptions } from '@alneas/eaos-server/execution/chat';\n * export function connectChat(options: ChatClientOptions) { return createChatClient(options); }\n * ```\n */\nexport function createChatClient(options: ChatClientOptions) {\n const adapter = options.adapter, authorize = options.authorize, tools = options.tools\n const parameters = structuredClone(options.parameters), governance = options.governance, registry = options.modelRegistry\n const modelAdapters = Object.freeze(Object.fromEntries(Object.entries(options.modelAdapters ?? {}).map(([model,transport]) => {\n if (typeof transport?.stream !== 'function') throw new Error('Invalid AI model adapter binding')\n return [model,Object.freeze({id:transport.id,capabilities:Object.freeze({...transport.capabilities}),stream:transport.stream.bind(transport)})]\n })))\n if (registry && !options.modelAdapters) throw new Error('AI model adapter bindings required')\n if (parameters !== undefined && (!parameters || typeof parameters !== 'object' || Array.isArray(parameters) || Object.keys(parameters).some(key => ['model','messages','tools','stream'].includes(key)))) throw new Error('Invalid or reserved chat parameters')\n const timeout = options.timeoutMs ?? 30000, maxInput = options.maxInputChars ?? 200000, maxOutput = options.maxOutputChars ?? 100000, maxEvents = options.maxEvents ?? 10000\n for (const [value, max] of [[timeout,3600000],[maxInput,7000000],[maxOutput,10000000],[maxEvents,100000]] as const) if (!Number.isSafeInteger(value) || value < 1 || value > max) throw new Error('Invalid chat limit')\n if (typeof adapter?.stream !== 'function' || typeof authorize !== 'function' || tools !== undefined && typeof tools !== 'function') throw new Error('Chat adapter and authorization required')\n return {\n /**\n * Request one bounded completion for the current actor.\n * @param principal - Verified nonblank tenant/user identity; copied before invoking host callbacks.\n * @param input - One to 1000 messages, optional cancellation, and explicit none/catalog tool disclosure.\n * @returns Assistant data only after final live authorization; tools remain unexecuted requests.\n * @throws Rejects invalid requests, governance/provider failure, revocation, limits or cancellation.\n * @example\n * ```typescript\n * import { createChatClient } from '@alneas/eaos-server/execution/chat';\n * export function complete(client: ReturnType<typeof createChatClient>, ...args: Parameters<typeof client.complete>) {\n * return client.complete(...args);\n * }\n * ```\n */\n async complete(principal: ExecutionPrincipal, input: { messages: readonly AIChatMessage[]; signal?: AbortSignal; tools?: 'none' | 'catalog' }): Promise<ChatCompletion> {\n const p = structuredClone(principal)\n if (!p || [p.tenantId,p.userId].some(v => typeof v !== 'string' || !v.trim())) throw new Error('Chat access denied')\n if (!Array.isArray(input?.messages) || !input.messages.length || input.messages.length > 1000 || Object.keys(input).some(k => !['messages','signal','tools'].includes(k)) || input.tools !== undefined && !['none','catalog'].includes(input.tools)) throw new Error('Invalid chat history or options')\n let messages: AIChatMessage[] = structuredClone(input.messages) as AIChatMessage[]\n const toolMode = input.tools, traceId = crypto.randomUUID()\n let sensitivityLevel: AIExecutionContext['sensitivityLevel'], usage: AIUsage | undefined, selectedModelId: string | undefined\n let attemptStarted = false, usageRecord: Promise<void> | undefined\n const context = (): AIExecutionContext => ({ tenantId: p.tenantId, userId: p.userId, operation: governance?.operation ?? 'model:chat', traceId, ...(governance?.sessionId ? { sessionId: governance.sessionId } : {}), ...((selectedModelId ?? governance?.model) ? { model: selectedModelId ?? governance?.model } : {}), ...(sensitivityLevel ? { sensitivityLevel } : {}) })\n const observe = async (phase: Parameters<AIObservabilitySink['record']>[0]['phase'], extra: Omit<Parameters<AIObservabilitySink['record']>[0], 'phase' | 'context'> = {}) => {\n try { await governance?.observability?.record({ phase, context: context(), ...extra }) } catch { /* Telemetry is best-effort within the request deadline. */ }\n }\n const controller = new AbortController(); let iterator: AsyncIterator<AIChatEvent> | undefined, timer: ReturnType<typeof setTimeout> | undefined\n const abort = () => controller.abort()\n input.signal?.addEventListener('abort', abort, { once: true })\n if (input.signal?.aborted) abort()\n const check = () => { if (controller.signal.aborted) throw new Error('Chat cancelled or timed out') }\n const allow = async () => { check(); if (await authorize(structuredClone(p), 'model:chat') !== true) throw new Error('Chat access denied'); check() }\n const recordAttemptUsage = (): Promise<void> => {\n if (!attemptStarted || !governance?.budget?.recordUsage) return Promise.resolve()\n return usageRecord ??= Promise.resolve().then(() => governance.budget!.recordUsage!({context:context(),usage:usage && structuredClone(usage)}))\n }\n const work = async (): Promise<ChatCompletion> => {\n await allow()\n const catalog = toolMode === 'catalog' ? structuredClone(await tools?.(structuredClone(p)) ?? []) : []\n await allow()\n if (catalog.length > 100 || new Set(catalog.map(t => t.name)).size !== catalog.length) throw new Error('Invalid chat tool catalog')\n if (JSON.stringify({ messages, tools: catalog, parameters }).length > maxInput) throw new Error('Chat input limit')\n if (governance?.guard?.before) {\n const guarded = await governance.guard.before({ context: context(), messages, toolNames: catalog.map(tool => tool.name) })\n if (!guarded.allowed) throw new Error(`Chat blocked${guarded.reason ? `: ${guarded.reason}` : ''}`)\n if (guarded.messages !== undefined) messages = structuredClone(guarded.messages) as AIChatMessage[]\n sensitivityLevel = guarded.sensitivityLevel\n }\n await allow()\n const route = registry?.resolve({ context: context(), capability: 'chat', ...(governance?.model ? { modelId: governance.model } : {}), ...(sensitivityLevel ? { sensitivityLevel } : {}) })\n let selectedAdapter = adapter\n if (route) {\n selectedModelId = route.modelId\n if (!Object.hasOwn(modelAdapters,route.modelId) || typeof modelAdapters[route.modelId]?.stream !== 'function') throw new Error('AI model adapter binding missing')\n selectedAdapter = modelAdapters[route.modelId]\n if (selectedAdapter.id !== route.adapterId) throw new Error('AI model adapter does not match the approved route')\n if (toolMode === 'catalog' && !route.capabilities.includes('tools')) throw new Error('AI model route does not support tools')\n }\n if (catalog.length && !selectedAdapter.capabilities.tools) throw new Error('Invalid chat tool catalog')\n const inputLimit = Math.min(maxInput, route?.maxInputChars ?? maxInput), outputLimit = Math.min(maxOutput, route?.maxOutputChars ?? maxOutput)\n if (JSON.stringify({ messages, tools: catalog, parameters }).length > inputLimit) throw new Error('Chat input limit')\n await allow()\n if (governance?.budget) {\n const decision = await governance.budget.authorize({ context: context() })\n if (!decision.allowed) throw new Error(`Chat budget denied${decision.reason ? `: ${decision.reason}` : ''}`)\n }\n await allow()\n await observe('started', { input: { messageCount: messages.length, toolCount: catalog.length }, metadata: { adapter: selectedAdapter.id, ...(route ? { modelId: route.modelId } : {}) } })\n await allow()\n attemptStarted = true\n iterator = selectedAdapter.stream({ messages, ...(catalog.length ? { tools: catalog } : {}), parameters: structuredClone(parameters), signal: controller.signal })[Symbol.asyncIterator]()\n const parts: AIChatPart[] = [], calls = new Set<string>(), names = new Set(catalog.map(t => t.name))\n let size = 0, events = 0\n while (true) {\n check()\n const next = await iterator.next(); check()\n if (next.done) throw new Error('Chat stream ended without completion')\n await allow()\n const event = next.value\n await observe('event', { eventType: event.type })\n if (++events > maxEvents || (size += JSON.stringify(event).length) > outputLimit) throw new Error('Chat output limit')\n if (event.type === 'metadata') usage = mergeUsage(usage, readUsage(event.metadata))\n if (event.type === 'finish') {\n if (!['stop','tool-calls'].includes(event.reason) || (event.reason === 'tool-calls') !== (calls.size > 0)) throw new Error('Chat response incomplete or inconsistent')\n let message: AIChatMessage = { id: crypto.randomUUID(), role: 'assistant', parts }\n if (governance?.guard?.after) {\n const guarded = await governance.guard.after({ context: context(), message })\n if (!guarded.allowed) throw new Error(`Chat output blocked${guarded.reason ? `: ${guarded.reason}` : ''}`)\n if (guarded.messages !== undefined) {\n if (guarded.messages.length !== 1) throw new Error('Chat output guard returned invalid message count')\n message = structuredClone(guarded.messages[0])\n }\n }\n if (JSON.stringify(message).length > outputLimit) throw new Error('Chat output limit after guard')\n await allow()\n return { message, finishReason: event.reason as ChatCompletion['finishReason'], traceId, usage, sensitivityLevel }\n }\n if (event.type === 'text-delta') {\n if (typeof event.text !== 'string') throw new Error('Invalid chat text')\n const previous = parts.at(-1)\n if (previous?.type === 'text') parts[parts.length - 1] = { type: 'text', text: previous.text + event.text }\n else parts.push({ type: 'text', text: event.text })\n } else if (event.type === 'tool-call') {\n if (!names.has(event.name) || typeof event.callId !== 'string' || !event.callId.trim() || calls.has(event.callId) || calls.size >= 100 || !event.input || typeof event.input !== 'object' || Array.isArray(event.input)) throw new Error('Invalid or unregistered chat tool call')\n calls.add(event.callId); parts.push(structuredClone(event))\n } else if (event.type === 'data') parts.push(structuredClone(event))\n else if (event.type !== 'metadata') throw new Error('Unexpected chat event')\n }\n }\n let rejectAbort: (() => void) | undefined\n const stopped = new Promise<never>((_resolve, reject) => {\n rejectAbort = () => reject(new Error('Chat cancelled or timed out'))\n controller.signal.addEventListener('abort', rejectAbort, { once: true })\n if (controller.signal.aborted) rejectAbort()\n timer = setTimeout(abort, timeout)\n })\n const accountedWork = async () => {\n let result: ChatCompletion\n try { result = await work() }\n catch (error) { await recordAttemptUsage(); throw error }\n await recordAttemptUsage()\n await allow()\n await observe('completed', {output:result.message,usage})\n await allow()\n return result\n }\n try { return await Promise.race([accountedWork(), stopped]) }\n catch (error) {\n let failure = error\n // A deadline can win while a started provider/output guard is pending. Account that attempt once.\n try { await Promise.race([recordAttemptUsage(),stopped]) }\n catch (accountingError) { if (!controller.signal.aborted) failure = accountingError }\n void observe('failed', { error: failure instanceof Error ? failure.message : String(failure), usage })\n throw failure\n }\n finally {\n clearTimeout(timer); input.signal?.removeEventListener('abort', abort)\n if (rejectAbort) controller.signal.removeEventListener('abort', rejectAbort)\n controller.abort()\n try { void Promise.resolve(iterator?.return?.()).catch(() => {}) } catch { /* Preserve the original outcome. */ }\n }\n },\n }\n}\n\nfunction readUsage(value: unknown): AIUsage | undefined {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return undefined\n const record = value as Record<string, unknown>, raw = record.usage && typeof record.usage === 'object' && !Array.isArray(record.usage) ? record.usage as Record<string, unknown> : record\n const inputTokens = number(raw.inputTokens ?? raw.promptTokens ?? raw.input_tokens), outputTokens = number(raw.outputTokens ?? raw.completionTokens ?? raw.output_tokens), totalTokens = number(raw.totalTokens ?? raw.total_tokens), cost = number(raw.cost), currency = typeof raw.currency === 'string' ? raw.currency : undefined\n if (inputTokens === undefined && outputTokens === undefined && totalTokens === undefined && cost === undefined) return undefined\n return { ...(inputTokens === undefined ? {} : { inputTokens }), ...(outputTokens === undefined ? {} : { outputTokens }), ...(totalTokens === undefined ? {} : { totalTokens }), ...(cost === undefined ? {} : { cost }), ...(currency ? { currency } : {}) }\n}\n\nfunction number(value: unknown): number | undefined { return typeof value === 'number' && Number.isFinite(value) && value >= 0 ? value : undefined }\nfunction mergeUsage(previous: AIUsage | undefined, next: AIUsage | undefined): AIUsage | undefined { return next ? { ...(previous ?? {}), ...next } : previous }\n"],"mappings":"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","names":[]}
|