mulmoclaude 0.1.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.
Files changed (408) hide show
  1. package/README.md +44 -0
  2. package/bin/mulmoclaude.js +202 -0
  3. package/bin/prepare-dist.js +93 -0
  4. package/client/assets/chunk-vKJrgz-R-C_I3GbVV.js +1 -0
  5. package/client/assets/html2canvas-Cx501zZr-BF5dYYkY.js +5 -0
  6. package/client/assets/index-D8rhwXLq.js +4906 -0
  7. package/client/assets/index-KNLBjwuh.css +1 -0
  8. package/client/assets/index.es-D4YyL_Dg-BfRHLTZV.js +5 -0
  9. package/client/assets/material-icons-Dr0goTwe.woff +0 -0
  10. package/client/assets/material-icons-kAwBdRge.woff2 +0 -0
  11. package/client/assets/material-icons-outlined-BpWbwl2n.woff +0 -0
  12. package/client/assets/material-icons-outlined-DZhiGvEA.woff2 +0 -0
  13. package/client/assets/material-icons-round-BDlwx-sv.woff +0 -0
  14. package/client/assets/material-icons-round-DrirKXBx.woff2 +0 -0
  15. package/client/assets/material-icons-sharp-CH1KkVu7.woff +0 -0
  16. package/client/assets/material-icons-sharp-gidztirS.woff2 +0 -0
  17. package/client/assets/material-icons-two-tone-B7wz7mED.woff +0 -0
  18. package/client/assets/material-icons-two-tone-DuNIpaEj.woff2 +0 -0
  19. package/client/assets/mulmo_bw-ERmkSv0a.png +0 -0
  20. package/client/assets/purify.es-Fx1Nqyry-PeS5RUhs.js +2 -0
  21. package/client/assets/typeof-DBp4T-Ny-BC0P-2DM.js +1 -0
  22. package/client/index.html +28 -0
  23. package/package.json +66 -0
  24. package/server/agent/attachmentConverter.ts +270 -0
  25. package/server/agent/config.ts +414 -0
  26. package/server/agent/index.ts +260 -0
  27. package/server/agent/mcp-server.ts +412 -0
  28. package/server/agent/mcp-tools/index.ts +63 -0
  29. package/server/agent/mcp-tools/x.ts +188 -0
  30. package/server/agent/plugin-names.ts +75 -0
  31. package/server/agent/prompt.ts +349 -0
  32. package/server/agent/resumeFailover.ts +129 -0
  33. package/server/agent/sandboxMounts.ts +329 -0
  34. package/server/agent/stream.ts +194 -0
  35. package/server/api/auth/bearerAuth.ts +61 -0
  36. package/server/api/auth/token.ts +98 -0
  37. package/server/api/csrfGuard.ts +85 -0
  38. package/server/api/routes/agent.ts +478 -0
  39. package/server/api/routes/chart.ts +98 -0
  40. package/server/api/routes/chat-index.ts +46 -0
  41. package/server/api/routes/config.ts +258 -0
  42. package/server/api/routes/dispatchResponse.ts +79 -0
  43. package/server/api/routes/files.ts +812 -0
  44. package/server/api/routes/html.ts +101 -0
  45. package/server/api/routes/image.ts +169 -0
  46. package/server/api/routes/mulmo-script.ts +712 -0
  47. package/server/api/routes/mulmoScriptValidate.ts +101 -0
  48. package/server/api/routes/notifications.ts +69 -0
  49. package/server/api/routes/pdf.ts +163 -0
  50. package/server/api/routes/plugins.ts +276 -0
  51. package/server/api/routes/presentHtml.ts +48 -0
  52. package/server/api/routes/roles.ts +125 -0
  53. package/server/api/routes/scheduler.ts +153 -0
  54. package/server/api/routes/schedulerHandlers.ts +151 -0
  55. package/server/api/routes/schedulerTasks.ts +163 -0
  56. package/server/api/routes/sessions.ts +294 -0
  57. package/server/api/routes/sessionsCursor.ts +59 -0
  58. package/server/api/routes/skills.ts +195 -0
  59. package/server/api/routes/sources.ts +540 -0
  60. package/server/api/routes/todos.ts +263 -0
  61. package/server/api/routes/todosColumnsHandlers.ts +347 -0
  62. package/server/api/routes/todosHandlers.ts +274 -0
  63. package/server/api/routes/todosItemsHandlers.ts +386 -0
  64. package/server/api/routes/wiki/pageIndex.ts +53 -0
  65. package/server/api/routes/wiki.ts +363 -0
  66. package/server/api/sandboxStatus.ts +64 -0
  67. package/server/events/notifications.ts +160 -0
  68. package/server/events/pub-sub/index.ts +45 -0
  69. package/server/events/relay-client.ts +288 -0
  70. package/server/events/scheduler-adapter.ts +302 -0
  71. package/server/events/session-store/index.ts +492 -0
  72. package/server/events/task-manager/index.ts +181 -0
  73. package/server/index.ts +572 -0
  74. package/server/system/config.ts +243 -0
  75. package/server/system/credentials.ts +220 -0
  76. package/server/system/docker.ts +97 -0
  77. package/server/system/env.ts +109 -0
  78. package/server/system/logger/config.ts +112 -0
  79. package/server/system/logger/formatters.ts +40 -0
  80. package/server/system/logger/index.ts +53 -0
  81. package/server/system/logger/rotation.ts +37 -0
  82. package/server/system/logger/sinks.ts +101 -0
  83. package/server/system/logger/types.ts +29 -0
  84. package/server/utils/date.ts +57 -0
  85. package/server/utils/errors.ts +7 -0
  86. package/server/utils/fetch.ts +27 -0
  87. package/server/utils/files/atomic.ts +125 -0
  88. package/server/utils/files/html-io.ts +20 -0
  89. package/server/utils/files/image-store.ts +66 -0
  90. package/server/utils/files/index.ts +45 -0
  91. package/server/utils/files/journal-io.ts +213 -0
  92. package/server/utils/files/json.ts +69 -0
  93. package/server/utils/files/markdown-store.ts +33 -0
  94. package/server/utils/files/naming.ts +50 -0
  95. package/server/utils/files/reference-dirs-io.ts +45 -0
  96. package/server/utils/files/roles-io.ts +45 -0
  97. package/server/utils/files/safe.ts +106 -0
  98. package/server/utils/files/scheduler-io.ts +20 -0
  99. package/server/utils/files/scheduler-overrides-io.ts +64 -0
  100. package/server/utils/files/session-io.ts +136 -0
  101. package/server/utils/files/spreadsheet-store.ts +63 -0
  102. package/server/utils/files/todos-io.ts +29 -0
  103. package/server/utils/files/user-tasks-io.ts +25 -0
  104. package/server/utils/files/workspace-io.ts +221 -0
  105. package/server/utils/gemini.ts +59 -0
  106. package/server/utils/gitignore.ts +69 -0
  107. package/server/utils/http.ts +15 -0
  108. package/server/utils/httpError.ts +61 -0
  109. package/server/utils/id.ts +16 -0
  110. package/server/utils/json.ts +83 -0
  111. package/server/utils/logBackgroundError.ts +22 -0
  112. package/server/utils/markdown.ts +82 -0
  113. package/server/utils/request.ts +29 -0
  114. package/server/utils/slug.ts +50 -0
  115. package/server/utils/spawn.ts +62 -0
  116. package/server/utils/time.ts +34 -0
  117. package/server/utils/types.ts +47 -0
  118. package/server/workspace/chat-index/index.ts +153 -0
  119. package/server/workspace/chat-index/indexer.ts +209 -0
  120. package/server/workspace/chat-index/paths.ts +34 -0
  121. package/server/workspace/chat-index/summarizer.ts +247 -0
  122. package/server/workspace/chat-index/types.ts +38 -0
  123. package/server/workspace/custom-dirs.ts +220 -0
  124. package/server/workspace/helps/business.md +104 -0
  125. package/server/workspace/helps/github.md +23 -0
  126. package/server/workspace/helps/index.md +60 -0
  127. package/server/workspace/helps/mulmoscript.md +249 -0
  128. package/server/workspace/helps/sandbox.md +90 -0
  129. package/server/workspace/helps/spreadsheet.md +43 -0
  130. package/server/workspace/helps/telegram.md +135 -0
  131. package/server/workspace/helps/wiki.md +131 -0
  132. package/server/workspace/journal/archivist.ts +386 -0
  133. package/server/workspace/journal/dailyPass.ts +743 -0
  134. package/server/workspace/journal/diff.ts +71 -0
  135. package/server/workspace/journal/index.ts +185 -0
  136. package/server/workspace/journal/indexFile.ts +136 -0
  137. package/server/workspace/journal/linkRewrite.ts +4 -0
  138. package/server/workspace/journal/memoryExtractor.ts +130 -0
  139. package/server/workspace/journal/optimizationPass.ts +160 -0
  140. package/server/workspace/journal/paths.ts +76 -0
  141. package/server/workspace/journal/state.ts +125 -0
  142. package/server/workspace/paths.ts +158 -0
  143. package/server/workspace/reference-dirs.ts +252 -0
  144. package/server/workspace/roles.ts +37 -0
  145. package/server/workspace/skills/discovery.ts +125 -0
  146. package/server/workspace/skills/index.ts +10 -0
  147. package/server/workspace/skills/parser.ts +144 -0
  148. package/server/workspace/skills/paths.ts +41 -0
  149. package/server/workspace/skills/scheduler.ts +149 -0
  150. package/server/workspace/skills/types.ts +30 -0
  151. package/server/workspace/skills/user-tasks.ts +257 -0
  152. package/server/workspace/skills/writer.ts +189 -0
  153. package/server/workspace/sources/arxivDiscovery.ts +182 -0
  154. package/server/workspace/sources/classifier.ts +268 -0
  155. package/server/workspace/sources/fetchers/arxiv.ts +170 -0
  156. package/server/workspace/sources/fetchers/github.ts +106 -0
  157. package/server/workspace/sources/fetchers/githubIssues.ts +208 -0
  158. package/server/workspace/sources/fetchers/githubReleases.ts +186 -0
  159. package/server/workspace/sources/fetchers/index.ts +71 -0
  160. package/server/workspace/sources/fetchers/registerAll.ts +15 -0
  161. package/server/workspace/sources/fetchers/rss.ts +141 -0
  162. package/server/workspace/sources/fetchers/rssParser.ts +295 -0
  163. package/server/workspace/sources/httpFetcher.ts +230 -0
  164. package/server/workspace/sources/interests.ts +120 -0
  165. package/server/workspace/sources/paths.ts +110 -0
  166. package/server/workspace/sources/pipeline/dedup.ts +60 -0
  167. package/server/workspace/sources/pipeline/fetch.ts +136 -0
  168. package/server/workspace/sources/pipeline/index.ts +249 -0
  169. package/server/workspace/sources/pipeline/notify.ts +72 -0
  170. package/server/workspace/sources/pipeline/plan.ts +66 -0
  171. package/server/workspace/sources/pipeline/summarize.ts +189 -0
  172. package/server/workspace/sources/pipeline/write.ts +185 -0
  173. package/server/workspace/sources/rateLimiter.ts +148 -0
  174. package/server/workspace/sources/registry.ts +326 -0
  175. package/server/workspace/sources/robots.ts +271 -0
  176. package/server/workspace/sources/sourceState.ts +135 -0
  177. package/server/workspace/sources/taxonomy.ts +74 -0
  178. package/server/workspace/sources/types.ts +144 -0
  179. package/server/workspace/sources/urls.ts +112 -0
  180. package/server/workspace/tool-trace/classify.ts +114 -0
  181. package/server/workspace/tool-trace/index.ts +250 -0
  182. package/server/workspace/tool-trace/writeSearch.ts +98 -0
  183. package/server/workspace/wiki-backlinks/index.ts +107 -0
  184. package/server/workspace/wiki-backlinks/sessionBacklinks.ts +144 -0
  185. package/server/workspace/workspace.ts +66 -0
  186. package/src/App.vue +720 -0
  187. package/src/assets/mulmo_bw.png +0 -0
  188. package/src/components/CanvasViewToggle.vue +27 -0
  189. package/src/components/ChatAttachmentPreview.vue +45 -0
  190. package/src/components/ChatImagePreview.vue +17 -0
  191. package/src/components/ChatInput.vue +208 -0
  192. package/src/components/FileContentHeader.vue +49 -0
  193. package/src/components/FileContentRenderer.vue +162 -0
  194. package/src/components/FileTree.vue +115 -0
  195. package/src/components/FileTreePane.vue +85 -0
  196. package/src/components/FilesView.vue +206 -0
  197. package/src/components/LockStatusPopup.vue +111 -0
  198. package/src/components/NotificationBell.vue +131 -0
  199. package/src/components/NotificationToast.vue +72 -0
  200. package/src/components/PluginLauncher.vue +138 -0
  201. package/src/components/RightSidebar.vue +113 -0
  202. package/src/components/RoleSelector.vue +64 -0
  203. package/src/components/SessionHistoryPanel.vue +176 -0
  204. package/src/components/SessionTabBar.vue +81 -0
  205. package/src/components/SettingsMcpTab.vue +350 -0
  206. package/src/components/SettingsModal.vue +275 -0
  207. package/src/components/SettingsReferenceDirsTab.vue +173 -0
  208. package/src/components/SettingsWorkspaceDirsTab.vue +174 -0
  209. package/src/components/SidebarHeader.vue +69 -0
  210. package/src/components/StackView.vue +360 -0
  211. package/src/components/SuggestionsPanel.vue +65 -0
  212. package/src/components/TodoExplorer.vue +358 -0
  213. package/src/components/ToolResultsPanel.vue +77 -0
  214. package/src/components/todo/TodoAddDialog.vue +131 -0
  215. package/src/components/todo/TodoEditDialog.vue +47 -0
  216. package/src/components/todo/TodoEditPanel.vue +113 -0
  217. package/src/components/todo/TodoKanbanView.vue +249 -0
  218. package/src/components/todo/TodoListView.vue +79 -0
  219. package/src/components/todo/TodoTableView.vue +177 -0
  220. package/src/composables/useActiveSession.ts +40 -0
  221. package/src/composables/useAppApi.ts +45 -0
  222. package/src/composables/useCanvasViewMode.ts +121 -0
  223. package/src/composables/useChatScroll.ts +47 -0
  224. package/src/composables/useClickOutside.ts +26 -0
  225. package/src/composables/useClipboardCopy.ts +44 -0
  226. package/src/composables/useContentDisplay.ts +52 -0
  227. package/src/composables/useDebugBeat.ts +23 -0
  228. package/src/composables/useDynamicFavicon.ts +115 -0
  229. package/src/composables/useEventListeners.ts +42 -0
  230. package/src/composables/useExpandedDirs.ts +64 -0
  231. package/src/composables/useFaviconState.ts +30 -0
  232. package/src/composables/useFileSelection.ts +115 -0
  233. package/src/composables/useFileSortMode.ts +24 -0
  234. package/src/composables/useFileTree.ts +85 -0
  235. package/src/composables/useFreshPluginData.ts +89 -0
  236. package/src/composables/useHealth.ts +38 -0
  237. package/src/composables/useImeAwareEnter.ts +57 -0
  238. package/src/composables/useKeyNavigation.ts +60 -0
  239. package/src/composables/useMarkdownLinkHandler.ts +46 -0
  240. package/src/composables/useMarkdownMode.ts +17 -0
  241. package/src/composables/useMcpTools.ts +71 -0
  242. package/src/composables/useMergedSessions.ts +27 -0
  243. package/src/composables/useNotifications.ts +90 -0
  244. package/src/composables/usePdfDownload.ts +60 -0
  245. package/src/composables/usePendingCalls.ts +77 -0
  246. package/src/composables/usePubSub.ts +85 -0
  247. package/src/composables/useRightSidebar.ts +23 -0
  248. package/src/composables/useRoles.ts +34 -0
  249. package/src/composables/useSandboxStatus.ts +67 -0
  250. package/src/composables/useSelectedResult.ts +49 -0
  251. package/src/composables/useSessionDerived.ts +51 -0
  252. package/src/composables/useSessionHistory.ts +81 -0
  253. package/src/composables/useSessionSync.ts +57 -0
  254. package/src/composables/useViewLayout.ts +55 -0
  255. package/src/config/apiRoutes.ts +173 -0
  256. package/src/config/pubsubChannels.ts +45 -0
  257. package/src/config/roles.ts +335 -0
  258. package/src/config/schedulerActions.ts +25 -0
  259. package/src/config/toolNames.ts +71 -0
  260. package/src/config/workspacePaths.ts +24 -0
  261. package/src/index.css +107 -0
  262. package/src/main.ts +25 -0
  263. package/src/plugins/canvas/Preview.vue +13 -0
  264. package/src/plugins/canvas/View.vue +333 -0
  265. package/src/plugins/canvas/definition.ts +38 -0
  266. package/src/plugins/canvas/index.ts +36 -0
  267. package/src/plugins/chart/Preview.vue +49 -0
  268. package/src/plugins/chart/View.vue +143 -0
  269. package/src/plugins/chart/definition.ts +58 -0
  270. package/src/plugins/chart/index.ts +52 -0
  271. package/src/plugins/editImage/Preview.vue +13 -0
  272. package/src/plugins/editImage/View.vue +13 -0
  273. package/src/plugins/editImage/definition.ts +27 -0
  274. package/src/plugins/editImage/index.ts +36 -0
  275. package/src/plugins/generateImage/Preview.vue +13 -0
  276. package/src/plugins/generateImage/View.vue +33 -0
  277. package/src/plugins/generateImage/definition.ts +32 -0
  278. package/src/plugins/generateImage/index.ts +56 -0
  279. package/src/plugins/manageRoles/Preview.vue +49 -0
  280. package/src/plugins/manageRoles/View.vue +525 -0
  281. package/src/plugins/manageRoles/definition.ts +43 -0
  282. package/src/plugins/manageRoles/index.ts +47 -0
  283. package/src/plugins/manageSkills/Preview.vue +21 -0
  284. package/src/plugins/manageSkills/View.vue +321 -0
  285. package/src/plugins/manageSkills/definition.ts +49 -0
  286. package/src/plugins/manageSkills/index.ts +49 -0
  287. package/src/plugins/manageSource/Preview.vue +33 -0
  288. package/src/plugins/manageSource/View.vue +697 -0
  289. package/src/plugins/manageSource/definition.ts +63 -0
  290. package/src/plugins/manageSource/index.ts +66 -0
  291. package/src/plugins/markdown/Preview.vue +77 -0
  292. package/src/plugins/markdown/View.vue +476 -0
  293. package/src/plugins/markdown/definition.ts +50 -0
  294. package/src/plugins/markdown/index.ts +36 -0
  295. package/src/plugins/presentHtml/Preview.vue +25 -0
  296. package/src/plugins/presentHtml/View.vue +52 -0
  297. package/src/plugins/presentHtml/definition.ts +27 -0
  298. package/src/plugins/presentHtml/helpers.ts +72 -0
  299. package/src/plugins/presentHtml/index.ts +41 -0
  300. package/src/plugins/presentMulmoScript/Preview.vue +23 -0
  301. package/src/plugins/presentMulmoScript/View.vue +1166 -0
  302. package/src/plugins/presentMulmoScript/definition.ts +95 -0
  303. package/src/plugins/presentMulmoScript/helpers.ts +162 -0
  304. package/src/plugins/presentMulmoScript/index.ts +40 -0
  305. package/src/plugins/scheduler/Preview.vue +67 -0
  306. package/src/plugins/scheduler/TasksTab.vue +205 -0
  307. package/src/plugins/scheduler/View.vue +565 -0
  308. package/src/plugins/scheduler/definition.ts +57 -0
  309. package/src/plugins/scheduler/index.ts +45 -0
  310. package/src/plugins/scheduler/viewModes.ts +26 -0
  311. package/src/plugins/spreadsheet/Preview.vue +29 -0
  312. package/src/plugins/spreadsheet/View.vue +997 -0
  313. package/src/plugins/spreadsheet/cellHighlights.ts +79 -0
  314. package/src/plugins/spreadsheet/definition.ts +121 -0
  315. package/src/plugins/spreadsheet/engine/calculator.ts +459 -0
  316. package/src/plugins/spreadsheet/engine/cellBuilder.ts +81 -0
  317. package/src/plugins/spreadsheet/engine/date-parser.ts +220 -0
  318. package/src/plugins/spreadsheet/engine/date-utils.ts +56 -0
  319. package/src/plugins/spreadsheet/engine/engine.ts +176 -0
  320. package/src/plugins/spreadsheet/engine/evaluator.ts +390 -0
  321. package/src/plugins/spreadsheet/engine/formatter.ts +172 -0
  322. package/src/plugins/spreadsheet/engine/formulaRefs.ts +101 -0
  323. package/src/plugins/spreadsheet/engine/functions/date.ts +299 -0
  324. package/src/plugins/spreadsheet/engine/functions/financial.ts +387 -0
  325. package/src/plugins/spreadsheet/engine/functions/index.ts +16 -0
  326. package/src/plugins/spreadsheet/engine/functions/logical.ts +262 -0
  327. package/src/plugins/spreadsheet/engine/functions/lookup.ts +400 -0
  328. package/src/plugins/spreadsheet/engine/functions/mathematical.ts +297 -0
  329. package/src/plugins/spreadsheet/engine/functions/statistical.ts +338 -0
  330. package/src/plugins/spreadsheet/engine/functions/text.ts +389 -0
  331. package/src/plugins/spreadsheet/engine/index.ts +27 -0
  332. package/src/plugins/spreadsheet/engine/jsonCellLocator.ts +111 -0
  333. package/src/plugins/spreadsheet/engine/parser.ts +143 -0
  334. package/src/plugins/spreadsheet/engine/registry.ts +150 -0
  335. package/src/plugins/spreadsheet/engine/responseDecoder.ts +67 -0
  336. package/src/plugins/spreadsheet/engine/types.ts +64 -0
  337. package/src/plugins/spreadsheet/index.ts +36 -0
  338. package/src/plugins/textResponse/Preview.vue +94 -0
  339. package/src/plugins/textResponse/View.vue +503 -0
  340. package/src/plugins/textResponse/definition.ts +34 -0
  341. package/src/plugins/textResponse/index.ts +27 -0
  342. package/src/plugins/textResponse/plugin.ts +29 -0
  343. package/src/plugins/textResponse/samples.ts +97 -0
  344. package/src/plugins/textResponse/types.ts +11 -0
  345. package/src/plugins/todo/Preview.vue +63 -0
  346. package/src/plugins/todo/View.vue +364 -0
  347. package/src/plugins/todo/composables/useTodos.ts +177 -0
  348. package/src/plugins/todo/definition.ts +45 -0
  349. package/src/plugins/todo/index.ts +61 -0
  350. package/src/plugins/todo/labels.ts +163 -0
  351. package/src/plugins/todo/priority.ts +98 -0
  352. package/src/plugins/todo/viewModes.ts +19 -0
  353. package/src/plugins/ui-image/ImagePreview.vue +23 -0
  354. package/src/plugins/ui-image/ImageView.vue +34 -0
  355. package/src/plugins/ui-image/index.ts +3 -0
  356. package/src/plugins/ui-image/types.ts +4 -0
  357. package/src/plugins/wiki/Preview.vue +65 -0
  358. package/src/plugins/wiki/View.vue +342 -0
  359. package/src/plugins/wiki/definition.ts +25 -0
  360. package/src/plugins/wiki/helpers.ts +59 -0
  361. package/src/plugins/wiki/index.ts +52 -0
  362. package/src/router/guards.ts +61 -0
  363. package/src/router/index.ts +50 -0
  364. package/src/tools/index.ts +52 -0
  365. package/src/tools/types.ts +27 -0
  366. package/src/types/events.ts +16 -0
  367. package/src/types/fileTree.ts +13 -0
  368. package/src/types/notification.ts +67 -0
  369. package/src/types/session.ts +116 -0
  370. package/src/types/sse.ts +90 -0
  371. package/src/types/toolCallHistory.ts +13 -0
  372. package/src/utils/agent/eventDispatch.ts +74 -0
  373. package/src/utils/agent/request.ts +55 -0
  374. package/src/utils/agent/toolCalls.ts +62 -0
  375. package/src/utils/api.ts +218 -0
  376. package/src/utils/canvas/viewMode.ts +46 -0
  377. package/src/utils/dom/authTokenMeta.ts +20 -0
  378. package/src/utils/dom/clickOutside.ts +11 -0
  379. package/src/utils/dom/externalLink.ts +57 -0
  380. package/src/utils/dom/scrollable.ts +24 -0
  381. package/src/utils/errors.ts +11 -0
  382. package/src/utils/files/expandedDirs.ts +25 -0
  383. package/src/utils/files/filename.ts +12 -0
  384. package/src/utils/files/sortChildren.ts +20 -0
  385. package/src/utils/filesPreview/schedulerPreview.ts +38 -0
  386. package/src/utils/filesPreview/todoPreview.ts +40 -0
  387. package/src/utils/format/date.ts +85 -0
  388. package/src/utils/format/frontmatter.ts +80 -0
  389. package/src/utils/format/jsonSyntax.ts +109 -0
  390. package/src/utils/html/previewCsp.ts +65 -0
  391. package/src/utils/image/resolve.ts +8 -0
  392. package/src/utils/image/rewriteMarkdownImageRefs.ts +182 -0
  393. package/src/utils/markdown/extractFirstH1.ts +39 -0
  394. package/src/utils/notification/dispatch.ts +22 -0
  395. package/src/utils/path/relativeLink.ts +130 -0
  396. package/src/utils/role/icon.ts +20 -0
  397. package/src/utils/role/merge.ts +10 -0
  398. package/src/utils/role/plugins.ts +12 -0
  399. package/src/utils/session/mergeSessions.ts +103 -0
  400. package/src/utils/session/seedRoleDefault.ts +35 -0
  401. package/src/utils/session/sessionEntries.ts +121 -0
  402. package/src/utils/session/sessionFactory.ts +22 -0
  403. package/src/utils/session/sessionHelpers.ts +99 -0
  404. package/src/utils/tools/dedup.ts +17 -0
  405. package/src/utils/tools/mcp.ts +33 -0
  406. package/src/utils/tools/pendingCalls.ts +16 -0
  407. package/src/utils/tools/result.ts +40 -0
  408. package/src/utils/types.ts +44 -0
@@ -0,0 +1,299 @@
1
+ /**
2
+ * Date and Time Functions
3
+ * Excel stores dates as sequential serial numbers so they can be used in calculations.
4
+ * January 1, 1900 is serial number 1.
5
+ */
6
+
7
+ import { functionRegistry, toNumber, toString, type FunctionHandler } from "../registry";
8
+ import { dateToSerial, serialToDate } from "../date-utils";
9
+
10
+ const MS_PER_DAY = 24 * 60 * 60 * 1000;
11
+
12
+ const nowHandler: FunctionHandler = (args) => {
13
+ if (args.length !== 0) throw new Error("NOW requires 0 arguments");
14
+ // Return current date and time as serial number
15
+ // We need to adjust for timezone offset because Excel dates are "local" usually
16
+ // But for simplicity we'll use local time converted to serial
17
+ const now = new Date();
18
+ // Create a UTC date that matches the local time components
19
+ const localAsUtc = new Date(Date.UTC(now.getFullYear(), now.getMonth(), now.getDate(), now.getHours(), now.getMinutes(), now.getSeconds()));
20
+ return dateToSerial(localAsUtc);
21
+ };
22
+
23
+ const todayHandler: FunctionHandler = (args) => {
24
+ if (args.length !== 0) throw new Error("TODAY requires 0 arguments");
25
+ const now = new Date();
26
+ const today = new Date(Date.UTC(now.getFullYear(), now.getMonth(), now.getDate()));
27
+ return dateToSerial(today);
28
+ };
29
+
30
+ const dateHandler: FunctionHandler = (args, context) => {
31
+ if (args.length !== 3) throw new Error("DATE requires 3 arguments");
32
+
33
+ const year = toNumber(context.evaluateFormula(args[0]));
34
+ const month = toNumber(context.evaluateFormula(args[1]));
35
+ const day = toNumber(context.evaluateFormula(args[2]));
36
+
37
+ // JS Date constructor handles overflow (e.g. month 13 becomes Jan of next year)
38
+ // Month is 0-indexed in JS, 1-indexed in Excel
39
+ const date = new Date(Date.UTC(year, month - 1, day));
40
+ return dateToSerial(date);
41
+ };
42
+
43
+ const timeHandler: FunctionHandler = (args, context) => {
44
+ if (args.length !== 3) throw new Error("TIME requires 3 arguments");
45
+
46
+ const hour = toNumber(context.evaluateFormula(args[0]));
47
+ const minute = toNumber(context.evaluateFormula(args[1]));
48
+ const second = toNumber(context.evaluateFormula(args[2]));
49
+
50
+ // Time is a fraction of a day
51
+ // 1 hour = 1/24
52
+ // 1 minute = 1/(24*60)
53
+ // 1 second = 1/(24*60*60)
54
+
55
+ // Normalize inputs (e.g. 25 hours)
56
+ const totalSeconds = hour * 3600 + minute * 60 + second;
57
+ const secondsPerDay = 86400;
58
+
59
+ return (totalSeconds % secondsPerDay) / secondsPerDay;
60
+ };
61
+
62
+ const yearHandler: FunctionHandler = (args, context) => {
63
+ if (args.length !== 1) throw new Error("YEAR requires 1 argument");
64
+ const serial = toNumber(context.evaluateFormula(args[0]));
65
+ const date = serialToDate(serial);
66
+ return date.getUTCFullYear();
67
+ };
68
+
69
+ const monthHandler: FunctionHandler = (args, context) => {
70
+ if (args.length !== 1) throw new Error("MONTH requires 1 argument");
71
+ const serial = toNumber(context.evaluateFormula(args[0]));
72
+ const date = serialToDate(serial);
73
+ return date.getUTCMonth() + 1; // 1-indexed
74
+ };
75
+
76
+ const dayHandler: FunctionHandler = (args, context) => {
77
+ if (args.length !== 1) throw new Error("DAY requires 1 argument");
78
+ const serial = toNumber(context.evaluateFormula(args[0]));
79
+ const date = serialToDate(serial);
80
+ return date.getUTCDate();
81
+ };
82
+
83
+ const hourHandler: FunctionHandler = (args, context) => {
84
+ if (args.length !== 1) throw new Error("HOUR requires 1 argument");
85
+ const serial = toNumber(context.evaluateFormula(args[0]));
86
+ // Get fractional part
87
+ const timePart = serial - Math.floor(serial);
88
+ const totalSeconds = Math.round(timePart * 86400);
89
+ return Math.floor(totalSeconds / 3600);
90
+ };
91
+
92
+ const minuteHandler: FunctionHandler = (args, context) => {
93
+ if (args.length !== 1) throw new Error("MINUTE requires 1 argument");
94
+ const serial = toNumber(context.evaluateFormula(args[0]));
95
+ const timePart = serial - Math.floor(serial);
96
+ const totalSeconds = Math.round(timePart * 86400);
97
+ return Math.floor((totalSeconds % 3600) / 60);
98
+ };
99
+
100
+ const secondHandler: FunctionHandler = (args, context) => {
101
+ if (args.length !== 1) throw new Error("SECOND requires 1 argument");
102
+ const serial = toNumber(context.evaluateFormula(args[0]));
103
+ const timePart = serial - Math.floor(serial);
104
+ const totalSeconds = Math.round(timePart * 86400);
105
+ return totalSeconds % 60;
106
+ };
107
+
108
+ const datedifHandler: FunctionHandler = (args, context) => {
109
+ if (args.length !== 3) throw new Error("DATEDIF requires 3 arguments");
110
+
111
+ const startSerial = toNumber(context.evaluateFormula(args[0]));
112
+ const endSerial = toNumber(context.evaluateFormula(args[1]));
113
+ const unit = toString(context.evaluateFormula(args[2])).toUpperCase();
114
+
115
+ if (startSerial > endSerial) return "#NUM!";
116
+
117
+ const startDate = serialToDate(startSerial);
118
+ const endDate = serialToDate(endSerial);
119
+
120
+ const yearDiff = endDate.getUTCFullYear() - startDate.getUTCFullYear();
121
+ const monthDiff = endDate.getUTCMonth() - startDate.getUTCMonth();
122
+ const dayDiff = endDate.getUTCDate() - startDate.getUTCDate();
123
+
124
+ switch (unit) {
125
+ case "Y": {
126
+ // Complete years
127
+ let years = yearDiff;
128
+ if (monthDiff < 0 || (monthDiff === 0 && dayDiff < 0)) {
129
+ years--;
130
+ }
131
+ return years;
132
+ }
133
+
134
+ case "M": {
135
+ // Complete months
136
+ let months = yearDiff * 12 + monthDiff;
137
+ if (dayDiff < 0) {
138
+ months--;
139
+ }
140
+ return months;
141
+ }
142
+
143
+ case "D":
144
+ // Complete days
145
+ return Math.floor(endSerial - startSerial);
146
+
147
+ case "MD": {
148
+ // Difference in days, ignoring months and years
149
+ // This is tricky. It's basically day of month difference, but handling wrap around
150
+ // E.g. Jan 30 to Mar 1.
151
+ // Standard implementation:
152
+ const startD = startDate.getUTCDate();
153
+ const endD = endDate.getUTCDate();
154
+
155
+ if (endD >= startD) return endD - startD;
156
+
157
+ // Need to borrow days from previous month
158
+ const prevMonthDate = new Date(Date.UTC(endDate.getUTCFullYear(), endDate.getUTCMonth(), 0));
159
+ return prevMonthDate.getUTCDate() - startD + endD;
160
+ }
161
+
162
+ case "YM": {
163
+ // Difference in months, ignoring years
164
+ let ym = monthDiff;
165
+ if (dayDiff < 0) ym--;
166
+ if (ym < 0) ym += 12;
167
+ return ym;
168
+ }
169
+
170
+ case "YD": {
171
+ // Difference in days, ignoring years
172
+ // Treat start date as being in the same year as end date
173
+ // If start > end (after adjusting year), move start to previous year
174
+ const startCopy = new Date(startDate);
175
+ startCopy.setUTCFullYear(endDate.getUTCFullYear());
176
+
177
+ const diff = (startCopy.getTime() - endDate.getTime()) / MS_PER_DAY;
178
+ if (diff > 0) {
179
+ startCopy.setUTCFullYear(endDate.getUTCFullYear() - 1);
180
+ }
181
+
182
+ return Math.floor((endDate.getTime() - startCopy.getTime()) / MS_PER_DAY);
183
+ }
184
+
185
+ default:
186
+ return "#NUM!";
187
+ }
188
+ };
189
+
190
+ // Register functions
191
+ functionRegistry.register({
192
+ name: "NOW",
193
+ handler: nowHandler,
194
+ minArgs: 0,
195
+ maxArgs: 0,
196
+ description: "Returns the serial number of the current date and time",
197
+ examples: ["NOW()"],
198
+ category: "Date & Time",
199
+ });
200
+
201
+ functionRegistry.register({
202
+ name: "TODAY",
203
+ handler: todayHandler,
204
+ minArgs: 0,
205
+ maxArgs: 0,
206
+ description: "Returns the serial number of today's date",
207
+ examples: ["TODAY()"],
208
+ category: "Date & Time",
209
+ });
210
+
211
+ functionRegistry.register({
212
+ name: "DATE",
213
+ handler: dateHandler,
214
+ minArgs: 3,
215
+ maxArgs: 3,
216
+ description: "Returns the serial number that represents a particular date",
217
+ examples: ["DATE(2023, 11, 25)"],
218
+ category: "Date & Time",
219
+ });
220
+
221
+ functionRegistry.register({
222
+ name: "TIME",
223
+ handler: timeHandler,
224
+ minArgs: 3,
225
+ maxArgs: 3,
226
+ description: "Returns the serial number of a particular time",
227
+ examples: ["TIME(14, 30, 0)"],
228
+ category: "Date & Time",
229
+ });
230
+
231
+ functionRegistry.register({
232
+ name: "YEAR",
233
+ handler: yearHandler,
234
+ minArgs: 1,
235
+ maxArgs: 1,
236
+ description: "Converts a serial number to a year",
237
+ examples: ["YEAR(TODAY())", "YEAR(A1)"],
238
+ category: "Date & Time",
239
+ });
240
+
241
+ functionRegistry.register({
242
+ name: "MONTH",
243
+ handler: monthHandler,
244
+ minArgs: 1,
245
+ maxArgs: 1,
246
+ description: "Converts a serial number to a month",
247
+ examples: ["MONTH(TODAY())", "MONTH(A1)"],
248
+ category: "Date & Time",
249
+ });
250
+
251
+ functionRegistry.register({
252
+ name: "DAY",
253
+ handler: dayHandler,
254
+ minArgs: 1,
255
+ maxArgs: 1,
256
+ description: "Converts a serial number to a day of the month",
257
+ examples: ["DAY(TODAY())", "DAY(A1)"],
258
+ category: "Date & Time",
259
+ });
260
+
261
+ functionRegistry.register({
262
+ name: "HOUR",
263
+ handler: hourHandler,
264
+ minArgs: 1,
265
+ maxArgs: 1,
266
+ description: "Converts a serial number to an hour",
267
+ examples: ["HOUR(NOW())", "HOUR(A1)"],
268
+ category: "Date & Time",
269
+ });
270
+
271
+ functionRegistry.register({
272
+ name: "MINUTE",
273
+ handler: minuteHandler,
274
+ minArgs: 1,
275
+ maxArgs: 1,
276
+ description: "Converts a serial number to a minute",
277
+ examples: ["MINUTE(NOW())", "MINUTE(A1)"],
278
+ category: "Date & Time",
279
+ });
280
+
281
+ functionRegistry.register({
282
+ name: "SECOND",
283
+ handler: secondHandler,
284
+ minArgs: 1,
285
+ maxArgs: 1,
286
+ description: "Converts a serial number to a second",
287
+ examples: ["SECOND(NOW())", "SECOND(A1)"],
288
+ category: "Date & Time",
289
+ });
290
+
291
+ functionRegistry.register({
292
+ name: "DATEDIF",
293
+ handler: datedifHandler,
294
+ minArgs: 3,
295
+ maxArgs: 3,
296
+ description: "Calculates the number of days, months, or years between two dates",
297
+ examples: ['DATEDIF(A1, B1, "Y")', 'DATEDIF(DATE(2020,1,1), TODAY(), "D")'],
298
+ category: "Date & Time",
299
+ });
@@ -0,0 +1,387 @@
1
+ /**
2
+ * Financial Functions
3
+ */
4
+
5
+ import { functionRegistry, toNumber, type FunctionHandler } from "../registry";
6
+
7
+ /**
8
+ * FV - Future Value
9
+ * Calculates the future value of an investment based on periodic, constant payments and a constant interest rate.
10
+ * FV(rate, nper, pmt, [pv], [type])
11
+ * - rate: Interest rate per period
12
+ * - nper: Total number of payment periods
13
+ * - pmt: Payment made each period (negative for outflows)
14
+ * - pv: Present value (optional, default 0)
15
+ * - type: 0 = end of period, 1 = beginning of period (optional, default 0)
16
+ */
17
+ const fvHandler: FunctionHandler = (args, context) => {
18
+ if (args.length < 3 || args.length > 5) {
19
+ throw new Error("FV requires 3 to 5 arguments");
20
+ }
21
+
22
+ const rate = toNumber(context.evaluateFormula(args[0]));
23
+ const nper = toNumber(context.evaluateFormula(args[1]));
24
+ const pmt = toNumber(context.evaluateFormula(args[2]));
25
+ const pv = args.length >= 4 ? toNumber(context.evaluateFormula(args[3])) : 0;
26
+ const type = args.length >= 5 ? toNumber(context.evaluateFormula(args[4])) : 0;
27
+
28
+ if (rate === 0) {
29
+ return -(pv + pmt * nper);
30
+ }
31
+
32
+ const pvFactor = Math.pow(1 + rate, nper);
33
+ const fv = -pv * pvFactor - (pmt * (pvFactor - 1) * (1 + rate * type)) / rate;
34
+
35
+ return fv;
36
+ };
37
+
38
+ /**
39
+ * PV - Present Value
40
+ * Calculates the present value of an investment based on periodic, constant payments and a constant interest rate.
41
+ * PV(rate, nper, pmt, [fv], [type])
42
+ */
43
+ const pvHandler: FunctionHandler = (args, context) => {
44
+ if (args.length < 3 || args.length > 5) {
45
+ throw new Error("PV requires 3 to 5 arguments");
46
+ }
47
+
48
+ const rate = toNumber(context.evaluateFormula(args[0]));
49
+ const nper = toNumber(context.evaluateFormula(args[1]));
50
+ const pmt = toNumber(context.evaluateFormula(args[2]));
51
+ const fv = args.length >= 4 ? toNumber(context.evaluateFormula(args[3])) : 0;
52
+ const type = args.length >= 5 ? toNumber(context.evaluateFormula(args[4])) : 0;
53
+
54
+ if (rate === 0) {
55
+ return -(fv + pmt * nper);
56
+ }
57
+
58
+ const pvFactor = Math.pow(1 + rate, nper);
59
+ const pv = (-fv - (pmt * (pvFactor - 1) * (1 + rate * type)) / rate) / pvFactor;
60
+
61
+ return pv;
62
+ };
63
+
64
+ /**
65
+ * PMT - Payment
66
+ * Calculates the payment for a loan based on constant payments and a constant interest rate.
67
+ * PMT(rate, nper, pv, [fv], [type])
68
+ */
69
+ const pmtHandler: FunctionHandler = (args, context) => {
70
+ if (args.length < 3 || args.length > 5) {
71
+ throw new Error("PMT requires 3 to 5 arguments");
72
+ }
73
+
74
+ const rate = toNumber(context.evaluateFormula(args[0]));
75
+ const nper = toNumber(context.evaluateFormula(args[1]));
76
+ const pv = toNumber(context.evaluateFormula(args[2]));
77
+ const fv = args.length >= 4 ? toNumber(context.evaluateFormula(args[3])) : 0;
78
+ const type = args.length >= 5 ? toNumber(context.evaluateFormula(args[4])) : 0;
79
+
80
+ if (rate === 0) {
81
+ return -(fv + pv) / nper;
82
+ }
83
+
84
+ const pvFactor = Math.pow(1 + rate, nper);
85
+ const pmt = (-rate * (fv + pv * pvFactor)) / ((pvFactor - 1) * (1 + rate * type));
86
+
87
+ return pmt;
88
+ };
89
+
90
+ /**
91
+ * NPER - Number of Periods
92
+ * Calculates the number of periods for an investment based on periodic, constant payments and a constant interest rate.
93
+ * NPER(rate, pmt, pv, [fv], [type])
94
+ */
95
+ const nperHandler: FunctionHandler = (args, context) => {
96
+ if (args.length < 3 || args.length > 5) {
97
+ throw new Error("NPER requires 3 to 5 arguments");
98
+ }
99
+
100
+ const rate = toNumber(context.evaluateFormula(args[0]));
101
+ const pmt = toNumber(context.evaluateFormula(args[1]));
102
+ const pv = toNumber(context.evaluateFormula(args[2]));
103
+ const fv = args.length >= 4 ? toNumber(context.evaluateFormula(args[3])) : 0;
104
+ const type = args.length >= 5 ? toNumber(context.evaluateFormula(args[4])) : 0;
105
+
106
+ if (rate === 0) {
107
+ return -(fv + pv) / pmt;
108
+ }
109
+
110
+ const pmtWithType = pmt * (1 + rate * type);
111
+ const nper = Math.log((pmtWithType - fv * rate) / (pmtWithType + pv * rate)) / Math.log(1 + rate);
112
+
113
+ return nper;
114
+ };
115
+
116
+ /**
117
+ * RATE - Interest Rate
118
+ * Calculates the interest rate per period of an annuity.
119
+ * RATE(nper, pmt, pv, [fv], [type], [guess])
120
+ * Uses Newton-Raphson method for iteration
121
+ */
122
+ const rateHandler: FunctionHandler = (args, context) => {
123
+ if (args.length < 3 || args.length > 6) {
124
+ throw new Error("RATE requires 3 to 6 arguments");
125
+ }
126
+
127
+ const nper = toNumber(context.evaluateFormula(args[0]));
128
+ const pmt = toNumber(context.evaluateFormula(args[1]));
129
+ const pv = toNumber(context.evaluateFormula(args[2]));
130
+ const fv = args.length >= 4 ? toNumber(context.evaluateFormula(args[3])) : 0;
131
+ const type = args.length >= 5 ? toNumber(context.evaluateFormula(args[4])) : 0;
132
+ const guess = args.length >= 6 ? toNumber(context.evaluateFormula(args[5])) : 0.1;
133
+
134
+ // Use Newton-Raphson method to find rate
135
+ let rate = guess;
136
+ const maxIterations = 100;
137
+ const tolerance = 1e-7;
138
+
139
+ for (let i = 0; i < maxIterations; i++) {
140
+ if (Math.abs(rate) < tolerance) {
141
+ rate = tolerance; // Avoid division by zero
142
+ }
143
+
144
+ const y = Math.pow(1 + rate, nper);
145
+ const f = pv * y + pmt * ((y - 1) / rate) * (1 + rate * type) + fv;
146
+
147
+ const df =
148
+ nper * pv * Math.pow(1 + rate, nper - 1) +
149
+ (pmt * (1 + rate * type) * (nper * Math.pow(1 + rate, nper - 1) * rate - (Math.pow(1 + rate, nper) - 1))) / (rate * rate) +
150
+ pmt * type * ((Math.pow(1 + rate, nper) - 1) / rate);
151
+
152
+ const newRate = rate - f / df;
153
+
154
+ if (Math.abs(newRate - rate) < tolerance) {
155
+ return newRate;
156
+ }
157
+
158
+ rate = newRate;
159
+ }
160
+
161
+ return rate;
162
+ };
163
+
164
+ /**
165
+ * IPMT - Interest Payment
166
+ * Calculates the interest payment for a given period for an investment based on periodic, constant payments and a constant interest rate.
167
+ * IPMT(rate, per, nper, pv, [fv], [type])
168
+ */
169
+ const ipmtHandler: FunctionHandler = (args, context) => {
170
+ if (args.length < 4 || args.length > 6) {
171
+ throw new Error("IPMT requires 4 to 6 arguments");
172
+ }
173
+
174
+ const rate = toNumber(context.evaluateFormula(args[0]));
175
+ const per = toNumber(context.evaluateFormula(args[1]));
176
+ const type = args.length >= 6 ? toNumber(context.evaluateFormula(args[5])) : 0;
177
+
178
+ // Calculate payment first
179
+ const pmt = pmtHandler([args[0], args[2], args[3], ...(args.length >= 5 ? [args[4]] : []), ...(args.length >= 6 ? [args[5]] : [])], context);
180
+
181
+ if (per === 1 && type === 1) {
182
+ return 0; // No interest in first period when payment is at beginning
183
+ }
184
+
185
+ // Calculate remaining balance at previous period
186
+ const fvPrevious = fvHandler([args[0], String(type === 1 ? per - 2 : per - 1), String(pmt), args[3], ...(args.length >= 6 ? [args[5]] : [])], context);
187
+
188
+ const ipmt = -fvPrevious * rate;
189
+
190
+ return type === 1 ? ipmt / (1 + rate) : ipmt;
191
+ };
192
+
193
+ /**
194
+ * PPMT - Principal Payment
195
+ * Calculates the payment on the principal for a given period for an investment based on periodic, constant payments and a constant interest rate.
196
+ * PPMT(rate, per, nper, pv, [fv], [type])
197
+ */
198
+ const ppmtHandler: FunctionHandler = (args, context) => {
199
+ if (args.length < 4 || args.length > 6) {
200
+ throw new Error("PPMT requires 4 to 6 arguments");
201
+ }
202
+
203
+ // Calculate total payment
204
+ const pmt = pmtHandler([args[0], args[2], args[3], ...(args.length >= 5 ? [args[4]] : []), ...(args.length >= 6 ? [args[5]] : [])], context);
205
+
206
+ // Calculate interest payment
207
+ const ipmt = ipmtHandler(args, context);
208
+
209
+ // Principal payment = Total payment - Interest payment
210
+ return toNumber(pmt) - toNumber(ipmt);
211
+ };
212
+
213
+ /**
214
+ * NPV - Net Present Value
215
+ * Calculates the net present value of an investment based on a discount rate and a series of future cash flows.
216
+ * NPV(rate, value1, [value2], ...)
217
+ */
218
+ const npvHandler: FunctionHandler = (args, context) => {
219
+ if (args.length < 2) {
220
+ throw new Error("NPV requires at least 2 arguments");
221
+ }
222
+
223
+ const rate = toNumber(context.evaluateFormula(args[0]));
224
+ let npv = 0;
225
+
226
+ // Process each cash flow
227
+ for (let i = 1; i < args.length; i++) {
228
+ // Check if argument is a range
229
+ if (args[i].includes(":")) {
230
+ const values = context.getRangeValues(args[i]);
231
+ for (let j = 0; j < values.length; j++) {
232
+ const value = toNumber(values[j]);
233
+ // Period starts from i for first range element, then continues
234
+ const period = i + j;
235
+ npv += value / Math.pow(1 + rate, period);
236
+ }
237
+ } else {
238
+ const value = toNumber(context.evaluateFormula(args[i]));
239
+ npv += value / Math.pow(1 + rate, i);
240
+ }
241
+ }
242
+
243
+ return npv;
244
+ };
245
+
246
+ /**
247
+ * IRR - Internal Rate of Return
248
+ * Calculates the internal rate of return for a series of cash flows.
249
+ * IRR(values, [guess])
250
+ * Uses Newton-Raphson method for iteration
251
+ */
252
+ const irrHandler: FunctionHandler = (args, context) => {
253
+ if (args.length < 1 || args.length > 2) {
254
+ throw new Error("IRR requires 1 or 2 arguments");
255
+ }
256
+
257
+ const values = context.getRangeValues(args[0]).map(toNumber);
258
+ const guess = args.length === 2 ? toNumber(context.evaluateFormula(args[1])) : 0.1;
259
+
260
+ if (values.length === 0) {
261
+ throw new Error("IRR requires at least one value");
262
+ }
263
+
264
+ // Use Newton-Raphson method
265
+ let rate = guess;
266
+ const maxIterations = 100;
267
+ const tolerance = 1e-7;
268
+
269
+ for (let i = 0; i < maxIterations; i++) {
270
+ let npv = 0;
271
+ let dnpv = 0;
272
+
273
+ for (let j = 0; j < values.length; j++) {
274
+ const factor = Math.pow(1 + rate, j);
275
+ npv += values[j] / factor;
276
+ dnpv -= (j * values[j]) / (factor * (1 + rate));
277
+ }
278
+
279
+ if (Math.abs(npv) < tolerance) {
280
+ return rate;
281
+ }
282
+
283
+ if (Math.abs(dnpv) < tolerance) {
284
+ throw new Error("IRR cannot converge");
285
+ }
286
+
287
+ const newRate = rate - npv / dnpv;
288
+
289
+ if (Math.abs(newRate - rate) < tolerance) {
290
+ return newRate;
291
+ }
292
+
293
+ rate = newRate;
294
+ }
295
+
296
+ return rate;
297
+ };
298
+
299
+ // Register all financial functions
300
+ functionRegistry.register({
301
+ name: "FV",
302
+ handler: fvHandler,
303
+ minArgs: 3,
304
+ maxArgs: 5,
305
+ description: "Calculates the future value of an investment based on periodic, constant payments and a constant interest rate",
306
+ examples: ["FV(0.06/12, 12, -100, -1000, 1)", "FV(A1, A2, A3)"],
307
+ category: "Financial",
308
+ });
309
+
310
+ functionRegistry.register({
311
+ name: "PV",
312
+ handler: pvHandler,
313
+ minArgs: 3,
314
+ maxArgs: 5,
315
+ description: "Calculates the present value of an investment based on periodic, constant payments and a constant interest rate",
316
+ examples: ["PV(0.08/12, 12*20, 500, 0, 0)", "PV(A1, A2, A3)"],
317
+ category: "Financial",
318
+ });
319
+
320
+ functionRegistry.register({
321
+ name: "PMT",
322
+ handler: pmtHandler,
323
+ minArgs: 3,
324
+ maxArgs: 5,
325
+ description: "Calculates the payment for a loan based on constant payments and a constant interest rate",
326
+ examples: ["PMT(0.06/12, 30*12, 250000)", "PMT(A1, A2, A3)"],
327
+ category: "Financial",
328
+ });
329
+
330
+ functionRegistry.register({
331
+ name: "NPER",
332
+ handler: nperHandler,
333
+ minArgs: 3,
334
+ maxArgs: 5,
335
+ description: "Calculates the number of periods for an investment based on periodic, constant payments and a constant interest rate",
336
+ examples: ["NPER(0.06/12, -1000, 50000, 0, 0)", "NPER(A1, A2, A3)"],
337
+ category: "Financial",
338
+ });
339
+
340
+ functionRegistry.register({
341
+ name: "RATE",
342
+ handler: rateHandler,
343
+ minArgs: 3,
344
+ maxArgs: 6,
345
+ description: "Calculates the interest rate per period of an annuity using iteration",
346
+ examples: ["RATE(12, -100, 1000, 0, 0, 0.1)", "RATE(A1, A2, A3)"],
347
+ category: "Financial",
348
+ });
349
+
350
+ functionRegistry.register({
351
+ name: "IPMT",
352
+ handler: ipmtHandler,
353
+ minArgs: 4,
354
+ maxArgs: 6,
355
+ description: "Calculates the interest payment for a given period for an investment",
356
+ examples: ["IPMT(0.06/12, 1, 30*12, 250000)", "IPMT(A1, A2, A3, A4)"],
357
+ category: "Financial",
358
+ });
359
+
360
+ functionRegistry.register({
361
+ name: "PPMT",
362
+ handler: ppmtHandler,
363
+ minArgs: 4,
364
+ maxArgs: 6,
365
+ description: "Calculates the payment on the principal for a given period for an investment",
366
+ examples: ["PPMT(0.06/12, 1, 30*12, 250000)", "PPMT(A1, A2, A3, A4)"],
367
+ category: "Financial",
368
+ });
369
+
370
+ functionRegistry.register({
371
+ name: "NPV",
372
+ handler: npvHandler,
373
+ minArgs: 2,
374
+ description: "Calculates the net present value of an investment based on a discount rate and a series of future cash flows",
375
+ examples: ["NPV(0.1, -10000, 3000, 4200, 6800)", "NPV(A1, B1:B10)"],
376
+ category: "Financial",
377
+ });
378
+
379
+ functionRegistry.register({
380
+ name: "IRR",
381
+ handler: irrHandler,
382
+ minArgs: 1,
383
+ maxArgs: 2,
384
+ description: "Calculates the internal rate of return for a series of cash flows",
385
+ examples: ["IRR(A1:A5, 0.1)", "IRR(B1:B10)"],
386
+ category: "Financial",
387
+ });
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Spreadsheet Functions Index
3
+ *
4
+ * Imports all function categories to register them with the function registry.
5
+ * Import this file to load all available spreadsheet functions.
6
+ */
7
+
8
+ import "./statistical";
9
+ import "./mathematical";
10
+ import "./logical";
11
+ import "./text";
12
+ import "./financial";
13
+ import "./lookup";
14
+ import "./date";
15
+
16
+ export { functionRegistry } from "../registry";