@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.
- package/dist/agents/checkpoints.d.ts +4 -0
- package/dist/agents/checkpoints.d.ts.map +1 -1
- package/dist/index.js +182 -6
- package/dist/index.js.map +7 -7
- package/dist/pg-ai-usage-storage.d.ts +2 -1
- package/dist/pg-ai-usage-storage.d.ts.map +1 -1
- package/dist/pg-object-storage.d.ts +4 -3
- package/dist/pg-object-storage.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/agents/checkpoints.ts +29 -0
- package/src/pg-ai-usage-storage.ts +15 -0
- package/src/pg-object-query-compiler.ts +81 -1
- package/src/pg-object-storage.ts +109 -13
|
@@ -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;
|
|
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 '
|
|
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(
|
|
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 =
|
|
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(
|
|
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=
|
|
15349
|
+
//# debugId=0531F72AD7BC178764756E2164756E21
|