@factlayer/adapter-zep 0.6.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 +23 -0
- package/dist/client.d.ts +2 -0
- package/dist/client.js +13 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +3 -0
- package/dist/mapper.d.ts +3 -0
- package/dist/mapper.js +41 -0
- package/dist/scan.d.ts +7 -0
- package/dist/scan.js +17 -0
- package/dist/types.d.ts +15 -0
- package/dist/types.js +1 -0
- package/package.json +25 -0
package/README.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# @factlayer/adapter-zep
|
|
2
|
+
|
|
3
|
+
A [FactLayer](https://github.com/Rubber-Duck-Screaming/factlayer) adapter for [Zep](https://www.getzep.com): pulls a user's graph facts, maps them to FactLayer facts, persists them locally (keyed by Zep's own edge uuid), and checks each one for freshness.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bun add @factlayer/adapter-zep
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { createZepClient, scanZep } from "@factlayer/adapter-zep";
|
|
15
|
+
|
|
16
|
+
const client = createZepClient(process.env.ZEP_API_KEY!);
|
|
17
|
+
const results = await scanZep(client, "alice");
|
|
18
|
+
// each result: { fact, result: { status: "fresh" | "needs-verification", ... } }
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Zep's bi-temporal fact model can flag an edge as no longer current via `invalidAt` or `expiredAt`. When either is present, this adapter maps it straight to the fact's `expiresAt`, so `check()` reports `needs-verification` immediately -- it never runs the category half-life math on a fact Zep has already flagged as outdated itself.
|
|
22
|
+
|
|
23
|
+
See the [main repo](https://github.com/Rubber-Duck-Screaming/factlayer) for the full architecture, the freshness model, and how this adapter fits alongside `@factlayer/core`, `@factlayer/cli`, and `@factlayer/mcp-server`.
|
package/dist/client.d.ts
ADDED
package/dist/client.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ZepClient as RealZepClient } from "@getzep/zep-cloud";
|
|
2
|
+
// Wraps the real @getzep/zep-cloud ZepClient so it satisfies the minimal
|
|
3
|
+
// ZepClient shape scanZep() depends on. Keeping scan.ts decoupled from the
|
|
4
|
+
// real SDK client is what lets the automated test suite inject a fake
|
|
5
|
+
// client instead of making real network calls (see scan.test.ts). This file
|
|
6
|
+
// is exercised only by a manual smoke test against the live Zep API, not by
|
|
7
|
+
// `bun test`.
|
|
8
|
+
export function createZepClient(apiKey) {
|
|
9
|
+
const client = new RealZepClient({ apiKey });
|
|
10
|
+
return {
|
|
11
|
+
getByUserId: (userId, request) => client.graph.edge.getByUserId(userId, request),
|
|
12
|
+
};
|
|
13
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
package/dist/mapper.d.ts
ADDED
package/dist/mapper.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { classify } from "@factlayer/core";
|
|
2
|
+
function toMs(value, fallback) {
|
|
3
|
+
if (!value)
|
|
4
|
+
return fallback;
|
|
5
|
+
const ms = Date.parse(value);
|
|
6
|
+
return Number.isNaN(ms) ? fallback : ms;
|
|
7
|
+
}
|
|
8
|
+
// Earliest of invalidAt/expiredAt that parses -- either one is Zep's own
|
|
9
|
+
// bi-temporal signal that the fact is no longer current, so whichever fired
|
|
10
|
+
// first is when the fact actually went stale.
|
|
11
|
+
function earliestInvalidation(edge) {
|
|
12
|
+
const candidates = [edge.invalidAt, edge.expiredAt]
|
|
13
|
+
.map((value) => (value ? Date.parse(value) : NaN))
|
|
14
|
+
.filter((ms) => !Number.isNaN(ms));
|
|
15
|
+
return candidates.length > 0 ? Math.min(...candidates) : null;
|
|
16
|
+
}
|
|
17
|
+
// Converts a Zep entity edge (Zep's unit of stored knowledge -- effectively
|
|
18
|
+
// "the fact") into a factlayer Fact.
|
|
19
|
+
//
|
|
20
|
+
// - storedAt prefers validAt (when the fact became true in the real world)
|
|
21
|
+
// and falls back to createdAt (when Zep's graph recorded the edge) when
|
|
22
|
+
// validAt is absent. lastVerifiedAt matches whichever one was used. Zep
|
|
23
|
+
// has no separate "last verified" concept.
|
|
24
|
+
// - category always comes from classify() on the fact text -- Zep doesn't
|
|
25
|
+
// expose a comparable freeform category on edges.
|
|
26
|
+
// - When Zep has already flagged the edge via invalidAt or expiredAt (its
|
|
27
|
+
// own bi-temporal signal that the fact is no longer current), that maps
|
|
28
|
+
// straight to expiresAt so check() reports needs-verification
|
|
29
|
+
// immediately, without running the category half-life math at all.
|
|
30
|
+
export async function toFact(edge, now = Date.now()) {
|
|
31
|
+
const text = edge.fact;
|
|
32
|
+
const storedAt = toMs(edge.validAt, toMs(edge.createdAt, now));
|
|
33
|
+
return {
|
|
34
|
+
id: edge.uuid,
|
|
35
|
+
text,
|
|
36
|
+
category: await classify(text),
|
|
37
|
+
storedAt,
|
|
38
|
+
lastVerifiedAt: storedAt,
|
|
39
|
+
expiresAt: earliestInvalidation(edge),
|
|
40
|
+
};
|
|
41
|
+
}
|
package/dist/scan.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { CheckResult, Fact } from "@factlayer/core";
|
|
2
|
+
import type { ZepClient } from "./types.ts";
|
|
3
|
+
export interface ScannedFact {
|
|
4
|
+
fact: Fact;
|
|
5
|
+
result: CheckResult;
|
|
6
|
+
}
|
|
7
|
+
export declare function scanZep(client: ZepClient, userId: string, now?: number): Promise<ScannedFact[]>;
|
package/dist/scan.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { addFact, check } from "@factlayer/core";
|
|
2
|
+
import { toFact } from "./mapper";
|
|
3
|
+
// Pulls facts (Zep's "entity edges") for a user via graph.edge.getByUserId()
|
|
4
|
+
// -- a direct listing, not a relevance-ranked search -- maps each to a
|
|
5
|
+
// Fact, persists it locally (upserted via addFact, keyed by Zep's own edge
|
|
6
|
+
// uuid so the two systems share one id space), and runs factlayer's
|
|
7
|
+
// check() on it. Never writes anything back to Zep itself -- only to
|
|
8
|
+
// factlayer's local store, which is what lets mark_verified act on
|
|
9
|
+
// Zep-sourced facts afterward.
|
|
10
|
+
export async function scanZep(client, userId, now = Date.now()) {
|
|
11
|
+
const edges = await client.getByUserId(userId, {});
|
|
12
|
+
return Promise.all(edges.map(async (edge) => {
|
|
13
|
+
const fact = await toFact(edge, now);
|
|
14
|
+
await addFact(fact);
|
|
15
|
+
return { fact, result: check(fact, now) };
|
|
16
|
+
}));
|
|
17
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface ZepEntityEdge {
|
|
2
|
+
uuid: string;
|
|
3
|
+
fact: string;
|
|
4
|
+
createdAt: string;
|
|
5
|
+
validAt?: string;
|
|
6
|
+
invalidAt?: string;
|
|
7
|
+
expiredAt?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface ZepGraphEdgesRequest {
|
|
10
|
+
cursor?: string;
|
|
11
|
+
limit?: number;
|
|
12
|
+
}
|
|
13
|
+
export interface ZepClient {
|
|
14
|
+
getByUserId(userId: string, request: ZepGraphEdgesRequest): Promise<ZepEntityEdge[]>;
|
|
15
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@factlayer/adapter-zep",
|
|
3
|
+
"version": "0.6.0",
|
|
4
|
+
"description": "Zep adapter for FactLayer: scans, persists, and checks Zep graph facts for freshness.",
|
|
5
|
+
"keywords": ["ai", "agent-memory", "llm", "freshness", "zep", "factlayer"],
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"files": ["dist"],
|
|
10
|
+
"publishConfig": {
|
|
11
|
+
"access": "public"
|
|
12
|
+
},
|
|
13
|
+
"scripts": {
|
|
14
|
+
"test": "bun test",
|
|
15
|
+
"build": "tsc -p tsconfig.json",
|
|
16
|
+
"prepublishOnly": "bun run ../../scripts/check-publish-ready.ts"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@factlayer/core": "0.6.0",
|
|
20
|
+
"@getzep/zep-cloud": "^3.28.0"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"typescript": "^5.6.3"
|
|
24
|
+
}
|
|
25
|
+
}
|