evlog 2.19.2 → 2.20.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/README.md +30 -1
- package/dist/adapters/axiom.d.mts +1 -1
- package/dist/adapters/axiom.mjs +2 -2
- package/dist/adapters/better-stack.d.mts +1 -1
- package/dist/adapters/better-stack.mjs +2 -2
- package/dist/adapters/datadog.d.mts +1 -1
- package/dist/adapters/datadog.mjs +2 -2
- package/dist/adapters/fs.d.mts +1 -1
- package/dist/adapters/fs.mjs +1 -1
- package/dist/adapters/hyperdx.d.mts +1 -1
- package/dist/adapters/hyperdx.mjs +1 -1
- package/dist/adapters/memory.d.mts +1 -1
- package/dist/adapters/memory.mjs +1 -1
- package/dist/adapters/otlp.d.mts +1 -1
- package/dist/adapters/otlp.mjs +2 -2
- package/dist/adapters/posthog.d.mts +1 -1
- package/dist/adapters/posthog.mjs +2 -2
- package/dist/adapters/sentry.d.mts +1 -1
- package/dist/adapters/sentry.mjs +2 -2
- package/dist/ai/index.d.mts +27 -10
- package/dist/ai/index.d.mts.map +1 -1
- package/dist/ai/index.mjs +80 -15
- package/dist/ai/index.mjs.map +1 -1
- package/dist/asyncStorageScope-DnF7Xk8l.mjs +81 -0
- package/dist/asyncStorageScope-DnF7Xk8l.mjs.map +1 -0
- package/dist/{audit-CL0q7GJU.mjs → audit-BXCYMjcC.mjs} +21 -6
- package/dist/audit-BXCYMjcC.mjs.map +1 -0
- package/dist/{audit-CBfv3rl1.d.mts → audit-BZrUvjfW.d.mts} +2 -1
- package/dist/{audit-CBfv3rl1.d.mts.map → audit-BZrUvjfW.d.mts.map} +1 -1
- package/dist/audit-action.d.mts +1 -1
- package/dist/audit.d.mts +1 -1
- package/dist/audit.mjs +1 -1
- package/dist/better-auth/index.d.mts +1 -1
- package/dist/browser.d.mts +1 -1
- package/dist/{catalog-CyemiLYG.d.mts → catalog-1cQnNxR2.d.mts} +3 -3
- package/dist/{catalog-CyemiLYG.d.mts.map → catalog-1cQnNxR2.d.mts.map} +1 -1
- package/dist/catalog.d.mts +1 -1
- package/dist/{define-BuDJpV2b.d.mts → define-Ct2QyrE9.d.mts} +3 -3
- package/dist/{define-BuDJpV2b.d.mts.map → define-Ct2QyrE9.d.mts.map} +1 -1
- package/dist/{drain-6lV-g7JB.mjs → drain-Dl2ZJKRA.mjs} +3 -3
- package/dist/{drain-6lV-g7JB.mjs.map → drain-Dl2ZJKRA.mjs.map} +1 -1
- package/dist/elysia/index.d.mts +6 -5
- package/dist/elysia/index.d.mts.map +1 -1
- package/dist/elysia/index.mjs +11 -8
- package/dist/elysia/index.mjs.map +1 -1
- package/dist/{enrich-error-stack-next.node-BecxSKUc.mjs → enrich-error-stack-next.node-KB0Oap7R.mjs} +1 -1
- package/dist/{enrich-error-stack-next.node-BecxSKUc.mjs.map → enrich-error-stack-next.node-KB0Oap7R.mjs.map} +1 -1
- package/dist/{enricher-VdBVX4oT.d.mts → enricher-BOzt2FCi.d.mts} +2 -2
- package/dist/{enricher-VdBVX4oT.d.mts.map → enricher-BOzt2FCi.d.mts.map} +1 -1
- package/dist/enrichers.d.mts +2 -2
- package/dist/{error-CPCM5a1D.d.mts → error-BRymuv8U.d.mts} +2 -2
- package/dist/{error-CPCM5a1D.d.mts.map → error-BRymuv8U.d.mts.map} +1 -1
- package/dist/error.d.mts +1 -1
- package/dist/{errors-ZdY6Ohi6.d.mts → errors-C7qA6CAi.d.mts} +2 -2
- package/dist/{errors-ZdY6Ohi6.d.mts.map → errors-C7qA6CAi.d.mts.map} +1 -1
- package/dist/eve/index.d.mts +72 -0
- package/dist/eve/index.d.mts.map +1 -0
- package/dist/eve/index.mjs +593 -0
- package/dist/eve/index.mjs.map +1 -0
- package/dist/express/index.d.mts +2 -2
- package/dist/express/index.mjs +3 -3
- package/dist/fastify/index.d.mts +2 -2
- package/dist/fastify/index.mjs +3 -3
- package/dist/fork-S9gpZmF8.mjs +72 -0
- package/dist/fork-S9gpZmF8.mjs.map +1 -0
- package/dist/hono/index.d.mts +2 -2
- package/dist/hono/index.mjs +1 -1
- package/dist/{http-DA3RWQrm.mjs → http-pKfd8UDu.mjs} +2 -2
- package/dist/{http-DA3RWQrm.mjs.map → http-pKfd8UDu.mjs.map} +1 -1
- package/dist/http.d.mts +1 -1
- package/dist/index.d.mts +8 -8
- package/dist/index.mjs +1 -1
- package/dist/{instrumentation-create-STGmQGQt.d.mts → instrumentation-create-gSDk0leX.d.mts} +2 -2
- package/dist/{instrumentation-create-STGmQGQt.d.mts.map → instrumentation-create-gSDk0leX.d.mts.map} +1 -1
- package/dist/{integration-2PpI-bCm.mjs → integration-CeL90DtN.mjs} +3 -2
- package/dist/{integration-2PpI-bCm.mjs.map → integration-CeL90DtN.mjs.map} +1 -1
- package/dist/{logger-DWTPZ0c1.d.mts → logger-CxWz7QJ3.d.mts} +7 -3
- package/dist/logger-CxWz7QJ3.d.mts.map +1 -0
- package/dist/logger.d.mts +2 -2
- package/dist/logger.mjs +2 -2
- package/dist/{fork-Di44utlp.mjs → middleware-Cdebyfdt.mjs} +3 -69
- package/dist/middleware-Cdebyfdt.mjs.map +1 -0
- package/dist/{middleware-CjVyGyrG.d.mts → middleware-fbtEs6bq.d.mts} +2 -2
- package/dist/{middleware-CjVyGyrG.d.mts.map → middleware-fbtEs6bq.d.mts.map} +1 -1
- package/dist/nestjs/index.d.mts +2 -2
- package/dist/nestjs/index.mjs +4 -3
- package/dist/nestjs/index.mjs.map +1 -1
- package/dist/next/client.d.mts +1 -1
- package/dist/next/index.d.mts +4 -4
- package/dist/next/index.mjs +3 -3
- package/dist/next/instrumentation/create.d.mts +1 -1
- package/dist/next/instrumentation/create.mjs +1 -1
- package/dist/next/instrumentation.d.mts +1 -1
- package/dist/next/stream.d.mts +1 -1
- package/dist/nitro/errorHandler.mjs +1 -1
- package/dist/nitro/module.d.mts +2 -2
- package/dist/nitro/module.mjs +1 -1
- package/dist/nitro/plugin.mjs +2 -2
- package/dist/nitro/v3/errorHandler.mjs +1 -1
- package/dist/nitro/v3/index.d.mts +2 -2
- package/dist/nitro/v3/module.d.mts +1 -1
- package/dist/nitro/v3/module.mjs +1 -1
- package/dist/nitro/v3/plugin.mjs +2 -2
- package/dist/nitro/v3/useLogger.d.mts +1 -1
- package/dist/{nitro--E4op34w.d.mts → nitro-CcN7HDnr.d.mts} +2 -2
- package/dist/{nitro--E4op34w.d.mts.map → nitro-CcN7HDnr.d.mts.map} +1 -1
- package/dist/{nitro-ClHmVj1H.mjs → nitro-DYFCSlho.mjs} +2 -2
- package/dist/{nitro-ClHmVj1H.mjs.map → nitro-DYFCSlho.mjs.map} +1 -1
- package/dist/{nitroConfigBridge-BkVWnSV3.mjs → nitroConfigBridge-lHPsE5zG.mjs} +8 -6
- package/dist/nitroConfigBridge-lHPsE5zG.mjs.map +1 -0
- package/dist/{nodeResponse-DKrYWrxk.mjs → nodeResponse-Dsl7gZUf.mjs} +1 -1
- package/dist/{nodeResponse-DKrYWrxk.mjs.map → nodeResponse-Dsl7gZUf.mjs.map} +1 -1
- package/dist/nuxt/module.d.mts +1 -1
- package/dist/nuxt/module.mjs +2 -2
- package/dist/orpc/index.d.mts +2 -2
- package/dist/orpc/index.mjs +2 -2
- package/dist/{package-Bgs0VSDF.mjs → package-Drb3wqqt.mjs} +2 -2
- package/dist/package-Drb3wqqt.mjs.map +1 -0
- package/dist/{parseError-BwBg-iW4.d.mts → parseError-BmoJ7XeF.d.mts} +2 -2
- package/dist/parseError-BmoJ7XeF.d.mts.map +1 -0
- package/dist/react-router/index.d.mts +2 -2
- package/dist/react-router/index.mjs +3 -2
- package/dist/react-router/index.mjs.map +1 -1
- package/dist/{register-disk-snippet-B_JyhodL.mjs → register-disk-snippet-B5svlT8-.mjs} +1 -1
- package/dist/{register-disk-snippet-B_JyhodL.mjs.map → register-disk-snippet-B5svlT8-.mjs.map} +1 -1
- package/dist/runtime/client/log.d.mts +1 -1
- package/dist/runtime/server/routes/_evlog/ingest.post.mjs +1 -1
- package/dist/runtime/server/useLogger.d.mts +1 -1
- package/dist/runtime/utils/parseError.d.mts +2 -2
- package/dist/{storage-D4sBVffQ.mjs → storage-BeFdoGTI.mjs} +1 -1
- package/dist/{storage-D4sBVffQ.mjs.map → storage-BeFdoGTI.mjs.map} +1 -1
- package/dist/stream.d.mts +1 -1
- package/dist/stream.d.mts.map +1 -1
- package/dist/stream.mjs +7 -1
- package/dist/stream.mjs.map +1 -1
- package/dist/sveltekit/index.d.mts +2 -2
- package/dist/sveltekit/index.mjs +5 -4
- package/dist/sveltekit/index.mjs.map +1 -1
- package/dist/toolkit.d.mts +5 -5
- package/dist/toolkit.mjs +7 -6
- package/dist/types.d.mts +1 -1
- package/dist/{useLogger-DiRWGD33.d.mts → useLogger-BupVLO9_.d.mts} +2 -2
- package/dist/{useLogger-DiRWGD33.d.mts.map → useLogger-BupVLO9_.d.mts.map} +1 -1
- package/dist/{utils-XPMPENUK.d.mts → utils-D_LY-J1k.d.mts} +2 -2
- package/dist/{utils-XPMPENUK.d.mts.map → utils-D_LY-J1k.d.mts.map} +1 -1
- package/dist/utils.d.mts +1 -1
- package/dist/vite/index.d.mts +1 -1
- package/dist/workers.d.mts +1 -1
- package/dist/workers.mjs +1 -1
- package/package.json +17 -2
- package/dist/audit-CL0q7GJU.mjs.map +0 -1
- package/dist/fork-Di44utlp.mjs.map +0 -1
- package/dist/logger-DWTPZ0c1.d.mts.map +0 -1
- package/dist/nitroConfigBridge-BkVWnSV3.mjs.map +0 -1
- package/dist/package-Bgs0VSDF.mjs.map +0 -1
- package/dist/parseError-BwBg-iW4.d.mts.map +0 -1
|
@@ -0,0 +1,593 @@
|
|
|
1
|
+
import { C as isLoggerInitialized, w as isLoggerLocked, x as initLogger } from "../audit-BXCYMjcC.mjs";
|
|
2
|
+
import { t as createMiddlewareLogger } from "../middleware-Cdebyfdt.mjs";
|
|
3
|
+
import { n as clearAsyncLocalStorage, r as patchAsyncLocalStorageEnterWith, t as bindAsyncLocalStorage } from "../asyncStorageScope-DnF7Xk8l.mjs";
|
|
4
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
5
|
+
import { defineHook } from "eve/hooks";
|
|
6
|
+
//#region src/eve/index.ts
|
|
7
|
+
const DEFAULT_MAX_SESSIONS = 256;
|
|
8
|
+
/** Top-level wide-event keys that stay turn-scoped and are not carried across turns. */
|
|
9
|
+
const TURN_ONLY_KEYS = new Set([
|
|
10
|
+
"eve",
|
|
11
|
+
"ai",
|
|
12
|
+
"message",
|
|
13
|
+
"method",
|
|
14
|
+
"path",
|
|
15
|
+
"status",
|
|
16
|
+
"duration",
|
|
17
|
+
"level",
|
|
18
|
+
"error",
|
|
19
|
+
"agent",
|
|
20
|
+
"channel",
|
|
21
|
+
"approval",
|
|
22
|
+
"audit",
|
|
23
|
+
"requestId",
|
|
24
|
+
"service",
|
|
25
|
+
"timestamp",
|
|
26
|
+
"traceId",
|
|
27
|
+
"spanId"
|
|
28
|
+
]);
|
|
29
|
+
function turnKey(sessionId, turnId) {
|
|
30
|
+
return `${sessionId}:${turnId}`;
|
|
31
|
+
}
|
|
32
|
+
function freshAccumulator(options) {
|
|
33
|
+
return {
|
|
34
|
+
calls: 0,
|
|
35
|
+
steps: 0,
|
|
36
|
+
inputTokens: 0,
|
|
37
|
+
outputTokens: 0,
|
|
38
|
+
cacheReadTokens: 0,
|
|
39
|
+
cacheWriteTokens: 0,
|
|
40
|
+
toolExecutions: [],
|
|
41
|
+
subagents: [],
|
|
42
|
+
pausedForInput: false,
|
|
43
|
+
costMap: options.cost,
|
|
44
|
+
costModel: resolveCostModel(options)
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function resolveCostModel(options) {
|
|
48
|
+
if (options.model) return options.model;
|
|
49
|
+
const keys = options.cost ? Object.keys(options.cost) : [];
|
|
50
|
+
if (keys.length === 1) return keys[0];
|
|
51
|
+
}
|
|
52
|
+
function computeEstimatedCost(state) {
|
|
53
|
+
if (!state.costMap || !state.costModel) return void 0;
|
|
54
|
+
const pricing = state.costMap[state.costModel];
|
|
55
|
+
if (!pricing) return void 0;
|
|
56
|
+
const total = state.inputTokens / 1e6 * pricing.input + state.outputTokens / 1e6 * pricing.output;
|
|
57
|
+
return total > 0 ? Math.round(total * 1e6) / 1e6 : void 0;
|
|
58
|
+
}
|
|
59
|
+
function buildAiField(state) {
|
|
60
|
+
const totalTokens = state.inputTokens + state.outputTokens;
|
|
61
|
+
const data = {
|
|
62
|
+
calls: state.calls,
|
|
63
|
+
inputTokens: state.inputTokens,
|
|
64
|
+
outputTokens: state.outputTokens,
|
|
65
|
+
totalTokens,
|
|
66
|
+
steps: state.steps
|
|
67
|
+
};
|
|
68
|
+
if (state.costModel) data.model = state.costModel;
|
|
69
|
+
if (state.cacheReadTokens > 0) data.cacheReadTokens = state.cacheReadTokens;
|
|
70
|
+
if (state.cacheWriteTokens > 0) data.cacheWriteTokens = state.cacheWriteTokens;
|
|
71
|
+
if (state.finishReason) data.finishReason = state.finishReason;
|
|
72
|
+
const estimatedCost = computeEstimatedCost(state);
|
|
73
|
+
if (estimatedCost !== void 0) data.estimatedCost = estimatedCost;
|
|
74
|
+
if (state.toolExecutions.length > 0) data.tools = state.toolExecutions.map((t) => ({ ...t }));
|
|
75
|
+
return data;
|
|
76
|
+
}
|
|
77
|
+
function extractToolName(result) {
|
|
78
|
+
if (result && typeof result === "object") {
|
|
79
|
+
const record = result;
|
|
80
|
+
if (typeof record.toolName === "string") return record.toolName;
|
|
81
|
+
if (typeof record.subagentName === "string") return record.subagentName;
|
|
82
|
+
if (typeof record.name === "string") return record.name;
|
|
83
|
+
}
|
|
84
|
+
return "unknown";
|
|
85
|
+
}
|
|
86
|
+
function extractCallId(result) {
|
|
87
|
+
if (result && typeof result === "object") {
|
|
88
|
+
const { callId } = result;
|
|
89
|
+
if (typeof callId === "string") return callId;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function truncateMessage(message, maxLength = 500) {
|
|
93
|
+
if (message.length <= maxLength) return message;
|
|
94
|
+
return `${message.slice(0, maxLength)}…`;
|
|
95
|
+
}
|
|
96
|
+
function ensureInit(options) {
|
|
97
|
+
const state = getEveGlobalState();
|
|
98
|
+
if (options.maxSessions !== void 0) state.maxSessions = options.maxSessions;
|
|
99
|
+
if (isEveInitialized()) return;
|
|
100
|
+
if (!isLoggerLocked() && !isLoggerInitialized()) initLogger(options.init ?? { env: { service: "eve-agent" } });
|
|
101
|
+
setEveInitialized(true);
|
|
102
|
+
}
|
|
103
|
+
const turnLoggerStorage = new AsyncLocalStorage();
|
|
104
|
+
patchAsyncLocalStorageEnterWith(turnLoggerStorage);
|
|
105
|
+
const activeTurnLoggers = /* @__PURE__ */ new WeakSet();
|
|
106
|
+
function bindTurnLogger(logger) {
|
|
107
|
+
bindAsyncLocalStorage(turnLoggerStorage, logger);
|
|
108
|
+
activeTurnLoggers.add(logger);
|
|
109
|
+
}
|
|
110
|
+
function unbindTurnLogger(logger) {
|
|
111
|
+
activeTurnLoggers.delete(logger);
|
|
112
|
+
if (turnLoggerStorage.getStore() === logger) clearAsyncLocalStorage(turnLoggerStorage);
|
|
113
|
+
}
|
|
114
|
+
function resolveTurnLogger(ctx) {
|
|
115
|
+
const sessionId = ctx.session.id;
|
|
116
|
+
const turnId = ctx.session.turn?.id ?? activeTurnBySession().get(sessionId);
|
|
117
|
+
if (!turnId) throw new Error("[evlog] useLogger() could not resolve the active turn. Ensure defineEvlogHook() is registered and the turn has started.");
|
|
118
|
+
const state = turnStates().get(turnKey(sessionId, turnId));
|
|
119
|
+
if (!state) throw new Error("[evlog] useLogger() could not find a logger for the current turn. Ensure defineEvlogHook() is registered and the turn has started.");
|
|
120
|
+
return state.logger;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Turn-scoped logger for eve tool `execute()` handlers.
|
|
124
|
+
*
|
|
125
|
+
* When {@link defineEvlogHook} is registered, the logger is bound via
|
|
126
|
+
* AsyncLocalStorage on `turn.started`. Inside tool handlers, `useLogger()`
|
|
127
|
+
* resolves from ALS when it propagated, otherwise from the sole active turn
|
|
128
|
+
* in the process (typical eve dev). Pass eve tool `ctx` only when multiple
|
|
129
|
+
* sessions are active concurrently.
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* ```ts
|
|
133
|
+
* import { useLogger } from 'evlog/eve'
|
|
134
|
+
*
|
|
135
|
+
* export default defineTool({
|
|
136
|
+
* async execute(input) {
|
|
137
|
+
* const log = useLogger()
|
|
138
|
+
* log.set({ order: { id: input.orderId } })
|
|
139
|
+
* },
|
|
140
|
+
* })
|
|
141
|
+
* ```
|
|
142
|
+
*/
|
|
143
|
+
function resolveActiveTurnLogger() {
|
|
144
|
+
const active = activeTurnBySession();
|
|
145
|
+
if (active.size !== 1) return null;
|
|
146
|
+
const [sessionId, turnId] = active.entries().next().value;
|
|
147
|
+
return turnStates().get(turnKey(sessionId, turnId))?.logger ?? null;
|
|
148
|
+
}
|
|
149
|
+
function useLogger(ctx) {
|
|
150
|
+
const fromStorage = turnLoggerStorage.getStore();
|
|
151
|
+
if (fromStorage && activeTurnLoggers.has(fromStorage)) return fromStorage;
|
|
152
|
+
if (ctx?.session?.id) return resolveTurnLogger(ctx);
|
|
153
|
+
const active = resolveActiveTurnLogger();
|
|
154
|
+
if (active) return active;
|
|
155
|
+
throw new Error("[evlog] useLogger() was called outside an evlog eve turn. Add agent/hooks/evlog.ts with defineEvlogHook() or pass ctx from the tool handler.");
|
|
156
|
+
}
|
|
157
|
+
const EVE_GLOBAL_STATE = Symbol.for("evlog.eve.state");
|
|
158
|
+
function getEveGlobalState() {
|
|
159
|
+
const host = globalThis;
|
|
160
|
+
if (!host[EVE_GLOBAL_STATE]) host[EVE_GLOBAL_STATE] = {
|
|
161
|
+
turnStates: /* @__PURE__ */ new Map(),
|
|
162
|
+
activeTurnBySession: /* @__PURE__ */ new Map(),
|
|
163
|
+
sessionSnapshots: /* @__PURE__ */ new Map(),
|
|
164
|
+
sessionPendingActions: /* @__PURE__ */ new Map(),
|
|
165
|
+
sessionApprovals: /* @__PURE__ */ new Map(),
|
|
166
|
+
sessionRollups: /* @__PURE__ */ new Map(),
|
|
167
|
+
maxSessions: DEFAULT_MAX_SESSIONS,
|
|
168
|
+
initialized: false
|
|
169
|
+
};
|
|
170
|
+
return host[EVE_GLOBAL_STATE];
|
|
171
|
+
}
|
|
172
|
+
function turnStates() {
|
|
173
|
+
return getEveGlobalState().turnStates;
|
|
174
|
+
}
|
|
175
|
+
function activeTurnBySession() {
|
|
176
|
+
return getEveGlobalState().activeTurnBySession;
|
|
177
|
+
}
|
|
178
|
+
function sessionSnapshots() {
|
|
179
|
+
return getEveGlobalState().sessionSnapshots;
|
|
180
|
+
}
|
|
181
|
+
function sessionPendingActions() {
|
|
182
|
+
return getEveGlobalState().sessionPendingActions;
|
|
183
|
+
}
|
|
184
|
+
function sessionApprovals() {
|
|
185
|
+
return getEveGlobalState().sessionApprovals;
|
|
186
|
+
}
|
|
187
|
+
function sessionRollups() {
|
|
188
|
+
return getEveGlobalState().sessionRollups;
|
|
189
|
+
}
|
|
190
|
+
function touchSession(sessionId) {
|
|
191
|
+
const rollups = sessionRollups();
|
|
192
|
+
const rollup = rollups.get(sessionId) ?? {
|
|
193
|
+
turnCount: 0,
|
|
194
|
+
lastAccess: 0
|
|
195
|
+
};
|
|
196
|
+
rollup.lastAccess = Date.now();
|
|
197
|
+
rollups.set(sessionId, rollup);
|
|
198
|
+
evictStaleSessions();
|
|
199
|
+
}
|
|
200
|
+
function clearSessionState(sessionId) {
|
|
201
|
+
sessionSnapshots().delete(sessionId);
|
|
202
|
+
sessionRollups().delete(sessionId);
|
|
203
|
+
sessionPendingActions().delete(sessionId);
|
|
204
|
+
sessionApprovals().delete(sessionId);
|
|
205
|
+
}
|
|
206
|
+
function evictStaleSessions() {
|
|
207
|
+
const { maxSessions } = getEveGlobalState();
|
|
208
|
+
const rollups = sessionRollups();
|
|
209
|
+
if (rollups.size <= maxSessions) return;
|
|
210
|
+
const oldest = [...rollups.entries()].sort((a, b) => a[1].lastAccess - b[1].lastAccess).slice(0, rollups.size - maxSessions);
|
|
211
|
+
for (const [sessionId] of oldest) {
|
|
212
|
+
if (activeTurnBySession().has(sessionId)) continue;
|
|
213
|
+
clearSessionState(sessionId);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
function pruneEmptySessionMaps(sessionId) {
|
|
217
|
+
if (sessionPendingActions().get(sessionId)?.size === 0) sessionPendingActions().delete(sessionId);
|
|
218
|
+
if (sessionApprovals().get(sessionId)?.length === 0) sessionApprovals().delete(sessionId);
|
|
219
|
+
}
|
|
220
|
+
function bumpSessionTurnCount(sessionId) {
|
|
221
|
+
touchSession(sessionId);
|
|
222
|
+
const rollup = sessionRollups().get(sessionId);
|
|
223
|
+
rollup.turnCount += 1;
|
|
224
|
+
return rollup.turnCount;
|
|
225
|
+
}
|
|
226
|
+
/** Turn-level label — only set when the turn ends in a non-routine state. */
|
|
227
|
+
function derivePhase(ctx, accumulator, httpStatus) {
|
|
228
|
+
const approval = ctx.approval;
|
|
229
|
+
if (approval?.status === "rejected") return "rejected";
|
|
230
|
+
if (approval?.status === "pending" || accumulator.pausedForInput) return "awaiting-approval";
|
|
231
|
+
if (httpStatus >= 400) return "failed";
|
|
232
|
+
}
|
|
233
|
+
function getSessionPendingActions(sessionId) {
|
|
234
|
+
let map = sessionPendingActions().get(sessionId);
|
|
235
|
+
if (!map) {
|
|
236
|
+
map = /* @__PURE__ */ new Map();
|
|
237
|
+
sessionPendingActions().set(sessionId, map);
|
|
238
|
+
}
|
|
239
|
+
return map;
|
|
240
|
+
}
|
|
241
|
+
function trackPendingAction(sessionId, turnId, action) {
|
|
242
|
+
touchSession(sessionId);
|
|
243
|
+
getSessionPendingActions(sessionId).set(action.callId, {
|
|
244
|
+
toolName: action.toolName,
|
|
245
|
+
startedAt: action.startedAt ?? Date.now(),
|
|
246
|
+
turnId
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
function resolveToolDurationMs(state, callId) {
|
|
250
|
+
const pending = callId ? getSessionPendingActions(state.sessionId).get(callId) : void 0;
|
|
251
|
+
if (pending) {
|
|
252
|
+
if (pending.turnId !== state.turnId && state.accumulator.stepStartedAt !== void 0) return Math.max(0, Date.now() - state.accumulator.stepStartedAt);
|
|
253
|
+
return Math.max(0, Date.now() - pending.startedAt);
|
|
254
|
+
}
|
|
255
|
+
if (state.accumulator.stepStartedAt !== void 0) return Math.max(0, Date.now() - state.accumulator.stepStartedAt);
|
|
256
|
+
return 0;
|
|
257
|
+
}
|
|
258
|
+
function consumeSessionApproval(sessionId, toolName, callId) {
|
|
259
|
+
const list = sessionApprovals().get(sessionId);
|
|
260
|
+
if (!list?.length) return void 0;
|
|
261
|
+
const index = list.findIndex((approval) => callId ? approval.callId === callId : approval.toolName === toolName);
|
|
262
|
+
if (index === -1) return void 0;
|
|
263
|
+
const [approval] = list.splice(index, 1);
|
|
264
|
+
if (list.length === 0) sessionApprovals().delete(sessionId);
|
|
265
|
+
return approval;
|
|
266
|
+
}
|
|
267
|
+
function storeSessionApprovals(sessionId, pending) {
|
|
268
|
+
touchSession(sessionId);
|
|
269
|
+
const existing = sessionApprovals().get(sessionId) ?? [];
|
|
270
|
+
sessionApprovals().set(sessionId, [...existing, ...pending]);
|
|
271
|
+
}
|
|
272
|
+
function isEveInitialized() {
|
|
273
|
+
return getEveGlobalState().initialized;
|
|
274
|
+
}
|
|
275
|
+
function setEveInitialized(value) {
|
|
276
|
+
getEveGlobalState().initialized = value;
|
|
277
|
+
}
|
|
278
|
+
function applySessionContext(sessionId, logger) {
|
|
279
|
+
touchSession(sessionId);
|
|
280
|
+
const snapshot = sessionSnapshots().get(sessionId);
|
|
281
|
+
if (snapshot && Object.keys(snapshot).length > 0) logger.set({ ...snapshot });
|
|
282
|
+
}
|
|
283
|
+
function persistSessionContext(sessionId, logger) {
|
|
284
|
+
const ctx = logger.getContext();
|
|
285
|
+
const snapshot = { ...sessionSnapshots().get(sessionId) ?? {} };
|
|
286
|
+
for (const [key, value] of Object.entries(ctx)) if (!TURN_ONLY_KEYS.has(key) && value !== void 0) snapshot[key] = value;
|
|
287
|
+
sessionSnapshots().set(sessionId, snapshot);
|
|
288
|
+
}
|
|
289
|
+
function flushEveMetadata(state) {
|
|
290
|
+
if (state.accumulator.subagents.length === 0) return;
|
|
291
|
+
state.logger.set({ eve: { subagents: state.accumulator.subagents.map((s) => ({ ...s })) } });
|
|
292
|
+
}
|
|
293
|
+
function getOrCreateTurnState(sessionId, turnId, options, ctx) {
|
|
294
|
+
const key = turnKey(sessionId, turnId);
|
|
295
|
+
const existing = turnStates().get(key);
|
|
296
|
+
if (existing) return existing;
|
|
297
|
+
touchSession(sessionId);
|
|
298
|
+
const middlewareOptions = {
|
|
299
|
+
method: "EVE",
|
|
300
|
+
path: `/sessions/${sessionId}/turns/${turnId}`,
|
|
301
|
+
requestId: turnId,
|
|
302
|
+
drain: options.drain,
|
|
303
|
+
enrich: options.enrich,
|
|
304
|
+
keep: options.keep,
|
|
305
|
+
redact: options.redact,
|
|
306
|
+
plugins: options.plugins,
|
|
307
|
+
include: options.include,
|
|
308
|
+
exclude: options.exclude,
|
|
309
|
+
routes: options.routes
|
|
310
|
+
};
|
|
311
|
+
const { logger, finish, skipped } = createMiddlewareLogger(middlewareOptions);
|
|
312
|
+
if (skipped) return null;
|
|
313
|
+
const state = {
|
|
314
|
+
logger,
|
|
315
|
+
finish,
|
|
316
|
+
middlewareOptions,
|
|
317
|
+
accumulator: freshAccumulator(options),
|
|
318
|
+
sessionId,
|
|
319
|
+
turnId
|
|
320
|
+
};
|
|
321
|
+
applySessionContext(sessionId, logger);
|
|
322
|
+
logger.set({
|
|
323
|
+
eve: {
|
|
324
|
+
sessionId,
|
|
325
|
+
turnId
|
|
326
|
+
},
|
|
327
|
+
agent: {
|
|
328
|
+
name: ctx.agent.name,
|
|
329
|
+
...ctx.agent.nodeId ? { nodeId: ctx.agent.nodeId } : {}
|
|
330
|
+
},
|
|
331
|
+
channel: {
|
|
332
|
+
kind: ctx.channel.kind ?? "unknown",
|
|
333
|
+
...ctx.channel.continuationToken ? { continuing: true } : {}
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
turnStates().set(key, state);
|
|
337
|
+
activeTurnBySession().set(sessionId, turnId);
|
|
338
|
+
return state;
|
|
339
|
+
}
|
|
340
|
+
function flushAi(state) {
|
|
341
|
+
state.logger.set({ ai: buildAiField(state.accumulator) });
|
|
342
|
+
}
|
|
343
|
+
async function finishTurn(sessionId, turnId, opts) {
|
|
344
|
+
const key = turnKey(sessionId, turnId);
|
|
345
|
+
const state = turnStates().get(key);
|
|
346
|
+
if (!state) return;
|
|
347
|
+
try {
|
|
348
|
+
flushEveMetadata(state);
|
|
349
|
+
flushAi(state);
|
|
350
|
+
const httpStatus = opts.status ?? (opts.error ? 500 : 200);
|
|
351
|
+
const phase = derivePhase(state.logger.getContext(), state.accumulator, httpStatus);
|
|
352
|
+
const sessionTurns = bumpSessionTurnCount(sessionId);
|
|
353
|
+
state.logger.set({ eve: {
|
|
354
|
+
...phase ? { phase } : {},
|
|
355
|
+
sessionTurns
|
|
356
|
+
} });
|
|
357
|
+
persistSessionContext(sessionId, state.logger);
|
|
358
|
+
await state.finish(opts);
|
|
359
|
+
} finally {
|
|
360
|
+
unbindTurnLogger(state.logger);
|
|
361
|
+
turnStates().delete(key);
|
|
362
|
+
if (activeTurnBySession().get(sessionId) === turnId) activeTurnBySession().delete(sessionId);
|
|
363
|
+
pruneEmptySessionMaps(sessionId);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
function runSafe(fn) {
|
|
367
|
+
(async () => {
|
|
368
|
+
try {
|
|
369
|
+
await fn();
|
|
370
|
+
} catch (err) {
|
|
371
|
+
console.error("[evlog] eve hook handler failed:", err);
|
|
372
|
+
}
|
|
373
|
+
})();
|
|
374
|
+
}
|
|
375
|
+
function getTurnState(sessionId, turnId) {
|
|
376
|
+
return turnStates().get(turnKey(sessionId, turnId));
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Create an eve stream hook that emits one evlog wide event per agent turn.
|
|
380
|
+
*
|
|
381
|
+
* Export the result as the default export of `agent/hooks/evlog.ts`. eve
|
|
382
|
+
* auto-discovers hook files; evlog maps turn lifecycle events to a wide event
|
|
383
|
+
* with AI usage, tool executions, and your drain/enrich/keep pipeline.
|
|
384
|
+
*
|
|
385
|
+
* Complements eve Agent Runs and OpenTelemetry — it does not replace them.
|
|
386
|
+
*
|
|
387
|
+
* @example
|
|
388
|
+
* ```ts
|
|
389
|
+
* // agent/hooks/evlog.ts
|
|
390
|
+
* import { defineEvlogHook } from 'evlog/eve'
|
|
391
|
+
* import { createAxiomDrain } from 'evlog/axiom'
|
|
392
|
+
*
|
|
393
|
+
* export default defineEvlogHook({
|
|
394
|
+
* drain: createAxiomDrain(),
|
|
395
|
+
* enrich: (ctx) => {
|
|
396
|
+
* ctx.event.runtime = process.env.VERCEL_REGION
|
|
397
|
+
* },
|
|
398
|
+
* })
|
|
399
|
+
* ```
|
|
400
|
+
*/
|
|
401
|
+
function defineEvlogHook(options = {}) {
|
|
402
|
+
const redactMessage = options.redactMessage ?? true;
|
|
403
|
+
return defineHook({ events: {
|
|
404
|
+
"turn.started"(event, ctx) {
|
|
405
|
+
try {
|
|
406
|
+
ensureInit(options);
|
|
407
|
+
const state = getOrCreateTurnState(ctx.session.id, event.data.turnId, options, ctx);
|
|
408
|
+
state?.logger.set({ eve: { turnSequence: event.data.sequence } });
|
|
409
|
+
if (state) bindTurnLogger(state.logger);
|
|
410
|
+
} catch (err) {
|
|
411
|
+
console.error("[evlog] eve hook handler failed:", err);
|
|
412
|
+
}
|
|
413
|
+
},
|
|
414
|
+
"message.received"(event, ctx) {
|
|
415
|
+
runSafe(() => {
|
|
416
|
+
if (redactMessage) return;
|
|
417
|
+
const state = getTurnState(ctx.session.id, event.data.turnId);
|
|
418
|
+
if (!state) return;
|
|
419
|
+
state.logger.set({ message: { received: truncateMessage(event.data.message) } });
|
|
420
|
+
});
|
|
421
|
+
},
|
|
422
|
+
"step.started"(event, ctx) {
|
|
423
|
+
runSafe(() => {
|
|
424
|
+
const state = getTurnState(ctx.session.id, event.data.turnId);
|
|
425
|
+
if (!state) return;
|
|
426
|
+
state.accumulator.stepStartedAt = Date.now();
|
|
427
|
+
});
|
|
428
|
+
},
|
|
429
|
+
"step.completed"(event, ctx) {
|
|
430
|
+
runSafe(() => {
|
|
431
|
+
const state = getTurnState(ctx.session.id, event.data.turnId);
|
|
432
|
+
if (!state) return;
|
|
433
|
+
const acc = state.accumulator;
|
|
434
|
+
acc.steps += 1;
|
|
435
|
+
acc.calls += 1;
|
|
436
|
+
acc.finishReason = event.data.finishReason;
|
|
437
|
+
const { usage } = event.data;
|
|
438
|
+
if (usage) {
|
|
439
|
+
acc.inputTokens += usage.inputTokens ?? 0;
|
|
440
|
+
acc.outputTokens += usage.outputTokens ?? 0;
|
|
441
|
+
acc.cacheReadTokens += usage.cacheReadTokens ?? 0;
|
|
442
|
+
acc.cacheWriteTokens += usage.cacheWriteTokens ?? 0;
|
|
443
|
+
}
|
|
444
|
+
});
|
|
445
|
+
},
|
|
446
|
+
"actions.requested"(event, ctx) {
|
|
447
|
+
runSafe(() => {
|
|
448
|
+
const state = getTurnState(ctx.session.id, event.data.turnId);
|
|
449
|
+
if (!state) return;
|
|
450
|
+
bindTurnLogger(state.logger);
|
|
451
|
+
const startedAt = Date.now();
|
|
452
|
+
for (const action of event.data.actions) if (action.kind === "tool-call") trackPendingAction(ctx.session.id, event.data.turnId, {
|
|
453
|
+
callId: action.callId,
|
|
454
|
+
toolName: action.toolName,
|
|
455
|
+
startedAt
|
|
456
|
+
});
|
|
457
|
+
});
|
|
458
|
+
},
|
|
459
|
+
"input.requested"(event, ctx) {
|
|
460
|
+
runSafe(() => {
|
|
461
|
+
const state = getTurnState(ctx.session.id, event.data.turnId);
|
|
462
|
+
if (!state) return;
|
|
463
|
+
state.accumulator.pausedForInput = true;
|
|
464
|
+
const pending = event.data.requests.map((req) => ({
|
|
465
|
+
toolName: req.action.toolName,
|
|
466
|
+
callId: req.action.callId
|
|
467
|
+
}));
|
|
468
|
+
storeSessionApprovals(ctx.session.id, pending);
|
|
469
|
+
const [first] = pending;
|
|
470
|
+
if (first) state.logger.set({ approval: {
|
|
471
|
+
status: "pending",
|
|
472
|
+
tool: first.toolName
|
|
473
|
+
} });
|
|
474
|
+
});
|
|
475
|
+
},
|
|
476
|
+
"action.result"(event, ctx) {
|
|
477
|
+
runSafe(() => {
|
|
478
|
+
const state = getTurnState(ctx.session.id, event.data.turnId);
|
|
479
|
+
if (!state) return;
|
|
480
|
+
const callId = extractCallId(event.data.result);
|
|
481
|
+
const sessionPending = getSessionPendingActions(state.sessionId);
|
|
482
|
+
const turnPending = callId ? sessionPending.get(callId) : void 0;
|
|
483
|
+
const { status } = event.data;
|
|
484
|
+
const rejected = status === "rejected";
|
|
485
|
+
const success = status === "completed";
|
|
486
|
+
const toolName = turnPending?.toolName ?? extractToolName(event.data.result);
|
|
487
|
+
const durationMs = resolveToolDurationMs(state, callId);
|
|
488
|
+
if (callId) sessionPending.delete(callId);
|
|
489
|
+
const execution = {
|
|
490
|
+
name: toolName,
|
|
491
|
+
durationMs,
|
|
492
|
+
success
|
|
493
|
+
};
|
|
494
|
+
if (rejected) {
|
|
495
|
+
execution.error = "rejected";
|
|
496
|
+
state.accumulator.pausedForInput = false;
|
|
497
|
+
consumeSessionApproval(state.sessionId, toolName, callId);
|
|
498
|
+
state.logger.set({ approval: {
|
|
499
|
+
status: "rejected",
|
|
500
|
+
tool: toolName
|
|
501
|
+
} });
|
|
502
|
+
} else if (success) {
|
|
503
|
+
const approval = consumeSessionApproval(state.sessionId, toolName, callId);
|
|
504
|
+
if (approval) {
|
|
505
|
+
state.accumulator.pausedForInput = false;
|
|
506
|
+
state.logger.set({ approval: {
|
|
507
|
+
status: "approved",
|
|
508
|
+
tool: approval.toolName
|
|
509
|
+
} });
|
|
510
|
+
}
|
|
511
|
+
} else if (event.data.error) execution.error = event.data.error.message;
|
|
512
|
+
state.accumulator.toolExecutions.push(execution);
|
|
513
|
+
});
|
|
514
|
+
},
|
|
515
|
+
"subagent.called"(event, ctx) {
|
|
516
|
+
runSafe(() => {
|
|
517
|
+
const state = getTurnState(ctx.session.id, event.data.turnId);
|
|
518
|
+
if (!state) return;
|
|
519
|
+
state.accumulator.subagents.push({
|
|
520
|
+
callId: event.data.callId,
|
|
521
|
+
name: event.data.name,
|
|
522
|
+
toolName: event.data.toolName,
|
|
523
|
+
childSessionId: event.data.childSessionId,
|
|
524
|
+
status: "called"
|
|
525
|
+
});
|
|
526
|
+
});
|
|
527
|
+
},
|
|
528
|
+
"subagent.completed"(event, ctx) {
|
|
529
|
+
runSafe(() => {
|
|
530
|
+
const sessionId = ctx.session.id;
|
|
531
|
+
const turnId = activeTurnBySession().get(sessionId);
|
|
532
|
+
if (!turnId) return;
|
|
533
|
+
const state = getTurnState(sessionId, turnId);
|
|
534
|
+
if (!state) return;
|
|
535
|
+
const existing = state.accumulator.subagents.find((s) => s.callId === event.data.callId);
|
|
536
|
+
if (existing) {
|
|
537
|
+
existing.status = "completed";
|
|
538
|
+
existing.output = event.data.output;
|
|
539
|
+
} else state.accumulator.subagents.push({
|
|
540
|
+
callId: event.data.callId,
|
|
541
|
+
name: event.data.subagentName,
|
|
542
|
+
status: "completed",
|
|
543
|
+
output: event.data.output
|
|
544
|
+
});
|
|
545
|
+
});
|
|
546
|
+
},
|
|
547
|
+
async "turn.completed"(event, ctx) {
|
|
548
|
+
try {
|
|
549
|
+
await finishTurn(ctx.session.id, event.data.turnId, { status: 200 });
|
|
550
|
+
} catch (err) {
|
|
551
|
+
console.error("[evlog] eve hook handler failed:", err);
|
|
552
|
+
}
|
|
553
|
+
},
|
|
554
|
+
async "turn.failed"(event, ctx) {
|
|
555
|
+
try {
|
|
556
|
+
getTurnState(ctx.session.id, event.data.turnId)?.logger.set({ eve: { failure: {
|
|
557
|
+
code: event.data.code,
|
|
558
|
+
message: event.data.message,
|
|
559
|
+
...event.data.details ? { details: event.data.details } : {}
|
|
560
|
+
} } });
|
|
561
|
+
const error = new Error(event.data.message);
|
|
562
|
+
error.name = event.data.code;
|
|
563
|
+
await finishTurn(ctx.session.id, event.data.turnId, {
|
|
564
|
+
error,
|
|
565
|
+
status: 500
|
|
566
|
+
});
|
|
567
|
+
} catch (err) {
|
|
568
|
+
console.error("[evlog] eve hook handler failed:", err);
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
} });
|
|
572
|
+
}
|
|
573
|
+
/** @internal Simulates eve tool execution where AsyncLocalStorage did not propagate. */
|
|
574
|
+
function detachActiveTurnLoggerForTests() {
|
|
575
|
+
const logger = turnLoggerStorage.getStore();
|
|
576
|
+
if (logger) unbindTurnLogger(logger);
|
|
577
|
+
}
|
|
578
|
+
/** @internal Resets module state between unit tests. Clears turn maps, session context, and the Eve init flag. */
|
|
579
|
+
function resetEvlogEveForTests() {
|
|
580
|
+
clearAsyncLocalStorage(turnLoggerStorage);
|
|
581
|
+
turnStates().clear();
|
|
582
|
+
activeTurnBySession().clear();
|
|
583
|
+
sessionSnapshots().clear();
|
|
584
|
+
sessionPendingActions().clear();
|
|
585
|
+
sessionApprovals().clear();
|
|
586
|
+
sessionRollups().clear();
|
|
587
|
+
setEveInitialized(false);
|
|
588
|
+
delete globalThis[EVE_GLOBAL_STATE];
|
|
589
|
+
}
|
|
590
|
+
//#endregion
|
|
591
|
+
export { defineEvlogHook, detachActiveTurnLoggerForTests, resetEvlogEveForTests, useLogger };
|
|
592
|
+
|
|
593
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/eve/index.ts"],"sourcesContent":["import { AsyncLocalStorage } from 'node:async_hooks'\nimport { defineHook, type HookContext, type HookDefinition } from 'eve/hooks'\nimport type { AuditableLogger } from '../audit'\nimport type { AIToolExecution, AIEventData, ModelCost } from '../ai/index'\nimport { initLogger, isLoggerInitialized, isLoggerLocked } from '../logger'\nimport type { LoggerConfig } from '../types'\nimport type { BaseEvlogOptions, MiddlewareLoggerOptions } from '../shared/middleware'\nimport { createMiddlewareLogger } from '../shared/middleware'\nimport {\n bindAsyncLocalStorage,\n clearAsyncLocalStorage,\n patchAsyncLocalStorageEnterWith,\n} from '../shared/asyncStorageScope'\n\nconst DEFAULT_MAX_SESSIONS = 256\n\n/** Options for {@link defineEvlogHook}. */\nexport interface EvlogEveOptions extends BaseEvlogOptions {\n /** Passed to {@link initLogger} on the first hook invocation. */\n init?: LoggerConfig\n /**\n * When `true` (default), user message content from `message.received` is\n * omitted from the wide event. Set to `false` to include a truncated preview.\n */\n redactMessage?: boolean\n /**\n * Pricing map for {@link AIEventData.estimatedCost}. Keys are model IDs,\n * values are dollars per 1M tokens — same shape as `evlog/ai`.\n */\n cost?: Record<string, ModelCost>\n /**\n * Model ID used with `cost` when eve stream events do not expose the model\n * name. When `cost` has exactly one entry, that key is used automatically.\n */\n model?: string\n /**\n * Max in-memory sessions for context carry-over and approval state.\n * Oldest sessions are evicted when exceeded. Default `256`.\n */\n maxSessions?: number\n}\n\n/** Minimal session shape accepted by {@link useLogger} as a fallback lookup key. */\nexport interface EveTurnSessionContext {\n readonly session: {\n readonly id: string\n readonly turn?: { readonly id?: string }\n }\n}\n\ninterface PendingAction {\n toolName: string\n startedAt: number\n turnId: string\n}\n\ninterface EveApprovalPending {\n toolName: string\n callId: string\n}\n\ninterface SessionRollup {\n turnCount: number\n lastAccess: number\n}\n\ninterface EveSubagentRecord {\n callId: string\n name: string\n toolName?: string\n childSessionId?: string\n status: 'called' | 'completed'\n output?: string\n}\n\ninterface TurnAccumulator {\n calls: number\n steps: number\n inputTokens: number\n outputTokens: number\n cacheReadTokens: number\n cacheWriteTokens: number\n finishReason?: string\n toolExecutions: AIToolExecution[]\n subagents: EveSubagentRecord[]\n pausedForInput: boolean\n stepStartedAt?: number\n costMap?: Record<string, ModelCost>\n costModel?: string\n}\n\ninterface TurnState {\n logger: AuditableLogger\n finish: (opts?: { status?: number; error?: Error }) => Promise<unknown>\n middlewareOptions: MiddlewareLoggerOptions\n accumulator: TurnAccumulator\n sessionId: string\n turnId: string\n}\n\n/** Top-level wide-event keys that stay turn-scoped and are not carried across turns. */\nconst TURN_ONLY_KEYS = new Set([\n 'eve',\n 'ai',\n 'message',\n 'method',\n 'path',\n 'status',\n 'duration',\n 'level',\n 'error',\n 'agent',\n 'channel',\n 'approval',\n 'audit',\n 'requestId',\n 'service',\n 'timestamp',\n 'traceId',\n 'spanId',\n])\n\nfunction turnKey(sessionId: string, turnId: string): string {\n return `${sessionId}:${turnId}`\n}\n\nfunction freshAccumulator(options: EvlogEveOptions): TurnAccumulator {\n return {\n calls: 0,\n steps: 0,\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n cacheWriteTokens: 0,\n toolExecutions: [],\n subagents: [],\n pausedForInput: false,\n costMap: options.cost,\n costModel: resolveCostModel(options),\n }\n}\n\nfunction resolveCostModel(options: EvlogEveOptions): string | undefined {\n if (options.model) return options.model\n const keys = options.cost ? Object.keys(options.cost) : []\n if (keys.length === 1) return keys[0]\n return undefined\n}\n\nfunction computeEstimatedCost(state: TurnAccumulator): number | undefined {\n if (!state.costMap || !state.costModel) return undefined\n const pricing = state.costMap[state.costModel]\n if (!pricing) return undefined\n const inputCost = (state.inputTokens / 1_000_000) * pricing.input\n const outputCost = (state.outputTokens / 1_000_000) * pricing.output\n const total = inputCost + outputCost\n return total > 0 ? Math.round(total * 1_000_000) / 1_000_000 : undefined\n}\n\nfunction buildAiField(state: TurnAccumulator): AIEventData {\n const totalTokens = state.inputTokens + state.outputTokens\n const data: AIEventData = {\n calls: state.calls,\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n totalTokens,\n steps: state.steps,\n }\n if (state.costModel) data.model = state.costModel\n if (state.cacheReadTokens > 0) data.cacheReadTokens = state.cacheReadTokens\n if (state.cacheWriteTokens > 0) data.cacheWriteTokens = state.cacheWriteTokens\n if (state.finishReason) data.finishReason = state.finishReason\n const estimatedCost = computeEstimatedCost(state)\n if (estimatedCost !== undefined) data.estimatedCost = estimatedCost\n if (state.toolExecutions.length > 0) {\n data.tools = state.toolExecutions.map(t => ({ ...t }))\n }\n return data\n}\n\nfunction extractToolName(result: unknown): string {\n if (result && typeof result === 'object') {\n const record = result as Record<string, unknown>\n if (typeof record.toolName === 'string') return record.toolName\n if (typeof record.subagentName === 'string') return record.subagentName\n if (typeof record.name === 'string') return record.name\n }\n return 'unknown'\n}\n\nfunction extractCallId(result: unknown): string | undefined {\n if (result && typeof result === 'object') {\n const { callId } = result as Record<string, unknown>\n if (typeof callId === 'string') return callId\n }\n return undefined\n}\n\nfunction truncateMessage(message: string, maxLength = 500): string {\n if (message.length <= maxLength) return message\n return `${message.slice(0, maxLength)}…`\n}\n\nfunction ensureInit(options: EvlogEveOptions): void {\n const state = getEveGlobalState()\n if (options.maxSessions !== undefined) {\n state.maxSessions = options.maxSessions\n }\n if (isEveInitialized()) return\n if (!isLoggerLocked() && !isLoggerInitialized()) {\n initLogger(options.init ?? { env: { service: 'eve-agent' } })\n }\n setEveInitialized(true)\n}\n\nconst turnLoggerStorage = new AsyncLocalStorage<AuditableLogger>()\npatchAsyncLocalStorageEnterWith(turnLoggerStorage)\nconst activeTurnLoggers = new WeakSet<AuditableLogger>()\n\nfunction bindTurnLogger(logger: AuditableLogger): void {\n bindAsyncLocalStorage(turnLoggerStorage, logger)\n activeTurnLoggers.add(logger)\n}\n\nfunction unbindTurnLogger(logger: AuditableLogger): void {\n activeTurnLoggers.delete(logger)\n if (turnLoggerStorage.getStore() === logger) {\n clearAsyncLocalStorage(turnLoggerStorage)\n }\n}\n\nfunction resolveTurnLogger(ctx: EveTurnSessionContext): AuditableLogger {\n const sessionId = ctx.session.id\n const turnId = ctx.session.turn?.id ?? activeTurnBySession().get(sessionId)\n\n if (!turnId) {\n throw new Error(\n '[evlog] useLogger() could not resolve the active turn. '\n + 'Ensure defineEvlogHook() is registered and the turn has started.',\n )\n }\n\n const state = turnStates().get(turnKey(sessionId, turnId))\n if (!state) {\n throw new Error(\n '[evlog] useLogger() could not find a logger for the current turn. '\n + 'Ensure defineEvlogHook() is registered and the turn has started.',\n )\n }\n\n return state.logger\n}\n\n/**\n * Turn-scoped logger for eve tool `execute()` handlers.\n *\n * When {@link defineEvlogHook} is registered, the logger is bound via\n * AsyncLocalStorage on `turn.started`. Inside tool handlers, `useLogger()`\n * resolves from ALS when it propagated, otherwise from the sole active turn\n * in the process (typical eve dev). Pass eve tool `ctx` only when multiple\n * sessions are active concurrently.\n *\n * @example\n * ```ts\n * import { useLogger } from 'evlog/eve'\n *\n * export default defineTool({\n * async execute(input) {\n * const log = useLogger()\n * log.set({ order: { id: input.orderId } })\n * },\n * })\n * ```\n */\nfunction resolveActiveTurnLogger(): AuditableLogger | null {\n const active = activeTurnBySession()\n if (active.size !== 1) return null\n\n const [sessionId, turnId] = active.entries().next().value!\n return turnStates().get(turnKey(sessionId, turnId))?.logger ?? null\n}\n\nexport function useLogger(ctx?: EveTurnSessionContext): AuditableLogger {\n const fromStorage = turnLoggerStorage.getStore()\n if (fromStorage && activeTurnLoggers.has(fromStorage)) {\n return fromStorage\n }\n\n if (ctx?.session?.id) {\n return resolveTurnLogger(ctx)\n }\n\n const active = resolveActiveTurnLogger()\n if (active) return active\n\n throw new Error(\n '[evlog] useLogger() was called outside an evlog eve turn. '\n + 'Add agent/hooks/evlog.ts with defineEvlogHook() or pass ctx from the tool handler.',\n )\n}\n\ninterface EveGlobalState {\n turnStates: Map<string, TurnState>\n activeTurnBySession: Map<string, string>\n sessionSnapshots: Map<string, Record<string, unknown>>\n sessionPendingActions: Map<string, Map<string, PendingAction>>\n sessionApprovals: Map<string, EveApprovalPending[]>\n sessionRollups: Map<string, SessionRollup>\n maxSessions: number\n initialized: boolean\n}\n\nconst EVE_GLOBAL_STATE = Symbol.for('evlog.eve.state')\n\nfunction getEveGlobalState(): EveGlobalState {\n const host = globalThis as typeof globalThis & {\n [EVE_GLOBAL_STATE]?: EveGlobalState\n }\n if (!host[EVE_GLOBAL_STATE]) {\n host[EVE_GLOBAL_STATE] = {\n turnStates: new Map(),\n activeTurnBySession: new Map(),\n sessionSnapshots: new Map(),\n sessionPendingActions: new Map(),\n sessionApprovals: new Map(),\n sessionRollups: new Map(),\n maxSessions: DEFAULT_MAX_SESSIONS,\n initialized: false,\n }\n }\n return host[EVE_GLOBAL_STATE]\n}\n\nfunction turnStates(): Map<string, TurnState> {\n return getEveGlobalState().turnStates\n}\n\nfunction activeTurnBySession(): Map<string, string> {\n return getEveGlobalState().activeTurnBySession\n}\n\nfunction sessionSnapshots(): Map<string, Record<string, unknown>> {\n return getEveGlobalState().sessionSnapshots\n}\n\nfunction sessionPendingActions(): Map<string, Map<string, PendingAction>> {\n return getEveGlobalState().sessionPendingActions\n}\n\nfunction sessionApprovals(): Map<string, EveApprovalPending[]> {\n return getEveGlobalState().sessionApprovals\n}\n\nfunction sessionRollups(): Map<string, SessionRollup> {\n return getEveGlobalState().sessionRollups\n}\n\nfunction touchSession(sessionId: string): void {\n const rollups = sessionRollups()\n const rollup = rollups.get(sessionId) ?? { turnCount: 0, lastAccess: 0 }\n rollup.lastAccess = Date.now()\n rollups.set(sessionId, rollup)\n evictStaleSessions()\n}\n\nfunction clearSessionState(sessionId: string): void {\n sessionSnapshots().delete(sessionId)\n sessionRollups().delete(sessionId)\n sessionPendingActions().delete(sessionId)\n sessionApprovals().delete(sessionId)\n}\n\nfunction evictStaleSessions(): void {\n const { maxSessions } = getEveGlobalState()\n const rollups = sessionRollups()\n if (rollups.size <= maxSessions) return\n\n const oldest = [...rollups.entries()]\n .sort((a, b) => a[1].lastAccess - b[1].lastAccess)\n .slice(0, rollups.size - maxSessions)\n\n for (const [sessionId] of oldest) {\n if (activeTurnBySession().has(sessionId)) continue\n clearSessionState(sessionId)\n }\n}\n\nfunction pruneEmptySessionMaps(sessionId: string): void {\n const pending = sessionPendingActions().get(sessionId)\n if (pending?.size === 0) sessionPendingActions().delete(sessionId)\n\n const approvals = sessionApprovals().get(sessionId)\n if (approvals?.length === 0) sessionApprovals().delete(sessionId)\n}\n\nfunction bumpSessionTurnCount(sessionId: string): number {\n touchSession(sessionId)\n const rollup = sessionRollups().get(sessionId)!\n rollup.turnCount += 1\n return rollup.turnCount\n}\n\n/** Turn-level label — only set when the turn ends in a non-routine state. */\nfunction derivePhase(\n ctx: Record<string, unknown>,\n accumulator: TurnAccumulator,\n httpStatus: number,\n): string | undefined {\n const approval = ctx.approval as { status?: string } | undefined\n if (approval?.status === 'rejected') return 'rejected'\n if (approval?.status === 'pending' || accumulator.pausedForInput) return 'awaiting-approval'\n if (httpStatus >= 400) return 'failed'\n return undefined\n}\n\nfunction getSessionPendingActions(sessionId: string): Map<string, PendingAction> {\n let map = sessionPendingActions().get(sessionId)\n if (!map) {\n map = new Map()\n sessionPendingActions().set(sessionId, map)\n }\n return map\n}\n\nfunction trackPendingAction(\n sessionId: string,\n turnId: string,\n action: { callId: string, toolName: string, startedAt?: number },\n): void {\n touchSession(sessionId)\n getSessionPendingActions(sessionId).set(action.callId, {\n toolName: action.toolName,\n startedAt: action.startedAt ?? Date.now(),\n turnId,\n })\n}\n\nfunction resolveToolDurationMs(\n state: TurnState,\n callId: string | undefined,\n): number {\n const pending = callId ? getSessionPendingActions(state.sessionId).get(callId) : undefined\n if (pending) {\n if (pending.turnId !== state.turnId && state.accumulator.stepStartedAt !== undefined) {\n return Math.max(0, Date.now() - state.accumulator.stepStartedAt)\n }\n return Math.max(0, Date.now() - pending.startedAt)\n }\n if (state.accumulator.stepStartedAt !== undefined) {\n return Math.max(0, Date.now() - state.accumulator.stepStartedAt)\n }\n return 0\n}\n\nfunction consumeSessionApproval(\n sessionId: string,\n toolName: string,\n callId?: string,\n): EveApprovalPending | undefined {\n const list = sessionApprovals().get(sessionId)\n if (!list?.length) return undefined\n const index = list.findIndex(approval =>\n callId ? approval.callId === callId : approval.toolName === toolName,\n )\n if (index === -1) return undefined\n const [approval] = list.splice(index, 1)\n if (list.length === 0) sessionApprovals().delete(sessionId)\n return approval\n}\n\nfunction storeSessionApprovals(sessionId: string, pending: EveApprovalPending[]): void {\n touchSession(sessionId)\n const existing = sessionApprovals().get(sessionId) ?? []\n sessionApprovals().set(sessionId, [...existing, ...pending])\n}\n\nfunction isEveInitialized(): boolean {\n return getEveGlobalState().initialized\n}\n\nfunction setEveInitialized(value: boolean): void {\n getEveGlobalState().initialized = value\n}\n\nfunction applySessionContext(sessionId: string, logger: AuditableLogger): void {\n touchSession(sessionId)\n const snapshot = sessionSnapshots().get(sessionId)\n if (snapshot && Object.keys(snapshot).length > 0) {\n logger.set({ ...snapshot })\n }\n}\n\nfunction persistSessionContext(sessionId: string, logger: AuditableLogger): void {\n const ctx = logger.getContext() as Record<string, unknown>\n const snapshot = { ...(sessionSnapshots().get(sessionId) ?? {}) }\n for (const [key, value] of Object.entries(ctx)) {\n if (!TURN_ONLY_KEYS.has(key) && value !== undefined) {\n snapshot[key] = value\n }\n }\n sessionSnapshots().set(sessionId, snapshot)\n}\n\nfunction flushEveMetadata(state: TurnState): void {\n if (state.accumulator.subagents.length === 0) return\n state.logger.set({\n eve: {\n subagents: state.accumulator.subagents.map(s => ({ ...s })),\n },\n })\n}\n\nfunction getOrCreateTurnState(\n sessionId: string,\n turnId: string,\n options: EvlogEveOptions,\n ctx: HookContext,\n): TurnState | null {\n const key = turnKey(sessionId, turnId)\n const existing = turnStates().get(key)\n if (existing) return existing\n\n touchSession(sessionId)\n\n const path = `/sessions/${sessionId}/turns/${turnId}`\n const middlewareOptions: MiddlewareLoggerOptions = {\n method: 'EVE',\n path,\n requestId: turnId,\n drain: options.drain,\n enrich: options.enrich,\n keep: options.keep,\n redact: options.redact,\n plugins: options.plugins,\n include: options.include,\n exclude: options.exclude,\n routes: options.routes,\n }\n\n const { logger, finish, skipped } = createMiddlewareLogger(middlewareOptions)\n if (skipped) return null\n\n const state: TurnState = {\n logger,\n finish,\n middlewareOptions,\n accumulator: freshAccumulator(options),\n sessionId,\n turnId,\n }\n\n applySessionContext(sessionId, logger)\n\n logger.set({\n eve: {\n sessionId,\n turnId,\n },\n agent: {\n name: ctx.agent.name,\n ...(ctx.agent.nodeId ? { nodeId: ctx.agent.nodeId } : {}),\n },\n channel: {\n kind: ctx.channel.kind ?? 'unknown',\n ...(ctx.channel.continuationToken ? { continuing: true } : {}),\n },\n })\n\n turnStates().set(key, state)\n activeTurnBySession().set(sessionId, turnId)\n return state\n}\n\nfunction flushAi(state: TurnState): void {\n state.logger.set({ ai: buildAiField(state.accumulator) })\n}\n\nasync function finishTurn(\n sessionId: string,\n turnId: string,\n opts: { status?: number; error?: Error },\n): Promise<void> {\n const key = turnKey(sessionId, turnId)\n const state = turnStates().get(key)\n if (!state) return\n\n try {\n flushEveMetadata(state)\n flushAi(state)\n const httpStatus = opts.status ?? (opts.error ? 500 : 200)\n const ctx = state.logger.getContext() as Record<string, unknown>\n const phase = derivePhase(ctx, state.accumulator, httpStatus)\n const sessionTurns = bumpSessionTurnCount(sessionId)\n state.logger.set({\n eve: {\n ...(phase ? { phase } : {}),\n sessionTurns,\n },\n })\n persistSessionContext(sessionId, state.logger)\n await state.finish(opts)\n } finally {\n unbindTurnLogger(state.logger)\n turnStates().delete(key)\n if (activeTurnBySession().get(sessionId) === turnId) {\n activeTurnBySession().delete(sessionId)\n }\n pruneEmptySessionMaps(sessionId)\n }\n}\n\nfunction runSafe(fn: () => void | Promise<void>): void {\n void (async () => {\n try {\n await fn()\n } catch (err) {\n console.error('[evlog] eve hook handler failed:', err)\n }\n })()\n}\n\nfunction getTurnState(sessionId: string, turnId: string): TurnState | undefined {\n return turnStates().get(turnKey(sessionId, turnId))\n}\n\n/**\n * Create an eve stream hook that emits one evlog wide event per agent turn.\n *\n * Export the result as the default export of `agent/hooks/evlog.ts`. eve\n * auto-discovers hook files; evlog maps turn lifecycle events to a wide event\n * with AI usage, tool executions, and your drain/enrich/keep pipeline.\n *\n * Complements eve Agent Runs and OpenTelemetry — it does not replace them.\n *\n * @example\n * ```ts\n * // agent/hooks/evlog.ts\n * import { defineEvlogHook } from 'evlog/eve'\n * import { createAxiomDrain } from 'evlog/axiom'\n *\n * export default defineEvlogHook({\n * drain: createAxiomDrain(),\n * enrich: (ctx) => {\n * ctx.event.runtime = process.env.VERCEL_REGION\n * },\n * })\n * ```\n */\nexport function defineEvlogHook(options: EvlogEveOptions = {}): HookDefinition {\n const redactMessage = options.redactMessage ?? true\n\n return defineHook({\n events: {\n 'turn.started'(event, ctx) {\n try {\n ensureInit(options)\n const state = getOrCreateTurnState(ctx.session.id, event.data.turnId, options, ctx)\n state?.logger.set({\n eve: { turnSequence: event.data.sequence },\n })\n if (state) bindTurnLogger(state.logger)\n } catch (err) {\n console.error('[evlog] eve hook handler failed:', err)\n }\n },\n\n 'message.received'(event, ctx) {\n runSafe(() => {\n if (redactMessage) return\n const state = getTurnState(ctx.session.id, event.data.turnId)\n if (!state) return\n state.logger.set({\n message: { received: truncateMessage(event.data.message) },\n })\n })\n },\n\n 'step.started'(event, ctx) {\n runSafe(() => {\n const state = getTurnState(ctx.session.id, event.data.turnId)\n if (!state) return\n state.accumulator.stepStartedAt = Date.now()\n })\n },\n\n 'step.completed'(event, ctx) {\n runSafe(() => {\n const state = getTurnState(ctx.session.id, event.data.turnId)\n if (!state) return\n const acc = state.accumulator\n acc.steps += 1\n acc.calls += 1\n acc.finishReason = event.data.finishReason\n const { usage } = event.data\n if (usage) {\n acc.inputTokens += usage.inputTokens ?? 0\n acc.outputTokens += usage.outputTokens ?? 0\n acc.cacheReadTokens += usage.cacheReadTokens ?? 0\n acc.cacheWriteTokens += usage.cacheWriteTokens ?? 0\n }\n })\n },\n\n 'actions.requested'(event, ctx) {\n runSafe(() => {\n const state = getTurnState(ctx.session.id, event.data.turnId)\n if (!state) return\n bindTurnLogger(state.logger)\n const startedAt = Date.now()\n for (const action of event.data.actions) {\n if (action.kind === 'tool-call') {\n trackPendingAction(ctx.session.id, event.data.turnId, {\n callId: action.callId,\n toolName: action.toolName,\n startedAt,\n })\n }\n }\n })\n },\n\n 'input.requested'(event, ctx) {\n runSafe(() => {\n const state = getTurnState(ctx.session.id, event.data.turnId)\n if (!state) return\n state.accumulator.pausedForInput = true\n const pending = event.data.requests.map(req => ({\n toolName: req.action.toolName,\n callId: req.action.callId,\n }))\n storeSessionApprovals(ctx.session.id, pending)\n const [first] = pending\n if (first) {\n state.logger.set({\n approval: { status: 'pending', tool: first.toolName },\n })\n }\n })\n },\n\n 'action.result'(event, ctx) {\n runSafe(() => {\n const state = getTurnState(ctx.session.id, event.data.turnId)\n if (!state) return\n const callId = extractCallId(event.data.result)\n const sessionPending = getSessionPendingActions(state.sessionId)\n const turnPending = callId ? sessionPending.get(callId) : undefined\n\n const { status } = event.data\n const rejected = status === 'rejected'\n const success = status === 'completed'\n const toolName = turnPending?.toolName ?? extractToolName(event.data.result)\n const durationMs = resolveToolDurationMs(state, callId)\n\n if (callId) sessionPending.delete(callId)\n\n const execution: AIToolExecution = {\n name: toolName,\n durationMs,\n success,\n }\n if (rejected) {\n execution.error = 'rejected'\n state.accumulator.pausedForInput = false\n consumeSessionApproval(state.sessionId, toolName, callId)\n state.logger.set({\n approval: { status: 'rejected', tool: toolName },\n })\n } else if (success) {\n const approval = consumeSessionApproval(state.sessionId, toolName, callId)\n if (approval) {\n state.accumulator.pausedForInput = false\n state.logger.set({\n approval: { status: 'approved', tool: approval.toolName },\n })\n }\n } else if (event.data.error) {\n execution.error = event.data.error.message\n }\n state.accumulator.toolExecutions.push(execution)\n })\n },\n\n 'subagent.called'(event, ctx) {\n runSafe(() => {\n const state = getTurnState(ctx.session.id, event.data.turnId)\n if (!state) return\n state.accumulator.subagents.push({\n callId: event.data.callId,\n name: event.data.name,\n toolName: event.data.toolName,\n childSessionId: event.data.childSessionId,\n status: 'called',\n })\n })\n },\n\n 'subagent.completed'(event, ctx) {\n runSafe(() => {\n const sessionId = ctx.session.id\n const turnId = activeTurnBySession().get(sessionId)\n if (!turnId) return\n const state = getTurnState(sessionId, turnId)\n if (!state) return\n const existing = state.accumulator.subagents.find(s => s.callId === event.data.callId)\n if (existing) {\n existing.status = 'completed'\n existing.output = event.data.output\n } else {\n state.accumulator.subagents.push({\n callId: event.data.callId,\n name: event.data.subagentName,\n status: 'completed',\n output: event.data.output,\n })\n }\n })\n },\n\n async 'turn.completed'(event, ctx) {\n try {\n await finishTurn(ctx.session.id, event.data.turnId, { status: 200 })\n } catch (err) {\n console.error('[evlog] eve hook handler failed:', err)\n }\n },\n\n async 'turn.failed'(event, ctx) {\n try {\n const state = getTurnState(ctx.session.id, event.data.turnId)\n state?.logger.set({\n eve: {\n failure: {\n code: event.data.code,\n message: event.data.message,\n ...(event.data.details ? { details: event.data.details } : {}),\n },\n },\n })\n const error = new Error(event.data.message)\n error.name = event.data.code\n await finishTurn(ctx.session.id, event.data.turnId, { error, status: 500 })\n } catch (err) {\n console.error('[evlog] eve hook handler failed:', err)\n }\n },\n },\n })\n}\n\n/** @internal Simulates eve tool execution where AsyncLocalStorage did not propagate. */\nexport function detachActiveTurnLoggerForTests(): void {\n const logger = turnLoggerStorage.getStore()\n if (logger) unbindTurnLogger(logger)\n}\n\n/** @internal Resets module state between unit tests. Clears turn maps, session context, and the Eve init flag. */\nexport function resetEvlogEveForTests(): void {\n clearAsyncLocalStorage(turnLoggerStorage)\n turnStates().clear()\n activeTurnBySession().clear()\n sessionSnapshots().clear()\n sessionPendingActions().clear()\n sessionApprovals().clear()\n sessionRollups().clear()\n setEveInitialized(false)\n delete (globalThis as typeof globalThis & { [EVE_GLOBAL_STATE]?: EveGlobalState })[EVE_GLOBAL_STATE]\n}\n\nexport type { ModelCost } from '../ai/index'\n"],"mappings":"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"}
|