opensentinel 2.1.1 → 3.1.1

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.
Files changed (268) hide show
  1. package/README.md +354 -283
  2. package/dist/archiver-AVNBYCKQ.js +15340 -0
  3. package/dist/archiver-AVNBYCKQ.js.map +1 -0
  4. package/dist/audit-logger-OBPR7CRO.js +22 -0
  5. package/dist/auth-UOX5K2BE.js +18 -0
  6. package/dist/autonomy-ZXDBDQUJ.js +86 -0
  7. package/dist/autonomy-ZXDBDQUJ.js.map +1 -0
  8. package/dist/aws-s3-Q4LLZZPD.js +146 -0
  9. package/dist/aws-s3-Q4LLZZPD.js.map +1 -0
  10. package/dist/backup-restore-PZ7CYYB7.js +16 -0
  11. package/dist/blocks-R3PODY47.js +23 -0
  12. package/dist/bot-QRARP4UN.js +36 -0
  13. package/dist/brain-7XLLM3KC.js +56 -0
  14. package/dist/camera-monitor-M5CYKUU4.js +335 -0
  15. package/dist/camera-monitor-M5CYKUU4.js.map +1 -0
  16. package/dist/{charts-MMXM6BWW.js → charts-V7ARZNKF.js} +2 -2
  17. package/dist/chunk-22VGGA7S.js +330 -0
  18. package/dist/chunk-22VGGA7S.js.map +1 -0
  19. package/dist/chunk-35WYTA3C.js +382 -0
  20. package/dist/chunk-35WYTA3C.js.map +1 -0
  21. package/dist/chunk-3E2PSU2C.js +146 -0
  22. package/dist/chunk-3E2PSU2C.js.map +1 -0
  23. package/dist/{chunk-L3F43VPB.js → chunk-4GLYY4NN.js} +2 -2
  24. package/dist/{chunk-L3F43VPB.js.map → chunk-4GLYY4NN.js.map} +1 -1
  25. package/dist/{chunk-L3PDU3XN.js → chunk-4UOE5TUZ.js} +4 -4
  26. package/dist/{chunk-6SNHU3CY.js → chunk-66OJ3WB4.js} +2 -2
  27. package/dist/chunk-6KONMXQ6.js +297 -0
  28. package/dist/chunk-6KONMXQ6.js.map +1 -0
  29. package/dist/chunk-6PMVAAA7.js +196 -0
  30. package/dist/chunk-6PMVAAA7.js.map +1 -0
  31. package/dist/chunk-766ASQWE.js +32620 -0
  32. package/dist/chunk-766ASQWE.js.map +1 -0
  33. package/dist/chunk-7WQO5J2M.js +29 -0
  34. package/dist/chunk-7WQO5J2M.js.map +1 -0
  35. package/dist/chunk-APHSRMBS.js +148 -0
  36. package/dist/chunk-APHSRMBS.js.map +1 -0
  37. package/dist/{chunk-4LVWXUNC.js → chunk-AYUKPTSM.js} +57 -39
  38. package/dist/chunk-AYUKPTSM.js.map +1 -0
  39. package/dist/chunk-BIPYADGB.js +84 -0
  40. package/dist/chunk-BIPYADGB.js.map +1 -0
  41. package/dist/chunk-BRBWNV65.js +457 -0
  42. package/dist/chunk-BRBWNV65.js.map +1 -0
  43. package/dist/chunk-BXZ6EA52.js +382 -0
  44. package/dist/chunk-BXZ6EA52.js.map +1 -0
  45. package/dist/chunk-EVE7MIIY.js +290 -0
  46. package/dist/chunk-EVE7MIIY.js.map +1 -0
  47. package/dist/chunk-F3TTNID2.js +138 -0
  48. package/dist/chunk-F3TTNID2.js.map +1 -0
  49. package/dist/chunk-H5RQOFO2.js +190 -0
  50. package/dist/chunk-H5RQOFO2.js.map +1 -0
  51. package/dist/chunk-HN3F4WSW.js +145 -0
  52. package/dist/chunk-HN3F4WSW.js.map +1 -0
  53. package/dist/{chunk-6DRDKB45.js → chunk-I6BDYQIG.js} +20 -9
  54. package/dist/chunk-I6BDYQIG.js.map +1 -0
  55. package/dist/chunk-IZJMVV7O.js +347 -0
  56. package/dist/chunk-IZJMVV7O.js.map +1 -0
  57. package/dist/chunk-KM22GV7G.js +211 -0
  58. package/dist/chunk-KM22GV7G.js.map +1 -0
  59. package/dist/chunk-MGFBLVR7.js +103 -0
  60. package/dist/chunk-MGFBLVR7.js.map +1 -0
  61. package/dist/chunk-MQJ2ECQT.js +228 -0
  62. package/dist/chunk-MQJ2ECQT.js.map +1 -0
  63. package/dist/{chunk-F6QUZQGI.js → chunk-MXAPLSJ5.js} +2 -2
  64. package/dist/{chunk-GK3E2I7A.js → chunk-NHMBTUMW.js} +2 -2
  65. package/dist/chunk-NPRTSZIF.js +131 -0
  66. package/dist/chunk-NPRTSZIF.js.map +1 -0
  67. package/dist/chunk-O7IH7JTI.js +1898 -0
  68. package/dist/chunk-O7IH7JTI.js.map +1 -0
  69. package/dist/chunk-OCVQGBJK.js +293 -0
  70. package/dist/chunk-OCVQGBJK.js.map +1 -0
  71. package/dist/chunk-P6QINGFL.js +332 -0
  72. package/dist/chunk-P6QINGFL.js.map +1 -0
  73. package/dist/chunk-PHDZKPNE.js +91 -0
  74. package/dist/chunk-PHDZKPNE.js.map +1 -0
  75. package/dist/chunk-PLDDJCW6.js +49 -0
  76. package/dist/chunk-PTGTGXV2.js +164 -0
  77. package/dist/chunk-PTGTGXV2.js.map +1 -0
  78. package/dist/chunk-REMIY4U2.js +171 -0
  79. package/dist/chunk-REMIY4U2.js.map +1 -0
  80. package/dist/chunk-RZ4YESBG.js +141 -0
  81. package/dist/chunk-RZ4YESBG.js.map +1 -0
  82. package/dist/chunk-SAX5MHK4.js +111 -0
  83. package/dist/chunk-SAX5MHK4.js.map +1 -0
  84. package/dist/{chunk-GVJVEWHI.js → chunk-SJSUSJ47.js} +2 -2
  85. package/dist/chunk-SPPMCAKG.js +777 -0
  86. package/dist/chunk-SPPMCAKG.js.map +1 -0
  87. package/dist/chunk-SVAPX2XN.js +2441 -0
  88. package/dist/chunk-SVAPX2XN.js.map +1 -0
  89. package/dist/chunk-TVEWKIK3.js +452 -0
  90. package/dist/chunk-TVEWKIK3.js.map +1 -0
  91. package/dist/{chunk-HH2HBTQM.js → chunk-TYAGMJNV.js} +5 -5
  92. package/dist/{chunk-JXUP2X7V.js → chunk-VEHFVBLI.js} +2 -2
  93. package/dist/chunk-VNX5GMTN.js +128 -0
  94. package/dist/chunk-VNX5GMTN.js.map +1 -0
  95. package/dist/chunk-VRD5CYRL.js +1568 -0
  96. package/dist/chunk-VRD5CYRL.js.map +1 -0
  97. package/dist/chunk-WLUHNG6X.js +122 -0
  98. package/dist/chunk-WLUHNG6X.js.map +1 -0
  99. package/dist/chunk-WRAKK6K6.js +265 -0
  100. package/dist/chunk-WRAKK6K6.js.map +1 -0
  101. package/dist/chunk-XKYRH4FM.js +681 -0
  102. package/dist/chunk-XKYRH4FM.js.map +1 -0
  103. package/dist/{chunk-GUBEEYDW.js → chunk-XMCVRVTF.js} +2 -2
  104. package/dist/{chunk-GUBEEYDW.js.map → chunk-XMCVRVTF.js.map} +1 -1
  105. package/dist/chunk-ZLZKF2PM.js +310 -0
  106. package/dist/chunk-ZLZKF2PM.js.map +1 -0
  107. package/dist/cli.js +5 -1
  108. package/dist/cli.js.map +1 -1
  109. package/dist/client-ZQSFPMOB.js +21 -0
  110. package/dist/clipboard-manager-TEO2GEDN.js +24 -0
  111. package/dist/commands/setup.js +3 -3
  112. package/dist/commands/setup.js.map +1 -1
  113. package/dist/commands/start.js +3 -3
  114. package/dist/commands/status.js +2 -2
  115. package/dist/commands/stop.js +2 -2
  116. package/dist/commands/utils.js +2 -2
  117. package/dist/cron-explain-HHQKPD3M.js +16 -0
  118. package/dist/crypto-4AP47IKC.js +14 -0
  119. package/dist/crypto-4AP47IKC.js.map +1 -0
  120. package/dist/databases-37X4CI2Y.js +21 -0
  121. package/dist/databases-37X4CI2Y.js.map +1 -0
  122. package/dist/discord-B3HUPGQ6.js +70 -0
  123. package/dist/discord-B3HUPGQ6.js.map +1 -0
  124. package/dist/dist-UISMLMFN.js +21847 -0
  125. package/dist/dist-UISMLMFN.js.map +1 -0
  126. package/dist/email-K7LO2IPB.js +268 -0
  127. package/dist/email-K7LO2IPB.js.map +1 -0
  128. package/dist/enhanced-retrieval-DNLLEM4Z.js +753 -0
  129. package/dist/enhanced-retrieval-DNLLEM4Z.js.map +1 -0
  130. package/dist/enrichment-pipeline-MNHNW65K.js +13 -0
  131. package/dist/enrichment-pipeline-MNHNW65K.js.map +1 -0
  132. package/dist/entity-resolution-Y3IUWEAT.js +24 -0
  133. package/dist/entity-resolution-Y3IUWEAT.js.map +1 -0
  134. package/dist/env-IWXUVTCB.js +12 -0
  135. package/dist/env-IWXUVTCB.js.map +1 -0
  136. package/dist/google-workspace-DKWUVNGC.js +169 -0
  137. package/dist/google-workspace-DKWUVNGC.js.map +1 -0
  138. package/dist/hash-tool-ULQYD7B5.js +22 -0
  139. package/dist/hash-tool-ULQYD7B5.js.map +1 -0
  140. package/dist/heartbeat-monitor-GCISLXI3.js +22 -0
  141. package/dist/heartbeat-monitor-GCISLXI3.js.map +1 -0
  142. package/dist/image-generation-OSU7FP6F.js +486 -0
  143. package/dist/image-generation-OSU7FP6F.js.map +1 -0
  144. package/dist/imessage-NGA2XF2V.js +35 -0
  145. package/dist/imessage-NGA2XF2V.js.map +1 -0
  146. package/dist/inbox-summarizer-NRI4S7IF.js +47 -0
  147. package/dist/inbox-summarizer-NRI4S7IF.js.map +1 -0
  148. package/dist/incident-response-C5J7Q6DT.js +244 -0
  149. package/dist/incident-response-C5J7Q6DT.js.map +1 -0
  150. package/dist/inventory-manager-352OHXWD.js +24 -0
  151. package/dist/inventory-manager-352OHXWD.js.map +1 -0
  152. package/dist/jira-GSGDBMIG.js +199 -0
  153. package/dist/jira-GSGDBMIG.js.map +1 -0
  154. package/dist/json-tool-QE2SYHEG.js +26 -0
  155. package/dist/json-tool-QE2SYHEG.js.map +1 -0
  156. package/dist/key-rotation-DPHU4ZTB.js +18 -0
  157. package/dist/key-rotation-DPHU4ZTB.js.map +1 -0
  158. package/dist/lib.d.ts +603 -11
  159. package/dist/lib.js +161 -35
  160. package/dist/lib.js.map +1 -1
  161. package/dist/mailchimp-KKNF6QJ7.js +152 -0
  162. package/dist/mailchimp-KKNF6QJ7.js.map +1 -0
  163. package/dist/matrix-QVHG76I7.js +279 -0
  164. package/dist/matrix-QVHG76I7.js.map +1 -0
  165. package/dist/{mcp-LS7Q3Z5W.js → mcp-3JI6W7ZE.js} +3 -3
  166. package/dist/mcp-3JI6W7ZE.js.map +1 -0
  167. package/dist/microsoft365-UCBKJHNX.js +164 -0
  168. package/dist/microsoft365-UCBKJHNX.js.map +1 -0
  169. package/dist/ocr-AC7NPX33.js +22 -0
  170. package/dist/ocr-AC7NPX33.js.map +1 -0
  171. package/dist/ollama-BOAMSPLJ.js +8 -0
  172. package/dist/ollama-BOAMSPLJ.js.map +1 -0
  173. package/dist/pages-MI523RB7.js +26 -0
  174. package/dist/pages-MI523RB7.js.map +1 -0
  175. package/dist/pair-JDFTERIK.js +24 -0
  176. package/dist/pair-JDFTERIK.js.map +1 -0
  177. package/dist/pairing-IFQYCPNS.js +10 -0
  178. package/dist/pairing-IFQYCPNS.js.map +1 -0
  179. package/dist/pdf-ALQVOEJR.js +17 -0
  180. package/dist/pdf-ALQVOEJR.js.map +1 -0
  181. package/dist/presentations-DSV5IHG5.js +1002 -0
  182. package/dist/presentations-DSV5IHG5.js.map +1 -0
  183. package/dist/prometheus-JNT2BD4L.js +10 -0
  184. package/dist/prometheus-JNT2BD4L.js.map +1 -0
  185. package/dist/providers-J4LYPHDR.js +19 -0
  186. package/dist/providers-J4LYPHDR.js.map +1 -0
  187. package/dist/qr-code-WIX4PB4U.js +16 -0
  188. package/dist/qr-code-WIX4PB4U.js.map +1 -0
  189. package/dist/quickbooks-XB4NII2S.js +190 -0
  190. package/dist/quickbooks-XB4NII2S.js.map +1 -0
  191. package/dist/regex-tool-W4ABRKGK.js +24 -0
  192. package/dist/regex-tool-W4ABRKGK.js.map +1 -0
  193. package/dist/scheduler-VK4WFERV.js +63 -0
  194. package/dist/scheduler-VK4WFERV.js.map +1 -0
  195. package/dist/search-BCLBO5E3.js +25 -0
  196. package/dist/search-BCLBO5E3.js.map +1 -0
  197. package/dist/sendgrid-RNXCAFKM.js +152 -0
  198. package/dist/sendgrid-RNXCAFKM.js.map +1 -0
  199. package/dist/shopify-NCXYJB4R.js +171 -0
  200. package/dist/shopify-NCXYJB4R.js.map +1 -0
  201. package/dist/signal-6CGDFYL2.js +35 -0
  202. package/dist/signal-6CGDFYL2.js.map +1 -0
  203. package/dist/slack-IZQWIKOH.js +75 -0
  204. package/dist/slack-IZQWIKOH.js.map +1 -0
  205. package/dist/sms-M3JIOTCW.js +23 -0
  206. package/dist/sms-M3JIOTCW.js.map +1 -0
  207. package/dist/{src-K7GASHRH.js → src-VYUE6LRA.js} +138 -32
  208. package/dist/src-VYUE6LRA.js.map +1 -0
  209. package/dist/stocks-XXWBPOCU.js +14 -0
  210. package/dist/stocks-XXWBPOCU.js.map +1 -0
  211. package/dist/text-transform-6SGUA5Z4.js +22 -0
  212. package/dist/text-transform-6SGUA5Z4.js.map +1 -0
  213. package/dist/tools-2RLEI2N6.js +38 -0
  214. package/dist/tools-2RLEI2N6.js.map +1 -0
  215. package/dist/tunnel-IWMXUML4.js +301 -0
  216. package/dist/tunnel-IWMXUML4.js.map +1 -0
  217. package/dist/twilio-53GEW5JT.js +139 -0
  218. package/dist/twilio-53GEW5JT.js.map +1 -0
  219. package/dist/unit-converter-ZYXMEZOE.js +14 -0
  220. package/dist/unit-converter-ZYXMEZOE.js.map +1 -0
  221. package/dist/whatsapp-LFX6YKCM.js +35 -0
  222. package/dist/whatsapp-LFX6YKCM.js.map +1 -0
  223. package/dist/word-document-7B6SJMAY.js +902 -0
  224. package/dist/word-document-7B6SJMAY.js.map +1 -0
  225. package/dist/xero-QYO66D45.js +162 -0
  226. package/dist/xero-QYO66D45.js.map +1 -0
  227. package/dist/zapier-webhook-TBZ5YF2A.js +106 -0
  228. package/dist/zapier-webhook-TBZ5YF2A.js.map +1 -0
  229. package/drizzle/0002_mushy_master_mold.sql +140 -0
  230. package/drizzle/meta/0002_snapshot.json +3637 -0
  231. package/drizzle/meta/_journal.json +7 -0
  232. package/package.json +100 -98
  233. package/dist/bot-KJ26BG56.js +0 -15
  234. package/dist/chunk-4LVWXUNC.js.map +0 -1
  235. package/dist/chunk-4TG2IG5K.js +0 -5249
  236. package/dist/chunk-4TG2IG5K.js.map +0 -1
  237. package/dist/chunk-6DRDKB45.js.map +0 -1
  238. package/dist/chunk-CI6Q63MM.js +0 -1613
  239. package/dist/chunk-CI6Q63MM.js.map +0 -1
  240. package/dist/chunk-KHNYJY2Z.js +0 -178
  241. package/dist/chunk-KHNYJY2Z.js.map +0 -1
  242. package/dist/chunk-NSBPE2FW.js +0 -17
  243. package/dist/discord-ZOJFTVTB.js +0 -49
  244. package/dist/imessage-JFRB6EJ7.js +0 -14
  245. package/dist/scheduler-EZ7CZMCS.js +0 -42
  246. package/dist/signal-T3MCSULM.js +0 -14
  247. package/dist/slack-N2M4FHAJ.js +0 -54
  248. package/dist/src-K7GASHRH.js.map +0 -1
  249. package/dist/tools-24GZHYRF.js +0 -16
  250. package/dist/whatsapp-VCRUPAO5.js +0 -14
  251. /package/dist/{bot-KJ26BG56.js.map → audit-logger-OBPR7CRO.js.map} +0 -0
  252. /package/dist/{chunk-NSBPE2FW.js.map → auth-UOX5K2BE.js.map} +0 -0
  253. /package/dist/{discord-ZOJFTVTB.js.map → backup-restore-PZ7CYYB7.js.map} +0 -0
  254. /package/dist/{imessage-JFRB6EJ7.js.map → blocks-R3PODY47.js.map} +0 -0
  255. /package/dist/{mcp-LS7Q3Z5W.js.map → bot-QRARP4UN.js.map} +0 -0
  256. /package/dist/{scheduler-EZ7CZMCS.js.map → brain-7XLLM3KC.js.map} +0 -0
  257. /package/dist/{charts-MMXM6BWW.js.map → charts-V7ARZNKF.js.map} +0 -0
  258. /package/dist/{chunk-L3PDU3XN.js.map → chunk-4UOE5TUZ.js.map} +0 -0
  259. /package/dist/{chunk-6SNHU3CY.js.map → chunk-66OJ3WB4.js.map} +0 -0
  260. /package/dist/{chunk-F6QUZQGI.js.map → chunk-MXAPLSJ5.js.map} +0 -0
  261. /package/dist/{chunk-GK3E2I7A.js.map → chunk-NHMBTUMW.js.map} +0 -0
  262. /package/dist/{signal-T3MCSULM.js.map → chunk-PLDDJCW6.js.map} +0 -0
  263. /package/dist/{chunk-GVJVEWHI.js.map → chunk-SJSUSJ47.js.map} +0 -0
  264. /package/dist/{chunk-HH2HBTQM.js.map → chunk-TYAGMJNV.js.map} +0 -0
  265. /package/dist/{chunk-JXUP2X7V.js.map → chunk-VEHFVBLI.js.map} +0 -0
  266. /package/dist/{slack-N2M4FHAJ.js.map → client-ZQSFPMOB.js.map} +0 -0
  267. /package/dist/{tools-24GZHYRF.js.map → clipboard-manager-TEO2GEDN.js.map} +0 -0
  268. /package/dist/{whatsapp-VCRUPAO5.js.map → cron-explain-HHQKPD3M.js.map} +0 -0
@@ -0,0 +1,290 @@
1
+ import {
2
+ isPathAllowed
3
+ } from "./chunk-CQ4JURG7.js";
4
+ import {
5
+ env
6
+ } from "./chunk-ZLZKF2PM.js";
7
+
8
+ // src/tools/image-analysis.ts
9
+ import Anthropic from "@anthropic-ai/sdk";
10
+ import { readFile } from "fs/promises";
11
+ var anthropic = new Anthropic({
12
+ apiKey: env.CLAUDE_API_KEY
13
+ });
14
+ var SUPPORTED_TYPES = {
15
+ ".jpg": "image/jpeg",
16
+ ".jpeg": "image/jpeg",
17
+ ".png": "image/png",
18
+ ".gif": "image/gif",
19
+ ".webp": "image/webp"
20
+ };
21
+ function getMimeType(filename) {
22
+ const ext = filename.toLowerCase().slice(filename.lastIndexOf("."));
23
+ return SUPPORTED_TYPES[ext] || null;
24
+ }
25
+ async function analyzeImageUrl(imageUrl, prompt) {
26
+ try {
27
+ const response = await anthropic.messages.create({
28
+ model: "claude-sonnet-4-20250514",
29
+ max_tokens: 1024,
30
+ messages: [
31
+ {
32
+ role: "user",
33
+ content: [
34
+ {
35
+ type: "image",
36
+ source: {
37
+ type: "url",
38
+ url: imageUrl
39
+ }
40
+ },
41
+ {
42
+ type: "text",
43
+ text: prompt || "Describe this image in detail."
44
+ }
45
+ ]
46
+ }
47
+ ]
48
+ });
49
+ const textContent = response.content.find((c) => c.type === "text");
50
+ return {
51
+ success: true,
52
+ analysis: textContent?.type === "text" ? textContent.text : void 0
53
+ };
54
+ } catch (error) {
55
+ return {
56
+ success: false,
57
+ error: error instanceof Error ? error.message : String(error)
58
+ };
59
+ }
60
+ }
61
+ async function analyzeImageFile(filePath, prompt) {
62
+ try {
63
+ if (!isPathAllowed(filePath)) {
64
+ return {
65
+ success: false,
66
+ error: "Access to this path is not allowed"
67
+ };
68
+ }
69
+ const mimeType = getMimeType(filePath);
70
+ if (!mimeType) {
71
+ return {
72
+ success: false,
73
+ error: "Unsupported image format. Supported: jpg, png, gif, webp"
74
+ };
75
+ }
76
+ const imageData = await readFile(filePath);
77
+ const base64 = imageData.toString("base64");
78
+ const response = await anthropic.messages.create({
79
+ model: "claude-sonnet-4-20250514",
80
+ max_tokens: 1024,
81
+ messages: [
82
+ {
83
+ role: "user",
84
+ content: [
85
+ {
86
+ type: "image",
87
+ source: {
88
+ type: "base64",
89
+ media_type: mimeType,
90
+ data: base64
91
+ }
92
+ },
93
+ {
94
+ type: "text",
95
+ text: prompt || "Describe this image in detail."
96
+ }
97
+ ]
98
+ }
99
+ ]
100
+ });
101
+ const textContent = response.content.find((c) => c.type === "text");
102
+ return {
103
+ success: true,
104
+ analysis: textContent?.type === "text" ? textContent.text : void 0
105
+ };
106
+ } catch (error) {
107
+ return {
108
+ success: false,
109
+ error: error instanceof Error ? error.message : String(error)
110
+ };
111
+ }
112
+ }
113
+ async function analyzeImageBuffer(imageBuffer, mimeType, prompt) {
114
+ try {
115
+ const base64 = imageBuffer.toString("base64");
116
+ const response = await anthropic.messages.create({
117
+ model: "claude-sonnet-4-20250514",
118
+ max_tokens: 1024,
119
+ messages: [
120
+ {
121
+ role: "user",
122
+ content: [
123
+ {
124
+ type: "image",
125
+ source: {
126
+ type: "base64",
127
+ media_type: mimeType,
128
+ data: base64
129
+ }
130
+ },
131
+ {
132
+ type: "text",
133
+ text: prompt || "Describe this image in detail."
134
+ }
135
+ ]
136
+ }
137
+ ]
138
+ });
139
+ const textContent = response.content.find((c) => c.type === "text");
140
+ return {
141
+ success: true,
142
+ analysis: textContent?.type === "text" ? textContent.text : void 0
143
+ };
144
+ } catch (error) {
145
+ return {
146
+ success: false,
147
+ error: error instanceof Error ? error.message : String(error)
148
+ };
149
+ }
150
+ }
151
+ async function analyzeImage(options) {
152
+ if (options.imageUrl) {
153
+ return analyzeImageUrl(options.imageUrl, options.prompt);
154
+ }
155
+ if (options.imagePath) {
156
+ return analyzeImageFile(options.imagePath, options.prompt);
157
+ }
158
+ return {
159
+ success: false,
160
+ error: "Either imageUrl or imagePath must be provided"
161
+ };
162
+ }
163
+
164
+ // src/tools/ocr.ts
165
+ async function ocrWithTesseract(filePath, language = "eng") {
166
+ try {
167
+ const Tesseract = await import("tesseract.js");
168
+ const worker = await Tesseract.createWorker(language);
169
+ const { data } = await worker.recognize(filePath);
170
+ await worker.terminate();
171
+ return {
172
+ success: true,
173
+ text: data.text,
174
+ confidence: data.confidence / 100
175
+ };
176
+ } catch (error) {
177
+ return {
178
+ success: false,
179
+ error: `Tesseract OCR failed: ${error instanceof Error ? error.message : String(error)}`
180
+ };
181
+ }
182
+ }
183
+ async function ocrWithVision(filePath, language) {
184
+ const prompt = language ? `Extract all text from this image. The text is in ${language}. Return only the extracted text, preserving the original formatting and layout as much as possible.` : `Extract all text from this image. Return only the extracted text, preserving the original formatting and layout as much as possible.`;
185
+ const result = await analyzeImageFile(filePath, prompt);
186
+ if (result.success && result.analysis) {
187
+ return {
188
+ success: true,
189
+ text: result.analysis
190
+ };
191
+ }
192
+ return {
193
+ success: false,
194
+ error: result.error || "Failed to extract text"
195
+ };
196
+ }
197
+ async function ocrSimple(filePath) {
198
+ const result = await ocrWithTesseract(filePath);
199
+ if (result.success && result.confidence && result.confidence > 0.6) {
200
+ return result;
201
+ }
202
+ return ocrWithVision(filePath);
203
+ }
204
+ async function ocrPdf(filePath, pages) {
205
+ const prompt = `Extract all text from this PDF document. Return the text content, preserving the structure and formatting as much as possible. If there are multiple pages, separate them clearly.`;
206
+ const result = await analyzeImageFile(filePath, prompt);
207
+ if (result.success && result.analysis) {
208
+ return {
209
+ success: true,
210
+ text: result.analysis
211
+ };
212
+ }
213
+ return {
214
+ success: false,
215
+ error: result.error || "Failed to extract text from PDF"
216
+ };
217
+ }
218
+ async function performOCR(filePath, options) {
219
+ if (!isPathAllowed(filePath)) {
220
+ return {
221
+ success: false,
222
+ error: "Access to this path is not allowed"
223
+ };
224
+ }
225
+ const ext = filePath.toLowerCase().slice(filePath.lastIndexOf("."));
226
+ if (ext === ".pdf") {
227
+ return ocrPdf(filePath);
228
+ }
229
+ if ([".jpg", ".jpeg", ".png", ".gif", ".webp", ".bmp", ".tiff"].includes(ext)) {
230
+ if (options?.useVision !== false) {
231
+ return ocrWithVision(filePath, options?.language);
232
+ }
233
+ return ocrSimple(filePath);
234
+ }
235
+ return {
236
+ success: false,
237
+ error: `Unsupported file type: ${ext}`
238
+ };
239
+ }
240
+ async function extractStructuredData(filePath, dataType) {
241
+ const prompts = {
242
+ table: `Extract all tables from this image. Return the data as JSON arrays where each table is an array of rows, and each row is an array of cell values.`,
243
+ form: `Extract all form fields from this image. Return as a JSON object where keys are field labels and values are the filled-in content.`,
244
+ receipt: `Extract receipt information from this image. Return as JSON with: store_name, date, items (array with name, quantity, price), subtotal, tax, total.`,
245
+ invoice: `Extract invoice information from this image. Return as JSON with: vendor, invoice_number, date, due_date, line_items (array), subtotal, tax, total, billing_address.`
246
+ };
247
+ const prompt = dataType ? prompts[dataType] : `Extract any structured data from this image. Return as JSON.`;
248
+ const result = await analyzeImageFile(filePath, prompt);
249
+ if (result.success && result.analysis) {
250
+ try {
251
+ const jsonMatch = result.analysis.match(/```json\n?([\s\S]*?)\n?```/);
252
+ if (jsonMatch) {
253
+ return {
254
+ success: true,
255
+ data: JSON.parse(jsonMatch[1])
256
+ };
257
+ }
258
+ const data = JSON.parse(result.analysis);
259
+ return { success: true, data };
260
+ } catch {
261
+ return {
262
+ success: true,
263
+ data: { rawText: result.analysis }
264
+ };
265
+ }
266
+ }
267
+ return {
268
+ success: false,
269
+ error: result.error || "Failed to extract structured data"
270
+ };
271
+ }
272
+ var ocr_default = {
273
+ performOCR,
274
+ ocrWithVision,
275
+ ocrWithTesseract,
276
+ extractStructuredData
277
+ };
278
+
279
+ export {
280
+ analyzeImageBuffer,
281
+ analyzeImage,
282
+ ocrWithTesseract,
283
+ ocrWithVision,
284
+ ocrSimple,
285
+ ocrPdf,
286
+ performOCR,
287
+ extractStructuredData,
288
+ ocr_default
289
+ };
290
+ //# sourceMappingURL=chunk-EVE7MIIY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/tools/image-analysis.ts","../src/tools/ocr.ts"],"sourcesContent":["import Anthropic from \"@anthropic-ai/sdk\";\nimport { env } from \"../config/env\";\nimport { readFile } from \"fs/promises\";\nimport { isPathAllowed } from \"../utils/paths\";\n\nconst anthropic = new Anthropic({\n apiKey: env.CLAUDE_API_KEY,\n});\n\nexport interface ImageAnalysisResult {\n success: boolean;\n analysis?: string;\n error?: string;\n}\n\n// Supported image MIME types\nconst SUPPORTED_TYPES: Record<string, string> = {\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".png\": \"image/png\",\n \".gif\": \"image/gif\",\n \".webp\": \"image/webp\",\n};\n\nfunction getMimeType(filename: string): string | null {\n const ext = filename.toLowerCase().slice(filename.lastIndexOf(\".\"));\n return SUPPORTED_TYPES[ext] || null;\n}\n\n// Analyze image from URL\nexport async function analyzeImageUrl(\n imageUrl: string,\n prompt: string\n): Promise<ImageAnalysisResult> {\n try {\n const response = await anthropic.messages.create({\n model: \"claude-sonnet-4-20250514\",\n max_tokens: 1024,\n messages: [\n {\n role: \"user\",\n content: [\n {\n type: \"image\",\n source: {\n type: \"url\",\n url: imageUrl,\n },\n },\n {\n type: \"text\",\n text: prompt || \"Describe this image in detail.\",\n },\n ],\n },\n ],\n });\n\n const textContent = response.content.find((c) => c.type === \"text\");\n return {\n success: true,\n analysis: textContent?.type === \"text\" ? textContent.text : undefined,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\n// Analyze image from local file\nexport async function analyzeImageFile(\n filePath: string,\n prompt: string\n): Promise<ImageAnalysisResult> {\n try {\n // Security check\n if (!isPathAllowed(filePath)) {\n return {\n success: false,\n error: \"Access to this path is not allowed\",\n };\n }\n\n const mimeType = getMimeType(filePath);\n if (!mimeType) {\n return {\n success: false,\n error: \"Unsupported image format. Supported: jpg, png, gif, webp\",\n };\n }\n\n const imageData = await readFile(filePath);\n const base64 = imageData.toString(\"base64\");\n\n const response = await anthropic.messages.create({\n model: \"claude-sonnet-4-20250514\",\n max_tokens: 1024,\n messages: [\n {\n role: \"user\",\n content: [\n {\n type: \"image\",\n source: {\n type: \"base64\",\n media_type: mimeType as \"image/jpeg\" | \"image/png\" | \"image/gif\" | \"image/webp\",\n data: base64,\n },\n },\n {\n type: \"text\",\n text: prompt || \"Describe this image in detail.\",\n },\n ],\n },\n ],\n });\n\n const textContent = response.content.find((c) => c.type === \"text\");\n return {\n success: true,\n analysis: textContent?.type === \"text\" ? textContent.text : undefined,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\n// Analyze image from buffer\nexport async function analyzeImageBuffer(\n imageBuffer: Buffer,\n mimeType: \"image/jpeg\" | \"image/png\" | \"image/gif\" | \"image/webp\",\n prompt: string\n): Promise<ImageAnalysisResult> {\n try {\n const base64 = imageBuffer.toString(\"base64\");\n\n const response = await anthropic.messages.create({\n model: \"claude-sonnet-4-20250514\",\n max_tokens: 1024,\n messages: [\n {\n role: \"user\",\n content: [\n {\n type: \"image\",\n source: {\n type: \"base64\",\n media_type: mimeType,\n data: base64,\n },\n },\n {\n type: \"text\",\n text: prompt || \"Describe this image in detail.\",\n },\n ],\n },\n ],\n });\n\n const textContent = response.content.find((c) => c.type === \"text\");\n return {\n success: true,\n analysis: textContent?.type === \"text\" ? textContent.text : undefined,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\n// Combined function for tool use\nexport async function analyzeImage(\n options: {\n imageUrl?: string;\n imagePath?: string;\n prompt: string;\n }\n): Promise<ImageAnalysisResult> {\n if (options.imageUrl) {\n return analyzeImageUrl(options.imageUrl, options.prompt);\n }\n\n if (options.imagePath) {\n return analyzeImageFile(options.imagePath, options.prompt);\n }\n\n return {\n success: false,\n error: \"Either imageUrl or imagePath must be provided\",\n };\n}\n\nexport default {\n analyzeImage,\n analyzeImageUrl,\n analyzeImageFile,\n analyzeImageBuffer,\n};\n","import { readFile } from \"fs/promises\";\nimport { isPathAllowed } from \"../utils/paths\";\nimport { analyzeImageFile } from \"./image-analysis\";\n\nexport interface OCRResult {\n success: boolean;\n text?: string;\n confidence?: number;\n error?: string;\n}\n\n// OCR using Tesseract.js (local, no API key needed)\nexport async function ocrWithTesseract(\n filePath: string,\n language: string = \"eng\"\n): Promise<OCRResult> {\n try {\n const Tesseract = await import(\"tesseract.js\");\n const worker = await Tesseract.createWorker(language);\n const { data } = await worker.recognize(filePath);\n await worker.terminate();\n\n return {\n success: true,\n text: data.text,\n confidence: data.confidence / 100,\n };\n } catch (error) {\n return {\n success: false,\n error: `Tesseract OCR failed: ${error instanceof Error ? error.message : String(error)}`,\n };\n }\n}\n\n// Use Claude Vision for OCR (most reliable for complex documents)\nexport async function ocrWithVision(\n filePath: string,\n language?: string\n): Promise<OCRResult> {\n const prompt = language\n ? `Extract all text from this image. The text is in ${language}. Return only the extracted text, preserving the original formatting and layout as much as possible.`\n : `Extract all text from this image. Return only the extracted text, preserving the original formatting and layout as much as possible.`;\n\n const result = await analyzeImageFile(filePath, prompt);\n\n if (result.success && result.analysis) {\n return {\n success: true,\n text: result.analysis,\n };\n }\n\n return {\n success: false,\n error: result.error || \"Failed to extract text\",\n };\n}\n\n// OCR using Tesseract.js as primary, falling back to Vision API\nexport async function ocrSimple(filePath: string): Promise<OCRResult> {\n const result = await ocrWithTesseract(filePath);\n if (result.success && result.confidence && result.confidence > 0.6) {\n return result;\n }\n // Fall back to Vision API on low confidence or failure\n return ocrWithVision(filePath);\n}\n\n// OCR for PDF files (extract text from each page)\nexport async function ocrPdf(\n filePath: string,\n pages?: string // e.g., \"1-5\" or \"1,3,5\"\n): Promise<OCRResult> {\n // For PDFs, we'll use Claude Vision on the file directly\n const prompt = `Extract all text from this PDF document. Return the text content, preserving the structure and formatting as much as possible. If there are multiple pages, separate them clearly.`;\n\n const result = await analyzeImageFile(filePath, prompt);\n\n if (result.success && result.analysis) {\n return {\n success: true,\n text: result.analysis,\n };\n }\n\n return {\n success: false,\n error: result.error || \"Failed to extract text from PDF\",\n };\n}\n\n// Main OCR function that determines the best approach\nexport async function performOCR(\n filePath: string,\n options?: {\n language?: string;\n useVision?: boolean;\n }\n): Promise<OCRResult> {\n // Security check\n if (!isPathAllowed(filePath)) {\n return {\n success: false,\n error: \"Access to this path is not allowed\",\n };\n }\n\n const ext = filePath.toLowerCase().slice(filePath.lastIndexOf(\".\"));\n\n // PDF handling\n if (ext === \".pdf\") {\n return ocrPdf(filePath);\n }\n\n // Image handling - use Vision API (most accurate)\n if ([\".jpg\", \".jpeg\", \".png\", \".gif\", \".webp\", \".bmp\", \".tiff\"].includes(ext)) {\n if (options?.useVision !== false) {\n return ocrWithVision(filePath, options?.language);\n }\n return ocrSimple(filePath);\n }\n\n return {\n success: false,\n error: `Unsupported file type: ${ext}`,\n };\n}\n\n// Extract structured data from document (tables, forms)\nexport async function extractStructuredData(\n filePath: string,\n dataType?: \"table\" | \"form\" | \"receipt\" | \"invoice\"\n): Promise<{\n success: boolean;\n data?: Record<string, unknown>;\n error?: string;\n}> {\n const prompts: Record<string, string> = {\n table: `Extract all tables from this image. Return the data as JSON arrays where each table is an array of rows, and each row is an array of cell values.`,\n form: `Extract all form fields from this image. Return as a JSON object where keys are field labels and values are the filled-in content.`,\n receipt: `Extract receipt information from this image. Return as JSON with: store_name, date, items (array with name, quantity, price), subtotal, tax, total.`,\n invoice: `Extract invoice information from this image. Return as JSON with: vendor, invoice_number, date, due_date, line_items (array), subtotal, tax, total, billing_address.`,\n };\n\n const prompt = dataType\n ? prompts[dataType]\n : `Extract any structured data from this image. Return as JSON.`;\n\n const result = await analyzeImageFile(filePath, prompt);\n\n if (result.success && result.analysis) {\n try {\n // Try to parse as JSON\n const jsonMatch = result.analysis.match(/```json\\n?([\\s\\S]*?)\\n?```/);\n if (jsonMatch) {\n return {\n success: true,\n data: JSON.parse(jsonMatch[1]),\n };\n }\n\n // Try direct parse\n const data = JSON.parse(result.analysis);\n return { success: true, data };\n } catch {\n // Return raw text if not JSON\n return {\n success: true,\n data: { rawText: result.analysis },\n };\n }\n }\n\n return {\n success: false,\n error: result.error || \"Failed to extract structured data\",\n };\n}\n\nexport default {\n performOCR,\n ocrWithVision,\n ocrWithTesseract,\n extractStructuredData,\n};\n"],"mappings":"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","names":[]}
@@ -0,0 +1,138 @@
1
+ // src/tools/json-tool.ts
2
+ function validateJson(input) {
3
+ try {
4
+ JSON.parse(input);
5
+ return { valid: true };
6
+ } catch (error) {
7
+ return { valid: false, error: error instanceof Error ? error.message : String(error) };
8
+ }
9
+ }
10
+ function formatJson(input, indent = 2) {
11
+ const obj = typeof input === "string" ? JSON.parse(input) : input;
12
+ return JSON.stringify(obj, null, indent);
13
+ }
14
+ function minifyJson(input) {
15
+ const obj = typeof input === "string" ? JSON.parse(input) : input;
16
+ return JSON.stringify(obj);
17
+ }
18
+ function flattenJson(obj, prefix = "", separator = ".") {
19
+ const result = {};
20
+ for (const [key, value] of Object.entries(obj)) {
21
+ const newKey = prefix ? `${prefix}${separator}${key}` : key;
22
+ if (value && typeof value === "object" && !Array.isArray(value)) {
23
+ Object.assign(result, flattenJson(value, newKey, separator));
24
+ } else {
25
+ result[newKey] = value;
26
+ }
27
+ }
28
+ return result;
29
+ }
30
+ function unflattenJson(obj, separator = ".") {
31
+ const result = {};
32
+ for (const [key, value] of Object.entries(obj)) {
33
+ const parts = key.split(separator);
34
+ let current = result;
35
+ for (let i = 0; i < parts.length - 1; i++) {
36
+ if (!current[parts[i]] || typeof current[parts[i]] !== "object") {
37
+ current[parts[i]] = {};
38
+ }
39
+ current = current[parts[i]];
40
+ }
41
+ current[parts[parts.length - 1]] = value;
42
+ }
43
+ return result;
44
+ }
45
+ function diffJson(a, b, path = "") {
46
+ const diffs = [];
47
+ if (a === b) return diffs;
48
+ if (typeof a !== typeof b || a === null || b === null || typeof a !== "object" || typeof b !== "object") {
49
+ diffs.push({ path: path || "/", type: "changed", oldValue: a, newValue: b });
50
+ return diffs;
51
+ }
52
+ const aObj = a;
53
+ const bObj = b;
54
+ const allKeys = /* @__PURE__ */ new Set([...Object.keys(aObj), ...Object.keys(bObj)]);
55
+ for (const key of allKeys) {
56
+ const newPath = path ? `${path}.${key}` : key;
57
+ if (!(key in aObj)) {
58
+ diffs.push({ path: newPath, type: "added", newValue: bObj[key] });
59
+ } else if (!(key in bObj)) {
60
+ diffs.push({ path: newPath, type: "removed", oldValue: aObj[key] });
61
+ } else {
62
+ diffs.push(...diffJson(aObj[key], bObj[key], newPath));
63
+ }
64
+ }
65
+ return diffs;
66
+ }
67
+ function queryJson(obj, path) {
68
+ const parts = path.replace(/\[(\d+)\]/g, ".$1").split(".").filter(Boolean);
69
+ let current = obj;
70
+ for (const part of parts) {
71
+ if (current === null || current === void 0) return void 0;
72
+ if (typeof current === "object") {
73
+ current = current[part];
74
+ } else {
75
+ return void 0;
76
+ }
77
+ }
78
+ return current;
79
+ }
80
+ function getKeys(obj, prefix = "") {
81
+ if (!obj || typeof obj !== "object") return [];
82
+ const keys = [];
83
+ for (const [key, value] of Object.entries(obj)) {
84
+ const fullKey = prefix ? `${prefix}.${key}` : key;
85
+ keys.push(fullKey);
86
+ if (value && typeof value === "object" && !Array.isArray(value)) {
87
+ keys.push(...getKeys(value, fullKey));
88
+ }
89
+ }
90
+ return keys;
91
+ }
92
+ async function jsonTool(action, input, options) {
93
+ try {
94
+ switch (action) {
95
+ case "validate":
96
+ return { success: true, result: validateJson(input) };
97
+ case "format":
98
+ return { success: true, result: formatJson(input, options?.indent || 2) };
99
+ case "minify":
100
+ return { success: true, result: minifyJson(input) };
101
+ case "flatten":
102
+ return { success: true, result: flattenJson(JSON.parse(input)) };
103
+ case "unflatten":
104
+ return { success: true, result: unflattenJson(JSON.parse(input)) };
105
+ case "diff": {
106
+ const other = options?.compare;
107
+ if (!other) return { success: false, error: "Missing 'compare' option for diff" };
108
+ return { success: true, result: diffJson(JSON.parse(input), JSON.parse(other)) };
109
+ }
110
+ case "query": {
111
+ const path = options?.path;
112
+ if (!path) return { success: false, error: "Missing 'path' option for query" };
113
+ return { success: true, result: queryJson(JSON.parse(input), path) };
114
+ }
115
+ case "keys":
116
+ return { success: true, result: getKeys(JSON.parse(input)) };
117
+ default:
118
+ return { success: false, error: `Unknown action: ${action}` };
119
+ }
120
+ } catch (error) {
121
+ return { success: false, error: error instanceof Error ? error.message : String(error) };
122
+ }
123
+ }
124
+ var json_tool_default = { jsonTool, validateJson, formatJson, minifyJson, flattenJson, unflattenJson, diffJson, queryJson, getKeys };
125
+
126
+ export {
127
+ validateJson,
128
+ formatJson,
129
+ minifyJson,
130
+ flattenJson,
131
+ unflattenJson,
132
+ diffJson,
133
+ queryJson,
134
+ getKeys,
135
+ jsonTool,
136
+ json_tool_default
137
+ };
138
+ //# sourceMappingURL=chunk-F3TTNID2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/tools/json-tool.ts"],"sourcesContent":["/**\r\n * JSON Tool\r\n * Validate, format, flatten, diff, query, and schema-validate JSON\r\n */\r\n\r\nexport interface JsonToolResult {\r\n success: boolean;\r\n result?: unknown;\r\n error?: string;\r\n}\r\n\r\n// Validate JSON string\r\nexport function validateJson(input: string): { valid: boolean; error?: string } {\r\n try {\r\n JSON.parse(input);\r\n return { valid: true };\r\n } catch (error) {\r\n return { valid: false, error: error instanceof Error ? error.message : String(error) };\r\n }\r\n}\r\n\r\n// Pretty-print JSON\r\nexport function formatJson(input: string | object, indent: number = 2): string {\r\n const obj = typeof input === \"string\" ? JSON.parse(input) : input;\r\n return JSON.stringify(obj, null, indent);\r\n}\r\n\r\n// Minify JSON\r\nexport function minifyJson(input: string | object): string {\r\n const obj = typeof input === \"string\" ? JSON.parse(input) : input;\r\n return JSON.stringify(obj);\r\n}\r\n\r\n// Flatten nested JSON: { a: { b: 1 } } → { \"a.b\": 1 }\r\nexport function flattenJson(\r\n obj: Record<string, unknown>,\r\n prefix: string = \"\",\r\n separator: string = \".\"\r\n): Record<string, unknown> {\r\n const result: Record<string, unknown> = {};\r\n\r\n for (const [key, value] of Object.entries(obj)) {\r\n const newKey = prefix ? `${prefix}${separator}${key}` : key;\r\n if (value && typeof value === \"object\" && !Array.isArray(value)) {\r\n Object.assign(result, flattenJson(value as Record<string, unknown>, newKey, separator));\r\n } else {\r\n result[newKey] = value;\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\n// Unflatten JSON: { \"a.b\": 1 } → { a: { b: 1 } }\r\nexport function unflattenJson(\r\n obj: Record<string, unknown>,\r\n separator: string = \".\"\r\n): Record<string, unknown> {\r\n const result: Record<string, unknown> = {};\r\n\r\n for (const [key, value] of Object.entries(obj)) {\r\n const parts = key.split(separator);\r\n let current: Record<string, unknown> = result;\r\n\r\n for (let i = 0; i < parts.length - 1; i++) {\r\n if (!current[parts[i]] || typeof current[parts[i]] !== \"object\") {\r\n current[parts[i]] = {};\r\n }\r\n current = current[parts[i]] as Record<string, unknown>;\r\n }\r\n\r\n current[parts[parts.length - 1]] = value;\r\n }\r\n\r\n return result;\r\n}\r\n\r\n// Diff two JSON objects\r\nexport function diffJson(\r\n a: unknown,\r\n b: unknown,\r\n path: string = \"\"\r\n): Array<{ path: string; type: \"added\" | \"removed\" | \"changed\"; oldValue?: unknown; newValue?: unknown }> {\r\n const diffs: Array<{ path: string; type: \"added\" | \"removed\" | \"changed\"; oldValue?: unknown; newValue?: unknown }> = [];\r\n\r\n if (a === b) return diffs;\r\n\r\n if (typeof a !== typeof b || a === null || b === null || typeof a !== \"object\" || typeof b !== \"object\") {\r\n diffs.push({ path: path || \"/\", type: \"changed\", oldValue: a, newValue: b });\r\n return diffs;\r\n }\r\n\r\n const aObj = a as Record<string, unknown>;\r\n const bObj = b as Record<string, unknown>;\r\n const allKeys = new Set([...Object.keys(aObj), ...Object.keys(bObj)]);\r\n\r\n for (const key of allKeys) {\r\n const newPath = path ? `${path}.${key}` : key;\r\n\r\n if (!(key in aObj)) {\r\n diffs.push({ path: newPath, type: \"added\", newValue: bObj[key] });\r\n } else if (!(key in bObj)) {\r\n diffs.push({ path: newPath, type: \"removed\", oldValue: aObj[key] });\r\n } else {\r\n diffs.push(...diffJson(aObj[key], bObj[key], newPath));\r\n }\r\n }\r\n\r\n return diffs;\r\n}\r\n\r\n// Simple JSONPath-like query (supports dot notation and array indices)\r\nexport function queryJson(obj: unknown, path: string): unknown {\r\n const parts = path.replace(/\\[(\\d+)\\]/g, \".$1\").split(\".\").filter(Boolean);\r\n let current: unknown = obj;\r\n\r\n for (const part of parts) {\r\n if (current === null || current === undefined) return undefined;\r\n if (typeof current === \"object\") {\r\n current = (current as Record<string, unknown>)[part];\r\n } else {\r\n return undefined;\r\n }\r\n }\r\n\r\n return current;\r\n}\r\n\r\n// Get all keys from a JSON object (recursive)\r\nexport function getKeys(obj: unknown, prefix: string = \"\"): string[] {\r\n if (!obj || typeof obj !== \"object\") return [];\r\n\r\n const keys: string[] = [];\r\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\r\n const fullKey = prefix ? `${prefix}.${key}` : key;\r\n keys.push(fullKey);\r\n if (value && typeof value === \"object\" && !Array.isArray(value)) {\r\n keys.push(...getKeys(value, fullKey));\r\n }\r\n }\r\n\r\n return keys;\r\n}\r\n\r\n// Main entry point\r\nexport async function jsonTool(\r\n action: string,\r\n input: string,\r\n options?: Record<string, unknown>\r\n): Promise<JsonToolResult> {\r\n try {\r\n switch (action) {\r\n case \"validate\":\r\n return { success: true, result: validateJson(input) };\r\n case \"format\":\r\n return { success: true, result: formatJson(input, (options?.indent as number) || 2) };\r\n case \"minify\":\r\n return { success: true, result: minifyJson(input) };\r\n case \"flatten\":\r\n return { success: true, result: flattenJson(JSON.parse(input)) };\r\n case \"unflatten\":\r\n return { success: true, result: unflattenJson(JSON.parse(input)) };\r\n case \"diff\": {\r\n const other = options?.compare as string;\r\n if (!other) return { success: false, error: \"Missing 'compare' option for diff\" };\r\n return { success: true, result: diffJson(JSON.parse(input), JSON.parse(other)) };\r\n }\r\n case \"query\": {\r\n const path = options?.path as string;\r\n if (!path) return { success: false, error: \"Missing 'path' option for query\" };\r\n return { success: true, result: queryJson(JSON.parse(input), path) };\r\n }\r\n case \"keys\":\r\n return { success: true, result: getKeys(JSON.parse(input)) };\r\n default:\r\n return { success: false, error: `Unknown action: ${action}` };\r\n }\r\n } catch (error) {\r\n return { success: false, error: error instanceof Error ? error.message : String(error) };\r\n }\r\n}\r\n\r\nexport default { jsonTool, validateJson, formatJson, minifyJson, flattenJson, unflattenJson, diffJson, queryJson, getKeys };\r\n"],"mappings":"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","names":[]}
@@ -0,0 +1,190 @@
1
+ import {
2
+ getNotionClient,
3
+ init_client
4
+ } from "./chunk-VRD5CYRL.js";
5
+
6
+ // src/integrations/notion/search.ts
7
+ init_client();
8
+ function extractPageTitle(properties) {
9
+ for (const value of Object.values(properties)) {
10
+ if (value?.type === "title" && Array.isArray(value.title)) {
11
+ return value.title.map((t) => t.plain_text || "").join("");
12
+ }
13
+ }
14
+ return "Untitled";
15
+ }
16
+ function pageToSearchResult(page) {
17
+ let parent;
18
+ if (page.parent.type === "page_id") {
19
+ parent = { type: "page", id: page.parent.page_id };
20
+ } else if (page.parent.type === "database_id") {
21
+ parent = { type: "database", id: page.parent.database_id };
22
+ } else {
23
+ parent = { type: "workspace" };
24
+ }
25
+ return {
26
+ type: "page",
27
+ id: page.id,
28
+ url: page.url,
29
+ title: extractPageTitle(page.properties),
30
+ createdTime: page.created_time,
31
+ lastEditedTime: page.last_edited_time,
32
+ archived: page.archived,
33
+ icon: page.icon?.type === "emoji" ? page.icon.emoji : page.icon?.type === "external" ? page.icon.external.url : void 0,
34
+ cover: page.cover?.type === "external" ? page.cover.external.url : page.cover?.type === "file" ? page.cover.file.url : void 0,
35
+ parent
36
+ };
37
+ }
38
+ function databaseToSearchResult(database) {
39
+ let parent;
40
+ if (database.parent.type === "page_id") {
41
+ parent = { type: "page", id: database.parent.page_id };
42
+ } else {
43
+ parent = { type: "workspace" };
44
+ }
45
+ return {
46
+ type: "database",
47
+ id: database.id,
48
+ url: database.url,
49
+ title: database.title.map((t) => t.plain_text).join(""),
50
+ description: database.description.map((t) => t.plain_text).join(""),
51
+ createdTime: database.created_time,
52
+ lastEditedTime: database.last_edited_time,
53
+ isInline: database.is_inline,
54
+ icon: database.icon?.type === "emoji" ? database.icon.emoji : database.icon?.type === "external" ? database.icon.external.url : void 0,
55
+ cover: database.cover?.type === "external" ? database.cover.external.url : database.cover?.type === "file" ? database.cover.file.url : void 0,
56
+ parent
57
+ };
58
+ }
59
+ async function search(options = {}) {
60
+ const notion = getNotionClient();
61
+ const params = {};
62
+ if (options.query) {
63
+ params.query = options.query;
64
+ }
65
+ if (options.filter) {
66
+ const filterValue = options.filter.value === "database" ? "data_source" : options.filter.value;
67
+ params.filter = { value: filterValue, property: options.filter.property };
68
+ }
69
+ if (options.sort) {
70
+ params.sort = options.sort;
71
+ }
72
+ if (options.startCursor) {
73
+ params.start_cursor = options.startCursor;
74
+ }
75
+ if (options.pageSize) {
76
+ params.page_size = options.pageSize;
77
+ }
78
+ const response = await notion.search(params);
79
+ const results = response.results.map((item) => {
80
+ if (item.object === "page") {
81
+ return pageToSearchResult(item);
82
+ } else {
83
+ return databaseToSearchResult(item);
84
+ }
85
+ });
86
+ return {
87
+ results,
88
+ hasMore: response.has_more,
89
+ nextCursor: response.next_cursor
90
+ };
91
+ }
92
+ async function searchPages(query, options = {}) {
93
+ const response = await search({
94
+ ...options,
95
+ query,
96
+ filter: { value: "page", property: "object" }
97
+ });
98
+ return response.results.filter(
99
+ (r) => r.type === "page"
100
+ );
101
+ }
102
+ async function searchDatabases(query, options = {}) {
103
+ const response = await search({
104
+ ...options,
105
+ query,
106
+ filter: { value: "database", property: "object" }
107
+ });
108
+ return response.results.filter(
109
+ (r) => r.type === "database"
110
+ );
111
+ }
112
+ async function searchAll(query, options = {}) {
113
+ const allResults = [];
114
+ let cursor;
115
+ do {
116
+ const response = await search({
117
+ ...options,
118
+ query,
119
+ startCursor: cursor,
120
+ pageSize: 100
121
+ });
122
+ allResults.push(...response.results);
123
+ cursor = response.nextCursor ?? void 0;
124
+ } while (cursor);
125
+ return allResults;
126
+ }
127
+ async function findPageByTitle(title, exactMatch = false) {
128
+ const pages = await searchPages(title);
129
+ if (exactMatch) {
130
+ return pages.find((p) => p.title === title) || null;
131
+ }
132
+ return pages[0] || null;
133
+ }
134
+ async function findDatabaseByTitle(title, exactMatch = false) {
135
+ const databases = await searchDatabases(title);
136
+ if (exactMatch) {
137
+ return databases.find((d) => d.title === title) || null;
138
+ }
139
+ return databases[0] || null;
140
+ }
141
+ async function getRecentlyEditedPages(limit = 10) {
142
+ const response = await search({
143
+ filter: { value: "page", property: "object" },
144
+ sort: { direction: "descending", timestamp: "last_edited_time" },
145
+ pageSize: limit
146
+ });
147
+ return response.results.filter(
148
+ (r) => r.type === "page"
149
+ );
150
+ }
151
+ async function getRecentlyEditedDatabases(limit = 10) {
152
+ const response = await search({
153
+ filter: { value: "database", property: "object" },
154
+ sort: { direction: "descending", timestamp: "last_edited_time" },
155
+ pageSize: limit
156
+ });
157
+ return response.results.filter(
158
+ (r) => r.type === "database"
159
+ );
160
+ }
161
+ async function fullTextSearch(query, options = {}) {
162
+ const searchOptions = {
163
+ query,
164
+ pageSize: options.limit ?? 20
165
+ };
166
+ if (options.objectType) {
167
+ searchOptions.filter = { value: options.objectType, property: "object" };
168
+ }
169
+ if (!options.sortByRelevance) {
170
+ searchOptions.sort = {
171
+ direction: "descending",
172
+ timestamp: "last_edited_time"
173
+ };
174
+ }
175
+ const response = await search(searchOptions);
176
+ return response.results;
177
+ }
178
+
179
+ export {
180
+ search,
181
+ searchPages,
182
+ searchDatabases,
183
+ searchAll,
184
+ findPageByTitle,
185
+ findDatabaseByTitle,
186
+ getRecentlyEditedPages,
187
+ getRecentlyEditedDatabases,
188
+ fullTextSearch
189
+ };
190
+ //# sourceMappingURL=chunk-H5RQOFO2.js.map