@aigne/afs 1.0.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.
Files changed (50) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/LICENSE.md +93 -0
  3. package/lib/cjs/afs.d.ts +26 -0
  4. package/lib/cjs/afs.js +126 -0
  5. package/lib/cjs/history/index.d.ts +14 -0
  6. package/lib/cjs/history/index.js +45 -0
  7. package/lib/cjs/index.d.ts +4 -0
  8. package/lib/cjs/index.js +20 -0
  9. package/lib/cjs/package.json +3 -0
  10. package/lib/cjs/storage/index.d.ts +24 -0
  11. package/lib/cjs/storage/index.js +72 -0
  12. package/lib/cjs/storage/migrate.d.ts +3 -0
  13. package/lib/cjs/storage/migrate.js +31 -0
  14. package/lib/cjs/storage/migrations/001-init.d.ts +2 -0
  15. package/lib/cjs/storage/migrations/001-init.js +25 -0
  16. package/lib/cjs/storage/models/entries.d.ts +199 -0
  17. package/lib/cjs/storage/models/entries.js +28 -0
  18. package/lib/cjs/storage/type.d.ts +23 -0
  19. package/lib/cjs/storage/type.js +2 -0
  20. package/lib/cjs/type.d.ts +54 -0
  21. package/lib/cjs/type.js +2 -0
  22. package/lib/dts/afs.d.ts +26 -0
  23. package/lib/dts/history/index.d.ts +14 -0
  24. package/lib/dts/index.d.ts +4 -0
  25. package/lib/dts/storage/index.d.ts +24 -0
  26. package/lib/dts/storage/migrate.d.ts +3 -0
  27. package/lib/dts/storage/migrations/001-init.d.ts +2 -0
  28. package/lib/dts/storage/models/entries.d.ts +199 -0
  29. package/lib/dts/storage/type.d.ts +23 -0
  30. package/lib/dts/type.d.ts +54 -0
  31. package/lib/esm/afs.d.ts +26 -0
  32. package/lib/esm/afs.js +122 -0
  33. package/lib/esm/history/index.d.ts +14 -0
  34. package/lib/esm/history/index.js +41 -0
  35. package/lib/esm/index.d.ts +4 -0
  36. package/lib/esm/index.js +4 -0
  37. package/lib/esm/package.json +3 -0
  38. package/lib/esm/storage/index.d.ts +24 -0
  39. package/lib/esm/storage/index.js +67 -0
  40. package/lib/esm/storage/migrate.d.ts +3 -0
  41. package/lib/esm/storage/migrate.js +28 -0
  42. package/lib/esm/storage/migrations/001-init.d.ts +2 -0
  43. package/lib/esm/storage/migrations/001-init.js +22 -0
  44. package/lib/esm/storage/models/entries.d.ts +199 -0
  45. package/lib/esm/storage/models/entries.js +23 -0
  46. package/lib/esm/storage/type.d.ts +23 -0
  47. package/lib/esm/storage/type.js +1 -0
  48. package/lib/esm/type.d.ts +54 -0
  49. package/lib/esm/type.js +1 -0
  50. package/package.json +69 -0
@@ -0,0 +1,26 @@
1
+ import { Emitter } from "strict-event-emitter";
2
+ import { SharedAFSStorage, type SharedAFSStorageOptions } from "./storage/index.js";
3
+ import type { AFSStorage } from "./storage/type.js";
4
+ import type { AFSEntry, AFSListOptions, AFSModule, AFSRoot, AFSRootEvents, AFSSearchOptions, AFSWriteEntryPayload } from "./type.js";
5
+ export interface AFSOptions {
6
+ storage?: SharedAFSStorage | SharedAFSStorageOptions;
7
+ }
8
+ export declare class AFS extends Emitter<AFSRootEvents> implements AFSRoot {
9
+ moduleId: string;
10
+ path: string;
11
+ constructor(options?: AFSOptions);
12
+ private _storage;
13
+ storage(module: AFSModule): AFSStorage;
14
+ private modules;
15
+ use(module: AFSModule): this;
16
+ list(path: string, options?: AFSListOptions): Promise<{
17
+ list: AFSEntry[];
18
+ }>;
19
+ private findModules;
20
+ private isSubpath;
21
+ read(path: string): Promise<AFSEntry | undefined>;
22
+ write(path: string, content: AFSWriteEntryPayload): Promise<AFSEntry>;
23
+ search(path: string, query: string, options?: AFSSearchOptions): Promise<{
24
+ list: AFSEntry[];
25
+ }>;
26
+ }
package/lib/esm/afs.js ADDED
@@ -0,0 +1,122 @@
1
+ import { Emitter } from "strict-event-emitter";
2
+ import { joinURL } from "ufo";
3
+ import { AFSHistory } from "./history/index.js";
4
+ import { SharedAFSStorage } from "./storage/index.js";
5
+ const DEFAULT_MAX_DEPTH = 5;
6
+ export class AFS extends Emitter {
7
+ moduleId = "AFSRoot";
8
+ path = "/";
9
+ constructor(options) {
10
+ super();
11
+ this._storage =
12
+ options?.storage instanceof SharedAFSStorage
13
+ ? options.storage
14
+ : new SharedAFSStorage(options?.storage);
15
+ this.use(new AFSHistory());
16
+ }
17
+ _storage;
18
+ storage(module) {
19
+ return this._storage.withModule(module);
20
+ }
21
+ modules = new Map();
22
+ use(module) {
23
+ this.modules.set(module.path, module);
24
+ module.onMount?.(this);
25
+ return this;
26
+ }
27
+ async list(path, options) {
28
+ const maxDepth = options?.maxDepth ?? DEFAULT_MAX_DEPTH;
29
+ if (!(maxDepth >= 0))
30
+ throw new Error(`Invalid maxDepth: ${maxDepth}`);
31
+ const results = [];
32
+ const modules = this.findModules(path);
33
+ for (const { module, subpath, mountPath } of modules) {
34
+ if (!module.list)
35
+ continue;
36
+ try {
37
+ const newMaxDepth = maxDepth - mountPath.split("/").filter(Boolean).length;
38
+ if (newMaxDepth < 0)
39
+ continue;
40
+ const { list } = await module.list(subpath, { ...options, maxDepth: newMaxDepth });
41
+ results.push(...list.map((entry) => ({
42
+ ...entry,
43
+ path: joinURL(mountPath, entry.path),
44
+ })));
45
+ }
46
+ catch (error) {
47
+ console.error(`Error listing from module at ${mountPath}`, error);
48
+ }
49
+ }
50
+ return { list: results };
51
+ }
52
+ findModules(fullPath) {
53
+ const modules = [];
54
+ for (const [mountPath, module] of this.modules) {
55
+ const match = this.isSubpath(fullPath, mountPath);
56
+ if (!match)
57
+ continue;
58
+ modules.push({ ...match, module, mountPath });
59
+ }
60
+ return modules.sort((a, b) => b.matchedDepth - a.matchedDepth);
61
+ }
62
+ isSubpath(fullPath, mountPath) {
63
+ const fullPathSegments = fullPath.split("/").filter(Boolean);
64
+ const mountPathSegments = mountPath.split("/").filter(Boolean);
65
+ const fp = fullPathSegments.join("/");
66
+ const mp = mountPathSegments.join("/");
67
+ if (fp.startsWith(mp)) {
68
+ return {
69
+ matchedDepth: mountPathSegments.length,
70
+ subpath: joinURL("/", ...fullPathSegments.slice(mountPathSegments.length)),
71
+ };
72
+ }
73
+ else if (mp.startsWith(fp)) {
74
+ return {
75
+ matchedDepth: fullPathSegments.length,
76
+ subpath: joinURL("/", ...mountPathSegments.slice(fullPathSegments.length)),
77
+ };
78
+ }
79
+ }
80
+ async read(path) {
81
+ const modules = this.findModules(path);
82
+ for (const { module, mountPath, subpath } of modules) {
83
+ const entry = await module.read?.(subpath);
84
+ if (entry) {
85
+ return {
86
+ ...entry,
87
+ path: joinURL(mountPath, entry.path),
88
+ };
89
+ }
90
+ }
91
+ }
92
+ async write(path, content) {
93
+ const module = this.findModules(path)[0];
94
+ if (!module?.module.write)
95
+ throw new Error(`No module found for path: ${path}`);
96
+ const entry = await module.module.write(module.subpath, content);
97
+ return {
98
+ ...entry,
99
+ path: joinURL(module.mountPath, entry.path),
100
+ };
101
+ }
102
+ async search(path, query, options) {
103
+ const results = [];
104
+ for (const { module, mountPath, subpath } of this.findModules(path)) {
105
+ if (mountPath.startsWith(path)) {
106
+ if (!module.search)
107
+ continue;
108
+ try {
109
+ const { list } = await module.search(subpath, query, options);
110
+ results.push(...list.map((entry) => ({
111
+ ...entry,
112
+ path: joinURL(mountPath, entry.path),
113
+ })));
114
+ }
115
+ catch (error) {
116
+ console.error(`Error searching in module at ${mountPath}`, error);
117
+ }
118
+ }
119
+ }
120
+ return { list: results };
121
+ }
122
+ }
@@ -0,0 +1,14 @@
1
+ import type { AFSEntry, AFSListOptions, AFSModule, AFSRoot, AFSWriteEntryPayload } from "../type.js";
2
+ export declare class AFSHistory implements AFSModule {
3
+ static Path: string;
4
+ path: string;
5
+ moduleId: string;
6
+ private _afs?;
7
+ get afs(): AFSRoot;
8
+ onMount(afs: AFSRoot): void;
9
+ list(path: string, options?: AFSListOptions): Promise<{
10
+ list: AFSEntry[];
11
+ }>;
12
+ read(path: string): Promise<AFSEntry | undefined>;
13
+ write(path: string, content: AFSWriteEntryPayload): Promise<AFSEntry>;
14
+ }
@@ -0,0 +1,41 @@
1
+ import { v7 } from "@aigne/uuid";
2
+ import { joinURL } from "ufo";
3
+ export class AFSHistory {
4
+ static Path = "/history";
5
+ path = AFSHistory.Path;
6
+ moduleId = "AFSHistory";
7
+ _afs;
8
+ get afs() {
9
+ if (!this._afs)
10
+ throw new Error("AFSHistory module is not mounted");
11
+ return this._afs;
12
+ }
13
+ onMount(afs) {
14
+ this._afs = afs;
15
+ afs.on("agentSucceed", ({ input, output }) => {
16
+ this.afs
17
+ .storage(this)
18
+ .create({
19
+ path: joinURL("/", v7()),
20
+ content: { input, output },
21
+ })
22
+ .then((entry) => {
23
+ afs.emit("historyCreated", { entry });
24
+ })
25
+ .catch((error) => {
26
+ console.error("Failed to store history entry", error);
27
+ });
28
+ });
29
+ }
30
+ async list(path, options) {
31
+ if (path !== "/")
32
+ return { list: [] };
33
+ return this.afs.storage(this).list(options);
34
+ }
35
+ async read(path) {
36
+ return this.afs.storage(this).read(path);
37
+ }
38
+ async write(path, content) {
39
+ return this.afs.storage(this).create({ ...content, path });
40
+ }
41
+ }
@@ -0,0 +1,4 @@
1
+ export * from "./afs.js";
2
+ export * from "./history/index.js";
3
+ export * from "./storage/index.js";
4
+ export * from "./type.js";
@@ -0,0 +1,4 @@
1
+ export * from "./afs.js";
2
+ export * from "./history/index.js";
3
+ export * from "./storage/index.js";
4
+ export * from "./type.js";
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "module"
3
+ }
@@ -0,0 +1,24 @@
1
+ import { initDatabase } from "@aigne/sqlite";
2
+ import type { AFSEntry, AFSModule } from "../type.js";
3
+ import { entriesTable } from "./models/entries.js";
4
+ import type { AFSStorage, AFSStorageCreatePayload, AFSStorageListOptions } from "./type.js";
5
+ export interface SharedAFSStorageOptions {
6
+ url?: string;
7
+ }
8
+ export declare class SharedAFSStorage {
9
+ options?: SharedAFSStorageOptions | undefined;
10
+ constructor(options?: SharedAFSStorageOptions | undefined);
11
+ private _db;
12
+ get db(): Promise<import("drizzle-orm/libsql").LibSQLDatabase<Record<string, never>>>;
13
+ withModule(module: AFSModule): AFSStorage;
14
+ }
15
+ export declare class AFSStorageWithModule implements AFSStorage {
16
+ private db;
17
+ private table;
18
+ constructor(db: ReturnType<typeof initDatabase>, table: Promise<ReturnType<typeof entriesTable>>);
19
+ list(options?: AFSStorageListOptions): Promise<{
20
+ list: AFSEntry[];
21
+ }>;
22
+ read(path: string): Promise<AFSEntry | undefined>;
23
+ create(entry: AFSStorageCreatePayload): Promise<AFSEntry>;
24
+ }
@@ -0,0 +1,67 @@
1
+ import { and, asc, desc, eq, initDatabase, sql } from "@aigne/sqlite";
2
+ import { migrate } from "./migrate.js";
3
+ import { entriesTable } from "./models/entries.js";
4
+ const DEFAULT_AFS_STORAGE_LIST_LIMIT = 10;
5
+ export class SharedAFSStorage {
6
+ options;
7
+ constructor(options) {
8
+ this.options = options;
9
+ }
10
+ _db;
11
+ get db() {
12
+ this._db ??= initDatabase({ url: this.options?.url });
13
+ return this._db;
14
+ }
15
+ withModule(module) {
16
+ return new AFSStorageWithModule(this.db, migrate(this.db, module).then(() => entriesTable(module)));
17
+ }
18
+ }
19
+ export class AFSStorageWithModule {
20
+ db;
21
+ table;
22
+ constructor(db, table) {
23
+ this.db = db;
24
+ this.table = table;
25
+ }
26
+ async list(options = {}) {
27
+ const { filter, limit = DEFAULT_AFS_STORAGE_LIST_LIMIT } = options;
28
+ const db = await this.db;
29
+ const table = await this.table;
30
+ const list = await db
31
+ .select()
32
+ .from(table)
33
+ .where(and(filter?.userId ? eq(table.userId, filter.userId) : undefined, filter?.sessionId ? eq(table.sessionId, filter.sessionId) : undefined))
34
+ .orderBy(...(options.orderBy ?? []).map((item) => (item[1] === "asc" ? asc : desc)(sql.identifier(item[0]))))
35
+ .limit(limit)
36
+ .execute();
37
+ return { list };
38
+ }
39
+ async read(path) {
40
+ const db = await this.db;
41
+ const table = await this.table;
42
+ return db
43
+ .select()
44
+ .from(table)
45
+ .where(eq(table.path, path))
46
+ .limit(1)
47
+ .execute()
48
+ .then((memory) => memory.at(0));
49
+ }
50
+ async create(entry) {
51
+ const db = await this.db;
52
+ const table = await this.table;
53
+ let result = await db
54
+ .update(table)
55
+ .set(entry)
56
+ .where(eq(table.path, entry.path))
57
+ .returning()
58
+ .execute();
59
+ if (!result.length) {
60
+ result = await db.insert(table).values(entry).returning().execute();
61
+ }
62
+ const [res] = result;
63
+ if (!res)
64
+ throw new Error("Failed to create AFS entry, no result");
65
+ return res;
66
+ }
67
+ }
@@ -0,0 +1,3 @@
1
+ import { type initDatabase } from "@aigne/sqlite";
2
+ import type { AFSModule } from "../type.js";
3
+ export declare function migrate(db: ReturnType<typeof initDatabase>, module: AFSModule): Promise<void>;
@@ -0,0 +1,28 @@
1
+ import { sql } from "@aigne/sqlite";
2
+ import { v7 } from "@aigne/uuid";
3
+ import { init } from "./migrations/001-init.js";
4
+ export async function migrate(db, module) {
5
+ const migrations = [init];
6
+ const migrationsTable = "__drizzle_migrations";
7
+ const migrationTableCreate = sql `
8
+ CREATE TABLE IF NOT EXISTS ${sql.identifier(migrationsTable)} (
9
+ "id" SERIAL PRIMARY KEY,
10
+ "moduleId" TEXT NOT NULL,
11
+ "hash" TEXT NOT NULL
12
+ )
13
+ `;
14
+ await (await db).run(migrationTableCreate).execute();
15
+ const dbMigrations = await (await db)
16
+ .values(sql `SELECT "id", "moduleId", "hash" FROM ${sql.identifier(migrationsTable)} WHERE "moduleId" = ${sql.param(module.moduleId)} ORDER BY id DESC LIMIT 1`)
17
+ .execute();
18
+ const lastDbMigration = dbMigrations[0];
19
+ const queriesToRun = [];
20
+ for (const migration of migrations) {
21
+ if (!lastDbMigration || lastDbMigration[1] < migration.hash) {
22
+ queriesToRun.push(...migration.sql(module), sql `INSERT INTO ${sql.identifier(migrationsTable)} ("id", "moduleId", "hash") VALUES(${sql.param(v7())}, ${sql.param(module.moduleId)}, ${sql.param(migration.hash)})`);
23
+ }
24
+ }
25
+ for (const query of queriesToRun) {
26
+ await (await db).run(query).execute();
27
+ }
28
+ }
@@ -0,0 +1,2 @@
1
+ import type { AFSStorageMigrations } from "../type.js";
2
+ export declare const init: AFSStorageMigrations;
@@ -0,0 +1,22 @@
1
+ import { sql } from "@aigne/sqlite";
2
+ import { entriesTableName } from "../models/entries.js";
3
+ export const init = {
4
+ hash: "001-init",
5
+ sql: (module) => [
6
+ sql `\
7
+ CREATE TABLE ${sql.identifier(entriesTableName(module))} (
8
+ "id" TEXT NOT NULL PRIMARY KEY,
9
+ "createdAt" DATETIME NOT NULL,
10
+ "updatedAt" DATETIME NOT NULL,
11
+ "path" TEXT NOT NULL,
12
+ "userId" TEXT,
13
+ "sessionId" TEXT,
14
+ "summary" TEXT,
15
+ "metadata" JSON,
16
+ "linkTo" TEXT,
17
+ "content" JSON,
18
+ UNIQUE (path)
19
+ )
20
+ `,
21
+ ],
22
+ };
@@ -0,0 +1,199 @@
1
+ import type { AFSModule } from "../../type.js";
2
+ export declare const entriesTableName: (module: AFSModule) => string;
3
+ export declare const entriesTable: (module: AFSModule) => import("@aigne/sqlite").SQLiteTableWithColumns<{
4
+ name: string;
5
+ schema: undefined;
6
+ columns: {
7
+ id: import("@aigne/sqlite").SQLiteColumn<{
8
+ name: "id";
9
+ tableName: string;
10
+ dataType: "string";
11
+ columnType: "SQLiteText";
12
+ data: string;
13
+ driverParam: string;
14
+ notNull: true;
15
+ hasDefault: true;
16
+ isPrimaryKey: true;
17
+ isAutoincrement: false;
18
+ hasRuntimeDefault: true;
19
+ enumValues: [string, ...string[]];
20
+ baseColumn: never;
21
+ identity: undefined;
22
+ generated: undefined;
23
+ }, {}, {
24
+ length: number | undefined;
25
+ }>;
26
+ createdAt: import("@aigne/sqlite").SQLiteColumn<{
27
+ name: "createdAt";
28
+ tableName: string;
29
+ dataType: "custom";
30
+ columnType: "SQLiteCustomColumn";
31
+ data: Date;
32
+ driverParam: string;
33
+ notNull: true;
34
+ hasDefault: true;
35
+ isPrimaryKey: false;
36
+ isAutoincrement: false;
37
+ hasRuntimeDefault: true;
38
+ enumValues: undefined;
39
+ baseColumn: never;
40
+ identity: undefined;
41
+ generated: undefined;
42
+ }, {}, {
43
+ sqliteColumnBuilderBrand: "SQLiteCustomColumnBuilderBrand";
44
+ }>;
45
+ updatedAt: import("@aigne/sqlite").SQLiteColumn<{
46
+ name: "updatedAt";
47
+ tableName: string;
48
+ dataType: "custom";
49
+ columnType: "SQLiteCustomColumn";
50
+ data: Date;
51
+ driverParam: string;
52
+ notNull: true;
53
+ hasDefault: true;
54
+ isPrimaryKey: false;
55
+ isAutoincrement: false;
56
+ hasRuntimeDefault: true;
57
+ enumValues: undefined;
58
+ baseColumn: never;
59
+ identity: undefined;
60
+ generated: undefined;
61
+ }, {}, {
62
+ sqliteColumnBuilderBrand: "SQLiteCustomColumnBuilderBrand";
63
+ }>;
64
+ path: import("@aigne/sqlite").SQLiteColumn<{
65
+ name: "path";
66
+ tableName: string;
67
+ dataType: "string";
68
+ columnType: "SQLiteText";
69
+ data: string;
70
+ driverParam: string;
71
+ notNull: true;
72
+ hasDefault: false;
73
+ isPrimaryKey: false;
74
+ isAutoincrement: false;
75
+ hasRuntimeDefault: false;
76
+ enumValues: [string, ...string[]];
77
+ baseColumn: never;
78
+ identity: undefined;
79
+ generated: undefined;
80
+ }, {}, {
81
+ length: number | undefined;
82
+ }>;
83
+ userId: import("@aigne/sqlite").SQLiteColumn<{
84
+ name: "userId";
85
+ tableName: string;
86
+ dataType: "string";
87
+ columnType: "SQLiteText";
88
+ data: string;
89
+ driverParam: string;
90
+ notNull: false;
91
+ hasDefault: false;
92
+ isPrimaryKey: false;
93
+ isAutoincrement: false;
94
+ hasRuntimeDefault: false;
95
+ enumValues: [string, ...string[]];
96
+ baseColumn: never;
97
+ identity: undefined;
98
+ generated: undefined;
99
+ }, {}, {
100
+ length: number | undefined;
101
+ }>;
102
+ sessionId: import("@aigne/sqlite").SQLiteColumn<{
103
+ name: "sessionId";
104
+ tableName: string;
105
+ dataType: "string";
106
+ columnType: "SQLiteText";
107
+ data: string;
108
+ driverParam: string;
109
+ notNull: false;
110
+ hasDefault: false;
111
+ isPrimaryKey: false;
112
+ isAutoincrement: false;
113
+ hasRuntimeDefault: false;
114
+ enumValues: [string, ...string[]];
115
+ baseColumn: never;
116
+ identity: undefined;
117
+ generated: undefined;
118
+ }, {}, {
119
+ length: number | undefined;
120
+ }>;
121
+ summary: import("@aigne/sqlite").SQLiteColumn<{
122
+ name: "summary";
123
+ tableName: string;
124
+ dataType: "string";
125
+ columnType: "SQLiteText";
126
+ data: string;
127
+ driverParam: string;
128
+ notNull: false;
129
+ hasDefault: false;
130
+ isPrimaryKey: false;
131
+ isAutoincrement: false;
132
+ hasRuntimeDefault: false;
133
+ enumValues: [string, ...string[]];
134
+ baseColumn: never;
135
+ identity: undefined;
136
+ generated: undefined;
137
+ }, {}, {
138
+ length: number | undefined;
139
+ }>;
140
+ metadata: import("@aigne/sqlite").SQLiteColumn<{
141
+ name: string;
142
+ tableName: string;
143
+ dataType: "custom";
144
+ columnType: "SQLiteCustomColumn";
145
+ data: Record<string, unknown>;
146
+ driverParam: string;
147
+ notNull: false;
148
+ hasDefault: false;
149
+ isPrimaryKey: false;
150
+ isAutoincrement: false;
151
+ hasRuntimeDefault: false;
152
+ enumValues: undefined;
153
+ baseColumn: never;
154
+ identity: undefined;
155
+ generated: undefined;
156
+ }, {}, {
157
+ sqliteColumnBuilderBrand: "SQLiteCustomColumnBuilderBrand";
158
+ }>;
159
+ linkTo: import("@aigne/sqlite").SQLiteColumn<{
160
+ name: "linkTo";
161
+ tableName: string;
162
+ dataType: "string";
163
+ columnType: "SQLiteText";
164
+ data: string;
165
+ driverParam: string;
166
+ notNull: false;
167
+ hasDefault: false;
168
+ isPrimaryKey: false;
169
+ isAutoincrement: false;
170
+ hasRuntimeDefault: false;
171
+ enumValues: [string, ...string[]];
172
+ baseColumn: never;
173
+ identity: undefined;
174
+ generated: undefined;
175
+ }, {}, {
176
+ length: number | undefined;
177
+ }>;
178
+ content: import("@aigne/sqlite").SQLiteColumn<{
179
+ name: string;
180
+ tableName: string;
181
+ dataType: "custom";
182
+ columnType: "SQLiteCustomColumn";
183
+ data: any;
184
+ driverParam: string;
185
+ notNull: false;
186
+ hasDefault: false;
187
+ isPrimaryKey: false;
188
+ isAutoincrement: false;
189
+ hasRuntimeDefault: false;
190
+ enumValues: undefined;
191
+ baseColumn: never;
192
+ identity: undefined;
193
+ generated: undefined;
194
+ }, {}, {
195
+ sqliteColumnBuilderBrand: "SQLiteCustomColumnBuilderBrand";
196
+ }>;
197
+ };
198
+ dialect: "sqlite";
199
+ }>;
@@ -0,0 +1,23 @@
1
+ import { datetime, json, sqliteTable, text } from "@aigne/sqlite";
2
+ import { v7 } from "@aigne/uuid";
3
+ export const entriesTableName = (module) => `Entries_${module.moduleId}`;
4
+ export const entriesTable = (module) => sqliteTable(entriesTableName(module), {
5
+ id: text("id")
6
+ .notNull()
7
+ .primaryKey()
8
+ .$defaultFn(() => v7()),
9
+ createdAt: datetime("createdAt")
10
+ .notNull()
11
+ .$defaultFn(() => new Date()),
12
+ updatedAt: datetime("updatedAt")
13
+ .notNull()
14
+ .$defaultFn(() => new Date())
15
+ .$onUpdateFn(() => new Date()),
16
+ path: text("path").notNull(),
17
+ userId: text("userId"),
18
+ sessionId: text("sessionId"),
19
+ summary: text("summary"),
20
+ metadata: json("metadata"),
21
+ linkTo: text("linkTo"),
22
+ content: json("content"),
23
+ });
@@ -0,0 +1,23 @@
1
+ import type { SQL } from "@aigne/sqlite";
2
+ import type { AFSEntry, AFSModule } from "../type.js";
3
+ export interface AFSStorageCreatePayload extends Omit<AFSEntry, "id"> {
4
+ }
5
+ export interface AFSStorageListOptions {
6
+ filter?: {
7
+ userId?: string;
8
+ sessionId?: string;
9
+ };
10
+ limit?: number;
11
+ orderBy?: [string, "asc" | "desc"][];
12
+ }
13
+ export interface AFSStorage {
14
+ create(entry: AFSStorageCreatePayload): Promise<AFSEntry>;
15
+ list(options?: AFSStorageListOptions): Promise<{
16
+ list: AFSEntry[];
17
+ }>;
18
+ read(path: string): Promise<AFSEntry | undefined>;
19
+ }
20
+ export type AFSStorageMigrations = {
21
+ hash: string;
22
+ sql: (module: AFSModule) => SQL[];
23
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,54 @@
1
+ import type { Emitter } from "strict-event-emitter";
2
+ import type { AFSStorage } from "./storage/type.js";
3
+ export interface AFSListOptions {
4
+ filter?: {
5
+ userId?: string;
6
+ sessionId?: string;
7
+ };
8
+ recursive?: boolean;
9
+ maxDepth?: number;
10
+ limit?: number;
11
+ orderBy?: [string, "asc" | "desc"][];
12
+ }
13
+ export interface AFSSearchOptions {
14
+ limit?: number;
15
+ }
16
+ export interface AFSWriteEntryPayload extends Omit<AFSEntry, "id" | "path"> {
17
+ }
18
+ export interface AFSModule {
19
+ readonly moduleId: string;
20
+ readonly path: string;
21
+ onMount?(root: AFSRoot): void;
22
+ list?(path: string, options?: AFSListOptions): Promise<{
23
+ list: AFSEntry[];
24
+ }>;
25
+ read?(path: string): Promise<AFSEntry | undefined>;
26
+ write?(path: string, content: AFSWriteEntryPayload): Promise<AFSEntry>;
27
+ search?(path: string, query: string, options?: AFSSearchOptions): Promise<{
28
+ list: AFSEntry[];
29
+ }>;
30
+ }
31
+ export type AFSRootEvents = {
32
+ agentSucceed: [{
33
+ input: object;
34
+ output: object;
35
+ }];
36
+ historyCreated: [{
37
+ entry: AFSEntry;
38
+ }];
39
+ };
40
+ export interface AFSRoot extends Emitter<AFSRootEvents>, AFSModule {
41
+ storage(module: AFSModule): AFSStorage;
42
+ }
43
+ export interface AFSEntry<T = any> {
44
+ id: string;
45
+ createdAt?: Date;
46
+ updatedAt?: Date;
47
+ path: string;
48
+ userId?: string | null;
49
+ sessionId?: string | null;
50
+ summary?: string | null;
51
+ metadata?: Record<string, any> | null;
52
+ linkTo?: string | null;
53
+ content?: T;
54
+ }
@@ -0,0 +1 @@
1
+ export {};