raindrop-ai 0.9.0 → 0.9.1
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 +38 -0
- package/dist/{chunk-VBZXQNJY.mjs → chunk-SUW3YBV3.mjs} +1 -1
- package/dist/{chunk-RIL2CV7Q.mjs → chunk-WLBBPTI6.mjs} +224 -3
- package/dist/evals/cli.js +226 -5
- package/dist/evals/cli.mjs +2 -2
- package/dist/{index-DZB7DoZS.d.mts → index-C5Aj6zuo.d.mts} +37 -1
- package/dist/{index-DZB7DoZS.d.ts → index-C5Aj6zuo.d.ts} +37 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +226 -5
- package/dist/index.mjs +2 -2
- package/dist/tracing/index.d.mts +2 -2
- package/dist/tracing/index.d.ts +2 -2
- package/dist/tracing/index.js +224 -3
- package/dist/tracing/index.mjs +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -56,6 +56,44 @@ const raindrop = new Raindrop({
|
|
|
56
56
|
|
|
57
57
|
This sets the `X-Raindrop-Project-Id` header on every event and trace. Omit it (or pass `"default"`) to use your org's default **Production** project — the existing behavior. Single-project orgs need nothing new.
|
|
58
58
|
|
|
59
|
+
## Tool catalog capture (`ai.prompt.tools`)
|
|
60
|
+
|
|
61
|
+
Every model-call span can carry `ai.prompt.tools`: a string array with one JSON
|
|
62
|
+
document per tool the model was given
|
|
63
|
+
(`{"type":"function","name":…,"description"?:…,"inputSchema"?:<JSON Schema>}` or
|
|
64
|
+
`{"type":"provider-defined",…}`). The core SDK records it two ways:
|
|
65
|
+
|
|
66
|
+
- **Mirrored from Traceloop-style instrumentation.** OpenLLMetry
|
|
67
|
+
instrumentations (OpenAI, Anthropic, LangChain, …) record the request's
|
|
68
|
+
functions as `llm.request.functions.{i}.name|description|parameters`. When such
|
|
69
|
+
a span ends without an `ai.prompt.tools`, the SDK's span processor adds one
|
|
70
|
+
built from those attributes (schemas pass through untouched; a function
|
|
71
|
+
without `parameters` is recorded without an invented `inputSchema`). The
|
|
72
|
+
original attributes stay in place. This is the exact per-call list the
|
|
73
|
+
instrumentation saw.
|
|
74
|
+
- **Override from `begin({ tools })`.** `tools` overrides the tool catalog
|
|
75
|
+
recorded as `ai.prompt.tools` on every model span started inside the
|
|
76
|
+
interaction — use when the integration cannot see the tools the model was
|
|
77
|
+
given. It replaces whatever the instrumentation recorded (`tools: []` records
|
|
78
|
+
an empty catalog), applies only to spans that carry a model attribute
|
|
79
|
+
(`llm.request.type`, `gen_ai.request.model` or `ai.model.id`) and ends with
|
|
80
|
+
`interaction.finish()`. It rides on the same execution-context mechanism as
|
|
81
|
+
the multi-project routing binding, so the `begin()` caveats below (Cloudflare
|
|
82
|
+
Workers) apply to it too.
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
const interaction = raindrop.begin({
|
|
86
|
+
event: "agent_turn",
|
|
87
|
+
userId: "user-123",
|
|
88
|
+
tools: [{ name: "get_weather", description: "Get the current weather", parameters: weatherJsonSchema }],
|
|
89
|
+
});
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Both paths honour the prompt-content switch (`traceContent: false` or
|
|
93
|
+
`TRACELOOP_TRACE_CONTENT=false`): with content capture off, no
|
|
94
|
+
`ai.prompt.tools` is recorded. An absent attribute means the SDK could not
|
|
95
|
+
observe the list; `[]` means the model had no tools.
|
|
96
|
+
|
|
59
97
|
## Multi-project tracing
|
|
60
98
|
|
|
61
99
|
You can run several `Raindrop` clients in one process, each pinned to a different project, and their **traces** are routed independently (manual events were already per-instance):
|
|
@@ -79,7 +79,7 @@ function evalScopeAttributes() {
|
|
|
79
79
|
return { [EVAL_CORRELATION_ID_ATTRIBUTE]: scope.correlationId };
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
// ../core/dist/chunk-
|
|
82
|
+
// ../core/dist/chunk-I6TVJQEC.js
|
|
83
83
|
var STATE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.replayTraceRoutingState");
|
|
84
84
|
function state() {
|
|
85
85
|
const holder = globalThis;
|
|
@@ -1467,6 +1467,178 @@ var DEFAULT_REDACT_ATTRIBUTE_KEYS = [
|
|
|
1467
1467
|
"ai.response.providerMetadata"
|
|
1468
1468
|
];
|
|
1469
1469
|
var REDACT_JSON_ATTRIBUTE_KEYS = new Set(DEFAULT_REDACT_ATTRIBUTE_KEYS);
|
|
1470
|
+
var PROMPT_TOOLS_ATTRIBUTE = "ai.prompt.tools";
|
|
1471
|
+
function isRecord(value) {
|
|
1472
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1473
|
+
}
|
|
1474
|
+
var JSON_SCHEMA_KEYS = [
|
|
1475
|
+
"type",
|
|
1476
|
+
"properties",
|
|
1477
|
+
"$schema",
|
|
1478
|
+
"$ref",
|
|
1479
|
+
"anyOf",
|
|
1480
|
+
"oneOf",
|
|
1481
|
+
"allOf",
|
|
1482
|
+
"enum",
|
|
1483
|
+
"const",
|
|
1484
|
+
"items",
|
|
1485
|
+
"additionalProperties",
|
|
1486
|
+
"required"
|
|
1487
|
+
];
|
|
1488
|
+
function isJsonSchema(value) {
|
|
1489
|
+
if (!isRecord(value)) return false;
|
|
1490
|
+
if (typeof value["~standard"] === "object") return false;
|
|
1491
|
+
if (isRecord(value._def) || isRecord(value._zod)) return false;
|
|
1492
|
+
if (Object.keys(value).length === 0) return true;
|
|
1493
|
+
return JSON_SCHEMA_KEYS.some((key) => key in value);
|
|
1494
|
+
}
|
|
1495
|
+
function toJsonSchema(value, options) {
|
|
1496
|
+
if (value === void 0 || value === null) return void 0;
|
|
1497
|
+
if (isJsonSchema(value)) return value;
|
|
1498
|
+
if (isRecord(value) && isJsonSchema(value.jsonSchema)) return value.jsonSchema;
|
|
1499
|
+
if (isRecord(value) && isJsonSchema(value.json)) return value.json;
|
|
1500
|
+
if (options == null ? void 0 : options.schema) {
|
|
1501
|
+
try {
|
|
1502
|
+
return options.schema(value);
|
|
1503
|
+
} catch (e) {
|
|
1504
|
+
return void 0;
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
return void 0;
|
|
1508
|
+
}
|
|
1509
|
+
function pickString(value) {
|
|
1510
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
1511
|
+
}
|
|
1512
|
+
function functionTool(name, description, schema, options) {
|
|
1513
|
+
const tool = { type: "function", name };
|
|
1514
|
+
const desc = pickString(description);
|
|
1515
|
+
if (desc !== void 0) tool.description = desc;
|
|
1516
|
+
const inputSchema = toJsonSchema(schema, options);
|
|
1517
|
+
if (inputSchema !== void 0) tool.inputSchema = inputSchema;
|
|
1518
|
+
return tool;
|
|
1519
|
+
}
|
|
1520
|
+
function normalizeToolDeclaration(tool, options, fallbackName) {
|
|
1521
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
1522
|
+
if (!isRecord(tool)) return void 0;
|
|
1523
|
+
if (tool.type === "provider-defined" || tool.type === "provider") {
|
|
1524
|
+
const name2 = (_b = (_a = pickString(tool.name)) != null ? _a : pickString(tool.id)) != null ? _b : fallbackName;
|
|
1525
|
+
if (name2 === void 0) return void 0;
|
|
1526
|
+
const declaration = { type: "provider-defined", name: name2 };
|
|
1527
|
+
const id = pickString(tool.id);
|
|
1528
|
+
if (id !== void 0) declaration.id = id;
|
|
1529
|
+
if (isRecord(tool.args)) declaration.args = tool.args;
|
|
1530
|
+
return declaration;
|
|
1531
|
+
}
|
|
1532
|
+
if (isRecord(tool.toolSpec)) {
|
|
1533
|
+
const spec = tool.toolSpec;
|
|
1534
|
+
const name2 = (_c = pickString(spec.name)) != null ? _c : fallbackName;
|
|
1535
|
+
if (name2 === void 0) return void 0;
|
|
1536
|
+
return functionTool(name2, spec.description, spec.inputSchema, options);
|
|
1537
|
+
}
|
|
1538
|
+
if (isRecord(tool.function)) {
|
|
1539
|
+
const fn = tool.function;
|
|
1540
|
+
const name2 = (_d = pickString(fn.name)) != null ? _d : fallbackName;
|
|
1541
|
+
if (name2 === void 0) return void 0;
|
|
1542
|
+
return functionTool(name2, fn.description, (_e = fn.parameters) != null ? _e : fn.input_schema, options);
|
|
1543
|
+
}
|
|
1544
|
+
const name = (_g = (_f = pickString(tool.name)) != null ? _f : pickString(tool.id)) != null ? _g : fallbackName;
|
|
1545
|
+
if (name === void 0) return void 0;
|
|
1546
|
+
const type = pickString(tool.type);
|
|
1547
|
+
if (type !== void 0 && type !== "function" && type !== "dynamic" && type !== "custom") {
|
|
1548
|
+
if (!("input_schema" in tool) && !("inputSchema" in tool) && !("parameters" in tool)) {
|
|
1549
|
+
return { type: "provider-defined", id: type, name };
|
|
1550
|
+
}
|
|
1551
|
+
}
|
|
1552
|
+
return functionTool(
|
|
1553
|
+
name,
|
|
1554
|
+
tool.description,
|
|
1555
|
+
(_j = (_i = (_h = tool.inputSchema) != null ? _h : tool.input_schema) != null ? _i : tool.parameters) != null ? _j : tool.schema,
|
|
1556
|
+
options
|
|
1557
|
+
);
|
|
1558
|
+
}
|
|
1559
|
+
var NOT_A_GEMINI_GROUP_KEYS = ["name", "id", "type", "function", "toolSpec", "cachePoint"];
|
|
1560
|
+
function isGeminiToolGroup(tool) {
|
|
1561
|
+
if (Array.isArray(tool.functionDeclarations)) return true;
|
|
1562
|
+
const keys = Object.keys(tool);
|
|
1563
|
+
if (keys.length === 0 || NOT_A_GEMINI_GROUP_KEYS.some((key) => key in tool)) return false;
|
|
1564
|
+
return keys.every((key) => isRecord(tool[key]));
|
|
1565
|
+
}
|
|
1566
|
+
function expandGeminiTool(tool, options) {
|
|
1567
|
+
const declarations = [];
|
|
1568
|
+
for (const [key, value] of Object.entries(tool)) {
|
|
1569
|
+
if (key === "functionDeclarations" && Array.isArray(value)) {
|
|
1570
|
+
for (const declaration of value) {
|
|
1571
|
+
const normalized = normalizeToolDeclaration(declaration, options);
|
|
1572
|
+
if (normalized) declarations.push(normalized);
|
|
1573
|
+
}
|
|
1574
|
+
} else if (isRecord(value)) {
|
|
1575
|
+
declarations.push({ type: "provider-defined", id: key, name: key, args: value });
|
|
1576
|
+
}
|
|
1577
|
+
}
|
|
1578
|
+
return declarations;
|
|
1579
|
+
}
|
|
1580
|
+
function normalizeToolDeclarations(tools, options) {
|
|
1581
|
+
if (tools === void 0 || tools === null) return void 0;
|
|
1582
|
+
if (Array.isArray(tools)) {
|
|
1583
|
+
return tools.flatMap((tool) => {
|
|
1584
|
+
if (isRecord(tool) && isGeminiToolGroup(tool)) {
|
|
1585
|
+
return expandGeminiTool(tool, options);
|
|
1586
|
+
}
|
|
1587
|
+
const declaration = normalizeToolDeclaration(tool, options);
|
|
1588
|
+
return declaration ? [declaration] : [];
|
|
1589
|
+
});
|
|
1590
|
+
}
|
|
1591
|
+
if (!isRecord(tools)) return void 0;
|
|
1592
|
+
return Object.entries(tools).flatMap(([key, tool]) => {
|
|
1593
|
+
const declaration = normalizeToolDeclaration(tool, options, key);
|
|
1594
|
+
return declaration ? [declaration] : [];
|
|
1595
|
+
});
|
|
1596
|
+
}
|
|
1597
|
+
function promptToolsAttributeValue(tools) {
|
|
1598
|
+
if (tools === void 0) return void 0;
|
|
1599
|
+
return tools.map((tool) => {
|
|
1600
|
+
try {
|
|
1601
|
+
return JSON.stringify(tool);
|
|
1602
|
+
} catch (e) {
|
|
1603
|
+
return JSON.stringify({ type: tool.type, name: tool.name });
|
|
1604
|
+
}
|
|
1605
|
+
});
|
|
1606
|
+
}
|
|
1607
|
+
function promptToolsFromTraceloopAttributes(attributes) {
|
|
1608
|
+
var _a;
|
|
1609
|
+
const byIndex = /* @__PURE__ */ new Map();
|
|
1610
|
+
const prefix = "llm.request.functions.";
|
|
1611
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
1612
|
+
if (!key.startsWith(prefix)) continue;
|
|
1613
|
+
const rest = key.slice(prefix.length);
|
|
1614
|
+
const dot = rest.indexOf(".");
|
|
1615
|
+
if (dot <= 0) continue;
|
|
1616
|
+
const index = Number(rest.slice(0, dot));
|
|
1617
|
+
if (!Number.isInteger(index) || index < 0) continue;
|
|
1618
|
+
const field = rest.slice(dot + 1);
|
|
1619
|
+
const entry = (_a = byIndex.get(index)) != null ? _a : {};
|
|
1620
|
+
if (field === "name" && typeof value === "string") entry.name = value;
|
|
1621
|
+
else if (field === "description" && typeof value === "string") entry.description = value;
|
|
1622
|
+
else if (field === "parameters") entry.parameters = value;
|
|
1623
|
+
byIndex.set(index, entry);
|
|
1624
|
+
}
|
|
1625
|
+
if (byIndex.size === 0) return void 0;
|
|
1626
|
+
const tools = [];
|
|
1627
|
+
for (const index of [...byIndex.keys()].sort((a, b) => a - b)) {
|
|
1628
|
+
const entry = byIndex.get(index);
|
|
1629
|
+
if (!(entry == null ? void 0 : entry.name)) continue;
|
|
1630
|
+
let parameters = entry.parameters;
|
|
1631
|
+
if (typeof parameters === "string") {
|
|
1632
|
+
try {
|
|
1633
|
+
parameters = JSON.parse(parameters);
|
|
1634
|
+
} catch (e) {
|
|
1635
|
+
parameters = void 0;
|
|
1636
|
+
}
|
|
1637
|
+
}
|
|
1638
|
+
tools.push(functionTool(entry.name, entry.description, parameters, void 0));
|
|
1639
|
+
}
|
|
1640
|
+
return tools;
|
|
1641
|
+
}
|
|
1470
1642
|
|
|
1471
1643
|
// ../core/dist/index.node.js
|
|
1472
1644
|
import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
|
|
@@ -1612,7 +1784,7 @@ installTracingSuppressionHook();
|
|
|
1612
1784
|
// package.json
|
|
1613
1785
|
var package_default = {
|
|
1614
1786
|
name: "raindrop-ai",
|
|
1615
|
-
version: "0.9.
|
|
1787
|
+
version: "0.9.1",
|
|
1616
1788
|
main: "dist/index.js",
|
|
1617
1789
|
module: "dist/index.mjs",
|
|
1618
1790
|
types: "dist/index.d.ts",
|
|
@@ -2848,6 +3020,34 @@ function enrichStart(span) {
|
|
|
2848
3020
|
}
|
|
2849
3021
|
}
|
|
2850
3022
|
}
|
|
3023
|
+
var PROMPT_TOOLS_OVERRIDE_MARKER = "raindrop.prompt_tools.override";
|
|
3024
|
+
var MODEL_SPAN_ATTRIBUTES = ["llm.request.type", "gen_ai.request.model", "ai.model.id"];
|
|
3025
|
+
function isModelSpan(attributes) {
|
|
3026
|
+
return MODEL_SPAN_ATTRIBUTES.some((key) => attributes[key] !== void 0);
|
|
3027
|
+
}
|
|
3028
|
+
function applyPromptTools(span) {
|
|
3029
|
+
var _a;
|
|
3030
|
+
const attributes = span.attributes;
|
|
3031
|
+
const marker = attributes[PROMPT_TOOLS_OVERRIDE_MARKER];
|
|
3032
|
+
if (marker !== void 0) {
|
|
3033
|
+
delete attributes[PROMPT_TOOLS_OVERRIDE_MARKER];
|
|
3034
|
+
if (!isModelSpan(attributes) || !shouldSendTraceContent()) return;
|
|
3035
|
+
let parsed;
|
|
3036
|
+
try {
|
|
3037
|
+
parsed = JSON.parse(String(marker));
|
|
3038
|
+
} catch (e) {
|
|
3039
|
+
return;
|
|
3040
|
+
}
|
|
3041
|
+
const tools = (_a = normalizeToolDeclarations(parsed)) != null ? _a : [];
|
|
3042
|
+
attributes[PROMPT_TOOLS_ATTRIBUTE] = promptToolsAttributeValue(tools);
|
|
3043
|
+
return;
|
|
3044
|
+
}
|
|
3045
|
+
if (attributes[PROMPT_TOOLS_ATTRIBUTE] !== void 0) return;
|
|
3046
|
+
if (!shouldSendTraceContent()) return;
|
|
3047
|
+
const inferred = promptToolsFromTraceloopAttributes(attributes);
|
|
3048
|
+
if (inferred === void 0) return;
|
|
3049
|
+
attributes[PROMPT_TOOLS_ATTRIBUTE] = promptToolsAttributeValue(inferred);
|
|
3050
|
+
}
|
|
2851
3051
|
function createSpanProcessor(options) {
|
|
2852
3052
|
var _a, _b;
|
|
2853
3053
|
const baseUrl = options.baseUrl || process.env.TRACELOOP_BASE_URL || "https://api.traceloop.com";
|
|
@@ -2873,6 +3073,7 @@ function createSpanProcessor(options) {
|
|
|
2873
3073
|
if (allowed !== ALL_INSTRUMENTATION_LIBRARIES && ![...INSTRUMENTATION_LIBRARIES, ...allowed != null ? allowed : []].includes((_a2 = scopeName(span)) != null ? _a2 : "")) {
|
|
2874
3074
|
return;
|
|
2875
3075
|
}
|
|
3076
|
+
applyPromptTools(span);
|
|
2876
3077
|
outgoing = transformAiSdkSpan(span);
|
|
2877
3078
|
if (outgoing !== span) copyReplayTraceDestination(span, outgoing);
|
|
2878
3079
|
} catch (e) {
|
|
@@ -3995,6 +4196,22 @@ var LiveInteraction = class {
|
|
|
3995
4196
|
if (this.toolEventsFrame) return;
|
|
3996
4197
|
this.toolEventsFrame = bindSpanAttributes(attributes, this);
|
|
3997
4198
|
}
|
|
4199
|
+
/**
|
|
4200
|
+
* Carry a `begin({ tools })` override to every span started inside this
|
|
4201
|
+
* interaction. Frames stamp strings, so the normalized catalog rides as one
|
|
4202
|
+
* JSON marker attribute; the span processor turns it into `ai.prompt.tools`
|
|
4203
|
+
* on model spans (and drops it from every other span) when the span ends.
|
|
4204
|
+
* Same lifetime as the tool-events frame: removed by `finish()`.
|
|
4205
|
+
*/
|
|
4206
|
+
bindPromptToolsOverride(tools) {
|
|
4207
|
+
var _a;
|
|
4208
|
+
if (tools === void 0 || this.promptToolsFrame) return;
|
|
4209
|
+
const declarations = (_a = normalizeToolDeclarations(tools)) != null ? _a : [];
|
|
4210
|
+
this.promptToolsFrame = bindSpanAttributes(
|
|
4211
|
+
{ [PROMPT_TOOLS_OVERRIDE_MARKER]: JSON.stringify(declarations) },
|
|
4212
|
+
this
|
|
4213
|
+
);
|
|
4214
|
+
}
|
|
3998
4215
|
subagent(options) {
|
|
3999
4216
|
return recordSubagentDispatch(this, options);
|
|
4000
4217
|
}
|
|
@@ -4122,6 +4339,8 @@ var LiveInteraction = class {
|
|
|
4122
4339
|
this.boundContext = void 0;
|
|
4123
4340
|
unbindSpanAttributes(this.toolEventsFrame);
|
|
4124
4341
|
this.toolEventsFrame = void 0;
|
|
4342
|
+
unbindSpanAttributes(this.promptToolsFrame);
|
|
4343
|
+
this.promptToolsFrame = void 0;
|
|
4125
4344
|
if (!this.traceId) {
|
|
4126
4345
|
this.resolveLiveTraceId();
|
|
4127
4346
|
}
|
|
@@ -5147,8 +5366,9 @@ var tracing = (analytics, apiUrl, writeKey, options, isDebug = false) => {
|
|
|
5147
5366
|
} catch (e) {
|
|
5148
5367
|
}
|
|
5149
5368
|
}) : void 0;
|
|
5150
|
-
const beginInteraction = (
|
|
5369
|
+
const beginInteraction = (params) => {
|
|
5151
5370
|
var _a2;
|
|
5371
|
+
const { tools, ...traceContext } = params;
|
|
5152
5372
|
if (!traceContext.eventId) {
|
|
5153
5373
|
traceContext.eventId = crypto.randomUUID();
|
|
5154
5374
|
}
|
|
@@ -5162,6 +5382,7 @@ var tracing = (analytics, apiUrl, writeKey, options, isDebug = false) => {
|
|
|
5162
5382
|
);
|
|
5163
5383
|
const bound = bindRoutingContext({ projectId, authHint, appGit: analytics.getAppGitSnapshot(traceContext.properties, traceContext.eventId) }, interaction);
|
|
5164
5384
|
interaction.setBoundContext(bound);
|
|
5385
|
+
interaction.bindPromptToolsOverride(tools);
|
|
5165
5386
|
try {
|
|
5166
5387
|
analytics._trackAiPartial({
|
|
5167
5388
|
...traceContext,
|
package/dist/evals/cli.js
CHANGED
|
@@ -6726,7 +6726,7 @@ function evalScopeAttributes() {
|
|
|
6726
6726
|
return { [EVAL_CORRELATION_ID_ATTRIBUTE]: scope.correlationId };
|
|
6727
6727
|
}
|
|
6728
6728
|
|
|
6729
|
-
// ../core/dist/chunk-
|
|
6729
|
+
// ../core/dist/chunk-I6TVJQEC.js
|
|
6730
6730
|
var STATE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.replayTraceRoutingState");
|
|
6731
6731
|
function state() {
|
|
6732
6732
|
const holder = globalThis;
|
|
@@ -8114,6 +8114,178 @@ var DEFAULT_REDACT_ATTRIBUTE_KEYS = [
|
|
|
8114
8114
|
"ai.response.providerMetadata"
|
|
8115
8115
|
];
|
|
8116
8116
|
var REDACT_JSON_ATTRIBUTE_KEYS = new Set(DEFAULT_REDACT_ATTRIBUTE_KEYS);
|
|
8117
|
+
var PROMPT_TOOLS_ATTRIBUTE = "ai.prompt.tools";
|
|
8118
|
+
function isRecord(value) {
|
|
8119
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8120
|
+
}
|
|
8121
|
+
var JSON_SCHEMA_KEYS = [
|
|
8122
|
+
"type",
|
|
8123
|
+
"properties",
|
|
8124
|
+
"$schema",
|
|
8125
|
+
"$ref",
|
|
8126
|
+
"anyOf",
|
|
8127
|
+
"oneOf",
|
|
8128
|
+
"allOf",
|
|
8129
|
+
"enum",
|
|
8130
|
+
"const",
|
|
8131
|
+
"items",
|
|
8132
|
+
"additionalProperties",
|
|
8133
|
+
"required"
|
|
8134
|
+
];
|
|
8135
|
+
function isJsonSchema(value) {
|
|
8136
|
+
if (!isRecord(value)) return false;
|
|
8137
|
+
if (typeof value["~standard"] === "object") return false;
|
|
8138
|
+
if (isRecord(value._def) || isRecord(value._zod)) return false;
|
|
8139
|
+
if (Object.keys(value).length === 0) return true;
|
|
8140
|
+
return JSON_SCHEMA_KEYS.some((key) => key in value);
|
|
8141
|
+
}
|
|
8142
|
+
function toJsonSchema(value, options) {
|
|
8143
|
+
if (value === void 0 || value === null) return void 0;
|
|
8144
|
+
if (isJsonSchema(value)) return value;
|
|
8145
|
+
if (isRecord(value) && isJsonSchema(value.jsonSchema)) return value.jsonSchema;
|
|
8146
|
+
if (isRecord(value) && isJsonSchema(value.json)) return value.json;
|
|
8147
|
+
if (options == null ? void 0 : options.schema) {
|
|
8148
|
+
try {
|
|
8149
|
+
return options.schema(value);
|
|
8150
|
+
} catch (e) {
|
|
8151
|
+
return void 0;
|
|
8152
|
+
}
|
|
8153
|
+
}
|
|
8154
|
+
return void 0;
|
|
8155
|
+
}
|
|
8156
|
+
function pickString(value) {
|
|
8157
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
8158
|
+
}
|
|
8159
|
+
function functionTool(name, description, schema, options) {
|
|
8160
|
+
const tool = { type: "function", name };
|
|
8161
|
+
const desc = pickString(description);
|
|
8162
|
+
if (desc !== void 0) tool.description = desc;
|
|
8163
|
+
const inputSchema = toJsonSchema(schema, options);
|
|
8164
|
+
if (inputSchema !== void 0) tool.inputSchema = inputSchema;
|
|
8165
|
+
return tool;
|
|
8166
|
+
}
|
|
8167
|
+
function normalizeToolDeclaration(tool, options, fallbackName) {
|
|
8168
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
8169
|
+
if (!isRecord(tool)) return void 0;
|
|
8170
|
+
if (tool.type === "provider-defined" || tool.type === "provider") {
|
|
8171
|
+
const name2 = (_b = (_a = pickString(tool.name)) != null ? _a : pickString(tool.id)) != null ? _b : fallbackName;
|
|
8172
|
+
if (name2 === void 0) return void 0;
|
|
8173
|
+
const declaration = { type: "provider-defined", name: name2 };
|
|
8174
|
+
const id = pickString(tool.id);
|
|
8175
|
+
if (id !== void 0) declaration.id = id;
|
|
8176
|
+
if (isRecord(tool.args)) declaration.args = tool.args;
|
|
8177
|
+
return declaration;
|
|
8178
|
+
}
|
|
8179
|
+
if (isRecord(tool.toolSpec)) {
|
|
8180
|
+
const spec = tool.toolSpec;
|
|
8181
|
+
const name2 = (_c = pickString(spec.name)) != null ? _c : fallbackName;
|
|
8182
|
+
if (name2 === void 0) return void 0;
|
|
8183
|
+
return functionTool(name2, spec.description, spec.inputSchema, options);
|
|
8184
|
+
}
|
|
8185
|
+
if (isRecord(tool.function)) {
|
|
8186
|
+
const fn = tool.function;
|
|
8187
|
+
const name2 = (_d = pickString(fn.name)) != null ? _d : fallbackName;
|
|
8188
|
+
if (name2 === void 0) return void 0;
|
|
8189
|
+
return functionTool(name2, fn.description, (_e = fn.parameters) != null ? _e : fn.input_schema, options);
|
|
8190
|
+
}
|
|
8191
|
+
const name = (_g = (_f = pickString(tool.name)) != null ? _f : pickString(tool.id)) != null ? _g : fallbackName;
|
|
8192
|
+
if (name === void 0) return void 0;
|
|
8193
|
+
const type = pickString(tool.type);
|
|
8194
|
+
if (type !== void 0 && type !== "function" && type !== "dynamic" && type !== "custom") {
|
|
8195
|
+
if (!("input_schema" in tool) && !("inputSchema" in tool) && !("parameters" in tool)) {
|
|
8196
|
+
return { type: "provider-defined", id: type, name };
|
|
8197
|
+
}
|
|
8198
|
+
}
|
|
8199
|
+
return functionTool(
|
|
8200
|
+
name,
|
|
8201
|
+
tool.description,
|
|
8202
|
+
(_j = (_i = (_h = tool.inputSchema) != null ? _h : tool.input_schema) != null ? _i : tool.parameters) != null ? _j : tool.schema,
|
|
8203
|
+
options
|
|
8204
|
+
);
|
|
8205
|
+
}
|
|
8206
|
+
var NOT_A_GEMINI_GROUP_KEYS = ["name", "id", "type", "function", "toolSpec", "cachePoint"];
|
|
8207
|
+
function isGeminiToolGroup(tool) {
|
|
8208
|
+
if (Array.isArray(tool.functionDeclarations)) return true;
|
|
8209
|
+
const keys = Object.keys(tool);
|
|
8210
|
+
if (keys.length === 0 || NOT_A_GEMINI_GROUP_KEYS.some((key) => key in tool)) return false;
|
|
8211
|
+
return keys.every((key) => isRecord(tool[key]));
|
|
8212
|
+
}
|
|
8213
|
+
function expandGeminiTool(tool, options) {
|
|
8214
|
+
const declarations = [];
|
|
8215
|
+
for (const [key, value] of Object.entries(tool)) {
|
|
8216
|
+
if (key === "functionDeclarations" && Array.isArray(value)) {
|
|
8217
|
+
for (const declaration of value) {
|
|
8218
|
+
const normalized = normalizeToolDeclaration(declaration, options);
|
|
8219
|
+
if (normalized) declarations.push(normalized);
|
|
8220
|
+
}
|
|
8221
|
+
} else if (isRecord(value)) {
|
|
8222
|
+
declarations.push({ type: "provider-defined", id: key, name: key, args: value });
|
|
8223
|
+
}
|
|
8224
|
+
}
|
|
8225
|
+
return declarations;
|
|
8226
|
+
}
|
|
8227
|
+
function normalizeToolDeclarations(tools, options) {
|
|
8228
|
+
if (tools === void 0 || tools === null) return void 0;
|
|
8229
|
+
if (Array.isArray(tools)) {
|
|
8230
|
+
return tools.flatMap((tool) => {
|
|
8231
|
+
if (isRecord(tool) && isGeminiToolGroup(tool)) {
|
|
8232
|
+
return expandGeminiTool(tool, options);
|
|
8233
|
+
}
|
|
8234
|
+
const declaration = normalizeToolDeclaration(tool, options);
|
|
8235
|
+
return declaration ? [declaration] : [];
|
|
8236
|
+
});
|
|
8237
|
+
}
|
|
8238
|
+
if (!isRecord(tools)) return void 0;
|
|
8239
|
+
return Object.entries(tools).flatMap(([key, tool]) => {
|
|
8240
|
+
const declaration = normalizeToolDeclaration(tool, options, key);
|
|
8241
|
+
return declaration ? [declaration] : [];
|
|
8242
|
+
});
|
|
8243
|
+
}
|
|
8244
|
+
function promptToolsAttributeValue(tools) {
|
|
8245
|
+
if (tools === void 0) return void 0;
|
|
8246
|
+
return tools.map((tool) => {
|
|
8247
|
+
try {
|
|
8248
|
+
return JSON.stringify(tool);
|
|
8249
|
+
} catch (e) {
|
|
8250
|
+
return JSON.stringify({ type: tool.type, name: tool.name });
|
|
8251
|
+
}
|
|
8252
|
+
});
|
|
8253
|
+
}
|
|
8254
|
+
function promptToolsFromTraceloopAttributes(attributes) {
|
|
8255
|
+
var _a;
|
|
8256
|
+
const byIndex = /* @__PURE__ */ new Map();
|
|
8257
|
+
const prefix = "llm.request.functions.";
|
|
8258
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
8259
|
+
if (!key.startsWith(prefix)) continue;
|
|
8260
|
+
const rest = key.slice(prefix.length);
|
|
8261
|
+
const dot = rest.indexOf(".");
|
|
8262
|
+
if (dot <= 0) continue;
|
|
8263
|
+
const index = Number(rest.slice(0, dot));
|
|
8264
|
+
if (!Number.isInteger(index) || index < 0) continue;
|
|
8265
|
+
const field = rest.slice(dot + 1);
|
|
8266
|
+
const entry = (_a = byIndex.get(index)) != null ? _a : {};
|
|
8267
|
+
if (field === "name" && typeof value === "string") entry.name = value;
|
|
8268
|
+
else if (field === "description" && typeof value === "string") entry.description = value;
|
|
8269
|
+
else if (field === "parameters") entry.parameters = value;
|
|
8270
|
+
byIndex.set(index, entry);
|
|
8271
|
+
}
|
|
8272
|
+
if (byIndex.size === 0) return void 0;
|
|
8273
|
+
const tools = [];
|
|
8274
|
+
for (const index of [...byIndex.keys()].sort((a, b) => a - b)) {
|
|
8275
|
+
const entry = byIndex.get(index);
|
|
8276
|
+
if (!(entry == null ? void 0 : entry.name)) continue;
|
|
8277
|
+
let parameters = entry.parameters;
|
|
8278
|
+
if (typeof parameters === "string") {
|
|
8279
|
+
try {
|
|
8280
|
+
parameters = JSON.parse(parameters);
|
|
8281
|
+
} catch (e) {
|
|
8282
|
+
parameters = void 0;
|
|
8283
|
+
}
|
|
8284
|
+
}
|
|
8285
|
+
tools.push(functionTool(entry.name, entry.description, parameters, void 0));
|
|
8286
|
+
}
|
|
8287
|
+
return tools;
|
|
8288
|
+
}
|
|
8117
8289
|
|
|
8118
8290
|
// ../core/dist/index.node.js
|
|
8119
8291
|
var import_async_hooks = require("async_hooks");
|
|
@@ -12373,7 +12545,7 @@ var SignalEventSchema = external_exports.object({
|
|
|
12373
12545
|
// package.json
|
|
12374
12546
|
var package_default = {
|
|
12375
12547
|
name: "raindrop-ai",
|
|
12376
|
-
version: "0.9.
|
|
12548
|
+
version: "0.9.1",
|
|
12377
12549
|
main: "dist/index.js",
|
|
12378
12550
|
module: "dist/index.mjs",
|
|
12379
12551
|
types: "dist/index.d.ts",
|
|
@@ -13682,6 +13854,34 @@ function enrichStart(span) {
|
|
|
13682
13854
|
}
|
|
13683
13855
|
}
|
|
13684
13856
|
}
|
|
13857
|
+
var PROMPT_TOOLS_OVERRIDE_MARKER = "raindrop.prompt_tools.override";
|
|
13858
|
+
var MODEL_SPAN_ATTRIBUTES = ["llm.request.type", "gen_ai.request.model", "ai.model.id"];
|
|
13859
|
+
function isModelSpan(attributes) {
|
|
13860
|
+
return MODEL_SPAN_ATTRIBUTES.some((key) => attributes[key] !== void 0);
|
|
13861
|
+
}
|
|
13862
|
+
function applyPromptTools(span) {
|
|
13863
|
+
var _a;
|
|
13864
|
+
const attributes = span.attributes;
|
|
13865
|
+
const marker = attributes[PROMPT_TOOLS_OVERRIDE_MARKER];
|
|
13866
|
+
if (marker !== void 0) {
|
|
13867
|
+
delete attributes[PROMPT_TOOLS_OVERRIDE_MARKER];
|
|
13868
|
+
if (!isModelSpan(attributes) || !shouldSendTraceContent()) return;
|
|
13869
|
+
let parsed;
|
|
13870
|
+
try {
|
|
13871
|
+
parsed = JSON.parse(String(marker));
|
|
13872
|
+
} catch (e) {
|
|
13873
|
+
return;
|
|
13874
|
+
}
|
|
13875
|
+
const tools = (_a = normalizeToolDeclarations(parsed)) != null ? _a : [];
|
|
13876
|
+
attributes[PROMPT_TOOLS_ATTRIBUTE] = promptToolsAttributeValue(tools);
|
|
13877
|
+
return;
|
|
13878
|
+
}
|
|
13879
|
+
if (attributes[PROMPT_TOOLS_ATTRIBUTE] !== void 0) return;
|
|
13880
|
+
if (!shouldSendTraceContent()) return;
|
|
13881
|
+
const inferred = promptToolsFromTraceloopAttributes(attributes);
|
|
13882
|
+
if (inferred === void 0) return;
|
|
13883
|
+
attributes[PROMPT_TOOLS_ATTRIBUTE] = promptToolsAttributeValue(inferred);
|
|
13884
|
+
}
|
|
13685
13885
|
function createSpanProcessor(options) {
|
|
13686
13886
|
var _a, _b;
|
|
13687
13887
|
const baseUrl = options.baseUrl || process.env.TRACELOOP_BASE_URL || "https://api.traceloop.com";
|
|
@@ -13707,6 +13907,7 @@ function createSpanProcessor(options) {
|
|
|
13707
13907
|
if (allowed !== ALL_INSTRUMENTATION_LIBRARIES && ![...INSTRUMENTATION_LIBRARIES, ...allowed != null ? allowed : []].includes((_a2 = scopeName(span)) != null ? _a2 : "")) {
|
|
13708
13908
|
return;
|
|
13709
13909
|
}
|
|
13910
|
+
applyPromptTools(span);
|
|
13710
13911
|
outgoing = transformAiSdkSpan(span);
|
|
13711
13912
|
if (outgoing !== span) copyReplayTraceDestination(span, outgoing);
|
|
13712
13913
|
} catch (e) {
|
|
@@ -14822,6 +15023,22 @@ var LiveInteraction = class {
|
|
|
14822
15023
|
if (this.toolEventsFrame) return;
|
|
14823
15024
|
this.toolEventsFrame = bindSpanAttributes(attributes, this);
|
|
14824
15025
|
}
|
|
15026
|
+
/**
|
|
15027
|
+
* Carry a `begin({ tools })` override to every span started inside this
|
|
15028
|
+
* interaction. Frames stamp strings, so the normalized catalog rides as one
|
|
15029
|
+
* JSON marker attribute; the span processor turns it into `ai.prompt.tools`
|
|
15030
|
+
* on model spans (and drops it from every other span) when the span ends.
|
|
15031
|
+
* Same lifetime as the tool-events frame: removed by `finish()`.
|
|
15032
|
+
*/
|
|
15033
|
+
bindPromptToolsOverride(tools) {
|
|
15034
|
+
var _a;
|
|
15035
|
+
if (tools === void 0 || this.promptToolsFrame) return;
|
|
15036
|
+
const declarations = (_a = normalizeToolDeclarations(tools)) != null ? _a : [];
|
|
15037
|
+
this.promptToolsFrame = bindSpanAttributes(
|
|
15038
|
+
{ [PROMPT_TOOLS_OVERRIDE_MARKER]: JSON.stringify(declarations) },
|
|
15039
|
+
this
|
|
15040
|
+
);
|
|
15041
|
+
}
|
|
14825
15042
|
subagent(options) {
|
|
14826
15043
|
return recordSubagentDispatch(this, options);
|
|
14827
15044
|
}
|
|
@@ -14949,6 +15166,8 @@ var LiveInteraction = class {
|
|
|
14949
15166
|
this.boundContext = void 0;
|
|
14950
15167
|
unbindSpanAttributes(this.toolEventsFrame);
|
|
14951
15168
|
this.toolEventsFrame = void 0;
|
|
15169
|
+
unbindSpanAttributes(this.promptToolsFrame);
|
|
15170
|
+
this.promptToolsFrame = void 0;
|
|
14952
15171
|
if (!this.traceId) {
|
|
14953
15172
|
this.resolveLiveTraceId();
|
|
14954
15173
|
}
|
|
@@ -15974,8 +16193,9 @@ var tracing = (analytics, apiUrl, writeKey, options, isDebug = false) => {
|
|
|
15974
16193
|
} catch (e) {
|
|
15975
16194
|
}
|
|
15976
16195
|
}) : void 0;
|
|
15977
|
-
const beginInteraction = (
|
|
16196
|
+
const beginInteraction = (params) => {
|
|
15978
16197
|
var _a2;
|
|
16198
|
+
const { tools, ...traceContext } = params;
|
|
15979
16199
|
if (!traceContext.eventId) {
|
|
15980
16200
|
traceContext.eventId = crypto.randomUUID();
|
|
15981
16201
|
}
|
|
@@ -15989,6 +16209,7 @@ var tracing = (analytics, apiUrl, writeKey, options, isDebug = false) => {
|
|
|
15989
16209
|
);
|
|
15990
16210
|
const bound = bindRoutingContext({ projectId, authHint, appGit: analytics.getAppGitSnapshot(traceContext.properties, traceContext.eventId) }, interaction);
|
|
15991
16211
|
interaction.setBoundContext(bound);
|
|
16212
|
+
interaction.bindPromptToolsOverride(tools);
|
|
15992
16213
|
try {
|
|
15993
16214
|
analytics._trackAiPartial({
|
|
15994
16215
|
...traceContext,
|
|
@@ -19149,7 +19370,7 @@ var SELF_DIAGNOSTICS_SIGNALS_DEFAULT = {
|
|
|
19149
19370
|
sentiment: "NEGATIVE"
|
|
19150
19371
|
}
|
|
19151
19372
|
};
|
|
19152
|
-
function
|
|
19373
|
+
function isRecord2(value) {
|
|
19153
19374
|
return typeof value === "object" && value !== null;
|
|
19154
19375
|
}
|
|
19155
19376
|
function normalizeSelfDiagnosticsSignals(signals) {
|
|
@@ -19586,7 +19807,7 @@ var Raindrop = class {
|
|
|
19586
19807
|
const onMissingEventId = (_b = options.onMissingEventId) != null ? _b : "warn";
|
|
19587
19808
|
const execute = async (rawInput, context8) => {
|
|
19588
19809
|
var _a2, _b2, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
|
|
19589
|
-
const input =
|
|
19810
|
+
const input = isRecord2(rawInput) ? rawInput : void 0;
|
|
19590
19811
|
const fallbackCategory = (_a2 = signalKeys[0]) != null ? _a2 : "unknown";
|
|
19591
19812
|
const categoryCandidate = normalizeEventId(input == null ? void 0 : input["category"]);
|
|
19592
19813
|
const category = categoryCandidate && signalKeySet.has(categoryCandidate) ? categoryCandidate : fallbackCategory;
|
package/dist/evals/cli.mjs
CHANGED
|
@@ -5,8 +5,8 @@ import {
|
|
|
5
5
|
publishEvalSuite,
|
|
6
6
|
readEvaluator,
|
|
7
7
|
runEvalSuite
|
|
8
|
-
} from "../chunk-
|
|
9
|
-
import "../chunk-
|
|
8
|
+
} from "../chunk-SUW3YBV3.mjs";
|
|
9
|
+
import "../chunk-WLBBPTI6.mjs";
|
|
10
10
|
import {
|
|
11
11
|
isEvalSuiteDefinition
|
|
12
12
|
} from "../chunk-UY6537WW.mjs";
|