4runr-os 2.10.2 → 2.10.3

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.
@@ -261,9 +261,9 @@
261
261
  }
262
262
  },
263
263
  "node_modules/@aws-sdk/client-kms": {
264
- "version": "3.1036.0",
265
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-kms/-/client-kms-3.1036.0.tgz",
266
- "integrity": "sha512-tpqED4Wxmwx3gKv4czaMBbptyoYYX/2KuJ/F3+ZUQ5xPimQ448Wrx6Ci0aOfnbBIKek8DIL24LdgYSoApgnHoQ==",
264
+ "version": "3.1037.0",
265
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-kms/-/client-kms-3.1037.0.tgz",
266
+ "integrity": "sha512-kCaCPJVob3ArRGqBougLiHkarRKJx4C5okwX54VJVdSrsKmF/HMXsFXWB7DAS3mfvc5HGaTUstneuaM7VmhO6A==",
267
267
  "license": "Apache-2.0",
268
268
  "dependencies": {
269
269
  "@aws-crypto/sha256-browser": "5.2.0",
@@ -311,9 +311,9 @@
311
311
  }
312
312
  },
313
313
  "node_modules/@aws-sdk/client-secrets-manager": {
314
- "version": "3.1036.0",
315
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.1036.0.tgz",
316
- "integrity": "sha512-4Q0Rqh1CrNfwmAOrQF9FiuU2QmV51cTSa+rJJNan7/KzYUUlUFmavuWpKH+S3preT8iaTlCT0JyCqO46kg24RA==",
314
+ "version": "3.1037.0",
315
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.1037.0.tgz",
316
+ "integrity": "sha512-SBXVNgXdzFeiuUod1AZXJexTDndPcpSTGOrVDe5Ny81Xq7d3r18th7ZTzvnc7BsD9MQa8SckNgOYscvi/fYZhw==",
317
317
  "license": "Apache-2.0",
318
318
  "dependencies": {
319
319
  "@aws-crypto/sha256-browser": "5.2.0",
@@ -361,9 +361,9 @@
361
361
  }
362
362
  },
363
363
  "node_modules/@aws-sdk/client-ssm": {
364
- "version": "3.1036.0",
365
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-ssm/-/client-ssm-3.1036.0.tgz",
366
- "integrity": "sha512-MGUcW/ITX37ktOQpBI9T2x0bHt1KFi5z8FjkSRC8FrBezxyViMMRbvJcbU3sOojsRvFpZePUgfB4RkcYu7BAbg==",
364
+ "version": "3.1037.0",
365
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-ssm/-/client-ssm-3.1037.0.tgz",
366
+ "integrity": "sha512-bpOon1QQ+FN1yH7NbjjHnyQ7y5xPvS/3vS2nL3+e2+Iu9sA+WJwgwquk6N+U1EtnAuGPAl9eNzk0GnEHaIwAOQ==",
367
367
  "license": "Apache-2.0",
368
368
  "dependencies": {
369
369
  "@aws-crypto/sha256-browser": "5.2.0",
@@ -1964,9 +1964,9 @@
1964
1964
  }
1965
1965
  },
1966
1966
  "node_modules/@fastify/ajv-compiler/node_modules/ajv": {
1967
- "version": "8.18.0",
1968
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
1969
- "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
1967
+ "version": "8.20.0",
1968
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
1969
+ "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
1970
1970
  "license": "MIT",
1971
1971
  "dependencies": {
1972
1972
  "fast-deep-equal": "^3.1.3",
@@ -4102,9 +4102,9 @@
4102
4102
  }
4103
4103
  },
4104
4104
  "node_modules/ajv-formats/node_modules/ajv": {
4105
- "version": "8.18.0",
4106
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
4107
- "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
4105
+ "version": "8.20.0",
4106
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
4107
+ "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
4108
4108
  "license": "MIT",
4109
4109
  "dependencies": {
4110
4110
  "fast-deep-equal": "^3.1.3",
@@ -5420,9 +5420,9 @@
5420
5420
  }
5421
5421
  },
5422
5422
  "node_modules/fast-json-stringify/node_modules/ajv": {
5423
- "version": "8.18.0",
5424
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
5425
- "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
5423
+ "version": "8.20.0",
5424
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
5425
+ "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
5426
5426
  "license": "MIT",
5427
5427
  "dependencies": {
5428
5428
  "fast-deep-equal": "^3.1.3",
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "4runr-os",
3
- "version": "2.10.2",
3
+ "version": "2.10.3",
4
4
  "type": "module",
5
- "description": "4Runr AI Agent OS - Secure terminal interface for AI agents. v2.10.2: Portal Monitoringauto-refresh, uptime/queue/memory metrics, /api/monitoring/summary; /health includes uptime+memory; TUI text-only (no decorative emoji). v2.10.1+ Docker Postgres+Redis in auto mode. See docs/4RUNR-DB-IMPLEMENTATION-PLAN.md, docs/MONITORING-IMPROVEMENTS-V1.md",
5
+ "description": "4Runr AI Agent OS - Secure terminal interface for AI agents. v2.10.3: npm global Gateway ship prisma/ in package, postinstall always runs prisma generate (fixes @prisma/client not initialized). v2.10.2: Portal monitoring metrics. v2.10.1+ Docker Postgres+Redis in auto mode. See docs/4RUNR-DB-IMPLEMENTATION-PLAN.md, docs/MONITORING-IMPROVEMENTS-V1.md",
6
6
  "main": "dist/index.js",
7
7
  "bin": {
8
8
  "4runr": "dist/index.js",
@@ -84,6 +84,7 @@
84
84
  "mk3-tui/bin/**/*",
85
85
  "mk3-tui/binaries/**/*",
86
86
  "apps/gateway/**/*",
87
+ "prisma/**/*",
87
88
  "packages/shared/package.json",
88
89
  "packages/shared/dist/**/*",
89
90
  "packages/sentinel/package.json",
@@ -0,0 +1,23 @@
1
+ -- CreateTable
2
+ CREATE TABLE "Agent" (
3
+ "id" TEXT NOT NULL PRIMARY KEY,
4
+ "name" TEXT NOT NULL,
5
+ "role" TEXT NOT NULL,
6
+ "createdBy" TEXT NOT NULL,
7
+ "publicKey" TEXT NOT NULL,
8
+ "status" TEXT NOT NULL DEFAULT 'active',
9
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
10
+ );
11
+
12
+ -- CreateTable
13
+ CREATE TABLE "Token" (
14
+ "id" TEXT NOT NULL PRIMARY KEY,
15
+ "agentId" TEXT NOT NULL,
16
+ "token" TEXT NOT NULL,
17
+ "expiresAt" DATETIME NOT NULL,
18
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
19
+ CONSTRAINT "Token_agentId_fkey" FOREIGN KEY ("agentId") REFERENCES "Agent" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
20
+ );
21
+
22
+ -- CreateIndex
23
+ CREATE UNIQUE INDEX "Token_token_key" ON "Token"("token");
@@ -0,0 +1,24 @@
1
+ /*
2
+ Warnings:
3
+
4
+ - You are about to drop the column `token` on the `Token` table. All the data in the column will be lost.
5
+ - Added the required column `encrypted` to the `Token` table without a default value. This is not possible if the table is not empty.
6
+
7
+ */
8
+ -- RedefineTables
9
+ PRAGMA defer_foreign_keys=ON;
10
+ PRAGMA foreign_keys=OFF;
11
+ CREATE TABLE "new_Token" (
12
+ "id" TEXT NOT NULL PRIMARY KEY,
13
+ "agentId" TEXT NOT NULL,
14
+ "encrypted" TEXT NOT NULL,
15
+ "expiresAt" DATETIME NOT NULL,
16
+ "revoked" BOOLEAN NOT NULL DEFAULT false,
17
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
18
+ CONSTRAINT "Token_agentId_fkey" FOREIGN KEY ("agentId") REFERENCES "Agent" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
19
+ );
20
+ INSERT INTO "new_Token" ("agentId", "createdAt", "expiresAt", "id") SELECT "agentId", "createdAt", "expiresAt", "id" FROM "Token";
21
+ DROP TABLE "Token";
22
+ ALTER TABLE "new_Token" RENAME TO "Token";
23
+ PRAGMA foreign_keys=ON;
24
+ PRAGMA defer_foreign_keys=OFF;
@@ -0,0 +1,12 @@
1
+ -- CreateTable
2
+ CREATE TABLE "RequestLog" (
3
+ "id" TEXT NOT NULL PRIMARY KEY,
4
+ "agentId" TEXT NOT NULL,
5
+ "tool" TEXT NOT NULL,
6
+ "action" TEXT NOT NULL,
7
+ "responseTime" INTEGER NOT NULL,
8
+ "statusCode" INTEGER NOT NULL,
9
+ "success" BOOLEAN NOT NULL,
10
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
11
+ CONSTRAINT "RequestLog_agentId_fkey" FOREIGN KEY ("agentId") REFERENCES "Agent" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
12
+ );
@@ -0,0 +1,75 @@
1
+ -- CreateTable
2
+ CREATE TABLE "Policy" (
3
+ "id" TEXT NOT NULL PRIMARY KEY,
4
+ "name" TEXT NOT NULL,
5
+ "description" TEXT,
6
+ "agentId" TEXT,
7
+ "role" TEXT,
8
+ "spec" TEXT NOT NULL,
9
+ "specHash" TEXT NOT NULL,
10
+ "active" BOOLEAN NOT NULL DEFAULT true,
11
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
12
+ "updatedAt" DATETIME NOT NULL,
13
+ CONSTRAINT "Policy_agentId_fkey" FOREIGN KEY ("agentId") REFERENCES "Agent" ("id") ON DELETE SET NULL ON UPDATE CASCADE
14
+ );
15
+
16
+ -- CreateTable
17
+ CREATE TABLE "PolicyLog" (
18
+ "id" TEXT NOT NULL PRIMARY KEY,
19
+ "policyId" TEXT NOT NULL,
20
+ "agentId" TEXT NOT NULL,
21
+ "tool" TEXT NOT NULL,
22
+ "action" TEXT NOT NULL,
23
+ "decision" TEXT NOT NULL,
24
+ "reason" TEXT,
25
+ "requestData" TEXT,
26
+ "responseData" TEXT,
27
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
28
+ CONSTRAINT "PolicyLog_policyId_fkey" FOREIGN KEY ("policyId") REFERENCES "Policy" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
29
+ CONSTRAINT "PolicyLog_agentId_fkey" FOREIGN KEY ("agentId") REFERENCES "Agent" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
30
+ );
31
+
32
+ -- CreateTable
33
+ CREATE TABLE "QuotaCounter" (
34
+ "id" TEXT NOT NULL PRIMARY KEY,
35
+ "policyId" TEXT NOT NULL,
36
+ "quotaKey" TEXT NOT NULL,
37
+ "current" INTEGER NOT NULL DEFAULT 0,
38
+ "resetAt" DATETIME NOT NULL,
39
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
40
+ "updatedAt" DATETIME NOT NULL,
41
+ CONSTRAINT "QuotaCounter_policyId_fkey" FOREIGN KEY ("policyId") REFERENCES "Policy" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
42
+ );
43
+
44
+ -- CreateTable
45
+ CREATE TABLE "ToolCredential" (
46
+ "id" TEXT NOT NULL PRIMARY KEY,
47
+ "tool" TEXT NOT NULL,
48
+ "version" TEXT NOT NULL,
49
+ "isActive" BOOLEAN NOT NULL DEFAULT false,
50
+ "encryptedCredential" TEXT NOT NULL,
51
+ "metadata" TEXT,
52
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
53
+ "updatedAt" DATETIME NOT NULL,
54
+ "activatedAt" DATETIME,
55
+ "deactivatedAt" DATETIME
56
+ );
57
+
58
+ -- CreateTable
59
+ CREATE TABLE "TokenRegistry" (
60
+ "id" TEXT NOT NULL PRIMARY KEY,
61
+ "tokenId" TEXT NOT NULL,
62
+ "agentId" TEXT NOT NULL,
63
+ "payloadHash" TEXT NOT NULL,
64
+ "issuedAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
65
+ "expiresAt" DATETIME NOT NULL,
66
+ "isRevoked" BOOLEAN NOT NULL DEFAULT false,
67
+ "revokedAt" DATETIME,
68
+ CONSTRAINT "TokenRegistry_agentId_fkey" FOREIGN KEY ("agentId") REFERENCES "Agent" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
69
+ );
70
+
71
+ -- CreateIndex
72
+ CREATE UNIQUE INDEX "ToolCredential_tool_version_key" ON "ToolCredential"("tool", "version");
73
+
74
+ -- CreateIndex
75
+ CREATE UNIQUE INDEX "TokenRegistry_tokenId_key" ON "TokenRegistry"("tokenId");
@@ -0,0 +1,44 @@
1
+ -- CreateTable
2
+ CREATE TABLE "runtime_agents" (
3
+ "id" TEXT NOT NULL PRIMARY KEY,
4
+ "name" TEXT NOT NULL,
5
+ "language" TEXT NOT NULL,
6
+ "sourceType" TEXT NOT NULL DEFAULT 'ZIP',
7
+ "sourceUri" TEXT,
8
+ "entrypoint" TEXT NOT NULL,
9
+ "env" JSONB NOT NULL,
10
+ "limitsCpu" REAL,
11
+ "limitsMemMb" INTEGER,
12
+ "networkMode" TEXT NOT NULL DEFAULT 'NONE',
13
+ "status" TEXT NOT NULL DEFAULT 'READY',
14
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
15
+ "updatedAt" DATETIME NOT NULL
16
+ );
17
+
18
+ -- CreateTable
19
+ CREATE TABLE "runtime_runs" (
20
+ "id" TEXT NOT NULL PRIMARY KEY,
21
+ "agentId" TEXT NOT NULL,
22
+ "status" TEXT NOT NULL DEFAULT 'QUEUED',
23
+ "startedAt" DATETIME,
24
+ "endedAt" DATETIME,
25
+ "exitCode" INTEGER,
26
+ "reason" TEXT,
27
+ "cpuSeconds" REAL,
28
+ "maxMemMb" INTEGER,
29
+ "logsPtr" TEXT,
30
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
31
+ CONSTRAINT "runtime_runs_agentId_fkey" FOREIGN KEY ("agentId") REFERENCES "runtime_agents" ("id") ON DELETE CASCADE ON UPDATE CASCADE
32
+ );
33
+
34
+ -- CreateTable
35
+ CREATE TABLE "runtime_schedules" (
36
+ "id" TEXT NOT NULL PRIMARY KEY,
37
+ "agentId" TEXT NOT NULL,
38
+ "cronExpr" TEXT NOT NULL,
39
+ "enabled" BOOLEAN NOT NULL DEFAULT true,
40
+ "lastRunAt" DATETIME,
41
+ "nextRunAt" DATETIME,
42
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
43
+ CONSTRAINT "runtime_schedules_agentId_fkey" FOREIGN KEY ("agentId") REFERENCES "runtime_agents" ("id") ON DELETE CASCADE ON UPDATE CASCADE
44
+ );
@@ -0,0 +1,49 @@
1
+ /*
2
+ Warnings:
3
+
4
+ - You are about to drop the column `logsPtr` on the `runtime_runs` table. All the data in the column will be lost.
5
+
6
+ */
7
+ -- RedefineTables
8
+ PRAGMA defer_foreign_keys=ON;
9
+ PRAGMA foreign_keys=OFF;
10
+ CREATE TABLE "new_runtime_agents" (
11
+ "id" TEXT NOT NULL PRIMARY KEY,
12
+ "name" TEXT NOT NULL,
13
+ "language" TEXT NOT NULL,
14
+ "sourceType" TEXT NOT NULL DEFAULT 'ZIP',
15
+ "sourceUri" TEXT,
16
+ "entrypoint" TEXT NOT NULL,
17
+ "env" JSONB NOT NULL,
18
+ "limitsCpu" REAL,
19
+ "limitsMemMb" INTEGER,
20
+ "networkMode" TEXT NOT NULL DEFAULT 'NONE',
21
+ "status" TEXT NOT NULL DEFAULT 'READY',
22
+ "maxRestarts" INTEGER NOT NULL DEFAULT 2,
23
+ "restartBackoffMs" INTEGER NOT NULL DEFAULT 5000,
24
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
25
+ "updatedAt" DATETIME NOT NULL
26
+ );
27
+ INSERT INTO "new_runtime_agents" ("createdAt", "entrypoint", "env", "id", "language", "limitsCpu", "limitsMemMb", "name", "networkMode", "sourceType", "sourceUri", "status", "updatedAt") SELECT "createdAt", "entrypoint", "env", "id", "language", "limitsCpu", "limitsMemMb", "name", "networkMode", "sourceType", "sourceUri", "status", "updatedAt" FROM "runtime_agents";
28
+ DROP TABLE "runtime_agents";
29
+ ALTER TABLE "new_runtime_agents" RENAME TO "runtime_agents";
30
+ CREATE TABLE "new_runtime_runs" (
31
+ "id" TEXT NOT NULL PRIMARY KEY,
32
+ "agentId" TEXT NOT NULL,
33
+ "status" TEXT NOT NULL DEFAULT 'QUEUED',
34
+ "startedAt" DATETIME,
35
+ "endedAt" DATETIME,
36
+ "exitCode" INTEGER,
37
+ "reason" TEXT,
38
+ "cpuSeconds" REAL,
39
+ "maxMemMb" INTEGER,
40
+ "restarts" INTEGER NOT NULL DEFAULT 0,
41
+ "lastSampleAt" DATETIME,
42
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
43
+ CONSTRAINT "runtime_runs_agentId_fkey" FOREIGN KEY ("agentId") REFERENCES "runtime_agents" ("id") ON DELETE CASCADE ON UPDATE CASCADE
44
+ );
45
+ INSERT INTO "new_runtime_runs" ("agentId", "cpuSeconds", "createdAt", "endedAt", "exitCode", "id", "maxMemMb", "reason", "startedAt", "status") SELECT "agentId", "cpuSeconds", "createdAt", "endedAt", "exitCode", "id", "maxMemMb", "reason", "startedAt", "status" FROM "runtime_runs";
46
+ DROP TABLE "runtime_runs";
47
+ ALTER TABLE "new_runtime_runs" RENAME TO "runtime_runs";
48
+ PRAGMA foreign_keys=ON;
49
+ PRAGMA defer_foreign_keys=OFF;
@@ -0,0 +1,26 @@
1
+ -- RedefineTables
2
+ PRAGMA defer_foreign_keys=ON;
3
+ PRAGMA foreign_keys=OFF;
4
+ CREATE TABLE "new_runtime_agents" (
5
+ "id" TEXT NOT NULL PRIMARY KEY,
6
+ "name" TEXT NOT NULL,
7
+ "language" TEXT NOT NULL,
8
+ "sourceType" TEXT NOT NULL DEFAULT 'ZIP',
9
+ "sourceUri" TEXT,
10
+ "entrypoint" TEXT NOT NULL,
11
+ "env" JSONB NOT NULL,
12
+ "limitsCpu" REAL,
13
+ "limitsMemMb" INTEGER,
14
+ "networkMode" TEXT NOT NULL DEFAULT 'NONE',
15
+ "status" TEXT NOT NULL DEFAULT 'READY',
16
+ "maxRestarts" INTEGER NOT NULL DEFAULT 2,
17
+ "restartBackoffMs" INTEGER NOT NULL DEFAULT 5000,
18
+ "tags" JSONB NOT NULL DEFAULT [],
19
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
20
+ "updatedAt" DATETIME NOT NULL
21
+ );
22
+ INSERT INTO "new_runtime_agents" ("createdAt", "entrypoint", "env", "id", "language", "limitsCpu", "limitsMemMb", "maxRestarts", "name", "networkMode", "restartBackoffMs", "sourceType", "sourceUri", "status", "updatedAt") SELECT "createdAt", "entrypoint", "env", "id", "language", "limitsCpu", "limitsMemMb", "maxRestarts", "name", "networkMode", "restartBackoffMs", "sourceType", "sourceUri", "status", "updatedAt" FROM "runtime_agents";
23
+ DROP TABLE "runtime_agents";
24
+ ALTER TABLE "new_runtime_agents" RENAME TO "runtime_agents";
25
+ PRAGMA foreign_keys=ON;
26
+ PRAGMA defer_foreign_keys=OFF;
@@ -0,0 +1,24 @@
1
+ -- RedefineTables
2
+ PRAGMA defer_foreign_keys=ON;
3
+ PRAGMA foreign_keys=OFF;
4
+ CREATE TABLE "new_runtime_runs" (
5
+ "id" TEXT NOT NULL PRIMARY KEY,
6
+ "agentId" TEXT NOT NULL,
7
+ "status" TEXT NOT NULL DEFAULT 'QUEUED',
8
+ "startedAt" DATETIME,
9
+ "endedAt" DATETIME,
10
+ "exitCode" INTEGER,
11
+ "reason" TEXT,
12
+ "cpuSeconds" REAL,
13
+ "maxMemMb" INTEGER,
14
+ "restarts" INTEGER NOT NULL DEFAULT 0,
15
+ "lastSampleAt" DATETIME,
16
+ "triggeredBy" TEXT NOT NULL DEFAULT 'MANUAL',
17
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
18
+ CONSTRAINT "runtime_runs_agentId_fkey" FOREIGN KEY ("agentId") REFERENCES "runtime_agents" ("id") ON DELETE CASCADE ON UPDATE CASCADE
19
+ );
20
+ INSERT INTO "new_runtime_runs" ("agentId", "cpuSeconds", "createdAt", "endedAt", "exitCode", "id", "lastSampleAt", "maxMemMb", "reason", "restarts", "startedAt", "status") SELECT "agentId", "cpuSeconds", "createdAt", "endedAt", "exitCode", "id", "lastSampleAt", "maxMemMb", "reason", "restarts", "startedAt", "status" FROM "runtime_runs";
21
+ DROP TABLE "runtime_runs";
22
+ ALTER TABLE "new_runtime_runs" RENAME TO "runtime_runs";
23
+ PRAGMA foreign_keys=ON;
24
+ PRAGMA defer_foreign_keys=OFF;
@@ -0,0 +1,3 @@
1
+ # Please do not edit this file manually
2
+ # It should be added in your version-control system (e.g., Git)
3
+ provider = "postgresql"
@@ -0,0 +1,469 @@
1
+ // This is your Prisma schema file,
2
+ // learn more about it in the docs: https://pris.ly/d/prisma-schema
3
+
4
+ generator client {
5
+ provider = "prisma-client-js"
6
+ binaryTargets = ["native", "linux-musl-openssl-3.0.x", "linux-musl"]
7
+ }
8
+
9
+ datasource db {
10
+ provider = "postgresql"
11
+ url = env("DATABASE_URL")
12
+ }
13
+
14
+ model Agent {
15
+ id String @id @default(uuid())
16
+ name String
17
+ role String
18
+ createdBy String
19
+ publicKey String
20
+ status String @default("active")
21
+ createdAt DateTime @default(now())
22
+ tokens Token[]
23
+ requestLogs RequestLog[]
24
+ policies Policy[]
25
+ policyLogs PolicyLog[]
26
+ tokenRegistries TokenRegistry[]
27
+ }
28
+
29
+ model Token {
30
+ id String @id @default(uuid())
31
+ agentId String
32
+ agent Agent @relation(fields: [agentId], references: [id])
33
+ encrypted String
34
+ expiresAt DateTime
35
+ revoked Boolean @default(false)
36
+ createdAt DateTime @default(now())
37
+ }
38
+
39
+ model RequestLog {
40
+ id String @id @default(uuid())
41
+ agentId String
42
+ agent Agent @relation(fields: [agentId], references: [id])
43
+ tool String
44
+ action String
45
+ responseTime Int // milliseconds
46
+ statusCode Int
47
+ success Boolean
48
+ createdAt DateTime @default(now())
49
+ }
50
+
51
+ model Policy {
52
+ id String @id @default(uuid())
53
+ name String
54
+ description String?
55
+ agentId String? // null for role-based policies
56
+ role String? // null for agent-specific policies
57
+ spec String // JSON policy specification
58
+ specHash String // SHA256 hash of spec for change detection
59
+ active Boolean @default(true)
60
+ createdAt DateTime @default(now())
61
+ updatedAt DateTime @updatedAt
62
+ agent Agent? @relation(fields: [agentId], references: [id])
63
+ policyLogs PolicyLog[]
64
+ quotaCounters QuotaCounter[]
65
+ }
66
+
67
+ model PolicyLog {
68
+ id String @id @default(uuid())
69
+ policyId String
70
+ agentId String
71
+ tool String
72
+ action String
73
+ decision String // "allow", "deny"
74
+ reason String? // denial reason
75
+ requestData String? // JSON request data (truncated)
76
+ responseData String? // JSON response data (truncated)
77
+ createdAt DateTime @default(now())
78
+ policy Policy @relation(fields: [policyId], references: [id])
79
+ agent Agent @relation(fields: [agentId], references: [id])
80
+ }
81
+
82
+ model QuotaCounter {
83
+ id String @id @default(uuid())
84
+ policyId String
85
+ quotaKey String // e.g., "serpapi:search:2024-01-15"
86
+ current Int @default(0)
87
+ resetAt DateTime
88
+ createdAt DateTime @default(now())
89
+ updatedAt DateTime @updatedAt
90
+ policy Policy @relation(fields: [policyId], references: [id])
91
+ }
92
+
93
+ model ToolCredential {
94
+ id String @id @default(uuid())
95
+ tool String // e.g., "serpapi", "openai", "gmail_send"
96
+ version String // e.g., "v1", "v2"
97
+ isActive Boolean @default(false)
98
+ encryptedCredential String // Encrypted credential data
99
+ metadata String? // JSON metadata (encrypted)
100
+ createdAt DateTime @default(now())
101
+ updatedAt DateTime @updatedAt
102
+ activatedAt DateTime?
103
+ deactivatedAt DateTime?
104
+
105
+ @@unique([tool, version])
106
+ }
107
+
108
+ model TokenRegistry {
109
+ id String @id @default(uuid())
110
+ tokenId String @unique // The token ID issued to the agent
111
+ agentId String
112
+ payloadHash String // SHA256 hash of the token payload
113
+ issuedAt DateTime @default(now())
114
+ expiresAt DateTime
115
+ isRevoked Boolean @default(false)
116
+ revokedAt DateTime?
117
+ agent Agent @relation(fields: [agentId], references: [id])
118
+ }
119
+
120
+ // ====== AI AGENT RUNTIME MODELS (TASK-001) ======
121
+
122
+ model RuntimeAgent {
123
+ id String @id @default(uuid())
124
+ name String
125
+ language AgentLanguage
126
+ sourceType SourceType @default(ZIP) // ZIP | GIT (ZIP for MVP)
127
+ sourceUri String? // path to extracted zip in local FS (MVP)
128
+ entrypoint String // index.js | main.py
129
+ env Json // non-secret env vars (secrets via Gateway only)
130
+ limitsCpu Float? // e.g. 0.5
131
+ limitsMemMb Int? // e.g. 256
132
+ networkMode NetworkMode @default(NONE) // NONE | EGRESS (via Gateway proxy only)
133
+ status AgentStatus @default(READY)
134
+ // NEW: restart policy & limits
135
+ maxRestarts Int @default(2) // per run
136
+ restartBackoffMs Int @default(5000)
137
+ // NEW: tags for demo functionality (JSON array for SQLite compatibility)
138
+ tags Json @default("[]")
139
+ createdAt DateTime @default(now())
140
+ updatedAt DateTime @updatedAt
141
+
142
+ runs RuntimeRun[]
143
+ schedules RuntimeSchedule[]
144
+
145
+ @@map("runtime_agents")
146
+ }
147
+
148
+ model RuntimeRun {
149
+ id String @id @default(uuid())
150
+ agentId String
151
+ agent RuntimeAgent @relation(fields: [agentId], references: [id], onDelete: Cascade)
152
+ status RunStatus @default(QUEUED) // QUEUED | RUNNING | SUCCEEDED | FAILED | KILLED
153
+ startedAt DateTime?
154
+ endedAt DateTime?
155
+ exitCode Int?
156
+ reason String? // containerId or failure reason
157
+ // NEW: restart policy & limits
158
+ cpuSeconds Float? // cumulative seconds
159
+ maxMemMb Int? // peak RSS MB
160
+ restarts Int @default(0)
161
+ lastSampleAt DateTime? // last stats collection time
162
+ // NEW: trigger tracking
163
+ triggeredBy TriggerType @default(MANUAL)
164
+ // (optional) logsPtr for future
165
+ createdAt DateTime @default(now())
166
+
167
+ @@map("runtime_runs")
168
+ }
169
+
170
+ model RuntimeSchedule {
171
+ id String @id @default(uuid())
172
+ agentId String
173
+ agent RuntimeAgent @relation(fields: [agentId], references: [id], onDelete: Cascade)
174
+ cronExpr String
175
+ enabled Boolean @default(true)
176
+ lastRunAt DateTime?
177
+ nextRunAt DateTime?
178
+ createdAt DateTime @default(now())
179
+
180
+ @@map("runtime_schedules")
181
+ }
182
+
183
+ enum AgentLanguage {
184
+ NODE
185
+ PYTHON
186
+ }
187
+
188
+ enum SourceType {
189
+ ZIP
190
+ GIT
191
+ }
192
+
193
+ enum NetworkMode {
194
+ NONE
195
+ EGRESS
196
+ }
197
+
198
+ enum AgentStatus {
199
+ READY
200
+ ERROR
201
+ DISABLED
202
+ }
203
+
204
+ enum RunStatus {
205
+ CREATED
206
+ QUEUED
207
+ RUNNING
208
+ COMPLETED
209
+ FAILED
210
+ KILLED
211
+ SUCCEEDED // Alias for COMPLETED (keeping for RuntimeRun compatibility)
212
+ }
213
+
214
+ enum TriggerType {
215
+ MANUAL
216
+ SCHEDULE
217
+ }
218
+
219
+ // ====== GATEWAY RUNS MODELS ======
220
+
221
+ model Run {
222
+ id String @id @default(uuid())
223
+ name String
224
+ status RunStatus @default(CREATED)
225
+ input Json? // JSON input payload
226
+ output Json? // JSON output payload
227
+ logs Json @default("[]") // Array of log entries
228
+ clientToken String? @unique // Idempotency token from client
229
+ tags String[] @default([])
230
+ startedAt DateTime?
231
+ completedAt DateTime?
232
+ createdAt DateTime @default(now())
233
+ updatedAt DateTime @updatedAt
234
+
235
+ @@map("runs")
236
+ @@index([status])
237
+ @@index([clientToken])
238
+ @@index([createdAt])
239
+ }
240
+
241
+ model ApiKey {
242
+ id String @id @default(cuid())
243
+ key String @unique // Hashed or opaque token
244
+ label String?
245
+ revoked Boolean @default(false)
246
+ userId String? // Link to user if applicable
247
+ user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
248
+ createdAt DateTime @default(now())
249
+ revokedAt DateTime?
250
+
251
+ @@map("api_keys")
252
+ @@index([key])
253
+ @@index([userId])
254
+ }
255
+
256
+ // ====== RBAC MODELS ======
257
+
258
+ model User {
259
+ id String @id @default(uuid())
260
+ email String @unique
261
+ username String @unique
262
+ passwordHash String? // Optional - can use external auth
263
+ status UserStatus @default(ACTIVE)
264
+ createdAt DateTime @default(now())
265
+ updatedAt DateTime @updatedAt
266
+ lastLoginAt DateTime?
267
+
268
+ // MFA fields
269
+ mfaEnabled Boolean @default(false)
270
+ mfaSecret String? // TOTP secret (encrypted)
271
+ mfaBackupCodes String[] @default([]) // Encrypted backup codes
272
+ mfaVerifiedAt DateTime? // When MFA was last verified
273
+
274
+ // Relations
275
+ roles UserRole[]
276
+ apiKeys ApiKey[]
277
+ sessions UserSession[]
278
+
279
+ @@map("users")
280
+ @@index([email])
281
+ @@index([username])
282
+ @@index([status])
283
+ }
284
+
285
+ model Role {
286
+ id String @id @default(uuid())
287
+ name String @unique
288
+ description String?
289
+ isSystem Boolean @default(false) // System roles cannot be deleted
290
+ createdAt DateTime @default(now())
291
+ updatedAt DateTime @updatedAt
292
+
293
+ // Relations
294
+ users UserRole[]
295
+ permissions RolePermission[]
296
+
297
+ @@map("roles")
298
+ @@index([name])
299
+ }
300
+
301
+ model Permission {
302
+ id String @id @default(uuid())
303
+ resource String // e.g., "runs", "agents", "users"
304
+ action String // e.g., "create", "read", "update", "delete", "execute"
305
+ description String?
306
+ createdAt DateTime @default(now())
307
+
308
+ // Relations
309
+ roles RolePermission[]
310
+
311
+ @@unique([resource, action])
312
+ @@map("permissions")
313
+ @@index([resource])
314
+ @@index([action])
315
+ }
316
+
317
+ model UserRole {
318
+ id String @id @default(uuid())
319
+ userId String
320
+ roleId String
321
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
322
+ role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)
323
+ assignedAt DateTime @default(now())
324
+ assignedBy String? // User ID who assigned this role
325
+
326
+ @@unique([userId, roleId])
327
+ @@map("user_roles")
328
+ @@index([userId])
329
+ @@index([roleId])
330
+ }
331
+
332
+ model RolePermission {
333
+ id String @id @default(uuid())
334
+ roleId String
335
+ permissionId String
336
+ role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)
337
+ permission Permission @relation(fields: [permissionId], references: [id], onDelete: Cascade)
338
+ grantedAt DateTime @default(now())
339
+ grantedBy String? // User ID who granted this permission
340
+
341
+ @@unique([roleId, permissionId])
342
+ @@map("role_permissions")
343
+ @@index([roleId])
344
+ @@index([permissionId])
345
+ }
346
+
347
+ model UserSession {
348
+ id String @id @default(uuid())
349
+ userId String
350
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
351
+ token String @unique // JWT or session token
352
+ ipAddress String?
353
+ userAgent String?
354
+ expiresAt DateTime
355
+ createdAt DateTime @default(now())
356
+ lastActivityAt DateTime @default(now())
357
+
358
+ @@map("user_sessions")
359
+ @@index([userId])
360
+ @@index([token])
361
+ @@index([expiresAt])
362
+ }
363
+
364
+ enum UserStatus {
365
+ ACTIVE
366
+ INACTIVE
367
+ SUSPENDED
368
+ DELETED
369
+ }
370
+
371
+ // ====== IDEMPOTENCY & CACHE MODELS ======
372
+
373
+ model IdempotencyToken {
374
+ id String @id @default(uuid())
375
+ token String @unique
376
+ runId String? // Reference to Run if applicable
377
+ response Json? // Cached response
378
+ expiresAt DateTime
379
+ createdAt DateTime @default(now())
380
+
381
+ @@map("idempotency_tokens")
382
+ @@index([token])
383
+ @@index([expiresAt])
384
+ }
385
+
386
+ model CacheEntry {
387
+ id String @id @default(uuid())
388
+ key String @unique
389
+ value Json
390
+ expiresAt DateTime?
391
+ createdAt DateTime @default(now())
392
+ updatedAt DateTime @updatedAt
393
+
394
+ @@map("cache_entries")
395
+ @@index([key])
396
+ @@index([expiresAt])
397
+ }
398
+
399
+ // ====== CHAT HISTORY MODELS ======
400
+
401
+ model ChatHistory {
402
+ id String @id @default(uuid())
403
+ clientId String // Client identifier (e.g., machine ID, user ID)
404
+ agentName String
405
+ agentDescription String?
406
+ messages Json // Array of { role: 'user' | 'assistant', content: string }
407
+ createdAt DateTime @default(now())
408
+ lastMessageAt DateTime @default(now())
409
+ updatedAt DateTime @updatedAt
410
+
411
+ @@map("chat_history")
412
+ @@index([clientId])
413
+ @@index([clientId, lastMessageAt])
414
+ }
415
+
416
+ // ====== DEVKIT AGENT & TOOL MANAGEMENT ======
417
+
418
+ model DevKitAgent {
419
+ id String @id @default(uuid())
420
+ name String
421
+ slug String @unique
422
+ description String?
423
+ type String // lead_agent, education_agent, custom, etc.
424
+ model String // gpt-4, claude-3, etc.
425
+ config Json @default("{}") // { prompt, temperature, maxTokens, etc. }
426
+ createdAt DateTime @default(now())
427
+ updatedAt DateTime @updatedAt
428
+
429
+ // Relations
430
+ tools DevKitAgentTool[]
431
+
432
+ @@map("devkit_agents")
433
+ @@index([slug])
434
+ @@index([type])
435
+ }
436
+
437
+ model DevKitTool {
438
+ id String @id @default(uuid())
439
+ name String
440
+ kind String // http, email, vector, database, etc.
441
+ config Json @default("{}") // Flexible config per kind
442
+ enabled Boolean @default(true)
443
+ createdAt DateTime @default(now())
444
+ updatedAt DateTime @updatedAt
445
+
446
+ // Relations
447
+ agents DevKitAgentTool[]
448
+
449
+ @@map("devkit_tools")
450
+ @@index([kind])
451
+ @@index([enabled])
452
+ }
453
+
454
+ model DevKitAgentTool {
455
+ id String @id @default(uuid())
456
+ agentId String
457
+ toolId String
458
+ configOverride Json? // Optional per-agent tool configuration
459
+ createdAt DateTime @default(now())
460
+
461
+ // Relations
462
+ agent DevKitAgent @relation(fields: [agentId], references: [id], onDelete: Cascade)
463
+ tool DevKitTool @relation(fields: [toolId], references: [id], onDelete: Cascade)
464
+
465
+ @@unique([agentId, toolId])
466
+ @@map("devkit_agent_tools")
467
+ @@index([agentId])
468
+ @@index([toolId])
469
+ }
@@ -20,8 +20,31 @@ if (!fs.existsSync(packageJson)) {
20
20
  process.exit(0); // No gateway in this install
21
21
  }
22
22
 
23
+ const prismaSchema = path.join(__dirname, '..', 'prisma', 'schema.prisma');
24
+
25
+ function ensurePrismaClient() {
26
+ if (!fs.existsSync(prismaSchema)) {
27
+ return;
28
+ }
29
+ try {
30
+ console.log('🔧 Prisma: generating client for Gateway (global 4runr-os install)...');
31
+ execSync('npx prisma generate --schema=../../prisma/schema.prisma', {
32
+ cwd: gatewayDir,
33
+ stdio: 'inherit',
34
+ shell: process.platform === 'win32',
35
+ });
36
+ console.log('✓ Prisma client ready for Gateway');
37
+ } catch (err) {
38
+ console.warn(
39
+ '⚠️ prisma generate failed. OS auto-start Gateway may fail until you run:\n' +
40
+ ' cd apps/gateway && npx prisma generate --schema=../../prisma/schema.prisma',
41
+ );
42
+ }
43
+ }
44
+
23
45
  if (fs.existsSync(nodeModules) && fs.readdirSync(nodeModules).length > 0) {
24
- process.exit(0); // Already has deps (e.g. from prepublish)
46
+ ensurePrismaClient();
47
+ process.exit(0); // Deps already present (e.g. from prepublish) — still (re)generate Prisma
25
48
  }
26
49
 
27
50
  try {
@@ -36,3 +59,5 @@ try {
36
59
  console.warn('⚠️ Gateway dependency install failed. Start gateway from repo with: cd apps/gateway && npm start');
37
60
  // Don't fail the main install
38
61
  }
62
+
63
+ ensurePrismaClient();