@assemblyline-agents/node 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +19 -0
  3. package/dist/adapters.d.ts +17 -0
  4. package/dist/adapters.d.ts.map +1 -0
  5. package/dist/adapters.js +122 -0
  6. package/dist/adapters.js.map +1 -0
  7. package/dist/auth.d.ts +45 -0
  8. package/dist/auth.d.ts.map +1 -0
  9. package/dist/auth.js +196 -0
  10. package/dist/auth.js.map +1 -0
  11. package/dist/direct-conversations-http.d.ts +40 -0
  12. package/dist/direct-conversations-http.d.ts.map +1 -0
  13. package/dist/direct-conversations-http.js +140 -0
  14. package/dist/direct-conversations-http.js.map +1 -0
  15. package/dist/http-io.d.ts +20 -0
  16. package/dist/http-io.d.ts.map +1 -0
  17. package/dist/http-io.js +101 -0
  18. package/dist/http-io.js.map +1 -0
  19. package/dist/index.d.ts +49 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +750 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/lifecycle.d.ts +56 -0
  24. package/dist/lifecycle.d.ts.map +1 -0
  25. package/dist/lifecycle.js +112 -0
  26. package/dist/lifecycle.js.map +1 -0
  27. package/dist/multipart.d.ts +3 -0
  28. package/dist/multipart.d.ts.map +1 -0
  29. package/dist/multipart.js +125 -0
  30. package/dist/multipart.js.map +1 -0
  31. package/dist/provider-resolver.d.ts +17 -0
  32. package/dist/provider-resolver.d.ts.map +1 -0
  33. package/dist/provider-resolver.js +94 -0
  34. package/dist/provider-resolver.js.map +1 -0
  35. package/dist/rate-limit.d.ts +60 -0
  36. package/dist/rate-limit.d.ts.map +1 -0
  37. package/dist/rate-limit.js +98 -0
  38. package/dist/rate-limit.js.map +1 -0
  39. package/dist/route-match.d.ts +21 -0
  40. package/dist/route-match.d.ts.map +1 -0
  41. package/dist/route-match.js +89 -0
  42. package/dist/route-match.js.map +1 -0
  43. package/dist/run-stream-http.d.ts +13 -0
  44. package/dist/run-stream-http.d.ts.map +1 -0
  45. package/dist/run-stream-http.js +145 -0
  46. package/dist/run-stream-http.js.map +1 -0
  47. package/dist/usage-http.d.ts +9 -0
  48. package/dist/usage-http.d.ts.map +1 -0
  49. package/dist/usage-http.js +184 -0
  50. package/dist/usage-http.js.map +1 -0
  51. package/package.json +96 -0
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Ingress rate limiting for the OpenEve Node host: a token bucket with a
3
+ * pluggable async store so multi-replica deployments can share a Redis-shaped
4
+ * backend. Default OFF — limits apply only when configured via
5
+ * `NodeRuntimeServerOptions.rateLimit` or the `OPENEVE_INGRESS_RATE_LIMIT` /
6
+ * `OPENEVE_RUNS_RATE_LIMIT` env vars ("capacity/refillPerSecond", e.g. "60/10").
7
+ */
8
+ export function createMemoryRateLimiterStore() {
9
+ const buckets = new Map();
10
+ return {
11
+ async take(key, options) {
12
+ const now = options.now ?? Date.now();
13
+ const cost = options.cost ?? 1;
14
+ const bucket = buckets.get(key) ?? { tokens: options.capacity, updatedAtMs: now };
15
+ const elapsedSeconds = Math.max(0, now - bucket.updatedAtMs) / 1_000;
16
+ const tokens = Math.min(options.capacity, bucket.tokens + elapsedSeconds * options.refillPerSecond);
17
+ if (tokens >= cost) {
18
+ buckets.set(key, { tokens: tokens - cost, updatedAtMs: now });
19
+ return { allowed: true, retryAfterMs: 0 };
20
+ }
21
+ buckets.set(key, { tokens, updatedAtMs: now });
22
+ const retryAfterMs = options.refillPerSecond > 0
23
+ ? Math.ceil(((cost - tokens) / options.refillPerSecond) * 1_000)
24
+ : Number.MAX_SAFE_INTEGER;
25
+ return { allowed: false, retryAfterMs };
26
+ }
27
+ };
28
+ }
29
+ /** Parses "capacity/refillPerSecond" (e.g. "60/10"). Returns undefined for unset/invalid values. */
30
+ export function parseRateLimitSpec(value) {
31
+ if (!value)
32
+ return undefined;
33
+ const match = /^\s*(\d+(?:\.\d+)?)\s*\/\s*(\d+(?:\.\d+)?)\s*$/.exec(value);
34
+ if (!match)
35
+ return undefined;
36
+ const capacity = Number(match[1]);
37
+ const refillPerSecond = Number(match[2]);
38
+ if (!(capacity > 0) || !(refillPerSecond > 0))
39
+ return undefined;
40
+ return { capacity, refillPerSecond };
41
+ }
42
+ /**
43
+ * Default bucket key by route class + client address. `X-Forwarded-For` is
44
+ * client-supplied and only trusted when the deployment opts in via
45
+ * `OPENEVE_TRUST_PROXY=true`; otherwise the socket address is used. Without this
46
+ * gate, any client could rotate the XFF header to mint a fresh full bucket per
47
+ * request and defeat the limiter entirely.
48
+ */
49
+ function makeDefaultKeyFor(trustProxy) {
50
+ return (request) => {
51
+ const forwarded = trustProxy ? request.headers["x-forwarded-for"]?.split(",")[0]?.trim() : undefined;
52
+ const client = forwarded || request.remoteAddress || "unknown";
53
+ return `${request.routeClass}:${client}`;
54
+ };
55
+ }
56
+ /**
57
+ * Combines an explicit policy with env-configured limits. Returns undefined
58
+ * (no limiting) when nothing is configured or the policy is `false`.
59
+ */
60
+ export function resolveIngressRateLimit(policy, env) {
61
+ if (policy === false)
62
+ return undefined;
63
+ const limits = {
64
+ ...(policy?.limits ?? {})
65
+ };
66
+ const ingressSpec = parseRateLimitSpec(env.OPENEVE_INGRESS_RATE_LIMIT);
67
+ if (ingressSpec && !limits["provider-channel"])
68
+ limits["provider-channel"] = ingressSpec;
69
+ const runsSpec = parseRateLimitSpec(env.OPENEVE_RUNS_RATE_LIMIT);
70
+ if (runsSpec && !limits["run-create"])
71
+ limits["run-create"] = runsSpec;
72
+ // Resume shares the runs budget unless separately configured.
73
+ if (runsSpec && !limits["run-resume"])
74
+ limits["run-resume"] = runsSpec;
75
+ if (runsSpec && !limits["run-control"])
76
+ limits["run-control"] = runsSpec;
77
+ if (Object.values(limits).every((limit) => limit === undefined) || Object.keys(limits).length === 0)
78
+ return undefined;
79
+ const store = policy?.store ?? createMemoryRateLimiterStore();
80
+ const keyFor = policy?.keyFor ?? makeDefaultKeyFor(env.OPENEVE_TRUST_PROXY === "true");
81
+ const now = policy?.now;
82
+ return {
83
+ async check(request) {
84
+ const limit = limits[request.routeClass];
85
+ if (!limit)
86
+ return { allowed: true, retryAfterMs: 0 };
87
+ const key = keyFor(request);
88
+ if (key === undefined)
89
+ return { allowed: true, retryAfterMs: 0 };
90
+ return store.take(key, {
91
+ capacity: limit.capacity,
92
+ refillPerSecond: limit.refillPerSecond,
93
+ ...(now ? { now: now() } : {})
94
+ });
95
+ }
96
+ };
97
+ }
98
+ //# sourceMappingURL=rate-limit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../src/rate-limit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { RuntimeOptions } from "@assemblyline-agents/runtime";
2
+ type RouteTableEntry = RuntimeOptions["manifest"]["routeTable"][number];
3
+ /** POST /runs/:id/{approve,answer,cancel,suspend,resume}. */
4
+ export declare function parseRunResumeRoute(pathname: string): {
5
+ runId: string;
6
+ kind: "approve" | "answer" | "cancel" | "suspend" | "resume";
7
+ } | undefined;
8
+ /** GET /agent/control and POST /agent/{enable,disable,quiesce,resume}. */
9
+ export declare function parseAgentControlRoute(pathname: string): {
10
+ kind: "control" | "enable" | "disable" | "quiesce" | "resume";
11
+ } | undefined;
12
+ export declare function parseRunRoute(pathname: string): {
13
+ runId: string;
14
+ kind: "detail" | "events" | "timeline" | "stream";
15
+ } | undefined;
16
+ export declare function matchRoute(routes: RouteTableEntry[], method: string, pathname: string): {
17
+ route: RouteTableEntry;
18
+ params: Record<string, string>;
19
+ } | undefined;
20
+ export {};
21
+ //# sourceMappingURL=route-match.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-match.d.ts","sourceRoot":"","sources":["../src/route-match.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAEnE,KAAK,eAAe,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAExE,6DAA6D;AAC7D,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG;IACrD,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;CAC9D,GAAG,SAAS,CAWZ;AAED,0EAA0E;AAC1E,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAA;CAAE,GAAG,SAAS,CAOtI;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,UAAU,GAAG,QAAQ,CAAA;CAAE,GAAG,SAAS,CAShI;AAED,wBAAgB,UAAU,CACxB,MAAM,EAAE,eAAe,EAAE,EACzB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf;IAAE,KAAK,EAAE,eAAe,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAAG,SAAS,CASxE"}
@@ -0,0 +1,89 @@
1
+ /** POST /runs/:id/{approve,answer,cancel,suspend,resume}. */
2
+ export function parseRunResumeRoute(pathname) {
3
+ const parts = pathname.split("/").filter(Boolean);
4
+ if (parts[0] !== "runs" || parts.length !== 3)
5
+ return undefined;
6
+ const runId = decodeURIComponent(parts[1] ?? "");
7
+ if (!runId)
8
+ return undefined;
9
+ if (parts[2] === "approve")
10
+ return { runId, kind: "approve" };
11
+ if (parts[2] === "answer")
12
+ return { runId, kind: "answer" };
13
+ if (parts[2] === "cancel")
14
+ return { runId, kind: "cancel" };
15
+ if (parts[2] === "suspend")
16
+ return { runId, kind: "suspend" };
17
+ if (parts[2] === "resume")
18
+ return { runId, kind: "resume" };
19
+ return undefined;
20
+ }
21
+ /** GET /agent/control and POST /agent/{enable,disable,quiesce,resume}. */
22
+ export function parseAgentControlRoute(pathname) {
23
+ if (pathname === "/agent/control")
24
+ return { kind: "control" };
25
+ if (pathname === "/agent/enable")
26
+ return { kind: "enable" };
27
+ if (pathname === "/agent/disable")
28
+ return { kind: "disable" };
29
+ if (pathname === "/agent/quiesce")
30
+ return { kind: "quiesce" };
31
+ if (pathname === "/agent/resume")
32
+ return { kind: "resume" };
33
+ return undefined;
34
+ }
35
+ export function parseRunRoute(pathname) {
36
+ const parts = pathname.split("/").filter(Boolean);
37
+ if (parts[0] !== "runs" || parts.length < 2 || parts.length > 3)
38
+ return undefined;
39
+ const runId = decodeURIComponent(parts[1] ?? "");
40
+ if (!runId)
41
+ return undefined;
42
+ const suffix = parts[2];
43
+ if (suffix === undefined)
44
+ return { runId, kind: "detail" };
45
+ if (suffix === "events" || suffix === "timeline" || suffix === "stream")
46
+ return { runId, kind: suffix };
47
+ return undefined;
48
+ }
49
+ export function matchRoute(routes, method, pathname) {
50
+ const methodRoutes = routes.filter((candidate) => candidate.methods.includes(method));
51
+ const exact = methodRoutes.find((candidate) => candidate.route === pathname);
52
+ if (exact)
53
+ return { route: exact, params: {} };
54
+ for (const route of methodRoutes) {
55
+ const params = matchRoutePattern(route.route, pathname);
56
+ if (params)
57
+ return { route, params };
58
+ }
59
+ return undefined;
60
+ }
61
+ function matchRoutePattern(pattern, pathname) {
62
+ const patternSegments = splitRoutePath(pattern);
63
+ const pathSegments = splitRoutePath(pathname);
64
+ if (patternSegments.length !== pathSegments.length)
65
+ return undefined;
66
+ const params = {};
67
+ for (let index = 0; index < patternSegments.length; index += 1) {
68
+ const patternSegment = patternSegments[index] ?? "";
69
+ const pathSegment = pathSegments[index] ?? "";
70
+ if (patternSegment.startsWith(":") && patternSegment.length > 1) {
71
+ try {
72
+ params[patternSegment.slice(1)] = decodeURIComponent(pathSegment);
73
+ }
74
+ catch {
75
+ return undefined;
76
+ }
77
+ continue;
78
+ }
79
+ if (patternSegment !== pathSegment)
80
+ return undefined;
81
+ }
82
+ return params;
83
+ }
84
+ function splitRoutePath(pathname) {
85
+ if (pathname === "/")
86
+ return [];
87
+ return pathname.split("/").filter(Boolean);
88
+ }
89
+ //# sourceMappingURL=route-match.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-match.js","sourceRoot":"","sources":["../src/route-match.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { ServerResponse } from "node:http";
2
+ import { type OpenEveRuntime } from "@assemblyline-agents/runtime";
3
+ /** GET /runs/:id/stream */
4
+ export declare function serveRunEventStream(runtime: OpenEveRuntime, response: ServerResponse, runId: string, lastEventIdHeader: string | undefined): Promise<void>;
5
+ /**
6
+ * POST /runs with `"stream": true`: open the SSE channel immediately, attach
7
+ * to the run as soon as its record exists, and finish with a `run_result`
8
+ * event carrying the same summary the JSON endpoint returns.
9
+ */
10
+ export declare function serveStreamingRun(runtime: OpenEveRuntime, response: ServerResponse, startRun: (onRunCreated: (run: {
11
+ id: string;
12
+ }) => void) => Promise<unknown>, summarize: (result: unknown) => unknown): Promise<void>;
13
+ //# sourceMappingURL=run-stream-http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-stream-http.d.ts","sourceRoot":"","sources":["../src/run-stream-http.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAA8B,KAAK,cAAc,EAAuB,MAAM,8BAA8B,CAAC;AA0HpH,2BAA2B;AAC3B,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,cAAc,EACvB,QAAQ,EAAE,cAAc,EACxB,KAAK,EAAE,MAAM,EACb,iBAAiB,EAAE,MAAM,GAAG,SAAS,GACpC,OAAO,CAAC,IAAI,CAAC,CAIf;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,cAAc,EACvB,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,CAAC,YAAY,EAAE,CAAC,GAAG,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,KAAK,IAAI,KAAK,OAAO,CAAC,OAAO,CAAC,EAC3E,SAAS,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,GACtC,OAAO,CAAC,IAAI,CAAC,CAYf"}
@@ -0,0 +1,145 @@
1
+ import { RUN_STREAM_TERMINAL_EVENTS } from "@assemblyline-agents/runtime";
2
+ /**
3
+ * Server-sent-events plumbing for live run streams.
4
+ *
5
+ * `GET /runs/:id/stream` attaches to any run: it replays the durable event
6
+ * log (honoring `Last-Event-ID` for reconnects — the SSE `id:` is the event
7
+ * sequence), then tails live events including ephemeral
8
+ * `model.response_delta` tokens, and ends after a terminal run event.
9
+ * `POST /runs` with `"stream": true` runs a new turn over the same wire.
10
+ */
11
+ const HEARTBEAT_MS = 15_000;
12
+ function openSseChannel(response) {
13
+ response.writeHead(200, {
14
+ "content-type": "text/event-stream",
15
+ "cache-control": "no-cache, no-transform",
16
+ connection: "keep-alive",
17
+ "x-accel-buffering": "no"
18
+ });
19
+ response.write(": stream open\n\n");
20
+ const heartbeat = setInterval(() => {
21
+ if (!response.writableEnded)
22
+ response.write(`: ping ${Date.now()}\n\n`);
23
+ }, HEARTBEAT_MS);
24
+ heartbeat.unref?.();
25
+ const closeListeners = [];
26
+ let closed = false;
27
+ const close = () => {
28
+ if (closed)
29
+ return;
30
+ closed = true;
31
+ clearInterval(heartbeat);
32
+ for (const listener of closeListeners.splice(0))
33
+ listener();
34
+ };
35
+ response.on("close", close);
36
+ return {
37
+ write(event) {
38
+ if (response.writableEnded)
39
+ return;
40
+ const idLine = event.sequence !== undefined ? `id: ${event.sequence}\n` : "";
41
+ response.write(`${idLine}event: ${event.type}\ndata: ${JSON.stringify(event)}\n\n`);
42
+ },
43
+ comment(text) {
44
+ if (!response.writableEnded)
45
+ response.write(`: ${text}\n\n`);
46
+ },
47
+ end(finalEvent) {
48
+ if (!response.writableEnded) {
49
+ if (finalEvent)
50
+ response.write(`event: ${finalEvent.type}\ndata: ${JSON.stringify(finalEvent.data ?? {})}\n\n`);
51
+ response.end();
52
+ }
53
+ close();
54
+ },
55
+ get closed() {
56
+ return closed;
57
+ },
58
+ onClose(listener) {
59
+ if (closed)
60
+ listener();
61
+ else
62
+ closeListeners.push(listener);
63
+ }
64
+ };
65
+ }
66
+ /**
67
+ * Attach an SSE channel to a run id: subscribe first, replay the log with
68
+ * dedupe by sequence, then flush buffered live events. Ends the stream after
69
+ * a terminal run event (or immediately when the run is already terminal).
70
+ */
71
+ async function attachRunStream(runtime, channel, runId, lastEventId, options = {}) {
72
+ const endOnTerminal = options.endOnTerminal !== false;
73
+ let maxSequence = lastEventId;
74
+ let replaying = true;
75
+ let sawTerminal = false;
76
+ const buffered = [];
77
+ const deliver = (event) => {
78
+ if (event.sequence !== undefined) {
79
+ if (event.sequence <= maxSequence)
80
+ return;
81
+ maxSequence = event.sequence;
82
+ }
83
+ channel.write(event);
84
+ if (RUN_STREAM_TERMINAL_EVENTS.has(event.type)) {
85
+ sawTerminal = true;
86
+ if (endOnTerminal)
87
+ channel.end({ type: "stream_end", data: { runId } });
88
+ }
89
+ };
90
+ const unsubscribe = runtime.subscribeRunStream(runId, (event) => {
91
+ if (channel.closed)
92
+ return;
93
+ if (replaying)
94
+ buffered.push(event);
95
+ else
96
+ deliver(event);
97
+ });
98
+ channel.onClose(unsubscribe);
99
+ for (const event of await runtime.state.listEvents(runId)) {
100
+ deliver({ type: event.type, timestamp: event.timestamp, data: event.data, sequence: event.sequence });
101
+ if (channel.closed)
102
+ return;
103
+ }
104
+ replaying = false;
105
+ for (const event of buffered.splice(0)) {
106
+ deliver(event);
107
+ if (channel.closed)
108
+ return;
109
+ }
110
+ if (endOnTerminal && !sawTerminal) {
111
+ // Cancelled orphans can be terminal without a run.* terminal event.
112
+ const run = await runtime.state.getRun(runId);
113
+ if (!run)
114
+ channel.end({ type: "stream_end", data: { runId, error: "Run not found." } });
115
+ else if (run.status === "completed" || run.status === "failed" || run.status === "cancelled") {
116
+ channel.end({ type: "stream_end", data: { runId, status: run.status } });
117
+ }
118
+ }
119
+ }
120
+ /** GET /runs/:id/stream */
121
+ export async function serveRunEventStream(runtime, response, runId, lastEventIdHeader) {
122
+ const lastEventId = Number(lastEventIdHeader ?? 0);
123
+ const channel = openSseChannel(response);
124
+ await attachRunStream(runtime, channel, runId, Number.isFinite(lastEventId) ? lastEventId : 0);
125
+ }
126
+ /**
127
+ * POST /runs with `"stream": true`: open the SSE channel immediately, attach
128
+ * to the run as soon as its record exists, and finish with a `run_result`
129
+ * event carrying the same summary the JSON endpoint returns.
130
+ */
131
+ export async function serveStreamingRun(runtime, response, startRun, summarize) {
132
+ const channel = openSseChannel(response);
133
+ let attached;
134
+ try {
135
+ const result = await startRun((run) => {
136
+ attached = attachRunStream(runtime, channel, run.id, 0, { endOnTerminal: false }).catch(() => undefined);
137
+ });
138
+ await attached;
139
+ channel.end({ type: "run_result", data: summarize(result) });
140
+ }
141
+ catch (error) {
142
+ channel.end({ type: "run_error", data: { error: error instanceof Error ? error.message : String(error) } });
143
+ }
144
+ }
145
+ //# sourceMappingURL=run-stream-http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-stream-http.js","sourceRoot":"","sources":["../src/run-stream-http.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,0BAA0B,EAA4C,MAAM,8BAA8B,CAAC;AAEpH;;;;;;;;GAQG;AAEH,MAAM,YAAY,GAAG,MAAM,CAAC;AAU5B,SAAS,cAAc,CAAC,QAAwB;IAC9C,QAAQ,CAAC,SAAS,CAAC,GAAG,EAAE;QACtB,cAAc,EAAE,mBAAmB;QACnC,eAAe,EAAE,wBAAwB;QACzC,UAAU,EAAE,YAAY;QACxB,mBAAmB,EAAE,IAAI;KAC1B,CAAC,CAAC;IACH,QAAQ,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;IACpC,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE;QACjC,IAAI,CAAC,QAAQ,CAAC,aAAa;YAAE,QAAQ,CAAC,KAAK,CAAC,UAAU,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAC1E,CAAC,EAAE,YAAY,CAAC,CAAC;IACjB,SAAS,CAAC,KAAK,EAAE,EAAE,CAAC;IACpB,MAAM,cAAc,GAAsB,EAAE,CAAC;IAC7C,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,MAAM,KAAK,GAAG,GAAG,EAAE;QACjB,IAAI,MAAM;YAAE,OAAO;QACnB,MAAM,GAAG,IAAI,CAAC;QACd,aAAa,CAAC,SAAS,CAAC,CAAC;QACzB,KAAK,MAAM,QAAQ,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;YAAE,QAAQ,EAAE,CAAC;IAC9D,CAAC,CAAC;IACF,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC5B,OAAO;QACL,KAAK,CAAC,KAAK;YACT,IAAI,QAAQ,CAAC,aAAa;gBAAE,OAAO;YACnC,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7E,QAAQ,CAAC,KAAK,CAAC,GAAG,MAAM,UAAU,KAAK,CAAC,IAAI,WAAW,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACtF,CAAC;QACD,OAAO,CAAC,IAAI;YACV,IAAI,CAAC,QAAQ,CAAC,aAAa;gBAAE,QAAQ,CAAC,KAAK,CAAC,KAAK,IAAI,MAAM,CAAC,CAAC;QAC/D,CAAC;QACD,GAAG,CAAC,UAAU;YACZ,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;gBAC5B,IAAI,UAAU;oBAAE,QAAQ,CAAC,KAAK,CAAC,UAAU,UAAU,CAAC,IAAI,WAAW,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC;gBAChH,QAAQ,CAAC,GAAG,EAAE,CAAC;YACjB,CAAC;YACD,KAAK,EAAE,CAAC;QACV,CAAC;QACD,IAAI,MAAM;YACR,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,OAAO,CAAC,QAAQ;YACd,IAAI,MAAM;gBAAE,QAAQ,EAAE,CAAC;;gBAClB,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACrC,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,eAAe,CAC5B,OAAuB,EACvB,OAAmB,EACnB,KAAa,EACb,WAAmB,EACnB,UAAuC,EAAE;IAEzC,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,KAAK,KAAK,CAAC;IACtD,IAAI,WAAW,GAAG,WAAW,CAAC;IAC9B,IAAI,SAAS,GAAG,IAAI,CAAC;IACrB,IAAI,WAAW,GAAG,KAAK,CAAC;IACxB,MAAM,QAAQ,GAAqB,EAAE,CAAC;IACtC,MAAM,OAAO,GAAG,CAAC,KAAqB,EAAQ,EAAE;QAC9C,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;YACjC,IAAI,KAAK,CAAC,QAAQ,IAAI,WAAW;gBAAE,OAAO;YAC1C,WAAW,GAAG,KAAK,CAAC,QAAQ,CAAC;QAC/B,CAAC;QACD,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACrB,IAAI,0BAA0B,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/C,WAAW,GAAG,IAAI,CAAC;YACnB,IAAI,aAAa;gBAAE,OAAO,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC,CAAC;IACF,MAAM,WAAW,GAAG,OAAO,CAAC,kBAAkB,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE;QAC9D,IAAI,OAAO,CAAC,MAAM;YAAE,OAAO;QAC3B,IAAI,SAAS;YAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;;YAC/B,OAAO,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC,CAAC,CAAC;IACH,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAC7B,KAAK,MAAM,KAAK,IAAI,MAAM,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1D,OAAO,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;QACtG,IAAI,OAAO,CAAC,MAAM;YAAE,OAAO;IAC7B,CAAC;IACD,SAAS,GAAG,KAAK,CAAC;IAClB,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;QACvC,OAAO,CAAC,KAAK,CAAC,CAAC;QACf,IAAI,OAAO,CAAC,MAAM;YAAE,OAAO;IAC7B,CAAC;IACD,IAAI,aAAa,IAAI,CAAC,WAAW,EAAE,CAAC;QAClC,oEAAoE;QACpE,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC9C,IAAI,CAAC,GAAG;YAAE,OAAO,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,gBAAgB,EAAE,EAAE,CAAC,CAAC;aACnF,IAAI,GAAG,CAAC,MAAM,KAAK,WAAW,IAAI,GAAG,CAAC,MAAM,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YAC7F,OAAO,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC3E,CAAC;IACH,CAAC;AACH,CAAC;AAED,2BAA2B;AAC3B,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,OAAuB,EACvB,QAAwB,EACxB,KAAa,EACb,iBAAqC;IAErC,MAAM,WAAW,GAAG,MAAM,CAAC,iBAAiB,IAAI,CAAC,CAAC,CAAC;IACnD,MAAM,OAAO,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;IACzC,MAAM,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACjG,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,OAAuB,EACvB,QAAwB,EACxB,QAA2E,EAC3E,SAAuC;IAEvC,MAAM,OAAO,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;IACzC,IAAI,QAAmC,CAAC;IACxC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,CAAC,GAAG,EAAE,EAAE;YACpC,QAAQ,GAAG,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC3G,CAAC,CAAC,CAAC;QACH,MAAM,QAAQ,CAAC;QACf,OAAO,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC/D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;IAC9G,CAAC;AACH,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { JsonObject } from "@assemblyline-agents/core";
2
+ import { type ProviderReconciliationResult, type ResolvedStateAdapter, type UsageQuery, type UsageSummaryQuery } from "@assemblyline-agents/runtime";
3
+ export declare function usageHttpResult(state: ResolvedStateAdapter, url: URL): Promise<{
4
+ view: "records" | "summary";
5
+ query: UsageQuery | UsageSummaryQuery;
6
+ data: unknown[];
7
+ }>;
8
+ export declare function usageReconciliationHttpResult(state: ResolvedStateAdapter, env: Record<string, string | undefined>, body: JsonObject): Promise<ProviderReconciliationResult>;
9
+ //# sourceMappingURL=usage-http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage-http.d.ts","sourceRoot":"","sources":["../src/usage-http.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAKL,KAAK,4BAA4B,EACjC,KAAK,oBAAoB,EAEzB,KAAK,UAAU,EAEf,KAAK,iBAAiB,EACvB,MAAM,8BAA8B,CAAC;AAoBtC,wBAAsB,eAAe,CACnC,KAAK,EAAE,oBAAoB,EAC3B,GAAG,EAAE,GAAG,GACP,OAAO,CAAC;IAAE,IAAI,EAAE,SAAS,GAAG,SAAS,CAAC;IAAC,KAAK,EAAE,UAAU,GAAG,iBAAiB,CAAC;IAAC,IAAI,EAAE,OAAO,EAAE,CAAA;CAAE,CAAC,CAmBlG;AAED,wBAAsB,6BAA6B,CACjD,KAAK,EAAE,oBAAoB,EAC3B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EACvC,IAAI,EAAE,UAAU,GACf,OAAO,CAAC,4BAA4B,CAAC,CA8CvC"}
@@ -0,0 +1,184 @@
1
+ import { queryUsageRecords, reconcileOpenAIOrganization, reconcileOpenRouterUsage, summarizeUsageRecords } from "@assemblyline-agents/runtime";
2
+ const GROUPS = new Set([
3
+ "agentId",
4
+ "agentRevision",
5
+ "runId",
6
+ "parentRunId",
7
+ "subagent",
8
+ "provider",
9
+ "model",
10
+ "responseModel",
11
+ "billingMode",
12
+ "currency",
13
+ "tokenSource",
14
+ "costSource",
15
+ "recordKind",
16
+ "day",
17
+ "month"
18
+ ]);
19
+ export async function usageHttpResult(state, url) {
20
+ const base = usageQuery(url);
21
+ const view = url.searchParams.get("view") === "records" ? "records" : "summary";
22
+ if (view === "records") {
23
+ const records = state.queryUsage
24
+ ? await state.queryUsage(base)
25
+ : queryUsageRecords(await state.listUsage(), base);
26
+ return { view, query: base, data: records };
27
+ }
28
+ const summary = {
29
+ ...base,
30
+ groupBy: groupBy(url)
31
+ };
32
+ delete summary.before;
33
+ delete summary.limit;
34
+ const aggregates = state.summarizeUsage
35
+ ? await state.summarizeUsage(summary)
36
+ : summarizeUsageRecords(await state.listUsage(), summary);
37
+ return { view, query: summary, data: aggregates };
38
+ }
39
+ export async function usageReconciliationHttpResult(state, env, body) {
40
+ const provider = bodyString(body, "provider");
41
+ const from = bodyString(body, "from");
42
+ if (!from)
43
+ throw new Error("Usage reconciliation requires an ISO `from` timestamp.");
44
+ const to = bodyString(body, "to");
45
+ const providerLabel = bodyString(body, "providerLabel");
46
+ if (provider === "openai") {
47
+ const adminKey = env.OPENEVE_OPENAI_ADMIN_KEY ?? env.OPENAI_ADMIN_KEY;
48
+ if (!adminKey) {
49
+ throw new Error("OPENEVE_OPENAI_ADMIN_KEY or OPENAI_ADMIN_KEY is required for OpenAI reconciliation.");
50
+ }
51
+ const projectIds = commaList(env.OPENEVE_OPENAI_USAGE_PROJECT_IDS);
52
+ const apiKeyIds = commaList(env.OPENEVE_OPENAI_USAGE_API_KEY_IDS);
53
+ const agentByProjectId = jsonStringMap(env.OPENEVE_OPENAI_AGENT_BY_PROJECT_ID);
54
+ const agentByApiKeyId = jsonStringMap(env.OPENEVE_OPENAI_AGENT_BY_API_KEY_ID);
55
+ const settlementLagHours = optionalNumber(env.OPENEVE_USAGE_RECONCILIATION_LAG_HOURS);
56
+ return reconcileOpenAIOrganization({
57
+ state,
58
+ adminKey,
59
+ from,
60
+ ...(to ? { to } : {}),
61
+ ...(providerLabel ? { provider: providerLabel } : {}),
62
+ ...(projectIds ? { projectIds } : {}),
63
+ ...(apiKeyIds ? { apiKeyIds } : {}),
64
+ ...(agentByProjectId ? { agentByProjectId } : {}),
65
+ ...(agentByApiKeyId ? { agentByApiKeyId } : {}),
66
+ ...(settlementLagHours !== undefined ? { settlementLagHours } : {})
67
+ });
68
+ }
69
+ if (provider === "openrouter") {
70
+ const apiKey = env.OPENROUTER_API_KEY;
71
+ const managementKey = env.OPENROUTER_MANAGEMENT_KEY;
72
+ const apiKeyHash = env.OPENEVE_OPENROUTER_API_KEY_HASH;
73
+ const agentId = env.OPENEVE_OPENROUTER_CONTROL_AGENT_ID;
74
+ return reconcileOpenRouterUsage({
75
+ state,
76
+ from,
77
+ ...(to ? { to } : {}),
78
+ ...(providerLabel ? { provider: providerLabel } : {}),
79
+ ...(apiKey ? { apiKey } : {}),
80
+ ...(managementKey ? { managementKey } : {}),
81
+ ...(apiKeyHash ? { apiKeyHash } : {}),
82
+ ...(agentId ? { agentId } : {})
83
+ });
84
+ }
85
+ throw new Error("Usage reconciliation provider must be `openai` or `openrouter`.");
86
+ }
87
+ function usageQuery(url) {
88
+ const query = { recordKind: recordKind(url.searchParams.get("recordKind")) };
89
+ copy(url, query, "runId");
90
+ copy(url, query, "parentRunId");
91
+ copy(url, query, "agentId");
92
+ copy(url, query, "agentRevision");
93
+ copy(url, query, "subagent");
94
+ copy(url, query, "provider");
95
+ copy(url, query, "model");
96
+ copy(url, query, "responseModel");
97
+ copy(url, query, "billingMode");
98
+ copy(url, query, "currency");
99
+ copy(url, query, "tokenSource");
100
+ copy(url, query, "costSource");
101
+ const from = iso(url.searchParams.get("from"), "from");
102
+ const to = iso(url.searchParams.get("to"), "to");
103
+ if (from)
104
+ query.from = from;
105
+ if (to)
106
+ query.to = to;
107
+ if (from && to && from >= to)
108
+ throw new Error("Usage query from must be before to.");
109
+ const limit = url.searchParams.get("limit");
110
+ if (limit !== null) {
111
+ const parsed = Number(limit);
112
+ if (!Number.isInteger(parsed) || parsed < 1 || parsed > 10_000) {
113
+ throw new Error("Usage query limit must be an integer from 1 to 10000.");
114
+ }
115
+ query.limit = parsed;
116
+ }
117
+ return query;
118
+ }
119
+ function groupBy(url) {
120
+ const raw = url.searchParams.get("groupBy") ?? "agentId,provider,model,billingMode,costSource,currency,day";
121
+ const groups = raw.split(",").map((value) => value.trim()).filter(Boolean);
122
+ for (const group of groups) {
123
+ if (!GROUPS.has(group))
124
+ throw new Error(`Unsupported usage group: ${group}.`);
125
+ }
126
+ return [...new Set(groups)];
127
+ }
128
+ function recordKind(value) {
129
+ if (value === null || value === "")
130
+ return "transaction";
131
+ if (value === "transaction" || value === "control_total" || value === "adjustment")
132
+ return value;
133
+ throw new Error(`Unsupported usage recordKind: ${value}.`);
134
+ }
135
+ function copy(url, query, key) {
136
+ const value = url.searchParams.get(String(key));
137
+ if (value !== null && value.trim())
138
+ query[key] = value.trim();
139
+ }
140
+ function iso(value, name) {
141
+ if (value === null || value.trim() === "")
142
+ return undefined;
143
+ const date = new Date(value);
144
+ if (Number.isNaN(date.getTime()))
145
+ throw new Error(`Usage query ${name} must be an ISO timestamp.`);
146
+ return date.toISOString();
147
+ }
148
+ function bodyString(body, key) {
149
+ const value = body[key];
150
+ return typeof value === "string" && value.trim() ? value.trim() : undefined;
151
+ }
152
+ function commaList(value) {
153
+ const values = value?.split(",").map((entry) => entry.trim()).filter(Boolean);
154
+ return values && values.length > 0 ? values : undefined;
155
+ }
156
+ function optionalNumber(value) {
157
+ if (value === undefined || value.trim() === "")
158
+ return undefined;
159
+ const parsed = Number(value);
160
+ if (!Number.isFinite(parsed) || parsed < 0) {
161
+ throw new Error("OPENEVE_USAGE_RECONCILIATION_LAG_HOURS must be non-negative.");
162
+ }
163
+ return parsed;
164
+ }
165
+ function jsonStringMap(value) {
166
+ if (!value?.trim())
167
+ return undefined;
168
+ let parsed;
169
+ try {
170
+ parsed = JSON.parse(value);
171
+ }
172
+ catch {
173
+ throw new Error("Usage attribution maps must be JSON objects with string values.");
174
+ }
175
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
176
+ throw new Error("Usage attribution maps must be JSON objects with string values.");
177
+ }
178
+ const entries = Object.entries(parsed);
179
+ if (!entries.every(([, entry]) => typeof entry === "string" && entry.trim())) {
180
+ throw new Error("Usage attribution maps must be JSON objects with string values.");
181
+ }
182
+ return Object.fromEntries(entries.map(([key, entry]) => [key, entry.trim()]));
183
+ }
184
+ //# sourceMappingURL=usage-http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage-http.js","sourceRoot":"","sources":["../src/usage-http.ts"],"names":[],"mappings":"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"}