@opengeni/db 0.10.7 → 0.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/{chunk-P6PKXY5W.js → chunk-VUKRIBO5.js} +485 -12
  2. package/dist/chunk-VUKRIBO5.js.map +1 -0
  3. package/dist/{chunk-KW526IJA.js → chunk-Y5WZZVQK.js} +80 -4
  4. package/dist/chunk-Y5WZZVQK.js.map +1 -0
  5. package/dist/index.d.ts +3 -2
  6. package/dist/index.js +5114 -2085
  7. package/dist/index.js.map +1 -1
  8. package/dist/migrate.d.ts +6 -3
  9. package/dist/migrate.js +1 -1
  10. package/dist/provision-roles.d.ts +720 -63
  11. package/dist/{schema-CqkzrBRS.d.ts → schema-BejThLcd.d.ts} +2965 -1194
  12. package/dist/schema.d.ts +1 -1
  13. package/dist/schema.js +17 -1
  14. package/drizzle/0109_nested_agent_depth_expand.sql +42 -0
  15. package/drizzle/0110_nested_agent_depth_boundary.sql +480 -0
  16. package/drizzle/0111_nested_agent_depth_backfill.sql +49 -0
  17. package/drizzle/0112_nested_agent_depth_contract.sql +38 -0
  18. package/drizzle/0113_nested_agent_depth_validate.sql +13 -0
  19. package/drizzle/0114_nested_agent_depth_contract.sql +49 -0
  20. package/drizzle/0115_nested_agent_depth_validate.sql +11 -0
  21. package/drizzle/0116_nested_agent_depth_index.sql +4 -0
  22. package/drizzle/0117_sandbox_recovery_generations.sql +699 -0
  23. package/drizzle/0118_new_session_drafts.sql +59 -0
  24. package/drizzle/0119_pending_tool_output_policy.sql +5 -0
  25. package/drizzle/0120_durable_goal_wake.sql +360 -0
  26. package/drizzle/0121_goal_update_idempotency.sql +11 -0
  27. package/package.json +3 -3
  28. package/src/index.ts +5961 -1240
  29. package/src/migrate.ts +131 -2
  30. package/src/new-session-drafts.ts +144 -0
  31. package/src/schema.ts +519 -15
  32. package/src/session-control.ts +42 -18
  33. package/src/session-tool-call-settlement.ts +6 -1
  34. package/dist/chunk-KW526IJA.js.map +0 -1
  35. package/dist/chunk-P6PKXY5W.js.map +0 -1
@@ -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 rows = await db
1353
- .select()
1354
- .from(schema.sessionCommandReceipts)
1355
- .where(
1356
- and(
1357
- eq(schema.sessionCommandReceipts.workspaceId, input.workspaceId),
1358
- eq(schema.sessionCommandReceipts.actorType, input.actor.type),
1359
- sql`${schema.sessionCommandReceipts.actorSubjectId} is not distinct from ${actorSubjectId}`,
1360
- sql`${schema.sessionCommandReceipts.actorAttemptId} is not distinct from ${actorAttemptId}::uuid`,
1361
- eq(schema.sessionCommandReceipts.action, input.action),
1362
- sql`${schema.sessionCommandReceipts.targetSessionId} is not distinct from ${input.targetSessionId}::uuid`,
1363
- sql`${schema.sessionCommandReceipts.targetTurnId} is not distinct from ${input.targetTurnId}::uuid`,
1364
- eq(schema.sessionCommandReceipts.operationKey, input.operationKey),
1365
- ),
1366
- )
1367
- .for("update");
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(boundModelToolOutputItem(resolution.result)),
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":[]}