@hexis-ai/engram-server 0.1.5 → 0.1.6
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/dist/adapters/postgres-key-store.d.ts +4 -1
- package/dist/adapters/postgres-key-store.js +6 -24
- package/dist/adapters/postgres.d.ts +2 -2
- package/dist/adapters/postgres.js +4 -52
- package/dist/main.js +4 -14
- package/dist/migrations/0001-baseline.d.ts +2 -0
- package/dist/migrations/0001-baseline.js +72 -0
- package/dist/migrations/index.d.ts +12 -0
- package/dist/migrations/index.js +9 -0
- package/dist/migrator.d.ts +17 -0
- package/dist/migrator.js +37 -0
- package/package.json +12 -3
|
@@ -3,7 +3,10 @@ import type { SqlClient } from "./postgres";
|
|
|
3
3
|
export declare class PostgresKeyStore implements KeyStore {
|
|
4
4
|
private readonly sql;
|
|
5
5
|
constructor(sql: SqlClient);
|
|
6
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* Apply all pending schema migrations. Safe to call repeatedly and
|
|
8
|
+
* concurrently with other instances — see `runMigrations` for details.
|
|
9
|
+
*/
|
|
7
10
|
ensureSchema(): Promise<void>;
|
|
8
11
|
createWorkspace(input: {
|
|
9
12
|
id?: string;
|
|
@@ -1,34 +1,16 @@
|
|
|
1
1
|
import { generateRawKey, hashKey, isValidWorkspaceId, keyPrefix, } from "../key-store";
|
|
2
|
-
|
|
3
|
-
CREATE TABLE IF NOT EXISTS engram_workspaces (
|
|
4
|
-
id TEXT PRIMARY KEY,
|
|
5
|
-
name TEXT,
|
|
6
|
-
metadata JSONB NOT NULL DEFAULT '{}',
|
|
7
|
-
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
8
|
-
);
|
|
9
|
-
|
|
10
|
-
CREATE TABLE IF NOT EXISTS engram_api_keys (
|
|
11
|
-
id TEXT PRIMARY KEY,
|
|
12
|
-
workspace_id TEXT NOT NULL REFERENCES engram_workspaces(id) ON DELETE CASCADE,
|
|
13
|
-
key_hash TEXT NOT NULL UNIQUE,
|
|
14
|
-
prefix TEXT NOT NULL,
|
|
15
|
-
name TEXT,
|
|
16
|
-
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
17
|
-
last_used_at TIMESTAMPTZ,
|
|
18
|
-
revoked_at TIMESTAMPTZ
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
CREATE INDEX IF NOT EXISTS idx_engram_api_keys_workspace
|
|
22
|
-
ON engram_api_keys (workspace_id);
|
|
23
|
-
`;
|
|
2
|
+
import { runMigrations } from "../migrator";
|
|
24
3
|
export class PostgresKeyStore {
|
|
25
4
|
sql;
|
|
26
5
|
constructor(sql) {
|
|
27
6
|
this.sql = sql;
|
|
28
7
|
}
|
|
29
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
* Apply all pending schema migrations. Safe to call repeatedly and
|
|
10
|
+
* concurrently with other instances — see `runMigrations` for details.
|
|
11
|
+
*/
|
|
30
12
|
async ensureSchema() {
|
|
31
|
-
await this.sql
|
|
13
|
+
await runMigrations(this.sql);
|
|
32
14
|
}
|
|
33
15
|
async createWorkspace(input) {
|
|
34
16
|
const id = input.id ?? crypto.randomUUID();
|
|
@@ -27,8 +27,8 @@ export declare class PostgresAdapter implements StorageAdapter {
|
|
|
27
27
|
private readonly newPersonId;
|
|
28
28
|
constructor(opts: PostgresAdapterOptions);
|
|
29
29
|
/**
|
|
30
|
-
*
|
|
31
|
-
*
|
|
30
|
+
* Apply all pending schema migrations. Safe to call repeatedly and
|
|
31
|
+
* concurrently with other instances — see `runMigrations` for details.
|
|
32
32
|
*/
|
|
33
33
|
ensureSchema(): Promise<void>;
|
|
34
34
|
createSession(init: SessionInit & {
|
|
@@ -1,53 +1,5 @@
|
|
|
1
|
+
import { runMigrations } from "../migrator";
|
|
1
2
|
import { foldEvents } from "../storage";
|
|
2
|
-
const SCHEMA_SQL = `
|
|
3
|
-
CREATE TABLE IF NOT EXISTS engram_sessions (
|
|
4
|
-
workspace_id TEXT NOT NULL,
|
|
5
|
-
id TEXT NOT NULL,
|
|
6
|
-
title TEXT,
|
|
7
|
-
channel TEXT,
|
|
8
|
-
participants TEXT[] NOT NULL DEFAULT '{}',
|
|
9
|
-
viewable_by TEXT[] NOT NULL DEFAULT '{}',
|
|
10
|
-
created_at TIMESTAMPTZ NOT NULL,
|
|
11
|
-
PRIMARY KEY (workspace_id, id)
|
|
12
|
-
);
|
|
13
|
-
|
|
14
|
-
-- Existing deployments may pre-date viewable_by; backfill the column on
|
|
15
|
-
-- upgrade. Idempotent.
|
|
16
|
-
ALTER TABLE engram_sessions ADD COLUMN IF NOT EXISTS viewable_by TEXT[] NOT NULL DEFAULT '{}';
|
|
17
|
-
|
|
18
|
-
CREATE TABLE IF NOT EXISTS engram_events (
|
|
19
|
-
workspace_id TEXT NOT NULL,
|
|
20
|
-
session_id TEXT NOT NULL,
|
|
21
|
-
seq INTEGER NOT NULL,
|
|
22
|
-
type TEXT NOT NULL,
|
|
23
|
-
at TIMESTAMPTZ NOT NULL,
|
|
24
|
-
payload JSONB NOT NULL,
|
|
25
|
-
PRIMARY KEY (workspace_id, session_id, seq),
|
|
26
|
-
FOREIGN KEY (workspace_id, session_id)
|
|
27
|
-
REFERENCES engram_sessions(workspace_id, id) ON DELETE CASCADE
|
|
28
|
-
);
|
|
29
|
-
|
|
30
|
-
CREATE TABLE IF NOT EXISTS engram_persons (
|
|
31
|
-
workspace_id TEXT NOT NULL,
|
|
32
|
-
id TEXT NOT NULL,
|
|
33
|
-
display_name TEXT,
|
|
34
|
-
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
35
|
-
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
36
|
-
PRIMARY KEY (workspace_id, id)
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
CREATE INDEX IF NOT EXISTS idx_engram_sessions_workspace_created
|
|
40
|
-
ON engram_sessions (workspace_id, created_at DESC);
|
|
41
|
-
|
|
42
|
-
-- Person-axis lookups. GIN supports the @> contains operator efficiently.
|
|
43
|
-
CREATE INDEX IF NOT EXISTS idx_engram_sessions_participants
|
|
44
|
-
ON engram_sessions USING GIN (participants);
|
|
45
|
-
CREATE INDEX IF NOT EXISTS idx_engram_sessions_viewable_by
|
|
46
|
-
ON engram_sessions USING GIN (viewable_by);
|
|
47
|
-
|
|
48
|
-
CREATE INDEX IF NOT EXISTS idx_engram_persons_updated
|
|
49
|
-
ON engram_persons (workspace_id, updated_at DESC);
|
|
50
|
-
`;
|
|
51
3
|
/**
|
|
52
4
|
* 10-char alphanumeric id, e.g. `p_a8b3c2d4`. Cryptographic randomness via
|
|
53
5
|
* the platform's getRandomValues; collision probability negligible for any
|
|
@@ -72,11 +24,11 @@ export class PostgresAdapter {
|
|
|
72
24
|
this.newPersonId = opts.newPersonId ?? defaultPersonId;
|
|
73
25
|
}
|
|
74
26
|
/**
|
|
75
|
-
*
|
|
76
|
-
*
|
|
27
|
+
* Apply all pending schema migrations. Safe to call repeatedly and
|
|
28
|
+
* concurrently with other instances — see `runMigrations` for details.
|
|
77
29
|
*/
|
|
78
30
|
async ensureSchema() {
|
|
79
|
-
await this.sql
|
|
31
|
+
await runMigrations(this.sql);
|
|
80
32
|
}
|
|
81
33
|
// --- Sessions -----------------------------------------------------
|
|
82
34
|
async createSession(init) {
|
package/dist/main.js
CHANGED
|
@@ -11,13 +11,10 @@
|
|
|
11
11
|
* DATABASE_URL if unset, falls back to InMemoryKeyStore +
|
|
12
12
|
* InMemoryAdapter (NOT durable across restarts)
|
|
13
13
|
* DATABASE_SOCKET_PATH Cloud SQL Auth Proxy unix socket dir
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* while the multi-tenant flow rolls out.
|
|
19
|
-
* ENGRAM_WORKSPACE_ID default "default" — the workspace id used for
|
|
20
|
-
* the legacy bootstrap above.
|
|
14
|
+
*
|
|
15
|
+
* Workspaces and their API keys are provisioned exclusively through the
|
|
16
|
+
* admin API. There is no single-tenant fallback — every caller must hold a
|
|
17
|
+
* workspace-scoped key issued by `POST /admin/v1/workspaces`.
|
|
21
18
|
*/
|
|
22
19
|
import { createServer } from "./server";
|
|
23
20
|
import { InMemoryAdapter } from "./adapters/memory";
|
|
@@ -26,8 +23,6 @@ import { InMemoryKeyStore } from "./adapters/memory-key-store";
|
|
|
26
23
|
import { PostgresKeyStore } from "./adapters/postgres-key-store";
|
|
27
24
|
const PORT = Number(process.env.PORT ?? 8080);
|
|
28
25
|
const ADMIN_TOKEN = process.env.ENGRAM_ADMIN_TOKEN;
|
|
29
|
-
const LEGACY_API_KEY = process.env.ENGRAM_API_KEY;
|
|
30
|
-
const LEGACY_WORKSPACE_ID = process.env.ENGRAM_WORKSPACE_ID ?? "default";
|
|
31
26
|
const DATABASE_URL = process.env.DATABASE_URL;
|
|
32
27
|
const DATABASE_SOCKET_PATH = process.env.DATABASE_SOCKET_PATH;
|
|
33
28
|
if (!ADMIN_TOKEN) {
|
|
@@ -35,11 +30,6 @@ if (!ADMIN_TOKEN) {
|
|
|
35
30
|
process.exit(1);
|
|
36
31
|
}
|
|
37
32
|
const { keyStore, getStorage } = await buildStores();
|
|
38
|
-
if (LEGACY_API_KEY) {
|
|
39
|
-
await keyStore.createWorkspace({ id: LEGACY_WORKSPACE_ID, name: "Legacy" });
|
|
40
|
-
await keyStore.registerLegacyKey(LEGACY_WORKSPACE_ID, LEGACY_API_KEY, "ENGRAM_API_KEY");
|
|
41
|
-
console.log(`[engram-server] legacy key bootstrapped (workspace=${LEGACY_WORKSPACE_ID})`);
|
|
42
|
-
}
|
|
43
33
|
const app = createServer({
|
|
44
34
|
auth: async (key) => {
|
|
45
35
|
const r = await keyStore.resolveKey(key);
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare const name = "0001-baseline";
|
|
2
|
+
export declare const sql = "\n-- Session storage (workspace-scoped).\nCREATE TABLE IF NOT EXISTS engram_sessions (\n workspace_id TEXT NOT NULL,\n id TEXT NOT NULL,\n title TEXT,\n channel TEXT,\n participants TEXT[] NOT NULL DEFAULT '{}',\n viewable_by TEXT[] NOT NULL DEFAULT '{}',\n created_at TIMESTAMPTZ NOT NULL,\n PRIMARY KEY (workspace_id, id)\n);\n\n-- Deployments that pre-date viewable_by need the column backfilled.\nALTER TABLE engram_sessions ADD COLUMN IF NOT EXISTS viewable_by TEXT[] NOT NULL DEFAULT '{}';\n\nCREATE TABLE IF NOT EXISTS engram_events (\n workspace_id TEXT NOT NULL,\n session_id TEXT NOT NULL,\n seq INTEGER NOT NULL,\n type TEXT NOT NULL,\n at TIMESTAMPTZ NOT NULL,\n payload JSONB NOT NULL,\n PRIMARY KEY (workspace_id, session_id, seq),\n FOREIGN KEY (workspace_id, session_id)\n REFERENCES engram_sessions(workspace_id, id) ON DELETE CASCADE\n);\n\nCREATE TABLE IF NOT EXISTS engram_persons (\n workspace_id TEXT NOT NULL,\n id TEXT NOT NULL,\n display_name TEXT,\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n PRIMARY KEY (workspace_id, id)\n);\n\nCREATE INDEX IF NOT EXISTS idx_engram_sessions_workspace_created\n ON engram_sessions (workspace_id, created_at DESC);\n\n-- Person-axis lookups. GIN supports the @> contains operator efficiently.\nCREATE INDEX IF NOT EXISTS idx_engram_sessions_participants\n ON engram_sessions USING GIN (participants);\nCREATE INDEX IF NOT EXISTS idx_engram_sessions_viewable_by\n ON engram_sessions USING GIN (viewable_by);\n\nCREATE INDEX IF NOT EXISTS idx_engram_persons_updated\n ON engram_persons (workspace_id, updated_at DESC);\n\n-- Control plane: workspaces + API keys.\nCREATE TABLE IF NOT EXISTS engram_workspaces (\n id TEXT PRIMARY KEY,\n name TEXT,\n metadata JSONB NOT NULL DEFAULT '{}',\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()\n);\n\nCREATE TABLE IF NOT EXISTS engram_api_keys (\n id TEXT PRIMARY KEY,\n workspace_id TEXT NOT NULL REFERENCES engram_workspaces(id) ON DELETE CASCADE,\n key_hash TEXT NOT NULL UNIQUE,\n prefix TEXT NOT NULL,\n name TEXT,\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n last_used_at TIMESTAMPTZ,\n revoked_at TIMESTAMPTZ\n);\n\nCREATE INDEX IF NOT EXISTS idx_engram_api_keys_workspace\n ON engram_api_keys (workspace_id);\n";
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
export const name = "0001-baseline";
|
|
2
|
+
export const sql = `
|
|
3
|
+
-- Session storage (workspace-scoped).
|
|
4
|
+
CREATE TABLE IF NOT EXISTS engram_sessions (
|
|
5
|
+
workspace_id TEXT NOT NULL,
|
|
6
|
+
id TEXT NOT NULL,
|
|
7
|
+
title TEXT,
|
|
8
|
+
channel TEXT,
|
|
9
|
+
participants TEXT[] NOT NULL DEFAULT '{}',
|
|
10
|
+
viewable_by TEXT[] NOT NULL DEFAULT '{}',
|
|
11
|
+
created_at TIMESTAMPTZ NOT NULL,
|
|
12
|
+
PRIMARY KEY (workspace_id, id)
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
-- Deployments that pre-date viewable_by need the column backfilled.
|
|
16
|
+
ALTER TABLE engram_sessions ADD COLUMN IF NOT EXISTS viewable_by TEXT[] NOT NULL DEFAULT '{}';
|
|
17
|
+
|
|
18
|
+
CREATE TABLE IF NOT EXISTS engram_events (
|
|
19
|
+
workspace_id TEXT NOT NULL,
|
|
20
|
+
session_id TEXT NOT NULL,
|
|
21
|
+
seq INTEGER NOT NULL,
|
|
22
|
+
type TEXT NOT NULL,
|
|
23
|
+
at TIMESTAMPTZ NOT NULL,
|
|
24
|
+
payload JSONB NOT NULL,
|
|
25
|
+
PRIMARY KEY (workspace_id, session_id, seq),
|
|
26
|
+
FOREIGN KEY (workspace_id, session_id)
|
|
27
|
+
REFERENCES engram_sessions(workspace_id, id) ON DELETE CASCADE
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
CREATE TABLE IF NOT EXISTS engram_persons (
|
|
31
|
+
workspace_id TEXT NOT NULL,
|
|
32
|
+
id TEXT NOT NULL,
|
|
33
|
+
display_name TEXT,
|
|
34
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
35
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
36
|
+
PRIMARY KEY (workspace_id, id)
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
CREATE INDEX IF NOT EXISTS idx_engram_sessions_workspace_created
|
|
40
|
+
ON engram_sessions (workspace_id, created_at DESC);
|
|
41
|
+
|
|
42
|
+
-- Person-axis lookups. GIN supports the @> contains operator efficiently.
|
|
43
|
+
CREATE INDEX IF NOT EXISTS idx_engram_sessions_participants
|
|
44
|
+
ON engram_sessions USING GIN (participants);
|
|
45
|
+
CREATE INDEX IF NOT EXISTS idx_engram_sessions_viewable_by
|
|
46
|
+
ON engram_sessions USING GIN (viewable_by);
|
|
47
|
+
|
|
48
|
+
CREATE INDEX IF NOT EXISTS idx_engram_persons_updated
|
|
49
|
+
ON engram_persons (workspace_id, updated_at DESC);
|
|
50
|
+
|
|
51
|
+
-- Control plane: workspaces + API keys.
|
|
52
|
+
CREATE TABLE IF NOT EXISTS engram_workspaces (
|
|
53
|
+
id TEXT PRIMARY KEY,
|
|
54
|
+
name TEXT,
|
|
55
|
+
metadata JSONB NOT NULL DEFAULT '{}',
|
|
56
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
CREATE TABLE IF NOT EXISTS engram_api_keys (
|
|
60
|
+
id TEXT PRIMARY KEY,
|
|
61
|
+
workspace_id TEXT NOT NULL REFERENCES engram_workspaces(id) ON DELETE CASCADE,
|
|
62
|
+
key_hash TEXT NOT NULL UNIQUE,
|
|
63
|
+
prefix TEXT NOT NULL,
|
|
64
|
+
name TEXT,
|
|
65
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
66
|
+
last_used_at TIMESTAMPTZ,
|
|
67
|
+
revoked_at TIMESTAMPTZ
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
CREATE INDEX IF NOT EXISTS idx_engram_api_keys_workspace
|
|
71
|
+
ON engram_api_keys (workspace_id);
|
|
72
|
+
`;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface Migration {
|
|
2
|
+
name: string;
|
|
3
|
+
sql: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Schema migrations, applied in array order. Add a new file under
|
|
7
|
+
* `migrations/NNNN-<slug>.ts` exporting `name` and `sql`, then append it
|
|
8
|
+
* here. Each migration's SQL must be idempotent (CREATE TABLE IF NOT
|
|
9
|
+
* EXISTS, ADD COLUMN IF NOT EXISTS, etc.) so a first apply on a DB that
|
|
10
|
+
* predates the migrator is a no-op.
|
|
11
|
+
*/
|
|
12
|
+
export declare const MIGRATIONS: Migration[];
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as m0001 from "./0001-baseline";
|
|
2
|
+
/**
|
|
3
|
+
* Schema migrations, applied in array order. Add a new file under
|
|
4
|
+
* `migrations/NNNN-<slug>.ts` exporting `name` and `sql`, then append it
|
|
5
|
+
* here. Each migration's SQL must be idempotent (CREATE TABLE IF NOT
|
|
6
|
+
* EXISTS, ADD COLUMN IF NOT EXISTS, etc.) so a first apply on a DB that
|
|
7
|
+
* predates the migrator is a no-op.
|
|
8
|
+
*/
|
|
9
|
+
export const MIGRATIONS = [{ name: m0001.name, sql: m0001.sql }];
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { SqlClient } from "./adapters/postgres";
|
|
2
|
+
import { type Migration } from "./migrations";
|
|
3
|
+
/**
|
|
4
|
+
* Apply pending schema migrations in order. Records applied migrations in
|
|
5
|
+
* `engram_schema_migrations` so subsequent boots skip them.
|
|
6
|
+
*
|
|
7
|
+
* Each migration's SQL must itself be idempotent (IF NOT EXISTS, etc.) —
|
|
8
|
+
* the tracking table protects against unnecessary re-runs but a partial
|
|
9
|
+
* failure between executing the SQL and inserting the tracking row would
|
|
10
|
+
* cause a replay on next boot, and we want that replay to be a no-op.
|
|
11
|
+
*
|
|
12
|
+
* Safe to call concurrently from multiple instances: the INSERT uses ON
|
|
13
|
+
* CONFLICT and the migration SQL itself is idempotent, so two boots
|
|
14
|
+
* applying the same migration in parallel just race to a consistent end
|
|
15
|
+
* state.
|
|
16
|
+
*/
|
|
17
|
+
export declare function runMigrations(sql: SqlClient, migrations?: readonly Migration[]): Promise<void>;
|
package/dist/migrator.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { MIGRATIONS } from "./migrations";
|
|
2
|
+
/**
|
|
3
|
+
* Apply pending schema migrations in order. Records applied migrations in
|
|
4
|
+
* `engram_schema_migrations` so subsequent boots skip them.
|
|
5
|
+
*
|
|
6
|
+
* Each migration's SQL must itself be idempotent (IF NOT EXISTS, etc.) —
|
|
7
|
+
* the tracking table protects against unnecessary re-runs but a partial
|
|
8
|
+
* failure between executing the SQL and inserting the tracking row would
|
|
9
|
+
* cause a replay on next boot, and we want that replay to be a no-op.
|
|
10
|
+
*
|
|
11
|
+
* Safe to call concurrently from multiple instances: the INSERT uses ON
|
|
12
|
+
* CONFLICT and the migration SQL itself is idempotent, so two boots
|
|
13
|
+
* applying the same migration in parallel just race to a consistent end
|
|
14
|
+
* state.
|
|
15
|
+
*/
|
|
16
|
+
export async function runMigrations(sql, migrations = MIGRATIONS) {
|
|
17
|
+
await sql.unsafe(`
|
|
18
|
+
CREATE TABLE IF NOT EXISTS engram_schema_migrations (
|
|
19
|
+
name TEXT PRIMARY KEY,
|
|
20
|
+
applied_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
21
|
+
)
|
|
22
|
+
`);
|
|
23
|
+
const appliedRows = await sql `
|
|
24
|
+
SELECT name FROM engram_schema_migrations
|
|
25
|
+
`;
|
|
26
|
+
const applied = new Set(appliedRows.map((r) => r.name));
|
|
27
|
+
for (const m of migrations) {
|
|
28
|
+
if (applied.has(m.name))
|
|
29
|
+
continue;
|
|
30
|
+
await sql.unsafe(m.sql);
|
|
31
|
+
await sql `
|
|
32
|
+
INSERT INTO engram_schema_migrations (name)
|
|
33
|
+
VALUES (${m.name})
|
|
34
|
+
ON CONFLICT (name) DO NOTHING
|
|
35
|
+
`;
|
|
36
|
+
}
|
|
37
|
+
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hexis-ai/engram-server",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Engram server: ingest agent session events, persist via a pluggable adapter, expose search.",
|
|
5
|
-
"keywords": [
|
|
5
|
+
"keywords": [
|
|
6
|
+
"engram",
|
|
7
|
+
"agents",
|
|
8
|
+
"search",
|
|
9
|
+
"hono",
|
|
10
|
+
"postgres",
|
|
11
|
+
"server"
|
|
12
|
+
],
|
|
6
13
|
"homepage": "https://github.com/hexis-ltd/engram#readme",
|
|
7
14
|
"repository": {
|
|
8
15
|
"type": "git",
|
|
@@ -49,7 +56,9 @@
|
|
|
49
56
|
"postgres": "^3.4.0"
|
|
50
57
|
},
|
|
51
58
|
"peerDependenciesMeta": {
|
|
52
|
-
"postgres": {
|
|
59
|
+
"postgres": {
|
|
60
|
+
"optional": true
|
|
61
|
+
}
|
|
53
62
|
},
|
|
54
63
|
"devDependencies": {
|
|
55
64
|
"postgres": "^3.4.0"
|