@xandreed/plugin-memory 0.4.0 → 0.8.0-next.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 +1 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +12 -9
- package/package.json +3 -3
package/README.md
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
import { HarnessError, Memory, SessionEnvironment } from "@xandreed/core";
|
|
2
|
+
export declare const memoryPlugin: import("@xandreed/core").TypedPlugin<{
|
|
3
|
+
readonly file: string;
|
|
4
|
+
readonly limit: number;
|
|
5
|
+
}, {
|
|
6
|
+
readonly file: string;
|
|
7
|
+
readonly limit: number;
|
|
8
|
+
}, Memory, HarnessError, SessionEnvironment>;
|
|
2
9
|
export default memoryPlugin;
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { appendFile, mkdir, readFile } from "node:fs/promises";
|
|
2
2
|
import { dirname, resolve, relative } from "node:path";
|
|
3
|
-
import { Effect, Layer, Schema } from "effect";
|
|
3
|
+
import { Effect, Layer, Schema, Semaphore } from "effect";
|
|
4
4
|
import { definePlugin, HarnessError, Memory, MemoryEntry, SessionEnvironment } from "@xandreed/core";
|
|
5
|
-
const Config = Schema.Struct({ file: Schema.String, limit: Schema.Int.pipe(Schema.
|
|
5
|
+
const Config = Schema.Struct({ file: Schema.String, limit: Schema.Int.pipe(Schema.check(Schema.isBetween({ minimum: 1, maximum: 100 }))) }), Row = Schema.Union([
|
|
6
|
+
Schema.Struct({ kind: Schema.Literal("remember"), entry: MemoryEntry }),
|
|
7
|
+
Schema.Struct({ kind: Schema.Literal("forget"), id: Schema.String })
|
|
8
|
+
]);
|
|
6
9
|
export const memoryPlugin = definePlugin({
|
|
7
10
|
id: "@xandreed/plugin-memory",
|
|
8
|
-
version: "0.
|
|
11
|
+
version: "0.8.0-next.0",
|
|
9
12
|
requires: [SessionEnvironment],
|
|
10
13
|
provides: [Memory],
|
|
11
14
|
config: Config,
|
|
@@ -14,11 +17,11 @@ export const memoryPlugin = definePlugin({
|
|
|
14
17
|
const { workspace } = yield* SessionEnvironment, path = resolve(workspace, file);
|
|
15
18
|
if (relative(workspace, path).startsWith(".."))
|
|
16
19
|
return yield* Effect.fail(new HarnessError({ code: "memory.path", message: "Memory file must be inside the workspace" }));
|
|
17
|
-
const allowed = (requested) => requested === workspace ? Effect.void : Effect.fail(new HarnessError({ code: "memory.workspace", message: "Memory belongs to a different workspace" })), gate = yield*
|
|
20
|
+
const allowed = (requested) => requested === workspace ? Effect.void : Effect.fail(new HarnessError({ code: "memory.workspace", message: "Memory belongs to a different workspace" })), gate = yield* Semaphore.make(1), read = Effect.tryPromise({
|
|
18
21
|
try: () => readFile(path, "utf8"),
|
|
19
22
|
catch: (error) => ({ error, missing: typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT" })
|
|
20
|
-
}).pipe(Effect.
|
|
21
|
-
`).filter(Boolean), (line) => Schema.
|
|
23
|
+
}).pipe(Effect.catch(({ error, missing }) => missing ? Effect.succeed("") : Effect.fail(new HarnessError({ code: "memory.read", message: String(error) }))), Effect.flatMap((text) => Effect.forEach(text.split(`
|
|
24
|
+
`).filter(Boolean), (line) => Schema.decodeUnknownEffect(Schema.fromJsonString(Row))(line))), Effect.map((rows) => rows.reduce((entries, row) => row.kind === "remember" ? [...entries.filter((entry) => entry.id !== row.entry.id), row.entry] : entries.filter((entry) => entry.id !== row.id), [])), Effect.mapError((error) => new HarnessError({ code: "memory.read", message: String(error) }))), append = (row) => gate.withPermits(1)(Effect.tryPromise({
|
|
22
25
|
try: async () => {
|
|
23
26
|
await mkdir(dirname(path), { recursive: !0 });
|
|
24
27
|
await appendFile(path, `${JSON.stringify(row)}
|
|
@@ -27,15 +30,15 @@ export const memoryPlugin = definePlugin({
|
|
|
27
30
|
catch: (error) => new HarnessError({ code: "memory.write", message: String(error) })
|
|
28
31
|
}));
|
|
29
32
|
return Memory.of({
|
|
30
|
-
recall: (requested, query) => allowed(requested).pipe(Effect.
|
|
33
|
+
recall: (requested, query) => allowed(requested).pipe(Effect.andThen(read), Effect.map((entries) => {
|
|
31
34
|
const terms = query.toLowerCase().split(/\W+/).filter((term) => term.length > 2), score = (entry) => terms.filter((term) => entry.text.toLowerCase().includes(term)).length;
|
|
32
35
|
return entries.filter((entry) => entry.workspace === requested).sort((a, b) => score(b) - score(a) || b.createdAt - a.createdAt).slice(0, limit);
|
|
33
36
|
})),
|
|
34
37
|
remember: (requested, text) => {
|
|
35
38
|
const entry = { id: crypto.randomUUID(), workspace: requested, text, createdAt: Date.now() };
|
|
36
|
-
return text.trim().length === 0 ? Effect.fail(new HarnessError({ code: "memory.empty", message: "Memory cannot be empty" })) : allowed(requested).pipe(Effect.
|
|
39
|
+
return text.trim().length === 0 ? Effect.fail(new HarnessError({ code: "memory.empty", message: "Memory cannot be empty" })) : allowed(requested).pipe(Effect.andThen(append({ kind: "remember", entry })), Effect.as(entry));
|
|
37
40
|
},
|
|
38
|
-
forget: (requested, id) => allowed(requested).pipe(Effect.
|
|
41
|
+
forget: (requested, id) => allowed(requested).pipe(Effect.andThen(append({ kind: "forget", id })))
|
|
39
42
|
});
|
|
40
43
|
}))
|
|
41
44
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xandreed/plugin-memory",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0-next.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
}
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@xandreed/core": "0.
|
|
14
|
-
"effect": "
|
|
13
|
+
"@xandreed/core": "0.8.0-next.0",
|
|
14
|
+
"effect": "4.0.0-rc.118"
|
|
15
15
|
},
|
|
16
16
|
"private": false,
|
|
17
17
|
"types": "./dist/index.d.ts",
|