@xopcai/xopc 0.0.228 → 0.0.230
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/{agent-avatar-dicebear-CjGZBs4C.js → agent-avatar-dicebear-Bp_wmuGW.js} +1 -1
- package/dist/gateway/static/root/assets/{agents-B0NI4_NI.js → agents-CKG93dlc.js} +1 -1
- package/dist/gateway/static/root/assets/{app-management-settings-panel--SjycrXk.js → app-management-settings-panel-CwAPK4Jm.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-8G-TVUtg.js → appearance-settings-DsGLvqTb.js} +1 -1
- package/dist/gateway/static/root/assets/{apps-page-2NiqD-YP.js → apps-page-Ee9qOQEx.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-Bx44zSpz.js → attachment-load-B4qqigAQ.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-page-CrKAHqc0.js → automations-page-B8ImehSW.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-workspace-Q3g9cf0h.js → automations-workspace-BNFAfNwC.js} +1 -1
- package/dist/gateway/static/root/assets/{binary-plugins-DjDwnHAQ.js → binary-plugins-DaJbyYc2.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-7aMOKoZM.js → block-editor-Kl25XWJc.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-settings-page-DTwPkmAC.js → browser-settings-page-Cg6NgwE_.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-workflows-page-DVLrWKz_.js → browser-workflows-page-DjMxs33B.js} +1 -1
- package/dist/gateway/static/root/assets/{capabilities-settings-panel-YcP4FbN7.js → capabilities-settings-panel-NvJKgF1u.js} +1 -1
- package/dist/gateway/static/root/assets/{capability-presets-settings-panel-AcPjHHia.js → capability-presets-settings-panel-C2uBdALe.js} +1 -1
- package/dist/gateway/static/root/assets/{channels-settings-Ca94Q1D-.js → channels-settings-CIcYKMEs.js} +1 -1
- package/dist/gateway/static/root/assets/{chat-terminal-dock-BR-_7KC0.js → chat-terminal-dock-BiU_4Rq6.js} +1 -1
- package/dist/gateway/static/root/assets/{connectors-page-SGxfLTd6.js → connectors-page-CEEcmUiP.js} +1 -1
- package/dist/gateway/static/root/assets/{cron-expression-D8-c-Tkw.js → cron-expression-Cs_5pUPT.js} +1 -1
- package/dist/gateway/static/root/assets/{date-picker-kV-Jyl9J.js → date-picker-y1kWrFVU.js} +1 -1
- package/dist/gateway/static/root/assets/{dependency-picker-CwKcrfGj.js → dependency-picker-skc62zrn.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-CTs5WGzk.js → desktop-pet-settings-BVVCBgYK.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-D9rnchu3.js → desktop-pet-ux9DxchT.js} +1 -1
- package/dist/gateway/static/root/assets/{directory-picker-path-field-CCl0aaDm.js → directory-picker-path-field-V8vZP0Dy.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-Cau40SvC.js → extension-debug-page-Dh6DDuvQ.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-BsJXdvIL.js → extension-page-8OKQDEat.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-qWqJyF7-.js → extension-settings-page-BgSV0Nny.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-api-BI0SELXm.js → gateway-config-api-Dlc6eaTG.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-settings-6ZdOIC7F.js → gateway-settings-DqQgiAUv.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-settings-KBwhXeFD.js → heartbeat-settings-Pxqk5GFH.js} +1 -1
- package/dist/gateway/static/root/assets/{home-page-BA2M4CLi.js → home-page-1xjo6wE4.js} +1 -1
- package/dist/gateway/static/root/assets/{index-BX0dz1JK.js → index-Bbd_dXui.js} +17 -17
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-kHtpnyEm.js → keyboard-shortcuts-settings-BSFNqxzY.js} +1 -1
- package/dist/gateway/static/root/assets/{local-app-workbench-page-D2nkn09R.js → local-app-workbench-page-heQ4-PJ7.js} +1 -1
- package/dist/gateway/static/root/assets/{local-apps-page-BCXa0oUa.js → local-apps-page-DzU6yZ9-.js} +1 -1
- package/dist/gateway/static/root/assets/{logs-page-D3sNst0K.js → logs-page-BblnS6Jy.js} +1 -1
- package/dist/gateway/static/root/assets/{management-settings-tHnlfOAQ.js → management-settings-B8hM56HS.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-split-BMLqHHr5.js → markdown-split-DRbZjxMK.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-DybwqTgv.js → media-plugins-B8vMe5VX.js} +1 -1
- package/dist/gateway/static/root/assets/{notes-page-C24SfF6r.js → notes-page-B-YZ7iuK.js} +1 -1
- package/dist/gateway/static/root/assets/{notes-workbench-CTdZc3ov.js → notes-workbench-CAM09C8b.js} +2 -2
- package/dist/gateway/static/root/assets/{product-open-page-DBfCVlJq.js → product-open-page-DkWcyki5.js} +1 -1
- package/dist/gateway/static/root/assets/{project-detail-page-COHaEpbA.js → project-detail-page-BIPIwgU2.js} +1 -1
- package/dist/gateway/static/root/assets/{projects-page-lMnST7D_.js → projects-page-B_kzTn1K.js} +1 -1
- package/dist/gateway/static/root/assets/{remote-access-hub-BIRKBvO_.js → remote-access-hub-CtD8DsD-.js} +1 -1
- package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-BPEGTip5.js → runtime-tools-settings-panel-Bq_ETeal.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-Dxlu60Td.js → schema-form-BogTlrsP.js} +1 -1
- package/dist/gateway/static/root/assets/{sessions-page-CATO9G3y.js → sessions-page-B8n9HI1y.js} +1 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-xlhdRTME.js +1 -0
- package/dist/gateway/static/root/assets/{settings-form-section-ChXh3Bwk.js → settings-form-section-Coy1Cbp6.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-loading-skeleton-BCAUqIe2.js → settings-loading-skeleton-B5GU7iCG.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-D25W9Okr.js → settings-page-Dd-BRu12.js} +1 -1
- package/dist/gateway/static/root/assets/{setup-status-panel-DsN7Z4Fl.js → setup-status-panel-CwEFAVWx.js} +1 -1
- package/dist/gateway/static/root/assets/{share-preview-page-CRFnUaNb.js → share-preview-page-DzXw9UQJ.js} +1 -1
- package/dist/gateway/static/root/assets/{shares-settings-CAX0eNaP.js → shares-settings-Bk6UQOwS.js} +1 -1
- package/dist/gateway/static/root/assets/{skill-reload-api-Doy1gghe.js → skill-reload-api-DrmQZ3Au.js} +1 -1
- package/dist/gateway/static/root/assets/{skills-page-Cl7jjTK7.js → skills-page-Brxb6QnW.js} +1 -1
- package/dist/gateway/static/root/assets/{skills-page.utils-BiCl4nb5.js → skills-page.utils-FB5LtEGm.js} +1 -1
- package/dist/gateway/static/root/assets/{system-settings-panel-BuESR7ZT.js → system-settings-panel-ChosWt8n.js} +1 -1
- package/dist/gateway/static/root/assets/{task-detail-page-BRiy8NL3.js → task-detail-page-CW2sJbdc.js} +1 -1
- package/dist/gateway/static/root/assets/{use-autosave-Dg1mgJ_l.js → use-autosave-2SqnmSKD.js} +1 -1
- package/dist/gateway/static/root/assets/{user-context-page-CqoADNKu.js → user-context-page-Bq9KB-Oj.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-api-key-field-BDNexlVR.js → voice-api-key-field-DtTIF6M8.js} +1 -1
- package/dist/gateway/static/root/assets/{work-discovery-overlay-BHTfeaWL.js → work-discovery-overlay-CK3aZDdE.js} +1 -1
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-Cf_w-NZy.js → workflow-run-setup-panel-BjOuddkX.js} +1 -1
- package/dist/gateway/static/root/assets/{workflows-page-j0P-uECz.js → workflows-page-CcbGEQol.js} +1 -1
- package/dist/gateway/static/root/index.html +1 -1
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-instance-gateway.d.ts +1 -1
- package/dist/src/agent/agent-manager.d.ts +1 -1
- package/dist/src/agent/agent-manager.js +18 -3
- package/dist/src/agent/background-review/prompts.d.ts +8 -2
- package/dist/src/agent/background-review/prompts.js +25 -12
- package/dist/src/agent/background-review/run-background-review.d.ts +7 -2
- package/dist/src/agent/background-review/run-background-review.js +175 -160
- package/dist/src/agent/inbound/turn-dispatcher.js +1 -1
- package/dist/src/agent/memory/index.d.ts +1 -1
- package/dist/src/agent/memory/index.js +2 -2
- package/dist/src/agent/memory/manager.d.ts +1 -11
- package/dist/src/agent/memory/manager.js +0 -16
- package/dist/src/agent/memory/understanding/service.d.ts +0 -11
- package/dist/src/agent/memory/understanding/service.js +7 -173
- package/dist/src/agent/memory/user-context-coordinator.d.ts +1 -3
- package/dist/src/agent/memory/user-context-coordinator.js +3 -66
- package/dist/src/agent/orchestration/agent-orchestrator.js +1 -1
- package/dist/src/agent/service/direct-turn-helpers.js +1 -1
- package/dist/src/agent/service/process-direct-streaming.js +4 -1
- package/dist/src/agent/service/webchat-tts.d.ts +2 -0
- package/dist/src/agent/service/webchat-tts.js +15 -2
- package/dist/src/agent/tools/tts-tool.js +19 -13
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/config/schema.d.ts +4 -0
- package/dist/src/config/schema.js +1 -0
- package/dist/src/connectors/connected-source-understanding.js +35 -21
- package/dist/src/connectors/learning-coordinator.js +1 -42
- package/dist/src/gateway/chat-stream/mapper.d.ts +2 -0
- package/dist/src/gateway/chat-stream/mapper.js +16 -0
- package/dist/src/gateway/hono/routes/understanding-sources.js +4 -1
- package/dist/src/gateway/hono/routes/voice.js +1 -1
- package/dist/src/gateway/hono/routes/you.js +29 -11
- package/dist/src/gateway/service/run-gateway-agent.js +5 -1
- package/dist/src/knowledge/index.d.ts +0 -1
- package/dist/src/knowledge/index.js +1 -2
- package/dist/src/notifications/planner.js +5 -1
- package/dist/src/storage/sqlite/index.d.ts +1 -1
- package/dist/src/storage/sqlite/index.js +2 -2
- package/dist/src/storage/sqlite/migrations/137_understanding_status_audit.sql +71 -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/storage/sqlite/user-context-repository.d.ts +16 -4
- package/dist/src/storage/sqlite/user-context-repository.js +56 -12
- package/dist/src/user-context/config.d.ts +8 -0
- package/dist/src/user-context/config.js +3 -0
- package/dist/src/user-context/consolidation.js +16 -4
- package/dist/src/user-context/extraction/executor.d.ts +22 -0
- package/dist/src/user-context/extraction/executor.js +142 -0
- package/dist/src/user-context/extraction/registry.d.ts +1 -1
- package/dist/src/user-context/extraction/registry.js +5 -34
- package/dist/src/user-context/extraction/repair.js +4 -1
- package/dist/src/user-context/extraction/semantic.d.ts +18 -0
- package/dist/src/user-context/extraction/semantic.js +148 -0
- package/dist/src/user-context/understandingQuality.js +4 -0
- package/dist/src/work-discovery/analyzer.js +9 -4
- package/dist/src/work-discovery/service.d.ts +1 -0
- package/dist/src/work-discovery/service.js +5 -4
- package/dist/src/work-discovery/types.d.ts +1 -0
- package/package.json +14 -8
- package/dist/gateway/static/root/assets/settings-advanced-gate-Cco_W41x.js +0 -1
- package/dist/src/agent/memory/understanding/correction.d.ts +0 -3
- package/dist/src/agent/memory/understanding/correction.js +0 -39
- package/dist/src/knowledge/connected-understanding-pipeline.d.ts +0 -17
- package/dist/src/knowledge/connected-understanding-pipeline.js +0 -278
|
@@ -4,6 +4,11 @@ import { retrievalQueryAuditValue } from "../../retrieval/audit.js";
|
|
|
4
4
|
import { buildFts5SearchQuery, fts5RankToScore } from "./fts.js";
|
|
5
5
|
import { createHash, randomUUID } from "node:crypto";
|
|
6
6
|
//#region src/storage/sqlite/user-context-repository.ts
|
|
7
|
+
function insertUnderstandingStatusEvent(db, input) {
|
|
8
|
+
db.prepare(`INSERT INTO understanding_status_events (
|
|
9
|
+
event_id, understanding_id, from_status, to_status, actor_type, source, created_at
|
|
10
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?)`).run(randomUUID(), input.understandingId, input.fromStatus ?? null, input.toStatus, input.actorType, input.source, input.createdAt);
|
|
11
|
+
}
|
|
7
12
|
function evidenceFromRow(row) {
|
|
8
13
|
return {
|
|
9
14
|
id: row.evidence_id,
|
|
@@ -144,6 +149,13 @@ function createUnderstanding(input, principalId = USER_CONTEXT_PRINCIPAL_ID) {
|
|
|
144
149
|
version_id, understanding_id, statement, payload_json, created_by, change_reason, created_at
|
|
145
150
|
) VALUES (?, ?, ?, ?, ?, ?, ?)`).run(versionId, id, input.statement.trim(), JSON.stringify(input.payload ?? {}), input.createdBy, input.changeReason, now);
|
|
146
151
|
db.prepare("INSERT INTO user_understanding_fts (statement, understanding_id, version_id) VALUES (?, ?, ?)").run(input.statement.trim(), id, versionId);
|
|
152
|
+
insertUnderstandingStatusEvent(db, {
|
|
153
|
+
understandingId: id,
|
|
154
|
+
toStatus: input.status,
|
|
155
|
+
actorType: input.createdBy === "user" ? "user" : "runtime",
|
|
156
|
+
source: `create:${input.changeReason}`,
|
|
157
|
+
createdAt: now
|
|
158
|
+
});
|
|
147
159
|
});
|
|
148
160
|
return getUnderstanding(id);
|
|
149
161
|
}
|
|
@@ -197,17 +209,29 @@ function reviseUnderstanding(id, statement, options) {
|
|
|
197
209
|
});
|
|
198
210
|
return getUnderstanding(id);
|
|
199
211
|
}
|
|
200
|
-
function setUnderstandingStatus(id, status,
|
|
212
|
+
function setUnderstandingStatus(id, status, options) {
|
|
213
|
+
const current = getUnderstanding(id);
|
|
214
|
+
if (!current) throw new Error(`User understanding not found: ${id}`);
|
|
201
215
|
const now = Date.now();
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
216
|
+
runSqliteWriteTransaction((db) => {
|
|
217
|
+
db.prepare(`UPDATE user_understandings
|
|
218
|
+
SET status = ?,
|
|
219
|
+
explicitness = COALESCE(?, explicitness),
|
|
220
|
+
confidence = COALESCE(?, confidence),
|
|
221
|
+
updated_at = ?
|
|
222
|
+
WHERE understanding_id = ?`).run(status, options?.explicitness ?? null, options?.confidence ?? null, now, id);
|
|
223
|
+
const assertionStatus = status === "active" ? "active" : status === "archived" ? "closed" : status === "rejected" ? "rejected" : "candidate";
|
|
224
|
+
db.prepare(`UPDATE context_temporal_assertions
|
|
225
|
+
SET status = ?, updated_at = ? WHERE object_type = 'understanding' AND object_id = ?`).run(assertionStatus, now, id);
|
|
226
|
+
if (current.status !== status) insertUnderstandingStatusEvent(db, {
|
|
227
|
+
understandingId: id,
|
|
228
|
+
fromStatus: current.status,
|
|
229
|
+
toStatus: status,
|
|
230
|
+
actorType: options?.actorType ?? "runtime",
|
|
231
|
+
source: options?.source ?? "repository-status-change",
|
|
232
|
+
createdAt: now
|
|
233
|
+
});
|
|
234
|
+
});
|
|
211
235
|
const result = getUnderstanding(id);
|
|
212
236
|
if (!result) throw new Error(`User understanding not found: ${id}`);
|
|
213
237
|
return result;
|
|
@@ -219,12 +243,20 @@ function closeUnderstandingValidity(id, validTo = Date.now()) {
|
|
|
219
243
|
if (!result) throw new Error(`User understanding not found: ${id}`);
|
|
220
244
|
return result;
|
|
221
245
|
}
|
|
222
|
-
function rejectUnderstanding(id, reason) {
|
|
246
|
+
function rejectUnderstanding(id, reason, actorType = "runtime") {
|
|
223
247
|
const current = getUnderstanding(id);
|
|
224
248
|
if (!current) throw new Error(`User understanding not found: ${id}`);
|
|
225
249
|
const now = Date.now();
|
|
226
250
|
runSqliteWriteTransaction((db) => {
|
|
227
251
|
db.prepare("UPDATE user_understandings SET status = 'rejected', updated_at = ? WHERE understanding_id = ?").run(now, id);
|
|
252
|
+
if (current.status !== "rejected") insertUnderstandingStatusEvent(db, {
|
|
253
|
+
understandingId: id,
|
|
254
|
+
fromStatus: current.status,
|
|
255
|
+
toStatus: "rejected",
|
|
256
|
+
actorType,
|
|
257
|
+
source: reason,
|
|
258
|
+
createdAt: now
|
|
259
|
+
});
|
|
228
260
|
db.prepare(`INSERT INTO context_suppressions (
|
|
229
261
|
suppression_id, principal_id, canonical_key, scope_type, scope_id, reason, expires_at, created_at
|
|
230
262
|
) VALUES (?, ?, ?, ?, ?, ?, NULL, ?)
|
|
@@ -232,6 +264,18 @@ function rejectUnderstanding(id, reason) {
|
|
|
232
264
|
});
|
|
233
265
|
return getUnderstanding(id);
|
|
234
266
|
}
|
|
267
|
+
function listUnderstandingStatusEvents(id) {
|
|
268
|
+
return getSqliteDatabase().prepare(`SELECT * FROM understanding_status_events
|
|
269
|
+
WHERE understanding_id = ? ORDER BY created_at DESC, rowid DESC`).all(id).map((row) => ({
|
|
270
|
+
id: row.event_id,
|
|
271
|
+
understandingId: row.understanding_id,
|
|
272
|
+
...row.from_status ? { fromStatus: row.from_status } : {},
|
|
273
|
+
toStatus: row.to_status,
|
|
274
|
+
actorType: row.actor_type,
|
|
275
|
+
source: row.source,
|
|
276
|
+
createdAt: row.created_at
|
|
277
|
+
}));
|
|
278
|
+
}
|
|
235
279
|
function deleteUnderstanding(id) {
|
|
236
280
|
return runSqliteWriteTransaction((db) => {
|
|
237
281
|
db.prepare("DELETE FROM user_understanding_fts WHERE understanding_id = ?").run(id);
|
|
@@ -442,4 +486,4 @@ function decideContextConsent(id, decision) {
|
|
|
442
486
|
return Number(result.changes) > 0;
|
|
443
487
|
}
|
|
444
488
|
//#endregion
|
|
445
|
-
export { closeUnderstandingValidity, consumeContextConsent, createCollaborationRule, createContextEvidence, createUnderstanding, decideContextConsent, deleteCollaborationRule, deleteUnderstanding, ensureContextConsent, getCollaborationRule, getTurnPersonalization, getUnderstanding, getUserProfile, hasContextConsent, isUnderstandingSuppressed, linkUnderstandingEvidence, listCollaborationRules, listUnderstandingEvidence, listUnderstandings, recordContextFeedback, recordContextRun, rejectUnderstanding, reviseCollaborationRule, reviseUnderstanding, searchActiveUnderstandings, setCollaborationRuleStatus, setUnderstandingStatus, updateUserProfile };
|
|
489
|
+
export { closeUnderstandingValidity, consumeContextConsent, createCollaborationRule, createContextEvidence, createUnderstanding, decideContextConsent, deleteCollaborationRule, deleteUnderstanding, ensureContextConsent, getCollaborationRule, getTurnPersonalization, getUnderstanding, getUserProfile, hasContextConsent, isUnderstandingSuppressed, linkUnderstandingEvidence, listCollaborationRules, listUnderstandingEvidence, listUnderstandingStatusEvents, listUnderstandings, recordContextFeedback, recordContextRun, rejectUnderstanding, reviseCollaborationRule, reviseUnderstanding, searchActiveUnderstandings, setCollaborationRuleStatus, setUnderstandingStatus, updateUserProfile };
|
|
@@ -96,6 +96,10 @@ export declare const UserMemoryConfigSchema: z.ZodDefault<z.ZodObject<{
|
|
|
96
96
|
}, z.core.$strict>>;
|
|
97
97
|
export declare const UserUnderstandingConfigSchema: z.ZodDefault<z.ZodObject<{
|
|
98
98
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
99
|
+
processingPolicy: z.ZodDefault<z.ZodEnum<{
|
|
100
|
+
local_only: "local_only";
|
|
101
|
+
remote_allowed: "remote_allowed";
|
|
102
|
+
}>>;
|
|
99
103
|
adaptiveCadence: z.ZodDefault<z.ZodBoolean>;
|
|
100
104
|
reviewIntervalTurns: z.ZodDefault<z.ZodNumber>;
|
|
101
105
|
maxHistoryMessages: z.ZodDefault<z.ZodNumber>;
|
|
@@ -204,6 +208,10 @@ export declare const UserContextConfigSchema: z.ZodDefault<z.ZodObject<{
|
|
|
204
208
|
}, z.core.$strict>>;
|
|
205
209
|
understanding: z.ZodDefault<z.ZodObject<{
|
|
206
210
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
211
|
+
processingPolicy: z.ZodDefault<z.ZodEnum<{
|
|
212
|
+
local_only: "local_only";
|
|
213
|
+
remote_allowed: "remote_allowed";
|
|
214
|
+
}>>;
|
|
207
215
|
adaptiveCadence: z.ZodDefault<z.ZodBoolean>;
|
|
208
216
|
reviewIntervalTurns: z.ZodDefault<z.ZodNumber>;
|
|
209
217
|
maxHistoryMessages: z.ZodDefault<z.ZodNumber>;
|
|
@@ -91,12 +91,14 @@ var init_config = __esmMin((() => {
|
|
|
91
91
|
});
|
|
92
92
|
UserUnderstandingConfigSchema = z.object({
|
|
93
93
|
enabled: z.boolean().default(true),
|
|
94
|
+
processingPolicy: z.enum(["local_only", "remote_allowed"]).default("remote_allowed"),
|
|
94
95
|
adaptiveCadence: z.boolean().default(true),
|
|
95
96
|
reviewIntervalTurns: z.number().int().min(1).max(1e3).default(10),
|
|
96
97
|
maxHistoryMessages: z.number().int().min(1).max(200).default(80),
|
|
97
98
|
maxDurationMs: z.number().int().min(1e3).max(6e5).default(12e4)
|
|
98
99
|
}).strict().default({
|
|
99
100
|
enabled: true,
|
|
101
|
+
processingPolicy: "remote_allowed",
|
|
100
102
|
adaptiveCadence: true,
|
|
101
103
|
reviewIntervalTurns: 10,
|
|
102
104
|
maxHistoryMessages: 80,
|
|
@@ -161,6 +163,7 @@ var init_config = __esmMin((() => {
|
|
|
161
163
|
},
|
|
162
164
|
understanding: {
|
|
163
165
|
enabled: true,
|
|
166
|
+
processingPolicy: "remote_allowed",
|
|
164
167
|
adaptiveCadence: true,
|
|
165
168
|
reviewIntervalTurns: 10,
|
|
166
169
|
maxHistoryMessages: 80,
|
|
@@ -97,7 +97,10 @@ async function runContextConsolidation(input) {
|
|
|
97
97
|
const evidenceCount = distinctEvidenceCount(understanding.id, "supports");
|
|
98
98
|
const contradictionCount = distinctEvidenceCount(understanding.id, "contradicts");
|
|
99
99
|
if (understanding.validTo != null && understanding.validTo <= now || understanding.expiresAt != null && understanding.expiresAt <= now) {
|
|
100
|
-
setUnderstandingStatus(understanding.id, "stale"
|
|
100
|
+
setUnderstandingStatus(understanding.id, "stale", {
|
|
101
|
+
actorType: "runtime",
|
|
102
|
+
source: "consolidation-expired"
|
|
103
|
+
});
|
|
101
104
|
recordContextConsolidationDecision({
|
|
102
105
|
runId: run.runId,
|
|
103
106
|
understandingId: understanding.id,
|
|
@@ -110,7 +113,10 @@ async function runContextConsolidation(input) {
|
|
|
110
113
|
continue;
|
|
111
114
|
}
|
|
112
115
|
if (contradictionCount > 0) {
|
|
113
|
-
setUnderstandingStatus(understanding.id, "needs_review"
|
|
116
|
+
setUnderstandingStatus(understanding.id, "needs_review", {
|
|
117
|
+
actorType: "runtime",
|
|
118
|
+
source: "consolidation-contradiction"
|
|
119
|
+
});
|
|
114
120
|
recordContextConsolidationDecision({
|
|
115
121
|
runId: run.runId,
|
|
116
122
|
understandingId: understanding.id,
|
|
@@ -123,7 +129,10 @@ async function runContextConsolidation(input) {
|
|
|
123
129
|
continue;
|
|
124
130
|
}
|
|
125
131
|
if (understanding.status === "active" && understanding.reviewAt != null && understanding.reviewAt <= now) {
|
|
126
|
-
setUnderstandingStatus(understanding.id, "needs_review"
|
|
132
|
+
setUnderstandingStatus(understanding.id, "needs_review", {
|
|
133
|
+
actorType: "runtime",
|
|
134
|
+
source: "consolidation-review-due"
|
|
135
|
+
});
|
|
127
136
|
recordContextConsolidationDecision({
|
|
128
137
|
runId: run.runId,
|
|
129
138
|
understandingId: understanding.id,
|
|
@@ -136,7 +145,10 @@ async function runContextConsolidation(input) {
|
|
|
136
145
|
continue;
|
|
137
146
|
}
|
|
138
147
|
if (understanding.status === "candidate" && evidenceCount >= resolved.minEvidenceSources) {
|
|
139
|
-
setUnderstandingStatus(understanding.id, "needs_review"
|
|
148
|
+
setUnderstandingStatus(understanding.id, "needs_review", {
|
|
149
|
+
actorType: "runtime",
|
|
150
|
+
source: "consolidation-evidence-threshold"
|
|
151
|
+
});
|
|
140
152
|
recordContextConsolidationDecision({
|
|
141
153
|
runId: run.runId,
|
|
142
154
|
understandingId: understanding.id,
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Config } from '../../config/schema.js';
|
|
2
|
+
import type { MemoryManager } from '../../agent/memory/manager.js';
|
|
3
|
+
import type { UnderstandingReviewResult } from '../../agent/memory/understanding/types.js';
|
|
4
|
+
import { type ExtractorId } from './registry.js';
|
|
5
|
+
import type { SemanticEvidence, SemanticUnderstandingInterpretation } from './semantic.js';
|
|
6
|
+
export type UnderstandingEvidenceMessage = SemanticEvidence & {
|
|
7
|
+
createdAt: number;
|
|
8
|
+
message: unknown;
|
|
9
|
+
};
|
|
10
|
+
export declare function emptyUnderstandingReview(): UnderstandingReviewResult;
|
|
11
|
+
export declare function executeUnderstandingInterpretation(params: {
|
|
12
|
+
interpretation: SemanticUnderstandingInterpretation;
|
|
13
|
+
evidence: UnderstandingEvidenceMessage[];
|
|
14
|
+
extractionRunId: string;
|
|
15
|
+
extractorId: ExtractorId;
|
|
16
|
+
sessionKey: string;
|
|
17
|
+
turnId?: string;
|
|
18
|
+
memoryManager: MemoryManager;
|
|
19
|
+
getConfig: () => Config | undefined;
|
|
20
|
+
reviewSource: 'turn' | 'background';
|
|
21
|
+
processingPolicy: 'local_only' | 'remote_allowed';
|
|
22
|
+
}): Promise<UnderstandingReviewResult>;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { createContextEvidence, getTurnPersonalization, getUnderstanding, recordContextFeedback, rejectUnderstanding, setUnderstandingStatus } from "../../storage/sqlite/user-context-repository.js";
|
|
2
|
+
import { getSessionMetadata } from "../../storage/sqlite/session-repository.js";
|
|
3
|
+
import "../../storage/sqlite/index.js";
|
|
4
|
+
import { extractionInputHash } from "./registry.js";
|
|
5
|
+
//#region src/user-context/extraction/executor.ts
|
|
6
|
+
function emptyUnderstandingReview() {
|
|
7
|
+
return {
|
|
8
|
+
proposed: 0,
|
|
9
|
+
created: 0,
|
|
10
|
+
deduplicated: 0,
|
|
11
|
+
rejected: 0,
|
|
12
|
+
createdRecords: [],
|
|
13
|
+
writeOutputs: []
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function resolveWritePolicy(config) {
|
|
17
|
+
const memory = config?.userContext.memory;
|
|
18
|
+
if (!memory || memory.mode === "off" || memory.mode === "readOnly") return "deny";
|
|
19
|
+
return memory.writePolicy?.understanding ?? (memory.mode === "auto" ? "allow" : "confirm");
|
|
20
|
+
}
|
|
21
|
+
function recordTargetFeedback(turnId, targetIds, rating, reason) {
|
|
22
|
+
if (!turnId || targetIds.length === 0) return;
|
|
23
|
+
const personalization = getTurnPersonalization(turnId);
|
|
24
|
+
if (!personalization) return;
|
|
25
|
+
for (const objectId of targetIds) recordContextFeedback({
|
|
26
|
+
turnId,
|
|
27
|
+
runId: personalization.runId,
|
|
28
|
+
objectType: "understanding",
|
|
29
|
+
objectId,
|
|
30
|
+
rating,
|
|
31
|
+
reason
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
async function executeUnderstandingInterpretation(params) {
|
|
35
|
+
const { interpretation } = params;
|
|
36
|
+
const result = emptyUnderstandingReview();
|
|
37
|
+
const targets = interpretation.targetUnderstandingIds.flatMap((id) => {
|
|
38
|
+
const item = getUnderstanding(id);
|
|
39
|
+
return item ? [item] : [];
|
|
40
|
+
});
|
|
41
|
+
const targetIds = targets.map((item) => item.id);
|
|
42
|
+
const policy = resolveWritePolicy(params.getConfig());
|
|
43
|
+
if (interpretation.intent === "memory_forget") {
|
|
44
|
+
for (const target of targets) {
|
|
45
|
+
const rejected = rejectUnderstanding(target.id, "explicit user forget request", "user");
|
|
46
|
+
result.writeOutputs.push({
|
|
47
|
+
candidateKey: rejected.canonicalKey,
|
|
48
|
+
objectId: rejected.id,
|
|
49
|
+
versionId: rejected.versionId,
|
|
50
|
+
outcome: "rejected"
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
result.rejected += targets.length;
|
|
54
|
+
recordTargetFeedback(params.turnId, targetIds, "irrelevant", "explicit_user_forget_request");
|
|
55
|
+
return result;
|
|
56
|
+
}
|
|
57
|
+
if (interpretation.intent === "memory_confirm" && policy !== "deny") {
|
|
58
|
+
for (const target of targets) {
|
|
59
|
+
const confirmed = setUnderstandingStatus(target.id, "active", {
|
|
60
|
+
explicitness: "explicit",
|
|
61
|
+
confidence: 1,
|
|
62
|
+
actorType: "user",
|
|
63
|
+
source: "semantic-memory-confirmation"
|
|
64
|
+
});
|
|
65
|
+
result.createdRecords.push({
|
|
66
|
+
id: confirmed.id,
|
|
67
|
+
content: confirmed.statement,
|
|
68
|
+
kind: confirmed.kind,
|
|
69
|
+
status: confirmed.status
|
|
70
|
+
});
|
|
71
|
+
result.writeOutputs.push({
|
|
72
|
+
candidateKey: confirmed.canonicalKey,
|
|
73
|
+
objectId: confirmed.id,
|
|
74
|
+
versionId: confirmed.versionId,
|
|
75
|
+
outcome: "deduplicated"
|
|
76
|
+
});
|
|
77
|
+
result.deduplicated += 1;
|
|
78
|
+
}
|
|
79
|
+
recordTargetFeedback(params.turnId, targetIds, "helpful", "explicit_user_confirmation");
|
|
80
|
+
}
|
|
81
|
+
if (interpretation.intent === "memory_correct" && targets.length && interpretation.candidates.length === 0) {
|
|
82
|
+
for (const target of targets) setUnderstandingStatus(target.id, "needs_review", {
|
|
83
|
+
actorType: "user",
|
|
84
|
+
source: "semantic-memory-correction"
|
|
85
|
+
});
|
|
86
|
+
recordTargetFeedback(params.turnId, targetIds, "wrong", "explicit_user_correction_without_replacement");
|
|
87
|
+
return result;
|
|
88
|
+
}
|
|
89
|
+
if (interpretation.candidates.length === 0) return result;
|
|
90
|
+
if (policy === "deny") {
|
|
91
|
+
result.proposed = interpretation.candidates.length;
|
|
92
|
+
result.rejected = interpretation.candidates.length;
|
|
93
|
+
return result;
|
|
94
|
+
}
|
|
95
|
+
const evidenceByRef = new Map(params.evidence.map((entry) => [entry.ref, entry]));
|
|
96
|
+
const candidates = interpretation.candidates.map((candidate) => ({
|
|
97
|
+
...candidate,
|
|
98
|
+
explicitness: policy === "confirm" && candidate.explicitness === "explicit" ? "observed" : candidate.explicitness
|
|
99
|
+
}));
|
|
100
|
+
const evidenceIdsByRef = /* @__PURE__ */ new Map();
|
|
101
|
+
for (const ref of new Set(candidates.flatMap((candidate) => candidate.evidenceRefs))) {
|
|
102
|
+
const entry = evidenceByRef.get(ref);
|
|
103
|
+
if (!entry || entry.role !== "user") continue;
|
|
104
|
+
const evidence = createContextEvidence({
|
|
105
|
+
sourceType: "conversation",
|
|
106
|
+
sourceRef: `session:${params.sessionKey}:entry:${entry.ref}`,
|
|
107
|
+
sourceRunId: params.extractionRunId,
|
|
108
|
+
sessionId: params.sessionKey,
|
|
109
|
+
...params.turnId ? { turnId: params.turnId } : {},
|
|
110
|
+
messageId: entry.ref,
|
|
111
|
+
contentHash: extractionInputHash(JSON.stringify(entry.message)),
|
|
112
|
+
retentionPolicy: "derived_only",
|
|
113
|
+
processingPolicy: params.processingPolicy,
|
|
114
|
+
extractorId: params.extractorId,
|
|
115
|
+
extractorVersion: "1",
|
|
116
|
+
trustLevel: "owner",
|
|
117
|
+
observedAt: entry.createdAt
|
|
118
|
+
});
|
|
119
|
+
evidenceIdsByRef.set(ref, evidence.id);
|
|
120
|
+
}
|
|
121
|
+
const projectId = getSessionMetadata(params.sessionKey)?.projectId;
|
|
122
|
+
for (const candidate of candidates) {
|
|
123
|
+
const applied = await params.memoryManager.applyUnderstandingCandidates([candidate], {
|
|
124
|
+
sessionKey: params.sessionKey,
|
|
125
|
+
...projectId ? { projectId } : {},
|
|
126
|
+
evidenceIds: candidate.evidenceRefs.flatMap((ref) => evidenceIdsByRef.get(ref) ?? []),
|
|
127
|
+
reviewSource: params.reviewSource,
|
|
128
|
+
extractionRunId: params.extractionRunId,
|
|
129
|
+
...interpretation.intent === "memory_correct" ? { supersedesRecordIds: targetIds } : {}
|
|
130
|
+
});
|
|
131
|
+
result.proposed += applied.proposed;
|
|
132
|
+
result.created += applied.created;
|
|
133
|
+
result.deduplicated += applied.deduplicated;
|
|
134
|
+
result.rejected += applied.rejected;
|
|
135
|
+
result.createdRecords.push(...applied.createdRecords);
|
|
136
|
+
result.writeOutputs.push(...applied.writeOutputs ?? []);
|
|
137
|
+
}
|
|
138
|
+
if (interpretation.intent === "memory_correct" && result.created > 0) recordTargetFeedback(params.turnId, targetIds, "wrong", "explicit_user_correction_with_replacement");
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
//#endregion
|
|
142
|
+
export { emptyUnderstandingReview, executeUnderstandingInterpretation };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type ContextExtractionRun } from '../../storage/sqlite/index.js';
|
|
2
2
|
import type { UnderstandingKind } from '../domain.js';
|
|
3
|
-
export type ExtractorId = '
|
|
3
|
+
export type ExtractorId = 'turn-semantics' | 'transcript-synthesis' | 'connector-semantic';
|
|
4
4
|
export type ExtractorDefinition = {
|
|
5
5
|
id: ExtractorId;
|
|
6
6
|
version: string;
|
|
@@ -14,62 +14,33 @@ const UNDERSTANDING_KINDS = [
|
|
|
14
14
|
"derived_insight"
|
|
15
15
|
];
|
|
16
16
|
const DEFINITIONS = {
|
|
17
|
-
"
|
|
18
|
-
id: "
|
|
17
|
+
"turn-semantics": {
|
|
18
|
+
id: "turn-semantics",
|
|
19
19
|
version: "1",
|
|
20
20
|
inputKinds: ["conversation"],
|
|
21
21
|
requiredProcessingPolicy: "local_only",
|
|
22
22
|
authorityCeiling: "user_explicit",
|
|
23
23
|
candidateKinds: UNDERSTANDING_KINDS,
|
|
24
24
|
maxAutomaticStatus: "active",
|
|
25
|
-
timeoutMs:
|
|
26
|
-
},
|
|
27
|
-
"deterministic-signal": {
|
|
28
|
-
id: "deterministic-signal",
|
|
29
|
-
version: "1",
|
|
30
|
-
inputKinds: ["conversation", "task"],
|
|
31
|
-
requiredProcessingPolicy: "local_only",
|
|
32
|
-
authorityCeiling: "user_observed",
|
|
33
|
-
candidateKinds: UNDERSTANDING_KINDS,
|
|
34
|
-
maxAutomaticStatus: "candidate",
|
|
35
|
-
timeoutMs: 500
|
|
25
|
+
timeoutMs: 3e4
|
|
36
26
|
},
|
|
37
27
|
"transcript-synthesis": {
|
|
38
28
|
id: "transcript-synthesis",
|
|
39
29
|
version: "1",
|
|
40
30
|
inputKinds: ["conversation"],
|
|
41
|
-
requiredProcessingPolicy: "
|
|
31
|
+
requiredProcessingPolicy: "local_only",
|
|
42
32
|
authorityCeiling: "system_inferred",
|
|
43
33
|
candidateKinds: UNDERSTANDING_KINDS,
|
|
44
34
|
maxAutomaticStatus: "candidate",
|
|
45
35
|
timeoutMs: 3e4
|
|
46
36
|
},
|
|
47
|
-
"connector-structural": {
|
|
48
|
-
id: "connector-structural",
|
|
49
|
-
version: "1",
|
|
50
|
-
inputKinds: ["connector"],
|
|
51
|
-
requiredProcessingPolicy: "local_only",
|
|
52
|
-
authorityCeiling: "external_untrusted",
|
|
53
|
-
candidateKinds: [
|
|
54
|
-
"project_context",
|
|
55
|
-
"current_state",
|
|
56
|
-
"routine"
|
|
57
|
-
],
|
|
58
|
-
maxAutomaticStatus: "candidate",
|
|
59
|
-
timeoutMs: 1e4
|
|
60
|
-
},
|
|
61
37
|
"connector-semantic": {
|
|
62
38
|
id: "connector-semantic",
|
|
63
39
|
version: "1",
|
|
64
40
|
inputKinds: ["connector", "file"],
|
|
65
41
|
requiredProcessingPolicy: "remote_allowed",
|
|
66
42
|
authorityCeiling: "external_untrusted",
|
|
67
|
-
candidateKinds: [
|
|
68
|
-
"preference",
|
|
69
|
-
"routine",
|
|
70
|
-
"current_state",
|
|
71
|
-
"project_context"
|
|
72
|
-
],
|
|
43
|
+
candidateKinds: ["preference", "routine"],
|
|
73
44
|
maxAutomaticStatus: "candidate",
|
|
74
45
|
timeoutMs: 3e4
|
|
75
46
|
}
|
|
@@ -39,7 +39,10 @@ function repairExtractedContext(filter) {
|
|
|
39
39
|
});
|
|
40
40
|
continue;
|
|
41
41
|
}
|
|
42
|
-
setUnderstandingStatus(output.objectId, "archived"
|
|
42
|
+
setUnderstandingStatus(output.objectId, "archived", {
|
|
43
|
+
actorType: "runtime",
|
|
44
|
+
source: "context-extraction-repair"
|
|
45
|
+
});
|
|
43
46
|
} else {
|
|
44
47
|
const focus = listUserFocuses().find((item) => item.id === output.objectId);
|
|
45
48
|
if (!focus) continue;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { UnderstandingCandidate } from '../../agent/memory/understanding/types.js';
|
|
2
|
+
export declare const UNDERSTANDING_INTENTS: readonly ["memory_create", "memory_query", "memory_confirm", "memory_correct", "memory_forget", "user_assertion", "task_request", "none"];
|
|
3
|
+
export type UnderstandingIntent = typeof UNDERSTANDING_INTENTS[number];
|
|
4
|
+
export type SemanticEvidence = {
|
|
5
|
+
ref: string;
|
|
6
|
+
role: 'user' | 'assistant';
|
|
7
|
+
text: string;
|
|
8
|
+
};
|
|
9
|
+
export type SemanticUnderstandingCandidate = UnderstandingCandidate & {
|
|
10
|
+
evidenceRefs: string[];
|
|
11
|
+
};
|
|
12
|
+
export type SemanticUnderstandingInterpretation = {
|
|
13
|
+
intent: UnderstandingIntent;
|
|
14
|
+
candidates: SemanticUnderstandingCandidate[];
|
|
15
|
+
targetUnderstandingIds: string[];
|
|
16
|
+
abstentionReason?: string;
|
|
17
|
+
};
|
|
18
|
+
export declare function parseSemanticUnderstanding(raw: string, evidence: SemanticEvidence[], allowedTargetIds?: string[]): SemanticUnderstandingInterpretation | null;
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { UNDERSTANDING_KINDS } from "../domain.js";
|
|
2
|
+
import { isDurableUnderstandingCandidate } from "../understandingQuality.js";
|
|
3
|
+
import { inferMemorySensitivity } from "../../agent/memory/sensitivity.js";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
//#region src/user-context/extraction/semantic.ts
|
|
6
|
+
const UNDERSTANDING_INTENTS = [
|
|
7
|
+
"memory_create",
|
|
8
|
+
"memory_query",
|
|
9
|
+
"memory_confirm",
|
|
10
|
+
"memory_correct",
|
|
11
|
+
"memory_forget",
|
|
12
|
+
"user_assertion",
|
|
13
|
+
"task_request",
|
|
14
|
+
"none"
|
|
15
|
+
];
|
|
16
|
+
const EvidenceSchema = z.object({
|
|
17
|
+
ref: z.string().min(1),
|
|
18
|
+
quote: z.string().min(1)
|
|
19
|
+
}).strict();
|
|
20
|
+
const CandidateSchema = z.object({
|
|
21
|
+
factKey: z.string().regex(/^[a-z0-9][a-z0-9:-]{2,119}$/),
|
|
22
|
+
statement: z.string().min(4).max(600),
|
|
23
|
+
kind: z.enum(UNDERSTANDING_KINDS),
|
|
24
|
+
explicitness: z.enum([
|
|
25
|
+
"explicit",
|
|
26
|
+
"observed",
|
|
27
|
+
"inferred"
|
|
28
|
+
]),
|
|
29
|
+
durability: z.enum([
|
|
30
|
+
"ephemeral",
|
|
31
|
+
"durable",
|
|
32
|
+
"recurring"
|
|
33
|
+
]),
|
|
34
|
+
scopeHint: z.enum([
|
|
35
|
+
"global",
|
|
36
|
+
"workspace",
|
|
37
|
+
"project",
|
|
38
|
+
"session"
|
|
39
|
+
]),
|
|
40
|
+
confidence: z.number().min(0).max(1),
|
|
41
|
+
importance: z.number().min(0).max(1),
|
|
42
|
+
sensitivity: z.enum([
|
|
43
|
+
"normal",
|
|
44
|
+
"personal",
|
|
45
|
+
"secret",
|
|
46
|
+
"regulated"
|
|
47
|
+
]).optional(),
|
|
48
|
+
disclosurePolicy: z.enum([
|
|
49
|
+
"silent",
|
|
50
|
+
"referenceable",
|
|
51
|
+
"ask_before_reference"
|
|
52
|
+
]).optional(),
|
|
53
|
+
evidence: z.array(EvidenceSchema).min(1).max(8),
|
|
54
|
+
selfContained: z.boolean(),
|
|
55
|
+
unresolvedReferences: z.array(z.string()).max(8)
|
|
56
|
+
}).strict();
|
|
57
|
+
const InterpretationSchema = z.object({
|
|
58
|
+
intent: z.enum(UNDERSTANDING_INTENTS),
|
|
59
|
+
candidates: z.array(CandidateSchema).max(8),
|
|
60
|
+
targetUnderstandingIds: z.array(z.string().min(1)).max(8),
|
|
61
|
+
abstentionReason: z.string().max(500).optional()
|
|
62
|
+
}).strict();
|
|
63
|
+
const CANDIDATE_INTENTS = new Set([
|
|
64
|
+
"memory_create",
|
|
65
|
+
"memory_confirm",
|
|
66
|
+
"memory_correct",
|
|
67
|
+
"user_assertion"
|
|
68
|
+
]);
|
|
69
|
+
const QUESTION_END = /[??]\s*$/u;
|
|
70
|
+
function extractJson(raw) {
|
|
71
|
+
const fenced = /```(?:json)?\s*([\s\S]*?)```/i.exec(raw)?.[1];
|
|
72
|
+
const start = raw.indexOf("{");
|
|
73
|
+
const end = raw.lastIndexOf("}");
|
|
74
|
+
const candidate = fenced ?? (start >= 0 && end > start ? raw.slice(start, end + 1) : raw);
|
|
75
|
+
return JSON.parse(candidate);
|
|
76
|
+
}
|
|
77
|
+
function comparableText(value) {
|
|
78
|
+
return value.normalize("NFKC").toLocaleLowerCase().replace(/\s+/g, " ").trim();
|
|
79
|
+
}
|
|
80
|
+
function quoteIsGrounded(quote, source) {
|
|
81
|
+
return comparableText(source).includes(comparableText(quote));
|
|
82
|
+
}
|
|
83
|
+
function bigramSimilarity(left, right) {
|
|
84
|
+
const pairs = (value) => {
|
|
85
|
+
const normalized = comparableText(value).replace(/[^\p{L}\p{N}]/gu, "");
|
|
86
|
+
const output = /* @__PURE__ */ new Set();
|
|
87
|
+
for (let index = 0; index < normalized.length - 1; index += 1) output.add(normalized.slice(index, index + 2));
|
|
88
|
+
return output;
|
|
89
|
+
};
|
|
90
|
+
const a = pairs(left);
|
|
91
|
+
const b = pairs(right);
|
|
92
|
+
if (!a.size || !b.size) return 0;
|
|
93
|
+
let overlap = 0;
|
|
94
|
+
for (const pair of a) if (b.has(pair)) overlap += 1;
|
|
95
|
+
return 2 * overlap / (a.size + b.size);
|
|
96
|
+
}
|
|
97
|
+
function effectiveExplicitness(intent, declared) {
|
|
98
|
+
if (intent === "memory_create" || intent === "memory_correct" || intent === "memory_confirm") return declared;
|
|
99
|
+
return declared === "explicit" ? "observed" : declared;
|
|
100
|
+
}
|
|
101
|
+
function parseSemanticUnderstanding(raw, evidence, allowedTargetIds = []) {
|
|
102
|
+
let parsed;
|
|
103
|
+
try {
|
|
104
|
+
const result = InterpretationSchema.safeParse(extractJson(raw));
|
|
105
|
+
if (!result.success) return null;
|
|
106
|
+
parsed = result.data;
|
|
107
|
+
} catch {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
const evidenceByRef = new Map(evidence.map((item) => [item.ref, item]));
|
|
111
|
+
const allowedTargets = new Set(allowedTargetIds);
|
|
112
|
+
const candidates = [];
|
|
113
|
+
if (CANDIDATE_INTENTS.has(parsed.intent)) for (const item of parsed.candidates) {
|
|
114
|
+
if (!item.selfContained || item.unresolvedReferences.length > 0) continue;
|
|
115
|
+
if (QUESTION_END.test(item.statement)) continue;
|
|
116
|
+
if (!isDurableUnderstandingCandidate(item.kind, item.statement)) continue;
|
|
117
|
+
if (!item.evidence.every((claim) => {
|
|
118
|
+
const source = evidenceByRef.get(claim.ref);
|
|
119
|
+
return source?.role === "user" && quoteIsGrounded(claim.quote, source.text);
|
|
120
|
+
})) continue;
|
|
121
|
+
if (item.explicitness === "explicit") {
|
|
122
|
+
const quotedText = item.evidence.map((claim) => claim.quote).join(" ");
|
|
123
|
+
if (bigramSimilarity(item.statement, quotedText) < .45) continue;
|
|
124
|
+
}
|
|
125
|
+
const evidenceRefs = [...new Set(item.evidence.map((claim) => claim.ref))];
|
|
126
|
+
candidates.push({
|
|
127
|
+
kind: item.kind,
|
|
128
|
+
content: item.statement.trim(),
|
|
129
|
+
canonicalKey: `understanding:${item.kind}:${item.factKey}`,
|
|
130
|
+
confidence: item.confidence,
|
|
131
|
+
importance: item.importance,
|
|
132
|
+
explicitness: effectiveExplicitness(parsed.intent, item.explicitness),
|
|
133
|
+
durability: item.durability,
|
|
134
|
+
sensitivity: item.sensitivity ?? inferMemorySensitivity(item.statement),
|
|
135
|
+
disclosurePolicy: item.disclosurePolicy ?? "referenceable",
|
|
136
|
+
payload: { scopeHint: item.scopeHint },
|
|
137
|
+
evidenceRefs
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
intent: parsed.intent,
|
|
142
|
+
candidates,
|
|
143
|
+
targetUnderstandingIds: [...new Set(parsed.targetUnderstandingIds.filter((id) => allowedTargets.has(id)))],
|
|
144
|
+
...parsed.abstentionReason ? { abstentionReason: parsed.abstentionReason } : {}
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
//#endregion
|
|
148
|
+
export { UNDERSTANDING_INTENTS, parseSemanticUnderstanding };
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
const INCOMPLETE_PREFIX = /^(?:and\b|also\b|then\b|plus\b|as\s+well\s+as\b|which\b|that\b|并且|并将|以及|然后|同时|另外|还有|而且|或者|的事项|事项[,,、::]?)/i;
|
|
3
3
|
const DEFERRED_OR_NEGATED_ACTION = /(?:not\s+now|no\s+need\s+to|do\s+not\s+(?:start|proceed)|don't\s+(?:start|proceed)|later\s+maybe|暂时不用|暂时不(?:用|要|开始)?|先不用|无需|不用开始|不要推进|不需要推进)/i;
|
|
4
4
|
const ONE_OFF_ACTION_PREFIX = /^(?:please\s+|update\b|investigate\b|summari[sz]e\b|fix\b|write\b|add\b|record\b|track\b)|^(?:请|帮我|更新|调查|汇总|整理|修复|写入|加入|记录|跟进)/i;
|
|
5
|
+
const DURABLE_MARKER = /(?:从现在起|今后|以后|长期|每次|每回|始终|一直|默认|下次|教训|原则|习惯|from now on|going forward|long[- ]term|every time|always|by default|next time|lesson|principle|habit)/i;
|
|
6
|
+
const TURN_EXECUTION_INSTRUCTION = /(?:不要再问|别再问|直接执行|立即执行|当前任务|这次|本次|现在就|do not ask|don't ask|just do it|execute directly|proceed now|this task|this time)/i;
|
|
5
7
|
function meaningfulLength(content) {
|
|
6
8
|
return content.normalize("NFKC").replace(/[\p{P}\p{S}\s]/gu, "").length;
|
|
7
9
|
}
|
|
@@ -15,6 +17,8 @@ function isActionableUnderstandingContent(content) {
|
|
|
15
17
|
function isDurableUnderstandingCandidate(kind, content) {
|
|
16
18
|
if (!isStandaloneUnderstandingContent(content)) return false;
|
|
17
19
|
if ((kind === "commitment" || kind === "long_term_goal") && ONE_OFF_ACTION_PREFIX.test(content.trim())) return false;
|
|
20
|
+
if (kind === "task_lesson" && !DURABLE_MARKER.test(content)) return false;
|
|
21
|
+
if (kind === "boundary" && TURN_EXECUTION_INSTRUCTION.test(content) && !DURABLE_MARKER.test(content)) return false;
|
|
18
22
|
return true;
|
|
19
23
|
}
|
|
20
24
|
function comparableText(content) {
|