@cognipeer/agent-sdk 0.9.2 → 0.9.3

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/dist/index.cjs CHANGED
@@ -294,63 +294,16 @@ var NativeJsonSchemaStrategy = class {
294
294
  }
295
295
  return resolvedSchema;
296
296
  }
297
- normalizeOpenAIStrictSchema(schema) {
298
- const visit = (node) => {
299
- if (!node || typeof node !== "object") return node;
300
- if (Array.isArray(node)) {
301
- return node.map(visit);
302
- }
303
- const clone2 = { ...node };
304
- if (clone2.properties && typeof clone2.properties === "object") {
305
- const normalizedProperties = {};
306
- for (const [key, value] of Object.entries(clone2.properties)) {
307
- normalizedProperties[key] = visit(value);
308
- }
309
- clone2.properties = normalizedProperties;
310
- clone2.required = Object.keys(normalizedProperties);
311
- if (clone2.additionalProperties === void 0) {
312
- clone2.additionalProperties = false;
313
- }
314
- }
315
- if (clone2.items) {
316
- clone2.items = visit(clone2.items);
317
- }
318
- if (clone2.definitions && typeof clone2.definitions === "object") {
319
- const normalizedDefinitions = {};
320
- for (const [key, value] of Object.entries(clone2.definitions)) {
321
- normalizedDefinitions[key] = visit(value);
322
- }
323
- clone2.definitions = normalizedDefinitions;
324
- }
325
- if (clone2.$defs && typeof clone2.$defs === "object") {
326
- const normalizedDefs = {};
327
- for (const [key, value] of Object.entries(clone2.$defs)) {
328
- normalizedDefs[key] = visit(value);
329
- }
330
- clone2.$defs = normalizedDefs;
331
- }
332
- for (const compositeKey of ["anyOf", "oneOf", "allOf"]) {
333
- if (Array.isArray(clone2[compositeKey])) {
334
- clone2[compositeKey] = clone2[compositeKey].map(visit);
335
- }
336
- }
337
- return clone2;
338
- };
339
- return visit(schema);
340
- }
341
297
  /**
342
298
  * Convert a Zod schema to the JSON Schema object used in response_format.
343
299
  */
344
300
  toJsonSchema(schema, name = "structured_response") {
345
301
  const result = zodToJsonSchema.zodToJsonSchema(schema, {
346
302
  name,
347
- openaiStrictMode: true,
348
- nameStrategy: "duplicate-ref",
349
- $refStrategy: "extract-to-root",
350
- nullableStrategy: "property"
303
+ target: "openAi",
304
+ $refStrategy: "root"
351
305
  });
352
- const normalized = this.normalizeOpenAIStrictSchema(result);
353
- return this.unwrapRootObjectSchema(normalized);
306
+ return this.unwrapRootObjectSchema(result);
354
307
  }
355
308
  /**
356
309
  * Build response_format configuration for the model call.
@@ -1261,6 +1214,8 @@ function eventToOtlpSpan(event) {
1261
1214
  stringAttr("cognipeer.actor.name", event.actor?.name),
1262
1215
  stringAttr("cognipeer.actor.role", event.actor?.role),
1263
1216
  stringAttr("cognipeer.model", event.model),
1217
+ intAttr("cognipeer.tokens.reasoning", event.reasoningTokens),
1218
+ stringAttr("cognipeer.finish_reason", event.finishReason),
1264
1219
  stringAttr("cognipeer.provider", event.provider),
1265
1220
  stringAttr("cognipeer.tool.details", event.toolDetails ? JSON.stringify(event.toolDetails) : void 0),
1266
1221
  intAttr("cognipeer.tokens.input", event.inputTokens),
@@ -1488,6 +1443,8 @@ function defaultSectionLabel(kind) {
1488
1443
  return "Details";
1489
1444
  case "tool_definitions":
1490
1445
  return "Tool Definitions";
1446
+ case "response_format":
1447
+ return "Response Format";
1491
1448
  default:
1492
1449
  return "Section";
1493
1450
  }
@@ -1545,6 +1502,42 @@ function buildToolDefinitionsSection(toolDefinitions) {
1545
1502
  }
1546
1503
  return section;
1547
1504
  }
1505
+ var RESPONSE_FORMAT_MAX_SECTION_BYTES = 64 * 1024;
1506
+ var RESPONSE_FORMAT_MAX_NAME_CHARS = 200;
1507
+ function buildResponseFormatSection(responseFormat, strategy) {
1508
+ if (!responseFormat || typeof responseFormat !== "object" || Array.isArray(responseFormat)) return void 0;
1509
+ const raw = responseFormat.response_format ?? responseFormat.responseFormat ?? responseFormat;
1510
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
1511
+ const type = typeof raw.type === "string" && raw.type.trim().length > 0 ? raw.type.trim() : void 0;
1512
+ const jsonSchema = raw.json_schema ?? raw.jsonSchema;
1513
+ const schemaSource = jsonSchema && typeof jsonSchema === "object" ? jsonSchema : raw;
1514
+ const schema = schemaSource.schema && typeof schemaSource.schema === "object" && !Array.isArray(schemaSource.schema) ? schemaSource.schema : void 0;
1515
+ if (!type && !schema) return void 0;
1516
+ const section = {
1517
+ kind: "response_format",
1518
+ label: "Response Format",
1519
+ type: type ?? (schema ? "json_schema" : "unknown"),
1520
+ ...strategy ? { strategy } : {},
1521
+ ...typeof schemaSource.name === "string" && schemaSource.name.length > 0 ? { schemaName: schemaSource.name.slice(0, RESPONSE_FORMAT_MAX_NAME_CHARS) } : {},
1522
+ ...typeof schemaSource.strict === "boolean" ? { strict: schemaSource.strict } : {}
1523
+ };
1524
+ if (schema) {
1525
+ try {
1526
+ section.schema = JSON.parse(JSON.stringify(schema));
1527
+ } catch {
1528
+ }
1529
+ }
1530
+ try {
1531
+ if (section.schema && buffer.Buffer.byteLength(JSON.stringify(section), "utf8") > RESPONSE_FORMAT_MAX_SECTION_BYTES) {
1532
+ delete section.schema;
1533
+ section.truncated = true;
1534
+ }
1535
+ } catch {
1536
+ delete section.schema;
1537
+ section.truncated = true;
1538
+ }
1539
+ return section;
1540
+ }
1548
1541
  function buildMessageLabel(role, index) {
1549
1542
  const normalized = role?.trim().length ? role.trim() : "message";
1550
1543
  const base = `${normalized.charAt(0).toUpperCase()}${normalized.slice(1)} Message`;
@@ -1740,6 +1733,7 @@ function recordTraceEvent(session, event) {
1740
1733
  if (!Number.isNaN(cachedInputTokens ?? NaN) && cachedInputTokens !== void 0) {
1741
1734
  session.summary.totalCachedInputTokens += cachedInputTokens;
1742
1735
  }
1736
+ const reasoningTokens = event.reasoningTokens !== void 0 ? Number(event.reasoningTokens) : void 0;
1743
1737
  const totalTokens = event.totalTokens !== void 0 ? Number(event.totalTokens) : void 0;
1744
1738
  const requestBytes = event.requestBytes !== void 0 ? Number(event.requestBytes) : void 0;
1745
1739
  if (!Number.isNaN(requestBytes ?? NaN) && requestBytes !== void 0) {
@@ -1765,6 +1759,13 @@ function recordTraceEvent(session, event) {
1765
1759
  if (menuSection) sections = ensureUniqueSections(id, [...sections ?? [], menuSection]);
1766
1760
  }
1767
1761
  }
1762
+ if (event.responseFormat) {
1763
+ const existing = (sections ?? []).some((section) => section.kind === "response_format");
1764
+ if (!existing) {
1765
+ const formatSection = buildResponseFormatSection(event.responseFormat, event.responseFormatStrategy);
1766
+ if (formatSection) sections = ensureUniqueSections(id, [...sections ?? [], formatSection]);
1767
+ }
1768
+ }
1768
1769
  }
1769
1770
  const resolvedModel = event.model ?? inferModelFromMessages(event.messageList);
1770
1771
  const resolvedProvider = event.provider ?? inferProviderFromMessages(event.messageList);
@@ -1795,6 +1796,11 @@ function recordTraceEvent(session, event) {
1795
1796
  ...totalTokens !== void 0 && { totalTokens },
1796
1797
  ...cachedInputTokens !== void 0 && { cachedInputTokens }
1797
1798
  },
1799
+ // Absent, never zeroed for ai_call the way the four above are: a model
1800
+ // that does no reasoning and one whose provider reports nothing are
1801
+ // different facts, and a zero would erase the difference.
1802
+ ...reasoningTokens !== void 0 && !Number.isNaN(reasoningTokens) ? { reasoningTokens } : {},
1803
+ ...event.finishReason ? { finishReason: event.finishReason } : {},
1798
1804
  requestBytes,
1799
1805
  responseBytes,
1800
1806
  model: resolvedModel,
@@ -3892,6 +3898,18 @@ function createAgentCoreNode(opts) {
3892
3898
  }
3893
3899
  }
3894
3900
  const responseFormat = runtime.responseFormat;
3901
+ let traceResponseFormat = responseFormat;
3902
+ let traceResponseFormatStrategy = responseFormat ? "native" : void 0;
3903
+ if (!traceResponseFormat && runtime.outputSchema) {
3904
+ const responseTool = traceToolDefinitions?.find((tool) => tool.name === "response");
3905
+ if (responseTool?.parameters) {
3906
+ traceResponseFormat = {
3907
+ type: "json_schema",
3908
+ json_schema: { name: "response", strict: false, schema: responseTool.parameters }
3909
+ };
3910
+ traceResponseFormatStrategy = "tool_based";
3911
+ }
3912
+ }
3895
3913
  const reasoningForCall = state.ctx?.__reasoning;
3896
3914
  const reasoningInvokeOpts = reasoningForCall ? { reasoning: reasoningForCall } : void 0;
3897
3915
  const extractText2 = (chunk) => {
@@ -3951,7 +3969,9 @@ function createAgentCoreNode(opts) {
3951
3969
  provider: getProviderName(runtime.model || opts.model),
3952
3970
  error: { message: err?.message || String(err), stack: err?.stack },
3953
3971
  messageList: state.messages,
3954
- toolDefinitions: traceToolDefinitions
3972
+ toolDefinitions: traceToolDefinitions,
3973
+ responseFormat: traceResponseFormat,
3974
+ responseFormatStrategy: traceResponseFormatStrategy
3955
3975
  });
3956
3976
  throw err;
3957
3977
  }
@@ -3966,6 +3986,7 @@ function createAgentCoreNode(opts) {
3966
3986
  const shouldLogResponse = !!traceSession && traceSession.resolvedConfig.logData;
3967
3987
  const responsePayload = shouldLogResponse ? sanitizeTracePayload(response) : void 0;
3968
3988
  const responseBytes = responsePayload !== void 0 ? estimatePayloadBytes(responsePayload) : void 0;
3989
+ const finishReason = response?.response_metadata?.finish_reason ?? response?.response_metadata?.finishReason ?? response?.finishReason;
3969
3990
  recordTraceEvent(traceSession, {
3970
3991
  type: "ai_call",
3971
3992
  label: "Assistant Response",
@@ -3975,12 +3996,18 @@ function createAgentCoreNode(opts) {
3975
3996
  outputTokens: normalized?.completion_tokens,
3976
3997
  totalTokens: normalized?.total_tokens,
3977
3998
  cachedInputTokens: normalized?.prompt_tokens_details?.cached_tokens,
3999
+ // A subset of completion_tokens, and on a reasoning model routinely most
4000
+ // of the output bill while being invisible in the response text.
4001
+ reasoningTokens: normalized?.completion_tokens_details?.reasoning_tokens,
4002
+ finishReason: typeof finishReason === "string" ? finishReason : void 0,
3978
4003
  requestBytes: promptBytes,
3979
4004
  responseBytes,
3980
4005
  model: modelName,
3981
4006
  provider: getProviderName(runtime.model || opts.model),
3982
4007
  messageList: messagesWithResponse,
3983
- toolDefinitions: traceToolDefinitions
4008
+ toolDefinitions: traceToolDefinitions,
4009
+ responseFormat: traceResponseFormat,
4010
+ responseFormatStrategy: traceResponseFormatStrategy
3984
4011
  });
3985
4012
  if (normalized) {
3986
4013
  recordUsage(state, modelName, normalized);
@@ -11793,6 +11820,7 @@ exports.ToolBasedStrategy = ToolBasedStrategy;
11793
11820
  exports.VertexProvider = VertexProvider;
11794
11821
  exports.agentVerdictRule = agentVerdictRule;
11795
11822
  exports.appendBoundTools = appendBoundTools;
11823
+ exports.buildResponseFormatSection = buildResponseFormatSection;
11796
11824
  exports.buildSkillHeaderBlock = buildSkillHeaderBlock;
11797
11825
  exports.buildSubagentCatalogBlock = buildSubagentCatalogBlock;
11798
11826
  exports.buildSystemPrompt = buildSystemPrompt;