@opengeni/db 0.10.7 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-P6PKXY5W.js → chunk-VUKRIBO5.js} +485 -12
- package/dist/chunk-VUKRIBO5.js.map +1 -0
- package/dist/{chunk-KW526IJA.js → chunk-Y5WZZVQK.js} +80 -4
- package/dist/chunk-Y5WZZVQK.js.map +1 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +5114 -2085
- package/dist/index.js.map +1 -1
- package/dist/migrate.d.ts +6 -3
- package/dist/migrate.js +1 -1
- package/dist/provision-roles.d.ts +720 -63
- package/dist/{schema-CqkzrBRS.d.ts → schema-CnpD6BcX.d.ts} +4684 -2913
- package/dist/schema.d.ts +1 -1
- package/dist/schema.js +17 -1
- package/drizzle/0109_nested_agent_depth_expand.sql +42 -0
- package/drizzle/0110_nested_agent_depth_boundary.sql +480 -0
- package/drizzle/0111_nested_agent_depth_backfill.sql +49 -0
- package/drizzle/0112_nested_agent_depth_contract.sql +38 -0
- package/drizzle/0113_nested_agent_depth_validate.sql +13 -0
- package/drizzle/0114_nested_agent_depth_contract.sql +49 -0
- package/drizzle/0115_nested_agent_depth_validate.sql +11 -0
- package/drizzle/0116_nested_agent_depth_index.sql +4 -0
- package/drizzle/0117_sandbox_recovery_generations.sql +699 -0
- package/drizzle/0118_new_session_drafts.sql +59 -0
- package/drizzle/0119_pending_tool_output_policy.sql +5 -0
- package/drizzle/0120_durable_goal_wake.sql +360 -0
- package/drizzle/0121_goal_update_idempotency.sql +11 -0
- package/package.json +3 -3
- package/src/index.ts +5961 -1240
- package/src/migrate.ts +131 -2
- package/src/new-session-drafts.ts +144 -0
- package/src/schema.ts +519 -15
- package/src/session-control.ts +42 -18
- package/src/session-tool-call-settlement.ts +6 -1
- package/dist/chunk-KW526IJA.js.map +0 -1
- package/dist/chunk-P6PKXY5W.js.map +0 -1
package/src/session-control.ts
CHANGED
|
@@ -11,7 +11,7 @@ import * as schema from "./schema";
|
|
|
11
11
|
|
|
12
12
|
export const SESSION_ANCESTRY_LIMIT = 10_000;
|
|
13
13
|
|
|
14
|
-
export type WorkspaceControlLockMode = "share" | "update";
|
|
14
|
+
export type WorkspaceControlLockMode = "none" | "share" | "update";
|
|
15
15
|
export type EffectiveControlState = "active" | "paused";
|
|
16
16
|
export type SessionCommandActor =
|
|
17
17
|
| { type: "human" | "operator"; subjectId: string }
|
|
@@ -202,9 +202,12 @@ export async function assertAgentCommandAuthorityInTransaction(
|
|
|
202
202
|
workspaceId: string;
|
|
203
203
|
actor: Extract<SessionCommandActor, { type: "agent_attempt" }>;
|
|
204
204
|
targetSessionId: string;
|
|
205
|
-
action: "pause" | "resume" | "steer" | "message";
|
|
205
|
+
action: "pause" | "resume" | "steer" | "message" | "goal";
|
|
206
206
|
},
|
|
207
207
|
): Promise<void> {
|
|
208
|
+
if (input.action === "goal" && input.targetSessionId !== input.actor.sessionId) {
|
|
209
|
+
throw new SessionControlInvariantError("An agent goal command must target its own session");
|
|
210
|
+
}
|
|
208
211
|
// Every command caller establishes the control/workspace prefix first.
|
|
209
212
|
// Reusing the event-write helper here keeps cross-session actor authority on
|
|
210
213
|
// the same UUID-ordered session -> exact turn -> exact attempt suffix.
|
|
@@ -355,6 +358,7 @@ function controlEtag(value: unknown): string {
|
|
|
355
358
|
}
|
|
356
359
|
|
|
357
360
|
function lockClause(mode: WorkspaceControlLockMode) {
|
|
361
|
+
if (mode === "none") return sql.empty();
|
|
358
362
|
return mode === "update" ? sql.raw("for update") : sql.raw("for share");
|
|
359
363
|
}
|
|
360
364
|
|
|
@@ -1345,26 +1349,32 @@ async function findCommandReceipt(
|
|
|
1345
1349
|
targetSessionId: string | null;
|
|
1346
1350
|
targetTurnId: string | null;
|
|
1347
1351
|
operationKey: string;
|
|
1352
|
+
identityScope: "actor" | "goal_operation";
|
|
1348
1353
|
},
|
|
1349
1354
|
): Promise<SessionCommandReceiptRow | null> {
|
|
1350
1355
|
const actorSubjectId = input.actor.type === "agent_attempt" ? null : input.actor.subjectId;
|
|
1351
1356
|
const actorAttemptId = input.actor.type === "agent_attempt" ? input.actor.attemptId : null;
|
|
1352
|
-
const
|
|
1353
|
-
.
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1357
|
+
const identity =
|
|
1358
|
+
input.identityScope === "goal_operation"
|
|
1359
|
+
? and(
|
|
1360
|
+
eq(schema.sessionCommandReceipts.workspaceId, input.workspaceId),
|
|
1361
|
+
eq(schema.sessionCommandReceipts.actorType, "agent_attempt"),
|
|
1362
|
+
eq(schema.sessionCommandReceipts.action, input.action),
|
|
1363
|
+
eq(schema.sessionCommandReceipts.targetSessionId, input.targetSessionId!),
|
|
1364
|
+
sql`${schema.sessionCommandReceipts.targetTurnId} is null`,
|
|
1365
|
+
eq(schema.sessionCommandReceipts.operationKey, input.operationKey),
|
|
1366
|
+
)
|
|
1367
|
+
: and(
|
|
1368
|
+
eq(schema.sessionCommandReceipts.workspaceId, input.workspaceId),
|
|
1369
|
+
eq(schema.sessionCommandReceipts.actorType, input.actor.type),
|
|
1370
|
+
sql`${schema.sessionCommandReceipts.actorSubjectId} is not distinct from ${actorSubjectId}`,
|
|
1371
|
+
sql`${schema.sessionCommandReceipts.actorAttemptId} is not distinct from ${actorAttemptId}::uuid`,
|
|
1372
|
+
eq(schema.sessionCommandReceipts.action, input.action),
|
|
1373
|
+
sql`${schema.sessionCommandReceipts.targetSessionId} is not distinct from ${input.targetSessionId}::uuid`,
|
|
1374
|
+
sql`${schema.sessionCommandReceipts.targetTurnId} is not distinct from ${input.targetTurnId}::uuid`,
|
|
1375
|
+
eq(schema.sessionCommandReceipts.operationKey, input.operationKey),
|
|
1376
|
+
);
|
|
1377
|
+
const rows = await db.select().from(schema.sessionCommandReceipts).where(identity).for("update");
|
|
1368
1378
|
return rows[0] ?? null;
|
|
1369
1379
|
}
|
|
1370
1380
|
|
|
@@ -1379,9 +1389,22 @@ export async function reserveSessionCommandReceipt(
|
|
|
1379
1389
|
targetTurnId: string | null;
|
|
1380
1390
|
operationKey: string;
|
|
1381
1391
|
canonicalRequestHash: string;
|
|
1392
|
+
identityScope?: "actor" | "goal_operation";
|
|
1382
1393
|
},
|
|
1383
1394
|
): Promise<{ receipt: SessionCommandReceiptRow; replay: boolean }> {
|
|
1384
1395
|
if (!input.operationKey.trim()) throw new Error("operationKey must not be empty");
|
|
1396
|
+
const identityScope = input.identityScope ?? "actor";
|
|
1397
|
+
if (
|
|
1398
|
+
identityScope === "goal_operation" &&
|
|
1399
|
+
(input.actor.type !== "agent_attempt" ||
|
|
1400
|
+
input.action !== "goal.update" ||
|
|
1401
|
+
input.targetSessionId === null ||
|
|
1402
|
+
input.targetTurnId !== null)
|
|
1403
|
+
) {
|
|
1404
|
+
throw new SessionControlInvariantError(
|
|
1405
|
+
"Target-scoped receipt identity is reserved for agent goal.update commands",
|
|
1406
|
+
);
|
|
1407
|
+
}
|
|
1385
1408
|
const actorSubjectId = input.actor.type === "agent_attempt" ? null : input.actor.subjectId;
|
|
1386
1409
|
const actorAttemptId = input.actor.type === "agent_attempt" ? input.actor.attemptId : null;
|
|
1387
1410
|
const [inserted] = await db
|
|
@@ -1409,6 +1432,7 @@ export async function reserveSessionCommandReceipt(
|
|
|
1409
1432
|
targetSessionId: input.targetSessionId,
|
|
1410
1433
|
targetTurnId: input.targetTurnId,
|
|
1411
1434
|
operationKey: input.operationKey,
|
|
1435
|
+
identityScope,
|
|
1412
1436
|
}));
|
|
1413
1437
|
if (!receipt) throw new SessionControlInvariantError("Command receipt conflict was not readable");
|
|
1414
1438
|
if (receipt.canonicalRequestHash !== input.canonicalRequestHash) {
|
|
@@ -255,7 +255,12 @@ export async function closePendingSessionToolCallsInTransaction(
|
|
|
255
255
|
sessionId: input.sessionId,
|
|
256
256
|
turnId: input.turnId,
|
|
257
257
|
position: nextPosition++,
|
|
258
|
-
item: sanitizeModelPayload(
|
|
258
|
+
item: sanitizeModelPayload(
|
|
259
|
+
boundModelToolOutputItem(
|
|
260
|
+
resolution.result,
|
|
261
|
+
resolution.call.modelToolOutputTruncationTokens ?? undefined,
|
|
262
|
+
),
|
|
263
|
+
),
|
|
259
264
|
active: true,
|
|
260
265
|
});
|
|
261
266
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/migrate.ts"],"sourcesContent":["import { readdir, readFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport postgres from \"postgres\";\n\nconst DEFAULT_DATABASE_URL = \"postgres://opengeni:opengeni@127.0.0.1:5432/opengeni\";\nconst concurrentIndexDirective = /^-- opengeni:concurrent-index lock-timeout=(\\d+(?:ms|s|min))$/;\nconst concurrentIndexStatement =\n /^CREATE\\s+(?:UNIQUE\\s+)?INDEX\\s+CONCURRENTLY\\s+(?:(IF\\s+NOT\\s+EXISTS)\\s+)?(?:\"((?:[^\"]|\"\")+)\"|([A-Za-z_][A-Za-z0-9_]*))\\s+ON\\b/is;\nconst governedLegacyConcurrentIndexMigrations = new Set([\n \"0066_session_interruption_attempt_lookup.sql\",\n \"0070_session_event_type_sequence_lookup.sql\",\n \"0071_session_event_monitoring_tail.sql\",\n \"0072_sessions_workspace_created_id_idx.sql\",\n \"0073_sessions_workspace_updated_id_idx.sql\",\n \"0075_sessions_workspace_activity_revision_idx.sql\",\n \"0077_session_attempt_latest_lookup.sql\",\n]);\n\nexport interface ConcurrentIndexMigration {\n indexName: string;\n lockTimeout: string;\n skipWhenValid: boolean;\n statement: string;\n}\n\n/** A bare Postgres identifier (schema/role name) safe to interpolate into DDL. */\nfunction assertIdentifier(name: string, value: string): string {\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(value)) {\n throw new Error(`${name} is not a valid Postgres identifier: ${value}`);\n }\n return value;\n}\n\n/**\n * Most migration files intentionally execute as one implicit transaction.\n * PostgreSQL forbids CREATE INDEX CONCURRENTLY there, so a migration may opt\n * into one narrowly validated transactionless statement with:\n *\n * -- opengeni:concurrent-index lock-timeout=5s\n * CREATE [UNIQUE] INDEX CONCURRENTLY IF NOT EXISTS ...;\n *\n * The directive is deliberately not a generic \"no transaction\" escape hatch:\n * only one idempotent concurrent-index statement is accepted, lock acquisition\n * is always bounded, and an invalid artifact left by a failed concurrent build\n * is removed before retry. Seven governed historical migrations predate the\n * IF NOT EXISTS rule; only those exact filenames may use their immutable bare\n * statements, and the runner makes their retries idempotent by skipping an\n * already-valid index. This keeps additive large-table indexes online without\n * rewriting shipped history or making arbitrary partially-applied migration\n * scripts possible.\n */\nexport function parseConcurrentIndexMigration(\n file: string,\n sqlText: string,\n): ConcurrentIndexMigration | null {\n const lines = sqlText.replaceAll(\"\\r\\n\", \"\\n\").split(\"\\n\");\n const firstLine = lines[0]?.trim() ?? \"\";\n const deploymentPrefixed = /^-- deployment-mode: (?:rolling|maintenance)$/.test(firstLine);\n const directiveIndex = deploymentPrefixed ? 1 : 0;\n const directiveLine = lines[directiveIndex]?.trim() ?? \"\";\n const directive = concurrentIndexDirective.exec(directiveLine);\n if (!directive) {\n if (directiveLine.startsWith(\"-- opengeni:\")) {\n throw new Error(`Unsupported OpenGeni migration directive in ${file}`);\n }\n return null;\n }\n\n const lockTimeout = directive[1]!;\n const statement = lines\n .slice(directiveIndex + 1)\n .join(\"\\n\")\n .trim();\n const withoutTrailingSemicolon = statement.endsWith(\";\")\n ? statement.slice(0, -1).trimEnd()\n : statement;\n const parsedStatement = concurrentIndexStatement.exec(withoutTrailingSemicolon);\n if (!parsedStatement || withoutTrailingSemicolon.includes(\";\")) {\n throw new Error(\n `${file}: opengeni:concurrent-index requires exactly one CREATE [UNIQUE] INDEX CONCURRENTLY IF NOT EXISTS statement with an unqualified index name`,\n );\n }\n const idempotentInSql = parsedStatement[1] !== undefined;\n if (!idempotentInSql && !governedLegacyConcurrentIndexMigrations.has(file)) {\n throw new Error(\n `${file}: opengeni:concurrent-index requires IF NOT EXISTS; bare statements are supported only for governed historical migrations`,\n );\n }\n return {\n indexName: (parsedStatement[2] ?? parsedStatement[3]!).replaceAll('\"\"', '\"'),\n lockTimeout,\n skipWhenValid: !idempotentInSql,\n statement,\n };\n}\n\nasync function executeMigrationFile(\n sql: postgres.Sql,\n file: string,\n sqlText: string,\n): Promise<void> {\n const concurrentIndex = parseConcurrentIndexMigration(file, sqlText);\n if (!concurrentIndex) {\n await sql.unsafe(sqlText);\n return;\n }\n\n await sql`select set_config('lock_timeout', ${concurrentIndex.lockTimeout}, false)`;\n try {\n const [existing] = await sql<Array<{ valid: boolean; ready: boolean }>>`\n select i.indisvalid as valid, i.indisready as ready\n from pg_catalog.pg_class c\n join pg_catalog.pg_namespace n on n.oid = c.relnamespace\n join pg_catalog.pg_index i on i.indexrelid = c.oid\n where n.nspname = current_schema() and c.relname = ${concurrentIndex.indexName}\n `;\n if (existing && (!existing.valid || !existing.ready)) {\n const quotedIndexName = `\"${concurrentIndex.indexName.replaceAll('\"', '\"\"')}\"`;\n await sql.unsafe(`DROP INDEX CONCURRENTLY ${quotedIndexName}`);\n } else if (existing && concurrentIndex.skipWhenValid) {\n return;\n }\n await sql.unsafe(concurrentIndex.statement);\n } finally {\n await sql`select set_config('lock_timeout', '0', false)`;\n }\n}\n\n/**\n * Apply the OpenGeni SQL migration chain.\n *\n * STANDALONE (default, unchanged): `migrate()` / `migrate(databaseUrl)` runs the\n * whole chain with NO search_path manipulation, so every unqualified\n * table/index/policy lands in the server default schema (`public`). This is the\n * byte-for-byte historical behavior — the migration test suite calls\n * `migrate(DB_URL)` and is unaffected.\n *\n * EMBEDDED SCHEMA MODE: pass a `schema` (or set\n * `OPENGENI_DB_SCHEMA`). The migrate session then `CREATE SCHEMA IF NOT EXISTS`\n * for both `<schema>` and `opengeni_private`, and sets\n * `search_path = \"<schema>\", \"opengeni_private\", \"public\"`, so EVERY unqualified\n * DDL statement lands in the dedicated schema with NO per-statement SQL rewrite\n * (the schema-isolation contract). Two things make this work and stay idempotent:\n * 1. The policy-existence guards in the migration SQL use `current_schema()`\n * (not a hardcoded `'public'`) — so a re-run finds the policy it already\n * created in `<schema>` and DROP/CREATEs idempotently instead of failing\n * with \"policy already exists\". (This guard substitution is the migrate-\n * time enabler for the runtime search_path approach; without it the SDK\n * entry point silently fails on re-run — the migration replay hazard.)\n * 2. `public` stays LAST on the path so `gen_random_uuid()` (pgcrypto) and the\n * `vector` type — both installed into `public` by 0000 — still resolve. The\n * `opengeni_private.*` helpers are always called with an absolute prefix.\n *\n * `OPENGENI_DB_SCHEMA` defaults UNSET → `public` → standalone, so the default\n * binding never regresses.\n */\nexport async function migrate(\n databaseUrl = process.env.OPENGENI_MIGRATIONS_DATABASE_URL ??\n process.env.OPENGENI_DATABASE_URL ??\n DEFAULT_DATABASE_URL,\n schema: string | undefined = process.env.OPENGENI_DB_SCHEMA?.trim() || undefined,\n): Promise<void> {\n const migrationsDir = join(dirname(fileURLToPath(import.meta.url)), \"../drizzle\");\n const files = (await readdir(migrationsDir)).filter((file) => file.endsWith(\".sql\")).sort();\n const sql = postgres(databaseUrl, { max: 1 });\n try {\n // Serialize concurrent migrate() runs; the session-level lock is released\n // when the connection closes.\n await sql`SELECT pg_advisory_lock(727458)`;\n if (schema) {\n assertIdentifier(\"OPENGENI_DB_SCHEMA\", schema);\n await sql.unsafe(`CREATE SCHEMA IF NOT EXISTS \"${schema}\"`);\n // opengeni_private is also created by 0001 with an absolute prefix, but the\n // session search_path must already resolve it for the policy predicates\n // and the SECURITY DEFINER functions that inherit the caller's path.\n await sql.unsafe(`CREATE SCHEMA IF NOT EXISTS \"opengeni_private\"`);\n await sql.unsafe(`SET search_path = \"${schema}\", \"opengeni_private\", \"public\"`);\n }\n await sql.unsafe(\n `CREATE TABLE IF NOT EXISTS \"schema_migrations\" (\"name\" text PRIMARY KEY, \"applied_at\" timestamptz NOT NULL DEFAULT now())`,\n );\n const appliedRows = await sql`SELECT \"name\" FROM \"schema_migrations\"`;\n const applied = new Set(appliedRows.map((row) => row.name as string));\n for (const file of files) {\n if (applied.has(file)) {\n continue;\n }\n const sqlText = await readFile(join(migrationsDir, file), \"utf8\");\n await executeMigrationFile(sql, file, sqlText);\n await sql`INSERT INTO \"schema_migrations\" (\"name\") VALUES (${file}) ON CONFLICT DO NOTHING`;\n }\n } finally {\n await sql.end();\n }\n}\n\n/**\n * SDK entry point (Step I): run the migration chain over a host-supplied admin\n * connection string against an explicit target schema. This is the embedded\n * topology's named entry — a host calls `runMigrations(adminConnection,\n * targetSchema)` from its own provisioning code instead of relying on env vars.\n * `targetSchema` undefined → `public` → standalone behavior. Thin wrapper over\n * `migrate` so there is one migration engine.\n */\nexport async function runMigrations(adminConnection: string, targetSchema?: string): Promise<void> {\n await migrate(adminConnection, targetSchema);\n}\n\nif (import.meta.main) {\n await migrate();\n console.log(\"Applied Drizzle SQL migrations.\");\n}\n"],"mappings":"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","names":[]}
|