mirror-mind 0.0.1 → 0.32.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (467) hide show
  1. package/.claude/hooks/log-session-end.sh +85 -0
  2. package/.claude/hooks/log-user-prompt.sh +85 -0
  3. package/.claude/hooks/mirror-inject.sh +85 -0
  4. package/.claude/hooks/session-start.sh +85 -0
  5. package/.gemini/hooks/log-assistant.sh +85 -0
  6. package/.gemini/hooks/log-user.sh +85 -0
  7. package/.gemini/hooks/session-end.sh +85 -0
  8. package/.gemini/hooks/session-start.sh +85 -0
  9. package/.pi/extensions/mirror-logger.ts +561 -0
  10. package/.pi/skills/mm-backup/SKILL.md +21 -0
  11. package/.pi/skills/mm-build/SKILL.md +1206 -0
  12. package/.pi/skills/mm-consolidate/SKILL.md +112 -0
  13. package/.pi/skills/mm-consult/SKILL.md +70 -0
  14. package/.pi/skills/mm-conversations/SKILL.md +16 -0
  15. package/.pi/skills/mm-discard/SKILL.md +39 -0
  16. package/.pi/skills/mm-explore/SKILL.md +255 -0
  17. package/.pi/skills/mm-help/SKILL.md +74 -0
  18. package/.pi/skills/mm-identity/SKILL.md +96 -0
  19. package/.pi/skills/mm-journal/SKILL.md +16 -0
  20. package/.pi/skills/mm-journey/SKILL.md +23 -0
  21. package/.pi/skills/mm-journeys/SKILL.md +15 -0
  22. package/.pi/skills/mm-memories/SKILL.md +17 -0
  23. package/.pi/skills/mm-mirror/SKILL.md +98 -0
  24. package/.pi/skills/mm-mute/SKILL.md +18 -0
  25. package/.pi/skills/mm-new/SKILL.md +18 -0
  26. package/.pi/skills/mm-recall/SKILL.md +17 -0
  27. package/.pi/skills/mm-release-notes/SKILL.md +52 -0
  28. package/.pi/skills/mm-seed/SKILL.md +19 -0
  29. package/.pi/skills/mm-shadow/SKILL.md +117 -0
  30. package/.pi/skills/mm-soul/SKILL.md +502 -0
  31. package/.pi/skills/mm-tasks/SKILL.md +24 -0
  32. package/.pi/skills/mm-update/SKILL.md +32 -0
  33. package/.pi/skills/mm-week/SKILL.md +28 -0
  34. package/.pi/skills/mm-welcome/SKILL.md +24 -0
  35. package/AGENTS.md +188 -0
  36. package/README.md +126 -9
  37. package/bin/loader.js +67 -0
  38. package/bin/mirror-hook.js +7 -0
  39. package/bin/mirror.js +7 -0
  40. package/docs/releases/index.md +99 -0
  41. package/docs/releases/pending-cutoffs.md +510 -0
  42. package/docs/releases/v0.10.0.md +123 -0
  43. package/docs/releases/v0.10.1.md +66 -0
  44. package/docs/releases/v0.10.10.md +51 -0
  45. package/docs/releases/v0.10.11.md +39 -0
  46. package/docs/releases/v0.10.12.md +57 -0
  47. package/docs/releases/v0.10.13.md +35 -0
  48. package/docs/releases/v0.10.14.md +42 -0
  49. package/docs/releases/v0.10.15.md +53 -0
  50. package/docs/releases/v0.10.16.md +35 -0
  51. package/docs/releases/v0.10.17.md +43 -0
  52. package/docs/releases/v0.10.2.md +64 -0
  53. package/docs/releases/v0.10.3.md +78 -0
  54. package/docs/releases/v0.10.4.md +42 -0
  55. package/docs/releases/v0.10.5.md +57 -0
  56. package/docs/releases/v0.10.6.md +47 -0
  57. package/docs/releases/v0.10.7.md +53 -0
  58. package/docs/releases/v0.10.8.md +49 -0
  59. package/docs/releases/v0.10.9.md +37 -0
  60. package/docs/releases/v0.11.0.md +86 -0
  61. package/docs/releases/v0.12.0.md +67 -0
  62. package/docs/releases/v0.13.0.md +64 -0
  63. package/docs/releases/v0.14.0.md +68 -0
  64. package/docs/releases/v0.15.0.md +48 -0
  65. package/docs/releases/v0.16.0.md +50 -0
  66. package/docs/releases/v0.16.1.md +55 -0
  67. package/docs/releases/v0.16.2.md +36 -0
  68. package/docs/releases/v0.17.0.md +50 -0
  69. package/docs/releases/v0.17.1.md +58 -0
  70. package/docs/releases/v0.17.2.md +42 -0
  71. package/docs/releases/v0.17.3.md +58 -0
  72. package/docs/releases/v0.18.0.md +84 -0
  73. package/docs/releases/v0.18.1.md +51 -0
  74. package/docs/releases/v0.18.2.md +69 -0
  75. package/docs/releases/v0.19.0.md +85 -0
  76. package/docs/releases/v0.19.1.md +46 -0
  77. package/docs/releases/v0.20.0.md +85 -0
  78. package/docs/releases/v0.21.0.md +61 -0
  79. package/docs/releases/v0.21.1.md +47 -0
  80. package/docs/releases/v0.22.0.md +77 -0
  81. package/docs/releases/v0.22.1.md +42 -0
  82. package/docs/releases/v0.23.0.md +105 -0
  83. package/docs/releases/v0.24.0.md +125 -0
  84. package/docs/releases/v0.25.0.md +107 -0
  85. package/docs/releases/v0.26.0.md +139 -0
  86. package/docs/releases/v0.26.1.md +65 -0
  87. package/docs/releases/v0.26.2.md +43 -0
  88. package/docs/releases/v0.27.0.md +63 -0
  89. package/docs/releases/v0.28.0.md +59 -0
  90. package/docs/releases/v0.29.0.md +61 -0
  91. package/docs/releases/v0.29.1.md +59 -0
  92. package/docs/releases/v0.29.2.md +59 -0
  93. package/docs/releases/v0.29.3.md +93 -0
  94. package/docs/releases/v0.30.0.md +75 -0
  95. package/docs/releases/v0.30.1.md +93 -0
  96. package/docs/releases/v0.30.2.md +66 -0
  97. package/docs/releases/v0.31.0.md +122 -0
  98. package/docs/releases/v0.31.1.md +142 -0
  99. package/docs/releases/v0.31.10.md +118 -0
  100. package/docs/releases/v0.31.11.md +88 -0
  101. package/docs/releases/v0.31.12.md +105 -0
  102. package/docs/releases/v0.31.13.md +99 -0
  103. package/docs/releases/v0.31.14.md +97 -0
  104. package/docs/releases/v0.31.2.md +115 -0
  105. package/docs/releases/v0.31.3.md +142 -0
  106. package/docs/releases/v0.31.4.md +117 -0
  107. package/docs/releases/v0.31.5.md +155 -0
  108. package/docs/releases/v0.31.6.md +132 -0
  109. package/docs/releases/v0.31.7.md +132 -0
  110. package/docs/releases/v0.31.8.md +120 -0
  111. package/docs/releases/v0.31.9.md +120 -0
  112. package/docs/releases/v0.32.0.md +261 -0
  113. package/docs/releases/v0.32.1.md +59 -0
  114. package/docs/releases/v0.8.0.md +118 -0
  115. package/docs/releases/v0.9.0.md +98 -0
  116. package/docs/releases/v0.9.1.md +83 -0
  117. package/package.json +102 -6
  118. package/plugins/mirror-mind/.claude-plugin/plugin.json +13 -0
  119. package/plugins/mirror-mind/hooks/hooks.json +50 -0
  120. package/plugins/mirror-mind/hooks/log-session-end.sh +98 -0
  121. package/plugins/mirror-mind/hooks/log-user-prompt.sh +98 -0
  122. package/plugins/mirror-mind/hooks/mirror-inject.sh +98 -0
  123. package/plugins/mirror-mind/hooks/session-start.sh +98 -0
  124. package/plugins/mirror-mind/mcp/launch.sh +52 -0
  125. package/plugins/mirror-mind/skills/mm-backup/SKILL.md +27 -0
  126. package/plugins/mirror-mind/skills/mm-build/SKILL.md +1206 -0
  127. package/plugins/mirror-mind/skills/mm-consolidate/SKILL.md +112 -0
  128. package/plugins/mirror-mind/skills/mm-consult/SKILL.md +83 -0
  129. package/plugins/mirror-mind/skills/mm-conversations/SKILL.md +17 -0
  130. package/plugins/mirror-mind/skills/mm-discard/SKILL.md +40 -0
  131. package/plugins/mirror-mind/skills/mm-explore/SKILL.md +241 -0
  132. package/plugins/mirror-mind/skills/mm-help/SKILL.md +104 -0
  133. package/plugins/mirror-mind/skills/mm-identity/SKILL.md +96 -0
  134. package/plugins/mirror-mind/skills/mm-journal/SKILL.md +21 -0
  135. package/plugins/mirror-mind/skills/mm-journey/SKILL.md +37 -0
  136. package/plugins/mirror-mind/skills/mm-journeys/SKILL.md +15 -0
  137. package/plugins/mirror-mind/skills/mm-memories/SKILL.md +20 -0
  138. package/plugins/mirror-mind/skills/mm-mirror/SKILL.md +65 -0
  139. package/plugins/mirror-mind/skills/mm-mute/SKILL.md +18 -0
  140. package/plugins/mirror-mind/skills/mm-new/SKILL.md +18 -0
  141. package/plugins/mirror-mind/skills/mm-recall/SKILL.md +17 -0
  142. package/plugins/mirror-mind/skills/mm-release-notes/SKILL.md +31 -0
  143. package/plugins/mirror-mind/skills/mm-seed/SKILL.md +15 -0
  144. package/plugins/mirror-mind/skills/mm-shadow/SKILL.md +117 -0
  145. package/plugins/mirror-mind/skills/mm-soul/SKILL.md +488 -0
  146. package/plugins/mirror-mind/skills/mm-tasks/SKILL.md +36 -0
  147. package/plugins/mirror-mind/skills/mm-update/SKILL.md +30 -0
  148. package/plugins/mirror-mind/skills/mm-week/SKILL.md +46 -0
  149. package/plugins/mirror-mind/skills/mm-welcome/SKILL.md +22 -0
  150. package/scripts/codex-hooks/session-end.sh +85 -0
  151. package/scripts/codex-hooks/session-start.sh +85 -0
  152. package/scripts/codex-mirror.sh +48 -0
  153. package/templates/identity/README.md +119 -0
  154. package/templates/identity/ego/behavior.yaml +52 -0
  155. package/templates/identity/ego/constraints.yaml +15 -0
  156. package/templates/identity/ego/identity.yaml +43 -0
  157. package/templates/identity/journeys/personal-growth.yaml +39 -0
  158. package/templates/identity/organization/identity.yaml +24 -0
  159. package/templates/identity/organization/principles.yaml +17 -0
  160. package/templates/identity/personas/coach.yaml +94 -0
  161. package/templates/identity/personas/designer.yaml +93 -0
  162. package/templates/identity/personas/doctor.yaml +96 -0
  163. package/templates/identity/personas/engineer.yaml +77 -0
  164. package/templates/identity/personas/financial.yaml +97 -0
  165. package/templates/identity/personas/prompt-engineer.yaml +122 -0
  166. package/templates/identity/personas/researcher.yaml +88 -0
  167. package/templates/identity/personas/strategist.yaml +91 -0
  168. package/templates/identity/personas/teacher.yaml +95 -0
  169. package/templates/identity/personas/therapist.yaml +91 -0
  170. package/templates/identity/personas/thinker.yaml +74 -0
  171. package/templates/identity/personas/writer.yaml +76 -0
  172. package/templates/identity/self/config.yaml +16 -0
  173. package/templates/identity/self/soul.yaml +105 -0
  174. package/templates/identity/user/identity.yaml +30 -0
  175. package/ts/src/backup/staging.ts +62 -0
  176. package/ts/src/backup/zipBackup.ts +267 -0
  177. package/ts/src/backup/zipReader.ts +109 -0
  178. package/ts/src/backup/zipWriter.ts +148 -0
  179. package/ts/src/builder/activeCheckpoint.ts +134 -0
  180. package/ts/src/builder/aggregateStatus.ts +34 -0
  181. package/ts/src/builder/approve.ts +149 -0
  182. package/ts/src/builder/argv.ts +292 -0
  183. package/ts/src/builder/ariadMethod.ts +536 -0
  184. package/ts/src/builder/artifacts/artifactSurfaces.ts +106 -0
  185. package/ts/src/builder/artifacts/artifactWriter.ts +113 -0
  186. package/ts/src/builder/artifacts/closureArtifacts.ts +199 -0
  187. package/ts/src/builder/artifacts/deliveryStoryArtifacts.ts +316 -0
  188. package/ts/src/builder/artifacts/planArtifacts.ts +242 -0
  189. package/ts/src/builder/artifacts/scaffoldSections.ts +273 -0
  190. package/ts/src/builder/artifacts/scaffoldState.ts +227 -0
  191. package/ts/src/builder/artifacts/storyFiles.ts +61 -0
  192. package/ts/src/builder/artifacts/storyIndex.ts +166 -0
  193. package/ts/src/builder/cadence.ts +59 -0
  194. package/ts/src/builder/card.ts +192 -0
  195. package/ts/src/builder/checkpointRefused.ts +66 -0
  196. package/ts/src/builder/closure.ts +964 -0
  197. package/ts/src/builder/commands.ts +2053 -0
  198. package/ts/src/builder/cursorPosition.ts +176 -0
  199. package/ts/src/builder/cursorTransitions.ts +77 -0
  200. package/ts/src/builder/deliveryCursor.ts +577 -0
  201. package/ts/src/builder/deliveryStoryClosure.ts +521 -0
  202. package/ts/src/builder/deliveryStoryPlan.ts +536 -0
  203. package/ts/src/builder/deliveryStoryReady.ts +160 -0
  204. package/ts/src/builder/deliveryStoryRoadmapClosure.ts +151 -0
  205. package/ts/src/builder/expand.ts +336 -0
  206. package/ts/src/builder/flowUnit.ts +339 -0
  207. package/ts/src/builder/homeSurface.ts +122 -0
  208. package/ts/src/builder/implementationGuard.ts +125 -0
  209. package/ts/src/builder/index.ts +11 -0
  210. package/ts/src/builder/lifecycleRefusal.ts +92 -0
  211. package/ts/src/builder/lifecycleRibbon.ts +159 -0
  212. package/ts/src/builder/load.ts +313 -0
  213. package/ts/src/builder/methodAdoption.ts +113 -0
  214. package/ts/src/builder/methodDefinition.ts +429 -0
  215. package/ts/src/builder/methodInspection.ts +371 -0
  216. package/ts/src/builder/plan.ts +408 -0
  217. package/ts/src/builder/planPreauthorization.ts +265 -0
  218. package/ts/src/builder/prepare.ts +225 -0
  219. package/ts/src/builder/projectPaths.ts +64 -0
  220. package/ts/src/builder/pull.ts +356 -0
  221. package/ts/src/builder/pullCandidates.ts +463 -0
  222. package/ts/src/builder/pullCandidatesRender.ts +238 -0
  223. package/ts/src/builder/refinementField.ts +93 -0
  224. package/ts/src/builder/releaseIntent.ts +173 -0
  225. package/ts/src/builder/resumeState.ts +84 -0
  226. package/ts/src/builder/resumeSurface.ts +149 -0
  227. package/ts/src/builder/roadmapGrammar.ts +300 -0
  228. package/ts/src/builder/roadmapScan.ts +97 -0
  229. package/ts/src/builder/roadmapScope.ts +210 -0
  230. package/ts/src/builder/scopePhrases.ts +146 -0
  231. package/ts/src/builder/storyPaths.ts +196 -0
  232. package/ts/src/builder/storyPlanPreauthorization.ts +287 -0
  233. package/ts/src/builder/surfaceProtocol.ts +42 -0
  234. package/ts/src/builder/templateGeneration.ts +148 -0
  235. package/ts/src/builder/transition.ts +178 -0
  236. package/ts/src/consult/args.ts +99 -0
  237. package/ts/src/consult/core.ts +122 -0
  238. package/ts/src/consult/modelCatalog.ts +55 -0
  239. package/ts/src/consult/render.ts +47 -0
  240. package/ts/src/conversation/append.ts +414 -0
  241. package/ts/src/conversation/backfill.ts +387 -0
  242. package/ts/src/conversation/closeTail.ts +467 -0
  243. package/ts/src/conversation/extraction.ts +333 -0
  244. package/ts/src/conversation/extractionDriver.ts +130 -0
  245. package/ts/src/conversation/extractionRun.ts +70 -0
  246. package/ts/src/conversation/journeyInference.ts +165 -0
  247. package/ts/src/conversation/journeyRepair.ts +114 -0
  248. package/ts/src/conversation/lifecycleFaces.ts +197 -0
  249. package/ts/src/conversation/lifecycleWrites.ts +313 -0
  250. package/ts/src/conversation/listing.ts +77 -0
  251. package/ts/src/conversation/logger.ts +576 -0
  252. package/ts/src/conversation/loggerCli.ts +282 -0
  253. package/ts/src/conversation/loggerRuntime.ts +259 -0
  254. package/ts/src/conversation/metadataLifecycle.ts +443 -0
  255. package/ts/src/conversation/recall.ts +66 -0
  256. package/ts/src/conversation/sessionComposites.ts +258 -0
  257. package/ts/src/conversation/sessionImport.ts +90 -0
  258. package/ts/src/conversation/transcriptBackfill.ts +141 -0
  259. package/ts/src/cultivation/applyActions.ts +241 -0
  260. package/ts/src/cultivation/cluster.ts +86 -0
  261. package/ts/src/cultivation/consolidationStore.ts +281 -0
  262. package/ts/src/cultivation/promptContext.ts +62 -0
  263. package/ts/src/cultivation/propose.ts +305 -0
  264. package/ts/src/cultivation/scan.ts +155 -0
  265. package/ts/src/db/backupGate.ts +47 -0
  266. package/ts/src/db/bootstrap.ts +108 -0
  267. package/ts/src/db/bootstrapLock.ts +223 -0
  268. package/ts/src/db/copyGuard.ts +60 -0
  269. package/ts/src/db/database.ts +397 -0
  270. package/ts/src/db/decode.ts +66 -0
  271. package/ts/src/db/ftsIntegrity.ts +41 -0
  272. package/ts/src/db/migrateOnOpen.ts +214 -0
  273. package/ts/src/db/migrations.ts +576 -0
  274. package/ts/src/db/readyOnOpen.ts +35 -0
  275. package/ts/src/db/rowDecode.ts +42 -0
  276. package/ts/src/db/schema.ts +432 -0
  277. package/ts/src/db/schemaInventory.ts +225 -0
  278. package/ts/src/db/schemaInventorySnapshot.ts +2107 -0
  279. package/ts/src/db/schemaState.ts +91 -0
  280. package/ts/src/db/schemaTsDivergence.ts +114 -0
  281. package/ts/src/descriptor/descriptorRead.ts +49 -0
  282. package/ts/src/docs/docsLint.ts +265 -0
  283. package/ts/src/explorer/handoff.ts +522 -0
  284. package/ts/src/explorer/render.ts +335 -0
  285. package/ts/src/explorer/story.ts +769 -0
  286. package/ts/src/explorer/transition.ts +72 -0
  287. package/ts/src/extensions/bindings.ts +170 -0
  288. package/ts/src/extensions/catalog.ts +249 -0
  289. package/ts/src/extensions/catalogCommands.ts +513 -0
  290. package/ts/src/extensions/catalogWrites.ts +652 -0
  291. package/ts/src/extensions/contextRuntime.ts +325 -0
  292. package/ts/src/extensions/dispatch.ts +374 -0
  293. package/ts/src/extensions/errors.ts +24 -0
  294. package/ts/src/extensions/manifest.ts +356 -0
  295. package/ts/src/extensions/migrations.ts +350 -0
  296. package/ts/src/extraction/conversation.ts +304 -0
  297. package/ts/src/extraction/conversationMetadata.ts +206 -0
  298. package/ts/src/extraction/fencing.ts +106 -0
  299. package/ts/src/extraction/json.ts +17 -0
  300. package/ts/src/extraction/prompts.ts +470 -0
  301. package/ts/src/frontDoor/args.ts +30 -0
  302. package/ts/src/frontDoor/argvShape.ts +106 -0
  303. package/ts/src/frontDoor/buildLoadRuntime.ts +139 -0
  304. package/ts/src/frontDoor/buildRoute.ts +398 -0
  305. package/ts/src/frontDoor/cli.ts +1865 -0
  306. package/ts/src/frontDoor/cloneRoleGuard.ts +98 -0
  307. package/ts/src/frontDoor/consultRoute.ts +50 -0
  308. package/ts/src/frontDoor/contentTailRoute.ts +239 -0
  309. package/ts/src/frontDoor/conversationLoggerRoute.ts +73 -0
  310. package/ts/src/frontDoor/cultivationRoute.ts +210 -0
  311. package/ts/src/frontDoor/dbPath.ts +131 -0
  312. package/ts/src/frontDoor/dbSafetyToolsRoute.ts +240 -0
  313. package/ts/src/frontDoor/exploreRoute.ts +572 -0
  314. package/ts/src/frontDoor/extensionCatalogRoute.ts +252 -0
  315. package/ts/src/frontDoor/frontDoorLog.ts +57 -0
  316. package/ts/src/frontDoor/identityWrite.ts +36 -0
  317. package/ts/src/frontDoor/journeyWriteRoute.ts +26 -0
  318. package/ts/src/frontDoor/lifecycleWriteRoute.ts +110 -0
  319. package/ts/src/frontDoor/liveBackup.ts +100 -0
  320. package/ts/src/frontDoor/mirrorModeRoute.ts +163 -0
  321. package/ts/src/frontDoor/namedRefusal.ts +35 -0
  322. package/ts/src/frontDoor/nodeSupport.ts +24 -0
  323. package/ts/src/frontDoor/render/consolidate.ts +199 -0
  324. package/ts/src/frontDoor/render/conversations.ts +33 -0
  325. package/ts/src/frontDoor/render/cultivationShared.ts +21 -0
  326. package/ts/src/frontDoor/render/descriptor.ts +20 -0
  327. package/ts/src/frontDoor/render/detectPersona.ts +50 -0
  328. package/ts/src/frontDoor/render/icons.ts +13 -0
  329. package/ts/src/frontDoor/render/identity.ts +59 -0
  330. package/ts/src/frontDoor/render/identityRows.ts +17 -0
  331. package/ts/src/frontDoor/render/inspectPersona.ts +53 -0
  332. package/ts/src/frontDoor/render/journeyStatus.ts +78 -0
  333. package/ts/src/frontDoor/render/journeys.ts +79 -0
  334. package/ts/src/frontDoor/render/list.ts +41 -0
  335. package/ts/src/frontDoor/render/memories.ts +67 -0
  336. package/ts/src/frontDoor/render/recall.ts +49 -0
  337. package/ts/src/frontDoor/render/shadow.ts +155 -0
  338. package/ts/src/frontDoor/render/tasks.ts +99 -0
  339. package/ts/src/frontDoor/render/tasksImportSync.ts +63 -0
  340. package/ts/src/frontDoor/render/week.ts +113 -0
  341. package/ts/src/frontDoor/routing.ts +999 -0
  342. package/ts/src/frontDoor/runtimeRoute.ts +623 -0
  343. package/ts/src/frontDoor/searchRoute.ts +166 -0
  344. package/ts/src/frontDoor/seedPaths.ts +98 -0
  345. package/ts/src/frontDoor/soulRoute.ts +433 -0
  346. package/ts/src/frontDoor/tasksImportSyncRoute.ts +110 -0
  347. package/ts/src/frontDoor/tasksWriteRoute.ts +101 -0
  348. package/ts/src/frontDoor/usage.ts +176 -0
  349. package/ts/src/guards/claudePlugin.ts +252 -0
  350. package/ts/src/guards/packContents.ts +306 -0
  351. package/ts/src/guards/piSourcedSkills.ts +70 -0
  352. package/ts/src/guards/retiredRouteShadows.ts +57 -0
  353. package/ts/src/guards/retiredSurfaces.ts +564 -0
  354. package/ts/src/hooks/claude.ts +176 -0
  355. package/ts/src/hooks/codex.ts +45 -0
  356. package/ts/src/hooks/gemini.ts +126 -0
  357. package/ts/src/hooks/main.ts +109 -0
  358. package/ts/src/hooks/mirrorState.ts +71 -0
  359. package/ts/src/hooks/payload.ts +68 -0
  360. package/ts/src/hooks/runtime.ts +159 -0
  361. package/ts/src/identity/applyConsolidationIdentityUpdate.ts +67 -0
  362. package/ts/src/identity/descriptorGenerate.ts +162 -0
  363. package/ts/src/identity/identityEdit.ts +143 -0
  364. package/ts/src/identity/identityKey.ts +77 -0
  365. package/ts/src/identity/identityRead.ts +69 -0
  366. package/ts/src/identity/identityStore.ts +80 -0
  367. package/ts/src/identity/journeyListing.ts +53 -0
  368. package/ts/src/identity/personaInspect.ts +44 -0
  369. package/ts/src/identity/personaListing.ts +37 -0
  370. package/ts/src/identity/setIdentity.ts +64 -0
  371. package/ts/src/index.ts +231 -0
  372. package/ts/src/init/init.ts +111 -0
  373. package/ts/src/journey/journeyOptions.ts +131 -0
  374. package/ts/src/journey/journeyRemoval.ts +158 -0
  375. package/ts/src/journey/journeyStatus.ts +149 -0
  376. package/ts/src/journey/journeySyncFile.ts +87 -0
  377. package/ts/src/journey/journeyWrite.ts +203 -0
  378. package/ts/src/journey/parentJourney.ts +41 -0
  379. package/ts/src/journey/validateParentJourney.ts +55 -0
  380. package/ts/src/mcp/boundary.ts +151 -0
  381. package/ts/src/mcp/guards.ts +244 -0
  382. package/ts/src/mcp/main.ts +121 -0
  383. package/ts/src/mcp/payload.ts +141 -0
  384. package/ts/src/mcp/protocol.ts +141 -0
  385. package/ts/src/mcp/readModels.ts +241 -0
  386. package/ts/src/mcp/registry.ts +201 -0
  387. package/ts/src/mcp/serve.ts +120 -0
  388. package/ts/src/mcp/tools/deterministic.ts +137 -0
  389. package/ts/src/mcp/tools/providerCrossing.ts +187 -0
  390. package/ts/src/mcp/wire.ts +8 -0
  391. package/ts/src/memory/journal.ts +180 -0
  392. package/ts/src/memory/listing.ts +107 -0
  393. package/ts/src/memory/memoryWrite.ts +88 -0
  394. package/ts/src/memory/reinforcement.ts +35 -0
  395. package/ts/src/mirror/context.ts +161 -0
  396. package/ts/src/mirror/defaultResolution.ts +199 -0
  397. package/ts/src/mirror/orchestration.ts +364 -0
  398. package/ts/src/mirror/reception.ts +194 -0
  399. package/ts/src/mirror/render.ts +75 -0
  400. package/ts/src/mirror/runtimeSession.ts +205 -0
  401. package/ts/src/mode/operatingMode.ts +148 -0
  402. package/ts/src/observability/callOutcome.ts +115 -0
  403. package/ts/src/observability/inspectLedger.ts +329 -0
  404. package/ts/src/observability/ledgerHooks.ts +126 -0
  405. package/ts/src/observability/llmCalls.ts +154 -0
  406. package/ts/src/persona/detectPersona.ts +81 -0
  407. package/ts/src/planning/promptAssembly.ts +111 -0
  408. package/ts/src/planning/weekPending.ts +81 -0
  409. package/ts/src/planning/weekPlan.ts +183 -0
  410. package/ts/src/planning/weekSave.ts +117 -0
  411. package/ts/src/providers/config.ts +189 -0
  412. package/ts/src/providers/cost.ts +64 -0
  413. package/ts/src/providers/credits.ts +204 -0
  414. package/ts/src/providers/embedding.ts +321 -0
  415. package/ts/src/providers/familyProviders.ts +147 -0
  416. package/ts/src/providers/llm.ts +334 -0
  417. package/ts/src/providers/openrouter.ts +244 -0
  418. package/ts/src/providers/redaction.ts +110 -0
  419. package/ts/src/providers/replay.ts +15 -0
  420. package/ts/src/providers/transport.ts +410 -0
  421. package/ts/src/repair/encodingRepair.ts +253 -0
  422. package/ts/src/runtime/backup.ts +151 -0
  423. package/ts/src/runtime/channel.ts +146 -0
  424. package/ts/src/runtime/config.ts +168 -0
  425. package/ts/src/runtime/diagnose.ts +686 -0
  426. package/ts/src/runtime/git.ts +510 -0
  427. package/ts/src/runtime/installKind.ts +220 -0
  428. package/ts/src/runtime/migrate.ts +154 -0
  429. package/ts/src/runtime/packageIdentity.ts +102 -0
  430. package/ts/src/runtime/releaseNotes.ts +244 -0
  431. package/ts/src/runtime/status.ts +557 -0
  432. package/ts/src/runtime/strategies/clone.ts +200 -0
  433. package/ts/src/runtime/strategies/package.ts +328 -0
  434. package/ts/src/runtime/treeRoot.ts +30 -0
  435. package/ts/src/runtime/update.ts +445 -0
  436. package/ts/src/runtime/updateGate.ts +40 -0
  437. package/ts/src/runtime/updatePipeline.ts +159 -0
  438. package/ts/src/runtime/version.ts +36 -0
  439. package/ts/src/runtime/wiring.ts +130 -0
  440. package/ts/src/search/memorySearch.ts +338 -0
  441. package/ts/src/search/ranker.ts +154 -0
  442. package/ts/src/seed/seed.ts +256 -0
  443. package/ts/src/seed/seedYaml.ts +133 -0
  444. package/ts/src/soul/apply.ts +218 -0
  445. package/ts/src/soul/harvest.ts +267 -0
  446. package/ts/src/soul/prompts/soul_beauty_voice.md +103 -0
  447. package/ts/src/soul/prompts/soul_self_voice.md +219 -0
  448. package/ts/src/soul/prompts/soul_wisdom_voice.md +121 -0
  449. package/ts/src/soul/prompts.ts +85 -0
  450. package/ts/src/soul/render.ts +358 -0
  451. package/ts/src/soul/state.ts +212 -0
  452. package/ts/src/soul/transition.ts +37 -0
  453. package/ts/src/tasks/journeyPathParse.ts +113 -0
  454. package/ts/src/tasks/taskImportSync.ts +142 -0
  455. package/ts/src/tasks/taskStore.ts +312 -0
  456. package/ts/src/tasks/weekView.ts +120 -0
  457. package/ts/src/util/clipCodePoints.ts +26 -0
  458. package/ts/src/util/paths.ts +63 -0
  459. package/ts/src/util/program.ts +9 -0
  460. package/ts/src/util/pyGenerators.ts +144 -0
  461. package/ts/src/util/pythonText.ts +317 -0
  462. package/ts/src/util/semver.ts +45 -0
  463. package/ts/src/util/shellWord.ts +25 -0
  464. package/ts/src/util/slug.ts +64 -0
  465. package/ts/src/welcome/card.ts +339 -0
  466. package/ts/src/welcome/statusLine.ts +101 -0
  467. package/ts/src/welcome/updateCache.ts +129 -0
@@ -0,0 +1,414 @@
1
+ // CV22.DS7.US5 slice B — the explicit conversation append boundary (v0.31.13).
2
+ //
3
+ // Ports `src/memory/services/conversation_append.py` and
4
+ // `MessageStore.append_conversation_messages`. This is a published contract
5
+ // for external shells, so rejections stay bounded and public, metadata is
6
+ // canonical JSON, batches are atomic, and replay is idempotent on the caller's
7
+ // message ids.
8
+ //
9
+ // KNOWN DIVERGENCE (registered for Debt Review): caller metadata containing an
10
+ // integer-valued float (`1.0`) serializes as `1.0` in Python and `1` in TS,
11
+ // because `JSON.parse` collapses the two before either core can see the
12
+ // difference. Non-integer floats (`1.5`) agree. Metadata bytes participate in
13
+ // the idempotency comparison, so a batch written by one core and replayed
14
+ // through the other with such metadata would raise `idempotency_conflict`.
15
+
16
+ import { type WritableDatabase, withTransaction } from "#db/database.ts";
17
+ import { compareByCodePoint } from "#util/pythonText.ts";
18
+
19
+ export const APPEND_SCHEMA_VERSION = "1.0.0";
20
+ export const MAX_PAYLOAD_BYTES = 262_144;
21
+ export const MAX_MESSAGES = 20;
22
+ export const MAX_CONTENT_BYTES = 51_200;
23
+ export const MAX_METADATA_BYTES = 4_096;
24
+ const MICROSECOND_DIGITS = 6;
25
+
26
+ const MESSAGE_ID_RE = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;
27
+ const SOURCE_INTERFACE_RE = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
28
+ const RFC3339_RE =
29
+ /^(?<civil>\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2})(?:\.(?<fraction>\d+))?(?<offset>Z|[+-]\d{2}:\d{2})$/;
30
+
31
+ export type AppendRejectionReason =
32
+ | "malformed_request"
33
+ | "unsupported_schema_version"
34
+ | "limit_exceeded"
35
+ | "conversation_not_found"
36
+ | "journey_mismatch"
37
+ | "duplicate_request_message_id"
38
+ | "idempotency_conflict"
39
+ | "persistence_failure";
40
+
41
+ const PUBLIC_MESSAGES: Record<AppendRejectionReason, string> = {
42
+ malformed_request: "Request does not match the conversation append contract.",
43
+ unsupported_schema_version: "Request schema version is unsupported.",
44
+ limit_exceeded: "Request exceeds a conversation append limit.",
45
+ conversation_not_found: "Conversation was not found.",
46
+ journey_mismatch: "Conversation belongs to a different journey.",
47
+ duplicate_request_message_id: "Request contains a duplicate message ID.",
48
+ idempotency_conflict: "Message ID conflicts with persisted conversation data.",
49
+ persistence_failure: "Conversation append could not be persisted.",
50
+ };
51
+
52
+ /** A bounded public rejection; never carries caller content. */
53
+ export class AppendRejectedError extends Error {
54
+ readonly reason: AppendRejectionReason;
55
+ readonly publicMessage: string;
56
+
57
+ constructor(reason: AppendRejectionReason) {
58
+ super(PUBLIC_MESSAGES[reason]);
59
+ this.reason = reason;
60
+ this.publicMessage = PUBLIC_MESSAGES[reason];
61
+ }
62
+
63
+ receipt(): Record<string, string> {
64
+ return {
65
+ schemaVersion: APPEND_SCHEMA_VERSION,
66
+ status: "rejected",
67
+ reason: this.reason,
68
+ message: this.publicMessage,
69
+ };
70
+ }
71
+ }
72
+
73
+ export interface AppendMessage {
74
+ id: string;
75
+ role: "user" | "assistant";
76
+ content: string;
77
+ createdAt: string;
78
+ metadataJson: string;
79
+ }
80
+
81
+ export interface ConversationAppendRequest {
82
+ conversationId: string;
83
+ journeyId: string;
84
+ sourceInterface: string;
85
+ messages: AppendMessage[];
86
+ }
87
+
88
+ export interface AppendReceipt {
89
+ schemaVersion: string;
90
+ status: "accepted";
91
+ conversationId: string;
92
+ journeyId: string;
93
+ insertedCount: number;
94
+ existingCount: number;
95
+ messages: { id: string; state: "inserted" | "existing" }[];
96
+ }
97
+
98
+ function isRecord(value: unknown): value is Record<string, unknown> {
99
+ return typeof value === "object" && value !== null && !Array.isArray(value);
100
+ }
101
+
102
+ /** Python `json.dumps(..., ensure_ascii=False, sort_keys=True, separators=(",", ":"))`. */
103
+ export function canonicalJson(value: unknown): string {
104
+ if (value === null) return "null";
105
+ if (typeof value === "boolean" || typeof value === "string") return JSON.stringify(value);
106
+ if (typeof value === "number") {
107
+ // Python passes allow_nan=False, so NaN/Infinity are contract failures.
108
+ if (!Number.isFinite(value)) throw new AppendRejectedError("malformed_request");
109
+ return JSON.stringify(value);
110
+ }
111
+ if (Array.isArray(value)) return `[${value.map((item) => canonicalJson(item)).join(",")}]`;
112
+ if (isRecord(value)) {
113
+ const entries = Object.keys(value)
114
+ .sort(compareByCodePoint)
115
+ .map((key) => `${JSON.stringify(key)}:${canonicalJson(value[key])}`);
116
+ return `{${entries.join(",")}}`;
117
+ }
118
+ throw new AppendRejectedError("malformed_request");
119
+ }
120
+
121
+ /**
122
+ * Idempotency comparison for stored message metadata (CV22.DS7.US10 slice B′).
123
+ *
124
+ * The contract is value-semantics ("same JSON value"), not byte-semantics.
125
+ * Bytes remain the fast path, but rows written before Python collapsed
126
+ * integer-valued floats carry `1.0` where the same request now canonicalizes
127
+ * to `1`. Rejecting those as `idempotency_conflict` would break replay for
128
+ * every caller that ever sent such a value, so equivalent JSON values compare
129
+ * equal while genuinely different ones still conflict.
130
+ *
131
+ * Mirrors `metadata_matches` in `src/memory/storage/messages.py`.
132
+ */
133
+ export function metadataMatches(stored: unknown, incoming: unknown): boolean {
134
+ if (stored === incoming) return true;
135
+ if (typeof stored !== "string" || typeof incoming !== "string") return false;
136
+ try {
137
+ return jsonValueEqual(JSON.parse(stored), JSON.parse(incoming));
138
+ } catch {
139
+ return false;
140
+ }
141
+ }
142
+
143
+ /**
144
+ * Compare decoded JSON values, keeping JSON's type classes distinct.
145
+ *
146
+ * Booleans are compared as booleans, never as numbers: Python's `True == 1`
147
+ * makes this a live hazard on the oracle side, and accepting `{"flag": 1}` as a
148
+ * replay of `{"flag": true}` would silently swallow a different payload.
149
+ */
150
+ function jsonValueEqual(left: unknown, right: unknown): boolean {
151
+ if (typeof left === "boolean" || typeof right === "boolean") {
152
+ return typeof left === "boolean" && typeof right === "boolean" && left === right;
153
+ }
154
+ if (typeof left === "number" && typeof right === "number") return left === right;
155
+ if (Array.isArray(left) && Array.isArray(right)) {
156
+ return (
157
+ left.length === right.length &&
158
+ left.every((item, index) => jsonValueEqual(item, right[index]))
159
+ );
160
+ }
161
+ if (isRecord(left) && isRecord(right)) {
162
+ const leftKeys = Object.keys(left).sort();
163
+ const rightKeys = Object.keys(right).sort();
164
+ return (
165
+ leftKeys.length === rightKeys.length &&
166
+ leftKeys.every((key, index) => key === rightKeys[index]) &&
167
+ leftKeys.every((key) => jsonValueEqual(left[key], right[key]))
168
+ );
169
+ }
170
+ return left === right;
171
+ }
172
+
173
+ function isFiniteJson(value: unknown): boolean {
174
+ if (value === null || typeof value === "string" || typeof value === "boolean") return true;
175
+ if (typeof value === "number") return Number.isFinite(value);
176
+ if (Array.isArray(value)) return value.every((item) => isFiniteJson(item));
177
+ if (isRecord(value)) return Object.values(value).every((item) => isFiniteJson(item));
178
+ return false;
179
+ }
180
+
181
+ function utf8Length(value: string): number {
182
+ return Buffer.byteLength(value, "utf8");
183
+ }
184
+
185
+ /**
186
+ * Normalize RFC 3339 input to UTC microseconds. The fraction is padded or
187
+ * truncated as a string so precision never passes through a millisecond-only
188
+ * Date, mirroring the explicit normalization the Python side now performs.
189
+ */
190
+ function normalizeTimestamp(value: unknown): string {
191
+ if (typeof value !== "string") throw new AppendRejectedError("malformed_request");
192
+ const match = RFC3339_RE.exec(value);
193
+ const groups = match?.groups;
194
+ if (!groups) throw new AppendRejectedError("malformed_request");
195
+
196
+ const civil = groups.civil as string;
197
+ const offset = groups.offset as string;
198
+ const micros = (groups.fraction ?? "")
199
+ .slice(0, MICROSECOND_DIGITS)
200
+ .padEnd(MICROSECOND_DIGITS, "0");
201
+
202
+ const year = Number(civil.slice(0, 4));
203
+ const month = Number(civil.slice(5, 7));
204
+ const day = Number(civil.slice(8, 10));
205
+ const hour = Number(civil.slice(11, 13));
206
+ const minute = Number(civil.slice(14, 16));
207
+ const second = Number(civil.slice(17, 19));
208
+
209
+ // `Date.UTC` silently rolls over (month 13 -> next January, second 60 -> next
210
+ // minute), which Python's parser rejects, so the components must round-trip.
211
+ const civilMs = Date.UTC(year, month - 1, day, hour, minute, second);
212
+ const roundTrip = new Date(civilMs);
213
+ if (
214
+ roundTrip.getUTCFullYear() !== year ||
215
+ roundTrip.getUTCMonth() !== month - 1 ||
216
+ roundTrip.getUTCDate() !== day ||
217
+ roundTrip.getUTCHours() !== hour ||
218
+ roundTrip.getUTCMinutes() !== minute ||
219
+ roundTrip.getUTCSeconds() !== second
220
+ ) {
221
+ throw new AppendRejectedError("malformed_request");
222
+ }
223
+
224
+ let utcMs = civilMs;
225
+ if (offset !== "Z") {
226
+ const offsetHours = Number(offset.slice(1, 3));
227
+ const offsetMinutes = Number(offset.slice(4, 6));
228
+ if (offsetHours > 23 || offsetMinutes > 59) {
229
+ throw new AppendRejectedError("malformed_request");
230
+ }
231
+ const totalMinutes = offsetHours * 60 + offsetMinutes;
232
+ utcMs -= (offset.startsWith("-") ? -1 : 1) * totalMinutes * 60_000;
233
+ }
234
+ return `${new Date(utcMs).toISOString().slice(0, 19)}.${micros}Z`;
235
+ }
236
+
237
+ function requiredString(value: unknown): string {
238
+ if (typeof value !== "string" || !value) throw new AppendRejectedError("malformed_request");
239
+ return value;
240
+ }
241
+
242
+ const ENVELOPE_KEYS = [
243
+ "schemaVersion",
244
+ "conversationId",
245
+ "journeyId",
246
+ "sourceInterface",
247
+ "messages",
248
+ ];
249
+ const MESSAGE_REQUIRED_KEYS = ["id", "role", "content", "createdAt"];
250
+
251
+ function sameKeySet(actual: string[], expected: string[]): boolean {
252
+ return actual.length === expected.length && expected.every((key) => actual.includes(key));
253
+ }
254
+
255
+ function parseMessage(raw: unknown, sourceInterface: string): AppendMessage {
256
+ if (!isRecord(raw)) throw new AppendRejectedError("malformed_request");
257
+ const keys = Object.keys(raw);
258
+ const allowed = new Set([...MESSAGE_REQUIRED_KEYS, "metadata"]);
259
+ if (
260
+ !MESSAGE_REQUIRED_KEYS.every((key) => keys.includes(key)) ||
261
+ !keys.every((key) => allowed.has(key))
262
+ ) {
263
+ throw new AppendRejectedError("malformed_request");
264
+ }
265
+
266
+ const id = raw.id;
267
+ if (typeof id !== "string" || !MESSAGE_ID_RE.test(id)) {
268
+ throw new AppendRejectedError("malformed_request");
269
+ }
270
+ const role = raw.role;
271
+ if (role !== "user" && role !== "assistant") {
272
+ throw new AppendRejectedError("malformed_request");
273
+ }
274
+ const content = raw.content;
275
+ if (typeof content !== "string" || !content) {
276
+ throw new AppendRejectedError("malformed_request");
277
+ }
278
+ if (utf8Length(content) > MAX_CONTENT_BYTES) {
279
+ throw new AppendRejectedError("limit_exceeded");
280
+ }
281
+
282
+ const callerMetadata = raw.metadata ?? {};
283
+ if (!isRecord(callerMetadata) || !isFiniteJson(callerMetadata)) {
284
+ throw new AppendRejectedError("malformed_request");
285
+ }
286
+ const metadataJson = canonicalJson({
287
+ callerMetadata,
288
+ mirrorAppend: { schemaVersion: APPEND_SCHEMA_VERSION, sourceInterface },
289
+ });
290
+ if (utf8Length(metadataJson) > MAX_METADATA_BYTES) {
291
+ throw new AppendRejectedError("limit_exceeded");
292
+ }
293
+
294
+ return { id, role, content, createdAt: normalizeTimestamp(raw.createdAt), metadataJson };
295
+ }
296
+
297
+ export function parseAppendRequest(payload: unknown): ConversationAppendRequest {
298
+ if (!isRecord(payload) || !sameKeySet(Object.keys(payload), ENVELOPE_KEYS)) {
299
+ throw new AppendRejectedError("malformed_request");
300
+ }
301
+ if (payload.schemaVersion !== APPEND_SCHEMA_VERSION) {
302
+ // A non-string version is malformed; a string one is merely unsupported.
303
+ if (typeof payload.schemaVersion !== "string") {
304
+ throw new AppendRejectedError("malformed_request");
305
+ }
306
+ throw new AppendRejectedError("unsupported_schema_version");
307
+ }
308
+
309
+ const conversationId = requiredString(payload.conversationId);
310
+ const journeyId = requiredString(payload.journeyId);
311
+ const sourceInterface = payload.sourceInterface;
312
+ if (typeof sourceInterface !== "string" || !SOURCE_INTERFACE_RE.test(sourceInterface)) {
313
+ throw new AppendRejectedError("malformed_request");
314
+ }
315
+
316
+ const rawMessages = payload.messages;
317
+ if (!Array.isArray(rawMessages)) throw new AppendRejectedError("malformed_request");
318
+ if (rawMessages.length < 1 || rawMessages.length > MAX_MESSAGES) {
319
+ throw new AppendRejectedError("limit_exceeded");
320
+ }
321
+
322
+ const messages: AppendMessage[] = [];
323
+ const seen = new Set<string>();
324
+ for (const raw of rawMessages) {
325
+ const message = parseMessage(raw, sourceInterface);
326
+ if (seen.has(message.id)) {
327
+ throw new AppendRejectedError("duplicate_request_message_id");
328
+ }
329
+ seen.add(message.id);
330
+ messages.push(message);
331
+ }
332
+ return { conversationId, journeyId, sourceInterface, messages };
333
+ }
334
+
335
+ /**
336
+ * Classify and append one validated batch inside a single owned transaction:
337
+ * all-or-nothing, so a conflict anywhere leaves the batch unwritten.
338
+ */
339
+ export function appendConversationMessages(
340
+ db: WritableDatabase,
341
+ request: ConversationAppendRequest,
342
+ ): AppendReceipt {
343
+ const states = withTransaction(db, () => {
344
+ const conversation = db
345
+ .prepare("SELECT journey FROM conversations WHERE id = ?")
346
+ .get(request.conversationId);
347
+ if (conversation === undefined) {
348
+ throw new AppendRejectedError("conversation_not_found");
349
+ }
350
+ if (conversation.journey !== request.journeyId) {
351
+ throw new AppendRejectedError("journey_mismatch");
352
+ }
353
+
354
+ const placeholders = request.messages.map(() => "?").join(",");
355
+ const rows = db
356
+ .prepare(
357
+ `SELECT id, conversation_id, role, content, created_at, metadata
358
+ FROM messages WHERE id IN (${placeholders})`,
359
+ )
360
+ .all(...request.messages.map((message) => message.id));
361
+ const existing = new Map(rows.map((row) => [String(row.id), row]));
362
+
363
+ const classified: ("inserted" | "existing")[] = [];
364
+ const absent: AppendMessage[] = [];
365
+ for (const message of request.messages) {
366
+ const row = existing.get(message.id);
367
+ if (row === undefined) {
368
+ classified.push("inserted");
369
+ absent.push(message);
370
+ continue;
371
+ }
372
+ if (
373
+ row.conversation_id !== request.conversationId ||
374
+ row.role !== message.role ||
375
+ row.content !== message.content ||
376
+ row.created_at !== message.createdAt ||
377
+ !metadataMatches(row.metadata, message.metadataJson)
378
+ ) {
379
+ throw new AppendRejectedError("idempotency_conflict");
380
+ }
381
+ classified.push("existing");
382
+ }
383
+
384
+ for (const message of absent) {
385
+ db.prepare(
386
+ `INSERT INTO messages
387
+ (id, conversation_id, role, content, created_at, token_count, metadata)
388
+ VALUES (?, ?, ?, ?, ?, NULL, ?)`,
389
+ ).run(
390
+ message.id,
391
+ request.conversationId,
392
+ message.role,
393
+ message.content,
394
+ message.createdAt,
395
+ message.metadataJson,
396
+ );
397
+ }
398
+ return classified;
399
+ });
400
+
401
+ const insertedCount = states.filter((state) => state === "inserted").length;
402
+ return {
403
+ schemaVersion: APPEND_SCHEMA_VERSION,
404
+ status: "accepted",
405
+ conversationId: request.conversationId,
406
+ journeyId: request.journeyId,
407
+ insertedCount,
408
+ existingCount: states.length - insertedCount,
409
+ messages: request.messages.map((message, index) => ({
410
+ id: message.id,
411
+ state: states[index] as "inserted" | "existing",
412
+ })),
413
+ };
414
+ }