@raindrop-ai/openai-managed-agents 0.0.2 → 0.0.4

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 CHANGED
@@ -120,6 +120,27 @@ responsibility.
120
120
  `users.identify`, and `signals.track` expose the shared core enrichment API.
121
121
  `flush()` ships current buffers; `shutdown()` also closes unfinished captures.
122
122
 
123
+ ## Tool catalog capture (`ai.prompt.tools`)
124
+
125
+ **Agent configuration, not exact per-call capture.** Model calls run inside
126
+ OpenAI's managed runtime, so the wrapper never sees individual requests. It
127
+ does see the resolved agent definition on the session (`session.agent.tools`)
128
+ and records it as `ai.prompt.tools` on every coordinator `openai.agent.turn`
129
+ span (one per model turn), together with
130
+ `ai.prompt.tools.source = "agent.config"` so consumers can tell this
131
+ configuration snapshot from exact capture. Function tools keep their JSON
132
+ Schema `parameters`; `mcp`, `web_search`, `tool_search` and
133
+ `programmatic_tool_calling` entries are provider-owned and recorded as
134
+ `{"type":"provider-defined",…}` without an invented schema. Subagent turns run
135
+ their own tool sets, so they only receive an explicit override. Absent
136
+ attribute = catalog unknown; `[]` = the agent has no tools. This package has no
137
+ separate prompt-content switch, so the attribute is recorded whenever tracing
138
+ is enabled.
139
+
140
+ | Option | Description |
141
+ | --- | --- |
142
+ | `tools` (on `createRaindropOpenAIManagedAgents({ tools })` or `wrap(client, { tools })`) | Overrides the tool catalog recorded as `ai.prompt.tools` on every model span. Use when the integration cannot see the tools the model was given. Replaces the agent definition entirely (`tools: []` records an empty catalog) and carries no `source` attribute. |
143
+
123
144
  ## Limits
124
145
 
125
146
  The service does not expose individual inference requests. Captures represent
package/dist/index.d.mts CHANGED
@@ -506,9 +506,42 @@ declare global {
506
506
  var RAINDROP_CONTEXT_MANAGER: (new () => ContextManager) | undefined;
507
507
  var RAINDROP_ASYNC_LOCAL_STORAGE: (new <T>() => AsyncLocalStorageLike<T>) | undefined;
508
508
  }
509
+ type JsonSchema = Record<string, unknown>;
510
+ type FunctionToolDeclaration = {
511
+ type: "function";
512
+ name: string;
513
+ description?: string;
514
+ inputSchema?: JsonSchema;
515
+ };
516
+ type ProviderDefinedToolDeclaration = {
517
+ type: "provider-defined";
518
+ id?: string;
519
+ name: string;
520
+ args?: Record<string, unknown>;
521
+ };
522
+ type ToolDeclaration = FunctionToolDeclaration | ProviderDefinedToolDeclaration;
523
+ /**
524
+ * What callers hand to a `tools` override. The canonical `ToolDeclaration`
525
+ * shape is accepted as-is; so is any framework shape `normalizeToolDeclarations`
526
+ * recognizes (OpenAI, Anthropic, Bedrock, LangChain, Pi, Mastra, AI SDK).
527
+ */
528
+ type ToolDeclarationInput = ToolDeclaration | {
529
+ name: string;
530
+ description?: string;
531
+ inputSchema?: JsonSchema;
532
+ parameters?: JsonSchema;
533
+ };
534
+ type PromptToolsOverride = ReadonlyArray<ToolDeclarationInput | unknown>;
509
535
 
510
536
  type SessionContext = {
511
537
  [Key in keyof Pick<Patch, "userId" | "convoId" | "eventName" | "properties">]?: Patch[Key] | undefined;
538
+ } & {
539
+ /**
540
+ * Overrides the tool catalog recorded as `ai.prompt.tools` on every model
541
+ * span. Use when the integration cannot see the tools the model was given.
542
+ * Without it the agent definition on the session (`session.agent.tools`) is used.
543
+ */
544
+ tools?: PromptToolsOverride | undefined;
512
545
  };
513
546
  type OpenAIManagedAgentsOptions = SessionContext & {
514
547
  writeKey?: string | undefined;
@@ -569,4 +602,5 @@ type RaindropOpenAIManagedAgentsClient = {
569
602
  };
570
603
  declare function createRaindropOpenAIManagedAgents(opts?: OpenAIManagedAgentsOptions): RaindropOpenAIManagedAgentsClient;
571
604
 
572
- export { type OpenAIManagedAgentsOptions, RaindropManagedAgentsHandler, type RaindropOpenAIManagedAgentsClient, type SessionContext, createRaindropOpenAIManagedAgents };
605
+ export { RaindropManagedAgentsHandler, createRaindropOpenAIManagedAgents };
606
+ export type { OpenAIManagedAgentsOptions, RaindropOpenAIManagedAgentsClient, SessionContext };
package/dist/index.d.ts CHANGED
@@ -506,9 +506,42 @@ declare global {
506
506
  var RAINDROP_CONTEXT_MANAGER: (new () => ContextManager) | undefined;
507
507
  var RAINDROP_ASYNC_LOCAL_STORAGE: (new <T>() => AsyncLocalStorageLike<T>) | undefined;
508
508
  }
509
+ type JsonSchema = Record<string, unknown>;
510
+ type FunctionToolDeclaration = {
511
+ type: "function";
512
+ name: string;
513
+ description?: string;
514
+ inputSchema?: JsonSchema;
515
+ };
516
+ type ProviderDefinedToolDeclaration = {
517
+ type: "provider-defined";
518
+ id?: string;
519
+ name: string;
520
+ args?: Record<string, unknown>;
521
+ };
522
+ type ToolDeclaration = FunctionToolDeclaration | ProviderDefinedToolDeclaration;
523
+ /**
524
+ * What callers hand to a `tools` override. The canonical `ToolDeclaration`
525
+ * shape is accepted as-is; so is any framework shape `normalizeToolDeclarations`
526
+ * recognizes (OpenAI, Anthropic, Bedrock, LangChain, Pi, Mastra, AI SDK).
527
+ */
528
+ type ToolDeclarationInput = ToolDeclaration | {
529
+ name: string;
530
+ description?: string;
531
+ inputSchema?: JsonSchema;
532
+ parameters?: JsonSchema;
533
+ };
534
+ type PromptToolsOverride = ReadonlyArray<ToolDeclarationInput | unknown>;
509
535
 
510
536
  type SessionContext = {
511
537
  [Key in keyof Pick<Patch, "userId" | "convoId" | "eventName" | "properties">]?: Patch[Key] | undefined;
538
+ } & {
539
+ /**
540
+ * Overrides the tool catalog recorded as `ai.prompt.tools` on every model
541
+ * span. Use when the integration cannot see the tools the model was given.
542
+ * Without it the agent definition on the session (`session.agent.tools`) is used.
543
+ */
544
+ tools?: PromptToolsOverride | undefined;
512
545
  };
513
546
  type OpenAIManagedAgentsOptions = SessionContext & {
514
547
  writeKey?: string | undefined;
@@ -569,4 +602,5 @@ type RaindropOpenAIManagedAgentsClient = {
569
602
  };
570
603
  declare function createRaindropOpenAIManagedAgents(opts?: OpenAIManagedAgentsOptions): RaindropOpenAIManagedAgentsClient;
571
604
 
572
- export { type OpenAIManagedAgentsOptions, RaindropManagedAgentsHandler, type RaindropOpenAIManagedAgentsClient, type SessionContext, createRaindropOpenAIManagedAgents };
605
+ export { RaindropManagedAgentsHandler, createRaindropOpenAIManagedAgents };
606
+ export type { OpenAIManagedAgentsOptions, RaindropOpenAIManagedAgentsClient, SessionContext };
package/dist/index.js CHANGED
@@ -87,7 +87,7 @@ function evalScopeAttributes() {
87
87
  return { [EVAL_CORRELATION_ID_ATTRIBUTE]: scope.correlationId };
88
88
  }
89
89
 
90
- // ../core/dist/chunk-WJOR6M7H.js
90
+ // ../core/dist/chunk-QH6U6QYP.js
91
91
  var STATE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.replayTraceRoutingState");
92
92
  function state() {
93
93
  const holder = globalThis;
@@ -1648,12 +1648,41 @@ var REDACTED_PLACEHOLDER = "[REDACTED]";
1648
1648
  function normalizeKeyName(name) {
1649
1649
  return name.toLowerCase().replace(/[-_.]/g, "");
1650
1650
  }
1651
+ var URL_USERINFO = new RegExp(
1652
+ String.raw`\b([a-z][a-z0-9+.-]{0,${DEFAULT_MAX_TEXT_FIELD_CHARS - 1}})(?::\/\/([^\s/?#]{1,${DEFAULT_MAX_TEXT_FIELD_CHARS}})@)?`,
1653
+ "gi"
1654
+ );
1655
+ var URL_QUERY_PARAM = /([?&#]([A-Za-z0-9_.\-]+)=)[^&#?\s"']*/g;
1656
+ var URL_SECRET_QUERY_KEYS = /* @__PURE__ */ new Set([
1657
+ "token",
1658
+ "secret",
1659
+ "sig",
1660
+ "signature",
1661
+ "awsaccesskeyid",
1662
+ "xamzsignature",
1663
+ "xamzcredential",
1664
+ "xamzsecuritytoken",
1665
+ "xgoogsignature"
1666
+ ]);
1667
+ var DEFAULT_SECRET_SET = buildSecretSet(DEFAULT_SECRET_KEY_NAMES);
1668
+ function redactUrlSecrets(text, secretSet = DEFAULT_SECRET_SET, placeholder = REDACTED_PLACEHOLDER) {
1669
+ if (text.length > DEFAULT_MAX_TEXT_FIELD_CHARS) return placeholder;
1670
+ if (!text.includes("://") && !text.includes("=")) return text;
1671
+ return text.replace(
1672
+ URL_USERINFO,
1673
+ (whole, scheme, userinfo) => userinfo === void 0 ? whole : `${scheme}://${placeholder}@`
1674
+ ).replace(URL_QUERY_PARAM, (whole, prefix, key) => {
1675
+ const normalized = normalizeKeyName(key);
1676
+ return secretSet.has(normalized) || URL_SECRET_QUERY_KEYS.has(normalized) ? `${prefix}${placeholder}` : whole;
1677
+ });
1678
+ }
1651
1679
  function redactSecretsInObject(value, options) {
1652
1680
  var _a, _b;
1653
1681
  const normalizedSecretSet = buildSecretSet((_a = options == null ? void 0 : options.secretKeyNames) != null ? _a : DEFAULT_SECRET_KEY_NAMES);
1654
1682
  const placeholder = (_b = options == null ? void 0 : options.placeholder) != null ? _b : REDACTED_PLACEHOLDER;
1655
1683
  const seen = /* @__PURE__ */ new WeakSet();
1656
1684
  const walk = (node) => {
1685
+ if (typeof node === "string") return redactUrlSecrets(node, normalizedSecretSet, placeholder);
1657
1686
  if (node === null || typeof node !== "object") return node;
1658
1687
  if (seen.has(node)) return "[CIRCULAR]";
1659
1688
  seen.add(node);
@@ -2169,6 +2198,158 @@ var TraceShipper = class {
2169
2198
  }
2170
2199
  }
2171
2200
  };
2201
+ var PROMPT_TOOLS_ATTRIBUTE = "ai.prompt.tools";
2202
+ function isRecord(value) {
2203
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2204
+ }
2205
+ var JSON_SCHEMA_KEYS = [
2206
+ "type",
2207
+ "properties",
2208
+ "$schema",
2209
+ "$ref",
2210
+ "anyOf",
2211
+ "oneOf",
2212
+ "allOf",
2213
+ "enum",
2214
+ "const",
2215
+ "items",
2216
+ "additionalProperties",
2217
+ "required"
2218
+ ];
2219
+ function isJsonSchema(value) {
2220
+ if (!isRecord(value)) return false;
2221
+ if (typeof value["~standard"] === "object") return false;
2222
+ if (isRecord(value._def) || isRecord(value._zod)) return false;
2223
+ if (Object.keys(value).length === 0) return true;
2224
+ return JSON_SCHEMA_KEYS.some((key) => key in value);
2225
+ }
2226
+ function toJsonSchema(value, options) {
2227
+ if (value === void 0 || value === null) return void 0;
2228
+ if (isJsonSchema(value)) return value;
2229
+ if (isRecord(value) && isJsonSchema(value.jsonSchema)) return value.jsonSchema;
2230
+ if (isRecord(value) && isJsonSchema(value.json)) return value.json;
2231
+ if (options == null ? void 0 : options.schema) {
2232
+ try {
2233
+ return options.schema(value);
2234
+ } catch (e) {
2235
+ return void 0;
2236
+ }
2237
+ }
2238
+ return void 0;
2239
+ }
2240
+ function pickString(value) {
2241
+ return typeof value === "string" && value.length > 0 ? value : void 0;
2242
+ }
2243
+ function functionTool(name, description, schema, options) {
2244
+ const tool = { type: "function", name };
2245
+ const desc = pickString(description);
2246
+ if (desc !== void 0) tool.description = desc;
2247
+ const inputSchema = toJsonSchema(schema, options);
2248
+ if (inputSchema !== void 0) tool.inputSchema = inputSchema;
2249
+ return tool;
2250
+ }
2251
+ function normalizeToolDeclaration(tool, options, fallbackName) {
2252
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
2253
+ if (!isRecord(tool)) return void 0;
2254
+ if (tool.type === "provider-defined" || tool.type === "provider") {
2255
+ const name2 = (_b = (_a = pickString(tool.name)) != null ? _a : pickString(tool.id)) != null ? _b : fallbackName;
2256
+ if (name2 === void 0) return void 0;
2257
+ const declaration = { type: "provider-defined", name: name2 };
2258
+ const id = pickString(tool.id);
2259
+ if (id !== void 0) declaration.id = id;
2260
+ if (isRecord(tool.args)) declaration.args = tool.args;
2261
+ return declaration;
2262
+ }
2263
+ if (isRecord(tool.toolSpec)) {
2264
+ const spec = tool.toolSpec;
2265
+ const name2 = (_c = pickString(spec.name)) != null ? _c : fallbackName;
2266
+ if (name2 === void 0) return void 0;
2267
+ return functionTool(name2, spec.description, spec.inputSchema, options);
2268
+ }
2269
+ if (isRecord(tool.function)) {
2270
+ const fn = tool.function;
2271
+ const name2 = (_d = pickString(fn.name)) != null ? _d : fallbackName;
2272
+ if (name2 === void 0) return void 0;
2273
+ return functionTool(name2, fn.description, (_e = fn.parameters) != null ? _e : fn.input_schema, options);
2274
+ }
2275
+ const name = (_g = (_f = pickString(tool.name)) != null ? _f : pickString(tool.id)) != null ? _g : fallbackName;
2276
+ if (name === void 0) return void 0;
2277
+ const type = pickString(tool.type);
2278
+ if (type !== void 0 && type !== "function" && type !== "dynamic" && type !== "custom") {
2279
+ if (!("input_schema" in tool) && !("inputSchema" in tool) && !("parameters" in tool)) {
2280
+ return { type: "provider-defined", id: type, name };
2281
+ }
2282
+ }
2283
+ return functionTool(
2284
+ name,
2285
+ tool.description,
2286
+ (_j = (_i = (_h = tool.inputSchema) != null ? _h : tool.input_schema) != null ? _i : tool.parameters) != null ? _j : tool.schema,
2287
+ options
2288
+ );
2289
+ }
2290
+ var NOT_A_GEMINI_GROUP_KEYS = ["name", "id", "type", "function", "toolSpec", "cachePoint"];
2291
+ function isGeminiToolGroup(tool) {
2292
+ if (Array.isArray(tool.functionDeclarations)) return true;
2293
+ const keys = Object.keys(tool);
2294
+ if (keys.length === 0 || NOT_A_GEMINI_GROUP_KEYS.some((key) => key in tool)) return false;
2295
+ return keys.every((key) => isRecord(tool[key]));
2296
+ }
2297
+ function expandGeminiTool(tool, options) {
2298
+ const declarations = [];
2299
+ for (const [key, value] of Object.entries(tool)) {
2300
+ if (key === "functionDeclarations" && Array.isArray(value)) {
2301
+ for (const declaration of value) {
2302
+ const normalized = normalizeToolDeclaration(declaration, options);
2303
+ if (normalized) declarations.push(normalized);
2304
+ }
2305
+ } else if (isRecord(value)) {
2306
+ declarations.push({ type: "provider-defined", id: key, name: key, args: value });
2307
+ }
2308
+ }
2309
+ return declarations;
2310
+ }
2311
+ function normalizeToolDeclarations(tools, options) {
2312
+ if (tools === void 0 || tools === null) return void 0;
2313
+ if (Array.isArray(tools)) {
2314
+ return tools.flatMap((tool) => {
2315
+ if (isRecord(tool) && isGeminiToolGroup(tool)) {
2316
+ return expandGeminiTool(tool, options);
2317
+ }
2318
+ const declaration = normalizeToolDeclaration(tool, options);
2319
+ return declaration ? [declaration] : [];
2320
+ });
2321
+ }
2322
+ if (!isRecord(tools)) return void 0;
2323
+ return Object.entries(tools).flatMap(([key, tool]) => {
2324
+ const declaration = normalizeToolDeclaration(tool, options, key);
2325
+ return declaration ? [declaration] : [];
2326
+ });
2327
+ }
2328
+ function resolvePromptTools(args) {
2329
+ var _a;
2330
+ if (args.override !== void 0) {
2331
+ return (_a = normalizeToolDeclarations(args.override, args.options)) != null ? _a : [];
2332
+ }
2333
+ return normalizeToolDeclarations(args.inferred, args.options);
2334
+ }
2335
+ function promptToolsAttribute(tools) {
2336
+ const values = promptToolsAttributeValue(tools);
2337
+ if (values === void 0) return void 0;
2338
+ return {
2339
+ key: PROMPT_TOOLS_ATTRIBUTE,
2340
+ value: { arrayValue: { values: values.map((stringValue) => ({ stringValue })) } }
2341
+ };
2342
+ }
2343
+ function promptToolsAttributeValue(tools) {
2344
+ if (tools === void 0) return void 0;
2345
+ return tools.map((tool) => {
2346
+ try {
2347
+ return JSON.stringify(tool);
2348
+ } catch (e) {
2349
+ return JSON.stringify({ type: tool.type, name: tool.name });
2350
+ }
2351
+ });
2352
+ }
2172
2353
 
2173
2354
  // ../core/dist/index.node.js
2174
2355
  var import_async_hooks = require("async_hooks");
@@ -2345,6 +2526,21 @@ function installTracingSuppressionHook() {
2345
2526
  installTracingSuppressionHook();
2346
2527
 
2347
2528
  // src/handler.ts
2529
+ var AGENT_CONFIG_SOURCE = {
2530
+ key: "ai.prompt.tools.source",
2531
+ value: { stringValue: "agent.config" }
2532
+ };
2533
+ function agentConfigTools(tools) {
2534
+ if (!Array.isArray(tools)) return void 0;
2535
+ return tools.map((tool) => {
2536
+ if (!isRecord2(tool)) return tool;
2537
+ const record = tool;
2538
+ if (typeof record.name === "string" || typeof record.type !== "string") return tool;
2539
+ const { type, ...args } = record;
2540
+ const name = typeof record.server_label === "string" ? record.server_label : type;
2541
+ return { type: "provider-defined", id: type, name, args };
2542
+ });
2543
+ }
2348
2544
  var RaindropManagedAgentsHandler = class {
2349
2545
  constructor(events, traces, opts) {
2350
2546
  this.events = events;
@@ -2398,6 +2594,12 @@ var RaindropManagedAgentsHandler = class {
2398
2594
  ...context.properties
2399
2595
  }
2400
2596
  };
2597
+ const override = capture.context.tools;
2598
+ const toolsAttr = promptToolsAttribute(
2599
+ resolvePromptTools({ override, inferred: agentConfigTools(session.agent.tools) })
2600
+ );
2601
+ capture.promptToolsOverridden = override !== void 0;
2602
+ capture.promptTools = !toolsAttr ? void 0 : override !== void 0 ? [toolsAttr] : [toolsAttr, AGENT_CONFIG_SOURCE];
2401
2603
  this.cacheSession(session.id, capture);
2402
2604
  } catch (e) {
2403
2605
  }
@@ -2479,8 +2681,8 @@ var RaindropManagedAgentsHandler = class {
2479
2681
  attrInt("openai.turn.started_at", (_a = turn.started_at) != null ? _a : void 0),
2480
2682
  attrInt("openai.turn.completed_at", (_b = turn.completed_at) != null ? _b : void 0)
2481
2683
  ]);
2684
+ const session = this.sessions.get(turn.session_id);
2482
2685
  if (turn.subagent_id === null) {
2483
- const session = this.sessions.get(turn.session_id);
2484
2686
  capture.patch.model = session == null ? void 0 : session.model;
2485
2687
  if (!capture.inputFromItem) capture.patch.input = session == null ? void 0 : session.input;
2486
2688
  this.setAttributes(capture.root, [
@@ -2489,6 +2691,9 @@ var RaindropManagedAgentsHandler = class {
2489
2691
  attrString("gen_ai.response.model", session == null ? void 0 : session.model)
2490
2692
  ]);
2491
2693
  }
2694
+ if ((session == null ? void 0 : session.promptTools) && (turn.subagent_id === null || session.promptToolsOverridden)) {
2695
+ this.setAttributes(capture.root, session.promptTools);
2696
+ }
2492
2697
  if (turn.subagent_id)
2493
2698
  capture.patch.properties = {
2494
2699
  ...capture.patch.properties,
@@ -2743,11 +2948,14 @@ var RaindropManagedAgentsHandler = class {
2743
2948
  this.completed.clear();
2744
2949
  }
2745
2950
  };
2951
+ function isRecord2(value) {
2952
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2953
+ }
2746
2954
 
2747
2955
  // package.json
2748
2956
  var package_default = {
2749
2957
  name: "@raindrop-ai/openai-managed-agents",
2750
- version: "0.0.2",
2958
+ version: "0.0.4",
2751
2959
  description: "Raindrop tracing for the OpenAI Agents API",
2752
2960
  main: "dist/index.js",
2753
2961
  module: "dist/index.mjs",
@@ -2789,11 +2997,11 @@ var package_default = {
2789
2997
  "@raindrop-ai/core": "workspace:*",
2790
2998
  "@types/node": "^20.11.17",
2791
2999
  msw: "^2.12.7",
2792
- tsup: "^8.4.0",
3000
+ tsup: "^9.0.0",
2793
3001
  typescript: "^5.3.3",
2794
- vitest: "^2.1.9",
3002
+ vitest: "^4.1.12",
2795
3003
  openai: "7.15.0",
2796
- zod: "^3.23.8"
3004
+ zod: "^4.6.6"
2797
3005
  },
2798
3006
  tsup: {
2799
3007
  entry: [
package/dist/index.mjs CHANGED
@@ -60,7 +60,7 @@ function evalScopeAttributes() {
60
60
  return { [EVAL_CORRELATION_ID_ATTRIBUTE]: scope.correlationId };
61
61
  }
62
62
 
63
- // ../core/dist/chunk-WJOR6M7H.js
63
+ // ../core/dist/chunk-QH6U6QYP.js
64
64
  var STATE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.replayTraceRoutingState");
65
65
  function state() {
66
66
  const holder = globalThis;
@@ -1621,12 +1621,41 @@ var REDACTED_PLACEHOLDER = "[REDACTED]";
1621
1621
  function normalizeKeyName(name) {
1622
1622
  return name.toLowerCase().replace(/[-_.]/g, "");
1623
1623
  }
1624
+ var URL_USERINFO = new RegExp(
1625
+ String.raw`\b([a-z][a-z0-9+.-]{0,${DEFAULT_MAX_TEXT_FIELD_CHARS - 1}})(?::\/\/([^\s/?#]{1,${DEFAULT_MAX_TEXT_FIELD_CHARS}})@)?`,
1626
+ "gi"
1627
+ );
1628
+ var URL_QUERY_PARAM = /([?&#]([A-Za-z0-9_.\-]+)=)[^&#?\s"']*/g;
1629
+ var URL_SECRET_QUERY_KEYS = /* @__PURE__ */ new Set([
1630
+ "token",
1631
+ "secret",
1632
+ "sig",
1633
+ "signature",
1634
+ "awsaccesskeyid",
1635
+ "xamzsignature",
1636
+ "xamzcredential",
1637
+ "xamzsecuritytoken",
1638
+ "xgoogsignature"
1639
+ ]);
1640
+ var DEFAULT_SECRET_SET = buildSecretSet(DEFAULT_SECRET_KEY_NAMES);
1641
+ function redactUrlSecrets(text, secretSet = DEFAULT_SECRET_SET, placeholder = REDACTED_PLACEHOLDER) {
1642
+ if (text.length > DEFAULT_MAX_TEXT_FIELD_CHARS) return placeholder;
1643
+ if (!text.includes("://") && !text.includes("=")) return text;
1644
+ return text.replace(
1645
+ URL_USERINFO,
1646
+ (whole, scheme, userinfo) => userinfo === void 0 ? whole : `${scheme}://${placeholder}@`
1647
+ ).replace(URL_QUERY_PARAM, (whole, prefix, key) => {
1648
+ const normalized = normalizeKeyName(key);
1649
+ return secretSet.has(normalized) || URL_SECRET_QUERY_KEYS.has(normalized) ? `${prefix}${placeholder}` : whole;
1650
+ });
1651
+ }
1624
1652
  function redactSecretsInObject(value, options) {
1625
1653
  var _a, _b;
1626
1654
  const normalizedSecretSet = buildSecretSet((_a = options == null ? void 0 : options.secretKeyNames) != null ? _a : DEFAULT_SECRET_KEY_NAMES);
1627
1655
  const placeholder = (_b = options == null ? void 0 : options.placeholder) != null ? _b : REDACTED_PLACEHOLDER;
1628
1656
  const seen = /* @__PURE__ */ new WeakSet();
1629
1657
  const walk = (node) => {
1658
+ if (typeof node === "string") return redactUrlSecrets(node, normalizedSecretSet, placeholder);
1630
1659
  if (node === null || typeof node !== "object") return node;
1631
1660
  if (seen.has(node)) return "[CIRCULAR]";
1632
1661
  seen.add(node);
@@ -2142,6 +2171,158 @@ var TraceShipper = class {
2142
2171
  }
2143
2172
  }
2144
2173
  };
2174
+ var PROMPT_TOOLS_ATTRIBUTE = "ai.prompt.tools";
2175
+ function isRecord(value) {
2176
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2177
+ }
2178
+ var JSON_SCHEMA_KEYS = [
2179
+ "type",
2180
+ "properties",
2181
+ "$schema",
2182
+ "$ref",
2183
+ "anyOf",
2184
+ "oneOf",
2185
+ "allOf",
2186
+ "enum",
2187
+ "const",
2188
+ "items",
2189
+ "additionalProperties",
2190
+ "required"
2191
+ ];
2192
+ function isJsonSchema(value) {
2193
+ if (!isRecord(value)) return false;
2194
+ if (typeof value["~standard"] === "object") return false;
2195
+ if (isRecord(value._def) || isRecord(value._zod)) return false;
2196
+ if (Object.keys(value).length === 0) return true;
2197
+ return JSON_SCHEMA_KEYS.some((key) => key in value);
2198
+ }
2199
+ function toJsonSchema(value, options) {
2200
+ if (value === void 0 || value === null) return void 0;
2201
+ if (isJsonSchema(value)) return value;
2202
+ if (isRecord(value) && isJsonSchema(value.jsonSchema)) return value.jsonSchema;
2203
+ if (isRecord(value) && isJsonSchema(value.json)) return value.json;
2204
+ if (options == null ? void 0 : options.schema) {
2205
+ try {
2206
+ return options.schema(value);
2207
+ } catch (e) {
2208
+ return void 0;
2209
+ }
2210
+ }
2211
+ return void 0;
2212
+ }
2213
+ function pickString(value) {
2214
+ return typeof value === "string" && value.length > 0 ? value : void 0;
2215
+ }
2216
+ function functionTool(name, description, schema, options) {
2217
+ const tool = { type: "function", name };
2218
+ const desc = pickString(description);
2219
+ if (desc !== void 0) tool.description = desc;
2220
+ const inputSchema = toJsonSchema(schema, options);
2221
+ if (inputSchema !== void 0) tool.inputSchema = inputSchema;
2222
+ return tool;
2223
+ }
2224
+ function normalizeToolDeclaration(tool, options, fallbackName) {
2225
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
2226
+ if (!isRecord(tool)) return void 0;
2227
+ if (tool.type === "provider-defined" || tool.type === "provider") {
2228
+ const name2 = (_b = (_a = pickString(tool.name)) != null ? _a : pickString(tool.id)) != null ? _b : fallbackName;
2229
+ if (name2 === void 0) return void 0;
2230
+ const declaration = { type: "provider-defined", name: name2 };
2231
+ const id = pickString(tool.id);
2232
+ if (id !== void 0) declaration.id = id;
2233
+ if (isRecord(tool.args)) declaration.args = tool.args;
2234
+ return declaration;
2235
+ }
2236
+ if (isRecord(tool.toolSpec)) {
2237
+ const spec = tool.toolSpec;
2238
+ const name2 = (_c = pickString(spec.name)) != null ? _c : fallbackName;
2239
+ if (name2 === void 0) return void 0;
2240
+ return functionTool(name2, spec.description, spec.inputSchema, options);
2241
+ }
2242
+ if (isRecord(tool.function)) {
2243
+ const fn = tool.function;
2244
+ const name2 = (_d = pickString(fn.name)) != null ? _d : fallbackName;
2245
+ if (name2 === void 0) return void 0;
2246
+ return functionTool(name2, fn.description, (_e = fn.parameters) != null ? _e : fn.input_schema, options);
2247
+ }
2248
+ const name = (_g = (_f = pickString(tool.name)) != null ? _f : pickString(tool.id)) != null ? _g : fallbackName;
2249
+ if (name === void 0) return void 0;
2250
+ const type = pickString(tool.type);
2251
+ if (type !== void 0 && type !== "function" && type !== "dynamic" && type !== "custom") {
2252
+ if (!("input_schema" in tool) && !("inputSchema" in tool) && !("parameters" in tool)) {
2253
+ return { type: "provider-defined", id: type, name };
2254
+ }
2255
+ }
2256
+ return functionTool(
2257
+ name,
2258
+ tool.description,
2259
+ (_j = (_i = (_h = tool.inputSchema) != null ? _h : tool.input_schema) != null ? _i : tool.parameters) != null ? _j : tool.schema,
2260
+ options
2261
+ );
2262
+ }
2263
+ var NOT_A_GEMINI_GROUP_KEYS = ["name", "id", "type", "function", "toolSpec", "cachePoint"];
2264
+ function isGeminiToolGroup(tool) {
2265
+ if (Array.isArray(tool.functionDeclarations)) return true;
2266
+ const keys = Object.keys(tool);
2267
+ if (keys.length === 0 || NOT_A_GEMINI_GROUP_KEYS.some((key) => key in tool)) return false;
2268
+ return keys.every((key) => isRecord(tool[key]));
2269
+ }
2270
+ function expandGeminiTool(tool, options) {
2271
+ const declarations = [];
2272
+ for (const [key, value] of Object.entries(tool)) {
2273
+ if (key === "functionDeclarations" && Array.isArray(value)) {
2274
+ for (const declaration of value) {
2275
+ const normalized = normalizeToolDeclaration(declaration, options);
2276
+ if (normalized) declarations.push(normalized);
2277
+ }
2278
+ } else if (isRecord(value)) {
2279
+ declarations.push({ type: "provider-defined", id: key, name: key, args: value });
2280
+ }
2281
+ }
2282
+ return declarations;
2283
+ }
2284
+ function normalizeToolDeclarations(tools, options) {
2285
+ if (tools === void 0 || tools === null) return void 0;
2286
+ if (Array.isArray(tools)) {
2287
+ return tools.flatMap((tool) => {
2288
+ if (isRecord(tool) && isGeminiToolGroup(tool)) {
2289
+ return expandGeminiTool(tool, options);
2290
+ }
2291
+ const declaration = normalizeToolDeclaration(tool, options);
2292
+ return declaration ? [declaration] : [];
2293
+ });
2294
+ }
2295
+ if (!isRecord(tools)) return void 0;
2296
+ return Object.entries(tools).flatMap(([key, tool]) => {
2297
+ const declaration = normalizeToolDeclaration(tool, options, key);
2298
+ return declaration ? [declaration] : [];
2299
+ });
2300
+ }
2301
+ function resolvePromptTools(args) {
2302
+ var _a;
2303
+ if (args.override !== void 0) {
2304
+ return (_a = normalizeToolDeclarations(args.override, args.options)) != null ? _a : [];
2305
+ }
2306
+ return normalizeToolDeclarations(args.inferred, args.options);
2307
+ }
2308
+ function promptToolsAttribute(tools) {
2309
+ const values = promptToolsAttributeValue(tools);
2310
+ if (values === void 0) return void 0;
2311
+ return {
2312
+ key: PROMPT_TOOLS_ATTRIBUTE,
2313
+ value: { arrayValue: { values: values.map((stringValue) => ({ stringValue })) } }
2314
+ };
2315
+ }
2316
+ function promptToolsAttributeValue(tools) {
2317
+ if (tools === void 0) return void 0;
2318
+ return tools.map((tool) => {
2319
+ try {
2320
+ return JSON.stringify(tool);
2321
+ } catch (e) {
2322
+ return JSON.stringify({ type: tool.type, name: tool.name });
2323
+ }
2324
+ });
2325
+ }
2145
2326
 
2146
2327
  // ../core/dist/index.node.js
2147
2328
  import { AsyncLocalStorage } from "async_hooks";
@@ -2318,6 +2499,21 @@ function installTracingSuppressionHook() {
2318
2499
  installTracingSuppressionHook();
2319
2500
 
2320
2501
  // src/handler.ts
2502
+ var AGENT_CONFIG_SOURCE = {
2503
+ key: "ai.prompt.tools.source",
2504
+ value: { stringValue: "agent.config" }
2505
+ };
2506
+ function agentConfigTools(tools) {
2507
+ if (!Array.isArray(tools)) return void 0;
2508
+ return tools.map((tool) => {
2509
+ if (!isRecord2(tool)) return tool;
2510
+ const record = tool;
2511
+ if (typeof record.name === "string" || typeof record.type !== "string") return tool;
2512
+ const { type, ...args } = record;
2513
+ const name = typeof record.server_label === "string" ? record.server_label : type;
2514
+ return { type: "provider-defined", id: type, name, args };
2515
+ });
2516
+ }
2321
2517
  var RaindropManagedAgentsHandler = class {
2322
2518
  constructor(events, traces, opts) {
2323
2519
  this.events = events;
@@ -2371,6 +2567,12 @@ var RaindropManagedAgentsHandler = class {
2371
2567
  ...context.properties
2372
2568
  }
2373
2569
  };
2570
+ const override = capture.context.tools;
2571
+ const toolsAttr = promptToolsAttribute(
2572
+ resolvePromptTools({ override, inferred: agentConfigTools(session.agent.tools) })
2573
+ );
2574
+ capture.promptToolsOverridden = override !== void 0;
2575
+ capture.promptTools = !toolsAttr ? void 0 : override !== void 0 ? [toolsAttr] : [toolsAttr, AGENT_CONFIG_SOURCE];
2374
2576
  this.cacheSession(session.id, capture);
2375
2577
  } catch (e) {
2376
2578
  }
@@ -2452,8 +2654,8 @@ var RaindropManagedAgentsHandler = class {
2452
2654
  attrInt("openai.turn.started_at", (_a = turn.started_at) != null ? _a : void 0),
2453
2655
  attrInt("openai.turn.completed_at", (_b = turn.completed_at) != null ? _b : void 0)
2454
2656
  ]);
2657
+ const session = this.sessions.get(turn.session_id);
2455
2658
  if (turn.subagent_id === null) {
2456
- const session = this.sessions.get(turn.session_id);
2457
2659
  capture.patch.model = session == null ? void 0 : session.model;
2458
2660
  if (!capture.inputFromItem) capture.patch.input = session == null ? void 0 : session.input;
2459
2661
  this.setAttributes(capture.root, [
@@ -2462,6 +2664,9 @@ var RaindropManagedAgentsHandler = class {
2462
2664
  attrString("gen_ai.response.model", session == null ? void 0 : session.model)
2463
2665
  ]);
2464
2666
  }
2667
+ if ((session == null ? void 0 : session.promptTools) && (turn.subagent_id === null || session.promptToolsOverridden)) {
2668
+ this.setAttributes(capture.root, session.promptTools);
2669
+ }
2465
2670
  if (turn.subagent_id)
2466
2671
  capture.patch.properties = {
2467
2672
  ...capture.patch.properties,
@@ -2716,11 +2921,14 @@ var RaindropManagedAgentsHandler = class {
2716
2921
  this.completed.clear();
2717
2922
  }
2718
2923
  };
2924
+ function isRecord2(value) {
2925
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2926
+ }
2719
2927
 
2720
2928
  // package.json
2721
2929
  var package_default = {
2722
2930
  name: "@raindrop-ai/openai-managed-agents",
2723
- version: "0.0.2",
2931
+ version: "0.0.4",
2724
2932
  description: "Raindrop tracing for the OpenAI Agents API",
2725
2933
  main: "dist/index.js",
2726
2934
  module: "dist/index.mjs",
@@ -2762,11 +2970,11 @@ var package_default = {
2762
2970
  "@raindrop-ai/core": "workspace:*",
2763
2971
  "@types/node": "^20.11.17",
2764
2972
  msw: "^2.12.7",
2765
- tsup: "^8.4.0",
2973
+ tsup: "^9.0.0",
2766
2974
  typescript: "^5.3.3",
2767
- vitest: "^2.1.9",
2975
+ vitest: "^4.1.12",
2768
2976
  openai: "7.15.0",
2769
- zod: "^3.23.8"
2977
+ zod: "^4.6.6"
2770
2978
  },
2771
2979
  tsup: {
2772
2980
  entry: [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raindrop-ai/openai-managed-agents",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "Raindrop tracing for the OpenAI Agents API",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -33,12 +33,12 @@
33
33
  "devDependencies": {
34
34
  "@types/node": "^20.11.17",
35
35
  "msw": "^2.12.7",
36
- "tsup": "^8.4.0",
36
+ "tsup": "^9.0.0",
37
37
  "typescript": "^5.3.3",
38
- "vitest": "^2.1.9",
38
+ "vitest": "^4.1.12",
39
39
  "openai": "7.15.0",
40
- "zod": "^3.23.8",
41
- "@raindrop-ai/core": "0.3.0"
40
+ "zod": "^4.6.6",
41
+ "@raindrop-ai/core": "0.3.2"
42
42
  },
43
43
  "tsup": {
44
44
  "entry": [