@sixb/pg 0.1.3 → 0.1.5

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.
@@ -8,5 +8,9 @@ export declare class PgAgentContextCheckpointStore implements AgentContextCheckp
8
8
  readonly projectId: string;
9
9
  readonly threadId: string;
10
10
  }): Promise<AgentContextCheckpointRecord | null>;
11
+ getByRunIds(input: {
12
+ readonly projectId: string;
13
+ readonly runIds: readonly string[];
14
+ }): Promise<readonly AgentContextCheckpointRecord[]>;
11
15
  }
12
16
  //# sourceMappingURL=checkpoints.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"checkpoints.d.ts","sourceRoot":"","sources":["../../src/agents/checkpoints.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,KAAK,4BAA4B,EACjC,KAAK,2BAA2B,EAEhC,KAAK,iCAAiC,EACvC,MAAM,oBAAoB,CAAA;AAE3B,OAAO,EAAE,KAAK,aAAa,EAAoB,MAAM,iBAAiB,CAAA;AAYtE,qBAAa,6BAA8B,YAAW,2BAA2B;IACnE,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAAH,GAAG,EAAE,aAAa;IAEzC,MAAM,CAAC,KAAK,EAAE,iCAAiC,GAAG,OAAO,CAAC,4BAA4B,CAAC;IAqIvF,SAAS,CAAC,KAAK,EAAE;QACrB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;QAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAC1B,GAAG,OAAO,CAAC,4BAA4B,GAAG,IAAI,CAAC;CASjD"}
1
+ {"version":3,"file":"checkpoints.d.ts","sourceRoot":"","sources":["../../src/agents/checkpoints.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,KAAK,4BAA4B,EACjC,KAAK,2BAA2B,EAEhC,KAAK,iCAAiC,EACvC,MAAM,oBAAoB,CAAA;AAE3B,OAAO,EAAE,KAAK,aAAa,EAAoB,MAAM,iBAAiB,CAAA;AActE,qBAAa,6BAA8B,YAAW,2BAA2B;IACnE,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAAH,GAAG,EAAE,aAAa;IAEzC,MAAM,CAAC,KAAK,EAAE,iCAAiC,GAAG,OAAO,CAAC,4BAA4B,CAAC;IAqIvF,SAAS,CAAC,KAAK,EAAE;QACrB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;QAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAC1B,GAAG,OAAO,CAAC,4BAA4B,GAAG,IAAI,CAAC;IAU1C,WAAW,CAAC,KAAK,EAAE;QACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;QAC1B,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;KACnC,GAAG,OAAO,CAAC,SAAS,4BAA4B,EAAE,CAAC;CAuBrD"}
package/dist/index.js CHANGED
@@ -213,6 +213,8 @@ async function queryAgentList(input) {
213
213
  }
214
214
 
215
215
  // src/agents/checkpoints.ts
216
+ var PG_CHECKPOINT_RUN_ID_BATCH_SIZE = 1e4;
217
+
216
218
  class PgAgentContextCheckpointStore {
217
219
  sql;
218
220
  constructor(sql) {
@@ -343,6 +345,22 @@ class PgAgentContextCheckpointStore {
343
345
  `;
344
346
  return row ? rowToContextCheckpointRecord(row) : null;
345
347
  }
348
+ async getByRunIds(input) {
349
+ const runIds = [...new Set(input.runIds)];
350
+ if (runIds.length === 0)
351
+ return [];
352
+ const rows = [];
353
+ for (let offset = 0;offset < runIds.length; offset += PG_CHECKPOINT_RUN_ID_BATCH_SIZE) {
354
+ const batch = runIds.slice(offset, offset + PG_CHECKPOINT_RUN_ID_BATCH_SIZE);
355
+ const placeholders = batch.map((_, index) => `$${index + 2}`).join(", ");
356
+ rows.push(...await this.sql.unsafe(`SELECT * FROM agent_context_checkpoints WHERE project_id = $1 AND created_by_run_id IN (${placeholders})`, [input.projectId, ...batch]));
357
+ }
358
+ const byRunId = new Map(rows.map((row) => [row.created_by_run_id, rowToContextCheckpointRecord(row)]));
359
+ return runIds.flatMap((runId) => {
360
+ const checkpoint = byRunId.get(runId);
361
+ return checkpoint ? [checkpoint] : [];
362
+ });
363
+ }
346
364
  }
347
365
 
348
366
  // src/agents/messages.ts
@@ -10718,6 +10736,17 @@ class PgAiUsageStorage {
10718
10736
  });
10719
10737
  return summary;
10720
10738
  }
10739
+ async getLatestForExecution(input) {
10740
+ assertNonBlankProjectId(input.projectId);
10741
+ assertAiUsageExecutionId(input.executionId);
10742
+ const [row] = await this.sql`
10743
+ SELECT * FROM ai_model_call_usage
10744
+ WHERE project_id = ${input.projectId} AND execution_id = ${input.executionId}
10745
+ ORDER BY occurred_at DESC, id DESC
10746
+ LIMIT 1
10747
+ `;
10748
+ return row ? this.rowToRecord(this.sql, row) : null;
10749
+ }
10721
10750
  async summarizeExecutions(input) {
10722
10751
  assertNonBlankProjectId(input.projectId);
10723
10752
  for (const executionId of input.executionIds)
@@ -10980,6 +11009,9 @@ function toStorageRow(row) {
10980
11009
  };
10981
11010
  }
10982
11011
 
11012
+ // src/pg-object-storage.ts
11013
+ import { linkBatchKey, objectBatchKey } from "@sixb/core/storage";
11014
+
10983
11015
  // src/pg-object-query-compiler.ts
10984
11016
  import {
10985
11017
  ObjectQueryExecutionError
@@ -11045,6 +11077,8 @@ function compileObjectQueryInternal(projectId, query, ctx) {
11045
11077
  switch (query.kind) {
11046
11078
  case "start":
11047
11079
  return compileStart(projectId, query);
11080
+ case "refs":
11081
+ return compileRefs(projectId, query);
11048
11082
  case "filter":
11049
11083
  return compileFilter(projectId, query.input, query.predicate);
11050
11084
  case "sort":
@@ -11091,6 +11125,50 @@ function compileStart(projectId, query) {
11091
11125
  }
11092
11126
  };
11093
11127
  }
11128
+ function compileRefs(projectId, query) {
11129
+ if (query.refs.length === 0) {
11130
+ throw new Error("[SixbPg] PostgreSQL object storage requires at least one ref");
11131
+ }
11132
+ const order = compileOrder(identityOrderFields());
11133
+ const selectedOrder = compileOrder(identityOrderFields(), "selected");
11134
+ const refsJson = JSON.stringify(query.refs);
11135
+ const requested = `
11136
+ SELECT DISTINCT
11137
+ ref.value ->> 'objectTypeId' AS object_type_id,
11138
+ ref.value ->> 'primaryId' AS primary_id
11139
+ FROM jsonb_array_elements(?::text::jsonb) AS ref(value)
11140
+ `;
11141
+ const sql = `
11142
+ WITH requested AS (${requested})
11143
+ SELECT selected.*, selected.properties AS _cursor_properties
11144
+ FROM requested
11145
+ JOIN objects AS selected
11146
+ ON selected.project_id = ?
11147
+ AND selected.object_type_id = requested.object_type_id
11148
+ AND selected.primary_id = requested.primary_id
11149
+ ORDER BY ${selectedOrder.sql}
11150
+ `;
11151
+ return {
11152
+ sql,
11153
+ args: [refsJson, projectId, ...selectedOrder.args],
11154
+ totalSql: `
11155
+ WITH requested AS (${requested})
11156
+ SELECT COUNT(*)::bigint AS total
11157
+ FROM requested
11158
+ JOIN objects AS selected
11159
+ ON selected.project_id = ?
11160
+ AND selected.object_type_id = requested.object_type_id
11161
+ AND selected.primary_id = requested.primary_id
11162
+ `,
11163
+ totalArgs: [refsJson, projectId],
11164
+ order,
11165
+ hasMore: () => false,
11166
+ trimRows: identityRows,
11167
+ nextPageToken: () => {
11168
+ return;
11169
+ }
11170
+ };
11171
+ }
11094
11172
  function compileFilter(projectId, inputQuery, predicateNode) {
11095
11173
  return compileWhere(projectId, inputQuery, compilePredicate(predicateNode));
11096
11174
  }
@@ -11455,6 +11533,8 @@ function compileAggregateSource(projectId, query) {
11455
11533
  switch (query.kind) {
11456
11534
  case "start":
11457
11535
  return compileAggregateStart(projectId, query);
11536
+ case "refs":
11537
+ return compileAggregateRefs(projectId, query);
11458
11538
  case "filter":
11459
11539
  return compileAggregateWhere(projectId, query.input, compilePredicate(query.predicate));
11460
11540
  case "text": {
@@ -11472,7 +11552,7 @@ function compileAggregateSource(projectId, query) {
11472
11552
  case "page":
11473
11553
  return compileRowQueryAggregateSource(projectId, query);
11474
11554
  case "vector":
11475
- throw new Error(`[SixbPg] PostgreSQL object storage does not support query node 'vector'`);
11555
+ throw new Error(`[SixbPg] PostgreSQL object storage does not support query node '${query.kind}'`);
11476
11556
  }
11477
11557
  }
11478
11558
  function compileAggregateStart(projectId, query) {
@@ -11488,6 +11568,27 @@ function compileAggregateStart(projectId, query) {
11488
11568
  args: [projectId, query.objectTypeId]
11489
11569
  };
11490
11570
  }
11571
+ function compileAggregateRefs(projectId, query) {
11572
+ if (query.refs.length === 0) {
11573
+ throw new Error("[SixbPg] PostgreSQL object storage requires at least one ref");
11574
+ }
11575
+ return {
11576
+ sql: `
11577
+ SELECT selected.project_id, selected.object_type_id, selected.primary_id, selected.properties
11578
+ FROM (
11579
+ SELECT DISTINCT
11580
+ ref.value ->> 'objectTypeId' AS object_type_id,
11581
+ ref.value ->> 'primaryId' AS primary_id
11582
+ FROM jsonb_array_elements(?::text::jsonb) AS ref(value)
11583
+ ) AS requested
11584
+ JOIN objects AS selected
11585
+ ON selected.project_id = ?
11586
+ AND selected.object_type_id = requested.object_type_id
11587
+ AND selected.primary_id = requested.primary_id
11588
+ `,
11589
+ args: [JSON.stringify(query.refs), projectId]
11590
+ };
11591
+ }
11491
11592
  function compileAggregateWhere(projectId, inputQuery, predicate) {
11492
11593
  const input = compileAggregateSource(projectId, inputQuery);
11493
11594
  return {
@@ -12033,6 +12134,7 @@ var PG_OBJECT_QUERY_CAPABILITIES = {
12033
12134
  facetObjects: true,
12034
12135
  nodes: {
12035
12136
  start: true,
12137
+ refs: true,
12036
12138
  filter: true,
12037
12139
  text: true,
12038
12140
  sort: true,
@@ -12084,7 +12186,7 @@ var PG_OBJECT_QUERY_CAPABILITIES = {
12084
12186
  stablePageTokens: true
12085
12187
  },
12086
12188
  notes: [
12087
- "PostgreSQL object query pushdown supports start/filter/text/sort/limit/page/traverse/set/project/expand over JSONB properties and object links.",
12189
+ "PostgreSQL object query pushdown supports start/refs/filter/text/sort/limit/page/traverse/set/project/expand over JSONB properties and object links.",
12088
12190
  "expand hydrates linked objects in-database (top-N per parent via LATERAL + jsonb_agg); core resolves each expansion's cardinality before pushdown, and a mixed/unresolved one stays on the fallback.",
12089
12191
  "Exact decimal predicates, ordering, and keyset pagination use PostgreSQL numeric casts.",
12090
12192
  "Relevance sorting, vector search, and unresolved start.includeSubtypes remain planner fallback or rejection cases."
@@ -12171,7 +12273,7 @@ class PgObjectStorage {
12171
12273
  return result;
12172
12274
  const rows = await valuesJoin(this.sql, "SELECT o.* FROM objects o", ["object_type_id", "primary_id"], params.items.map((i) => [i.objectTypeId, i.primaryId]), `WHERE o.project_id = $1`, [params.projectId]);
12173
12275
  for (const row of rows) {
12174
- result.set(`${row.object_type_id}:${row.primary_id}`, rowToObject(row));
12276
+ result.set(objectBatchKey(row.object_type_id, row.primary_id), rowToObject(row));
12175
12277
  }
12176
12278
  return result;
12177
12279
  }
@@ -12181,13 +12283,73 @@ class PgObjectStorage {
12181
12283
  return result;
12182
12284
  const rows = await valuesJoin(this.sql, "SELECT l.* FROM links l", ["source_type_id", "source_id", "link_id"], params.items.map((i) => [i.objectTypeId, i.objectId, i.linkId]), `WHERE l.project_id = $1`, [params.projectId]);
12183
12285
  for (const row of rows) {
12184
- const key = `${row.source_type_id}:${row.source_id}:${row.link_id}`;
12286
+ const key = linkBatchKey(row.source_type_id, row.source_id, row.link_id);
12185
12287
  const existing = result.get(key) ?? [];
12186
12288
  existing.push(rowToLink(row));
12187
12289
  result.set(key, existing);
12188
12290
  }
12189
12291
  return result;
12190
12292
  }
12293
+ async queryLinks(params) {
12294
+ assertLinkQueryLimit(params.limit);
12295
+ if (params.objectRefs.length === 0 || params.endpointObjectTypeIds?.length === 0) {
12296
+ return { links: [], hasMore: false };
12297
+ }
12298
+ const args = [JSON.stringify(params.objectRefs), params.projectId];
12299
+ const addArg = (value) => {
12300
+ args.push(value);
12301
+ return `$${args.length}`;
12302
+ };
12303
+ const sourceJoin = `
12304
+ SELECT link.*
12305
+ FROM links AS link
12306
+ JOIN requested
12307
+ ON requested.object_type_id = link.source_type_id
12308
+ AND requested.object_id = link.source_id
12309
+ WHERE link.project_id = $2
12310
+ `;
12311
+ const targetJoin = `
12312
+ SELECT link.*
12313
+ FROM links AS link
12314
+ JOIN requested
12315
+ ON requested.object_type_id = link.target_type_id
12316
+ AND requested.object_id = link.target_id
12317
+ WHERE link.project_id = $2
12318
+ `;
12319
+ const incidentSql = params.direction === "outgoing" ? sourceJoin : params.direction === "incoming" ? targetJoin : `${sourceJoin} UNION ${targetJoin}`;
12320
+ const predicates = [];
12321
+ if (params.linkId !== undefined) {
12322
+ predicates.push(`link_id = ${addArg(params.linkId)}::text`);
12323
+ }
12324
+ if (params.endpointObjectTypeIds !== undefined) {
12325
+ const allowedTypes = addArg(JSON.stringify([...new Set(params.endpointObjectTypeIds)]));
12326
+ predicates.push(`source_type_id IN (SELECT jsonb_array_elements_text(${allowedTypes}::text::jsonb))`, `target_type_id IN (SELECT jsonb_array_elements_text(${allowedTypes}::text::jsonb))`);
12327
+ }
12328
+ if (params.after) {
12329
+ const cursor = params.after.map((value) => `${addArg(value)}::text`);
12330
+ predicates.push(`(source_type_id, source_id, link_id, target_type_id, target_id) > (${cursor.join(", ")})`);
12331
+ }
12332
+ const limit = addArg(params.limit + 1);
12333
+ const whereSql = predicates.length > 0 ? `WHERE ${predicates.join(" AND ")}` : "";
12334
+ const rows = await this.sql.unsafe(`
12335
+ WITH requested AS (
12336
+ SELECT DISTINCT
12337
+ requested."objectTypeId" AS object_type_id,
12338
+ requested."primaryId" AS object_id
12339
+ FROM jsonb_to_recordset($1::text::jsonb)
12340
+ AS requested("objectTypeId" text, "primaryId" text)
12341
+ ), incident AS (${incidentSql})
12342
+ SELECT *
12343
+ FROM incident
12344
+ ${whereSql}
12345
+ ORDER BY source_type_id, source_id, link_id, target_type_id, target_id
12346
+ LIMIT ${limit}
12347
+ `, args);
12348
+ return {
12349
+ links: rows.slice(0, params.limit).map((row) => rowToLink(row)),
12350
+ hasMore: rows.length > params.limit
12351
+ };
12352
+ }
12191
12353
  async listIncidentLinksBatch(params) {
12192
12354
  if (params.items.length === 0)
12193
12355
  return [];
@@ -12197,7 +12359,7 @@ class PgObjectStorage {
12197
12359
  const deduped = new Map;
12198
12360
  for (const row of [...sourceRows, ...targetRows]) {
12199
12361
  const link = rowToLink(row);
12200
- deduped.set(`${link.sourceTypeId}:${link.sourceId}:${link.linkId}:${link.targetTypeId}:${link.targetId}`, link);
12362
+ deduped.set(linkIdentity(link), link);
12201
12363
  }
12202
12364
  return [...deduped.values()];
12203
12365
  }
@@ -12379,6 +12541,20 @@ function rowToLink(row) {
12379
12541
  lastCommitId: row.last_commit_id
12380
12542
  };
12381
12543
  }
12544
+ function linkIdentity(link) {
12545
+ return JSON.stringify([
12546
+ link.sourceTypeId,
12547
+ link.sourceId,
12548
+ link.linkId,
12549
+ link.targetTypeId,
12550
+ link.targetId
12551
+ ]);
12552
+ }
12553
+ function assertLinkQueryLimit(limit) {
12554
+ if (!Number.isSafeInteger(limit) || limit <= 0) {
12555
+ throw new Error("Object link query limit must be a positive safe integer.");
12556
+ }
12557
+ }
12382
12558
 
12383
12559
  // src/pg-pipeline-run-storage.ts
12384
12560
  import { parseSixbFailure as parseSixbFailure3, serializeSixbFailure as serializeSixbFailure3 } from "@sixb/core/internal/errors";
@@ -15170,4 +15346,4 @@ export {
15170
15346
  PostgresStorage
15171
15347
  };
15172
15348
 
15173
- //# debugId=687ACDC68EF0C51B64756E2164756E21
15349
+ //# debugId=0531F72AD7BC178764756E2164756E21