@diegoaltoworks/chatter 0.55.0 → 0.56.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/dist/index.js CHANGED
@@ -36,6 +36,7 @@ __export(index_exports, {
36
36
  VectorStore: () => VectorStore,
37
37
  answerOnce: () => answerOnce,
38
38
  answerStream: () => answerStream,
39
+ applyTransformReply: () => applyTransformReply,
39
40
  chatBodyLimit: () => chatBodyLimit,
40
41
  completeOnce: () => completeOnce,
41
42
  completeStream: () => completeStream,
@@ -282,6 +283,18 @@ async function answerOnce({
282
283
  }
283
284
  return completeOnce({ client, system, messages, temperature, model });
284
285
  }
286
+ async function applyTransformReply(transformReply, input, logger) {
287
+ if (!transformReply) return input.text;
288
+ try {
289
+ return await transformReply(input);
290
+ } catch (error) {
291
+ logger?.error(
292
+ `transformReply threw for channel "${input.channel}"; sending the original reply`,
293
+ error
294
+ );
295
+ return input.text;
296
+ }
297
+ }
285
298
  async function* answerStream({
286
299
  answerFn,
287
300
  client,
@@ -1002,6 +1015,11 @@ async function createMCPServer(config) {
1002
1015
  conversationId: convId,
1003
1016
  model
1004
1017
  });
1018
+ const replyText = await applyTransformReply(
1019
+ config.transformReply,
1020
+ { channel: "mcp-public", conversationId: convId, text: result.content },
1021
+ log
1022
+ );
1005
1023
  const cost = calculateCost(result.usage, config.openai.pricing);
1006
1024
  const duration = Date.now() - startTime;
1007
1025
  await logger.logChatInteraction(
@@ -1009,7 +1027,7 @@ async function createMCPServer(config) {
1009
1027
  convId,
1010
1028
  conversationMessages,
1011
1029
  ctx,
1012
- result.content,
1030
+ replyText ?? "",
1013
1031
  duration,
1014
1032
  cost
1015
1033
  ).catch((err) => log.error("Logging error:", err));
@@ -1017,7 +1035,7 @@ async function createMCPServer(config) {
1017
1035
  content: [
1018
1036
  {
1019
1037
  type: "text",
1020
- text: result.content
1038
+ text: replyText ?? ""
1021
1039
  }
1022
1040
  ],
1023
1041
  _meta: {
@@ -1083,6 +1101,11 @@ async function createMCPServer(config) {
1083
1101
  conversationId: convId,
1084
1102
  model
1085
1103
  });
1104
+ const replyText = await applyTransformReply(
1105
+ config.transformReply,
1106
+ { channel: "mcp-private", conversationId: convId, text: result.content },
1107
+ log
1108
+ );
1086
1109
  const cost = calculateCost(result.usage, config.openai.pricing);
1087
1110
  const duration = Date.now() - startTime;
1088
1111
  await logger.logChatInteraction(
@@ -1090,7 +1113,7 @@ async function createMCPServer(config) {
1090
1113
  convId,
1091
1114
  conversationMessages,
1092
1115
  ctx,
1093
- result.content,
1116
+ replyText ?? "",
1094
1117
  duration,
1095
1118
  cost
1096
1119
  ).catch((err) => log.error("Logging error:", err));
@@ -1098,7 +1121,7 @@ async function createMCPServer(config) {
1098
1121
  content: [
1099
1122
  {
1100
1123
  type: "text",
1101
- text: result.content
1124
+ text: replyText ?? ""
1102
1125
  }
1103
1126
  ],
1104
1127
  _meta: {
@@ -1571,7 +1594,12 @@ function demoRoutes(deps) {
1571
1594
  mode: "public",
1572
1595
  model
1573
1596
  });
1574
- return c.json({ reply: out.content });
1597
+ const reply = await applyTransformReply(
1598
+ config.transformReply,
1599
+ { channel: "widget-demo", text: out.content },
1600
+ logger
1601
+ );
1602
+ return c.json({ reply: reply ?? "" });
1575
1603
  } catch (error) {
1576
1604
  const err = error;
1577
1605
  logger.error("Demo chat error:", err);
@@ -1614,7 +1642,7 @@ function oversizedBodyError(message) {
1614
1642
  return { error: { message, type: "invalid_request_error" } };
1615
1643
  }
1616
1644
  function openaiRoutes(deps) {
1617
- const { client, store, config, prompts, apiKeyManager } = deps;
1645
+ const { client, store, config, prompts, apiKeyManager, logger } = deps;
1618
1646
  const app = new import_hono2.Hono();
1619
1647
  const { limitPublic, limitPrivate } = createRateLimiter2(config);
1620
1648
  const requirePrivateJWT = createJWTMiddleware(config);
@@ -1709,13 +1737,18 @@ function openaiRoutes(deps) {
1709
1737
  temperature,
1710
1738
  model: serverModel
1711
1739
  });
1740
+ const reply = await applyTransformReply(
1741
+ config.transformReply,
1742
+ { channel: `openai-compat-${mode}`, sender, conversationId, text: out.content },
1743
+ logger
1744
+ );
1712
1745
  return c.json({
1713
1746
  id,
1714
1747
  object: "chat.completion",
1715
1748
  created,
1716
1749
  model: serverModel,
1717
1750
  choices: [
1718
- { index: 0, message: { role: "assistant", content: out.content }, finish_reason: "stop" }
1751
+ { index: 0, message: { role: "assistant", content: reply ?? "" }, finish_reason: "stop" }
1719
1752
  ],
1720
1753
  usage: out.usage
1721
1754
  });
@@ -1745,7 +1778,7 @@ function wantsStream(c) {
1745
1778
  return acc.includes("text/event-stream");
1746
1779
  }
1747
1780
  function privateRoutes(deps) {
1748
- const { client, store, config, prompts } = deps;
1781
+ const { client, store, config, prompts, logger } = deps;
1749
1782
  const app = new import_hono3.Hono();
1750
1783
  const requirePrivateJWT = createJWTMiddleware(config);
1751
1784
  const { limitPrivate } = createRateLimiter2(config);
@@ -1800,7 +1833,12 @@ function privateRoutes(deps) {
1800
1833
  sender,
1801
1834
  model
1802
1835
  });
1803
- return c.json({ reply: out.content });
1836
+ const reply = await applyTransformReply(
1837
+ config.transformReply,
1838
+ { channel: "widget-private", sender, text: out.content },
1839
+ logger
1840
+ );
1841
+ return c.json({ reply: reply ?? "" });
1804
1842
  });
1805
1843
  return app;
1806
1844
  }
@@ -1862,7 +1900,12 @@ function publicRoutes(deps) {
1862
1900
  });
1863
1901
  }
1864
1902
  const out = await answerOnce({ answerFn, client, system, messages, mode: "public", model });
1865
- return c.json({ reply: out.content });
1903
+ const reply = await applyTransformReply(
1904
+ config.transformReply,
1905
+ { channel: "widget-public", text: out.content },
1906
+ logger
1907
+ );
1908
+ return c.json({ reply: reply ?? "" });
1866
1909
  });
1867
1910
  return app;
1868
1911
  }
@@ -2201,6 +2244,7 @@ function createShortener(config, fetchImpl = fetch) {
2201
2244
  VectorStore,
2202
2245
  answerOnce,
2203
2246
  answerStream,
2247
+ applyTransformReply,
2204
2248
  chatBodyLimit,
2205
2249
  completeOnce,
2206
2250
  completeStream,
package/dist/index.mjs CHANGED
@@ -209,6 +209,18 @@ async function answerOnce({
209
209
  }
210
210
  return completeOnce({ client, system, messages, temperature, model });
211
211
  }
212
+ async function applyTransformReply(transformReply, input, logger) {
213
+ if (!transformReply) return input.text;
214
+ try {
215
+ return await transformReply(input);
216
+ } catch (error) {
217
+ logger?.error(
218
+ `transformReply threw for channel "${input.channel}"; sending the original reply`,
219
+ error
220
+ );
221
+ return input.text;
222
+ }
223
+ }
212
224
  async function* answerStream({
213
225
  answerFn,
214
226
  client,
@@ -929,6 +941,11 @@ async function createMCPServer(config) {
929
941
  conversationId: convId,
930
942
  model
931
943
  });
944
+ const replyText = await applyTransformReply(
945
+ config.transformReply,
946
+ { channel: "mcp-public", conversationId: convId, text: result.content },
947
+ log
948
+ );
932
949
  const cost = calculateCost(result.usage, config.openai.pricing);
933
950
  const duration = Date.now() - startTime;
934
951
  await logger.logChatInteraction(
@@ -936,7 +953,7 @@ async function createMCPServer(config) {
936
953
  convId,
937
954
  conversationMessages,
938
955
  ctx,
939
- result.content,
956
+ replyText ?? "",
940
957
  duration,
941
958
  cost
942
959
  ).catch((err) => log.error("Logging error:", err));
@@ -944,7 +961,7 @@ async function createMCPServer(config) {
944
961
  content: [
945
962
  {
946
963
  type: "text",
947
- text: result.content
964
+ text: replyText ?? ""
948
965
  }
949
966
  ],
950
967
  _meta: {
@@ -1010,6 +1027,11 @@ async function createMCPServer(config) {
1010
1027
  conversationId: convId,
1011
1028
  model
1012
1029
  });
1030
+ const replyText = await applyTransformReply(
1031
+ config.transformReply,
1032
+ { channel: "mcp-private", conversationId: convId, text: result.content },
1033
+ log
1034
+ );
1013
1035
  const cost = calculateCost(result.usage, config.openai.pricing);
1014
1036
  const duration = Date.now() - startTime;
1015
1037
  await logger.logChatInteraction(
@@ -1017,7 +1039,7 @@ async function createMCPServer(config) {
1017
1039
  convId,
1018
1040
  conversationMessages,
1019
1041
  ctx,
1020
- result.content,
1042
+ replyText ?? "",
1021
1043
  duration,
1022
1044
  cost
1023
1045
  ).catch((err) => log.error("Logging error:", err));
@@ -1025,7 +1047,7 @@ async function createMCPServer(config) {
1025
1047
  content: [
1026
1048
  {
1027
1049
  type: "text",
1028
- text: result.content
1050
+ text: replyText ?? ""
1029
1051
  }
1030
1052
  ],
1031
1053
  _meta: {
@@ -1498,7 +1520,12 @@ function demoRoutes(deps) {
1498
1520
  mode: "public",
1499
1521
  model
1500
1522
  });
1501
- return c.json({ reply: out.content });
1523
+ const reply = await applyTransformReply(
1524
+ config.transformReply,
1525
+ { channel: "widget-demo", text: out.content },
1526
+ logger
1527
+ );
1528
+ return c.json({ reply: reply ?? "" });
1502
1529
  } catch (error) {
1503
1530
  const err = error;
1504
1531
  logger.error("Demo chat error:", err);
@@ -1541,7 +1568,7 @@ function oversizedBodyError(message) {
1541
1568
  return { error: { message, type: "invalid_request_error" } };
1542
1569
  }
1543
1570
  function openaiRoutes(deps) {
1544
- const { client, store, config, prompts, apiKeyManager } = deps;
1571
+ const { client, store, config, prompts, apiKeyManager, logger } = deps;
1545
1572
  const app = new Hono2();
1546
1573
  const { limitPublic, limitPrivate } = createRateLimiter2(config);
1547
1574
  const requirePrivateJWT = createJWTMiddleware(config);
@@ -1636,13 +1663,18 @@ function openaiRoutes(deps) {
1636
1663
  temperature,
1637
1664
  model: serverModel
1638
1665
  });
1666
+ const reply = await applyTransformReply(
1667
+ config.transformReply,
1668
+ { channel: `openai-compat-${mode}`, sender, conversationId, text: out.content },
1669
+ logger
1670
+ );
1639
1671
  return c.json({
1640
1672
  id,
1641
1673
  object: "chat.completion",
1642
1674
  created,
1643
1675
  model: serverModel,
1644
1676
  choices: [
1645
- { index: 0, message: { role: "assistant", content: out.content }, finish_reason: "stop" }
1677
+ { index: 0, message: { role: "assistant", content: reply ?? "" }, finish_reason: "stop" }
1646
1678
  ],
1647
1679
  usage: out.usage
1648
1680
  });
@@ -1672,7 +1704,7 @@ function wantsStream(c) {
1672
1704
  return acc.includes("text/event-stream");
1673
1705
  }
1674
1706
  function privateRoutes(deps) {
1675
- const { client, store, config, prompts } = deps;
1707
+ const { client, store, config, prompts, logger } = deps;
1676
1708
  const app = new Hono3();
1677
1709
  const requirePrivateJWT = createJWTMiddleware(config);
1678
1710
  const { limitPrivate } = createRateLimiter2(config);
@@ -1727,7 +1759,12 @@ function privateRoutes(deps) {
1727
1759
  sender,
1728
1760
  model
1729
1761
  });
1730
- return c.json({ reply: out.content });
1762
+ const reply = await applyTransformReply(
1763
+ config.transformReply,
1764
+ { channel: "widget-private", sender, text: out.content },
1765
+ logger
1766
+ );
1767
+ return c.json({ reply: reply ?? "" });
1731
1768
  });
1732
1769
  return app;
1733
1770
  }
@@ -1789,7 +1826,12 @@ function publicRoutes(deps) {
1789
1826
  });
1790
1827
  }
1791
1828
  const out = await answerOnce({ answerFn, client, system, messages, mode: "public", model });
1792
- return c.json({ reply: out.content });
1829
+ const reply = await applyTransformReply(
1830
+ config.transformReply,
1831
+ { channel: "widget-public", text: out.content },
1832
+ logger
1833
+ );
1834
+ return c.json({ reply: reply ?? "" });
1793
1835
  });
1794
1836
  return app;
1795
1837
  }
@@ -2126,6 +2168,7 @@ export {
2126
2168
  VectorStore,
2127
2169
  answerOnce,
2128
2170
  answerStream,
2171
+ applyTransformReply,
2129
2172
  chatBodyLimit,
2130
2173
  completeOnce,
2131
2174
  completeStream,
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAoBH,YAAY,EACV,WAAW,EACX,QAAQ,EACR,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,gBAAgB,GACjB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,gBAAgB,qEAwS7D"}
1
+ {"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAoBH,YAAY,EACV,WAAW,EACX,QAAQ,EACR,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,gBAAgB,GACjB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,gBAAgB,qEAoT7D"}
@@ -104,6 +104,18 @@ async function answerOnce({
104
104
  }
105
105
  return completeOnce({ client, system, messages, temperature, model });
106
106
  }
107
+ async function applyTransformReply(transformReply, input, logger) {
108
+ if (!transformReply) return input.text;
109
+ try {
110
+ return await transformReply(input);
111
+ } catch (error) {
112
+ logger?.error(
113
+ `transformReply threw for channel "${input.channel}"; sending the original reply`,
114
+ error
115
+ );
116
+ return input.text;
117
+ }
118
+ }
107
119
 
108
120
  // src/core/buckets.ts
109
121
  function defaultBuckets(mode) {
@@ -704,6 +716,11 @@ async function createMCPServer(config) {
704
716
  conversationId: convId,
705
717
  model
706
718
  });
719
+ const replyText = await applyTransformReply(
720
+ config.transformReply,
721
+ { channel: "mcp-public", conversationId: convId, text: result.content },
722
+ log
723
+ );
707
724
  const cost = calculateCost(result.usage, config.openai.pricing);
708
725
  const duration = Date.now() - startTime;
709
726
  await logger.logChatInteraction(
@@ -711,7 +728,7 @@ async function createMCPServer(config) {
711
728
  convId,
712
729
  conversationMessages,
713
730
  ctx,
714
- result.content,
731
+ replyText ?? "",
715
732
  duration,
716
733
  cost
717
734
  ).catch((err) => log.error("Logging error:", err));
@@ -719,7 +736,7 @@ async function createMCPServer(config) {
719
736
  content: [
720
737
  {
721
738
  type: "text",
722
- text: result.content
739
+ text: replyText ?? ""
723
740
  }
724
741
  ],
725
742
  _meta: {
@@ -785,6 +802,11 @@ async function createMCPServer(config) {
785
802
  conversationId: convId,
786
803
  model
787
804
  });
805
+ const replyText = await applyTransformReply(
806
+ config.transformReply,
807
+ { channel: "mcp-private", conversationId: convId, text: result.content },
808
+ log
809
+ );
788
810
  const cost = calculateCost(result.usage, config.openai.pricing);
789
811
  const duration = Date.now() - startTime;
790
812
  await logger.logChatInteraction(
@@ -792,7 +814,7 @@ async function createMCPServer(config) {
792
814
  convId,
793
815
  conversationMessages,
794
816
  ctx,
795
- result.content,
817
+ replyText ?? "",
796
818
  duration,
797
819
  cost
798
820
  ).catch((err) => log.error("Logging error:", err));
@@ -800,7 +822,7 @@ async function createMCPServer(config) {
800
822
  content: [
801
823
  {
802
824
  type: "text",
803
- text: result.content
825
+ text: replyText ?? ""
804
826
  }
805
827
  ],
806
828
  _meta: {
@@ -70,6 +70,18 @@ async function answerOnce({
70
70
  }
71
71
  return completeOnce({ client, system, messages, temperature, model });
72
72
  }
73
+ async function applyTransformReply(transformReply, input, logger) {
74
+ if (!transformReply) return input.text;
75
+ try {
76
+ return await transformReply(input);
77
+ } catch (error) {
78
+ logger?.error(
79
+ `transformReply threw for channel "${input.channel}"; sending the original reply`,
80
+ error
81
+ );
82
+ return input.text;
83
+ }
84
+ }
73
85
 
74
86
  // src/core/buckets.ts
75
87
  function defaultBuckets(mode) {
@@ -670,6 +682,11 @@ async function createMCPServer(config) {
670
682
  conversationId: convId,
671
683
  model
672
684
  });
685
+ const replyText = await applyTransformReply(
686
+ config.transformReply,
687
+ { channel: "mcp-public", conversationId: convId, text: result.content },
688
+ log
689
+ );
673
690
  const cost = calculateCost(result.usage, config.openai.pricing);
674
691
  const duration = Date.now() - startTime;
675
692
  await logger.logChatInteraction(
@@ -677,7 +694,7 @@ async function createMCPServer(config) {
677
694
  convId,
678
695
  conversationMessages,
679
696
  ctx,
680
- result.content,
697
+ replyText ?? "",
681
698
  duration,
682
699
  cost
683
700
  ).catch((err) => log.error("Logging error:", err));
@@ -685,7 +702,7 @@ async function createMCPServer(config) {
685
702
  content: [
686
703
  {
687
704
  type: "text",
688
- text: result.content
705
+ text: replyText ?? ""
689
706
  }
690
707
  ],
691
708
  _meta: {
@@ -751,6 +768,11 @@ async function createMCPServer(config) {
751
768
  conversationId: convId,
752
769
  model
753
770
  });
771
+ const replyText = await applyTransformReply(
772
+ config.transformReply,
773
+ { channel: "mcp-private", conversationId: convId, text: result.content },
774
+ log
775
+ );
754
776
  const cost = calculateCost(result.usage, config.openai.pricing);
755
777
  const duration = Date.now() - startTime;
756
778
  await logger.logChatInteraction(
@@ -758,7 +780,7 @@ async function createMCPServer(config) {
758
780
  convId,
759
781
  conversationMessages,
760
782
  ctx,
761
- result.content,
783
+ replyText ?? "",
762
784
  duration,
763
785
  cost
764
786
  ).catch((err) => log.error("Logging error:", err));
@@ -766,7 +788,7 @@ async function createMCPServer(config) {
766
788
  content: [
767
789
  {
768
790
  type: "text",
769
- text: result.content
791
+ text: replyText ?? ""
770
792
  }
771
793
  ],
772
794
  _meta: {
@@ -1 +1 @@
1
- {"version":3,"file":"demo.d.ts","sourceRoot":"","sources":["../../src/routes/demo.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAY5B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAuFnD,wBAAgB,UAAU,CAAC,IAAI,EAAE,kBAAkB,8EAoHlD"}
1
+ {"version":3,"file":"demo.d.ts","sourceRoot":"","sources":["../../src/routes/demo.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAY5B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAuFnD,wBAAgB,UAAU,CAAC,IAAI,EAAE,kBAAkB,8EAyHlD"}
@@ -1 +1 @@
1
- {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/routes/openai.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAGH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAU5B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAsDnD,wBAAgB,YAAY,CAAC,IAAI,EAAE,kBAAkB,8EA8JpD"}
1
+ {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/routes/openai.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAGH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAU5B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAsDnD,wBAAgB,YAAY,CAAC,IAAI,EAAE,kBAAkB,8EAmKpD"}
@@ -1 +1 @@
1
- {"version":3,"file":"private.d.ts","sourceRoot":"","sources":["../../src/routes/private.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAS5B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AASnD,wBAAgB,aAAa,CAAC,IAAI,EAAE,kBAAkB,8EAuErD"}
1
+ {"version":3,"file":"private.d.ts","sourceRoot":"","sources":["../../src/routes/private.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAS5B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AASnD,wBAAgB,aAAa,CAAC,IAAI,EAAE,kBAAkB,8EA4ErD"}
@@ -1 +1 @@
1
- {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/routes/public.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAW5B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AASnD,wBAAgB,YAAY,CAAC,IAAI,EAAE,kBAAkB,8EAuEpD"}
1
+ {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/routes/public.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAW5B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AASnD,wBAAgB,YAAY,CAAC,IAAI,EAAE,kBAAkB,8EA4EpD"}
package/dist/server.js CHANGED
@@ -249,6 +249,18 @@ async function answerOnce({
249
249
  }
250
250
  return completeOnce({ client, system, messages, temperature, model });
251
251
  }
252
+ async function applyTransformReply(transformReply, input, logger) {
253
+ if (!transformReply) return input.text;
254
+ try {
255
+ return await transformReply(input);
256
+ } catch (error) {
257
+ logger?.error(
258
+ `transformReply threw for channel "${input.channel}"; sending the original reply`,
259
+ error
260
+ );
261
+ return input.text;
262
+ }
263
+ }
252
264
  async function* answerStream({
253
265
  answerFn,
254
266
  client,
@@ -1080,7 +1092,12 @@ function demoRoutes(deps) {
1080
1092
  mode: "public",
1081
1093
  model
1082
1094
  });
1083
- return c.json({ reply: out.content });
1095
+ const reply = await applyTransformReply(
1096
+ config.transformReply,
1097
+ { channel: "widget-demo", text: out.content },
1098
+ logger
1099
+ );
1100
+ return c.json({ reply: reply ?? "" });
1084
1101
  } catch (error) {
1085
1102
  const err = error;
1086
1103
  logger.error("Demo chat error:", err);
@@ -1204,7 +1221,7 @@ function oversizedBodyError(message) {
1204
1221
  return { error: { message, type: "invalid_request_error" } };
1205
1222
  }
1206
1223
  function openaiRoutes(deps) {
1207
- const { client, store, config, prompts, apiKeyManager } = deps;
1224
+ const { client, store, config, prompts, apiKeyManager, logger } = deps;
1208
1225
  const app = new import_hono2.Hono();
1209
1226
  const { limitPublic, limitPrivate } = createRateLimiter(config);
1210
1227
  const requirePrivateJWT = createJWTMiddleware(config);
@@ -1299,13 +1316,18 @@ function openaiRoutes(deps) {
1299
1316
  temperature,
1300
1317
  model: serverModel
1301
1318
  });
1319
+ const reply = await applyTransformReply(
1320
+ config.transformReply,
1321
+ { channel: `openai-compat-${mode}`, sender, conversationId, text: out.content },
1322
+ logger
1323
+ );
1302
1324
  return c.json({
1303
1325
  id,
1304
1326
  object: "chat.completion",
1305
1327
  created,
1306
1328
  model: serverModel,
1307
1329
  choices: [
1308
- { index: 0, message: { role: "assistant", content: out.content }, finish_reason: "stop" }
1330
+ { index: 0, message: { role: "assistant", content: reply ?? "" }, finish_reason: "stop" }
1309
1331
  ],
1310
1332
  usage: out.usage
1311
1333
  });
@@ -1335,7 +1357,7 @@ function wantsStream(c) {
1335
1357
  return acc.includes("text/event-stream");
1336
1358
  }
1337
1359
  function privateRoutes(deps) {
1338
- const { client, store, config, prompts } = deps;
1360
+ const { client, store, config, prompts, logger } = deps;
1339
1361
  const app = new import_hono3.Hono();
1340
1362
  const requirePrivateJWT = createJWTMiddleware(config);
1341
1363
  const { limitPrivate } = createRateLimiter(config);
@@ -1390,7 +1412,12 @@ function privateRoutes(deps) {
1390
1412
  sender,
1391
1413
  model
1392
1414
  });
1393
- return c.json({ reply: out.content });
1415
+ const reply = await applyTransformReply(
1416
+ config.transformReply,
1417
+ { channel: "widget-private", sender, text: out.content },
1418
+ logger
1419
+ );
1420
+ return c.json({ reply: reply ?? "" });
1394
1421
  });
1395
1422
  return app;
1396
1423
  }
@@ -1548,7 +1575,12 @@ function publicRoutes(deps) {
1548
1575
  });
1549
1576
  }
1550
1577
  const out = await answerOnce({ answerFn, client, system, messages, mode: "public", model });
1551
- return c.json({ reply: out.content });
1578
+ const reply = await applyTransformReply(
1579
+ config.transformReply,
1580
+ { channel: "widget-public", text: out.content },
1581
+ logger
1582
+ );
1583
+ return c.json({ reply: reply ?? "" });
1552
1584
  });
1553
1585
  return app;
1554
1586
  }