@xopcai/xopc 0.0.408 → 0.0.410

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 (196) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/telegram/xopc.extension.json +1 -1
  3. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-B0em9Xfs.js → agent-avatar-dicebear-ColV_Z1C.js} +1 -1
  4. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-rgRXzBCX.js +1 -0
  5. package/dist/gateway/static/root/assets/agents-C1rSl_yE.js +77 -0
  6. package/dist/gateway/static/root/assets/app-management-settings-panel-B-Cl1lzt.js +1 -0
  7. package/dist/gateway/static/root/assets/appearance-settings-byEnJz9H.js +1 -0
  8. package/dist/gateway/static/root/assets/apps-page-BfVMfjkC.js +1 -0
  9. package/dist/gateway/static/root/assets/{archive-plugin-BjWaZIHe.js → archive-plugin-BXssEuq3.js} +1 -1
  10. package/dist/gateway/static/root/assets/{automations-page-IkrLEkMb.js → automations-page-C-puATkS.js} +1 -1
  11. package/dist/gateway/static/root/assets/automations-workspace-b7MTHd-X.js +6 -0
  12. package/dist/gateway/static/root/assets/{binary-plugins-DKy1DC62.js → binary-plugins-DBz_2AhG.js} +1 -1
  13. package/dist/gateway/static/root/assets/{block-editor-4E-OdmNm.js → block-editor-BOO5kjIl.js} +4 -4
  14. package/dist/gateway/static/root/assets/browser-automation-inputs-D8bZ9iz2.js +1 -0
  15. package/dist/gateway/static/root/assets/browser-automations-page-DMqDOJgO.js +3 -0
  16. package/dist/gateway/static/root/assets/browser-settings-page-KZStwhX7.js +3 -0
  17. package/dist/gateway/static/root/assets/button-aIC072nz.js +1 -0
  18. package/dist/gateway/static/root/assets/capabilities-page-DeJuO2rf.js +2 -0
  19. package/dist/gateway/static/root/assets/capabilities-settings-panel-DPxL_3Km.js +8 -0
  20. package/dist/gateway/static/root/assets/capability-header-actions-yfPUz5Wt.js +1 -0
  21. package/dist/gateway/static/root/assets/channels-Cp4F9zPz.js +1 -0
  22. package/dist/gateway/static/root/assets/{chat-terminal-dock-vb3kBSeI.js → chat-terminal-dock-Dlzn80cK.js} +2 -2
  23. package/dist/gateway/static/root/assets/computer-settings-page-BXhmUWbA.js +1 -0
  24. package/dist/gateway/static/root/assets/connector-service-page-B1oJCj74.js +1 -0
  25. package/dist/gateway/static/root/assets/connectors-page-Da_M7h3m.js +1 -0
  26. package/dist/gateway/static/root/assets/date-picker-DGjpqOKx.js +1 -0
  27. package/dist/gateway/static/root/assets/dependency-picker-BfWUD3LG.js +1 -0
  28. package/dist/gateway/static/root/assets/{desktop-pet-Bb-s29ag.js → desktop-pet-CPEi55Vt.js} +1 -1
  29. package/dist/gateway/static/root/assets/desktop-pet-settings-CmQ_H-nM.js +1 -0
  30. package/dist/gateway/static/root/assets/device-pairing-wizard-BeTjXc3C.js +1 -0
  31. package/dist/gateway/static/root/assets/{directory-picker-path-field-CkGfC105.js → directory-picker-path-field-CwT1LcLR.js} +1 -1
  32. package/dist/gateway/static/root/assets/dist-C3DSFZCi.js +1 -0
  33. package/dist/gateway/static/root/assets/{extension-debug-page-Cm0F3rcI.js → extension-debug-page-DX-hX_d0.js} +1 -1
  34. package/dist/gateway/static/root/assets/{extension-page-B72a-tnZ.js → extension-page-Cji87mN9.js} +1 -1
  35. package/dist/gateway/static/root/assets/extension-settings-page-BulzpwBD.js +1 -0
  36. package/dist/gateway/static/root/assets/file-archive-DanfQJNe.js +1 -0
  37. package/dist/gateway/static/root/assets/file-braces-BoAMI_k9.js +1 -0
  38. package/dist/gateway/static/root/assets/file-image-CDUPkZvG.js +1 -0
  39. package/dist/gateway/static/root/assets/gateway-settings-CIdEroWr.js +1 -0
  40. package/dist/gateway/static/root/assets/globe-DSSGFWFn.js +1 -0
  41. package/dist/gateway/static/root/assets/{highlighted-body-KQOG7T2V-BWjkqT5j.js → highlighted-body-KQOG7T2V-BgTqMa_d.js} +1 -1
  42. package/dist/gateway/static/root/assets/home-page-BSbYrVda.js +2 -0
  43. package/dist/gateway/static/root/assets/image-generation-api-BfPYnMoc.js +1 -0
  44. package/dist/gateway/static/root/assets/imports-page-DYSOfHfw.js +1 -0
  45. package/dist/gateway/static/root/assets/index-D2hEKnTM.js +267 -0
  46. package/dist/gateway/static/root/assets/index-SmKNPEmJ.css +1 -0
  47. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-Cf29ltoI.js → keyboard-shortcuts-settings-BwsGM6Yd.js} +1 -1
  48. package/dist/gateway/static/root/assets/loader-circle-CifKLtgG.js +1 -0
  49. package/dist/gateway/static/root/assets/local-app-workbench-page-K6UR6cAx.js +1 -0
  50. package/dist/gateway/static/root/assets/local-apps-page-gkdwtjDE.js +1 -0
  51. package/dist/gateway/static/root/assets/logs-page-BAQNYk0e.js +2 -0
  52. package/dist/gateway/static/root/assets/management-settings-CMVRLGox.js +1 -0
  53. package/dist/gateway/static/root/assets/{markdown-view-B35a4o1v.js → markdown-view-Ljt0bhfF.js} +6 -6
  54. package/dist/gateway/static/root/assets/{media-plugins-Bl1Xga_v.js → media-plugins-DQJXvbr_.js} +1 -1
  55. package/dist/gateway/static/root/assets/mermaid-MCJ5UELQ-Cx0bXBqu.js +1 -0
  56. package/dist/gateway/static/root/assets/note-detail-panel-1GCqp26U.js +5 -0
  57. package/dist/gateway/static/root/assets/note-image-lightbox-B7RA-WsY.js +1 -0
  58. package/dist/gateway/static/root/assets/notes-page-DnjlEdzM.js +8 -0
  59. package/dist/gateway/static/root/assets/page-context-capture-button-BAwI_3uh.js +1 -0
  60. package/dist/gateway/static/root/assets/personal-page-XoLrcR0U.js +1 -0
  61. package/dist/gateway/static/root/assets/personal-settings-panel-DzubCRqj.js +1 -0
  62. package/dist/gateway/static/root/assets/plugin-details-dialog-BjzIp3T5.js +1 -0
  63. package/dist/gateway/static/root/assets/popover-select-DGKUpVsz.js +1 -0
  64. package/dist/gateway/static/root/assets/{preview-open-alternatives-6XU-2lVI.js → preview-open-alternatives-2YjwlRHu.js} +1 -1
  65. package/dist/gateway/static/root/assets/product-open-page-Bfqez8Je.js +1 -0
  66. package/dist/gateway/static/root/assets/product-preview-content-D7wLwrqj.js +1 -0
  67. package/dist/gateway/static/root/assets/project-detail-page-1ueRCmXg.js +1 -0
  68. package/dist/gateway/static/root/assets/projects-page-CDQycMPo.js +1 -0
  69. package/dist/gateway/static/root/assets/remote-access-hub-YvVmZA4K.js +1 -0
  70. package/dist/gateway/static/root/assets/runtime-tools-settings-panel-DSsANtha.js +1 -0
  71. package/dist/gateway/static/root/assets/schema-form-vbhv4JE6.js +1 -0
  72. package/dist/gateway/static/root/assets/sessions-page-B3rPljgr.js +1 -0
  73. package/dist/gateway/static/root/assets/settings-advanced-gate-Ch20Ptzp.js +1 -0
  74. package/dist/gateway/static/root/assets/{settings-form-section-Cl0eF4hl.js → settings-form-section-4nn0sb6v.js} +1 -1
  75. package/dist/gateway/static/root/assets/{settings-page-1jcGeVtB.js → settings-page-_HB9FC08.js} +1 -1
  76. package/dist/gateway/static/root/assets/settings-shell-dialog-layer-BU3UuiJr.js +1 -0
  77. package/dist/gateway/static/root/assets/setup-status-panel-L1HHrvzi.js +1 -0
  78. package/dist/gateway/static/root/assets/share-preview-page-C4lC0W3d.js +2 -0
  79. package/dist/gateway/static/root/assets/shares-settings-DtHZ9z5K.js +1 -0
  80. package/dist/gateway/static/root/assets/skeleton-BI5TyibZ.js +1 -0
  81. package/dist/gateway/static/root/assets/{skill-api-BxCyuPhf.js → skill-api-CyO89DKl.js} +1 -1
  82. package/dist/gateway/static/root/assets/skill-reload-api-Drg356Pb.js +1 -0
  83. package/dist/gateway/static/root/assets/skills-page-XhCLHKlK.js +2 -0
  84. package/dist/gateway/static/root/assets/style-DTLpCnuA.js +7 -0
  85. package/dist/gateway/static/root/assets/{system-settings-panel-C9ejxax1.js → system-settings-panel-bSogz4S-.js} +1 -1
  86. package/dist/gateway/static/root/assets/task-detail-page-CSv2x4q-.js +2 -0
  87. package/dist/gateway/static/root/assets/{task-expandable-content-BMCvE36l.js → task-expandable-content-4s_FTl-9.js} +1 -1
  88. package/dist/gateway/static/root/assets/tracing-settings-page-CZ5XLQmX.js +1 -0
  89. package/dist/gateway/static/root/assets/tunnel-api-DOUyF9Ew.js +1 -0
  90. package/dist/gateway/static/root/assets/usage-page-Bv3fdfw1.js +1 -0
  91. package/dist/gateway/static/root/assets/use-autosave-D0MhLMD2.js +1 -0
  92. package/dist/gateway/static/root/assets/user-model-page-BD7WvhI0.js +2 -0
  93. package/dist/gateway/static/root/assets/{voice-api-key-field-Bk947X8N.js → voice-api-key-field-Ds_ADBQH.js} +1 -1
  94. package/dist/gateway/static/root/assets/work-discovery-overlay-CDJp2_l2.js +1 -0
  95. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-xQUvtVUU.js → workflow-run-setup-panel-CR4fRhZZ.js} +2 -2
  96. package/dist/gateway/static/root/assets/workflows-page-BeJw5liC.js +6 -0
  97. package/dist/gateway/static/root/assets/xopc-cloud-account-card-Di-oEpCt.js +1 -0
  98. package/dist/gateway/static/root/index.html +13 -7
  99. package/dist/package.js +1 -1
  100. package/dist/src/agent/background-review/prompts.d.ts +8 -0
  101. package/dist/src/agent/background-review/prompts.js +9 -2
  102. package/dist/src/agent/background-review/run-background-review.js +73 -11
  103. package/dist/src/agent/inbound/attachment-pipeline.d.ts +2 -0
  104. package/dist/src/agent/inbound/attachment-pipeline.js +10 -5
  105. package/dist/src/agent/tools/factory.js +15 -1
  106. package/dist/src/agent/tools/session-recall-tool.d.ts +3 -0
  107. package/dist/src/agent/tools/session-recall-tool.js +3 -0
  108. package/dist/src/agent/tools/session-search-tool.d.ts +3 -0
  109. package/dist/src/agent/tools/session-search-tool.js +20 -4
  110. package/dist/src/knowledge-memory/repository.d.ts +3 -1
  111. package/dist/src/knowledge-memory/repository.js +10 -3
  112. package/dist/src/memory-learning/forget-capture.d.ts +14 -0
  113. package/dist/src/memory-learning/forget-capture.js +100 -0
  114. package/dist/src/memory-learning/forgotten-history.d.ts +5 -0
  115. package/dist/src/memory-learning/forgotten-history.js +33 -0
  116. package/dist/src/memory-learning/work-capture.js +2 -1
  117. package/dist/src/providers/domestic-presets.d.ts +12 -5
  118. package/dist/src/providers/domestic-presets.js +27 -28
  119. package/dist/src/providers/presentation.js +7 -19
  120. package/dist/src/providers/setup/engine.js +2 -2
  121. package/dist/src/session/store.d.ts +1 -0
  122. package/dist/src/storage/sqlite/fts.d.ts +4 -0
  123. package/dist/src/storage/sqlite/fts.js +13 -4
  124. package/dist/src/storage/sqlite/session-repository.js +6 -3
  125. package/dist/src/storage/sqlite/transcript-repository.d.ts +1 -0
  126. package/dist/src/storage/sqlite/transcript-repository.js +14 -12
  127. package/dist/src/user-model/capture/semantic.d.ts +18 -1
  128. package/dist/src/user-model/capture/semantic.js +26 -1
  129. package/package.json +10 -10
  130. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-CtE1h2xU.js +0 -1
  131. package/dist/gateway/static/root/assets/agents-DAgFeHEb.js +0 -77
  132. package/dist/gateway/static/root/assets/app-management-settings-panel-B1qR8ElB.js +0 -1
  133. package/dist/gateway/static/root/assets/appearance-settings-GA819R2q.js +0 -1
  134. package/dist/gateway/static/root/assets/apps-page-DZptDZ7h.js +0 -1
  135. package/dist/gateway/static/root/assets/automations-workspace-qfEjk_ws.js +0 -6
  136. package/dist/gateway/static/root/assets/browser-automation-inputs-Bs-AkQ1q.js +0 -1
  137. package/dist/gateway/static/root/assets/browser-automations-page-D0Vbe1Q_.js +0 -3
  138. package/dist/gateway/static/root/assets/browser-settings-page-BXCNNpQd.js +0 -3
  139. package/dist/gateway/static/root/assets/capabilities-page-DMtxaYgt.js +0 -2
  140. package/dist/gateway/static/root/assets/capabilities-settings-panel-BlWrMG6Z.js +0 -8
  141. package/dist/gateway/static/root/assets/capability-header-actions-BMffrHhT.js +0 -1
  142. package/dist/gateway/static/root/assets/channels-C96r2Rqq.js +0 -1
  143. package/dist/gateway/static/root/assets/computer-settings-page-75SDQxQW.js +0 -1
  144. package/dist/gateway/static/root/assets/connector-service-page-DmJ9dIql.js +0 -1
  145. package/dist/gateway/static/root/assets/connectors-page-Bua_nhSH.js +0 -1
  146. package/dist/gateway/static/root/assets/date-picker-BEDH1AbM.js +0 -1
  147. package/dist/gateway/static/root/assets/dependency-picker-LwWL5fo8.js +0 -1
  148. package/dist/gateway/static/root/assets/desktop-pet-settings-Btt-DzyT.js +0 -1
  149. package/dist/gateway/static/root/assets/device-pairing-wizard-_UWo9-4N.js +0 -1
  150. package/dist/gateway/static/root/assets/ellipsis-0k4rZLoy.js +0 -1
  151. package/dist/gateway/static/root/assets/extension-settings-page-BEDAm_Ib.js +0 -1
  152. package/dist/gateway/static/root/assets/eye-CABVeTq0.js +0 -1
  153. package/dist/gateway/static/root/assets/files-Bw4SBGdM.js +0 -1
  154. package/dist/gateway/static/root/assets/folder-open-CyzJ19I9.js +0 -1
  155. package/dist/gateway/static/root/assets/gateway-settings-BapgXAhB.js +0 -1
  156. package/dist/gateway/static/root/assets/home-page-DNGjF6h4.js +0 -2
  157. package/dist/gateway/static/root/assets/image-generation-api-Bi1-Hvtr.js +0 -1
  158. package/dist/gateway/static/root/assets/imports-page-b4VDs6Bd.js +0 -1
  159. package/dist/gateway/static/root/assets/index-Cgd4fGVP.js +0 -267
  160. package/dist/gateway/static/root/assets/index-gYRNcY2Q.css +0 -1
  161. package/dist/gateway/static/root/assets/local-app-workbench-page-dgUxHhW8.js +0 -1
  162. package/dist/gateway/static/root/assets/local-apps-page-D3k9GjgF.js +0 -1
  163. package/dist/gateway/static/root/assets/logs-page-BUlU7t8l.js +0 -2
  164. package/dist/gateway/static/root/assets/management-settings-2L7XFZXc.js +0 -1
  165. package/dist/gateway/static/root/assets/mermaid-MCJ5UELQ-Bi62iXra.js +0 -1
  166. package/dist/gateway/static/root/assets/note-detail-panel-ogBu93h0.js +0 -5
  167. package/dist/gateway/static/root/assets/note-image-lightbox-Dxvo_WsE.js +0 -1
  168. package/dist/gateway/static/root/assets/notes-page-CNdoxzIZ.js +0 -8
  169. package/dist/gateway/static/root/assets/page-context-capture-button-Bq4Xpop5.js +0 -1
  170. package/dist/gateway/static/root/assets/personal-page-7P2leCsB.js +0 -1
  171. package/dist/gateway/static/root/assets/personal-settings-panel-D6n6TObP.js +0 -1
  172. package/dist/gateway/static/root/assets/plugin-details-dialog-JTxDbMI4.js +0 -1
  173. package/dist/gateway/static/root/assets/product-open-page-BpB0klIl.js +0 -1
  174. package/dist/gateway/static/root/assets/product-preview-content-DxQaoQew.js +0 -1
  175. package/dist/gateway/static/root/assets/project-detail-page-LilHE2OV.js +0 -1
  176. package/dist/gateway/static/root/assets/projects-page-D4Jxhuhq.js +0 -1
  177. package/dist/gateway/static/root/assets/remote-access-hub-Cy71CCQq.js +0 -1
  178. package/dist/gateway/static/root/assets/runtime-tools-settings-panel-CrbjrokA.js +0 -1
  179. package/dist/gateway/static/root/assets/schema-form-DITi2cne.js +0 -1
  180. package/dist/gateway/static/root/assets/sessions-page-D1THmRXE.js +0 -1
  181. package/dist/gateway/static/root/assets/settings-advanced-gate-CjRLXfoo.js +0 -1
  182. package/dist/gateway/static/root/assets/setup-status-panel-CFhDHkyK.js +0 -1
  183. package/dist/gateway/static/root/assets/share-preview-page-By4IKKgg.js +0 -2
  184. package/dist/gateway/static/root/assets/shares-settings-q2sa1VvF.js +0 -1
  185. package/dist/gateway/static/root/assets/skill-reload-api-CIHSQxr1.js +0 -1
  186. package/dist/gateway/static/root/assets/skills-page-BQaej_2C.js +0 -2
  187. package/dist/gateway/static/root/assets/style-Dt_oHNvB.js +0 -7
  188. package/dist/gateway/static/root/assets/task-detail-page-SipLlGGk.js +0 -2
  189. package/dist/gateway/static/root/assets/tracing-settings-page-bn9vnLrf.js +0 -1
  190. package/dist/gateway/static/root/assets/tunnel-api-BeTAD8BN.js +0 -1
  191. package/dist/gateway/static/root/assets/usage-page-BPuc6leN.js +0 -1
  192. package/dist/gateway/static/root/assets/use-autosave-DwcmmxWR.js +0 -1
  193. package/dist/gateway/static/root/assets/user-model-page-YWSqv_kR.js +0 -2
  194. package/dist/gateway/static/root/assets/work-discovery-overlay-mjj7w_wU.js +0 -1
  195. package/dist/gateway/static/root/assets/workflows-page-DbKRAEWP.js +0 -6
  196. package/dist/gateway/static/root/assets/xopc-cloud-account-card-C4jQM6Uo.js +0 -1
@@ -0,0 +1,100 @@
1
+ import { createLogger } from "../utils/logger/index.js";
2
+ import { init_logger } from "../utils/logger.js";
3
+ import { init_transaction, runSqliteWriteTransaction } from "../storage/sqlite/transaction.js";
4
+ import { createCollaborationRule, init_collaboration_rule_repository, listCollaborationRules } from "../storage/sqlite/collaboration-rule-repository.js";
5
+ import { canUseKnowledge } from "../knowledge-memory/usage-policy.js";
6
+ import { deleteKnowledgeItem, getKnowledgeItem, writeKnowledgeItem } from "../knowledge-memory/repository.js";
7
+ import "../knowledge-memory/index.js";
8
+ import { createHash } from "node:crypto";
9
+ //#region src/memory-learning/forget-capture.ts
10
+ init_logger();
11
+ init_transaction();
12
+ init_collaboration_rule_repository();
13
+ const log = createLogger("MemoryLearning:Forget");
14
+ /** Only grounded owner requests can forget derived knowledge visible in this scope. */
15
+ function applyKnowledgeDeletions(input) {
16
+ return runSqliteWriteTransaction((db) => {
17
+ const outputs = [];
18
+ for (const operation of input.interpretation.knowledgeDeletions ?? []) {
19
+ if (!operation.evidenceRefs.length || operation.evidenceRefs.some((ref) => !input.evidence.some((entry) => entry.ref === ref && entry.role === "user"))) continue;
20
+ if (!operation.evidence?.length || operation.evidence.some((claim) => !input.evidence.some((entry) => entry.ref === claim.ref && entry.role === "user" && entry.text.normalize("NFKC").toLowerCase().includes(claim.quote.normalize("NFKC").toLowerCase())))) continue;
21
+ let targets = operation.targetKnowledgeIds.flatMap((id) => {
22
+ const item = input.allowedTargetIds.includes(id) ? getKnowledgeItem(id) : void 0;
23
+ return item && item.recordClass === "memory" && canUseKnowledge(item, input.context) ? [item] : [];
24
+ });
25
+ const requestedRetention = operation.retained ?? [];
26
+ const invalidTargets = new Set(requestedRetention.filter((part) => {
27
+ const item = targets.find((target) => target.id === part.targetKnowledgeId);
28
+ return !item || !part.spans.length || part.spans.some((span) => !span.trim() || !item.content.includes(span));
29
+ }).map((part) => part.targetKnowledgeId));
30
+ if (invalidTargets.size) log.warn({
31
+ phase: "forget_retention",
32
+ count: invalidTargets.size,
33
+ conversationId: input.context.conversationId
34
+ }, "Ungrounded retained spans rejected; affected knowledge was preserved");
35
+ targets = targets.filter((item) => !invalidTargets.has(item.id));
36
+ const retained = requestedRetention.filter((part) => targets.some((item) => item.id === part.targetKnowledgeId));
37
+ for (const part of retained) {
38
+ const item = targets.find((target) => target.id === part.targetKnowledgeId);
39
+ const content = [...new Set(part.spans)].join(";");
40
+ const links = db.prepare(`SELECT evidence_id, content_hash, consent_receipt_id FROM knowledge_evidence_links
41
+ WHERE knowledge_id = ?`).all(item.id);
42
+ const saved = writeKnowledgeItem({
43
+ ...item,
44
+ content,
45
+ canonicalKey: `${item.canonicalKey}:retained:${createHash("sha256").update(content).digest("hex").slice(0, 16)}`,
46
+ evidence: links.map((link) => ({
47
+ id: link.evidence_id,
48
+ contentHash: link.content_hash ?? void 0,
49
+ consentReceiptId: link.consent_receipt_id ?? void 0
50
+ })),
51
+ source: {
52
+ ...item.source,
53
+ evidenceQuotes: void 0,
54
+ retainedFromKnowledgeId: item.id
55
+ },
56
+ replaceExisting: false
57
+ });
58
+ if (!saved.item) throw new Error("Unable to retain unforgotten knowledge; deletion was rolled back.");
59
+ outputs.push({
60
+ candidateKey: saved.item.canonicalKey,
61
+ objectType: "knowledge",
62
+ objectId: saved.item.id,
63
+ outcome: "created"
64
+ });
65
+ }
66
+ const forgottenEntries = targets.flatMap((item) => db.prepare(`SELECT DISTINCT e.conversation_id, e.message_id
67
+ FROM context_evidence e WHERE e.conversation_id IS NOT NULL AND e.message_id IS NOT NULL
68
+ AND (e.evidence_id IN (SELECT evidence_id FROM knowledge_evidence_links WHERE knowledge_id=?)
69
+ OR e.message_id IN (SELECT value FROM knowledge_revisions r, json_each(r.source_json, '$.evidenceRefs')
70
+ WHERE r.knowledge_id=?))`).all(item.id, item.id).flatMap((entry) => [`${entry.conversation_id}:${entry.message_id}`, `${entry.conversation_id}:*`]));
71
+ for (const item of targets) {
72
+ deleteKnowledgeItem(item.id, Date.now(), { includeRelated: false });
73
+ outputs.push({
74
+ candidateKey: item.id,
75
+ objectType: "knowledge",
76
+ objectId: item.id,
77
+ outcome: "rejected"
78
+ });
79
+ }
80
+ for (const scope of new Map(targets.map((item) => [JSON.stringify(item.scope), item.scope])).values()) {
81
+ if (scope.type === "agent") continue;
82
+ if (!listCollaborationRules().some((rule) => rule.category === "boundary" && rule.status === "active" && JSON.stringify(rule.scope) === JSON.stringify(scope) && rule.statement === operation.boundary && forgottenEntries.every((entry) => Array.isArray(rule.conditions.forgottenHistoryEntries) && rule.conditions.forgottenHistoryEntries.includes(entry)))) createCollaborationRule({
83
+ category: "boundary",
84
+ priority: 0,
85
+ scope,
86
+ conditions: {
87
+ enforcementLevel: "prompt",
88
+ forgottenHistoryEntries: [...new Set(forgottenEntries)],
89
+ reread: operation.reread
90
+ },
91
+ statement: operation.boundary,
92
+ status: "active"
93
+ });
94
+ }
95
+ }
96
+ return outputs;
97
+ });
98
+ }
99
+ //#endregion
100
+ export { applyKnowledgeDeletions };
@@ -0,0 +1,5 @@
1
+ import type { CaptureScopeContext } from '../user-model/capture/executor.js';
2
+ /** A later source-specific read request does not authorize saving forgotten facts again. */
3
+ export declare function explicitlyReadsOriginalHistory(text: string): boolean;
4
+ export declare function forgottenHistoryEntries(context: CaptureScopeContext, userText?: string): Set<string>;
5
+ export declare const FORGOTTEN_HISTORY_EXCERPT = "[This entry supported information the user asked to forget. Automatic recall is withheld. A later explicit request to re-read original records is required; do not infer the hidden values.]";
@@ -0,0 +1,33 @@
1
+ import { isXopcDatabaseOpen } from "../storage/sqlite/connection.js";
2
+ import { init_collaboration_rule_repository, listCollaborationRules } from "../storage/sqlite/collaboration-rule-repository.js";
3
+ import { init_sqlite } from "../storage/sqlite/index.js";
4
+ //#region src/memory-learning/forgotten-history.ts
5
+ init_sqlite();
6
+ init_collaboration_rule_repository();
7
+ /** A later source-specific read request does not authorize saving forgotten facts again. */
8
+ function explicitlyReadsOriginalHistory(text) {
9
+ if (/(?:引文|引用|改写|措辞|不是要|quoted|rephrase)/iu.test(text)) return false;
10
+ if (/(?:不要|别|不必|禁止)\s*(?:再|去)?(?:恢复|查阅|查出|读取|找回|查)|(?:do not|don't)\s+(?:read|look|recover|retrieve|restore)/iu.test(text)) return false;
11
+ return /(?:原始|旧|先前|过去).{0,8}(?:记录|对话|原文)|(?:original|old|previous|past).{0,20}(?:record|conversation|transcript|history)/iu.test(text) && /(?:^|\n)\s*(?:(?:请|麻烦|本次|这次|现在|please|this time)[,,\s]*){0,3}[^。\n!?]{0,150}(?:恢复|查阅|查出|读取|找回|read|look up|retrieve|recover|restore)/iu.test(text);
12
+ }
13
+ function forgottenHistoryEntries(context, userText = "") {
14
+ if (!isXopcDatabaseOpen()) return /* @__PURE__ */ new Set();
15
+ const entries = /* @__PURE__ */ new Set();
16
+ for (const rule of listCollaborationRules()) {
17
+ if (rule.status !== "active" || rule.category !== "boundary") continue;
18
+ if (!(rule.scope.type === "global" || rule.scope.id === {
19
+ agent: context.agentId,
20
+ workspace: context.workspaceId,
21
+ project: context.projectId,
22
+ session: context.conversationId
23
+ }[rule.scope.type]) || !Array.isArray(rule.conditions.forgottenHistoryEntries)) continue;
24
+ const binding = rule.conditions.reread;
25
+ const property = binding?.property === "date_time" ? /日期|时间|哪天|哪日|几点|日程|\b(?:date|time|when|schedule)\b/iu : binding?.property === "price" ? /票价|报价|价格|总价|金额|费用|花费|价钱|\b(?:price|cost|amount)\b/iu : void 0;
26
+ if (typeof binding?.subject === "string" && binding.subject.length > 0 && property && userText.split(/[。;;,,!?!?\n]/u).some((clause) => explicitlyReadsOriginalHistory(clause) && clause.normalize("NFKC").toLowerCase().includes(binding.subject.normalize("NFKC").toLowerCase()) && property.test(clause))) continue;
27
+ for (const entry of rule.conditions.forgottenHistoryEntries) if (typeof entry === "string") entries.add(entry);
28
+ }
29
+ return entries;
30
+ }
31
+ const FORGOTTEN_HISTORY_EXCERPT = "[This entry supported information the user asked to forget. Automatic recall is withheld. A later explicit request to re-read original records is required; do not infer the hidden values.]";
32
+ //#endregion
33
+ export { FORGOTTEN_HISTORY_EXCERPT, explicitlyReadsOriginalHistory, forgottenHistoryEntries };
@@ -112,7 +112,8 @@ function applyWorkCandidates(input) {
112
112
  replaceExisting: true,
113
113
  source: {
114
114
  extractor: "work-synthesis",
115
- evidenceRefs: candidate.evidence.map((claim) => claim.ref),
115
+ evidenceRefs: [...new Set(candidate.evidence.map((claim) => claim.ref))],
116
+ evidenceQuotes: candidate.evidence,
116
117
  ...input.source ? {
117
118
  sourceInstanceId: input.source.instanceId,
118
119
  sourceItemId: input.source.itemId,
@@ -390,8 +390,15 @@ export declare const DOMESTIC_PROVIDER_PRESETS: readonly [{
390
390
  readonly baseUrl: "https://api.xiaomimimo.com/v1";
391
391
  }];
392
392
  readonly defaultBaseUrlPreset: "api";
393
- readonly defaultModel: "mimo-v2.5-pro";
394
- readonly models: DomesticProviderModelPreset[];
393
+ readonly defaultModel: "mimo-v2.6-pro";
394
+ readonly models: [...DomesticProviderModelPreset[], {
395
+ readonly id: "mimo-v2.6-pro-ultraspeed";
396
+ readonly name: "MiMo V2.6 Pro UltraSpeed";
397
+ readonly contextWindow: 1048576;
398
+ readonly maxTokens: 131072;
399
+ readonly reasoning: true;
400
+ readonly input: ["text", "image"];
401
+ }];
395
402
  readonly aliases: ["xiaomi", "mimo", "xiaomimimo"];
396
403
  readonly quirks: ["Some MiMo plans document api-key style auth; keep auth header behavior configurable if needed."];
397
404
  }, {
@@ -409,7 +416,7 @@ export declare const DOMESTIC_PROVIDER_PRESETS: readonly [{
409
416
  readonly baseUrl: "https://token-plan-cn.xiaomimimo.com/v1";
410
417
  }];
411
418
  readonly defaultBaseUrlPreset: "cn";
412
- readonly defaultModel: "mimo-v2.5-pro";
419
+ readonly defaultModel: "mimo-v2.6-pro";
413
420
  readonly models: DomesticProviderModelPreset[];
414
421
  readonly aliases: ["xiaomi token plan cn", "mimo token plan cn"];
415
422
  }, {
@@ -427,7 +434,7 @@ export declare const DOMESTIC_PROVIDER_PRESETS: readonly [{
427
434
  readonly baseUrl: "https://token-plan-ams.xiaomimimo.com/v1";
428
435
  }];
429
436
  readonly defaultBaseUrlPreset: "ams";
430
- readonly defaultModel: "mimo-v2.5-pro";
437
+ readonly defaultModel: "mimo-v2.6-pro";
431
438
  readonly models: DomesticProviderModelPreset[];
432
439
  readonly aliases: ["xiaomi token plan ams", "mimo token plan ams"];
433
440
  }, {
@@ -445,7 +452,7 @@ export declare const DOMESTIC_PROVIDER_PRESETS: readonly [{
445
452
  readonly baseUrl: "https://token-plan-sgp.xiaomimimo.com/v1";
446
453
  }];
447
454
  readonly defaultBaseUrlPreset: "sgp";
448
- readonly defaultModel: "mimo-v2.5-pro";
455
+ readonly defaultModel: "mimo-v2.6-pro";
449
456
  readonly models: DomesticProviderModelPreset[];
450
457
  readonly aliases: ["xiaomi token plan sgp", "mimo token plan sgp"];
451
458
  }, {
@@ -42,29 +42,21 @@ const STEPFUN_MODELS = [
42
42
  input: ["text"]
43
43
  }
44
44
  ];
45
- const MIMO_MODELS = [
46
- {
47
- id: "mimo-v2.5-pro",
48
- name: "MiMo V2.5 Pro",
49
- contextWindow: 1e6,
50
- reasoning: true,
51
- input: ["text"]
52
- },
53
- {
54
- id: "mimo-v2.5-pro-ultraspeed",
55
- name: "MiMo V2.5 Pro UltraSpeed",
56
- contextWindow: 1e6,
57
- reasoning: true,
58
- input: ["text"]
59
- },
60
- {
61
- id: "mimo-v2.5",
62
- name: "MiMo V2.5",
63
- contextWindow: 1e6,
64
- reasoning: true,
65
- input: ["text", "image"]
66
- }
67
- ];
45
+ const MIMO_MODELS = [{
46
+ id: "mimo-v2.6-pro",
47
+ name: "MiMo V2.6 Pro",
48
+ contextWindow: 1048576,
49
+ maxTokens: 131072,
50
+ reasoning: true,
51
+ input: ["text", "image"]
52
+ }, {
53
+ id: "mimo-v2.6-flash",
54
+ name: "MiMo V2.6 Flash",
55
+ contextWindow: 1048576,
56
+ maxTokens: 131072,
57
+ reasoning: true,
58
+ input: ["text", "image"]
59
+ }];
68
60
  const MINIMAX_MODELS = [
69
61
  {
70
62
  id: "MiniMax-M3",
@@ -527,8 +519,15 @@ const DOMESTIC_PROVIDER_PRESETS = [
527
519
  baseUrl: "https://api.xiaomimimo.com/v1"
528
520
  }],
529
521
  defaultBaseUrlPreset: "api",
530
- defaultModel: "mimo-v2.5-pro",
531
- models: MIMO_MODELS,
522
+ defaultModel: "mimo-v2.6-pro",
523
+ models: [...MIMO_MODELS, {
524
+ id: "mimo-v2.6-pro-ultraspeed",
525
+ name: "MiMo V2.6 Pro UltraSpeed",
526
+ contextWindow: 1048576,
527
+ maxTokens: 131072,
528
+ reasoning: true,
529
+ input: ["text", "image"]
530
+ }],
532
531
  aliases: [
533
532
  "xiaomi",
534
533
  "mimo",
@@ -551,7 +550,7 @@ const DOMESTIC_PROVIDER_PRESETS = [
551
550
  baseUrl: "https://token-plan-cn.xiaomimimo.com/v1"
552
551
  }],
553
552
  defaultBaseUrlPreset: "cn",
554
- defaultModel: "mimo-v2.5-pro",
553
+ defaultModel: "mimo-v2.6-pro",
555
554
  models: MIMO_MODELS,
556
555
  aliases: ["xiaomi token plan cn", "mimo token plan cn"]
557
556
  },
@@ -570,7 +569,7 @@ const DOMESTIC_PROVIDER_PRESETS = [
570
569
  baseUrl: "https://token-plan-ams.xiaomimimo.com/v1"
571
570
  }],
572
571
  defaultBaseUrlPreset: "ams",
573
- defaultModel: "mimo-v2.5-pro",
572
+ defaultModel: "mimo-v2.6-pro",
574
573
  models: MIMO_MODELS,
575
574
  aliases: ["xiaomi token plan ams", "mimo token plan ams"]
576
575
  },
@@ -589,7 +588,7 @@ const DOMESTIC_PROVIDER_PRESETS = [
589
588
  baseUrl: "https://token-plan-sgp.xiaomimimo.com/v1"
590
589
  }],
591
590
  defaultBaseUrlPreset: "sgp",
592
- defaultModel: "mimo-v2.5-pro",
591
+ defaultModel: "mimo-v2.6-pro",
593
592
  models: MIMO_MODELS,
594
593
  aliases: ["xiaomi token plan sgp", "mimo token plan sgp"]
595
594
  },
@@ -54,7 +54,7 @@ const PROVIDER_HINTS = {
54
54
  deepseek: "DeepSeek V4 models with strong price/performance.",
55
55
  moonshotai: "Kimi models through Moonshot International.",
56
56
  "moonshotai-cn": "Kimi models through Moonshot China.",
57
- "kimi-coding": "Kimi dedicated coding endpoint with Anthropic-compatible requests.",
57
+ "kimi-coding": "Kimi dedicated coding endpoint with OpenAI-compatible Chat Completions requests.",
58
58
  stepfun: "StepFun OpenAI-compatible endpoint.",
59
59
  "stepfun-cn": "StepFun China OpenAI-compatible endpoint.",
60
60
  "stepfun-intl": "StepFun international OpenAI-compatible endpoint.",
@@ -184,25 +184,13 @@ const RECOMMENDED_MODEL_PATTERNS = {
184
184
  /^step-3\.5-flash$/i
185
185
  ],
186
186
  xiaomi: [
187
- /^mimo-v2\.5-pro$/i,
188
- /^mimo-v2\.5-pro-ultraspeed$/i,
189
- /^mimo-v2\.5$/i
190
- ],
191
- "xiaomi-token-plan-cn": [
192
- /^mimo-v2\.5-pro$/i,
193
- /^mimo-v2\.5-pro-ultraspeed$/i,
194
- /^mimo-v2\.5$/i
195
- ],
196
- "xiaomi-token-plan-ams": [
197
- /^mimo-v2\.5-pro$/i,
198
- /^mimo-v2\.5-pro-ultraspeed$/i,
199
- /^mimo-v2\.5$/i
200
- ],
201
- "xiaomi-token-plan-sgp": [
202
- /^mimo-v2\.5-pro$/i,
203
- /^mimo-v2\.5-pro-ultraspeed$/i,
204
- /^mimo-v2\.5$/i
187
+ /^mimo-v2\.6-pro$/i,
188
+ /^mimo-v2\.6-pro-ultraspeed$/i,
189
+ /^mimo-v2\.6-flash$/i
205
190
  ],
191
+ "xiaomi-token-plan-cn": [/^mimo-v2\.6-pro$/i, /^mimo-v2\.6-flash$/i],
192
+ "xiaomi-token-plan-ams": [/^mimo-v2\.6-pro$/i, /^mimo-v2\.6-flash$/i],
193
+ "xiaomi-token-plan-sgp": [/^mimo-v2\.6-pro$/i, /^mimo-v2\.6-flash$/i],
206
194
  "ant-ling": [
207
195
  /^Ling-2\.6-1T$/i,
208
196
  /^Ling-2\.6-flash$/i,
@@ -20,8 +20,8 @@ const preferred = {
20
20
  reasoning: ["advanced", "auto"]
21
21
  },
22
22
  "xiaomi-token-plan-cn": {
23
- fast: ["mimo-v2.5", "mimo-v2.5-pro"],
24
- reasoning: ["mimo-v2.5-pro", "mimo-v2.5"]
23
+ fast: ["mimo-v2.6-flash", "mimo-v2.6-pro"],
24
+ reasoning: ["mimo-v2.6-pro", "mimo-v2.6-flash"]
25
25
  }
26
26
  };
27
27
  const uses = [
@@ -209,6 +209,7 @@ export declare class SessionStore {
209
209
  limit?: number;
210
210
  beforeSeq?: number;
211
211
  orderBySeq?: boolean;
212
+ matchMode?: 'keyword' | 'phrase';
212
213
  }): import("../storage/sqlite/transcript-repository.js").SessionTranscriptRecallMatch[];
213
214
  exportSession(key: string, format: ExportFormat): Promise<string>;
214
215
  importSessionExport(targetKey: string, jsonContent: string): Promise<{
@@ -1,6 +1,10 @@
1
1
  /** Quote a user query for FTS5 phrase/prefix-safe matching. */
2
2
  export declare function escapeFts5Query(raw: string): string;
3
3
  /** Build a syntax-safe, recall-oriented query for natural-language memory search. */
4
+ export declare function sessionSearchTerms(raw: string): string[];
4
5
  export declare function buildFts5SearchQuery(raw: string): string;
6
+ /** unicode61 does not split Han words; use literal substrings for those terms. */
7
+ export declare function sessionHanSearchTerms(raw: string): string[];
8
+ export declare function escapeSqlLike(raw: string): string;
5
9
  /** Normalize FTS5 BM25 ranks, where a more-negative rank is a better match. */
6
10
  export declare function fts5RankToScore(rank: number, bestRank: number, worstRank: number): number;
@@ -7,10 +7,19 @@ function escapeFts5Query(raw) {
7
7
  return `"${trimmed.replace(/"/g, "\"\"")}"`;
8
8
  }
9
9
  /** Build a syntax-safe, recall-oriented query for natural-language memory search. */
10
- function buildFts5SearchQuery(raw) {
10
+ function sessionSearchTerms(raw) {
11
11
  const terms = raw.normalize("NFKC").match(/[\p{L}\p{N}_]+/gu)?.map((term) => term.toLowerCase()).filter((term) => term.length > 1 && !FTS_SEARCH_STOP_WORDS.has(term));
12
- if (!terms?.length) return escapeFts5Query(raw);
13
- return [...new Set(terms)].slice(0, 12).map((term) => escapeFts5Query(term)).join(" OR ");
12
+ return [...new Set(terms?.length ? terms : [raw.trim()])].slice(0, 12);
13
+ }
14
+ function buildFts5SearchQuery(raw) {
15
+ return sessionSearchTerms(raw).map(escapeFts5Query).join(" OR ");
16
+ }
17
+ /** unicode61 does not split Han words; use literal substrings for those terms. */
18
+ function sessionHanSearchTerms(raw) {
19
+ return sessionSearchTerms(raw).filter((term) => /\p{Script=Han}/u.test(term));
20
+ }
21
+ function escapeSqlLike(raw) {
22
+ return raw.replaceAll("\\", "\\\\").replaceAll("%", "\\%").replaceAll("_", "\\_");
14
23
  }
15
24
  /** Normalize FTS5 BM25 ranks, where a more-negative rank is a better match. */
16
25
  function fts5RankToScore(rank, bestRank, worstRank) {
@@ -61,4 +70,4 @@ var init_fts = __esmMin((() => {
61
70
  }));
62
71
  //#endregion
63
72
  init_fts();
64
- export { buildFts5SearchQuery, escapeFts5Query, fts5RankToScore, init_fts };
73
+ export { buildFts5SearchQuery, escapeFts5Query, escapeSqlLike, fts5RankToScore, init_fts, sessionHanSearchTerms, sessionSearchTerms };
@@ -10,7 +10,7 @@ import { buildGlobalSessionStats, init_row_mappers, metadataToSessionInsert, ses
10
10
  import { cancelConnectionObjective, init_connection_wait_repository } from "./connection-wait-repository.js";
11
11
  import { init_changes, notifyUserContextChange } from "../../user-context/changes.js";
12
12
  import { SESSION_PURPOSE_SQL, SESSION_SOURCE_SQL, init_session_identity_sql } from "./session-identity-sql.js";
13
- import { buildFts5SearchQuery, init_fts } from "./fts.js";
13
+ import { buildFts5SearchQuery, escapeSqlLike, init_fts, sessionHanSearchTerms } from "./fts.js";
14
14
  import { SESSION_COLUMNS, SESSION_FROM_JOIN, getSessionMetadata, init_session_read_repository, readSessionRow } from "./session-read-repository.js";
15
15
  import { randomUUID } from "node:crypto";
16
16
  //#region src/storage/sqlite/session-repository.ts
@@ -166,14 +166,17 @@ function listSessionMetadata(query = {}) {
166
166
  if (query.search?.trim()) {
167
167
  const rawSearch = query.search.trim();
168
168
  const like = `%${rawSearch.toLowerCase()}%`;
169
+ const hanTerms = sessionHanSearchTerms(rawSearch);
169
170
  conditions.push(`(s.conversation_id IN (
170
171
  SELECT conversation_id FROM transcript_fts WHERE transcript_fts MATCH ?
171
- ) OR LOWER(s.conversation_id) LIKE ?
172
+ ) ${hanTerms.length ? `OR s.conversation_id IN (
173
+ SELECT conversation_id FROM transcript_fts WHERE ${hanTerms.map(() => "content LIKE ? ESCAPE '\\'").join(" OR ")}
174
+ )` : ""} OR LOWER(s.conversation_id) LIKE ?
172
175
  OR LOWER(COALESCE(s.name, '')) LIKE ?
173
176
  OR LOWER(s.source_channel) LIKE ?
174
177
  OR LOWER(s.source_chat_id) LIKE ?
175
178
  OR LOWER(s.tags_json) LIKE ?)`);
176
- params.push(buildFts5SearchQuery(rawSearch), like, like, like, like, like);
179
+ params.push(buildFts5SearchQuery(rawSearch), ...hanTerms.map((term) => `%${escapeSqlLike(term)}%`), like, like, like, like, like);
177
180
  }
178
181
  const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
179
182
  const sortColumn = sessionSortColumn(query.sortBy);
@@ -34,6 +34,7 @@ export declare function searchSessionTranscript(conversationId: string, query: s
34
34
  limit?: number;
35
35
  beforeSeq?: number;
36
36
  orderBySeq?: boolean;
37
+ matchMode?: 'keyword' | 'phrase';
37
38
  }): SessionTranscriptRecallMatch[];
38
39
  export declare function loadTranscriptRowsForSession(conversationId: string): TranscriptStoredRow[];
39
40
  export declare function loadTranscriptHistoryRowsForSession(conversationId: string): TranscriptStoredRow[];
@@ -3,7 +3,7 @@ import { getSqliteDatabase, init_transaction, runSqliteWriteTransaction } from "
3
3
  import { readCurrentTranscriptId } from "./session-instance-repository.js";
4
4
  import { buildSessionContextForLlm, init_session_context_for_llm, isRuntimeOnlyTranscriptMessage } from "../../session/session-context-for-llm.js";
5
5
  import { classifyStoredRow, estimateTokensFromMessages, extractFtsContent, init_row_mappers, transcriptEntryRowToStoredRow } from "./row-mappers.js";
6
- import { escapeFts5Query, init_fts } from "./fts.js";
6
+ import { buildFts5SearchQuery, escapeFts5Query, escapeSqlLike, init_fts, sessionHanSearchTerms } from "./fts.js";
7
7
  import { getCurrentTranscriptId, init_session_repository } from "./session-repository.js";
8
8
  import { createHash, randomUUID } from "node:crypto";
9
9
  //#region src/storage/sqlite/transcript-repository.ts
@@ -167,25 +167,27 @@ function searchSessionTranscript(conversationId, query, options = {}) {
167
167
  const limit = Math.min(20, Math.max(1, options.limit ?? 8));
168
168
  const beforeSeq = options.beforeSeq ?? Number.MAX_SAFE_INTEGER;
169
169
  const db = getSqliteDatabase();
170
+ const phrase = options.matchMode !== "keyword";
171
+ const hanTerms = phrase ? [] : sessionHanSearchTerms(normalized);
170
172
  const ftsRows = db.prepare(`SELECT e.entry_id, e.seq, e.role, e.created_at, f.content
171
173
  FROM transcript_fts f
172
174
  JOIN transcript_entries e
173
175
  ON e.transcript_id = f.transcript_id AND e.entry_id = f.entry_id
174
- WHERE transcript_fts MATCH ?
176
+ WHERE (transcript_fts MATCH ?)
175
177
  AND f.transcript_id = ?
176
178
  AND e.entry_kind <> 'compaction'
177
179
  AND e.seq < ?
178
180
  ORDER BY ${options.orderBySeq ? "e.seq DESC" : "bm25(transcript_fts), e.seq DESC"}
179
- LIMIT ?`).all(escapeFts5Query(normalized), transcriptId, beforeSeq, limit);
180
- const escapedLike = normalized.replaceAll("\\", "\\\\").replaceAll("%", "\\%").replaceAll("_", "\\_");
181
- const literalRows = db.prepare(`SELECT entry_id, seq, role, created_at, payload_json AS content
182
- FROM transcript_entries
183
- WHERE transcript_id = ?
184
- AND entry_kind <> 'compaction'
185
- AND seq < ?
186
- AND payload_json LIKE ? ESCAPE '\\'
187
- ORDER BY seq DESC
188
- LIMIT ?`).all(transcriptId, beforeSeq, `%${escapedLike}%`, limit);
181
+ LIMIT ?`).all(phrase ? escapeFts5Query(normalized) : buildFts5SearchQuery(normalized), transcriptId, beforeSeq, limit);
182
+ const literalTerms = [normalized, ...hanTerms];
183
+ const literalRows = phrase ? db.prepare(`SELECT entry_id, seq, role, created_at, payload_json AS content
184
+ FROM transcript_entries WHERE transcript_id = ? AND entry_kind <> 'compaction' AND seq < ?
185
+ AND payload_json LIKE ? ESCAPE '\\' ORDER BY seq DESC LIMIT ?`).all(transcriptId, beforeSeq, `%${escapeSqlLike(normalized)}%`, limit) : db.prepare(`SELECT e.entry_id, e.seq, e.role, e.created_at, f.content
186
+ FROM transcript_fts f JOIN transcript_entries e
187
+ ON e.transcript_id = f.transcript_id AND e.entry_id = f.entry_id
188
+ WHERE f.transcript_id = ? AND e.entry_kind <> 'compaction' AND e.seq < ?
189
+ AND (${literalTerms.map(() => "f.content LIKE ? ESCAPE '\\'").join(" OR ")})
190
+ ORDER BY e.seq DESC LIMIT ?`).all(transcriptId, beforeSeq, ...literalTerms.map((term) => `%${escapeSqlLike(term)}%`), limit);
189
191
  const seen = /* @__PURE__ */ new Set();
190
192
  const matches = [...ftsRows, ...literalRows].flatMap((row) => {
191
193
  const result = row;
@@ -34,6 +34,23 @@ export interface ParsedCollaborationRuleCandidate {
34
34
  }
35
35
  export interface UserModelInterpretation {
36
36
  knowledge?: WorkCandidate[];
37
+ knowledgeDeletions?: Array<{
38
+ targetKnowledgeIds: string[];
39
+ boundary: string;
40
+ reread?: {
41
+ subject: string;
42
+ property: 'date_time' | 'price';
43
+ };
44
+ evidenceRefs: string[];
45
+ evidence: Array<{
46
+ ref: string;
47
+ quote: string;
48
+ }>;
49
+ retained?: Array<{
50
+ targetKnowledgeId: string;
51
+ spans: string[];
52
+ }>;
53
+ }>;
37
54
  intent: UserModelCaptureIntent;
38
55
  assertions: ParsedAssertionOperation[];
39
56
  goals?: ParsedGoalCandidate[];
@@ -48,4 +65,4 @@ export interface InterpretationParseFailure {
48
65
  code: string;
49
66
  }>;
50
67
  }
51
- export declare function parseUserModelInterpretation(raw: string, evidence: CaptureEvidence[], allowedTargetIds?: string[], onInvalid?: (failure: InterpretationParseFailure) => void): UserModelInterpretation | null;
68
+ export declare function parseUserModelInterpretation(raw: string, evidence: CaptureEvidence[], allowedTargetIds?: string[], onInvalid?: (failure: InterpretationParseFailure) => void, allowedKnowledgeIds?: string[]): UserModelInterpretation | null;
@@ -154,6 +154,18 @@ const CollaborationRuleSchema = z.object({
154
154
  }).merge(GroundingSchema).strict();
155
155
  const InterpretationSchema = z.object({
156
156
  knowledge: z.array(WorkCandidateSchema).max(8).default([]),
157
+ knowledgeDeletions: z.array(z.object({
158
+ targetKnowledgeIds: z.array(z.string().min(1)).min(1).max(16),
159
+ boundary: z.string().min(4).max(600),
160
+ reread: z.object({
161
+ subject: z.string().min(1).max(160),
162
+ property: z.enum(["date_time", "price"])
163
+ }).strict().optional(),
164
+ retained: z.array(z.object({
165
+ targetKnowledgeId: z.string().min(1),
166
+ spans: z.array(z.string().min(1).max(600)).min(1).max(8)
167
+ }).strict()).max(8).default([])
168
+ }).merge(GroundingSchema).strict()).max(4).default([]),
157
169
  intent: z.enum(USER_MODEL_CAPTURE_INTENTS),
158
170
  assertions: z.array(AssertionOperationSchema).max(8),
159
171
  goals: z.array(GoalSchema).max(4).default([]),
@@ -184,7 +196,7 @@ function groundedEvidenceRefs(item, evidenceByRef) {
184
196
  return source?.role === "user" && comparable(source.text).includes(comparable(claim.quote));
185
197
  }) ? [...new Set(item.evidence.map((claim) => claim.ref))] : void 0;
186
198
  }
187
- function parseUserModelInterpretation(raw, evidence, allowedTargetIds = [], onInvalid) {
199
+ function parseUserModelInterpretation(raw, evidence, allowedTargetIds = [], onInvalid, allowedKnowledgeIds = []) {
188
200
  if (!raw.trim()) {
189
201
  onInvalid?.({
190
202
  reason: "empty_output",
@@ -296,6 +308,19 @@ function parseUserModelInterpretation(raw, evidence, allowedTargetIds = [], onIn
296
308
  });
297
309
  return {
298
310
  knowledge: parsed.knowledge,
311
+ knowledgeDeletions: parsed.knowledgeDeletions.flatMap((item) => {
312
+ const evidenceRefs = groundedEvidenceRefs(item, evidenceByRef);
313
+ if (!evidenceRefs || (item.intent ?? parsed.intent) !== "forget") return [];
314
+ const targetKnowledgeIds = [...new Set(item.targetKnowledgeIds.filter((id) => allowedKnowledgeIds.includes(id)))];
315
+ return targetKnowledgeIds.length ? [{
316
+ targetKnowledgeIds,
317
+ boundary: item.boundary,
318
+ evidenceRefs,
319
+ evidence: item.evidence,
320
+ retained: item.retained.filter((retained) => targetKnowledgeIds.includes(retained.targetKnowledgeId)),
321
+ ...item.reread && item.evidence.some((claim) => claim.quote.includes(item.reread.subject)) ? { reread: item.reread } : {}
322
+ }] : [];
323
+ }),
299
324
  intent: parsed.intent,
300
325
  assertions,
301
326
  goals,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xopcai/xopc",
3
- "version": "0.0.408",
3
+ "version": "0.0.410",
4
4
  "description": "Local-first personal AI with Ada, task delegation, files, projects, workflows, and automations. Use cloud or local models.",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",
@@ -69,13 +69,13 @@
69
69
  "@composio/core": "0.21.0",
70
70
  "@dicebear/collection": "9.4.2",
71
71
  "@dicebear/core": "9.4.2",
72
- "@earendil-works/chord": "1.1.0",
73
- "@earendil-works/pi-agent-core": "1.1.0",
74
- "@earendil-works/pi-ai": "1.1.0",
75
- "@earendil-works/pi-codemode": "1.1.0",
76
- "@earendil-works/pi-coding-agent": "1.1.0",
77
- "@earendil-works/pi-mcp": "1.1.0",
78
- "@earendil-works/pi-tui": "1.1.0",
72
+ "@earendil-works/chord": "1.4.0",
73
+ "@earendil-works/pi-agent-core": "1.4.0",
74
+ "@earendil-works/pi-ai": "1.4.0",
75
+ "@earendil-works/pi-codemode": "1.4.0",
76
+ "@earendil-works/pi-coding-agent": "1.4.0",
77
+ "@earendil-works/pi-mcp": "1.4.0",
78
+ "@earendil-works/pi-tui": "1.4.0",
79
79
  "@grammyjs/runner": "^2.0.3",
80
80
  "@hono/node-server": "^2.0.4",
81
81
  "@inquirer/prompts": "^8.5.0",
@@ -170,12 +170,12 @@
170
170
  "xlsx": "file:web/vendor/xlsx-0.20.3.tgz",
171
171
  "@xopcai/browser-control-contract": "0.1.0",
172
172
  "@xopcai/computer-control-contract": "0.1.0",
173
- "@xopcai/endpoint-tools-client": "0.0.0",
174
173
  "@xopcai/endpoint-tools-protocol": "0.0.0",
175
174
  "@xopcai/gateway-contract": "0.0.0",
176
175
  "@xopcai/image-providers": "0.1.0",
177
176
  "@xopcai/realtime-client": "0.0.0",
178
- "@xopcai/realtime-protocol": "0.0.0"
177
+ "@xopcai/realtime-protocol": "0.0.0",
178
+ "@xopcai/endpoint-tools-client": "0.0.0"
179
179
  },
180
180
  "scripts": {
181
181
  "generate:device-tools": "tsx scripts/devices/generate-mobile-tools.mts",