@brightbeamai/chap-coordinator 0.2.8
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/LICENSE +201 -0
- package/README.md +271 -0
- package/dist/api-C3nkEk-B.d.cts +260 -0
- package/dist/api-CmSvlIqO.d.ts +260 -0
- package/dist/api.cjs +125 -0
- package/dist/api.cjs.map +1 -0
- package/dist/api.d.cts +4 -0
- package/dist/api.d.ts +4 -0
- package/dist/api.js +98 -0
- package/dist/api.js.map +1 -0
- package/dist/index.cjs +2804 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +175 -0
- package/dist/index.d.ts +175 -0
- package/dist/index.js +2762 -0
- package/dist/index.js.map +1 -0
- package/dist/jsonrpc.cjs +103 -0
- package/dist/jsonrpc.cjs.map +1 -0
- package/dist/jsonrpc.d.cts +65 -0
- package/dist/jsonrpc.d.ts +65 -0
- package/dist/jsonrpc.js +76 -0
- package/dist/jsonrpc.js.map +1 -0
- package/dist/methods.cjs +19 -0
- package/dist/methods.cjs.map +1 -0
- package/dist/methods.d.cts +455 -0
- package/dist/methods.d.ts +455 -0
- package/dist/methods.js +1 -0
- package/dist/methods.js.map +1 -0
- package/dist/patch.cjs +277 -0
- package/dist/patch.cjs.map +1 -0
- package/dist/patch.d.cts +29 -0
- package/dist/patch.d.ts +29 -0
- package/dist/patch.js +250 -0
- package/dist/patch.js.map +1 -0
- package/dist/storage/sqlite.cjs +94 -0
- package/dist/storage/sqlite.cjs.map +1 -0
- package/dist/storage/sqlite.d.cts +67 -0
- package/dist/storage/sqlite.d.ts +67 -0
- package/dist/storage/sqlite.js +76 -0
- package/dist/storage/sqlite.js.map +1 -0
- package/dist/storage/store.cjs +45 -0
- package/dist/storage/store.cjs.map +1 -0
- package/dist/storage/store.d.cts +53 -0
- package/dist/storage/store.d.ts +53 -0
- package/dist/storage/store.js +20 -0
- package/dist/storage/store.js.map +1 -0
- package/dist/types.cjs +34 -0
- package/dist/types.cjs.map +1 -0
- package/dist/types.d.cts +287 -0
- package/dist/types.d.ts +287 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/package.json +52 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/storage/sqlite.ts
|
|
21
|
+
var sqlite_exports = {};
|
|
22
|
+
__export(sqlite_exports, {
|
|
23
|
+
SqliteStore: () => SqliteStore
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(sqlite_exports);
|
|
26
|
+
var SqliteStore = class {
|
|
27
|
+
db;
|
|
28
|
+
stmtLoad;
|
|
29
|
+
stmtSave;
|
|
30
|
+
stmtDelete;
|
|
31
|
+
constructor(path, options = {}) {
|
|
32
|
+
let Database;
|
|
33
|
+
try {
|
|
34
|
+
Database = require("better-sqlite3");
|
|
35
|
+
} catch (err) {
|
|
36
|
+
throw new Error(
|
|
37
|
+
"SqliteStore requires the `better-sqlite3` package. Install it with `npm install better-sqlite3` or use MemoryStore for non-persistent workloads."
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
this.db = new Database(path);
|
|
41
|
+
if (path !== ":memory:" && options.wal !== false) {
|
|
42
|
+
this.db.pragma("journal_mode = WAL");
|
|
43
|
+
}
|
|
44
|
+
this.db.exec(`
|
|
45
|
+
CREATE TABLE IF NOT EXISTS chap_workspaces (
|
|
46
|
+
id TEXT PRIMARY KEY,
|
|
47
|
+
data TEXT NOT NULL,
|
|
48
|
+
version INTEGER NOT NULL,
|
|
49
|
+
updated_at TEXT NOT NULL
|
|
50
|
+
);
|
|
51
|
+
CREATE INDEX IF NOT EXISTS idx_chap_workspaces_updated_at
|
|
52
|
+
ON chap_workspaces (updated_at);
|
|
53
|
+
`);
|
|
54
|
+
this.stmtLoad = this.db.prepare(
|
|
55
|
+
"SELECT id, data, version, updated_at FROM chap_workspaces"
|
|
56
|
+
);
|
|
57
|
+
this.stmtSave = this.db.prepare(
|
|
58
|
+
"INSERT INTO chap_workspaces (id, data, version, updated_at) VALUES (?, ?, ?, ?) ON CONFLICT(id) DO UPDATE SET data = excluded.data, version = excluded.version, updated_at = excluded.updated_at"
|
|
59
|
+
);
|
|
60
|
+
this.stmtDelete = this.db.prepare(
|
|
61
|
+
"DELETE FROM chap_workspaces WHERE id = ?"
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
load() {
|
|
65
|
+
const rows = this.stmtLoad.all();
|
|
66
|
+
const out = [];
|
|
67
|
+
for (const r of rows) {
|
|
68
|
+
try {
|
|
69
|
+
out.push({ id: r.id, data: JSON.parse(r.data), version: r.version, updated_at: r.updated_at });
|
|
70
|
+
} catch {
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return out;
|
|
74
|
+
}
|
|
75
|
+
save(record) {
|
|
76
|
+
this.stmtSave.run(
|
|
77
|
+
record.id,
|
|
78
|
+
JSON.stringify(record.data),
|
|
79
|
+
record.version,
|
|
80
|
+
record.updated_at
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
delete(id) {
|
|
84
|
+
this.stmtDelete.run(id);
|
|
85
|
+
}
|
|
86
|
+
close() {
|
|
87
|
+
this.db.close();
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
91
|
+
0 && (module.exports = {
|
|
92
|
+
SqliteStore
|
|
93
|
+
});
|
|
94
|
+
//# sourceMappingURL=sqlite.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/storage/sqlite.ts"],"sourcesContent":["/**\n * SQLite-backed store using better-sqlite3.\n *\n * Schema:\n * CREATE TABLE chap_workspaces (\n * id TEXT PRIMARY KEY,\n * data TEXT NOT NULL, -- JSON.stringify of snapshot\n * version INTEGER NOT NULL,\n * updated_at TEXT NOT NULL -- ISO-8601\n * )\n *\n * Usage:\n * import { Coordinator } from \"@brightbeamai/chap-coordinator\";\n * import { SqliteStore } from \"@brightbeamai/chap-coordinator/storage/sqlite\";\n *\n * const coord = new Coordinator({\n * store: new SqliteStore(\"./chap.db\"),\n * });\n *\n * Pass `\":memory:\"` for an in-memory SQLite instance (faster than the\n * MemoryStore for tests that need transactional semantics).\n *\n * better-sqlite3 is declared as an optionalDependency. If the binary\n * cannot be built (rare on Linux/macOS, common on locked-down CI), the\n * SqliteStore import will throw with a clear message and applications\n * can fall back to MemoryStore or another implementation.\n */\n\nimport type { Store, WorkspaceRecord } from \"./store.js\";\n\n// better-sqlite3 has no published types in its own package, but the\n// `@types/better-sqlite3` package provides them. We require a structural\n// subset so the file type-checks even if the typings are absent.\ninterface SqliteDatabase {\n exec(sql: string): unknown;\n prepare(sql: string): SqliteStatement;\n pragma(name: string, options?: { simple?: boolean }): unknown;\n close(): void;\n}\ninterface SqliteStatement {\n run(...params: unknown[]): { changes: number; lastInsertRowid: number | bigint };\n get(...params: unknown[]): unknown;\n all(...params: unknown[]): unknown[];\n}\n\nexport interface SqliteStoreOptions {\n /**\n * Enable WAL journal mode for better concurrent-read performance.\n * Default true. Set false for `:memory:` databases or when the\n * filesystem does not support WAL (some network filesystems).\n */\n wal?: boolean;\n}\n\nexport class SqliteStore implements Store {\n readonly db: SqliteDatabase;\n private readonly stmtLoad: SqliteStatement;\n private readonly stmtSave: SqliteStatement;\n private readonly stmtDelete: SqliteStatement;\n\n constructor(path: string, options: SqliteStoreOptions = {}) {\n let Database: new (path: string) => SqliteDatabase;\n try {\n // require() is used so the dependency stays optional. ESM consumers\n // can still load this file; the actual import is dynamic.\n Database = require(\"better-sqlite3\");\n } catch (err) {\n throw new Error(\n \"SqliteStore requires the `better-sqlite3` package. \" +\n \"Install it with `npm install better-sqlite3` \" +\n \"or use MemoryStore for non-persistent workloads.\",\n );\n }\n\n this.db = new Database(path);\n if (path !== \":memory:\" && options.wal !== false) {\n this.db.pragma(\"journal_mode = WAL\");\n }\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS chap_workspaces (\n id TEXT PRIMARY KEY,\n data TEXT NOT NULL,\n version INTEGER NOT NULL,\n updated_at TEXT NOT NULL\n );\n CREATE INDEX IF NOT EXISTS idx_chap_workspaces_updated_at\n ON chap_workspaces (updated_at);\n `);\n\n this.stmtLoad = this.db.prepare(\n \"SELECT id, data, version, updated_at FROM chap_workspaces\",\n );\n this.stmtSave = this.db.prepare(\n \"INSERT INTO chap_workspaces (id, data, version, updated_at) \" +\n \"VALUES (?, ?, ?, ?) \" +\n \"ON CONFLICT(id) DO UPDATE SET \" +\n \"data = excluded.data, \" +\n \"version = excluded.version, \" +\n \"updated_at = excluded.updated_at\",\n );\n this.stmtDelete = this.db.prepare(\n \"DELETE FROM chap_workspaces WHERE id = ?\",\n );\n }\n\n load(): WorkspaceRecord[] {\n const rows = this.stmtLoad.all() as Array<{\n id: string;\n data: string;\n version: number;\n updated_at: string;\n }>;\n const out: WorkspaceRecord[] = [];\n for (const r of rows) {\n try {\n out.push({ id: r.id, data: JSON.parse(r.data), version: r.version, updated_at: r.updated_at });\n } catch {\n // A single unreadable row must not discard every other workspace; skip it.\n }\n }\n return out;\n }\n\n save(record: WorkspaceRecord): void {\n this.stmtSave.run(\n record.id,\n JSON.stringify(record.data),\n record.version,\n record.updated_at,\n );\n }\n\n delete(id: string): void {\n this.stmtDelete.run(id);\n }\n\n close(): void {\n this.db.close();\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAsDO,IAAM,cAAN,MAAmC;AAAA,EAC/B;AAAA,EACQ;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,MAAc,UAA8B,CAAC,GAAG;AAC1D,QAAI;AACJ,QAAI;AAGF,iBAAW,QAAQ,gBAAgB;AAAA,IACrC,SAAS,KAAK;AACZ,YAAM,IAAI;AAAA,QACR;AAAA,MAGF;AAAA,IACF;AAEA,SAAK,KAAK,IAAI,SAAS,IAAI;AAC3B,QAAI,SAAS,cAAc,QAAQ,QAAQ,OAAO;AAChD,WAAK,GAAG,OAAO,oBAAoB;AAAA,IACrC;AACA,SAAK,GAAG,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KASZ;AAED,SAAK,WAAW,KAAK,GAAG;AAAA,MACtB;AAAA,IACF;AACA,SAAK,WAAW,KAAK,GAAG;AAAA,MACtB;AAAA,IAMF;AACA,SAAK,aAAa,KAAK,GAAG;AAAA,MACxB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAA0B;AACxB,UAAM,OAAO,KAAK,SAAS,IAAI;AAM/B,UAAM,MAAyB,CAAC;AAChC,eAAW,KAAK,MAAM;AACpB,UAAI;AACF,YAAI,KAAK,EAAE,IAAI,EAAE,IAAI,MAAM,KAAK,MAAM,EAAE,IAAI,GAAG,SAAS,EAAE,SAAS,YAAY,EAAE,WAAW,CAAC;AAAA,MAC/F,QAAQ;AAAA,MAER;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,KAAK,QAA+B;AAClC,SAAK,SAAS;AAAA,MACZ,OAAO;AAAA,MACP,KAAK,UAAU,OAAO,IAAI;AAAA,MAC1B,OAAO;AAAA,MACP,OAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,OAAO,IAAkB;AACvB,SAAK,WAAW,IAAI,EAAE;AAAA,EACxB;AAAA,EAEA,QAAc;AACZ,SAAK,GAAG,MAAM;AAAA,EAChB;AACF;","names":[]}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Store, WorkspaceRecord } from './store.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* SQLite-backed store using better-sqlite3.
|
|
5
|
+
*
|
|
6
|
+
* Schema:
|
|
7
|
+
* CREATE TABLE chap_workspaces (
|
|
8
|
+
* id TEXT PRIMARY KEY,
|
|
9
|
+
* data TEXT NOT NULL, -- JSON.stringify of snapshot
|
|
10
|
+
* version INTEGER NOT NULL,
|
|
11
|
+
* updated_at TEXT NOT NULL -- ISO-8601
|
|
12
|
+
* )
|
|
13
|
+
*
|
|
14
|
+
* Usage:
|
|
15
|
+
* import { Coordinator } from "@brightbeamai/chap-coordinator";
|
|
16
|
+
* import { SqliteStore } from "@brightbeamai/chap-coordinator/storage/sqlite";
|
|
17
|
+
*
|
|
18
|
+
* const coord = new Coordinator({
|
|
19
|
+
* store: new SqliteStore("./chap.db"),
|
|
20
|
+
* });
|
|
21
|
+
*
|
|
22
|
+
* Pass `":memory:"` for an in-memory SQLite instance (faster than the
|
|
23
|
+
* MemoryStore for tests that need transactional semantics).
|
|
24
|
+
*
|
|
25
|
+
* better-sqlite3 is declared as an optionalDependency. If the binary
|
|
26
|
+
* cannot be built (rare on Linux/macOS, common on locked-down CI), the
|
|
27
|
+
* SqliteStore import will throw with a clear message and applications
|
|
28
|
+
* can fall back to MemoryStore or another implementation.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
interface SqliteDatabase {
|
|
32
|
+
exec(sql: string): unknown;
|
|
33
|
+
prepare(sql: string): SqliteStatement;
|
|
34
|
+
pragma(name: string, options?: {
|
|
35
|
+
simple?: boolean;
|
|
36
|
+
}): unknown;
|
|
37
|
+
close(): void;
|
|
38
|
+
}
|
|
39
|
+
interface SqliteStatement {
|
|
40
|
+
run(...params: unknown[]): {
|
|
41
|
+
changes: number;
|
|
42
|
+
lastInsertRowid: number | bigint;
|
|
43
|
+
};
|
|
44
|
+
get(...params: unknown[]): unknown;
|
|
45
|
+
all(...params: unknown[]): unknown[];
|
|
46
|
+
}
|
|
47
|
+
interface SqliteStoreOptions {
|
|
48
|
+
/**
|
|
49
|
+
* Enable WAL journal mode for better concurrent-read performance.
|
|
50
|
+
* Default true. Set false for `:memory:` databases or when the
|
|
51
|
+
* filesystem does not support WAL (some network filesystems).
|
|
52
|
+
*/
|
|
53
|
+
wal?: boolean;
|
|
54
|
+
}
|
|
55
|
+
declare class SqliteStore implements Store {
|
|
56
|
+
readonly db: SqliteDatabase;
|
|
57
|
+
private readonly stmtLoad;
|
|
58
|
+
private readonly stmtSave;
|
|
59
|
+
private readonly stmtDelete;
|
|
60
|
+
constructor(path: string, options?: SqliteStoreOptions);
|
|
61
|
+
load(): WorkspaceRecord[];
|
|
62
|
+
save(record: WorkspaceRecord): void;
|
|
63
|
+
delete(id: string): void;
|
|
64
|
+
close(): void;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export { SqliteStore, type SqliteStoreOptions };
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Store, WorkspaceRecord } from './store.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* SQLite-backed store using better-sqlite3.
|
|
5
|
+
*
|
|
6
|
+
* Schema:
|
|
7
|
+
* CREATE TABLE chap_workspaces (
|
|
8
|
+
* id TEXT PRIMARY KEY,
|
|
9
|
+
* data TEXT NOT NULL, -- JSON.stringify of snapshot
|
|
10
|
+
* version INTEGER NOT NULL,
|
|
11
|
+
* updated_at TEXT NOT NULL -- ISO-8601
|
|
12
|
+
* )
|
|
13
|
+
*
|
|
14
|
+
* Usage:
|
|
15
|
+
* import { Coordinator } from "@brightbeamai/chap-coordinator";
|
|
16
|
+
* import { SqliteStore } from "@brightbeamai/chap-coordinator/storage/sqlite";
|
|
17
|
+
*
|
|
18
|
+
* const coord = new Coordinator({
|
|
19
|
+
* store: new SqliteStore("./chap.db"),
|
|
20
|
+
* });
|
|
21
|
+
*
|
|
22
|
+
* Pass `":memory:"` for an in-memory SQLite instance (faster than the
|
|
23
|
+
* MemoryStore for tests that need transactional semantics).
|
|
24
|
+
*
|
|
25
|
+
* better-sqlite3 is declared as an optionalDependency. If the binary
|
|
26
|
+
* cannot be built (rare on Linux/macOS, common on locked-down CI), the
|
|
27
|
+
* SqliteStore import will throw with a clear message and applications
|
|
28
|
+
* can fall back to MemoryStore or another implementation.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
interface SqliteDatabase {
|
|
32
|
+
exec(sql: string): unknown;
|
|
33
|
+
prepare(sql: string): SqliteStatement;
|
|
34
|
+
pragma(name: string, options?: {
|
|
35
|
+
simple?: boolean;
|
|
36
|
+
}): unknown;
|
|
37
|
+
close(): void;
|
|
38
|
+
}
|
|
39
|
+
interface SqliteStatement {
|
|
40
|
+
run(...params: unknown[]): {
|
|
41
|
+
changes: number;
|
|
42
|
+
lastInsertRowid: number | bigint;
|
|
43
|
+
};
|
|
44
|
+
get(...params: unknown[]): unknown;
|
|
45
|
+
all(...params: unknown[]): unknown[];
|
|
46
|
+
}
|
|
47
|
+
interface SqliteStoreOptions {
|
|
48
|
+
/**
|
|
49
|
+
* Enable WAL journal mode for better concurrent-read performance.
|
|
50
|
+
* Default true. Set false for `:memory:` databases or when the
|
|
51
|
+
* filesystem does not support WAL (some network filesystems).
|
|
52
|
+
*/
|
|
53
|
+
wal?: boolean;
|
|
54
|
+
}
|
|
55
|
+
declare class SqliteStore implements Store {
|
|
56
|
+
readonly db: SqliteDatabase;
|
|
57
|
+
private readonly stmtLoad;
|
|
58
|
+
private readonly stmtSave;
|
|
59
|
+
private readonly stmtDelete;
|
|
60
|
+
constructor(path: string, options?: SqliteStoreOptions);
|
|
61
|
+
load(): WorkspaceRecord[];
|
|
62
|
+
save(record: WorkspaceRecord): void;
|
|
63
|
+
delete(id: string): void;
|
|
64
|
+
close(): void;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export { SqliteStore, type SqliteStoreOptions };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
// src/storage/sqlite.ts
|
|
9
|
+
var SqliteStore = class {
|
|
10
|
+
db;
|
|
11
|
+
stmtLoad;
|
|
12
|
+
stmtSave;
|
|
13
|
+
stmtDelete;
|
|
14
|
+
constructor(path, options = {}) {
|
|
15
|
+
let Database;
|
|
16
|
+
try {
|
|
17
|
+
Database = __require("better-sqlite3");
|
|
18
|
+
} catch (err) {
|
|
19
|
+
throw new Error(
|
|
20
|
+
"SqliteStore requires the `better-sqlite3` package. Install it with `npm install better-sqlite3` or use MemoryStore for non-persistent workloads."
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
this.db = new Database(path);
|
|
24
|
+
if (path !== ":memory:" && options.wal !== false) {
|
|
25
|
+
this.db.pragma("journal_mode = WAL");
|
|
26
|
+
}
|
|
27
|
+
this.db.exec(`
|
|
28
|
+
CREATE TABLE IF NOT EXISTS chap_workspaces (
|
|
29
|
+
id TEXT PRIMARY KEY,
|
|
30
|
+
data TEXT NOT NULL,
|
|
31
|
+
version INTEGER NOT NULL,
|
|
32
|
+
updated_at TEXT NOT NULL
|
|
33
|
+
);
|
|
34
|
+
CREATE INDEX IF NOT EXISTS idx_chap_workspaces_updated_at
|
|
35
|
+
ON chap_workspaces (updated_at);
|
|
36
|
+
`);
|
|
37
|
+
this.stmtLoad = this.db.prepare(
|
|
38
|
+
"SELECT id, data, version, updated_at FROM chap_workspaces"
|
|
39
|
+
);
|
|
40
|
+
this.stmtSave = this.db.prepare(
|
|
41
|
+
"INSERT INTO chap_workspaces (id, data, version, updated_at) VALUES (?, ?, ?, ?) ON CONFLICT(id) DO UPDATE SET data = excluded.data, version = excluded.version, updated_at = excluded.updated_at"
|
|
42
|
+
);
|
|
43
|
+
this.stmtDelete = this.db.prepare(
|
|
44
|
+
"DELETE FROM chap_workspaces WHERE id = ?"
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
load() {
|
|
48
|
+
const rows = this.stmtLoad.all();
|
|
49
|
+
const out = [];
|
|
50
|
+
for (const r of rows) {
|
|
51
|
+
try {
|
|
52
|
+
out.push({ id: r.id, data: JSON.parse(r.data), version: r.version, updated_at: r.updated_at });
|
|
53
|
+
} catch {
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return out;
|
|
57
|
+
}
|
|
58
|
+
save(record) {
|
|
59
|
+
this.stmtSave.run(
|
|
60
|
+
record.id,
|
|
61
|
+
JSON.stringify(record.data),
|
|
62
|
+
record.version,
|
|
63
|
+
record.updated_at
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
delete(id) {
|
|
67
|
+
this.stmtDelete.run(id);
|
|
68
|
+
}
|
|
69
|
+
close() {
|
|
70
|
+
this.db.close();
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
export {
|
|
74
|
+
SqliteStore
|
|
75
|
+
};
|
|
76
|
+
//# sourceMappingURL=sqlite.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/storage/sqlite.ts"],"sourcesContent":["/**\n * SQLite-backed store using better-sqlite3.\n *\n * Schema:\n * CREATE TABLE chap_workspaces (\n * id TEXT PRIMARY KEY,\n * data TEXT NOT NULL, -- JSON.stringify of snapshot\n * version INTEGER NOT NULL,\n * updated_at TEXT NOT NULL -- ISO-8601\n * )\n *\n * Usage:\n * import { Coordinator } from \"@brightbeamai/chap-coordinator\";\n * import { SqliteStore } from \"@brightbeamai/chap-coordinator/storage/sqlite\";\n *\n * const coord = new Coordinator({\n * store: new SqliteStore(\"./chap.db\"),\n * });\n *\n * Pass `\":memory:\"` for an in-memory SQLite instance (faster than the\n * MemoryStore for tests that need transactional semantics).\n *\n * better-sqlite3 is declared as an optionalDependency. If the binary\n * cannot be built (rare on Linux/macOS, common on locked-down CI), the\n * SqliteStore import will throw with a clear message and applications\n * can fall back to MemoryStore or another implementation.\n */\n\nimport type { Store, WorkspaceRecord } from \"./store.js\";\n\n// better-sqlite3 has no published types in its own package, but the\n// `@types/better-sqlite3` package provides them. We require a structural\n// subset so the file type-checks even if the typings are absent.\ninterface SqliteDatabase {\n exec(sql: string): unknown;\n prepare(sql: string): SqliteStatement;\n pragma(name: string, options?: { simple?: boolean }): unknown;\n close(): void;\n}\ninterface SqliteStatement {\n run(...params: unknown[]): { changes: number; lastInsertRowid: number | bigint };\n get(...params: unknown[]): unknown;\n all(...params: unknown[]): unknown[];\n}\n\nexport interface SqliteStoreOptions {\n /**\n * Enable WAL journal mode for better concurrent-read performance.\n * Default true. Set false for `:memory:` databases or when the\n * filesystem does not support WAL (some network filesystems).\n */\n wal?: boolean;\n}\n\nexport class SqliteStore implements Store {\n readonly db: SqliteDatabase;\n private readonly stmtLoad: SqliteStatement;\n private readonly stmtSave: SqliteStatement;\n private readonly stmtDelete: SqliteStatement;\n\n constructor(path: string, options: SqliteStoreOptions = {}) {\n let Database: new (path: string) => SqliteDatabase;\n try {\n // require() is used so the dependency stays optional. ESM consumers\n // can still load this file; the actual import is dynamic.\n Database = require(\"better-sqlite3\");\n } catch (err) {\n throw new Error(\n \"SqliteStore requires the `better-sqlite3` package. \" +\n \"Install it with `npm install better-sqlite3` \" +\n \"or use MemoryStore for non-persistent workloads.\",\n );\n }\n\n this.db = new Database(path);\n if (path !== \":memory:\" && options.wal !== false) {\n this.db.pragma(\"journal_mode = WAL\");\n }\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS chap_workspaces (\n id TEXT PRIMARY KEY,\n data TEXT NOT NULL,\n version INTEGER NOT NULL,\n updated_at TEXT NOT NULL\n );\n CREATE INDEX IF NOT EXISTS idx_chap_workspaces_updated_at\n ON chap_workspaces (updated_at);\n `);\n\n this.stmtLoad = this.db.prepare(\n \"SELECT id, data, version, updated_at FROM chap_workspaces\",\n );\n this.stmtSave = this.db.prepare(\n \"INSERT INTO chap_workspaces (id, data, version, updated_at) \" +\n \"VALUES (?, ?, ?, ?) \" +\n \"ON CONFLICT(id) DO UPDATE SET \" +\n \"data = excluded.data, \" +\n \"version = excluded.version, \" +\n \"updated_at = excluded.updated_at\",\n );\n this.stmtDelete = this.db.prepare(\n \"DELETE FROM chap_workspaces WHERE id = ?\",\n );\n }\n\n load(): WorkspaceRecord[] {\n const rows = this.stmtLoad.all() as Array<{\n id: string;\n data: string;\n version: number;\n updated_at: string;\n }>;\n const out: WorkspaceRecord[] = [];\n for (const r of rows) {\n try {\n out.push({ id: r.id, data: JSON.parse(r.data), version: r.version, updated_at: r.updated_at });\n } catch {\n // A single unreadable row must not discard every other workspace; skip it.\n }\n }\n return out;\n }\n\n save(record: WorkspaceRecord): void {\n this.stmtSave.run(\n record.id,\n JSON.stringify(record.data),\n record.version,\n record.updated_at,\n );\n }\n\n delete(id: string): void {\n this.stmtDelete.run(id);\n }\n\n close(): void {\n this.db.close();\n }\n}\n"],"mappings":";;;;;;;;AAsDO,IAAM,cAAN,MAAmC;AAAA,EAC/B;AAAA,EACQ;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,MAAc,UAA8B,CAAC,GAAG;AAC1D,QAAI;AACJ,QAAI;AAGF,iBAAW,UAAQ,gBAAgB;AAAA,IACrC,SAAS,KAAK;AACZ,YAAM,IAAI;AAAA,QACR;AAAA,MAGF;AAAA,IACF;AAEA,SAAK,KAAK,IAAI,SAAS,IAAI;AAC3B,QAAI,SAAS,cAAc,QAAQ,QAAQ,OAAO;AAChD,WAAK,GAAG,OAAO,oBAAoB;AAAA,IACrC;AACA,SAAK,GAAG,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KASZ;AAED,SAAK,WAAW,KAAK,GAAG;AAAA,MACtB;AAAA,IACF;AACA,SAAK,WAAW,KAAK,GAAG;AAAA,MACtB;AAAA,IAMF;AACA,SAAK,aAAa,KAAK,GAAG;AAAA,MACxB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAA0B;AACxB,UAAM,OAAO,KAAK,SAAS,IAAI;AAM/B,UAAM,MAAyB,CAAC;AAChC,eAAW,KAAK,MAAM;AACpB,UAAI;AACF,YAAI,KAAK,EAAE,IAAI,EAAE,IAAI,MAAM,KAAK,MAAM,EAAE,IAAI,GAAG,SAAS,EAAE,SAAS,YAAY,EAAE,WAAW,CAAC;AAAA,MAC/F,QAAQ;AAAA,MAER;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,KAAK,QAA+B;AAClC,SAAK,SAAS;AAAA,MACZ,OAAO;AAAA,MACP,KAAK,UAAU,OAAO,IAAI;AAAA,MAC1B,OAAO;AAAA,MACP,OAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,OAAO,IAAkB;AACvB,SAAK,WAAW,IAAI,EAAE;AAAA,EACxB;AAAA,EAEA,QAAc;AACZ,SAAK,GAAG,MAAM;AAAA,EAChB;AACF;","names":[]}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/storage/store.ts
|
|
21
|
+
var store_exports = {};
|
|
22
|
+
__export(store_exports, {
|
|
23
|
+
MemoryStore: () => MemoryStore
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(store_exports);
|
|
26
|
+
var MemoryStore = class {
|
|
27
|
+
records = /* @__PURE__ */ new Map();
|
|
28
|
+
load() {
|
|
29
|
+
return Array.from(this.records.values());
|
|
30
|
+
}
|
|
31
|
+
save(record) {
|
|
32
|
+
this.records.set(record.id, record);
|
|
33
|
+
}
|
|
34
|
+
delete(id) {
|
|
35
|
+
this.records.delete(id);
|
|
36
|
+
}
|
|
37
|
+
close() {
|
|
38
|
+
this.records.clear();
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
42
|
+
0 && (module.exports = {
|
|
43
|
+
MemoryStore
|
|
44
|
+
});
|
|
45
|
+
//# sourceMappingURL=store.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/storage/store.ts"],"sourcesContent":["/**\n * Pluggable persistence for the Coordinator.\n *\n * A Store persists workspace state between process restarts. Coordinators\n * call `store.save(workspaceId, snapshot)` after every mutation that\n * appends to the audit chain, and `store.load()` on startup to restore.\n *\n * Two implementations ship in-tree:\n * - MemoryStore (default, no persistence; existing behaviour)\n * - SqliteStore (real SQLite via better-sqlite3, opt-in)\n *\n * Third-party stores (Postgres, Redis, etc.) implement this interface.\n *\n * Stores hold per-workspace JSON snapshots, not a decomposed relational\n * model. The Coordinator's snapshot/restore methods produce JSON-safe\n * payloads; this is fast for workspaces in the low-thousands of audit\n * entries and trades query flexibility for simplicity. Production\n * deployments needing rich query semantics should project the audit log\n * into their own analytics store via the `onAudit` listener.\n */\n\nexport interface WorkspaceRecord {\n /** Workspace identifier. */\n id: string;\n /** JSON-serialisable payload produced by `Coordinator.snapshot()`. */\n data: unknown;\n /** Monotonically increasing version for optimistic concurrency. */\n version: number;\n /** Wall-clock timestamp of the last write, ISO-8601. */\n updated_at: string;\n}\n\nexport interface Store {\n /** Load all workspace records into memory. Called once on coordinator start. */\n load(): Promise<WorkspaceRecord[]> | WorkspaceRecord[];\n\n /** Persist one workspace record. Called after every mutation. */\n save(record: WorkspaceRecord): Promise<void> | void;\n\n /** Remove one workspace. Used by `workspace.delete` semantics (not in v0.2). */\n delete(id: string): Promise<void> | void;\n\n /** Release resources. Idempotent. */\n close?(): Promise<void> | void;\n}\n\n/**\n * In-memory store. Default behaviour: no persistence, fast tests.\n * State lives in a Map; closing it discards everything.\n */\nexport class MemoryStore implements Store {\n private records = new Map<string, WorkspaceRecord>();\n\n load(): WorkspaceRecord[] {\n return Array.from(this.records.values());\n }\n\n save(record: WorkspaceRecord): void {\n this.records.set(record.id, record);\n }\n\n delete(id: string): void {\n this.records.delete(id);\n }\n\n close(): void {\n this.records.clear();\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAkDO,IAAM,cAAN,MAAmC;AAAA,EAChC,UAAU,oBAAI,IAA6B;AAAA,EAEnD,OAA0B;AACxB,WAAO,MAAM,KAAK,KAAK,QAAQ,OAAO,CAAC;AAAA,EACzC;AAAA,EAEA,KAAK,QAA+B;AAClC,SAAK,QAAQ,IAAI,OAAO,IAAI,MAAM;AAAA,EACpC;AAAA,EAEA,OAAO,IAAkB;AACvB,SAAK,QAAQ,OAAO,EAAE;AAAA,EACxB;AAAA,EAEA,QAAc;AACZ,SAAK,QAAQ,MAAM;AAAA,EACrB;AACF;","names":[]}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pluggable persistence for the Coordinator.
|
|
3
|
+
*
|
|
4
|
+
* A Store persists workspace state between process restarts. Coordinators
|
|
5
|
+
* call `store.save(workspaceId, snapshot)` after every mutation that
|
|
6
|
+
* appends to the audit chain, and `store.load()` on startup to restore.
|
|
7
|
+
*
|
|
8
|
+
* Two implementations ship in-tree:
|
|
9
|
+
* - MemoryStore (default, no persistence; existing behaviour)
|
|
10
|
+
* - SqliteStore (real SQLite via better-sqlite3, opt-in)
|
|
11
|
+
*
|
|
12
|
+
* Third-party stores (Postgres, Redis, etc.) implement this interface.
|
|
13
|
+
*
|
|
14
|
+
* Stores hold per-workspace JSON snapshots, not a decomposed relational
|
|
15
|
+
* model. The Coordinator's snapshot/restore methods produce JSON-safe
|
|
16
|
+
* payloads; this is fast for workspaces in the low-thousands of audit
|
|
17
|
+
* entries and trades query flexibility for simplicity. Production
|
|
18
|
+
* deployments needing rich query semantics should project the audit log
|
|
19
|
+
* into their own analytics store via the `onAudit` listener.
|
|
20
|
+
*/
|
|
21
|
+
interface WorkspaceRecord {
|
|
22
|
+
/** Workspace identifier. */
|
|
23
|
+
id: string;
|
|
24
|
+
/** JSON-serialisable payload produced by `Coordinator.snapshot()`. */
|
|
25
|
+
data: unknown;
|
|
26
|
+
/** Monotonically increasing version for optimistic concurrency. */
|
|
27
|
+
version: number;
|
|
28
|
+
/** Wall-clock timestamp of the last write, ISO-8601. */
|
|
29
|
+
updated_at: string;
|
|
30
|
+
}
|
|
31
|
+
interface Store {
|
|
32
|
+
/** Load all workspace records into memory. Called once on coordinator start. */
|
|
33
|
+
load(): Promise<WorkspaceRecord[]> | WorkspaceRecord[];
|
|
34
|
+
/** Persist one workspace record. Called after every mutation. */
|
|
35
|
+
save(record: WorkspaceRecord): Promise<void> | void;
|
|
36
|
+
/** Remove one workspace. Used by `workspace.delete` semantics (not in v0.2). */
|
|
37
|
+
delete(id: string): Promise<void> | void;
|
|
38
|
+
/** Release resources. Idempotent. */
|
|
39
|
+
close?(): Promise<void> | void;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* In-memory store. Default behaviour: no persistence, fast tests.
|
|
43
|
+
* State lives in a Map; closing it discards everything.
|
|
44
|
+
*/
|
|
45
|
+
declare class MemoryStore implements Store {
|
|
46
|
+
private records;
|
|
47
|
+
load(): WorkspaceRecord[];
|
|
48
|
+
save(record: WorkspaceRecord): void;
|
|
49
|
+
delete(id: string): void;
|
|
50
|
+
close(): void;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export { MemoryStore, type Store, type WorkspaceRecord };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pluggable persistence for the Coordinator.
|
|
3
|
+
*
|
|
4
|
+
* A Store persists workspace state between process restarts. Coordinators
|
|
5
|
+
* call `store.save(workspaceId, snapshot)` after every mutation that
|
|
6
|
+
* appends to the audit chain, and `store.load()` on startup to restore.
|
|
7
|
+
*
|
|
8
|
+
* Two implementations ship in-tree:
|
|
9
|
+
* - MemoryStore (default, no persistence; existing behaviour)
|
|
10
|
+
* - SqliteStore (real SQLite via better-sqlite3, opt-in)
|
|
11
|
+
*
|
|
12
|
+
* Third-party stores (Postgres, Redis, etc.) implement this interface.
|
|
13
|
+
*
|
|
14
|
+
* Stores hold per-workspace JSON snapshots, not a decomposed relational
|
|
15
|
+
* model. The Coordinator's snapshot/restore methods produce JSON-safe
|
|
16
|
+
* payloads; this is fast for workspaces in the low-thousands of audit
|
|
17
|
+
* entries and trades query flexibility for simplicity. Production
|
|
18
|
+
* deployments needing rich query semantics should project the audit log
|
|
19
|
+
* into their own analytics store via the `onAudit` listener.
|
|
20
|
+
*/
|
|
21
|
+
interface WorkspaceRecord {
|
|
22
|
+
/** Workspace identifier. */
|
|
23
|
+
id: string;
|
|
24
|
+
/** JSON-serialisable payload produced by `Coordinator.snapshot()`. */
|
|
25
|
+
data: unknown;
|
|
26
|
+
/** Monotonically increasing version for optimistic concurrency. */
|
|
27
|
+
version: number;
|
|
28
|
+
/** Wall-clock timestamp of the last write, ISO-8601. */
|
|
29
|
+
updated_at: string;
|
|
30
|
+
}
|
|
31
|
+
interface Store {
|
|
32
|
+
/** Load all workspace records into memory. Called once on coordinator start. */
|
|
33
|
+
load(): Promise<WorkspaceRecord[]> | WorkspaceRecord[];
|
|
34
|
+
/** Persist one workspace record. Called after every mutation. */
|
|
35
|
+
save(record: WorkspaceRecord): Promise<void> | void;
|
|
36
|
+
/** Remove one workspace. Used by `workspace.delete` semantics (not in v0.2). */
|
|
37
|
+
delete(id: string): Promise<void> | void;
|
|
38
|
+
/** Release resources. Idempotent. */
|
|
39
|
+
close?(): Promise<void> | void;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* In-memory store. Default behaviour: no persistence, fast tests.
|
|
43
|
+
* State lives in a Map; closing it discards everything.
|
|
44
|
+
*/
|
|
45
|
+
declare class MemoryStore implements Store {
|
|
46
|
+
private records;
|
|
47
|
+
load(): WorkspaceRecord[];
|
|
48
|
+
save(record: WorkspaceRecord): void;
|
|
49
|
+
delete(id: string): void;
|
|
50
|
+
close(): void;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export { MemoryStore, type Store, type WorkspaceRecord };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// src/storage/store.ts
|
|
2
|
+
var MemoryStore = class {
|
|
3
|
+
records = /* @__PURE__ */ new Map();
|
|
4
|
+
load() {
|
|
5
|
+
return Array.from(this.records.values());
|
|
6
|
+
}
|
|
7
|
+
save(record) {
|
|
8
|
+
this.records.set(record.id, record);
|
|
9
|
+
}
|
|
10
|
+
delete(id) {
|
|
11
|
+
this.records.delete(id);
|
|
12
|
+
}
|
|
13
|
+
close() {
|
|
14
|
+
this.records.clear();
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
export {
|
|
18
|
+
MemoryStore
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/storage/store.ts"],"sourcesContent":["/**\n * Pluggable persistence for the Coordinator.\n *\n * A Store persists workspace state between process restarts. Coordinators\n * call `store.save(workspaceId, snapshot)` after every mutation that\n * appends to the audit chain, and `store.load()` on startup to restore.\n *\n * Two implementations ship in-tree:\n * - MemoryStore (default, no persistence; existing behaviour)\n * - SqliteStore (real SQLite via better-sqlite3, opt-in)\n *\n * Third-party stores (Postgres, Redis, etc.) implement this interface.\n *\n * Stores hold per-workspace JSON snapshots, not a decomposed relational\n * model. The Coordinator's snapshot/restore methods produce JSON-safe\n * payloads; this is fast for workspaces in the low-thousands of audit\n * entries and trades query flexibility for simplicity. Production\n * deployments needing rich query semantics should project the audit log\n * into their own analytics store via the `onAudit` listener.\n */\n\nexport interface WorkspaceRecord {\n /** Workspace identifier. */\n id: string;\n /** JSON-serialisable payload produced by `Coordinator.snapshot()`. */\n data: unknown;\n /** Monotonically increasing version for optimistic concurrency. */\n version: number;\n /** Wall-clock timestamp of the last write, ISO-8601. */\n updated_at: string;\n}\n\nexport interface Store {\n /** Load all workspace records into memory. Called once on coordinator start. */\n load(): Promise<WorkspaceRecord[]> | WorkspaceRecord[];\n\n /** Persist one workspace record. Called after every mutation. */\n save(record: WorkspaceRecord): Promise<void> | void;\n\n /** Remove one workspace. Used by `workspace.delete` semantics (not in v0.2). */\n delete(id: string): Promise<void> | void;\n\n /** Release resources. Idempotent. */\n close?(): Promise<void> | void;\n}\n\n/**\n * In-memory store. Default behaviour: no persistence, fast tests.\n * State lives in a Map; closing it discards everything.\n */\nexport class MemoryStore implements Store {\n private records = new Map<string, WorkspaceRecord>();\n\n load(): WorkspaceRecord[] {\n return Array.from(this.records.values());\n }\n\n save(record: WorkspaceRecord): void {\n this.records.set(record.id, record);\n }\n\n delete(id: string): void {\n this.records.delete(id);\n }\n\n close(): void {\n this.records.clear();\n }\n}\n"],"mappings":";AAkDO,IAAM,cAAN,MAAmC;AAAA,EAChC,UAAU,oBAAI,IAA6B;AAAA,EAEnD,OAA0B;AACxB,WAAO,MAAM,KAAK,KAAK,QAAQ,OAAO,CAAC;AAAA,EACzC;AAAA,EAEA,KAAK,QAA+B;AAClC,SAAK,QAAQ,IAAI,OAAO,IAAI,MAAM;AAAA,EACpC;AAAA,EAEA,OAAO,IAAkB;AACvB,SAAK,QAAQ,OAAO,EAAE;AAAA,EACxB;AAAA,EAEA,QAAc;AACZ,SAAK,QAAQ,MAAM;AAAA,EACrB;AACF;","names":[]}
|
package/dist/types.cjs
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/types.ts
|
|
21
|
+
var types_exports = {};
|
|
22
|
+
__export(types_exports, {
|
|
23
|
+
modeLE: () => modeLE
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(types_exports);
|
|
26
|
+
function modeLE(a, ceiling) {
|
|
27
|
+
const order = { shadow: 0, trial: 1, production: 2 };
|
|
28
|
+
return order[a] <= order[ceiling];
|
|
29
|
+
}
|
|
30
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
31
|
+
0 && (module.exports = {
|
|
32
|
+
modeLE
|
|
33
|
+
});
|
|
34
|
+
//# sourceMappingURL=types.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["/**\n * @brightbeamai/chap-coordinator. type vocabulary\n *\n * Wire-shape and in-memory types for the Coordinator. The schemas at\n * schemas/ are the normative wire types; these mirror them in\n * TypeScript for in-process use.\n */\n\nexport type ParticipantUri = string;\nexport type WorkspaceId = string;\nexport type TaskId = string;\nexport type ArtefactId = string;\n\nexport type ParticipantType = \"human\" | \"agent\" | \"service\" | \"group\" | \"workspace\";\n\nexport interface Envelope {\n jsonrpc: \"2.0\";\n id?: string | number;\n method?: string;\n params?: Record<string, unknown>;\n result?: unknown;\n error?: { code: number; message: string; data?: unknown };\n /** security-signed/1.0: top-level signature, signed over JCS of the\n * envelope with this field removed. Form: ``ed25519:<kid>:<b64>``. */\n sig?: string;\n}\n\nexport type Mode = \"shadow\" | \"trial\" | \"production\";\nexport type WorkspaceState = \"active\" | \"paused\" | \"closed\";\nexport type PauseScope = \"task\" | \"participant\" | \"workspace\";\n\nexport type TaskState =\n | \"created\"\n | \"in_progress\"\n | \"review_requested\"\n | \"completed\"\n | \"declined\"\n | \"abstained\"\n | \"escalated\"\n | \"superseded\"\n | \"paused\"\n | \"cancelled\";\n\n// ============================================================\n// Key records (security-signed/1.0)\n// ============================================================\n\nexport interface Jwk {\n kty: \"OKP\";\n crv: \"Ed25519\";\n kid: string;\n x: string;\n use?: string;\n alg?: string;\n}\n\n/** A participant's JWK plus the validity window. Lookup by\n * (participant, kid, ts) so historical envelopes verify across\n * rotation per security-signed/1.0 S3-S5. */\nexport interface KeyRecord {\n jwk: Jwk;\n kid: string;\n valid_from: string; // ISO timestamp; inclusive\n valid_until?: string; // ISO timestamp; exclusive; absent = unbounded\n revoked_at?: string;\n revoked_reason?: string;\n}\n\n// ============================================================\n// Participants\n// ============================================================\n\nexport interface Member {\n uri: ParticipantUri;\n type: ParticipantType;\n role: string;\n joined: string;\n display_name?: string;\n capabilities?: Record<string, unknown>;\n scopes?: string[];\n keys: KeyRecord[];\n paused: boolean; // control.pause scope=participant\n oidc_sub?: string;\n oidc_auth_time?: number; // unix seconds\n vc_holder?: string;\n}\n\n// ============================================================\n// Routing hints\n// ============================================================\n\nexport interface TaskRoutingHints {\n criticality?: \"low\" | \"medium\" | \"high\" | \"critical\";\n deadline?: string;\n max_cost_usd?: number;\n risk_tier?: string;\n [extra: string]: unknown;\n}\n\nexport interface ArtefactRoutingHints {\n confidence?: number | string;\n model_id?: string;\n cost_consumed_usd?: number;\n latency_ms?: number;\n [extra: string]: unknown;\n}\n\n// ============================================================\n// JSON Patch (RFC 6902)\n// ============================================================\n\nexport interface JsonPatchOp {\n op: \"add\" | \"replace\" | \"remove\" | \"copy\" | \"move\" | \"test\";\n path: string;\n value?: unknown;\n from?: string;\n}\n\n// ============================================================\n// Override artefact (review/1.0)\n// ============================================================\n\nexport interface OverrideArtefact {\n id: ArtefactId;\n task_id: TaskId;\n reviewer: ParticipantUri;\n based_on_artefact: unknown;\n diff: JsonPatchOp[];\n result: unknown;\n rationale: string;\n tags: string[];\n policy_refs: string[];\n ts: string;\n logical_id?: string;\n instance_id?: string;\n intent_preserved?: boolean;\n}\n\n// ============================================================\n// Route decision artefact (routing/1.0)\n// ============================================================\n\nexport interface RouteDecisionArtefact {\n id: ArtefactId;\n kind: \"route_decision\";\n decision_type: \"task.route\" | \"review.depth\" | \"escalate.auto\";\n outcome: unknown;\n produced_by: ParticipantUri;\n produced_at: string;\n task?: TaskId;\n policy_id?: string;\n hints_observed: Record<string, unknown>;\n rationale: string;\n // Auxiliary fields per decision_type:\n // task.route: alternatives_considered\n // review.depth: sampling_probability\n // escalate.auto: escalation_target\n [extra: string]: unknown;\n}\n\n// ============================================================\n// Snapshot artefact (control/1.0)\n// ============================================================\n\nexport interface SnapshotArtefact {\n id: ArtefactId;\n kind: \"snapshot\";\n ts: string;\n by: ParticipantUri;\n workspace: WorkspaceId;\n audit_seq: number;\n label?: string;\n include: string[];\n state: Record<string, unknown>;\n}\n\n// ============================================================\n// Whisper (whisper/1.0)\n// ============================================================\n\nexport interface WhisperPrompt {\n id: ArtefactId;\n task_id: TaskId;\n asker: ParticipantUri;\n askee: ParticipantUri[];\n question: string;\n options?: Array<{ id: string; label?: string }>;\n asked_at: string;\n deadline_ms: number;\n default_if_lapsed: unknown;\n urgency: \"low\" | \"medium\" | \"high\";\n state: \"pending\" | \"answered\" | \"lapsed\";\n answered_at?: string;\n answered_by?: ParticipantUri;\n answer_option?: string;\n answer_text?: string;\n comment?: string;\n default_applied?: unknown;\n}\n\n// ============================================================\n// Deliberation (deliberation/1.0)\n// ============================================================\n\nexport interface DeliberationVote {\n ts: string;\n voter: ParticipantUri;\n vote: \"yea\" | \"nay\" | \"abstain\";\n weight?: number;\n comment?: string;\n veto_invoked?: boolean;\n}\n\nexport interface Deliberation {\n id: string;\n task_id?: TaskId;\n opener: ParticipantUri;\n participants: ParticipantUri[];\n rule: string; // raw rule string\n question?: string;\n weights?: Record<ParticipantUri, number>;\n veto?: Record<ParticipantUri, boolean>;\n deadline?: string;\n state: \"open\" | \"closed\" | \"lapsed\";\n comments: { ts: string; from: ParticipantUri; text: string }[];\n votes: DeliberationVote[];\n outcome?: {\n outcome: \"approved\" | \"rejected\" | \"error\";\n rule: string;\n tally?: { yea: number; nay: number };\n vetoes?: ParticipantUri[];\n reason?: string;\n };\n opened_at: string;\n}\n\n// ============================================================\n// Handoff (handoff/1.0)\n// ============================================================\n\nexport interface HandoffTaskItem {\n task_id: TaskId;\n title?: string;\n status_summary?: string;\n next_action?: string;\n blockers?: string[];\n}\n\nexport interface Handoff {\n id: string;\n proposer: ParticipantUri;\n recipient: ParticipantUri; // single URI or \"group:...\"\n proposed_at: string;\n tasks: HandoffTaskItem[];\n summary?: string;\n context_links: string[];\n state: \"proposed\" | \"accepted\" | \"declined\";\n resolved_at?: string;\n accepted_by?: ParticipantUri;\n accepted_task_ids?: TaskId[];\n accept_comment?: string;\n decline_reason?: string;\n decline_suggested_target?: ParticipantUri;\n}\n\n// ============================================================\n// Review decision (review/1.0)\n// ============================================================\n\nexport interface ReviewDecision {\n reviewer: ParticipantUri;\n kind: \"approve\" | \"reject\" | \"override\" | \"abstain\";\n ts: string;\n comment?: string;\n tags?: string[];\n override_artefact_id?: ArtefactId;\n abstain_category?: string;\n}\n\n// ============================================================\n// Task\n// ============================================================\n\nexport interface Task {\n id: TaskId;\n kind: string;\n state: TaskState;\n assignee: ParticipantUri;\n delegator: ParticipantUri;\n input: Record<string, unknown>;\n output?: unknown;\n confidence?: number | string;\n deadline?: string;\n created_at: string;\n updated_at: string;\n mode: Mode;\n review_required?: boolean;\n routing_hints?: TaskRoutingHints;\n artefact_routing_hints?: ArtefactRoutingHints;\n review?: {\n requested_at: string;\n requested_to: ParticipantUri[];\n rule: string;\n deadline?: string;\n decisions: ReviewDecision[];\n };\n history: { ts: string; from: ParticipantUri; state: TaskState; note?: string }[];\n supersedes?: TaskId;\n superseded_by?: TaskId;\n parent?: TaskId;\n paused: boolean;\n /** Transient: holds the artefact passed to review.request so\n * decide.override can use it as the patch base. */\n pending_artefact?: unknown;\n}\n\n// ============================================================\n// Audit\n// ============================================================\n\nexport interface AuditEntry {\n seq: number;\n arrived: string;\n envelope: Envelope;\n prev_hash?: string;\n}\n\n// ============================================================\n// Workspace\n// ============================================================\n\nexport interface Workspace {\n id: WorkspaceId;\n created: string;\n state: WorkspaceState;\n profiles: string[];\n mode: Mode;\n mode_ceiling: Mode;\n routing_policy_uri?: string;\n step_up_window_sec: number;\n members: Map<ParticipantUri, Member>;\n tasks: Map<TaskId, Task>;\n overrides: Map<ArtefactId, OverrideArtefact>;\n whispers: Map<string, WhisperPrompt>;\n deliberations: Map<string, Deliberation>;\n handoffs: Map<string, Handoff>;\n snapshots: Map<ArtefactId, SnapshotArtefact>;\n route_decisions: Map<ArtefactId, RouteDecisionArtefact>;\n audit: AuditEntry[];\n chain_head?: string;\n chain_enabled: boolean;\n}\n\n/**\n * Listener callback invoked synchronously when an envelope is appended\n * to the workspace audit log.\n */\nexport type AuditListener = (workspace: Workspace, entry: AuditEntry) => void;\n\n/** True iff mode `a` is <= ceiling. */\nexport function modeLE(a: Mode, ceiling: Mode): boolean {\n const order: Record<Mode, number> = { shadow: 0, trial: 1, production: 2 };\n return order[a] <= order[ceiling];\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAwWO,SAAS,OAAO,GAAS,SAAwB;AACtD,QAAM,QAA8B,EAAE,QAAQ,GAAG,OAAO,GAAG,YAAY,EAAE;AACzE,SAAO,MAAM,CAAC,KAAK,MAAM,OAAO;AAClC;","names":[]}
|