@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.
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{action-boundary-settings-panel-CaRK2vIy.js → action-boundary-settings-panel-BIVBUiNT.js} +1 -1
- package/dist/gateway/static/root/assets/activity-store-o7GRljfD.js +1 -0
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-BeVf03hx.js → agent-avatar-dicebear-9R3szLMc.js} +1 -1
- package/dist/gateway/static/root/assets/agents-_qbUaYbs.js +2 -0
- package/dist/gateway/static/root/assets/{api-BjcBIV2O.js → api-jSTqFMq9.js} +1 -1
- package/dist/gateway/static/root/assets/{app-management-settings-panel-BG2ulMYw.js → app-management-settings-panel-D81cyE76.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-0Kjenr2T.js → appearance-settings-Ct6bZQCV.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-0sPqD0FK.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-ChiNnH1e.js → archive-plugin-CfD7AZKn.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-pbBlQR-g.js → attachment-load-CP_Gaxt3.js} +1 -1
- package/dist/gateway/static/root/assets/{automation-suggestion-card-CTZDOyDy.js → automation-suggestion-card-BGKM_NDZ.js} +1 -1
- package/dist/gateway/static/root/assets/automations-page-BxWBuBsE.js +6 -0
- package/dist/gateway/static/root/assets/{binary-plugins-BeZGzpGF.js → binary-plugins-IPr2EVnS.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-BnDmhN5Z.js → block-editor-B6aHEGA6.js} +3 -3
- package/dist/gateway/static/root/assets/browser-settings-page-C499b9AH.js +8 -0
- package/dist/gateway/static/root/assets/{capability-presets-api-Ii36j_7v.js → capability-presets-api-CCX9-LjU.js} +1 -1
- package/dist/gateway/static/root/assets/{capability-presets-settings-panel-Cl3dw4yh.js → capability-presets-settings-panel-Dva9SiPK.js} +2 -2
- package/dist/gateway/static/root/assets/{channel-recipient-api-CFqrSi5K.js → channel-recipient-api-MmLMLDWf.js} +1 -1
- package/dist/gateway/static/root/assets/channels-settings-DNAU7u9o.js +1 -0
- package/dist/gateway/static/root/assets/channels-status-swr-CIOH7tgn.js +1 -0
- package/dist/gateway/static/root/assets/check-DUBLcKHA.js +1 -0
- package/dist/gateway/static/root/assets/circle-alert-BEjgurr2.js +1 -0
- package/dist/gateway/static/root/assets/cn-JdwAhgNB.js +1 -0
- package/dist/gateway/static/root/assets/{connector-logo-CiLxuZ8S.js → connector-logo-BbjzIs87.js} +1 -1
- package/dist/gateway/static/root/assets/connectors-page-TwiBp8vY.js +2 -0
- package/dist/gateway/static/root/assets/createLucideIcon-DPHK1VkS.js +1 -0
- package/dist/gateway/static/root/assets/desktop-pet-CYH5ZSXy.js +1 -0
- package/dist/gateway/static/root/assets/desktop-pet-settings-DQLqGLc0.js +1 -0
- package/dist/gateway/static/root/assets/desktop-pet-sprite-DTqXSpqf.js +1 -0
- package/dist/gateway/static/root/assets/{directory-picker-path-field-CC2VL5Mc.js → directory-picker-path-field-ClsiXhmz.js} +1 -1
- package/dist/gateway/static/root/assets/{dreaming-settings-KY7ZfVsy.js → dreaming-settings-CjMPPdzg.js} +3 -3
- package/dist/gateway/static/root/assets/{extension-debug-page-C8KBeucs.js → extension-debug-page-57eizjhB.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-CV-5Kcyk.js → extension-page-CsbSb3u1.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-DvUtDrAu.js → extension-settings-page-DKA9-lyP.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-api-DXfVeJLc.js → gateway-config-api-DIPJuzBZ.js} +1 -1
- package/dist/gateway/static/root/assets/gateway-settings-CDLqAQY7.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-startup-retry-cxQ94qMm.js → gateway-startup-retry-DrfSJtvT.js} +1 -1
- package/dist/gateway/static/root/assets/goal-create-dialog-Q3B0E-0s.js +1 -0
- package/dist/gateway/static/root/assets/goal-detail-page-C5VAK04G.js +4 -0
- package/dist/gateway/static/root/assets/{goals-config-api-P8VhLqYF.js → goals-config-api-lGC10UkU.js} +1 -1
- package/dist/gateway/static/root/assets/goals-page-BJb-5IYw.js +2 -0
- package/dist/gateway/static/root/assets/{goals-settings-DHXyaH_O.js → goals-settings-BWq0pdrA.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-settings-CNckP_Dv.js → heartbeat-settings-D4o8BJVv.js} +1 -1
- package/dist/gateway/static/root/assets/index-CkUHH170.css +1 -0
- package/dist/gateway/static/root/assets/index-vq_cJZJC.js +199 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-jXmv1RVX.js → keyboard-shortcuts-settings-6T2QYehS.js} +1 -1
- package/dist/gateway/static/root/assets/local-app-workbench-page-euH17Kvb.js +2 -0
- package/dist/gateway/static/root/assets/{local-apps-page-Cs5LKjtc.js → local-apps-page-DCjg2K9f.js} +1 -1
- package/dist/gateway/static/root/assets/{locale-store-C_M71MK9.js → locale-store-Dar-xqQr.js} +1 -1
- package/dist/gateway/static/root/assets/logs-page-CyYCBqym.js +7 -0
- package/dist/gateway/static/root/assets/{markdown-split-BFqeSNte.js → markdown-split-rt1XO43g.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-Cc8379gq.js → media-plugins-Bwo8CJuh.js} +1 -1
- package/dist/gateway/static/root/assets/messages-CxySDn9d.js +5 -0
- package/dist/gateway/static/root/assets/models-hub-panel-DObxxjc9.js +2 -0
- package/dist/gateway/static/root/assets/{notes-page-DlGU4ipo.js → notes-page-Dp-pkX7d.js} +1 -1
- package/dist/gateway/static/root/assets/notes-workbench-CCb4RXcZ.js +4 -0
- package/dist/gateway/static/root/assets/{page-tabs-kFOswGlG.js → page-tabs-CzZ4iKOb.js} +1 -1
- package/dist/gateway/static/root/assets/{preview-open-alternatives-CvjuvABg.js → preview-open-alternatives-3E_Qa-58.js} +1 -1
- package/dist/gateway/static/root/assets/product-delivery-BTRT9kCS.js +1 -0
- package/dist/gateway/static/root/assets/product-open-page-B2T48Sbt.js +1 -0
- package/dist/gateway/static/root/assets/project-detail-page-BvEcriRC.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-B_e79MRJ.js +1 -0
- package/dist/gateway/static/root/assets/remote-access-hub-DGcqnYfR.js +1 -0
- package/dist/gateway/static/root/assets/{save-bar-controls-DwrD7ODx.js → save-bar-controls-CkeKasGm.js} +1 -1
- package/dist/gateway/static/root/assets/{schedule-field-Ba4WzTmE.js → schedule-field-TkqUL3wm.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-DvydL8eF.js → schema-form-DC-iU5IG.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-DQZhrDJ8.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-BkdeN99Y.js +1 -0
- package/dist/gateway/static/root/assets/{settings-collapsible-section-LaQqGGej.js → settings-collapsible-section-Dpqth3oA.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-form-section-DruI__qO.js → settings-form-section-CNqF6IwY.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-loading-skeleton-UvA-eDhF.js → settings-loading-skeleton-DkvwitK_.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-layout-DG-XMIPu.js → settings-page-layout-DWvNgISx.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-5oCGSebm.js → settings-page-qPG7I2zd.js} +1 -1
- package/dist/gateway/static/root/assets/setup-status-panel-lwRAh9aw.js +1 -0
- package/dist/gateway/static/root/assets/{share-preview-page-FLVeTrRt.js → share-preview-page-DGpSPW-n.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-BGj9IVUr.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-B2UBAs5U.js +1 -0
- package/dist/gateway/static/root/assets/skills-page-DdjzFZ8I.js +2 -0
- package/dist/gateway/static/root/assets/{system-settings-panel-CeK93xVi.js → system-settings-panel-8TxxSbUw.js} +1 -1
- package/dist/gateway/static/root/assets/{theme-store-C8ohIHhw.js → theme-store-B5FzMWOx.js} +1 -1
- package/dist/gateway/static/root/assets/{typed-models-lib-D1Lr2gG0.js → typed-models-lib-DEGtSA5h.js} +1 -1
- package/dist/gateway/static/root/assets/{use-channel-catalog-BWzou5ar.js → use-channel-catalog-BDU6FneG.js} +1 -1
- package/dist/gateway/static/root/assets/user-context-page-BTTZpAGV.js +1 -0
- package/dist/gateway/static/root/assets/voice-api-key-field-DuDQd-WU.js +1 -0
- package/dist/gateway/static/root/assets/work-discovery-page-BUVkVCsW.js +1 -0
- package/dist/gateway/static/root/assets/work-item-detail-page-DeEPPu4n.js +1 -0
- package/dist/gateway/static/root/assets/work-page-DQNUyTUq.js +1 -0
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-Bynqe4kV.js → workflow-run-setup-panel-Cwi8Pz7n.js} +2 -2
- package/dist/gateway/static/root/assets/workflows-page-BIy4wrzO.js +11 -0
- package/dist/gateway/static/root/index.html +12 -10
- package/dist/package.js +1 -1
- package/dist/src/automations/service/action-executor.js +1 -1
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/config/agent-profile.js +1 -1
- package/dist/src/gateway/agents-admin.js +1 -1
- package/dist/src/gateway/chat-stream/mapper.d.ts +1 -0
- package/dist/src/gateway/chat-stream/mapper.js +43 -7
- package/dist/src/gateway/hono/routes/home.js +15 -2
- package/dist/src/gateway/hono/routes/work-discovery.js +451 -0
- package/dist/src/gateway/hono/sse.d.ts +2 -0
- package/dist/src/gateway/hono/sse.js +10 -3
- package/dist/src/gateway/run-loop.js +17 -7
- package/dist/src/gateway/server.d.ts +1 -0
- package/dist/src/gateway/server.js +9 -0
- package/dist/src/gateway/service.d.ts +2 -0
- package/dist/src/gateway/service.js +27 -2
- package/dist/src/local-apps/preview-runtime-bridge.d.ts +1 -1
- package/dist/src/local-apps/preview-runtime-bridge.js +14 -11
- package/dist/src/mobile/notification-service.js +1 -0
- package/dist/src/pets/factory.js +23 -26
- package/dist/src/pets/manifest.d.ts +2 -1
- package/dist/src/pets/manifest.js +15 -8
- package/dist/src/pets/validator.js +8 -3
- package/dist/src/proactive/calendar-signals.d.ts +4 -0
- package/dist/src/proactive/calendar-signals.js +120 -0
- package/dist/src/proactive/focus-service.d.ts +62 -0
- package/dist/src/proactive/focus-service.js +173 -0
- package/dist/src/proactive/index.d.ts +7 -0
- package/dist/src/proactive/index.js +7 -0
- package/dist/src/proactive/insight-repository.d.ts +19 -0
- package/dist/src/proactive/insight-repository.js +106 -0
- package/dist/src/proactive/run-processor.d.ts +19 -0
- package/dist/src/proactive/run-processor.js +125 -0
- package/dist/src/proactive/trial-expiry-reconciler.d.ts +5 -0
- package/dist/src/proactive/trial-expiry-reconciler.js +30 -0
- package/dist/src/proactive/types.d.ts +64 -0
- package/dist/src/proactive/types.js +1 -0
- package/dist/src/proactive/watch-repository.d.ts +28 -0
- package/dist/src/proactive/watch-repository.js +129 -0
- package/dist/src/storage/sqlite/knowledge-repository.d.ts +1 -0
- package/dist/src/storage/sqlite/knowledge-repository.js +4 -0
- package/dist/src/storage/sqlite/migrations/047_work_discovery_sources.sql +16 -0
- package/dist/src/storage/sqlite/migrations/048_work_understanding_investigations.sql +40 -0
- package/dist/src/storage/sqlite/migrations/049_work_understanding_threads.sql +52 -0
- package/dist/src/storage/sqlite/migrations/050_work_discovery_source_refreshes.sql +15 -0
- package/dist/src/storage/sqlite/migrations/051_focus_watches.sql +26 -0
- package/dist/src/storage/sqlite/migrations/052_proactive_insights.sql +25 -0
- package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
- package/dist/src/storage/sqlite/migrations/runner.js +3 -3
- package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
- package/dist/src/storage/sqlite/schema.js +1 -1
- package/dist/src/work-discovery/analyzer.d.ts +12 -1
- package/dist/src/work-discovery/analyzer.js +126 -7
- package/dist/src/work-discovery/candidate-discovery.d.ts +17 -0
- package/dist/src/work-discovery/candidate-discovery.js +279 -0
- package/dist/src/work-discovery/evaluation.d.ts +11 -0
- package/dist/src/work-discovery/evaluation.js +17 -0
- package/dist/src/work-discovery/governance.d.ts +25 -0
- package/dist/src/work-discovery/governance.js +96 -0
- package/dist/src/work-discovery/incremental-repository.d.ts +13 -0
- package/dist/src/work-discovery/incremental-repository.js +55 -0
- package/dist/src/work-discovery/incremental.d.ts +2 -0
- package/dist/src/work-discovery/incremental.js +7 -0
- package/dist/src/work-discovery/index.d.ts +10 -0
- package/dist/src/work-discovery/index.js +13 -3
- package/dist/src/work-discovery/investigation-repository.d.ts +16 -0
- package/dist/src/work-discovery/investigation-repository.js +122 -0
- package/dist/src/work-discovery/investigator.d.ts +55 -0
- package/dist/src/work-discovery/investigator.js +358 -0
- package/dist/src/work-discovery/probe.d.ts +22 -0
- package/dist/src/work-discovery/probe.js +88 -1
- package/dist/src/work-discovery/service.d.ts +110 -1
- package/dist/src/work-discovery/service.js +578 -8
- package/dist/src/work-discovery/source-repository.d.ts +13 -0
- package/dist/src/work-discovery/source-repository.js +72 -0
- package/dist/src/work-discovery/thread-repository.d.ts +34 -0
- package/dist/src/work-discovery/thread-repository.js +112 -0
- package/dist/src/work-discovery/thread-service.d.ts +8 -0
- package/dist/src/work-discovery/thread-service.js +104 -0
- package/dist/src/work-discovery/types.d.ts +145 -0
- package/package.json +1 -1
- package/skills/creative/hatch-pet/SKILL.md +2 -2
- package/dist/gateway/static/root/assets/activity-store-C-57rvkX.js +0 -1
- package/dist/gateway/static/root/assets/agents-P05C4A-3.js +0 -2
- package/dist/gateway/static/root/assets/apps-page-DANGrBpN.js +0 -1
- package/dist/gateway/static/root/assets/automations-page-BXfGL_cm.js +0 -6
- package/dist/gateway/static/root/assets/browser-settings-page-534luV0B.js +0 -8
- package/dist/gateway/static/root/assets/channels-settings-M91zFJVi.js +0 -1
- package/dist/gateway/static/root/assets/channels-status-swr-vooEF4lG.js +0 -1
- package/dist/gateway/static/root/assets/check-BODqo66o.js +0 -1
- package/dist/gateway/static/root/assets/circle-alert-RzVebuX2.js +0 -1
- package/dist/gateway/static/root/assets/cn-BQ_8x0bT.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-CV5UulW6.js +0 -2
- package/dist/gateway/static/root/assets/desktop-pet-Cil2eSpW.js +0 -1
- package/dist/gateway/static/root/assets/desktop-pet-settings-DwsC6l5F.js +0 -1
- package/dist/gateway/static/root/assets/desktop-pet-sprite-DqZ6fbIj.js +0 -1
- package/dist/gateway/static/root/assets/gateway-settings-BpJ0v56l.js +0 -1
- package/dist/gateway/static/root/assets/goal-create-dialog-lMHD-2CX.js +0 -1
- package/dist/gateway/static/root/assets/goal-detail-page-yPmF-G7b.js +0 -4
- package/dist/gateway/static/root/assets/goals-page-BHTCKobG.js +0 -2
- package/dist/gateway/static/root/assets/index-BgZhEOkN.css +0 -1
- package/dist/gateway/static/root/assets/index-BuqGh2SW.js +0 -193
- package/dist/gateway/static/root/assets/local-app-workbench-page-zpp_wciE.js +0 -2
- package/dist/gateway/static/root/assets/logs-page-B4CRYqYR.js +0 -7
- package/dist/gateway/static/root/assets/messages-BuT0SR1R.js +0 -5
- package/dist/gateway/static/root/assets/models-hub-panel-1hdoAoB_.js +0 -2
- package/dist/gateway/static/root/assets/notes-workbench-DQEAZTA5.js +0 -4
- package/dist/gateway/static/root/assets/project-detail-page-Bp9bC7A6.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-RNorFXTw.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-BqRTcM_6.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-B2EfW1cm.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-CklL85T4.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-D3my1HgB.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-DVxgjrsP.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-Bcu58ZaF.js +0 -1
- package/dist/gateway/static/root/assets/skills-page-CDd-84FE.js +0 -2
- package/dist/gateway/static/root/assets/sliding-segmented-uWmrxE3P.js +0 -1
- package/dist/gateway/static/root/assets/user-context-page-1OyJnTyR.js +0 -1
- package/dist/gateway/static/root/assets/voice-api-key-field-B2ncRwHS.js +0 -1
- package/dist/gateway/static/root/assets/work-discovery-page-BZlY4PZL.js +0 -1
- package/dist/gateway/static/root/assets/work-item-detail-page-DPXMrneY.js +0 -1
- package/dist/gateway/static/root/assets/work-page-CTERoqyv.js +0 -1
- 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
|
@@ -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: `
|
|
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
|
|
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};
|