@xopcai/xopc 0.0.307 → 0.0.308

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 (165) 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-CZeQo09T.js → agent-avatar-dicebear-dUotwUO6.js} +1 -1
  4. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-C6LflMXr.js +1 -0
  5. package/dist/gateway/static/root/assets/{agents-BlrHMbRx.js → agents-VPDIGRSS.js} +1 -1
  6. package/dist/gateway/static/root/assets/{app-management-settings-panel-Bzw4fQP8.js → app-management-settings-panel-zPz0rOND.js} +1 -1
  7. package/dist/gateway/static/root/assets/{appearance-settings-8GZpUXva.js → appearance-settings-DhvhR43G.js} +1 -1
  8. package/dist/gateway/static/root/assets/{apps-page-BkQQtIxH.js → apps-page-Pmslbzzr.js} +1 -1
  9. package/dist/gateway/static/root/assets/{archive-plugin-CQ2NaoHb.js → archive-plugin-BQVZMreT.js} +1 -1
  10. package/dist/gateway/static/root/assets/{attachment-load-BFi1H7yJ.js → attachment-load-CPE-TMPf.js} +1 -1
  11. package/dist/gateway/static/root/assets/{automations-page-CDBXcii_.js → automations-page-C4IAy_zF.js} +1 -1
  12. package/dist/gateway/static/root/assets/automations-workspace-Fx5VUJRu.js +6 -0
  13. package/dist/gateway/static/root/assets/{binary-plugins-D07eWmOx.js → binary-plugins-DgTl7diZ.js} +1 -1
  14. package/dist/gateway/static/root/assets/{block-editor-CtVnjyYU.js → block-editor-CcOVA-Gw.js} +3 -3
  15. package/dist/gateway/static/root/assets/{browser-automations-page-DyrSbDdG.js → browser-automations-page--zKAgj1k.js} +1 -1
  16. package/dist/gateway/static/root/assets/browser-settings-page-DBms6d35.js +3 -0
  17. package/dist/gateway/static/root/assets/capabilities-settings-panel-epdDWIZy.js +8 -0
  18. package/dist/gateway/static/root/assets/{channels-settings-DAD9qE3J.js → channels-settings-B0bsDtmP.js} +1 -1
  19. package/dist/gateway/static/root/assets/{chat-terminal-dock-B62SZdAo.js → chat-terminal-dock-BfLd2rIJ.js} +1 -1
  20. package/dist/gateway/static/root/assets/{computer-settings-page-ClSresNq.js → computer-settings-page-Ckgc0Py-.js} +1 -1
  21. package/dist/gateway/static/root/assets/connector-service-page-BlC1OXX4.js +1 -0
  22. package/dist/gateway/static/root/assets/connectors-page-By33-bF1.js +2 -0
  23. package/dist/gateway/static/root/assets/{cron-expression-CTMi_tql.js → cron-expression-CqNE-nf6.js} +1 -1
  24. package/dist/gateway/static/root/assets/{date-picker-B71AJK50.js → date-picker-BS9ZjzYJ.js} +1 -1
  25. package/dist/gateway/static/root/assets/{dependency-picker-DlyGK-kA.js → dependency-picker-CF_zYzxX.js} +1 -1
  26. package/dist/gateway/static/root/assets/{desktop-pet-DGkbTE8_.js → desktop-pet-CDwtLR7Z.js} +1 -1
  27. package/dist/gateway/static/root/assets/{desktop-pet-settings-BY8r9j66.js → desktop-pet-settings-C0djIc1J.js} +1 -1
  28. package/dist/gateway/static/root/assets/{device-pairing-wizard-DzRrgd59.js → device-pairing-wizard-CDKj9LQj.js} +1 -1
  29. package/dist/gateway/static/root/assets/{extension-debug-page-L8Mm1n3A.js → extension-debug-page-CX5OXxEU.js} +1 -1
  30. package/dist/gateway/static/root/assets/{extension-page-CFc4vSNU.js → extension-page-BytR1PaY.js} +1 -1
  31. package/dist/gateway/static/root/assets/{extension-settings-page-B5zWyHr3.js → extension-settings-page-CkaMJA5F.js} +1 -1
  32. package/dist/gateway/static/root/assets/{gateway-settings-D7qmTH4R.js → gateway-settings-_YU-1p0z.js} +1 -1
  33. package/dist/gateway/static/root/assets/{heartbeat-settings-Glsl3X5b.js → heartbeat-settings-CVIvvm4x.js} +1 -1
  34. package/dist/gateway/static/root/assets/home-page-COCHelcL.js +1 -0
  35. package/dist/gateway/static/root/assets/{imports-page-ByBX7ome.js → imports-page-DrtbjL8O.js} +1 -1
  36. package/dist/gateway/static/root/assets/index-CDfcPiPb.js +79 -0
  37. package/dist/gateway/static/root/assets/index-CRu1p38D.css +1 -0
  38. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-C45RlO8a.js → keyboard-shortcuts-settings-BlZh41Xq.js} +1 -1
  39. package/dist/gateway/static/root/assets/{local-app-workbench-page-DP0x2jpR.js → local-app-workbench-page-D7_Raxjw.js} +2 -2
  40. package/dist/gateway/static/root/assets/{local-apps-page-C_AQc2bI.js → local-apps-page-DbP7wWuh.js} +1 -1
  41. package/dist/gateway/static/root/assets/{logs-page-DvM8Pyok.js → logs-page-C0n66FiO.js} +1 -1
  42. package/dist/gateway/static/root/assets/{management-settings-D1uwSutV.js → management-settings-i6GhxpGV.js} +1 -1
  43. package/dist/gateway/static/root/assets/{media-plugins-C4mhf13f.js → media-plugins-CnWChQ3Y.js} +1 -1
  44. package/dist/gateway/static/root/assets/note-detail-panel-C59d8vDW.js +5 -0
  45. package/dist/gateway/static/root/assets/notes-page-C1GBPrVI.js +8 -0
  46. package/dist/gateway/static/root/assets/{page-tabs-1go_BtX1.js → page-tabs-BWitjb3e.js} +1 -1
  47. package/dist/gateway/static/root/assets/{preview-open-alternatives-DmoSC0j1.js → preview-open-alternatives-UaCWCxZv.js} +1 -1
  48. package/dist/gateway/static/root/assets/{proactive-page-xAjKTIID.js → proactive-page-CtSFJxoM.js} +1 -1
  49. package/dist/gateway/static/root/assets/project-detail-page-ILTmQ1YN.js +1 -0
  50. package/dist/gateway/static/root/assets/projects-page-snl4rOQZ.js +1 -0
  51. package/dist/gateway/static/root/assets/remote-access-hub-BbaAcEN3.js +1 -0
  52. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-ClkOoxDl.js → runtime-tools-settings-panel-CtOjKGWg.js} +1 -1
  53. package/dist/gateway/static/root/assets/{schema-form-BuEmLiaU.js → schema-form-DkyyDcl2.js} +1 -1
  54. package/dist/gateway/static/root/assets/sessions-page-DrWL71O8.js +1 -0
  55. package/dist/gateway/static/root/assets/settings-advanced-gate-BG0kl4HT.js +1 -0
  56. package/dist/gateway/static/root/assets/{settings-form-section-Dor39QON.js → settings-form-section-C0JDGN_V.js} +1 -1
  57. package/dist/gateway/static/root/assets/{settings-page-Xj-yvIc8.js → settings-page-DiIyMQ52.js} +1 -1
  58. package/dist/gateway/static/root/assets/setup-status-panel-EPazhoZO.js +1 -0
  59. package/dist/gateway/static/root/assets/{share-preview-page-BFWZoXdm.js → share-preview-page-Bt1K657Y.js} +1 -1
  60. package/dist/gateway/static/root/assets/shares-settings-g2MdRXSZ.js +1 -0
  61. package/dist/gateway/static/root/assets/skill-reload-api-B1DPzu98.js +1 -0
  62. package/dist/gateway/static/root/assets/skills-page-Wd0uYSPG.js +2 -0
  63. package/dist/gateway/static/root/assets/{skills-page.utils-Ii8qeXhs.js → skills-page.utils-vq5Ujm03.js} +1 -1
  64. package/dist/gateway/static/root/assets/{system-settings-panel-Di6OSO-0.js → system-settings-panel-Cz1P-HDH.js} +1 -1
  65. package/dist/gateway/static/root/assets/task-detail-page-BG3A5gPZ.js +1 -0
  66. package/dist/gateway/static/root/assets/{tunnel-api-DDOlOYlj.js → tunnel-api-DQGoFuZO.js} +1 -1
  67. package/dist/gateway/static/root/assets/{use-autosave-CQ8uWNnB.js → use-autosave-DVDlBb95.js} +1 -1
  68. package/dist/gateway/static/root/assets/user-model-page-qM5UiTGx.js +2 -0
  69. package/dist/gateway/static/root/assets/{voice-api-key-field-COTzshjL.js → voice-api-key-field-B2pZCcxY.js} +1 -1
  70. package/dist/gateway/static/root/assets/{work-discovery-overlay-_URrXbi4.js → work-discovery-overlay-Bptv7bEY.js} +1 -1
  71. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-CALs-1nd.js → workflow-run-setup-panel-BijCrNc4.js} +2 -2
  72. package/dist/gateway/static/root/assets/workflows-page-DRy1RAYH.js +6 -0
  73. package/dist/gateway/static/root/index.html +2 -2
  74. package/dist/package.js +1 -1
  75. package/dist/packages/gateway-contract/src/notifications.js +1 -1
  76. package/dist/src/agent/background-review/prompts.js +3 -1
  77. package/dist/src/agent/context/execution-context.js +4 -4
  78. package/dist/src/agent/memory/compaction-promotion.d.ts +1 -1
  79. package/dist/src/agent/memory/compaction-promotion.js +4 -3
  80. package/dist/src/agent/tools/knowledge-memory-tool.d.ts +1 -1
  81. package/dist/src/agent/tools/knowledge-memory-tool.js +3 -3
  82. package/dist/src/agent/tools/user-context-tool.js +17 -7
  83. package/dist/src/chat-commands/builtins/understanding.js +1 -1
  84. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  85. package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
  86. package/dist/src/config/schema.d.ts +2 -4
  87. package/dist/src/config/schema.js +2 -2
  88. package/dist/src/connectors/connected-source-understanding.d.ts +1 -0
  89. package/dist/src/connectors/connected-source-understanding.js +1 -0
  90. package/dist/src/connectors/learning-coordinator.js +31 -9
  91. package/dist/src/gateway/hono/lib/config-payload.d.ts +2 -2
  92. package/dist/src/gateway/hono/routes/connectors.js +1 -1
  93. package/dist/src/gateway/hono/routes/context-sources.js +0 -23
  94. package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
  95. package/dist/src/gateway/hono/routes/projects.js +8 -0
  96. package/dist/src/gateway/hono/routes/user-model-refresh.d.ts +5 -0
  97. package/dist/src/gateway/hono/routes/user-model-refresh.js +128 -0
  98. package/dist/src/gateway/hono/routes/user-model.js +12 -5
  99. package/dist/src/gateway/hono/routes/work-discovery.js +0 -30
  100. package/dist/src/gateway/service.js +6 -6
  101. package/dist/src/infra/update-restart.js +1 -1
  102. package/dist/src/knowledge/connected-knowledge-pipeline.js +1 -1
  103. package/dist/src/knowledge-memory/index.js +2 -2
  104. package/dist/src/knowledge-memory/repository.d.ts +7 -0
  105. package/dist/src/knowledge-memory/repository.js +58 -8
  106. package/dist/src/memory-maintenance/service.js +61 -31
  107. package/dist/src/migrations/memory-config.d.ts +2 -0
  108. package/dist/src/migrations/memory-config.js +77 -0
  109. package/dist/src/migrations/runner.js +2 -2
  110. package/dist/src/notifications/planner.js +5 -5
  111. package/dist/src/notifications/service.d.ts +2 -2
  112. package/dist/src/notifications/service.js +1 -1
  113. package/dist/src/storage/sqlite/migrations/184_memory_suppressions.sql +12 -0
  114. package/dist/src/storage/sqlite/migrations/185_understanding_refresh_batches.sql +6 -0
  115. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  116. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  117. package/dist/src/storage/sqlite/schema.js +1 -1
  118. package/dist/src/user-context/config.d.ts +4 -9
  119. package/dist/src/user-context/config.js +7 -27
  120. package/dist/src/user-context/memory-suppression.d.ts +7 -0
  121. package/dist/src/user-context/memory-suppression.js +23 -0
  122. package/dist/src/user-context/relationship-continuity.js +1 -1
  123. package/dist/src/user-context/sources/refresh-service.d.ts +48 -0
  124. package/dist/src/user-context/sources/refresh-service.js +221 -0
  125. package/dist/src/user-context/sources/repository.js +1 -1
  126. package/dist/src/user-model/bootstrap.js +27 -24
  127. package/dist/src/user-model/capture/executor.d.ts +1 -1
  128. package/dist/src/user-model/capture/executor.js +17 -11
  129. package/dist/src/user-model/capture/semantic.js +1 -1
  130. package/dist/src/user-model/domain.d.ts +6 -2
  131. package/dist/src/user-model/index.js +3 -3
  132. package/dist/src/user-model/profile.js +1 -1
  133. package/dist/src/user-model/repository.d.ts +4 -1
  134. package/dist/src/user-model/repository.js +96 -6
  135. package/dist/src/user-model/usage-policy.d.ts +2 -0
  136. package/dist/src/user-model/usage-policy.js +6 -2
  137. package/dist/src/work-discovery/project-understanding.js +2 -1
  138. package/dist/src/work-discovery/service.d.ts +8 -24
  139. package/dist/src/work-discovery/service.js +138 -180
  140. package/package.json +3 -3
  141. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-BPsRb9Ck.js +0 -1
  142. package/dist/gateway/static/root/assets/automations-workspace-CUpiTTiY.js +0 -6
  143. package/dist/gateway/static/root/assets/browser-settings-page-CqTxLpil.js +0 -3
  144. package/dist/gateway/static/root/assets/capabilities-settings-panel-BZ_-pnS6.js +0 -8
  145. package/dist/gateway/static/root/assets/connector-service-page-CPqVmNvx.js +0 -1
  146. package/dist/gateway/static/root/assets/connectors-page-BUQyg3CW.js +0 -2
  147. package/dist/gateway/static/root/assets/home-page-s9hDQ8Hc.js +0 -1
  148. package/dist/gateway/static/root/assets/index-RBCkv8a_.js +0 -79
  149. package/dist/gateway/static/root/assets/index-cFU4S35z.css +0 -1
  150. package/dist/gateway/static/root/assets/note-detail-panel-D35sErp2.js +0 -5
  151. package/dist/gateway/static/root/assets/notes-page-8jCDklDn.js +0 -8
  152. package/dist/gateway/static/root/assets/project-detail-page-BUMQHy_N.js +0 -1
  153. package/dist/gateway/static/root/assets/projects-page-DT-Mt7XR.js +0 -1
  154. package/dist/gateway/static/root/assets/remote-access-hub-Clz3byir.js +0 -1
  155. package/dist/gateway/static/root/assets/sessions-page-tQRwktKm.js +0 -1
  156. package/dist/gateway/static/root/assets/settings-advanced-gate-DqWg9XS5.js +0 -1
  157. package/dist/gateway/static/root/assets/setup-status-panel-BB_sMB7P.js +0 -1
  158. package/dist/gateway/static/root/assets/shares-settings-oDALm4b6.js +0 -1
  159. package/dist/gateway/static/root/assets/skill-reload-api-DmwelnfK.js +0 -1
  160. package/dist/gateway/static/root/assets/skills-page-BE9JXz4U.js +0 -2
  161. package/dist/gateway/static/root/assets/task-detail-page-D1AWszc7.js +0 -1
  162. package/dist/gateway/static/root/assets/user-model-page-C00i4ea0.js +0 -2
  163. package/dist/gateway/static/root/assets/workflows-page-BUiBjz6m.js +0 -6
  164. package/dist/src/migrations/knowledge-memory-read-policy-config.d.ts +0 -2
  165. package/dist/src/migrations/knowledge-memory-read-policy-config.js +0 -48
@@ -1,6 +1,6 @@
1
1
  import { retrievalLexicalSimilarity } from "../../retrieval/textFeatures.js";
2
- import { getAssertionSlot, getUserAssertion, listUserAssertions, reconcileAssertion, setAssertionStatus } from "../../user-model/repository.js";
3
- import { isWorkingAssumption } from "../../user-model/usage-policy.js";
2
+ import { deleteUserAssertion, getAssertionSlot, getUserAssertion, listUserAssertions, reconcileAssertion, setAssertionStatus } from "../../user-model/repository.js";
3
+ import { canUseAssertion } from "../../user-model/usage-policy.js";
4
4
  import "../../user-model/index.js";
5
5
  import { Type } from "@sinclair/typebox";
6
6
  //#region src/agent/tools/user-context-tool.ts
@@ -31,9 +31,6 @@ function visible(options, slotId) {
31
31
  const scope = getAssertionSlot(slotId)?.scope;
32
32
  return scope?.type === "global" || scope?.type === "agent" && scope.id === options.agentId || scope?.type === "workspace" && scope.id === options.workspaceId || scope?.type === "project" && scope.id === options.getProjectId?.() || scope?.type === "session" && scope.id === options.getSessionId();
33
33
  }
34
- function referenceable(assertion) {
35
- return (assertion.status === "active" || isWorkingAssumption(assertion)) && assertion.authority !== "external_untrusted" && assertion.sensitivity !== "secret" && assertion.sensitivity !== "regulated" && assertion.disclosurePolicy !== "ask_before_reference";
36
- }
37
34
  function createUserContextSearchTool(options) {
38
35
  return {
39
36
  name: "user_context_search",
@@ -52,7 +49,7 @@ function createUserContextSearchTool(options) {
52
49
  const results = listUserAssertions({
53
50
  statuses: ["active", "candidate"],
54
51
  limit: 1e3
55
- }).filter((assertion) => visible(options, assertion.slotId)).filter(referenceable).map((assertion) => ({
52
+ }).filter((assertion) => visible(options, assertion.slotId)).filter((item) => canUseAssertion(item)).map((assertion) => ({
56
53
  assertion,
57
54
  score: retrievalLexicalSimilarity(input.query, `${assertion.statement} ${assertion.normalizedValue}`)
58
55
  })).filter((item) => item.score > 0).sort((left, right) => right.score - left.score).slice(0, input.maxResults ?? 12).map(({ assertion, score }) => ({
@@ -89,7 +86,7 @@ function createUserContextGetTool(options) {
89
86
  };
90
87
  const id = raw.id;
91
88
  const assertion = getUserAssertion(id);
92
- if (!assertion || !visible(options, assertion.slotId) || !referenceable(assertion)) return {
89
+ if (!assertion || !visible(options, assertion.slotId) || !canUseAssertion(assertion)) return {
93
90
  content: [{
94
91
  type: "text",
95
92
  text: `User assertion not found: ${id}`
@@ -199,6 +196,19 @@ function createUserContextUpdateTool(options) {
199
196
  details: receipt
200
197
  };
201
198
  }
199
+ if (input.action === "forget") {
200
+ deleteUserAssertion(current.id);
201
+ return {
202
+ content: [{
203
+ type: "text",
204
+ text: "Memory deleted."
205
+ }],
206
+ details: {
207
+ action: "forget",
208
+ id: current.id
209
+ }
210
+ };
211
+ }
202
212
  const status = {
203
213
  confirm: "active",
204
214
  reject: "rejected",
@@ -58,7 +58,7 @@ const rememberCommand = {
58
58
  disclosurePolicy: "referenceable",
59
59
  observedAt: Date.now(),
60
60
  createdBy: "user"
61
- });
61
+ }, Date.now(), { restoreDeleted: true });
62
62
  const scopeLabel = sessionOnly ? "this conversation" : "all conversations";
63
63
  return {
64
64
  content: result.action === "created" ? `Remembered for ${scopeLabel}. You can review or remove it in User Model.` : `This is already remembered for ${scopeLabel}.`,
@@ -53,7 +53,7 @@ async function checkDatabaseSchema(ctx) {
53
53
  id: "database-schema",
54
54
  label: "Database schema",
55
55
  status: "pass",
56
- message: `SQLite schema v${status.dbVersion} (current release v183).`,
56
+ message: `SQLite schema v${status.dbVersion} (current release v185).`,
57
57
  hints: []
58
58
  };
59
59
  }
@@ -1,8 +1,8 @@
1
1
  import { init_paths, resolveConfigPath } from "../../../config/paths.js";
2
2
  import { loadConfig } from "../../../config/loader.js";
3
3
  import "../../../config/index.js";
4
- import { resolveGatewayService } from "../../../daemon/service.js";
5
4
  import { isRestartEnabled } from "../../../config/commands.flags.js";
5
+ import { resolveGatewayService } from "../../../daemon/service.js";
6
6
  import { authorizeGatewaySigusr1Restart, writeGatewayRestartIntentSync } from "../../../infra/restart.js";
7
7
  import { findVerifiedGatewayListenerPidsOnPortSync, formatGatewayPidList, signalVerifiedGatewayPidSync } from "../../../infra/gateway-processes.js";
8
8
  import { runServiceRestart, runServiceStop } from "./lifecycle-core.js";
@@ -1465,7 +1465,6 @@ export declare const ConfigSchema: z.ZodDefault<z.ZodObject<{
1465
1465
  enabled: z.ZodDefault<z.ZodBoolean>;
1466
1466
  writePolicy: z.ZodDefault<z.ZodEnum<{
1467
1467
  allow: "allow";
1468
- confirm: "confirm";
1469
1468
  deny: "deny";
1470
1469
  }>>;
1471
1470
  sensitiveWritePolicy: z.ZodDefault<z.ZodEnum<{
@@ -1502,11 +1501,10 @@ export declare const ConfigSchema: z.ZodDefault<z.ZodObject<{
1502
1501
  staleRetentionDays: z.ZodDefault<z.ZodNumber>;
1503
1502
  }, z.core.$strict>>;
1504
1503
  }, z.core.$strict>>;
1505
- knowledgeMemory: z.ZodDefault<z.ZodPreprocess<z.ZodObject<{
1504
+ knowledgeMemory: z.ZodDefault<z.ZodObject<{
1506
1505
  enabled: z.ZodDefault<z.ZodBoolean>;
1507
1506
  writePolicy: z.ZodDefault<z.ZodEnum<{
1508
1507
  allow: "allow";
1509
- confirm: "confirm";
1510
1508
  deny: "deny";
1511
1509
  }>>;
1512
1510
  readScopes: z.ZodDefault<z.ZodArray<z.ZodEnum<{
@@ -1539,7 +1537,7 @@ export declare const ConfigSchema: z.ZodDefault<z.ZodObject<{
1539
1537
  allowExternalWrites: z.ZodDefault<z.ZodBoolean>;
1540
1538
  allowedProviderIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
1541
1539
  autoWriteKinds: z.ZodOptional<z.ZodArray<z.ZodString>>;
1542
- }, z.core.$strict>>>;
1540
+ }, z.core.$strict>>;
1543
1541
  contextPlanning: z.ZodDefault<z.ZodObject<{
1544
1542
  enabled: z.ZodDefault<z.ZodBoolean>;
1545
1543
  maxAssertions: z.ZodDefault<z.ZodNumber>;
@@ -1054,7 +1054,7 @@ workDiscoveryOnboarding: z.boolean().default(true) }).strict().default({ workDis
1054
1054
  preferences: { responseLanguage: "auto" },
1055
1055
  userModel: {
1056
1056
  enabled: true,
1057
- writePolicy: "confirm",
1057
+ writePolicy: "allow",
1058
1058
  sensitiveWritePolicy: "confirm",
1059
1059
  processingPolicy: "remote_allowed",
1060
1060
  extraction: {
@@ -1075,7 +1075,7 @@ workDiscoveryOnboarding: z.boolean().default(true) }).strict().default({ workDis
1075
1075
  },
1076
1076
  knowledgeMemory: {
1077
1077
  enabled: true,
1078
- writePolicy: "confirm",
1078
+ writePolicy: "allow",
1079
1079
  readScopes: [
1080
1080
  "global",
1081
1081
  "agent",
@@ -10,6 +10,7 @@ export declare function deriveConnectedSourceUnderstanding(input: {
10
10
  sourceRunId: string;
11
11
  processingPolicy: 'local_only' | 'remote_allowed';
12
12
  analyze?: typeof analyzeUnderstandingSources;
13
+ assertAuthorized?: () => void;
13
14
  }): Promise<{
14
15
  created: number;
15
16
  knowledgeCount: number;
@@ -95,6 +95,7 @@ async function deriveConnectedSourceUnderstanding(input) {
95
95
  config: input.config,
96
96
  items
97
97
  });
98
+ input.assertAuthorized?.();
98
99
  const byRef = new Map(items.map((item) => [item.evidenceRef, item]));
99
100
  let created = 0;
100
101
  for (const candidate of analysis.profileCandidates.filter(isPortraitCandidate)) {
@@ -15,7 +15,7 @@ import "../knowledge/index.js";
15
15
  import { ingestComposioConnectedSource } from "./connected-source-ingestion.js";
16
16
  import { deriveConnectedSourceUnderstanding } from "./connected-source-understanding.js";
17
17
  import { listConnectedContentCandidates, readConnectedContent } from "./content-enrichment.js";
18
- import { createUnderstandingSourceRun, getUnderstandingSourceGrant, listUnderstandingSourceRuns, updateUnderstandingSourceGrantCheckpoint, updateUnderstandingSourceRun, upsertUnderstandingSourceGrant } from "../user-context/sources/repository.js";
18
+ import { createUnderstandingSourceRun, getUnderstandingSourceGrant, listUnderstandingSourceGrants, listUnderstandingSourceRuns, updateUnderstandingSourceGrantCheckpoint, updateUnderstandingSourceRun, upsertUnderstandingSourceGrant } from "../user-context/sources/repository.js";
19
19
  //#region src/connectors/learning-coordinator.ts
20
20
  init_logger();
21
21
  const log = createLogger("ConnectorLearning");
@@ -33,7 +33,9 @@ function connectorSourceCategory(toolkit) {
33
33
  return "files";
34
34
  }
35
35
  function ensureUnderstandingSourceRun(job, toolkit, displayName) {
36
- const grant = upsertUnderstandingSourceGrant({
36
+ const existing = listUnderstandingSourceGrants({ includeRevoked: true }).find((grant) => grant.sourceKey === `connector-account:${job.accountId}`);
37
+ if (existing?.status === "revoked") throw new Error("Source authorization was revoked.");
38
+ const grant = existing ?? upsertUnderstandingSourceGrant({
37
39
  sourceKey: `connector-account:${job.accountId}`,
38
40
  adapterId: `connector:${job.connectorId}`,
39
41
  category: connectorSourceCategory(toolkit),
@@ -75,6 +77,14 @@ function startConnectorLearningCoordinator(options) {
75
77
  if (!connection) return null;
76
78
  if (!connection.accountId) throw new Error(`Connector account is missing for connection ${connection.id}.`);
77
79
  if (!getConnectorAccount(connection.accountId)?.enabled) return null;
80
+ if (listUnderstandingSourceGrants({ includeRevoked: true }).some((grant) => grant.sourceKey === `connector-account:${connection.accountId}` && grant.status === "revoked")) return null;
81
+ if (request.reason === "manual") {
82
+ const active = listConnectorLearningJobs({
83
+ accountId: connection.accountId,
84
+ limit: 100
85
+ }).find((job) => job.status === "running" || job.status === "queued" && (!job.nextRunAt || Date.parse(job.nextRunAt) <= Date.now()));
86
+ if (active) return active;
87
+ }
78
88
  const syncPolicy = getConnectorSyncPolicyForConnection(connection.id);
79
89
  if (request.reason !== "manual" && syncPolicy?.scanEnabled !== true) return null;
80
90
  const definition = getConnectorDefinition(connection.connectorId);
@@ -213,13 +223,21 @@ function startConnectorLearningCoordinator(options) {
213
223
  knowledgeCount: 0,
214
224
  status: "completed"
215
225
  };
226
+ const sourceGrantPolicy = getUnderstandingSourceGrant(sourceRun.grantId)?.processingPolicy;
216
227
  try {
217
228
  semantic = await deriveConnectedSourceUnderstanding({
218
229
  config: options.getConfig(),
219
230
  agentId: job.agentId,
220
231
  sourceInstanceId: job.sourceInstanceId,
221
232
  sourceRunId: sourceRun.id,
222
- processingPolicy: getUnderstandingSourceGrant(sourceRun.grantId)?.processingPolicy ?? "local_only"
233
+ processingPolicy: getUnderstandingSourceGrant(sourceRun.grantId)?.processingPolicy ?? "local_only",
234
+ assertAuthorized: () => {
235
+ const grant = getUnderstandingSourceGrant(sourceRun.grantId);
236
+ if (grant?.status !== "active" || !getConnectorAccount(job.accountId)?.enabled || grant.processingPolicy !== sourceGrantPolicy || !learningEnabled(options.getConfig()) || listConnectorLearningJobs({
237
+ accountId: job.accountId,
238
+ limit: 100
239
+ }).find((item) => item.id === job.id)?.status !== "running") throw new Error("Source authorization changed during analysis.");
240
+ }
223
241
  });
224
242
  } catch (error) {
225
243
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -297,7 +315,7 @@ function startConnectorLearningCoordinator(options) {
297
315
  await execute(job);
298
316
  } catch (err) {
299
317
  const errorMessage = err instanceof Error ? err.message : String(err);
300
- const exhausted = job.attemptCount >= 5;
318
+ const exhausted = job.attemptCount >= 5 || job.idempotencyKey.startsWith("understanding-refresh:");
301
319
  publish(updateConnectorLearningJob(job.id, {
302
320
  status: exhausted ? "paused" : "failed",
303
321
  error: learningFailureCode(err),
@@ -305,11 +323,15 @@ function startConnectorLearningCoordinator(options) {
305
323
  finished: true
306
324
  }));
307
325
  const definition = getConnectorDefinition(job.connectorId);
308
- if (definition?.runtime.type === "composio" && definition.runtime.role === "toolkit") updateUnderstandingSourceRun(ensureUnderstandingSourceRun(job, definition.runtime.toolkit, definition.displayName).id, {
309
- status: "failed",
310
- errorMessage: learningFailureCode(err),
311
- completed: true
312
- });
326
+ if (definition?.runtime.type === "composio" && definition.runtime.role === "toolkit") {
327
+ const grant = listUnderstandingSourceGrants({ includeRevoked: true }).find((item) => item.sourceKey === `connector-account:${job.accountId}`);
328
+ const sourceRun = grant && listUnderstandingSourceRuns(grant.id, 100).find((item) => item.metadata.connectorLearningJobId === job.id);
329
+ if (sourceRun) updateUnderstandingSourceRun(sourceRun.id, {
330
+ status: "failed",
331
+ errorMessage: learningFailureCode(err),
332
+ completed: true
333
+ });
334
+ }
313
335
  log.warn({
314
336
  err,
315
337
  jobId: job.id,
@@ -222,7 +222,7 @@ export declare function buildSafeWebConfigPayload(service: GatewayService, optio
222
222
  };
223
223
  userModel: {
224
224
  enabled: boolean;
225
- writePolicy: "allow" | "confirm" | "deny";
225
+ writePolicy: "allow" | "deny";
226
226
  sensitiveWritePolicy: "allow" | "confirm" | "deny";
227
227
  processingPolicy: "local_only" | "remote_allowed";
228
228
  extraction: {
@@ -244,7 +244,7 @@ export declare function buildSafeWebConfigPayload(service: GatewayService, optio
244
244
  };
245
245
  knowledgeMemory: {
246
246
  enabled: boolean;
247
- writePolicy: "allow" | "confirm" | "deny";
247
+ writePolicy: "allow" | "deny";
248
248
  readScopes: ("project" | "session" | "agent" | "workspace" | "global")[];
249
249
  contentSources: ("memory" | "connector" | "local_import")[];
250
250
  searchStrategy: "local-first" | "external-first" | "fanout" | "local-only" | "external-only";
@@ -19,6 +19,7 @@ import { createConnectorSetupSecretRequest, submitConnectorSetupSecret } from ".
19
19
  import { recordConnectorHealthUsage } from "../../../connectors/usage.js";
20
20
  import { getConnectorInstance, getInstalledConnectorDefinition, listConnectorInstances } from "../../../connectors/instances.js";
21
21
  import { installConnector, installConnectorDefinition, uninstallConnector, updateConnectorConfig } from "../../../connectors/install.js";
22
+ import { ConfigPersistenceError, persistConfigMutation } from "../../../config/config-mutation.js";
22
23
  import { resumeApprovedConnectorAction } from "../../../connectors/approval-resume.js";
23
24
  import { getMcpOAuthManager } from "../../../agent/mcp/oauth/mcp-oauth-manager.js";
24
25
  import { startConnectorAuthorization } from "../../../connectors/auth-provider-registry.js";
@@ -26,7 +27,6 @@ import { composioLogoResponse } from "../../../connectors/composio-logo.js";
26
27
  import { inspectManagedComposioStatus } from "../../../connectors/composio-managed-client.js";
27
28
  import { appendComposioTriggerEvent, listComposioTriggerEvents } from "../../../connectors/composio-triggers.js";
28
29
  import { ingestLocalFolderSource } from "../../../connectors/connected-source-ingestion.js";
29
- import { ConfigPersistenceError, persistConfigMutation } from "../../../config/config-mutation.js";
30
30
  import { previewConnectorDefinition, testConnectorInstance } from "../../../connectors/health.js";
31
31
  import { listUnderstandingSourceGrants, revokeUnderstandingSourceGrant } from "../../../user-context/sources/repository.js";
32
32
  import { setConnectorEnabled } from "../../../connectors/lifecycle.js";
@@ -8,7 +8,6 @@ import "../../../user-model/index.js";
8
8
  import { listConnectedContentCandidates, readConnectedContent } from "../../../connectors/content-enrichment.js";
9
9
  import { getUnderstandingSourceGrant, listUnderstandingSourceGrants, listUnderstandingSourceRuns, revokeUnderstandingSourceGrant, updateUnderstandingSourceGrantPolicies } from "../../../user-context/sources/repository.js";
10
10
  import { listUnderstandingSourceDefinitions } from "../../../user-context/sources/catalog.js";
11
- import { randomUUID } from "node:crypto";
12
11
  //#region src/gateway/hono/routes/context-sources.ts
13
12
  init_agent_scope();
14
13
  init_transaction();
@@ -103,28 +102,6 @@ function registerContextSourceRoutes(authenticated, deps) {
103
102
  return c.json({ error: error instanceof Error ? error.message : String(error) }, 400);
104
103
  }
105
104
  });
106
- authenticated.post("/api/context-sources/grants/:grantId/refresh", limited, async (c) => {
107
- const grant = getUnderstandingSourceGrant(c.req.param("grantId"));
108
- if (!grant || grant.status !== "active") return c.json({ error: "Active context source not found" }, 404);
109
- try {
110
- if (grant.adapterId === "local-work-folders") {
111
- const result = await service.refreshDirectorySourceIfChanged({
112
- id: grant.id,
113
- idempotencyKey: randomUUID()
114
- });
115
- return c.json({ result }, result.changed ? 202 : 200);
116
- }
117
- const accountId = typeof grant.config.accountId === "string" ? grant.config.accountId : "";
118
- const connectionId = accountId ? getConnectorAccount(accountId)?.currentConnectionId : void 0;
119
- const job = connectionId ? deps.service.requestConnectorLearning(connectionId, {
120
- mode: "incremental",
121
- reason: "manual"
122
- }) : null;
123
- return job ? c.json({ job }, 202) : c.json({ error: "Context source cannot be refreshed here" }, 409);
124
- } catch (error) {
125
- return c.json({ error: error instanceof Error ? error.message : String(error) }, 400);
126
- }
127
- });
128
105
  authenticated.get("/api/context-sources/work-folders", (c) => c.json({ sources: service.listDirectorySources() }));
129
106
  authenticated.post("/api/context-sources/work-folders", limited, async (c) => {
130
107
  const input = await c.req.json().catch(() => null);
@@ -329,6 +329,14 @@ const AUTHENTICATED_LAZY_ROUTE_BUNDLES = [
329
329
  return { register: registerVoiceRoutes };
330
330
  }
331
331
  },
332
+ {
333
+ id: "user-model-refresh",
334
+ match: (pathname) => pathname === "/api/user-model/refresh" || pathname.startsWith("/api/user-model/refresh/"),
335
+ load: async () => {
336
+ const { registerUserModelRefreshRoutes } = await import("./user-model-refresh.js");
337
+ return { register: registerUserModelRefreshRoutes };
338
+ }
339
+ },
332
340
  {
333
341
  id: "user-model",
334
342
  match: (path) => startsWithAny(path, [
@@ -405,6 +405,10 @@ function registerProjectsRoutes(authenticated, deps) {
405
405
  originClass: "system",
406
406
  replaceExisting: true
407
407
  });
408
+ if (!record.item) return c.json({
409
+ ok: false,
410
+ error: "This memory was deleted and automatic recreation is disabled."
411
+ }, 409);
408
412
  return c.json({
409
413
  ok: true,
410
414
  knowledge: record.item
@@ -804,6 +808,10 @@ function registerProjectsRoutes(authenticated, deps) {
804
808
  originClass: "agent",
805
809
  replaceExisting: true
806
810
  });
811
+ if (!record.item) return c.json({
812
+ ok: false,
813
+ error: "This memory was deleted and automatic recreation is disabled."
814
+ }, 409);
807
815
  return c.json({
808
816
  ok: true,
809
817
  knowledge: record.item
@@ -0,0 +1,5 @@
1
+ import type { Hono } from 'hono';
2
+ import { UnderstandingRefreshService } from '../../../user-context/sources/refresh-service.js';
3
+ import type { AuthenticatedRouteDeps } from './deps.js';
4
+ export declare function createUnderstandingRefreshService(deps: AuthenticatedRouteDeps): UnderstandingRefreshService;
5
+ export declare function registerUserModelRefreshRoutes(app: Hono, deps: AuthenticatedRouteDeps, refresh?: UnderstandingRefreshService): void;
@@ -0,0 +1,128 @@
1
+ import { listConnectorLearningJobs } from "../../../storage/sqlite/connector-learning-repository.js";
2
+ import { getConnectorAccount } from "../../../storage/sqlite/connector-account-repository.js";
3
+ import "../../../storage/sqlite/index.js";
4
+ import { listUnderstandingSourceRuns } from "../../../user-context/sources/repository.js";
5
+ import { isLocalUnderstandingSourceId } from "../../../user-context/sources/local-source-contract.js";
6
+ import { getWorkDiscoveryRun } from "../../../work-discovery/repository.js";
7
+ import { normalizeUnderstandingSourceItems } from "../../../work-discovery/service.js";
8
+ import { UnderstandingRefreshService } from "../../../user-context/sources/refresh-service.js";
9
+ import { randomUUID } from "node:crypto";
10
+ //#region src/gateway/hono/routes/user-model-refresh.ts
11
+ function createUnderstandingRefreshService(deps) {
12
+ const service = deps.service;
13
+ return new UnderstandingRefreshService({
14
+ enabled: () => service.currentConfig.userContext.enabled && service.currentConfig.userContext.userModel.enabled,
15
+ emit: (type, payload) => service.emit(type, payload),
16
+ async start(grant, runId) {
17
+ if (grant.adapterId === "local-work-folders") return {
18
+ discoveryRunId: (await service.workDiscovery.rescanDirectorySource({
19
+ id: grant.id,
20
+ idempotencyKey: runId
21
+ })).id,
22
+ phase: "reading"
23
+ };
24
+ if (isLocalUnderstandingSourceId(grant.adapterId)) return { phase: "waiting_desktop" };
25
+ if (grant.adapterId.startsWith("connector:")) {
26
+ const account = typeof grant.config.accountId === "string" ? getConnectorAccount(grant.config.accountId) : void 0;
27
+ if (!account?.enabled || !account.currentConnectionId) throw new Error("Reconnect this source before updating.");
28
+ const job = service.requestConnectorLearning(account.currentConnectionId, {
29
+ mode: "incremental",
30
+ reason: "manual",
31
+ idempotencyKey: `understanding-refresh:${randomUUID()}`
32
+ });
33
+ if (!job) throw new Error("This source cannot currently be updated.");
34
+ return {
35
+ connectorLearningJobId: job.id,
36
+ accountId: account.id,
37
+ phase: "reading"
38
+ };
39
+ }
40
+ throw new Error("This source does not support understanding updates.");
41
+ },
42
+ progress(run) {
43
+ if (typeof run.metadata.discoveryRunId === "string") {
44
+ const discovery = getWorkDiscoveryRun(run.metadata.discoveryRunId);
45
+ if (!discovery) return {
46
+ status: "failed",
47
+ phase: "completed",
48
+ error: "Work folder update is no longer available."
49
+ };
50
+ return {
51
+ status: discovery.status === "completed" ? "completed" : discovery.status === "failed" || discovery.status === "canceled" ? "failed" : "running",
52
+ phase: discovery.status === "analyzing" ? "analyzing" : discovery.status === "queued" || discovery.status === "probing" ? "reading" : "completed",
53
+ error: discovery.errorMessage
54
+ };
55
+ }
56
+ if (typeof run.metadata.connectorLearningJobId === "string") {
57
+ const job = listConnectorLearningJobs({
58
+ accountId: String(run.metadata.accountId),
59
+ limit: 100
60
+ }).find((item) => item.id === run.metadata.connectorLearningJobId);
61
+ if (!job) return {
62
+ status: "failed",
63
+ phase: "completed",
64
+ error: "Connector update is no longer available."
65
+ };
66
+ const sourceRun = listUnderstandingSourceRuns(run.grantId, 100).find((item) => item.id !== run.id && item.metadata.connectorLearningJobId === job.id);
67
+ if (job.status === "completed") return {
68
+ status: sourceRun?.status === "partial" ? "partial" : "completed",
69
+ phase: "completed",
70
+ added: job.candidatesCreated,
71
+ itemsSeen: job.itemsDiscovered,
72
+ error: sourceRun?.status === "partial" ? "Some source information could not be analyzed. Retry this source." : void 0
73
+ };
74
+ if (job.status === "paused" || job.status === "failed") return {
75
+ status: "failed",
76
+ phase: "completed",
77
+ error: job.error ?? "Connector update failed."
78
+ };
79
+ return {
80
+ status: "running",
81
+ phase: job.phase === "deriving" ? "analyzing" : "reading",
82
+ itemsSeen: job.itemsDiscovered
83
+ };
84
+ }
85
+ },
86
+ async analyzeDesktop(grant, items, signal) {
87
+ const status = (await service.workDiscovery.importUnderstandingSources(items, grant.processingPolicy, signal, void 0, void 0, { grantId: grant.id })).sourceStatuses.find((item) => item.sourceId === grant.adapterId);
88
+ if (status?.status !== "completed") throw new Error(status?.error ?? "Source analysis did not complete.");
89
+ return {};
90
+ }
91
+ });
92
+ }
93
+ function registerUserModelRefreshRoutes(app, deps, refresh = createUnderstandingRefreshService(deps)) {
94
+ app.post("/api/user-model/refresh", deps.strictRateLimitMiddleware, async (c) => {
95
+ const input = await c.req.json().catch(() => null);
96
+ if (!input || typeof input !== "object" || Array.isArray(input) || input.sourceIds !== void 0 && (!Array.isArray(input.sourceIds) || !input.sourceIds.length || input.sourceIds.length > 100 || input.sourceIds.some((id) => typeof id !== "string" || !id))) return c.json({ error: "Provide sourceIds or an empty object to update all authorized sources." }, 400);
97
+ try {
98
+ return c.json({ batch: refresh.start(input.sourceIds) }, 202);
99
+ } catch (err) {
100
+ return c.json({ error: err instanceof Error ? err.message : String(err) }, 400);
101
+ }
102
+ });
103
+ app.get("/api/user-model/refresh", (c) => c.json({
104
+ batch: refresh.latest(),
105
+ sources: refresh.sources()
106
+ }));
107
+ app.get("/api/user-model/refresh/:id", (c) => {
108
+ const batch = refresh.get(c.req.param("id"));
109
+ return batch ? c.json({ batch }) : c.json({ error: "Update not found." }, 404);
110
+ });
111
+ app.post("/api/user-model/refresh/sources/:runId/collection", deps.strictRateLimitMiddleware, async (c) => {
112
+ const raw = await c.req.json().catch(() => null);
113
+ if (!raw || !Array.isArray(raw.items) || raw.items.length > 1200 || raw.error !== void 0 && typeof raw.error !== "string") return c.json({ error: "Invalid collection." }, 400);
114
+ const items = normalizeUnderstandingSourceItems(raw.items);
115
+ if (raw.items.length && !items.length) return c.json({ error: "No valid source items." }, 400);
116
+ try {
117
+ refresh.submitDesktop(c.req.param("runId"), {
118
+ items,
119
+ error: raw.error
120
+ });
121
+ return c.json({ ok: true }, 202);
122
+ } catch (err) {
123
+ return c.json({ error: err instanceof Error ? err.message : String(err) }, 409);
124
+ }
125
+ });
126
+ }
127
+ //#endregion
128
+ export { createUnderstandingRefreshService, registerUserModelRefreshRoutes };
@@ -1,10 +1,11 @@
1
1
  import { createCollaborationRule, getCollaborationRule, listCollaborationRules, setCollaborationRuleStatus } from "../../../storage/sqlite/collaboration-rule-repository.js";
2
- import { KnowledgeReviewConflictError, getKnowledgeItem, listKnowledgeItems, reviewKnowledgeItem, searchKnowledgeItems } from "../../../knowledge-memory/repository.js";
2
+ import { KnowledgeReviewConflictError, deleteKnowledgeItem, getKnowledgeItem, listKnowledgeItems, reviewKnowledgeItem, searchKnowledgeItems } from "../../../knowledge-memory/repository.js";
3
3
  import "../../../knowledge-memory/index.js";
4
4
  import { createPriorityWindow, createUserGoal, listPriorityWindows, listUserGoals, setUserGoalStatus } from "../../../user-model/goals.js";
5
- import { getAssertionSlot, getUserAssertion, listUserAssertionSources, listUserAssertions, reconcileAssertion, setAssertionStatus } from "../../../user-model/repository.js";
5
+ import { deleteUserAssertion, getAssertionSlot, getUserAssertion, listUserAssertionSources, listUserAssertions, reconcileAssertion, setAssertionStatus } from "../../../user-model/repository.js";
6
6
  import { applyUserProfilePatch, getUserProfileSnapshot } from "../../../user-model/profile.js";
7
7
  import { bootstrapUserModel } from "../../../user-model/bootstrap.js";
8
+ import { canUseAssertion } from "../../../user-model/usage-policy.js";
8
9
  import "../../../user-model/index.js";
9
10
  import { listMemoryMaintenanceRuns } from "../../../memory-maintenance/service.js";
10
11
  import "../../../memory-maintenance/index.js";
@@ -117,7 +118,8 @@ function assertionView(assertion, sources = listUserAssertionSources([assertion.
117
118
  predicate: slot.predicate,
118
119
  subject: slot.subject,
119
120
  scope: slot.scope,
120
- sources
121
+ sources,
122
+ usable: canUseAssertion(assertion)
121
123
  };
122
124
  }
123
125
  function registerUserModelRoutes(authenticated, deps) {
@@ -259,11 +261,14 @@ function registerUserModelRoutes(authenticated, deps) {
259
261
  createdBy: "user",
260
262
  ...typeof input.correctionOfAssertionId === "string" ? { correctionOfAssertionId: input.correctionOfAssertionId } : {}
261
263
  };
262
- return c.json(reconcileAssertion(candidate), 201);
264
+ return c.json(reconcileAssertion(candidate, Date.now(), { restoreDeleted: true }), 201);
263
265
  } catch (error) {
264
266
  return c.json({ error: errorMessage(error) }, 400);
265
267
  }
266
268
  });
269
+ authenticated.delete("/api/user-model/assertions/:id", write, (c) => {
270
+ return deleteUserAssertion(c.req.param("id")) ? c.json({ ok: true }) : c.json({ error: "Assertion not found" }, 404);
271
+ });
267
272
  authenticated.patch("/api/user-model/assertions/:id/status", write, async (c) => {
268
273
  const input = await body(c);
269
274
  const status = input?.status;
@@ -307,7 +312,6 @@ function registerUserModelRoutes(authenticated, deps) {
307
312
  ...current.validFrom === void 0 ? {} : { validFrom: current.validFrom },
308
313
  ...current.validTo === void 0 ? {} : { validTo: current.validTo },
309
314
  observedAt: Date.now(),
310
- ...current.reviewAt === void 0 ? {} : { reviewAt: current.reviewAt },
311
315
  createdBy: "user",
312
316
  correctionOfAssertionId: current.id
313
317
  }));
@@ -405,6 +409,9 @@ function registerUserModelRoutes(authenticated, deps) {
405
409
  const item = getKnowledgeItem(c.req.param("id"));
406
410
  return item ? c.json({ item }) : c.json({ error: "Knowledge item not found" }, 404);
407
411
  });
412
+ authenticated.delete("/api/knowledge-memory/:id", write, (c) => {
413
+ return deleteKnowledgeItem(c.req.param("id")) ? c.json({ ok: true }) : c.json({ error: "Knowledge item not found" }, 404);
414
+ });
408
415
  authenticated.post("/api/knowledge-memory/:id/review", write, async (c) => {
409
416
  const input = await body(c);
410
417
  const action = String(input?.action ?? "");
@@ -216,36 +216,6 @@ function registerWorkDiscoveryRoutes(authenticated, deps) {
216
216
  }, 400);
217
217
  }
218
218
  });
219
- authenticated.post("/api/work-discovery/runs/:runId/profile", limited, async (c) => {
220
- const body = await c.req.json().catch(() => null);
221
- const decisions = (body && typeof body === "object" && Array.isArray(body.decisions) ? body.decisions : []).flatMap((value) => {
222
- if (!value || typeof value !== "object") return [];
223
- const item = value;
224
- const id = typeof item.id === "string" ? item.id.trim() : "";
225
- const status = item.status === "accepted" || item.status === "edited" || item.status === "rejected" ? item.status : void 0;
226
- if (!id || !status) return [];
227
- return [{
228
- id,
229
- status,
230
- ...typeof item.statement === "string" ? { statement: item.statement } : {}
231
- }];
232
- }).slice(0, 10);
233
- if (!decisions.length) return c.json({
234
- ok: false,
235
- error: "At least one valid decision is required"
236
- }, 400);
237
- const run = service.updateProfileCandidates({
238
- runId: c.req.param("runId"),
239
- decisions
240
- });
241
- return run ? c.json({
242
- ok: true,
243
- run
244
- }) : c.json({
245
- ok: false,
246
- error: "Profile candidates not found"
247
- }, 404);
248
- });
249
219
  authenticated.post("/api/work-discovery/runs/:runId/suggestions/:suggestionId/select", (c) => {
250
220
  return service.selectSuggestion(c.req.param("runId"), c.req.param("suggestionId")) ? c.json({ ok: true }) : c.json({
251
221
  ok: false,
@@ -59,12 +59,6 @@ import { registerClarificationChannelRuntime } from "./clarify-runtime.js";
59
59
  import { ChannelManager } from "../channels/manager.js";
60
60
  import { getWorkspacePath } from "../config/workspace-path-helpers.js";
61
61
  import "../config/index.js";
62
- import { DiscussionService } from "../discussions/service.js";
63
- import { DiscussionOrganizer } from "../discussions/organizer.js";
64
- import { DiscussionLiveWorker } from "../discussions/live-worker.js";
65
- import { DiscussionOrganizerWorker } from "../discussions/organizer-worker.js";
66
- import { DiscussionSealer } from "../discussions/sealer.js";
67
- import "../discussions/index.js";
68
62
  import { ManagedComposioEventPoller } from "../connectors/composio-managed-events.js";
69
63
  import { startConnectedKnowledgeCoordinator } from "../knowledge/coordinator.js";
70
64
  import "../knowledge/index.js";
@@ -72,6 +66,12 @@ import { ConnectionRecoveryService } from "../connectors/connection-recovery-ser
72
66
  import { startConnectorLearningCoordinator } from "../connectors/learning-coordinator.js";
73
67
  import { ConnectedSourceChangePublisher } from "../connectors/source-change-publisher.js";
74
68
  import { startConnectorSupervisor } from "../connectors/supervisor.js";
69
+ import { DiscussionService } from "../discussions/service.js";
70
+ import { DiscussionOrganizer } from "../discussions/organizer.js";
71
+ import { DiscussionLiveWorker } from "../discussions/live-worker.js";
72
+ import { DiscussionOrganizerWorker } from "../discussions/organizer-worker.js";
73
+ import { DiscussionSealer } from "../discussions/sealer.js";
74
+ import "../discussions/index.js";
75
75
  import { EndpointToolRuntime } from "../endpoint-tools/runtime.js";
76
76
  import "../endpoint-tools/index.js";
77
77
  import { assertGatewayAuthConfigured, extractToken, resolveGatewayAuth, validateToken } from "./auth.js";
@@ -2,8 +2,8 @@ import { createLogger } from "../utils/logger/index.js";
2
2
  import { init_logger } from "../utils/logger.js";
3
3
  import { init_paths, resolveConfigPath } from "../config/paths.js";
4
4
  import { init_loader, loadConfig } from "../config/loader.js";
5
- import { resolveGatewayService } from "../daemon/service.js";
6
5
  import { isRestartEnabled } from "../config/commands.flags.js";
6
+ import { resolveGatewayService } from "../daemon/service.js";
7
7
  import { authorizeGatewaySigusr1Restart, writeGatewayRestartIntentSync } from "./restart.js";
8
8
  import { findVerifiedGatewayListenerPidsOnPortSync, signalVerifiedGatewayPidSync } from "./gateway-processes.js";
9
9
  import { refreshGatewayServiceAfterUpdate } from "./update-service-refresh.js";
@@ -106,7 +106,7 @@ var ConnectedKnowledgePipeline = class {
106
106
  status: "completed"
107
107
  });
108
108
  result.completed += 1;
109
- result.recordIds.push(written.item.id);
109
+ if (written.item) result.recordIds.push(written.item.id);
110
110
  } catch (error) {
111
111
  const message = error instanceof Error ? error.message : String(error);
112
112
  completeKnowledgeSourceItemSynthesis({