@opengeni/db 0.13.1 → 0.14.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/src/schema.ts CHANGED
@@ -1,4 +1,8 @@
1
- import type { McpServerConnectionRef, SessionMcpApprovalPolicy } from "@opengeni/contracts";
1
+ import type {
2
+ FirstPartyMcpToolName,
3
+ McpServerConnectionRef,
4
+ SessionMcpApprovalPolicy,
5
+ } from "@opengeni/contracts";
2
6
  import { sql } from "drizzle-orm";
3
7
  import type { SessionToolPolicy } from "@opengeni/contracts";
4
8
  import type { HumanInputQuestion, HumanInputResponse } from "@opengeni/contracts";
@@ -776,6 +780,7 @@ export const sessions = pgTable(
776
780
  // as a timeline event.
777
781
  instructions: text("instructions"),
778
782
  resources: jsonb("resources").$type<unknown[]>().notNull().default([]),
783
+ skills: jsonb("skills").$type<unknown[]>().notNull().default([]),
779
784
  tools: jsonb("tools").$type<unknown[]>().notNull().default([]),
780
785
  metadata: jsonb("metadata").$type<Record<string, unknown>>().notNull().default({}),
781
786
  // Frozen creator fact. This is used for creation attribution and for the
@@ -837,6 +842,9 @@ export const sessions = pgTable(
837
842
  // Non-default first-party MCP token permissions (manager-style sessions);
838
843
  // null means the fixed worker default set in @opengeni/runtime.
839
844
  firstPartyMcpPermissions: jsonb("first_party_mcp_permissions").$type<string[]>(),
845
+ // Exact model-visible first-party tool selection. NULL resolves to the
846
+ // fixed minimal default; [] intentionally selects no broad-server tools.
847
+ firstPartyMcpTools: jsonb("first_party_mcp_tools").$type<FirstPartyMcpToolName[]>(),
840
848
  // Durable tool-policy origin. NULL is retained for pre-migration rows;
841
849
  // mapSession exposes those rows as `legacy` instead of guessing omitted vs
842
850
  // explicit [].
@@ -1912,14 +1920,15 @@ export const sessionSystemUpdates = pgTable(
1912
1920
  summary: text("summary").notNull(),
1913
1921
  payload: jsonb("payload").$type<Record<string, unknown>>().notNull().default({}),
1914
1922
  lineage: jsonb("lineage").$type<Record<string, unknown>>().notNull().default({}),
1915
- // pending: eligible to start/attach to an inference; deferred: preserved
1916
- // after a failed internal-only inference but dormant until a real prompt or
1917
- // a genuinely new pending update arrives; delivered/cancelled/failed are
1918
- // terminal for that delivery attempt.
1923
+ // pending is visible queue truth; delivered means its exact model-memory
1924
+ // batch was durably claimed. Terminal cancellation/supersession is explicit.
1919
1925
  state: text("state").notNull().default("pending"),
1920
1926
  deliveredTurnId: uuid("delivered_turn_id").references(() => sessionTurns.id, {
1921
1927
  onDelete: "set null",
1922
1928
  }),
1929
+ // Migration owns the forward FK to session_history_items, declared later.
1930
+ // Every member of one claimed batch points at the exact model-memory row.
1931
+ deliveredHistoryItemId: uuid("delivered_history_item_id"),
1923
1932
  deliveredAt: timestamp("delivered_at", { withTimezone: true }),
1924
1933
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
1925
1934
  },
@@ -1934,7 +1943,7 @@ export const sessionSystemUpdates = pgTable(
1934
1943
  ),
1935
1944
  stateValid: check(
1936
1945
  "system_updates_state_check",
1937
- sql`${table.state} in ('pending', 'deferred', 'delivered', 'cancelled', 'superseded', 'failed')`,
1946
+ sql`${table.state} in ('pending', 'delivered', 'cancelled', 'superseded', 'failed')`,
1938
1947
  ),
1939
1948
  dedupe: uniqueIndex("session_system_updates_dedupe_uq").on(
1940
1949
  table.workspaceId,
@@ -1947,6 +1956,17 @@ export const sessionSystemUpdates = pgTable(
1947
1956
  table.state,
1948
1957
  table.createdAt,
1949
1958
  ),
1959
+ onePendingSteer: uniqueIndex("session_system_updates_one_pending_steer_idx")
1960
+ .on(table.workspaceId, table.sessionId)
1961
+ .where(sql`${table.kind} = 'agent_steer_instruction' and ${table.state} = 'pending'`),
1962
+ deliveryHistoryValid: check(
1963
+ "session_system_updates_delivery_history_check",
1964
+ sql`(
1965
+ (${table.state} = 'delivered' and ${table.deliveredHistoryItemId} is not null)
1966
+ or
1967
+ (${table.state} <> 'delivered' and ${table.deliveredHistoryItemId} is null)
1968
+ )`,
1969
+ ),
1950
1970
  }),
1951
1971
  );
1952
1972
 
@@ -279,17 +279,6 @@ export async function supersedeSessionCurrentDirectionInTransaction(
279
279
  updatedAt: now,
280
280
  })
281
281
  .where(eq(schema.sessionTurns.id, current.id));
282
- await db
283
- .update(schema.sessionSystemUpdates)
284
- .set({ state: "pending", deliveredTurnId: null, deliveredAt: null })
285
- .where(
286
- and(
287
- eq(schema.sessionSystemUpdates.workspaceId, input.workspaceId),
288
- eq(schema.sessionSystemUpdates.sessionId, input.sessionId),
289
- eq(schema.sessionSystemUpdates.deliveredTurnId, current.id),
290
- eq(schema.sessionSystemUpdates.state, "delivered"),
291
- ),
292
- );
293
282
  if (current.status === "waiting_capacity") {
294
283
  await db
295
284
  .update(schema.codexCapacityWaiters)
@@ -1927,7 +1916,7 @@ export async function steerAgentSessionInTransaction(
1927
1916
  controlRevision: resumed.revision,
1928
1917
  lastSequence: session.lastSequence,
1929
1918
  });
1930
- await db
1919
+ const supersededUpdates = await db
1931
1920
  .update(schema.sessionSystemUpdates)
1932
1921
  .set({ state: "superseded" })
1933
1922
  .where(
@@ -1935,9 +1924,10 @@ export async function steerAgentSessionInTransaction(
1935
1924
  eq(schema.sessionSystemUpdates.workspaceId, input.workspaceId),
1936
1925
  eq(schema.sessionSystemUpdates.sessionId, input.targetSessionId),
1937
1926
  eq(schema.sessionSystemUpdates.kind, "agent_steer_instruction"),
1938
- inArray(schema.sessionSystemUpdates.state, ["pending", "deferred"]),
1927
+ eq(schema.sessionSystemUpdates.state, "pending"),
1939
1928
  ),
1940
- );
1929
+ )
1930
+ .returning({ id: schema.sessionSystemUpdates.id });
1941
1931
  const now = new Date();
1942
1932
  const [update] = await db
1943
1933
  .insert(schema.sessionSystemUpdates)
@@ -1999,6 +1989,24 @@ export async function steerAgentSessionInTransaction(
1999
1989
  },
2000
1990
  occurredAt: now,
2001
1991
  },
1992
+ ...(supersededUpdates.length > 0
1993
+ ? [
1994
+ {
1995
+ accountId: input.accountId,
1996
+ workspaceId: input.workspaceId,
1997
+ sessionId: input.targetSessionId,
1998
+ sequence: ++sequence,
1999
+ type: "system.update.superseded" as const,
2000
+ payload: {
2001
+ updateIds: supersededUpdates.map((entry) => entry.id),
2002
+ count: supersededUpdates.length,
2003
+ replacementUpdateId: update.id,
2004
+ reason: "newer_agent_steer",
2005
+ },
2006
+ occurredAt: now,
2007
+ },
2008
+ ]
2009
+ : []),
2002
2010
  {
2003
2011
  accountId: input.accountId,
2004
2012
  workspaceId: input.workspaceId,