@cognipeer/agent-sdk 0.9.2 → 0.9.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 +2 -0
- package/dist/index.cjs +90 -57
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +64 -3
- package/dist/index.d.ts +64 -3
- package/dist/index.mjs +90 -58
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -417,6 +417,8 @@ You can disable payload capture with `logData: false` to keep only metrics, or c
|
|
|
417
417
|
|
|
418
418
|
Each session/event also carries OTel-compatible correlation identifiers (`traceId`, `rootSpanId`, `spanId`, `parentSpanId`) so you can stitch agent traces into distributed telemetry pipelines.
|
|
419
419
|
|
|
420
|
+
Pass `tracing: { metadata: { ... } }` to attach arbitrary key-value tags (e.g. `{ complexity: "complex" }`) to every payload sent to the sink. The SDK does not interpret these tags itself — they're forwarded as-is so a downstream consumer (e.g. Console) can use them as reporting/attribution dimensions.
|
|
421
|
+
|
|
420
422
|
## Development
|
|
421
423
|
|
|
422
424
|
Install dependencies and build the package:
|
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
|
-
|
|
348
|
-
|
|
349
|
-
$refStrategy: "extract-to-root",
|
|
350
|
-
nullableStrategy: "property"
|
|
303
|
+
target: "openAi",
|
|
304
|
+
$refStrategy: "root"
|
|
351
305
|
});
|
|
352
|
-
|
|
353
|
-
return this.unwrapRootObjectSchema(normalized);
|
|
306
|
+
return this.unwrapRootObjectSchema(result);
|
|
354
307
|
}
|
|
355
308
|
/**
|
|
356
309
|
* Build response_format configuration for the model call.
|
|
@@ -1209,9 +1162,9 @@ async function postStreamingSessionStart(baseUrl, headers, payload) {
|
|
|
1209
1162
|
const url = `${baseUrl.replace(/\/$/, "")}/stream/${payload.sessionId}/start`;
|
|
1210
1163
|
await postJsonReliable(url, headers, payload, { retry: true });
|
|
1211
1164
|
}
|
|
1212
|
-
async function postStreamingEvent(baseUrl, headers, sessionId, event) {
|
|
1165
|
+
async function postStreamingEvent(baseUrl, headers, sessionId, event, metadata) {
|
|
1213
1166
|
const url = `${baseUrl.replace(/\/$/, "")}/stream/${sessionId}/events`;
|
|
1214
|
-
await postJsonReliable(url, headers, { event }, { retry: false });
|
|
1167
|
+
await postJsonReliable(url, headers, { event, metadata }, { retry: false });
|
|
1215
1168
|
}
|
|
1216
1169
|
async function postStreamingSessionEnd(baseUrl, headers, payload) {
|
|
1217
1170
|
const url = `${baseUrl.replace(/\/$/, "")}/stream/${payload.sessionId}/end`;
|
|
@@ -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),
|
|
@@ -1316,7 +1271,8 @@ function traceSessionToOtlp(session) {
|
|
|
1316
1271
|
stringAttr("cognipeer.session.id", session.sessionId),
|
|
1317
1272
|
stringAttr("cognipeer.thread.id", session.threadId),
|
|
1318
1273
|
stringAttr("cognipeer.agent.model", session.agent?.model),
|
|
1319
|
-
stringAttr("cognipeer.agent.provider", session.agent?.provider)
|
|
1274
|
+
stringAttr("cognipeer.agent.provider", session.agent?.provider),
|
|
1275
|
+
...Object.entries(session.metadata || {}).map(([key, value]) => stringAttr(`cognipeer.metadata.${key}`, value))
|
|
1320
1276
|
].filter(Boolean);
|
|
1321
1277
|
const rootAttrs = [
|
|
1322
1278
|
stringAttr("cognipeer.session.status", session.status),
|
|
@@ -1488,6 +1444,8 @@ function defaultSectionLabel(kind) {
|
|
|
1488
1444
|
return "Details";
|
|
1489
1445
|
case "tool_definitions":
|
|
1490
1446
|
return "Tool Definitions";
|
|
1447
|
+
case "response_format":
|
|
1448
|
+
return "Response Format";
|
|
1491
1449
|
default:
|
|
1492
1450
|
return "Section";
|
|
1493
1451
|
}
|
|
@@ -1545,6 +1503,42 @@ function buildToolDefinitionsSection(toolDefinitions) {
|
|
|
1545
1503
|
}
|
|
1546
1504
|
return section;
|
|
1547
1505
|
}
|
|
1506
|
+
var RESPONSE_FORMAT_MAX_SECTION_BYTES = 64 * 1024;
|
|
1507
|
+
var RESPONSE_FORMAT_MAX_NAME_CHARS = 200;
|
|
1508
|
+
function buildResponseFormatSection(responseFormat, strategy) {
|
|
1509
|
+
if (!responseFormat || typeof responseFormat !== "object" || Array.isArray(responseFormat)) return void 0;
|
|
1510
|
+
const raw = responseFormat.response_format ?? responseFormat.responseFormat ?? responseFormat;
|
|
1511
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
|
|
1512
|
+
const type = typeof raw.type === "string" && raw.type.trim().length > 0 ? raw.type.trim() : void 0;
|
|
1513
|
+
const jsonSchema = raw.json_schema ?? raw.jsonSchema;
|
|
1514
|
+
const schemaSource = jsonSchema && typeof jsonSchema === "object" ? jsonSchema : raw;
|
|
1515
|
+
const schema = schemaSource.schema && typeof schemaSource.schema === "object" && !Array.isArray(schemaSource.schema) ? schemaSource.schema : void 0;
|
|
1516
|
+
if (!type && !schema) return void 0;
|
|
1517
|
+
const section = {
|
|
1518
|
+
kind: "response_format",
|
|
1519
|
+
label: "Response Format",
|
|
1520
|
+
type: type ?? (schema ? "json_schema" : "unknown"),
|
|
1521
|
+
...strategy ? { strategy } : {},
|
|
1522
|
+
...typeof schemaSource.name === "string" && schemaSource.name.length > 0 ? { schemaName: schemaSource.name.slice(0, RESPONSE_FORMAT_MAX_NAME_CHARS) } : {},
|
|
1523
|
+
...typeof schemaSource.strict === "boolean" ? { strict: schemaSource.strict } : {}
|
|
1524
|
+
};
|
|
1525
|
+
if (schema) {
|
|
1526
|
+
try {
|
|
1527
|
+
section.schema = JSON.parse(JSON.stringify(schema));
|
|
1528
|
+
} catch {
|
|
1529
|
+
}
|
|
1530
|
+
}
|
|
1531
|
+
try {
|
|
1532
|
+
if (section.schema && buffer.Buffer.byteLength(JSON.stringify(section), "utf8") > RESPONSE_FORMAT_MAX_SECTION_BYTES) {
|
|
1533
|
+
delete section.schema;
|
|
1534
|
+
section.truncated = true;
|
|
1535
|
+
}
|
|
1536
|
+
} catch {
|
|
1537
|
+
delete section.schema;
|
|
1538
|
+
section.truncated = true;
|
|
1539
|
+
}
|
|
1540
|
+
return section;
|
|
1541
|
+
}
|
|
1548
1542
|
function buildMessageLabel(role, index) {
|
|
1549
1543
|
const normalized = role?.trim().length ? role.trim() : "message";
|
|
1550
1544
|
const base = `${normalized.charAt(0).toUpperCase()}${normalized.slice(1)} Message`;
|
|
@@ -1653,6 +1647,7 @@ function createTraceSession(opts) {
|
|
|
1653
1647
|
rootSpanId,
|
|
1654
1648
|
threadId: opts.tracing?.threadId,
|
|
1655
1649
|
configAgentName: opts.tracing?.agentName?.trim() || void 0,
|
|
1650
|
+
configMetadata: opts.tracing?.metadata && Object.keys(opts.tracing.metadata).length > 0 ? opts.tracing.metadata : void 0,
|
|
1656
1651
|
startedAt: Date.now(),
|
|
1657
1652
|
resolvedConfig: cfg,
|
|
1658
1653
|
events: [],
|
|
@@ -1691,6 +1686,7 @@ async function startStreamingSession(session, agentRuntime) {
|
|
|
1691
1686
|
threadId: session.threadId,
|
|
1692
1687
|
startedAt: startedAtIso,
|
|
1693
1688
|
agent: agentInfo,
|
|
1689
|
+
metadata: session.configMetadata,
|
|
1694
1690
|
config: configSnapshot
|
|
1695
1691
|
};
|
|
1696
1692
|
if (sink.type === "cognipeer" || sink.type === "http") {
|
|
@@ -1740,6 +1736,7 @@ function recordTraceEvent(session, event) {
|
|
|
1740
1736
|
if (!Number.isNaN(cachedInputTokens ?? NaN) && cachedInputTokens !== void 0) {
|
|
1741
1737
|
session.summary.totalCachedInputTokens += cachedInputTokens;
|
|
1742
1738
|
}
|
|
1739
|
+
const reasoningTokens = event.reasoningTokens !== void 0 ? Number(event.reasoningTokens) : void 0;
|
|
1743
1740
|
const totalTokens = event.totalTokens !== void 0 ? Number(event.totalTokens) : void 0;
|
|
1744
1741
|
const requestBytes = event.requestBytes !== void 0 ? Number(event.requestBytes) : void 0;
|
|
1745
1742
|
if (!Number.isNaN(requestBytes ?? NaN) && requestBytes !== void 0) {
|
|
@@ -1765,6 +1762,13 @@ function recordTraceEvent(session, event) {
|
|
|
1765
1762
|
if (menuSection) sections = ensureUniqueSections(id, [...sections ?? [], menuSection]);
|
|
1766
1763
|
}
|
|
1767
1764
|
}
|
|
1765
|
+
if (event.responseFormat) {
|
|
1766
|
+
const existing = (sections ?? []).some((section) => section.kind === "response_format");
|
|
1767
|
+
if (!existing) {
|
|
1768
|
+
const formatSection = buildResponseFormatSection(event.responseFormat, event.responseFormatStrategy);
|
|
1769
|
+
if (formatSection) sections = ensureUniqueSections(id, [...sections ?? [], formatSection]);
|
|
1770
|
+
}
|
|
1771
|
+
}
|
|
1768
1772
|
}
|
|
1769
1773
|
const resolvedModel = event.model ?? inferModelFromMessages(event.messageList);
|
|
1770
1774
|
const resolvedProvider = event.provider ?? inferProviderFromMessages(event.messageList);
|
|
@@ -1795,6 +1799,11 @@ function recordTraceEvent(session, event) {
|
|
|
1795
1799
|
...totalTokens !== void 0 && { totalTokens },
|
|
1796
1800
|
...cachedInputTokens !== void 0 && { cachedInputTokens }
|
|
1797
1801
|
},
|
|
1802
|
+
// Absent, never zeroed for ai_call the way the four above are: a model
|
|
1803
|
+
// that does no reasoning and one whose provider reports nothing are
|
|
1804
|
+
// different facts, and a zero would erase the difference.
|
|
1805
|
+
...reasoningTokens !== void 0 && !Number.isNaN(reasoningTokens) ? { reasoningTokens } : {},
|
|
1806
|
+
...event.finishReason ? { finishReason: event.finishReason } : {},
|
|
1798
1807
|
requestBytes,
|
|
1799
1808
|
responseBytes,
|
|
1800
1809
|
model: resolvedModel,
|
|
@@ -1838,7 +1847,7 @@ function recordTraceEvent(session, event) {
|
|
|
1838
1847
|
if (session.resolvedConfig.mode === "streaming" && session.sessionStarted) {
|
|
1839
1848
|
if (sink.type === "cognipeer" || sink.type === "http") {
|
|
1840
1849
|
const headers = sink.type === "cognipeer" ? { Authorization: `Bearer ${sink.apiKey}` } : sink.headers;
|
|
1841
|
-
postStreamingEvent(sink.url, headers, session.sessionId, record).catch((err) => {
|
|
1850
|
+
postStreamingEvent(sink.url, headers, session.sessionId, record, session.configMetadata).catch((err) => {
|
|
1842
1851
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
1843
1852
|
if (typeof console !== "undefined" && typeof console.warn === "function") {
|
|
1844
1853
|
console.warn("[Tracing] Failed to send streaming event:", errMsg);
|
|
@@ -1890,6 +1899,7 @@ async function finalizeTraceSession(session, params = {}) {
|
|
|
1890
1899
|
endedAt: endedAtIso,
|
|
1891
1900
|
durationMs,
|
|
1892
1901
|
agent: agentInfo || session.agentInfo,
|
|
1902
|
+
metadata: session.configMetadata,
|
|
1893
1903
|
config: configSnapshot,
|
|
1894
1904
|
summary: session.summary,
|
|
1895
1905
|
events: session.events,
|
|
@@ -1924,7 +1934,8 @@ async function finalizeTraceSession(session, params = {}) {
|
|
|
1924
1934
|
durationMs,
|
|
1925
1935
|
status: initialStatus,
|
|
1926
1936
|
summary: session.summary,
|
|
1927
|
-
errors: session.errors
|
|
1937
|
+
errors: session.errors,
|
|
1938
|
+
metadata: session.configMetadata
|
|
1928
1939
|
});
|
|
1929
1940
|
} else {
|
|
1930
1941
|
await postTraceSession(sink.url, headers, payloadForSink);
|
|
@@ -3892,6 +3903,18 @@ function createAgentCoreNode(opts) {
|
|
|
3892
3903
|
}
|
|
3893
3904
|
}
|
|
3894
3905
|
const responseFormat = runtime.responseFormat;
|
|
3906
|
+
let traceResponseFormat = responseFormat;
|
|
3907
|
+
let traceResponseFormatStrategy = responseFormat ? "native" : void 0;
|
|
3908
|
+
if (!traceResponseFormat && runtime.outputSchema) {
|
|
3909
|
+
const responseTool = traceToolDefinitions?.find((tool) => tool.name === "response");
|
|
3910
|
+
if (responseTool?.parameters) {
|
|
3911
|
+
traceResponseFormat = {
|
|
3912
|
+
type: "json_schema",
|
|
3913
|
+
json_schema: { name: "response", strict: false, schema: responseTool.parameters }
|
|
3914
|
+
};
|
|
3915
|
+
traceResponseFormatStrategy = "tool_based";
|
|
3916
|
+
}
|
|
3917
|
+
}
|
|
3895
3918
|
const reasoningForCall = state.ctx?.__reasoning;
|
|
3896
3919
|
const reasoningInvokeOpts = reasoningForCall ? { reasoning: reasoningForCall } : void 0;
|
|
3897
3920
|
const extractText2 = (chunk) => {
|
|
@@ -3951,7 +3974,9 @@ function createAgentCoreNode(opts) {
|
|
|
3951
3974
|
provider: getProviderName(runtime.model || opts.model),
|
|
3952
3975
|
error: { message: err?.message || String(err), stack: err?.stack },
|
|
3953
3976
|
messageList: state.messages,
|
|
3954
|
-
toolDefinitions: traceToolDefinitions
|
|
3977
|
+
toolDefinitions: traceToolDefinitions,
|
|
3978
|
+
responseFormat: traceResponseFormat,
|
|
3979
|
+
responseFormatStrategy: traceResponseFormatStrategy
|
|
3955
3980
|
});
|
|
3956
3981
|
throw err;
|
|
3957
3982
|
}
|
|
@@ -3966,6 +3991,7 @@ function createAgentCoreNode(opts) {
|
|
|
3966
3991
|
const shouldLogResponse = !!traceSession && traceSession.resolvedConfig.logData;
|
|
3967
3992
|
const responsePayload = shouldLogResponse ? sanitizeTracePayload(response) : void 0;
|
|
3968
3993
|
const responseBytes = responsePayload !== void 0 ? estimatePayloadBytes(responsePayload) : void 0;
|
|
3994
|
+
const finishReason = response?.response_metadata?.finish_reason ?? response?.response_metadata?.finishReason ?? response?.finishReason;
|
|
3969
3995
|
recordTraceEvent(traceSession, {
|
|
3970
3996
|
type: "ai_call",
|
|
3971
3997
|
label: "Assistant Response",
|
|
@@ -3975,12 +4001,18 @@ function createAgentCoreNode(opts) {
|
|
|
3975
4001
|
outputTokens: normalized?.completion_tokens,
|
|
3976
4002
|
totalTokens: normalized?.total_tokens,
|
|
3977
4003
|
cachedInputTokens: normalized?.prompt_tokens_details?.cached_tokens,
|
|
4004
|
+
// A subset of completion_tokens, and on a reasoning model routinely most
|
|
4005
|
+
// of the output bill while being invisible in the response text.
|
|
4006
|
+
reasoningTokens: normalized?.completion_tokens_details?.reasoning_tokens,
|
|
4007
|
+
finishReason: typeof finishReason === "string" ? finishReason : void 0,
|
|
3978
4008
|
requestBytes: promptBytes,
|
|
3979
4009
|
responseBytes,
|
|
3980
4010
|
model: modelName,
|
|
3981
4011
|
provider: getProviderName(runtime.model || opts.model),
|
|
3982
4012
|
messageList: messagesWithResponse,
|
|
3983
|
-
toolDefinitions: traceToolDefinitions
|
|
4013
|
+
toolDefinitions: traceToolDefinitions,
|
|
4014
|
+
responseFormat: traceResponseFormat,
|
|
4015
|
+
responseFormatStrategy: traceResponseFormatStrategy
|
|
3984
4016
|
});
|
|
3985
4017
|
if (normalized) {
|
|
3986
4018
|
recordUsage(state, modelName, normalized);
|
|
@@ -11793,6 +11825,7 @@ exports.ToolBasedStrategy = ToolBasedStrategy;
|
|
|
11793
11825
|
exports.VertexProvider = VertexProvider;
|
|
11794
11826
|
exports.agentVerdictRule = agentVerdictRule;
|
|
11795
11827
|
exports.appendBoundTools = appendBoundTools;
|
|
11828
|
+
exports.buildResponseFormatSection = buildResponseFormatSection;
|
|
11796
11829
|
exports.buildSkillHeaderBlock = buildSkillHeaderBlock;
|
|
11797
11830
|
exports.buildSubagentCatalogBlock = buildSubagentCatalogBlock;
|
|
11798
11831
|
exports.buildSystemPrompt = buildSystemPrompt;
|