@duetso/agent 0.2.5 → 0.3.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 +15 -12
- package/dist/package.json +8 -3
- package/dist/src/cli/help.d.ts.map +1 -1
- package/dist/src/cli/help.js +41 -27
- package/dist/src/cli/help.js.map +1 -1
- package/dist/src/cli/memory-add.d.ts +18 -13
- package/dist/src/cli/memory-add.d.ts.map +1 -1
- package/dist/src/cli/memory-add.js +91 -32
- package/dist/src/cli/memory-add.js.map +1 -1
- package/dist/src/cli/memory-recall.d.ts.map +1 -1
- package/dist/src/cli/memory-recall.js +3 -0
- package/dist/src/cli/memory-recall.js.map +1 -1
- package/dist/src/cli/memory-sources.d.ts +20 -0
- package/dist/src/cli/memory-sources.d.ts.map +1 -0
- package/dist/src/cli/memory-sources.js +40 -0
- package/dist/src/cli/memory-sources.js.map +1 -0
- package/dist/src/cli/route.d.ts +2 -0
- package/dist/src/cli/route.d.ts.map +1 -1
- package/dist/src/cli/route.js +8 -8
- package/dist/src/cli/route.js.map +1 -1
- package/dist/src/cli/rpc.d.ts +3 -2
- package/dist/src/cli/rpc.d.ts.map +1 -1
- package/dist/src/cli/rpc.js +3 -2
- package/dist/src/cli/rpc.js.map +1 -1
- package/dist/src/cli/run.d.ts +1 -0
- package/dist/src/cli/run.d.ts.map +1 -1
- package/dist/src/cli/run.js +1 -0
- package/dist/src/cli/run.js.map +1 -1
- package/dist/src/cli/train.d.ts +31 -7
- package/dist/src/cli/train.d.ts.map +1 -1
- package/dist/src/cli/train.js +233 -79
- package/dist/src/cli/train.js.map +1 -1
- package/dist/src/memory/context-pack.d.ts +5 -0
- package/dist/src/memory/context-pack.d.ts.map +1 -1
- package/dist/src/memory/context-pack.js +6 -0
- package/dist/src/memory/context-pack.js.map +1 -1
- package/dist/src/memory/id.d.ts +3 -0
- package/dist/src/memory/id.d.ts.map +1 -0
- package/dist/src/memory/id.js +6 -0
- package/dist/src/memory/id.js.map +1 -0
- package/dist/src/memory/observational-prompts.d.ts +2 -0
- package/dist/src/memory/observational-prompts.d.ts.map +1 -1
- package/dist/src/memory/observational-prompts.js +4 -2
- package/dist/src/memory/observational-prompts.js.map +1 -1
- package/dist/src/memory/observational.d.ts +22 -0
- package/dist/src/memory/observational.d.ts.map +1 -1
- package/dist/src/memory/observational.js +65 -22
- package/dist/src/memory/observational.js.map +1 -1
- package/dist/src/memory/paths.d.ts +9 -0
- package/dist/src/memory/paths.d.ts.map +1 -0
- package/dist/src/memory/paths.js +11 -0
- package/dist/src/memory/paths.js.map +1 -0
- package/dist/src/memory/storage.d.ts.map +1 -1
- package/dist/src/memory/storage.js +1 -4
- package/dist/src/memory/storage.js.map +1 -1
- package/dist/src/memory/store/discovery.d.ts +7 -0
- package/dist/src/memory/store/discovery.d.ts.map +1 -0
- package/dist/src/memory/store/discovery.js +34 -0
- package/dist/src/memory/store/discovery.js.map +1 -0
- package/dist/src/memory/store/file.d.ts +52 -0
- package/dist/src/memory/store/file.d.ts.map +1 -0
- package/dist/src/memory/store/file.js +287 -0
- package/dist/src/memory/store/file.js.map +1 -0
- package/dist/src/memory/store/index.d.ts +5 -0
- package/dist/src/memory/store/index.d.ts.map +1 -0
- package/dist/src/memory/store/index.js +5 -0
- package/dist/src/memory/store/index.js.map +1 -0
- package/dist/src/memory/store/pack.d.ts +25 -0
- package/dist/src/memory/store/pack.d.ts.map +1 -0
- package/dist/src/memory/store/pack.js +71 -0
- package/dist/src/memory/store/pack.js.map +1 -0
- package/dist/src/memory/store/sources.d.ts +55 -0
- package/dist/src/memory/store/sources.d.ts.map +1 -0
- package/dist/src/memory/store/sources.js +85 -0
- package/dist/src/memory/store/sources.js.map +1 -0
- package/dist/src/memory/store/store.d.ts +46 -0
- package/dist/src/memory/store/store.d.ts.map +1 -0
- package/dist/src/memory/store/store.js +171 -0
- package/dist/src/memory/store/store.js.map +1 -0
- package/dist/src/memory/store.d.ts +19 -16
- package/dist/src/memory/store.d.ts.map +1 -1
- package/dist/src/memory/store.js +14 -11
- package/dist/src/memory/store.js.map +1 -1
- package/dist/src/memory-store.js +554 -0
- package/dist/src/model-routing/advisor-context.d.ts +31 -5
- package/dist/src/model-routing/advisor-context.d.ts.map +1 -1
- package/dist/src/model-routing/advisor-context.js +87 -10
- package/dist/src/model-routing/advisor-context.js.map +1 -1
- package/dist/src/model-routing/advisor-lifecycle.d.ts +14 -5
- package/dist/src/model-routing/advisor-lifecycle.d.ts.map +1 -1
- package/dist/src/model-routing/advisor-lifecycle.js +24 -7
- package/dist/src/model-routing/advisor-lifecycle.js.map +1 -1
- package/dist/src/model-routing/prompts.d.ts.map +1 -1
- package/dist/src/model-routing/prompts.js +18 -10
- package/dist/src/model-routing/prompts.js.map +1 -1
- package/dist/src/session/session-manager.d.ts +1 -4
- package/dist/src/session/session-manager.d.ts.map +1 -1
- package/dist/src/session/session-manager.js +2 -5
- package/dist/src/session/session-manager.js.map +1 -1
- package/dist/src/session/session.d.ts +2 -2
- package/dist/src/session/session.js +2 -2
- package/dist/src/train/archive.d.ts.map +1 -1
- package/dist/src/train/archive.js +5 -0
- package/dist/src/train/archive.js.map +1 -1
- package/dist/src/train/types.d.ts +8 -7
- package/dist/src/train/types.d.ts.map +1 -1
- package/dist/src/turn-runner/tools.d.ts +3 -3
- package/dist/src/turn-runner/tools.d.ts.map +1 -1
- package/dist/src/turn-runner/tools.js +1 -1
- package/dist/src/turn-runner/tools.js.map +1 -1
- package/dist/src/turn-runner/turn-runner.d.ts +15 -2
- package/dist/src/turn-runner/turn-runner.d.ts.map +1 -1
- package/dist/src/turn-runner/turn-runner.js +102 -15
- package/dist/src/turn-runner/turn-runner.js.map +1 -1
- package/dist/src/turn-runner/wire-shaping.d.ts +3 -1
- package/dist/src/turn-runner/wire-shaping.d.ts.map +1 -1
- package/dist/src/turn-runner/wire-shaping.js +5 -1
- package/dist/src/turn-runner/wire-shaping.js.map +1 -1
- package/dist/src/types/config.d.ts +7 -0
- package/dist/src/types/config.d.ts.map +1 -1
- package/dist/src/types/protocol.d.ts +2 -2
- package/package.json +8 -3
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { lstat } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { walkAncestors } from "../../lib/walk-ancestors.js";
|
|
4
|
+
const MEMORY_ROOT_NAMES = [".duet", ".agents", ".claude"];
|
|
5
|
+
/**
|
|
6
|
+
* Find real memory-store directories from cwd toward the filesystem root.
|
|
7
|
+
* Nearest ancestors win naturally because callers consume this order first;
|
|
8
|
+
* `$HOME` remains excluded by the shared project-scope ancestor walk.
|
|
9
|
+
*/
|
|
10
|
+
export async function discoverMemoryStores(cwd) {
|
|
11
|
+
const stores = [];
|
|
12
|
+
for (const ancestor of walkAncestors(cwd)) {
|
|
13
|
+
for (const rootName of MEMORY_ROOT_NAMES) {
|
|
14
|
+
const storeDir = join(ancestor, rootName, "memories");
|
|
15
|
+
const status = await lstat(storeDir).catch((error) => {
|
|
16
|
+
if (isNodeError(error, "ENOENT") || isNodeError(error, "ENOTDIR"))
|
|
17
|
+
return undefined;
|
|
18
|
+
throw error;
|
|
19
|
+
});
|
|
20
|
+
if (!status)
|
|
21
|
+
continue;
|
|
22
|
+
if (status.isSymbolicLink())
|
|
23
|
+
throw new Error(`Memory stores cannot be symlinks: ${storeDir}`);
|
|
24
|
+
if (!status.isDirectory())
|
|
25
|
+
throw new Error(`Memory store is not a directory: ${storeDir}`);
|
|
26
|
+
stores.push(storeDir);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return stores;
|
|
30
|
+
}
|
|
31
|
+
function isNodeError(error, code) {
|
|
32
|
+
return error instanceof Error && "code" in error && error.code === code;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../../../src/memory/store/discovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAE5D,MAAM,iBAAiB,GAAG,CAAC,OAAO,EAAE,SAAS,EAAE,SAAS,CAAU,CAAC;AAEnE;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,GAAW;IACpD,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,MAAM,QAAQ,IAAI,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1C,KAAK,MAAM,QAAQ,IAAI,iBAAiB,EAAE,CAAC;YACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;YACtD,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;gBAC5D,IAAI,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,WAAW,CAAC,KAAK,EAAE,SAAS,CAAC;oBAAE,OAAO,SAAS,CAAC;gBACpF,MAAM,KAAK,CAAC;YACd,CAAC,CAAC,CAAC;YACH,IAAI,CAAC,MAAM;gBAAE,SAAS;YACtB,IAAI,MAAM,CAAC,cAAc,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,QAAQ,EAAE,CAAC,CAAC;YAC9F,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,QAAQ,EAAE,CAAC,CAAC;YAC3F,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,WAAW,CAAC,KAAc,EAAE,IAAY;IAC/C,OAAO,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC;AAC1E,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/** The established Train API ceiling, applied to UTF-8 body bytes. */
|
|
2
|
+
export declare const MAX_TRAIN_RECORD_CONTENT_BYTES: number;
|
|
3
|
+
/** A memory file's role: synthesized training or a directly curated note. */
|
|
4
|
+
export type MemoryKind = "train" | "note";
|
|
5
|
+
/** Scalar values retained for forward-compatible, unknown frontmatter keys. */
|
|
6
|
+
export type MemoryFrontmatterValue = string | number | string[];
|
|
7
|
+
/** The typed contents of one markdown memory file, excluding its filename-owned slug. */
|
|
8
|
+
export interface MemoryFileRecord {
|
|
9
|
+
/** Byte-format version. Version 1 is the only format currently understood. */
|
|
10
|
+
version: 1;
|
|
11
|
+
/** Stable record identity shared with APIs and private archive metadata. */
|
|
12
|
+
id: string;
|
|
13
|
+
/** Whether the content came from training synthesis or direct note curation. */
|
|
14
|
+
kind: MemoryKind;
|
|
15
|
+
/** Unix epoch milliseconds used to derive observed dates and newest-first ordering. */
|
|
16
|
+
createdAt: number;
|
|
17
|
+
/** Short display label for the curated content. */
|
|
18
|
+
headline?: string;
|
|
19
|
+
/** Model identifier that produced synthesized content, when applicable. */
|
|
20
|
+
model?: string;
|
|
21
|
+
/** Number of source files represented by synthesized content. */
|
|
22
|
+
fileCount?: number;
|
|
23
|
+
/** Private archive manifest identifier; never an absolute archive path. */
|
|
24
|
+
archiveId?: string;
|
|
25
|
+
/** Ranking hint consumed by memory-context selection. */
|
|
26
|
+
priority?: string;
|
|
27
|
+
/** Origin label used when projecting a file into observational-memory shapes. */
|
|
28
|
+
source?: string;
|
|
29
|
+
/** Search and provenance labels attached to the record. */
|
|
30
|
+
tags?: string[];
|
|
31
|
+
/**
|
|
32
|
+
* Unknown scalar keys retained byte-stably so a newer writer can add metadata
|
|
33
|
+
* without an older reader silently deleting it on a content-only update.
|
|
34
|
+
*/
|
|
35
|
+
extra?: Record<string, MemoryFrontmatterValue>;
|
|
36
|
+
/** Exact curated markdown after the closing frontmatter delimiter. */
|
|
37
|
+
content: string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Parse the canonical YAML-compatible subset used by memory files.
|
|
41
|
+
*
|
|
42
|
+
* Values are canonical JSON strings, finite decimal numbers, or inline
|
|
43
|
+
* arrays of canonical JSON strings. Known keys stay in the order emitted by
|
|
44
|
+
* {@link serializeMemoryFile}; unknown keys may follow them and use the same
|
|
45
|
+
* scalar grammar.
|
|
46
|
+
*/
|
|
47
|
+
export declare function parseMemoryFile(text: string): MemoryFileRecord;
|
|
48
|
+
/** Serialize a memory record into the one canonical byte representation. */
|
|
49
|
+
export declare function serializeMemoryFile(record: MemoryFileRecord): string;
|
|
50
|
+
/** Return the safe slug owned by a bare `<slug>.md` filename. */
|
|
51
|
+
export declare function slugFromFilename(name: string): string;
|
|
52
|
+
//# sourceMappingURL=file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../../../src/memory/store/file.ts"],"names":[],"mappings":"AAGA,sEAAsE;AACtE,eAAO,MAAM,8BAA8B,QAAmB,CAAC;AAE/D,6EAA6E;AAC7E,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,MAAM,CAAC;AAE1C,+EAA+E;AAC/E,MAAM,MAAM,sBAAsB,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,CAAC;AAEhE,yFAAyF;AACzF,MAAM,WAAW,gBAAgB;IAC/B,8EAA8E;IAC9E,OAAO,EAAE,CAAC,CAAC;IACX,4EAA4E;IAC5E,EAAE,EAAE,MAAM,CAAC;IACX,gFAAgF;IAChF,IAAI,EAAE,UAAU,CAAC;IACjB,uFAAuF;IACvF,SAAS,EAAE,MAAM,CAAC;IAClB,mDAAmD;IACnD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iFAAiF;IACjF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2DAA2D;IAC3D,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC;IAC/C,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;CACjB;AA2BD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAyE9D;AAED,4EAA4E;AAC5E,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAyBpE;AAED,iEAAiE;AACjE,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAOrD"}
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import { Buffer } from "node:buffer";
|
|
2
|
+
import { basename } from "node:path";
|
|
3
|
+
/** The established Train API ceiling, applied to UTF-8 body bytes. */
|
|
4
|
+
export const MAX_TRAIN_RECORD_CONTENT_BYTES = 10 * 1024 * 1024;
|
|
5
|
+
const SLUG_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
6
|
+
// Identifiers become path segments under the private archive root, so they
|
|
7
|
+
// must never be able to traverse (`..`, separators) out of it. nanoid's
|
|
8
|
+
// alphabet plus the `mem_` prefix always satisfies this.
|
|
9
|
+
const ID_SEGMENT_PATTERN = /^[A-Za-z0-9_-]+$/;
|
|
10
|
+
const KEY_PATTERN = /^[A-Za-z][A-Za-z0-9]*$/;
|
|
11
|
+
const NUMBER_PATTERN = /^-?(?:0|[1-9]\d*)(?:\.\d+)?$/;
|
|
12
|
+
const KNOWN_KEYS = [
|
|
13
|
+
"version",
|
|
14
|
+
"id",
|
|
15
|
+
"kind",
|
|
16
|
+
"createdAt",
|
|
17
|
+
"headline",
|
|
18
|
+
"model",
|
|
19
|
+
"fileCount",
|
|
20
|
+
"archiveId",
|
|
21
|
+
"priority",
|
|
22
|
+
"source",
|
|
23
|
+
"tags",
|
|
24
|
+
];
|
|
25
|
+
const KNOWN_KEY_ORDER = new Map(KNOWN_KEYS.map((key, index) => [key, index]));
|
|
26
|
+
// Line endings are byte-format state, not record metadata. Keeping them on the
|
|
27
|
+
// parsed object preserves CRLF without exposing a formatting field to callers.
|
|
28
|
+
const parsedLineEndings = new WeakMap();
|
|
29
|
+
/**
|
|
30
|
+
* Parse the canonical YAML-compatible subset used by memory files.
|
|
31
|
+
*
|
|
32
|
+
* Values are canonical JSON strings, finite decimal numbers, or inline
|
|
33
|
+
* arrays of canonical JSON strings. Known keys stay in the order emitted by
|
|
34
|
+
* {@link serializeMemoryFile}; unknown keys may follow them and use the same
|
|
35
|
+
* scalar grammar.
|
|
36
|
+
*/
|
|
37
|
+
export function parseMemoryFile(text) {
|
|
38
|
+
const lineEnding = text.startsWith("---\r\n")
|
|
39
|
+
? "\r\n"
|
|
40
|
+
: text.startsWith("---\n")
|
|
41
|
+
? "\n"
|
|
42
|
+
: undefined;
|
|
43
|
+
if (!lineEnding)
|
|
44
|
+
throw new Error("Memory file must start with a frontmatter delimiter");
|
|
45
|
+
const closingDelimiter = `${lineEnding}---${lineEnding}`;
|
|
46
|
+
const closingIndex = text.indexOf(closingDelimiter, 3 + lineEnding.length);
|
|
47
|
+
if (closingIndex === -1)
|
|
48
|
+
throw new Error("Memory file is missing its closing delimiter");
|
|
49
|
+
const header = text.slice(3 + lineEnding.length, closingIndex);
|
|
50
|
+
const content = text.slice(closingIndex + closingDelimiter.length);
|
|
51
|
+
assertContent(content);
|
|
52
|
+
const values = new Map();
|
|
53
|
+
let lastKnownIndex = -1;
|
|
54
|
+
let sawUnknown = false;
|
|
55
|
+
for (const line of header.split(lineEnding)) {
|
|
56
|
+
const separator = line.indexOf(": ");
|
|
57
|
+
if (separator <= 0)
|
|
58
|
+
throw new Error(`Invalid frontmatter line: ${line}`);
|
|
59
|
+
const key = line.slice(0, separator);
|
|
60
|
+
const rawValue = line.slice(separator + 2);
|
|
61
|
+
if (!KEY_PATTERN.test(key))
|
|
62
|
+
throw new Error(`Invalid frontmatter key: ${key}`);
|
|
63
|
+
if (values.has(key))
|
|
64
|
+
throw new Error(`Duplicate frontmatter key: ${key}`);
|
|
65
|
+
if (key === "sourceFolder") {
|
|
66
|
+
throw new Error("sourceFolder is private archive metadata and cannot enter a memory file");
|
|
67
|
+
}
|
|
68
|
+
const knownIndex = KNOWN_KEY_ORDER.get(key);
|
|
69
|
+
if (knownIndex === undefined) {
|
|
70
|
+
sawUnknown = true;
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
if (sawUnknown || knownIndex <= lastKnownIndex) {
|
|
74
|
+
throw new Error(`Frontmatter key is out of canonical order: ${key}`);
|
|
75
|
+
}
|
|
76
|
+
lastKnownIndex = knownIndex;
|
|
77
|
+
}
|
|
78
|
+
values.set(key, parseScalar(rawValue));
|
|
79
|
+
}
|
|
80
|
+
const version = requireNumber(values, "version");
|
|
81
|
+
if (version !== 1)
|
|
82
|
+
throw new Error(`Unsupported memory file version: ${version}`);
|
|
83
|
+
const kind = requireString(values, "kind");
|
|
84
|
+
if (kind !== "train" && kind !== "note")
|
|
85
|
+
throw new Error(`Invalid memory kind: ${kind}`);
|
|
86
|
+
const createdAt = requireNumber(values, "createdAt");
|
|
87
|
+
if (!Number.isSafeInteger(createdAt) || createdAt < 0) {
|
|
88
|
+
throw new Error("createdAt must be a non-negative integer");
|
|
89
|
+
}
|
|
90
|
+
const fileCount = optionalNumber(values, "fileCount");
|
|
91
|
+
if (fileCount !== undefined && (!Number.isSafeInteger(fileCount) || fileCount < 0)) {
|
|
92
|
+
throw new Error("fileCount must be a non-negative integer");
|
|
93
|
+
}
|
|
94
|
+
const record = {
|
|
95
|
+
version: 1,
|
|
96
|
+
id: requireIdSegment(values, "id"),
|
|
97
|
+
kind,
|
|
98
|
+
createdAt,
|
|
99
|
+
...optionalStringProperty(values, "headline"),
|
|
100
|
+
...optionalStringProperty(values, "model"),
|
|
101
|
+
...(fileCount === undefined ? {} : { fileCount }),
|
|
102
|
+
...optionalIdSegmentProperty(values, "archiveId"),
|
|
103
|
+
...optionalStringProperty(values, "priority"),
|
|
104
|
+
...optionalStringProperty(values, "source"),
|
|
105
|
+
...optionalStringArrayProperty(values, "tags"),
|
|
106
|
+
...extraProperties(values),
|
|
107
|
+
content,
|
|
108
|
+
};
|
|
109
|
+
parsedLineEndings.set(record, lineEnding);
|
|
110
|
+
return record;
|
|
111
|
+
}
|
|
112
|
+
/** Serialize a memory record into the one canonical byte representation. */
|
|
113
|
+
export function serializeMemoryFile(record) {
|
|
114
|
+
validateRecord(record);
|
|
115
|
+
const lineEnding = parsedLineEndings.get(record) ?? "\n";
|
|
116
|
+
const fields = [
|
|
117
|
+
["version", record.version],
|
|
118
|
+
["id", record.id],
|
|
119
|
+
["kind", record.kind],
|
|
120
|
+
["createdAt", record.createdAt],
|
|
121
|
+
];
|
|
122
|
+
appendOptional(fields, "headline", record.headline);
|
|
123
|
+
appendOptional(fields, "model", record.model);
|
|
124
|
+
appendOptional(fields, "fileCount", record.fileCount);
|
|
125
|
+
appendOptional(fields, "archiveId", record.archiveId);
|
|
126
|
+
appendOptional(fields, "priority", record.priority);
|
|
127
|
+
appendOptional(fields, "source", record.source);
|
|
128
|
+
appendOptional(fields, "tags", record.tags);
|
|
129
|
+
for (const [key, value] of Object.entries(record.extra ?? {})) {
|
|
130
|
+
if (!KEY_PATTERN.test(key) || KNOWN_KEY_ORDER.has(key) || key === "sourceFolder") {
|
|
131
|
+
throw new Error(`Invalid extra frontmatter key: ${key}`);
|
|
132
|
+
}
|
|
133
|
+
fields.push([key, value]);
|
|
134
|
+
}
|
|
135
|
+
const header = fields.map(([key, value]) => `${key}: ${serializeScalar(value)}`).join(lineEnding);
|
|
136
|
+
return `---${lineEnding}${header}${lineEnding}---${lineEnding}${record.content}`;
|
|
137
|
+
}
|
|
138
|
+
/** Return the safe slug owned by a bare `<slug>.md` filename. */
|
|
139
|
+
export function slugFromFilename(name) {
|
|
140
|
+
if (basename(name) !== name || !name.endsWith(".md")) {
|
|
141
|
+
throw new Error(`Memory filename must be a bare .md filename: ${name}`);
|
|
142
|
+
}
|
|
143
|
+
const slug = name.slice(0, -3);
|
|
144
|
+
if (!SLUG_PATTERN.test(slug))
|
|
145
|
+
throw new Error(`Unsafe memory slug: ${slug}`);
|
|
146
|
+
return slug;
|
|
147
|
+
}
|
|
148
|
+
function parseScalar(rawValue) {
|
|
149
|
+
if (NUMBER_PATTERN.test(rawValue)) {
|
|
150
|
+
const value = Number(rawValue);
|
|
151
|
+
if (Number.isFinite(value) && String(value) === rawValue)
|
|
152
|
+
return value;
|
|
153
|
+
}
|
|
154
|
+
try {
|
|
155
|
+
const value = JSON.parse(rawValue);
|
|
156
|
+
if (typeof value === "string" && JSON.stringify(value) === rawValue)
|
|
157
|
+
return value;
|
|
158
|
+
if (Array.isArray(value) &&
|
|
159
|
+
value.every((item) => typeof item === "string") &&
|
|
160
|
+
`[${value.map((item) => JSON.stringify(item)).join(", ")}]` === rawValue) {
|
|
161
|
+
return value;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
// The grammar error below is more useful than JSON's parser diagnostic.
|
|
166
|
+
}
|
|
167
|
+
throw new Error(`Unsupported frontmatter scalar: ${rawValue}`);
|
|
168
|
+
}
|
|
169
|
+
function serializeScalar(value) {
|
|
170
|
+
if (typeof value === "number") {
|
|
171
|
+
if (!Number.isFinite(value) || /[eE]/.test(String(value))) {
|
|
172
|
+
throw new Error(`Frontmatter numbers must be finite decimals: ${value}`);
|
|
173
|
+
}
|
|
174
|
+
return String(value);
|
|
175
|
+
}
|
|
176
|
+
if (typeof value === "string")
|
|
177
|
+
return JSON.stringify(value);
|
|
178
|
+
if (Array.isArray(value) && value.every((item) => typeof item === "string")) {
|
|
179
|
+
return `[${value.map((item) => JSON.stringify(item)).join(", ")}]`;
|
|
180
|
+
}
|
|
181
|
+
throw new Error("Frontmatter values must be strings, numbers, or string arrays");
|
|
182
|
+
}
|
|
183
|
+
function requireNumber(values, key) {
|
|
184
|
+
const value = values.get(key);
|
|
185
|
+
if (typeof value !== "number")
|
|
186
|
+
throw new Error(`Frontmatter ${key} must be a number`);
|
|
187
|
+
return value;
|
|
188
|
+
}
|
|
189
|
+
function optionalNumber(values, key) {
|
|
190
|
+
const value = values.get(key);
|
|
191
|
+
if (value === undefined)
|
|
192
|
+
return undefined;
|
|
193
|
+
if (typeof value !== "number")
|
|
194
|
+
throw new Error(`Frontmatter ${key} must be a number`);
|
|
195
|
+
return value;
|
|
196
|
+
}
|
|
197
|
+
function requireString(values, key) {
|
|
198
|
+
const value = values.get(key);
|
|
199
|
+
if (typeof value !== "string")
|
|
200
|
+
throw new Error(`Frontmatter ${key} must be a string`);
|
|
201
|
+
return value;
|
|
202
|
+
}
|
|
203
|
+
function requireNonBlankString(values, key) {
|
|
204
|
+
const value = requireString(values, key);
|
|
205
|
+
if (value.trim().length === 0)
|
|
206
|
+
throw new Error(`Frontmatter ${key} cannot be blank`);
|
|
207
|
+
return value;
|
|
208
|
+
}
|
|
209
|
+
function requireIdSegment(values, key) {
|
|
210
|
+
return assertIdSegment(key, requireNonBlankString(values, key));
|
|
211
|
+
}
|
|
212
|
+
function optionalIdSegmentProperty(values, key) {
|
|
213
|
+
if (!values.has(key))
|
|
214
|
+
return {};
|
|
215
|
+
return { [key]: requireIdSegment(values, key) };
|
|
216
|
+
}
|
|
217
|
+
function assertIdSegment(key, value) {
|
|
218
|
+
if (!ID_SEGMENT_PATTERN.test(value)) {
|
|
219
|
+
throw new Error(`Frontmatter ${key} must be a safe path segment: ${value}`);
|
|
220
|
+
}
|
|
221
|
+
return value;
|
|
222
|
+
}
|
|
223
|
+
function optionalStringProperty(values, key) {
|
|
224
|
+
if (!values.has(key))
|
|
225
|
+
return {};
|
|
226
|
+
return { [key]: requireNonBlankString(values, key) };
|
|
227
|
+
}
|
|
228
|
+
function optionalStringArrayProperty(values, key) {
|
|
229
|
+
const value = values.get(key);
|
|
230
|
+
if (value === undefined)
|
|
231
|
+
return {};
|
|
232
|
+
if (!Array.isArray(value) || value.some((item) => item.trim().length === 0)) {
|
|
233
|
+
throw new Error(`Frontmatter ${key} must be a string array without blank items`);
|
|
234
|
+
}
|
|
235
|
+
return { tags: value };
|
|
236
|
+
}
|
|
237
|
+
function extraProperties(values) {
|
|
238
|
+
const extra = Object.fromEntries(Array.from(values).filter(([key]) => !KNOWN_KEY_ORDER.has(key)));
|
|
239
|
+
return Object.keys(extra).length === 0 ? {} : { extra };
|
|
240
|
+
}
|
|
241
|
+
function appendOptional(fields, key, value) {
|
|
242
|
+
if (value !== undefined)
|
|
243
|
+
fields.push([key, value]);
|
|
244
|
+
}
|
|
245
|
+
function validateRecord(record) {
|
|
246
|
+
if (record.version !== 1)
|
|
247
|
+
throw new Error(`Unsupported memory file version: ${record.version}`);
|
|
248
|
+
if (record.id.trim().length === 0)
|
|
249
|
+
throw new Error("Frontmatter id cannot be blank");
|
|
250
|
+
assertIdSegment("id", record.id);
|
|
251
|
+
if (record.archiveId !== undefined)
|
|
252
|
+
assertIdSegment("archiveId", record.archiveId);
|
|
253
|
+
if (record.kind !== "train" && record.kind !== "note") {
|
|
254
|
+
throw new Error(`Invalid memory kind: ${String(record.kind)}`);
|
|
255
|
+
}
|
|
256
|
+
if (!Number.isSafeInteger(record.createdAt) || record.createdAt < 0) {
|
|
257
|
+
throw new Error("createdAt must be a non-negative integer");
|
|
258
|
+
}
|
|
259
|
+
if (record.fileCount !== undefined &&
|
|
260
|
+
(!Number.isSafeInteger(record.fileCount) || record.fileCount < 0)) {
|
|
261
|
+
throw new Error("fileCount must be a non-negative integer");
|
|
262
|
+
}
|
|
263
|
+
for (const [key, value] of Object.entries({
|
|
264
|
+
headline: record.headline,
|
|
265
|
+
model: record.model,
|
|
266
|
+
archiveId: record.archiveId,
|
|
267
|
+
priority: record.priority,
|
|
268
|
+
source: record.source,
|
|
269
|
+
})) {
|
|
270
|
+
if (value !== undefined && value.trim().length === 0) {
|
|
271
|
+
throw new Error(`Frontmatter ${key} cannot be blank`);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
if (record.tags?.some((tag) => tag.trim().length === 0)) {
|
|
275
|
+
throw new Error("Frontmatter tags cannot contain blank items");
|
|
276
|
+
}
|
|
277
|
+
assertContent(record.content);
|
|
278
|
+
}
|
|
279
|
+
function assertContent(content) {
|
|
280
|
+
if (content.trim().length === 0)
|
|
281
|
+
throw new Error("Memory content cannot be blank");
|
|
282
|
+
const bytes = Buffer.byteLength(content, "utf8");
|
|
283
|
+
if (bytes > MAX_TRAIN_RECORD_CONTENT_BYTES) {
|
|
284
|
+
throw new Error(`Memory content exceeds ${MAX_TRAIN_RECORD_CONTENT_BYTES} UTF-8 bytes`);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
//# sourceMappingURL=file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file.js","sourceRoot":"","sources":["../../../../src/memory/store/file.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { MAX_TRAIN_RECORD_CONTENT_BYTES, parseMemoryFile, serializeMemoryFile, slugFromFilename, type MemoryFileRecord, type MemoryFrontmatterValue, type MemoryKind, } from "./file.js";
|
|
2
|
+
export { discoverMemoryStores } from "./discovery.js";
|
|
3
|
+
export { mergeListings, resolveSources, type MemorySourceFlags, type MemorySources, type MemoryWriteTarget, type SourceListing, } from "./sources.js";
|
|
4
|
+
export { deleteEntry, listStore, readEntry, updateEntry, writeEntry, type MemoryEntryInput, type StoredMemory, } from "./store.js";
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/memory/store/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,8BAA8B,EAC9B,eAAe,EACf,mBAAmB,EACnB,gBAAgB,EAChB,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,UAAU,GAChB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EACL,aAAa,EACb,cAAc,EACd,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,aAAa,GACnB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,WAAW,EACX,SAAS,EACT,SAAS,EACT,WAAW,EACX,UAAU,EACV,KAAK,gBAAgB,EACrB,KAAK,YAAY,GAClB,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { MAX_TRAIN_RECORD_CONTENT_BYTES, parseMemoryFile, serializeMemoryFile, slugFromFilename, } from "./file.js";
|
|
2
|
+
export { discoverMemoryStores } from "./discovery.js";
|
|
3
|
+
export { mergeListings, resolveSources, } from "./sources.js";
|
|
4
|
+
export { deleteEntry, listStore, readEntry, updateEntry, writeEntry, } from "./store.js";
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/memory/store/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,8BAA8B,EAC9B,eAAe,EACf,mBAAmB,EACnB,gBAAgB,GAIjB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EACL,aAAa,EACb,cAAc,GAKf,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,WAAW,EACX,SAAS,EACT,SAAS,EACT,WAAW,EACX,UAAU,GAGX,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type StoredMemory } from "./store.js";
|
|
2
|
+
/** Standalone ceiling for curated file memory pinned into an agent prompt. */
|
|
3
|
+
export declare const PINNED_STORE_TOKEN_BUDGET = 15000;
|
|
4
|
+
export interface LoadPinnedStorePackOptions {
|
|
5
|
+
/** Store directories in collision precedence order, nearest first. */
|
|
6
|
+
stores: readonly string[];
|
|
7
|
+
/** Independent ceiling for file-backed content; defaults to 15,000 tokens. */
|
|
8
|
+
tokenBudget?: number;
|
|
9
|
+
}
|
|
10
|
+
export interface PinnedStorePack {
|
|
11
|
+
/** Newest-first entries retained after collision resolution and budget fitting. */
|
|
12
|
+
entries: StoredMemory[];
|
|
13
|
+
/** Number of complete older entries removed to satisfy the cap. */
|
|
14
|
+
dropped: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Load a frozen, newest-first view of curated file memories.
|
|
18
|
+
*
|
|
19
|
+
* Malformed entries are isolated to their own file and warned about instead
|
|
20
|
+
* of making agent startup fail. When the complete set exceeds the independent
|
|
21
|
+
* cap, whole entries leave oldest-first; the newest entry is retained and
|
|
22
|
+
* deterministically tail-truncated when it alone is too large.
|
|
23
|
+
*/
|
|
24
|
+
export declare function loadPinnedStorePack(options: LoadPinnedStorePackOptions): Promise<PinnedStorePack>;
|
|
25
|
+
//# sourceMappingURL=pack.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pack.d.ts","sourceRoot":"","sources":["../../../../src/memory/store/pack.ts"],"names":[],"mappings":"AAEA,OAAO,EAAqB,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAElE,8EAA8E;AAC9E,eAAO,MAAM,yBAAyB,QAAS,CAAC;AAEhD,MAAM,WAAW,0BAA0B;IACzC,sEAAsE;IACtE,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,mFAAmF;IACnF,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,mEAAmE;IACnE,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,eAAe,CAAC,CAwC1B"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { estimateTokens } from "../observational.js";
|
|
2
|
+
import { mergeListings } from "./sources.js";
|
|
3
|
+
import { listStoreTolerant } from "./store.js";
|
|
4
|
+
/** Standalone ceiling for curated file memory pinned into an agent prompt. */
|
|
5
|
+
export const PINNED_STORE_TOKEN_BUDGET = 15_000;
|
|
6
|
+
/**
|
|
7
|
+
* Load a frozen, newest-first view of curated file memories.
|
|
8
|
+
*
|
|
9
|
+
* Malformed entries are isolated to their own file and warned about instead
|
|
10
|
+
* of making agent startup fail. When the complete set exceeds the independent
|
|
11
|
+
* cap, whole entries leave oldest-first; the newest entry is retained and
|
|
12
|
+
* deterministically tail-truncated when it alone is too large.
|
|
13
|
+
*/
|
|
14
|
+
export async function loadPinnedStorePack(options) {
|
|
15
|
+
const tokenBudget = options.tokenBudget ?? PINNED_STORE_TOKEN_BUDGET;
|
|
16
|
+
if (!Number.isFinite(tokenBudget) || tokenBudget < 0) {
|
|
17
|
+
throw new Error(`Pinned store token budget must be a non-negative number: ${tokenBudget}`);
|
|
18
|
+
}
|
|
19
|
+
const listings = await Promise.all(options.stores.map(async (store) => ({
|
|
20
|
+
source: store,
|
|
21
|
+
entries: await loadStoreEntries(store),
|
|
22
|
+
})));
|
|
23
|
+
const entries = mergeListings(listings, []);
|
|
24
|
+
let totalTokens = entries.reduce((total, entry) => total + estimateTokens(entry.content), 0);
|
|
25
|
+
let dropped = 0;
|
|
26
|
+
let truncated = false;
|
|
27
|
+
while (entries.length > 1 && totalTokens > tokenBudget) {
|
|
28
|
+
const removed = entries.pop();
|
|
29
|
+
totalTokens -= estimateTokens(removed.content);
|
|
30
|
+
dropped += 1;
|
|
31
|
+
}
|
|
32
|
+
if (entries.length === 1 && totalTokens > tokenBudget) {
|
|
33
|
+
entries[0] = {
|
|
34
|
+
...entries[0],
|
|
35
|
+
content: truncateToTokenBudget(entries[0].content, tokenBudget),
|
|
36
|
+
};
|
|
37
|
+
truncated = true;
|
|
38
|
+
}
|
|
39
|
+
if (dropped > 0 || truncated) {
|
|
40
|
+
const truncation = truncated ? " and truncated the newest entry" : "";
|
|
41
|
+
const formattedBudget = tokenBudget.toLocaleString("en-US");
|
|
42
|
+
console.warn(`[duet-agent] pinned memory store context exceeded ${formattedBudget}-token cap; dropped ${dropped} older memory ${dropped === 1 ? "entry" : "entries"}${truncation}.`);
|
|
43
|
+
}
|
|
44
|
+
return { entries, dropped };
|
|
45
|
+
}
|
|
46
|
+
async function loadStoreEntries(store) {
|
|
47
|
+
try {
|
|
48
|
+
return await listStoreTolerant(store, warnSkippedStore);
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
warnSkippedStore(store, error);
|
|
52
|
+
return [];
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function truncateToTokenBudget(content, tokenBudget) {
|
|
56
|
+
let low = 0;
|
|
57
|
+
let high = content.length;
|
|
58
|
+
while (low < high) {
|
|
59
|
+
const midpoint = Math.ceil((low + high) / 2);
|
|
60
|
+
if (estimateTokens(content.slice(0, midpoint)) <= tokenBudget)
|
|
61
|
+
low = midpoint;
|
|
62
|
+
else
|
|
63
|
+
high = midpoint - 1;
|
|
64
|
+
}
|
|
65
|
+
return content.slice(0, low);
|
|
66
|
+
}
|
|
67
|
+
function warnSkippedStore(path, error) {
|
|
68
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
69
|
+
console.warn(`[duet-agent] skipped malformed memory store entry ${path}: ${reason}`);
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=pack.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pack.js","sourceRoot":"","sources":["../../../../src/memory/store/pack.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAqB,MAAM,YAAY,CAAC;AAElE,8EAA8E;AAC9E,MAAM,CAAC,MAAM,yBAAyB,GAAG,MAAM,CAAC;AAgBhD;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,OAAmC;IAEnC,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,yBAAyB,CAAC;IACrE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,KAAK,CAAC,4DAA4D,WAAW,EAAE,CAAC,CAAC;IAC7F,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,CAChC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;QACnC,MAAM,EAAE,KAAK;QACb,OAAO,EAAE,MAAM,gBAAgB,CAAC,KAAK,CAAC;KACvC,CAAC,CAAC,CACJ,CAAC;IACF,MAAM,OAAO,GAAG,aAAa,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAC5C,IAAI,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7F,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,IAAI,SAAS,GAAG,KAAK,CAAC;IAEtB,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,WAAW,GAAG,WAAW,EAAE,CAAC;QACvD,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,EAAG,CAAC;QAC/B,WAAW,IAAI,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC/C,OAAO,IAAI,CAAC,CAAC;IACf,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,WAAW,GAAG,WAAW,EAAE,CAAC;QACtD,OAAO,CAAC,CAAC,CAAC,GAAG;YACX,GAAG,OAAO,CAAC,CAAC,CAAE;YACd,OAAO,EAAE,qBAAqB,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,OAAO,EAAE,WAAW,CAAC;SACjE,CAAC;QACF,SAAS,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,IAAI,OAAO,GAAG,CAAC,IAAI,SAAS,EAAE,CAAC;QAC7B,MAAM,UAAU,GAAG,SAAS,CAAC,CAAC,CAAC,iCAAiC,CAAC,CAAC,CAAC,EAAE,CAAC;QACtE,MAAM,eAAe,GAAG,WAAW,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QAC5D,OAAO,CAAC,IAAI,CACV,qDAAqD,eAAe,uBAAuB,OAAO,iBAAiB,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,GAAG,UAAU,GAAG,CACvK,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAC9B,CAAC;AAED,KAAK,UAAU,gBAAgB,CAAC,KAAa;IAC3C,IAAI,CAAC;QACH,OAAO,MAAM,iBAAiB,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;IAC1D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,gBAAgB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAC/B,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,SAAS,qBAAqB,CAAC,OAAe,EAAE,WAAmB;IACjE,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,IAAI,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC;IAC1B,OAAO,GAAG,GAAG,IAAI,EAAE,CAAC;QAClB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAC7C,IAAI,cAAc,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,WAAW;YAAE,GAAG,GAAG,QAAQ,CAAC;;YACzE,IAAI,GAAG,QAAQ,GAAG,CAAC,CAAC;IAC3B,CAAC;IACD,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAC/B,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAY,EAAE,KAAc;IACpD,MAAM,MAAM,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACtE,OAAO,CAAC,IAAI,CAAC,qDAAqD,IAAI,KAAK,MAAM,EAAE,CAAC,CAAC;AACvF,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/** Ordered source paths collected from repeatable CLI backend flags. */
|
|
2
|
+
export interface MemorySourceFlags {
|
|
3
|
+
/** Explicit memory-file directories, in command-line order. */
|
|
4
|
+
stores: string[];
|
|
5
|
+
/** Explicit PGlite files, in command-line order. */
|
|
6
|
+
dbs: string[];
|
|
7
|
+
}
|
|
8
|
+
/** The single backend selected for a create operation. */
|
|
9
|
+
export interface MemoryWriteTarget {
|
|
10
|
+
/** Selects the file-store or legacy PGlite persistence path. */
|
|
11
|
+
kind: "store" | "db";
|
|
12
|
+
/** Absolute store directory or PGlite data path. */
|
|
13
|
+
path: string;
|
|
14
|
+
}
|
|
15
|
+
/** Effective read sources plus the create-operation target implied by them. */
|
|
16
|
+
export interface MemorySources {
|
|
17
|
+
/** File stores in collision-precedence order. */
|
|
18
|
+
stores: string[];
|
|
19
|
+
/** PGlite paths in collision-precedence order after every file store. */
|
|
20
|
+
dbs: string[];
|
|
21
|
+
/** Present only when the invocation selects exactly one write backend. */
|
|
22
|
+
writeTarget?: MemoryWriteTarget;
|
|
23
|
+
}
|
|
24
|
+
/** One backend's already-projected listing rows. */
|
|
25
|
+
export interface SourceListing<T> {
|
|
26
|
+
/** Absolute backend path; file-store groups stamp it as row provenance. */
|
|
27
|
+
source: string;
|
|
28
|
+
/** Rows returned by this backend before collision resolution. */
|
|
29
|
+
entries: readonly T[];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Resolve explicit flags or the skills-style flagless source set.
|
|
33
|
+
*
|
|
34
|
+
* Any explicit backend flag replaces discovery. Without flags, reads inherit
|
|
35
|
+
* every existing memory store from cwd toward the filesystem root and then
|
|
36
|
+
* consult the default DB. Writes target the nearest ancestor that owns an
|
|
37
|
+
* `.agents` directory, falling back to cwd when no agent marker exists; the
|
|
38
|
+
* `memories` child itself is allowed to be absent because writers create it.
|
|
39
|
+
*/
|
|
40
|
+
export declare function resolveSources(flags: MemorySourceFlags, cwd: string): Promise<MemorySources>;
|
|
41
|
+
/**
|
|
42
|
+
* Merge projected rows under the one canonical ordering policy.
|
|
43
|
+
*
|
|
44
|
+
* File-store groups precede DB groups; within each family the caller supplies
|
|
45
|
+
* nearest-to-root or explicit flag order. The first row for a slug wins that
|
|
46
|
+
* collision. Only after shadowed copies are removed are all winners sorted
|
|
47
|
+
* newest-first, with the precedence order retained for timestamp ties.
|
|
48
|
+
*/
|
|
49
|
+
export declare function mergeListings<T extends {
|
|
50
|
+
slug: string;
|
|
51
|
+
createdAt: number;
|
|
52
|
+
}>(storeEntries: readonly SourceListing<T>[], dbEntries: readonly SourceListing<T>[]): Array<T & {
|
|
53
|
+
store?: string;
|
|
54
|
+
}>;
|
|
55
|
+
//# sourceMappingURL=sources.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sources.d.ts","sourceRoot":"","sources":["../../../../src/memory/store/sources.ts"],"names":[],"mappings":"AAOA,wEAAwE;AACxE,MAAM,WAAW,iBAAiB;IAChC,+DAA+D;IAC/D,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,oDAAoD;IACpD,GAAG,EAAE,MAAM,EAAE,CAAC;CACf;AAED,0DAA0D;AAC1D,MAAM,WAAW,iBAAiB;IAChC,gEAAgE;IAChE,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;IACrB,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,+EAA+E;AAC/E,MAAM,WAAW,aAAa;IAC5B,iDAAiD;IACjD,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,yEAAyE;IACzE,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,0EAA0E;IAC1E,WAAW,CAAC,EAAE,iBAAiB,CAAC;CACjC;AAED,oDAAoD;AACpD,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,2EAA2E;IAC3E,MAAM,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,OAAO,EAAE,SAAS,CAAC,EAAE,CAAC;CACvB;AAED;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAClC,KAAK,EAAE,iBAAiB,EACxB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,aAAa,CAAC,CAuBxB;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,EACzE,YAAY,EAAE,SAAS,aAAa,CAAC,CAAC,CAAC,EAAE,EACzC,SAAS,EAAE,SAAS,aAAa,CAAC,CAAC,CAAC,EAAE,GACrC,KAAK,CAAC,CAAC,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAa/B"}
|