@xopcai/xopc 0.0.208 → 0.0.210

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 (182) 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/{activity-store-D0mYZqhc.js → activity-store-JLmEb1p0.js} +1 -1
  4. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-MWLQWL_i.js → agent-avatar-dicebear-CI1zQfzY.js} +1 -1
  5. package/dist/gateway/static/root/assets/agents-DqGMj3QJ.js +68 -0
  6. package/dist/gateway/static/root/assets/{api-DZA1yVzM.js → api-C6MmWfcb.js} +1 -1
  7. package/dist/gateway/static/root/assets/{app-management-settings-panel-B2X6quAF.js → app-management-settings-panel-Cd02GGpV.js} +1 -1
  8. package/dist/gateway/static/root/assets/{appearance-settings-BZW-c38q.js → appearance-settings-Db-h2I3G.js} +1 -1
  9. package/dist/gateway/static/root/assets/apps-page-BT7F4WBI.js +1 -0
  10. package/dist/gateway/static/root/assets/{archive-plugin-CK-gsjsJ.js → archive-plugin-CMHzJT2a.js} +1 -1
  11. package/dist/gateway/static/root/assets/{attachment-load-EJGP4rCw.js → attachment-load-BzhI2LoH.js} +1 -1
  12. package/dist/gateway/static/root/assets/automations-page-CwOXGV9z.js +6 -0
  13. package/dist/gateway/static/root/assets/{binary-plugins-Tbss_4P-.js → binary-plugins-DsUeHvZO.js} +1 -1
  14. package/dist/gateway/static/root/assets/{block-editor-C-dOWigw.js → block-editor-CFfsIeZ4.js} +47 -47
  15. package/dist/gateway/static/root/assets/{browser-settings-page-NlvDyMwD.js → browser-settings-page-CyRLhCod.js} +4 -4
  16. package/dist/gateway/static/root/assets/{browser-workflow-inputs-DW06Zo1N.js → browser-workflow-inputs-BiWghvJ0.js} +1 -1
  17. package/dist/gateway/static/root/assets/{browser-workflows-page-B6RnRGwm.js → browser-workflows-page-DPLdT6Zn.js} +1 -1
  18. package/dist/gateway/static/root/assets/capabilities-settings-panel-jRKcS7lZ.js +7 -0
  19. package/dist/gateway/static/root/assets/{capability-presets-api-Cc3BtQar.js → capability-presets-api-CTxGFvsS.js} +1 -1
  20. package/dist/gateway/static/root/assets/{capability-presets-settings-panel-D0loEbzq.js → capability-presets-settings-panel-B3bKdtwU.js} +2 -2
  21. package/dist/gateway/static/root/assets/{channel-recipient-api-BvZO5FaO.js → channel-recipient-api-BklVUOxC.js} +1 -1
  22. package/dist/gateway/static/root/assets/channels-settings-yZBWH02s.js +1 -0
  23. package/dist/gateway/static/root/assets/channels-status-swr-C3zlimZd.js +1 -0
  24. package/dist/gateway/static/root/assets/chat-terminal-dock-0F4Jmma2.js +36 -0
  25. package/dist/gateway/static/root/assets/{connectors-api-CUl6_EQJ.js → connectors-api-BvIZ51ty.js} +1 -1
  26. package/dist/gateway/static/root/assets/connectors-page-OX4KvUkA.js +2 -0
  27. package/dist/gateway/static/root/assets/{cron-expression-BD9MgoE_.js → cron-expression-BHmwaMbO.js} +1 -1
  28. package/dist/gateway/static/root/assets/{date-picker-ChqNmoxw.js → date-picker-fj_pPCv5.js} +1 -1
  29. package/dist/gateway/static/root/assets/{dependency-picker-CDUmFs6H.js → dependency-picker-DsWvwOv-.js} +1 -1
  30. package/dist/gateway/static/root/assets/{desktop-pet-D61gqxaD.js → desktop-pet-mjkF0Xxh.js} +1 -1
  31. package/dist/gateway/static/root/assets/{desktop-pet-settings-QvuJvIX_.js → desktop-pet-settings-ClwUpRYu.js} +1 -1
  32. package/dist/gateway/static/root/assets/{directory-picker-path-field-DvXMvDNY.js → directory-picker-path-field-OkqRFyRL.js} +1 -1
  33. package/dist/gateway/static/root/assets/{extension-debug-page-DMdVTAQ3.js → extension-debug-page-DC69wplH.js} +1 -1
  34. package/dist/gateway/static/root/assets/{extension-page-BNzxZtaK.js → extension-page-DCtk6zdJ.js} +1 -1
  35. package/dist/gateway/static/root/assets/{extension-settings-page-DoEfyizU.js → extension-settings-page-Bkm4zzv-.js} +1 -1
  36. package/dist/gateway/static/root/assets/{gateway-config-api-o7AKvthC.js → gateway-config-api-Dr_NQt7v.js} +1 -1
  37. package/dist/gateway/static/root/assets/{gateway-config-swr-BQbkUP5X.js → gateway-config-swr-CEfv8N1J.js} +1 -1
  38. package/dist/gateway/static/root/assets/gateway-settings-V1XVxjHa.js +1 -0
  39. package/dist/gateway/static/root/assets/{gateway-startup-retry-DIgdpHgk.js → gateway-startup-retry-B8hebJ7s.js} +1 -1
  40. package/dist/gateway/static/root/assets/{heartbeat-settings-UZAn1aAQ.js → heartbeat-settings-CWUBAQrE.js} +1 -1
  41. package/dist/gateway/static/root/assets/home-page-D57cYRd3.js +1 -0
  42. package/dist/gateway/static/root/assets/index-DJ7HSgKs.js +85 -0
  43. package/dist/gateway/static/root/assets/index-PNBFdxHb.css +2 -0
  44. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-4xaM3jjU.js → keyboard-shortcuts-settings-DCQvf05d.js} +1 -1
  45. package/dist/gateway/static/root/assets/{local-app-workbench-page-D9bguWRo.js → local-app-workbench-page-BbAiMZE1.js} +2 -2
  46. package/dist/gateway/static/root/assets/{local-apps-page-C1xDicdr.js → local-apps-page-B3Ugd0my.js} +1 -1
  47. package/dist/gateway/static/root/assets/{locale-store-pByvK12G.js → locale-store-hDBVeG3G.js} +1 -1
  48. package/dist/gateway/static/root/assets/{logs-page-Gr-nE4nW.js → logs-page-nXdF3wOT.js} +1 -1
  49. package/dist/gateway/static/root/assets/{management-settings-D1XdHm7v.js → management-settings-C-S5Llq3.js} +1 -1
  50. package/dist/gateway/static/root/assets/{markdown-split-B_Ijq1Fr.js → markdown-split-DuVq37Uh.js} +1 -1
  51. package/dist/gateway/static/root/assets/{markdown-view-CyJlGUxB.js → markdown-view-D8eO_6h3.js} +1 -1
  52. package/dist/gateway/static/root/assets/{media-plugins-CXXNRROJ.js → media-plugins-C1V6pkX3.js} +1 -1
  53. package/dist/gateway/static/root/assets/messages-1qg_hOOd.js +3 -0
  54. package/dist/gateway/static/root/assets/{notes-page-rkePB4CB.js → notes-page-Dn71ZV8c.js} +1 -1
  55. package/dist/gateway/static/root/assets/notes-workbench-BYPoZeRw.js +4 -0
  56. package/dist/gateway/static/root/assets/{page-tabs-gw-RMQCV.js → page-tabs-B5a5aSoS.js} +1 -1
  57. package/dist/gateway/static/root/assets/{preview-open-alternatives-B8aMScJ2.js → preview-open-alternatives-5041AIBX.js} +1 -1
  58. package/dist/gateway/static/root/assets/{product-open-page-CjcpkWAz.js → product-open-page-7UkouFQU.js} +1 -1
  59. package/dist/gateway/static/root/assets/project-detail-page-D27nOKbo.js +1 -0
  60. package/dist/gateway/static/root/assets/{projects-page-DPRxKGbs.js → projects-page-CdB5cJJ-.js} +1 -1
  61. package/dist/gateway/static/root/assets/remote-access-hub-DFoZ3UNS.js +1 -0
  62. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-Ch5qq86o.js → runtime-tools-settings-panel-DvaXzHYS.js} +1 -1
  63. package/dist/gateway/static/root/assets/{schema-form-DHYWYUFt.js → schema-form-Dlxl_5X0.js} +1 -1
  64. package/dist/gateway/static/root/assets/sessions-page-C1cbIcJ7.js +1 -0
  65. package/dist/gateway/static/root/assets/settings-advanced-gate-DnXRlQXS.js +1 -0
  66. package/dist/gateway/static/root/assets/{settings-form-section-DlzZx0-i.js → settings-form-section-CSaiuuer.js} +1 -1
  67. package/dist/gateway/static/root/assets/{settings-loading-skeleton-BVLhreQi.js → settings-loading-skeleton-H3mJwt3r.js} +1 -1
  68. package/dist/gateway/static/root/assets/{settings-page-BJU-kUnN.js → settings-page-Cs7zA4BS.js} +1 -1
  69. package/dist/gateway/static/root/assets/setup-status-panel-CwgMODfJ.js +1 -0
  70. package/dist/gateway/static/root/assets/{share-preview-page-hvIuZXMe.js → share-preview-page-Bdpw5m7M.js} +1 -1
  71. package/dist/gateway/static/root/assets/shares-settings-hlUgIkrp.js +1 -0
  72. package/dist/gateway/static/root/assets/skill-reload-api-DR31B_Gz.js +1 -0
  73. package/dist/gateway/static/root/assets/{skills-page-Dlvuh7D-.js → skills-page-Bup3Lg1Z.js} +1 -1
  74. package/dist/gateway/static/root/assets/{skills-page.utils-B6ddOpnf.js → skills-page.utils-D22ORR21.js} +1 -1
  75. package/dist/gateway/static/root/assets/{system-settings-panel-BdbCAyoA.js → system-settings-panel-GmtWsfjB.js} +1 -1
  76. package/dist/gateway/static/root/assets/task-detail-page-CTKDpxhf.js +1 -0
  77. package/dist/gateway/static/root/assets/{theme-store-BtdGacMI.js → theme-store-CtY8RwMX.js} +1 -1
  78. package/dist/gateway/static/root/assets/{typed-models-lib-CL6qHYJA.js → typed-models-lib-C2aOdlEA.js} +1 -1
  79. package/dist/gateway/static/root/assets/{use-autosave-DysNnqCS.js → use-autosave-DOj5i8d_.js} +1 -1
  80. package/dist/gateway/static/root/assets/{user-context-page-Bwg4KV8B.js → user-context-page-keJJYpix.js} +1 -1
  81. package/dist/gateway/static/root/assets/{voice-api-key-field-UEsO9Jr-.js → voice-api-key-field-5WfurWYa.js} +1 -1
  82. package/dist/gateway/static/root/assets/{work-discovery-overlay-B9disASf.js → work-discovery-overlay-D5_MH3n3.js} +1 -1
  83. package/dist/gateway/static/root/assets/{work-discovery-page-CmPfOfHl.js → work-discovery-page-BcvBiebt.js} +1 -1
  84. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-A0zTQHFQ.js → workflow-run-setup-panel-bBA8LinI.js} +1 -1
  85. package/dist/gateway/static/root/assets/workflows-page-Cz2VpWdj.js +5 -0
  86. package/dist/gateway/static/root/index.html +9 -9
  87. package/dist/package.js +1 -1
  88. package/dist/src/agent/agent-manager.js +2 -2
  89. package/dist/src/agent/background-review/coordinator.d.ts +1 -1
  90. package/dist/src/agent/background-review/coordinator.js +4 -5
  91. package/dist/src/agent/background-review/run-background-review.js +0 -1
  92. package/dist/src/agent/background-review/settings.d.ts +1 -2
  93. package/dist/src/agent/background-review/settings.js +3 -4
  94. package/dist/src/agent/external-tools/composio-provider.js +8 -4
  95. package/dist/src/agent/memory/builtin-provider.js +1 -1
  96. package/dist/src/agent/memory/create-memory-manager.js +1 -1
  97. package/dist/src/agent/memory/manager.js +2 -0
  98. package/dist/src/agent/memory/sensitivity.js +1 -1
  99. package/dist/src/agent/memory/understanding/service.js +43 -19
  100. package/dist/src/agent/memory/user-context-coordinator.js +1 -1
  101. package/dist/src/agent-runtime/index.js +1 -1
  102. package/dist/src/agent-runtime/runtime-profile.js +1 -1
  103. package/dist/src/automations/domain/validation.d.ts +7 -7
  104. package/dist/src/automations/draft/automation-draft-validator.d.ts +2 -2
  105. package/dist/src/connectors/auth-provider-registry.d.ts +2 -1
  106. package/dist/src/connectors/auth-provider-registry.js +5 -2
  107. package/dist/src/connectors/composio-sessions.d.ts +38 -0
  108. package/dist/src/connectors/composio-sessions.js +64 -6
  109. package/dist/src/connectors/composio.d.ts +4 -1
  110. package/dist/src/connectors/composio.js +26 -4
  111. package/dist/src/connectors/runtime-adapter-registry.js +14 -1
  112. package/dist/src/gateway/heartbeat/service.js +1 -1
  113. package/dist/src/gateway/hono/routes/agent-stream.js +4 -1
  114. package/dist/src/gateway/hono/routes/connectors.js +15 -2
  115. package/dist/src/gateway/hono/routes/session-input-handler.d.ts +60 -0
  116. package/dist/src/gateway/hono/routes/session-input-handler.js +75 -1
  117. package/dist/src/gateway/service/agent-runner.d.ts +9 -1
  118. package/dist/src/gateway/service/agent-runner.js +9 -0
  119. package/dist/src/gateway/service/session-input-coordinator.d.ts +12 -0
  120. package/dist/src/gateway/service/session-input-coordinator.js +64 -6
  121. package/dist/src/gateway/service.d.ts +8 -0
  122. package/dist/src/gateway/service.js +8 -5
  123. package/dist/src/heartbeat/index.js +1 -1
  124. package/dist/src/retrieval/audit.d.ts +1 -0
  125. package/dist/src/retrieval/audit.js +8 -0
  126. package/dist/src/retrieval/candidateFusion.d.ts +5 -0
  127. package/dist/src/retrieval/candidateFusion.js +20 -0
  128. package/dist/src/retrieval/queryProfile.d.ts +16 -0
  129. package/dist/src/retrieval/queryProfile.js +66 -0
  130. package/dist/src/retrieval/textFeatures.d.ts +5 -0
  131. package/dist/src/retrieval/textFeatures.js +71 -0
  132. package/dist/src/session/client-history.d.ts +1 -0
  133. package/dist/src/session/client-history.js +4 -0
  134. package/dist/src/session/index.js +1 -1
  135. package/dist/src/session/store.js +1 -1
  136. package/dist/src/storage/sqlite/fts.d.ts +0 -4
  137. package/dist/src/storage/sqlite/fts.js +2 -49
  138. package/dist/src/storage/sqlite/index.d.ts +3 -2
  139. package/dist/src/storage/sqlite/index.js +6 -5
  140. package/dist/src/storage/sqlite/memory-records-repository.js +60 -38
  141. package/dist/src/storage/sqlite/row-mappers.js +2 -2
  142. package/dist/src/storage/sqlite/session-repository.js +2 -2
  143. package/dist/src/storage/sqlite/session-turn-replace-repository.d.ts +34 -0
  144. package/dist/src/storage/sqlite/session-turn-replace-repository.js +110 -0
  145. package/dist/src/storage/sqlite/transcript-repository.js +1 -1
  146. package/dist/src/storage/sqlite/user-context-quality-repository.d.ts +7 -0
  147. package/dist/src/storage/sqlite/user-context-quality-repository.js +25 -1
  148. package/dist/src/storage/sqlite/user-context-repository.d.ts +4 -0
  149. package/dist/src/storage/sqlite/user-context-repository.js +29 -3
  150. package/dist/src/tasks/home-query-service.d.ts +3 -1
  151. package/dist/src/tasks/home-query-service.js +73 -70
  152. package/dist/src/tui/backends/embedded-backend.js +1 -1
  153. package/dist/src/user-context/planner.d.ts +1 -0
  154. package/dist/src/user-context/planner.js +16 -29
  155. package/dist/src/user-context/retriever.d.ts +15 -0
  156. package/dist/src/user-context/retriever.js +65 -0
  157. package/dist/src/user-context/scope.d.ts +7 -0
  158. package/dist/src/user-context/scope.js +9 -0
  159. package/package.json +1 -1
  160. package/dist/gateway/static/root/assets/agents-Bl8FQZxW.js +0 -68
  161. package/dist/gateway/static/root/assets/apps-page-CRUgTO10.js +0 -1
  162. package/dist/gateway/static/root/assets/automations-page-DrSwolhG.js +0 -6
  163. package/dist/gateway/static/root/assets/capabilities-settings-panel-BWXUznw5.js +0 -7
  164. package/dist/gateway/static/root/assets/channels-settings-CcivCw8U.js +0 -1
  165. package/dist/gateway/static/root/assets/channels-status-swr-DkHAD2Zn.js +0 -1
  166. package/dist/gateway/static/root/assets/chat-terminal-dock-DVedGAeX.js +0 -36
  167. package/dist/gateway/static/root/assets/connectors-page-DlBSlfkv.js +0 -2
  168. package/dist/gateway/static/root/assets/gateway-settings-TO5YYZ9a.js +0 -1
  169. package/dist/gateway/static/root/assets/home-page-CRJDpy5E.js +0 -3
  170. package/dist/gateway/static/root/assets/index-BSjP0Wsx.css +0 -2
  171. package/dist/gateway/static/root/assets/index-C2ZYFBGL.js +0 -85
  172. package/dist/gateway/static/root/assets/messages-yG5P43Q9.js +0 -3
  173. package/dist/gateway/static/root/assets/notes-workbench-CpbD4XG2.js +0 -4
  174. package/dist/gateway/static/root/assets/project-detail-page-GvSYDbjR.js +0 -1
  175. package/dist/gateway/static/root/assets/remote-access-hub-WIzeu-gB.js +0 -1
  176. package/dist/gateway/static/root/assets/sessions-page-2XEJM0YE.js +0 -1
  177. package/dist/gateway/static/root/assets/settings-advanced-gate-g1GThZ0O.js +0 -1
  178. package/dist/gateway/static/root/assets/setup-status-panel-C6qj2L-q.js +0 -1
  179. package/dist/gateway/static/root/assets/shares-settings-BBpE1bep.js +0 -1
  180. package/dist/gateway/static/root/assets/skill-reload-api-DXORBJNk.js +0 -1
  181. package/dist/gateway/static/root/assets/task-detail-page-DC0hc8hp.js +0 -1
  182. package/dist/gateway/static/root/assets/workflows-page-DhQNh7W6.js +0 -5
@@ -14,6 +14,7 @@ type HomeAttention = HomeResponse['attention'][number];
14
14
  type HomeBriefingWin = HomeResponse['briefing']['wins'][number];
15
15
  type HomeAutomation = HomeResponse['upcomingAutomations'][number];
16
16
  type HomeFocusItem = HomeResponse['focusItems'][number];
17
+ type HomeRecentTask = HomeResponse['recentTasks'][number];
17
18
  type HomeWorkflowRun = {
18
19
  id: string;
19
20
  definitionId: string;
@@ -151,7 +152,8 @@ export declare function buildHomeFocusItems(input: {
151
152
  activeWorkflowRuns: HomeWorkflowRun[];
152
153
  runningTasks: HomeResponse['tasks']['running'];
153
154
  wins: HomeBriefingWin[];
154
- nextScheduled?: HomeAutomation;
155
+ scheduled: HomeAutomation[];
156
+ recentTasks: HomeRecentTask[];
155
157
  inboxCount: number;
156
158
  nowMs: number;
157
159
  }): HomeFocusItem[];
@@ -124,6 +124,10 @@ function homeActionCopy(locale) {
124
124
  viewProgress: "查看进度",
125
125
  viewResult: "查看结果",
126
126
  viewSchedule: "查看计划",
127
+ remaining: "项待继续",
128
+ taskCompleted: "任务已完成",
129
+ workflowCompleted: "工作流已完成",
130
+ automationCompleted: "自动化已完成",
127
131
  runningTask: "任务正在推进",
128
132
  runningWorkflow: "工作流正在推进",
129
133
  scheduled: "下一项定时工作",
@@ -142,6 +146,10 @@ function homeActionCopy(locale) {
142
146
  viewProgress: "View progress",
143
147
  viewResult: "View result",
144
148
  viewSchedule: "View schedule",
149
+ remaining: "remaining",
150
+ taskCompleted: "Task completed",
151
+ workflowCompleted: "Workflow completed",
152
+ automationCompleted: "Automation completed",
145
153
  runningTask: "Task in progress",
146
154
  runningWorkflow: "Workflow in progress",
147
155
  scheduled: "Next scheduled work",
@@ -153,23 +161,26 @@ function homeActionCopy(locale) {
153
161
  askAi: "Ask an agent"
154
162
  };
155
163
  }
164
+ function formatScheduleDistance(value, nowMs, locale) {
165
+ const distanceMs = Math.max(0, Date.parse(value) - nowMs);
166
+ const formatter = new Intl.RelativeTimeFormat(locale, { numeric: "always" });
167
+ const minutes = Math.max(1, Math.ceil(distanceMs / 6e4));
168
+ if (minutes < 60) return formatter.format(minutes, "minute");
169
+ const hours = Math.ceil(distanceMs / 36e5);
170
+ if (hours < 48) return formatter.format(hours, "hour");
171
+ return formatter.format(Math.ceil(distanceMs / 864e5), "day");
172
+ }
156
173
  function buildHomeFocusItems(input) {
157
174
  const copy = homeActionCopy(input.locale);
158
175
  const decisions = input.decisions.map((decision) => {
159
176
  const openAction = decision.kind === "agent_judgment" && decision.judgment ? {
160
- type: "open",
177
+ type: "review_judgment",
161
178
  label: copy.review,
162
- target: "inbox_judgment",
163
- targetId: decision.judgment.inboxItemId
164
- } : decision.kind === "task" ? {
165
- type: "open",
166
- label: copy.review,
167
- target: "task",
168
- targetId: decision.id.replace(/^task:/, "")
179
+ itemId: decision.judgment.inboxItemId
169
180
  } : {
170
181
  type: "open",
171
182
  label: copy.review,
172
- target: "work"
183
+ href: decision.href
173
184
  };
174
185
  const connectorActions = decision.response?.kind === "connector_approval" ? {
175
186
  primaryAction: {
@@ -196,7 +207,6 @@ function buildHomeFocusItems(input) {
196
207
  summary: decision.detail || copy.review,
197
208
  statusLabel: copy.review,
198
209
  updatedAt: decision.updatedAt,
199
- pinnable: false,
200
210
  openAction,
201
211
  ...connectorActions
202
212
  };
@@ -208,22 +218,10 @@ function buildHomeFocusItems(input) {
208
218
  title: item.title,
209
219
  summary: item.detail,
210
220
  updatedAt: item.updatedAt,
211
- pinnable: false,
212
- openAction: item.kind === "workflow_run" ? item.sessionKey ? {
213
- type: "open",
214
- label: copy.review,
215
- target: "session",
216
- sessionKey: item.sessionKey
217
- } : {
218
- type: "open",
219
- label: copy.review,
220
- target: "workflow_run",
221
- targetId: item.runId
222
- } : {
221
+ openAction: {
223
222
  type: "open",
224
223
  label: copy.review,
225
- target: "automation",
226
- targetId: item.runId
224
+ href: item.href
227
225
  },
228
226
  primaryAction: {
229
227
  type: "retry_run",
@@ -239,16 +237,10 @@ function buildHomeFocusItems(input) {
239
237
  }]
240
238
  }));
241
239
  const workflows = input.activeWorkflowRuns.map((run) => {
242
- const openAction = run.sessionKey ? {
243
- type: "open",
244
- label: copy.viewProgress,
245
- target: "session",
246
- sessionKey: run.sessionKey
247
- } : {
240
+ const openAction = {
248
241
  type: "open",
249
242
  label: copy.viewProgress,
250
- target: "workflow_run",
251
- targetId: run.id
243
+ href: run.sessionKey ? `/chat/${encodeURIComponent(run.sessionKey)}` : `/workflows?runId=${encodeURIComponent(run.id)}`
252
244
  };
253
245
  return {
254
246
  id: `workflow:${run.id}`,
@@ -258,7 +250,6 @@ function buildHomeFocusItems(input) {
258
250
  summary: copy.runningWorkflow,
259
251
  statusLabel: run.metrics.agentCount > 0 ? `${run.metrics.doneAgentCount}/${run.metrics.agentCount}` : void 0,
260
252
  updatedAt: run.startedAtMs ?? run.createdAtMs,
261
- pinnable: true,
262
253
  openAction,
263
254
  primaryAction: openAction,
264
255
  secondaryActions: []
@@ -268,8 +259,7 @@ function buildHomeFocusItems(input) {
268
259
  const openAction = {
269
260
  type: "open",
270
261
  label: copy.viewProgress,
271
- target: "task",
272
- targetId: task.id
262
+ href: `/tasks/${encodeURIComponent(task.id)}`
273
263
  };
274
264
  return {
275
265
  id: `task:${task.id}`,
@@ -278,73 +268,82 @@ function buildHomeFocusItems(input) {
278
268
  title: task.title,
279
269
  summary: copy.runningTask,
280
270
  updatedAt: task.updatedAt,
281
- pinnable: true,
282
271
  openAction,
283
272
  primaryAction: openAction,
284
273
  secondaryActions: []
285
274
  };
286
275
  });
287
276
  const results = input.wins.map((win) => {
288
- const openAction = win.kind === "workflow_run" ? {
289
- type: "open",
290
- label: copy.viewResult,
291
- target: "workflow_run",
292
- targetId: win.id.replace(/^workflow:/, "")
293
- } : win.kind === "automation_run" ? {
294
- type: "open",
295
- label: copy.viewResult,
296
- target: "automation",
297
- targetId: win.id.replace(/^automation:/, "")
298
- } : {
277
+ const openAction = {
299
278
  type: "open",
300
279
  label: copy.viewResult,
301
- target: "task",
302
- targetId: win.id.replace(/^task:/, "")
280
+ href: win.href
303
281
  };
304
282
  return {
305
283
  id: win.id,
306
284
  kind: "result",
307
285
  priority: 40,
308
286
  title: win.title,
309
- summary: copy.viewResult,
287
+ summary: win.kind === "workflow_run" ? copy.workflowCompleted : win.kind === "automation_run" ? copy.automationCompleted : copy.taskCompleted,
310
288
  updatedAt: win.completedAt,
311
- pinnable: true,
312
289
  openAction,
313
290
  primaryAction: openAction,
314
291
  secondaryActions: []
315
292
  };
316
293
  });
317
- const scheduled = input.nextScheduled ? [{
318
- id: `automation:${input.nextScheduled.id}:scheduled`,
294
+ const taskResults = input.recentTasks.map(({ taskId, taskTitle, receipt }) => {
295
+ const openAction = {
296
+ type: "open",
297
+ label: copy.viewResult,
298
+ href: `/tasks/${encodeURIComponent(taskId)}`
299
+ };
300
+ return {
301
+ id: `task-result:${taskId}:${receipt.runId}`,
302
+ kind: "result",
303
+ priority: 40,
304
+ title: taskTitle,
305
+ summary: receipt.summary,
306
+ statusLabel: receipt.remainingWork.length > 0 ? `${receipt.remainingWork.length} ${copy.remaining}` : void 0,
307
+ updatedAt: receipt.finalizedAt,
308
+ openAction,
309
+ primaryAction: openAction,
310
+ secondaryActions: []
311
+ };
312
+ });
313
+ const scheduled = input.scheduled.map((automation) => ({
314
+ id: `automation:${automation.id}:scheduled`,
319
315
  kind: "scheduled",
320
316
  priority: 30,
321
- title: input.nextScheduled.name || input.nextScheduled.id,
317
+ title: automation.name || automation.id,
322
318
  summary: copy.scheduled,
323
- statusLabel: new Date(input.nextScheduled.nextRunAt).toLocaleString(input.locale),
324
- updatedAt: Date.parse(input.nextScheduled.nextRunAt),
325
- pinnable: true,
319
+ statusLabel: formatScheduleDistance(automation.nextRunAt, input.nowMs, input.locale),
320
+ updatedAt: Date.parse(automation.nextRunAt),
326
321
  openAction: {
327
322
  type: "open",
328
323
  label: copy.viewSchedule,
329
- target: "automation",
330
- targetId: input.nextScheduled.id
324
+ href: `/automations?automation=${encodeURIComponent(automation.id)}`
331
325
  },
332
326
  primaryAction: {
333
327
  type: "open",
334
328
  label: copy.viewSchedule,
335
- target: "automation",
336
- targetId: input.nextScheduled.id
329
+ href: `/automations?automation=${encodeURIComponent(automation.id)}`
337
330
  },
338
331
  secondaryActions: []
339
- }] : [];
332
+ }));
340
333
  const items = [
341
334
  ...decisions,
342
335
  ...failures,
343
336
  ...workflows,
344
337
  ...tasks,
345
338
  ...results,
339
+ ...taskResults,
346
340
  ...scheduled
347
- ].sort((left, right) => right.priority - left.priority || right.updatedAt - left.updatedAt);
341
+ ].sort((left, right) => {
342
+ const priorityDelta = right.priority - left.priority;
343
+ if (priorityDelta !== 0) return priorityDelta;
344
+ if (left.kind === "scheduled" && right.kind === "scheduled") return left.updatedAt - right.updatedAt;
345
+ return right.updatedAt - left.updatedAt;
346
+ });
348
347
  if (items.length > 0) return items;
349
348
  if (input.inboxCount > 0) return [{
350
349
  id: "suggestion:organize-inbox",
@@ -353,16 +352,15 @@ function buildHomeFocusItems(input) {
353
352
  title: `${copy.organizeInbox} · ${input.inboxCount}`,
354
353
  summary: copy.organizeInboxSummary,
355
354
  updatedAt: input.nowMs,
356
- pinnable: false,
357
355
  openAction: {
358
356
  type: "open",
359
357
  label: copy.openInbox,
360
- target: "inbox"
358
+ href: "/notes?status=inbox"
361
359
  },
362
360
  primaryAction: {
363
361
  type: "open",
364
362
  label: copy.openInbox,
365
- target: "inbox"
363
+ href: "/notes?status=inbox"
366
364
  },
367
365
  secondaryActions: []
368
366
  }];
@@ -373,7 +371,6 @@ function buildHomeFocusItems(input) {
373
371
  title: copy.startSomething,
374
372
  summary: copy.startSomethingSummary,
375
373
  updatedAt: input.nowMs,
376
- pinnable: false,
377
374
  primaryAction: {
378
375
  type: "ask_ai",
379
376
  label: copy.askAi
@@ -525,7 +522,7 @@ var HomeQueryService = class {
525
522
  id: `automation:${run.id}`,
526
523
  kind: "automation_run",
527
524
  title: run.automationName || run.automationId,
528
- href: "/automations",
525
+ href: `/automations?automation=${encodeURIComponent(run.automationId)}&run=${encodeURIComponent(run.id)}`,
529
526
  completedAt: run.endedAtMs ?? run.createdAtMs
530
527
  }))].sort((left, right) => right.completedAt - left.completedAt);
531
528
  const runningTasks = tasks.filter((task) => {
@@ -542,6 +539,11 @@ var HomeQueryService = class {
542
539
  nextScheduled: upcomingAutomations[0],
543
540
  nowMs
544
541
  });
542
+ const recentTasks = tasks.flatMap((task) => this.#runs.listReceipts(task.id, 3).map((receipt) => ({
543
+ taskId: task.id,
544
+ taskTitle: task.title,
545
+ receipt
546
+ }))).sort((a, b) => b.receipt.finalizedAt - a.receipt.finalizedAt).slice(0, 8);
545
547
  return {
546
548
  focusItems: buildHomeFocusItems({
547
549
  locale,
@@ -550,7 +552,8 @@ var HomeQueryService = class {
550
552
  activeWorkflowRuns,
551
553
  runningTasks,
552
554
  wins,
553
- nextScheduled: upcomingAutomations[0],
555
+ scheduled: upcomingAutomations.slice(0, 3),
556
+ recentTasks: recentTasks.slice(0, 3),
554
557
  inboxCount: inbox.total,
555
558
  nowMs
556
559
  }),
@@ -590,7 +593,7 @@ var HomeQueryService = class {
590
593
  },
591
594
  upcomingAutomations,
592
595
  tasks: { running: runningTasks },
593
- recentTasks: tasks.flatMap((task) => this.#runs.listReceipts(task.id, 3)).sort((a, b) => b.finalizedAt - a.finalizedAt).slice(0, 8),
596
+ recentTasks,
594
597
  recentAutomationRuns: automationRuns.slice(0, 5).map(toHomeAutomationRun)
595
598
  };
596
599
  }
@@ -1,8 +1,8 @@
1
1
  import { createLogger } from "../../utils/logger/index.js";
2
2
  import { init_logger } from "../../utils/logger.js";
3
3
  import { openXopcDatabase } from "../../storage/sqlite/connection.js";
4
- import { appendComposerInputHistory, listComposerInputHistory } from "../../storage/sqlite/composer-input-history-repository.js";
5
4
  import { init_agent_session_key, resolveAgentIdFromSessionKey } from "../../routing/agent-session-key.js";
5
+ import { appendComposerInputHistory, listComposerInputHistory } from "../../storage/sqlite/composer-input-history-repository.js";
6
6
  import { getSessionMetadata } from "../../storage/sqlite/session-repository.js";
7
7
  import "../../storage/sqlite/index.js";
8
8
  import { getAgentDefaultModelRef, init_schema } from "../../config/schema.js";
@@ -2,6 +2,7 @@ import type { AgentMessage } from '@earendil-works/pi-agent-core';
2
2
  import type { UserContextPlan } from '../agent/memory/context/types.js';
3
3
  export declare function prependAgentContext(message: AgentMessage, block: string): AgentMessage;
4
4
  export declare class UserContextPlanner {
5
+ private readonly retriever;
5
6
  plan(params: {
6
7
  sessionKey: string;
7
8
  workspaceId: string;
@@ -1,8 +1,10 @@
1
- import { consumeContextConsent, ensureContextConsent, getUserProfile, listCollaborationRules, listUnderstandings, recordContextRun } from "../storage/sqlite/user-context-repository.js";
1
+ import { consumeContextConsent, ensureContextConsent, getUserProfile, listCollaborationRules, recordContextRun } from "../storage/sqlite/user-context-repository.js";
2
2
  import "../storage/sqlite/index.js";
3
3
  import { readAgentMessageContent } from "../agent/memory/agent-message-access.js";
4
4
  import { buildUserContextBlock } from "../agent/memory/context-fence.js";
5
5
  import { listUserFocuses } from "./sources/repository.js";
6
+ import { matchesUserContextScope } from "./scope.js";
7
+ import { UserUnderstandingRetriever } from "./retriever.js";
6
8
  import { randomUUID } from "node:crypto";
7
9
  //#region src/user-context/planner.ts
8
10
  const DEFAULT_MAX_CONTEXT_CHARS = 6e3;
@@ -33,28 +35,6 @@ function prependAgentContext(message, block) {
33
35
  }
34
36
  return message;
35
37
  }
36
- function scopeMatches(scope, input) {
37
- if (scope.type === "global") return true;
38
- if (scope.type === "session") return scope.id === input.sessionKey;
39
- if (scope.type === "workspace") return scope.id === input.workspaceId;
40
- return Boolean(input.projectId && scope.id === input.projectId);
41
- }
42
- function terms(value) {
43
- const normalized = value.toLocaleLowerCase().replace(/[^\p{L}\p{N}]+/gu, " ").trim();
44
- const words = normalized.split(/\s+/).filter((word) => word.length > 1);
45
- const cjk = [...normalized.replace(/[^\p{Script=Han}]/gu, "")];
46
- for (let index = 0; index < cjk.length - 1; index += 1) words.push(`${cjk[index]}${cjk[index + 1]}`);
47
- return new Set(words);
48
- }
49
- function relevance(query, item) {
50
- const queryTerms = terms(query);
51
- const itemTerms = terms(item.statement);
52
- const shared = [...queryTerms].filter((term) => itemTerms.has(term)).length;
53
- const lexical = queryTerms.size ? shared / queryTerms.size : 0;
54
- const baseline = item.kind === "boundary" && item.explicitness === "explicit" ? .8 : item.kind === "preference" && item.explicitness === "explicit" ? .35 : 0;
55
- const explicitness = item.explicitness === "explicit" ? .1 : item.explicitness === "observed" ? .05 : 0;
56
- return Math.min(1, Math.max(baseline, lexical * .75 + item.confidence * .15 + explicitness));
57
- }
58
38
  function sectionFor(item) {
59
39
  if (item.kind === "boundary") return "safety";
60
40
  if ([
@@ -77,18 +57,19 @@ function sourceLabel(item) {
77
57
  function rejectionReason(item, input, now) {
78
58
  if (item.status === "needs_review" || item.status === "stale" || item.status === "candidate") return "needs_review";
79
59
  if (item.status === "archived" || item.status === "rejected") return "disabled";
80
- if (!scopeMatches(item.scope, input)) return "scope_mismatch";
60
+ if (!matchesUserContextScope(item.scope, input)) return "scope_mismatch";
81
61
  if (item.validFrom && item.validFrom > now) return "not_yet_valid";
82
62
  if (item.validTo && item.validTo < now || item.expiresAt && item.expiresAt < now) return "expired";
83
63
  if (item.sensitivity === "secret" || item.sensitivity === "regulated") return "sensitive";
84
64
  if (item.conflictGroupId) return "conflict";
85
65
  }
86
66
  function ruleMatches(rule, input) {
87
- if (rule.status !== "active" || !scopeMatches(rule.scope, input)) return false;
67
+ if (rule.status !== "active" || !matchesUserContextScope(rule.scope, input)) return false;
88
68
  const channel = typeof rule.conditions.channel === "string" ? rule.conditions.channel : void 0;
89
69
  return !channel || channel === input.channel;
90
70
  }
91
71
  var UserContextPlanner = class {
72
+ retriever = new UserUnderstandingRetriever();
92
73
  plan(params) {
93
74
  const traceId = randomUUID();
94
75
  const query = params.query.trim();
@@ -176,10 +157,16 @@ var UserContextPlanner = class {
176
157
  injectedChars: rule.statement.length
177
158
  });
178
159
  }
179
- const ranked = listUnderstandings(["active"]).filter((item) => !excluded.has(item.id)).map((item) => ({
180
- item,
181
- score: relevance(query, item)
182
- })).sort((left, right) => right.score - left.score).slice(0, Math.max(maxResults * 5, 50));
160
+ const ranked = this.retriever.retrieve({
161
+ query,
162
+ sessionKey: params.sessionKey,
163
+ workspaceId: params.workspaceId,
164
+ ...params.projectId ? { projectId: params.projectId } : {},
165
+ maxCandidates: Math.max(maxResults * 5, 50)
166
+ }).filter((result) => !excluded.has(result.understanding.id)).map((result) => ({
167
+ item: result.understanding,
168
+ score: result.score
169
+ }));
183
170
  for (const { item, score } of ranked) {
184
171
  if (items.length >= maxResults) {
185
172
  rejected.push({
@@ -0,0 +1,15 @@
1
+ import type { UserUnderstanding } from './domain.js';
2
+ export interface UnderstandingRetrievalResult {
3
+ understanding: UserUnderstanding;
4
+ score: number;
5
+ reasons: string[];
6
+ }
7
+ export declare class UserUnderstandingRetriever {
8
+ retrieve(params: {
9
+ query: string;
10
+ sessionKey: string;
11
+ workspaceId: string;
12
+ projectId?: string;
13
+ maxCandidates: number;
14
+ }): UnderstandingRetrievalResult[];
15
+ }
@@ -0,0 +1,65 @@
1
+ import { summarizeUnderstandingFeedback } from "../storage/sqlite/user-context-quality-repository.js";
2
+ import { listUnderstandings, searchActiveUnderstandings } from "../storage/sqlite/user-context-repository.js";
3
+ import { normalizeRetrievalText, retrievalLexicalSimilarity } from "../retrieval/textFeatures.js";
4
+ import { buildRetrievalQueryProfile } from "../retrieval/queryProfile.js";
5
+ import "../storage/sqlite/index.js";
6
+ import { matchesUserContextScope } from "./scope.js";
7
+ //#region src/user-context/retriever.ts
8
+ function authorityBonus(item) {
9
+ if (item.explicitness === "explicit") return .1;
10
+ if (item.explicitness === "observed") return .05;
11
+ return 0;
12
+ }
13
+ function baseline(item) {
14
+ if (item.kind === "boundary" && item.explicitness === "explicit") return .8;
15
+ if (item.kind === "preference" && item.explicitness === "explicit") return .35;
16
+ return 0;
17
+ }
18
+ function feedbackAdjustment(summary) {
19
+ if (!summary || summary.total < 3) return 0;
20
+ const helpfulRate = (summary.helpful + 1) / (summary.total + 2);
21
+ const relevancePenalty = summary.irrelevant >= 3 ? .05 : 0;
22
+ return Math.max(-.1, Math.min(.05, (helpfulRate - .5) * .1 - relevancePenalty));
23
+ }
24
+ var UserUnderstandingRetriever = class {
25
+ retrieve(params) {
26
+ const profile = buildRetrievalQueryProfile(params.query, {
27
+ sessionKey: params.sessionKey,
28
+ workspaceId: params.workspaceId,
29
+ ...params.projectId ? { projectId: params.projectId } : {}
30
+ });
31
+ if (!profile.normalized) return [];
32
+ const maxCandidates = Math.max(1, Math.min(200, Math.floor(params.maxCandidates)));
33
+ const fts = searchActiveUnderstandings(profile.normalized, Math.max(50, maxCandidates));
34
+ const ftsScores = new Map(fts.map((result) => [result.understanding.id, result.score]));
35
+ const recentLimit = Math.max(200, Math.min(500, maxCandidates * 5));
36
+ const recent = listUnderstandings(["active"]).slice(0, recentLimit);
37
+ const candidates = /* @__PURE__ */ new Map();
38
+ for (const result of fts) candidates.set(result.understanding.id, result.understanding);
39
+ for (const item of recent) candidates.set(item.id, item);
40
+ const feedback = new Map(summarizeUnderstandingFeedback([...candidates.keys()]).map((summary) => [summary.understandingId, summary]));
41
+ return [...candidates.values()].map((item) => {
42
+ const lexical = retrievalLexicalSimilarity(profile.normalized, item.statement);
43
+ const ftsScore = ftsScores.get(item.id) ?? 0;
44
+ const textScore = Math.max(lexical, ftsScore);
45
+ const kindMatched = profile.intentKinds.includes(item.kind);
46
+ const normalizedStatement = normalizeRetrievalText(item.statement);
47
+ const identifierMatched = profile.identifiers.some((identifier) => normalizedStatement.includes(identifier));
48
+ const feedbackScore = feedbackAdjustment(feedback.get(item.id));
49
+ return {
50
+ understanding: item,
51
+ score: Math.min(1, Math.max(0, Math.max(baseline(item), textScore * .7 + lexical * .1 + item.confidence * .1 + authorityBonus(item) + (kindMatched ? .08 : 0) + (identifierMatched ? .12 : 0) + (matchesUserContextScope(item.scope, params) && item.scope.type !== "global" ? .05 : 0)) + feedbackScore)),
52
+ reasons: [
53
+ ftsScore > 0 ? "fts" : "",
54
+ lexical > 0 ? "lexical" : "",
55
+ identifierMatched ? "identifier" : "",
56
+ kindMatched ? "kind" : "",
57
+ item.explicitness === "explicit" ? "explicit" : "",
58
+ feedbackScore !== 0 ? "feedback" : ""
59
+ ].filter(Boolean)
60
+ };
61
+ }).sort((left, right) => Number(matchesUserContextScope(right.understanding.scope, params)) - Number(matchesUserContextScope(left.understanding.scope, params)) || right.score - left.score || right.understanding.updatedAt - left.understanding.updatedAt).slice(0, maxCandidates);
62
+ }
63
+ };
64
+ //#endregion
65
+ export { UserUnderstandingRetriever };
@@ -0,0 +1,7 @@
1
+ import type { UserContextScope } from './domain.js';
2
+ export interface UserContextScopeTarget {
3
+ sessionKey: string;
4
+ workspaceId: string;
5
+ projectId?: string;
6
+ }
7
+ export declare function matchesUserContextScope(scope: UserContextScope, target: UserContextScopeTarget): boolean;
@@ -0,0 +1,9 @@
1
+ //#region src/user-context/scope.ts
2
+ function matchesUserContextScope(scope, target) {
3
+ if (scope.type === "global") return true;
4
+ if (scope.type === "session") return scope.id === target.sessionKey;
5
+ if (scope.type === "workspace") return scope.id === target.workspaceId;
6
+ return Boolean(target.projectId && scope.id === target.projectId);
7
+ }
8
+ //#endregion
9
+ export { matchesUserContextScope };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xopcai/xopc",
3
- "version": "0.0.208",
3
+ "version": "0.0.210",
4
4
  "description": "Local-first AI system that remembers context, coordinates AI, and sustains long-term progress.",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",