create-agentfs 0.1.1
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/LICENSE +21 -0
- package/README.md +238 -0
- package/dist/cli.d.ts +51 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +246 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/compile.d.ts +48 -0
- package/dist/commands/compile.d.ts.map +1 -0
- package/dist/commands/compile.js +228 -0
- package/dist/commands/compile.js.map +1 -0
- package/dist/commands/cron.d.ts +18 -0
- package/dist/commands/cron.d.ts.map +1 -0
- package/dist/commands/cron.js +95 -0
- package/dist/commands/cron.js.map +1 -0
- package/dist/commands/doctor.d.ts +11 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +199 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/memory.d.ts +19 -0
- package/dist/commands/memory.d.ts.map +1 -0
- package/dist/commands/memory.js +213 -0
- package/dist/commands/memory.js.map +1 -0
- package/dist/commands/onboard.d.ts +31 -0
- package/dist/commands/onboard.d.ts.map +1 -0
- package/dist/commands/onboard.js +362 -0
- package/dist/commands/onboard.js.map +1 -0
- package/dist/commands/secret.d.ts +13 -0
- package/dist/commands/secret.d.ts.map +1 -0
- package/dist/commands/secret.js +109 -0
- package/dist/commands/secret.js.map +1 -0
- package/dist/commands/security.d.ts +16 -0
- package/dist/commands/security.d.ts.map +1 -0
- package/dist/commands/security.js +203 -0
- package/dist/commands/security.js.map +1 -0
- package/dist/commands/sync.d.ts +14 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +84 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/compilers/agent-map.d.ts +34 -0
- package/dist/compilers/agent-map.d.ts.map +1 -0
- package/dist/compilers/agent-map.js +66 -0
- package/dist/compilers/agent-map.js.map +1 -0
- package/dist/compilers/base.d.ts +67 -0
- package/dist/compilers/base.d.ts.map +1 -0
- package/dist/compilers/base.js +183 -0
- package/dist/compilers/base.js.map +1 -0
- package/dist/compilers/claude.d.ts +26 -0
- package/dist/compilers/claude.d.ts.map +1 -0
- package/dist/compilers/claude.js +151 -0
- package/dist/compilers/claude.js.map +1 -0
- package/dist/compilers/cursor.d.ts +11 -0
- package/dist/compilers/cursor.d.ts.map +1 -0
- package/dist/compilers/cursor.js +52 -0
- package/dist/compilers/cursor.js.map +1 -0
- package/dist/compilers/index.d.ts +14 -0
- package/dist/compilers/index.d.ts.map +1 -0
- package/dist/compilers/index.js +14 -0
- package/dist/compilers/index.js.map +1 -0
- package/dist/compilers/openclaw.d.ts +12 -0
- package/dist/compilers/openclaw.d.ts.map +1 -0
- package/dist/compilers/openclaw.js +51 -0
- package/dist/compilers/openclaw.js.map +1 -0
- package/dist/cron/index.d.ts +10 -0
- package/dist/cron/index.d.ts.map +1 -0
- package/dist/cron/index.js +9 -0
- package/dist/cron/index.js.map +1 -0
- package/dist/cron/jobs/consolidate.d.ts +16 -0
- package/dist/cron/jobs/consolidate.d.ts.map +1 -0
- package/dist/cron/jobs/consolidate.js +61 -0
- package/dist/cron/jobs/consolidate.js.map +1 -0
- package/dist/cron/jobs/heartbeat.d.ts +11 -0
- package/dist/cron/jobs/heartbeat.d.ts.map +1 -0
- package/dist/cron/jobs/heartbeat.js +66 -0
- package/dist/cron/jobs/heartbeat.js.map +1 -0
- package/dist/cron/jobs/inbox-triage.d.ts +11 -0
- package/dist/cron/jobs/inbox-triage.d.ts.map +1 -0
- package/dist/cron/jobs/inbox-triage.js +85 -0
- package/dist/cron/jobs/inbox-triage.js.map +1 -0
- package/dist/cron/runner.d.ts +32 -0
- package/dist/cron/runner.d.ts.map +1 -0
- package/dist/cron/runner.js +69 -0
- package/dist/cron/runner.js.map +1 -0
- package/dist/cron/types.d.ts +21 -0
- package/dist/cron/types.d.ts.map +1 -0
- package/dist/cron/types.js +6 -0
- package/dist/cron/types.js.map +1 -0
- package/dist/generators/filesystem.d.ts +52 -0
- package/dist/generators/filesystem.d.ts.map +1 -0
- package/dist/generators/filesystem.js +155 -0
- package/dist/generators/filesystem.js.map +1 -0
- package/dist/generators/ignore.d.ts +38 -0
- package/dist/generators/ignore.d.ts.map +1 -0
- package/dist/generators/ignore.js +154 -0
- package/dist/generators/ignore.js.map +1 -0
- package/dist/generators/index.d.ts +14 -0
- package/dist/generators/index.d.ts.map +1 -0
- package/dist/generators/index.js +14 -0
- package/dist/generators/index.js.map +1 -0
- package/dist/generators/init.d.ts +37 -0
- package/dist/generators/init.d.ts.map +1 -0
- package/dist/generators/init.js +169 -0
- package/dist/generators/init.js.map +1 -0
- package/dist/generators/manifest.d.ts +31 -0
- package/dist/generators/manifest.d.ts.map +1 -0
- package/dist/generators/manifest.js +123 -0
- package/dist/generators/manifest.js.map +1 -0
- package/dist/generators/memory.d.ts +36 -0
- package/dist/generators/memory.d.ts.map +1 -0
- package/dist/generators/memory.js +106 -0
- package/dist/generators/memory.js.map +1 -0
- package/dist/generators/profiles.d.ts +22 -0
- package/dist/generators/profiles.d.ts.map +1 -0
- package/dist/generators/profiles.js +92 -0
- package/dist/generators/profiles.js.map +1 -0
- package/dist/generators/prompts.d.ts +24 -0
- package/dist/generators/prompts.d.ts.map +1 -0
- package/dist/generators/prompts.js +122 -0
- package/dist/generators/prompts.js.map +1 -0
- package/dist/generators/scaffold.d.ts +29 -0
- package/dist/generators/scaffold.d.ts.map +1 -0
- package/dist/generators/scaffold.js +90 -0
- package/dist/generators/scaffold.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/memory/confidence.d.ts +69 -0
- package/dist/memory/confidence.d.ts.map +1 -0
- package/dist/memory/confidence.js +125 -0
- package/dist/memory/confidence.js.map +1 -0
- package/dist/memory/episodic.d.ts +40 -0
- package/dist/memory/episodic.d.ts.map +1 -0
- package/dist/memory/episodic.js +139 -0
- package/dist/memory/episodic.js.map +1 -0
- package/dist/memory/index.d.ts +17 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +17 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/parser.d.ts +73 -0
- package/dist/memory/parser.d.ts.map +1 -0
- package/dist/memory/parser.js +156 -0
- package/dist/memory/parser.js.map +1 -0
- package/dist/memory/procedural.d.ts +43 -0
- package/dist/memory/procedural.d.ts.map +1 -0
- package/dist/memory/procedural.js +126 -0
- package/dist/memory/procedural.js.map +1 -0
- package/dist/secrets/exfil-guard.d.ts +31 -0
- package/dist/secrets/exfil-guard.d.ts.map +1 -0
- package/dist/secrets/exfil-guard.js +51 -0
- package/dist/secrets/exfil-guard.js.map +1 -0
- package/dist/secrets/index.d.ts +8 -0
- package/dist/secrets/index.d.ts.map +1 -0
- package/dist/secrets/index.js +7 -0
- package/dist/secrets/index.js.map +1 -0
- package/dist/secrets/vault.d.ts +63 -0
- package/dist/secrets/vault.d.ts.map +1 -0
- package/dist/secrets/vault.js +163 -0
- package/dist/secrets/vault.js.map +1 -0
- package/dist/security/claude-compiler.d.ts +28 -0
- package/dist/security/claude-compiler.d.ts.map +1 -0
- package/dist/security/claude-compiler.js +66 -0
- package/dist/security/claude-compiler.js.map +1 -0
- package/dist/security/index.d.ts +7 -0
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/index.js +7 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/parser.d.ts +47 -0
- package/dist/security/parser.d.ts.map +1 -0
- package/dist/security/parser.js +136 -0
- package/dist/security/parser.js.map +1 -0
- package/dist/sync/index.d.ts +7 -0
- package/dist/sync/index.d.ts.map +1 -0
- package/dist/sync/index.js +6 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/sync/sync.d.ts +46 -0
- package/dist/sync/sync.d.ts.map +1 -0
- package/dist/sync/sync.js +174 -0
- package/dist/sync/sync.js.map +1 -0
- package/dist/types/compiler.d.ts +81 -0
- package/dist/types/compiler.d.ts.map +1 -0
- package/dist/types/compiler.js +10 -0
- package/dist/types/compiler.js.map +1 -0
- package/dist/types/index.d.ts +15 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +10 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/manifest.d.ts +112 -0
- package/dist/types/manifest.d.ts.map +1 -0
- package/dist/types/manifest.js +10 -0
- package/dist/types/manifest.js.map +1 -0
- package/dist/types/memory.d.ts +85 -0
- package/dist/types/memory.d.ts.map +1 -0
- package/dist/types/memory.js +20 -0
- package/dist/types/memory.js.map +1 -0
- package/dist/types/security.d.ts +67 -0
- package/dist/types/security.d.ts.map +1 -0
- package/dist/types/security.js +10 -0
- package/dist/types/security.js.map +1 -0
- package/dist/types/setup.d.ts +54 -0
- package/dist/types/setup.d.ts.map +1 -0
- package/dist/types/setup.js +9 -0
- package/dist/types/setup.js.map +1 -0
- package/dist/utils/fhs-mapping.d.ts +76 -0
- package/dist/utils/fhs-mapping.d.ts.map +1 -0
- package/dist/utils/fhs-mapping.js +189 -0
- package/dist/utils/fhs-mapping.js.map +1 -0
- package/package.json +58 -0
- package/templates/compilers/agent-map.md.hbs +36 -0
- package/templates/compilers/claude.md.hbs +95 -0
- package/templates/procedural/code-review.md +54 -0
- package/templates/procedural/debugging.md +52 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Confidence scoring engine for PATTERN entries in semantic memory.
|
|
3
|
+
*
|
|
4
|
+
* Implements the rules from docs/architecture.md Section 4:
|
|
5
|
+
*
|
|
6
|
+
* New PATTERN → confidence: 0.3 (DEFAULT_CONFIDENCE.initial)
|
|
7
|
+
* Confirmed → confidence += 0.2 (max 1.0)
|
|
8
|
+
* Denied → confidence -= 0.3
|
|
9
|
+
* Inactive 30 days → confidence -= 0.1 (decay)
|
|
10
|
+
* confidence < 0.1 → mark as superseded
|
|
11
|
+
*
|
|
12
|
+
* All functions are pure — they return a new `SemanticEntry` and never
|
|
13
|
+
* mutate the input. Non-PATTERN entries are returned unchanged.
|
|
14
|
+
*
|
|
15
|
+
* @module memory/confidence
|
|
16
|
+
*/
|
|
17
|
+
import { DEFAULT_CONFIDENCE } from '../types/index.js';
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
// Internal helpers
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
/**
|
|
22
|
+
* Clamp a number to [min, max].
|
|
23
|
+
*/
|
|
24
|
+
function clamp(value, min, max) {
|
|
25
|
+
return Math.min(max, Math.max(min, value));
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Returns the effective confidence for an entry.
|
|
29
|
+
* For non-PATTERN entries this is always 1.0 (not used in scoring).
|
|
30
|
+
* For PATTERN entries it defaults to DEFAULT_CONFIDENCE.initial when absent.
|
|
31
|
+
*/
|
|
32
|
+
function effectiveConfidence(entry) {
|
|
33
|
+
if (entry.type !== 'PATTERN')
|
|
34
|
+
return 1.0;
|
|
35
|
+
return entry.confidence ?? DEFAULT_CONFIDENCE.initial;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Returns a copy of `entry` with the given confidence applied, automatically
|
|
39
|
+
* marking the entry as superseded when the score drops below the threshold.
|
|
40
|
+
*/
|
|
41
|
+
function withConfidence(entry, score) {
|
|
42
|
+
const clamped = clamp(score, 0, 1.0);
|
|
43
|
+
if (clamped < DEFAULT_CONFIDENCE.supersededThreshold) {
|
|
44
|
+
// Use today's date in YYYY-MM-DD format for the superseded marker.
|
|
45
|
+
const today = new Date().toISOString().slice(0, 10);
|
|
46
|
+
return {
|
|
47
|
+
...entry,
|
|
48
|
+
confidence: clamped,
|
|
49
|
+
status: `superseded:${today}`,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
return { ...entry, confidence: clamped, status: 'active' };
|
|
53
|
+
}
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
// Public API
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
/**
|
|
58
|
+
* Increases the confidence of a PATTERN entry by `confirmBoost` (default 0.2),
|
|
59
|
+
* capped at 1.0.
|
|
60
|
+
*
|
|
61
|
+
* Non-PATTERN entries are returned unchanged.
|
|
62
|
+
*
|
|
63
|
+
* @param entry - The entry to confirm.
|
|
64
|
+
* @returns A new entry with updated confidence.
|
|
65
|
+
*/
|
|
66
|
+
export function confirmPattern(entry) {
|
|
67
|
+
if (entry.type !== 'PATTERN')
|
|
68
|
+
return entry;
|
|
69
|
+
return withConfidence(entry, effectiveConfidence(entry) + DEFAULT_CONFIDENCE.confirmBoost);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Decreases the confidence of a PATTERN entry by `denyPenalty` (default 0.3).
|
|
73
|
+
*
|
|
74
|
+
* If the result drops below `supersededThreshold` (0.1) the entry is
|
|
75
|
+
* automatically marked as superseded.
|
|
76
|
+
*
|
|
77
|
+
* Non-PATTERN entries are returned unchanged.
|
|
78
|
+
*
|
|
79
|
+
* @param entry - The entry to deny.
|
|
80
|
+
* @returns A new entry with updated confidence and status.
|
|
81
|
+
*/
|
|
82
|
+
export function denyPattern(entry) {
|
|
83
|
+
if (entry.type !== 'PATTERN')
|
|
84
|
+
return entry;
|
|
85
|
+
return withConfidence(entry, effectiveConfidence(entry) - DEFAULT_CONFIDENCE.denyPenalty);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Applies time-based confidence decay to a PATTERN entry.
|
|
89
|
+
*
|
|
90
|
+
* Each full `decayDays`-period (default 30 days) of inactivity reduces
|
|
91
|
+
* confidence by `decayRate` (default 0.1). Fractional periods are truncated.
|
|
92
|
+
*
|
|
93
|
+
* Examples:
|
|
94
|
+
* - 29 days inactive → 0 decay periods → no change
|
|
95
|
+
* - 30 days inactive → 1 decay period → -0.1
|
|
96
|
+
* - 75 days inactive → 2 decay periods → -0.2
|
|
97
|
+
*
|
|
98
|
+
* Non-PATTERN entries are returned unchanged.
|
|
99
|
+
*
|
|
100
|
+
* @param entry - The entry to decay.
|
|
101
|
+
* @param daysSinceLastSeen - Number of days since the pattern was last confirmed.
|
|
102
|
+
* @returns A new entry with decayed confidence (and possibly superseded status).
|
|
103
|
+
*/
|
|
104
|
+
export function decayPattern(entry, daysSinceLastSeen) {
|
|
105
|
+
if (entry.type !== 'PATTERN')
|
|
106
|
+
return entry;
|
|
107
|
+
const periods = Math.floor(daysSinceLastSeen / DEFAULT_CONFIDENCE.decayDays);
|
|
108
|
+
if (periods === 0)
|
|
109
|
+
return entry;
|
|
110
|
+
return withConfidence(entry, effectiveConfidence(entry) - periods * DEFAULT_CONFIDENCE.decayRate);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Returns `true` when an entry has been marked as superseded.
|
|
114
|
+
*
|
|
115
|
+
* An entry is superseded when its `status` string starts with "superseded:".
|
|
116
|
+
* This covers both confidence-driven supersession and manual date-based
|
|
117
|
+
* supersession (e.g. `FACT: [superseded:2026-04-01] …`).
|
|
118
|
+
*
|
|
119
|
+
* @param entry - Any semantic entry.
|
|
120
|
+
* @returns Whether the entry is superseded.
|
|
121
|
+
*/
|
|
122
|
+
export function isSuperseded(entry) {
|
|
123
|
+
return entry.status.startsWith('superseded:');
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=confidence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"confidence.js","sourceRoot":"","sources":["../../src/memory/confidence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAGvD,8EAA8E;AAC9E,mBAAmB;AACnB,8EAA8E;AAE9E;;GAEG;AACH,SAAS,KAAK,CAAC,KAAa,EAAE,GAAW,EAAE,GAAW;IACpD,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED;;;;GAIG;AACH,SAAS,mBAAmB,CAAC,KAAoB;IAC/C,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS;QAAE,OAAO,GAAG,CAAC;IACzC,OAAO,KAAK,CAAC,UAAU,IAAI,kBAAkB,CAAC,OAAO,CAAC;AACxD,CAAC;AAED;;;GAGG;AACH,SAAS,cAAc,CAAC,KAAoB,EAAE,KAAa;IACzD,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC;IAErC,IAAI,OAAO,GAAG,kBAAkB,CAAC,mBAAmB,EAAE,CAAC;QACrD,mEAAmE;QACnE,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACpD,OAAO;YACL,GAAG,KAAK;YACR,UAAU,EAAE,OAAO;YACnB,MAAM,EAAE,cAAc,KAAK,EAAE;SAC9B,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,GAAG,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;AAC7D,CAAC;AAED,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAAC,KAAoB;IACjD,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IAC3C,OAAO,cAAc,CACnB,KAAK,EACL,mBAAmB,CAAC,KAAK,CAAC,GAAG,kBAAkB,CAAC,YAAY,CAC7D,CAAC;AACJ,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,WAAW,CAAC,KAAoB;IAC9C,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IAC3C,OAAO,cAAc,CACnB,KAAK,EACL,mBAAmB,CAAC,KAAK,CAAC,GAAG,kBAAkB,CAAC,WAAW,CAC5D,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,YAAY,CAC1B,KAAoB,EACpB,iBAAyB;IAEzB,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IAE3C,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,iBAAiB,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;IAC7E,IAAI,OAAO,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAEhC,OAAO,cAAc,CACnB,KAAK,EACL,mBAAmB,CAAC,KAAK,CAAC,GAAG,OAAO,GAAG,kBAAkB,CAAC,SAAS,CACpE,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,YAAY,CAAC,KAAoB;IAC/C,OAAO,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAChD,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Episodic memory writer — creates/appends to daily event logs.
|
|
3
|
+
*
|
|
4
|
+
* Episodic memory stores timestamped session events in per-day markdown files:
|
|
5
|
+
* `.agentos/memory/episodic/YYYY-MM-DD.md`
|
|
6
|
+
*
|
|
7
|
+
* Each file contains sections for events, decisions, and lessons learned.
|
|
8
|
+
* Appending is idempotent — duplicate event lines are skipped.
|
|
9
|
+
*
|
|
10
|
+
* @module memory/episodic
|
|
11
|
+
*/
|
|
12
|
+
import type { EpisodicEntry } from '../types/index.js';
|
|
13
|
+
/**
|
|
14
|
+
* Write or append an episodic entry for a given date.
|
|
15
|
+
*
|
|
16
|
+
* If the file for the date already exists, new events/decisions/lessons are
|
|
17
|
+
* appended only if they are not already present (substring dedup).
|
|
18
|
+
*
|
|
19
|
+
* If the file does not exist, it is created with the full entry.
|
|
20
|
+
*
|
|
21
|
+
* @param vaultRoot - Absolute path to the vault root directory
|
|
22
|
+
* @param entry - The episodic entry to persist
|
|
23
|
+
*/
|
|
24
|
+
export declare function writeEpisodicEntry(vaultRoot: string, entry: EpisodicEntry): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Read an episodic entry for a specific date, returning null if it doesn't exist.
|
|
27
|
+
*
|
|
28
|
+
* @param vaultRoot - Absolute path to the vault root directory
|
|
29
|
+
* @param date - Date string in YYYY-MM-DD format
|
|
30
|
+
* @returns The raw markdown content, or null
|
|
31
|
+
*/
|
|
32
|
+
export declare function readEpisodicEntry(vaultRoot: string, date: string): Promise<string | null>;
|
|
33
|
+
/**
|
|
34
|
+
* List all episodic entry dates available in the vault.
|
|
35
|
+
*
|
|
36
|
+
* @param vaultRoot - Absolute path to the vault root directory
|
|
37
|
+
* @returns Sorted array of date strings (YYYY-MM-DD)
|
|
38
|
+
*/
|
|
39
|
+
export declare function listEpisodicDates(vaultRoot: string): Promise<string[]>;
|
|
40
|
+
//# sourceMappingURL=episodic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"episodic.d.ts","sourceRoot":"","sources":["../../src/memory/episodic.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAYvD;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,aAAa,GACnB,OAAO,CAAC,IAAI,CAAC,CA6Cf;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAOxB;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,EAAE,CAAC,CAWnB"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Episodic memory writer — creates/appends to daily event logs.
|
|
3
|
+
*
|
|
4
|
+
* Episodic memory stores timestamped session events in per-day markdown files:
|
|
5
|
+
* `.agentos/memory/episodic/YYYY-MM-DD.md`
|
|
6
|
+
*
|
|
7
|
+
* Each file contains sections for events, decisions, and lessons learned.
|
|
8
|
+
* Appending is idempotent — duplicate event lines are skipped.
|
|
9
|
+
*
|
|
10
|
+
* @module memory/episodic
|
|
11
|
+
*/
|
|
12
|
+
import fs from 'node:fs/promises';
|
|
13
|
+
import path from 'node:path';
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// Constants
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
const EPISODIC_DIR = '.agentos/memory/episodic';
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
// Public API
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
/**
|
|
22
|
+
* Write or append an episodic entry for a given date.
|
|
23
|
+
*
|
|
24
|
+
* If the file for the date already exists, new events/decisions/lessons are
|
|
25
|
+
* appended only if they are not already present (substring dedup).
|
|
26
|
+
*
|
|
27
|
+
* If the file does not exist, it is created with the full entry.
|
|
28
|
+
*
|
|
29
|
+
* @param vaultRoot - Absolute path to the vault root directory
|
|
30
|
+
* @param entry - The episodic entry to persist
|
|
31
|
+
*/
|
|
32
|
+
export async function writeEpisodicEntry(vaultRoot, entry) {
|
|
33
|
+
const dir = path.join(vaultRoot, EPISODIC_DIR);
|
|
34
|
+
await fs.mkdir(dir, { recursive: true });
|
|
35
|
+
const filePath = path.join(dir, `${entry.date}.md`);
|
|
36
|
+
let existing = null;
|
|
37
|
+
try {
|
|
38
|
+
existing = await fs.readFile(filePath, 'utf8');
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
// File doesn't exist — will create fresh
|
|
42
|
+
}
|
|
43
|
+
if (existing === null) {
|
|
44
|
+
// Create new file
|
|
45
|
+
const content = renderEpisodicEntry(entry);
|
|
46
|
+
await fs.writeFile(filePath, content, 'utf8');
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
// Append new items that don't already exist
|
|
50
|
+
const linesToAppend = [];
|
|
51
|
+
for (const event of entry.events) {
|
|
52
|
+
if (!existing.includes(event)) {
|
|
53
|
+
linesToAppend.push(`- ${event}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
for (const decision of entry.decisions) {
|
|
57
|
+
if (!existing.includes(decision)) {
|
|
58
|
+
linesToAppend.push(`- **Decision:** ${decision}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
for (const lesson of entry.lessons) {
|
|
62
|
+
if (!existing.includes(lesson)) {
|
|
63
|
+
linesToAppend.push(`- **Lesson:** ${lesson}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (linesToAppend.length > 0) {
|
|
67
|
+
const separator = existing.endsWith('\n') ? '' : '\n';
|
|
68
|
+
await fs.appendFile(filePath, `${separator}${linesToAppend.join('\n')}\n`, 'utf8');
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Read an episodic entry for a specific date, returning null if it doesn't exist.
|
|
73
|
+
*
|
|
74
|
+
* @param vaultRoot - Absolute path to the vault root directory
|
|
75
|
+
* @param date - Date string in YYYY-MM-DD format
|
|
76
|
+
* @returns The raw markdown content, or null
|
|
77
|
+
*/
|
|
78
|
+
export async function readEpisodicEntry(vaultRoot, date) {
|
|
79
|
+
const filePath = path.join(vaultRoot, EPISODIC_DIR, `${date}.md`);
|
|
80
|
+
try {
|
|
81
|
+
return await fs.readFile(filePath, 'utf8');
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* List all episodic entry dates available in the vault.
|
|
89
|
+
*
|
|
90
|
+
* @param vaultRoot - Absolute path to the vault root directory
|
|
91
|
+
* @returns Sorted array of date strings (YYYY-MM-DD)
|
|
92
|
+
*/
|
|
93
|
+
export async function listEpisodicDates(vaultRoot) {
|
|
94
|
+
const dir = path.join(vaultRoot, EPISODIC_DIR);
|
|
95
|
+
try {
|
|
96
|
+
const files = await fs.readdir(dir);
|
|
97
|
+
return files
|
|
98
|
+
.filter((f) => f.endsWith('.md'))
|
|
99
|
+
.map((f) => f.replace(/\.md$/, ''))
|
|
100
|
+
.sort();
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
return [];
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// ---------------------------------------------------------------------------
|
|
107
|
+
// Internal helpers
|
|
108
|
+
// ---------------------------------------------------------------------------
|
|
109
|
+
/**
|
|
110
|
+
* Render a full episodic entry as markdown.
|
|
111
|
+
*/
|
|
112
|
+
function renderEpisodicEntry(entry) {
|
|
113
|
+
const lines = [];
|
|
114
|
+
lines.push(`# ${entry.date}`);
|
|
115
|
+
lines.push('');
|
|
116
|
+
if (entry.events.length > 0) {
|
|
117
|
+
lines.push('## Events');
|
|
118
|
+
for (const event of entry.events) {
|
|
119
|
+
lines.push(`- ${event}`);
|
|
120
|
+
}
|
|
121
|
+
lines.push('');
|
|
122
|
+
}
|
|
123
|
+
if (entry.decisions.length > 0) {
|
|
124
|
+
lines.push('## Decisions');
|
|
125
|
+
for (const decision of entry.decisions) {
|
|
126
|
+
lines.push(`- ${decision}`);
|
|
127
|
+
}
|
|
128
|
+
lines.push('');
|
|
129
|
+
}
|
|
130
|
+
if (entry.lessons.length > 0) {
|
|
131
|
+
lines.push('## Lessons');
|
|
132
|
+
for (const lesson of entry.lessons) {
|
|
133
|
+
lines.push(`- ${lesson}`);
|
|
134
|
+
}
|
|
135
|
+
lines.push('');
|
|
136
|
+
}
|
|
137
|
+
return lines.join('\n');
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=episodic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"episodic.js","sourceRoot":"","sources":["../../src/memory/episodic.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory module — barrel export.
|
|
3
|
+
*
|
|
4
|
+
* Re-exports the semantic memory parser and confidence scoring engine so
|
|
5
|
+
* consumers can import from a single path:
|
|
6
|
+
*
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { parseSemanticMemory, confirmPattern } from './memory/index.js';
|
|
9
|
+
* ```
|
|
10
|
+
*
|
|
11
|
+
* @module memory
|
|
12
|
+
*/
|
|
13
|
+
export { parseSemanticMemory, serializeSemanticEntry, appendSemanticEntry, } from './parser.js';
|
|
14
|
+
export { confirmPattern, denyPattern, decayPattern, isSuperseded, } from './confidence.js';
|
|
15
|
+
export { writeEpisodicEntry, readEpisodicEntry, listEpisodicDates, } from './episodic.js';
|
|
16
|
+
export { writeProceduralEntry, readProceduralEntry, listProceduralSkills, slugify, } from './procedural.js';
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/memory/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,cAAc,EACd,WAAW,EACX,YAAY,EACZ,YAAY,GACb,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,OAAO,GACR,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory module — barrel export.
|
|
3
|
+
*
|
|
4
|
+
* Re-exports the semantic memory parser and confidence scoring engine so
|
|
5
|
+
* consumers can import from a single path:
|
|
6
|
+
*
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { parseSemanticMemory, confirmPattern } from './memory/index.js';
|
|
9
|
+
* ```
|
|
10
|
+
*
|
|
11
|
+
* @module memory
|
|
12
|
+
*/
|
|
13
|
+
export { parseSemanticMemory, serializeSemanticEntry, appendSemanticEntry, } from './parser.js';
|
|
14
|
+
export { confirmPattern, denyPattern, decayPattern, isSuperseded, } from './confidence.js';
|
|
15
|
+
export { writeEpisodicEntry, readEpisodicEntry, listEpisodicDates, } from './episodic.js';
|
|
16
|
+
export { writeProceduralEntry, readProceduralEntry, listProceduralSkills, slugify, } from './procedural.js';
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/memory/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,cAAc,EACd,WAAW,EACX,YAAY,EACZ,YAAY,GACb,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,OAAO,GACR,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Semantic memory parser — reads and writes `semantic.md` entry lines.
|
|
3
|
+
*
|
|
4
|
+
* Supported line formats (from docs/architecture.md Section 4):
|
|
5
|
+
*
|
|
6
|
+
* PREF: no emoji in headings
|
|
7
|
+
* FACT: [active] primary stack is Kubernetes + ArgoCD
|
|
8
|
+
* FACT: [superseded:2026-04-01] old stack was AWS
|
|
9
|
+
* PATTERN: [confidence:0.85] more productive in the morning
|
|
10
|
+
* AVOID: don't suggest LangChain
|
|
11
|
+
*
|
|
12
|
+
* Rules:
|
|
13
|
+
* - PREF and AVOID carry no bracketed modifier — status defaults to "active".
|
|
14
|
+
* - FACT carries [active] or [superseded:YYYY-MM-DD].
|
|
15
|
+
* - PATTERN carries [confidence:X.XX] — status always "active" unless confidence
|
|
16
|
+
* drops below the superseded threshold (handled by confidence.ts).
|
|
17
|
+
* - Lines that do not match the recognised format are silently ignored.
|
|
18
|
+
* - Duplicate detection in `appendSemanticEntry` is substring-based on `content`.
|
|
19
|
+
*
|
|
20
|
+
* @module memory/parser
|
|
21
|
+
*/
|
|
22
|
+
import type { SemanticEntry } from '../types/index.js';
|
|
23
|
+
/**
|
|
24
|
+
* Parses a `semantic.md` file content string into structured `SemanticEntry`
|
|
25
|
+
* objects.
|
|
26
|
+
*
|
|
27
|
+
* Only lines that match the canonical format are returned; markdown headings,
|
|
28
|
+
* comments, blank lines, and unrecognised lines are discarded.
|
|
29
|
+
*
|
|
30
|
+
* @param content - Raw text content of the file.
|
|
31
|
+
* @returns Array of parsed entries in document order.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```ts
|
|
35
|
+
* const entries = parseSemanticMemory(
|
|
36
|
+
* 'FACT: [active] primary stack is Kubernetes\nAVOID: don\'t use LangChain'
|
|
37
|
+
* );
|
|
38
|
+
* // entries[0] → { type: 'FACT', content: 'primary stack is Kubernetes', status: 'active' }
|
|
39
|
+
* // entries[1] → { type: 'AVOID', content: "don't use LangChain", status: 'active' }
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export declare function parseSemanticMemory(content: string): SemanticEntry[];
|
|
43
|
+
/**
|
|
44
|
+
* Converts a `SemanticEntry` back to its single-line string representation.
|
|
45
|
+
*
|
|
46
|
+
* Output examples:
|
|
47
|
+
* ```
|
|
48
|
+
* PREF: no emoji in headings
|
|
49
|
+
* FACT: [active] primary stack is Kubernetes + ArgoCD
|
|
50
|
+
* FACT: [superseded:2026-04-01] old stack was AWS
|
|
51
|
+
* PATTERN: [confidence:0.85] more productive in the morning
|
|
52
|
+
* AVOID: don't suggest LangChain
|
|
53
|
+
* ```
|
|
54
|
+
*
|
|
55
|
+
* @param entry - The entry to serialise.
|
|
56
|
+
* @returns A single line without a trailing newline.
|
|
57
|
+
*/
|
|
58
|
+
export declare function serializeSemanticEntry(entry: SemanticEntry): string;
|
|
59
|
+
/**
|
|
60
|
+
* Appends a `SemanticEntry` to a `semantic.md` file at `filePath`.
|
|
61
|
+
*
|
|
62
|
+
* Duplicate detection: if any existing entry's `content` is a substring of
|
|
63
|
+
* (or exactly equals) the new entry's `content`, the append is skipped
|
|
64
|
+
* silently. Comparison is case-sensitive and whitespace-sensitive.
|
|
65
|
+
*
|
|
66
|
+
* The file must already exist. If the file does not end with a newline the
|
|
67
|
+
* appended line is still placed on its own line.
|
|
68
|
+
*
|
|
69
|
+
* @param filePath - Absolute path to the target `semantic.md` file.
|
|
70
|
+
* @param entry - Entry to append.
|
|
71
|
+
*/
|
|
72
|
+
export declare function appendSemanticEntry(filePath: string, entry: SemanticEntry): Promise<void>;
|
|
73
|
+
//# sourceMappingURL=parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/memory/parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAkC,MAAM,mBAAmB,CAAC;AAqBvF;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,EAAE,CA+CpE;AAMD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAiBnE;AAMD;;;;;;;;;;;;GAYG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,aAAa,GACnB,OAAO,CAAC,IAAI,CAAC,CAcf"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Semantic memory parser — reads and writes `semantic.md` entry lines.
|
|
3
|
+
*
|
|
4
|
+
* Supported line formats (from docs/architecture.md Section 4):
|
|
5
|
+
*
|
|
6
|
+
* PREF: no emoji in headings
|
|
7
|
+
* FACT: [active] primary stack is Kubernetes + ArgoCD
|
|
8
|
+
* FACT: [superseded:2026-04-01] old stack was AWS
|
|
9
|
+
* PATTERN: [confidence:0.85] more productive in the morning
|
|
10
|
+
* AVOID: don't suggest LangChain
|
|
11
|
+
*
|
|
12
|
+
* Rules:
|
|
13
|
+
* - PREF and AVOID carry no bracketed modifier — status defaults to "active".
|
|
14
|
+
* - FACT carries [active] or [superseded:YYYY-MM-DD].
|
|
15
|
+
* - PATTERN carries [confidence:X.XX] — status always "active" unless confidence
|
|
16
|
+
* drops below the superseded threshold (handled by confidence.ts).
|
|
17
|
+
* - Lines that do not match the recognised format are silently ignored.
|
|
18
|
+
* - Duplicate detection in `appendSemanticEntry` is substring-based on `content`.
|
|
19
|
+
*
|
|
20
|
+
* @module memory/parser
|
|
21
|
+
*/
|
|
22
|
+
import fs from 'node:fs/promises';
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// Internal regex
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
/**
|
|
27
|
+
* Matches any recognised semantic entry line.
|
|
28
|
+
*
|
|
29
|
+
* Capture groups:
|
|
30
|
+
* 1 — entry type (PREF | FACT | PATTERN | AVOID | DIRECTIVE)
|
|
31
|
+
* 2 — optional bracketed modifier, without the brackets
|
|
32
|
+
* 3 — content text (trimmed)
|
|
33
|
+
*/
|
|
34
|
+
const ENTRY_RE = /^(PREF|FACT|PATTERN|AVOID|DIRECTIVE):\s+(?:\[([^\]]+)\]\s+)?(.+)$/;
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
// parseSemanticMemory
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
/**
|
|
39
|
+
* Parses a `semantic.md` file content string into structured `SemanticEntry`
|
|
40
|
+
* objects.
|
|
41
|
+
*
|
|
42
|
+
* Only lines that match the canonical format are returned; markdown headings,
|
|
43
|
+
* comments, blank lines, and unrecognised lines are discarded.
|
|
44
|
+
*
|
|
45
|
+
* @param content - Raw text content of the file.
|
|
46
|
+
* @returns Array of parsed entries in document order.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```ts
|
|
50
|
+
* const entries = parseSemanticMemory(
|
|
51
|
+
* 'FACT: [active] primary stack is Kubernetes\nAVOID: don\'t use LangChain'
|
|
52
|
+
* );
|
|
53
|
+
* // entries[0] → { type: 'FACT', content: 'primary stack is Kubernetes', status: 'active' }
|
|
54
|
+
* // entries[1] → { type: 'AVOID', content: "don't use LangChain", status: 'active' }
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export function parseSemanticMemory(content) {
|
|
58
|
+
const entries = [];
|
|
59
|
+
for (const rawLine of content.split('\n')) {
|
|
60
|
+
const line = rawLine.trim();
|
|
61
|
+
const match = ENTRY_RE.exec(line);
|
|
62
|
+
if (match === null)
|
|
63
|
+
continue;
|
|
64
|
+
const [, rawType, modifier, entryContent] = match;
|
|
65
|
+
const type = rawType;
|
|
66
|
+
const trimmedContent = entryContent.trim();
|
|
67
|
+
// Determine status and confidence from the optional modifier.
|
|
68
|
+
let status = 'active';
|
|
69
|
+
let confidence;
|
|
70
|
+
if (modifier !== undefined) {
|
|
71
|
+
if (modifier === 'active') {
|
|
72
|
+
status = 'active';
|
|
73
|
+
}
|
|
74
|
+
else if (modifier.startsWith('superseded:')) {
|
|
75
|
+
status = modifier;
|
|
76
|
+
}
|
|
77
|
+
else if (modifier.startsWith('confidence:')) {
|
|
78
|
+
const raw = modifier.slice('confidence:'.length);
|
|
79
|
+
const parsed = parseFloat(raw);
|
|
80
|
+
if (!isNaN(parsed)) {
|
|
81
|
+
confidence = parsed;
|
|
82
|
+
}
|
|
83
|
+
// PATTERN entries with confidence tag keep status "active"
|
|
84
|
+
status = 'active';
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const entry = { type, content: trimmedContent, status };
|
|
88
|
+
if (confidence !== undefined) {
|
|
89
|
+
entry.confidence = confidence;
|
|
90
|
+
}
|
|
91
|
+
entries.push(entry);
|
|
92
|
+
}
|
|
93
|
+
return entries;
|
|
94
|
+
}
|
|
95
|
+
// ---------------------------------------------------------------------------
|
|
96
|
+
// serializeSemanticEntry
|
|
97
|
+
// ---------------------------------------------------------------------------
|
|
98
|
+
/**
|
|
99
|
+
* Converts a `SemanticEntry` back to its single-line string representation.
|
|
100
|
+
*
|
|
101
|
+
* Output examples:
|
|
102
|
+
* ```
|
|
103
|
+
* PREF: no emoji in headings
|
|
104
|
+
* FACT: [active] primary stack is Kubernetes + ArgoCD
|
|
105
|
+
* FACT: [superseded:2026-04-01] old stack was AWS
|
|
106
|
+
* PATTERN: [confidence:0.85] more productive in the morning
|
|
107
|
+
* AVOID: don't suggest LangChain
|
|
108
|
+
* ```
|
|
109
|
+
*
|
|
110
|
+
* @param entry - The entry to serialise.
|
|
111
|
+
* @returns A single line without a trailing newline.
|
|
112
|
+
*/
|
|
113
|
+
export function serializeSemanticEntry(entry) {
|
|
114
|
+
const { type, content, status, confidence } = entry;
|
|
115
|
+
// PATTERN entries encode confidence in the modifier slot.
|
|
116
|
+
if (type === 'PATTERN') {
|
|
117
|
+
const score = confidence !== undefined ? confidence : 0.3;
|
|
118
|
+
// Format to two decimal places, matching the canonical format.
|
|
119
|
+
return `PATTERN: [confidence:${score.toFixed(2)}] ${content}`;
|
|
120
|
+
}
|
|
121
|
+
// PREF, AVOID, and DIRECTIVE have no modifier when status is active.
|
|
122
|
+
if (type === 'PREF' || type === 'AVOID' || type === 'DIRECTIVE') {
|
|
123
|
+
return `${type}: ${content}`;
|
|
124
|
+
}
|
|
125
|
+
// FACT always carries an explicit status modifier.
|
|
126
|
+
return `FACT: [${status}] ${content}`;
|
|
127
|
+
}
|
|
128
|
+
// ---------------------------------------------------------------------------
|
|
129
|
+
// appendSemanticEntry
|
|
130
|
+
// ---------------------------------------------------------------------------
|
|
131
|
+
/**
|
|
132
|
+
* Appends a `SemanticEntry` to a `semantic.md` file at `filePath`.
|
|
133
|
+
*
|
|
134
|
+
* Duplicate detection: if any existing entry's `content` is a substring of
|
|
135
|
+
* (or exactly equals) the new entry's `content`, the append is skipped
|
|
136
|
+
* silently. Comparison is case-sensitive and whitespace-sensitive.
|
|
137
|
+
*
|
|
138
|
+
* The file must already exist. If the file does not end with a newline the
|
|
139
|
+
* appended line is still placed on its own line.
|
|
140
|
+
*
|
|
141
|
+
* @param filePath - Absolute path to the target `semantic.md` file.
|
|
142
|
+
* @param entry - Entry to append.
|
|
143
|
+
*/
|
|
144
|
+
export async function appendSemanticEntry(filePath, entry) {
|
|
145
|
+
const raw = await fs.readFile(filePath, 'utf8');
|
|
146
|
+
const existing = parseSemanticMemory(raw);
|
|
147
|
+
// Duplicate check: skip if the incoming content already appears.
|
|
148
|
+
const isDuplicate = existing.some((e) => e.content === entry.content && e.type === entry.type);
|
|
149
|
+
if (isDuplicate)
|
|
150
|
+
return;
|
|
151
|
+
const line = serializeSemanticEntry(entry);
|
|
152
|
+
// Ensure the new line starts on a fresh line.
|
|
153
|
+
const separator = raw.endsWith('\n') || raw.length === 0 ? '' : '\n';
|
|
154
|
+
await fs.appendFile(filePath, `${separator}${line}\n`, 'utf8');
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/memory/parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Procedural memory writer — creates/updates skill files.
|
|
3
|
+
*
|
|
4
|
+
* Procedural memory stores learned workflows as individual markdown files:
|
|
5
|
+
* `.agentos/memory/procedural/{skill-name}.md`
|
|
6
|
+
*
|
|
7
|
+
* Each file documents: description, steps, context, and optional examples.
|
|
8
|
+
* Creates new files or overwrites existing ones (skills are versioned as a
|
|
9
|
+
* whole, not appended line-by-line like episodic memory).
|
|
10
|
+
*
|
|
11
|
+
* @module memory/procedural
|
|
12
|
+
*/
|
|
13
|
+
import type { ProceduralEntry } from '../types/index.js';
|
|
14
|
+
/**
|
|
15
|
+
* Write or overwrite a procedural skill file.
|
|
16
|
+
*
|
|
17
|
+
* The skill name is slugified for the filename (lowercase, hyphens).
|
|
18
|
+
* The full content is always rewritten — procedural skills are atomic.
|
|
19
|
+
*
|
|
20
|
+
* @param vaultRoot - Absolute path to the vault root directory
|
|
21
|
+
* @param entry - The procedural entry to persist
|
|
22
|
+
*/
|
|
23
|
+
export declare function writeProceduralEntry(vaultRoot: string, entry: ProceduralEntry): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Read a procedural entry by skill name, returning null if it doesn't exist.
|
|
26
|
+
*
|
|
27
|
+
* @param vaultRoot - Absolute path to the vault root directory
|
|
28
|
+
* @param name - Skill name (will be slugified)
|
|
29
|
+
* @returns The raw markdown content, or null
|
|
30
|
+
*/
|
|
31
|
+
export declare function readProceduralEntry(vaultRoot: string, name: string): Promise<string | null>;
|
|
32
|
+
/**
|
|
33
|
+
* List all procedural skill names available in the vault.
|
|
34
|
+
*
|
|
35
|
+
* @param vaultRoot - Absolute path to the vault root directory
|
|
36
|
+
* @returns Sorted array of skill names (derived from filenames)
|
|
37
|
+
*/
|
|
38
|
+
export declare function listProceduralSkills(vaultRoot: string): Promise<string[]>;
|
|
39
|
+
/**
|
|
40
|
+
* Slugify a skill name: lowercase, spaces → hyphens, strip non-alnum.
|
|
41
|
+
*/
|
|
42
|
+
export declare function slugify(name: string): string;
|
|
43
|
+
//# sourceMappingURL=procedural.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"procedural.d.ts","sourceRoot":"","sources":["../../src/memory/procedural.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAYzD;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,eAAe,GACrB,OAAO,CAAC,IAAI,CAAC,CASf;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAQxB;AAED;;;;;GAKG;AACH,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,EAAE,CAAC,CAWnB;AAMD;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAM5C"}
|