@xopcai/xopc 0.0.100 → 0.0.102

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 (260) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/feishu/src/outbound/media-load.js +1 -1
  3. package/dist/extensions/feishu/src/workflow-progress.js +1 -1
  4. package/dist/extensions/telegram/src/adapters/streaming-adapter.js +1 -1
  5. package/dist/extensions/telegram/src/inbound-processor.js +1 -1
  6. package/dist/extensions/telegram/src/plugin.js +1 -1
  7. package/dist/extensions/telegram/src/routing-integration.js +2 -2
  8. package/dist/extensions/telegram/src/update-offset-store.js +1 -1
  9. package/dist/extensions/telegram/src/workflow-progress.js +1 -1
  10. package/dist/extensions/telegram/xopc.extension.json +1 -1
  11. package/dist/extensions/weixin/src/api/api.js +7 -5
  12. package/dist/extensions/weixin/src/api/api.js.map +1 -1
  13. package/dist/extensions/weixin/src/auth/accounts.js +1 -1
  14. package/dist/extensions/weixin/src/cdn/upload.js +1 -1
  15. package/dist/extensions/weixin/src/media/data-url.js +1 -1
  16. package/dist/extensions/weixin/src/messaging/debug-mode.js +1 -1
  17. package/dist/extensions/weixin/src/messaging/inbound.js +1 -1
  18. package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
  19. package/dist/extensions/weixin/src/plugin.js +1 -1
  20. package/dist/extensions/weixin/src/storage/sync-buf.js +1 -1
  21. package/dist/extensions/weixin/src/workflow-progress.js +1 -1
  22. package/dist/gateway/static/root/assets/{agents-C5jtBK-H.js → agents-DQ0mQxIA.js} +2 -2
  23. package/dist/gateway/static/root/assets/{apps-page-smJl-qf_.js → apps-page-Uv4kOmDE.js} +1 -1
  24. package/dist/gateway/static/root/assets/{attachment-preview-renderer-DBAxQXb-.js → attachment-preview-renderer-CybMSIoS.js} +2 -2
  25. package/dist/gateway/static/root/assets/{attachment-process-heavy-Csq3TrrP.js → attachment-process-heavy-RnGYy9bC.js} +2 -2
  26. package/dist/gateway/static/root/assets/{channels-settings-CH6KgFK6.js → channels-settings-BEtP53V6.js} +1 -1
  27. package/dist/gateway/static/root/assets/{channels-status-swr-CV70xvY7.js → channels-status-swr-CxTtS1hI.js} +1 -1
  28. package/dist/gateway/static/root/assets/{cron-api-CgBO8B7I.js → cron-api-CznlPIZT.js} +1 -1
  29. package/dist/gateway/static/root/assets/{cron-page-Be0cW1cR.js → cron-page-Dx6dE3eD.js} +1 -1
  30. package/dist/gateway/static/root/assets/{dist-P8HRGUuh.js → dist-DH4IuRV0.js} +1 -1
  31. package/dist/gateway/static/root/assets/{docx-preview-Dxj1EkCO.js → docx-preview-CajIk2FR.js} +1 -1
  32. package/dist/gateway/static/root/assets/{extension-debug-page-BowuycYu.js → extension-debug-page-BNkhvRQW.js} +1 -1
  33. package/dist/gateway/static/root/assets/{extension-page-27-Zpv8O.js → extension-page-CcIGQah2.js} +1 -1
  34. package/dist/gateway/static/root/assets/{extension-settings-page-DDFa_rIq.js → extension-settings-page-DuDCSb3J.js} +1 -1
  35. package/dist/gateway/static/root/assets/{field-primitives-BWLssxEb.js → field-primitives-BUwUiDf5.js} +1 -1
  36. package/dist/gateway/static/root/assets/{heartbeat-config-api-BVuYNYT_.js → heartbeat-config-api-BjFW1cl-.js} +1 -1
  37. package/dist/gateway/static/root/assets/{index-CRDAmr3W.js → index-DKgHC1Ta.js} +9 -9
  38. package/dist/gateway/static/root/assets/{logs-page-BDX8IrDQ.js → logs-page-CiG0m81R.js} +1 -1
  39. package/dist/gateway/static/root/assets/{note-detail-page-BmQ9KeiA.js → note-detail-page-DG3DVFTf.js} +2 -2
  40. package/dist/gateway/static/root/assets/{note-time-14I9Sgqh.js → note-time-DjlllCF3.js} +1 -1
  41. package/dist/gateway/static/root/assets/{notes-page-BMfP0FFf.js → notes-page-D40ZpS0Y.js} +1 -1
  42. package/dist/gateway/static/root/assets/{sessions-page-C3scyChq.js → sessions-page-BvtdbmW8.js} +1 -1
  43. package/dist/gateway/static/root/assets/{settings-advanced-gate-2ODuCjHP.js → settings-advanced-gate-BQamRjkV.js} +2 -2
  44. package/dist/gateway/static/root/assets/{settings-form-section-DUoGKAiW.js → settings-form-section-C3_sEFfD.js} +1 -1
  45. package/dist/gateway/static/root/assets/{settings-page-CttAfOWV.js → settings-page-D972_jaS.js} +2 -2
  46. package/dist/gateway/static/root/assets/{share-preview-page-B77xqiiI.js → share-preview-page-CKCTMo0_.js} +2 -2
  47. package/dist/gateway/static/root/assets/{skills-page-B_bAZGzB.js → skills-page-QwFCB4yV.js} +1 -1
  48. package/dist/gateway/static/root/assets/{theme-store-BgCPrmxU.js → theme-store-B6KXPHgK.js} +1 -1
  49. package/dist/gateway/static/root/assets/{utils-CCGejlcX.js → utils-DCm11_KW.js} +1 -1
  50. package/dist/gateway/static/root/assets/{voice-api-key-field-DZzzihcY.js → voice-api-key-field-CywiB7Dw.js} +1 -1
  51. package/dist/gateway/static/root/assets/{workflow-page.utils-D5RMAmT4.js → workflow-page.utils-g57BRfEd.js} +1 -1
  52. package/dist/gateway/static/root/assets/{workflows-page-DEYpC6Bv.js → workflows-page-Be7l_SWw.js} +1 -1
  53. package/dist/gateway/static/root/index.html +2 -2
  54. package/dist/package.js +1 -1
  55. package/dist/src/agent/agent-manager.js +23 -7
  56. package/dist/src/agent/agent-manager.js.map +1 -1
  57. package/dist/src/agent/agent-scope.js +1 -1
  58. package/dist/src/agent/bootstrap/load-bootstrap-files.js +1 -1
  59. package/dist/src/agent/context/workspace-seed.js +2 -2
  60. package/dist/src/agent/context/workspace-state.js +1 -1
  61. package/dist/src/agent/embedded/run-for-session.js +1 -0
  62. package/dist/src/agent/embedded/run-for-session.js.map +1 -1
  63. package/dist/src/agent/goals/goal-run-store.js +4 -4
  64. package/dist/src/agent/goals/persistent-goal-service.js +1 -1
  65. package/dist/src/agent/goals/post-turn.js +2 -2
  66. package/dist/src/agent/image/load-image-media.js +2 -2
  67. package/dist/src/agent/ipc/bus.js +1 -1
  68. package/dist/src/agent/ipc/inbox.js +2 -2
  69. package/dist/src/agent/ipc/socket.js +1 -1
  70. package/dist/src/agent/mcp/bundle-mcp-materialize.js +1 -1
  71. package/dist/src/agent/mcp/bundle-mcp-runtime.js +1 -1
  72. package/dist/src/agent/mcp/mcp-transport-config.js +1 -1
  73. package/dist/src/agent/mcp/mcp-transport.js +1 -1
  74. package/dist/src/agent/memory/builtin-memory-store.js +1 -1
  75. package/dist/src/agent/memory/dreaming/deep-promotion.js +1 -1
  76. package/dist/src/agent/memory/dreaming/events.js +1 -1
  77. package/dist/src/agent/memory/dreaming/last-run.js +1 -1
  78. package/dist/src/agent/memory/dreaming/light-sweep.js +1 -1
  79. package/dist/src/agent/memory/dreaming/preview.js +1 -1
  80. package/dist/src/agent/memory/dreaming/rem-patterns.js +1 -1
  81. package/dist/src/agent/memory/dreaming/short-term-store.js +1 -1
  82. package/dist/src/agent/memory/dreaming/utils.js +1 -1
  83. package/dist/src/agent/memory/memory-flush.js +1 -1
  84. package/dist/src/agent/memory/plugin-discovery.js +1 -1
  85. package/dist/src/agent/models/manager.js +1 -1
  86. package/dist/src/agent/prompt/service-prompt-builder.js +2 -2
  87. package/dist/src/agent/reply/post-compaction-context.js +1 -1
  88. package/dist/src/agent/reply/workspace-boundary-read.js +1 -1
  89. package/dist/src/agent/sandbox/path-policy.js +2 -2
  90. package/dist/src/agent/service.js +4 -4
  91. package/dist/src/agent/session/session-inspector.js +1 -1
  92. package/dist/src/agent/skills/config.js +1 -1
  93. package/dist/src/agent/skills/hub-hash.js +2 -2
  94. package/dist/src/agent/skills/hub-lock.js +1 -1
  95. package/dist/src/agent/skills/hub-pull.js +2 -2
  96. package/dist/src/agent/skills/index.js +1 -1
  97. package/dist/src/agent/skills/managed-store.js +1 -1
  98. package/dist/src/agent/skills/scanner.js +1 -1
  99. package/dist/src/agent/skills/skill-manage-ops.js +1 -1
  100. package/dist/src/agent/skills/skill-manager.js +1 -1
  101. package/dist/src/agent/tools/dreaming-tool.js +1 -1
  102. package/dist/src/agent/tools/factory.js +1 -1
  103. package/dist/src/agent/tools/image-generate-tool.js +1 -1
  104. package/dist/src/agent/tools/send-media.js +1 -1
  105. package/dist/src/agent/tools/skill-manage-tool.js +1 -1
  106. package/dist/src/agent/tools/workflow-tool.js +1 -1
  107. package/dist/src/agent/tools/write.js +1 -1
  108. package/dist/src/agent/workflow/catalog.js +1 -1
  109. package/dist/src/auth/credentials.js +3 -4
  110. package/dist/src/auth/credentials.js.map +1 -1
  111. package/dist/src/auth/profiles/store.js +1 -1
  112. package/dist/src/auth/sync-provider-auth.js +1 -1
  113. package/dist/src/browser/cache-dir-policy.js +1 -1
  114. package/dist/src/browser/cdp-local-launcher.js +2 -2
  115. package/dist/src/browser/providers/browser-ext-install.js +3 -3
  116. package/dist/src/browser/providers/cloakbrowser.js +4 -4
  117. package/dist/src/browser/providers/playwright-doctor.js +1 -1
  118. package/dist/src/browser/stealth.js +1 -1
  119. package/dist/src/channels/outbound/persist-store.js +1 -1
  120. package/dist/src/channels/pairing/allow-from-file.js +1 -1
  121. package/dist/src/channels/pairing/pairing-store.js +2 -2
  122. package/dist/src/chat-commands/agent-edit.js +2 -2
  123. package/dist/src/chat-commands/builtins/config.js +2 -2
  124. package/dist/src/chat-commands/context.js +1 -1
  125. package/dist/src/cli/bin.d.ts +1 -0
  126. package/dist/src/cli/bin.js +1 -0
  127. package/dist/src/cli/bin.js.map +1 -1
  128. package/dist/src/cli/commands/config.js +1 -1
  129. package/dist/src/cli/commands/doctor/checks/config-health.js +1 -1
  130. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  131. package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
  132. package/dist/src/cli/commands/doctor/checks/state-integrity.js +1 -1
  133. package/dist/src/cli/commands/doctor/checks/workspace-status.js +1 -1
  134. package/dist/src/cli/commands/extension-dev.js +1 -1
  135. package/dist/src/cli/commands/extension-marketplace.js +1 -1
  136. package/dist/src/cli/commands/extension-pack.js +1 -1
  137. package/dist/src/cli/commands/gateway/logs.js +1 -1
  138. package/dist/src/cli/commands/image.js +1 -1
  139. package/dist/src/cli/commands/init.js +3 -3
  140. package/dist/src/cli/utils/init-workspace-core.js +2 -2
  141. package/dist/src/commands/agents.config.js +1 -1
  142. package/dist/src/config/agent-profile.js +1 -1
  143. package/dist/src/config/gateway-bind.js +1 -1
  144. package/dist/src/config/index.js +5 -5
  145. package/dist/src/config/loader.js +2 -2
  146. package/dist/src/config/models-json.js +2 -2
  147. package/dist/src/config/paths-state.js +1 -1
  148. package/dist/src/config/profile.js +2 -2
  149. package/dist/src/config/workspace-path.js +1 -1
  150. package/dist/src/cron/executor.js +2 -2
  151. package/dist/src/cron/persistence.js +1 -1
  152. package/dist/src/daemon/constants.js +1 -1
  153. package/dist/src/daemon/install-plan.js +2 -2
  154. package/dist/src/daemon/launchd.js +2 -2
  155. package/dist/src/daemon/schtasks.js +2 -2
  156. package/dist/src/daemon/systemd.js +2 -2
  157. package/dist/src/extensions/bundle-mcp.js +1 -1
  158. package/dist/src/extensions/discover-extensions.js +1 -1
  159. package/dist/src/extensions/health.js +1 -1
  160. package/dist/src/extensions/loader.js +1 -1
  161. package/dist/src/extensions/lockfile.js +2 -2
  162. package/dist/src/extensions/update.js +1 -1
  163. package/dist/src/gateway/agents-admin.js +3 -3
  164. package/dist/src/gateway/file-path-classifier.js +2 -2
  165. package/dist/src/gateway/hono/lib/config-payload.js +1 -1
  166. package/dist/src/gateway/hono/lib/extension-store.js +2 -2
  167. package/dist/src/gateway/hono/lib/static-ui.js +2 -2
  168. package/dist/src/gateway/hono/oauth-async.js +36 -3
  169. package/dist/src/gateway/hono/oauth-async.js.map +1 -1
  170. package/dist/src/gateway/hono/oauth.js +1 -1
  171. package/dist/src/gateway/hono/routes/agents.js +1 -1
  172. package/dist/src/gateway/hono/routes/auth-registry-extensions.js +1 -1
  173. package/dist/src/gateway/hono/routes/config-patch/misc.js +1 -1
  174. package/dist/src/gateway/hono/routes/dreaming.js +1 -1
  175. package/dist/src/gateway/hono/routes/host-fs.js +2 -2
  176. package/dist/src/gateway/hono/routes/models.js +1 -1
  177. package/dist/src/gateway/hono/routes/notes.js +9 -22
  178. package/dist/src/gateway/hono/routes/notes.js.map +1 -1
  179. package/dist/src/gateway/hono/routes/shares.js +1 -1
  180. package/dist/src/gateway/hono/routes/workspace.js +2 -2
  181. package/dist/src/gateway/lock.js +3 -3
  182. package/dist/src/gateway/ports.js +1 -1
  183. package/dist/src/gateway/service/agent-runner.js +2 -2
  184. package/dist/src/gateway/service/marketplace-service.js +2 -2
  185. package/dist/src/gateway/service.js +1 -1
  186. package/dist/src/gateway/workspace-fs-file-list.js +1 -1
  187. package/dist/src/infra/brew.js +1 -1
  188. package/dist/src/infra/http-proxy-env.d.ts +4 -0
  189. package/dist/src/infra/http-proxy-env.js +23 -0
  190. package/dist/src/infra/http-proxy-env.js.map +1 -0
  191. package/dist/src/infra/package-json.js +1 -1
  192. package/dist/src/infra/package-update-steps.js +1 -1
  193. package/dist/src/infra/path-env.js +2 -2
  194. package/dist/src/infra/restart.js +2 -2
  195. package/dist/src/infra/stable-node-path.js +1 -1
  196. package/dist/src/infra/update-check.js +1 -1
  197. package/dist/src/infra/update-global.js +1 -1
  198. package/dist/src/infra/update-lock.js +3 -3
  199. package/dist/src/infra/update-runner.js +1 -1
  200. package/dist/src/infra/update-startup.js +2 -2
  201. package/dist/src/infra/write-file-atomic.js +2 -2
  202. package/dist/src/media/store.js +1 -1
  203. package/dist/src/notes/note-attachment-sync.d.ts +2 -3
  204. package/dist/src/notes/note-attachment-sync.js +2 -27
  205. package/dist/src/notes/note-attachment-sync.js.map +1 -1
  206. package/dist/src/notes/note-index-meta.d.ts +6 -2
  207. package/dist/src/notes/note-index-meta.js +11 -16
  208. package/dist/src/notes/note-index-meta.js.map +1 -1
  209. package/dist/src/notes/note-markdown.d.ts +61 -0
  210. package/dist/src/notes/note-markdown.js +177 -0
  211. package/dist/src/notes/note-markdown.js.map +1 -0
  212. package/dist/src/notes/service.d.ts +9 -7
  213. package/dist/src/notes/service.js +163 -312
  214. package/dist/src/notes/service.js.map +1 -1
  215. package/dist/src/notes/store.js +4 -5
  216. package/dist/src/notes/store.js.map +1 -1
  217. package/dist/src/notes/types.d.ts +29 -58
  218. package/dist/src/providers/auth-runtime/auth-profile-store.js +1 -1
  219. package/dist/src/providers/index.js +2 -2
  220. package/dist/src/providers/model-registry.js +1 -1
  221. package/dist/src/session/init-session-turn.js +2 -2
  222. package/dist/src/session/resolve-session.js +3 -3
  223. package/dist/src/session/session-title.js +2 -2
  224. package/dist/src/session/store.js +2 -2
  225. package/dist/src/share/share-auto.js +2 -2
  226. package/dist/src/share/share-store.js +3 -3
  227. package/dist/src/share/share-thumbnail.js +2 -2
  228. package/dist/src/share/share-zip.js +1 -1
  229. package/dist/src/share/site-share-store.js +3 -3
  230. package/dist/src/share/site-static-serve.js +1 -1
  231. package/dist/src/storage/sqlite/connection.js +2 -2
  232. package/dist/src/storage/sqlite/memory-index-repository.js +2 -2
  233. package/dist/src/storage/sqlite/migrations/003_add_note_markdown_meta.sql +4 -0
  234. package/dist/src/storage/sqlite/migrations/discover.js +1 -1
  235. package/dist/src/storage/sqlite/migrations/runner.d.ts +2 -2
  236. package/dist/src/storage/sqlite/migrations/runner.js +5 -5
  237. package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
  238. package/dist/src/storage/sqlite/migrations/runner.ts +2 -2
  239. package/dist/src/storage/sqlite/notes-repository.js +18 -6
  240. package/dist/src/storage/sqlite/notes-repository.js.map +1 -1
  241. package/dist/src/storage/sqlite/schema.js +4 -4
  242. package/dist/src/storage/sqlite/schema.sql +5 -1
  243. package/dist/src/tui/clipboard-image.js +3 -3
  244. package/dist/src/tui/theme-manager.js +1 -1
  245. package/dist/src/tui/tui-keybindings-file.js +1 -1
  246. package/dist/src/tui/tui-scoped-models.js +2 -2
  247. package/dist/src/tui/tui-settings.js +1 -1
  248. package/dist/src/tui/tui.js +3 -3
  249. package/dist/src/tunnel/frpc-binary.js +3 -3
  250. package/dist/src/tunnel/frpc-config.js +1 -1
  251. package/dist/src/tunnel/frpc-extract.js +1 -1
  252. package/dist/src/tunnel/tunnel-state.js +1 -1
  253. package/dist/src/utils/logger/audit.js +1 -1
  254. package/dist/src/utils/logger/log-store.js +1 -1
  255. package/dist/src/utils/logger/rotation.js +1 -1
  256. package/dist/src/voice/tts/audio.js +1 -1
  257. package/dist/src/voice/tts/providers/edge-speech.js +2 -2
  258. package/dist/src/workflows/store/event-store.js +1 -1
  259. package/dist/src/workflows/store/run-store.js +1 -1
  260. package/package.json +3 -3
@@ -1,6 +1,6 @@
1
- import { resolveStateDir } from "../../config/paths-state.js";
2
1
  import { createLogger } from "../../utils/logger/index.js";
3
2
  import { init_logger } from "../../utils/logger.js";
3
+ import { resolveStateDir } from "../../config/paths-state.js";
4
4
  import { init_paths, resolveExtensionsDir } from "../../config/paths.js";
5
5
  import { createSkillConfigManager } from "../../agent/skills/config.js";
6
6
  import { removeSkillsLockEntry } from "../../agent/skills/hub-lock.js";
@@ -11,8 +11,8 @@ import { installExtensionFromStoreZip, peekExtensionIdFromStoreZip } from "../..
11
11
  import { downloadExtensionStoreZipBuffer, fetchMarketplacePackageDetail, resolveExtensionZipDownloadUrl, resolveExtensionsStoreBaseUrl } from "../../agent/skills/marketplace/adapters/store/store-api-client.js";
12
12
  import { getMarketplaceProviderDisplayName, resolveSkillsMarketplaceProvider } from "../../agent/skills/marketplace/resolve-adapter.js";
13
13
  import { downloadFromMarketplace, getMarketplacePackageDetail, listMarketplaceCategories, listMarketplacePackages } from "../../agent/skills/skills-marketplace.js";
14
- import { join } from "node:path";
15
14
  import { existsSync, mkdirSync, rmSync } from "node:fs";
15
+ import { join } from "node:path";
16
16
  //#region src/gateway/service/marketplace-service.ts
17
17
  /**
18
18
  * GatewayMarketplaceService — install / browse / remove for the two marketplaces
@@ -1,12 +1,12 @@
1
1
  import { __toCommonJS } from "../../_virtual/_rolldown/runtime.js";
2
2
  import { PACKAGE_VERSION, init_package_version } from "../package-version.js";
3
- import { getDefaultAgentId, init_resolve_route } from "../routing/resolve-route.js";
4
3
  import { getLogDir } from "../utils/logger/config.js";
5
4
  import { getRuntimeLogStats } from "../utils/logger/stats.js";
6
5
  import { createLogger } from "../utils/logger/index.js";
7
6
  import { init_logger } from "../utils/logger.js";
8
7
  import { init_paths, resolveAgentDir, resolveConfigPath, resolveCronJobsPath, resolveExtensionsDir } from "../config/paths.js";
9
8
  import { loadConfig, saveConfig } from "../config/loader.js";
9
+ import { getDefaultAgentId, init_resolve_route } from "../routing/resolve-route.js";
10
10
  import { prewarmModelRegistry } from "../providers/model-registry.js";
11
11
  import { init_providers, providers_exports } from "../providers/index.js";
12
12
  import { closeXopcDatabase, openXopcDatabase } from "../storage/sqlite/connection.js";
@@ -1,7 +1,7 @@
1
1
  import { createLogger } from "../utils/logger/index.js";
2
2
  import { init_logger } from "../utils/logger.js";
3
- import { join, relative } from "node:path";
4
3
  import { readdir } from "node:fs/promises";
4
+ import { join, relative } from "node:path";
5
5
  //#region src/gateway/workspace-fs-file-list.ts
6
6
  init_logger();
7
7
  const log = createLogger("WorkspaceFsFileList");
@@ -1,5 +1,5 @@
1
- import os from "node:os";
2
1
  import path from "node:path";
2
+ import os from "node:os";
3
3
  //#region src/infra/brew.ts
4
4
  function normalizePathValue(value) {
5
5
  if (typeof value !== "string") return void 0;
@@ -0,0 +1,4 @@
1
+ type ProxyEnv = Record<string, string | undefined>;
2
+ export declare function hasProxyEnv(env?: ProxyEnv): boolean;
3
+ export declare function installGlobalProxyDispatcherFromEnv(env?: ProxyEnv): boolean;
4
+ export {};
@@ -0,0 +1,23 @@
1
+ import { EnvHttpProxyAgent, setGlobalDispatcher } from "undici";
2
+ //#region src/infra/http-proxy-env.ts
3
+ const PROXY_ENV_KEYS = [
4
+ "http_proxy",
5
+ "HTTP_PROXY",
6
+ "https_proxy",
7
+ "HTTPS_PROXY",
8
+ "no_proxy",
9
+ "NO_PROXY"
10
+ ];
11
+ function hasProxyEnv(env = process.env) {
12
+ return PROXY_ENV_KEYS.some((key) => typeof env[key] === "string" && env[key].trim().length > 0);
13
+ }
14
+ function installGlobalProxyDispatcherFromEnv(env = process.env) {
15
+ if (!hasProxyEnv(env)) return false;
16
+ setGlobalDispatcher(new EnvHttpProxyAgent());
17
+ return true;
18
+ }
19
+ installGlobalProxyDispatcherFromEnv();
20
+ //#endregion
21
+ export { hasProxyEnv, installGlobalProxyDispatcherFromEnv };
22
+
23
+ //# sourceMappingURL=http-proxy-env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-proxy-env.js","names":[],"sources":["../../../src/infra/http-proxy-env.ts"],"sourcesContent":["import { EnvHttpProxyAgent, setGlobalDispatcher } from 'undici';\n\nconst PROXY_ENV_KEYS = [\n 'http_proxy',\n 'HTTP_PROXY',\n 'https_proxy',\n 'HTTPS_PROXY',\n 'no_proxy',\n 'NO_PROXY',\n] as const;\n\ntype ProxyEnv = Record<string, string | undefined>;\n\nexport function hasProxyEnv(env: ProxyEnv = process.env): boolean {\n return PROXY_ENV_KEYS.some((key) => typeof env[key] === 'string' && env[key]!.trim().length > 0);\n}\n\nexport function installGlobalProxyDispatcherFromEnv(env: ProxyEnv = process.env): boolean {\n if (!hasProxyEnv(env)) {\n return false;\n }\n\n setGlobalDispatcher(new EnvHttpProxyAgent());\n return true;\n}\n\ninstallGlobalProxyDispatcherFromEnv();\n"],"mappings":";;AAEA,MAAM,iBAAiB;CACrB;CACA;CACA;CACA;CACA;CACA;CACD;AAID,SAAgB,YAAY,MAAgB,QAAQ,KAAc;AAChE,QAAO,eAAe,MAAM,QAAQ,OAAO,IAAI,SAAS,YAAY,IAAI,KAAM,MAAM,CAAC,SAAS,EAAE;;AAGlG,SAAgB,oCAAoC,MAAgB,QAAQ,KAAc;AACxF,KAAI,CAAC,YAAY,IAAI,CACnB,QAAO;AAGT,qBAAoB,IAAI,mBAAmB,CAAC;AAC5C,QAAO;;AAGT,qCAAqC"}
@@ -1,5 +1,5 @@
1
- import path from "node:path";
2
1
  import fs from "node:fs/promises";
2
+ import path from "node:path";
3
3
  //#region src/infra/package-json.ts
4
4
  async function readPackageVersion(root) {
5
5
  try {
@@ -1,7 +1,7 @@
1
1
  import { readPackageVersion } from "./package-json.js";
2
2
  import { XOPC_PACKAGE_NAME, collectInstalledGlobalPackageErrors, globalInstallArgs, globalInstallFallbackArgs, resolveExpectedInstalledVersionFromSpec, resolveGlobalInstallTarget, resolveNpmGlobalPrefixLayoutFromGlobalRoot, resolveNpmGlobalPrefixLayoutFromPrefix } from "./update-global.js";
3
- import path from "node:path";
4
3
  import fs from "node:fs/promises";
4
+ import path from "node:path";
5
5
  //#region src/infra/package-update-steps.ts
6
6
  function formatError(err) {
7
7
  return err instanceof Error ? err.message : String(err);
@@ -1,7 +1,7 @@
1
1
  import { resolveBrewPathDirs } from "./brew.js";
2
- import os from "node:os";
3
- import path from "node:path";
4
2
  import fs from "node:fs";
3
+ import path from "node:path";
4
+ import os from "node:os";
5
5
  //#region src/infra/path-env.ts
6
6
  function isTruthyEnvValue(value) {
7
7
  if (!value) return false;
@@ -1,8 +1,8 @@
1
- import { init_paths_state, resolveStateDir } from "../config/paths-state.js";
2
1
  import { createLogger } from "../utils/logger/index.js";
3
2
  import { init_logger } from "../utils/logger.js";
4
- import path from "node:path";
3
+ import { init_paths_state, resolveStateDir } from "../config/paths-state.js";
5
4
  import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
5
+ import path from "node:path";
6
6
  //#region src/infra/restart.ts
7
7
  /**
8
8
  * Gateway restart coordination — OpenClaw-aligned SIGUSR1 authorization and restart intent.
@@ -1,5 +1,5 @@
1
- import path from "node:path";
2
1
  import fs from "node:fs/promises";
2
+ import path from "node:path";
3
3
  //#region src/infra/stable-node-path.ts
4
4
  /** Resolve Homebrew Cellar node paths to stable opt/bin symlinks. */
5
5
  async function resolveStableNodePath(nodePath) {
@@ -1,7 +1,7 @@
1
1
  import { PACKAGE_VERSION, init_package_version } from "../package-version.js";
2
2
  import { channelToNpmTag } from "./update-channels.js";
3
- import { dirname, join } from "node:path";
4
3
  import { access, readFile } from "node:fs/promises";
4
+ import { dirname, join } from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
6
  //#region src/infra/update-check.ts
7
7
  init_package_version();
@@ -2,9 +2,9 @@ import { resolveExecPathBinPrepend } from "./path-env.js";
2
2
  import { readPackageVersion } from "./package-json.js";
3
3
  import { applyPathPrepend } from "./path-prepend.js";
4
4
  import { createDefaultCommandRunner } from "./run-command.js";
5
- import path from "node:path";
6
5
  import fs from "node:fs";
7
6
  import fs$1 from "node:fs/promises";
7
+ import path from "node:path";
8
8
  //#region src/infra/update-global.ts
9
9
  const XOPC_PACKAGE_NAME = "@xopcai/xopc";
10
10
  const GLOBAL_RENAME_PREFIX = ".";
@@ -1,9 +1,9 @@
1
- import { init_paths_state, resolveUpdateLockPath } from "../config/paths-state.js";
1
+ import { init_write_file_atomic, writeTextAtomic } from "./write-file-atomic.js";
2
2
  import { createLogger } from "../utils/logger/index.js";
3
3
  import { init_logger } from "../utils/logger.js";
4
- import { init_write_file_atomic, writeTextAtomic } from "./write-file-atomic.js";
5
- import { dirname } from "node:path";
4
+ import { init_paths_state, resolveUpdateLockPath } from "../config/paths-state.js";
6
5
  import { mkdir, readFile, unlink } from "node:fs/promises";
6
+ import { dirname } from "node:path";
7
7
  //#region src/infra/update-lock.ts
8
8
  init_write_file_atomic();
9
9
  init_paths_state();
@@ -8,8 +8,8 @@ import { runGlobalPackageUpdateSteps } from "./package-update-steps.js";
8
8
  import { resolveStableNodePath } from "./stable-node-path.js";
9
9
  import { trimLogTail } from "./update-log.js";
10
10
  import { maybeRestartGatewayAfterUpdate } from "./update-restart.js";
11
- import path from "node:path";
12
11
  import fs from "node:fs/promises";
12
+ import path from "node:path";
13
13
  //#region src/infra/update-runner.ts
14
14
  const DEFAULT_TIMEOUT_MS = 2700 * 1e3;
15
15
  const MAX_LOG_CHARS = 8e3;
@@ -1,8 +1,8 @@
1
1
  import { PACKAGE_VERSION, init_package_version } from "../package-version.js";
2
- import { init_paths_state, resolveUpdateCheckStatePath } from "../config/paths-state.js";
2
+ import { init_write_file_atomic, writeTextAtomic } from "./write-file-atomic.js";
3
3
  import { createLogger } from "../utils/logger/index.js";
4
4
  import { init_logger } from "../utils/logger.js";
5
- import { init_write_file_atomic, writeTextAtomic } from "./write-file-atomic.js";
5
+ import { init_paths_state, resolveUpdateCheckStatePath } from "../config/paths-state.js";
6
6
  import { acquireUpdateLock } from "./update-lock.js";
7
7
  import { normalizeUpdateChannel } from "./update-channels.js";
8
8
  import { compareSemver, detectInstallKind, resolveNpmChannelTag, resolvePackageRoot } from "./update-check.js";
@@ -1,8 +1,8 @@
1
1
  import { __esmMin } from "../../_virtual/_rolldown/runtime.js";
2
- import path from "node:path";
3
- import { chmodSync, closeSync, copyFileSync, fsyncSync, mkdirSync, openSync, renameSync, rmSync, writeFileSync } from "node:fs";
4
2
  import { randomUUID } from "node:crypto";
3
+ import { chmodSync, closeSync, copyFileSync, fsyncSync, mkdirSync, openSync, renameSync, rmSync, writeFileSync } from "node:fs";
5
4
  import { chmod, copyFile, mkdir, open, rename, rm } from "node:fs/promises";
5
+ import path from "node:path";
6
6
  //#region src/infra/write-file-atomic.ts
7
7
  /**
8
8
  * Durable single-file writes: temp file → fsync → rename to target.
@@ -1,8 +1,8 @@
1
1
  import { getMediaBucketDir, getMediaDir, isPathInside } from "./paths.js";
2
2
  import { buildMediaUri } from "./uri.js";
3
- import { extname, join, parse } from "node:path";
4
3
  import { randomUUID } from "node:crypto";
5
4
  import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
5
+ import { extname, join, parse } from "node:path";
6
6
  //#region src/media/store.ts
7
7
  /** Default per-file cap for inbound staging (5 MiB). */
8
8
  const MEDIA_MAX_BYTES = 5 * 1024 * 1024;
@@ -1,7 +1,6 @@
1
1
  import type { Note, NoteAttachment } from './types.js';
2
- /** Attachment ids referenced in note markdown, blocks, or plain text. */
3
- export declare function collectReferencedAttachmentIds(note: Pick<Note, 'id' | 'text' | 'blocks'>): Set<string>;
4
- export declare function partitionAttachmentsByReference(note: Pick<Note, 'id' | 'text' | 'blocks' | 'attachments'>): {
2
+ export declare function collectReferencedAttachmentIds(note: Pick<Note, 'id' | 'markdown'>): Set<string>;
3
+ export declare function partitionAttachmentsByReference(note: Pick<Note, 'id' | 'markdown' | 'attachments'>): {
5
4
  kept: NoteAttachment[];
6
5
  removed: NoteAttachment[];
7
6
  };
@@ -1,32 +1,7 @@
1
- import { attachmentIdFromTarget } from "./attachment-ref.js";
2
- import { notePlainText } from "./note-index-meta.js";
1
+ import { parseNoteMarkdown } from "./note-markdown.js";
3
2
  //#region src/notes/note-attachment-sync.ts
4
- const MARKDOWN_IMAGE = /!\[([^\]]*)\]\(([^)]+)\)/g;
5
- const MARKDOWN_LINK = /(?<!!)\[([^\]]*)\]\(([^)]+)\)/g;
6
- const BARE_ATTACHMENT_REF = /xopc-attachment:\/\/notes\/([^/]+)\/([^/?#"'\s)]+)/gi;
7
- /** Attachment ids referenced in note markdown, blocks, or plain text. */
8
3
  function collectReferencedAttachmentIds(note) {
9
- const ids = /* @__PURE__ */ new Set();
10
- for (const block of note.blocks ?? []) if (block.type === "image") ids.add(block.attachmentId);
11
- const source = notePlainText(note);
12
- if (!source.trim()) return ids;
13
- for (const match of source.matchAll(MARKDOWN_IMAGE)) {
14
- const target = match[2];
15
- if (typeof target !== "string") continue;
16
- const attachmentId = attachmentIdFromTarget(target, note.id);
17
- if (attachmentId) ids.add(attachmentId);
18
- }
19
- for (const match of source.matchAll(MARKDOWN_LINK)) {
20
- const target = match[2];
21
- if (typeof target !== "string") continue;
22
- const attachmentId = attachmentIdFromTarget(target, note.id);
23
- if (attachmentId) ids.add(attachmentId);
24
- }
25
- for (const match of source.matchAll(BARE_ATTACHMENT_REF)) {
26
- if (decodeURIComponent(match[1]) !== note.id) continue;
27
- ids.add(decodeURIComponent(match[2]));
28
- }
29
- return ids;
4
+ return new Set(parseNoteMarkdown(note.markdown, note.id).attachments.map((item) => item.attachmentId));
30
5
  }
31
6
  function partitionAttachmentsByReference(note) {
32
7
  const referenced = collectReferencedAttachmentIds(note);
@@ -1 +1 @@
1
- {"version":3,"file":"note-attachment-sync.js","names":[],"sources":["../../../src/notes/note-attachment-sync.ts"],"sourcesContent":["import type { Note, NoteAttachment } from './types.js';\nimport { attachmentIdFromTarget } from './attachment-ref.js';\nimport { notePlainText } from './note-index-meta.js';\n\nconst MARKDOWN_IMAGE = /!\\[([^\\]]*)\\]\\(([^)]+)\\)/g;\nconst MARKDOWN_LINK = /(?<!!)\\[([^\\]]*)\\]\\(([^)]+)\\)/g;\nconst BARE_ATTACHMENT_REF = /xopc-attachment:\\/\\/notes\\/([^/]+)\\/([^/?#\"'\\s)]+)/gi;\n\n/** Attachment ids referenced in note markdown, blocks, or plain text. */\nexport function collectReferencedAttachmentIds(\n note: Pick<Note, 'id' | 'text' | 'blocks'>,\n): Set<string> {\n const ids = new Set<string>();\n\n for (const block of note.blocks ?? []) {\n if (block.type === 'image') ids.add(block.attachmentId);\n }\n\n const source = notePlainText(note);\n if (!source.trim()) return ids;\n\n for (const match of source.matchAll(MARKDOWN_IMAGE)) {\n const target = match[2];\n if (typeof target !== 'string') continue;\n const attachmentId = attachmentIdFromTarget(target, note.id);\n if (attachmentId) ids.add(attachmentId);\n }\n\n for (const match of source.matchAll(MARKDOWN_LINK)) {\n const target = match[2];\n if (typeof target !== 'string') continue;\n const attachmentId = attachmentIdFromTarget(target, note.id);\n if (attachmentId) ids.add(attachmentId);\n }\n\n for (const match of source.matchAll(BARE_ATTACHMENT_REF)) {\n const noteId = decodeURIComponent(match[1]);\n if (noteId !== note.id) continue;\n ids.add(decodeURIComponent(match[2]));\n }\n\n return ids;\n}\n\nexport function partitionAttachmentsByReference(\n note: Pick<Note, 'id' | 'text' | 'blocks' | 'attachments'>,\n): { kept: NoteAttachment[]; removed: NoteAttachment[] } {\n const referenced = collectReferencedAttachmentIds(note);\n const attachments = note.attachments ?? [];\n const kept: NoteAttachment[] = [];\n const removed: NoteAttachment[] = [];\n\n for (const attachment of attachments) {\n if (referenced.has(attachment.id)) {\n kept.push(attachment);\n } else {\n removed.push(attachment);\n }\n }\n\n return { kept, removed };\n}\n"],"mappings":";;;AAIA,MAAM,iBAAiB;AACvB,MAAM,gBAAgB;AACtB,MAAM,sBAAsB;;AAG5B,SAAgB,+BACd,MACa;CACb,MAAM,sBAAM,IAAI,KAAa;AAE7B,MAAK,MAAM,SAAS,KAAK,UAAU,EAAE,CACnC,KAAI,MAAM,SAAS,QAAS,KAAI,IAAI,MAAM,aAAa;CAGzD,MAAM,SAAS,cAAc,KAAK;AAClC,KAAI,CAAC,OAAO,MAAM,CAAE,QAAO;AAE3B,MAAK,MAAM,SAAS,OAAO,SAAS,eAAe,EAAE;EACnD,MAAM,SAAS,MAAM;AACrB,MAAI,OAAO,WAAW,SAAU;EAChC,MAAM,eAAe,uBAAuB,QAAQ,KAAK,GAAG;AAC5D,MAAI,aAAc,KAAI,IAAI,aAAa;;AAGzC,MAAK,MAAM,SAAS,OAAO,SAAS,cAAc,EAAE;EAClD,MAAM,SAAS,MAAM;AACrB,MAAI,OAAO,WAAW,SAAU;EAChC,MAAM,eAAe,uBAAuB,QAAQ,KAAK,GAAG;AAC5D,MAAI,aAAc,KAAI,IAAI,aAAa;;AAGzC,MAAK,MAAM,SAAS,OAAO,SAAS,oBAAoB,EAAE;AAExD,MADe,mBAAmB,MAAM,GAC9B,KAAK,KAAK,GAAI;AACxB,MAAI,IAAI,mBAAmB,MAAM,GAAG,CAAC;;AAGvC,QAAO;;AAGT,SAAgB,gCACd,MACuD;CACvD,MAAM,aAAa,+BAA+B,KAAK;CACvD,MAAM,cAAc,KAAK,eAAe,EAAE;CAC1C,MAAM,OAAyB,EAAE;CACjC,MAAM,UAA4B,EAAE;AAEpC,MAAK,MAAM,cAAc,YACvB,KAAI,WAAW,IAAI,WAAW,GAAG,CAC/B,MAAK,KAAK,WAAW;KAErB,SAAQ,KAAK,WAAW;AAI5B,QAAO;EAAE;EAAM;EAAS"}
1
+ {"version":3,"file":"note-attachment-sync.js","names":[],"sources":["../../../src/notes/note-attachment-sync.ts"],"sourcesContent":["import type { Note, NoteAttachment } from './types.js';\nimport { parseNoteMarkdown } from './note-markdown.js';\n\nexport function collectReferencedAttachmentIds(note: Pick<Note, 'id' | 'markdown'>): Set<string> {\n return new Set(parseNoteMarkdown(note.markdown, note.id).attachments.map((item) => item.attachmentId));\n}\n\nexport function partitionAttachmentsByReference(\n note: Pick<Note, 'id' | 'markdown' | 'attachments'>,\n): { kept: NoteAttachment[]; removed: NoteAttachment[] } {\n const referenced = collectReferencedAttachmentIds(note);\n const attachments = note.attachments ?? [];\n const kept: NoteAttachment[] = [];\n const removed: NoteAttachment[] = [];\n\n for (const attachment of attachments) {\n if (referenced.has(attachment.id)) kept.push(attachment);\n else removed.push(attachment);\n }\n\n return { kept, removed };\n}\n"],"mappings":";;AAGA,SAAgB,+BAA+B,MAAkD;AAC/F,QAAO,IAAI,IAAI,kBAAkB,KAAK,UAAU,KAAK,GAAG,CAAC,YAAY,KAAK,SAAS,KAAK,aAAa,CAAC;;AAGxG,SAAgB,gCACd,MACuD;CACvD,MAAM,aAAa,+BAA+B,KAAK;CACvD,MAAM,cAAc,KAAK,eAAe,EAAE;CAC1C,MAAM,OAAyB,EAAE;CACjC,MAAM,UAA4B,EAAE;AAEpC,MAAK,MAAM,cAAc,YACvB,KAAI,WAAW,IAAI,WAAW,GAAG,CAAE,MAAK,KAAK,WAAW;KACnD,SAAQ,KAAK,WAAW;AAG/B,QAAO;EAAE;EAAM;EAAS"}
@@ -1,14 +1,18 @@
1
1
  import type { Note } from './types.js';
2
2
  export { parseNoteAttachmentTarget, buildNoteAttachmentRef } from './attachment-ref.js';
3
- export declare function notePlainText(note: Pick<Note, 'id' | 'text' | 'blocks'>): string;
3
+ export declare function notePlainText(note: Pick<Note, 'id' | 'markdown'>): string;
4
4
  export declare function stripMediaFromPlainText(text: string): string;
5
5
  export declare function extractAttachmentFileNames(note: Pick<Note, 'attachments'>): string[] | undefined;
6
6
  export declare function extractCoverAttachmentId(note: Note): string | undefined;
7
- export declare function buildNoteSnippet(note: Pick<Note, 'id' | 'text' | 'blocks'>): string | undefined;
7
+ export declare function buildNoteSnippet(note: Pick<Note, 'id' | 'markdown'>): string | undefined;
8
8
  export declare function buildNoteIndexMeta(note: Note): {
9
9
  snippet?: string;
10
10
  coverAttachmentId?: string;
11
11
  voiceAttachmentId?: string;
12
12
  voiceDurationSec?: number;
13
13
  attachmentNames?: string[];
14
+ headingCount?: number;
15
+ taskCount?: number;
16
+ uncheckedTaskCount?: number;
17
+ linkCount?: number;
14
18
  };
@@ -1,17 +1,12 @@
1
1
  import { attachmentIdFromTarget, buildNoteAttachmentRef, parseNoteAttachmentTarget } from "./attachment-ref.js";
2
+ import { parseNoteMarkdown } from "./note-markdown.js";
2
3
  //#region src/notes/note-index-meta.ts
3
4
  const SNIPPET_LENGTH = 100;
4
5
  const MARKDOWN_IMAGE = /!\[([^\]]*)\]\(([^)]+)\)/g;
5
6
  const MARKDOWN_LINK = /(?<!!)\[([^\]]*)\]\(([^)]+)\)/g;
6
7
  const BARE_ATTACHMENT_REF = /xopc-attachment:\/\/notes\/[^/]+\/[^/?#"'\s)]+/gi;
7
8
  function notePlainText(note) {
8
- if (note.text?.trim()) return note.text;
9
- return note.blocks?.map((block) => {
10
- if (block.type === "divider") return "";
11
- if (block.type === "todo") return block.text;
12
- if (block.type === "image") return `![${block.alt ?? ""}](${buildNoteAttachmentRef(note.id, block.attachmentId)})`;
13
- return block.text;
14
- }).join(" ") ?? "";
9
+ return note.markdown ?? "";
15
10
  }
16
11
  function isNoteMediaTarget(target) {
17
12
  return parseNoteAttachmentTarget(target) !== null;
@@ -31,11 +26,6 @@ function extractAttachmentFileNames(note) {
31
26
  return [...new Set(names)];
32
27
  }
33
28
  function extractCoverAttachmentId(note) {
34
- for (const block of note.blocks ?? []) {
35
- if (block.type !== "image") continue;
36
- const attachment = note.attachments?.find((item) => item.id === block.attachmentId);
37
- if (!attachment || attachment.type === "image") return block.attachmentId;
38
- }
39
29
  const text = notePlainText(note);
40
30
  if (!text.trim()) return void 0;
41
31
  for (const match of text.matchAll(MARKDOWN_IMAGE)) {
@@ -54,9 +44,9 @@ function extractCoverAttachmentId(note) {
54
44
  }
55
45
  }
56
46
  function buildNoteSnippet(note) {
57
- const text = notePlainText(note);
58
- if (!text.trim()) return void 0;
59
- const clean = stripMediaFromPlainText(text);
47
+ const parsed = parseNoteMarkdown(note.markdown, note.id);
48
+ if (!parsed.plainText.trim()) return void 0;
49
+ const clean = stripMediaFromPlainText(parsed.plainText);
60
50
  if (!clean) return void 0;
61
51
  return clean.length > SNIPPET_LENGTH ? `${clean.slice(0, SNIPPET_LENGTH)}…` : clean;
62
52
  }
@@ -69,6 +59,7 @@ function extractVoiceAttachment(note) {
69
59
  };
70
60
  }
71
61
  function buildNoteIndexMeta(note) {
62
+ const parsed = parseNoteMarkdown(note.markdown, note.id);
72
63
  const coverAttachmentId = extractCoverAttachmentId(note);
73
64
  const snippet = buildNoteSnippet(note);
74
65
  const attachmentNames = extractAttachmentFileNames(note);
@@ -78,7 +69,11 @@ function buildNoteIndexMeta(note) {
78
69
  coverAttachmentId,
79
70
  voiceAttachmentId,
80
71
  voiceDurationSec,
81
- attachmentNames
72
+ attachmentNames,
73
+ headingCount: parsed.headings.length,
74
+ taskCount: parsed.tasks.length,
75
+ uncheckedTaskCount: parsed.tasks.filter((task) => !task.checked).length,
76
+ linkCount: parsed.wikilinks.length
82
77
  };
83
78
  }
84
79
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"note-index-meta.js","names":[],"sources":["../../../src/notes/note-index-meta.ts"],"sourcesContent":["import type { Note } from './types.js';\nimport {\n attachmentIdFromTarget,\n buildNoteAttachmentRef,\n parseNoteAttachmentTarget,\n} from './attachment-ref.js';\n\nconst SNIPPET_LENGTH = 100;\nconst MARKDOWN_IMAGE = /!\\[([^\\]]*)\\]\\(([^)]+)\\)/g;\nconst MARKDOWN_LINK = /(?<!!)\\[([^\\]]*)\\]\\(([^)]+)\\)/g;\nconst BARE_ATTACHMENT_REF = /xopc-attachment:\\/\\/notes\\/[^/]+\\/[^/?#\"'\\s)]+/gi;\n\nexport { parseNoteAttachmentTarget, buildNoteAttachmentRef } from './attachment-ref.js';\n\nexport function notePlainText(note: Pick<Note, 'id' | 'text' | 'blocks'>): string {\n if (note.text?.trim()) return note.text;\n return (\n note.blocks\n ?.map((block) => {\n if (block.type === 'divider') return '';\n if (block.type === 'todo') return block.text;\n if (block.type === 'image') {\n const alt = block.alt ?? '';\n return `![${alt}](${buildNoteAttachmentRef(note.id, block.attachmentId)})`;\n }\n return block.text;\n })\n .join(' ') ?? ''\n );\n}\n\nfunction isNoteMediaTarget(target: string): boolean {\n return parseNoteAttachmentTarget(target) !== null;\n}\n\nexport function stripMediaFromPlainText(text: string): string {\n let result = text.replace(MARKDOWN_IMAGE, ' ');\n result = result.replace(MARKDOWN_LINK, (full, _alt, target) => {\n if (typeof target !== 'string') return full;\n return isNoteMediaTarget(target) ? ' ' : full;\n });\n result = result.replace(BARE_ATTACHMENT_REF, ' ');\n return result.replace(/\\s+/g, ' ').trim();\n}\n\nexport function extractAttachmentFileNames(note: Pick<Note, 'attachments'>): string[] | undefined {\n const names = note.attachments?.map((item) => item.fileName.trim().toLowerCase()).filter(Boolean);\n if (!names?.length) return undefined;\n return [...new Set(names)];\n}\n\nexport function extractCoverAttachmentId(note: Note): string | undefined {\n for (const block of note.blocks ?? []) {\n if (block.type !== 'image') continue;\n const attachment = note.attachments?.find((item) => item.id === block.attachmentId);\n if (!attachment || attachment.type === 'image') return block.attachmentId;\n }\n\n const text = notePlainText(note);\n if (!text.trim()) return undefined;\n\n for (const match of text.matchAll(MARKDOWN_IMAGE)) {\n const target = match[2];\n if (typeof target !== 'string') continue;\n const attachmentId = attachmentIdFromTarget(target, note.id);\n if (!attachmentId) continue;\n const attachment = note.attachments?.find((item) => item.id === attachmentId);\n if (!attachment || attachment.type === 'image') return attachmentId;\n }\n\n for (const match of text.matchAll(BARE_ATTACHMENT_REF)) {\n const parsed = parseNoteAttachmentTarget(match[0], note.id);\n if (!parsed) continue;\n const attachment = note.attachments?.find((item) => item.id === parsed.attachmentId);\n if (!attachment || attachment.type === 'image') return parsed.attachmentId;\n }\n\n return undefined;\n}\n\nexport function buildNoteSnippet(note: Pick<Note, 'id' | 'text' | 'blocks'>): string | undefined {\n const text = notePlainText(note);\n if (!text.trim()) return undefined;\n const clean = stripMediaFromPlainText(text);\n if (!clean) return undefined;\n return clean.length > SNIPPET_LENGTH ? `${clean.slice(0, SNIPPET_LENGTH)}…` : clean;\n}\n\nfunction extractVoiceAttachment(note: Note): { voiceAttachmentId?: string; voiceDurationSec?: number } {\n const audio = note.attachments?.find((a) => a.type === 'audio');\n if (!audio) return {};\n return { voiceAttachmentId: audio.id, voiceDurationSec: audio.duration };\n}\n\nexport function buildNoteIndexMeta(note: Note): {\n snippet?: string;\n coverAttachmentId?: string;\n voiceAttachmentId?: string;\n voiceDurationSec?: number;\n attachmentNames?: string[];\n} {\n const coverAttachmentId = extractCoverAttachmentId(note);\n const snippet = buildNoteSnippet(note);\n const attachmentNames = extractAttachmentFileNames(note);\n const { voiceAttachmentId, voiceDurationSec } = extractVoiceAttachment(note);\n return {\n snippet,\n coverAttachmentId,\n voiceAttachmentId,\n voiceDurationSec,\n attachmentNames,\n };\n}\n"],"mappings":";;AAOA,MAAM,iBAAiB;AACvB,MAAM,iBAAiB;AACvB,MAAM,gBAAgB;AACtB,MAAM,sBAAsB;AAI5B,SAAgB,cAAc,MAAoD;AAChF,KAAI,KAAK,MAAM,MAAM,CAAE,QAAO,KAAK;AACnC,QACE,KAAK,QACD,KAAK,UAAU;AACf,MAAI,MAAM,SAAS,UAAW,QAAO;AACrC,MAAI,MAAM,SAAS,OAAQ,QAAO,MAAM;AACxC,MAAI,MAAM,SAAS,QAEjB,QAAO,KADK,MAAM,OAAO,GACT,IAAI,uBAAuB,KAAK,IAAI,MAAM,aAAa,CAAC;AAE1E,SAAO,MAAM;GACb,CACD,KAAK,IAAI,IAAI;;AAIpB,SAAS,kBAAkB,QAAyB;AAClD,QAAO,0BAA0B,OAAO,KAAK;;AAG/C,SAAgB,wBAAwB,MAAsB;CAC5D,IAAI,SAAS,KAAK,QAAQ,gBAAgB,IAAI;AAC9C,UAAS,OAAO,QAAQ,gBAAgB,MAAM,MAAM,WAAW;AAC7D,MAAI,OAAO,WAAW,SAAU,QAAO;AACvC,SAAO,kBAAkB,OAAO,GAAG,MAAM;GACzC;AACF,UAAS,OAAO,QAAQ,qBAAqB,IAAI;AACjD,QAAO,OAAO,QAAQ,QAAQ,IAAI,CAAC,MAAM;;AAG3C,SAAgB,2BAA2B,MAAuD;CAChG,MAAM,QAAQ,KAAK,aAAa,KAAK,SAAS,KAAK,SAAS,MAAM,CAAC,aAAa,CAAC,CAAC,OAAO,QAAQ;AACjG,KAAI,CAAC,OAAO,OAAQ,QAAO,KAAA;AAC3B,QAAO,CAAC,GAAG,IAAI,IAAI,MAAM,CAAC;;AAG5B,SAAgB,yBAAyB,MAAgC;AACvE,MAAK,MAAM,SAAS,KAAK,UAAU,EAAE,EAAE;AACrC,MAAI,MAAM,SAAS,QAAS;EAC5B,MAAM,aAAa,KAAK,aAAa,MAAM,SAAS,KAAK,OAAO,MAAM,aAAa;AACnF,MAAI,CAAC,cAAc,WAAW,SAAS,QAAS,QAAO,MAAM;;CAG/D,MAAM,OAAO,cAAc,KAAK;AAChC,KAAI,CAAC,KAAK,MAAM,CAAE,QAAO,KAAA;AAEzB,MAAK,MAAM,SAAS,KAAK,SAAS,eAAe,EAAE;EACjD,MAAM,SAAS,MAAM;AACrB,MAAI,OAAO,WAAW,SAAU;EAChC,MAAM,eAAe,uBAAuB,QAAQ,KAAK,GAAG;AAC5D,MAAI,CAAC,aAAc;EACnB,MAAM,aAAa,KAAK,aAAa,MAAM,SAAS,KAAK,OAAO,aAAa;AAC7E,MAAI,CAAC,cAAc,WAAW,SAAS,QAAS,QAAO;;AAGzD,MAAK,MAAM,SAAS,KAAK,SAAS,oBAAoB,EAAE;EACtD,MAAM,SAAS,0BAA0B,MAAM,IAAI,KAAK,GAAG;AAC3D,MAAI,CAAC,OAAQ;EACb,MAAM,aAAa,KAAK,aAAa,MAAM,SAAS,KAAK,OAAO,OAAO,aAAa;AACpF,MAAI,CAAC,cAAc,WAAW,SAAS,QAAS,QAAO,OAAO;;;AAMlE,SAAgB,iBAAiB,MAAgE;CAC/F,MAAM,OAAO,cAAc,KAAK;AAChC,KAAI,CAAC,KAAK,MAAM,CAAE,QAAO,KAAA;CACzB,MAAM,QAAQ,wBAAwB,KAAK;AAC3C,KAAI,CAAC,MAAO,QAAO,KAAA;AACnB,QAAO,MAAM,SAAS,iBAAiB,GAAG,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK;;AAGhF,SAAS,uBAAuB,MAAuE;CACrG,MAAM,QAAQ,KAAK,aAAa,MAAM,MAAM,EAAE,SAAS,QAAQ;AAC/D,KAAI,CAAC,MAAO,QAAO,EAAE;AACrB,QAAO;EAAE,mBAAmB,MAAM;EAAI,kBAAkB,MAAM;EAAU;;AAG1E,SAAgB,mBAAmB,MAMjC;CACA,MAAM,oBAAoB,yBAAyB,KAAK;CACxD,MAAM,UAAU,iBAAiB,KAAK;CACtC,MAAM,kBAAkB,2BAA2B,KAAK;CACxD,MAAM,EAAE,mBAAmB,qBAAqB,uBAAuB,KAAK;AAC5E,QAAO;EACL;EACA;EACA;EACA;EACA;EACD"}
1
+ {"version":3,"file":"note-index-meta.js","names":[],"sources":["../../../src/notes/note-index-meta.ts"],"sourcesContent":["import type { Note } from './types.js';\nimport { attachmentIdFromTarget, parseNoteAttachmentTarget } from './attachment-ref.js';\nimport { parseNoteMarkdown } from './note-markdown.js';\n\nconst SNIPPET_LENGTH = 100;\nconst MARKDOWN_IMAGE = /!\\[([^\\]]*)\\]\\(([^)]+)\\)/g;\nconst MARKDOWN_LINK = /(?<!!)\\[([^\\]]*)\\]\\(([^)]+)\\)/g;\nconst BARE_ATTACHMENT_REF = /xopc-attachment:\\/\\/notes\\/[^/]+\\/[^/?#\"'\\s)]+/gi;\n\nexport { parseNoteAttachmentTarget, buildNoteAttachmentRef } from './attachment-ref.js';\n\nexport function notePlainText(note: Pick<Note, 'id' | 'markdown'>): string {\n return note.markdown ?? '';\n}\n\nfunction isNoteMediaTarget(target: string): boolean {\n return parseNoteAttachmentTarget(target) !== null;\n}\n\nexport function stripMediaFromPlainText(text: string): string {\n let result = text.replace(MARKDOWN_IMAGE, ' ');\n result = result.replace(MARKDOWN_LINK, (full, _alt, target) => {\n if (typeof target !== 'string') return full;\n return isNoteMediaTarget(target) ? ' ' : full;\n });\n result = result.replace(BARE_ATTACHMENT_REF, ' ');\n return result.replace(/\\s+/g, ' ').trim();\n}\n\nexport function extractAttachmentFileNames(note: Pick<Note, 'attachments'>): string[] | undefined {\n const names = note.attachments?.map((item) => item.fileName.trim().toLowerCase()).filter(Boolean);\n if (!names?.length) return undefined;\n return [...new Set(names)];\n}\n\nexport function extractCoverAttachmentId(note: Note): string | undefined {\n const text = notePlainText(note);\n if (!text.trim()) return undefined;\n\n for (const match of text.matchAll(MARKDOWN_IMAGE)) {\n const target = match[2];\n if (typeof target !== 'string') continue;\n const attachmentId = attachmentIdFromTarget(target, note.id);\n if (!attachmentId) continue;\n const attachment = note.attachments?.find((item) => item.id === attachmentId);\n if (!attachment || attachment.type === 'image') return attachmentId;\n }\n\n for (const match of text.matchAll(BARE_ATTACHMENT_REF)) {\n const parsed = parseNoteAttachmentTarget(match[0], note.id);\n if (!parsed) continue;\n const attachment = note.attachments?.find((item) => item.id === parsed.attachmentId);\n if (!attachment || attachment.type === 'image') return parsed.attachmentId;\n }\n\n return undefined;\n}\n\nexport function buildNoteSnippet(note: Pick<Note, 'id' | 'markdown'>): string | undefined {\n const parsed = parseNoteMarkdown(note.markdown, note.id);\n if (!parsed.plainText.trim()) return undefined;\n const clean = stripMediaFromPlainText(parsed.plainText);\n if (!clean) return undefined;\n return clean.length > SNIPPET_LENGTH ? `${clean.slice(0, SNIPPET_LENGTH)}…` : clean;\n}\n\nfunction extractVoiceAttachment(note: Note): { voiceAttachmentId?: string; voiceDurationSec?: number } {\n const audio = note.attachments?.find((a) => a.type === 'audio');\n if (!audio) return {};\n return { voiceAttachmentId: audio.id, voiceDurationSec: audio.duration };\n}\n\nexport function buildNoteIndexMeta(note: Note): {\n snippet?: string;\n coverAttachmentId?: string;\n voiceAttachmentId?: string;\n voiceDurationSec?: number;\n attachmentNames?: string[];\n headingCount?: number;\n taskCount?: number;\n uncheckedTaskCount?: number;\n linkCount?: number;\n} {\n const parsed = parseNoteMarkdown(note.markdown, note.id);\n const coverAttachmentId = extractCoverAttachmentId(note);\n const snippet = buildNoteSnippet(note);\n const attachmentNames = extractAttachmentFileNames(note);\n const { voiceAttachmentId, voiceDurationSec } = extractVoiceAttachment(note);\n return {\n snippet,\n coverAttachmentId,\n voiceAttachmentId,\n voiceDurationSec,\n attachmentNames,\n headingCount: parsed.headings.length,\n taskCount: parsed.tasks.length,\n uncheckedTaskCount: parsed.tasks.filter((task) => !task.checked).length,\n linkCount: parsed.wikilinks.length,\n };\n}\n"],"mappings":";;;AAIA,MAAM,iBAAiB;AACvB,MAAM,iBAAiB;AACvB,MAAM,gBAAgB;AACtB,MAAM,sBAAsB;AAI5B,SAAgB,cAAc,MAA6C;AACzE,QAAO,KAAK,YAAY;;AAG1B,SAAS,kBAAkB,QAAyB;AAClD,QAAO,0BAA0B,OAAO,KAAK;;AAG/C,SAAgB,wBAAwB,MAAsB;CAC5D,IAAI,SAAS,KAAK,QAAQ,gBAAgB,IAAI;AAC9C,UAAS,OAAO,QAAQ,gBAAgB,MAAM,MAAM,WAAW;AAC7D,MAAI,OAAO,WAAW,SAAU,QAAO;AACvC,SAAO,kBAAkB,OAAO,GAAG,MAAM;GACzC;AACF,UAAS,OAAO,QAAQ,qBAAqB,IAAI;AACjD,QAAO,OAAO,QAAQ,QAAQ,IAAI,CAAC,MAAM;;AAG3C,SAAgB,2BAA2B,MAAuD;CAChG,MAAM,QAAQ,KAAK,aAAa,KAAK,SAAS,KAAK,SAAS,MAAM,CAAC,aAAa,CAAC,CAAC,OAAO,QAAQ;AACjG,KAAI,CAAC,OAAO,OAAQ,QAAO,KAAA;AAC3B,QAAO,CAAC,GAAG,IAAI,IAAI,MAAM,CAAC;;AAG5B,SAAgB,yBAAyB,MAAgC;CACvE,MAAM,OAAO,cAAc,KAAK;AAChC,KAAI,CAAC,KAAK,MAAM,CAAE,QAAO,KAAA;AAEzB,MAAK,MAAM,SAAS,KAAK,SAAS,eAAe,EAAE;EACjD,MAAM,SAAS,MAAM;AACrB,MAAI,OAAO,WAAW,SAAU;EAChC,MAAM,eAAe,uBAAuB,QAAQ,KAAK,GAAG;AAC5D,MAAI,CAAC,aAAc;EACnB,MAAM,aAAa,KAAK,aAAa,MAAM,SAAS,KAAK,OAAO,aAAa;AAC7E,MAAI,CAAC,cAAc,WAAW,SAAS,QAAS,QAAO;;AAGzD,MAAK,MAAM,SAAS,KAAK,SAAS,oBAAoB,EAAE;EACtD,MAAM,SAAS,0BAA0B,MAAM,IAAI,KAAK,GAAG;AAC3D,MAAI,CAAC,OAAQ;EACb,MAAM,aAAa,KAAK,aAAa,MAAM,SAAS,KAAK,OAAO,OAAO,aAAa;AACpF,MAAI,CAAC,cAAc,WAAW,SAAS,QAAS,QAAO,OAAO;;;AAMlE,SAAgB,iBAAiB,MAAyD;CACxF,MAAM,SAAS,kBAAkB,KAAK,UAAU,KAAK,GAAG;AACxD,KAAI,CAAC,OAAO,UAAU,MAAM,CAAE,QAAO,KAAA;CACrC,MAAM,QAAQ,wBAAwB,OAAO,UAAU;AACvD,KAAI,CAAC,MAAO,QAAO,KAAA;AACnB,QAAO,MAAM,SAAS,iBAAiB,GAAG,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK;;AAGhF,SAAS,uBAAuB,MAAuE;CACrG,MAAM,QAAQ,KAAK,aAAa,MAAM,MAAM,EAAE,SAAS,QAAQ;AAC/D,KAAI,CAAC,MAAO,QAAO,EAAE;AACrB,QAAO;EAAE,mBAAmB,MAAM;EAAI,kBAAkB,MAAM;EAAU;;AAG1E,SAAgB,mBAAmB,MAUjC;CACA,MAAM,SAAS,kBAAkB,KAAK,UAAU,KAAK,GAAG;CACxD,MAAM,oBAAoB,yBAAyB,KAAK;CACxD,MAAM,UAAU,iBAAiB,KAAK;CACtC,MAAM,kBAAkB,2BAA2B,KAAK;CACxD,MAAM,EAAE,mBAAmB,qBAAqB,uBAAuB,KAAK;AAC5E,QAAO;EACL;EACA;EACA;EACA;EACA;EACA,cAAc,OAAO,SAAS;EAC9B,WAAW,OAAO,MAAM;EACxB,oBAAoB,OAAO,MAAM,QAAQ,SAAS,CAAC,KAAK,QAAQ,CAAC;EACjE,WAAW,OAAO,UAAU;EAC7B"}
@@ -0,0 +1,61 @@
1
+ export interface NoteHeading {
2
+ id: string;
3
+ depth: 1 | 2 | 3 | 4 | 5 | 6;
4
+ title: string;
5
+ start: number;
6
+ end: number;
7
+ path: string[];
8
+ }
9
+ export interface NoteSection {
10
+ id: string;
11
+ heading?: NoteHeading;
12
+ start: number;
13
+ end: number;
14
+ markdown: string;
15
+ plainText: string;
16
+ }
17
+ export interface NoteTaskItem {
18
+ id: string;
19
+ text: string;
20
+ checked: boolean;
21
+ start: number;
22
+ end: number;
23
+ line: number;
24
+ }
25
+ export interface NoteWikiLink {
26
+ raw: string;
27
+ target: string;
28
+ alias?: string;
29
+ heading?: string;
30
+ start: number;
31
+ end: number;
32
+ }
33
+ export interface NoteAttachmentRef {
34
+ attachmentId: string;
35
+ start: number;
36
+ end: number;
37
+ }
38
+ export interface NoteCallout {
39
+ type: string;
40
+ title?: string;
41
+ start: number;
42
+ end: number;
43
+ }
44
+ export interface ParsedNoteMarkdown {
45
+ plainText: string;
46
+ headings: NoteHeading[];
47
+ sections: NoteSection[];
48
+ tasks: NoteTaskItem[];
49
+ tags: string[];
50
+ wikilinks: NoteWikiLink[];
51
+ attachments: NoteAttachmentRef[];
52
+ callouts: NoteCallout[];
53
+ codeBlocks: Array<{
54
+ lang?: string;
55
+ start: number;
56
+ end: number;
57
+ code: string;
58
+ }>;
59
+ }
60
+ export declare function parseNoteMarkdown(markdown?: string, noteId?: string): ParsedNoteMarkdown;
61
+ export declare function applyNotePatch(markdown: string, operations: import('./types.js').NotePatchOperation[], parsed?: ParsedNoteMarkdown): string;
@@ -0,0 +1,177 @@
1
+ import { attachmentIdFromTarget } from "./attachment-ref.js";
2
+ //#region src/notes/note-markdown.ts
3
+ const WIKILINK = /!??\[\[([^\]]+)\]\]/g;
4
+ const TAG = /(^|\s)#([\p{L}\p{N}_/-]+)/gu;
5
+ const MARKDOWN_IMAGE = /!\[([^\]]*)\]\(([^)]+)\)/g;
6
+ const MARKDOWN_LINK = /(?<!!)\[([^\]]*)\]\(([^)]+)\)/g;
7
+ const BARE_ATTACHMENT_REF = /xopc-attachment:\/\/notes\/([^/]+)\/([^/?#"'\s)]+)/gi;
8
+ function stripMarkdown(markdown) {
9
+ return markdown.replace(/^---[\s\S]*?\n---\s*/m, "").replace(/```[\s\S]*?```/g, " ").replace(MARKDOWN_IMAGE, " ").replace(MARKDOWN_LINK, "$1").replace(WIKILINK, "$1").replace(/^\s{0,3}>\s?/gm, "").replace(/^\s{0,3}#{1,6}\s+/gm, "").replace(/^\s*[-*+]\s+\[[ xX]\]\s+/gm, "").replace(/^\s*[-*+]\s+/gm, "").replace(/^\s*\d+\.\s+/gm, "").replace(/[*_`~]/g, "").replace(/\s+/g, " ").trim();
10
+ }
11
+ function lineOffsets(markdown) {
12
+ const lines = [];
13
+ let start = 0;
14
+ for (const part of markdown.split(/\n/)) {
15
+ const end = start + part.length;
16
+ lines.push({
17
+ line: part,
18
+ start,
19
+ end
20
+ });
21
+ start = end + 1;
22
+ }
23
+ return lines;
24
+ }
25
+ function parseNoteMarkdown(markdown = "", noteId) {
26
+ const headings = [];
27
+ const tasks = [];
28
+ const callouts = [];
29
+ const codeBlocks = [];
30
+ const stack = [];
31
+ let inCode = null;
32
+ lineOffsets(markdown).forEach(({ line, start, end }, index) => {
33
+ const fence = /^```\s*([^`]*)$/.exec(line.trim());
34
+ if (fence) {
35
+ if (inCode) {
36
+ codeBlocks.push({
37
+ start: inCode.start,
38
+ end,
39
+ lang: inCode.lang,
40
+ code: inCode.lines.join("\n")
41
+ });
42
+ inCode = null;
43
+ } else inCode = {
44
+ start,
45
+ lang: fence[1]?.trim() || void 0,
46
+ lines: []
47
+ };
48
+ return;
49
+ }
50
+ if (inCode) {
51
+ inCode.lines.push(line);
52
+ return;
53
+ }
54
+ const heading = /^(#{1,6})\s+(.+?)\s*$/.exec(line);
55
+ if (heading) {
56
+ const depth = heading[1].length;
57
+ stack.length = depth - 1;
58
+ stack[depth - 1] = heading[2].trim();
59
+ headings.push({
60
+ id: `heading-${headings.length + 1}`,
61
+ depth,
62
+ title: heading[2].trim(),
63
+ start,
64
+ end,
65
+ path: stack.slice(0, depth)
66
+ });
67
+ }
68
+ const task = /^\s*[-*+]\s+\[([ xX])\]\s+(.+)$/.exec(line);
69
+ if (task) tasks.push({
70
+ id: `task-${tasks.length + 1}`,
71
+ text: task[2].trim(),
72
+ checked: task[1].toLowerCase() === "x",
73
+ start,
74
+ end,
75
+ line: index + 1
76
+ });
77
+ const callout = /^\s*>\s*\[!([A-Za-z0-9_-]+)\]\s*(.*)$/.exec(line);
78
+ if (callout) callouts.push({
79
+ type: callout[1].toLowerCase(),
80
+ title: callout[2]?.trim() || void 0,
81
+ start,
82
+ end
83
+ });
84
+ });
85
+ if (inCode) codeBlocks.push({
86
+ start: inCode.start,
87
+ end: markdown.length,
88
+ lang: inCode.lang,
89
+ code: inCode.lines.join("\n")
90
+ });
91
+ const sections = [];
92
+ if (headings.length === 0) sections.push({
93
+ id: "section-1",
94
+ start: 0,
95
+ end: markdown.length,
96
+ markdown,
97
+ plainText: stripMarkdown(markdown)
98
+ });
99
+ else for (let i = 0; i < headings.length; i += 1) {
100
+ const heading = headings[i];
101
+ const end = headings.slice(i + 1).find((item) => item.depth <= heading.depth)?.start ?? markdown.length;
102
+ const slice = markdown.slice(heading.start, end).trimEnd();
103
+ sections.push({
104
+ id: `section-${i + 1}`,
105
+ heading,
106
+ start: heading.start,
107
+ end,
108
+ markdown: slice,
109
+ plainText: stripMarkdown(slice)
110
+ });
111
+ }
112
+ const wikilinks = [];
113
+ for (const match of markdown.matchAll(WIKILINK)) {
114
+ const [targetPart, alias] = match[1].split("|");
115
+ const [target, heading] = targetPart.split("#");
116
+ wikilinks.push({
117
+ raw: match[0],
118
+ target: target.trim(),
119
+ heading: heading?.trim() || void 0,
120
+ alias: alias?.trim() || void 0,
121
+ start: match.index ?? 0,
122
+ end: (match.index ?? 0) + match[0].length
123
+ });
124
+ }
125
+ const tags = /* @__PURE__ */ new Set();
126
+ for (const match of markdown.matchAll(TAG)) tags.add(match[2]);
127
+ const attachments = /* @__PURE__ */ new Map();
128
+ const addAttachment = (target, start, end) => {
129
+ const attachmentId = attachmentIdFromTarget(target, noteId ?? "");
130
+ if (attachmentId) attachments.set(`${attachmentId}:${start}`, {
131
+ attachmentId,
132
+ start,
133
+ end
134
+ });
135
+ };
136
+ for (const match of markdown.matchAll(MARKDOWN_IMAGE)) addAttachment(match[2], match.index ?? 0, (match.index ?? 0) + match[0].length);
137
+ for (const match of markdown.matchAll(MARKDOWN_LINK)) addAttachment(match[2], match.index ?? 0, (match.index ?? 0) + match[0].length);
138
+ for (const match of markdown.matchAll(BARE_ATTACHMENT_REF)) {
139
+ const start = match.index ?? 0;
140
+ const matchedNoteId = decodeURIComponent(match[1]);
141
+ if (!noteId || matchedNoteId === noteId) attachments.set(`${decodeURIComponent(match[2])}:${start}`, {
142
+ attachmentId: decodeURIComponent(match[2]),
143
+ start,
144
+ end: start + match[0].length
145
+ });
146
+ }
147
+ return {
148
+ plainText: stripMarkdown(markdown),
149
+ headings,
150
+ sections,
151
+ tasks,
152
+ tags: [...tags],
153
+ wikilinks,
154
+ attachments: [...attachments.values()],
155
+ callouts,
156
+ codeBlocks
157
+ };
158
+ }
159
+ function applyNotePatch(markdown, operations, parsed = parseNoteMarkdown(markdown)) {
160
+ let next = markdown;
161
+ const rangeOps = operations.filter((op) => op.type === "replaceRange" || op.type === "insertAt");
162
+ for (const op of [...rangeOps].sort((a, b) => (b.type === "insertAt" ? b.offset : b.from) - (a.type === "insertAt" ? a.offset : a.from))) if (op.type === "insertAt") next = `${next.slice(0, op.offset)}${op.markdown}${next.slice(op.offset)}`;
163
+ else next = `${next.slice(0, op.from)}${op.markdown}${next.slice(op.to)}`;
164
+ for (const op of operations) {
165
+ if (op.type === "appendSection") next = `${next.trimEnd()}\n\n## ${op.heading}\n\n${op.markdown.trim()}\n`;
166
+ if (op.type === "prependSection") next = `## ${op.heading}\n\n${op.markdown.trim()}\n\n${next.trimStart()}`;
167
+ if (op.type === "replaceSection") {
168
+ const section = parsed.sections.find((item) => item.id === op.sectionId);
169
+ if (section) next = `${next.slice(0, section.start)}${op.markdown}${next.slice(section.end)}`;
170
+ }
171
+ }
172
+ return next;
173
+ }
174
+ //#endregion
175
+ export { applyNotePatch, parseNoteMarkdown };
176
+
177
+ //# sourceMappingURL=note-markdown.js.map