@kortyx/hooks 0.13.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.15.0](https://github.com/kortyx-io/kortyx/compare/hooks-v0.14.0...hooks-v0.15.0) (2026-05-24)
4
+
5
+
6
+ ### Features
7
+
8
+ * add OpenTelemetry tracing adapter ([dc1218f](https://github.com/kortyx-io/kortyx/commit/dc1218fb3759b8cb467f6c58f953a80127b25783))
9
+
10
+ ## [0.14.0](https://github.com/kortyx-io/kortyx/compare/hooks-v0.13.0...hooks-v0.14.0) (2026-05-22)
11
+
12
+
13
+ ### Features
14
+
15
+ * **hooks:** support wildcard structured streaming ([cdc646c](https://github.com/kortyx-io/kortyx/commit/cdc646cf7e3a8f36fc62d0cb4123a427eb823f8f))
16
+ * **hooks:** support wildcard structured streaming ([fa7fec7](https://github.com/kortyx-io/kortyx/commit/fa7fec7f5a86a5bad73f3889b9698b8eb62451df))
17
+
3
18
  ## [0.13.0](https://github.com/kortyx-io/kortyx/compare/hooks-v0.12.1...hooks-v0.13.0) (2026-05-22)
4
19
 
5
20
 
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { NodeConfig, InterruptInput, InterruptResult, GraphState } from '@kortyx/core';
2
- import { R as ReasonTraceAdapter } from './tracing-BG-j1cer.js';
3
- export { a as ReasonTraceAttributes, b as ReasonTraceSpan, c as ReasonTraceSpanEndArgs, d as ReasonTraceSpanStartArgs } from './tracing-BG-j1cer.js';
2
+ import { R as ReasonTraceAdapter, K as KortyxTraceMetadata } from './tracing-DK-T8zX5.js';
3
+ export { a as KortyxTelemetryConfig, b as KortyxTelemetryContentCapture, c as KortyxTelemetryPrompt, d as KortyxTraceAdapter, e as ReasonTraceAttributes, f as ReasonTraceSpan, g as ReasonTraceSpanEndArgs, h as ReasonTraceSpanStartArgs } from './tracing-DK-T8zX5.js';
4
4
  import { ProviderModelRef, KortyxReasoningOptions, KortyxResponseFormat, KortyxUsage, KortyxFinishReason, KortyxProviderMetadata, KortyxWarning } from '@kortyx/providers';
5
5
 
6
6
  type HookNodeRuntimeContext = {
@@ -79,7 +79,8 @@ type UseReasonStructuredConfig = {
79
79
  schemaVersion?: string | undefined;
80
80
  /**
81
81
  * Incremental extraction paths for useReason. Dotted paths target nested
82
- * object fields, and numeric segments target array indexes.
82
+ * object fields, numeric segments target array indexes, and `*` matches one
83
+ * object key or array index segment.
83
84
  */
84
85
  fields?: UseReasonStructuredFields | undefined;
85
86
  };
@@ -104,6 +105,7 @@ type UseReasonArgs<TOutput = unknown, TRequest extends InterruptInput = Interrup
104
105
  emit?: boolean | undefined;
105
106
  stream?: boolean | undefined;
106
107
  id?: string | undefined;
108
+ telemetry?: KortyxTraceMetadata | undefined;
107
109
  outputSchema?: SchemaLike<TOutput> | undefined;
108
110
  structured?: UseReasonStructuredConfig | undefined;
109
111
  interrupt?: UseReasonInterruptConfig<TRequest, TResponse> | undefined;
@@ -138,4 +140,4 @@ declare function useRuntimeContext<TContext extends Record<string, unknown> = Re
138
140
  declare function useNodeState<T>(initialValue: T): [T, StateSetter<T>];
139
141
  declare function useWorkflowState<T>(key: string, ...rest: [] | [T]): [T, StateSetter<T>];
140
142
 
141
- export { type HookRuntimeContext, ReasonTraceAdapter, type UseInterruptArgs, type UseReasonArgs, type UseReasonResult, type UseStructuredDataArgs, runWithHookContext, useInterrupt, useNodeState, useReason, useRuntimeContext, useStructuredData, useWorkflowState };
143
+ export { type HookRuntimeContext, KortyxTraceMetadata, ReasonTraceAdapter, type UseInterruptArgs, type UseReasonArgs, type UseReasonResult, type UseStructuredDataArgs, runWithHookContext, useInterrupt, useNodeState, useReason, useRuntimeContext, useStructuredData, useWorkflowState };
package/dist/index.js CHANGED
@@ -403,7 +403,15 @@ async function runReasonEngine(args) {
403
403
  modelId: args.model.modelId,
404
404
  stream,
405
405
  emit,
406
+ ...args.telemetry?.operation ? { operation: args.telemetry.operation } : {},
407
+ ...args.telemetry?.prompt?.name ? { promptName: args.telemetry.prompt.name } : {},
408
+ ...args.telemetry?.prompt?.version !== void 0 ? { promptVersion: args.telemetry.prompt.version } : {},
409
+ ...args.telemetry?.prompt?.type ? { promptType: args.telemetry.prompt.type } : {},
406
410
  ...typeof args.nodeId === "string" && args.nodeId.length > 0 ? { nodeId: args.nodeId } : {}
411
+ },
412
+ telemetry: {
413
+ ...args.telemetry ?? {},
414
+ input: args.telemetry?.input ?? messages
407
415
  }
408
416
  });
409
417
  const endTrace = (span, result) => {
@@ -414,6 +422,10 @@ async function runReasonEngine(args) {
414
422
  ...result.warnings !== void 0 ? { warnings: result.warnings } : {},
415
423
  attributes: {
416
424
  textLength: result.text.length
425
+ },
426
+ telemetry: {
427
+ ...args.telemetry ?? {},
428
+ output: args.telemetry?.output ?? result.text
417
429
  }
418
430
  });
419
431
  };
@@ -570,6 +582,7 @@ async function reasonEngine(args, meta, inputOverride) {
570
582
  stream: args.stream,
571
583
  emit: args.emit,
572
584
  onTextChunk: args.onTextChunk,
585
+ telemetry: args.telemetry,
573
586
  nodeId: ctx.node.graph.node,
574
587
  emitEvent: ctx.node.emit,
575
588
  reasonTrace: ctx.reasonTrace,
@@ -862,12 +875,12 @@ var withStructuredStreamHints = (input, args) => {
862
875
  const rules = [];
863
876
  for (const path of args.setFieldPaths ?? []) {
864
877
  rules.push(
865
- `- For the field path \`${path}\`, write one stable final value and do not rewrite it after it is complete.`
878
+ `- For the field path pattern \`${path}\`, write one stable final value and do not rewrite it after it is complete.`
866
879
  );
867
880
  }
868
881
  for (const path of args.appendFieldPaths ?? []) {
869
882
  rules.push(
870
- `- For the array field path \`${path}\`, write items in final order and finish each item before starting the next.`
883
+ `- For the array field path pattern \`${path}\`, write items in final order and finish each item before starting the next.`
871
884
  );
872
885
  rules.push(
873
886
  `- Once an item in \`${path}\` is complete, do not rewrite or reorder earlier items.`
@@ -875,7 +888,7 @@ var withStructuredStreamHints = (input, args) => {
875
888
  }
876
889
  for (const path of args.textDeltaFieldPaths ?? []) {
877
890
  rules.push(
878
- `- For the string field path \`${path}\`, write the value progressively by appending text to the end.`
891
+ `- For the string field path pattern \`${path}\`, write the value progressively by appending text to the end.`
879
892
  );
880
893
  rules.push(
881
894
  `- Do not rewrite or replace the earlier prefix of \`${path}\` once emitted.`
@@ -968,8 +981,11 @@ var skipWhitespace = (text, start) => {
968
981
  while (i < text.length && /\s/.test(text[i] ?? "")) i += 1;
969
982
  return i;
970
983
  };
971
- var pathEquals = (left, right) => left.length === right.length && left.every((part, index) => part === right[index]);
972
- var isPathPrefix = (prefix, full) => prefix.length <= full.length && prefix.every((part, index) => part === full[index]);
984
+ var pathSegmentMatches = (patternPart, actualPart) => patternPart === "*" || patternPart === actualPart;
985
+ var pathMatchesPattern = (actualParts, patternParts) => actualParts.length === patternParts.length && actualParts.every(
986
+ (part, index) => pathSegmentMatches(patternParts[index] ?? "", part)
987
+ );
988
+ var isPathPrefix = (prefix, full) => prefix.length <= full.length && prefix.every((part, index) => pathSegmentMatches(full[index] ?? "", part));
973
989
  var parseStringToken = (text, start) => {
974
990
  if (text[start] !== '"') return { complete: false };
975
991
  const parsed = extractCompletedStringValueAt({ text, start: start + 1 });
@@ -1064,78 +1080,92 @@ var skipCompleteValue = (text, start) => {
1064
1080
  return { complete: false };
1065
1081
  };
1066
1082
  var locateValueStart = (args) => {
1083
+ const [first] = locateValueStarts(args);
1084
+ return first ? {
1085
+ found: true,
1086
+ start: first.start
1087
+ } : {
1088
+ found: false
1089
+ };
1090
+ };
1091
+ var locateValueStarts = (args) => {
1067
1092
  const targetParts = parseStructuredPath(
1068
1093
  args.path,
1069
1094
  "useReason structured field"
1070
1095
  );
1096
+ const matches = [];
1071
1097
  const visitValue = (start, currentParts) => {
1072
1098
  const valueStart = skipWhitespace(args.text, start);
1073
- if (pathEquals(currentParts, targetParts)) {
1074
- return { found: true, start: valueStart };
1099
+ if (pathMatchesPattern(currentParts, targetParts)) {
1100
+ matches.push({
1101
+ path: currentParts.join("."),
1102
+ start: valueStart
1103
+ });
1104
+ return;
1075
1105
  }
1076
1106
  if (!isPathPrefix(currentParts, targetParts)) {
1077
- return { found: false };
1107
+ return;
1078
1108
  }
1079
1109
  const first = args.text[valueStart];
1080
- if (first === "{") return visitObject(valueStart + 1, currentParts);
1081
- if (first === "[") return visitArray(valueStart + 1, currentParts);
1082
- return { found: false };
1110
+ if (first === "{") visitObject(valueStart + 1, currentParts);
1111
+ if (first === "[") visitArray(valueStart + 1, currentParts);
1083
1112
  };
1084
1113
  const visitObject = (start, currentParts) => {
1085
1114
  let i = skipWhitespace(args.text, start);
1086
1115
  while (i < args.text.length) {
1087
1116
  const ch = args.text[i];
1088
- if (ch === "}") return { found: false };
1117
+ if (ch === "}") return;
1089
1118
  if (ch === ",") {
1090
1119
  i = skipWhitespace(args.text, i + 1);
1091
1120
  continue;
1092
1121
  }
1093
- if (ch !== '"') return { found: false };
1122
+ if (ch !== '"') return;
1094
1123
  const key = parseStringToken(args.text, i);
1095
1124
  if (!key.complete || key.end === void 0 || key.value === void 0) {
1096
- return { found: false };
1125
+ return;
1097
1126
  }
1098
1127
  i = skipWhitespace(args.text, key.end);
1099
- if (args.text[i] !== ":") return { found: false };
1128
+ if (args.text[i] !== ":") return;
1100
1129
  const valueStart = skipWhitespace(args.text, i + 1);
1101
1130
  const childParts = [...currentParts, key.value];
1102
- if (pathEquals(childParts, targetParts)) {
1103
- return { found: true, start: valueStart };
1104
- }
1105
- if (isPathPrefix(childParts, targetParts)) {
1106
- const nested = visitValue(valueStart, childParts);
1107
- if (nested.found) return nested;
1131
+ if (pathMatchesPattern(childParts, targetParts)) {
1132
+ matches.push({
1133
+ path: childParts.join("."),
1134
+ start: valueStart
1135
+ });
1136
+ } else if (isPathPrefix(childParts, targetParts)) {
1137
+ visitValue(valueStart, childParts);
1108
1138
  }
1109
1139
  const skipped = skipCompleteValue(args.text, valueStart);
1110
1140
  if (!skipped.complete || skipped.end === void 0) {
1111
- return { found: false };
1141
+ return;
1112
1142
  }
1113
1143
  i = skipWhitespace(args.text, skipped.end);
1114
1144
  if (args.text[i] === ",") {
1115
1145
  i = skipWhitespace(args.text, i + 1);
1116
1146
  continue;
1117
1147
  }
1118
- if (args.text[i] === "}") return { found: false };
1119
- return { found: false };
1148
+ if (args.text[i] === "}") return;
1149
+ return;
1120
1150
  }
1121
- return { found: false };
1122
1151
  };
1123
1152
  const visitArray = (start, currentParts) => {
1124
1153
  let i = skipWhitespace(args.text, start);
1125
1154
  let index = 0;
1126
1155
  while (i < args.text.length) {
1127
- if (args.text[i] === "]") return { found: false };
1156
+ if (args.text[i] === "]") return;
1128
1157
  const childParts = [...currentParts, String(index)];
1129
- if (pathEquals(childParts, targetParts)) {
1130
- return { found: true, start: i };
1131
- }
1132
- if (isPathPrefix(childParts, targetParts)) {
1133
- const nested = visitValue(i, childParts);
1134
- if (nested.found) return nested;
1158
+ if (pathMatchesPattern(childParts, targetParts)) {
1159
+ matches.push({
1160
+ path: childParts.join("."),
1161
+ start: i
1162
+ });
1163
+ } else if (isPathPrefix(childParts, targetParts)) {
1164
+ visitValue(i, childParts);
1135
1165
  }
1136
1166
  const skipped = skipCompleteValue(args.text, i);
1137
1167
  if (!skipped.complete || skipped.end === void 0) {
1138
- return { found: false };
1168
+ return;
1139
1169
  }
1140
1170
  i = skipWhitespace(args.text, skipped.end);
1141
1171
  if (args.text[i] === ",") {
@@ -1143,12 +1173,12 @@ var locateValueStart = (args) => {
1143
1173
  i = skipWhitespace(args.text, i + 1);
1144
1174
  continue;
1145
1175
  }
1146
- if (args.text[i] === "]") return { found: false };
1147
- return { found: false };
1176
+ if (args.text[i] === "]") return;
1177
+ return;
1148
1178
  }
1149
- return { found: false };
1150
1179
  };
1151
- return visitValue(0, []);
1180
+ visitValue(0, []);
1181
+ return matches;
1152
1182
  };
1153
1183
  var extractCompletedValueAt = (args) => {
1154
1184
  const start = skipWhitespace(args.text, args.start);
@@ -1249,26 +1279,21 @@ var extractCompletedNestedValueAt = (args) => {
1249
1279
  complete: false
1250
1280
  };
1251
1281
  };
1252
- var extractCompletedFieldValue = (args) => {
1253
- const located = locateValueStart(args);
1254
- if (!located.found || located.start === void 0) {
1255
- return {
1256
- found: located.found,
1257
- complete: false
1258
- };
1282
+ var extractCompletedFieldValues = (args) => {
1283
+ const located = locateValueStarts(args);
1284
+ const values = [];
1285
+ for (const match of located) {
1286
+ const parsed = extractCompletedValueAt({
1287
+ text: args.text,
1288
+ start: match.start
1289
+ });
1290
+ if (!parsed.complete) continue;
1291
+ values.push({
1292
+ path: match.path,
1293
+ value: parsed.value
1294
+ });
1259
1295
  }
1260
- const parsed = extractCompletedValueAt({
1261
- text: args.text,
1262
- start: located.start
1263
- });
1264
- return parsed.complete ? {
1265
- found: true,
1266
- complete: true,
1267
- value: parsed.value
1268
- } : {
1269
- found: true,
1270
- complete: false
1271
- };
1296
+ return values;
1272
1297
  };
1273
1298
  var extractCompletedArrayItems = (args) => {
1274
1299
  const located = locateValueStart(args);
@@ -1338,6 +1363,20 @@ var extractCompletedArrayItems = (args) => {
1338
1363
  }
1339
1364
  return items;
1340
1365
  };
1366
+ var extractCompletedArrayItemGroups = (args) => {
1367
+ return locateValueStarts(args).flatMap((match) => {
1368
+ const items = extractCompletedArrayItems({
1369
+ text: args.text,
1370
+ path: match.path
1371
+ });
1372
+ return items.length > 0 ? [
1373
+ {
1374
+ path: match.path,
1375
+ items
1376
+ }
1377
+ ] : [];
1378
+ });
1379
+ };
1341
1380
  var extractStreamingStringValue = (args) => {
1342
1381
  const located = locateValueStart(args);
1343
1382
  if (!located.found || located.start === void 0) {
@@ -1408,6 +1447,21 @@ var extractStreamingStringValue = (args) => {
1408
1447
  value
1409
1448
  };
1410
1449
  };
1450
+ var extractStreamingStringValues = (args) => {
1451
+ return locateValueStarts(args).flatMap((match) => {
1452
+ const current = extractStreamingStringValue({
1453
+ text: args.text,
1454
+ path: match.path
1455
+ });
1456
+ return current.found ? [
1457
+ {
1458
+ path: match.path,
1459
+ complete: current.complete,
1460
+ value: current.value
1461
+ }
1462
+ ] : [];
1463
+ });
1464
+ };
1411
1465
 
1412
1466
  // src/reason/use-reason.ts
1413
1467
  var mergeUsage = (left, right) => {
@@ -1507,9 +1561,17 @@ async function useReason(args) {
1507
1561
  modelId: args.model.modelId,
1508
1562
  stream: args.stream ?? args.model.options?.streaming ?? true,
1509
1563
  emit: args.emit ?? true,
1564
+ ...args.telemetry?.operation ? { operation: args.telemetry.operation } : {},
1565
+ ...args.telemetry?.prompt?.name ? { promptName: args.telemetry.prompt.name } : {},
1566
+ ...args.telemetry?.prompt?.version !== void 0 ? { promptVersion: args.telemetry.prompt.version } : {},
1567
+ ...args.telemetry?.prompt?.type ? { promptType: args.telemetry.prompt.type } : {},
1510
1568
  hasOutputSchema: Boolean(args.outputSchema),
1511
1569
  hasInterrupt: Boolean(args.interrupt),
1512
1570
  hasStructured: Boolean(args.structured)
1571
+ },
1572
+ telemetry: {
1573
+ ...args.telemetry ?? {},
1574
+ input: args.telemetry?.input ?? args.input
1513
1575
  }
1514
1576
  });
1515
1577
  const suppressTextStream = Boolean(args.outputSchema || args.interrupt);
@@ -1558,70 +1620,73 @@ async function useReason(args) {
1558
1620
  onTextChunk: (delta) => {
1559
1621
  firstText += delta;
1560
1622
  finalText = firstText;
1561
- for (const path of setFieldPaths) {
1562
- const current = extractCompletedFieldValue({
1623
+ for (const fieldPath of setFieldPaths) {
1624
+ const values = extractCompletedFieldValues({
1563
1625
  text: firstText,
1564
- path
1565
- });
1566
- if (!current.found || !current.complete) continue;
1567
- const nextSerialized = JSON.stringify(current.value);
1568
- if (emittedSetValues.get(path) === nextSerialized) continue;
1569
- emittedSetValues.set(path, nextSerialized);
1570
- emitStructuredData({
1571
- kind: "set",
1572
- path,
1573
- value: current.value,
1574
- dataType: args.structured?.dataType ?? "reason-output",
1575
- ...args.structured?.schemaId ? { schemaId: args.structured.schemaId } : {},
1576
- ...args.structured?.schemaVersion ? { schemaVersion: args.structured.schemaVersion } : {},
1577
- ...id ? { id } : {},
1578
- streamId: opId
1626
+ path: fieldPath
1579
1627
  });
1628
+ for (const { path, value } of values) {
1629
+ const nextSerialized = JSON.stringify(value);
1630
+ if (emittedSetValues.get(path) === nextSerialized) continue;
1631
+ emittedSetValues.set(path, nextSerialized);
1632
+ emitStructuredData({
1633
+ kind: "set",
1634
+ path,
1635
+ value,
1636
+ dataType: args.structured?.dataType ?? "reason-output",
1637
+ ...args.structured?.schemaId ? { schemaId: args.structured.schemaId } : {},
1638
+ ...args.structured?.schemaVersion ? { schemaVersion: args.structured.schemaVersion } : {},
1639
+ ...id ? { id } : {},
1640
+ streamId: opId
1641
+ });
1642
+ }
1580
1643
  }
1581
- for (const path of appendFieldPaths) {
1582
- const items = extractCompletedArrayItems({
1644
+ for (const fieldPath of appendFieldPaths) {
1645
+ const groups = extractCompletedArrayItemGroups({
1583
1646
  text: firstText,
1584
- path
1585
- });
1586
- const emittedAppendCount = emittedAppendCounts.get(path) ?? 0;
1587
- if (items.length <= emittedAppendCount) continue;
1588
- const nextItems = items.slice(emittedAppendCount);
1589
- emittedAppendCounts.set(path, items.length);
1590
- emitStructuredData({
1591
- kind: "append",
1592
- path,
1593
- items: nextItems,
1594
- dataType: args.structured?.dataType ?? "reason-output",
1595
- ...args.structured?.schemaId ? { schemaId: args.structured.schemaId } : {},
1596
- ...args.structured?.schemaVersion ? { schemaVersion: args.structured.schemaVersion } : {},
1597
- ...id ? { id } : {},
1598
- streamId: opId
1647
+ path: fieldPath
1599
1648
  });
1649
+ for (const { path, items } of groups) {
1650
+ const emittedAppendCount = emittedAppendCounts.get(path) ?? 0;
1651
+ if (items.length <= emittedAppendCount) continue;
1652
+ const nextItems = items.slice(emittedAppendCount);
1653
+ emittedAppendCounts.set(path, items.length);
1654
+ emitStructuredData({
1655
+ kind: "append",
1656
+ path,
1657
+ items: nextItems,
1658
+ dataType: args.structured?.dataType ?? "reason-output",
1659
+ ...args.structured?.schemaId ? { schemaId: args.structured.schemaId } : {},
1660
+ ...args.structured?.schemaVersion ? { schemaVersion: args.structured.schemaVersion } : {},
1661
+ ...id ? { id } : {},
1662
+ streamId: opId
1663
+ });
1664
+ }
1600
1665
  }
1601
- for (const path of textDeltaFieldPaths) {
1602
- const current = extractStreamingStringValue({
1666
+ for (const fieldPath of textDeltaFieldPaths) {
1667
+ const values = extractStreamingStringValues({
1603
1668
  text: firstText,
1604
- path
1669
+ path: fieldPath
1605
1670
  });
1606
- const emittedTextValue = emittedTextValues.get(path) ?? "";
1607
- if (!current.found || current.value.length <= emittedTextValue.length || !current.value.startsWith(emittedTextValue)) {
1608
- continue;
1671
+ for (const { path, value } of values) {
1672
+ const emittedTextValue = emittedTextValues.get(path) ?? "";
1673
+ if (value.length <= emittedTextValue.length || !value.startsWith(emittedTextValue)) {
1674
+ continue;
1675
+ }
1676
+ const nextDelta = value.slice(emittedTextValue.length);
1677
+ emittedTextValues.set(path, value);
1678
+ if (nextDelta.length === 0) continue;
1679
+ emitStructuredData({
1680
+ kind: "text-delta",
1681
+ path,
1682
+ delta: nextDelta,
1683
+ dataType: args.structured?.dataType ?? "reason-output",
1684
+ ...args.structured?.schemaId ? { schemaId: args.structured.schemaId } : {},
1685
+ ...args.structured?.schemaVersion ? { schemaVersion: args.structured.schemaVersion } : {},
1686
+ ...id ? { id } : {},
1687
+ streamId: opId
1688
+ });
1609
1689
  }
1610
- const nextDelta = current.value.slice(
1611
- emittedTextValue.length
1612
- );
1613
- emittedTextValues.set(path, current.value);
1614
- if (nextDelta.length === 0) continue;
1615
- emitStructuredData({
1616
- kind: "text-delta",
1617
- path,
1618
- delta: nextDelta,
1619
- dataType: args.structured?.dataType ?? "reason-output",
1620
- ...args.structured?.schemaId ? { schemaId: args.structured.schemaId } : {},
1621
- ...args.structured?.schemaVersion ? { schemaVersion: args.structured.schemaVersion } : {},
1622
- ...id ? { id } : {},
1623
- streamId: opId
1624
- });
1625
1690
  }
1626
1691
  }
1627
1692
  } : {}
@@ -1811,6 +1876,10 @@ async function useReason(args) {
1811
1876
  textLength: finalText.length,
1812
1877
  resumedFromCheckpoint: Boolean(existingCheckpoint),
1813
1878
  interrupted: Boolean(interruptResponse !== void 0)
1879
+ },
1880
+ telemetry: {
1881
+ ...args.telemetry ?? {},
1882
+ output: args.telemetry?.output ?? finalOutput ?? finalText
1814
1883
  }
1815
1884
  });
1816
1885
  return result;