risicare 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.
- package/README.md +99 -0
- package/dist/index.cjs +1268 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +564 -0
- package/dist/index.d.ts +564 -0
- package/dist/index.js +1193 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/anthropic/index.cjs +237 -0
- package/dist/providers/anthropic/index.cjs.map +1 -0
- package/dist/providers/anthropic/index.d.cts +23 -0
- package/dist/providers/anthropic/index.d.ts +23 -0
- package/dist/providers/anthropic/index.js +210 -0
- package/dist/providers/anthropic/index.js.map +1 -0
- package/dist/providers/openai/index.cjs +296 -0
- package/dist/providers/openai/index.cjs.map +1 -0
- package/dist/providers/openai/index.d.cts +27 -0
- package/dist/providers/openai/index.d.ts +27 -0
- package/dist/providers/openai/index.js +269 -0
- package/dist/providers/openai/index.js.map +1 -0
- package/dist/providers/vercel-ai/index.cjs +245 -0
- package/dist/providers/vercel-ai/index.cjs.map +1 -0
- package/dist/providers/vercel-ai/index.d.cts +33 -0
- package/dist/providers/vercel-ai/index.d.ts +33 -0
- package/dist/providers/vercel-ai/index.js +218 -0
- package/dist/providers/vercel-ai/index.js.map +1 -0
- package/package.json +101 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,1268 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var src_exports = {};
|
|
32
|
+
__export(src_exports, {
|
|
33
|
+
AgentRole: () => AgentRole,
|
|
34
|
+
MessageType: () => MessageType,
|
|
35
|
+
SemanticPhase: () => SemanticPhase,
|
|
36
|
+
SpanKind: () => SpanKind,
|
|
37
|
+
SpanStatus: () => SpanStatus,
|
|
38
|
+
agent: () => agent,
|
|
39
|
+
disable: () => disable,
|
|
40
|
+
enable: () => enable,
|
|
41
|
+
extractTraceContext: () => extractTraceContext,
|
|
42
|
+
flush: () => flush,
|
|
43
|
+
getCurrentAgent: () => getCurrentAgent,
|
|
44
|
+
getCurrentAgentId: () => getCurrentAgentId,
|
|
45
|
+
getCurrentContext: () => getCurrentContext,
|
|
46
|
+
getCurrentPhase: () => getCurrentPhase,
|
|
47
|
+
getCurrentSession: () => getCurrentSession,
|
|
48
|
+
getCurrentSessionId: () => getCurrentSessionId,
|
|
49
|
+
getCurrentSpan: () => getCurrentSpan,
|
|
50
|
+
getCurrentSpanId: () => getCurrentSpanId,
|
|
51
|
+
getCurrentTraceId: () => getCurrentTraceId,
|
|
52
|
+
getSpanById: () => getSpanById,
|
|
53
|
+
getTraceContext: () => getTraceContext,
|
|
54
|
+
getTracer: () => getTracer,
|
|
55
|
+
init: () => init,
|
|
56
|
+
injectTraceContext: () => injectTraceContext,
|
|
57
|
+
isEnabled: () => isEnabled,
|
|
58
|
+
registerSpan: () => registerSpan,
|
|
59
|
+
session: () => session,
|
|
60
|
+
shutdown: () => shutdown,
|
|
61
|
+
traceAct: () => traceAct,
|
|
62
|
+
traceCoordinate: () => traceCoordinate,
|
|
63
|
+
traceDecide: () => traceDecide,
|
|
64
|
+
traceDelegate: () => traceDelegate,
|
|
65
|
+
traceMessage: () => traceMessage,
|
|
66
|
+
traceObserve: () => traceObserve,
|
|
67
|
+
traceThink: () => traceThink,
|
|
68
|
+
unregisterSpan: () => unregisterSpan,
|
|
69
|
+
withAgent: () => withAgent,
|
|
70
|
+
withPhase: () => withPhase,
|
|
71
|
+
withSession: () => withSession
|
|
72
|
+
});
|
|
73
|
+
module.exports = __toCommonJS(src_exports);
|
|
74
|
+
|
|
75
|
+
// src/config.ts
|
|
76
|
+
var DEFAULT_ENDPOINT = "https://app.risicare.ai";
|
|
77
|
+
function resolveConfig(config) {
|
|
78
|
+
const env = process.env;
|
|
79
|
+
const apiKey = config?.apiKey ?? env.RISICARE_API_KEY;
|
|
80
|
+
const endpoint = config?.endpoint ?? env.RISICARE_ENDPOINT ?? DEFAULT_ENDPOINT;
|
|
81
|
+
const projectId = config?.projectId ?? env.RISICARE_PROJECT_ID;
|
|
82
|
+
const environment = config?.environment ?? env.RISICARE_ENVIRONMENT ?? "development";
|
|
83
|
+
const serviceName = config?.serviceName ?? env.RISICARE_SERVICE_NAME;
|
|
84
|
+
const serviceVersion = config?.serviceVersion ?? env.RISICARE_SERVICE_VERSION;
|
|
85
|
+
const traceContent = config?.traceContent ?? parseBool(env.RISICARE_TRACE_CONTENT, true);
|
|
86
|
+
const sampleRate = config?.sampleRate ?? parseFloat(env.RISICARE_SAMPLE_RATE ?? "1.0");
|
|
87
|
+
const debug2 = config?.debug ?? parseBool(env.RISICARE_DEBUG, false);
|
|
88
|
+
const batchSize = config?.batchSize ?? 100;
|
|
89
|
+
const batchTimeoutMs = config?.batchTimeoutMs ?? 1e3;
|
|
90
|
+
const maxQueueSize = config?.maxQueueSize ?? 1e4;
|
|
91
|
+
let enabled;
|
|
92
|
+
if (config?.enabled !== void 0) {
|
|
93
|
+
enabled = config.enabled;
|
|
94
|
+
} else if (env.RISICARE_TRACING !== void 0) {
|
|
95
|
+
enabled = parseBool(env.RISICARE_TRACING, false);
|
|
96
|
+
} else {
|
|
97
|
+
enabled = !!apiKey;
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
apiKey: apiKey ?? "",
|
|
101
|
+
endpoint,
|
|
102
|
+
projectId: projectId ?? "",
|
|
103
|
+
environment,
|
|
104
|
+
serviceName: serviceName ?? "",
|
|
105
|
+
serviceVersion: serviceVersion ?? "",
|
|
106
|
+
enabled,
|
|
107
|
+
traceContent,
|
|
108
|
+
sampleRate: Math.max(0, Math.min(1, sampleRate)),
|
|
109
|
+
batchSize,
|
|
110
|
+
batchTimeoutMs,
|
|
111
|
+
maxQueueSize,
|
|
112
|
+
debug: debug2,
|
|
113
|
+
metadata: config?.metadata ?? {}
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
function parseBool(value, defaultValue) {
|
|
117
|
+
if (value === void 0) return defaultValue;
|
|
118
|
+
const lower = value.toLowerCase();
|
|
119
|
+
return lower === "true" || lower === "1" || lower === "yes";
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// src/ids.ts
|
|
123
|
+
var import_node_crypto = require("crypto");
|
|
124
|
+
var HEX_REGEX_32 = /^[0-9a-f]{32}$/;
|
|
125
|
+
var HEX_REGEX_16 = /^[0-9a-f]{16}$/;
|
|
126
|
+
function generateTraceId() {
|
|
127
|
+
return (0, import_node_crypto.randomBytes)(16).toString("hex");
|
|
128
|
+
}
|
|
129
|
+
function generateSpanId() {
|
|
130
|
+
return (0, import_node_crypto.randomBytes)(8).toString("hex");
|
|
131
|
+
}
|
|
132
|
+
function generateAgentId(prefix) {
|
|
133
|
+
const suffix = (0, import_node_crypto.randomBytes)(6).toString("hex");
|
|
134
|
+
return prefix ? `${prefix}-${suffix}` : suffix;
|
|
135
|
+
}
|
|
136
|
+
function validateTraceId(id) {
|
|
137
|
+
return HEX_REGEX_32.test(id);
|
|
138
|
+
}
|
|
139
|
+
function validateSpanId(id) {
|
|
140
|
+
return HEX_REGEX_16.test(id);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// src/types.ts
|
|
144
|
+
var SpanKind = /* @__PURE__ */ ((SpanKind2) => {
|
|
145
|
+
SpanKind2["INTERNAL"] = "internal";
|
|
146
|
+
SpanKind2["CLIENT"] = "client";
|
|
147
|
+
SpanKind2["SERVER"] = "server";
|
|
148
|
+
SpanKind2["PRODUCER"] = "producer";
|
|
149
|
+
SpanKind2["CONSUMER"] = "consumer";
|
|
150
|
+
SpanKind2["AGENT"] = "agent";
|
|
151
|
+
SpanKind2["LLM_CALL"] = "llm_call";
|
|
152
|
+
SpanKind2["TOOL_CALL"] = "tool_call";
|
|
153
|
+
SpanKind2["RETRIEVAL"] = "retrieval";
|
|
154
|
+
SpanKind2["DECISION"] = "decision";
|
|
155
|
+
SpanKind2["MESSAGE"] = "message";
|
|
156
|
+
SpanKind2["DELEGATION"] = "delegation";
|
|
157
|
+
SpanKind2["COORDINATION"] = "coordination";
|
|
158
|
+
SpanKind2["THINK"] = "think";
|
|
159
|
+
SpanKind2["DECIDE"] = "decide";
|
|
160
|
+
SpanKind2["OBSERVE"] = "observe";
|
|
161
|
+
SpanKind2["REFLECT"] = "reflect";
|
|
162
|
+
return SpanKind2;
|
|
163
|
+
})(SpanKind || {});
|
|
164
|
+
var SpanStatus = /* @__PURE__ */ ((SpanStatus2) => {
|
|
165
|
+
SpanStatus2["UNSET"] = "unset";
|
|
166
|
+
SpanStatus2["OK"] = "ok";
|
|
167
|
+
SpanStatus2["ERROR"] = "error";
|
|
168
|
+
return SpanStatus2;
|
|
169
|
+
})(SpanStatus || {});
|
|
170
|
+
var SemanticPhase = /* @__PURE__ */ ((SemanticPhase2) => {
|
|
171
|
+
SemanticPhase2["THINK"] = "think";
|
|
172
|
+
SemanticPhase2["DECIDE"] = "decide";
|
|
173
|
+
SemanticPhase2["ACT"] = "act";
|
|
174
|
+
SemanticPhase2["OBSERVE"] = "observe";
|
|
175
|
+
return SemanticPhase2;
|
|
176
|
+
})(SemanticPhase || {});
|
|
177
|
+
var AgentRole = /* @__PURE__ */ ((AgentRole2) => {
|
|
178
|
+
AgentRole2["ORCHESTRATOR"] = "orchestrator";
|
|
179
|
+
AgentRole2["WORKER"] = "worker";
|
|
180
|
+
AgentRole2["REVIEWER"] = "reviewer";
|
|
181
|
+
AgentRole2["PLANNER"] = "planner";
|
|
182
|
+
AgentRole2["EXECUTOR"] = "executor";
|
|
183
|
+
AgentRole2["CRITIC"] = "critic";
|
|
184
|
+
AgentRole2["CUSTOM"] = "custom";
|
|
185
|
+
return AgentRole2;
|
|
186
|
+
})(AgentRole || {});
|
|
187
|
+
var MessageType = /* @__PURE__ */ ((MessageType2) => {
|
|
188
|
+
MessageType2["REQUEST"] = "request";
|
|
189
|
+
MessageType2["RESPONSE"] = "response";
|
|
190
|
+
MessageType2["DELEGATE"] = "delegate";
|
|
191
|
+
MessageType2["COORDINATE"] = "coordinate";
|
|
192
|
+
MessageType2["BROADCAST"] = "broadcast";
|
|
193
|
+
return MessageType2;
|
|
194
|
+
})(MessageType || {});
|
|
195
|
+
|
|
196
|
+
// src/utils/clock.ts
|
|
197
|
+
function nowISO() {
|
|
198
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
199
|
+
}
|
|
200
|
+
function hrtimeMs() {
|
|
201
|
+
return Number(process.hrtime.bigint()) / 1e6;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// src/span.ts
|
|
205
|
+
var Span = class {
|
|
206
|
+
traceId;
|
|
207
|
+
spanId;
|
|
208
|
+
parentSpanId;
|
|
209
|
+
name;
|
|
210
|
+
kind;
|
|
211
|
+
startTime;
|
|
212
|
+
startHrtime;
|
|
213
|
+
endTime;
|
|
214
|
+
status;
|
|
215
|
+
statusMessage;
|
|
216
|
+
attributes;
|
|
217
|
+
events;
|
|
218
|
+
links;
|
|
219
|
+
// Agent/session fields
|
|
220
|
+
sessionId;
|
|
221
|
+
agentId;
|
|
222
|
+
agentName;
|
|
223
|
+
agentType;
|
|
224
|
+
semanticPhase;
|
|
225
|
+
// LLM-specific fields
|
|
226
|
+
llmProvider;
|
|
227
|
+
llmModel;
|
|
228
|
+
llmPromptTokens;
|
|
229
|
+
llmCompletionTokens;
|
|
230
|
+
llmTotalTokens;
|
|
231
|
+
llmCostUsd;
|
|
232
|
+
// Tool fields
|
|
233
|
+
toolName;
|
|
234
|
+
toolSuccess;
|
|
235
|
+
_ended = false;
|
|
236
|
+
_endHrtime;
|
|
237
|
+
_onEnd;
|
|
238
|
+
constructor(options, onEnd) {
|
|
239
|
+
this.traceId = options.traceId ?? generateTraceId();
|
|
240
|
+
this.spanId = options.spanId ?? generateSpanId();
|
|
241
|
+
this.parentSpanId = options.parentSpanId;
|
|
242
|
+
this.name = options.name;
|
|
243
|
+
this.kind = options.kind ?? "internal" /* INTERNAL */;
|
|
244
|
+
this.startTime = nowISO();
|
|
245
|
+
this.startHrtime = hrtimeMs();
|
|
246
|
+
this.status = "unset" /* UNSET */;
|
|
247
|
+
this.attributes = options.attributes ? { ...options.attributes } : {};
|
|
248
|
+
this.events = [];
|
|
249
|
+
this.links = options.links ? [...options.links] : [];
|
|
250
|
+
this.sessionId = options.sessionId;
|
|
251
|
+
this.agentId = options.agentId;
|
|
252
|
+
this.agentName = options.agentName;
|
|
253
|
+
this.agentType = options.agentType;
|
|
254
|
+
this.semanticPhase = options.semanticPhase;
|
|
255
|
+
this._onEnd = onEnd;
|
|
256
|
+
}
|
|
257
|
+
get isEnded() {
|
|
258
|
+
return this._ended;
|
|
259
|
+
}
|
|
260
|
+
get durationMs() {
|
|
261
|
+
if (this._ended && this._endHrtime !== void 0) {
|
|
262
|
+
return this._endHrtime - this.startHrtime;
|
|
263
|
+
}
|
|
264
|
+
return hrtimeMs() - this.startHrtime;
|
|
265
|
+
}
|
|
266
|
+
setAttribute(key, value) {
|
|
267
|
+
if (this._ended) return this;
|
|
268
|
+
this.attributes[key] = value;
|
|
269
|
+
return this;
|
|
270
|
+
}
|
|
271
|
+
setAttributes(attrs) {
|
|
272
|
+
if (this._ended) return this;
|
|
273
|
+
Object.assign(this.attributes, attrs);
|
|
274
|
+
return this;
|
|
275
|
+
}
|
|
276
|
+
setStatus(status, message) {
|
|
277
|
+
if (this._ended) return this;
|
|
278
|
+
this.status = status;
|
|
279
|
+
if (message !== void 0) {
|
|
280
|
+
this.statusMessage = message;
|
|
281
|
+
}
|
|
282
|
+
return this;
|
|
283
|
+
}
|
|
284
|
+
addEvent(name, attributes) {
|
|
285
|
+
if (this._ended) return this;
|
|
286
|
+
this.events.push({
|
|
287
|
+
name,
|
|
288
|
+
timestamp: nowISO(),
|
|
289
|
+
attributes
|
|
290
|
+
});
|
|
291
|
+
return this;
|
|
292
|
+
}
|
|
293
|
+
addLink(traceId, spanId, attributes) {
|
|
294
|
+
if (this._ended) return this;
|
|
295
|
+
this.links.push({ traceId, spanId, attributes });
|
|
296
|
+
return this;
|
|
297
|
+
}
|
|
298
|
+
recordException(error) {
|
|
299
|
+
if (this._ended) return this;
|
|
300
|
+
const message = typeof error === "string" ? error : error.message;
|
|
301
|
+
const stack = typeof error === "string" ? void 0 : error.stack;
|
|
302
|
+
this.setStatus("error" /* ERROR */, message);
|
|
303
|
+
this.addEvent("exception", {
|
|
304
|
+
"exception.type": typeof error === "string" ? "Error" : error.constructor.name,
|
|
305
|
+
"exception.message": message,
|
|
306
|
+
...stack ? { "exception.stacktrace": stack } : {}
|
|
307
|
+
});
|
|
308
|
+
return this;
|
|
309
|
+
}
|
|
310
|
+
setLlmFields(fields) {
|
|
311
|
+
if (this._ended) return this;
|
|
312
|
+
if (fields.provider !== void 0) this.llmProvider = fields.provider;
|
|
313
|
+
if (fields.model !== void 0) this.llmModel = fields.model;
|
|
314
|
+
if (fields.promptTokens !== void 0) this.llmPromptTokens = fields.promptTokens;
|
|
315
|
+
if (fields.completionTokens !== void 0) this.llmCompletionTokens = fields.completionTokens;
|
|
316
|
+
if (fields.totalTokens !== void 0) this.llmTotalTokens = fields.totalTokens;
|
|
317
|
+
if (fields.costUsd !== void 0) this.llmCostUsd = fields.costUsd;
|
|
318
|
+
return this;
|
|
319
|
+
}
|
|
320
|
+
setToolFields(fields) {
|
|
321
|
+
if (this._ended) return this;
|
|
322
|
+
if (fields.name !== void 0) this.toolName = fields.name;
|
|
323
|
+
if (fields.success !== void 0) this.toolSuccess = fields.success;
|
|
324
|
+
return this;
|
|
325
|
+
}
|
|
326
|
+
end() {
|
|
327
|
+
if (this._ended) return;
|
|
328
|
+
this._ended = true;
|
|
329
|
+
this._endHrtime = hrtimeMs();
|
|
330
|
+
this.endTime = nowISO();
|
|
331
|
+
if (this.status === "unset" /* UNSET */) {
|
|
332
|
+
this.status = "ok" /* OK */;
|
|
333
|
+
}
|
|
334
|
+
this._onEnd?.(this);
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Serialize to the wire format expected by the Rust gateway.
|
|
338
|
+
*/
|
|
339
|
+
toPayload() {
|
|
340
|
+
const payload = {
|
|
341
|
+
traceId: this.traceId,
|
|
342
|
+
spanId: this.spanId,
|
|
343
|
+
name: this.name,
|
|
344
|
+
kind: this.kind,
|
|
345
|
+
startTime: this.startTime,
|
|
346
|
+
status: this.status,
|
|
347
|
+
attributes: this.attributes,
|
|
348
|
+
events: this.events,
|
|
349
|
+
links: this.links
|
|
350
|
+
};
|
|
351
|
+
if (this.parentSpanId !== void 0) payload.parentSpanId = this.parentSpanId;
|
|
352
|
+
if (this.endTime !== void 0) payload.endTime = this.endTime;
|
|
353
|
+
if (this._ended) payload.durationMs = this.durationMs;
|
|
354
|
+
if (this.statusMessage !== void 0) payload.statusMessage = this.statusMessage;
|
|
355
|
+
if (this.sessionId !== void 0) payload.sessionId = this.sessionId;
|
|
356
|
+
if (this.agentId !== void 0) payload.agentId = this.agentId;
|
|
357
|
+
if (this.agentName !== void 0) payload.agentName = this.agentName;
|
|
358
|
+
if (this.agentType !== void 0) payload.agentType = this.agentType;
|
|
359
|
+
if (this.semanticPhase !== void 0) payload.semanticPhase = this.semanticPhase;
|
|
360
|
+
if (this.llmProvider !== void 0) payload.llmProvider = this.llmProvider;
|
|
361
|
+
if (this.llmModel !== void 0) payload.llmModel = this.llmModel;
|
|
362
|
+
if (this.llmPromptTokens !== void 0) payload.llmPromptTokens = this.llmPromptTokens;
|
|
363
|
+
if (this.llmCompletionTokens !== void 0) payload.llmCompletionTokens = this.llmCompletionTokens;
|
|
364
|
+
if (this.llmTotalTokens !== void 0) payload.llmTotalTokens = this.llmTotalTokens;
|
|
365
|
+
if (this.llmCostUsd !== void 0) payload.llmCostUsd = this.llmCostUsd;
|
|
366
|
+
if (this.toolName !== void 0) payload.toolName = this.toolName;
|
|
367
|
+
if (this.toolSuccess !== void 0) payload.toolSuccess = this.toolSuccess;
|
|
368
|
+
return payload;
|
|
369
|
+
}
|
|
370
|
+
};
|
|
371
|
+
|
|
372
|
+
// src/noop.ts
|
|
373
|
+
var NOOP_SPAN = Object.freeze({
|
|
374
|
+
traceId: "00000000000000000000000000000000",
|
|
375
|
+
spanId: "0000000000000000",
|
|
376
|
+
parentSpanId: void 0,
|
|
377
|
+
name: "noop",
|
|
378
|
+
kind: "internal" /* INTERNAL */,
|
|
379
|
+
startTime: "",
|
|
380
|
+
startHrtime: 0,
|
|
381
|
+
endTime: void 0,
|
|
382
|
+
status: "unset" /* UNSET */,
|
|
383
|
+
statusMessage: void 0,
|
|
384
|
+
attributes: Object.freeze({}),
|
|
385
|
+
events: Object.freeze([]),
|
|
386
|
+
links: Object.freeze([]),
|
|
387
|
+
sessionId: void 0,
|
|
388
|
+
agentId: void 0,
|
|
389
|
+
agentName: void 0,
|
|
390
|
+
semanticPhase: void 0,
|
|
391
|
+
llmProvider: void 0,
|
|
392
|
+
llmModel: void 0,
|
|
393
|
+
llmPromptTokens: void 0,
|
|
394
|
+
llmCompletionTokens: void 0,
|
|
395
|
+
llmTotalTokens: void 0,
|
|
396
|
+
llmCostUsd: void 0,
|
|
397
|
+
toolName: void 0,
|
|
398
|
+
toolSuccess: void 0,
|
|
399
|
+
isEnded: true,
|
|
400
|
+
durationMs: 0,
|
|
401
|
+
setAttribute() {
|
|
402
|
+
return this;
|
|
403
|
+
},
|
|
404
|
+
setAttributes() {
|
|
405
|
+
return this;
|
|
406
|
+
},
|
|
407
|
+
setStatus() {
|
|
408
|
+
return this;
|
|
409
|
+
},
|
|
410
|
+
addEvent() {
|
|
411
|
+
return this;
|
|
412
|
+
},
|
|
413
|
+
addLink() {
|
|
414
|
+
return this;
|
|
415
|
+
},
|
|
416
|
+
recordException() {
|
|
417
|
+
return this;
|
|
418
|
+
},
|
|
419
|
+
setLlmFields() {
|
|
420
|
+
return this;
|
|
421
|
+
},
|
|
422
|
+
setToolFields() {
|
|
423
|
+
return this;
|
|
424
|
+
},
|
|
425
|
+
end() {
|
|
426
|
+
},
|
|
427
|
+
toPayload() {
|
|
428
|
+
return {
|
|
429
|
+
traceId: this.traceId,
|
|
430
|
+
spanId: this.spanId,
|
|
431
|
+
name: this.name,
|
|
432
|
+
kind: this.kind,
|
|
433
|
+
startTime: this.startTime,
|
|
434
|
+
status: this.status,
|
|
435
|
+
attributes: {},
|
|
436
|
+
events: [],
|
|
437
|
+
links: []
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
// src/utils/sampling.ts
|
|
443
|
+
function shouldSample(traceId, sampleRate) {
|
|
444
|
+
if (sampleRate >= 1) return true;
|
|
445
|
+
if (sampleRate <= 0) return false;
|
|
446
|
+
const hash = parseInt(traceId.substring(0, 8), 16);
|
|
447
|
+
return hash / 4294967295 < sampleRate;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// src/context/storage.ts
|
|
451
|
+
var import_node_async_hooks = require("async_hooks");
|
|
452
|
+
var contextStorage = new import_node_async_hooks.AsyncLocalStorage();
|
|
453
|
+
function getContext() {
|
|
454
|
+
return contextStorage.getStore() ?? {};
|
|
455
|
+
}
|
|
456
|
+
function runWithContext(overrides, fn) {
|
|
457
|
+
const parent = getContext();
|
|
458
|
+
const merged = { ...parent, ...overrides };
|
|
459
|
+
return contextStorage.run(merged, fn);
|
|
460
|
+
}
|
|
461
|
+
function getCurrentSession() {
|
|
462
|
+
return getContext().session;
|
|
463
|
+
}
|
|
464
|
+
function getCurrentAgent() {
|
|
465
|
+
return getContext().agent;
|
|
466
|
+
}
|
|
467
|
+
function getCurrentSpan() {
|
|
468
|
+
return getContext().span;
|
|
469
|
+
}
|
|
470
|
+
function getCurrentPhase() {
|
|
471
|
+
return getContext().phase;
|
|
472
|
+
}
|
|
473
|
+
function getCurrentSessionId() {
|
|
474
|
+
return getContext().session?.sessionId;
|
|
475
|
+
}
|
|
476
|
+
function getCurrentAgentId() {
|
|
477
|
+
return getContext().agent?.agentId;
|
|
478
|
+
}
|
|
479
|
+
function getCurrentTraceId() {
|
|
480
|
+
return getContext().span?.traceId;
|
|
481
|
+
}
|
|
482
|
+
function getCurrentSpanId() {
|
|
483
|
+
return getContext().span?.spanId;
|
|
484
|
+
}
|
|
485
|
+
function getCurrentContext() {
|
|
486
|
+
const ctx = getContext();
|
|
487
|
+
return {
|
|
488
|
+
session: ctx.session ? { sessionId: ctx.session.sessionId, userId: ctx.session.userId } : null,
|
|
489
|
+
agent: ctx.agent ? { agentId: ctx.agent.agentId, agentName: ctx.agent.agentName, agentRole: ctx.agent.agentRole } : null,
|
|
490
|
+
span: ctx.span ? { spanId: ctx.span.spanId, traceId: ctx.span.traceId } : null,
|
|
491
|
+
phase: ctx.phase ?? null
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// src/tracer.ts
|
|
496
|
+
var Tracer = class {
|
|
497
|
+
_onSpanEnd;
|
|
498
|
+
_sampleRate;
|
|
499
|
+
_enabled;
|
|
500
|
+
constructor(config) {
|
|
501
|
+
this._onSpanEnd = config.onSpanEnd;
|
|
502
|
+
this._sampleRate = config.sampleRate ?? 1;
|
|
503
|
+
this._enabled = config.enabled ?? true;
|
|
504
|
+
}
|
|
505
|
+
get enabled() {
|
|
506
|
+
return this._enabled;
|
|
507
|
+
}
|
|
508
|
+
set enabled(value) {
|
|
509
|
+
this._enabled = value;
|
|
510
|
+
}
|
|
511
|
+
/**
|
|
512
|
+
* Start a span, run the callback within its context, and auto-end on completion.
|
|
513
|
+
*
|
|
514
|
+
* The span is automatically:
|
|
515
|
+
* - Linked to the current parent span (if any)
|
|
516
|
+
* - Given the current trace ID (or a new one for root spans)
|
|
517
|
+
* - Enriched with session/agent/phase context
|
|
518
|
+
* - Ended when the callback returns (or throws)
|
|
519
|
+
* - Marked as ERROR if the callback throws
|
|
520
|
+
*
|
|
521
|
+
* @returns The callback's return value
|
|
522
|
+
*/
|
|
523
|
+
startSpan(options, fn) {
|
|
524
|
+
const opts = typeof options === "string" ? { name: options } : options;
|
|
525
|
+
if (!this._enabled) {
|
|
526
|
+
return fn(NOOP_SPAN);
|
|
527
|
+
}
|
|
528
|
+
const parentSpan = getCurrentSpan();
|
|
529
|
+
const session2 = getCurrentSession();
|
|
530
|
+
const agent2 = getCurrentAgent();
|
|
531
|
+
const phase = getCurrentPhase();
|
|
532
|
+
const traceId = opts.traceId ?? parentSpan?.traceId ?? generateTraceId();
|
|
533
|
+
if (!parentSpan && this._sampleRate < 1) {
|
|
534
|
+
if (!shouldSample(traceId, this._sampleRate)) {
|
|
535
|
+
return fn(NOOP_SPAN);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
const parentSpanId = opts.parentSpanId ?? parentSpan?.spanId;
|
|
539
|
+
const spanOptions = {
|
|
540
|
+
name: opts.name,
|
|
541
|
+
kind: opts.kind ?? "internal" /* INTERNAL */,
|
|
542
|
+
traceId,
|
|
543
|
+
parentSpanId,
|
|
544
|
+
attributes: opts.attributes,
|
|
545
|
+
sessionId: session2?.sessionId,
|
|
546
|
+
agentId: agent2?.agentId,
|
|
547
|
+
agentName: agent2?.agentName,
|
|
548
|
+
agentType: agent2?.agentType,
|
|
549
|
+
semanticPhase: phase
|
|
550
|
+
};
|
|
551
|
+
const span = new Span(spanOptions, this._onSpanEnd);
|
|
552
|
+
try {
|
|
553
|
+
const result = runWithContext({ span }, () => fn(span));
|
|
554
|
+
if (result instanceof Promise) {
|
|
555
|
+
return result.then(
|
|
556
|
+
(value) => {
|
|
557
|
+
span.end();
|
|
558
|
+
return value;
|
|
559
|
+
},
|
|
560
|
+
(error) => {
|
|
561
|
+
span.recordException(error instanceof Error ? error : String(error));
|
|
562
|
+
span.end();
|
|
563
|
+
throw error;
|
|
564
|
+
}
|
|
565
|
+
);
|
|
566
|
+
}
|
|
567
|
+
span.end();
|
|
568
|
+
return result;
|
|
569
|
+
} catch (error) {
|
|
570
|
+
span.recordException(error instanceof Error ? error : String(error));
|
|
571
|
+
span.end();
|
|
572
|
+
throw error;
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
/**
|
|
576
|
+
* Create a span without auto-ending. Caller is responsible for calling span.end().
|
|
577
|
+
*
|
|
578
|
+
* Useful for long-running operations where you need manual control.
|
|
579
|
+
* The span is still linked to context and enriched with session/agent/phase.
|
|
580
|
+
*/
|
|
581
|
+
createSpan(options) {
|
|
582
|
+
const opts = typeof options === "string" ? { name: options } : options;
|
|
583
|
+
if (!this._enabled) {
|
|
584
|
+
return NOOP_SPAN;
|
|
585
|
+
}
|
|
586
|
+
const parentSpan = getCurrentSpan();
|
|
587
|
+
const session2 = getCurrentSession();
|
|
588
|
+
const agent2 = getCurrentAgent();
|
|
589
|
+
const phase = getCurrentPhase();
|
|
590
|
+
const traceId = opts.traceId ?? parentSpan?.traceId ?? generateTraceId();
|
|
591
|
+
if (!parentSpan && this._sampleRate < 1) {
|
|
592
|
+
if (!shouldSample(traceId, this._sampleRate)) {
|
|
593
|
+
return NOOP_SPAN;
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
const parentSpanId = opts.parentSpanId ?? parentSpan?.spanId;
|
|
597
|
+
return new Span(
|
|
598
|
+
{
|
|
599
|
+
name: opts.name,
|
|
600
|
+
kind: opts.kind ?? "internal" /* INTERNAL */,
|
|
601
|
+
traceId,
|
|
602
|
+
parentSpanId,
|
|
603
|
+
attributes: opts.attributes,
|
|
604
|
+
sessionId: session2?.sessionId,
|
|
605
|
+
agentId: agent2?.agentId,
|
|
606
|
+
agentName: agent2?.agentName,
|
|
607
|
+
agentType: agent2?.agentType,
|
|
608
|
+
semanticPhase: phase
|
|
609
|
+
},
|
|
610
|
+
this._onSpanEnd
|
|
611
|
+
);
|
|
612
|
+
}
|
|
613
|
+
};
|
|
614
|
+
|
|
615
|
+
// src/utils/log.ts
|
|
616
|
+
var _debug = false;
|
|
617
|
+
function setDebug(enabled) {
|
|
618
|
+
_debug = enabled;
|
|
619
|
+
}
|
|
620
|
+
function debug(msg) {
|
|
621
|
+
if (_debug) {
|
|
622
|
+
process.stderr.write(`[risicare] ${msg}
|
|
623
|
+
`);
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
function warn(msg) {
|
|
627
|
+
process.stderr.write(`[risicare] WARNING: ${msg}
|
|
628
|
+
`);
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
// src/exporters/batch.ts
|
|
632
|
+
var BatchSpanProcessor = class {
|
|
633
|
+
_exporters;
|
|
634
|
+
_batchSize;
|
|
635
|
+
_batchTimeoutMs;
|
|
636
|
+
_maxQueueSize;
|
|
637
|
+
_debug;
|
|
638
|
+
_queue = [];
|
|
639
|
+
_timer = null;
|
|
640
|
+
_started = false;
|
|
641
|
+
_flushing = false;
|
|
642
|
+
// Metrics
|
|
643
|
+
droppedSpans = 0;
|
|
644
|
+
exportedSpans = 0;
|
|
645
|
+
failedExports = 0;
|
|
646
|
+
constructor(options) {
|
|
647
|
+
this._exporters = [...options.exporters];
|
|
648
|
+
this._batchSize = options.batchSize ?? 100;
|
|
649
|
+
this._batchTimeoutMs = options.batchTimeoutMs ?? 1e3;
|
|
650
|
+
this._maxQueueSize = options.maxQueueSize ?? 1e4;
|
|
651
|
+
this._debug = options.debug ?? false;
|
|
652
|
+
}
|
|
653
|
+
start() {
|
|
654
|
+
if (this._started) return;
|
|
655
|
+
this._started = true;
|
|
656
|
+
this._timer = setInterval(() => {
|
|
657
|
+
void this._exportBatch();
|
|
658
|
+
}, this._batchTimeoutMs);
|
|
659
|
+
this._timer.unref();
|
|
660
|
+
process.on("beforeExit", () => {
|
|
661
|
+
void this.shutdown();
|
|
662
|
+
});
|
|
663
|
+
}
|
|
664
|
+
async shutdown(timeoutMs = 5e3) {
|
|
665
|
+
if (!this._started) return;
|
|
666
|
+
this._started = false;
|
|
667
|
+
if (this._timer) {
|
|
668
|
+
clearInterval(this._timer);
|
|
669
|
+
this._timer = null;
|
|
670
|
+
}
|
|
671
|
+
const flushPromise = this._exportBatch();
|
|
672
|
+
const timeoutPromise = new Promise((resolve) => setTimeout(resolve, timeoutMs));
|
|
673
|
+
await Promise.race([flushPromise, timeoutPromise]);
|
|
674
|
+
for (const exporter of this._exporters) {
|
|
675
|
+
try {
|
|
676
|
+
await exporter.shutdown();
|
|
677
|
+
} catch (e) {
|
|
678
|
+
debug(`Error shutting down ${exporter.name}: ${e}`);
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
debug(
|
|
682
|
+
`BatchSpanProcessor shutdown. Exported: ${this.exportedSpans}, Dropped: ${this.droppedSpans}, Failed: ${this.failedExports}`
|
|
683
|
+
);
|
|
684
|
+
}
|
|
685
|
+
onSpanEnd(span) {
|
|
686
|
+
if (!this._started) return;
|
|
687
|
+
if (this._queue.length >= this._maxQueueSize) {
|
|
688
|
+
this.droppedSpans++;
|
|
689
|
+
if (this.droppedSpans === 1 || this.droppedSpans % 1e3 === 0) {
|
|
690
|
+
warn(`Span queue full (${this._maxQueueSize}). ${this.droppedSpans} spans dropped so far.`);
|
|
691
|
+
}
|
|
692
|
+
return;
|
|
693
|
+
}
|
|
694
|
+
this._queue.push(span);
|
|
695
|
+
if (this._queue.length >= this._batchSize) {
|
|
696
|
+
void this._exportBatch();
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
async flush(timeoutMs = 5e3) {
|
|
700
|
+
if (!this._started) return true;
|
|
701
|
+
const start = Date.now();
|
|
702
|
+
while (this._queue.length > 0 || this._flushing) {
|
|
703
|
+
if (!this._flushing && this._queue.length > 0) {
|
|
704
|
+
await this._exportBatch();
|
|
705
|
+
} else {
|
|
706
|
+
await new Promise((r) => setTimeout(r, 1));
|
|
707
|
+
}
|
|
708
|
+
if (Date.now() - start > timeoutMs) return false;
|
|
709
|
+
}
|
|
710
|
+
return true;
|
|
711
|
+
}
|
|
712
|
+
getMetrics() {
|
|
713
|
+
return {
|
|
714
|
+
exportedSpans: this.exportedSpans,
|
|
715
|
+
droppedSpans: this.droppedSpans,
|
|
716
|
+
failedExports: this.failedExports,
|
|
717
|
+
queueSize: this._queue.length,
|
|
718
|
+
queueCapacity: this._maxQueueSize,
|
|
719
|
+
queueUtilization: this._queue.length / this._maxQueueSize
|
|
720
|
+
};
|
|
721
|
+
}
|
|
722
|
+
async _exportBatch() {
|
|
723
|
+
if (this._flushing || this._queue.length === 0) return;
|
|
724
|
+
this._flushing = true;
|
|
725
|
+
try {
|
|
726
|
+
const batch = this._queue.splice(0, this._batchSize);
|
|
727
|
+
if (batch.length === 0) return;
|
|
728
|
+
debug(`Exporting batch of ${batch.length} spans`);
|
|
729
|
+
let batchExported = false;
|
|
730
|
+
for (const exporter of this._exporters) {
|
|
731
|
+
try {
|
|
732
|
+
const result = await exporter.export(batch);
|
|
733
|
+
if (result === "success" /* SUCCESS */) {
|
|
734
|
+
if (!batchExported) {
|
|
735
|
+
this.exportedSpans += batch.length;
|
|
736
|
+
batchExported = true;
|
|
737
|
+
}
|
|
738
|
+
} else {
|
|
739
|
+
this.failedExports++;
|
|
740
|
+
}
|
|
741
|
+
} catch (e) {
|
|
742
|
+
this.failedExports++;
|
|
743
|
+
debug(`Export to ${exporter.name} failed: ${e}`);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
} finally {
|
|
747
|
+
this._flushing = false;
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
};
|
|
751
|
+
|
|
752
|
+
// src/exporters/http.ts
|
|
753
|
+
var HttpExporter = class {
|
|
754
|
+
name = "http";
|
|
755
|
+
_endpoint;
|
|
756
|
+
_apiKey;
|
|
757
|
+
_projectId;
|
|
758
|
+
_environment;
|
|
759
|
+
_timeoutMs;
|
|
760
|
+
_maxRetries;
|
|
761
|
+
_compress;
|
|
762
|
+
// Circuit breaker
|
|
763
|
+
_consecutiveFailures = 0;
|
|
764
|
+
_circuitOpenUntil = 0;
|
|
765
|
+
_circuitBreakerThreshold = 3;
|
|
766
|
+
_circuitBreakerCooldownMs = 3e4;
|
|
767
|
+
constructor(options) {
|
|
768
|
+
this._endpoint = options.endpoint.replace(/\/+$/, "");
|
|
769
|
+
this._apiKey = options.apiKey;
|
|
770
|
+
this._projectId = options.projectId;
|
|
771
|
+
this._environment = options.environment;
|
|
772
|
+
this._timeoutMs = options.timeoutMs ?? 5e3;
|
|
773
|
+
this._maxRetries = options.maxRetries ?? 3;
|
|
774
|
+
this._compress = options.compress ?? false;
|
|
775
|
+
}
|
|
776
|
+
async export(spans) {
|
|
777
|
+
if (spans.length === 0) return "success" /* SUCCESS */;
|
|
778
|
+
const now = Date.now();
|
|
779
|
+
if (this._consecutiveFailures >= this._circuitBreakerThreshold) {
|
|
780
|
+
if (now < this._circuitOpenUntil) {
|
|
781
|
+
return "failure" /* FAILURE */;
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
const body = {
|
|
785
|
+
spans: spans.map((s) => s.toPayload())
|
|
786
|
+
};
|
|
787
|
+
if (this._projectId) body.projectId = this._projectId;
|
|
788
|
+
if (this._environment) body.environment = this._environment;
|
|
789
|
+
for (let attempt = 0; attempt < this._maxRetries; attempt++) {
|
|
790
|
+
const result = await this._sendRequest(body);
|
|
791
|
+
if (result === "success" /* SUCCESS */) {
|
|
792
|
+
this._consecutiveFailures = 0;
|
|
793
|
+
return result;
|
|
794
|
+
}
|
|
795
|
+
if (attempt < this._maxRetries - 1) {
|
|
796
|
+
await sleep(100 * Math.pow(2, attempt));
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
this._consecutiveFailures++;
|
|
800
|
+
if (this._consecutiveFailures >= this._circuitBreakerThreshold) {
|
|
801
|
+
this._circuitOpenUntil = Date.now() + this._circuitBreakerCooldownMs;
|
|
802
|
+
warn(
|
|
803
|
+
`HTTP exporter circuit breaker opened after ${this._consecutiveFailures} failures. Cooldown: ${this._circuitBreakerCooldownMs / 1e3}s`
|
|
804
|
+
);
|
|
805
|
+
}
|
|
806
|
+
return "failure" /* FAILURE */;
|
|
807
|
+
}
|
|
808
|
+
async _sendRequest(body) {
|
|
809
|
+
const url = `${this._endpoint}/v1/spans`;
|
|
810
|
+
const headers = {
|
|
811
|
+
"Content-Type": "application/json"
|
|
812
|
+
};
|
|
813
|
+
if (this._apiKey) {
|
|
814
|
+
headers["Authorization"] = `Bearer ${this._apiKey}`;
|
|
815
|
+
}
|
|
816
|
+
let payload = JSON.stringify(body);
|
|
817
|
+
if (this._compress && payload.length > 1024) {
|
|
818
|
+
try {
|
|
819
|
+
const { gzipSync } = await import("zlib");
|
|
820
|
+
payload = gzipSync(Buffer.from(payload));
|
|
821
|
+
headers["Content-Encoding"] = "gzip";
|
|
822
|
+
} catch {
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
try {
|
|
826
|
+
const controller = new AbortController();
|
|
827
|
+
const timeoutId = setTimeout(() => controller.abort(), this._timeoutMs);
|
|
828
|
+
const response = await fetch(url, {
|
|
829
|
+
method: "POST",
|
|
830
|
+
headers,
|
|
831
|
+
body: payload,
|
|
832
|
+
signal: controller.signal
|
|
833
|
+
});
|
|
834
|
+
clearTimeout(timeoutId);
|
|
835
|
+
if (response.status < 300) {
|
|
836
|
+
return "success" /* SUCCESS */;
|
|
837
|
+
} else if (response.status === 408 || response.status === 504) {
|
|
838
|
+
debug(`HTTP export timeout: ${response.status}`);
|
|
839
|
+
return "timeout" /* TIMEOUT */;
|
|
840
|
+
}
|
|
841
|
+
debug(`HTTP export failed: ${response.status}`);
|
|
842
|
+
return "failure" /* FAILURE */;
|
|
843
|
+
} catch (e) {
|
|
844
|
+
debug(`HTTP export error: ${e}`);
|
|
845
|
+
return "failure" /* FAILURE */;
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
shutdown() {
|
|
849
|
+
}
|
|
850
|
+
};
|
|
851
|
+
function sleep(ms) {
|
|
852
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
// src/exporters/console.ts
|
|
856
|
+
var ConsoleExporter = class {
|
|
857
|
+
name = "console";
|
|
858
|
+
export(spans) {
|
|
859
|
+
for (const span of spans) {
|
|
860
|
+
const payload = span.toPayload();
|
|
861
|
+
const line = JSON.stringify(payload);
|
|
862
|
+
process.stderr.write(`[risicare] ${line}
|
|
863
|
+
`);
|
|
864
|
+
}
|
|
865
|
+
return "success" /* SUCCESS */;
|
|
866
|
+
}
|
|
867
|
+
shutdown() {
|
|
868
|
+
}
|
|
869
|
+
};
|
|
870
|
+
|
|
871
|
+
// src/client.ts
|
|
872
|
+
var _client;
|
|
873
|
+
var _tracer;
|
|
874
|
+
var RisicareClient = class {
|
|
875
|
+
config;
|
|
876
|
+
processor;
|
|
877
|
+
tracer;
|
|
878
|
+
_shutdownCalled = false;
|
|
879
|
+
constructor(config) {
|
|
880
|
+
this.config = resolveConfig(config);
|
|
881
|
+
let exporter;
|
|
882
|
+
if (this.config.debug && !this.config.apiKey) {
|
|
883
|
+
exporter = new ConsoleExporter();
|
|
884
|
+
} else if (this.config.apiKey) {
|
|
885
|
+
exporter = new HttpExporter({
|
|
886
|
+
endpoint: this.config.endpoint,
|
|
887
|
+
apiKey: this.config.apiKey,
|
|
888
|
+
projectId: this.config.projectId || void 0,
|
|
889
|
+
environment: this.config.environment || void 0
|
|
890
|
+
});
|
|
891
|
+
} else {
|
|
892
|
+
exporter = new ConsoleExporter();
|
|
893
|
+
}
|
|
894
|
+
this.processor = new BatchSpanProcessor({
|
|
895
|
+
exporters: [exporter],
|
|
896
|
+
batchSize: this.config.batchSize,
|
|
897
|
+
batchTimeoutMs: this.config.batchTimeoutMs,
|
|
898
|
+
maxQueueSize: this.config.maxQueueSize,
|
|
899
|
+
debug: this.config.debug
|
|
900
|
+
});
|
|
901
|
+
this.tracer = new Tracer({
|
|
902
|
+
onSpanEnd: (span) => this.processor.onSpanEnd(span),
|
|
903
|
+
sampleRate: this.config.sampleRate,
|
|
904
|
+
enabled: this.config.enabled
|
|
905
|
+
});
|
|
906
|
+
this.processor.start();
|
|
907
|
+
this._registerShutdownHooks();
|
|
908
|
+
setDebug(this.config.debug);
|
|
909
|
+
debug(`Initialized: enabled=${this.config.enabled}, endpoint=${this.config.endpoint}`);
|
|
910
|
+
}
|
|
911
|
+
get enabled() {
|
|
912
|
+
return this.tracer.enabled;
|
|
913
|
+
}
|
|
914
|
+
set enabled(value) {
|
|
915
|
+
this.tracer.enabled = value;
|
|
916
|
+
}
|
|
917
|
+
async shutdown() {
|
|
918
|
+
if (this._shutdownCalled) return;
|
|
919
|
+
this._shutdownCalled = true;
|
|
920
|
+
debug("Shutting down...");
|
|
921
|
+
await this.processor.shutdown();
|
|
922
|
+
}
|
|
923
|
+
async flush() {
|
|
924
|
+
await this.processor.flush();
|
|
925
|
+
}
|
|
926
|
+
_registerShutdownHooks() {
|
|
927
|
+
const onShutdown = () => {
|
|
928
|
+
this.shutdown().catch(() => {
|
|
929
|
+
});
|
|
930
|
+
};
|
|
931
|
+
process.once("beforeExit", onShutdown);
|
|
932
|
+
process.once("SIGTERM", onShutdown);
|
|
933
|
+
process.once("SIGINT", onShutdown);
|
|
934
|
+
}
|
|
935
|
+
};
|
|
936
|
+
function init(config) {
|
|
937
|
+
if (_client) {
|
|
938
|
+
debug("Already initialized. Call shutdown() first to re-initialize.");
|
|
939
|
+
return;
|
|
940
|
+
}
|
|
941
|
+
_client = new RisicareClient(config);
|
|
942
|
+
_tracer = _client.tracer;
|
|
943
|
+
}
|
|
944
|
+
async function shutdown() {
|
|
945
|
+
if (!_client) return;
|
|
946
|
+
await _client.shutdown();
|
|
947
|
+
_client = void 0;
|
|
948
|
+
_tracer = void 0;
|
|
949
|
+
}
|
|
950
|
+
async function flush() {
|
|
951
|
+
if (!_client) return;
|
|
952
|
+
await _client.flush();
|
|
953
|
+
}
|
|
954
|
+
function enable() {
|
|
955
|
+
if (_client) _client.enabled = true;
|
|
956
|
+
}
|
|
957
|
+
function disable() {
|
|
958
|
+
if (_client) _client.enabled = false;
|
|
959
|
+
}
|
|
960
|
+
function isEnabled() {
|
|
961
|
+
return _client?.enabled ?? false;
|
|
962
|
+
}
|
|
963
|
+
function getTracer() {
|
|
964
|
+
return _tracer;
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
// src/context/agent.ts
|
|
968
|
+
function withAgent(options, fn) {
|
|
969
|
+
if (!isEnabled()) return fn();
|
|
970
|
+
const parent = getCurrentAgent();
|
|
971
|
+
const agentName = options.name ?? "agent";
|
|
972
|
+
const agent2 = {
|
|
973
|
+
agentId: options.agentId ?? generateAgentId(agentName),
|
|
974
|
+
agentName,
|
|
975
|
+
agentRole: options.role,
|
|
976
|
+
agentType: options.agentType,
|
|
977
|
+
parentAgentId: parent?.agentId,
|
|
978
|
+
version: options.version,
|
|
979
|
+
metadata: options.metadata
|
|
980
|
+
};
|
|
981
|
+
return runWithContext({ agent: agent2 }, fn);
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
// src/decorators/agent.ts
|
|
985
|
+
function agent(options, fn) {
|
|
986
|
+
const spanName = `agent:${options.name ?? "agent"}`;
|
|
987
|
+
return (...args) => {
|
|
988
|
+
const tracer = getTracer();
|
|
989
|
+
if (!tracer) {
|
|
990
|
+
return fn(...args);
|
|
991
|
+
}
|
|
992
|
+
return withAgent(options, () => {
|
|
993
|
+
return tracer.startSpan({ name: spanName, kind: "agent" /* AGENT */ }, () => {
|
|
994
|
+
return fn(...args);
|
|
995
|
+
});
|
|
996
|
+
});
|
|
997
|
+
};
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
// src/context/session.ts
|
|
1001
|
+
function withSession(options, fn) {
|
|
1002
|
+
if (!isEnabled()) return fn();
|
|
1003
|
+
const session2 = {
|
|
1004
|
+
sessionId: options.sessionId,
|
|
1005
|
+
userId: options.userId,
|
|
1006
|
+
metadata: options.metadata,
|
|
1007
|
+
parentSessionId: options.parentSessionId,
|
|
1008
|
+
turnNumber: options.turnNumber ?? 1
|
|
1009
|
+
};
|
|
1010
|
+
return runWithContext({ session: session2 }, fn);
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
// src/decorators/session.ts
|
|
1014
|
+
function session(optionsOrResolver, fn) {
|
|
1015
|
+
return (...args) => {
|
|
1016
|
+
const options = typeof optionsOrResolver === "function" ? optionsOrResolver(...args) : optionsOrResolver;
|
|
1017
|
+
return withSession(options, () => fn(...args));
|
|
1018
|
+
};
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
// src/context/phase.ts
|
|
1022
|
+
function withPhase(phase, fn) {
|
|
1023
|
+
if (!isEnabled()) return fn();
|
|
1024
|
+
return runWithContext({ phase }, fn);
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
// src/decorators/phase.ts
|
|
1028
|
+
function phaseWrapper(phase, fn) {
|
|
1029
|
+
return (...args) => {
|
|
1030
|
+
const tracer = getTracer();
|
|
1031
|
+
if (!tracer) {
|
|
1032
|
+
return fn(...args);
|
|
1033
|
+
}
|
|
1034
|
+
return withPhase(phase, () => {
|
|
1035
|
+
return tracer.startSpan({ name: `phase:${phase}` }, () => fn(...args));
|
|
1036
|
+
});
|
|
1037
|
+
};
|
|
1038
|
+
}
|
|
1039
|
+
function traceThink(fn) {
|
|
1040
|
+
return phaseWrapper("think" /* THINK */, fn);
|
|
1041
|
+
}
|
|
1042
|
+
function traceDecide(fn) {
|
|
1043
|
+
return phaseWrapper("decide" /* DECIDE */, fn);
|
|
1044
|
+
}
|
|
1045
|
+
function traceAct(fn) {
|
|
1046
|
+
return phaseWrapper("act" /* ACT */, fn);
|
|
1047
|
+
}
|
|
1048
|
+
function traceObserve(fn) {
|
|
1049
|
+
return phaseWrapper("observe" /* OBSERVE */, fn);
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
// src/decorators/multi-agent.ts
|
|
1053
|
+
function namespacedMetadata(metadata) {
|
|
1054
|
+
if (!metadata) return {};
|
|
1055
|
+
const result = {};
|
|
1056
|
+
for (const [key, value] of Object.entries(metadata)) {
|
|
1057
|
+
result[`metadata.${key}`] = value;
|
|
1058
|
+
}
|
|
1059
|
+
return result;
|
|
1060
|
+
}
|
|
1061
|
+
function traceMessage(options, fn) {
|
|
1062
|
+
const msgType = options.type ?? "request" /* REQUEST */;
|
|
1063
|
+
return (...args) => {
|
|
1064
|
+
const tracer = getTracer();
|
|
1065
|
+
if (!tracer) return fn(...args);
|
|
1066
|
+
return tracer.startSpan(
|
|
1067
|
+
{
|
|
1068
|
+
name: `message:${msgType}\u2192${options.to}`,
|
|
1069
|
+
kind: "message" /* MESSAGE */,
|
|
1070
|
+
attributes: {
|
|
1071
|
+
...namespacedMetadata(options.metadata),
|
|
1072
|
+
"message.to": options.to,
|
|
1073
|
+
"message.type": msgType,
|
|
1074
|
+
"message.target_agent_id": options.to
|
|
1075
|
+
}
|
|
1076
|
+
},
|
|
1077
|
+
() => fn(...args)
|
|
1078
|
+
);
|
|
1079
|
+
};
|
|
1080
|
+
}
|
|
1081
|
+
function traceDelegate(options, fn) {
|
|
1082
|
+
return (...args) => {
|
|
1083
|
+
const tracer = getTracer();
|
|
1084
|
+
if (!tracer) return fn(...args);
|
|
1085
|
+
return tracer.startSpan(
|
|
1086
|
+
{
|
|
1087
|
+
name: `delegate\u2192${options.to}`,
|
|
1088
|
+
kind: "delegation" /* DELEGATION */,
|
|
1089
|
+
attributes: {
|
|
1090
|
+
...namespacedMetadata(options.metadata),
|
|
1091
|
+
"delegate.to": options.to,
|
|
1092
|
+
"message.type": "delegate" /* DELEGATE */,
|
|
1093
|
+
"message.target_agent_id": options.to
|
|
1094
|
+
}
|
|
1095
|
+
},
|
|
1096
|
+
() => fn(...args)
|
|
1097
|
+
);
|
|
1098
|
+
};
|
|
1099
|
+
}
|
|
1100
|
+
function traceCoordinate(options, fn) {
|
|
1101
|
+
return (...args) => {
|
|
1102
|
+
const tracer = getTracer();
|
|
1103
|
+
if (!tracer) return fn(...args);
|
|
1104
|
+
return tracer.startSpan(
|
|
1105
|
+
{
|
|
1106
|
+
name: `coordinate:[${options.participants.join(",")}]`,
|
|
1107
|
+
kind: "coordination" /* COORDINATION */,
|
|
1108
|
+
attributes: {
|
|
1109
|
+
...namespacedMetadata(options.metadata),
|
|
1110
|
+
"coordinate.participants": options.participants.join(","),
|
|
1111
|
+
"message.type": "coordinate" /* COORDINATE */
|
|
1112
|
+
}
|
|
1113
|
+
},
|
|
1114
|
+
() => fn(...args)
|
|
1115
|
+
);
|
|
1116
|
+
};
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
// src/context/trace-context.ts
|
|
1120
|
+
function getTraceContext() {
|
|
1121
|
+
const span = getCurrentSpan();
|
|
1122
|
+
const session2 = getCurrentSession();
|
|
1123
|
+
const agent2 = getCurrentAgent();
|
|
1124
|
+
return {
|
|
1125
|
+
traceId: span?.traceId ?? generateTraceId(),
|
|
1126
|
+
spanId: span?.spanId ?? generateSpanId(),
|
|
1127
|
+
sessionId: session2?.sessionId,
|
|
1128
|
+
agentId: agent2?.agentId
|
|
1129
|
+
};
|
|
1130
|
+
}
|
|
1131
|
+
var TRACEPARENT_HEADER = "traceparent";
|
|
1132
|
+
var TRACESTATE_HEADER = "tracestate";
|
|
1133
|
+
var RISICARE_STATE_DELIMITER = ";";
|
|
1134
|
+
function injectTraceContext(headers) {
|
|
1135
|
+
const span = getCurrentSpan();
|
|
1136
|
+
const session2 = getCurrentSession();
|
|
1137
|
+
const agent2 = getCurrentAgent();
|
|
1138
|
+
if (span) {
|
|
1139
|
+
headers[TRACEPARENT_HEADER] = `00-${span.traceId}-${span.spanId}-01`;
|
|
1140
|
+
const parts = [];
|
|
1141
|
+
if (session2) parts.push(`session_id=${session2.sessionId}`);
|
|
1142
|
+
if (agent2) parts.push(`agent_id=${agent2.agentId}`);
|
|
1143
|
+
if (parts.length > 0) {
|
|
1144
|
+
const riscareEntry = `risicare=${parts.join(RISICARE_STATE_DELIMITER)}`;
|
|
1145
|
+
const existing = headers[TRACESTATE_HEADER] ?? "";
|
|
1146
|
+
const otherEntries = existing.split(",").map((e) => e.trim()).filter((e) => e && !e.startsWith("risicare="));
|
|
1147
|
+
headers[TRACESTATE_HEADER] = [riscareEntry, ...otherEntries].join(",");
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
return headers;
|
|
1151
|
+
}
|
|
1152
|
+
function extractTraceContext(headers) {
|
|
1153
|
+
const result = {};
|
|
1154
|
+
const normalizedHeaders = {};
|
|
1155
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
1156
|
+
normalizedHeaders[key.toLowerCase()] = value;
|
|
1157
|
+
}
|
|
1158
|
+
const traceparent = normalizedHeaders[TRACEPARENT_HEADER] ?? "";
|
|
1159
|
+
if (traceparent) {
|
|
1160
|
+
const parts = traceparent.split("-");
|
|
1161
|
+
if (parts.length >= 4) {
|
|
1162
|
+
const traceId = parts[1].toLowerCase();
|
|
1163
|
+
const spanId = parts[2].toLowerCase();
|
|
1164
|
+
if (validateTraceId(traceId)) result.traceId = traceId;
|
|
1165
|
+
if (validateSpanId(spanId)) result.parentSpanId = spanId;
|
|
1166
|
+
result.flags = parts[3];
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
const tracestate = normalizedHeaders[TRACESTATE_HEADER] ?? "";
|
|
1170
|
+
if (tracestate) {
|
|
1171
|
+
for (const entry of tracestate.split(",")) {
|
|
1172
|
+
const trimmed = entry.trim();
|
|
1173
|
+
if (trimmed.startsWith("risicare=")) {
|
|
1174
|
+
const state = trimmed.slice(9);
|
|
1175
|
+
for (const kv of state.split(RISICARE_STATE_DELIMITER)) {
|
|
1176
|
+
const eqIdx = kv.indexOf("=");
|
|
1177
|
+
if (eqIdx > 0) {
|
|
1178
|
+
const key = kv.slice(0, eqIdx).trim();
|
|
1179
|
+
const value = kv.slice(eqIdx + 1).trim();
|
|
1180
|
+
if (key && value) result[key] = value;
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
return result;
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
// src/context/registry.ts
|
|
1190
|
+
var DEFAULT_TTL_MS = 6e4;
|
|
1191
|
+
var MAX_ENTRIES = 1e4;
|
|
1192
|
+
var CLEANUP_INTERVAL = 100;
|
|
1193
|
+
var entries = /* @__PURE__ */ new Map();
|
|
1194
|
+
var operationCount = 0;
|
|
1195
|
+
function registerSpan(span, ttlMs = DEFAULT_TTL_MS) {
|
|
1196
|
+
entries.set(span.spanId, {
|
|
1197
|
+
span,
|
|
1198
|
+
registeredAt: Date.now(),
|
|
1199
|
+
ttlMs
|
|
1200
|
+
});
|
|
1201
|
+
operationCount++;
|
|
1202
|
+
maybeCleanup();
|
|
1203
|
+
}
|
|
1204
|
+
function getSpanById(spanId) {
|
|
1205
|
+
const entry = entries.get(spanId);
|
|
1206
|
+
if (!entry) return void 0;
|
|
1207
|
+
if (Date.now() - entry.registeredAt > entry.ttlMs) {
|
|
1208
|
+
entries.delete(spanId);
|
|
1209
|
+
return void 0;
|
|
1210
|
+
}
|
|
1211
|
+
return entry.span;
|
|
1212
|
+
}
|
|
1213
|
+
function unregisterSpan(spanId) {
|
|
1214
|
+
entries.delete(spanId);
|
|
1215
|
+
}
|
|
1216
|
+
function maybeCleanup() {
|
|
1217
|
+
if (operationCount % CLEANUP_INTERVAL !== 0) return;
|
|
1218
|
+
if (entries.size <= MAX_ENTRIES) return;
|
|
1219
|
+
const now = Date.now();
|
|
1220
|
+
for (const [id, entry] of entries) {
|
|
1221
|
+
if (now - entry.registeredAt > entry.ttlMs) {
|
|
1222
|
+
entries.delete(id);
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1227
|
+
0 && (module.exports = {
|
|
1228
|
+
AgentRole,
|
|
1229
|
+
MessageType,
|
|
1230
|
+
SemanticPhase,
|
|
1231
|
+
SpanKind,
|
|
1232
|
+
SpanStatus,
|
|
1233
|
+
agent,
|
|
1234
|
+
disable,
|
|
1235
|
+
enable,
|
|
1236
|
+
extractTraceContext,
|
|
1237
|
+
flush,
|
|
1238
|
+
getCurrentAgent,
|
|
1239
|
+
getCurrentAgentId,
|
|
1240
|
+
getCurrentContext,
|
|
1241
|
+
getCurrentPhase,
|
|
1242
|
+
getCurrentSession,
|
|
1243
|
+
getCurrentSessionId,
|
|
1244
|
+
getCurrentSpan,
|
|
1245
|
+
getCurrentSpanId,
|
|
1246
|
+
getCurrentTraceId,
|
|
1247
|
+
getSpanById,
|
|
1248
|
+
getTraceContext,
|
|
1249
|
+
getTracer,
|
|
1250
|
+
init,
|
|
1251
|
+
injectTraceContext,
|
|
1252
|
+
isEnabled,
|
|
1253
|
+
registerSpan,
|
|
1254
|
+
session,
|
|
1255
|
+
shutdown,
|
|
1256
|
+
traceAct,
|
|
1257
|
+
traceCoordinate,
|
|
1258
|
+
traceDecide,
|
|
1259
|
+
traceDelegate,
|
|
1260
|
+
traceMessage,
|
|
1261
|
+
traceObserve,
|
|
1262
|
+
traceThink,
|
|
1263
|
+
unregisterSpan,
|
|
1264
|
+
withAgent,
|
|
1265
|
+
withPhase,
|
|
1266
|
+
withSession
|
|
1267
|
+
});
|
|
1268
|
+
//# sourceMappingURL=index.cjs.map
|