clawvault 3.1.0 → 3.2.0
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/README.md +422 -141
- package/bin/clawvault.js +10 -2
- package/bin/command-registration.test.js +3 -1
- package/bin/command-runtime.js +9 -1
- package/bin/register-core-commands.js +23 -28
- package/bin/register-maintenance-commands.js +39 -3
- package/bin/register-query-commands.js +58 -29
- package/bin/register-tailscale-commands.js +106 -0
- package/bin/register-task-commands.js +18 -1
- package/bin/register-task-commands.test.js +16 -0
- package/bin/register-vault-operations-commands.js +29 -1
- package/bin/register-workgraph-commands.js +1368 -0
- package/dashboard/lib/graph-diff.js +104 -0
- package/dashboard/lib/graph-diff.test.js +75 -0
- package/dashboard/lib/vault-parser.js +556 -0
- package/dashboard/lib/vault-parser.test.js +254 -0
- package/dashboard/public/app.js +796 -0
- package/dashboard/public/index.html +52 -0
- package/dashboard/public/styles.css +221 -0
- package/dashboard/server.js +374 -0
- package/dist/{chunk-F2JEUD4J.js → chunk-23YDQ3QU.js} +6 -8
- package/dist/{chunk-C7OK5WKP.js → chunk-2JQ3O2YL.js} +4 -4
- package/dist/{chunk-VR5NE7PZ.js → chunk-2RAZ4ZFE.js} +1 -1
- package/dist/chunk-2ZDO52B4.js +52 -0
- package/dist/{chunk-ZZA73MFY.js → chunk-33DOSHTA.js} +176 -36
- package/dist/chunk-33VSQP4J.js +37 -0
- package/dist/chunk-4BQTQMJP.js +93 -0
- package/dist/{chunk-GUKMRGM7.js → chunk-4OXMU5S2.js} +1 -1
- package/dist/{chunk-62YTUT6J.js → chunk-4PY655YM.js} +15 -3
- package/dist/chunk-6FH3IULF.js +352 -0
- package/dist/{chunk-3NSBOUT3.js → chunk-77Q5CSPJ.js} +404 -80
- package/dist/{chunk-4VQTUVH7.js → chunk-7YZWHM36.js} +52 -26
- package/dist/chunk-BSJ6RIT7.js +447 -0
- package/dist/chunk-BUEW6IIK.js +364 -0
- package/dist/{chunk-LI4O6NVK.js → chunk-CLJTREDS.js} +74 -14
- package/dist/chunk-EK6S23ZB.js +469 -0
- package/dist/{chunk-LNJA2UGL.js → chunk-ESFLMDRB.js} +9 -86
- package/dist/{chunk-H34S76MB.js → chunk-ESVS6K2B.js} +6 -6
- package/dist/{chunk-WAZ3NLWL.js → chunk-F55HGNU4.js} +0 -47
- package/dist/{chunk-QK3UCXWL.js → chunk-FHFUXL6G.js} +2 -2
- package/dist/{chunk-H62BP7RI.js → chunk-GAOWA7GR.js} +212 -46
- package/dist/chunk-GGA32J2R.js +784 -0
- package/dist/chunk-GNJL4YGR.js +79 -0
- package/dist/chunk-IVRIKYFE.js +520 -0
- package/dist/chunk-MDIH26GC.js +183 -0
- package/dist/{chunk-LYHGEHXG.js → chunk-MFAWT5O5.js} +0 -1
- package/dist/chunk-MM6QGW3P.js +207 -0
- package/dist/{chunk-P5EPF6MB.js → chunk-MW5C6ZQA.js} +110 -13
- package/dist/chunk-NCKFNBHJ.js +257 -0
- package/dist/{chunk-QBLMXKF2.js → chunk-OIWVQYQF.js} +1 -1
- package/dist/{chunk-42MXU7A6.js → chunk-P62WHA27.js} +58 -47
- package/dist/chunk-PBACDKKP.js +66 -0
- package/dist/{chunk-VGLOTGAS.js → chunk-QSHD36LH.js} +2 -2
- package/dist/{chunk-OZ7RIXTO.js → chunk-QSRRMEYM.js} +2 -2
- package/dist/chunk-QVEERJSP.js +152 -0
- package/dist/{chunk-N2AXRYLC.js → chunk-QWQ3TIKS.js} +1 -1
- package/dist/{chunk-3DHXQHYG.js → chunk-R2MIW5G7.js} +1 -1
- package/dist/{chunk-SJSFRIYS.js → chunk-SLXOR3CC.js} +2 -2
- package/dist/chunk-SS4B7P7V.js +99 -0
- package/dist/{chunk-JY6FYXIT.js → chunk-STCQGCEQ.js} +6 -11
- package/dist/chunk-TIGW564L.js +628 -0
- package/dist/chunk-U4O6C46S.js +154 -0
- package/dist/{chunk-ITPEXLHA.js → chunk-URXDAUVH.js} +24 -5
- package/dist/chunk-VSL7KY3M.js +189 -0
- package/dist/{chunk-U55BGUAU.js → chunk-W4SPAEE7.js} +6 -6
- package/dist/chunk-WMGIIABP.js +15 -0
- package/dist/{chunk-33UGEQRT.js → chunk-X3SPPUFG.js} +151 -64
- package/dist/chunk-Y6VJKXGL.js +373 -0
- package/dist/{chunk-3WRJEKN4.js → chunk-ZN54U2OZ.js} +123 -10
- package/dist/cli/index.js +34 -24
- package/dist/commands/archive.js +3 -3
- package/dist/commands/backlog.js +3 -3
- package/dist/commands/blocked.js +3 -3
- package/dist/commands/canvas.d.ts +15 -0
- package/dist/commands/canvas.js +200 -0
- package/dist/commands/checkpoint.js +2 -2
- package/dist/commands/compat.js +2 -2
- package/dist/commands/context.js +8 -6
- package/dist/commands/doctor.d.ts +11 -7
- package/dist/commands/doctor.js +18 -16
- package/dist/commands/embed.js +5 -6
- package/dist/commands/entities.js +2 -2
- package/dist/commands/graph.js +4 -4
- package/dist/commands/inject.d.ts +1 -1
- package/dist/commands/inject.js +5 -6
- package/dist/commands/kanban.js +4 -4
- package/dist/commands/link.js +5 -5
- package/dist/commands/migrate-observations.js +4 -4
- package/dist/commands/observe.d.ts +0 -1
- package/dist/commands/observe.js +14 -13
- package/dist/commands/project.js +5 -5
- package/dist/commands/rebuild-embeddings.d.ts +21 -0
- package/dist/commands/rebuild-embeddings.js +91 -0
- package/dist/commands/rebuild.js +12 -11
- package/dist/commands/recover.js +3 -3
- package/dist/commands/reflect.js +6 -7
- package/dist/commands/repair-session.js +1 -1
- package/dist/commands/replay.js +14 -14
- package/dist/commands/session-recap.js +1 -1
- package/dist/commands/setup.d.ts +2 -89
- package/dist/commands/setup.js +3 -21
- package/dist/commands/shell-init.js +1 -1
- package/dist/commands/sleep.d.ts +1 -1
- package/dist/commands/sleep.js +20 -19
- package/dist/commands/status.d.ts +2 -0
- package/dist/commands/status.js +57 -35
- package/dist/commands/sync-bd.d.ts +10 -0
- package/dist/commands/sync-bd.js +10 -0
- package/dist/commands/tailscale.d.ts +52 -0
- package/dist/commands/tailscale.js +26 -0
- package/dist/commands/task.js +4 -4
- package/dist/commands/template.js +2 -2
- package/dist/commands/wake.d.ts +1 -1
- package/dist/commands/wake.js +11 -10
- package/dist/commands/workgraph.d.ts +124 -0
- package/dist/commands/workgraph.js +38 -0
- package/dist/index.d.ts +341 -191
- package/dist/index.js +446 -116
- package/dist/{inject-Bzi5E-By.d.ts → inject-DYUrDqQO.d.ts} +3 -3
- package/dist/ledger-B7g7jhqG.d.ts +44 -0
- package/dist/lib/auto-linker.js +2 -2
- package/dist/lib/canvas-layout.d.ts +115 -0
- package/dist/lib/canvas-layout.js +35 -0
- package/dist/lib/config.d.ts +27 -3
- package/dist/lib/config.js +4 -2
- package/dist/lib/entity-index.js +1 -1
- package/dist/lib/project-utils.js +4 -4
- package/dist/lib/session-repair.js +1 -1
- package/dist/lib/session-utils.js +1 -1
- package/dist/lib/tailscale.d.ts +225 -0
- package/dist/lib/tailscale.js +50 -0
- package/dist/lib/task-utils.js +3 -3
- package/dist/lib/template-engine.js +1 -1
- package/dist/lib/webdav.d.ts +109 -0
- package/dist/lib/webdav.js +35 -0
- package/dist/onnxruntime_binding-5QEF3SUC.node +0 -0
- package/dist/onnxruntime_binding-BKPKNEGC.node +0 -0
- package/dist/onnxruntime_binding-FMOXGIUT.node +0 -0
- package/dist/onnxruntime_binding-OI2KMXC5.node +0 -0
- package/dist/onnxruntime_binding-UX44MLAZ.node +0 -0
- package/dist/onnxruntime_binding-Y2W7N7WY.node +0 -0
- package/dist/openclaw-plugin.d.ts +8 -0
- package/dist/openclaw-plugin.js +14 -0
- package/dist/registry-BR4326o0.d.ts +30 -0
- package/dist/store-CA-6sKCJ.d.ts +34 -0
- package/dist/thread-B9LhXNU0.d.ts +41 -0
- package/dist/transformers.node-A2ZRORSQ.js +46775 -0
- package/dist/{types-Y2_Um2Ls.d.ts → types-BbWJoC1c.d.ts} +1 -44
- package/dist/workgraph/index.d.ts +5 -0
- package/dist/workgraph/index.js +23 -0
- package/dist/workgraph/ledger.d.ts +2 -0
- package/dist/workgraph/ledger.js +25 -0
- package/dist/workgraph/registry.d.ts +2 -0
- package/dist/workgraph/registry.js +19 -0
- package/dist/workgraph/store.d.ts +2 -0
- package/dist/workgraph/store.js +25 -0
- package/dist/workgraph/thread.d.ts +2 -0
- package/dist/workgraph/thread.js +25 -0
- package/dist/workgraph/types.d.ts +54 -0
- package/dist/workgraph/types.js +7 -0
- package/hooks/clawvault/HOOK.md +113 -0
- package/hooks/clawvault/handler.js +1561 -0
- package/hooks/clawvault/handler.test.js +510 -0
- package/hooks/clawvault/openclaw.plugin.json +72 -0
- package/openclaw.plugin.json +65 -38
- package/package.json +25 -22
- package/dist/chunk-3RG5ZIWI.js +0 -10
- package/dist/chunk-3ZIH425O.js +0 -871
- package/dist/chunk-6U6MK36V.js +0 -205
- package/dist/chunk-CMB7UL7C.js +0 -327
- package/dist/chunk-D2H45LON.js +0 -1074
- package/dist/chunk-E7MFQB6D.js +0 -163
- package/dist/chunk-GQSLDZTS.js +0 -560
- package/dist/chunk-MFM6K7PU.js +0 -374
- package/dist/chunk-MXSSG3QU.js +0 -42
- package/dist/chunk-OCGVIN3L.js +0 -88
- package/dist/chunk-PAH27GSN.js +0 -108
- package/dist/chunk-YCUNCH2I.js +0 -78
- package/dist/cli/index.cjs +0 -8584
- package/dist/cli/index.d.cts +0 -5
- package/dist/commands/archive.cjs +0 -287
- package/dist/commands/archive.d.cts +0 -11
- package/dist/commands/backlog.cjs +0 -721
- package/dist/commands/backlog.d.cts +0 -53
- package/dist/commands/blocked.cjs +0 -204
- package/dist/commands/blocked.d.cts +0 -26
- package/dist/commands/checkpoint.cjs +0 -244
- package/dist/commands/checkpoint.d.cts +0 -41
- package/dist/commands/compat.cjs +0 -294
- package/dist/commands/compat.d.cts +0 -28
- package/dist/commands/context.cjs +0 -2990
- package/dist/commands/context.d.cts +0 -2
- package/dist/commands/doctor.cjs +0 -2986
- package/dist/commands/doctor.d.cts +0 -21
- package/dist/commands/embed.cjs +0 -232
- package/dist/commands/embed.d.cts +0 -17
- package/dist/commands/entities.cjs +0 -141
- package/dist/commands/entities.d.cts +0 -7
- package/dist/commands/graph.cjs +0 -501
- package/dist/commands/graph.d.cts +0 -21
- package/dist/commands/inject.cjs +0 -1636
- package/dist/commands/inject.d.cts +0 -2
- package/dist/commands/kanban.cjs +0 -884
- package/dist/commands/kanban.d.cts +0 -63
- package/dist/commands/link.cjs +0 -965
- package/dist/commands/link.d.cts +0 -11
- package/dist/commands/migrate-observations.cjs +0 -362
- package/dist/commands/migrate-observations.d.cts +0 -19
- package/dist/commands/observe.cjs +0 -4099
- package/dist/commands/observe.d.cts +0 -23
- package/dist/commands/project.cjs +0 -1341
- package/dist/commands/project.d.cts +0 -85
- package/dist/commands/rebuild.cjs +0 -3136
- package/dist/commands/rebuild.d.cts +0 -11
- package/dist/commands/recover.cjs +0 -361
- package/dist/commands/recover.d.cts +0 -38
- package/dist/commands/reflect.cjs +0 -1008
- package/dist/commands/reflect.d.cts +0 -11
- package/dist/commands/repair-session.cjs +0 -457
- package/dist/commands/repair-session.d.cts +0 -38
- package/dist/commands/replay.cjs +0 -4103
- package/dist/commands/replay.d.cts +0 -16
- package/dist/commands/session-recap.cjs +0 -353
- package/dist/commands/session-recap.d.cts +0 -27
- package/dist/commands/setup.cjs +0 -1278
- package/dist/commands/setup.d.cts +0 -99
- package/dist/commands/shell-init.cjs +0 -75
- package/dist/commands/shell-init.d.cts +0 -7
- package/dist/commands/sleep.cjs +0 -6029
- package/dist/commands/sleep.d.cts +0 -36
- package/dist/commands/status.cjs +0 -2737
- package/dist/commands/status.d.cts +0 -52
- package/dist/commands/task.cjs +0 -1236
- package/dist/commands/task.d.cts +0 -97
- package/dist/commands/template.cjs +0 -457
- package/dist/commands/template.d.cts +0 -36
- package/dist/commands/wake.cjs +0 -2627
- package/dist/commands/wake.d.cts +0 -22
- package/dist/context-BUGaWpyL.d.cts +0 -46
- package/dist/index.cjs +0 -12373
- package/dist/index.d.cts +0 -854
- package/dist/inject-Bzi5E-By.d.cts +0 -137
- package/dist/lib/auto-linker.cjs +0 -176
- package/dist/lib/auto-linker.d.cts +0 -26
- package/dist/lib/config.cjs +0 -78
- package/dist/lib/config.d.cts +0 -11
- package/dist/lib/entity-index.cjs +0 -84
- package/dist/lib/entity-index.d.cts +0 -26
- package/dist/lib/project-utils.cjs +0 -864
- package/dist/lib/project-utils.d.cts +0 -97
- package/dist/lib/session-repair.cjs +0 -239
- package/dist/lib/session-repair.d.cts +0 -110
- package/dist/lib/session-utils.cjs +0 -209
- package/dist/lib/session-utils.d.cts +0 -63
- package/dist/lib/task-utils.cjs +0 -1137
- package/dist/lib/task-utils.d.cts +0 -208
- package/dist/lib/template-engine.cjs +0 -47
- package/dist/lib/template-engine.d.cts +0 -11
- package/dist/plugin/index.cjs +0 -1907
- package/dist/plugin/index.d.cts +0 -36
- package/dist/plugin/index.d.ts +0 -36
- package/dist/plugin/index.js +0 -572
- package/dist/plugin/inject.cjs +0 -356
- package/dist/plugin/inject.d.cts +0 -54
- package/dist/plugin/inject.d.ts +0 -54
- package/dist/plugin/inject.js +0 -17
- package/dist/plugin/observe.cjs +0 -631
- package/dist/plugin/observe.d.cts +0 -39
- package/dist/plugin/observe.d.ts +0 -39
- package/dist/plugin/observe.js +0 -18
- package/dist/plugin/templates.cjs +0 -593
- package/dist/plugin/templates.d.cts +0 -52
- package/dist/plugin/templates.d.ts +0 -52
- package/dist/plugin/templates.js +0 -25
- package/dist/plugin/types.cjs +0 -18
- package/dist/plugin/types.d.cts +0 -209
- package/dist/plugin/types.d.ts +0 -209
- package/dist/plugin/types.js +0 -0
- package/dist/plugin/vault.cjs +0 -927
- package/dist/plugin/vault.d.cts +0 -68
- package/dist/plugin/vault.d.ts +0 -68
- package/dist/plugin/vault.js +0 -22
- package/dist/types-Y2_Um2Ls.d.cts +0 -205
- package/templates/memory-event.md +0 -67
- package/templates/party.md +0 -63
- package/templates/primitive-registry.yaml +0 -551
- package/templates/run.md +0 -68
- package/templates/trigger.md +0 -68
- package/templates/workspace.md +0 -50
|
@@ -1,21 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
listProjects
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-4PY655YM.js";
|
|
4
4
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import {
|
|
10
|
-
resolveClaudeOAuthToken
|
|
11
|
-
} from "./chunk-PAH27GSN.js";
|
|
12
|
-
import {
|
|
13
|
-
createBacklogItem,
|
|
14
|
-
listBacklogItems,
|
|
15
|
-
listTasks,
|
|
16
|
-
updateBacklogItem,
|
|
17
|
-
updateTask
|
|
18
|
-
} from "./chunk-N2AXRYLC.js";
|
|
5
|
+
FactStore,
|
|
6
|
+
extractFactsLlm,
|
|
7
|
+
extractFactsRuleBased
|
|
8
|
+
} from "./chunk-BSJ6RIT7.js";
|
|
19
9
|
import {
|
|
20
10
|
DATE_HEADING_RE,
|
|
21
11
|
inferObservationType,
|
|
@@ -24,7 +14,16 @@ import {
|
|
|
24
14
|
parseObservationMarkdown,
|
|
25
15
|
renderObservationMarkdown,
|
|
26
16
|
renderScoredObservationLine
|
|
27
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-FHFUXL6G.js";
|
|
18
|
+
import {
|
|
19
|
+
listConfig,
|
|
20
|
+
listRouteRules,
|
|
21
|
+
matchRouteRule
|
|
22
|
+
} from "./chunk-URXDAUVH.js";
|
|
23
|
+
import {
|
|
24
|
+
requestLlmCompletion,
|
|
25
|
+
resolveLlmProvider
|
|
26
|
+
} from "./chunk-NCKFNBHJ.js";
|
|
28
27
|
import {
|
|
29
28
|
ensureLedgerStructure,
|
|
30
29
|
ensureParentDir,
|
|
@@ -33,16 +32,27 @@ import {
|
|
|
33
32
|
getRawTranscriptPath,
|
|
34
33
|
toDateKey
|
|
35
34
|
} from "./chunk-Z2XBWN7A.js";
|
|
35
|
+
import {
|
|
36
|
+
createBacklogItem,
|
|
37
|
+
listBacklogItems,
|
|
38
|
+
listTasks,
|
|
39
|
+
updateBacklogItem,
|
|
40
|
+
updateTask
|
|
41
|
+
} from "./chunk-QWQ3TIKS.js";
|
|
36
42
|
|
|
37
43
|
// src/observer/compressor.ts
|
|
38
44
|
var OPENAI_BASE_URL = "https://api.openai.com/v1";
|
|
45
|
+
var XAI_BASE_URL = "https://api.x.ai/v1";
|
|
39
46
|
var OLLAMA_BASE_URL = "http://localhost:11434/v1";
|
|
40
47
|
var DEFAULT_PROVIDER_MODELS = {
|
|
41
|
-
anthropic: "claude-haiku-
|
|
48
|
+
anthropic: "claude-3-5-haiku-latest",
|
|
42
49
|
openai: "gpt-4o-mini",
|
|
43
50
|
gemini: "gemini-2.0-flash",
|
|
51
|
+
xai: "grok-2-latest",
|
|
44
52
|
"openai-compatible": "gpt-4o-mini",
|
|
45
|
-
ollama: "llama3.2"
|
|
53
|
+
ollama: "llama3.2",
|
|
54
|
+
minimax: "MiniMax-M2.1",
|
|
55
|
+
zai: "glm-4.5-air"
|
|
46
56
|
};
|
|
47
57
|
var CRITICAL_RE = /(?:\b(?:decision|decided|chose|chosen|selected|picked|opted|switched to)\s*:?|\bdecid(?:e|ed|ing|ion)\b|\berror\b|\bfail(?:ed|ure|ing)?\b|\bblock(?:ed|er)?\b|\bbreaking(?:\s+change)?s?\b|\bcritical\b|\b\w+\s+chosen\s+(?:for|over|as)\b|\bpublish(?:ed)?\b.*@?\d+\.\d+|\bmerge[d]?\s+(?:PR|pull\s+request)\b|\bshipped\b|\breleased?\b.*v?\d+\.\d+|\bsigned\b.*\b(?:contract|agreement|deal)\b|\bpricing\b.*\$|\bdemo\b.*\b(?:completed?|done|finished)\b|\bmeeting\b.*\b(?:completed?|done|finished)\b|\bstrategy\b.*\b(?:pivot|change|shift)\b)/i;
|
|
48
58
|
var DEADLINE_WITH_DATE_RE = /(?:(?:\bdeadline\b|\bdue(?:\s+date)?\b|\bcutoff\b).*(?:\d{4}-\d{2}-\d{2}|\d{1,2}\/\d{1,2}(?:\/\d{2,4})?|(?:jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)[a-z]*\s+\d{1,2})|(?:\d{4}-\d{2}-\d{2}|\d{1,2}\/\d{1,2}(?:\/\d{2,4})?|(?:jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)[a-z]*\s+\d{1,2}).*(?:\bdeadline\b|\bdue(?:\s+date)?\b|\bcutoff\b))/i;
|
|
@@ -51,6 +61,11 @@ var TODO_SIGNAL_RE = /(?:\btodo:\s*|\bwe need to\b|\bdon't forget(?: to)?\b|\bre
|
|
|
51
61
|
var COMMITMENT_TASK_SIGNAL_RE = /\b(?:i'?ll|i will|let me|(?:i'?m\s+)?going to|plan to|should)\b/i;
|
|
52
62
|
var UNRESOLVED_COMMITMENT_RE = /\b(?:need to figure out|tbd|to be determined)\b/i;
|
|
53
63
|
var DEADLINE_SIGNAL_RE = /\b(?:by\s+(?:monday|tuesday|wednesday|thursday|friday|saturday|sunday|tomorrow)|before\s+the\s+\w+|deadline is)\b/i;
|
|
64
|
+
var ROLE_PREFIX_RE = /^([a-z][a-z0-9_-]{1,31})\s*:\s*(.+)$/i;
|
|
65
|
+
var BASE64_DATA_URI_RE = /\bdata:[^;\s]+;base64,[A-Za-z0-9+/=]{24,}\b/gi;
|
|
66
|
+
var LONG_BASE64_TOKEN_RE = /\b[A-Za-z0-9+/]{80,}={0,2}\b/g;
|
|
67
|
+
var NOISE_PREFIX_RE = /^(?:metadata|system metadata|session metadata|tool[_-]?result|toolresult)\s*:/i;
|
|
68
|
+
var STRUCTURED_NOISE_MARKER_RE = /\b(?:tool[_-]?result|tool[_-]?use|toolcallid|tooluseid|function[_-]?(?:call|result)|stdout|stderr|exitcode|recordedat|trace(?:_|-)?id|parent(?:_|-)?id|session(?:_|-)?id|metadata|base64|mime(?:type)?)\b/i;
|
|
54
69
|
var Compressor = class {
|
|
55
70
|
provider;
|
|
56
71
|
model;
|
|
@@ -67,15 +82,15 @@ var Compressor = class {
|
|
|
67
82
|
this.fetchImpl = options.fetchImpl ?? fetch;
|
|
68
83
|
}
|
|
69
84
|
async compress(messages, existingObservations) {
|
|
70
|
-
const cleanedMessages =
|
|
85
|
+
const cleanedMessages = this.sanitizeIncomingMessages(messages);
|
|
71
86
|
if (cleanedMessages.length === 0) {
|
|
72
87
|
return existingObservations.trim();
|
|
73
88
|
}
|
|
74
89
|
const prompt = this.buildPrompt(cleanedMessages, existingObservations);
|
|
75
|
-
const backend =
|
|
90
|
+
const backend = this.resolveProvider();
|
|
76
91
|
if (backend) {
|
|
77
92
|
try {
|
|
78
|
-
const llmOutput = backend.provider === "anthropic" ? await this.callAnthropic(prompt, backend) : backend.provider === "gemini" ? await this.callGemini(prompt, backend) : backend.provider === "openai" ? await this.callOpenAI(prompt, backend) : await this.callOpenAICompatible(prompt, backend);
|
|
93
|
+
const llmOutput = backend.provider === "anthropic" ? await this.callAnthropic(prompt, backend) : backend.provider === "gemini" ? await this.callGemini(prompt, backend) : backend.provider === "openai" ? await this.callOpenAI(prompt, backend) : backend.provider === "xai" ? await this.callXAI(prompt, backend) : await this.callOpenAICompatible(prompt, backend);
|
|
79
94
|
const normalized = this.normalizeLlmOutput(llmOutput);
|
|
80
95
|
if (normalized) {
|
|
81
96
|
return this.mergeObservations(existingObservations, normalized);
|
|
@@ -86,16 +101,100 @@ var Compressor = class {
|
|
|
86
101
|
const fallback = this.fallbackCompression(cleanedMessages);
|
|
87
102
|
return this.mergeObservations(existingObservations, fallback);
|
|
88
103
|
}
|
|
89
|
-
|
|
104
|
+
sanitizeIncomingMessages(messages) {
|
|
105
|
+
const sanitized = [];
|
|
106
|
+
for (const message of messages) {
|
|
107
|
+
const cleaned = this.sanitizeIncomingMessage(message);
|
|
108
|
+
if (cleaned) {
|
|
109
|
+
sanitized.push(cleaned);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return sanitized;
|
|
113
|
+
}
|
|
114
|
+
sanitizeIncomingMessage(message) {
|
|
115
|
+
const normalized = message.replace(/\s+/g, " ").trim();
|
|
116
|
+
if (!normalized) {
|
|
117
|
+
return "";
|
|
118
|
+
}
|
|
119
|
+
const sourceTagMatch = /^\[[^\]]+\]\s+/.exec(normalized);
|
|
120
|
+
const sourceTag = sourceTagMatch ? sourceTagMatch[0] : "";
|
|
121
|
+
const payload = sourceTag ? normalized.slice(sourceTag.length).trimStart() : normalized;
|
|
122
|
+
const roleMatch = ROLE_PREFIX_RE.exec(payload);
|
|
123
|
+
if (roleMatch && this.isConversationRolePrefix(roleMatch[1])) {
|
|
124
|
+
const role = this.normalizeMessageRole(roleMatch[1]);
|
|
125
|
+
if (this.shouldDropMessageRole(role)) {
|
|
126
|
+
return "";
|
|
127
|
+
}
|
|
128
|
+
const content = this.stripNoisyData(roleMatch[2]);
|
|
129
|
+
if (!content || this.isLikelyStructuredNoise(content)) {
|
|
130
|
+
return "";
|
|
131
|
+
}
|
|
132
|
+
const cleaned2 = `${role}: ${content}`;
|
|
133
|
+
return sourceTag ? `${sourceTag}${cleaned2}` : cleaned2;
|
|
134
|
+
}
|
|
135
|
+
const cleaned = this.stripNoisyData(payload);
|
|
136
|
+
if (!cleaned || this.isLikelyStructuredNoise(cleaned)) {
|
|
137
|
+
return "";
|
|
138
|
+
}
|
|
139
|
+
return sourceTag ? `${sourceTag}${cleaned}` : cleaned;
|
|
140
|
+
}
|
|
141
|
+
normalizeMessageRole(role) {
|
|
142
|
+
return role.trim().toLowerCase();
|
|
143
|
+
}
|
|
144
|
+
isConversationRolePrefix(role) {
|
|
145
|
+
const normalized = role.trim().toLowerCase().replace(/[\s_-]+/g, "");
|
|
146
|
+
if (!normalized) {
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
if (normalized === "user" || normalized === "assistant" || normalized === "system") {
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
if (normalized === "developer" || normalized === "metadata") {
|
|
153
|
+
return true;
|
|
154
|
+
}
|
|
155
|
+
return normalized.startsWith("tool");
|
|
156
|
+
}
|
|
157
|
+
shouldDropMessageRole(role) {
|
|
158
|
+
const normalized = role.replace(/[\s_-]+/g, "");
|
|
159
|
+
if (!normalized) {
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
if (normalized === "system" || normalized === "developer" || normalized === "metadata") {
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
return normalized.startsWith("tool");
|
|
166
|
+
}
|
|
167
|
+
stripNoisyData(value) {
|
|
168
|
+
return value.replace(BASE64_DATA_URI_RE, " ").replace(LONG_BASE64_TOKEN_RE, " ").replace(/\s+/g, " ").trim();
|
|
169
|
+
}
|
|
170
|
+
isLikelyStructuredNoise(value) {
|
|
171
|
+
const trimmed = value.trim();
|
|
172
|
+
if (!trimmed) {
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
175
|
+
if (NOISE_PREFIX_RE.test(trimmed)) {
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
const afterToolResult = trimmed.match(/^tool[_-]?result\s*:\s*(\{.*|\[.*)/i);
|
|
179
|
+
if (afterToolResult && STRUCTURED_NOISE_MARKER_RE.test(trimmed) && trimmed.length >= 40) {
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
182
|
+
const looksStructured = trimmed.startsWith("{") || trimmed.startsWith("[");
|
|
183
|
+
if (looksStructured && STRUCTURED_NOISE_MARKER_RE.test(trimmed) && trimmed.length >= 40) {
|
|
184
|
+
return true;
|
|
185
|
+
}
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
resolveProvider() {
|
|
90
189
|
if (process.env.CLAWVAULT_NO_LLM) return null;
|
|
91
190
|
if (this.provider) {
|
|
92
191
|
const configured = this.resolveConfiguredProvider(this.provider);
|
|
93
192
|
if (configured) {
|
|
94
193
|
return configured;
|
|
95
194
|
}
|
|
96
|
-
return
|
|
195
|
+
return this.resolveProviderFromEnv(false);
|
|
97
196
|
}
|
|
98
|
-
return
|
|
197
|
+
return this.resolveProviderFromEnv(true);
|
|
99
198
|
}
|
|
100
199
|
resolveConfiguredProvider(provider) {
|
|
101
200
|
const model = this.resolveModel(provider);
|
|
@@ -133,6 +232,18 @@ var Compressor = class {
|
|
|
133
232
|
baseUrl: this.resolveBaseUrl(provider)
|
|
134
233
|
};
|
|
135
234
|
}
|
|
235
|
+
if (provider === "xai") {
|
|
236
|
+
const apiKey2 = this.resolveApiKey(provider);
|
|
237
|
+
if (!apiKey2) {
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
240
|
+
return {
|
|
241
|
+
provider,
|
|
242
|
+
model,
|
|
243
|
+
apiKey: apiKey2,
|
|
244
|
+
baseUrl: XAI_BASE_URL
|
|
245
|
+
};
|
|
246
|
+
}
|
|
136
247
|
const apiKey = this.resolveApiKey(provider) ?? void 0;
|
|
137
248
|
return {
|
|
138
249
|
provider,
|
|
@@ -141,21 +252,14 @@ var Compressor = class {
|
|
|
141
252
|
baseUrl: this.resolveBaseUrl(provider)
|
|
142
253
|
};
|
|
143
254
|
}
|
|
144
|
-
|
|
145
|
-
const anthropicModel = allowConfiguredModel ? this.resolveModel("anthropic") : DEFAULT_PROVIDER_MODELS.anthropic;
|
|
146
|
-
const oauthEnvToken = this.readEnvValue("ANTHROPIC_OAUTH_TOKEN");
|
|
147
|
-
if (oauthEnvToken) {
|
|
148
|
-
return { provider: "anthropic", model: anthropicModel, apiKey: oauthEnvToken, isOAuth: true };
|
|
149
|
-
}
|
|
255
|
+
resolveProviderFromEnv(allowConfiguredModel) {
|
|
150
256
|
const anthropicApiKey = this.readEnvValue("ANTHROPIC_API_KEY");
|
|
151
257
|
if (anthropicApiKey) {
|
|
152
|
-
return {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
return { provider: "anthropic", model: anthropicModel, apiKey: oauthToken, isOAuth: true };
|
|
158
|
-
}
|
|
258
|
+
return {
|
|
259
|
+
provider: "anthropic",
|
|
260
|
+
model: allowConfiguredModel ? this.resolveModel("anthropic") : DEFAULT_PROVIDER_MODELS.anthropic,
|
|
261
|
+
apiKey: anthropicApiKey
|
|
262
|
+
};
|
|
159
263
|
}
|
|
160
264
|
const openAiApiKey = this.readEnvValue("OPENAI_API_KEY");
|
|
161
265
|
if (openAiApiKey) {
|
|
@@ -174,6 +278,15 @@ var Compressor = class {
|
|
|
174
278
|
apiKey: geminiApiKey
|
|
175
279
|
};
|
|
176
280
|
}
|
|
281
|
+
const xaiApiKey = this.readEnvValue("XAI_API_KEY");
|
|
282
|
+
if (xaiApiKey) {
|
|
283
|
+
return {
|
|
284
|
+
provider: "xai",
|
|
285
|
+
model: allowConfiguredModel ? this.resolveModel("xai") : DEFAULT_PROVIDER_MODELS.xai,
|
|
286
|
+
apiKey: xaiApiKey,
|
|
287
|
+
baseUrl: XAI_BASE_URL
|
|
288
|
+
};
|
|
289
|
+
}
|
|
177
290
|
return null;
|
|
178
291
|
}
|
|
179
292
|
resolveModel(provider) {
|
|
@@ -194,6 +307,9 @@ var Compressor = class {
|
|
|
194
307
|
if (provider === "gemini") {
|
|
195
308
|
return this.readEnvValue("GEMINI_API_KEY");
|
|
196
309
|
}
|
|
310
|
+
if (provider === "xai") {
|
|
311
|
+
return this.readEnvValue("XAI_API_KEY");
|
|
312
|
+
}
|
|
197
313
|
return this.readEnvValue("OPENAI_API_KEY");
|
|
198
314
|
}
|
|
199
315
|
resolveBaseUrl(provider) {
|
|
@@ -225,17 +341,6 @@ var Compressor = class {
|
|
|
225
341
|
"- Confidence c reflects extraction certainty, not importance.",
|
|
226
342
|
"- Preserve source tags when present (e.g., [main], [telegram-dm], [discord], [telegram-group]).",
|
|
227
343
|
"",
|
|
228
|
-
"PREFERENCE & PERSONAL CONTEXT EXTRACTION (critical for personalization):",
|
|
229
|
-
"- Emit [preference] for ANY personal detail that reveals tastes, habits, equipment, or context:",
|
|
230
|
-
' * Explicit: "I prefer X", "I like Y", "I always use Z"',
|
|
231
|
-
' * Ownership: "my Sony A7R IV", "I have a...", "I use...", "I own..."',
|
|
232
|
-
' * Habits/routines: "I usually...", "every morning I...", "I tend to..."',
|
|
233
|
-
" * Interests: topics the user is enthusiastic about, hobbies mentioned in passing",
|
|
234
|
-
" * Constraints: dietary restrictions, allergies, phobias, limitations",
|
|
235
|
-
` * Goals: "I'm trying to...", "I want to learn..."`,
|
|
236
|
-
"- These are HIGH VALUE observations (i >= 0.60) \u2014 they enable personalized responses.",
|
|
237
|
-
"- When in doubt between [preference] and [task], choose [preference] if it describes a lasting trait.",
|
|
238
|
-
"",
|
|
239
344
|
"TASK EXTRACTION (required):",
|
|
240
345
|
`- Emit [todo] for explicit TODO phrasing: "TODO:", "we need to", "don't forget", "remember to", "make sure to".`,
|
|
241
346
|
`- Emit [task] for commitments/action intent: "I'll", "I will", "let me", "going to", "plan to", "should".`,
|
|
@@ -314,35 +419,19 @@ var Compressor = class {
|
|
|
314
419
|
if (!backend.apiKey) {
|
|
315
420
|
return "";
|
|
316
421
|
}
|
|
317
|
-
const isOAuth = backend.isOAuth || backend.apiKey.includes("sk-ant-oat");
|
|
318
|
-
const headers = isOAuth ? {
|
|
319
|
-
"content-type": "application/json",
|
|
320
|
-
"authorization": `Bearer ${backend.apiKey}`,
|
|
321
|
-
"anthropic-version": "2023-06-01",
|
|
322
|
-
"anthropic-beta": "claude-code-20250219,oauth-2025-04-20",
|
|
323
|
-
"x-app": "cli",
|
|
324
|
-
"user-agent": "claude-cli/1.0.0 (external, cli)"
|
|
325
|
-
} : {
|
|
326
|
-
"content-type": "application/json",
|
|
327
|
-
"x-api-key": backend.apiKey,
|
|
328
|
-
"anthropic-version": "2023-06-01"
|
|
329
|
-
};
|
|
330
|
-
const body = isOAuth ? {
|
|
331
|
-
model: backend.model,
|
|
332
|
-
temperature: 0.1,
|
|
333
|
-
max_tokens: 1400,
|
|
334
|
-
system: [{ type: "text", text: "You are Claude Code, Anthropic's official CLI for Claude." }],
|
|
335
|
-
messages: [{ role: "user", content: prompt }]
|
|
336
|
-
} : {
|
|
337
|
-
model: backend.model,
|
|
338
|
-
temperature: 0.1,
|
|
339
|
-
max_tokens: 1400,
|
|
340
|
-
messages: [{ role: "user", content: prompt }]
|
|
341
|
-
};
|
|
342
422
|
const response = await this.fetchImpl("https://api.anthropic.com/v1/messages", {
|
|
343
423
|
method: "POST",
|
|
344
|
-
headers
|
|
345
|
-
|
|
424
|
+
headers: {
|
|
425
|
+
"content-type": "application/json",
|
|
426
|
+
"x-api-key": backend.apiKey,
|
|
427
|
+
"anthropic-version": "2023-06-01"
|
|
428
|
+
},
|
|
429
|
+
body: JSON.stringify({
|
|
430
|
+
model: backend.model,
|
|
431
|
+
temperature: 0.1,
|
|
432
|
+
max_tokens: 1400,
|
|
433
|
+
messages: [{ role: "user", content: prompt }]
|
|
434
|
+
})
|
|
346
435
|
});
|
|
347
436
|
if (!response.ok) {
|
|
348
437
|
throw new Error(`Anthropic request failed (${response.status})`);
|
|
@@ -353,6 +442,9 @@ var Compressor = class {
|
|
|
353
442
|
async callOpenAI(prompt, backend) {
|
|
354
443
|
return this.callOpenAICompatible(prompt, backend);
|
|
355
444
|
}
|
|
445
|
+
async callXAI(prompt, backend) {
|
|
446
|
+
return this.callOpenAICompatible(prompt, backend);
|
|
447
|
+
}
|
|
356
448
|
async callOpenAICompatible(prompt, backend) {
|
|
357
449
|
const baseUrl = backend.baseUrl ?? this.resolveBaseUrl(backend.provider);
|
|
358
450
|
const response = await this.fetchImpl(this.buildOpenAICompatibleUrl(baseUrl), {
|
|
@@ -728,6 +820,125 @@ var Reflector = class {
|
|
|
728
820
|
}
|
|
729
821
|
};
|
|
730
822
|
|
|
823
|
+
// src/lib/llm-adapter.ts
|
|
824
|
+
var GEMINI_FLASH_MODEL = "gemini-2.0-flash";
|
|
825
|
+
var OLLAMA_DEFAULT_MODEL = "llama3.1:8b";
|
|
826
|
+
var OLLAMA_BASE_URL2 = "http://127.0.0.1:11434";
|
|
827
|
+
function createGeminiFlashAdapter(options = {}) {
|
|
828
|
+
const apiKey = process.env.GEMINI_API_KEY;
|
|
829
|
+
return {
|
|
830
|
+
async call(prompt) {
|
|
831
|
+
if (!apiKey) {
|
|
832
|
+
return "";
|
|
833
|
+
}
|
|
834
|
+
return requestLlmCompletion({
|
|
835
|
+
prompt,
|
|
836
|
+
provider: "gemini",
|
|
837
|
+
model: options.model ?? GEMINI_FLASH_MODEL,
|
|
838
|
+
temperature: options.temperature ?? 0.1,
|
|
839
|
+
maxTokens: options.maxTokens ?? 2e3,
|
|
840
|
+
fetchImpl: options.fetchImpl
|
|
841
|
+
});
|
|
842
|
+
},
|
|
843
|
+
isAvailable() {
|
|
844
|
+
return Boolean(apiKey);
|
|
845
|
+
},
|
|
846
|
+
getProvider() {
|
|
847
|
+
return apiKey ? "gemini" : null;
|
|
848
|
+
}
|
|
849
|
+
};
|
|
850
|
+
}
|
|
851
|
+
function createOllamaAdapter(options = {}) {
|
|
852
|
+
let _available = null;
|
|
853
|
+
const fetchFn = options.fetchImpl ?? globalThis.fetch;
|
|
854
|
+
return {
|
|
855
|
+
async call(prompt) {
|
|
856
|
+
const resp = await fetchFn(`${OLLAMA_BASE_URL2}/api/generate`, {
|
|
857
|
+
method: "POST",
|
|
858
|
+
headers: { "Content-Type": "application/json" },
|
|
859
|
+
body: JSON.stringify({
|
|
860
|
+
model: options.model ?? OLLAMA_DEFAULT_MODEL,
|
|
861
|
+
prompt,
|
|
862
|
+
stream: false,
|
|
863
|
+
options: {
|
|
864
|
+
temperature: options.temperature ?? 0.1,
|
|
865
|
+
num_predict: options.maxTokens ?? 2e3
|
|
866
|
+
}
|
|
867
|
+
})
|
|
868
|
+
});
|
|
869
|
+
if (!resp.ok) return "";
|
|
870
|
+
const data = await resp.json();
|
|
871
|
+
return data.response ?? "";
|
|
872
|
+
},
|
|
873
|
+
isAvailable() {
|
|
874
|
+
if (_available !== null) return _available;
|
|
875
|
+
_available = true;
|
|
876
|
+
return true;
|
|
877
|
+
},
|
|
878
|
+
getProvider() {
|
|
879
|
+
return null;
|
|
880
|
+
}
|
|
881
|
+
};
|
|
882
|
+
}
|
|
883
|
+
function createDefaultAdapter(options = {}) {
|
|
884
|
+
const resolvedProvider = options.provider !== void 0 ? options.provider : resolveLlmProvider();
|
|
885
|
+
return {
|
|
886
|
+
async call(prompt) {
|
|
887
|
+
if (!resolvedProvider) {
|
|
888
|
+
return "";
|
|
889
|
+
}
|
|
890
|
+
return requestLlmCompletion({
|
|
891
|
+
prompt,
|
|
892
|
+
provider: resolvedProvider,
|
|
893
|
+
model: options.model,
|
|
894
|
+
temperature: options.temperature ?? 0.1,
|
|
895
|
+
maxTokens: options.maxTokens ?? 2e3,
|
|
896
|
+
fetchImpl: options.fetchImpl
|
|
897
|
+
});
|
|
898
|
+
},
|
|
899
|
+
isAvailable() {
|
|
900
|
+
return resolvedProvider !== null;
|
|
901
|
+
},
|
|
902
|
+
getProvider() {
|
|
903
|
+
return resolvedProvider;
|
|
904
|
+
}
|
|
905
|
+
};
|
|
906
|
+
}
|
|
907
|
+
function createFactExtractionAdapter(options = {}) {
|
|
908
|
+
if (options.provider) {
|
|
909
|
+
return createDefaultAdapter(options);
|
|
910
|
+
}
|
|
911
|
+
const geminiAdapter = createGeminiFlashAdapter(options);
|
|
912
|
+
if (geminiAdapter.isAvailable()) {
|
|
913
|
+
return geminiAdapter;
|
|
914
|
+
}
|
|
915
|
+
const ollamaAdapter = createOllamaAdapter(options);
|
|
916
|
+
if (ollamaAdapter.isAvailable()) {
|
|
917
|
+
return ollamaAdapter;
|
|
918
|
+
}
|
|
919
|
+
return createDefaultAdapter(options);
|
|
920
|
+
}
|
|
921
|
+
function createLlmFunction(adapter) {
|
|
922
|
+
if (!adapter.isAvailable()) {
|
|
923
|
+
return void 0;
|
|
924
|
+
}
|
|
925
|
+
return (prompt) => adapter.call(prompt);
|
|
926
|
+
}
|
|
927
|
+
function resolveFactExtractionMode(configuredMode, adapter) {
|
|
928
|
+
const mode = configuredMode ?? "llm";
|
|
929
|
+
if (mode === "off") {
|
|
930
|
+
return { mode: "off", useLlm: false };
|
|
931
|
+
}
|
|
932
|
+
if (mode === "rule") {
|
|
933
|
+
return { mode: "rule", useLlm: false };
|
|
934
|
+
}
|
|
935
|
+
const llmAvailable = adapter?.isAvailable() ?? resolveLlmProvider() !== null;
|
|
936
|
+
if (mode === "llm" || mode === "hybrid") {
|
|
937
|
+
return { mode, useLlm: llmAvailable };
|
|
938
|
+
}
|
|
939
|
+
return { mode: "rule", useLlm: false };
|
|
940
|
+
}
|
|
941
|
+
|
|
731
942
|
// src/observer/observer.ts
|
|
732
943
|
import * as fs2 from "fs";
|
|
733
944
|
import * as path2 from "path";
|
|
@@ -801,17 +1012,41 @@ var FUTURE_TASK_HINT_RE = /\b(need to|should|todo|must|plan to)\b/i;
|
|
|
801
1012
|
var Router = class {
|
|
802
1013
|
vaultPath;
|
|
803
1014
|
extractTasks;
|
|
1015
|
+
extractFacts;
|
|
1016
|
+
factExtractionMode;
|
|
1017
|
+
llmAdapter;
|
|
1018
|
+
factStore;
|
|
804
1019
|
now;
|
|
805
1020
|
customRoutes;
|
|
806
1021
|
constructor(vaultPath, options = {}) {
|
|
807
1022
|
this.vaultPath = path.resolve(vaultPath);
|
|
808
1023
|
this.extractTasks = options.extractTasks ?? true;
|
|
1024
|
+
this.extractFacts = options.extractFacts ?? true;
|
|
1025
|
+
this.factExtractionMode = options.factExtractionMode ?? this.loadFactExtractionMode();
|
|
1026
|
+
this.llmAdapter = options.llmAdapter ?? createFactExtractionAdapter();
|
|
1027
|
+
this.factStore = new FactStore(this.vaultPath);
|
|
809
1028
|
this.now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
810
1029
|
this.customRoutes = this.loadCustomRoutes();
|
|
1030
|
+
if (this.extractFacts && this.factExtractionMode !== "off") {
|
|
1031
|
+
this.factStore.load();
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
loadFactExtractionMode() {
|
|
1035
|
+
try {
|
|
1036
|
+
const config = listConfig(this.vaultPath);
|
|
1037
|
+
const observer = config.observer;
|
|
1038
|
+
const mode = observer?.factExtractionMode;
|
|
1039
|
+
if (mode === "off" || mode === "rule" || mode === "llm" || mode === "hybrid") {
|
|
1040
|
+
return mode;
|
|
1041
|
+
}
|
|
1042
|
+
} catch {
|
|
1043
|
+
}
|
|
1044
|
+
return "llm";
|
|
811
1045
|
}
|
|
812
1046
|
/**
|
|
813
1047
|
* Takes observation markdown and routes items to appropriate vault categories.
|
|
814
1048
|
* Routes only items with importance >= 0.4.
|
|
1049
|
+
* Also extracts structured facts from observations when fact extraction is enabled.
|
|
815
1050
|
* Returns a summary of what was routed where.
|
|
816
1051
|
*/
|
|
817
1052
|
route(observationMarkdown, context = {}) {
|
|
@@ -821,6 +1056,7 @@ var Router = class {
|
|
|
821
1056
|
const knownWorkItems = this.extractTasks ? this.loadExistingWorkItems() : [];
|
|
822
1057
|
const knownProjectDefinitions = this.loadKnownProjectDefinitions();
|
|
823
1058
|
let dedupHits = 0;
|
|
1059
|
+
let factsExtracted = 0;
|
|
824
1060
|
for (const item of items) {
|
|
825
1061
|
if (item.importance < 0.4) continue;
|
|
826
1062
|
if (this.extractTasks && this.isTaskObservation(item.type)) {
|
|
@@ -847,8 +1083,81 @@ var Router = class {
|
|
|
847
1083
|
routed.push(routedItem);
|
|
848
1084
|
this.appendToCategory(category, routedItem, knownProjectDefinitions);
|
|
849
1085
|
}
|
|
850
|
-
|
|
851
|
-
|
|
1086
|
+
if (this.extractFacts && this.factExtractionMode !== "off") {
|
|
1087
|
+
const extractedCount = this.extractAndStoreFacts(observationMarkdown, context);
|
|
1088
|
+
factsExtracted = extractedCount;
|
|
1089
|
+
}
|
|
1090
|
+
const summary = this.buildSummary(routed, dedupHits, factsExtracted);
|
|
1091
|
+
return { routed, summary, factsExtracted };
|
|
1092
|
+
}
|
|
1093
|
+
/**
|
|
1094
|
+
* Extract facts from observation markdown and store them in the fact store.
|
|
1095
|
+
* Uses the configured extraction mode (rule-based, LLM, or hybrid).
|
|
1096
|
+
*/
|
|
1097
|
+
extractAndStoreFacts(observationMarkdown, context) {
|
|
1098
|
+
const { mode, useLlm } = resolveFactExtractionMode(this.factExtractionMode, this.llmAdapter);
|
|
1099
|
+
if (mode === "off") {
|
|
1100
|
+
return 0;
|
|
1101
|
+
}
|
|
1102
|
+
const source = context.source ?? "observer";
|
|
1103
|
+
const timestamp = context.timestamp?.toISOString() ?? this.now().toISOString();
|
|
1104
|
+
let facts = [];
|
|
1105
|
+
if (mode === "rule" || !useLlm) {
|
|
1106
|
+
facts = extractFactsRuleBased(observationMarkdown, source, timestamp);
|
|
1107
|
+
} else if (mode === "llm") {
|
|
1108
|
+
const llmFn = createLlmFunction(this.llmAdapter);
|
|
1109
|
+
extractFactsLlm(observationMarkdown, source, timestamp, llmFn).then((llmFacts) => {
|
|
1110
|
+
if (llmFacts.length > 0) {
|
|
1111
|
+
this.factStore.addFacts(llmFacts);
|
|
1112
|
+
this.factStore.save();
|
|
1113
|
+
}
|
|
1114
|
+
}).catch(() => {
|
|
1115
|
+
const ruleFacts = extractFactsRuleBased(observationMarkdown, source, timestamp);
|
|
1116
|
+
if (ruleFacts.length > 0) {
|
|
1117
|
+
this.factStore.addFacts(ruleFacts);
|
|
1118
|
+
this.factStore.save();
|
|
1119
|
+
}
|
|
1120
|
+
});
|
|
1121
|
+
return 0;
|
|
1122
|
+
} else if (mode === "hybrid") {
|
|
1123
|
+
facts = extractFactsRuleBased(observationMarkdown, source, timestamp);
|
|
1124
|
+
const llmFn = createLlmFunction(this.llmAdapter);
|
|
1125
|
+
extractFactsLlm(observationMarkdown, source, timestamp, llmFn).then((llmFacts) => {
|
|
1126
|
+
const merged = this.mergeFacts(facts, llmFacts);
|
|
1127
|
+
if (merged.length > facts.length) {
|
|
1128
|
+
this.factStore.addFacts(merged.slice(facts.length));
|
|
1129
|
+
this.factStore.save();
|
|
1130
|
+
}
|
|
1131
|
+
}).catch(() => {
|
|
1132
|
+
});
|
|
1133
|
+
}
|
|
1134
|
+
if (facts.length > 0) {
|
|
1135
|
+
this.factStore.addFacts(facts);
|
|
1136
|
+
this.factStore.save();
|
|
1137
|
+
}
|
|
1138
|
+
return facts.length;
|
|
1139
|
+
}
|
|
1140
|
+
/**
|
|
1141
|
+
* Merge facts from rule-based and LLM extraction, deduplicating by entity+relation.
|
|
1142
|
+
*/
|
|
1143
|
+
mergeFacts(ruleFacts, llmFacts) {
|
|
1144
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1145
|
+
const merged = [];
|
|
1146
|
+
for (const fact of ruleFacts) {
|
|
1147
|
+
const key = `${fact.entityNorm}::${fact.relation}`;
|
|
1148
|
+
if (!seen.has(key)) {
|
|
1149
|
+
seen.add(key);
|
|
1150
|
+
merged.push(fact);
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
for (const fact of llmFacts) {
|
|
1154
|
+
const key = `${fact.entityNorm}::${fact.relation}`;
|
|
1155
|
+
if (!seen.has(key)) {
|
|
1156
|
+
seen.add(key);
|
|
1157
|
+
merged.push(fact);
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
return merged;
|
|
852
1161
|
}
|
|
853
1162
|
isTaskObservation(type) {
|
|
854
1163
|
return type === "task" || type === "todo" || type === "commitment-unresolved";
|
|
@@ -1436,8 +1745,8 @@ ${entry}
|
|
|
1436
1745
|
for (const bg of setA) if (setB.has(bg)) intersection++;
|
|
1437
1746
|
return intersection / (setA.size + setB.size - intersection);
|
|
1438
1747
|
}
|
|
1439
|
-
buildSummary(routed, dedupHits) {
|
|
1440
|
-
if (routed.length === 0) {
|
|
1748
|
+
buildSummary(routed, dedupHits, factsExtracted = 0) {
|
|
1749
|
+
if (routed.length === 0 && factsExtracted === 0) {
|
|
1441
1750
|
if (dedupHits > 0) {
|
|
1442
1751
|
return `No items routed to vault categories (dedup hits: ${dedupHits}).`;
|
|
1443
1752
|
}
|
|
@@ -1448,7 +1757,17 @@ ${entry}
|
|
|
1448
1757
|
byCat.set(item.category, (byCat.get(item.category) ?? 0) + 1);
|
|
1449
1758
|
}
|
|
1450
1759
|
const parts = [...byCat.entries()].map(([cat, count]) => `${cat}: ${count}`);
|
|
1451
|
-
const
|
|
1760
|
+
const suffixParts = [];
|
|
1761
|
+
if (dedupHits > 0) {
|
|
1762
|
+
suffixParts.push(`dedup hits: ${dedupHits}`);
|
|
1763
|
+
}
|
|
1764
|
+
if (factsExtracted > 0) {
|
|
1765
|
+
suffixParts.push(`facts: ${factsExtracted}`);
|
|
1766
|
+
}
|
|
1767
|
+
const suffix = suffixParts.length > 0 ? ` (${suffixParts.join(", ")})` : "";
|
|
1768
|
+
if (routed.length === 0 && factsExtracted > 0) {
|
|
1769
|
+
return `Extracted ${factsExtracted} facts${suffix}`;
|
|
1770
|
+
}
|
|
1452
1771
|
return `Routed ${routed.length} observations \u2192 ${parts.join(", ")}${suffix}`;
|
|
1453
1772
|
}
|
|
1454
1773
|
};
|
|
@@ -1698,5 +2017,10 @@ var Observer = class {
|
|
|
1698
2017
|
export {
|
|
1699
2018
|
Compressor,
|
|
1700
2019
|
Reflector,
|
|
2020
|
+
createGeminiFlashAdapter,
|
|
2021
|
+
createDefaultAdapter,
|
|
2022
|
+
createFactExtractionAdapter,
|
|
2023
|
+
createLlmFunction,
|
|
2024
|
+
resolveFactExtractionMode,
|
|
1701
2025
|
Observer
|
|
1702
2026
|
};
|