@xopcai/xopc 0.0.159 → 0.0.161

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 (215) 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/{action-boundary-settings-panel-CaRK2vIy.js → action-boundary-settings-panel-BIVBUiNT.js} +1 -1
  4. package/dist/gateway/static/root/assets/activity-store-o7GRljfD.js +1 -0
  5. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-BeVf03hx.js → agent-avatar-dicebear-9R3szLMc.js} +1 -1
  6. package/dist/gateway/static/root/assets/agents-_qbUaYbs.js +2 -0
  7. package/dist/gateway/static/root/assets/{api-BjcBIV2O.js → api-jSTqFMq9.js} +1 -1
  8. package/dist/gateway/static/root/assets/{app-management-settings-panel-BG2ulMYw.js → app-management-settings-panel-D81cyE76.js} +1 -1
  9. package/dist/gateway/static/root/assets/{appearance-settings-0Kjenr2T.js → appearance-settings-Ct6bZQCV.js} +1 -1
  10. package/dist/gateway/static/root/assets/apps-page-0sPqD0FK.js +1 -0
  11. package/dist/gateway/static/root/assets/{archive-plugin-ChiNnH1e.js → archive-plugin-CfD7AZKn.js} +1 -1
  12. package/dist/gateway/static/root/assets/{attachment-load-pbBlQR-g.js → attachment-load-CP_Gaxt3.js} +1 -1
  13. package/dist/gateway/static/root/assets/{automation-suggestion-card-CTZDOyDy.js → automation-suggestion-card-BGKM_NDZ.js} +1 -1
  14. package/dist/gateway/static/root/assets/automations-page-BxWBuBsE.js +6 -0
  15. package/dist/gateway/static/root/assets/{binary-plugins-BeZGzpGF.js → binary-plugins-IPr2EVnS.js} +1 -1
  16. package/dist/gateway/static/root/assets/{block-editor-BnDmhN5Z.js → block-editor-B6aHEGA6.js} +3 -3
  17. package/dist/gateway/static/root/assets/browser-settings-page-C499b9AH.js +8 -0
  18. package/dist/gateway/static/root/assets/{capability-presets-api-Ii36j_7v.js → capability-presets-api-CCX9-LjU.js} +1 -1
  19. package/dist/gateway/static/root/assets/{capability-presets-settings-panel-Cl3dw4yh.js → capability-presets-settings-panel-Dva9SiPK.js} +2 -2
  20. package/dist/gateway/static/root/assets/{channel-recipient-api-CFqrSi5K.js → channel-recipient-api-MmLMLDWf.js} +1 -1
  21. package/dist/gateway/static/root/assets/channels-settings-DNAU7u9o.js +1 -0
  22. package/dist/gateway/static/root/assets/channels-status-swr-CIOH7tgn.js +1 -0
  23. package/dist/gateway/static/root/assets/check-DUBLcKHA.js +1 -0
  24. package/dist/gateway/static/root/assets/circle-alert-BEjgurr2.js +1 -0
  25. package/dist/gateway/static/root/assets/cn-JdwAhgNB.js +1 -0
  26. package/dist/gateway/static/root/assets/{connector-logo-CiLxuZ8S.js → connector-logo-BbjzIs87.js} +1 -1
  27. package/dist/gateway/static/root/assets/connectors-page-TwiBp8vY.js +2 -0
  28. package/dist/gateway/static/root/assets/createLucideIcon-DPHK1VkS.js +1 -0
  29. package/dist/gateway/static/root/assets/desktop-pet-CYH5ZSXy.js +1 -0
  30. package/dist/gateway/static/root/assets/desktop-pet-settings-DQLqGLc0.js +1 -0
  31. package/dist/gateway/static/root/assets/desktop-pet-sprite-DTqXSpqf.js +1 -0
  32. package/dist/gateway/static/root/assets/{directory-picker-path-field-CC2VL5Mc.js → directory-picker-path-field-ClsiXhmz.js} +1 -1
  33. package/dist/gateway/static/root/assets/{dreaming-settings-KY7ZfVsy.js → dreaming-settings-CjMPPdzg.js} +3 -3
  34. package/dist/gateway/static/root/assets/{extension-debug-page-C8KBeucs.js → extension-debug-page-57eizjhB.js} +1 -1
  35. package/dist/gateway/static/root/assets/{extension-page-CV-5Kcyk.js → extension-page-CsbSb3u1.js} +1 -1
  36. package/dist/gateway/static/root/assets/{extension-settings-page-DvUtDrAu.js → extension-settings-page-DKA9-lyP.js} +1 -1
  37. package/dist/gateway/static/root/assets/{gateway-config-api-DXfVeJLc.js → gateway-config-api-DIPJuzBZ.js} +1 -1
  38. package/dist/gateway/static/root/assets/gateway-settings-CDLqAQY7.js +1 -0
  39. package/dist/gateway/static/root/assets/{gateway-startup-retry-cxQ94qMm.js → gateway-startup-retry-DrfSJtvT.js} +1 -1
  40. package/dist/gateway/static/root/assets/goal-create-dialog-Q3B0E-0s.js +1 -0
  41. package/dist/gateway/static/root/assets/goal-detail-page-C5VAK04G.js +4 -0
  42. package/dist/gateway/static/root/assets/{goals-config-api-P8VhLqYF.js → goals-config-api-lGC10UkU.js} +1 -1
  43. package/dist/gateway/static/root/assets/goals-page-BJb-5IYw.js +2 -0
  44. package/dist/gateway/static/root/assets/{goals-settings-DHXyaH_O.js → goals-settings-BWq0pdrA.js} +1 -1
  45. package/dist/gateway/static/root/assets/{heartbeat-settings-CNckP_Dv.js → heartbeat-settings-D4o8BJVv.js} +1 -1
  46. package/dist/gateway/static/root/assets/index-CkUHH170.css +1 -0
  47. package/dist/gateway/static/root/assets/index-vq_cJZJC.js +199 -0
  48. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-jXmv1RVX.js → keyboard-shortcuts-settings-6T2QYehS.js} +1 -1
  49. package/dist/gateway/static/root/assets/local-app-workbench-page-euH17Kvb.js +2 -0
  50. package/dist/gateway/static/root/assets/{local-apps-page-Cs5LKjtc.js → local-apps-page-DCjg2K9f.js} +1 -1
  51. package/dist/gateway/static/root/assets/{locale-store-C_M71MK9.js → locale-store-Dar-xqQr.js} +1 -1
  52. package/dist/gateway/static/root/assets/logs-page-CyYCBqym.js +7 -0
  53. package/dist/gateway/static/root/assets/{markdown-split-BFqeSNte.js → markdown-split-rt1XO43g.js} +1 -1
  54. package/dist/gateway/static/root/assets/{media-plugins-Cc8379gq.js → media-plugins-Bwo8CJuh.js} +1 -1
  55. package/dist/gateway/static/root/assets/messages-CxySDn9d.js +5 -0
  56. package/dist/gateway/static/root/assets/models-hub-panel-DObxxjc9.js +2 -0
  57. package/dist/gateway/static/root/assets/{notes-page-DlGU4ipo.js → notes-page-Dp-pkX7d.js} +1 -1
  58. package/dist/gateway/static/root/assets/notes-workbench-CCb4RXcZ.js +4 -0
  59. package/dist/gateway/static/root/assets/{page-tabs-kFOswGlG.js → page-tabs-CzZ4iKOb.js} +1 -1
  60. package/dist/gateway/static/root/assets/{preview-open-alternatives-CvjuvABg.js → preview-open-alternatives-3E_Qa-58.js} +1 -1
  61. package/dist/gateway/static/root/assets/product-delivery-BTRT9kCS.js +1 -0
  62. package/dist/gateway/static/root/assets/product-open-page-B2T48Sbt.js +1 -0
  63. package/dist/gateway/static/root/assets/project-detail-page-BvEcriRC.js +1 -0
  64. package/dist/gateway/static/root/assets/projects-page-B_e79MRJ.js +1 -0
  65. package/dist/gateway/static/root/assets/remote-access-hub-DGcqnYfR.js +1 -0
  66. package/dist/gateway/static/root/assets/{save-bar-controls-DwrD7ODx.js → save-bar-controls-CkeKasGm.js} +1 -1
  67. package/dist/gateway/static/root/assets/{schedule-field-Ba4WzTmE.js → schedule-field-TkqUL3wm.js} +1 -1
  68. package/dist/gateway/static/root/assets/{schema-form-DvydL8eF.js → schema-form-DC-iU5IG.js} +1 -1
  69. package/dist/gateway/static/root/assets/sessions-page-DQZhrDJ8.js +1 -0
  70. package/dist/gateway/static/root/assets/settings-advanced-gate-BkdeN99Y.js +1 -0
  71. package/dist/gateway/static/root/assets/{settings-collapsible-section-LaQqGGej.js → settings-collapsible-section-Dpqth3oA.js} +1 -1
  72. package/dist/gateway/static/root/assets/{settings-form-section-DruI__qO.js → settings-form-section-CNqF6IwY.js} +1 -1
  73. package/dist/gateway/static/root/assets/{settings-loading-skeleton-UvA-eDhF.js → settings-loading-skeleton-DkvwitK_.js} +1 -1
  74. package/dist/gateway/static/root/assets/{settings-page-layout-DG-XMIPu.js → settings-page-layout-DWvNgISx.js} +1 -1
  75. package/dist/gateway/static/root/assets/{settings-page-5oCGSebm.js → settings-page-qPG7I2zd.js} +1 -1
  76. package/dist/gateway/static/root/assets/setup-status-panel-lwRAh9aw.js +1 -0
  77. package/dist/gateway/static/root/assets/{share-preview-page-FLVeTrRt.js → share-preview-page-DGpSPW-n.js} +1 -1
  78. package/dist/gateway/static/root/assets/shares-settings-BGj9IVUr.js +1 -0
  79. package/dist/gateway/static/root/assets/skill-reload-api-B2UBAs5U.js +1 -0
  80. package/dist/gateway/static/root/assets/skills-page-DdjzFZ8I.js +2 -0
  81. package/dist/gateway/static/root/assets/{system-settings-panel-CeK93xVi.js → system-settings-panel-8TxxSbUw.js} +1 -1
  82. package/dist/gateway/static/root/assets/{theme-store-C8ohIHhw.js → theme-store-B5FzMWOx.js} +1 -1
  83. package/dist/gateway/static/root/assets/{typed-models-lib-D1Lr2gG0.js → typed-models-lib-DEGtSA5h.js} +1 -1
  84. package/dist/gateway/static/root/assets/{use-channel-catalog-BWzou5ar.js → use-channel-catalog-BDU6FneG.js} +1 -1
  85. package/dist/gateway/static/root/assets/user-context-page-BTTZpAGV.js +1 -0
  86. package/dist/gateway/static/root/assets/voice-api-key-field-DuDQd-WU.js +1 -0
  87. package/dist/gateway/static/root/assets/work-discovery-page-BUVkVCsW.js +1 -0
  88. package/dist/gateway/static/root/assets/work-item-detail-page-DeEPPu4n.js +1 -0
  89. package/dist/gateway/static/root/assets/work-page-DQNUyTUq.js +1 -0
  90. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-Bynqe4kV.js → workflow-run-setup-panel-Cwi8Pz7n.js} +2 -2
  91. package/dist/gateway/static/root/assets/workflows-page-BIy4wrzO.js +11 -0
  92. package/dist/gateway/static/root/index.html +12 -10
  93. package/dist/package.js +1 -1
  94. package/dist/src/automations/service/action-executor.js +1 -1
  95. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  96. package/dist/src/config/agent-profile.js +1 -1
  97. package/dist/src/gateway/agents-admin.js +1 -1
  98. package/dist/src/gateway/chat-stream/mapper.d.ts +1 -0
  99. package/dist/src/gateway/chat-stream/mapper.js +43 -7
  100. package/dist/src/gateway/hono/routes/home.js +15 -2
  101. package/dist/src/gateway/hono/routes/work-discovery.js +451 -0
  102. package/dist/src/gateway/hono/sse.d.ts +2 -0
  103. package/dist/src/gateway/hono/sse.js +10 -3
  104. package/dist/src/gateway/run-loop.js +17 -7
  105. package/dist/src/gateway/server.d.ts +1 -0
  106. package/dist/src/gateway/server.js +9 -0
  107. package/dist/src/gateway/service.d.ts +2 -0
  108. package/dist/src/gateway/service.js +27 -2
  109. package/dist/src/local-apps/preview-runtime-bridge.d.ts +1 -1
  110. package/dist/src/local-apps/preview-runtime-bridge.js +14 -11
  111. package/dist/src/mobile/notification-service.js +1 -0
  112. package/dist/src/pets/factory.js +23 -26
  113. package/dist/src/pets/manifest.d.ts +2 -1
  114. package/dist/src/pets/manifest.js +15 -8
  115. package/dist/src/pets/validator.js +8 -3
  116. package/dist/src/proactive/calendar-signals.d.ts +4 -0
  117. package/dist/src/proactive/calendar-signals.js +120 -0
  118. package/dist/src/proactive/focus-service.d.ts +62 -0
  119. package/dist/src/proactive/focus-service.js +173 -0
  120. package/dist/src/proactive/index.d.ts +7 -0
  121. package/dist/src/proactive/index.js +7 -0
  122. package/dist/src/proactive/insight-repository.d.ts +19 -0
  123. package/dist/src/proactive/insight-repository.js +106 -0
  124. package/dist/src/proactive/run-processor.d.ts +19 -0
  125. package/dist/src/proactive/run-processor.js +125 -0
  126. package/dist/src/proactive/trial-expiry-reconciler.d.ts +5 -0
  127. package/dist/src/proactive/trial-expiry-reconciler.js +30 -0
  128. package/dist/src/proactive/types.d.ts +64 -0
  129. package/dist/src/proactive/types.js +1 -0
  130. package/dist/src/proactive/watch-repository.d.ts +28 -0
  131. package/dist/src/proactive/watch-repository.js +129 -0
  132. package/dist/src/storage/sqlite/knowledge-repository.d.ts +1 -0
  133. package/dist/src/storage/sqlite/knowledge-repository.js +4 -0
  134. package/dist/src/storage/sqlite/migrations/047_work_discovery_sources.sql +16 -0
  135. package/dist/src/storage/sqlite/migrations/048_work_understanding_investigations.sql +40 -0
  136. package/dist/src/storage/sqlite/migrations/049_work_understanding_threads.sql +52 -0
  137. package/dist/src/storage/sqlite/migrations/050_work_discovery_source_refreshes.sql +15 -0
  138. package/dist/src/storage/sqlite/migrations/051_focus_watches.sql +26 -0
  139. package/dist/src/storage/sqlite/migrations/052_proactive_insights.sql +25 -0
  140. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  141. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  142. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  143. package/dist/src/storage/sqlite/schema.js +1 -1
  144. package/dist/src/work-discovery/analyzer.d.ts +12 -1
  145. package/dist/src/work-discovery/analyzer.js +126 -7
  146. package/dist/src/work-discovery/candidate-discovery.d.ts +17 -0
  147. package/dist/src/work-discovery/candidate-discovery.js +279 -0
  148. package/dist/src/work-discovery/evaluation.d.ts +11 -0
  149. package/dist/src/work-discovery/evaluation.js +17 -0
  150. package/dist/src/work-discovery/governance.d.ts +25 -0
  151. package/dist/src/work-discovery/governance.js +96 -0
  152. package/dist/src/work-discovery/incremental-repository.d.ts +13 -0
  153. package/dist/src/work-discovery/incremental-repository.js +55 -0
  154. package/dist/src/work-discovery/incremental.d.ts +2 -0
  155. package/dist/src/work-discovery/incremental.js +7 -0
  156. package/dist/src/work-discovery/index.d.ts +10 -0
  157. package/dist/src/work-discovery/index.js +13 -3
  158. package/dist/src/work-discovery/investigation-repository.d.ts +16 -0
  159. package/dist/src/work-discovery/investigation-repository.js +122 -0
  160. package/dist/src/work-discovery/investigator.d.ts +55 -0
  161. package/dist/src/work-discovery/investigator.js +358 -0
  162. package/dist/src/work-discovery/probe.d.ts +22 -0
  163. package/dist/src/work-discovery/probe.js +88 -1
  164. package/dist/src/work-discovery/service.d.ts +110 -1
  165. package/dist/src/work-discovery/service.js +578 -8
  166. package/dist/src/work-discovery/source-repository.d.ts +13 -0
  167. package/dist/src/work-discovery/source-repository.js +72 -0
  168. package/dist/src/work-discovery/thread-repository.d.ts +34 -0
  169. package/dist/src/work-discovery/thread-repository.js +112 -0
  170. package/dist/src/work-discovery/thread-service.d.ts +8 -0
  171. package/dist/src/work-discovery/thread-service.js +104 -0
  172. package/dist/src/work-discovery/types.d.ts +145 -0
  173. package/package.json +1 -1
  174. package/skills/creative/hatch-pet/SKILL.md +2 -2
  175. package/dist/gateway/static/root/assets/activity-store-C-57rvkX.js +0 -1
  176. package/dist/gateway/static/root/assets/agents-P05C4A-3.js +0 -2
  177. package/dist/gateway/static/root/assets/apps-page-DANGrBpN.js +0 -1
  178. package/dist/gateway/static/root/assets/automations-page-BXfGL_cm.js +0 -6
  179. package/dist/gateway/static/root/assets/browser-settings-page-534luV0B.js +0 -8
  180. package/dist/gateway/static/root/assets/channels-settings-M91zFJVi.js +0 -1
  181. package/dist/gateway/static/root/assets/channels-status-swr-vooEF4lG.js +0 -1
  182. package/dist/gateway/static/root/assets/check-BODqo66o.js +0 -1
  183. package/dist/gateway/static/root/assets/circle-alert-RzVebuX2.js +0 -1
  184. package/dist/gateway/static/root/assets/cn-BQ_8x0bT.js +0 -1
  185. package/dist/gateway/static/root/assets/connectors-page-CV5UulW6.js +0 -2
  186. package/dist/gateway/static/root/assets/desktop-pet-Cil2eSpW.js +0 -1
  187. package/dist/gateway/static/root/assets/desktop-pet-settings-DwsC6l5F.js +0 -1
  188. package/dist/gateway/static/root/assets/desktop-pet-sprite-DqZ6fbIj.js +0 -1
  189. package/dist/gateway/static/root/assets/gateway-settings-BpJ0v56l.js +0 -1
  190. package/dist/gateway/static/root/assets/goal-create-dialog-lMHD-2CX.js +0 -1
  191. package/dist/gateway/static/root/assets/goal-detail-page-yPmF-G7b.js +0 -4
  192. package/dist/gateway/static/root/assets/goals-page-BHTCKobG.js +0 -2
  193. package/dist/gateway/static/root/assets/index-BgZhEOkN.css +0 -1
  194. package/dist/gateway/static/root/assets/index-BuqGh2SW.js +0 -193
  195. package/dist/gateway/static/root/assets/local-app-workbench-page-zpp_wciE.js +0 -2
  196. package/dist/gateway/static/root/assets/logs-page-B4CRYqYR.js +0 -7
  197. package/dist/gateway/static/root/assets/messages-BuT0SR1R.js +0 -5
  198. package/dist/gateway/static/root/assets/models-hub-panel-1hdoAoB_.js +0 -2
  199. package/dist/gateway/static/root/assets/notes-workbench-DQEAZTA5.js +0 -4
  200. package/dist/gateway/static/root/assets/project-detail-page-Bp9bC7A6.js +0 -1
  201. package/dist/gateway/static/root/assets/projects-page-RNorFXTw.js +0 -1
  202. package/dist/gateway/static/root/assets/remote-access-hub-BqRTcM_6.js +0 -1
  203. package/dist/gateway/static/root/assets/sessions-page-B2EfW1cm.js +0 -1
  204. package/dist/gateway/static/root/assets/settings-advanced-gate-CklL85T4.js +0 -1
  205. package/dist/gateway/static/root/assets/setup-status-panel-D3my1HgB.js +0 -1
  206. package/dist/gateway/static/root/assets/shares-settings-DVxgjrsP.js +0 -1
  207. package/dist/gateway/static/root/assets/skill-reload-api-Bcu58ZaF.js +0 -1
  208. package/dist/gateway/static/root/assets/skills-page-CDd-84FE.js +0 -2
  209. package/dist/gateway/static/root/assets/sliding-segmented-uWmrxE3P.js +0 -1
  210. package/dist/gateway/static/root/assets/user-context-page-1OyJnTyR.js +0 -1
  211. package/dist/gateway/static/root/assets/voice-api-key-field-B2ncRwHS.js +0 -1
  212. package/dist/gateway/static/root/assets/work-discovery-page-BZlY4PZL.js +0 -1
  213. package/dist/gateway/static/root/assets/work-item-detail-page-DPXMrneY.js +0 -1
  214. package/dist/gateway/static/root/assets/work-page-CTERoqyv.js +0 -1
  215. package/dist/gateway/static/root/assets/workflows-page-CLgsnqFQ.js +0 -11
@@ -0,0 +1,72 @@
1
+ import { requireXopcDatabase } from "../storage/sqlite/connection.js";
2
+ import { runSqliteWriteTransaction } from "../storage/sqlite/transaction.js";
3
+ import { randomUUID } from "node:crypto";
4
+ //#region src/work-discovery/source-repository.ts
5
+ function parseJson(value) {
6
+ if (!value) return void 0;
7
+ try {
8
+ return JSON.parse(value);
9
+ } catch {
10
+ return;
11
+ }
12
+ }
13
+ function directorySource(row) {
14
+ if (row.kind !== "directory" || !row.root_path) return null;
15
+ return {
16
+ id: row.source_id,
17
+ kind: "directory",
18
+ rootPath: row.root_path,
19
+ displayName: row.display_name,
20
+ status: row.status === "revoked" ? "revoked" : "active",
21
+ scope: { readOnly: true },
22
+ ...parseJson(row.fingerprint_json) ? { fingerprint: parseJson(row.fingerprint_json) } : {},
23
+ ...row.last_scanned_at != null ? { lastScannedAt: row.last_scanned_at } : {},
24
+ createdAt: row.created_at,
25
+ updatedAt: row.updated_at
26
+ };
27
+ }
28
+ function readDirectorySource(db, id) {
29
+ const row = db.prepare("SELECT * FROM work_discovery_sources WHERE source_id = ?").get(id);
30
+ return row ? directorySource(row) : null;
31
+ }
32
+ function listWorkDiscoveryDirectorySources(options = {}) {
33
+ const { db } = requireXopcDatabase();
34
+ return db.prepare(`SELECT * FROM work_discovery_sources
35
+ WHERE kind = 'directory' ${options.includeRevoked ? "" : "AND status = 'active'"}
36
+ ORDER BY updated_at DESC`).all().flatMap((row) => {
37
+ const source = directorySource(row);
38
+ return source ? [source] : [];
39
+ });
40
+ }
41
+ function getWorkDiscoveryDirectorySource(id) {
42
+ const { db } = requireXopcDatabase();
43
+ return readDirectorySource(db, id);
44
+ }
45
+ function upsertWorkDiscoveryDirectorySource(input) {
46
+ const now = input.nowMs ?? Date.now();
47
+ const id = randomUUID();
48
+ runSqliteWriteTransaction((db) => {
49
+ db.prepare(`INSERT INTO work_discovery_sources (
50
+ source_id, kind, root_path, display_name, status, scope_json, fingerprint_json,
51
+ last_scanned_at, created_at, updated_at
52
+ ) VALUES (?, 'directory', ?, ?, 'active', ?, ?, ?, ?, ?)
53
+ ON CONFLICT(kind, root_path) DO UPDATE SET
54
+ display_name = excluded.display_name,
55
+ status = 'active',
56
+ scope_json = excluded.scope_json,
57
+ fingerprint_json = COALESCE(excluded.fingerprint_json, work_discovery_sources.fingerprint_json),
58
+ last_scanned_at = COALESCE(excluded.last_scanned_at, work_discovery_sources.last_scanned_at),
59
+ updated_at = excluded.updated_at`).run(id, input.rootPath, input.displayName, JSON.stringify({ readOnly: true }), input.fingerprint ? JSON.stringify(input.fingerprint) : null, input.scanned ? now : null, now, now);
60
+ });
61
+ const { db } = requireXopcDatabase();
62
+ return directorySource(db.prepare(`SELECT * FROM work_discovery_sources WHERE kind = 'directory' AND root_path = ?`).get(input.rootPath));
63
+ }
64
+ function revokeWorkDiscoveryDirectorySource(id, nowMs = Date.now()) {
65
+ runSqliteWriteTransaction((db) => {
66
+ db.prepare(`UPDATE work_discovery_sources SET status = 'revoked', updated_at = ?
67
+ WHERE source_id = ? AND kind = 'directory'`).run(nowMs, id);
68
+ });
69
+ return getWorkDiscoveryDirectorySource(id);
70
+ }
71
+ //#endregion
72
+ export { getWorkDiscoveryDirectorySource, listWorkDiscoveryDirectorySources, revokeWorkDiscoveryDirectorySource, upsertWorkDiscoveryDirectorySource };
@@ -0,0 +1,34 @@
1
+ import type { WorkUnderstandingThread } from './types.js';
2
+ export declare function getWorkUnderstandingThread(id: string): WorkUnderstandingThread | null;
3
+ export declare function getWorkUnderstandingThreadByCanonicalKey(key: string): WorkUnderstandingThread | null;
4
+ export declare function listWorkUnderstandingThreads(options?: {
5
+ projectId?: string;
6
+ includeRejected?: boolean;
7
+ limit?: number;
8
+ }): WorkUnderstandingThread[];
9
+ export declare function upsertWorkUnderstandingThread(input: {
10
+ canonicalKey: string;
11
+ title: string;
12
+ summary: string;
13
+ status: WorkUnderstandingThread['status'];
14
+ horizon: WorkUnderstandingThread['horizon'];
15
+ focusScore: number;
16
+ confidence: number;
17
+ projectIds: string[];
18
+ evidenceIds: string[];
19
+ observedAt?: number;
20
+ nowMs?: number;
21
+ }): WorkUnderstandingThread;
22
+ export declare function addWorkUnderstandingThreadFeedback(input: {
23
+ threadId: string;
24
+ decision: 'confirmed' | 'corrected' | 'rejected' | 'paused' | 'completed';
25
+ correctedTitle?: string;
26
+ correctedSummary?: string;
27
+ nowMs?: number;
28
+ }): WorkUnderstandingThread | null;
29
+ export declare function attachWorkUnderstandingThreadEvidence(input: {
30
+ threadId: string;
31
+ evidenceId: string;
32
+ projectId?: string;
33
+ nowMs?: number;
34
+ }): WorkUnderstandingThread | null;
@@ -0,0 +1,112 @@
1
+ import { requireXopcDatabase } from "../storage/sqlite/connection.js";
2
+ import { runSqliteWriteTransaction } from "../storage/sqlite/transaction.js";
3
+ import { randomUUID } from "node:crypto";
4
+ //#region src/work-discovery/thread-repository.ts
5
+ function idsForThread(table, column, id) {
6
+ const { db } = requireXopcDatabase();
7
+ return db.prepare(`SELECT ${column} AS id FROM ${table} WHERE thread_id = ? ORDER BY created_at ASC`).all(id).map((row) => row.id);
8
+ }
9
+ function threadFromRow(row) {
10
+ return {
11
+ id: row.thread_id,
12
+ canonicalKey: row.canonical_key,
13
+ title: row.title,
14
+ summary: row.summary,
15
+ status: row.status,
16
+ horizon: row.horizon,
17
+ focusScore: row.focus_score,
18
+ confidence: row.confidence,
19
+ userStatus: row.user_status,
20
+ projectIds: idsForThread("work_understanding_thread_projects", "project_id", row.thread_id),
21
+ evidenceIds: idsForThread("work_understanding_thread_evidence", "evidence_id", row.thread_id),
22
+ ...row.parent_thread_id ? { parentThreadId: row.parent_thread_id } : {},
23
+ firstObservedAt: row.first_observed_at,
24
+ lastObservedAt: row.last_observed_at,
25
+ createdAt: row.created_at,
26
+ updatedAt: row.updated_at
27
+ };
28
+ }
29
+ function getWorkUnderstandingThread(id) {
30
+ const { db } = requireXopcDatabase();
31
+ const row = db.prepare("SELECT * FROM work_understanding_threads WHERE thread_id = ?").get(id);
32
+ return row ? threadFromRow(row) : null;
33
+ }
34
+ function getWorkUnderstandingThreadByCanonicalKey(key) {
35
+ const { db } = requireXopcDatabase();
36
+ const row = db.prepare("SELECT * FROM work_understanding_threads WHERE canonical_key = ?").get(key);
37
+ return row ? threadFromRow(row) : null;
38
+ }
39
+ function listWorkUnderstandingThreads(options = {}) {
40
+ const { db } = requireXopcDatabase();
41
+ const clauses = [];
42
+ const args = [];
43
+ if (!options.includeRejected) clauses.push("t.user_status <> 'rejected'");
44
+ if (options.projectId) {
45
+ clauses.push("EXISTS (SELECT 1 FROM work_understanding_thread_projects p WHERE p.thread_id = t.thread_id AND p.project_id = ?)");
46
+ args.push(options.projectId);
47
+ }
48
+ args.push(Math.max(1, Math.min(200, options.limit ?? 50)));
49
+ return db.prepare(`SELECT t.* FROM work_understanding_threads t
50
+ ${clauses.length ? `WHERE ${clauses.join(" AND ")}` : ""}
51
+ ORDER BY t.focus_score DESC, t.last_observed_at DESC LIMIT ?`).all(...args).map(threadFromRow);
52
+ }
53
+ function upsertWorkUnderstandingThread(input) {
54
+ const now = input.nowMs ?? Date.now();
55
+ const observedAt = input.observedAt ?? now;
56
+ const id = getWorkUnderstandingThreadByCanonicalKey(input.canonicalKey)?.id ?? randomUUID();
57
+ runSqliteWriteTransaction((db) => {
58
+ db.prepare(`INSERT INTO work_understanding_threads (
59
+ thread_id, canonical_key, title, summary, status, horizon, focus_score,
60
+ confidence, user_status, first_observed_at, last_observed_at, created_at, updated_at
61
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'unreviewed', ?, ?, ?, ?)
62
+ ON CONFLICT(canonical_key) DO UPDATE SET
63
+ title = CASE WHEN work_understanding_threads.user_status = 'corrected' THEN work_understanding_threads.title ELSE excluded.title END,
64
+ summary = CASE WHEN work_understanding_threads.user_status = 'corrected' THEN work_understanding_threads.summary ELSE excluded.summary END,
65
+ status = CASE WHEN work_understanding_threads.status IN ('paused', 'completed') THEN work_understanding_threads.status ELSE excluded.status END,
66
+ horizon = excluded.horizon,
67
+ focus_score = CASE WHEN work_understanding_threads.user_status = 'confirmed'
68
+ THEN MIN(100, excluded.focus_score + 12) ELSE excluded.focus_score END,
69
+ confidence = CASE WHEN work_understanding_threads.user_status IN ('confirmed', 'corrected')
70
+ THEN MAX(work_understanding_threads.confidence, excluded.confidence) ELSE excluded.confidence END,
71
+ last_observed_at = excluded.last_observed_at,
72
+ updated_at = excluded.updated_at`).run(id, input.canonicalKey, input.title.slice(0, 200), input.summary.slice(0, 2e3), input.status, input.horizon, Math.max(0, Math.min(100, input.focusScore)), Math.max(0, Math.min(1, input.confidence)), observedAt, observedAt, now, now);
73
+ const row = db.prepare("SELECT thread_id FROM work_understanding_threads WHERE canonical_key = ?").get(input.canonicalKey);
74
+ const projectInsert = db.prepare("INSERT OR IGNORE INTO work_understanding_thread_projects (thread_id, project_id, created_at) VALUES (?, ?, ?)");
75
+ for (const projectId of [...new Set(input.projectIds)].slice(0, 20)) projectInsert.run(row.thread_id, projectId, now);
76
+ const evidenceInsert = db.prepare(`INSERT OR IGNORE INTO work_understanding_thread_evidence (thread_id, evidence_id, relation, created_at)
77
+ VALUES (?, ?, 'supports', ?)`);
78
+ for (const evidenceId of [...new Set(input.evidenceIds)].slice(0, 50)) evidenceInsert.run(row.thread_id, evidenceId, now);
79
+ });
80
+ return getWorkUnderstandingThreadByCanonicalKey(input.canonicalKey);
81
+ }
82
+ function addWorkUnderstandingThreadFeedback(input) {
83
+ const thread = getWorkUnderstandingThread(input.threadId);
84
+ if (!thread) return null;
85
+ const now = input.nowMs ?? Date.now();
86
+ const userStatus = input.decision === "confirmed" ? "confirmed" : input.decision === "corrected" ? "corrected" : input.decision === "rejected" ? "rejected" : thread.userStatus;
87
+ const status = input.decision === "paused" || input.decision === "completed" ? input.decision : thread.status;
88
+ runSqliteWriteTransaction((db) => {
89
+ db.prepare(`INSERT INTO work_understanding_thread_feedback (
90
+ feedback_id, thread_id, decision, corrected_title, corrected_summary, created_at
91
+ ) VALUES (?, ?, ?, ?, ?, ?)`).run(randomUUID(), thread.id, input.decision, input.correctedTitle ?? null, input.correctedSummary ?? null, now);
92
+ db.prepare(`UPDATE work_understanding_threads SET title = ?, summary = ?, status = ?, user_status = ?,
93
+ focus_score = ?, confidence = ?, updated_at = ? WHERE thread_id = ?`).run(input.decision === "corrected" && input.correctedTitle?.trim() ? input.correctedTitle.trim().slice(0, 200) : thread.title, input.decision === "corrected" && input.correctedSummary?.trim() ? input.correctedSummary.trim().slice(0, 2e3) : thread.summary, status, userStatus, input.decision === "confirmed" ? Math.min(100, thread.focusScore + 12) : thread.focusScore, input.decision === "confirmed" || input.decision === "corrected" ? 1 : thread.confidence, now, thread.id);
94
+ });
95
+ return getWorkUnderstandingThread(thread.id);
96
+ }
97
+ function attachWorkUnderstandingThreadEvidence(input) {
98
+ const thread = getWorkUnderstandingThread(input.threadId);
99
+ if (!thread) return null;
100
+ const now = input.nowMs ?? Date.now();
101
+ runSqliteWriteTransaction((db) => {
102
+ db.prepare(`INSERT OR IGNORE INTO work_understanding_thread_evidence (thread_id, evidence_id, relation, created_at)
103
+ VALUES (?, ?, 'supports', ?)`).run(thread.id, input.evidenceId, now);
104
+ if (input.projectId) db.prepare("INSERT OR IGNORE INTO work_understanding_thread_projects (thread_id, project_id, created_at) VALUES (?, ?, ?)").run(thread.id, input.projectId, now);
105
+ db.prepare(`UPDATE work_understanding_threads SET confidence = MIN(1, confidence + 0.05),
106
+ focus_score = MIN(100, focus_score + 4), last_observed_at = MAX(last_observed_at, ?), updated_at = ?
107
+ WHERE thread_id = ?`).run(now, now, thread.id);
108
+ });
109
+ return getWorkUnderstandingThread(thread.id);
110
+ }
111
+ //#endregion
112
+ export { addWorkUnderstandingThreadFeedback, attachWorkUnderstandingThreadEvidence, getWorkUnderstandingThread, getWorkUnderstandingThreadByCanonicalKey, listWorkUnderstandingThreads, upsertWorkUnderstandingThread };
@@ -0,0 +1,8 @@
1
+ import type { WorkContextSnapshot, WorkDiscoveryResult, WorkUnderstandingEvidenceItem, WorkUnderstandingThread } from './types.js';
2
+ export declare function persistWorkThreadsFromDiscovery(input: {
3
+ projectId: string;
4
+ result: WorkDiscoveryResult;
5
+ snapshot: WorkContextSnapshot;
6
+ evidence: WorkUnderstandingEvidenceItem[];
7
+ nowMs?: number;
8
+ }): WorkUnderstandingThread[];
@@ -0,0 +1,104 @@
1
+ import { listWorkUnderstandingThreads, upsertWorkUnderstandingThread } from "./thread-repository.js";
2
+ //#region src/work-discovery/thread-service.ts
3
+ function confidenceValue(value) {
4
+ return value === "high" ? .9 : value === "medium" ? .72 : .55;
5
+ }
6
+ function recencyPoints(observedAt, nowMs) {
7
+ if (!observedAt) return 8;
8
+ const days = Math.max(0, (nowMs - observedAt) / 864e5);
9
+ if (days <= 2) return 40;
10
+ if (days <= 7) return 32;
11
+ if (days <= 14) return 24;
12
+ if (days <= 30) return 14;
13
+ return 5;
14
+ }
15
+ function focusScore(input) {
16
+ const latest = input.evidence.reduce((value, item) => item.observedAt != null && (value == null || item.observedAt > value) ? item.observedAt : value, void 0);
17
+ const commitDays = new Set((input.snapshot.git?.recentCommits ?? []).flatMap((commit) => commit.committedAt ? [new Date(commit.committedAt).toISOString().slice(0, 10)] : []));
18
+ const sourceTypes = new Set(input.evidence.map((item) => item.sourceType));
19
+ const continuity = Math.min(20, commitDays.size * 5);
20
+ const corroboration = Math.min(15, input.evidence.length * 3 + Math.max(0, sourceTypes.size - 1) * 5);
21
+ const unfinished = input.candidate.status === "active" ? 15 : input.candidate.status === "blocked" ? 12 : 3;
22
+ const confidence = Math.round(confidenceValue(input.candidate.confidence) * 10);
23
+ const horizonAdjustment = input.candidate.horizon === "current" ? 0 : input.candidate.horizon === "ongoing" ? -4 : -8;
24
+ return Math.max(0, Math.min(100, Math.round(recencyPoints(latest, input.nowMs) + continuity + corroboration + unfinished + confidence + horizonAdjustment)));
25
+ }
26
+ function fallbackCandidate(result, evidence) {
27
+ return {
28
+ topicKey: "current-project-work",
29
+ title: result.projectSummary.slice(0, 200),
30
+ summary: result.currentState.slice(0, 2e3),
31
+ status: result.lowConfidence ? "uncertain" : "active",
32
+ horizon: "current",
33
+ confidence: result.lowConfidence ? "low" : "medium",
34
+ evidenceRefs: evidence.slice(0, 6).map((item) => item.sourceRef)
35
+ };
36
+ }
37
+ function titleTokens(value) {
38
+ return new Set(value.toLocaleLowerCase().match(/[\p{L}\p{N}]{2,}/gu)?.filter((token) => ![
39
+ "the",
40
+ "and",
41
+ "for",
42
+ "with",
43
+ "from",
44
+ "this",
45
+ "that"
46
+ ].includes(token)).slice(0, 30) ?? []);
47
+ }
48
+ function titleSimilarity(left, right) {
49
+ const leftTokens = titleTokens(left);
50
+ const rightTokens = titleTokens(right);
51
+ if (!leftTokens.size || !rightTokens.size) return 0;
52
+ return [...leftTokens].filter((token) => rightTokens.has(token)).length / Math.max(leftTokens.size, rightTokens.size);
53
+ }
54
+ function canonicalKeyForCandidate(input) {
55
+ const proposed = `${input.projectId}:${input.candidate.horizon}:${input.candidate.topicKey}`.slice(0, 300);
56
+ const existing = listWorkUnderstandingThreads({
57
+ projectId: input.projectId,
58
+ includeRejected: true,
59
+ limit: 100
60
+ });
61
+ const exact = existing.find((thread) => thread.canonicalKey === proposed);
62
+ if (exact) return exact.canonicalKey;
63
+ return existing.filter((thread) => thread.horizon === input.candidate.horizon && thread.userStatus !== "rejected").map((thread) => ({
64
+ thread,
65
+ similarity: titleSimilarity(thread.title, input.candidate.title)
66
+ })).filter((item) => item.similarity >= .5).sort((left, right) => right.similarity - left.similarity)[0]?.thread.canonicalKey ?? proposed;
67
+ }
68
+ function persistWorkThreadsFromDiscovery(input) {
69
+ const nowMs = input.nowMs ?? Date.now();
70
+ const candidates = input.result.workThreadCandidates?.length ? input.result.workThreadCandidates : input.evidence.length ? [fallbackCandidate(input.result, input.evidence)] : [];
71
+ const persist = (candidate) => {
72
+ const evidence = candidate.evidenceRefs.flatMap((ref) => {
73
+ const match = input.evidence.find((item) => item.sourceRef === ref);
74
+ return match ? [match] : [];
75
+ });
76
+ if (!evidence.length) return [];
77
+ return [upsertWorkUnderstandingThread({
78
+ canonicalKey: canonicalKeyForCandidate({
79
+ projectId: input.projectId,
80
+ candidate
81
+ }),
82
+ title: candidate.title,
83
+ summary: candidate.summary,
84
+ status: candidate.status,
85
+ horizon: candidate.horizon,
86
+ focusScore: focusScore({
87
+ candidate,
88
+ evidence,
89
+ snapshot: input.snapshot,
90
+ nowMs
91
+ }),
92
+ confidence: confidenceValue(candidate.confidence),
93
+ projectIds: [input.projectId],
94
+ evidenceIds: evidence.map((item) => item.id),
95
+ observedAt: evidence.reduce((latest, item) => Math.max(latest, item.observedAt ?? nowMs), 0) || nowMs,
96
+ nowMs
97
+ })];
98
+ };
99
+ const persisted = candidates.flatMap(persist);
100
+ if (persisted.length || !input.evidence.length || !input.result.workThreadCandidates?.length) return persisted;
101
+ return persist(fallbackCandidate(input.result, input.evidence));
102
+ }
103
+ //#endregion
104
+ export { persistWorkThreadsFromDiscovery };
@@ -9,6 +9,122 @@ export interface WorkDiscoveryOnboardingState {
9
9
  export type WorkDiscoveryRunStatus = 'queued' | 'probing' | 'analyzing' | 'completed' | 'failed' | 'canceled';
10
10
  export type WorkDiscoveryStage = 'folder_structure' | 'recent_progress' | 'next_steps';
11
11
  export type WorkDiscoverySource = 'onboarding_selected_directory' | 'manual_selected_directory';
12
+ export type WorkDiscoveryCandidateSource = 'existing_project' | 'approved_directory' | 'common_work_root' | 'personal_work_root';
13
+ export interface WorkDiscoveryCandidate {
14
+ id: string;
15
+ rootPath: string;
16
+ displayName: string;
17
+ source: WorkDiscoveryCandidateSource;
18
+ projectId?: string;
19
+ projectKind: 'coding' | 'general' | 'unknown';
20
+ projectKindConfidence: number;
21
+ score: number;
22
+ lastActiveAt?: number;
23
+ branch?: string;
24
+ changedFileCount: number;
25
+ evidence: string[];
26
+ }
27
+ export interface WorkDiscoveryDirectorySource {
28
+ id: string;
29
+ kind: 'directory';
30
+ rootPath: string;
31
+ displayName: string;
32
+ status: 'active' | 'revoked';
33
+ scope: {
34
+ readOnly: true;
35
+ };
36
+ fingerprint?: WorkDiscoveryPreview['fingerprint'];
37
+ lastScannedAt?: number;
38
+ createdAt: number;
39
+ updatedAt: number;
40
+ }
41
+ export interface WorkDiscoverySourceRefresh {
42
+ id: string;
43
+ sourceId: string;
44
+ changed: boolean;
45
+ previousFingerprint?: WorkDiscoveryPreview['fingerprint'];
46
+ currentFingerprint: WorkDiscoveryPreview['fingerprint'];
47
+ status: 'checked' | 'queued' | 'completed' | 'failed';
48
+ discoveryRunId?: string;
49
+ checkedAt: number;
50
+ }
51
+ export type WorkDiscoveryPersonalContextSource = 'apple_notes' | 'calendar' | 'reminders';
52
+ export interface WorkDiscoveryPersonalContextItem {
53
+ id: string;
54
+ source: WorkDiscoveryPersonalContextSource;
55
+ title: string;
56
+ group?: string;
57
+ content: string;
58
+ createdAt?: number;
59
+ modifiedAt?: number;
60
+ startsAt?: number;
61
+ endsAt?: number;
62
+ }
63
+ export type WorkUnderstandingInvestigationStatus = 'planning' | 'investigating' | 'synthesizing' | 'completed' | 'failed' | 'canceled';
64
+ export type WorkUnderstandingEvidenceSourceType = 'file' | 'git' | 'project_metadata' | 'personal_context' | 'session' | 'user_statement';
65
+ export interface WorkUnderstandingInvestigationBudget {
66
+ maxToolCalls: number;
67
+ maxContentChars: number;
68
+ maxDurationMs: number;
69
+ }
70
+ export interface WorkUnderstandingInvestigation {
71
+ id: string;
72
+ discoveryRunId: string;
73
+ status: WorkUnderstandingInvestigationStatus;
74
+ plan: {
75
+ hypotheses: string[];
76
+ questions: string[];
77
+ };
78
+ budget: WorkUnderstandingInvestigationBudget;
79
+ toolCallCount: number;
80
+ contentCharsRead: number;
81
+ startedAt: number;
82
+ completedAt?: number;
83
+ errorMessage?: string;
84
+ }
85
+ export interface WorkUnderstandingEvidenceItem {
86
+ id: string;
87
+ investigationId: string;
88
+ sourceGrantId?: string;
89
+ projectId?: string;
90
+ sourceType: WorkUnderstandingEvidenceSourceType;
91
+ sourceRef: string;
92
+ observation: string;
93
+ contentHash?: string;
94
+ observedAt?: number;
95
+ collectedAt: number;
96
+ sensitivity: 'normal' | 'restricted';
97
+ }
98
+ export type WorkUnderstandingThreadStatus = 'active' | 'paused' | 'blocked' | 'completed' | 'uncertain';
99
+ export type WorkUnderstandingThreadHorizon = 'current' | 'ongoing' | 'long_term';
100
+ export type WorkUnderstandingThreadUserStatus = 'unreviewed' | 'confirmed' | 'corrected' | 'rejected';
101
+ export interface WorkUnderstandingThreadCandidate {
102
+ topicKey: string;
103
+ title: string;
104
+ summary: string;
105
+ status: WorkUnderstandingThreadStatus;
106
+ horizon: WorkUnderstandingThreadHorizon;
107
+ confidence: 'high' | 'medium' | 'low';
108
+ evidenceRefs: string[];
109
+ }
110
+ export interface WorkUnderstandingThread {
111
+ id: string;
112
+ canonicalKey: string;
113
+ title: string;
114
+ summary: string;
115
+ status: WorkUnderstandingThreadStatus;
116
+ horizon: WorkUnderstandingThreadHorizon;
117
+ focusScore: number;
118
+ confidence: number;
119
+ userStatus: WorkUnderstandingThreadUserStatus;
120
+ projectIds: string[];
121
+ evidenceIds: string[];
122
+ parentThreadId?: string;
123
+ firstObservedAt: number;
124
+ lastObservedAt: number;
125
+ createdAt: number;
126
+ updatedAt: number;
127
+ }
12
128
  export type WorkDiscoveryErrorCode = 'folder_unavailable' | 'folder_not_readable' | 'nothing_useful_found' | 'model_unavailable' | 'analysis_invalid' | 'analysis_timeout' | 'canceled' | 'internal_error';
13
129
  export interface WorkDiscoveryEvidence {
14
130
  path?: string;
@@ -32,9 +148,37 @@ export interface WorkDiscoveryResult {
32
148
  currentState: string;
33
149
  uncertainties: string[];
34
150
  suggestions: WorkDiscoverySuggestion[];
151
+ discoveredProjects?: Array<{
152
+ rootPath: string;
153
+ displayName: string;
154
+ score: number;
155
+ projectKind: 'coding' | 'general' | 'unknown';
156
+ lastActiveAt?: number;
157
+ evidence: string[];
158
+ }>;
159
+ profileCandidates?: WorkDiscoveryProfileCandidate[];
35
160
  primarySuggestionId?: string;
36
161
  lowConfidence?: boolean;
37
162
  contextQuestion?: string;
163
+ investigation?: {
164
+ id: string;
165
+ hypotheses: string[];
166
+ questions: string[];
167
+ toolCallCount: number;
168
+ contentCharsRead: number;
169
+ degraded: boolean;
170
+ };
171
+ workThreadCandidates?: WorkUnderstandingThreadCandidate[];
172
+ workThreads?: WorkUnderstandingThread[];
173
+ }
174
+ export interface WorkDiscoveryProfileCandidate {
175
+ id: string;
176
+ memoryRecordId?: string;
177
+ category: 'role' | 'focus' | 'technology' | 'workflow' | 'preference';
178
+ statement: string;
179
+ confidence: 'high' | 'medium' | 'low';
180
+ evidence: string[];
181
+ status: 'pending' | 'accepted' | 'edited' | 'rejected';
38
182
  }
39
183
  export type WorkDiscoveryRecognitionDecision = 'confirmed' | 'corrected' | 'different_goal' | 'dismissed';
40
184
  export interface WorkDiscoveryFeedback {
@@ -127,6 +271,7 @@ export interface WorkDiscoveryPreview {
127
271
  branch?: string;
128
272
  changedFileCount: number;
129
273
  recentAreas: string[];
274
+ contentSignature: string;
130
275
  generatedAt: number;
131
276
  };
132
277
  provider: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xopcai/xopc",
3
- "version": "0.0.159",
3
+ "version": "0.0.161",
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",
@@ -26,7 +26,7 @@ Recommended questions for a new pet:
26
26
  - Choices: `Soft and cute`, `Techy and energetic`, `Calm and focused`, `Describe my own`
27
27
  - Default: `Soft and cute`
28
28
  3. Signature work behavior: ask which behavior should be most recognizable.
29
- - Choices: `Typing at a laptop`, `Searching a toolbox`, `Celebrating completed work`, `Describe my own`
29
+ - Choices: `Creating at a laptop`, `Investigating clues`, `Celebrating completed work`, `Describe my own`
30
30
  - Default: `Typing at a laptop`
31
31
 
32
32
  For an existing pet update, ask only what is missing for the requested refinement:
@@ -44,7 +44,7 @@ After clarification, synthesize one complete `prompt` for `create_desktop_pet`.
44
44
 
45
45
  - The pet's base form, silhouette, colors, face/expression, and visual style.
46
46
  - Personality and short dialogue tone.
47
- - Required desktop-helper animation ideas: idle, greeting, thinking, typing at a laptop, searching through a toolbox, reading/searching, file or terminal work, success celebration, and error/blocked reaction.
47
+ - Required v2 desktop-helper animation ideas: idle/sleep/wake, greeting and petting, preparing, researching, reading, creating, executing, safely waiting, success celebration, concern, and picked-up/released reactions.
48
48
  - Any user-requested refinements, constraints, or brand cues.
49
49
  - A note that the pet should read clearly at small desktop size and feel cute, lively, and polished.
50
50
 
@@ -1 +0,0 @@
1
- import{p as e}from"./locale-store-C_M71MK9.js";var t=`xopc.activity-center.v1`,n=80;function r(e){return e===`error`?`failed`:e===`warning`?`attention`:`done`}function i(){if(!(typeof window>`u`))return window.location.hash.replace(/^#/,``)||`${window.location.pathname}${window.location.search}`||void 0}function a(){try{let e=globalThis.localStorage?.getItem(t);if(!e)return[];let r=JSON.parse(e);return Array.isArray(r.items)?r.items.filter(e=>e&&typeof e.id==`string`&&typeof e.title==`string`).slice(0,n):[]}catch{return[]}}function o(e){try{globalThis.localStorage?.setItem(t,JSON.stringify({items:e}))}catch{}}function s(e){return`${e.toString(36)}-${Math.random().toString(36).slice(2,8)}`}var c=e(e=>({items:a(),add:t=>e(e=>{let a=t.title.trim();if(!a)return e;let c=Date.now(),l=t.tone??`info`,u=t.dedupeKey?e.items.findIndex(e=>e.dedupeKey===t.dedupeKey):-1,d=[{id:u>=0?e.items[u].id:s(c),tone:l,status:t.status??r(l),title:a,message:t.message?.trim()||void 0,source:t.source?.trim()||void 0,href:t.href??i(),dedupeKey:t.dedupeKey,createdAt:u>=0?e.items[u].createdAt:c,updatedAt:c,read:t.read??!1,occurrences:u>=0?e.items[u].occurrences+1:1},...u>=0?e.items.filter((e,t)=>t!==u):e.items].slice(0,n);return o(d),{items:d}}),markAllRead:()=>e(e=>{let t=e.items.map(e=>({...e,read:!0}));return o(t),{items:t}}),remove:t=>e(e=>{let n=e.items.filter(e=>e.id!==t);return o(n),{items:n}}),clearFinished:()=>e(e=>{let t=e.items.filter(e=>e.status!==`done`);return o(t),{items:t}}),clear:()=>{o([]),e({items:[]})}}));function l(e){c.getState().add(e)}export{c as n,l as t};