@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 CHANGED
@@ -1,5 +1,5 @@
1
1
  # @xandreed/plugin-memory
2
2
 
3
- Efferent composable agent framework, 0.4.0. Bun on Linux.
3
+ Efferent composable agent framework, 0.8.0-next.0. Bun on Linux.
4
4
 
5
5
  Documentation: https://github.com/xandreeddev/efferent
package/dist/index.d.ts CHANGED
@@ -1,2 +1,9 @@
1
- export declare const memoryPlugin: import("@xandreed/core").Plugin;
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.between(1, 100)) }), Row = Schema.Union(Schema.Struct({ kind: Schema.Literal("remember"), entry: MemoryEntry }), Schema.Struct({ kind: Schema.Literal("forget"), id: Schema.String }));
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.4.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* Effect.makeSemaphore(1), read = Effect.tryPromise({
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.catchAll(({ error, missing }) => missing ? Effect.succeed("") : Effect.fail(new HarnessError({ code: "memory.read", message: String(error) }))), Effect.flatMap((text) => Effect.forEach(text.split(`
21
- `).filter(Boolean), (line) => Schema.decodeUnknown(Schema.parseJson(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({
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.zipRight(read), Effect.map((entries) => {
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.zipRight(append({ kind: "remember", entry })), Effect.as(entry));
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.zipRight(append({ kind: "forget", id })))
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.4.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.4.0",
14
- "effect": "3.21.4"
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",