@opengeni/db 0.17.1 → 0.19.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-TLAC622R.js → chunk-SZP6KRLC.js} +2128 -1927
- package/dist/chunk-SZP6KRLC.js.map +1 -0
- package/dist/{chunk-T6RSJT6C.js → chunk-XOXEQ7HG.js} +29 -1
- package/dist/chunk-XOXEQ7HG.js.map +1 -0
- package/dist/index.d.ts +71 -2
- package/dist/index.js +1194 -562
- package/dist/index.js.map +1 -1
- package/dist/memory-domain.d.ts +110 -1
- package/dist/memory-governance-schema.d.ts +562 -0
- package/dist/memory-governance.d.ts +41 -0
- package/dist/provision-roles.js +1 -1
- package/dist/runtime-posture.d.ts +2 -2
- package/dist/schema.d.ts +286 -2
- package/dist/schema.js +5 -1
- package/drizzle/0141_social_connection_credentials.sql +8 -0
- package/drizzle/0151_slack_delivery_backoff.sql +134 -0
- package/drizzle/0152_hierarchical_memory_foundation.sql +1589 -0
- package/package.json +3 -3
- package/src/index.ts +304 -11
- package/src/memory-domain.ts +360 -1
- package/src/memory-governance-schema.ts +162 -0
- package/src/memory-governance.ts +317 -0
- package/src/provision-roles.ts +24 -0
- package/src/runtime-posture.ts +4 -0
- package/src/schema.ts +50 -2
- package/dist/chunk-T6RSJT6C.js.map +0 -1
- package/dist/chunk-TLAC622R.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -90,7 +90,7 @@ import {
|
|
|
90
90
|
workspaceVariableSetVariables,
|
|
91
91
|
workspaceVariableSets,
|
|
92
92
|
workspaces
|
|
93
|
-
} from "./chunk-
|
|
93
|
+
} from "./chunk-SZP6KRLC.js";
|
|
94
94
|
import {
|
|
95
95
|
migrate,
|
|
96
96
|
runMigrations
|
|
@@ -110,7 +110,7 @@ import {
|
|
|
110
110
|
inspectRuntimeDatabasePosture,
|
|
111
111
|
provisionRoles,
|
|
112
112
|
runtimeDatabaseReadyCheck
|
|
113
|
-
} from "./chunk-
|
|
113
|
+
} from "./chunk-XOXEQ7HG.js";
|
|
114
114
|
import "./chunk-PZ5AY32C.js";
|
|
115
115
|
|
|
116
116
|
// src/index.ts
|
|
@@ -122,7 +122,7 @@ import {
|
|
|
122
122
|
canonicalModalCheckpointProviderBinding,
|
|
123
123
|
decodeNativeSnapshotRef,
|
|
124
124
|
parseWorkspaceArchiveDescriptor,
|
|
125
|
-
stableJson as
|
|
125
|
+
stableJson as stableJson3
|
|
126
126
|
} from "@opengeni/contracts";
|
|
127
127
|
import {
|
|
128
128
|
approvalIdentifier,
|
|
@@ -164,6 +164,7 @@ import {
|
|
|
164
164
|
asc as asc5,
|
|
165
165
|
desc as desc5,
|
|
166
166
|
eq as eq10,
|
|
167
|
+
getTableColumns,
|
|
167
168
|
gt as gt2,
|
|
168
169
|
gte as gte2,
|
|
169
170
|
inArray as inArray5,
|
|
@@ -175,7 +176,7 @@ import {
|
|
|
175
176
|
ne,
|
|
176
177
|
notInArray,
|
|
177
178
|
or as or3,
|
|
178
|
-
sql as
|
|
179
|
+
sql as sql8
|
|
179
180
|
} from "drizzle-orm";
|
|
180
181
|
|
|
181
182
|
// src/turn-initiator.ts
|
|
@@ -2655,6 +2656,7 @@ async function insertWorkspaceControlEventInTransaction(db, input) {
|
|
|
2655
2656
|
|
|
2656
2657
|
// src/memory-domain.ts
|
|
2657
2658
|
import { createHash as createHash2 } from "crypto";
|
|
2659
|
+
import { stableJson } from "@opengeni/contracts";
|
|
2658
2660
|
var MEMORY_TEXT_MAX_CHARS = 4e3;
|
|
2659
2661
|
var MEMORY_VISIBLE_RECORD_CAP = 2e3;
|
|
2660
2662
|
var MEMORY_ACTIVE_RECORD_CAP = MEMORY_VISIBLE_RECORD_CAP;
|
|
@@ -2665,6 +2667,226 @@ var MEMORY_BLOCK_RECORD_LIMIT = 50;
|
|
|
2665
2667
|
var MEMORY_SEARCH_DEFAULT_LIMIT = 8;
|
|
2666
2668
|
var MEMORY_SEARCH_MAX_LIMIT = 20;
|
|
2667
2669
|
var AGENT_VISIBLE_MEMORY_STATUSES = ["active", "approved"];
|
|
2670
|
+
var MEMORY_LABEL_MAX_CHARS = 64;
|
|
2671
|
+
var MEMORY_LABEL_MAX_COUNT = 16;
|
|
2672
|
+
var MEMORY_NAMESPACE_MAX_CHARS = 128;
|
|
2673
|
+
var MEMORY_ROLE_KEY_MAX_CHARS = 64;
|
|
2674
|
+
var MEMORY_SUBJECT_ID_MAX_CHARS = 1024;
|
|
2675
|
+
var MEMORY_SELECTOR_SEGMENT_PATTERN = /^[a-z0-9](?:[a-z0-9._-]{0,62}[a-z0-9])?$/;
|
|
2676
|
+
var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
2677
|
+
var MEMORY_RELATIONSHIP_TYPES = [
|
|
2678
|
+
"derived_from",
|
|
2679
|
+
"supersedes",
|
|
2680
|
+
"corrects",
|
|
2681
|
+
"conflicts_with",
|
|
2682
|
+
"related_to",
|
|
2683
|
+
"depends_on",
|
|
2684
|
+
"applies_to"
|
|
2685
|
+
];
|
|
2686
|
+
var SYMMETRIC_MEMORY_RELATIONSHIPS = /* @__PURE__ */ new Set([
|
|
2687
|
+
"conflicts_with",
|
|
2688
|
+
"related_to"
|
|
2689
|
+
]);
|
|
2690
|
+
function normalizeSelectorSegment(value, label) {
|
|
2691
|
+
const normalized = value.trim().toLowerCase().replace(/\s+/g, "-");
|
|
2692
|
+
if (!MEMORY_SELECTOR_SEGMENT_PATTERN.test(normalized)) {
|
|
2693
|
+
throw new Error(
|
|
2694
|
+
`${label} must be a lowercase slug using letters, numbers, dot, underscore, or dash`
|
|
2695
|
+
);
|
|
2696
|
+
}
|
|
2697
|
+
return normalized;
|
|
2698
|
+
}
|
|
2699
|
+
function normalizeUuid(value, label) {
|
|
2700
|
+
const normalized = value.trim().toLowerCase();
|
|
2701
|
+
if (!UUID_PATTERN.test(normalized)) {
|
|
2702
|
+
throw new Error(`${label} must be a UUID`);
|
|
2703
|
+
}
|
|
2704
|
+
return normalized;
|
|
2705
|
+
}
|
|
2706
|
+
function normalizePositiveVersion(value, label) {
|
|
2707
|
+
if (!Number.isSafeInteger(value) || value <= 0) {
|
|
2708
|
+
throw new Error(`${label} must be a positive safe integer`);
|
|
2709
|
+
}
|
|
2710
|
+
return value;
|
|
2711
|
+
}
|
|
2712
|
+
function normalizeMemoryLabel(label) {
|
|
2713
|
+
const normalized = normalizeSelectorSegment(label, "memory label");
|
|
2714
|
+
if (normalized.length > MEMORY_LABEL_MAX_CHARS) {
|
|
2715
|
+
throw new Error(`memory label exceeds ${MEMORY_LABEL_MAX_CHARS} characters`);
|
|
2716
|
+
}
|
|
2717
|
+
return normalized;
|
|
2718
|
+
}
|
|
2719
|
+
function normalizeMemoryLabels(labels) {
|
|
2720
|
+
const normalized = new Set((labels ?? []).map(normalizeMemoryLabel));
|
|
2721
|
+
if (normalized.size > MEMORY_LABEL_MAX_COUNT) {
|
|
2722
|
+
throw new Error(`memory labels exceed the ${MEMORY_LABEL_MAX_COUNT}-label limit`);
|
|
2723
|
+
}
|
|
2724
|
+
return [...normalized].sort((left, right) => left < right ? -1 : left > right ? 1 : 0);
|
|
2725
|
+
}
|
|
2726
|
+
function normalizeMemoryNamespace(namespace) {
|
|
2727
|
+
const raw = namespace?.trim() || "general";
|
|
2728
|
+
const normalized = raw.split("/").map((segment) => normalizeSelectorSegment(segment, "memory namespace segment")).join("/");
|
|
2729
|
+
if (normalized.length > MEMORY_NAMESPACE_MAX_CHARS) {
|
|
2730
|
+
throw new Error(`memory namespace exceeds ${MEMORY_NAMESPACE_MAX_CHARS} characters`);
|
|
2731
|
+
}
|
|
2732
|
+
return normalized;
|
|
2733
|
+
}
|
|
2734
|
+
function normalizeMemoryRoleKey(roleKey) {
|
|
2735
|
+
const normalized = normalizeSelectorSegment(roleKey, "memory role key");
|
|
2736
|
+
if (normalized.length > MEMORY_ROLE_KEY_MAX_CHARS) {
|
|
2737
|
+
throw new Error(`memory role key exceeds ${MEMORY_ROLE_KEY_MAX_CHARS} characters`);
|
|
2738
|
+
}
|
|
2739
|
+
return normalized;
|
|
2740
|
+
}
|
|
2741
|
+
function normalizeMemoryScope(scope) {
|
|
2742
|
+
switch (scope.type) {
|
|
2743
|
+
case "workspace":
|
|
2744
|
+
return { type: "workspace" };
|
|
2745
|
+
case "user": {
|
|
2746
|
+
const subjectId = scope.subjectId.trim();
|
|
2747
|
+
if (!subjectId || subjectId.length > MEMORY_SUBJECT_ID_MAX_CHARS) {
|
|
2748
|
+
throw new Error(
|
|
2749
|
+
`memory user scope requires a subject id of at most ${MEMORY_SUBJECT_ID_MAX_CHARS} characters`
|
|
2750
|
+
);
|
|
2751
|
+
}
|
|
2752
|
+
return { type: "user", subjectId };
|
|
2753
|
+
}
|
|
2754
|
+
case "role":
|
|
2755
|
+
return { type: "role", roleKey: normalizeMemoryRoleKey(scope.roleKey) };
|
|
2756
|
+
case "session":
|
|
2757
|
+
return { type: "session", sessionId: normalizeUuid(scope.sessionId, "memory session id") };
|
|
2758
|
+
case "ephemeral": {
|
|
2759
|
+
const validUntil = new Date(scope.validUntil);
|
|
2760
|
+
if (!Number.isFinite(validUntil.getTime())) {
|
|
2761
|
+
throw new Error("ephemeral memory scope requires a valid expiry timestamp");
|
|
2762
|
+
}
|
|
2763
|
+
return {
|
|
2764
|
+
type: "ephemeral",
|
|
2765
|
+
sessionId: normalizeUuid(scope.sessionId, "ephemeral memory session id"),
|
|
2766
|
+
validUntil: validUntil.toISOString()
|
|
2767
|
+
};
|
|
2768
|
+
}
|
|
2769
|
+
case "legacy": {
|
|
2770
|
+
const legacyScope = scope.legacyScope.trim();
|
|
2771
|
+
if (!legacyScope || legacyScope.length > MEMORY_NAMESPACE_MAX_CHARS) {
|
|
2772
|
+
throw new Error("legacy memory scope must be a non-empty bounded string");
|
|
2773
|
+
}
|
|
2774
|
+
return { type: "legacy", legacyScope };
|
|
2775
|
+
}
|
|
2776
|
+
}
|
|
2777
|
+
}
|
|
2778
|
+
function isMemoryScopeApplicable(scope, context) {
|
|
2779
|
+
const normalized = normalizeMemoryScope(scope);
|
|
2780
|
+
switch (normalized.type) {
|
|
2781
|
+
case "workspace":
|
|
2782
|
+
return true;
|
|
2783
|
+
case "user":
|
|
2784
|
+
return Boolean(context.subjectId) && normalized.subjectId === context.subjectId;
|
|
2785
|
+
case "role":
|
|
2786
|
+
return Boolean(context.roleKey) && normalized.roleKey === normalizeMemoryRoleKey(context.roleKey);
|
|
2787
|
+
case "session":
|
|
2788
|
+
return Boolean(context.sessionId) && normalized.sessionId === context.sessionId;
|
|
2789
|
+
case "ephemeral": {
|
|
2790
|
+
if (!context.sessionId || normalized.sessionId !== context.sessionId) return false;
|
|
2791
|
+
const now = context.now instanceof Date ? context.now : new Date(context.now ?? Date.now());
|
|
2792
|
+
return Number.isFinite(now.getTime()) && now.getTime() < Date.parse(normalized.validUntil);
|
|
2793
|
+
}
|
|
2794
|
+
case "legacy":
|
|
2795
|
+
return false;
|
|
2796
|
+
}
|
|
2797
|
+
}
|
|
2798
|
+
function canonicalMemoryRelationship(input) {
|
|
2799
|
+
const sourceMemoryId = normalizeUuid(input.sourceMemoryId, "source memory id");
|
|
2800
|
+
const targetMemoryId = normalizeUuid(input.targetMemoryId, "target memory id");
|
|
2801
|
+
if (sourceMemoryId === targetMemoryId) {
|
|
2802
|
+
throw new Error("a memory relationship must connect two distinct memories");
|
|
2803
|
+
}
|
|
2804
|
+
if (!MEMORY_RELATIONSHIP_TYPES.includes(input.relationshipType)) {
|
|
2805
|
+
throw new Error(`unsupported memory relationship type: ${input.relationshipType}`);
|
|
2806
|
+
}
|
|
2807
|
+
if (SYMMETRIC_MEMORY_RELATIONSHIPS.has(input.relationshipType) && targetMemoryId < sourceMemoryId) {
|
|
2808
|
+
return {
|
|
2809
|
+
sourceMemoryId: targetMemoryId,
|
|
2810
|
+
targetMemoryId: sourceMemoryId,
|
|
2811
|
+
relationshipType: input.relationshipType
|
|
2812
|
+
};
|
|
2813
|
+
}
|
|
2814
|
+
return { sourceMemoryId, targetMemoryId, relationshipType: input.relationshipType };
|
|
2815
|
+
}
|
|
2816
|
+
function normalizeMemoryOperationPlan(input) {
|
|
2817
|
+
const base = {
|
|
2818
|
+
operationId: normalizeUuid(input.operationId, "memory operation id"),
|
|
2819
|
+
operationType: input.operationType,
|
|
2820
|
+
targetMemoryId: normalizeUuid(input.targetMemoryId, "target memory id"),
|
|
2821
|
+
expectedTargetVersion: normalizePositiveVersion(
|
|
2822
|
+
input.expectedTargetVersion,
|
|
2823
|
+
"expected target memory version"
|
|
2824
|
+
)
|
|
2825
|
+
};
|
|
2826
|
+
switch (input.operationType) {
|
|
2827
|
+
case "reclassify":
|
|
2828
|
+
return {
|
|
2829
|
+
...base,
|
|
2830
|
+
operationType: "reclassify",
|
|
2831
|
+
scope: normalizeMemoryScope(input.scope),
|
|
2832
|
+
namespace: normalizeMemoryNamespace(input.namespace),
|
|
2833
|
+
labels: normalizeMemoryLabels(input.labels)
|
|
2834
|
+
};
|
|
2835
|
+
case "archive":
|
|
2836
|
+
return { ...base, operationType: "archive" };
|
|
2837
|
+
case "relationship_add":
|
|
2838
|
+
case "relationship_remove": {
|
|
2839
|
+
const relatedMemoryId = normalizeUuid(input.relatedMemoryId, "related memory id");
|
|
2840
|
+
const expectedRelatedVersion = normalizePositiveVersion(
|
|
2841
|
+
input.expectedRelatedVersion,
|
|
2842
|
+
"expected related memory version"
|
|
2843
|
+
);
|
|
2844
|
+
const relationship = canonicalMemoryRelationship({
|
|
2845
|
+
sourceMemoryId: base.targetMemoryId,
|
|
2846
|
+
targetMemoryId: relatedMemoryId,
|
|
2847
|
+
relationshipType: input.relationshipType
|
|
2848
|
+
});
|
|
2849
|
+
const endpointsWereSwapped = relationship.sourceMemoryId !== base.targetMemoryId;
|
|
2850
|
+
return {
|
|
2851
|
+
...base,
|
|
2852
|
+
operationType: input.operationType,
|
|
2853
|
+
targetMemoryId: relationship.sourceMemoryId,
|
|
2854
|
+
relatedMemoryId: relationship.targetMemoryId,
|
|
2855
|
+
expectedTargetVersion: endpointsWereSwapped ? expectedRelatedVersion : base.expectedTargetVersion,
|
|
2856
|
+
expectedRelatedVersion: endpointsWereSwapped ? base.expectedTargetVersion : expectedRelatedVersion,
|
|
2857
|
+
relationshipType: relationship.relationshipType
|
|
2858
|
+
};
|
|
2859
|
+
}
|
|
2860
|
+
case "supersede":
|
|
2861
|
+
case "correct": {
|
|
2862
|
+
const relatedMemoryId = normalizeUuid(input.relatedMemoryId, "replacement memory id");
|
|
2863
|
+
if (relatedMemoryId === base.targetMemoryId) {
|
|
2864
|
+
throw new Error("a memory cannot supersede or correct itself");
|
|
2865
|
+
}
|
|
2866
|
+
return {
|
|
2867
|
+
...base,
|
|
2868
|
+
operationType: input.operationType,
|
|
2869
|
+
relatedMemoryId,
|
|
2870
|
+
expectedRelatedVersion: normalizePositiveVersion(
|
|
2871
|
+
input.expectedRelatedVersion,
|
|
2872
|
+
"expected replacement memory version"
|
|
2873
|
+
)
|
|
2874
|
+
};
|
|
2875
|
+
}
|
|
2876
|
+
}
|
|
2877
|
+
}
|
|
2878
|
+
function hashMemoryOperationPlan(plan) {
|
|
2879
|
+
return createHash2("sha256").update(stableJson(plan), "utf8").digest("hex");
|
|
2880
|
+
}
|
|
2881
|
+
function normalizeMemoryRevertPlan(input) {
|
|
2882
|
+
return {
|
|
2883
|
+
operationId: normalizeUuid(input.operationId, "memory revert operation id"),
|
|
2884
|
+
appliedOperationId: normalizeUuid(input.appliedOperationId, "applied memory operation id")
|
|
2885
|
+
};
|
|
2886
|
+
}
|
|
2887
|
+
function hashMemoryRevertPlan(plan) {
|
|
2888
|
+
return createHash2("sha256").update(stableJson(plan), "utf8").digest("hex");
|
|
2889
|
+
}
|
|
2668
2890
|
var MEMORY_BLOCK_KIND_ORDER = [
|
|
2669
2891
|
"preference",
|
|
2670
2892
|
"semantic",
|
|
@@ -2782,7 +3004,7 @@ function renderMemoryEntry(record) {
|
|
|
2782
3004
|
}
|
|
2783
3005
|
|
|
2784
3006
|
// src/index.ts
|
|
2785
|
-
import { sql as
|
|
3007
|
+
import { sql as sql9 } from "drizzle-orm";
|
|
2786
3008
|
|
|
2787
3009
|
// src/session-queue-commands.ts
|
|
2788
3010
|
import {
|
|
@@ -2790,7 +3012,7 @@ import {
|
|
|
2790
3012
|
mergeResourceRefs,
|
|
2791
3013
|
ResourceRef,
|
|
2792
3014
|
resourceMountPath,
|
|
2793
|
-
stableJson,
|
|
3015
|
+
stableJson as stableJson2,
|
|
2794
3016
|
turnExecutionPolicyAuditMetadata
|
|
2795
3017
|
} from "@opengeni/contracts";
|
|
2796
3018
|
import { and as and5, asc as asc2, eq as eq5, inArray as inArray2, sql as sql3 } from "drizzle-orm";
|
|
@@ -3003,7 +3225,7 @@ function withCanonicalResourceMountPaths(resources) {
|
|
|
3003
3225
|
...value,
|
|
3004
3226
|
mountPath: resourceMountPath(parsed.data)
|
|
3005
3227
|
};
|
|
3006
|
-
const key =
|
|
3228
|
+
const key = stableJson2(normalized);
|
|
3007
3229
|
if (seen.has(key)) continue;
|
|
3008
3230
|
seen.add(key);
|
|
3009
3231
|
canonical.push(normalized);
|
|
@@ -5637,8 +5859,225 @@ async function getPreferenceRegistryFullContent(db, claims, handle) {
|
|
|
5637
5859
|
});
|
|
5638
5860
|
}
|
|
5639
5861
|
|
|
5862
|
+
// src/memory-governance.ts
|
|
5863
|
+
import { sql as sql5 } from "drizzle-orm";
|
|
5864
|
+
var MemoryGovernanceAuthorityError = class extends Error {
|
|
5865
|
+
name = "MemoryGovernanceAuthorityError";
|
|
5866
|
+
};
|
|
5867
|
+
function requireBoundedActorId(value, label) {
|
|
5868
|
+
const normalized = value.trim();
|
|
5869
|
+
if (!normalized || normalized.length > 1024) {
|
|
5870
|
+
throw new MemoryGovernanceAuthorityError(`${label} must be a non-empty bounded identifier`);
|
|
5871
|
+
}
|
|
5872
|
+
return normalized;
|
|
5873
|
+
}
|
|
5874
|
+
async function setAndVerifyMemoryGovernanceContext(db, authority) {
|
|
5875
|
+
if (authority.actorKind === "subject") {
|
|
5876
|
+
await setSubjectRlsContext(db, authority.actorSubjectId);
|
|
5877
|
+
} else {
|
|
5878
|
+
await db.execute(sql5`select set_config('opengeni.subject_id', '', true)`);
|
|
5879
|
+
}
|
|
5880
|
+
await db.execute(sql5`
|
|
5881
|
+
select
|
|
5882
|
+
set_config('opengeni.memory_actor_kind', ${authority.actorKind}, true),
|
|
5883
|
+
set_config('opengeni.memory_actor_id', ${authority.actorSubjectId}, true),
|
|
5884
|
+
set_config('opengeni.memory_session_id', ${authority.sessionId ?? ""}, true),
|
|
5885
|
+
set_config('opengeni.memory_role_key', ${authority.roleKey ?? ""}, true)
|
|
5886
|
+
`);
|
|
5887
|
+
const rows = await db.execute(sql5`
|
|
5888
|
+
select
|
|
5889
|
+
nullif(current_setting('opengeni.account_id', true), '') as account_id,
|
|
5890
|
+
nullif(current_setting('opengeni.workspace_id', true), '') as workspace_id,
|
|
5891
|
+
nullif(current_setting('opengeni.subject_id', true), '') as subject_id,
|
|
5892
|
+
nullif(current_setting('opengeni.memory_actor_kind', true), '') as actor_kind,
|
|
5893
|
+
nullif(current_setting('opengeni.memory_actor_id', true), '') as actor_id,
|
|
5894
|
+
nullif(current_setting('opengeni.memory_session_id', true), '') as session_id,
|
|
5895
|
+
nullif(current_setting('opengeni.memory_role_key', true), '') as role_key
|
|
5896
|
+
`);
|
|
5897
|
+
const applied = rows[0];
|
|
5898
|
+
if (!applied || applied.account_id !== authority.accountId || applied.workspace_id !== authority.workspaceId || applied.subject_id !== (authority.actorKind === "subject" ? authority.actorSubjectId : null) || applied.actor_kind !== authority.actorKind || applied.actor_id !== authority.actorSubjectId || applied.session_id !== authority.sessionId || applied.role_key !== authority.roleKey) {
|
|
5899
|
+
throw new MemoryGovernanceAuthorityError(
|
|
5900
|
+
"Memory governance authority was not applied on the active database backend"
|
|
5901
|
+
);
|
|
5902
|
+
}
|
|
5903
|
+
}
|
|
5904
|
+
async function resolveAttemptAuthority(db, input) {
|
|
5905
|
+
if (!Number.isSafeInteger(input.executionGeneration) || input.executionGeneration <= 0) {
|
|
5906
|
+
throw new MemoryGovernanceAuthorityError(
|
|
5907
|
+
"Memory governance attempt requires a positive execution generation"
|
|
5908
|
+
);
|
|
5909
|
+
}
|
|
5910
|
+
const rows = await db.execute(sql5`
|
|
5911
|
+
with locked_workspace as materialized (
|
|
5912
|
+
select workspace.id, workspace.account_id
|
|
5913
|
+
from workspaces workspace
|
|
5914
|
+
where workspace.id = ${input.workspaceId}::uuid
|
|
5915
|
+
and workspace.account_id = ${input.accountId}::uuid
|
|
5916
|
+
for key share of workspace
|
|
5917
|
+
), locked_session as materialized (
|
|
5918
|
+
select session.id, session.account_id, session.workspace_id,
|
|
5919
|
+
session.active_turn_id, session.metadata ->> 'memoryRoleKey' as memory_role_key
|
|
5920
|
+
from sessions session
|
|
5921
|
+
join locked_workspace workspace
|
|
5922
|
+
on workspace.id = session.workspace_id
|
|
5923
|
+
and workspace.account_id = session.account_id
|
|
5924
|
+
where session.id = ${input.sessionId}::uuid
|
|
5925
|
+
and session.active_turn_id = ${input.turnId}::uuid
|
|
5926
|
+
for share of session
|
|
5927
|
+
), locked_turn as materialized (
|
|
5928
|
+
select turn.id, turn.account_id, turn.workspace_id, turn.session_id,
|
|
5929
|
+
turn.active_attempt_id, turn.execution_generation,
|
|
5930
|
+
turn.initiator_kind, turn.initiator_subject_id
|
|
5931
|
+
from session_turns turn
|
|
5932
|
+
join locked_session session
|
|
5933
|
+
on session.id = turn.session_id
|
|
5934
|
+
and session.workspace_id = turn.workspace_id
|
|
5935
|
+
and session.account_id = turn.account_id
|
|
5936
|
+
where turn.id = ${input.turnId}::uuid
|
|
5937
|
+
and turn.active_attempt_id = ${input.attemptId}::uuid
|
|
5938
|
+
and turn.execution_generation = ${input.executionGeneration}
|
|
5939
|
+
and turn.status in ('running', 'requires_action', 'recovering', 'waiting_capacity')
|
|
5940
|
+
and turn.initiator_kind in ('subject', 'service')
|
|
5941
|
+
and length(btrim(turn.initiator_subject_id)) between 1 and 1024
|
|
5942
|
+
for share of turn
|
|
5943
|
+
), locked_attempt as materialized (
|
|
5944
|
+
select attempt.id, attempt.account_id, attempt.workspace_id,
|
|
5945
|
+
attempt.session_id, attempt.turn_id, attempt.execution_generation
|
|
5946
|
+
from session_turn_attempts attempt
|
|
5947
|
+
join locked_turn turn
|
|
5948
|
+
on turn.id = attempt.turn_id
|
|
5949
|
+
and turn.session_id = attempt.session_id
|
|
5950
|
+
and turn.workspace_id = attempt.workspace_id
|
|
5951
|
+
and turn.account_id = attempt.account_id
|
|
5952
|
+
where attempt.id = ${input.attemptId}::uuid
|
|
5953
|
+
and attempt.execution_generation = ${input.executionGeneration}
|
|
5954
|
+
and attempt.state in ('claimed', 'running')
|
|
5955
|
+
and not exists (
|
|
5956
|
+
select 1
|
|
5957
|
+
from session_attempt_interruptions interruption
|
|
5958
|
+
where interruption.workspace_id = attempt.workspace_id
|
|
5959
|
+
and interruption.attempt_id = attempt.id
|
|
5960
|
+
and interruption.state in ('pending', 'delivered', 'acknowledged')
|
|
5961
|
+
)
|
|
5962
|
+
for share of attempt
|
|
5963
|
+
)
|
|
5964
|
+
select turn.initiator_kind, turn.initiator_subject_id, session.memory_role_key
|
|
5965
|
+
from locked_workspace workspace
|
|
5966
|
+
join locked_session session on true
|
|
5967
|
+
join locked_turn turn on true
|
|
5968
|
+
join locked_attempt attempt on true
|
|
5969
|
+
where workspace.account_id = attempt.account_id
|
|
5970
|
+
and workspace.id = attempt.workspace_id
|
|
5971
|
+
and session.id = attempt.session_id
|
|
5972
|
+
and turn.id = attempt.turn_id
|
|
5973
|
+
`);
|
|
5974
|
+
const row = rows[0];
|
|
5975
|
+
if (!row) {
|
|
5976
|
+
throw new MemoryGovernanceAuthorityError(
|
|
5977
|
+
"Memory governance requires the exact current attempt, generation, and immutable initiator"
|
|
5978
|
+
);
|
|
5979
|
+
}
|
|
5980
|
+
let roleKey = null;
|
|
5981
|
+
if (row.memory_role_key !== null) {
|
|
5982
|
+
try {
|
|
5983
|
+
roleKey = normalizeMemoryRoleKey(row.memory_role_key);
|
|
5984
|
+
} catch {
|
|
5985
|
+
throw new MemoryGovernanceAuthorityError(
|
|
5986
|
+
"Persisted session memoryRoleKey is invalid; role-scoped authority fails closed"
|
|
5987
|
+
);
|
|
5988
|
+
}
|
|
5989
|
+
if (roleKey !== row.memory_role_key) {
|
|
5990
|
+
throw new MemoryGovernanceAuthorityError(
|
|
5991
|
+
"Persisted session memoryRoleKey is not canonical; role-scoped authority fails closed"
|
|
5992
|
+
);
|
|
5993
|
+
}
|
|
5994
|
+
}
|
|
5995
|
+
return {
|
|
5996
|
+
accountId: input.accountId,
|
|
5997
|
+
workspaceId: input.workspaceId,
|
|
5998
|
+
actorKind: row.initiator_kind,
|
|
5999
|
+
actorSubjectId: row.initiator_subject_id,
|
|
6000
|
+
sessionId: input.sessionId,
|
|
6001
|
+
turnId: input.turnId,
|
|
6002
|
+
attemptId: input.attemptId,
|
|
6003
|
+
executionGeneration: input.executionGeneration,
|
|
6004
|
+
roleKey
|
|
6005
|
+
};
|
|
6006
|
+
}
|
|
6007
|
+
async function withMemoryGovernanceAuthority(db, authority, fn) {
|
|
6008
|
+
return await withWorkspaceRls(db, authority.workspaceId, async (scopedDb) => {
|
|
6009
|
+
let resolved;
|
|
6010
|
+
if (authority.kind === "attempt") {
|
|
6011
|
+
resolved = await resolveAttemptAuthority(scopedDb, authority);
|
|
6012
|
+
} else {
|
|
6013
|
+
const actorSubjectId = requireBoundedActorId(
|
|
6014
|
+
authority.kind === "subject" ? authority.subjectId : authority.serviceId,
|
|
6015
|
+
authority.kind === "subject" ? "subject id" : "service id"
|
|
6016
|
+
);
|
|
6017
|
+
resolved = {
|
|
6018
|
+
accountId: authority.accountId,
|
|
6019
|
+
workspaceId: authority.workspaceId,
|
|
6020
|
+
actorKind: authority.kind,
|
|
6021
|
+
actorSubjectId,
|
|
6022
|
+
sessionId: null,
|
|
6023
|
+
turnId: null,
|
|
6024
|
+
attemptId: null,
|
|
6025
|
+
executionGeneration: null,
|
|
6026
|
+
roleKey: null
|
|
6027
|
+
};
|
|
6028
|
+
}
|
|
6029
|
+
await setAndVerifyMemoryGovernanceContext(scopedDb, resolved);
|
|
6030
|
+
return await fn(scopedDb, resolved);
|
|
6031
|
+
});
|
|
6032
|
+
}
|
|
6033
|
+
async function applyKnowledgeMemoryOperation(db, input) {
|
|
6034
|
+
const plan = normalizeMemoryOperationPlan(input.plan);
|
|
6035
|
+
const planHash = hashMemoryOperationPlan(plan);
|
|
6036
|
+
return await withMemoryGovernanceAuthority(db, input.authority, async (scopedDb, authority) => {
|
|
6037
|
+
const rows = await scopedDb.execute(sql5`
|
|
6038
|
+
select event_id
|
|
6039
|
+
from knowledge_memory_apply_operation(
|
|
6040
|
+
${JSON.stringify(plan)}::jsonb,
|
|
6041
|
+
${planHash},
|
|
6042
|
+
${authority.actorKind},
|
|
6043
|
+
${authority.actorSubjectId},
|
|
6044
|
+
${authority.sessionId}::uuid,
|
|
6045
|
+
${authority.turnId}::uuid,
|
|
6046
|
+
${authority.attemptId}::uuid,
|
|
6047
|
+
${authority.executionGeneration}::integer
|
|
6048
|
+
)
|
|
6049
|
+
`);
|
|
6050
|
+
const eventId = rows[0]?.event_id;
|
|
6051
|
+
if (!eventId) throw new Error("Memory governance apply operation returned no event");
|
|
6052
|
+
return { eventId, planHash };
|
|
6053
|
+
});
|
|
6054
|
+
}
|
|
6055
|
+
async function revertKnowledgeMemoryOperation(db, input) {
|
|
6056
|
+
const plan = normalizeMemoryRevertPlan(input.plan);
|
|
6057
|
+
const planHash = hashMemoryRevertPlan(plan);
|
|
6058
|
+
return await withMemoryGovernanceAuthority(db, input.authority, async (scopedDb, authority) => {
|
|
6059
|
+
const rows = await scopedDb.execute(sql5`
|
|
6060
|
+
select event_id
|
|
6061
|
+
from knowledge_memory_revert_operation(
|
|
6062
|
+
${plan.operationId}::uuid,
|
|
6063
|
+
${plan.appliedOperationId}::uuid,
|
|
6064
|
+
${planHash},
|
|
6065
|
+
${authority.actorKind},
|
|
6066
|
+
${authority.actorSubjectId},
|
|
6067
|
+
${authority.sessionId}::uuid,
|
|
6068
|
+
${authority.turnId}::uuid,
|
|
6069
|
+
${authority.attemptId}::uuid,
|
|
6070
|
+
${authority.executionGeneration}::integer
|
|
6071
|
+
)
|
|
6072
|
+
`);
|
|
6073
|
+
const eventId = rows[0]?.event_id;
|
|
6074
|
+
if (!eventId) throw new Error("Memory governance revert operation returned no event");
|
|
6075
|
+
return { eventId, planHash };
|
|
6076
|
+
});
|
|
6077
|
+
}
|
|
6078
|
+
|
|
5640
6079
|
// src/insights.ts
|
|
5641
|
-
import { and as and8, desc as desc3, eq as eq8, gte, inArray as inArray4, lt as lt2, sql as
|
|
6080
|
+
import { and as and8, desc as desc3, eq as eq8, gte, inArray as inArray4, lt as lt2, sql as sql6 } from "drizzle-orm";
|
|
5642
6081
|
import { alias } from "drizzle-orm/pg-core";
|
|
5643
6082
|
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
5644
6083
|
function dayKeyUtc(value) {
|
|
@@ -5648,7 +6087,7 @@ async function sumUsageQuantityInRange(db, input) {
|
|
|
5648
6087
|
const context = await rlsContextForWorkspace(db, input.workspaceId);
|
|
5649
6088
|
return await withRlsContext(db, context, async (scopedDb) => {
|
|
5650
6089
|
const [{ total } = { total: 0 }] = await scopedDb.select({
|
|
5651
|
-
total:
|
|
6090
|
+
total: sql6`coalesce(sum(${usageEvents.quantity}), 0)`
|
|
5652
6091
|
}).from(usageEvents).where(
|
|
5653
6092
|
and8(
|
|
5654
6093
|
eq8(usageEvents.workspaceId, input.workspaceId),
|
|
@@ -5664,8 +6103,8 @@ async function sumUsageQuantityByDay(db, input) {
|
|
|
5664
6103
|
const context = await rlsContextForWorkspace(db, input.workspaceId);
|
|
5665
6104
|
return await withRlsContext(db, context, async (scopedDb) => {
|
|
5666
6105
|
const rows = await scopedDb.select({
|
|
5667
|
-
day:
|
|
5668
|
-
total:
|
|
6106
|
+
day: sql6`to_char(date_trunc('day', ${usageEvents.occurredAt} at time zone 'UTC'), 'YYYY-MM-DD')`,
|
|
6107
|
+
total: sql6`coalesce(sum(${usageEvents.quantity}), 0)`
|
|
5669
6108
|
}).from(usageEvents).where(
|
|
5670
6109
|
and8(
|
|
5671
6110
|
eq8(usageEvents.workspaceId, input.workspaceId),
|
|
@@ -5673,7 +6112,7 @@ async function sumUsageQuantityByDay(db, input) {
|
|
|
5673
6112
|
gte(usageEvents.occurredAt, input.since),
|
|
5674
6113
|
lt2(usageEvents.occurredAt, input.until)
|
|
5675
6114
|
)
|
|
5676
|
-
).groupBy(
|
|
6115
|
+
).groupBy(sql6`date_trunc('day', ${usageEvents.occurredAt} at time zone 'UTC')`);
|
|
5677
6116
|
return new Map(rows.map((row) => [row.day, Number(row.total)]));
|
|
5678
6117
|
});
|
|
5679
6118
|
}
|
|
@@ -5691,14 +6130,14 @@ async function aggregateModelCallFacts(db, input) {
|
|
|
5691
6130
|
provider: modelCallFacts.provider,
|
|
5692
6131
|
model: modelCallFacts.model,
|
|
5693
6132
|
billingPath: modelCallFacts.billingPath,
|
|
5694
|
-
calls:
|
|
5695
|
-
inputTokens:
|
|
5696
|
-
outputTokens:
|
|
5697
|
-
cachedTokens:
|
|
5698
|
-
cacheWriteTokens:
|
|
5699
|
-
reasoningTokens:
|
|
5700
|
-
totalTokens:
|
|
5701
|
-
pricedCostMicros:
|
|
6133
|
+
calls: sql6`count(*)::int`,
|
|
6134
|
+
inputTokens: sql6`coalesce(sum(${modelCallFacts.inputTokens}), 0)`,
|
|
6135
|
+
outputTokens: sql6`coalesce(sum(${modelCallFacts.outputTokens}), 0)`,
|
|
6136
|
+
cachedTokens: sql6`coalesce(sum(${modelCallFacts.cachedTokens}), 0)`,
|
|
6137
|
+
cacheWriteTokens: sql6`coalesce(sum(${modelCallFacts.cacheWriteTokens}), 0)`,
|
|
6138
|
+
reasoningTokens: sql6`coalesce(sum(${modelCallFacts.reasoningTokens}), 0)`,
|
|
6139
|
+
totalTokens: sql6`coalesce(sum(${modelCallFacts.totalTokens}), 0)`,
|
|
6140
|
+
pricedCostMicros: sql6`coalesce(sum(${modelCallFacts.pricedCostMicros}), 0)`
|
|
5702
6141
|
}).from(modelCallFacts).where(and8(...clauses)).groupBy(
|
|
5703
6142
|
modelCallFacts.provider,
|
|
5704
6143
|
modelCallFacts.model,
|
|
@@ -5730,12 +6169,12 @@ async function aggregateModelCallFactsByDay(db, input) {
|
|
|
5730
6169
|
...input.model ? [eq8(modelCallFacts.model, input.model)] : []
|
|
5731
6170
|
];
|
|
5732
6171
|
const rows = await scopedDb.select({
|
|
5733
|
-
day:
|
|
5734
|
-
costMicros:
|
|
5735
|
-
inputTokens:
|
|
5736
|
-
cachedTokens:
|
|
5737
|
-
calls:
|
|
5738
|
-
}).from(modelCallFacts).where(and8(...clauses)).groupBy(
|
|
6172
|
+
day: sql6`to_char(date_trunc('day', ${modelCallFacts.occurredAt} at time zone 'UTC'), 'YYYY-MM-DD')`,
|
|
6173
|
+
costMicros: sql6`coalesce(sum(${modelCallFacts.pricedCostMicros}), 0)`,
|
|
6174
|
+
inputTokens: sql6`coalesce(sum(${modelCallFacts.inputTokens}), 0)`,
|
|
6175
|
+
cachedTokens: sql6`coalesce(sum(${modelCallFacts.cachedTokens}), 0)`,
|
|
6176
|
+
calls: sql6`count(*)::int`
|
|
6177
|
+
}).from(modelCallFacts).where(and8(...clauses)).groupBy(sql6`date_trunc('day', ${modelCallFacts.occurredAt} at time zone 'UTC')`);
|
|
5739
6178
|
return new Map(
|
|
5740
6179
|
rows.map((row) => [
|
|
5741
6180
|
row.day,
|
|
@@ -5754,17 +6193,17 @@ async function aggregateWarmSecondsByGroup(db, input) {
|
|
|
5754
6193
|
const limit = input.limit ?? 24;
|
|
5755
6194
|
return await withRlsContext(db, context, async (scopedDb) => {
|
|
5756
6195
|
const rows = await scopedDb.select({
|
|
5757
|
-
groupId:
|
|
5758
|
-
warmSeconds:
|
|
6196
|
+
groupId: sql6`split_part(${usageEvents.sourceResourceId}, ':', 1)`,
|
|
6197
|
+
warmSeconds: sql6`coalesce(sum(${usageEvents.quantity}), 0)`
|
|
5759
6198
|
}).from(usageEvents).where(
|
|
5760
6199
|
and8(
|
|
5761
6200
|
eq8(usageEvents.workspaceId, input.workspaceId),
|
|
5762
6201
|
eq8(usageEvents.eventType, "sandbox.warm_seconds"),
|
|
5763
6202
|
gte(usageEvents.occurredAt, input.since),
|
|
5764
6203
|
lt2(usageEvents.occurredAt, input.until),
|
|
5765
|
-
|
|
6204
|
+
sql6`${usageEvents.sourceResourceId} is not null`
|
|
5766
6205
|
)
|
|
5767
|
-
).groupBy(
|
|
6206
|
+
).groupBy(sql6`split_part(${usageEvents.sourceResourceId}, ':', 1)`).orderBy(sql6`coalesce(sum(${usageEvents.quantity}), 0) desc`).limit(Math.max(limit * 4, limit));
|
|
5768
6207
|
return rows.filter((row) => UUID_RE.test(row.groupId)).slice(0, limit).map((row) => ({
|
|
5769
6208
|
groupId: row.groupId,
|
|
5770
6209
|
warmSeconds: Number(row.warmSeconds)
|
|
@@ -5804,7 +6243,7 @@ async function countSessionsAttachedToGroups(db, workspaceId, groupIds) {
|
|
|
5804
6243
|
return await withRlsContext(db, context, async (scopedDb) => {
|
|
5805
6244
|
const rows = await scopedDb.select({
|
|
5806
6245
|
groupId: sessions.sandboxGroupId,
|
|
5807
|
-
n:
|
|
6246
|
+
n: sql6`count(*)::int`
|
|
5808
6247
|
}).from(sessions).where(
|
|
5809
6248
|
and8(
|
|
5810
6249
|
eq8(sessions.workspaceId, workspaceId),
|
|
@@ -5833,9 +6272,9 @@ async function aggregateRootSessionDrivers(db, input) {
|
|
|
5833
6272
|
const query = scopedDb.select({
|
|
5834
6273
|
rootSessionId: childSessions.rootSessionId,
|
|
5835
6274
|
title: rootSessions.title,
|
|
5836
|
-
pricedCostMicros:
|
|
5837
|
-
inputTokens:
|
|
5838
|
-
cachedTokens:
|
|
6275
|
+
pricedCostMicros: sql6`coalesce(sum(${modelCallFacts.pricedCostMicros}), 0)`,
|
|
6276
|
+
inputTokens: sql6`coalesce(sum(${modelCallFacts.inputTokens}), 0)`,
|
|
6277
|
+
cachedTokens: sql6`coalesce(sum(${modelCallFacts.cachedTokens}), 0)`
|
|
5839
6278
|
}).from(modelCallFacts).innerJoin(
|
|
5840
6279
|
childSessions,
|
|
5841
6280
|
and8(
|
|
@@ -5848,7 +6287,7 @@ async function aggregateRootSessionDrivers(db, input) {
|
|
|
5848
6287
|
eq8(rootSessions.workspaceId, childSessions.workspaceId),
|
|
5849
6288
|
eq8(rootSessions.id, childSessions.rootSessionId)
|
|
5850
6289
|
)
|
|
5851
|
-
).where(and8(...clauses)).groupBy(childSessions.rootSessionId, rootSessions.title).orderBy(
|
|
6290
|
+
).where(and8(...clauses)).groupBy(childSessions.rootSessionId, rootSessions.title).orderBy(sql6`coalesce(sum(${modelCallFacts.pricedCostMicros}), 0) desc`);
|
|
5852
6291
|
const rows = input.rootSessionIds ? await query : await query.limit(input.limit ?? 8);
|
|
5853
6292
|
return rows.map((row) => ({
|
|
5854
6293
|
rootSessionId: row.rootSessionId,
|
|
@@ -5882,17 +6321,17 @@ async function aggregateScheduleFacts(db, input) {
|
|
|
5882
6321
|
eq8(modelCallFacts.workspaceId, input.workspaceId),
|
|
5883
6322
|
gte(modelCallFacts.occurredAt, input.since),
|
|
5884
6323
|
lt2(modelCallFacts.occurredAt, input.until),
|
|
5885
|
-
|
|
6324
|
+
sql6`${modelCallFacts.scheduledTaskId} is not null`,
|
|
5886
6325
|
...input.provider ? [eq8(modelCallFacts.provider, input.provider)] : [],
|
|
5887
6326
|
...input.model ? [eq8(modelCallFacts.model, input.model)] : []
|
|
5888
6327
|
];
|
|
5889
6328
|
const rows = await scopedDb.select({
|
|
5890
6329
|
scheduledTaskId: modelCallFacts.scheduledTaskId,
|
|
5891
|
-
pricedCostMicros:
|
|
5892
|
-
inputTokens:
|
|
5893
|
-
cachedTokens:
|
|
5894
|
-
calls:
|
|
5895
|
-
billingPath:
|
|
6330
|
+
pricedCostMicros: sql6`coalesce(sum(${modelCallFacts.pricedCostMicros}), 0)`,
|
|
6331
|
+
inputTokens: sql6`coalesce(sum(${modelCallFacts.inputTokens}), 0)`,
|
|
6332
|
+
cachedTokens: sql6`coalesce(sum(${modelCallFacts.cachedTokens}), 0)`,
|
|
6333
|
+
calls: sql6`count(*)::int`,
|
|
6334
|
+
billingPath: sql6`case
|
|
5896
6335
|
when bool_or(${modelCallFacts.billingPath} = 'opengeni_credits')
|
|
5897
6336
|
then 'opengeni_credits'
|
|
5898
6337
|
else 'external'
|
|
@@ -5914,7 +6353,7 @@ async function countScheduledTaskFires(db, input) {
|
|
|
5914
6353
|
return await withRlsContext(db, context, async (scopedDb) => {
|
|
5915
6354
|
const rows = await scopedDb.select({
|
|
5916
6355
|
taskId: scheduledTaskRuns.taskId,
|
|
5917
|
-
n:
|
|
6356
|
+
n: sql6`count(*)::int`
|
|
5918
6357
|
}).from(scheduledTaskRuns).where(
|
|
5919
6358
|
and8(
|
|
5920
6359
|
eq8(scheduledTaskRuns.workspaceId, input.workspaceId),
|
|
@@ -5931,21 +6370,21 @@ async function aggregateSessionDepth(db, workspaceId) {
|
|
|
5931
6370
|
return await withRlsContext(db, context, async (scopedDb) => {
|
|
5932
6371
|
const buckets = await scopedDb.select({
|
|
5933
6372
|
depth: sessions.nestedAgentDepth,
|
|
5934
|
-
sessions:
|
|
6373
|
+
sessions: sql6`count(*)::int`
|
|
5935
6374
|
}).from(sessions).where(eq8(sessions.workspaceId, workspaceId)).groupBy(sessions.nestedAgentDepth).orderBy(sessions.nestedAgentDepth);
|
|
5936
6375
|
const [stats] = await scopedDb.select({
|
|
5937
|
-
sessionsTouched:
|
|
5938
|
-
rootSessions:
|
|
5939
|
-
deepestDepth:
|
|
5940
|
-
avgDepth:
|
|
6376
|
+
sessionsTouched: sql6`count(*)::int`,
|
|
6377
|
+
rootSessions: sql6`count(*) filter (where ${sessions.nestedAgentDepth} = 0)::int`,
|
|
6378
|
+
deepestDepth: sql6`coalesce(max(${sessions.nestedAgentDepth}), 0)`,
|
|
6379
|
+
avgDepth: sql6`coalesce(avg(${sessions.nestedAgentDepth}), 0)`
|
|
5941
6380
|
}).from(sessions).where(eq8(sessions.workspaceId, workspaceId));
|
|
5942
6381
|
const [deepest] = await scopedDb.select({
|
|
5943
6382
|
title: sessions.title,
|
|
5944
6383
|
depth: sessions.nestedAgentDepth
|
|
5945
6384
|
}).from(sessions).where(eq8(sessions.workspaceId, workspaceId)).orderBy(desc3(sessions.nestedAgentDepth), desc3(sessions.updatedAt)).limit(1);
|
|
5946
6385
|
const [goals] = await scopedDb.select({
|
|
5947
|
-
active:
|
|
5948
|
-
completed:
|
|
6386
|
+
active: sql6`count(*) filter (where ${sessionGoals.status} = 'active')::int`,
|
|
6387
|
+
completed: sql6`count(*) filter (where ${sessionGoals.status} = 'completed')::int`
|
|
5949
6388
|
}).from(sessionGoals).where(eq8(sessionGoals.workspaceId, workspaceId));
|
|
5950
6389
|
return {
|
|
5951
6390
|
buckets: buckets.map((row) => ({
|
|
@@ -5983,7 +6422,7 @@ async function countOnlineMachines(db, workspaceId, heartbeatFreshMs) {
|
|
|
5983
6422
|
const context = await rlsContextForWorkspace(db, workspaceId);
|
|
5984
6423
|
return await withRlsContext(db, context, async (scopedDb) => {
|
|
5985
6424
|
const cutoff = new Date(Date.now() - heartbeatFreshMs);
|
|
5986
|
-
const [{ n } = { n: 0 }] = await scopedDb.select({ n:
|
|
6425
|
+
const [{ n } = { n: 0 }] = await scopedDb.select({ n: sql6`count(*)::int` }).from(enrollments).where(
|
|
5987
6426
|
and8(
|
|
5988
6427
|
eq8(enrollments.workspaceId, workspaceId),
|
|
5989
6428
|
eq8(enrollments.status, "active"),
|
|
@@ -6032,9 +6471,9 @@ async function backfillModelCallFactsFromSessionEvents(db, input) {
|
|
|
6032
6471
|
eq8(sessionEvents.type, "agent.model.usage"),
|
|
6033
6472
|
eq8(sessionEvents.turnAssociation, "current"),
|
|
6034
6473
|
lt2(sessionEvents.occurredAt, until),
|
|
6035
|
-
|
|
6474
|
+
sql6`${sessionEvents.turnId} is not null`,
|
|
6036
6475
|
// Keyset on (occurred_at, id) so same-millisecond bursts cannot be skipped.
|
|
6037
|
-
|
|
6476
|
+
sql6`(${sessionEvents.occurredAt}, ${sessionEvents.id}) > (${cursorOccurredAt}, ${cursorId}::uuid)`
|
|
6038
6477
|
)
|
|
6039
6478
|
).orderBy(sessionEvents.occurredAt, sessionEvents.id).limit(Math.min(batchSize, remaining));
|
|
6040
6479
|
});
|
|
@@ -6995,7 +7434,7 @@ async function cancelResponseBody(response) {
|
|
|
6995
7434
|
}
|
|
6996
7435
|
|
|
6997
7436
|
// src/workspace-artifacts.ts
|
|
6998
|
-
import { and as and9, desc as desc4, eq as eq9, lt as lt3, or as or2, sql as
|
|
7437
|
+
import { and as and9, desc as desc4, eq as eq9, lt as lt3, or as or2, sql as sql7 } from "drizzle-orm";
|
|
6999
7438
|
var WorkspaceArtifactNotFoundError = class extends Error {
|
|
7000
7439
|
name = "WorkspaceArtifactNotFoundError";
|
|
7001
7440
|
};
|
|
@@ -7185,7 +7624,7 @@ async function assertAttemptAuthority(scopedDb, input) {
|
|
|
7185
7624
|
if (provenance.some((value) => value === null) || input.sourceToolName === null) {
|
|
7186
7625
|
throw new WorkspaceArtifactOperationError("Artifact attempt provenance is incomplete");
|
|
7187
7626
|
}
|
|
7188
|
-
const rows = await scopedDb.execute(
|
|
7627
|
+
const rows = await scopedDb.execute(sql7`
|
|
7189
7628
|
WITH locked_workspace AS MATERIALIZED (
|
|
7190
7629
|
SELECT workspace.id, workspace.account_id
|
|
7191
7630
|
FROM workspaces workspace
|
|
@@ -7269,7 +7708,7 @@ async function replayForOperation(scopedDb, workspaceId, operationKey) {
|
|
|
7269
7708
|
}
|
|
7270
7709
|
async function lockOperation(scopedDb, workspaceId, operationKey) {
|
|
7271
7710
|
await scopedDb.execute(
|
|
7272
|
-
|
|
7711
|
+
sql7`SELECT pg_advisory_xact_lock(hashtextextended(${`${workspaceId}:${operationKey}`}, 0))`
|
|
7273
7712
|
);
|
|
7274
7713
|
}
|
|
7275
7714
|
function assertCreateReplay(replay) {
|
|
@@ -7619,7 +8058,7 @@ function validateHostExportIdentity(kind, consumerId) {
|
|
|
7619
8058
|
}
|
|
7620
8059
|
async function registerHostExportConsumer(db, input) {
|
|
7621
8060
|
validateHostExportIdentity(input.kind, input.consumerId);
|
|
7622
|
-
await db.execute(
|
|
8061
|
+
await db.execute(sql8`
|
|
7623
8062
|
select opengeni_host_export.register_host_export_consumer(
|
|
7624
8063
|
${input.kind}, ${input.consumerId}
|
|
7625
8064
|
)
|
|
@@ -7627,7 +8066,7 @@ async function registerHostExportConsumer(db, input) {
|
|
|
7627
8066
|
}
|
|
7628
8067
|
async function disableHostExportConsumer(db, input) {
|
|
7629
8068
|
validateHostExportIdentity(input.kind, input.consumerId);
|
|
7630
|
-
await db.execute(
|
|
8069
|
+
await db.execute(sql8`
|
|
7631
8070
|
select opengeni_host_export.disable_host_export_consumer(
|
|
7632
8071
|
${input.kind}, ${input.consumerId}
|
|
7633
8072
|
)
|
|
@@ -7635,7 +8074,7 @@ async function disableHostExportConsumer(db, input) {
|
|
|
7635
8074
|
}
|
|
7636
8075
|
async function retireHostExportConsumer(db, input) {
|
|
7637
8076
|
validateHostExportIdentity(input.kind, input.consumerId);
|
|
7638
|
-
await db.execute(
|
|
8077
|
+
await db.execute(sql8`
|
|
7639
8078
|
select opengeni_host_export.retire_host_export_consumer(
|
|
7640
8079
|
${input.kind}, ${input.consumerId}
|
|
7641
8080
|
)
|
|
@@ -7645,7 +8084,7 @@ async function claimHostExportBatch(db, input) {
|
|
|
7645
8084
|
validateHostExportIdentity(input.kind, input.consumerId);
|
|
7646
8085
|
const claimedRows = await rawRows(
|
|
7647
8086
|
db,
|
|
7648
|
-
|
|
8087
|
+
sql8`
|
|
7649
8088
|
select * from opengeni_host_export.claim_host_export_batch(
|
|
7650
8089
|
${input.kind}, ${input.consumerId}, ${input.leaseToken}::uuid,
|
|
7651
8090
|
${input.leaseHolderId}, ${input.leaseSeconds ?? 60},
|
|
@@ -7662,7 +8101,7 @@ async function claimHostExportBatch(db, input) {
|
|
|
7662
8101
|
}
|
|
7663
8102
|
const roots = await rawRows(
|
|
7664
8103
|
db,
|
|
7665
|
-
|
|
8104
|
+
sql8`
|
|
7666
8105
|
select * from opengeni_host_export.host_export_cursor_roots(
|
|
7667
8106
|
${input.kind}, ${input.consumerId}, ${input.leaseToken}::uuid
|
|
7668
8107
|
)
|
|
@@ -7768,7 +8207,7 @@ async function acknowledgeHostExportBatch(db, input) {
|
|
|
7768
8207
|
validateHostExportIdentity(input.kind, input.consumerId);
|
|
7769
8208
|
const [row] = await rawRows(
|
|
7770
8209
|
db,
|
|
7771
|
-
|
|
8210
|
+
sql8`
|
|
7772
8211
|
select opengeni_host_export.ack_host_export_batch(
|
|
7773
8212
|
${input.kind}, ${input.consumerId}, ${input.leaseToken}::uuid
|
|
7774
8213
|
) as checkpoint
|
|
@@ -7781,7 +8220,7 @@ async function failHostExportBatch(db, input) {
|
|
|
7781
8220
|
validateHostExportIdentity(input.kind, input.consumerId);
|
|
7782
8221
|
const [row] = await rawRows(
|
|
7783
8222
|
db,
|
|
7784
|
-
|
|
8223
|
+
sql8`
|
|
7785
8224
|
select opengeni_host_export.fail_host_export_batch(
|
|
7786
8225
|
${input.kind}, ${input.consumerId}, ${input.leaseToken}::uuid,
|
|
7787
8226
|
${input.error}, ${input.maxFailures ?? 20}
|
|
@@ -7796,7 +8235,7 @@ async function deadLetterHostExportHead(db, input) {
|
|
|
7796
8235
|
const cursor = hostExportCursor(input.cursor);
|
|
7797
8236
|
const [row] = await rawRows(
|
|
7798
8237
|
db,
|
|
7799
|
-
|
|
8238
|
+
sql8`
|
|
7800
8239
|
select opengeni_host_export.dead_letter_host_export_head(
|
|
7801
8240
|
${input.kind}, ${input.consumerId}, ${input.leaseToken}::uuid,
|
|
7802
8241
|
${cursor}::bigint, ${input.reason}
|
|
@@ -7808,7 +8247,7 @@ async function deadLetterHostExportHead(db, input) {
|
|
|
7808
8247
|
}
|
|
7809
8248
|
async function resumeHostExportConsumer(db, input) {
|
|
7810
8249
|
validateHostExportIdentity(input.kind, input.consumerId);
|
|
7811
|
-
await db.execute(
|
|
8250
|
+
await db.execute(sql8`
|
|
7812
8251
|
select opengeni_host_export.resume_host_export_consumer(
|
|
7813
8252
|
${input.kind}, ${input.consumerId}
|
|
7814
8253
|
)
|
|
@@ -7817,7 +8256,7 @@ async function resumeHostExportConsumer(db, input) {
|
|
|
7817
8256
|
async function rewindHostExportConsumer(db, input) {
|
|
7818
8257
|
validateHostExportIdentity(input.kind, input.consumerId);
|
|
7819
8258
|
const checkpoint = hostExportCursor(input.checkpoint);
|
|
7820
|
-
await db.execute(
|
|
8259
|
+
await db.execute(sql8`
|
|
7821
8260
|
select opengeni_host_export.rewind_host_export_consumer(
|
|
7822
8261
|
${input.kind}, ${input.consumerId}, ${checkpoint}::bigint
|
|
7823
8262
|
)
|
|
@@ -7827,7 +8266,7 @@ async function pruneHostExportOutbox(db, input) {
|
|
|
7827
8266
|
validateHostExportKind(input.kind);
|
|
7828
8267
|
const [row] = await rawRows(
|
|
7829
8268
|
db,
|
|
7830
|
-
|
|
8269
|
+
sql8`
|
|
7831
8270
|
select opengeni_host_export.prune_host_export_outbox(
|
|
7832
8271
|
${input.kind}, ${input.graceSeconds ?? 3600}, ${input.limit ?? 1e3}
|
|
7833
8272
|
) as deleted
|
|
@@ -7839,7 +8278,7 @@ async function getHostExportConsumerStatus(db, input) {
|
|
|
7839
8278
|
validateHostExportIdentity(input.kind, input.consumerId);
|
|
7840
8279
|
const [row] = await rawRows(
|
|
7841
8280
|
db,
|
|
7842
|
-
|
|
8281
|
+
sql8`
|
|
7843
8282
|
select * from opengeni_host_export.host_export_consumer_status(
|
|
7844
8283
|
${input.kind}, ${input.consumerId}
|
|
7845
8284
|
)
|
|
@@ -7868,18 +8307,18 @@ async function setRlsContext(db, context) {
|
|
|
7868
8307
|
if (typeof context.accountId !== "string" || context.accountId.trim() === "") {
|
|
7869
8308
|
throw new Error("setRlsContext: a non-empty accountId is required to establish an RLS context");
|
|
7870
8309
|
}
|
|
7871
|
-
await db.execute(
|
|
8310
|
+
await db.execute(sql8`select set_config('opengeni.account_id', ${context.accountId}, true)`);
|
|
7872
8311
|
await db.execute(
|
|
7873
|
-
|
|
8312
|
+
sql8`select set_config('opengeni.workspace_id', ${context.workspaceId ?? ""}, true)`
|
|
7874
8313
|
);
|
|
7875
|
-
await db.execute(
|
|
8314
|
+
await db.execute(sql8`select set_config('opengeni.sandbox_recovery_protocol_v2', '1', true)`);
|
|
7876
8315
|
}
|
|
7877
8316
|
async function withRlsContext(db, context, fn, transactionConfig) {
|
|
7878
8317
|
return await db.transaction(async (tx) => {
|
|
7879
8318
|
const scoped = tx;
|
|
7880
8319
|
await setRlsContext(scoped, context);
|
|
7881
8320
|
const applied = await tx.execute(
|
|
7882
|
-
|
|
8321
|
+
sql8`select
|
|
7883
8322
|
current_setting('opengeni.account_id', true) as account_id,
|
|
7884
8323
|
current_setting('opengeni.workspace_id', true) as workspace_id`
|
|
7885
8324
|
);
|
|
@@ -7938,9 +8377,9 @@ async function setSubjectRlsContext(db, subjectId) {
|
|
|
7938
8377
|
if (!subjectId.trim()) {
|
|
7939
8378
|
throw new Error("setSubjectRlsContext: a non-empty subjectId is required");
|
|
7940
8379
|
}
|
|
7941
|
-
await db.execute(
|
|
8380
|
+
await db.execute(sql8`select set_config('opengeni.subject_id', ${subjectId}, true)`);
|
|
7942
8381
|
const applied = await db.execute(
|
|
7943
|
-
|
|
8382
|
+
sql8`select current_setting('opengeni.subject_id', true) as subject_id`
|
|
7944
8383
|
);
|
|
7945
8384
|
if ((applied[0]?.subject_id ?? "") !== subjectId) {
|
|
7946
8385
|
throw new Error("Authenticated subject RLS context was not applied on the active backend");
|
|
@@ -7949,7 +8388,7 @@ async function setSubjectRlsContext(db, subjectId) {
|
|
|
7949
8388
|
async function withWorkspaceUsageLock(db, workspaceId, fn) {
|
|
7950
8389
|
const context = await rlsContextForWorkspace(db, workspaceId);
|
|
7951
8390
|
return await withRlsContext(db, context, async (scopedDb) => {
|
|
7952
|
-
await scopedDb.execute(
|
|
8391
|
+
await scopedDb.execute(sql8`select pg_advisory_xact_lock(hashtext(${`usage:${workspaceId}`}))`);
|
|
7953
8392
|
return await fn(scopedDb);
|
|
7954
8393
|
});
|
|
7955
8394
|
}
|
|
@@ -8278,7 +8717,7 @@ async function listWorkspacesForSubject(db, subjectId, limit = 100) {
|
|
|
8278
8717
|
}
|
|
8279
8718
|
async function countWorkspacesForAccount(db, accountId) {
|
|
8280
8719
|
const [{ count } = { count: 0 }] = await db.select({
|
|
8281
|
-
count:
|
|
8720
|
+
count: sql8`count(*)::int`
|
|
8282
8721
|
}).from(workspaces).where(eq10(workspaces.accountId, accountId));
|
|
8283
8722
|
return Number(count);
|
|
8284
8723
|
}
|
|
@@ -8356,7 +8795,7 @@ async function updateWorkspaceSettings(db, workspaceId, patch) {
|
|
|
8356
8795
|
async (scopedDb) => await scopedDb.transaction(async (tx) => {
|
|
8357
8796
|
await lockWorkspaceInferenceControl(tx, workspaceId, "update");
|
|
8358
8797
|
const [row2] = await tx.update(workspaces).set({
|
|
8359
|
-
settings: requested === null ?
|
|
8798
|
+
settings: requested === null ? sql8`(${workspaces.settings} - 'maxNestedAgentDepth') || ${JSON.stringify(nextPatch)}::jsonb` : sql8`${workspaces.settings} || ${JSON.stringify(nextPatch)}::jsonb`,
|
|
8360
8799
|
updatedAt: /* @__PURE__ */ new Date()
|
|
8361
8800
|
}).where(eq10(workspaces.id, workspaceId)).returning();
|
|
8362
8801
|
if (!row2) throw new Error(`Workspace not found: ${workspaceId}`);
|
|
@@ -8368,7 +8807,7 @@ async function updateWorkspaceSettings(db, workspaceId, patch) {
|
|
|
8368
8807
|
);
|
|
8369
8808
|
}
|
|
8370
8809
|
const [row] = await db.update(workspaces).set({
|
|
8371
|
-
settings:
|
|
8810
|
+
settings: sql8`${workspaces.settings} || ${JSON.stringify(patch)}::jsonb`,
|
|
8372
8811
|
updatedAt: /* @__PURE__ */ new Date()
|
|
8373
8812
|
}).where(eq10(workspaces.id, workspaceId)).returning();
|
|
8374
8813
|
if (!row) {
|
|
@@ -8455,7 +8894,7 @@ async function getManagedUserByEmail(db, email) {
|
|
|
8455
8894
|
if (binding?.userLookup) {
|
|
8456
8895
|
return await binding.userLookup(db, email);
|
|
8457
8896
|
}
|
|
8458
|
-
const rows = await db.execute(
|
|
8897
|
+
const rows = await db.execute(sql8`
|
|
8459
8898
|
select id from auth_users where lower(email) = lower(${email}) limit 1
|
|
8460
8899
|
`);
|
|
8461
8900
|
return rows[0]?.id ?? null;
|
|
@@ -8493,12 +8932,12 @@ async function listApiKeys(db, workspaceId) {
|
|
|
8493
8932
|
async function countActiveApiKeysForWorkspace(db, workspaceId) {
|
|
8494
8933
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
8495
8934
|
const [{ count } = { count: 0 }] = await scopedDb.select({
|
|
8496
|
-
count:
|
|
8935
|
+
count: sql8`count(*)::int`
|
|
8497
8936
|
}).from(apiKeys).where(
|
|
8498
8937
|
and10(
|
|
8499
8938
|
eq10(apiKeys.workspaceId, workspaceId),
|
|
8500
|
-
|
|
8501
|
-
|
|
8939
|
+
sql8`${apiKeys.revokedAt} is null`,
|
|
8940
|
+
sql8`(${apiKeys.expiresAt} is null or ${apiKeys.expiresAt} > now())`
|
|
8502
8941
|
)
|
|
8503
8942
|
);
|
|
8504
8943
|
return Number(count);
|
|
@@ -8518,12 +8957,12 @@ async function revokeApiKey(db, workspaceId, apiKeyId) {
|
|
|
8518
8957
|
}
|
|
8519
8958
|
async function findActiveApiKeyByHash(db, keyHash) {
|
|
8520
8959
|
return await db.transaction(async (tx) => {
|
|
8521
|
-
await tx.execute(
|
|
8960
|
+
await tx.execute(sql8`select set_config('opengeni.api_key_hash', ${keyHash}, true)`);
|
|
8522
8961
|
const [row] = await tx.select().from(apiKeys).where(
|
|
8523
8962
|
and10(
|
|
8524
8963
|
eq10(apiKeys.keyHash, keyHash),
|
|
8525
|
-
|
|
8526
|
-
|
|
8964
|
+
sql8`${apiKeys.revokedAt} is null`,
|
|
8965
|
+
sql8`(${apiKeys.expiresAt} is null or ${apiKeys.expiresAt} > now())`
|
|
8527
8966
|
)
|
|
8528
8967
|
).limit(1);
|
|
8529
8968
|
if (!row) {
|
|
@@ -8759,7 +9198,7 @@ async function bindAuthorizedGitHubInstallationRepositories(db, input) {
|
|
|
8759
9198
|
async function assertGitHubAuthorityWindowOpen(tx, checkedAt, expiresAt) {
|
|
8760
9199
|
const checkedAtIso = checkedAt.toISOString();
|
|
8761
9200
|
const expiresAtIso = expiresAt.toISOString();
|
|
8762
|
-
const result = await tx.execute(
|
|
9201
|
+
const result = await tx.execute(sql8`
|
|
8763
9202
|
select (
|
|
8764
9203
|
${checkedAtIso}::timestamptz <= clock_timestamp()
|
|
8765
9204
|
and clock_timestamp() < ${expiresAtIso}::timestamptz
|
|
@@ -8892,16 +9331,16 @@ async function recordUsageEvent(db, input) {
|
|
|
8892
9331
|
}).onConflictDoUpdate({
|
|
8893
9332
|
target: usageEvents.idempotencyKey,
|
|
8894
9333
|
set: {
|
|
8895
|
-
sessionId:
|
|
8896
|
-
turnId:
|
|
8897
|
-
turnAttemptId:
|
|
8898
|
-
initiatorKind:
|
|
8899
|
-
initiatorSubjectId:
|
|
8900
|
-
initiatorContext:
|
|
9334
|
+
sessionId: sql8`coalesce(${usageEvents.sessionId}, excluded.session_id)`,
|
|
9335
|
+
turnId: sql8`coalesce(${usageEvents.turnId}, excluded.turn_id)`,
|
|
9336
|
+
turnAttemptId: sql8`coalesce(${usageEvents.turnAttemptId}, excluded.turn_attempt_id)`,
|
|
9337
|
+
initiatorKind: sql8`coalesce(${usageEvents.initiatorKind}, excluded.initiator_kind)`,
|
|
9338
|
+
initiatorSubjectId: sql8`coalesce(${usageEvents.initiatorSubjectId}, excluded.initiator_subject_id)`,
|
|
9339
|
+
initiatorContext: sql8`case
|
|
8901
9340
|
when ${usageEvents.initiatorKind} is null then excluded.initiator_context
|
|
8902
9341
|
else ${usageEvents.initiatorContext}
|
|
8903
9342
|
end`,
|
|
8904
|
-
origin:
|
|
9343
|
+
origin: sql8`coalesce(${usageEvents.origin}, excluded.origin)`
|
|
8905
9344
|
}
|
|
8906
9345
|
}).returning();
|
|
8907
9346
|
if (row) {
|
|
@@ -9032,11 +9471,11 @@ async function recordModelCallFact(db, input) {
|
|
|
9032
9471
|
modelCallFacts.sourceKey
|
|
9033
9472
|
],
|
|
9034
9473
|
set: {
|
|
9035
|
-
turnAttemptId:
|
|
9036
|
-
scheduledTaskId:
|
|
9037
|
-
initiatorKind:
|
|
9038
|
-
initiatorSubjectId:
|
|
9039
|
-
turnSource:
|
|
9474
|
+
turnAttemptId: sql8`coalesce(${modelCallFacts.turnAttemptId}, excluded.turn_attempt_id)`,
|
|
9475
|
+
scheduledTaskId: sql8`coalesce(${modelCallFacts.scheduledTaskId}, excluded.scheduled_task_id)`,
|
|
9476
|
+
initiatorKind: sql8`coalesce(${modelCallFacts.initiatorKind}, excluded.initiator_kind)`,
|
|
9477
|
+
initiatorSubjectId: sql8`coalesce(${modelCallFacts.initiatorSubjectId}, excluded.initiator_subject_id)`,
|
|
9478
|
+
turnSource: sql8`coalesce(${modelCallFacts.turnSource}, excluded.turn_source)`
|
|
9040
9479
|
}
|
|
9041
9480
|
}).returning();
|
|
9042
9481
|
if (!row) {
|
|
@@ -9074,7 +9513,7 @@ async function sumUsageQuantity(db, input) {
|
|
|
9074
9513
|
...input.since ? [gt2(usageEvents.occurredAt, input.since)] : []
|
|
9075
9514
|
];
|
|
9076
9515
|
const [{ total } = { total: 0 }] = await scopedDb.select({
|
|
9077
|
-
total:
|
|
9516
|
+
total: sql8`coalesce(sum(${usageEvents.quantity}), 0)`
|
|
9078
9517
|
}).from(usageEvents).where(and10(...clauses));
|
|
9079
9518
|
return Number(total);
|
|
9080
9519
|
});
|
|
@@ -9112,7 +9551,7 @@ async function applyCreditDebitUpToBalance(db, input) {
|
|
|
9112
9551
|
db,
|
|
9113
9552
|
{ accountId: input.accountId, workspaceId: input.workspaceId ?? null },
|
|
9114
9553
|
async (scopedDb) => {
|
|
9115
|
-
await scopedDb.execute(
|
|
9554
|
+
await scopedDb.execute(sql8`select pg_advisory_xact_lock(hashtext(${input.accountId}))`);
|
|
9116
9555
|
const before = await getBillingBalance(scopedDb, input.accountId);
|
|
9117
9556
|
const candidateDebitMicros = Math.min(
|
|
9118
9557
|
input.requestedAmountMicros,
|
|
@@ -9209,7 +9648,7 @@ async function markStripeWebhookProcessed(db, id) {
|
|
|
9209
9648
|
async function getBillingBalance(db, accountId) {
|
|
9210
9649
|
return await withAccountRls(db, accountId, async (scopedDb) => {
|
|
9211
9650
|
const [{ balance } = { balance: 0 }] = await scopedDb.select({
|
|
9212
|
-
balance:
|
|
9651
|
+
balance: sql8`coalesce(sum(${creditLedgerEntries.amountMicros}), 0)`
|
|
9213
9652
|
}).from(creditLedgerEntries).where(eq10(creditLedgerEntries.accountId, accountId));
|
|
9214
9653
|
return {
|
|
9215
9654
|
accountId,
|
|
@@ -9222,7 +9661,7 @@ async function getBillingBalance(db, accountId) {
|
|
|
9222
9661
|
async function countScheduledTasksForWorkspace(db, workspaceId) {
|
|
9223
9662
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
9224
9663
|
const [{ count } = { count: 0 }] = await scopedDb.select({
|
|
9225
|
-
count:
|
|
9664
|
+
count: sql8`count(*)::int`
|
|
9226
9665
|
}).from(scheduledTasks).where(eq10(scheduledTasks.workspaceId, workspaceId));
|
|
9227
9666
|
return Number(count);
|
|
9228
9667
|
});
|
|
@@ -9438,7 +9877,7 @@ async function claimFileUploadCleanup(db, input) {
|
|
|
9438
9877
|
async function claimExpiredFileUploadCleanup(db, input) {
|
|
9439
9878
|
const rows = await rawRows(
|
|
9440
9879
|
db,
|
|
9441
|
-
|
|
9880
|
+
sql8`
|
|
9442
9881
|
select upload_id, account_id, workspace_id, file_id, object_key
|
|
9443
9882
|
from opengeni_private.claim_expired_file_upload_cleanup(
|
|
9444
9883
|
${input.graceMs},
|
|
@@ -9728,7 +10167,7 @@ async function upsertRegistryCapabilityCatalogItem(db, input) {
|
|
|
9728
10167
|
credentialFacts: values.credentialFacts,
|
|
9729
10168
|
tier: values.tier,
|
|
9730
10169
|
provenance: values.provenance,
|
|
9731
|
-
logoAssetPath:
|
|
10170
|
+
logoAssetPath: sql8`coalesce(excluded.logo_asset_path, ${capabilityCatalogItems.logoAssetPath})`,
|
|
9732
10171
|
importBatchId: values.importBatchId,
|
|
9733
10172
|
stale: false,
|
|
9734
10173
|
staleAt: null,
|
|
@@ -9890,7 +10329,7 @@ async function getCapabilityCatalogItem(db, workspaceId, capabilityId) {
|
|
|
9890
10329
|
isNull3(capabilityCatalogItems.workspaceId)
|
|
9891
10330
|
)
|
|
9892
10331
|
)
|
|
9893
|
-
).orderBy(asc5(
|
|
10332
|
+
).orderBy(asc5(sql8`(${capabilityCatalogItems.workspaceId} is null)`)).limit(1);
|
|
9894
10333
|
if (!row) {
|
|
9895
10334
|
return null;
|
|
9896
10335
|
}
|
|
@@ -10114,6 +10553,20 @@ function connectionSubjectVisibility(subjectId) {
|
|
|
10114
10553
|
function connectionExactSubject(subjectId) {
|
|
10115
10554
|
return subjectId ? eq10(connections.subjectId, subjectId) : isNull3(connections.subjectId);
|
|
10116
10555
|
}
|
|
10556
|
+
function personalSlackCanonicalConnectionOrder() {
|
|
10557
|
+
return [
|
|
10558
|
+
sql8`case ${connections.status}
|
|
10559
|
+
when 'active' then 0
|
|
10560
|
+
when 'needs_reauth' then 1
|
|
10561
|
+
when 'error' then 2
|
|
10562
|
+
when 'revoked' then 3
|
|
10563
|
+
else 4
|
|
10564
|
+
end`,
|
|
10565
|
+
desc5(connections.updatedAt),
|
|
10566
|
+
desc5(connections.createdAt),
|
|
10567
|
+
desc5(connections.id)
|
|
10568
|
+
];
|
|
10569
|
+
}
|
|
10117
10570
|
async function withConnectionSubjectRls(db, workspaceId, subjectId, fn) {
|
|
10118
10571
|
return subjectId ? await withWorkspaceSubjectRls(db, workspaceId, subjectId, fn) : await withWorkspaceRls(db, workspaceId, fn);
|
|
10119
10572
|
}
|
|
@@ -10183,7 +10636,7 @@ async function updateConnectionInScope(db, input) {
|
|
|
10183
10636
|
...input.status !== void 0 ? { status: input.status } : {},
|
|
10184
10637
|
...input.credentialEncrypted !== void 0 ? {
|
|
10185
10638
|
credentialEncrypted: input.credentialEncrypted,
|
|
10186
|
-
version:
|
|
10639
|
+
version: sql8`${connections.version} + 1`,
|
|
10187
10640
|
lastError: null
|
|
10188
10641
|
} : {},
|
|
10189
10642
|
...input.grantedScopes !== void 0 ? { grantedScopes: input.grantedScopes } : {},
|
|
@@ -10216,11 +10669,11 @@ async function revokeConnectionInScope(db, workspaceId, connectionId, updatedByS
|
|
|
10216
10669
|
status: "revoked",
|
|
10217
10670
|
// The version bump invalidates any in-flight refresh's (id, version) CAS,
|
|
10218
10671
|
// so a racing refresh cannot commit and flip the row back to active.
|
|
10219
|
-
version:
|
|
10672
|
+
version: sql8`${connections.version} + 1`,
|
|
10220
10673
|
// Status-only revocation does not replace the verified credential or bot
|
|
10221
10674
|
// identity. Carry the marker to the same new CAS version so the dedicated
|
|
10222
10675
|
// reinstall path can still recognize (but not use) the inactive row.
|
|
10223
|
-
verifiedInstallVersion:
|
|
10676
|
+
verifiedInstallVersion: sql8`case
|
|
10224
10677
|
when ${connections.verifiedInstallAt} is null then null
|
|
10225
10678
|
else ${connections.version} + 1
|
|
10226
10679
|
end`,
|
|
@@ -10248,7 +10701,7 @@ async function revokeConnection(db, workspaceId, connectionId, updatedBySubjectI
|
|
|
10248
10701
|
);
|
|
10249
10702
|
}
|
|
10250
10703
|
async function resolveSlackInstallationRoute(db, slackTeamId) {
|
|
10251
|
-
const rows = await db.execute(
|
|
10704
|
+
const rows = await db.execute(sql8`select * from opengeni_private.resolve_slack_installation(${slackTeamId})`);
|
|
10252
10705
|
const row = rows[0];
|
|
10253
10706
|
return row ? {
|
|
10254
10707
|
accountId: row.account_id,
|
|
@@ -10268,7 +10721,7 @@ async function saveSlackBotUserLink(db, input) {
|
|
|
10268
10721
|
slackTeamId: input.slackTeamId,
|
|
10269
10722
|
subjectId: input.subjectId,
|
|
10270
10723
|
linkedBySubjectId: input.linkedBySubjectId,
|
|
10271
|
-
updatedAt:
|
|
10724
|
+
updatedAt: sql8`now()`
|
|
10272
10725
|
}
|
|
10273
10726
|
}).returning();
|
|
10274
10727
|
if (!row) throw new Error("Slack identity link write returned no row");
|
|
@@ -10322,7 +10775,7 @@ async function enqueueSlackInteractionInbox(db, input) {
|
|
|
10322
10775
|
}
|
|
10323
10776
|
async function claimSlackInteractionInbox(db, claimHolderId, claimLeaseMs) {
|
|
10324
10777
|
const rows = await db.execute(
|
|
10325
|
-
|
|
10778
|
+
sql8`select * from opengeni_private.claim_slack_interaction_inbox(${claimHolderId}::uuid, ${claimLeaseMs})`
|
|
10326
10779
|
);
|
|
10327
10780
|
return rows[0] ? mapSlackInteractionInbox(rows[0]) : null;
|
|
10328
10781
|
}
|
|
@@ -10332,9 +10785,10 @@ async function settleSlackInteractionInbox(db, input) {
|
|
|
10332
10785
|
status: input.outcome,
|
|
10333
10786
|
claimHolderId: null,
|
|
10334
10787
|
claimExpiresAt: null,
|
|
10335
|
-
|
|
10788
|
+
retryAt: null,
|
|
10789
|
+
processedAt: sql8`now()`,
|
|
10336
10790
|
lastErrorCode: input.errorCode ?? null,
|
|
10337
|
-
updatedAt:
|
|
10791
|
+
updatedAt: sql8`now()`
|
|
10338
10792
|
}).where(
|
|
10339
10793
|
and10(
|
|
10340
10794
|
eq10(slackInteractionInbox.id, input.entry.id),
|
|
@@ -10351,8 +10805,9 @@ async function releaseSlackInteractionInbox(db, input) {
|
|
|
10351
10805
|
status: "pending",
|
|
10352
10806
|
claimHolderId: null,
|
|
10353
10807
|
claimExpiresAt: null,
|
|
10808
|
+
retryAt: input.retryAt,
|
|
10354
10809
|
lastErrorCode: input.errorCode,
|
|
10355
|
-
updatedAt:
|
|
10810
|
+
updatedAt: sql8`now()`
|
|
10356
10811
|
}).where(
|
|
10357
10812
|
and10(
|
|
10358
10813
|
eq10(slackInteractionInbox.id, input.entry.id),
|
|
@@ -10405,7 +10860,7 @@ async function getSlackInteractionSessionAccess(db, workspaceId, rootSessionId)
|
|
|
10405
10860
|
}
|
|
10406
10861
|
async function getSlackInteractionSessionAccessForSession(db, input) {
|
|
10407
10862
|
return await withRlsContext(db, input, async (scopedDb) => {
|
|
10408
|
-
const rows = await scopedDb.execute(
|
|
10863
|
+
const rows = await scopedDb.execute(sql8`
|
|
10409
10864
|
with recursive lineage(id, parent_session_id, depth, path, cycle) as (
|
|
10410
10865
|
select
|
|
10411
10866
|
${sessions.id},
|
|
@@ -10464,7 +10919,7 @@ async function getSlackInteractionSessionAccessForSession(db, input) {
|
|
|
10464
10919
|
}
|
|
10465
10920
|
async function bindSlackInteractionSession(db, input) {
|
|
10466
10921
|
return await withRlsContext(db, input, async (scopedDb) => {
|
|
10467
|
-
const [row] = await scopedDb.update(slackInteractions).set({ sessionId: input.sessionId, updatedAt:
|
|
10922
|
+
const [row] = await scopedDb.update(slackInteractions).set({ sessionId: input.sessionId, updatedAt: sql8`now()` }).where(
|
|
10468
10923
|
and10(
|
|
10469
10924
|
eq10(slackInteractions.id, input.id),
|
|
10470
10925
|
eq10(slackInteractions.owningSubjectId, input.owningSubjectId),
|
|
@@ -10526,7 +10981,7 @@ async function claimSlackInteractionProgressDelivery(db, input) {
|
|
|
10526
10981
|
operationId: crypto.randomUUID()
|
|
10527
10982
|
}).returning();
|
|
10528
10983
|
if (!delivery) throw new Error("Slack progress delivery claim returned no row");
|
|
10529
|
-
const [updated] = await scopedDb.update(slackInteractions).set({ progressCount: slot, updatedAt:
|
|
10984
|
+
const [updated] = await scopedDb.update(slackInteractions).set({ progressCount: slot, updatedAt: sql8`now()` }).where(
|
|
10530
10985
|
and10(
|
|
10531
10986
|
eq10(slackInteractions.id, input.interactionId),
|
|
10532
10987
|
eq10(slackInteractions.deliveryClaimHolderId, input.claimHolderId),
|
|
@@ -10548,20 +11003,26 @@ async function rekeySlackInteractionRoute(db, input) {
|
|
|
10548
11003
|
routeKey: input.routeKey,
|
|
10549
11004
|
slackThreadTs: input.slackThreadTs,
|
|
10550
11005
|
ackSlackMessageTs: input.ackSlackMessageTs,
|
|
10551
|
-
updatedAt:
|
|
11006
|
+
updatedAt: sql8`now()`
|
|
10552
11007
|
}).where(eq10(slackInteractions.id, input.id)).returning();
|
|
10553
11008
|
return row ? mapSlackInteraction(row) : null;
|
|
10554
11009
|
});
|
|
10555
11010
|
}
|
|
10556
11011
|
async function claimSlackInteractionDelivery(db, claimHolderId, claimLeaseMs) {
|
|
10557
11012
|
const rows = await db.execute(
|
|
10558
|
-
|
|
11013
|
+
sql8`select * from opengeni_private.claim_slack_interaction_delivery(${claimHolderId}::uuid, ${claimLeaseMs})`
|
|
10559
11014
|
);
|
|
10560
11015
|
return rows[0] ? mapSlackInteraction(rows[0]) : null;
|
|
10561
11016
|
}
|
|
10562
11017
|
async function reopenSlackInteractionDelivery(db, input) {
|
|
10563
11018
|
return await withRlsContext(db, input, async (scopedDb) => {
|
|
10564
|
-
const rows = await scopedDb.update(slackInteractions).set({
|
|
11019
|
+
const rows = await scopedDb.update(slackInteractions).set({
|
|
11020
|
+
terminalDeliveryState: "open",
|
|
11021
|
+
deliveryAttemptCount: 0,
|
|
11022
|
+
deliveryRetryAt: null,
|
|
11023
|
+
deliveryLastErrorCode: null,
|
|
11024
|
+
updatedAt: sql8`now()`
|
|
11025
|
+
}).where(eq10(slackInteractions.id, input.id)).returning({ id: slackInteractions.id });
|
|
10565
11026
|
return rows.length === 1;
|
|
10566
11027
|
});
|
|
10567
11028
|
}
|
|
@@ -10570,7 +11031,10 @@ async function advanceSlackInteractionDelivery(db, input) {
|
|
|
10570
11031
|
const rows = await scopedDb.update(slackInteractions).set({
|
|
10571
11032
|
lastDeliveredSessionEventSequence: input.sequence,
|
|
10572
11033
|
...input.ackSlackMessageTs !== void 0 ? { ackSlackMessageTs: input.ackSlackMessageTs } : {},
|
|
10573
|
-
|
|
11034
|
+
deliveryAttemptCount: 0,
|
|
11035
|
+
deliveryRetryAt: null,
|
|
11036
|
+
deliveryLastErrorCode: null,
|
|
11037
|
+
updatedAt: sql8`now()`
|
|
10574
11038
|
}).where(
|
|
10575
11039
|
and10(
|
|
10576
11040
|
eq10(slackInteractions.id, input.id),
|
|
@@ -10586,7 +11050,24 @@ async function releaseSlackInteractionDelivery(db, input) {
|
|
|
10586
11050
|
const rows = await scopedDb.update(slackInteractions).set({
|
|
10587
11051
|
deliveryClaimHolderId: null,
|
|
10588
11052
|
deliveryClaimExpiresAt: null,
|
|
10589
|
-
updatedAt:
|
|
11053
|
+
updatedAt: sql8`now()`
|
|
11054
|
+
}).where(
|
|
11055
|
+
and10(
|
|
11056
|
+
eq10(slackInteractions.id, input.id),
|
|
11057
|
+
eq10(slackInteractions.deliveryClaimHolderId, input.claimHolderId)
|
|
11058
|
+
)
|
|
11059
|
+
).returning({ id: slackInteractions.id });
|
|
11060
|
+
return rows.length === 1;
|
|
11061
|
+
});
|
|
11062
|
+
}
|
|
11063
|
+
async function deferSlackInteractionDelivery(db, input) {
|
|
11064
|
+
return await withRlsContext(db, input, async (scopedDb) => {
|
|
11065
|
+
const rows = await scopedDb.update(slackInteractions).set({
|
|
11066
|
+
deliveryClaimHolderId: null,
|
|
11067
|
+
deliveryClaimExpiresAt: null,
|
|
11068
|
+
deliveryRetryAt: input.retryAt,
|
|
11069
|
+
deliveryLastErrorCode: input.errorCode.slice(0, 128),
|
|
11070
|
+
updatedAt: sql8`now()`
|
|
10590
11071
|
}).where(
|
|
10591
11072
|
and10(
|
|
10592
11073
|
eq10(slackInteractions.id, input.id),
|
|
@@ -10603,7 +11084,9 @@ async function closeSlackInteractionDelivery(db, input) {
|
|
|
10603
11084
|
terminalDeliveryState: input.state,
|
|
10604
11085
|
deliveryClaimHolderId: null,
|
|
10605
11086
|
deliveryClaimExpiresAt: null,
|
|
10606
|
-
|
|
11087
|
+
deliveryRetryAt: null,
|
|
11088
|
+
deliveryLastErrorCode: input.errorCode?.slice(0, 128) ?? null,
|
|
11089
|
+
updatedAt: sql8`now()`
|
|
10607
11090
|
}).where(
|
|
10608
11091
|
and10(
|
|
10609
11092
|
eq10(slackInteractions.id, input.id),
|
|
@@ -10635,6 +11118,7 @@ function mapSlackInteractionInbox(row) {
|
|
|
10635
11118
|
claimHolderId: slackRowNullableString(row, "claimHolderId", "claim_holder_id"),
|
|
10636
11119
|
claimExpiresAt: slackRowNullableDate(row, "claimExpiresAt", "claim_expires_at"),
|
|
10637
11120
|
attemptCount: slackRowNumber(row, "attemptCount", "attempt_count"),
|
|
11121
|
+
retryAt: slackRowNullableDate(row, "retryAt", "retry_at"),
|
|
10638
11122
|
lastErrorCode: slackRowNullableString(row, "lastErrorCode", "last_error_code"),
|
|
10639
11123
|
processedAt: slackRowNullableDate(row, "processedAt", "processed_at"),
|
|
10640
11124
|
createdAt: slackRowDate(row, "createdAt", "created_at"),
|
|
@@ -10675,6 +11159,13 @@ function mapSlackInteraction(row) {
|
|
|
10675
11159
|
"deliveryClaimExpiresAt",
|
|
10676
11160
|
"delivery_claim_expires_at"
|
|
10677
11161
|
),
|
|
11162
|
+
deliveryAttemptCount: slackRowNumber(row, "deliveryAttemptCount", "delivery_attempt_count"),
|
|
11163
|
+
deliveryRetryAt: slackRowNullableDate(row, "deliveryRetryAt", "delivery_retry_at"),
|
|
11164
|
+
deliveryLastErrorCode: slackRowNullableString(
|
|
11165
|
+
row,
|
|
11166
|
+
"deliveryLastErrorCode",
|
|
11167
|
+
"delivery_last_error_code"
|
|
11168
|
+
),
|
|
10678
11169
|
ackSlackMessageTs: slackRowNullableString(row, "ackSlackMessageTs", "ack_slack_message_ts"),
|
|
10679
11170
|
progressCount: slackRowNumber(row, "progressCount", "progress_count"),
|
|
10680
11171
|
terminalDeliveryState: slackRowString(
|
|
@@ -10837,7 +11328,7 @@ async function recordSlackBotInstallCallbackFailure(db, input) {
|
|
|
10837
11328
|
await setSubjectRlsContext(scopedDb, input.subjectId);
|
|
10838
11329
|
await assertWorkspaceAccountPairInScope(scopedDb, input.accountId, input.workspaceId);
|
|
10839
11330
|
await scopedDb.execute(
|
|
10840
|
-
|
|
11331
|
+
sql8`select pg_advisory_xact_lock(hashtextextended(${`slack-callback-failure:${input.workspaceId}:${input.callbackDigest}`}, 0))`
|
|
10841
11332
|
);
|
|
10842
11333
|
const [existing] = await scopedDb.select({ id: auditEvents.id }).from(auditEvents).where(
|
|
10843
11334
|
and10(
|
|
@@ -10893,7 +11384,7 @@ async function claimSlackBotPostOperation(db, input) {
|
|
|
10893
11384
|
requestDigest: input.requestDigest,
|
|
10894
11385
|
status: "provider_started",
|
|
10895
11386
|
claimHolderId: input.claimHolderId,
|
|
10896
|
-
claimExpiresAt:
|
|
11387
|
+
claimExpiresAt: sql8`now() + (${claimLeaseMs} * interval '1 millisecond')`,
|
|
10897
11388
|
attemptCount: 1
|
|
10898
11389
|
}).onConflictDoNothing({
|
|
10899
11390
|
target: [
|
|
@@ -10927,16 +11418,16 @@ async function claimSlackBotPostOperation(db, input) {
|
|
|
10927
11418
|
}
|
|
10928
11419
|
const [reclaimed] = await tx.update(slackBotPostOperations).set({
|
|
10929
11420
|
claimHolderId: input.claimHolderId,
|
|
10930
|
-
claimExpiresAt:
|
|
10931
|
-
attemptCount:
|
|
11421
|
+
claimExpiresAt: sql8`now() + (${claimLeaseMs} * interval '1 millisecond')`,
|
|
11422
|
+
attemptCount: sql8`${slackBotPostOperations.attemptCount} + 1`,
|
|
10932
11423
|
lastFailureCode: null,
|
|
10933
|
-
updatedAt:
|
|
11424
|
+
updatedAt: sql8`now()`
|
|
10934
11425
|
}).where(
|
|
10935
11426
|
and10(
|
|
10936
11427
|
eq10(slackBotPostOperations.id, existing.id),
|
|
10937
11428
|
or3(
|
|
10938
11429
|
isNull3(slackBotPostOperations.claimHolderId),
|
|
10939
|
-
lte2(slackBotPostOperations.claimExpiresAt,
|
|
11430
|
+
lte2(slackBotPostOperations.claimExpiresAt, sql8`now()`)
|
|
10940
11431
|
)
|
|
10941
11432
|
)
|
|
10942
11433
|
).returning();
|
|
@@ -10959,7 +11450,7 @@ async function releaseSlackBotPostOperationClaim(db, input) {
|
|
|
10959
11450
|
claimHolderId: null,
|
|
10960
11451
|
claimExpiresAt: null,
|
|
10961
11452
|
lastFailureCode: input.failureCode.slice(0, 128),
|
|
10962
|
-
updatedAt:
|
|
11453
|
+
updatedAt: sql8`now()`
|
|
10963
11454
|
}).where(
|
|
10964
11455
|
and10(
|
|
10965
11456
|
eq10(slackBotPostOperations.workspaceId, input.workspaceId),
|
|
@@ -11004,8 +11495,8 @@ async function completeSlackBotPostOperation(db, input) {
|
|
|
11004
11495
|
lastFailureCode: null,
|
|
11005
11496
|
slackChannelId: input.slackChannelId,
|
|
11006
11497
|
slackMessageTimestamp: input.slackMessageTimestamp,
|
|
11007
|
-
completedAt:
|
|
11008
|
-
updatedAt:
|
|
11498
|
+
completedAt: sql8`now()`,
|
|
11499
|
+
updatedAt: sql8`now()`
|
|
11009
11500
|
}).where(eq10(slackBotPostOperations.id, current.id)).returning();
|
|
11010
11501
|
if (!completed) throw new Error("Slack post completion returned no row");
|
|
11011
11502
|
await tx.insert(auditEvents).values({
|
|
@@ -11068,7 +11559,7 @@ async function claimSlackBotDeleteOperation(db, input) {
|
|
|
11068
11559
|
requestDigest: input.requestDigest,
|
|
11069
11560
|
status: "pending",
|
|
11070
11561
|
claimHolderId: input.claimHolderId,
|
|
11071
|
-
claimExpiresAt:
|
|
11562
|
+
claimExpiresAt: sql8`now() + (${claimLeaseMs} * interval '1 millisecond')`,
|
|
11072
11563
|
attemptCount: 1
|
|
11073
11564
|
}).onConflictDoNothing({
|
|
11074
11565
|
target: [
|
|
@@ -11108,9 +11599,9 @@ async function claimSlackBotDeleteOperation(db, input) {
|
|
|
11108
11599
|
const [reclaimed] = await tx.update(slackBotDeleteOperations).set({
|
|
11109
11600
|
status: nextStatus,
|
|
11110
11601
|
claimHolderId: input.claimHolderId,
|
|
11111
|
-
claimExpiresAt:
|
|
11112
|
-
attemptCount:
|
|
11113
|
-
updatedAt:
|
|
11602
|
+
claimExpiresAt: sql8`now() + (${claimLeaseMs} * interval '1 millisecond')`,
|
|
11603
|
+
attemptCount: sql8`${slackBotDeleteOperations.attemptCount} + 1`,
|
|
11604
|
+
updatedAt: sql8`now()`
|
|
11114
11605
|
}).where(eq10(slackBotDeleteOperations.id, existing.id)).returning();
|
|
11115
11606
|
if (!reclaimed) throw new Error("Slack delete operation reclaim returned no row");
|
|
11116
11607
|
return {
|
|
@@ -11125,7 +11616,7 @@ async function markSlackBotDeleteOperationProviderStarted(db, input) {
|
|
|
11125
11616
|
db,
|
|
11126
11617
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
11127
11618
|
async (scopedDb) => {
|
|
11128
|
-
const rows = await scopedDb.update(slackBotDeleteOperations).set({ status: "provider_started", updatedAt:
|
|
11619
|
+
const rows = await scopedDb.update(slackBotDeleteOperations).set({ status: "provider_started", updatedAt: sql8`now()` }).where(
|
|
11129
11620
|
and10(
|
|
11130
11621
|
eq10(slackBotDeleteOperations.workspaceId, input.workspaceId),
|
|
11131
11622
|
eq10(slackBotDeleteOperations.connectionId, input.connectionId),
|
|
@@ -11151,7 +11642,7 @@ async function releaseSlackBotDeleteOperationClaim(db, input) {
|
|
|
11151
11642
|
claimHolderId: null,
|
|
11152
11643
|
claimExpiresAt: null,
|
|
11153
11644
|
lastFailureCode: input.failureCode.slice(0, 128),
|
|
11154
|
-
updatedAt:
|
|
11645
|
+
updatedAt: sql8`now()`
|
|
11155
11646
|
}).where(
|
|
11156
11647
|
and10(
|
|
11157
11648
|
eq10(slackBotDeleteOperations.workspaceId, input.workspaceId),
|
|
@@ -11196,8 +11687,8 @@ async function completeSlackBotDeleteOperation(db, input) {
|
|
|
11196
11687
|
lastFailureCode: null,
|
|
11197
11688
|
slackChannelId: input.slackChannelId,
|
|
11198
11689
|
slackMessageTimestamp: input.slackMessageTimestamp,
|
|
11199
|
-
completedAt:
|
|
11200
|
-
updatedAt:
|
|
11690
|
+
completedAt: sql8`now()`,
|
|
11691
|
+
updatedAt: sql8`now()`
|
|
11201
11692
|
}).where(eq10(slackBotDeleteOperations.id, current.id)).returning();
|
|
11202
11693
|
if (!completed) throw new Error("Slack delete completion returned no row");
|
|
11203
11694
|
await tx.insert(auditEvents).values({
|
|
@@ -11257,9 +11748,12 @@ async function loadConnectionCredentialForBroker(db, settings, input) {
|
|
|
11257
11748
|
input.workspaceId,
|
|
11258
11749
|
input.allowSubjectOwned ? input.subjectId : null,
|
|
11259
11750
|
async (scopedDb) => {
|
|
11751
|
+
const personalSlackSubjectLookup = !input.connectionId && input.allowSubjectOwned === true && input.providerDomain === "slack.com" && input.kind === "oauth2";
|
|
11260
11752
|
const [row] = await scopedDb.select().from(connections).where(and10(...conditions)).orderBy(
|
|
11261
|
-
|
|
11262
|
-
|
|
11753
|
+
...personalSlackSubjectLookup ? personalSlackCanonicalConnectionOrder() : [
|
|
11754
|
+
desc5(sql8`(${connections.status} = 'active')`),
|
|
11755
|
+
desc5(connections.updatedAt)
|
|
11756
|
+
]
|
|
11263
11757
|
).limit(1);
|
|
11264
11758
|
if (!row) {
|
|
11265
11759
|
return null;
|
|
@@ -11306,7 +11800,7 @@ async function recordConnectionTokenRefresh(db, input) {
|
|
|
11306
11800
|
lastRefreshAt: input.lastRefreshAt,
|
|
11307
11801
|
status: "active",
|
|
11308
11802
|
lastError: null,
|
|
11309
|
-
version:
|
|
11803
|
+
version: sql8`${connections.version} + 1`,
|
|
11310
11804
|
updatedAt: /* @__PURE__ */ new Date(),
|
|
11311
11805
|
...input.grantedScopes !== void 0 ? { grantedScopes: input.grantedScopes } : {}
|
|
11312
11806
|
};
|
|
@@ -11330,8 +11824,8 @@ async function setConnectionStatus(db, workspaceId, status, lastError, guard) {
|
|
|
11330
11824
|
const updated = await scopedDb.update(connections).set({
|
|
11331
11825
|
status,
|
|
11332
11826
|
lastError,
|
|
11333
|
-
version:
|
|
11334
|
-
verifiedInstallVersion:
|
|
11827
|
+
version: sql8`${connections.version} + 1`,
|
|
11828
|
+
verifiedInstallVersion: sql8`case
|
|
11335
11829
|
when ${connections.verifiedInstallAt} is null then null
|
|
11336
11830
|
else ${connections.version} + 1
|
|
11337
11831
|
end`,
|
|
@@ -11567,7 +12061,7 @@ async function updateKnowledgeMemory(db, workspaceId, memoryId, input, embedder)
|
|
|
11567
12061
|
);
|
|
11568
12062
|
if (willBeVisible) {
|
|
11569
12063
|
const [{ visibleCount } = { visibleCount: 0 }] = await scopedDb.select({
|
|
11570
|
-
visibleCount:
|
|
12064
|
+
visibleCount: sql8`count(*)::int`
|
|
11571
12065
|
}).from(knowledgeMemories).where(
|
|
11572
12066
|
and10(
|
|
11573
12067
|
eq10(knowledgeMemories.workspaceId, workspaceId),
|
|
@@ -11696,7 +12190,7 @@ async function listKnowledgeMemories(db, workspaceId, options = {}) {
|
|
|
11696
12190
|
const query = cleanDbString(options.query);
|
|
11697
12191
|
if (query) {
|
|
11698
12192
|
conditions.push(
|
|
11699
|
-
|
|
12193
|
+
sql8`to_tsvector('simple', ${knowledgeMemories.text}) @@ plainto_tsquery('simple', ${query})`
|
|
11700
12194
|
);
|
|
11701
12195
|
}
|
|
11702
12196
|
const limit = Math.min(Math.max(options.limit ?? 20, 1), 100);
|
|
@@ -11724,17 +12218,21 @@ function memoryVectorLiteral(values) {
|
|
|
11724
12218
|
return `[${values.join(",")}]`;
|
|
11725
12219
|
}
|
|
11726
12220
|
var agentVisibleMemoryStatuses = [...AGENT_VISIBLE_MEMORY_STATUSES];
|
|
11727
|
-
var
|
|
12221
|
+
var visibleTextHashUniqueIndexNames = /* @__PURE__ */ new Set([
|
|
12222
|
+
"knowledge_memories_workspace_visible_text_hash_uq",
|
|
12223
|
+
"knowledge_memories_scope_visible_text_hash_uq"
|
|
12224
|
+
]);
|
|
11728
12225
|
function isVisibleTextHashUniqueViolation(error) {
|
|
11729
12226
|
const candidate = error;
|
|
11730
12227
|
if (!candidate || typeof candidate !== "object") {
|
|
11731
12228
|
return false;
|
|
11732
12229
|
}
|
|
11733
12230
|
const constraint = candidate.constraint ?? candidate.constraint_name;
|
|
11734
|
-
if (candidate.code === "23505" && constraint
|
|
12231
|
+
if (candidate.code === "23505" && visibleTextHashUniqueIndexNames.has(String(constraint))) {
|
|
11735
12232
|
return true;
|
|
11736
12233
|
}
|
|
11737
|
-
|
|
12234
|
+
const message = typeof candidate.message === "string" ? candidate.message : null;
|
|
12235
|
+
if (message !== null && [...visibleTextHashUniqueIndexNames].some((name) => message.includes(name)) && (candidate.code === "23505" || message.includes("duplicate key value violates unique constraint"))) {
|
|
11738
12236
|
return true;
|
|
11739
12237
|
}
|
|
11740
12238
|
return isVisibleTextHashUniqueViolation(candidate.cause);
|
|
@@ -11796,7 +12294,7 @@ async function resolveWorkspaceMemoryId(scopedDb, workspaceId, rawId) {
|
|
|
11796
12294
|
const matches = await scopedDb.select({ id: knowledgeMemories.id }).from(knowledgeMemories).where(
|
|
11797
12295
|
and10(
|
|
11798
12296
|
eq10(knowledgeMemories.workspaceId, workspaceId),
|
|
11799
|
-
|
|
12297
|
+
sql8`${knowledgeMemories.id}::text like ${`${candidate}%`}`,
|
|
11800
12298
|
ne(knowledgeMemories.status, "archived"),
|
|
11801
12299
|
ne(knowledgeMemories.status, "superseded"),
|
|
11802
12300
|
ne(knowledgeMemories.status, "rejected")
|
|
@@ -11952,14 +12450,14 @@ async function saveWorkspaceMemory(db, input, embedder) {
|
|
|
11952
12450
|
inArray5(knowledgeMemories.status, agentVisibleMemoryStatuses)
|
|
11953
12451
|
)
|
|
11954
12452
|
).orderBy(
|
|
11955
|
-
replacesFullId ?
|
|
12453
|
+
replacesFullId ? sql8`case when ${knowledgeMemories.id} = ${replacesFullId} then 1 else 0 end` : knowledgeMemories.updatedAt
|
|
11956
12454
|
).limit(replacesFullId ? 2 : 1);
|
|
11957
12455
|
const exact = exactMatches.find((row) => row.id !== replacesFullId) ?? exactMatches[0];
|
|
11958
12456
|
if (exact) {
|
|
11959
12457
|
return await dedupeToExisting(exact, "exact");
|
|
11960
12458
|
}
|
|
11961
12459
|
if (embedding && embeddingModel) {
|
|
11962
|
-
const distance =
|
|
12460
|
+
const distance = sql8`${knowledgeMemories.embedding} <=> ${memoryVectorLiteral(embedding)}::vector`;
|
|
11963
12461
|
const neighbours = await scopedDb.select({
|
|
11964
12462
|
id: knowledgeMemories.id,
|
|
11965
12463
|
distance
|
|
@@ -11968,7 +12466,7 @@ async function saveWorkspaceMemory(db, input, embedder) {
|
|
|
11968
12466
|
eq10(knowledgeMemories.workspaceId, input.workspaceId),
|
|
11969
12467
|
inArray5(knowledgeMemories.status, agentVisibleMemoryStatuses),
|
|
11970
12468
|
eq10(knowledgeMemories.embeddingModel, embeddingModel),
|
|
11971
|
-
|
|
12469
|
+
sql8`${knowledgeMemories.embedding} is not null`
|
|
11972
12470
|
)
|
|
11973
12471
|
).orderBy(distance).limit(MEMORY_NEAR_DUP_NEIGHBORS);
|
|
11974
12472
|
const duplicateNeighbours = neighbours.filter(
|
|
@@ -11988,7 +12486,7 @@ async function saveWorkspaceMemory(db, input, embedder) {
|
|
|
11988
12486
|
}
|
|
11989
12487
|
}
|
|
11990
12488
|
const [{ visibleCount } = { visibleCount: 0 }] = await scopedDb.select({
|
|
11991
|
-
visibleCount:
|
|
12489
|
+
visibleCount: sql8`count(*)::int`
|
|
11992
12490
|
}).from(knowledgeMemories).where(
|
|
11993
12491
|
and10(
|
|
11994
12492
|
eq10(knowledgeMemories.workspaceId, input.workspaceId),
|
|
@@ -12173,12 +12671,12 @@ async function searchWorkspaceMemories(db, workspaceId, input, embedder) {
|
|
|
12173
12671
|
if (!vector || vector.length === 0) {
|
|
12174
12672
|
throw new Error("embedder returned no query vector");
|
|
12175
12673
|
}
|
|
12176
|
-
const distance =
|
|
12674
|
+
const distance = sql8`${knowledgeMemories.embedding} <=> ${memoryVectorLiteral(vector)}::vector`;
|
|
12177
12675
|
const rows = await scopedDb.select({ id: knowledgeMemories.id, distance }).from(knowledgeMemories).where(
|
|
12178
12676
|
and10(
|
|
12179
12677
|
...baseConditions,
|
|
12180
12678
|
eq10(knowledgeMemories.embeddingModel, embedder.model),
|
|
12181
|
-
|
|
12679
|
+
sql8`${knowledgeMemories.embedding} is not null`
|
|
12182
12680
|
)
|
|
12183
12681
|
).orderBy(distance).limit(candidateLimit);
|
|
12184
12682
|
for (const row of rows) {
|
|
@@ -12202,11 +12700,11 @@ async function searchWorkspaceMemories(db, workspaceId, input, embedder) {
|
|
|
12202
12700
|
}
|
|
12203
12701
|
}
|
|
12204
12702
|
if (mode === "keyword" || mode === "hybrid") {
|
|
12205
|
-
const rank =
|
|
12703
|
+
const rank = sql8`ts_rank_cd(to_tsvector('simple', ${knowledgeMemories.text}), plainto_tsquery('simple', ${query}))`;
|
|
12206
12704
|
const rows = await scopedDb.select({ id: knowledgeMemories.id, rank }).from(knowledgeMemories).where(
|
|
12207
12705
|
and10(
|
|
12208
12706
|
...baseConditions,
|
|
12209
|
-
|
|
12707
|
+
sql8`to_tsvector('simple', ${knowledgeMemories.text}) @@ plainto_tsquery('simple', ${query})`
|
|
12210
12708
|
)
|
|
12211
12709
|
).orderBy(desc5(rank)).limit(candidateLimit);
|
|
12212
12710
|
for (const row of rows) {
|
|
@@ -12239,7 +12737,7 @@ async function searchWorkspaceMemories(db, workspaceId, input, embedder) {
|
|
|
12239
12737
|
}
|
|
12240
12738
|
const ids = ranked.map((entry) => entry.id);
|
|
12241
12739
|
const bumped = await scopedDb.update(knowledgeMemories).set({
|
|
12242
|
-
usageCount:
|
|
12740
|
+
usageCount: sql8`${knowledgeMemories.usageCount} + 1`,
|
|
12243
12741
|
lastUsedAt: /* @__PURE__ */ new Date()
|
|
12244
12742
|
}).where(
|
|
12245
12743
|
and10(
|
|
@@ -12312,6 +12810,7 @@ async function createSocialConnection(db, input) {
|
|
|
12312
12810
|
status: input.status,
|
|
12313
12811
|
scopes: input.scopes ?? [],
|
|
12314
12812
|
credentialRef: input.credentialRef ?? null,
|
|
12813
|
+
credentialEncrypted: input.credentialEncrypted ?? null,
|
|
12315
12814
|
tokenMetadata: input.tokenMetadata ?? {},
|
|
12316
12815
|
metadata: input.metadata ?? {}
|
|
12317
12816
|
}).returning();
|
|
@@ -12322,15 +12821,85 @@ async function createSocialConnection(db, input) {
|
|
|
12322
12821
|
}
|
|
12323
12822
|
);
|
|
12324
12823
|
}
|
|
12824
|
+
async function upsertSocialOAuthConnection(db, input) {
|
|
12825
|
+
return await withRlsContext(
|
|
12826
|
+
db,
|
|
12827
|
+
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
12828
|
+
async (scopedDb) => {
|
|
12829
|
+
const [row] = await scopedDb.insert(socialConnections).values({
|
|
12830
|
+
accountId: input.accountId,
|
|
12831
|
+
workspaceId: input.workspaceId,
|
|
12832
|
+
provider: input.provider,
|
|
12833
|
+
accountHandle: input.accountHandle,
|
|
12834
|
+
accountName: input.accountName ?? null,
|
|
12835
|
+
externalAccountId: input.externalAccountId ?? null,
|
|
12836
|
+
status: "connected",
|
|
12837
|
+
scopes: input.scopes,
|
|
12838
|
+
credentialEncrypted: input.credentialEncrypted,
|
|
12839
|
+
tokenMetadata: input.tokenMetadata ?? {}
|
|
12840
|
+
}).onConflictDoUpdate({
|
|
12841
|
+
target: [
|
|
12842
|
+
socialConnections.workspaceId,
|
|
12843
|
+
socialConnections.provider,
|
|
12844
|
+
socialConnections.accountHandle
|
|
12845
|
+
],
|
|
12846
|
+
set: {
|
|
12847
|
+
accountName: input.accountName ?? null,
|
|
12848
|
+
externalAccountId: input.externalAccountId ?? null,
|
|
12849
|
+
status: "connected",
|
|
12850
|
+
scopes: input.scopes,
|
|
12851
|
+
credentialEncrypted: input.credentialEncrypted,
|
|
12852
|
+
tokenMetadata: input.tokenMetadata ?? {},
|
|
12853
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
12854
|
+
}
|
|
12855
|
+
}).returning();
|
|
12856
|
+
if (!row) {
|
|
12857
|
+
throw new Error("Failed to upsert social connection");
|
|
12858
|
+
}
|
|
12859
|
+
return mapSocialConnection(row);
|
|
12860
|
+
}
|
|
12861
|
+
);
|
|
12862
|
+
}
|
|
12863
|
+
async function loadSocialConnectionCredential(db, workspaceId, connectionId) {
|
|
12864
|
+
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
12865
|
+
const [row] = await scopedDb.select().from(socialConnections).where(
|
|
12866
|
+
and10(
|
|
12867
|
+
eq10(socialConnections.workspaceId, workspaceId),
|
|
12868
|
+
eq10(socialConnections.id, connectionId)
|
|
12869
|
+
)
|
|
12870
|
+
).limit(1);
|
|
12871
|
+
if (!row) {
|
|
12872
|
+
return null;
|
|
12873
|
+
}
|
|
12874
|
+
return { connection: mapSocialConnection(row), credentialEncrypted: row.credentialEncrypted };
|
|
12875
|
+
});
|
|
12876
|
+
}
|
|
12877
|
+
async function updateSocialConnectionCredential(db, input) {
|
|
12878
|
+
return await withWorkspaceRls(db, input.workspaceId, async (scopedDb) => {
|
|
12879
|
+
const [row] = await scopedDb.update(socialConnections).set({
|
|
12880
|
+
...input.credentialEncrypted !== void 0 ? { credentialEncrypted: input.credentialEncrypted } : {},
|
|
12881
|
+
...input.status !== void 0 ? { status: input.status } : {},
|
|
12882
|
+
...input.tokenMetadata !== void 0 ? { tokenMetadata: input.tokenMetadata } : {},
|
|
12883
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
12884
|
+
}).where(
|
|
12885
|
+
and10(
|
|
12886
|
+
eq10(socialConnections.workspaceId, input.workspaceId),
|
|
12887
|
+
eq10(socialConnections.id, input.connectionId)
|
|
12888
|
+
)
|
|
12889
|
+
).returning();
|
|
12890
|
+
return row ? mapSocialConnection(row) : null;
|
|
12891
|
+
});
|
|
12892
|
+
}
|
|
12893
|
+
var { credentialEncrypted: _socialCredentialColumn, ...socialConnectionPublicColumns } = getTableColumns(socialConnections);
|
|
12325
12894
|
async function listSocialConnections(db, workspaceId, limit = 100) {
|
|
12326
12895
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
12327
|
-
const rows = await scopedDb.select().from(socialConnections).where(eq10(socialConnections.workspaceId, workspaceId)).orderBy(desc5(socialConnections.createdAt)).limit(limit);
|
|
12896
|
+
const rows = await scopedDb.select(socialConnectionPublicColumns).from(socialConnections).where(eq10(socialConnections.workspaceId, workspaceId)).orderBy(desc5(socialConnections.createdAt)).limit(limit);
|
|
12328
12897
|
return rows.map(mapSocialConnection);
|
|
12329
12898
|
});
|
|
12330
12899
|
}
|
|
12331
12900
|
async function getSocialConnection(db, workspaceId, connectionId) {
|
|
12332
12901
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
12333
|
-
const [row] = await scopedDb.select().from(socialConnections).where(
|
|
12902
|
+
const [row] = await scopedDb.select(socialConnectionPublicColumns).from(socialConnections).where(
|
|
12334
12903
|
and10(
|
|
12335
12904
|
eq10(socialConnections.workspaceId, workspaceId),
|
|
12336
12905
|
eq10(socialConnections.id, connectionId)
|
|
@@ -12376,6 +12945,44 @@ async function createSocialPost(db, input) {
|
|
|
12376
12945
|
}
|
|
12377
12946
|
);
|
|
12378
12947
|
}
|
|
12948
|
+
async function recordSyncedSocialPosts(db, input) {
|
|
12949
|
+
if (input.posts.length === 0) {
|
|
12950
|
+
return { inserted: 0, skipped: 0 };
|
|
12951
|
+
}
|
|
12952
|
+
return await withRlsContext(
|
|
12953
|
+
db,
|
|
12954
|
+
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
12955
|
+
async (scopedDb) => {
|
|
12956
|
+
const connection = await requireSocialConnection(
|
|
12957
|
+
scopedDb,
|
|
12958
|
+
input.workspaceId,
|
|
12959
|
+
input.connectionId
|
|
12960
|
+
);
|
|
12961
|
+
const rows = await scopedDb.insert(socialPosts).values(
|
|
12962
|
+
input.posts.map((post) => ({
|
|
12963
|
+
accountId: input.accountId,
|
|
12964
|
+
workspaceId: input.workspaceId,
|
|
12965
|
+
connectionId: input.connectionId,
|
|
12966
|
+
provider: connection.provider,
|
|
12967
|
+
externalPostId: post.externalPostId,
|
|
12968
|
+
url: post.url ?? null,
|
|
12969
|
+
authorHandle: post.authorHandle ?? connection.accountHandle,
|
|
12970
|
+
text: post.text,
|
|
12971
|
+
publishedAt: post.publishedAt,
|
|
12972
|
+
metrics: post.metrics ?? {},
|
|
12973
|
+
raw: post.raw ?? {}
|
|
12974
|
+
}))
|
|
12975
|
+
).onConflictDoNothing({
|
|
12976
|
+
target: [
|
|
12977
|
+
socialPosts.workspaceId,
|
|
12978
|
+
socialPosts.connectionId,
|
|
12979
|
+
socialPosts.externalPostId
|
|
12980
|
+
]
|
|
12981
|
+
}).returning({ id: socialPosts.id });
|
|
12982
|
+
return { inserted: rows.length, skipped: input.posts.length - rows.length };
|
|
12983
|
+
}
|
|
12984
|
+
);
|
|
12985
|
+
}
|
|
12379
12986
|
async function listSocialPosts(db, options) {
|
|
12380
12987
|
const conditions = [eq10(socialPosts.workspaceId, options.workspaceId)];
|
|
12381
12988
|
if (options.connectionIds?.length) {
|
|
@@ -12486,7 +13093,7 @@ async function createScheduledTaskRun(db, input) {
|
|
|
12486
13093
|
};
|
|
12487
13094
|
const [inserted] = input.producerKey ? await scopedDb.insert(scheduledTaskRuns).values(values).onConflictDoNothing({
|
|
12488
13095
|
target: [scheduledTaskRuns.workspaceId, scheduledTaskRuns.producerKey],
|
|
12489
|
-
where:
|
|
13096
|
+
where: sql8`${scheduledTaskRuns.producerKey} is not null`
|
|
12490
13097
|
}).returning() : await scopedDb.insert(scheduledTaskRuns).values(values).returning();
|
|
12491
13098
|
const [row] = inserted ? [inserted] : await scopedDb.select().from(scheduledTaskRuns).where(
|
|
12492
13099
|
and10(
|
|
@@ -12685,7 +13292,7 @@ async function deleteVariableSet(db, workspaceId, variableSetId) {
|
|
|
12685
13292
|
async function countVariableSets(db, workspaceId) {
|
|
12686
13293
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
12687
13294
|
const [{ count } = { count: 0 }] = await scopedDb.select({
|
|
12688
|
-
count:
|
|
13295
|
+
count: sql8`count(*)::int`
|
|
12689
13296
|
}).from(workspaceVariableSets).where(eq10(workspaceVariableSets.workspaceId, workspaceId));
|
|
12690
13297
|
return Number(count);
|
|
12691
13298
|
});
|
|
@@ -12693,7 +13300,7 @@ async function countVariableSets(db, workspaceId) {
|
|
|
12693
13300
|
async function countScheduledTasksUsingVariableSet(db, workspaceId, variableSetId) {
|
|
12694
13301
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
12695
13302
|
const [{ count } = { count: 0 }] = await scopedDb.select({
|
|
12696
|
-
count:
|
|
13303
|
+
count: sql8`count(*)::int`
|
|
12697
13304
|
}).from(scheduledTasks).where(
|
|
12698
13305
|
and10(
|
|
12699
13306
|
eq10(scheduledTasks.workspaceId, workspaceId),
|
|
@@ -12706,7 +13313,7 @@ async function countScheduledTasksUsingVariableSet(db, workspaceId, variableSetI
|
|
|
12706
13313
|
async function countActiveSessionsUsingVariableSet(db, workspaceId, variableSetId) {
|
|
12707
13314
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
12708
13315
|
const [{ count } = { count: 0 }] = await scopedDb.select({
|
|
12709
|
-
count:
|
|
13316
|
+
count: sql8`count(*)::int`
|
|
12710
13317
|
}).from(sessions).where(
|
|
12711
13318
|
and10(
|
|
12712
13319
|
eq10(sessions.workspaceId, workspaceId),
|
|
@@ -12737,7 +13344,7 @@ async function setVariableSetVariable(db, input) {
|
|
|
12737
13344
|
],
|
|
12738
13345
|
set: {
|
|
12739
13346
|
valueEncrypted: input.valueEncrypted,
|
|
12740
|
-
version:
|
|
13347
|
+
version: sql8`${workspaceVariableSetVariables.version} + 1`,
|
|
12741
13348
|
updatedAt: now
|
|
12742
13349
|
}
|
|
12743
13350
|
}).returning({
|
|
@@ -12863,7 +13470,7 @@ async function loadRigActiveAndCount(scopedDb, workspaceId, rigId) {
|
|
|
12863
13470
|
eq10(rigVersions.active, true)
|
|
12864
13471
|
)
|
|
12865
13472
|
).limit(1);
|
|
12866
|
-
const [{ count } = { count: 0 }] = await scopedDb.select({ count:
|
|
13473
|
+
const [{ count } = { count: 0 }] = await scopedDb.select({ count: sql8`count(*)::int` }).from(rigVersions).where(
|
|
12867
13474
|
and10(eq10(rigVersions.workspaceId, workspaceId), eq10(rigVersions.rigId, rigId))
|
|
12868
13475
|
);
|
|
12869
13476
|
return {
|
|
@@ -12936,7 +13543,7 @@ async function loadRigHealthByActiveVersion(scopedDb, workspaceId, activeVersion
|
|
|
12936
13543
|
eq10(auditEvents.workspaceId, workspaceId),
|
|
12937
13544
|
eq10(auditEvents.targetType, "rig"),
|
|
12938
13545
|
inArray5(auditEvents.action, ["rig.verification.passed", "rig.verification.failed"]),
|
|
12939
|
-
inArray5(
|
|
13546
|
+
inArray5(sql8`${auditEvents.metadata}->>'versionId'`, versionIds)
|
|
12940
13547
|
)
|
|
12941
13548
|
);
|
|
12942
13549
|
for (const row of auditRows) {
|
|
@@ -13009,7 +13616,7 @@ async function listRigs(db, workspaceId) {
|
|
|
13009
13616
|
]);
|
|
13010
13617
|
const countRows = await scopedDb.select({
|
|
13011
13618
|
rigId: rigVersions.rigId,
|
|
13012
|
-
count:
|
|
13619
|
+
count: sql8`count(*)::int`
|
|
13013
13620
|
}).from(rigVersions).where(eq10(rigVersions.workspaceId, workspaceId)).groupBy(rigVersions.rigId);
|
|
13014
13621
|
const countByRig = new Map(countRows.map((row) => [row.rigId, Number(row.count)]));
|
|
13015
13622
|
return rows.map((row) => {
|
|
@@ -13111,11 +13718,11 @@ async function deleteRigIfNoActiveSessions(db, workspaceId, rigId) {
|
|
|
13111
13718
|
if (!rig) {
|
|
13112
13719
|
return { deleted: false, activeSessionCount: 0 };
|
|
13113
13720
|
}
|
|
13114
|
-
const [{ count } = { count: 0 }] = await scopedDb.select({ count:
|
|
13721
|
+
const [{ count } = { count: 0 }] = await scopedDb.select({ count: sql8`count(*)::int` }).from(sessions).where(
|
|
13115
13722
|
and10(
|
|
13116
13723
|
eq10(sessions.workspaceId, workspaceId),
|
|
13117
13724
|
eq10(sessions.rigId, rigId),
|
|
13118
|
-
|
|
13725
|
+
sql8`${sessions.status} not in ('failed', 'cancelled')`
|
|
13119
13726
|
)
|
|
13120
13727
|
);
|
|
13121
13728
|
const activeSessionCount = Number(count);
|
|
@@ -13128,13 +13735,13 @@ async function deleteRigIfNoActiveSessions(db, workspaceId, rigId) {
|
|
|
13128
13735
|
}
|
|
13129
13736
|
async function countRigs(db, workspaceId) {
|
|
13130
13737
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
13131
|
-
const [{ count } = { count: 0 }] = await scopedDb.select({ count:
|
|
13738
|
+
const [{ count } = { count: 0 }] = await scopedDb.select({ count: sql8`count(*)::int` }).from(rigs).where(eq10(rigs.workspaceId, workspaceId));
|
|
13132
13739
|
return Number(count);
|
|
13133
13740
|
});
|
|
13134
13741
|
}
|
|
13135
13742
|
async function countSessionsUsingRig(db, workspaceId, rigId) {
|
|
13136
13743
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
13137
|
-
const [{ count } = { count: 0 }] = await scopedDb.select({ count:
|
|
13744
|
+
const [{ count } = { count: 0 }] = await scopedDb.select({ count: sql8`count(*)::int` }).from(sessions).where(and10(eq10(sessions.workspaceId, workspaceId), eq10(sessions.rigId, rigId)));
|
|
13138
13745
|
return Number(count);
|
|
13139
13746
|
});
|
|
13140
13747
|
}
|
|
@@ -13145,7 +13752,7 @@ async function createRigVersion(db, workspaceId, rigId, input, options = {}) {
|
|
|
13145
13752
|
throw new Error(`Rig not found: ${rigId}`);
|
|
13146
13753
|
}
|
|
13147
13754
|
const [{ max } = { max: 0 }] = await scopedDb.select({
|
|
13148
|
-
max:
|
|
13755
|
+
max: sql8`coalesce(max(${rigVersions.version}), 0)::int`
|
|
13149
13756
|
}).from(rigVersions).where(
|
|
13150
13757
|
and10(eq10(rigVersions.workspaceId, workspaceId), eq10(rigVersions.rigId, rigId))
|
|
13151
13758
|
);
|
|
@@ -13221,7 +13828,7 @@ async function createRigVersionForChangePromotion(db, workspaceId, rigId, change
|
|
|
13221
13828
|
);
|
|
13222
13829
|
}
|
|
13223
13830
|
const [{ max } = { max: 0 }] = await scopedDb.select({
|
|
13224
|
-
max:
|
|
13831
|
+
max: sql8`coalesce(max(${rigVersions.version}), 0)::int`
|
|
13225
13832
|
}).from(rigVersions).where(
|
|
13226
13833
|
and10(eq10(rigVersions.workspaceId, workspaceId), eq10(rigVersions.rigId, rigId))
|
|
13227
13834
|
);
|
|
@@ -13283,20 +13890,20 @@ async function listRigVersionMonitoringSummaries(db, workspaceId, rigId, limit =
|
|
|
13283
13890
|
rigId: rigVersions.rigId,
|
|
13284
13891
|
version: rigVersions.version,
|
|
13285
13892
|
active: rigVersions.active,
|
|
13286
|
-
image:
|
|
13287
|
-
imageOriginalChars:
|
|
13288
|
-
setupScriptBytes:
|
|
13289
|
-
checkCount:
|
|
13290
|
-
credentialHookCount:
|
|
13291
|
-
defaultVariableSetCount:
|
|
13292
|
-
changelog:
|
|
13293
|
-
changelogOriginalChars:
|
|
13294
|
-
createdBy:
|
|
13893
|
+
image: sql8`left(${rigVersions.image}, 512)`,
|
|
13894
|
+
imageOriginalChars: sql8`char_length(${rigVersions.image})::int`,
|
|
13895
|
+
setupScriptBytes: sql8`octet_length(coalesce(${rigVersions.setupScript}, ''))::int`,
|
|
13896
|
+
checkCount: sql8`jsonb_array_length(${rigVersions.checks})::int`,
|
|
13897
|
+
credentialHookCount: sql8`jsonb_array_length(${rigVersions.credentialHooks})::int`,
|
|
13898
|
+
defaultVariableSetCount: sql8`jsonb_array_length(${rigVersions.defaultVariableSetIds})::int`,
|
|
13899
|
+
changelog: sql8`left(${rigVersions.changelog}, 600)`,
|
|
13900
|
+
changelogOriginalChars: sql8`char_length(${rigVersions.changelog})::int`,
|
|
13901
|
+
createdBy: sql8`left(${rigVersions.createdBy}, 200)`,
|
|
13295
13902
|
createdAt: rigVersions.createdAt
|
|
13296
13903
|
}).from(rigVersions).where(
|
|
13297
13904
|
and10(eq10(rigVersions.workspaceId, workspaceId), eq10(rigVersions.rigId, rigId))
|
|
13298
13905
|
).orderBy(desc5(rigVersions.version), desc5(rigVersions.id)).limit(boundedLimit + 1);
|
|
13299
|
-
const [{ total } = { total: 0 }] = await scopedDb.select({ total:
|
|
13906
|
+
const [{ total } = { total: 0 }] = await scopedDb.select({ total: sql8`count(*)::int` }).from(rigVersions).where(
|
|
13300
13907
|
and10(eq10(rigVersions.workspaceId, workspaceId), eq10(rigVersions.rigId, rigId))
|
|
13301
13908
|
);
|
|
13302
13909
|
return {
|
|
@@ -13417,16 +14024,16 @@ async function listRigChangeMonitoringSummaries(db, workspaceId, rigId, limit =
|
|
|
13417
14024
|
baseVersionId: rigChanges.baseVersionId,
|
|
13418
14025
|
kind: rigChanges.kind,
|
|
13419
14026
|
status: rigChanges.status,
|
|
13420
|
-
proposedBy:
|
|
14027
|
+
proposedBy: sql8`left(${rigChanges.proposedBy}, 200)`,
|
|
13421
14028
|
resultVersionId: rigChanges.resultVersionId,
|
|
13422
|
-
commandPreview:
|
|
13423
|
-
commandOriginalChars:
|
|
13424
|
-
payloadBytes:
|
|
13425
|
-
verificationBytes:
|
|
13426
|
-
verificationLogBytes:
|
|
13427
|
-
verificationStartedAt:
|
|
13428
|
-
verificationFinishedAt:
|
|
13429
|
-
verificationPassed:
|
|
14029
|
+
commandPreview: sql8`left(${rigChanges.payload}->>'command', 600)`,
|
|
14030
|
+
commandOriginalChars: sql8`char_length(${rigChanges.payload}->>'command')::int`,
|
|
14031
|
+
payloadBytes: sql8`octet_length(${rigChanges.payload}::text)::int`,
|
|
14032
|
+
verificationBytes: sql8`octet_length(coalesce(${rigChanges.verification}::text, 'null'))::int`,
|
|
14033
|
+
verificationLogBytes: sql8`octet_length(coalesce(${rigChanges.verification}->>'log', ''))::int`,
|
|
14034
|
+
verificationStartedAt: sql8`left(${rigChanges.verification}->>'startedAt', 64)`,
|
|
14035
|
+
verificationFinishedAt: sql8`left(${rigChanges.verification}->>'finishedAt', 64)`,
|
|
14036
|
+
verificationPassed: sql8`case
|
|
13430
14037
|
when ${rigChanges.verification}->>'passed' = 'true' then true
|
|
13431
14038
|
when ${rigChanges.verification}->>'passed' = 'false' then false
|
|
13432
14039
|
else null
|
|
@@ -13436,7 +14043,7 @@ async function listRigChangeMonitoringSummaries(db, workspaceId, rigId, limit =
|
|
|
13436
14043
|
}).from(rigChanges).where(
|
|
13437
14044
|
and10(eq10(rigChanges.workspaceId, workspaceId), eq10(rigChanges.rigId, rigId))
|
|
13438
14045
|
).orderBy(desc5(rigChanges.createdAt), desc5(rigChanges.id)).limit(boundedLimit + 1);
|
|
13439
|
-
const [{ total } = { total: 0 }] = await scopedDb.select({ total:
|
|
14046
|
+
const [{ total } = { total: 0 }] = await scopedDb.select({ total: sql8`count(*)::int` }).from(rigChanges).where(
|
|
13440
14047
|
and10(eq10(rigChanges.workspaceId, workspaceId), eq10(rigChanges.rigId, rigId))
|
|
13441
14048
|
);
|
|
13442
14049
|
return {
|
|
@@ -13619,7 +14226,7 @@ async function upsertCodexSubscriptionCredential(db, input) {
|
|
|
13619
14226
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
13620
14227
|
async (scopedDb) => {
|
|
13621
14228
|
await scopedDb.execute(
|
|
13622
|
-
|
|
14229
|
+
sql8`select pg_advisory_xact_lock(hashtextextended(${`codex-credential-upsert:${input.workspaceId}:${input.chatgptAccountId ?? "null"}`}, 0))`
|
|
13623
14230
|
);
|
|
13624
14231
|
const [existing] = input.chatgptAccountId ? await scopedDb.select({
|
|
13625
14232
|
id: codexSubscriptionCredentials.id,
|
|
@@ -13670,7 +14277,7 @@ async function upsertCodexSubscriptionCredential(db, input) {
|
|
|
13670
14277
|
codexSubscriptionCredentials.workspaceId,
|
|
13671
14278
|
codexSubscriptionCredentials.chatgptAccountId
|
|
13672
14279
|
],
|
|
13673
|
-
targetWhere:
|
|
14280
|
+
targetWhere: sql8`chatgpt_account_id is not null`,
|
|
13674
14281
|
set: {
|
|
13675
14282
|
// account_id MUST be re-asserted on conflict. Omitting it leaves a stale
|
|
13676
14283
|
// account_id on a row whose owning account changed (e.g. a reconnect
|
|
@@ -13686,7 +14293,7 @@ async function upsertCodexSubscriptionCredential(db, input) {
|
|
|
13686
14293
|
// Refresh the derived email; keep an existing user-chosen label (only seed
|
|
13687
14294
|
// it when still null) so a re-connect never clobbers a rename.
|
|
13688
14295
|
accountEmail: input.accountEmail ?? null,
|
|
13689
|
-
label:
|
|
14296
|
+
label: sql8`coalesce(${codexSubscriptionCredentials.label}, ${input.label ?? null})`,
|
|
13690
14297
|
// Ownership follows the most recent connection exactly. A
|
|
13691
14298
|
// configured/delegated/API-key reconnect is intentionally
|
|
13692
14299
|
// nonhuman and clears the prior human owner, making the row
|
|
@@ -13694,7 +14301,7 @@ async function upsertCodexSubscriptionCredential(db, input) {
|
|
|
13694
14301
|
connectedBySubjectId: input.connectedBySubjectId ?? null,
|
|
13695
14302
|
status: "active",
|
|
13696
14303
|
lastError: null,
|
|
13697
|
-
version:
|
|
14304
|
+
version: sql8`${codexSubscriptionCredentials.version} + 1`,
|
|
13698
14305
|
updatedAt: now
|
|
13699
14306
|
}
|
|
13700
14307
|
}).returning({
|
|
@@ -13766,7 +14373,7 @@ async function recordCodexTokenRefresh(db, input) {
|
|
|
13766
14373
|
lastRefreshAt: input.lastRefreshAt,
|
|
13767
14374
|
status: "active",
|
|
13768
14375
|
lastError: null,
|
|
13769
|
-
version:
|
|
14376
|
+
version: sql8`${codexSubscriptionCredentials.version} + 1`,
|
|
13770
14377
|
updatedAt: /* @__PURE__ */ new Date()
|
|
13771
14378
|
}).where(
|
|
13772
14379
|
and10(
|
|
@@ -13780,9 +14387,9 @@ async function recordCodexTokenRefresh(db, input) {
|
|
|
13780
14387
|
}
|
|
13781
14388
|
async function withCodexCredentialRefreshLock(db, workspaceId, credentialId, fn) {
|
|
13782
14389
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
13783
|
-
await scopedDb.execute(
|
|
14390
|
+
await scopedDb.execute(sql8`set local lock_timeout = '30s'`);
|
|
13784
14391
|
await scopedDb.execute(
|
|
13785
|
-
|
|
14392
|
+
sql8`select pg_advisory_xact_lock(hashtextextended(${`codex-refresh:${credentialId}`}, 0))`
|
|
13786
14393
|
);
|
|
13787
14394
|
return await fn(scopedDb);
|
|
13788
14395
|
});
|
|
@@ -13821,7 +14428,7 @@ async function setCodexCredentialStatusById(db, workspaceId, credentialId, statu
|
|
|
13821
14428
|
});
|
|
13822
14429
|
}
|
|
13823
14430
|
async function getCodexCredentialStatusScoped(scopedDb, workspaceId) {
|
|
13824
|
-
await scopedDb.execute(
|
|
14431
|
+
await scopedDb.execute(sql8`
|
|
13825
14432
|
select id from codex_rotation_settings
|
|
13826
14433
|
where workspace_id = ${workspaceId}
|
|
13827
14434
|
for update
|
|
@@ -13968,7 +14575,7 @@ function filterCodexLeaseCandidatesForPolicy(accounts, policyScope, filter) {
|
|
|
13968
14575
|
return { accounts: [...filteredAccounts], unavailableDiagnostics };
|
|
13969
14576
|
}
|
|
13970
14577
|
async function listCodexLeaseCandidatesInTransaction(tx, input) {
|
|
13971
|
-
const rows = await tx.execute(
|
|
14578
|
+
const rows = await tx.execute(sql8`
|
|
13972
14579
|
select
|
|
13973
14580
|
c.id,
|
|
13974
14581
|
c.chatgpt_account_id,
|
|
@@ -14017,13 +14624,13 @@ async function acquireCodexCredentialLease(db, input, select) {
|
|
|
14017
14624
|
db,
|
|
14018
14625
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
14019
14626
|
async (tx) => {
|
|
14020
|
-
await tx.execute(
|
|
14627
|
+
await tx.execute(sql8`
|
|
14021
14628
|
insert into codex_rotation_settings
|
|
14022
14629
|
(account_id, workspace_id, lease_rotation_enabled)
|
|
14023
14630
|
values (${input.accountId}, ${input.workspaceId}, false)
|
|
14024
14631
|
on conflict (workspace_id) do nothing
|
|
14025
14632
|
`);
|
|
14026
|
-
const settingsRows = await tx.execute(
|
|
14633
|
+
const settingsRows = await tx.execute(sql8`
|
|
14027
14634
|
select active_credential_id, rotation_enabled,
|
|
14028
14635
|
lease_rotation_enabled, rotation_strategy
|
|
14029
14636
|
from codex_rotation_settings
|
|
@@ -14034,7 +14641,7 @@ async function acquireCodexCredentialLease(db, input, select) {
|
|
|
14034
14641
|
if (!settingsRow) {
|
|
14035
14642
|
throw new Error(`Codex rotation settings not visible for workspace ${input.workspaceId}`);
|
|
14036
14643
|
}
|
|
14037
|
-
const turns = await tx.execute(
|
|
14644
|
+
const turns = await tx.execute(sql8`
|
|
14038
14645
|
select id, metadata from session_turns
|
|
14039
14646
|
where account_id = ${input.accountId}
|
|
14040
14647
|
and workspace_id = ${input.workspaceId}
|
|
@@ -14046,7 +14653,7 @@ async function acquireCodexCredentialLease(db, input, select) {
|
|
|
14046
14653
|
}
|
|
14047
14654
|
const policyScope = input.resolvePolicyScope?.(turns[0].metadata ?? {}) ?? null;
|
|
14048
14655
|
const continuationRows = input.continuationCredentialId ? await tx.execute(
|
|
14049
|
-
|
|
14656
|
+
sql8`
|
|
14050
14657
|
select frozen_codex_credential_id
|
|
14051
14658
|
from agent_run_states
|
|
14052
14659
|
where account_id = ${input.accountId}
|
|
@@ -14062,13 +14669,13 @@ async function acquireCodexCredentialLease(db, input, select) {
|
|
|
14062
14669
|
const leaseRotationEnabled = settingsRow.rotation_enabled && settingsRow.lease_rotation_enabled;
|
|
14063
14670
|
const rotationStrategy = settingsRow.rotation_strategy;
|
|
14064
14671
|
if (leaseRotationEnabled) {
|
|
14065
|
-
await tx.execute(
|
|
14672
|
+
await tx.execute(sql8`
|
|
14066
14673
|
delete from codex_credential_leases
|
|
14067
14674
|
where workspace_id = ${input.workspaceId} and leased_until <= now()
|
|
14068
14675
|
`);
|
|
14069
14676
|
}
|
|
14070
14677
|
const existingRows = leaseRotationEnabled ? await tx.execute(
|
|
14071
|
-
|
|
14678
|
+
sql8`
|
|
14072
14679
|
select credential_id, holder_id, generation from codex_credential_leases
|
|
14073
14680
|
where workspace_id = ${input.workspaceId}
|
|
14074
14681
|
and turn_id = ${input.turnId}
|
|
@@ -14115,7 +14722,7 @@ async function acquireCodexCredentialLease(db, input, select) {
|
|
|
14115
14722
|
}
|
|
14116
14723
|
if (selected.credentialId === null) {
|
|
14117
14724
|
if (leaseRotationEnabled && existingCredentialId !== null) {
|
|
14118
|
-
await tx.execute(
|
|
14725
|
+
await tx.execute(sql8`
|
|
14119
14726
|
delete from codex_credential_leases
|
|
14120
14727
|
where workspace_id = ${input.workspaceId} and turn_id = ${input.turnId}
|
|
14121
14728
|
`);
|
|
@@ -14145,7 +14752,7 @@ async function acquireCodexCredentialLease(db, input, select) {
|
|
|
14145
14752
|
const advanceActivePointer = input.advanceActivePointer && selected.advanceActivePointer !== false;
|
|
14146
14753
|
if (!leaseRotationEnabled) {
|
|
14147
14754
|
if (advanceActivePointer && activeCredentialId !== selected.credentialId) {
|
|
14148
|
-
await tx.execute(
|
|
14755
|
+
await tx.execute(sql8`
|
|
14149
14756
|
update codex_rotation_settings
|
|
14150
14757
|
set active_credential_id = ${selected.credentialId}, updated_at = now()
|
|
14151
14758
|
where account_id = ${input.accountId} and workspace_id = ${input.workspaceId}
|
|
@@ -14168,7 +14775,7 @@ async function acquireCodexCredentialLease(db, input, select) {
|
|
|
14168
14775
|
}
|
|
14169
14776
|
const reused = existingCredentialId === selected.credentialId;
|
|
14170
14777
|
const leaseRows = await tx.execute(
|
|
14171
|
-
|
|
14778
|
+
sql8`
|
|
14172
14779
|
insert into codex_credential_leases
|
|
14173
14780
|
(account_id, workspace_id, credential_id, turn_id, holder_id, generation, leased_until)
|
|
14174
14781
|
values
|
|
@@ -14191,7 +14798,7 @@ async function acquireCodexCredentialLease(db, input, select) {
|
|
|
14191
14798
|
throw new Error("Codex credential lease insert returned no expiry");
|
|
14192
14799
|
}
|
|
14193
14800
|
if (!reused) {
|
|
14194
|
-
await tx.execute(
|
|
14801
|
+
await tx.execute(sql8`
|
|
14195
14802
|
update codex_subscription_credentials
|
|
14196
14803
|
set selection_count = selection_count + 1,
|
|
14197
14804
|
last_selected_at = now()
|
|
@@ -14201,7 +14808,7 @@ async function acquireCodexCredentialLease(db, input, select) {
|
|
|
14201
14808
|
`);
|
|
14202
14809
|
}
|
|
14203
14810
|
if (advanceActivePointer && activeCredentialId !== selected.credentialId) {
|
|
14204
|
-
await tx.execute(
|
|
14811
|
+
await tx.execute(sql8`
|
|
14205
14812
|
update codex_rotation_settings
|
|
14206
14813
|
set active_credential_id = ${selected.credentialId}, updated_at = now()
|
|
14207
14814
|
where account_id = ${input.accountId} and workspace_id = ${input.workspaceId}
|
|
@@ -14261,7 +14868,7 @@ function codexCapacityPolicyHashFromTurnMetadata(metadata) {
|
|
|
14261
14868
|
return typeof value === "string" && value.length > 0 ? value : null;
|
|
14262
14869
|
}
|
|
14263
14870
|
async function lockExistingCodexRotationSettingsForCapacity(tx, workspaceId) {
|
|
14264
|
-
const rows = await tx.execute(
|
|
14871
|
+
const rows = await tx.execute(sql8`
|
|
14265
14872
|
select account_id, active_credential_id, rotation_enabled,
|
|
14266
14873
|
lease_rotation_enabled, rotation_strategy
|
|
14267
14874
|
from codex_rotation_settings
|
|
@@ -14319,7 +14926,7 @@ async function armCodexCapacityWait(db, input) {
|
|
|
14319
14926
|
eq10(sessionGoals.sessionId, input.sessionId)
|
|
14320
14927
|
)
|
|
14321
14928
|
).for("update").limit(1) : [];
|
|
14322
|
-
const leaseRows = input.leaseFence ? await tx.execute(
|
|
14929
|
+
const leaseRows = input.leaseFence ? await tx.execute(sql8`
|
|
14323
14930
|
select holder_id, generation
|
|
14324
14931
|
from codex_credential_leases
|
|
14325
14932
|
where account_id = ${input.accountId}
|
|
@@ -14495,7 +15102,7 @@ async function armCodexCapacityWait(db, input) {
|
|
|
14495
15102
|
throw new Error("Codex capacity session changed during atomic arm");
|
|
14496
15103
|
}
|
|
14497
15104
|
if (input.leaseFence) {
|
|
14498
|
-
await tx.execute(
|
|
15105
|
+
await tx.execute(sql8`
|
|
14499
15106
|
delete from codex_credential_leases
|
|
14500
15107
|
where account_id = ${input.accountId}
|
|
14501
15108
|
and workspace_id = ${input.workspaceId}
|
|
@@ -14536,7 +15143,7 @@ async function withCodexCapacityMutation(db, input, mutate) {
|
|
|
14536
15143
|
return { result: mutation.result, wakeTargets: [] };
|
|
14537
15144
|
}
|
|
14538
15145
|
const rows = await tx.update(codexCapacityWaiters).set({
|
|
14539
|
-
wakeRevision:
|
|
15146
|
+
wakeRevision: sql8`${codexCapacityWaiters.wakeRevision} + 1`,
|
|
14540
15147
|
lastWakeReason: input.reason,
|
|
14541
15148
|
updatedAt: /* @__PURE__ */ new Date()
|
|
14542
15149
|
}).where(
|
|
@@ -14590,7 +15197,7 @@ async function listPendingCodexCapacityWakeTargets(db, workspaceId) {
|
|
|
14590
15197
|
and10(
|
|
14591
15198
|
eq10(codexCapacityWaiters.workspaceId, workspaceId),
|
|
14592
15199
|
eq10(codexCapacityWaiters.status, "waiting"),
|
|
14593
|
-
|
|
15200
|
+
sql8`${codexCapacityWaiters.wakeRevision} > ${codexCapacityWaiters.observedWakeRevision}`
|
|
14594
15201
|
)
|
|
14595
15202
|
);
|
|
14596
15203
|
return rows.map(({ waiter: row, workflowWakeRevision }) => ({
|
|
@@ -14948,7 +15555,7 @@ async function reconcileCodexCapacityWait(db, input, decide, policy) {
|
|
|
14948
15555
|
}
|
|
14949
15556
|
async function heartbeatCodexCredentialLeaseUntil(db, accountId, workspaceId, turnId, holderId, generation, leaseTtlMs = CODEX_CREDENTIAL_LEASE_TTL_MS) {
|
|
14950
15557
|
return await withRlsContext(db, { accountId, workspaceId }, async (scopedDb) => {
|
|
14951
|
-
const rows = await scopedDb.execute(
|
|
15558
|
+
const rows = await scopedDb.execute(sql8`
|
|
14952
15559
|
update codex_credential_leases
|
|
14953
15560
|
set leased_until = now() + (${leaseTtlMs} * interval '1 millisecond'),
|
|
14954
15561
|
updated_at = now()
|
|
@@ -14992,7 +15599,7 @@ async function quarantineCodexCredentialForLease(db, input) {
|
|
|
14992
15599
|
db,
|
|
14993
15600
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
14994
15601
|
async (scopedDb) => await scopedDb.transaction(async (tx) => {
|
|
14995
|
-
const leaseRows = await tx.execute(
|
|
15602
|
+
const leaseRows = await tx.execute(sql8`
|
|
14996
15603
|
select id from codex_credential_leases
|
|
14997
15604
|
where account_id = ${input.accountId}
|
|
14998
15605
|
and workspace_id = ${input.workspaceId}
|
|
@@ -15117,7 +15724,7 @@ async function updateCodexAllocatorEligibility(db, input) {
|
|
|
15117
15724
|
const changedAt = /* @__PURE__ */ new Date();
|
|
15118
15725
|
const [updated] = await tx.update(codexSubscriptionCredentials).set({
|
|
15119
15726
|
allocatorEnabled: input.enabled,
|
|
15120
|
-
allocatorVersion:
|
|
15727
|
+
allocatorVersion: sql8`${codexSubscriptionCredentials.allocatorVersion} + 1`,
|
|
15121
15728
|
allocatorUpdatedBySubjectId: input.subjectId,
|
|
15122
15729
|
allocatorUpdatedAt: changedAt
|
|
15123
15730
|
// Deliberately no credential version/updatedAt write.
|
|
@@ -15287,7 +15894,7 @@ async function adoptCodexResetRedemptionAttempt(db, input) {
|
|
|
15287
15894
|
if (attempt.status !== "provider_started" && attempt.status !== "completed") {
|
|
15288
15895
|
return { kind: "conflict" };
|
|
15289
15896
|
}
|
|
15290
|
-
const claim = await tx.execute(
|
|
15897
|
+
const claim = await tx.execute(sql8`
|
|
15291
15898
|
select claim_expires_at > now() as claim_live
|
|
15292
15899
|
from codex_reset_redemption_attempts
|
|
15293
15900
|
where workspace_id = ${input.workspaceId} and id = ${input.attemptId}
|
|
@@ -15297,7 +15904,7 @@ async function adoptCodexResetRedemptionAttempt(db, input) {
|
|
|
15297
15904
|
browserSessionHash: input.browserSessionHash,
|
|
15298
15905
|
claimHolderId: null,
|
|
15299
15906
|
claimExpiresAt: null,
|
|
15300
|
-
updatedAt:
|
|
15907
|
+
updatedAt: sql8`now()`
|
|
15301
15908
|
}).where(eq10(codexResetRedemptionAttempts.id, input.attemptId)).returning();
|
|
15302
15909
|
if (!adopted) throw new Error("Codex redemption adoption returned no row");
|
|
15303
15910
|
return {
|
|
@@ -15320,10 +15927,10 @@ async function claimCodexResetRedemption(db, input) {
|
|
|
15320
15927
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
15321
15928
|
async (scopedDb) => await scopedDb.transaction(async (tx) => {
|
|
15322
15929
|
await tx.execute(
|
|
15323
|
-
|
|
15930
|
+
sql8`select pg_advisory_xact_lock(hashtextextended(${`codex-reset-attempt:${input.id}`}, 0))`
|
|
15324
15931
|
);
|
|
15325
15932
|
await tx.execute(
|
|
15326
|
-
|
|
15933
|
+
sql8`select pg_advisory_xact_lock(hashtextextended(${`codex-reset-credit:${input.workspaceId}:${input.credentialId}:${input.creditId}`}, 0))`
|
|
15327
15934
|
);
|
|
15328
15935
|
const [credential] = await tx.select({
|
|
15329
15936
|
connectedBySubjectId: codexSubscriptionCredentials.connectedBySubjectId,
|
|
@@ -15355,7 +15962,7 @@ async function claimCodexResetRedemption(db, input) {
|
|
|
15355
15962
|
if (credential.status !== "active") {
|
|
15356
15963
|
return { kind: "forbidden" };
|
|
15357
15964
|
}
|
|
15358
|
-
const claimState = await tx.execute(
|
|
15965
|
+
const claimState = await tx.execute(sql8`
|
|
15359
15966
|
select claim_expires_at > now() as claim_live
|
|
15360
15967
|
from codex_reset_redemption_attempts
|
|
15361
15968
|
where workspace_id = ${input.workspaceId} and id = ${input.id}
|
|
@@ -15365,10 +15972,10 @@ async function claimCodexResetRedemption(db, input) {
|
|
|
15365
15972
|
}
|
|
15366
15973
|
const [reclaimed] = await tx.update(codexResetRedemptionAttempts).set({
|
|
15367
15974
|
claimHolderId: input.claimHolderId,
|
|
15368
|
-
claimExpiresAt:
|
|
15975
|
+
claimExpiresAt: sql8`now() + (${claimTtlMs} * interval '1 millisecond')`,
|
|
15369
15976
|
confirmationExpiresAt: input.confirmationExpiresAt,
|
|
15370
15977
|
lastFailureKind: null,
|
|
15371
|
-
retryCount:
|
|
15978
|
+
retryCount: sql8`${codexResetRedemptionAttempts.retryCount} + 1`,
|
|
15372
15979
|
updatedAt: now
|
|
15373
15980
|
}).where(eq10(codexResetRedemptionAttempts.id, input.id)).returning();
|
|
15374
15981
|
if (!reclaimed) throw new Error("Codex redemption reclaim returned no row");
|
|
@@ -15380,7 +15987,7 @@ async function claimCodexResetRedemption(db, input) {
|
|
|
15380
15987
|
if (credential.status !== "active" || credential.connectedBySubjectId !== input.subjectId) {
|
|
15381
15988
|
return { kind: "forbidden" };
|
|
15382
15989
|
}
|
|
15383
|
-
const [creditAttempt] = await tx.execute(
|
|
15990
|
+
const [creditAttempt] = await tx.execute(sql8`
|
|
15384
15991
|
select id, status, claim_expires_at > now() as claim_live
|
|
15385
15992
|
from codex_reset_redemption_attempts
|
|
15386
15993
|
where workspace_id = ${input.workspaceId}
|
|
@@ -15399,7 +16006,7 @@ async function claimCodexResetRedemption(db, input) {
|
|
|
15399
16006
|
eq10(codexResetRedemptionAttempts.workspaceId, input.workspaceId),
|
|
15400
16007
|
eq10(codexResetRedemptionAttempts.id, creditAttempt.id),
|
|
15401
16008
|
eq10(codexResetRedemptionAttempts.status, "processing"),
|
|
15402
|
-
|
|
16009
|
+
sql8`(${codexResetRedemptionAttempts.claimExpiresAt} is null or ${codexResetRedemptionAttempts.claimExpiresAt} <= now())`
|
|
15403
16010
|
)
|
|
15404
16011
|
).returning({ id: codexResetRedemptionAttempts.id });
|
|
15405
16012
|
if (removed.length !== 1) return { kind: "conflict" };
|
|
@@ -15414,7 +16021,7 @@ async function claimCodexResetRedemption(db, input) {
|
|
|
15414
16021
|
creditId: input.creditId,
|
|
15415
16022
|
status: "processing",
|
|
15416
16023
|
claimHolderId: input.claimHolderId,
|
|
15417
|
-
claimExpiresAt:
|
|
16024
|
+
claimExpiresAt: sql8`now() + (${claimTtlMs} * interval '1 millisecond')`,
|
|
15418
16025
|
confirmationExpiresAt: input.confirmationExpiresAt
|
|
15419
16026
|
}).returning();
|
|
15420
16027
|
if (!created) throw new Error("Codex redemption claim returned no row");
|
|
@@ -15458,7 +16065,7 @@ async function fenceCodexResetRedemptionSend(db, input) {
|
|
|
15458
16065
|
if (attempt.status === "completed") {
|
|
15459
16066
|
return { kind: "not_ready", reason: "already_completed" };
|
|
15460
16067
|
}
|
|
15461
|
-
const [liveness] = await tx.execute(
|
|
16068
|
+
const [liveness] = await tx.execute(sql8`
|
|
15462
16069
|
select claim_expires_at > now() as claim_live,
|
|
15463
16070
|
confirmation_expires_at > now() as confirmation_live
|
|
15464
16071
|
from codex_reset_redemption_attempts
|
|
@@ -15472,10 +16079,10 @@ async function fenceCodexResetRedemptionSend(db, input) {
|
|
|
15472
16079
|
} else {
|
|
15473
16080
|
const [ready] = await tx.update(codexResetRedemptionAttempts).set({
|
|
15474
16081
|
status: "provider_started",
|
|
15475
|
-
providerStartedAt:
|
|
15476
|
-
claimExpiresAt:
|
|
16082
|
+
providerStartedAt: sql8`coalesce(${codexResetRedemptionAttempts.providerStartedAt}, now())`,
|
|
16083
|
+
claimExpiresAt: sql8`now() + (${sendLeaseMs} * interval '1 millisecond')`,
|
|
15477
16084
|
lastFailureKind: null,
|
|
15478
|
-
updatedAt:
|
|
16085
|
+
updatedAt: sql8`now()`
|
|
15479
16086
|
}).where(eq10(codexResetRedemptionAttempts.id, input.attemptId)).returning();
|
|
15480
16087
|
if (!ready) throw new Error("Codex redemption send fence returned no row");
|
|
15481
16088
|
return {
|
|
@@ -15490,7 +16097,7 @@ async function fenceCodexResetRedemptionSend(db, input) {
|
|
|
15490
16097
|
claimHolderId: null,
|
|
15491
16098
|
claimExpiresAt: null,
|
|
15492
16099
|
lastFailureKind: `send_fence_${reason}`,
|
|
15493
|
-
updatedAt:
|
|
16100
|
+
updatedAt: sql8`now()`
|
|
15494
16101
|
}).where(eq10(codexResetRedemptionAttempts.id, input.attemptId));
|
|
15495
16102
|
}
|
|
15496
16103
|
return { kind: "not_ready", reason };
|
|
@@ -15529,7 +16136,7 @@ async function releaseCodexResetRedemptionClaim(db, input) {
|
|
|
15529
16136
|
eq10(codexResetRedemptionAttempts.workspaceId, input.workspaceId),
|
|
15530
16137
|
eq10(codexResetRedemptionAttempts.id, input.attemptId),
|
|
15531
16138
|
eq10(codexResetRedemptionAttempts.claimHolderId, input.claimHolderId),
|
|
15532
|
-
|
|
16139
|
+
sql8`${codexResetRedemptionAttempts.status} <> 'completed'`
|
|
15533
16140
|
)
|
|
15534
16141
|
).returning({ id: codexResetRedemptionAttempts.id });
|
|
15535
16142
|
return rows.length === 1;
|
|
@@ -15545,7 +16152,7 @@ async function completeCodexResetRedemption(db, input) {
|
|
|
15545
16152
|
{ workspaceId: input.workspaceId, reason: "codex_reset_credit_redeemed" },
|
|
15546
16153
|
async (tx) => {
|
|
15547
16154
|
await tx.execute(
|
|
15548
|
-
|
|
16155
|
+
sql8`select pg_advisory_xact_lock(hashtextextended(${`codex-reset-attempt:${input.attemptId}`}, 0))`
|
|
15549
16156
|
);
|
|
15550
16157
|
const [current] = await tx.select().from(codexResetRedemptionAttempts).where(
|
|
15551
16158
|
and10(
|
|
@@ -15701,7 +16308,7 @@ async function ensureCodexRotationSettings(db, accountId, workspaceId) {
|
|
|
15701
16308
|
}
|
|
15702
16309
|
async function setActiveCodexCredential(db, workspaceId, credentialId) {
|
|
15703
16310
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
15704
|
-
await scopedDb.execute(
|
|
16311
|
+
await scopedDb.execute(sql8`
|
|
15705
16312
|
select id from codex_rotation_settings
|
|
15706
16313
|
where workspace_id = ${workspaceId}
|
|
15707
16314
|
for update
|
|
@@ -15721,7 +16328,7 @@ async function setActiveCodexCredential(db, workspaceId, credentialId) {
|
|
|
15721
16328
|
}
|
|
15722
16329
|
async function setInitialActiveCodexCredential(db, workspaceId, credentialId) {
|
|
15723
16330
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
15724
|
-
await scopedDb.execute(
|
|
16331
|
+
await scopedDb.execute(sql8`
|
|
15725
16332
|
select id from codex_rotation_settings
|
|
15726
16333
|
where workspace_id = ${workspaceId}
|
|
15727
16334
|
for update
|
|
@@ -15777,13 +16384,13 @@ async function countConsecutiveReactiveRotations(db, workspaceId, sessionId) {
|
|
|
15777
16384
|
eq10(sessionEvents.workspaceId, workspaceId),
|
|
15778
16385
|
eq10(sessionEvents.sessionId, sessionId),
|
|
15779
16386
|
eq10(sessionEvents.type, "turn.failed"),
|
|
15780
|
-
|
|
16387
|
+
sql8`${sessionEvents.payload} ->> 'rotated' = 'true'`
|
|
15781
16388
|
];
|
|
15782
16389
|
if (lastOk) {
|
|
15783
|
-
conditions.push(
|
|
16390
|
+
conditions.push(sql8`${sessionEvents.sequence} > ${lastOk.sequence}`);
|
|
15784
16391
|
}
|
|
15785
16392
|
const [{ rotated } = { rotated: 0 }] = await scopedDb.select({
|
|
15786
|
-
rotated:
|
|
16393
|
+
rotated: sql8`count(*)::int`
|
|
15787
16394
|
}).from(sessionEvents).where(and10(...conditions));
|
|
15788
16395
|
return Number(rotated);
|
|
15789
16396
|
});
|
|
@@ -15905,7 +16512,7 @@ async function recordSessionActiveCodexCredential(db, workspaceId, sessionId, cr
|
|
|
15905
16512
|
}
|
|
15906
16513
|
async function disconnectCodexAccount(db, workspaceId, credentialId) {
|
|
15907
16514
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
15908
|
-
await scopedDb.execute(
|
|
16515
|
+
await scopedDb.execute(sql8`
|
|
15909
16516
|
select id from codex_rotation_settings
|
|
15910
16517
|
where workspace_id = ${workspaceId}
|
|
15911
16518
|
for update
|
|
@@ -16144,7 +16751,7 @@ async function updateSessionMcpServerCredentialsInTransaction(tx, input) {
|
|
|
16144
16751
|
for (const update of input.updates) {
|
|
16145
16752
|
const [row] = await tx.update(sessionMcpServers).set({
|
|
16146
16753
|
headersEncrypted: update.headersEncrypted,
|
|
16147
|
-
credentialVersion:
|
|
16754
|
+
credentialVersion: sql8`${sessionMcpServers.credentialVersion} + 1`,
|
|
16148
16755
|
updatedAt: /* @__PURE__ */ new Date()
|
|
16149
16756
|
}).where(
|
|
16150
16757
|
and10(
|
|
@@ -16320,7 +16927,7 @@ async function lockWorkspaceForSessionCreate(tx, workspaceId, accountId) {
|
|
|
16320
16927
|
if (workspace.accountId !== accountId) {
|
|
16321
16928
|
throw new Error(`Workspace ${workspaceId} does not belong to account ${accountId}`);
|
|
16322
16929
|
}
|
|
16323
|
-
const [deploymentPolicy] = await tx.execute(
|
|
16930
|
+
const [deploymentPolicy] = await tx.execute(sql8`
|
|
16324
16931
|
select
|
|
16325
16932
|
max_nested_agent_depth as "maxNestedAgentDepth",
|
|
16326
16933
|
policy_source as "policySource"
|
|
@@ -16433,7 +17040,7 @@ async function existingSessionForCreateKey(tx, workspaceId, createIdempotencyKey
|
|
|
16433
17040
|
}
|
|
16434
17041
|
async function lockSessionCreateIdempotencyKey(tx, workspaceId, createIdempotencyKey) {
|
|
16435
17042
|
await tx.execute(
|
|
16436
|
-
|
|
17043
|
+
sql8`select pg_advisory_xact_lock(hashtext(${`session-create:${workspaceId}:${createIdempotencyKey}`}))`
|
|
16437
17044
|
);
|
|
16438
17045
|
}
|
|
16439
17046
|
async function existingSpawnDenialForKey(tx, workspaceId, createIdempotencyKey) {
|
|
@@ -16463,7 +17070,7 @@ async function recordSessionSpawnDenial(tx, input, decision) {
|
|
|
16463
17070
|
idempotencyKey: input.createIdempotencyKey ?? null
|
|
16464
17071
|
}).onConflictDoNothing({
|
|
16465
17072
|
target: [sessionSpawnDenials.workspaceId, sessionSpawnDenials.idempotencyKey],
|
|
16466
|
-
where:
|
|
17073
|
+
where: sql8`${sessionSpawnDenials.idempotencyKey} is not null`
|
|
16467
17074
|
}).returning();
|
|
16468
17075
|
if (inserted) return mapSessionSpawnDenial(inserted);
|
|
16469
17076
|
const key = input.createIdempotencyKey;
|
|
@@ -16780,12 +17387,12 @@ function sessionPersonalStateLockKey(workspaceId, subjectId) {
|
|
|
16780
17387
|
}
|
|
16781
17388
|
async function lockSessionPersonalStateShared(db, workspaceId, subjectId) {
|
|
16782
17389
|
await db.execute(
|
|
16783
|
-
|
|
17390
|
+
sql8`select pg_advisory_xact_lock_shared(hashtextextended(${sessionPersonalStateLockKey(workspaceId, subjectId)}, 0))`
|
|
16784
17391
|
);
|
|
16785
17392
|
}
|
|
16786
17393
|
async function lockSessionPersonalStateExclusive(db, workspaceId, subjectId) {
|
|
16787
17394
|
await db.execute(
|
|
16788
|
-
|
|
17395
|
+
sql8`select pg_advisory_xact_lock(hashtextextended(${sessionPersonalStateLockKey(workspaceId, subjectId)}, 0))`
|
|
16789
17396
|
);
|
|
16790
17397
|
}
|
|
16791
17398
|
function mapSessionPin(row) {
|
|
@@ -16871,7 +17478,7 @@ async function sessionTreeStatsForSessions(db, workspaceId, rootIds) {
|
|
|
16871
17478
|
}
|
|
16872
17479
|
const rows = await rawRows(
|
|
16873
17480
|
db,
|
|
16874
|
-
|
|
17481
|
+
sql8`
|
|
16875
17482
|
select
|
|
16876
17483
|
root.id as "rootId",
|
|
16877
17484
|
stats."directChildren",
|
|
@@ -16965,7 +17572,7 @@ async function sessionTreeStatsForSessions(db, workspaceId, rootIds) {
|
|
|
16965
17572
|
from numbered
|
|
16966
17573
|
) stats
|
|
16967
17574
|
where root.workspace_id = ${workspaceId}
|
|
16968
|
-
and ${inArray5(
|
|
17575
|
+
and ${inArray5(sql8`root.id`, uniqueRootIds)}
|
|
16969
17576
|
`
|
|
16970
17577
|
);
|
|
16971
17578
|
return new Map(
|
|
@@ -16986,7 +17593,7 @@ async function sessionTreeStatsForSessions(db, workspaceId, rootIds) {
|
|
|
16986
17593
|
}
|
|
16987
17594
|
function sessionFilters(options) {
|
|
16988
17595
|
const filters = [
|
|
16989
|
-
|
|
17596
|
+
sql8`not exists (
|
|
16990
17597
|
select 1
|
|
16991
17598
|
from ${slackInteractions} private_slack_interaction
|
|
16992
17599
|
where private_slack_interaction.workspace_id = ${sessions.workspaceId}
|
|
@@ -17016,7 +17623,7 @@ function sessionFilters(options) {
|
|
|
17016
17623
|
return filters;
|
|
17017
17624
|
}
|
|
17018
17625
|
function sessionAuthorizationScopeFilter(scope) {
|
|
17019
|
-
if (scope.kind === "all") return
|
|
17626
|
+
if (scope.kind === "all") return sql8`true`;
|
|
17020
17627
|
if (scope.rootSessionIds.length > SESSION_AUTHORIZATION_LIST_SCOPE_MAX_IDS || scope.sessionIds.length > SESSION_AUTHORIZATION_LIST_SCOPE_MAX_IDS) {
|
|
17021
17628
|
throw new RangeError(
|
|
17022
17629
|
`Session authorization scope exceeds ${SESSION_AUTHORIZATION_LIST_SCOPE_MAX_IDS} ids per field`
|
|
@@ -17024,14 +17631,14 @@ function sessionAuthorizationScopeFilter(scope) {
|
|
|
17024
17631
|
}
|
|
17025
17632
|
const rootIds = [...new Set(scope.rootSessionIds)];
|
|
17026
17633
|
const sessionIds = [...new Set(scope.sessionIds)];
|
|
17027
|
-
if (rootIds.length === 0 && sessionIds.length === 0) return
|
|
17028
|
-
const exact = sessionIds.length > 0 ? inArray5(sessions.id, sessionIds) :
|
|
17029
|
-
const descendants = rootIds.length > 0 ?
|
|
17634
|
+
if (rootIds.length === 0 && sessionIds.length === 0) return sql8`false`;
|
|
17635
|
+
const exact = sessionIds.length > 0 ? inArray5(sessions.id, sessionIds) : sql8`false`;
|
|
17636
|
+
const descendants = rootIds.length > 0 ? sql8`${sessions.id} in (
|
|
17030
17637
|
with recursive authorized_sessions(id) as (
|
|
17031
17638
|
select root.id
|
|
17032
17639
|
from ${sessions} root
|
|
17033
17640
|
where root.workspace_id = ${sessions.workspaceId}
|
|
17034
|
-
and ${inArray5(
|
|
17641
|
+
and ${inArray5(sql8`root.id`, rootIds)}
|
|
17035
17642
|
|
|
17036
17643
|
union
|
|
17037
17644
|
|
|
@@ -17042,7 +17649,7 @@ function sessionAuthorizationScopeFilter(scope) {
|
|
|
17042
17649
|
and child.parent_session_id = parent.id
|
|
17043
17650
|
)
|
|
17044
17651
|
select id from authorized_sessions
|
|
17045
|
-
)` :
|
|
17652
|
+
)` : sql8`false`;
|
|
17046
17653
|
return or3(exact, descendants);
|
|
17047
17654
|
}
|
|
17048
17655
|
async function sessionIdsCoveredByAuthorizationRoots(db, workspaceId, sessionIds, scope) {
|
|
@@ -17067,7 +17674,7 @@ var SESSION_LIST_SNAPSHOT_REUSE_MS = 5e3;
|
|
|
17067
17674
|
var SESSION_LIST_SNAPSHOT_MAX_IDS = 5e3;
|
|
17068
17675
|
var SESSION_LIST_SNAPSHOT_MAX_ACTIVE_PER_SUBJECT = 32;
|
|
17069
17676
|
var SESSION_LIST_SERIALIZATION_MAX_ATTEMPTS = 3;
|
|
17070
|
-
var
|
|
17677
|
+
var UUID_PATTERN2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
17071
17678
|
function sessionParentFilter(parentSessionId) {
|
|
17072
17679
|
return parentSessionId === void 0 ? "all" : parentSessionId === null ? "null" : parentSessionId;
|
|
17073
17680
|
}
|
|
@@ -17080,7 +17687,7 @@ function sessionListSnapshotLockKey(workspaceId, subjectId) {
|
|
|
17080
17687
|
}
|
|
17081
17688
|
async function lockSessionListSnapshotCreation(db, workspaceId, subjectId) {
|
|
17082
17689
|
await db.execute(
|
|
17083
|
-
|
|
17690
|
+
sql8`select pg_advisory_xact_lock(hashtextextended(${sessionListSnapshotLockKey(workspaceId, subjectId)}, 0))`
|
|
17084
17691
|
);
|
|
17085
17692
|
}
|
|
17086
17693
|
function encodeSessionListCursor(cursor) {
|
|
@@ -17099,7 +17706,7 @@ function decodeSessionListCursor(value) {
|
|
|
17099
17706
|
const parentSessionFilter = parsed.parentSessionFilter;
|
|
17100
17707
|
const search = parsed.search;
|
|
17101
17708
|
const offset = parsed.offset;
|
|
17102
|
-
if (typeof parsed.snapshotId !== "string" || !
|
|
17709
|
+
if (typeof parsed.snapshotId !== "string" || !UUID_PATTERN2.test(parsed.snapshotId) || typeof offset !== "number" || !Number.isSafeInteger(offset) || offset < 0 || parentSessionFilter !== "all" && parentSessionFilter !== "null" && (typeof parentSessionFilter !== "string" || !UUID_PATTERN2.test(parentSessionFilter)) || search !== null && (typeof search !== "string" || search.length > 200)) {
|
|
17103
17710
|
return null;
|
|
17104
17711
|
}
|
|
17105
17712
|
return {
|
|
@@ -17115,7 +17722,7 @@ function decodeSessionListCursor(value) {
|
|
|
17115
17722
|
async function reapExpiredSessionListSnapshots(db, limit = 500) {
|
|
17116
17723
|
const rows = await rawRows(
|
|
17117
17724
|
db,
|
|
17118
|
-
|
|
17725
|
+
sql8`select opengeni_private.reap_expired_session_list_snapshots(${limit}) as deleted_count`
|
|
17119
17726
|
);
|
|
17120
17727
|
return Number(rows[0]?.deleted_count ?? 0);
|
|
17121
17728
|
}
|
|
@@ -17280,7 +17887,7 @@ async function listSessionsForSubject(db, workspaceId, options) {
|
|
|
17280
17887
|
if (ordinaryIds.length > limit) {
|
|
17281
17888
|
let snapshot = reusableSnapshot;
|
|
17282
17889
|
if (!snapshot) {
|
|
17283
|
-
await tx.execute(
|
|
17890
|
+
await tx.execute(sql8`
|
|
17284
17891
|
delete from ${sessionListSnapshots} snapshot
|
|
17285
17892
|
where snapshot.workspace_id = ${workspaceId}
|
|
17286
17893
|
and snapshot.subject_id = ${options.subjectId}
|
|
@@ -17412,7 +18019,7 @@ async function getSessionForSubject(db, workspaceId, sessionId, subjectId, relat
|
|
|
17412
18019
|
and10(
|
|
17413
18020
|
eq10(sessions.workspaceId, workspaceId),
|
|
17414
18021
|
eq10(sessions.id, sessionId),
|
|
17415
|
-
|
|
18022
|
+
sql8`not exists (
|
|
17416
18023
|
select 1
|
|
17417
18024
|
from ${slackInteractions} private_slack_interaction
|
|
17418
18025
|
where private_slack_interaction.workspace_id = ${sessions.workspaceId}
|
|
@@ -17500,7 +18107,7 @@ async function setSessionPin(db, input) {
|
|
|
17500
18107
|
const [updated] = await tx.update(sessionPins).set({
|
|
17501
18108
|
pinned: input.pinned,
|
|
17502
18109
|
pinnedAt: input.pinned ? /* @__PURE__ */ new Date() : null,
|
|
17503
|
-
version:
|
|
18110
|
+
version: sql8`${sessionPins.version} + 1`
|
|
17504
18111
|
}).where(
|
|
17505
18112
|
and10(
|
|
17506
18113
|
eq10(sessionPins.workspaceId, input.workspaceId),
|
|
@@ -17582,7 +18189,7 @@ function normalizeSessionActivityRevision(value, label) {
|
|
|
17582
18189
|
return revision.toString();
|
|
17583
18190
|
}
|
|
17584
18191
|
async function lockWorkspaceSessionActivityRevision(db, workspaceId) {
|
|
17585
|
-
await db.execute(
|
|
18192
|
+
await db.execute(sql8`
|
|
17586
18193
|
insert into ${workspaceSessionActivityRevisions} (
|
|
17587
18194
|
workspace_id, account_id, revision
|
|
17588
18195
|
)
|
|
@@ -17591,7 +18198,7 @@ async function lockWorkspaceSessionActivityRevision(db, workspaceId) {
|
|
|
17591
18198
|
where ${workspaces.id} = ${workspaceId}
|
|
17592
18199
|
on conflict (workspace_id) do nothing
|
|
17593
18200
|
`);
|
|
17594
|
-
const rows = await db.execute(
|
|
18201
|
+
const rows = await db.execute(sql8`
|
|
17595
18202
|
select revision::text as revision
|
|
17596
18203
|
from ${workspaceSessionActivityRevisions}
|
|
17597
18204
|
where workspace_id = ${workspaceId}
|
|
@@ -17620,7 +18227,7 @@ async function listSessionDiscoverySummaries(db, workspaceId, options) {
|
|
|
17620
18227
|
}
|
|
17621
18228
|
const snapshotAt = options.cursor?.snapshotAt ?? (await rawRows(
|
|
17622
18229
|
scopedDb,
|
|
17623
|
-
|
|
18230
|
+
sql8`select to_char(statement_timestamp() at time zone 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.US"Z"') as value`
|
|
17624
18231
|
))[0].value;
|
|
17625
18232
|
const needsUpdatedSnapshot = orderBy === "updatedAt" && options.cursor?.snapshotRevision === void 0;
|
|
17626
18233
|
if (needsUpdatedSnapshot) {
|
|
@@ -17635,13 +18242,13 @@ async function listSessionDiscoverySummaries(db, workspaceId, options) {
|
|
|
17635
18242
|
throw new Error("sessions_list created-order cursor cannot carry activity revisions");
|
|
17636
18243
|
}
|
|
17637
18244
|
const cursorPredicate = options.cursor ? orderBy === "updatedAt" ? or3(
|
|
17638
|
-
|
|
18245
|
+
sql8`${sessions.activityRevision} < ${cursorSortRevision}::text::bigint`,
|
|
17639
18246
|
and10(
|
|
17640
|
-
|
|
18247
|
+
sql8`${sessions.activityRevision} = ${cursorSortRevision}::text::bigint`,
|
|
17641
18248
|
or3(
|
|
17642
|
-
|
|
18249
|
+
sql8`${sessions.updatedAt} < ${options.cursor.sortAt}::text::timestamptz`,
|
|
17643
18250
|
and10(
|
|
17644
|
-
|
|
18251
|
+
sql8`${sessions.updatedAt} = ${options.cursor.sortAt}::text::timestamptz`,
|
|
17645
18252
|
lt4(sessions.id, options.cursor.id)
|
|
17646
18253
|
)
|
|
17647
18254
|
)
|
|
@@ -17650,9 +18257,9 @@ async function listSessionDiscoverySummaries(db, workspaceId, options) {
|
|
|
17650
18257
|
// Cast through text deliberately. postgres.js otherwise infers a
|
|
17651
18258
|
// timestamptz parameter and serializes this exact cursor string via
|
|
17652
18259
|
// JS Date, which discards PostgreSQL's sub-millisecond precision.
|
|
17653
|
-
|
|
18260
|
+
sql8`${sessions.createdAt} < ${options.cursor.sortAt}::text::timestamptz`,
|
|
17654
18261
|
and10(
|
|
17655
|
-
|
|
18262
|
+
sql8`${sessions.createdAt} = ${options.cursor.sortAt}::text::timestamptz`,
|
|
17656
18263
|
lt4(sessions.id, options.cursor.id)
|
|
17657
18264
|
)
|
|
17658
18265
|
) : void 0;
|
|
@@ -17661,23 +18268,23 @@ async function listSessionDiscoverySummaries(db, workspaceId, options) {
|
|
|
17661
18268
|
snapshotFilters.push(sessionAuthorizationScopeFilter(options.authorizationScope));
|
|
17662
18269
|
}
|
|
17663
18270
|
snapshotFilters.push(
|
|
17664
|
-
orderBy === "updatedAt" ?
|
|
18271
|
+
orderBy === "updatedAt" ? sql8`${sessions.activityRevision} <= ${snapshotRevision}::text::bigint` : sql8`${sessions.createdAt} <= ${snapshotAt}::text::timestamptz`
|
|
17665
18272
|
);
|
|
17666
18273
|
if (updatedAfter !== null) {
|
|
17667
18274
|
snapshotFilters.push(
|
|
17668
|
-
|
|
18275
|
+
sql8`${sessions.activityRevision} > ${updatedAfter}::text::bigint`
|
|
17669
18276
|
);
|
|
17670
18277
|
}
|
|
17671
18278
|
const rows = await scopedDb.select({
|
|
17672
18279
|
id: sessions.id,
|
|
17673
|
-
title:
|
|
17674
|
-
titleOriginalChars:
|
|
18280
|
+
title: sql8`left(${sessions.title}, ${SESSION_DISCOVERY_CONTROL_TITLE_MAX_CHARS})`,
|
|
18281
|
+
titleOriginalChars: sql8`char_length(${sessions.title})::integer`,
|
|
17675
18282
|
parentSessionId: sessions.parentSessionId,
|
|
17676
18283
|
status: sessions.status,
|
|
17677
18284
|
createdAt: sessions.createdAt,
|
|
17678
18285
|
updatedAt: sessions.updatedAt,
|
|
17679
|
-
sortRevision: orderBy === "updatedAt" ?
|
|
17680
|
-
sortAt: orderBy === "updatedAt" ?
|
|
18286
|
+
sortRevision: orderBy === "updatedAt" ? sql8`${sessions.activityRevision}::text` : sql8`'0'`,
|
|
18287
|
+
sortAt: orderBy === "updatedAt" ? sql8`to_char(${sessions.updatedAt} at time zone 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.US"Z"')` : sql8`to_char(${sessions.createdAt} at time zone 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.US"Z"')`
|
|
17681
18288
|
}).from(sessions).where(and10(...snapshotFilters, cursorPredicate)).orderBy(
|
|
17682
18289
|
...orderBy === "updatedAt" ? [
|
|
17683
18290
|
desc5(sessions.activityRevision),
|
|
@@ -17688,7 +18295,7 @@ async function listSessionDiscoverySummaries(db, workspaceId, options) {
|
|
|
17688
18295
|
const hasMore = rows.length > limit;
|
|
17689
18296
|
const page = rows.slice(0, limit);
|
|
17690
18297
|
const ids = page.map((row) => row.id);
|
|
17691
|
-
const [{ total } = { total: 0 }] = await scopedDb.select({ total:
|
|
18298
|
+
const [{ total } = { total: 0 }] = await scopedDb.select({ total: sql8`count(*)::int` }).from(sessions).where(and10(...snapshotFilters));
|
|
17692
18299
|
if (ids.length === 0) {
|
|
17693
18300
|
return {
|
|
17694
18301
|
sessions: [],
|
|
@@ -17713,8 +18320,8 @@ async function listSessionDiscoverySummaries(db, workspaceId, options) {
|
|
|
17713
18320
|
const goals = await scopedDb.select({
|
|
17714
18321
|
sessionId: sessionGoals.sessionId,
|
|
17715
18322
|
status: sessionGoals.status,
|
|
17716
|
-
text:
|
|
17717
|
-
textOriginalChars:
|
|
18323
|
+
text: sql8`left(${sessionGoals.text}, ${SESSION_DISCOVERY_GOAL_MAX_CHARS})`,
|
|
18324
|
+
textOriginalChars: sql8`char_length(${sessionGoals.text})::integer`
|
|
17718
18325
|
}).from(sessionGoals).where(
|
|
17719
18326
|
and10(
|
|
17720
18327
|
eq10(sessionGoals.workspaceId, workspaceId),
|
|
@@ -17724,7 +18331,7 @@ async function listSessionDiscoverySummaries(db, workspaceId, options) {
|
|
|
17724
18331
|
const goalsBySession = new Map(goals.map((goal) => [goal.sessionId, goal]));
|
|
17725
18332
|
const queueCounts = await scopedDb.select({
|
|
17726
18333
|
sessionId: sessionTurns.sessionId,
|
|
17727
|
-
count:
|
|
18334
|
+
count: sql8`count(*)::int`
|
|
17728
18335
|
}).from(sessionTurns).where(
|
|
17729
18336
|
and10(
|
|
17730
18337
|
eq10(sessionTurns.workspaceId, workspaceId),
|
|
@@ -17742,12 +18349,12 @@ async function listSessionDiscoverySummaries(db, workspaceId, options) {
|
|
|
17742
18349
|
// Extract only the bounded textual preview in PostgreSQL. Selecting
|
|
17743
18350
|
// the JSON payload here would re-materialize the exact multi-MB
|
|
17744
18351
|
// event bodies this compact discovery path exists to avoid.
|
|
17745
|
-
preview:
|
|
18352
|
+
preview: sql8`left(coalesce(
|
|
17746
18353
|
${sessionEvents.payload}->>'text',
|
|
17747
18354
|
${sessionEvents.payload}->>'message',
|
|
17748
18355
|
${sessionEvents.payload}->>'content'
|
|
17749
18356
|
), ${SESSION_DISCOVERY_MESSAGE_MAX_CHARS})`,
|
|
17750
|
-
previewOriginalChars:
|
|
18357
|
+
previewOriginalChars: sql8`char_length(coalesce(
|
|
17751
18358
|
${sessionEvents.payload}->>'text',
|
|
17752
18359
|
${sessionEvents.payload}->>'message',
|
|
17753
18360
|
${sessionEvents.payload}->>'content'
|
|
@@ -17819,7 +18426,7 @@ async function listSessionDiscoverySummaries(db, workspaceId, options) {
|
|
|
17819
18426
|
}
|
|
17820
18427
|
async function getSessionRootId(db, workspaceId, sessionId) {
|
|
17821
18428
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
17822
|
-
const rows = await scopedDb.execute(
|
|
18429
|
+
const rows = await scopedDb.execute(sql8`
|
|
17823
18430
|
with recursive lineage(id, parent_session_id, depth, path, cycle) as (
|
|
17824
18431
|
select
|
|
17825
18432
|
${sessions.id},
|
|
@@ -17863,7 +18470,7 @@ async function getSessionRootId(db, workspaceId, sessionId) {
|
|
|
17863
18470
|
async function getSessionLineage(db, workspaceId, sessionId) {
|
|
17864
18471
|
const descendantLimit = 200;
|
|
17865
18472
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
17866
|
-
const rootRows = await scopedDb.execute(
|
|
18473
|
+
const rootRows = await scopedDb.execute(sql8`
|
|
17867
18474
|
select id from ${sessions}
|
|
17868
18475
|
where ${sessions.workspaceId} = ${workspaceId} and ${sessions.id} = ${sessionId}
|
|
17869
18476
|
limit 1
|
|
@@ -17871,7 +18478,7 @@ async function getSessionLineage(db, workspaceId, sessionId) {
|
|
|
17871
18478
|
if (rootRows.length === 0) {
|
|
17872
18479
|
return null;
|
|
17873
18480
|
}
|
|
17874
|
-
const ancestorLineageRows = await scopedDb.execute(
|
|
18481
|
+
const ancestorLineageRows = await scopedDb.execute(sql8`
|
|
17875
18482
|
with recursive ancestors(id, parent_session_id, depth, path, cycle) as (
|
|
17876
18483
|
select ${sessions.id}, ${sessions.parentSessionId}, 0, array[${sessions.id}], false
|
|
17877
18484
|
from ${sessions}
|
|
@@ -17899,7 +18506,7 @@ async function getSessionLineage(db, workspaceId, sessionId) {
|
|
|
17899
18506
|
throw new Error(`session lineage for ${sessionId} has no valid workspace root`);
|
|
17900
18507
|
}
|
|
17901
18508
|
const ancestorRows = ancestorLineageRows.filter((row) => row.depth > 0);
|
|
17902
|
-
const childRows = await scopedDb.execute(
|
|
18509
|
+
const childRows = await scopedDb.execute(sql8`
|
|
17903
18510
|
with recursive descendants(id, parent_session_id, depth, path) as (
|
|
17904
18511
|
select child.id, child.parent_session_id, 1, array[${sessionId}, child.id]
|
|
17905
18512
|
from ${sessions} child
|
|
@@ -17963,7 +18570,7 @@ async function getSessionLineage(db, workspaceId, sessionId) {
|
|
|
17963
18570
|
async function countActiveSessionsForWorkspace(db, workspaceId) {
|
|
17964
18571
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
17965
18572
|
const [{ count } = { count: 0 }] = await scopedDb.select({
|
|
17966
|
-
count:
|
|
18573
|
+
count: sql8`count(*)::int`
|
|
17967
18574
|
}).from(sessions).where(
|
|
17968
18575
|
and10(
|
|
17969
18576
|
eq10(sessions.workspaceId, workspaceId),
|
|
@@ -18092,48 +18699,48 @@ async function listSessionEventPage(db, workspaceId, sessionId, options = {}) {
|
|
|
18092
18699
|
});
|
|
18093
18700
|
}
|
|
18094
18701
|
function sessionEventProjectionSelect(payloadMode = "full") {
|
|
18095
|
-
const typeInvalid =
|
|
18702
|
+
const typeInvalid = sql8`(
|
|
18096
18703
|
octet_length(${sessionEvents.type}) > ${SESSION_EVENT_TYPE_MAX_BYTES}
|
|
18097
18704
|
or position(E'\\n' in ${sessionEvents.type}) > 0
|
|
18098
18705
|
or position(E'\\r' in ${sessionEvents.type}) > 0
|
|
18099
18706
|
)`;
|
|
18100
|
-
const clientEventIdInvalid =
|
|
18707
|
+
const clientEventIdInvalid = sql8`(
|
|
18101
18708
|
${sessionEvents.clientEventId} is not null
|
|
18102
18709
|
and octet_length(${sessionEvents.clientEventId})
|
|
18103
18710
|
> ${SESSION_EVENT_CLIENT_EVENT_ID_MAX_BYTES}
|
|
18104
18711
|
)`;
|
|
18105
|
-
const turnAssociationInvalid =
|
|
18712
|
+
const turnAssociationInvalid = sql8`(
|
|
18106
18713
|
${sessionEvents.turnAssociation} is not null
|
|
18107
18714
|
and ${sessionEvents.turnAssociation} not in (
|
|
18108
18715
|
'current', 'late_rejected', 'duplicate'
|
|
18109
18716
|
)
|
|
18110
18717
|
)`;
|
|
18111
|
-
const duplicateReasonInvalid =
|
|
18718
|
+
const duplicateReasonInvalid = sql8`(
|
|
18112
18719
|
${sessionEvents.duplicateReason} is not null
|
|
18113
18720
|
and octet_length(${sessionEvents.duplicateReason})
|
|
18114
18721
|
> ${SESSION_EVENT_DUPLICATE_REASON_MAX_BYTES}
|
|
18115
18722
|
)`;
|
|
18116
|
-
const envelopeInvalid =
|
|
18723
|
+
const envelopeInvalid = sql8`(
|
|
18117
18724
|
${typeInvalid} or ${clientEventIdInvalid}
|
|
18118
18725
|
or ${turnAssociationInvalid} or ${duplicateReasonInvalid}
|
|
18119
18726
|
)`;
|
|
18120
|
-
const projectedType =
|
|
18727
|
+
const projectedType = sql8`case
|
|
18121
18728
|
when ${typeInvalid} then 'session.event.envelope_omitted'
|
|
18122
18729
|
else ${sessionEvents.type}
|
|
18123
18730
|
end`;
|
|
18124
|
-
const projectedClientEventId =
|
|
18731
|
+
const projectedClientEventId = sql8`case
|
|
18125
18732
|
when ${clientEventIdInvalid} then left(${sessionEvents.clientEventId}, 256)
|
|
18126
18733
|
else ${sessionEvents.clientEventId}
|
|
18127
18734
|
end`;
|
|
18128
|
-
const projectedTurnAssociation =
|
|
18735
|
+
const projectedTurnAssociation = sql8`case
|
|
18129
18736
|
when ${turnAssociationInvalid} then null
|
|
18130
18737
|
else ${sessionEvents.turnAssociation}
|
|
18131
18738
|
end`;
|
|
18132
|
-
const projectedDuplicateReason =
|
|
18739
|
+
const projectedDuplicateReason = sql8`case
|
|
18133
18740
|
when ${duplicateReasonInvalid} then left(${sessionEvents.duplicateReason}, 1024)
|
|
18134
18741
|
else ${sessionEvents.duplicateReason}
|
|
18135
18742
|
end`;
|
|
18136
|
-
const projectedEnvelopeFields =
|
|
18743
|
+
const projectedEnvelopeFields = sql8`(
|
|
18137
18744
|
'[]'::jsonb
|
|
18138
18745
|
|| case when ${typeInvalid} then jsonb_build_array(jsonb_build_object(
|
|
18139
18746
|
'field', 'type',
|
|
@@ -18156,7 +18763,7 @@ function sessionEventProjectionSelect(payloadMode = "full") {
|
|
|
18156
18763
|
'deliveredBytes', octet_length(${projectedDuplicateReason})
|
|
18157
18764
|
)) else '[]'::jsonb end
|
|
18158
18765
|
)`;
|
|
18159
|
-
const projectedPayload =
|
|
18766
|
+
const projectedPayload = sql8`case
|
|
18160
18767
|
when ${envelopeInvalid} then jsonb_build_object(
|
|
18161
18768
|
'preview', '[legacy event envelope normalized at bounded database read boundary]',
|
|
18162
18769
|
'originalEventBytes', octet_length(row_to_json(${sessionEvents})::text),
|
|
@@ -18170,14 +18777,14 @@ function sessionEventProjectionSelect(payloadMode = "full") {
|
|
|
18170
18777
|
)
|
|
18171
18778
|
else opengeni_private.project_session_event_payload(${sessionEvents.payload})
|
|
18172
18779
|
end`;
|
|
18173
|
-
const projectedPayloadBytes =
|
|
18174
|
-
const selectedPayload = payloadMode === "none" ?
|
|
18780
|
+
const projectedPayloadBytes = sql8`octet_length((${projectedPayload})::text)`;
|
|
18781
|
+
const selectedPayload = payloadMode === "none" ? sql8`jsonb_build_object(
|
|
18175
18782
|
'_monitoring', jsonb_build_object(
|
|
18176
18783
|
'payloadMode', 'none',
|
|
18177
18784
|
'payloadOmitted', true,
|
|
18178
18785
|
'projectedPayloadBytes', ${projectedPayloadBytes}
|
|
18179
18786
|
)
|
|
18180
|
-
)` : payloadMode === "summary" ?
|
|
18787
|
+
)` : payloadMode === "summary" ? sql8`case
|
|
18181
18788
|
when ${projectedPayloadBytes} <= 4096 then ${projectedPayload}
|
|
18182
18789
|
else jsonb_build_object(
|
|
18183
18790
|
'_monitoring', jsonb_build_object(
|
|
@@ -18277,7 +18884,7 @@ async function reserveToolspaceCallForAttempt(db, input) {
|
|
|
18277
18884
|
return { reserved: false, reason: "budget_exhausted" };
|
|
18278
18885
|
}
|
|
18279
18886
|
const [row] = await tx.update(sessionTurns).set({
|
|
18280
|
-
toolspaceCallCount:
|
|
18887
|
+
toolspaceCallCount: sql8`${sessionTurns.toolspaceCallCount} + 1`
|
|
18281
18888
|
}).where(
|
|
18282
18889
|
and10(
|
|
18283
18890
|
eq10(sessionTurns.workspaceId, input.workspaceId),
|
|
@@ -18285,7 +18892,7 @@ async function reserveToolspaceCallForAttempt(db, input) {
|
|
|
18285
18892
|
eq10(sessionTurns.id, input.turnId),
|
|
18286
18893
|
eq10(sessionTurns.executionGeneration, input.executionGeneration),
|
|
18287
18894
|
eq10(sessionTurns.activeAttemptId, input.attemptId),
|
|
18288
|
-
|
|
18895
|
+
sql8`${sessionTurns.toolspaceCallCount} < ${input.limit}`
|
|
18289
18896
|
)
|
|
18290
18897
|
).returning({ count: sessionTurns.toolspaceCallCount });
|
|
18291
18898
|
if (!row) {
|
|
@@ -19058,7 +19665,7 @@ async function recordPendingSessionToolCallResult(db, input) {
|
|
|
19058
19665
|
}).where(
|
|
19059
19666
|
and10(
|
|
19060
19667
|
eq10(sessionPendingToolCalls.id, pending.id),
|
|
19061
|
-
|
|
19668
|
+
sql8`${sessionPendingToolCalls.resultItem} is null`
|
|
19062
19669
|
)
|
|
19063
19670
|
).returning({ id: sessionPendingToolCalls.id });
|
|
19064
19671
|
return {
|
|
@@ -19088,7 +19695,7 @@ async function clearDurablePendingSessionToolCalls(db, input) {
|
|
|
19088
19695
|
eq10(sessionPendingToolCalls.sessionId, input.sessionId),
|
|
19089
19696
|
eq10(sessionPendingToolCalls.turnId, input.turnId),
|
|
19090
19697
|
inArray5(sessionPendingToolCalls.callId, input.callIds),
|
|
19091
|
-
|
|
19698
|
+
sql8`${sessionPendingToolCalls.resultItem} is not null`
|
|
19092
19699
|
)
|
|
19093
19700
|
).for("update");
|
|
19094
19701
|
if (pending.length === 0) return { accepted: true, cleared: 0 };
|
|
@@ -19155,7 +19762,7 @@ async function getActiveSessionHistoryItems(db, workspaceId, sessionId) {
|
|
|
19155
19762
|
async function countActiveSessionHistoryItems(db, workspaceId, sessionId) {
|
|
19156
19763
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
19157
19764
|
const [row] = await scopedDb.select({
|
|
19158
|
-
count:
|
|
19765
|
+
count: sql8`count(*)`
|
|
19159
19766
|
}).from(sessionHistoryItems).where(
|
|
19160
19767
|
and10(
|
|
19161
19768
|
eq10(sessionHistoryItems.workspaceId, workspaceId),
|
|
@@ -19238,7 +19845,7 @@ async function applyContextCompaction(db, input) {
|
|
|
19238
19845
|
return { applied: false, reason: fence.reason };
|
|
19239
19846
|
}
|
|
19240
19847
|
const [{ maxPosition } = { maxPosition: -1 }] = await tx.select({
|
|
19241
|
-
maxPosition:
|
|
19848
|
+
maxPosition: sql8`coalesce(max(${sessionHistoryItems.position}), -1)`
|
|
19242
19849
|
}).from(sessionHistoryItems).where(
|
|
19243
19850
|
and10(
|
|
19244
19851
|
eq10(sessionHistoryItems.workspaceId, input.workspaceId),
|
|
@@ -19412,7 +20019,7 @@ async function recordSkippedContextCompaction(db, input) {
|
|
|
19412
20019
|
async function nextSessionHistoryPosition(db, workspaceId, sessionId) {
|
|
19413
20020
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
19414
20021
|
const [row] = await scopedDb.select({
|
|
19415
|
-
maxPosition:
|
|
20022
|
+
maxPosition: sql8`max(${sessionHistoryItems.position})`
|
|
19416
20023
|
}).from(sessionHistoryItems).where(
|
|
19417
20024
|
and10(
|
|
19418
20025
|
eq10(sessionHistoryItems.workspaceId, workspaceId),
|
|
@@ -19483,7 +20090,7 @@ async function clearSessionContext(db, input) {
|
|
|
19483
20090
|
)
|
|
19484
20091
|
).returning({ id: sessionHistoryItems.id });
|
|
19485
20092
|
const [{ maxPosition } = { maxPosition: -1 }] = await tx.select({
|
|
19486
|
-
maxPosition:
|
|
20093
|
+
maxPosition: sql8`coalesce(max(${sessionHistoryItems.position}), -1)`
|
|
19487
20094
|
}).from(sessionHistoryItems).where(
|
|
19488
20095
|
and10(
|
|
19489
20096
|
eq10(sessionHistoryItems.workspaceId, input.workspaceId),
|
|
@@ -19520,7 +20127,7 @@ async function clearSessionContext(db, input) {
|
|
|
19520
20127
|
async function countSessionHistoryItems(db, workspaceId, sessionId) {
|
|
19521
20128
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
19522
20129
|
const [row] = await scopedDb.select({
|
|
19523
|
-
count:
|
|
20130
|
+
count: sql8`count(*)`
|
|
19524
20131
|
}).from(sessionHistoryItems).where(
|
|
19525
20132
|
and10(
|
|
19526
20133
|
eq10(sessionHistoryItems.workspaceId, workspaceId),
|
|
@@ -19692,7 +20299,7 @@ async function abandonRecordingForTurnAttempt(db, input) {
|
|
|
19692
20299
|
eq10(sessionEvents.turnAttemptId, input.attemptId),
|
|
19693
20300
|
eq10(sessionEvents.turnAssociation, "current"),
|
|
19694
20301
|
eq10(sessionEvents.type, "recording.started"),
|
|
19695
|
-
eq10(
|
|
20302
|
+
eq10(sql8`${sessionEvents.payload} ->> 'recordingId'`, input.recordingId)
|
|
19696
20303
|
)
|
|
19697
20304
|
).limit(1);
|
|
19698
20305
|
if (!started) return false;
|
|
@@ -20079,20 +20686,20 @@ function archiveProjectionFromResumeState(resumeState) {
|
|
|
20079
20686
|
};
|
|
20080
20687
|
}
|
|
20081
20688
|
async function recomputeAndStampLease(tx, leaseId, leaseTtlMs, setLiveness) {
|
|
20082
|
-
const counts = await tx.execute(
|
|
20689
|
+
const counts = await tx.execute(sql8`
|
|
20083
20690
|
select count(*)::int as total,
|
|
20084
20691
|
count(*) filter (where kind = 'turn')::int as turns,
|
|
20085
20692
|
count(*) filter (where kind = 'viewer')::int as viewers
|
|
20086
20693
|
from sandbox_lease_holders where lease_id = ${leaseId}
|
|
20087
20694
|
`);
|
|
20088
20695
|
const c = counts[0];
|
|
20089
|
-
const updated = await tx.execute(
|
|
20696
|
+
const updated = await tx.execute(sql8`
|
|
20090
20697
|
update sandbox_leases set
|
|
20091
20698
|
refcount = ${c.total},
|
|
20092
20699
|
turn_holders = ${c.turns},
|
|
20093
20700
|
viewer_holders = ${c.viewers},
|
|
20094
20701
|
expires_at = now() + (${String(leaseTtlMs)} || ' milliseconds')::interval,
|
|
20095
|
-
${setLiveness ?
|
|
20702
|
+
${setLiveness ? sql8`liveness = ${setLiveness},` : sql8``}
|
|
20096
20703
|
updated_at = now()
|
|
20097
20704
|
where id = ${leaseId}
|
|
20098
20705
|
returning *
|
|
@@ -20100,7 +20707,7 @@ async function recomputeAndStampLease(tx, leaseId, leaseTtlMs, setLiveness) {
|
|
|
20100
20707
|
return updated[0];
|
|
20101
20708
|
}
|
|
20102
20709
|
async function upsertLeaseHolder(tx, leaseId, accountId, workspaceId, kind, holderId, subjectId) {
|
|
20103
|
-
await tx.execute(
|
|
20710
|
+
await tx.execute(sql8`
|
|
20104
20711
|
insert into sandbox_lease_holders
|
|
20105
20712
|
(account_id, workspace_id, lease_id, kind, holder_id, subject_id, last_heartbeat_at)
|
|
20106
20713
|
values (${accountId}, ${workspaceId}, ${leaseId}, ${kind}, ${holderId}, ${subjectId}, now())
|
|
@@ -20123,7 +20730,7 @@ async function acquireLeaseOnce(db, input) {
|
|
|
20123
20730
|
const tx = txRaw;
|
|
20124
20731
|
const image = input.image ?? null;
|
|
20125
20732
|
const rigVersionId = input.rigVersionId ?? null;
|
|
20126
|
-
await tx.execute(
|
|
20733
|
+
await tx.execute(sql8`
|
|
20127
20734
|
insert into sandbox_leases
|
|
20128
20735
|
(account_id, workspace_id, sandbox_group_id, liveness, backend, os, image, rig_version_id, expires_at)
|
|
20129
20736
|
values
|
|
@@ -20131,7 +20738,7 @@ async function acquireLeaseOnce(db, input) {
|
|
|
20131
20738
|
now() + (${String(input.leaseTtlMs)} || ' milliseconds')::interval)
|
|
20132
20739
|
on conflict (workspace_id, sandbox_group_id) do nothing
|
|
20133
20740
|
`);
|
|
20134
|
-
const rows = await tx.execute(
|
|
20741
|
+
const rows = await tx.execute(sql8`
|
|
20135
20742
|
select *, (liveness = 'draining' and expires_at <= now()) as draining_expired
|
|
20136
20743
|
from sandbox_leases
|
|
20137
20744
|
where workspace_id = ${workspaceId} and sandbox_group_id = ${sandboxGroupId}
|
|
@@ -20141,7 +20748,7 @@ async function acquireLeaseOnce(db, input) {
|
|
|
20141
20748
|
if (!row) throw new Error(`Lease row vanished post-insert: ${sandboxGroupId}`);
|
|
20142
20749
|
const liveness = row.liveness;
|
|
20143
20750
|
if (kind === "viewer" && Number(row.turn_holders) === 0) {
|
|
20144
|
-
const workspaceRows = await tx.execute(
|
|
20751
|
+
const workspaceRows = await tx.execute(sql8`
|
|
20145
20752
|
select sandbox_viewer_force_drain_reason
|
|
20146
20753
|
from workspaces
|
|
20147
20754
|
where id = ${workspaceId}
|
|
@@ -20163,7 +20770,7 @@ async function acquireLeaseOnce(db, input) {
|
|
|
20163
20770
|
const imageConflict = image !== null && row.image !== null && row.image !== image;
|
|
20164
20771
|
const rigConflict = rigVersionId !== null && row.rig_version_id !== null && row.rig_version_id !== rigVersionId;
|
|
20165
20772
|
if (liveness !== "cold" && (imageConflict || rigConflict)) {
|
|
20166
|
-
const others = await tx.execute(
|
|
20773
|
+
const others = await tx.execute(sql8`
|
|
20167
20774
|
select count(*)::int as n from sandbox_lease_holders
|
|
20168
20775
|
where lease_id = ${row.id} and not (kind = ${kind} and holder_id = ${holderId})
|
|
20169
20776
|
`);
|
|
@@ -20182,7 +20789,7 @@ async function acquireLeaseOnce(db, input) {
|
|
|
20182
20789
|
rigVersionId
|
|
20183
20790
|
);
|
|
20184
20791
|
}
|
|
20185
|
-
const rotating = await tx.execute(
|
|
20792
|
+
const rotating = await tx.execute(sql8`
|
|
20186
20793
|
update sandbox_leases set
|
|
20187
20794
|
rotation_requested_at = coalesce(rotation_requested_at, now()),
|
|
20188
20795
|
rotation_reason = coalesce(rotation_reason, 'operator'),
|
|
@@ -20210,11 +20817,11 @@ async function acquireLeaseOnce(db, input) {
|
|
|
20210
20817
|
lease: mapLeaseRow(row)
|
|
20211
20818
|
};
|
|
20212
20819
|
}
|
|
20213
|
-
const casRows = await tx.execute(
|
|
20820
|
+
const casRows = await tx.execute(sql8`
|
|
20214
20821
|
update sandbox_leases set
|
|
20215
20822
|
liveness = 'warming',
|
|
20216
|
-
${image !== null ?
|
|
20217
|
-
${rigVersionId !== null ?
|
|
20823
|
+
${image !== null ? sql8`image = ${image},` : sql8``}
|
|
20824
|
+
${rigVersionId !== null ? sql8`rig_version_id = ${rigVersionId},` : sql8``}
|
|
20218
20825
|
updated_at = now()
|
|
20219
20826
|
where id = ${row.id} and liveness = 'cold'
|
|
20220
20827
|
returning id
|
|
@@ -20278,7 +20885,7 @@ async function beginSandboxRematerialization(db, input) {
|
|
|
20278
20885
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
20279
20886
|
async (scopedDb) => await scopedDb.transaction(async (txRaw) => {
|
|
20280
20887
|
const tx = txRaw;
|
|
20281
|
-
const rows = await tx.execute(
|
|
20888
|
+
const rows = await tx.execute(sql8`
|
|
20282
20889
|
select * from sandbox_leases
|
|
20283
20890
|
where workspace_id = ${input.workspaceId}
|
|
20284
20891
|
and sandbox_group_id = ${input.sandboxGroupId}
|
|
@@ -20366,7 +20973,7 @@ async function beginSandboxRematerialization(db, input) {
|
|
|
20366
20973
|
}
|
|
20367
20974
|
};
|
|
20368
20975
|
const degradedResumeState = resumeStateWithRecovery(workingResumeState, degraded);
|
|
20369
|
-
const degradedRows = await tx.execute(
|
|
20976
|
+
const degradedRows = await tx.execute(sql8`
|
|
20370
20977
|
update sandbox_leases set
|
|
20371
20978
|
resume_state = ${JSON.stringify(degradedResumeState)}::jsonb,
|
|
20372
20979
|
resume_backend_id = coalesce(resume_backend_id, backend),
|
|
@@ -20386,7 +20993,7 @@ async function beginSandboxRematerialization(db, input) {
|
|
|
20386
20993
|
}
|
|
20387
20994
|
let checkpointArtifact = null;
|
|
20388
20995
|
if (workingRow.current_checkpoint_artifact_id !== null) {
|
|
20389
|
-
const artifactRows = await tx.execute(
|
|
20996
|
+
const artifactRows = await tx.execute(sql8`
|
|
20390
20997
|
select id, account_id, workspace_id, sandbox_group_id,
|
|
20391
20998
|
source_lease_id, source_workspace_generation, provenance, provider_backend,
|
|
20392
20999
|
provider_binding_key, provider_binding, object_kind, object_id,
|
|
@@ -20428,7 +21035,7 @@ async function beginSandboxRematerialization(db, input) {
|
|
|
20428
21035
|
verifiedAt: null
|
|
20429
21036
|
}
|
|
20430
21037
|
};
|
|
20431
|
-
const degradedRows = await tx.execute(
|
|
21038
|
+
const degradedRows = await tx.execute(sql8`
|
|
20432
21039
|
update sandbox_leases set
|
|
20433
21040
|
resume_state = ${JSON.stringify(
|
|
20434
21041
|
resumeStateWithRecovery(workingResumeState, degraded)
|
|
@@ -20494,10 +21101,10 @@ async function beginSandboxRematerialization(db, input) {
|
|
|
20494
21101
|
const resumeStateJson = JSON.stringify(
|
|
20495
21102
|
resumeStateWithRecovery(workingResumeState, recovery)
|
|
20496
21103
|
);
|
|
20497
|
-
const updated = await tx.execute(
|
|
21104
|
+
const updated = await tx.execute(sql8`
|
|
20498
21105
|
update sandbox_leases set
|
|
20499
21106
|
resume_state = ${resumeStateJson}::jsonb,
|
|
20500
|
-
${importedArchiveGeneration ?
|
|
21107
|
+
${importedArchiveGeneration ? sql8`archive_generation = workspace_generation,` : sql8``}
|
|
20501
21108
|
updated_at = now()
|
|
20502
21109
|
where id = ${row.id}
|
|
20503
21110
|
and liveness = 'warming'
|
|
@@ -20521,7 +21128,7 @@ async function markSandboxRestoreVerifying(db, input) {
|
|
|
20521
21128
|
db,
|
|
20522
21129
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
20523
21130
|
async (scopedDb) => {
|
|
20524
|
-
const rows = await scopedDb.execute(
|
|
21131
|
+
const rows = await scopedDb.execute(sql8`
|
|
20525
21132
|
update sandbox_leases set
|
|
20526
21133
|
resume_state = jsonb_set(resume_state, '{opengeniRecovery,restore,status}', '"verifying"'::jsonb),
|
|
20527
21134
|
updated_at = now()
|
|
@@ -20543,7 +21150,7 @@ async function failSandboxRematerialization(db, input) {
|
|
|
20543
21150
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
20544
21151
|
async (scopedDb) => await scopedDb.transaction(async (txRaw) => {
|
|
20545
21152
|
const tx = txRaw;
|
|
20546
|
-
const rows = await tx.execute(
|
|
21153
|
+
const rows = await tx.execute(sql8`
|
|
20547
21154
|
select * from sandbox_leases
|
|
20548
21155
|
where workspace_id = ${input.workspaceId}
|
|
20549
21156
|
and sandbox_group_id = ${input.sandboxGroupId}
|
|
@@ -20576,7 +21183,7 @@ async function failSandboxRematerialization(db, input) {
|
|
|
20576
21183
|
}
|
|
20577
21184
|
};
|
|
20578
21185
|
const resumeStateJson = JSON.stringify(archiveOnlyResumeState(row, recovery));
|
|
20579
|
-
const updated = await tx.execute(
|
|
21186
|
+
const updated = await tx.execute(sql8`
|
|
20580
21187
|
update sandbox_leases set
|
|
20581
21188
|
liveness = 'cold',
|
|
20582
21189
|
instance_id = null,
|
|
@@ -20608,7 +21215,7 @@ async function markSandboxProviderReady(db, input) {
|
|
|
20608
21215
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
20609
21216
|
async (scopedDb) => await scopedDb.transaction(async (txRaw) => {
|
|
20610
21217
|
const tx = txRaw;
|
|
20611
|
-
const rows = await tx.execute(
|
|
21218
|
+
const rows = await tx.execute(sql8`
|
|
20612
21219
|
select * from sandbox_leases
|
|
20613
21220
|
where workspace_id = ${input.workspaceId}
|
|
20614
21221
|
and sandbox_group_id = ${input.sandboxGroupId}
|
|
@@ -20641,7 +21248,7 @@ async function markSandboxProviderReady(db, input) {
|
|
|
20641
21248
|
}
|
|
20642
21249
|
};
|
|
20643
21250
|
const resumeStateJson = JSON.stringify(resumeStateWithRecovery(row.resume_state, recovery));
|
|
20644
|
-
const updated = await tx.execute(
|
|
21251
|
+
const updated = await tx.execute(sql8`
|
|
20645
21252
|
update sandbox_leases set resume_state = ${resumeStateJson}::jsonb, updated_at = now()
|
|
20646
21253
|
where id = ${row.id}
|
|
20647
21254
|
and liveness = 'warm'
|
|
@@ -20659,7 +21266,7 @@ async function commitWarmingToWarm(db, input) {
|
|
|
20659
21266
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
20660
21267
|
async (scopedDb) => await scopedDb.transaction(async (txRaw) => {
|
|
20661
21268
|
const tx = txRaw;
|
|
20662
|
-
const rows = await tx.execute(
|
|
21269
|
+
const rows = await tx.execute(sql8`
|
|
20663
21270
|
select * from sandbox_leases
|
|
20664
21271
|
where workspace_id = ${input.workspaceId}
|
|
20665
21272
|
and sandbox_group_id = ${input.sandboxGroupId}
|
|
@@ -20748,7 +21355,7 @@ async function commitWarmingToWarm(db, input) {
|
|
|
20748
21355
|
row.resume_state
|
|
20749
21356
|
);
|
|
20750
21357
|
const resumeStateJson = JSON.stringify(resumeStateWithRecovery(withArchives, recovery));
|
|
20751
|
-
const updated = await tx.execute(
|
|
21358
|
+
const updated = await tx.execute(sql8`
|
|
20752
21359
|
update sandbox_leases set
|
|
20753
21360
|
liveness = 'warm',
|
|
20754
21361
|
instance_id = ${input.instanceId},
|
|
@@ -20781,7 +21388,7 @@ async function recordWarmingSandboxCreated(db, input) {
|
|
|
20781
21388
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
20782
21389
|
async (scopedDb) => await scopedDb.transaction(async (txRaw) => {
|
|
20783
21390
|
const tx = txRaw;
|
|
20784
|
-
const rows = await tx.execute(
|
|
21391
|
+
const rows = await tx.execute(sql8`
|
|
20785
21392
|
select * from sandbox_leases
|
|
20786
21393
|
where workspace_id = ${input.workspaceId}
|
|
20787
21394
|
and sandbox_group_id = ${input.sandboxGroupId}
|
|
@@ -20824,7 +21431,7 @@ async function recordWarmingSandboxCreated(db, input) {
|
|
|
20824
21431
|
if (providerCreatedAt && providerDeadlineAt && providerDeadlineAt.getTime() <= providerCreatedAt.getTime()) {
|
|
20825
21432
|
throw new Error("Provider deadline must be later than provider creation");
|
|
20826
21433
|
}
|
|
20827
|
-
const updated = await tx.execute(
|
|
21434
|
+
const updated = await tx.execute(sql8`
|
|
20828
21435
|
update sandbox_leases set
|
|
20829
21436
|
instance_id = ${input.instanceId},
|
|
20830
21437
|
resume_backend_id = ${input.resumeBackendId ?? null},
|
|
@@ -20899,18 +21506,18 @@ function archiveSessionState(row) {
|
|
|
20899
21506
|
return sessionState && typeof sessionState === "object" ? sessionState : null;
|
|
20900
21507
|
}
|
|
20901
21508
|
async function readColdLostSnapshotRowsTx(tx, input) {
|
|
20902
|
-
const timestampRows = await tx.execute(
|
|
21509
|
+
const timestampRows = await tx.execute(sql8`
|
|
20903
21510
|
select transaction_timestamp() as snapshot_at
|
|
20904
21511
|
`);
|
|
20905
21512
|
const [sessionRows, leaseRows] = await Promise.all([
|
|
20906
|
-
tx.execute(
|
|
21513
|
+
tx.execute(sql8`
|
|
20907
21514
|
select id, status, sandbox_group_id, active_sandbox_id, active_epoch
|
|
20908
21515
|
from sessions
|
|
20909
21516
|
where account_id = ${input.accountId}
|
|
20910
21517
|
and workspace_id = ${input.workspaceId}
|
|
20911
21518
|
and id = ${input.sessionId}
|
|
20912
21519
|
`),
|
|
20913
|
-
tx.execute(
|
|
21520
|
+
tx.execute(sql8`
|
|
20914
21521
|
select * from sandbox_leases
|
|
20915
21522
|
where account_id = ${input.accountId}
|
|
20916
21523
|
and workspace_id = ${input.workspaceId}
|
|
@@ -20934,7 +21541,7 @@ async function readColdLostSnapshotRowsTx(tx, input) {
|
|
|
20934
21541
|
};
|
|
20935
21542
|
}
|
|
20936
21543
|
const [processes, admissions, ptys, holders, interruptions] = await Promise.all([
|
|
20937
|
-
tx.execute(
|
|
21544
|
+
tx.execute(sql8`
|
|
20938
21545
|
select id,
|
|
20939
21546
|
session_id as "sessionId",
|
|
20940
21547
|
parent_admission_id as "parentAdmissionId",
|
|
@@ -20967,7 +21574,7 @@ async function readColdLostSnapshotRowsTx(tx, input) {
|
|
|
20967
21574
|
))
|
|
20968
21575
|
order by id
|
|
20969
21576
|
`),
|
|
20970
|
-
tx.execute(
|
|
21577
|
+
tx.execute(sql8`
|
|
20971
21578
|
select id,
|
|
20972
21579
|
session_id as "sessionId",
|
|
20973
21580
|
actor_kind as "actorKind",
|
|
@@ -21002,7 +21609,7 @@ async function readColdLostSnapshotRowsTx(tx, input) {
|
|
|
21002
21609
|
))
|
|
21003
21610
|
order by id
|
|
21004
21611
|
`),
|
|
21005
|
-
tx.execute(
|
|
21612
|
+
tx.execute(sql8`
|
|
21006
21613
|
select id,
|
|
21007
21614
|
session_id as "sessionId",
|
|
21008
21615
|
retained_process_id as "retainedProcessId",
|
|
@@ -21030,7 +21637,7 @@ async function readColdLostSnapshotRowsTx(tx, input) {
|
|
|
21030
21637
|
))
|
|
21031
21638
|
order by id
|
|
21032
21639
|
`),
|
|
21033
|
-
tx.execute(
|
|
21640
|
+
tx.execute(sql8`
|
|
21034
21641
|
select holder.id,
|
|
21035
21642
|
holder.kind,
|
|
21036
21643
|
holder.holder_id,
|
|
@@ -21052,7 +21659,7 @@ async function readColdLostSnapshotRowsTx(tx, input) {
|
|
|
21052
21659
|
and holder.lease_id = ${lease.id}
|
|
21053
21660
|
order by holder.kind, holder.holder_id
|
|
21054
21661
|
`),
|
|
21055
|
-
tx.execute(
|
|
21662
|
+
tx.execute(sql8`
|
|
21056
21663
|
select interruption.id,
|
|
21057
21664
|
interruption.session_id as "sessionId",
|
|
21058
21665
|
interruption.operation_id as "operationId",
|
|
@@ -21686,7 +22293,7 @@ function evaluateColdLostSnapshot(input, rows, database, options = { requireRead
|
|
|
21686
22293
|
};
|
|
21687
22294
|
}
|
|
21688
22295
|
async function readColdLostDatabasePostureTx(tx) {
|
|
21689
|
-
const postureRows = await tx.execute(
|
|
22296
|
+
const postureRows = await tx.execute(sql8`
|
|
21690
22297
|
select current_user as role,
|
|
21691
22298
|
coalesce((select rolsuper from pg_roles where rolname = current_user), true) as role_superuser,
|
|
21692
22299
|
coalesce((select rolbypassrls from pg_roles where rolname = current_user), true) as role_bypass_rls,
|
|
@@ -21737,7 +22344,7 @@ async function previewColdLostLeaseInstanceBlockers(db, input) {
|
|
|
21737
22344
|
}
|
|
21738
22345
|
var LOST_PROVIDER_PROCESS_REASON = "provider_instance_lost";
|
|
21739
22346
|
async function lockExactLostProviderWorkspaceBlockersTx(tx, input) {
|
|
21740
|
-
await tx.execute(
|
|
22347
|
+
await tx.execute(sql8`
|
|
21741
22348
|
select id from sandbox_retained_processes
|
|
21742
22349
|
where account_id = ${input.accountId}
|
|
21743
22350
|
and workspace_id = ${input.workspaceId}
|
|
@@ -21749,7 +22356,7 @@ async function lockExactLostProviderWorkspaceBlockersTx(tx, input) {
|
|
|
21749
22356
|
order by id
|
|
21750
22357
|
for update
|
|
21751
22358
|
`);
|
|
21752
|
-
await tx.execute(
|
|
22359
|
+
await tx.execute(sql8`
|
|
21753
22360
|
select id from sandbox_workspace_mutation_admissions
|
|
21754
22361
|
where account_id = ${input.accountId}
|
|
21755
22362
|
and workspace_id = ${input.workspaceId}
|
|
@@ -21761,7 +22368,7 @@ async function lockExactLostProviderWorkspaceBlockersTx(tx, input) {
|
|
|
21761
22368
|
order by id
|
|
21762
22369
|
for update
|
|
21763
22370
|
`);
|
|
21764
|
-
await tx.execute(
|
|
22371
|
+
await tx.execute(sql8`
|
|
21765
22372
|
select id from sandbox_pty_sessions
|
|
21766
22373
|
where account_id = ${input.accountId}
|
|
21767
22374
|
and workspace_id = ${input.workspaceId}
|
|
@@ -21828,7 +22435,7 @@ async function settleExactLostProviderWorkspaceBlockersTx(tx, input) {
|
|
|
21828
22435
|
)
|
|
21829
22436
|
)
|
|
21830
22437
|
).returning({ holderId: sandboxLeaseHolders.holderId });
|
|
21831
|
-
await tx.execute(
|
|
22438
|
+
await tx.execute(sql8`
|
|
21832
22439
|
update sandbox_leases as lease set
|
|
21833
22440
|
refcount = counts.total,
|
|
21834
22441
|
turn_holders = counts.turns,
|
|
@@ -21856,7 +22463,7 @@ async function markWarmLeaseInstanceLost(db, input) {
|
|
|
21856
22463
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
21857
22464
|
async (scopedDb) => await scopedDb.transaction(async (txRaw) => {
|
|
21858
22465
|
const tx = txRaw;
|
|
21859
|
-
const observedRows = await tx.execute(
|
|
22466
|
+
const observedRows = await tx.execute(sql8`
|
|
21860
22467
|
select * from sandbox_leases
|
|
21861
22468
|
where workspace_id = ${input.workspaceId}
|
|
21862
22469
|
and sandbox_group_id = ${input.sandboxGroupId}
|
|
@@ -21877,7 +22484,7 @@ async function markWarmLeaseInstanceLost(db, input) {
|
|
|
21877
22484
|
lostInstanceId: input.expectedInstanceId
|
|
21878
22485
|
};
|
|
21879
22486
|
await lockExactLostProviderWorkspaceBlockersTx(tx, blockerScope);
|
|
21880
|
-
const currentRows = await tx.execute(
|
|
22487
|
+
const currentRows = await tx.execute(sql8`
|
|
21881
22488
|
select * from sandbox_leases
|
|
21882
22489
|
where workspace_id = ${input.workspaceId}
|
|
21883
22490
|
and sandbox_group_id = ${input.sandboxGroupId}
|
|
@@ -21924,7 +22531,7 @@ async function markWarmLeaseInstanceLost(db, input) {
|
|
|
21924
22531
|
};
|
|
21925
22532
|
const coldResumeState = archiveOnlyResumeState(current, recovery);
|
|
21926
22533
|
const coldResumeStateJson = JSON.stringify(coldResumeState);
|
|
21927
|
-
const updatedRows = await tx.execute(
|
|
22534
|
+
const updatedRows = await tx.execute(sql8`
|
|
21928
22535
|
update sandbox_leases set
|
|
21929
22536
|
liveness = 'cold',
|
|
21930
22537
|
instance_id = null,
|
|
@@ -22030,7 +22637,7 @@ async function reconcileColdLostLeaseInstanceBlockers(db, input) {
|
|
|
22030
22637
|
lostInstanceId: input.expectedLostInstanceId
|
|
22031
22638
|
};
|
|
22032
22639
|
await lockExactLostProviderWorkspaceBlockersTx(tx, blockerScope);
|
|
22033
|
-
const currentRows = await tx.execute(
|
|
22640
|
+
const currentRows = await tx.execute(sql8`
|
|
22034
22641
|
select * from sandbox_leases
|
|
22035
22642
|
where workspace_id = ${input.workspaceId}
|
|
22036
22643
|
and sandbox_group_id = ${input.sandboxGroupId}
|
|
@@ -22060,7 +22667,7 @@ async function reconcileColdLostLeaseInstanceBlockers(db, input) {
|
|
|
22060
22667
|
return { status: "blocked", preview: currentPreview };
|
|
22061
22668
|
}
|
|
22062
22669
|
const settlement = await settleExactLostProviderWorkspaceBlockersTx(tx, blockerScope);
|
|
22063
|
-
const refreshedRows = await tx.execute(
|
|
22670
|
+
const refreshedRows = await tx.execute(sql8`
|
|
22064
22671
|
select * from sandbox_leases where id = ${current.id}
|
|
22065
22672
|
`);
|
|
22066
22673
|
const refreshed = refreshedRows[0];
|
|
@@ -22079,7 +22686,7 @@ async function failWarmingToCold(db, input) {
|
|
|
22079
22686
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
22080
22687
|
async (scopedDb) => await scopedDb.transaction(async (txRaw) => {
|
|
22081
22688
|
const tx = txRaw;
|
|
22082
|
-
const rows = await tx.execute(
|
|
22689
|
+
const rows = await tx.execute(sql8`
|
|
22083
22690
|
select * from sandbox_leases
|
|
22084
22691
|
where workspace_id = ${input.workspaceId}
|
|
22085
22692
|
and sandbox_group_id = ${input.sandboxGroupId}
|
|
@@ -22119,7 +22726,7 @@ async function failWarmingToCold(db, input) {
|
|
|
22119
22726
|
}
|
|
22120
22727
|
};
|
|
22121
22728
|
const resumeStateJson = hasArchive ? JSON.stringify(archiveOnlyResumeState(row, recovery)) : null;
|
|
22122
|
-
await tx.execute(
|
|
22729
|
+
await tx.execute(sql8`
|
|
22123
22730
|
update sandbox_leases set
|
|
22124
22731
|
liveness = 'cold',
|
|
22125
22732
|
instance_id = null,
|
|
@@ -22153,18 +22760,18 @@ async function releaseLeaseHolder(db, input) {
|
|
|
22153
22760
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
22154
22761
|
async (scopedDb) => await scopedDb.transaction(async (txRaw) => {
|
|
22155
22762
|
const tx = txRaw;
|
|
22156
|
-
const rows = await tx.execute(
|
|
22763
|
+
const rows = await tx.execute(sql8`
|
|
22157
22764
|
select * from sandbox_leases
|
|
22158
22765
|
where workspace_id = ${input.workspaceId} and sandbox_group_id = ${input.sandboxGroupId}
|
|
22159
22766
|
for update
|
|
22160
22767
|
`);
|
|
22161
22768
|
const row = rows[0];
|
|
22162
22769
|
if (!row) return null;
|
|
22163
|
-
await tx.execute(
|
|
22770
|
+
await tx.execute(sql8`
|
|
22164
22771
|
delete from sandbox_lease_holders
|
|
22165
22772
|
where lease_id = ${row.id} and kind = ${input.kind} and holder_id = ${input.holderId}
|
|
22166
22773
|
`);
|
|
22167
|
-
const counts = await tx.execute(
|
|
22774
|
+
const counts = await tx.execute(sql8`
|
|
22168
22775
|
select count(*)::int as total,
|
|
22169
22776
|
count(*) filter (where kind = 'turn')::int as turns,
|
|
22170
22777
|
count(*) filter (where kind = 'viewer')::int as viewers
|
|
@@ -22173,10 +22780,10 @@ async function releaseLeaseHolder(db, input) {
|
|
|
22173
22780
|
const c = counts[0];
|
|
22174
22781
|
const enterDraining = row.liveness === "warm" && c.total === 0 && c.turns === 0;
|
|
22175
22782
|
const drainGraceMs = row.rotation_requested_at ? 0 : input.idleGraceMs;
|
|
22176
|
-
const updated = await tx.execute(
|
|
22783
|
+
const updated = await tx.execute(sql8`
|
|
22177
22784
|
update sandbox_leases set
|
|
22178
22785
|
refcount = ${c.total}, turn_holders = ${c.turns}, viewer_holders = ${c.viewers},
|
|
22179
|
-
${enterDraining ?
|
|
22786
|
+
${enterDraining ? sql8`liveness = 'draining', expires_at = now() + (${String(drainGraceMs)} || ' milliseconds')::interval,` : sql8``}
|
|
22180
22787
|
updated_at = now()
|
|
22181
22788
|
where id = ${row.id}
|
|
22182
22789
|
returning *
|
|
@@ -22185,7 +22792,7 @@ async function releaseLeaseHolder(db, input) {
|
|
|
22185
22792
|
})
|
|
22186
22793
|
);
|
|
22187
22794
|
}
|
|
22188
|
-
var LIVE_CANONICAL_TURN_HOLDER_PREDICATE =
|
|
22795
|
+
var LIVE_CANONICAL_TURN_HOLDER_PREDICATE = sql8`
|
|
22189
22796
|
(
|
|
22190
22797
|
holder.kind <> 'turn'
|
|
22191
22798
|
or holder.holder_id !~* '^turn-attempt:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$'
|
|
@@ -22208,7 +22815,7 @@ var LIVE_CANONICAL_TURN_HOLDER_PREDICATE = sql7`
|
|
|
22208
22815
|
)
|
|
22209
22816
|
`;
|
|
22210
22817
|
async function touchLiveLeaseHolder(tx, input) {
|
|
22211
|
-
const updated = await tx.execute(
|
|
22818
|
+
const updated = await tx.execute(sql8`
|
|
22212
22819
|
update sandbox_lease_holders as holder set last_heartbeat_at = now()
|
|
22213
22820
|
where holder.lease_id = (
|
|
22214
22821
|
select id from sandbox_leases
|
|
@@ -22229,7 +22836,7 @@ async function heartbeatLeaseHolder(db, input) {
|
|
|
22229
22836
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
22230
22837
|
async (scopedDb) => await scopedDb.transaction(async (txRaw) => {
|
|
22231
22838
|
const tx = txRaw;
|
|
22232
|
-
const leases = await tx.execute(
|
|
22839
|
+
const leases = await tx.execute(sql8`
|
|
22233
22840
|
select id from sandbox_leases
|
|
22234
22841
|
where workspace_id = ${input.workspaceId}
|
|
22235
22842
|
and sandbox_group_id = ${input.sandboxGroupId}
|
|
@@ -22244,7 +22851,7 @@ async function heartbeatLeaseHolder(db, input) {
|
|
|
22244
22851
|
holderId: input.holderId
|
|
22245
22852
|
});
|
|
22246
22853
|
if (!holderAlive) return false;
|
|
22247
|
-
const leaseRows = await tx.execute(
|
|
22854
|
+
const leaseRows = await tx.execute(sql8`
|
|
22248
22855
|
update sandbox_leases set
|
|
22249
22856
|
expires_at = now() + (${String(input.leaseTtlMs)} || ' milliseconds')::interval,
|
|
22250
22857
|
updated_at = now()
|
|
@@ -22280,13 +22887,13 @@ async function reapStaleLeaseHolders(db, input) {
|
|
|
22280
22887
|
input.workspaceId,
|
|
22281
22888
|
async (scopedDb) => await scopedDb.transaction(async (txRaw) => {
|
|
22282
22889
|
const tx = txRaw;
|
|
22283
|
-
await tx.execute(
|
|
22890
|
+
await tx.execute(sql8`
|
|
22284
22891
|
select id from sandbox_leases
|
|
22285
22892
|
where workspace_id = ${input.workspaceId}
|
|
22286
22893
|
order by id
|
|
22287
22894
|
for update
|
|
22288
22895
|
`);
|
|
22289
|
-
const reaped = await tx.execute(
|
|
22896
|
+
const reaped = await tx.execute(sql8`
|
|
22290
22897
|
delete from sandbox_lease_holders
|
|
22291
22898
|
where id in (
|
|
22292
22899
|
select id from sandbox_lease_holders
|
|
@@ -22302,7 +22909,7 @@ async function reapStaleLeaseHolders(db, input) {
|
|
|
22302
22909
|
const reapedDirect = reaped.filter(
|
|
22303
22910
|
(row) => row.kind === "direct"
|
|
22304
22911
|
).length;
|
|
22305
|
-
const reapedTurnRows = input.turnHolderTtlMs && input.turnHolderTtlMs > 0 ? await tx.execute(
|
|
22912
|
+
const reapedTurnRows = input.turnHolderTtlMs && input.turnHolderTtlMs > 0 ? await tx.execute(sql8`
|
|
22306
22913
|
delete from sandbox_lease_holders
|
|
22307
22914
|
where id in (
|
|
22308
22915
|
select id from sandbox_lease_holders
|
|
@@ -22312,7 +22919,7 @@ async function reapStaleLeaseHolders(db, input) {
|
|
|
22312
22919
|
)
|
|
22313
22920
|
returning lease_id
|
|
22314
22921
|
`) : [];
|
|
22315
|
-
await tx.execute(
|
|
22922
|
+
await tx.execute(sql8`
|
|
22316
22923
|
update sandbox_leases L set
|
|
22317
22924
|
refcount = c.total,
|
|
22318
22925
|
turn_holders = c.turns,
|
|
@@ -22335,7 +22942,7 @@ async function reapStaleLeaseHolders(db, input) {
|
|
|
22335
22942
|
) c
|
|
22336
22943
|
where L.id = c.id and L.workspace_id = ${input.workspaceId}
|
|
22337
22944
|
`);
|
|
22338
|
-
const expiredWarming = await tx.execute(
|
|
22945
|
+
const expiredWarming = await tx.execute(sql8`
|
|
22339
22946
|
select * from sandbox_leases
|
|
22340
22947
|
where workspace_id = ${input.workspaceId}
|
|
22341
22948
|
and liveness = 'warming' and expires_at < now() and instance_id is null
|
|
@@ -22368,7 +22975,7 @@ async function reapStaleLeaseHolders(db, input) {
|
|
|
22368
22975
|
verifiedAt: null
|
|
22369
22976
|
}
|
|
22370
22977
|
}) : null;
|
|
22371
|
-
const reset = await tx.execute(
|
|
22978
|
+
const reset = await tx.execute(sql8`
|
|
22372
22979
|
update sandbox_leases set
|
|
22373
22980
|
liveness = 'cold', instance_id = null,
|
|
22374
22981
|
lease_epoch = lease_epoch + 1,
|
|
@@ -22388,7 +22995,7 @@ async function reapStaleLeaseHolders(db, input) {
|
|
|
22388
22995
|
`);
|
|
22389
22996
|
warmingReset += reset.length;
|
|
22390
22997
|
}
|
|
22391
|
-
const warmingDrain = await tx.execute(
|
|
22998
|
+
const warmingDrain = await tx.execute(sql8`
|
|
22392
22999
|
update sandbox_leases set
|
|
22393
23000
|
liveness = 'draining',
|
|
22394
23001
|
refcount = 0,
|
|
@@ -22405,7 +23012,7 @@ async function reapStaleLeaseHolders(db, input) {
|
|
|
22405
23012
|
`);
|
|
22406
23013
|
const drainable = await rawRows(
|
|
22407
23014
|
tx,
|
|
22408
|
-
|
|
23015
|
+
sql8`
|
|
22409
23016
|
select sandbox_group_id, instance_id, lease_epoch from sandbox_leases
|
|
22410
23017
|
where workspace_id = ${input.workspaceId}
|
|
22411
23018
|
and liveness = 'draining' and expires_at < now() and refcount = 0
|
|
@@ -22430,10 +23037,10 @@ async function reapStaleLeaseHoldersGlobal(db, input) {
|
|
|
22430
23037
|
let rows;
|
|
22431
23038
|
const runCurrentReaper = async () => await db.transaction(async (txRaw) => {
|
|
22432
23039
|
const tx = txRaw;
|
|
22433
|
-
await tx.execute(
|
|
23040
|
+
await tx.execute(sql8`select set_config('opengeni.sandbox_recovery_protocol_v2', '1', true)`);
|
|
22434
23041
|
return await rawRows(
|
|
22435
23042
|
tx,
|
|
22436
|
-
|
|
23043
|
+
sql8`
|
|
22437
23044
|
select workspace_id, sandbox_group_id, instance_id, lease_epoch
|
|
22438
23045
|
from opengeni_private.reap_sandbox_leases(${input.viewerHolderTtlMs}, ${input.turnHolderTtlMs ?? 0}, ${input.idleGraceMs})
|
|
22439
23046
|
`
|
|
@@ -22441,10 +23048,10 @@ async function reapStaleLeaseHoldersGlobal(db, input) {
|
|
|
22441
23048
|
});
|
|
22442
23049
|
const runLegacyReaper = async () => await db.transaction(async (txRaw) => {
|
|
22443
23050
|
const tx = txRaw;
|
|
22444
|
-
await tx.execute(
|
|
23051
|
+
await tx.execute(sql8`select set_config('opengeni.sandbox_recovery_protocol_v2', '1', true)`);
|
|
22445
23052
|
return await rawRows(
|
|
22446
23053
|
tx,
|
|
22447
|
-
|
|
23054
|
+
sql8`
|
|
22448
23055
|
select workspace_id, sandbox_group_id, instance_id, lease_epoch
|
|
22449
23056
|
from opengeni_private.reap_sandbox_leases(${input.viewerHolderTtlMs}, ${input.idleGraceMs})
|
|
22450
23057
|
`
|
|
@@ -22474,7 +23081,7 @@ async function reapStaleLeaseHoldersGlobal(db, input) {
|
|
|
22474
23081
|
async function listMeterableWarmLeases(db) {
|
|
22475
23082
|
const rows = await rawRows(
|
|
22476
23083
|
db,
|
|
22477
|
-
|
|
23084
|
+
sql8`
|
|
22478
23085
|
select account_id, workspace_id, sandbox_group_id, lease_epoch, backend
|
|
22479
23086
|
from opengeni_private.list_meterable_warm_leases()
|
|
22480
23087
|
`
|
|
@@ -22490,7 +23097,7 @@ async function listMeterableWarmLeases(db) {
|
|
|
22490
23097
|
async function listSandboxViewerForceDrainWorkspaceIds(db) {
|
|
22491
23098
|
const rows = await rawRows(
|
|
22492
23099
|
db,
|
|
22493
|
-
|
|
23100
|
+
sql8`select workspace_id
|
|
22494
23101
|
from opengeni_private.list_sandbox_viewer_force_drain_workspaces()`
|
|
22495
23102
|
);
|
|
22496
23103
|
return rows.map((row) => row.workspace_id);
|
|
@@ -22498,7 +23105,7 @@ async function listSandboxViewerForceDrainWorkspaceIds(db) {
|
|
|
22498
23105
|
async function countQueuedTurns(db) {
|
|
22499
23106
|
const rows = await rawRows(
|
|
22500
23107
|
db,
|
|
22501
|
-
|
|
23108
|
+
sql8`
|
|
22502
23109
|
select opengeni_private.count_queued_turns() as count
|
|
22503
23110
|
`
|
|
22504
23111
|
);
|
|
@@ -22513,7 +23120,7 @@ async function countSandboxLeasesByLiveness(db) {
|
|
|
22513
23120
|
};
|
|
22514
23121
|
const rows = await rawRows(
|
|
22515
23122
|
db,
|
|
22516
|
-
|
|
23123
|
+
sql8`
|
|
22517
23124
|
select liveness, count
|
|
22518
23125
|
from opengeni_private.count_sandbox_leases_by_liveness()
|
|
22519
23126
|
`
|
|
@@ -22528,7 +23135,7 @@ async function countSandboxLeasesByLiveness(db) {
|
|
|
22528
23135
|
async function listCreditBalancesByAccount(db) {
|
|
22529
23136
|
const rows = await rawRows(
|
|
22530
23137
|
db,
|
|
22531
|
-
|
|
23138
|
+
sql8`
|
|
22532
23139
|
select account_id, balance_micros
|
|
22533
23140
|
from opengeni_private.credit_balance_by_account()
|
|
22534
23141
|
`
|
|
@@ -22541,7 +23148,7 @@ async function listCreditBalancesByAccount(db) {
|
|
|
22541
23148
|
async function listLiveModalSandboxLeaseAttributions(db) {
|
|
22542
23149
|
const rows = await rawRows(
|
|
22543
23150
|
db,
|
|
22544
|
-
|
|
23151
|
+
sql8`
|
|
22545
23152
|
select lease_id, workspace_id, sandbox_group_id, instance_id, liveness
|
|
22546
23153
|
from opengeni_private.list_live_modal_sandbox_leases()
|
|
22547
23154
|
`
|
|
@@ -22559,7 +23166,7 @@ async function reArmDrainingLease(db, input) {
|
|
|
22559
23166
|
db,
|
|
22560
23167
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
22561
23168
|
async (scopedDb) => {
|
|
22562
|
-
const rows = await scopedDb.execute(
|
|
23169
|
+
const rows = await scopedDb.execute(sql8`
|
|
22563
23170
|
update sandbox_leases set
|
|
22564
23171
|
liveness = 'warm',
|
|
22565
23172
|
expires_at = now() + (${String(input.leaseTtlMs)} || ' milliseconds')::interval,
|
|
@@ -22580,7 +23187,7 @@ async function confirmDrainCold(db, input) {
|
|
|
22580
23187
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
22581
23188
|
async (scopedDb) => await scopedDb.transaction(async (txRaw) => {
|
|
22582
23189
|
const tx = txRaw;
|
|
22583
|
-
const observedRows = await tx.execute(
|
|
23190
|
+
const observedRows = await tx.execute(sql8`
|
|
22584
23191
|
select * from sandbox_leases
|
|
22585
23192
|
where workspace_id = ${input.workspaceId}
|
|
22586
23193
|
and sandbox_group_id = ${input.sandboxGroupId}
|
|
@@ -22600,7 +23207,7 @@ async function confirmDrainCold(db, input) {
|
|
|
22600
23207
|
if (blockerScope) {
|
|
22601
23208
|
await lockExactLostProviderWorkspaceBlockersTx(tx, blockerScope);
|
|
22602
23209
|
}
|
|
22603
|
-
const locked = await tx.execute(
|
|
23210
|
+
const locked = await tx.execute(sql8`
|
|
22604
23211
|
select * from sandbox_leases
|
|
22605
23212
|
where workspace_id = ${input.workspaceId}
|
|
22606
23213
|
and sandbox_group_id = ${input.sandboxGroupId}
|
|
@@ -22645,7 +23252,7 @@ async function confirmDrainCold(db, input) {
|
|
|
22645
23252
|
};
|
|
22646
23253
|
const preserveRecovery = hasArchive || restoreStatus === "unrecoverable";
|
|
22647
23254
|
const resumeStateJson = preserveRecovery ? JSON.stringify(archiveOnlyResumeState(row, recovery)) : null;
|
|
22648
|
-
const rows = await tx.execute(
|
|
23255
|
+
const rows = await tx.execute(sql8`
|
|
22649
23256
|
update sandbox_leases set
|
|
22650
23257
|
liveness = 'cold',
|
|
22651
23258
|
instance_id = null,
|
|
@@ -22985,7 +23592,7 @@ async function advanceWorkspaceGenerationForAuthorityOnce(db, authority, operati
|
|
|
22985
23592
|
async (scopedDb) => await scopedDb.transaction(async (txRaw) => {
|
|
22986
23593
|
const tx = txRaw;
|
|
22987
23594
|
const locked = await lockWorkspaceMutationAuthorityTx(tx, authority);
|
|
22988
|
-
const rows = await tx.execute(
|
|
23595
|
+
const rows = await tx.execute(sql8`
|
|
22989
23596
|
with advanced as (
|
|
22990
23597
|
update sandbox_leases as lease set
|
|
22991
23598
|
workspace_generation = lease.workspace_generation + 1,
|
|
@@ -23033,7 +23640,7 @@ async function advanceWorkspaceGenerationForAuthorityOnce(db, authority, operati
|
|
|
23033
23640
|
`);
|
|
23034
23641
|
const row = rows[0];
|
|
23035
23642
|
if (!row) {
|
|
23036
|
-
const current = await tx.execute(
|
|
23643
|
+
const current = await tx.execute(sql8`
|
|
23037
23644
|
select lease.workspace_generation,
|
|
23038
23645
|
(
|
|
23039
23646
|
lease.account_id = ${locked.accountId}
|
|
@@ -23151,7 +23758,7 @@ async function advanceWorkspaceGenerationForRetainedProcess(db, input) {
|
|
|
23151
23758
|
);
|
|
23152
23759
|
}
|
|
23153
23760
|
async function selectExactAdmissionForUpdate(tx, input) {
|
|
23154
|
-
const rows = await tx.execute(
|
|
23761
|
+
const rows = await tx.execute(sql8`
|
|
23155
23762
|
select * from sandbox_workspace_mutation_admissions
|
|
23156
23763
|
where id = ${input.admissionId}
|
|
23157
23764
|
and account_id = ${input.accountId}
|
|
@@ -23214,7 +23821,7 @@ async function verifyResolvedAdmissionAuthority(tx, authority, admission) {
|
|
|
23214
23821
|
detail: "Workspace mutation output rejected because its active route moved"
|
|
23215
23822
|
};
|
|
23216
23823
|
}
|
|
23217
|
-
const [identity] = await tx.execute(
|
|
23824
|
+
const [identity] = await tx.execute(sql8`
|
|
23218
23825
|
select
|
|
23219
23826
|
(
|
|
23220
23827
|
lease.account_id = ${authority.accountId}
|
|
@@ -23282,7 +23889,7 @@ async function verifyWorkspaceMutationSettlementForAuthority(db, authorityInput,
|
|
|
23282
23889
|
};
|
|
23283
23890
|
}
|
|
23284
23891
|
if (!admission.settled_at) {
|
|
23285
|
-
await tx.execute(
|
|
23892
|
+
await tx.execute(sql8`
|
|
23286
23893
|
update sandbox_workspace_mutation_admissions set
|
|
23287
23894
|
provider_outcome = ${input.outcome}, settled_at = now()
|
|
23288
23895
|
where id = ${input.admission.id} and settled_at is null
|
|
@@ -23453,7 +24060,7 @@ async function retainWorkspaceMutationProcess(db, input) {
|
|
|
23453
24060
|
"Settled workspace mutation cannot be promoted to a retained process"
|
|
23454
24061
|
);
|
|
23455
24062
|
}
|
|
23456
|
-
const processLeases = await tx.execute(
|
|
24063
|
+
const processLeases = await tx.execute(sql8`
|
|
23457
24064
|
select id from sandbox_leases
|
|
23458
24065
|
where id = ${admission.lease_id}
|
|
23459
24066
|
for update
|
|
@@ -23465,7 +24072,7 @@ async function retainWorkspaceMutationProcess(db, input) {
|
|
|
23465
24072
|
);
|
|
23466
24073
|
}
|
|
23467
24074
|
const processHolderId = `process:${input.processId}`;
|
|
23468
|
-
await tx.execute(
|
|
24075
|
+
await tx.execute(sql8`
|
|
23469
24076
|
insert into sandbox_lease_holders
|
|
23470
24077
|
(account_id, workspace_id, lease_id, kind, holder_id, subject_id,
|
|
23471
24078
|
last_heartbeat_at)
|
|
@@ -23498,11 +24105,11 @@ async function retainWorkspaceMutationProcess(db, input) {
|
|
|
23498
24105
|
providerSessionId: input.providerSessionId,
|
|
23499
24106
|
state: "active"
|
|
23500
24107
|
}).returning();
|
|
23501
|
-
await tx.execute(
|
|
24108
|
+
await tx.execute(sql8`
|
|
23502
24109
|
update sandbox_workspace_mutation_admissions set provider_outcome = 'retained'
|
|
23503
24110
|
where id = ${admission.id} and provider_outcome is null and settled_at is null
|
|
23504
24111
|
`);
|
|
23505
|
-
await tx.execute(
|
|
24112
|
+
await tx.execute(sql8`
|
|
23506
24113
|
update sandbox_leases as lease set
|
|
23507
24114
|
refcount = counts.total,
|
|
23508
24115
|
turn_holders = counts.turns,
|
|
@@ -23561,7 +24168,7 @@ async function claimTerminalRetainedProcesses(db, input) {
|
|
|
23561
24168
|
}
|
|
23562
24169
|
const rows = await rawRows(
|
|
23563
24170
|
db,
|
|
23564
|
-
|
|
24171
|
+
sql8`
|
|
23565
24172
|
select account_id, workspace_id, session_id, process_id, claim_id,
|
|
23566
24173
|
owner_state, owner_attempt_outcome
|
|
23567
24174
|
from opengeni_private.claim_terminal_retained_processes(
|
|
@@ -23773,7 +24380,7 @@ async function deferRetainedProcessReconciliation(db, input) {
|
|
|
23773
24380
|
async function countActiveRetainedProcessesByOwnerState(db) {
|
|
23774
24381
|
const rows = await rawRows(
|
|
23775
24382
|
db,
|
|
23776
|
-
|
|
24383
|
+
sql8`
|
|
23777
24384
|
select owner_state, active_count, terminal_owner_count
|
|
23778
24385
|
from opengeni_private.count_active_retained_processes_by_owner_state()
|
|
23779
24386
|
`
|
|
@@ -23787,7 +24394,7 @@ async function countActiveRetainedProcessesByOwnerState(db) {
|
|
|
23787
24394
|
async function countExpiredDrainingSandboxLeases(db) {
|
|
23788
24395
|
const rows = await rawRows(
|
|
23789
24396
|
db,
|
|
23790
|
-
|
|
24397
|
+
sql8`
|
|
23791
24398
|
select backend, age_bucket, count
|
|
23792
24399
|
from opengeni_private.count_expired_draining_sandbox_leases()
|
|
23793
24400
|
`
|
|
@@ -23861,7 +24468,7 @@ async function settleRetainedProcess(db, input) {
|
|
|
23861
24468
|
"Retained process settlement conflicts with checkpointed provider proof"
|
|
23862
24469
|
);
|
|
23863
24470
|
}
|
|
23864
|
-
const admissions = await tx.execute(
|
|
24471
|
+
const admissions = await tx.execute(sql8`
|
|
23865
24472
|
select * from sandbox_workspace_mutation_admissions
|
|
23866
24473
|
where id = ${process.parentAdmissionId}
|
|
23867
24474
|
and account_id = ${input.accountId}
|
|
@@ -23885,7 +24492,7 @@ async function settleRetainedProcess(db, input) {
|
|
|
23885
24492
|
"Retained process parent admission is not open"
|
|
23886
24493
|
);
|
|
23887
24494
|
}
|
|
23888
|
-
const leases = await tx.execute(
|
|
24495
|
+
const leases = await tx.execute(sql8`
|
|
23889
24496
|
select * from sandbox_leases
|
|
23890
24497
|
where id = ${process.leaseId}
|
|
23891
24498
|
and account_id = ${input.accountId}
|
|
@@ -23933,39 +24540,39 @@ async function settleRetainedProcess(db, input) {
|
|
|
23933
24540
|
"Retained process changed while its row was locked"
|
|
23934
24541
|
);
|
|
23935
24542
|
}
|
|
23936
|
-
await tx.execute(
|
|
24543
|
+
await tx.execute(sql8`
|
|
23937
24544
|
update sandbox_workspace_mutation_admissions set
|
|
23938
24545
|
provider_outcome = ${input.outcome === "exited" ? "resolved" : "rejected"},
|
|
23939
24546
|
settled_at = now()
|
|
23940
24547
|
where id = ${process.parentAdmissionId}
|
|
23941
24548
|
and provider_outcome = 'retained' and settled_at is null
|
|
23942
24549
|
`);
|
|
23943
|
-
await tx.execute(
|
|
24550
|
+
await tx.execute(sql8`
|
|
23944
24551
|
delete from sandbox_lease_holders
|
|
23945
24552
|
where lease_id = ${process.leaseId}
|
|
23946
24553
|
and account_id = ${input.accountId}
|
|
23947
24554
|
and workspace_id = ${input.workspaceId}
|
|
23948
24555
|
and kind = 'process' and holder_id = ${process.holderId}
|
|
23949
24556
|
`);
|
|
23950
|
-
const [counts] = await tx.execute(
|
|
24557
|
+
const [counts] = await tx.execute(sql8`
|
|
23951
24558
|
select count(*)::int as total,
|
|
23952
24559
|
count(*) filter (where kind = 'turn')::int as turns,
|
|
23953
24560
|
count(*) filter (where kind = 'viewer')::int as viewers
|
|
23954
24561
|
from sandbox_lease_holders where lease_id = ${process.leaseId}
|
|
23955
24562
|
`);
|
|
23956
24563
|
const enterDraining = processOwnsCurrentLease && (counts?.total ?? 0) === 0;
|
|
23957
|
-
await tx.execute(
|
|
24564
|
+
await tx.execute(sql8`
|
|
23958
24565
|
update sandbox_leases set
|
|
23959
24566
|
refcount = ${counts?.total ?? 0},
|
|
23960
24567
|
turn_holders = ${counts?.turns ?? 0},
|
|
23961
24568
|
viewer_holders = ${counts?.viewers ?? 0},
|
|
23962
|
-
${enterDraining ?
|
|
24569
|
+
${enterDraining ? sql8`liveness = case when liveness = 'warm' then 'draining' else liveness end,
|
|
23963
24570
|
expires_at = case when liveness = 'warm'
|
|
23964
24571
|
then case when rotation_requested_at is not null
|
|
23965
24572
|
then now()
|
|
23966
24573
|
else now() + (${String(input.idleGraceMs)} || ' milliseconds')::interval
|
|
23967
24574
|
end
|
|
23968
|
-
else expires_at end,` :
|
|
24575
|
+
else expires_at end,` : sql8``}
|
|
23969
24576
|
updated_at = now()
|
|
23970
24577
|
where id = ${process.leaseId}
|
|
23971
24578
|
and sandbox_group_id = ${process.sandboxGroupId}
|
|
@@ -23979,14 +24586,14 @@ async function readWorkspaceArchiveCapturePreflight(db, input) {
|
|
|
23979
24586
|
db,
|
|
23980
24587
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
23981
24588
|
async (scopedDb) => {
|
|
23982
|
-
const rows = await scopedDb.execute(
|
|
24589
|
+
const rows = await scopedDb.execute(sql8`
|
|
23983
24590
|
select lease.* from sandbox_leases as lease
|
|
23984
24591
|
where lease.workspace_id = ${input.workspaceId}
|
|
23985
24592
|
and lease.sandbox_group_id = ${input.sandboxGroupId}
|
|
23986
24593
|
and lease.liveness = ${input.liveness}
|
|
23987
24594
|
and lease.lease_epoch = ${input.expectedEpoch}
|
|
23988
24595
|
and lease.instance_id = ${input.expectedInstanceId}
|
|
23989
|
-
${input.liveness === "draining" ?
|
|
24596
|
+
${input.liveness === "draining" ? sql8`and lease.refcount = 0` : sql8``}
|
|
23990
24597
|
and not exists (
|
|
23991
24598
|
select 1
|
|
23992
24599
|
from sandbox_workspace_mutation_admissions as admission
|
|
@@ -24076,7 +24683,7 @@ async function claimWorkspaceArchiveCapture(db, input) {
|
|
|
24076
24683
|
const attemptMayCapture = attempt !== void 0 && attempt.accountId === input.accountId && attempt.sandboxGroupId === input.sandboxGroupId && attempt.activeAttemptId === input.warmAttempt.attemptId && !interruption && (attempt.state === "claimed" || attempt.state === "running" ? attempt.outcome === null : attempt.state === "closed" && (attempt.outcome === "completed" || attempt.outcome === "failed" || attempt.outcome === "requires_action"));
|
|
24077
24684
|
if (!attemptMayCapture) return { status: "attempt_fenced" };
|
|
24078
24685
|
}
|
|
24079
|
-
const rows = await scopedDb.execute(
|
|
24686
|
+
const rows = await scopedDb.execute(sql8`
|
|
24080
24687
|
select lease.*
|
|
24081
24688
|
from sandbox_leases lease
|
|
24082
24689
|
where lease.account_id = ${input.accountId}
|
|
@@ -24091,7 +24698,7 @@ async function claimWorkspaceArchiveCapture(db, input) {
|
|
|
24091
24698
|
if (row.archive_capture_id !== null) {
|
|
24092
24699
|
return { status: "capture_in_progress" };
|
|
24093
24700
|
}
|
|
24094
|
-
const holderCounts = input.warmAttempt ? await scopedDb.execute(
|
|
24701
|
+
const holderCounts = input.warmAttempt ? await scopedDb.execute(sql8`
|
|
24095
24702
|
select
|
|
24096
24703
|
count(*)::integer as total,
|
|
24097
24704
|
count(*) filter (
|
|
@@ -24100,7 +24707,7 @@ async function claimWorkspaceArchiveCapture(db, input) {
|
|
|
24100
24707
|
)::integer as exact
|
|
24101
24708
|
from sandbox_lease_holders
|
|
24102
24709
|
where lease_id = ${row.id}
|
|
24103
|
-
`) : await scopedDb.execute(
|
|
24710
|
+
`) : await scopedDb.execute(sql8`
|
|
24104
24711
|
select count(*)::integer as total, 0::integer as exact
|
|
24105
24712
|
from sandbox_lease_holders
|
|
24106
24713
|
where lease_id = ${row.id}
|
|
@@ -24112,7 +24719,7 @@ async function claimWorkspaceArchiveCapture(db, input) {
|
|
|
24112
24719
|
if ((holderCounts[0]?.total ?? 0) !== expectedHolderCount) {
|
|
24113
24720
|
return { status: "holder_in_progress" };
|
|
24114
24721
|
}
|
|
24115
|
-
const unsettled = await scopedDb.execute(
|
|
24722
|
+
const unsettled = await scopedDb.execute(sql8`
|
|
24116
24723
|
select exists (
|
|
24117
24724
|
select 1
|
|
24118
24725
|
from sandbox_workspace_mutation_admissions admission
|
|
@@ -24146,7 +24753,7 @@ async function claimWorkspaceArchiveCapture(db, input) {
|
|
|
24146
24753
|
}
|
|
24147
24754
|
const startedAt = /* @__PURE__ */ new Date();
|
|
24148
24755
|
const deadlineAt = new Date(startedAt.getTime() + input.captureTimeoutMs);
|
|
24149
|
-
const claimed = await scopedDb.execute(
|
|
24756
|
+
const claimed = await scopedDb.execute(sql8`
|
|
24150
24757
|
update sandbox_leases set
|
|
24151
24758
|
archive_capture_id = ${input.captureId}::uuid,
|
|
24152
24759
|
archive_capture_generation = workspace_generation,
|
|
@@ -24187,7 +24794,7 @@ async function releaseWorkspaceArchiveCapture(db, input) {
|
|
|
24187
24794
|
db,
|
|
24188
24795
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
24189
24796
|
async (scopedDb) => {
|
|
24190
|
-
const rows = await scopedDb.execute(
|
|
24797
|
+
const rows = await scopedDb.execute(sql8`
|
|
24191
24798
|
update sandbox_leases set
|
|
24192
24799
|
archive_capture_id = null,
|
|
24193
24800
|
archive_capture_generation = null,
|
|
@@ -24215,7 +24822,7 @@ async function replaceExpiredWorkspaceArchiveCapture(db, input) {
|
|
|
24215
24822
|
db,
|
|
24216
24823
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
24217
24824
|
async (scopedDb) => {
|
|
24218
|
-
const rows = await scopedDb.execute(
|
|
24825
|
+
const rows = await scopedDb.execute(sql8`
|
|
24219
24826
|
update sandbox_leases as lease set
|
|
24220
24827
|
archive_capture_id = ${input.captureId}::uuid,
|
|
24221
24828
|
archive_capture_generation = lease.workspace_generation,
|
|
@@ -24317,7 +24924,7 @@ async function registerSandboxCheckpointArtifact(db, input) {
|
|
|
24317
24924
|
db,
|
|
24318
24925
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
24319
24926
|
async (scopedDb) => {
|
|
24320
|
-
const inserted = await scopedDb.execute(
|
|
24927
|
+
const inserted = await scopedDb.execute(sql8`
|
|
24321
24928
|
insert into sandbox_checkpoint_artifacts (
|
|
24322
24929
|
account_id, workspace_id, sandbox_group_id, source_lease_id,
|
|
24323
24930
|
source_lease_epoch, source_instance_id, source_workspace_generation,
|
|
@@ -24337,7 +24944,7 @@ async function registerSandboxCheckpointArtifact(db, input) {
|
|
|
24337
24944
|
do nothing
|
|
24338
24945
|
returning id, state, object_id
|
|
24339
24946
|
`);
|
|
24340
|
-
const row = inserted[0] ?? (await scopedDb.execute(
|
|
24947
|
+
const row = inserted[0] ?? (await scopedDb.execute(sql8`
|
|
24341
24948
|
select id, state, object_id, account_id, workspace_id,
|
|
24342
24949
|
sandbox_group_id, source_lease_id, source_lease_epoch,
|
|
24343
24950
|
source_instance_id, source_workspace_generation, provenance,
|
|
@@ -24350,7 +24957,7 @@ async function registerSandboxCheckpointArtifact(db, input) {
|
|
|
24350
24957
|
limit 1
|
|
24351
24958
|
for update
|
|
24352
24959
|
`))[0];
|
|
24353
|
-
if (!row || "account_id" in row && (row.account_id !== input.accountId || row.workspace_id !== input.workspaceId || row.sandbox_group_id !== input.sandboxGroupId || row.source_lease_id !== input.sourceLeaseId || Number(row.source_lease_epoch) !== input.sourceLeaseEpoch || row.source_instance_id !== input.sourceInstanceId || row.source_workspace_generation === null || Number(row.source_workspace_generation) !== input.sourceWorkspaceGeneration || row.provenance !== "native_capture" || row.archive_base64 !== input.workspaceArchive || row.archive_sha256 !== verified.descriptor.archiveSha256 ||
|
|
24960
|
+
if (!row || "account_id" in row && (row.account_id !== input.accountId || row.workspace_id !== input.workspaceId || row.sandbox_group_id !== input.sandboxGroupId || row.source_lease_id !== input.sourceLeaseId || Number(row.source_lease_epoch) !== input.sourceLeaseEpoch || row.source_instance_id !== input.sourceInstanceId || row.source_workspace_generation === null || Number(row.source_workspace_generation) !== input.sourceWorkspaceGeneration || row.provenance !== "native_capture" || row.archive_base64 !== input.workspaceArchive || row.archive_sha256 !== verified.descriptor.archiveSha256 || stableJson3(row.descriptor) !== stableJson3(verified.descriptor) || row.descriptor_revision !== verified.descriptor.revision || row.object_kind !== verified.objectKind || canonicalModalCheckpointProviderBinding(row.provider_binding)?.key !== providerIdentity.key)) {
|
|
24354
24961
|
throw new SandboxCheckpointArtifactRegistrationConflictError(
|
|
24355
24962
|
"Modal checkpoint object identity collision"
|
|
24356
24963
|
);
|
|
@@ -24377,7 +24984,7 @@ async function markSandboxCheckpointArtifactDeletePending(db, input) {
|
|
|
24377
24984
|
db,
|
|
24378
24985
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
24379
24986
|
async (scopedDb) => {
|
|
24380
|
-
const rows = await scopedDb.execute(
|
|
24987
|
+
const rows = await scopedDb.execute(sql8`
|
|
24381
24988
|
update sandbox_checkpoint_artifacts artifact set
|
|
24382
24989
|
state = 'delete_pending',
|
|
24383
24990
|
delete_after = now(),
|
|
@@ -24399,7 +25006,7 @@ async function markSandboxCheckpointArtifactDeletePending(db, input) {
|
|
|
24399
25006
|
async function claimSandboxCheckpointArtifactsForGc(db, input) {
|
|
24400
25007
|
const rows = await rawRows(
|
|
24401
25008
|
db,
|
|
24402
|
-
|
|
25009
|
+
sql8`select * from opengeni_private.claim_sandbox_checkpoint_artifacts(
|
|
24403
25010
|
${input.claimId}::uuid, ${input.limit}, ${input.claimTtlMs}
|
|
24404
25011
|
)`
|
|
24405
25012
|
);
|
|
@@ -24416,7 +25023,7 @@ async function claimSandboxCheckpointArtifactsForGc(db, input) {
|
|
|
24416
25023
|
async function settleSandboxCheckpointArtifactGc(db, input) {
|
|
24417
25024
|
const rows = await rawRows(
|
|
24418
25025
|
db,
|
|
24419
|
-
|
|
25026
|
+
sql8`select opengeni_private.settle_sandbox_checkpoint_artifact(
|
|
24420
25027
|
${input.artifactId}::uuid, ${input.claimId}::uuid, ${input.deleted},
|
|
24421
25028
|
${input.error?.slice(0, 4e3) ?? null}, ${input.retryAfterMs}
|
|
24422
25029
|
) as settled`
|
|
@@ -24426,7 +25033,7 @@ async function settleSandboxCheckpointArtifactGc(db, input) {
|
|
|
24426
25033
|
async function pruneDeletedSandboxCheckpointArtifacts(db, retentionMs, limit) {
|
|
24427
25034
|
const rows = await rawRows(
|
|
24428
25035
|
db,
|
|
24429
|
-
|
|
25036
|
+
sql8`select opengeni_private.prune_deleted_sandbox_checkpoint_artifacts(
|
|
24430
25037
|
${retentionMs}, ${limit}
|
|
24431
25038
|
) as pruned`
|
|
24432
25039
|
);
|
|
@@ -24435,7 +25042,7 @@ async function pruneDeletedSandboxCheckpointArtifacts(db, retentionMs, limit) {
|
|
|
24435
25042
|
async function requestDueSandboxRotationsGlobal(db, leadMs, limit) {
|
|
24436
25043
|
const rows = await rawRows(
|
|
24437
25044
|
db,
|
|
24438
|
-
|
|
25045
|
+
sql8`select opengeni_private.request_due_sandbox_rotations(
|
|
24439
25046
|
${leadMs}, ${limit}
|
|
24440
25047
|
) as requested`
|
|
24441
25048
|
);
|
|
@@ -24456,7 +25063,7 @@ async function countSandboxCheckpointArtifactsByState(db) {
|
|
|
24456
25063
|
);
|
|
24457
25064
|
const rows = await rawRows(
|
|
24458
25065
|
db,
|
|
24459
|
-
|
|
25066
|
+
sql8`select state, count
|
|
24460
25067
|
from opengeni_private.sandbox_checkpoint_artifact_inventory()`
|
|
24461
25068
|
);
|
|
24462
25069
|
for (const row of rows) {
|
|
@@ -24467,7 +25074,7 @@ async function countSandboxCheckpointArtifactsByState(db) {
|
|
|
24467
25074
|
return counts;
|
|
24468
25075
|
}
|
|
24469
25076
|
async function readSandboxRotationBacklog(db) {
|
|
24470
|
-
const rows = await rawRows(db,
|
|
25077
|
+
const rows = await rawRows(db, sql8`select * from opengeni_private.sandbox_rotation_backlog()`);
|
|
24471
25078
|
const row = rows[0];
|
|
24472
25079
|
return {
|
|
24473
25080
|
requested: Number(row?.requested ?? 0),
|
|
@@ -24478,7 +25085,7 @@ async function readSandboxRotationBacklog(db) {
|
|
|
24478
25085
|
};
|
|
24479
25086
|
}
|
|
24480
25087
|
async function listLegacyModalCheckpointSlots(db, limit = 100) {
|
|
24481
|
-
const rows = await rawRows(db,
|
|
25088
|
+
const rows = await rawRows(db, sql8`select * from opengeni_private.list_legacy_modal_checkpoint_slots(${limit})`);
|
|
24482
25089
|
return rows.flatMap((row) => {
|
|
24483
25090
|
const descriptor = parseArchiveRevision(row.descriptor);
|
|
24484
25091
|
return descriptor?.version === 2 ? [
|
|
@@ -24510,7 +25117,7 @@ async function adoptLegacyModalCheckpointArtifact(db, input) {
|
|
|
24510
25117
|
db,
|
|
24511
25118
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
24512
25119
|
async (scopedDb) => {
|
|
24513
|
-
const leaseRows = await scopedDb.execute(
|
|
25120
|
+
const leaseRows = await scopedDb.execute(sql8`
|
|
24514
25121
|
select lease.id, lease.current_checkpoint_artifact_id,
|
|
24515
25122
|
lease.previous_checkpoint_artifact_id
|
|
24516
25123
|
from sandbox_leases lease
|
|
@@ -24522,16 +25129,16 @@ async function adoptLegacyModalCheckpointArtifact(db, input) {
|
|
|
24522
25129
|
and lease.workspace_generation = ${input.workspaceGeneration}
|
|
24523
25130
|
and lease.backend = 'modal'
|
|
24524
25131
|
and lease.liveness in ('warming', 'warm', 'draining')
|
|
24525
|
-
${input.rematerializationId ?
|
|
25132
|
+
${input.rematerializationId ? sql8`and lease.liveness = 'warming'
|
|
24526
25133
|
and lease.resume_state #>> '{opengeniRecovery,restore,rematerializationId}' =
|
|
24527
25134
|
${input.rematerializationId}
|
|
24528
25135
|
and lease.resume_state #>> '{opengeniRecovery,restore,status}' in
|
|
24529
|
-
('restoring', 'verifying')` :
|
|
24530
|
-
and ${input.slot === "current" ?
|
|
25136
|
+
('restoring', 'verifying')` : sql8``}
|
|
25137
|
+
and ${input.slot === "current" ? sql8`lease.archive_generation = lease.workspace_generation
|
|
24531
25138
|
and lease.resume_state #>> '{sessionState,workspaceArchive}' =
|
|
24532
25139
|
${input.archiveBase64}
|
|
24533
25140
|
and lease.resume_state #> '{sessionState,workspaceArchiveMeta}' =
|
|
24534
|
-
${JSON.stringify(input.descriptor)}::jsonb` :
|
|
25141
|
+
${JSON.stringify(input.descriptor)}::jsonb` : sql8`lease.resume_state #>> '{sessionState,workspaceArchivePrev}' =
|
|
24535
25142
|
${input.archiveBase64}
|
|
24536
25143
|
and lease.resume_state #> '{sessionState,workspaceArchivePrevMeta}' =
|
|
24537
25144
|
${JSON.stringify(input.descriptor)}::jsonb`}
|
|
@@ -24541,7 +25148,7 @@ async function adoptLegacyModalCheckpointArtifact(db, input) {
|
|
|
24541
25148
|
if (!lease) return false;
|
|
24542
25149
|
const existingReference = input.slot === "current" ? lease.current_checkpoint_artifact_id : lease.previous_checkpoint_artifact_id;
|
|
24543
25150
|
if (existingReference !== null) {
|
|
24544
|
-
const exact = await scopedDb.execute(
|
|
25151
|
+
const exact = await scopedDb.execute(sql8`
|
|
24545
25152
|
select artifact.id
|
|
24546
25153
|
from sandbox_checkpoint_artifacts artifact
|
|
24547
25154
|
where artifact.id = ${existingReference}::uuid
|
|
@@ -24565,7 +25172,7 @@ async function adoptLegacyModalCheckpointArtifact(db, input) {
|
|
|
24565
25172
|
`);
|
|
24566
25173
|
return exact.length === 1;
|
|
24567
25174
|
}
|
|
24568
|
-
const inserted = await scopedDb.execute(
|
|
25175
|
+
const inserted = await scopedDb.execute(sql8`
|
|
24569
25176
|
insert into sandbox_checkpoint_artifacts (
|
|
24570
25177
|
account_id, workspace_id, sandbox_group_id, source_lease_id,
|
|
24571
25178
|
source_lease_epoch, source_instance_id, source_workspace_generation,
|
|
@@ -24585,7 +25192,7 @@ async function adoptLegacyModalCheckpointArtifact(db, input) {
|
|
|
24585
25192
|
do nothing
|
|
24586
25193
|
returning id, state
|
|
24587
25194
|
`);
|
|
24588
|
-
const artifact = inserted[0] ?? (await scopedDb.execute(
|
|
25195
|
+
const artifact = inserted[0] ?? (await scopedDb.execute(sql8`
|
|
24589
25196
|
select id, state, account_id, workspace_id, sandbox_group_id,
|
|
24590
25197
|
source_lease_id, source_lease_epoch, source_instance_id,
|
|
24591
25198
|
source_workspace_generation, provenance, archive_base64,
|
|
@@ -24597,7 +25204,7 @@ async function adoptLegacyModalCheckpointArtifact(db, input) {
|
|
|
24597
25204
|
limit 1
|
|
24598
25205
|
for update
|
|
24599
25206
|
`))[0];
|
|
24600
|
-
const exactExisting = artifact !== void 0 && (!("account_id" in artifact) || artifact.account_id === input.accountId && artifact.workspace_id === input.workspaceId && artifact.sandbox_group_id === input.sandboxGroupId && artifact.source_lease_id === input.leaseId && Number(artifact.source_lease_epoch) === input.leaseEpoch && artifact.source_instance_id === null && artifact.source_workspace_generation === null && artifact.provenance === "legacy_provider_adopted" && artifact.archive_base64 === input.archiveBase64 && artifact.archive_sha256 === verified.descriptor.archiveSha256 &&
|
|
25207
|
+
const exactExisting = artifact !== void 0 && (!("account_id" in artifact) || artifact.account_id === input.accountId && artifact.workspace_id === input.workspaceId && artifact.sandbox_group_id === input.sandboxGroupId && artifact.source_lease_id === input.leaseId && Number(artifact.source_lease_epoch) === input.leaseEpoch && artifact.source_instance_id === null && artifact.source_workspace_generation === null && artifact.provenance === "legacy_provider_adopted" && artifact.archive_base64 === input.archiveBase64 && artifact.archive_sha256 === verified.descriptor.archiveSha256 && stableJson3(artifact.descriptor) === stableJson3(verified.descriptor) && artifact.descriptor_revision === verified.descriptor.revision && artifact.object_kind === verified.objectKind);
|
|
24601
25208
|
if (!artifact || !exactExisting || artifact.state === "deleted") {
|
|
24602
25209
|
throw new SandboxCheckpointArtifactRegistrationConflictError(
|
|
24603
25210
|
"Modal checkpoint object identity collision"
|
|
@@ -24608,7 +25215,7 @@ async function adoptLegacyModalCheckpointArtifact(db, input) {
|
|
|
24608
25215
|
"Legacy Modal checkpoint is already owned by another archive slot"
|
|
24609
25216
|
);
|
|
24610
25217
|
}
|
|
24611
|
-
const published = await scopedDb.execute(
|
|
25218
|
+
const published = await scopedDb.execute(sql8`
|
|
24612
25219
|
update sandbox_checkpoint_artifacts set
|
|
24613
25220
|
state = ${input.slot}, published_at = coalesce(published_at, now()),
|
|
24614
25221
|
delete_after = null, last_delete_error = null, updated_at = now()
|
|
@@ -24618,12 +25225,12 @@ async function adoptLegacyModalCheckpointArtifact(db, input) {
|
|
|
24618
25225
|
if (published.length !== 1) {
|
|
24619
25226
|
throw new Error("Legacy Modal checkpoint adoption lost its locked provider object");
|
|
24620
25227
|
}
|
|
24621
|
-
const attached = await scopedDb.execute(
|
|
25228
|
+
const attached = await scopedDb.execute(sql8`
|
|
24622
25229
|
update sandbox_leases lease set
|
|
24623
|
-
${input.slot === "current" ?
|
|
25230
|
+
${input.slot === "current" ? sql8`current_checkpoint_artifact_id = ${artifact.id}::uuid` : sql8`previous_checkpoint_artifact_id = ${artifact.id}::uuid`},
|
|
24624
25231
|
updated_at = now()
|
|
24625
25232
|
where lease.id = ${input.leaseId}::uuid
|
|
24626
|
-
and ${input.slot === "current" ?
|
|
25233
|
+
and ${input.slot === "current" ? sql8`lease.current_checkpoint_artifact_id is null` : sql8`lease.previous_checkpoint_artifact_id is null`}
|
|
24627
25234
|
returning lease.id
|
|
24628
25235
|
`);
|
|
24629
25236
|
if (attached.length !== 1) {
|
|
@@ -24645,7 +25252,7 @@ async function persistDrainSnapshot(db, input) {
|
|
|
24645
25252
|
db,
|
|
24646
25253
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
24647
25254
|
async (scopedDb) => {
|
|
24648
|
-
const guard = await scopedDb.execute(
|
|
25255
|
+
const guard = await scopedDb.execute(sql8`
|
|
24649
25256
|
select
|
|
24650
25257
|
resume_state #>> '{sessionState,workspaceArchive}' as prior_archive,
|
|
24651
25258
|
resume_state #>> '{sessionState,workspaceArchivePrev}' as prior_archive_prev,
|
|
@@ -24693,7 +25300,7 @@ async function persistDrainSnapshot(db, input) {
|
|
|
24693
25300
|
const priorArchive = guard[0].prior_archive ?? null;
|
|
24694
25301
|
const priorArchivePrev = guard[0].prior_archive_prev ?? null;
|
|
24695
25302
|
if (input.workspaceArchive === null) {
|
|
24696
|
-
await scopedDb.execute(
|
|
25303
|
+
await scopedDb.execute(sql8`
|
|
24697
25304
|
update sandbox_leases set
|
|
24698
25305
|
archive_capture_id = null,
|
|
24699
25306
|
archive_capture_generation = null,
|
|
@@ -24764,7 +25371,7 @@ function rotateWorkspaceArchives(input) {
|
|
|
24764
25371
|
};
|
|
24765
25372
|
}
|
|
24766
25373
|
async function foldWorkspaceArchiveOntoLease(scopedDb, input) {
|
|
24767
|
-
const livenessGuard = input.livenessGuard === "draining" ?
|
|
25374
|
+
const livenessGuard = input.livenessGuard === "draining" ? sql8`lease.liveness = 'draining' and lease.refcount = 0` : sql8`lease.liveness = 'warm'`;
|
|
24768
25375
|
const archiveAtIso = input.workspaceArchiveMeta?.capturedAt ?? input.archiveAtIso ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
24769
25376
|
const base = input.resumeState && typeof input.resumeState === "object" ? input.resumeState : {};
|
|
24770
25377
|
const currentSession = base.sessionState && typeof base.sessionState === "object" ? base.sessionState : {};
|
|
@@ -24795,7 +25402,7 @@ async function foldWorkspaceArchiveOntoLease(scopedDb, input) {
|
|
|
24795
25402
|
archive: archiveProjectionFromResumeState(folded)
|
|
24796
25403
|
};
|
|
24797
25404
|
const foldedJson = JSON.stringify(folded);
|
|
24798
|
-
const rows = await scopedDb.execute(
|
|
25405
|
+
const rows = await scopedDb.execute(sql8`
|
|
24799
25406
|
update sandbox_leases as lease set
|
|
24800
25407
|
resume_state = ${foldedJson}::jsonb,
|
|
24801
25408
|
archive_generation = ${input.expectedWorkspaceGeneration},
|
|
@@ -24857,7 +25464,7 @@ async function foldWorkspaceArchiveOntoLease(scopedDb, input) {
|
|
|
24857
25464
|
`);
|
|
24858
25465
|
if (rows.length === 0) return false;
|
|
24859
25466
|
if (input.checkpointArtifactId) {
|
|
24860
|
-
await scopedDb.execute(
|
|
25467
|
+
await scopedDb.execute(sql8`
|
|
24861
25468
|
update sandbox_checkpoint_artifacts set
|
|
24862
25469
|
state = 'current', published_at = coalesce(published_at, now()),
|
|
24863
25470
|
delete_after = null, last_delete_error = null, updated_at = now()
|
|
@@ -24865,7 +25472,7 @@ async function foldWorkspaceArchiveOntoLease(scopedDb, input) {
|
|
|
24865
25472
|
`);
|
|
24866
25473
|
}
|
|
24867
25474
|
if (input.previousCheckpointArtifactId && input.previousCheckpointArtifactId !== input.checkpointArtifactId) {
|
|
24868
|
-
await scopedDb.execute(
|
|
25475
|
+
await scopedDb.execute(sql8`
|
|
24869
25476
|
update sandbox_checkpoint_artifacts set
|
|
24870
25477
|
state = 'previous', delete_after = null, last_delete_error = null,
|
|
24871
25478
|
updated_at = now()
|
|
@@ -24880,12 +25487,12 @@ async function foldWorkspaceArchiveOntoLease(scopedDb, input) {
|
|
|
24880
25487
|
(id) => id !== null && id !== input.checkpointArtifactId && id !== input.previousCheckpointArtifactId
|
|
24881
25488
|
);
|
|
24882
25489
|
if (evictedArtifactIds.length > 0) {
|
|
24883
|
-
await scopedDb.execute(
|
|
25490
|
+
await scopedDb.execute(sql8`
|
|
24884
25491
|
update sandbox_checkpoint_artifacts set
|
|
24885
25492
|
state = 'delete_pending', delete_after = now(), updated_at = now()
|
|
24886
|
-
where id in (${
|
|
24887
|
-
evictedArtifactIds.map((id) =>
|
|
24888
|
-
|
|
25493
|
+
where id in (${sql8.join(
|
|
25494
|
+
evictedArtifactIds.map((id) => sql8`${id}::uuid`),
|
|
25495
|
+
sql8`, `
|
|
24889
25496
|
)})
|
|
24890
25497
|
and state in ('current', 'previous', 'candidate', 'delete_failed')
|
|
24891
25498
|
`);
|
|
@@ -24941,7 +25548,7 @@ async function persistWarmSnapshot(db, input) {
|
|
|
24941
25548
|
archiveRevision: null
|
|
24942
25549
|
};
|
|
24943
25550
|
}
|
|
24944
|
-
const guard = await scopedDb.execute(
|
|
25551
|
+
const guard = await scopedDb.execute(sql8`
|
|
24945
25552
|
select
|
|
24946
25553
|
resume_state #>> '{sessionState,workspaceArchive}' as prior_archive,
|
|
24947
25554
|
resume_state #>> '{sessionState,workspaceArchivePrev}' as prior_archive_prev,
|
|
@@ -25056,7 +25663,7 @@ async function getMaterializedSandboxFileResources(db, input) {
|
|
|
25056
25663
|
db,
|
|
25057
25664
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
25058
25665
|
async (scopedDb) => {
|
|
25059
|
-
const rows = await scopedDb.execute(
|
|
25666
|
+
const rows = await scopedDb.execute(sql8`
|
|
25060
25667
|
select coalesce(
|
|
25061
25668
|
jsonb_path_query_array(
|
|
25062
25669
|
resume_state,
|
|
@@ -25086,7 +25693,7 @@ async function markSandboxFileResourcesMaterialized(db, input) {
|
|
|
25086
25693
|
db,
|
|
25087
25694
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
25088
25695
|
async (scopedDb) => {
|
|
25089
|
-
const rows = await scopedDb.execute(
|
|
25696
|
+
const rows = await scopedDb.execute(sql8`
|
|
25090
25697
|
update sandbox_leases set
|
|
25091
25698
|
resume_state = jsonb_set(
|
|
25092
25699
|
case when jsonb_typeof(resume_state) = 'object' then resume_state else '{}'::jsonb end,
|
|
@@ -25130,7 +25737,7 @@ async function markSandboxFileResourcesMaterialized(db, input) {
|
|
|
25130
25737
|
}
|
|
25131
25738
|
);
|
|
25132
25739
|
}
|
|
25133
|
-
var WORKSPACE_CAPTURE_COLUMNS =
|
|
25740
|
+
var WORKSPACE_CAPTURE_COLUMNS = sql8`
|
|
25134
25741
|
id, session_id, turn_id, revision, lease_epoch, state,
|
|
25135
25742
|
manifest_key, tree_index_key, blob_keys, size_bytes, stats, captured_at
|
|
25136
25743
|
`;
|
|
@@ -25180,7 +25787,7 @@ async function commitWorkspaceCaptureRevision(db, input) {
|
|
|
25180
25787
|
return null;
|
|
25181
25788
|
}
|
|
25182
25789
|
const capturedAt = input.capturedAt ?? /* @__PURE__ */ new Date();
|
|
25183
|
-
const rows = await tx.execute(
|
|
25790
|
+
const rows = await tx.execute(sql8`
|
|
25184
25791
|
insert into workspace_captures
|
|
25185
25792
|
(account_id, workspace_id, session_id, turn_id, revision, lease_epoch, state,
|
|
25186
25793
|
manifest_key, tree_index_key, blob_keys, size_bytes, stats, captured_at)
|
|
@@ -25262,7 +25869,7 @@ async function insertFailedWorkspaceCapture(db, input) {
|
|
|
25262
25869
|
}
|
|
25263
25870
|
async function latestWorkspaceCapture(db, workspaceId, sessionId) {
|
|
25264
25871
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
25265
|
-
const rows = await scopedDb.execute(
|
|
25872
|
+
const rows = await scopedDb.execute(sql8`
|
|
25266
25873
|
select ${WORKSPACE_CAPTURE_COLUMNS} from workspace_captures
|
|
25267
25874
|
where session_id = ${sessionId}
|
|
25268
25875
|
order by revision desc
|
|
@@ -25273,7 +25880,7 @@ async function latestWorkspaceCapture(db, workspaceId, sessionId) {
|
|
|
25273
25880
|
}
|
|
25274
25881
|
async function sessionLatestWorkspaceCapture(db, workspaceId, sessionId) {
|
|
25275
25882
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
25276
|
-
const rows = await scopedDb.execute(
|
|
25883
|
+
const rows = await scopedDb.execute(sql8`
|
|
25277
25884
|
select
|
|
25278
25885
|
sessions.id as found_session_id,
|
|
25279
25886
|
capture.id as capture_id,
|
|
@@ -25323,7 +25930,7 @@ async function sessionLatestWorkspaceCapture(db, workspaceId, sessionId) {
|
|
|
25323
25930
|
}
|
|
25324
25931
|
async function workspaceCaptureAtRevision(db, workspaceId, sessionId, revision) {
|
|
25325
25932
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
25326
|
-
const rows = await scopedDb.execute(
|
|
25933
|
+
const rows = await scopedDb.execute(sql8`
|
|
25327
25934
|
select ${WORKSPACE_CAPTURE_COLUMNS} from workspace_captures
|
|
25328
25935
|
where session_id = ${sessionId} and revision = ${revision}
|
|
25329
25936
|
limit 1
|
|
@@ -25353,7 +25960,7 @@ function computeWorkspaceCaptureGcPlan(rows, keepN) {
|
|
|
25353
25960
|
}
|
|
25354
25961
|
async function planWorkspaceCaptureGc(db, input) {
|
|
25355
25962
|
return await withWorkspaceRls(db, input.workspaceId, async (scopedDb) => {
|
|
25356
|
-
const rows = await scopedDb.execute(
|
|
25963
|
+
const rows = await scopedDb.execute(sql8`
|
|
25357
25964
|
select id, revision, manifest_key, tree_index_key, blob_keys
|
|
25358
25965
|
from workspace_captures
|
|
25359
25966
|
where session_id = ${input.sessionId}
|
|
@@ -25375,11 +25982,11 @@ async function planWorkspaceCaptureGc(db, input) {
|
|
|
25375
25982
|
async function deleteWorkspaceCaptureRows(db, input) {
|
|
25376
25983
|
if (input.rowIds.length === 0) return 0;
|
|
25377
25984
|
return await withWorkspaceRls(db, input.workspaceId, async (scopedDb) => {
|
|
25378
|
-
const result = await scopedDb.execute(
|
|
25985
|
+
const result = await scopedDb.execute(sql8`
|
|
25379
25986
|
delete from workspace_captures
|
|
25380
|
-
where id in (${
|
|
25381
|
-
input.rowIds.map((id) =>
|
|
25382
|
-
|
|
25987
|
+
where id in (${sql8.join(
|
|
25988
|
+
input.rowIds.map((id) => sql8`${id}`),
|
|
25989
|
+
sql8`, `
|
|
25383
25990
|
)})
|
|
25384
25991
|
returning id
|
|
25385
25992
|
`);
|
|
@@ -25388,7 +25995,7 @@ async function deleteWorkspaceCaptureRows(db, input) {
|
|
|
25388
25995
|
}
|
|
25389
25996
|
async function readLease(db, workspaceId, sandboxGroupId) {
|
|
25390
25997
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
25391
|
-
const rows = await scopedDb.execute(
|
|
25998
|
+
const rows = await scopedDb.execute(sql8`
|
|
25392
25999
|
select * from sandbox_leases
|
|
25393
26000
|
where workspace_id = ${workspaceId} and sandbox_group_id = ${sandboxGroupId}
|
|
25394
26001
|
limit 1
|
|
@@ -25401,7 +26008,7 @@ async function recordLeaseDataPlaneUrl(db, input) {
|
|
|
25401
26008
|
db,
|
|
25402
26009
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
25403
26010
|
async (scopedDb) => {
|
|
25404
|
-
const rows = await scopedDb.execute(
|
|
26011
|
+
const rows = await scopedDb.execute(sql8`
|
|
25405
26012
|
update sandbox_leases set
|
|
25406
26013
|
data_plane_url = ${input.dataPlaneUrl ?? null},
|
|
25407
26014
|
updated_at = now()
|
|
@@ -25419,7 +26026,7 @@ async function recordLeaseTerminalDataPlaneUrl(db, input) {
|
|
|
25419
26026
|
db,
|
|
25420
26027
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
25421
26028
|
async (scopedDb) => {
|
|
25422
|
-
const rows = await scopedDb.execute(
|
|
26029
|
+
const rows = await scopedDb.execute(sql8`
|
|
25423
26030
|
update sandbox_leases set
|
|
25424
26031
|
terminal_data_plane_url = ${input.terminalDataPlaneUrl ?? null},
|
|
25425
26032
|
updated_at = now()
|
|
@@ -25618,7 +26225,7 @@ async function setEnrollmentDisplayState(db, input) {
|
|
|
25618
26225
|
// null-safe inequality (a plain `ne` skips NULL rows).
|
|
25619
26226
|
or3(
|
|
25620
26227
|
ne(enrollments.hasDisplay, input.hasDisplay),
|
|
25621
|
-
|
|
26228
|
+
sql8`${enrollments.desktopUnavailableReason} IS DISTINCT FROM ${input.desktopUnavailableReason}`
|
|
25622
26229
|
)
|
|
25623
26230
|
)
|
|
25624
26231
|
).returning({ id: enrollments.id });
|
|
@@ -25699,7 +26306,7 @@ async function createDeviceEnrollmentRequest(db, input) {
|
|
|
25699
26306
|
);
|
|
25700
26307
|
}
|
|
25701
26308
|
async function getDeviceEnrollmentRequestByDeviceCode(db, deviceCode) {
|
|
25702
|
-
const resolved = await db.execute(
|
|
26309
|
+
const resolved = await db.execute(sql8`
|
|
25703
26310
|
select account_id, workspace_id from opengeni_private.resolve_device_enrollment_request(${deviceCode})
|
|
25704
26311
|
`);
|
|
25705
26312
|
const ctx = resolved[0];
|
|
@@ -25728,7 +26335,7 @@ async function getPendingDeviceEnrollmentRequestByUserCode(db, workspaceId, user
|
|
|
25728
26335
|
});
|
|
25729
26336
|
}
|
|
25730
26337
|
async function getPendingDeviceEnrollmentRequestByUserCodeGlobal(db, userCode) {
|
|
25731
|
-
const resolved = await db.execute(
|
|
26338
|
+
const resolved = await db.execute(sql8`
|
|
25732
26339
|
select account_id, workspace_id from opengeni_private.resolve_pending_device_enrollment_by_user_code(${userCode})
|
|
25733
26340
|
`);
|
|
25734
26341
|
const ctx = resolved[0];
|
|
@@ -25978,11 +26585,11 @@ async function setActiveSandbox(db, input) {
|
|
|
25978
26585
|
db,
|
|
25979
26586
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
25980
26587
|
async (scopedDb) => {
|
|
25981
|
-
const rows = await scopedDb.execute(
|
|
26588
|
+
const rows = await scopedDb.execute(sql8`
|
|
25982
26589
|
update sessions set
|
|
25983
26590
|
active_sandbox_id = ${input.targetSandboxId},
|
|
25984
26591
|
active_epoch = active_epoch + 1,
|
|
25985
|
-
working_dir = ${input.workingDir === void 0 ?
|
|
26592
|
+
working_dir = ${input.workingDir === void 0 ? sql8`working_dir` : input.workingDir},
|
|
25986
26593
|
updated_at = now()
|
|
25987
26594
|
where workspace_id = ${input.workspaceId} and id = ${input.sessionId}
|
|
25988
26595
|
and active_epoch = ${input.expectedEpoch}
|
|
@@ -26146,7 +26753,7 @@ async function recordStreamAcknowledgment(db, input) {
|
|
|
26146
26753
|
db,
|
|
26147
26754
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
26148
26755
|
async (scopedDb) => {
|
|
26149
|
-
const rows = await scopedDb.execute(
|
|
26756
|
+
const rows = await scopedDb.execute(sql8`
|
|
26150
26757
|
insert into session_stream_acknowledgments
|
|
26151
26758
|
(account_id, workspace_id, sandbox_group_id, subject_id,
|
|
26152
26759
|
acknowledged_unredacted, acknowledged_shared, acknowledged_at, updated_at)
|
|
@@ -26172,7 +26779,7 @@ async function recordStreamAcknowledgment(db, input) {
|
|
|
26172
26779
|
}
|
|
26173
26780
|
async function getStreamAcknowledgment(db, input) {
|
|
26174
26781
|
return await withWorkspaceRls(db, input.workspaceId, async (scopedDb) => {
|
|
26175
|
-
const rows = await scopedDb.execute(
|
|
26782
|
+
const rows = await scopedDb.execute(sql8`
|
|
26176
26783
|
select acknowledged_unredacted, acknowledged_shared
|
|
26177
26784
|
from session_stream_acknowledgments
|
|
26178
26785
|
where workspace_id = ${input.workspaceId}
|
|
@@ -26191,7 +26798,7 @@ async function listSessionIdsInGroup(db, workspaceId, sandboxGroupId) {
|
|
|
26191
26798
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
26192
26799
|
const rows = await rawRows(
|
|
26193
26800
|
scopedDb,
|
|
26194
|
-
|
|
26801
|
+
sql8`
|
|
26195
26802
|
select id from sessions
|
|
26196
26803
|
where workspace_id = ${workspaceId} and sandbox_group_id = ${sandboxGroupId}
|
|
26197
26804
|
order by created_at asc
|
|
@@ -26222,7 +26829,7 @@ async function accrueWarmSeconds(db, input) {
|
|
|
26222
26829
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
26223
26830
|
async (scopedDb) => await scopedDb.transaction(async (txRaw) => {
|
|
26224
26831
|
const tx = txRaw;
|
|
26225
|
-
const rows = await tx.execute(
|
|
26832
|
+
const rows = await tx.execute(sql8`
|
|
26226
26833
|
select *,
|
|
26227
26834
|
case when last_meter_at is null then null
|
|
26228
26835
|
else floor(extract(epoch from (now() - last_meter_at)))::int end as meter_elapsed_s
|
|
@@ -26236,7 +26843,7 @@ async function accrueWarmSeconds(db, input) {
|
|
|
26236
26843
|
return none;
|
|
26237
26844
|
}
|
|
26238
26845
|
if (row.last_meter_at == null) {
|
|
26239
|
-
await tx.execute(
|
|
26846
|
+
await tx.execute(sql8`
|
|
26240
26847
|
update sandbox_leases set last_meter_at = now(), updated_at = now()
|
|
26241
26848
|
where id = ${row.id}
|
|
26242
26849
|
`);
|
|
@@ -26248,7 +26855,7 @@ async function accrueWarmSeconds(db, input) {
|
|
|
26248
26855
|
}
|
|
26249
26856
|
const tick = Number(row.last_meter_tick) + 1;
|
|
26250
26857
|
const costMicros = Math.round(elapsedS * Math.max(0, input.warmRateMicrosPerSecond));
|
|
26251
|
-
await tx.execute(
|
|
26858
|
+
await tx.execute(sql8`
|
|
26252
26859
|
insert into usage_events
|
|
26253
26860
|
(account_id, workspace_id, subject_id, event_type, quantity, unit,
|
|
26254
26861
|
source_resource_type, source_resource_id, idempotency_key, occurred_at)
|
|
@@ -26261,7 +26868,7 @@ async function accrueWarmSeconds(db, input) {
|
|
|
26261
26868
|
on conflict (idempotency_key) do nothing
|
|
26262
26869
|
`);
|
|
26263
26870
|
if (costMicros > 0) {
|
|
26264
|
-
await tx.execute(
|
|
26871
|
+
await tx.execute(sql8`
|
|
26265
26872
|
insert into usage_events
|
|
26266
26873
|
(account_id, workspace_id, subject_id, event_type, quantity, unit,
|
|
26267
26874
|
source_resource_type, source_resource_id, idempotency_key, occurred_at)
|
|
@@ -26274,7 +26881,7 @@ async function accrueWarmSeconds(db, input) {
|
|
|
26274
26881
|
on conflict (idempotency_key) do nothing
|
|
26275
26882
|
`);
|
|
26276
26883
|
}
|
|
26277
|
-
await tx.execute(
|
|
26884
|
+
await tx.execute(sql8`
|
|
26278
26885
|
update sandbox_leases set
|
|
26279
26886
|
last_meter_at = now(), last_meter_tick = ${tick}, updated_at = now()
|
|
26280
26887
|
where id = ${row.id}
|
|
@@ -26306,7 +26913,7 @@ async function forceDrainOverLimitViewerOnlyBoxes(db, input) {
|
|
|
26306
26913
|
} else if (input.maxWarmSecondsPerWorkspace > 0) {
|
|
26307
26914
|
const since = input.capWindowStart ?? startOfUtcMonthDefault();
|
|
26308
26915
|
const [{ total } = { total: 0 }] = await scopedDb.select({
|
|
26309
|
-
total:
|
|
26916
|
+
total: sql8`coalesce(sum(${usageEvents.quantity}), 0)`
|
|
26310
26917
|
}).from(usageEvents).where(
|
|
26311
26918
|
and10(
|
|
26312
26919
|
eq10(usageEvents.workspaceId, input.workspaceId),
|
|
@@ -26319,7 +26926,7 @@ async function forceDrainOverLimitViewerOnlyBoxes(db, input) {
|
|
|
26319
26926
|
}
|
|
26320
26927
|
}
|
|
26321
26928
|
if (!reason) {
|
|
26322
|
-
await scopedDb.execute(
|
|
26929
|
+
await scopedDb.execute(sql8`
|
|
26323
26930
|
update workspaces set
|
|
26324
26931
|
sandbox_viewer_force_drain_reason = null,
|
|
26325
26932
|
sandbox_viewer_force_drain_requested_at = null,
|
|
@@ -26329,7 +26936,7 @@ async function forceDrainOverLimitViewerOnlyBoxes(db, input) {
|
|
|
26329
26936
|
`);
|
|
26330
26937
|
return { overLimit: false, reason: null, drained: [] };
|
|
26331
26938
|
}
|
|
26332
|
-
await scopedDb.execute(
|
|
26939
|
+
await scopedDb.execute(sql8`
|
|
26333
26940
|
update workspaces set
|
|
26334
26941
|
sandbox_viewer_force_drain_reason = ${reason},
|
|
26335
26942
|
sandbox_viewer_force_drain_requested_at =
|
|
@@ -26345,14 +26952,14 @@ async function forceDrainOverLimitViewerOnlyBoxes(db, input) {
|
|
|
26345
26952
|
or sandbox_viewer_force_drain_requested_at is null
|
|
26346
26953
|
)
|
|
26347
26954
|
`);
|
|
26348
|
-
await scopedDb.execute(
|
|
26955
|
+
await scopedDb.execute(sql8`
|
|
26349
26956
|
select id from sandbox_leases
|
|
26350
26957
|
where workspace_id = ${input.workspaceId}
|
|
26351
26958
|
and liveness = 'warm' and turn_holders = 0
|
|
26352
26959
|
order by id
|
|
26353
26960
|
for update
|
|
26354
26961
|
`);
|
|
26355
|
-
await scopedDb.execute(
|
|
26962
|
+
await scopedDb.execute(sql8`
|
|
26356
26963
|
delete from sandbox_lease_holders h
|
|
26357
26964
|
where h.kind = 'viewer'
|
|
26358
26965
|
and h.lease_id in (
|
|
@@ -26363,7 +26970,7 @@ async function forceDrainOverLimitViewerOnlyBoxes(db, input) {
|
|
|
26363
26970
|
`);
|
|
26364
26971
|
const drained = await rawRows(
|
|
26365
26972
|
scopedDb,
|
|
26366
|
-
|
|
26973
|
+
sql8`
|
|
26367
26974
|
update sandbox_leases set
|
|
26368
26975
|
liveness = 'draining',
|
|
26369
26976
|
refcount = 0, turn_holders = 0, viewer_holders = 0,
|
|
@@ -26399,7 +27006,7 @@ async function saveRunState(db, input) {
|
|
|
26399
27006
|
});
|
|
26400
27007
|
if (!allowed.allowed) return false;
|
|
26401
27008
|
const [{ maxVersion } = { maxVersion: 0 }] = await tx.select({
|
|
26402
|
-
maxVersion:
|
|
27009
|
+
maxVersion: sql8`coalesce(max(${agentRunStates.stateVersion}), 0)`
|
|
26403
27010
|
}).from(agentRunStates).where(
|
|
26404
27011
|
and10(
|
|
26405
27012
|
eq10(agentRunStates.workspaceId, input.workspaceId),
|
|
@@ -26491,7 +27098,7 @@ async function getSessionGoalWithContinuation(db, workspaceId, sessionId) {
|
|
|
26491
27098
|
// accepted while a goal turn is running can have a lower normalized
|
|
26492
27099
|
// queue position; that future human turn must not hide the live goal
|
|
26493
27100
|
// attempt in this projection.
|
|
26494
|
-
|
|
27101
|
+
sql8`case when ${sessionTurns.id} = ${session.activeTurnId} then 0 else 1 end`,
|
|
26495
27102
|
asc5(sessionTurns.position),
|
|
26496
27103
|
asc5(sessionTurns.createdAt)
|
|
26497
27104
|
).limit(1);
|
|
@@ -26501,8 +27108,8 @@ async function getSessionGoalWithContinuation(db, workspaceId, sessionId) {
|
|
|
26501
27108
|
eq10(sessionSystemUpdates.sessionId, sessionId),
|
|
26502
27109
|
eq10(sessionSystemUpdates.kind, "goal_continuation"),
|
|
26503
27110
|
eq10(sessionSystemUpdates.state, "pending"),
|
|
26504
|
-
|
|
26505
|
-
|
|
27111
|
+
sql8`${sessionSystemUpdates.payload} ->> 'goalId' = ${goal.id}`,
|
|
27112
|
+
sql8`(
|
|
26506
27113
|
jsonb_typeof(${sessionSystemUpdates.payload} -> 'goalVersion') = 'number'
|
|
26507
27114
|
and ${sessionSystemUpdates.payload} ->> 'goalVersion' ~ '^[1-9][0-9]*$'
|
|
26508
27115
|
and ${sessionSystemUpdates.payload} ->> 'goalVersion' = ${goal.version.toString()}
|
|
@@ -26748,7 +27355,7 @@ async function updateSessionGoal(db, workspaceId, sessionId, input) {
|
|
|
26748
27355
|
const [row] = await scopedDb.update(sessionGoals).set({
|
|
26749
27356
|
...input.text !== void 0 ? { text: input.text } : {},
|
|
26750
27357
|
...input.successCriteria !== void 0 ? { successCriteria: input.successCriteria } : {},
|
|
26751
|
-
version:
|
|
27358
|
+
version: sql8`${sessionGoals.version} + 1`,
|
|
26752
27359
|
noProgressStreak: 0,
|
|
26753
27360
|
updatedAt: /* @__PURE__ */ new Date()
|
|
26754
27361
|
}).where(
|
|
@@ -26885,8 +27492,8 @@ async function updateSessionTitle(db, input) {
|
|
|
26885
27492
|
and10(
|
|
26886
27493
|
eq10(sessions.workspaceId, input.workspaceId),
|
|
26887
27494
|
eq10(sessions.id, input.sessionId),
|
|
26888
|
-
|
|
26889
|
-
...input.source === "agent" ? [
|
|
27495
|
+
sql8`${sessions.title} is distinct from ${input.title}`,
|
|
27496
|
+
...input.source === "agent" ? [sql8`${sessions.titleSource} is distinct from 'user'`] : []
|
|
26890
27497
|
)
|
|
26891
27498
|
).returning({ title: sessions.title });
|
|
26892
27499
|
if (row) {
|
|
@@ -27045,7 +27652,7 @@ async function turnHasFailureCodeTx(tx, workspaceId, sessionId, turnId, code) {
|
|
|
27045
27652
|
eq10(sessionEvents.sessionId, sessionId),
|
|
27046
27653
|
eq10(sessionEvents.turnId, turnId),
|
|
27047
27654
|
eq10(sessionEvents.type, "turn.failed"),
|
|
27048
|
-
|
|
27655
|
+
sql8`${sessionEvents.payload} ->> 'code' = ${code}`
|
|
27049
27656
|
)
|
|
27050
27657
|
).limit(1);
|
|
27051
27658
|
return Boolean(failure);
|
|
@@ -27055,7 +27662,7 @@ async function latestFinishedTurnHasFailureCodeTx(tx, workspaceId, sessionId, co
|
|
|
27055
27662
|
and10(
|
|
27056
27663
|
eq10(sessionTurns.workspaceId, workspaceId),
|
|
27057
27664
|
eq10(sessionTurns.sessionId, sessionId),
|
|
27058
|
-
|
|
27665
|
+
sql8`${sessionTurns.finishedAt} is not null`
|
|
27059
27666
|
)
|
|
27060
27667
|
).orderBy(desc5(sessionTurns.position), desc5(sessionTurns.createdAt)).limit(1);
|
|
27061
27668
|
return latestFinished ? await turnHasFailureCodeTx(tx, workspaceId, sessionId, latestFinished.id, code) : false;
|
|
@@ -27108,7 +27715,7 @@ async function evaluateGoalContinuation(db, input) {
|
|
|
27108
27715
|
and10(
|
|
27109
27716
|
eq10(sessionTurns.workspaceId, input.workspaceId),
|
|
27110
27717
|
eq10(sessionTurns.sessionId, input.sessionId),
|
|
27111
|
-
|
|
27718
|
+
sql8`${sessionTurns.finishedAt} is not null`
|
|
27112
27719
|
)
|
|
27113
27720
|
).orderBy(desc5(sessionTurns.position), desc5(sessionTurns.createdAt)).limit(1);
|
|
27114
27721
|
const contextCompactionFailure = latestFinished ? await turnHasFailureCodeTx(
|
|
@@ -27131,18 +27738,18 @@ async function evaluateGoalContinuation(db, input) {
|
|
|
27131
27738
|
noProgressStreak = 0;
|
|
27132
27739
|
} else if (lastFinished) {
|
|
27133
27740
|
const [{ rotatedFailures } = { rotatedFailures: 0 }] = await tx.select({
|
|
27134
|
-
rotatedFailures:
|
|
27741
|
+
rotatedFailures: sql8`count(*)::int`
|
|
27135
27742
|
}).from(sessionEvents).where(
|
|
27136
27743
|
and10(
|
|
27137
27744
|
eq10(sessionEvents.workspaceId, input.workspaceId),
|
|
27138
27745
|
eq10(sessionEvents.turnId, row.lastContinuationTurnId),
|
|
27139
27746
|
eq10(sessionEvents.type, "turn.failed"),
|
|
27140
|
-
|
|
27747
|
+
sql8`${sessionEvents.payload} ->> 'rotated' = 'true'`
|
|
27141
27748
|
)
|
|
27142
27749
|
);
|
|
27143
27750
|
rotatedFailover = Number(rotatedFailures) > 0;
|
|
27144
27751
|
const [{ toolCalls } = { toolCalls: 0 }] = await tx.select({
|
|
27145
|
-
toolCalls:
|
|
27752
|
+
toolCalls: sql8`count(*)::int`
|
|
27146
27753
|
}).from(sessionEvents).where(
|
|
27147
27754
|
and10(
|
|
27148
27755
|
eq10(sessionEvents.workspaceId, input.workspaceId),
|
|
@@ -27155,13 +27762,13 @@ async function evaluateGoalContinuation(db, input) {
|
|
|
27155
27762
|
noProgressStreak = 0;
|
|
27156
27763
|
} else {
|
|
27157
27764
|
const [{ backpressureFailures } = { backpressureFailures: 0 }] = await tx.select({
|
|
27158
|
-
backpressureFailures:
|
|
27765
|
+
backpressureFailures: sql8`count(*)::int`
|
|
27159
27766
|
}).from(sessionEvents).where(
|
|
27160
27767
|
and10(
|
|
27161
27768
|
eq10(sessionEvents.workspaceId, input.workspaceId),
|
|
27162
27769
|
eq10(sessionEvents.turnId, row.lastContinuationTurnId),
|
|
27163
27770
|
eq10(sessionEvents.type, "turn.failed"),
|
|
27164
|
-
|
|
27771
|
+
sql8`${sessionEvents.payload} ->> 'recovery' = 'goal_continuation'`
|
|
27165
27772
|
)
|
|
27166
27773
|
);
|
|
27167
27774
|
if (Number(backpressureFailures) === 0) {
|
|
@@ -27266,7 +27873,7 @@ async function materializeGoalContinuation(db, input) {
|
|
|
27266
27873
|
if (!goalRead || goalRead.status !== "active" || session.status === "cancelled" || effectiveControl.state !== "active") {
|
|
27267
27874
|
return { action: "none", events: [] };
|
|
27268
27875
|
}
|
|
27269
|
-
const malformedGoalVersionEvidence =
|
|
27876
|
+
const malformedGoalVersionEvidence = sql8`
|
|
27270
27877
|
jsonb_build_object(
|
|
27271
27878
|
'reason', 'malformed_goal_version',
|
|
27272
27879
|
'rawGoalVersion', ${sessionSystemUpdates.payload} ->> 'goalVersion',
|
|
@@ -27279,7 +27886,7 @@ async function materializeGoalContinuation(db, input) {
|
|
|
27279
27886
|
deliveredTurnId: null,
|
|
27280
27887
|
deliveredAt: null,
|
|
27281
27888
|
summary: "Malformed goal continuation quarantined: malformed_goal_version",
|
|
27282
|
-
payload:
|
|
27889
|
+
payload: sql8`
|
|
27283
27890
|
(
|
|
27284
27891
|
case
|
|
27285
27892
|
when jsonb_typeof(${sessionSystemUpdates.payload}) = 'object'
|
|
@@ -27298,7 +27905,7 @@ async function materializeGoalContinuation(db, input) {
|
|
|
27298
27905
|
)
|
|
27299
27906
|
)
|
|
27300
27907
|
`,
|
|
27301
|
-
lineage:
|
|
27908
|
+
lineage: sql8`
|
|
27302
27909
|
(
|
|
27303
27910
|
case
|
|
27304
27911
|
when jsonb_typeof(${sessionSystemUpdates.lineage}) = 'object'
|
|
@@ -27314,8 +27921,8 @@ async function materializeGoalContinuation(db, input) {
|
|
|
27314
27921
|
eq10(sessionSystemUpdates.sessionId, input.sessionId),
|
|
27315
27922
|
eq10(sessionSystemUpdates.kind, "goal_continuation"),
|
|
27316
27923
|
eq10(sessionSystemUpdates.state, "pending"),
|
|
27317
|
-
|
|
27318
|
-
|
|
27924
|
+
sql8`${sessionSystemUpdates.payload} ->> 'goalId' = ${goalRead.id}`,
|
|
27925
|
+
sql8`(
|
|
27319
27926
|
jsonb_typeof(${sessionSystemUpdates.payload} -> 'goalVersion') = 'number'
|
|
27320
27927
|
and ${sessionSystemUpdates.payload} ->> 'goalVersion' ~ '^[1-9][0-9]*$'
|
|
27321
27928
|
and ${sessionSystemUpdates.payload} ->> 'goalVersion' = ${goalRead.version.toString()}
|
|
@@ -27359,8 +27966,8 @@ async function materializeGoalContinuation(db, input) {
|
|
|
27359
27966
|
eq10(sessionSystemUpdates.sessionId, input.sessionId),
|
|
27360
27967
|
eq10(sessionSystemUpdates.kind, "goal_continuation"),
|
|
27361
27968
|
eq10(sessionSystemUpdates.state, "pending"),
|
|
27362
|
-
|
|
27363
|
-
|
|
27969
|
+
sql8`${sessionSystemUpdates.payload} ->> 'goalId' = ${goalRead.id}`,
|
|
27970
|
+
sql8`(
|
|
27364
27971
|
jsonb_typeof(${sessionSystemUpdates.payload} -> 'goalVersion') = 'number'
|
|
27365
27972
|
and ${sessionSystemUpdates.payload} ->> 'goalVersion' ~ '^[1-9][0-9]*$'
|
|
27366
27973
|
and ${sessionSystemUpdates.payload} ->> 'goalVersion' = ${goalRead.version.toString()}
|
|
@@ -27389,7 +27996,7 @@ async function materializeGoalContinuation(db, input) {
|
|
|
27389
27996
|
let goalWakeRevision = goalRead.continuationWakeRevision;
|
|
27390
27997
|
if (goalWakeRevision <= goalRead.continuationObservedRevision) {
|
|
27391
27998
|
const [repaired] = await tx.update(sessionGoals).set({
|
|
27392
|
-
continuationWakeRevision:
|
|
27999
|
+
continuationWakeRevision: sql8`${sessionGoals.continuationWakeRevision} + 1`,
|
|
27393
28000
|
updatedAt: /* @__PURE__ */ new Date()
|
|
27394
28001
|
}).where(eq10(sessionGoals.id, goalRead.id)).returning({
|
|
27395
28002
|
revision: sessionGoals.continuationWakeRevision
|
|
@@ -28116,7 +28723,7 @@ async function claimSessionWorkForAttempt(db, workspaceId, input) {
|
|
|
28116
28723
|
return;
|
|
28117
28724
|
}
|
|
28118
28725
|
const [{ position } = { position: 0 }] = await tx.select({
|
|
28119
|
-
position:
|
|
28726
|
+
position: sql8`coalesce(max(${sessionHistoryItems.position}), -1) + 1`
|
|
28120
28727
|
}).from(sessionHistoryItems).where(
|
|
28121
28728
|
and10(
|
|
28122
28729
|
eq10(sessionHistoryItems.workspaceId, workspaceId),
|
|
@@ -28275,19 +28882,19 @@ async function claimSessionWorkForAttempt(db, workspaceId, input) {
|
|
|
28275
28882
|
}
|
|
28276
28883
|
const now2 = /* @__PURE__ */ new Date();
|
|
28277
28884
|
const dispatchGeneration2 = parsedDispatch.generation + 1;
|
|
28278
|
-
await tx.execute(
|
|
28885
|
+
await tx.execute(sql8`set local opengeni.session_inference_claim = '1'`);
|
|
28279
28886
|
const [resumed] = await tx.update(sessionTurns).set({
|
|
28280
28887
|
status: "running",
|
|
28281
28888
|
triggerEventId: input.trigger.triggerEventId,
|
|
28282
28889
|
temporalWorkflowId: workflowId,
|
|
28283
|
-
executionGeneration:
|
|
28890
|
+
executionGeneration: sql8`${sessionTurns.executionGeneration} + 1`,
|
|
28284
28891
|
activeAttemptId: input.attemptId,
|
|
28285
28892
|
metadata: metadataWithTurnDispatchAttempt(activeTurn.metadata, {
|
|
28286
28893
|
id: input.dispatchId,
|
|
28287
28894
|
generation: dispatchGeneration2,
|
|
28288
28895
|
triggerEventId: input.trigger.triggerEventId
|
|
28289
28896
|
}),
|
|
28290
|
-
version:
|
|
28897
|
+
version: sql8`${sessionTurns.version} + 1`,
|
|
28291
28898
|
startedAt: now2,
|
|
28292
28899
|
finishedAt: null,
|
|
28293
28900
|
updatedAt: now2
|
|
@@ -28319,18 +28926,18 @@ async function claimSessionWorkForAttempt(db, workspaceId, input) {
|
|
|
28319
28926
|
}
|
|
28320
28927
|
const now2 = /* @__PURE__ */ new Date();
|
|
28321
28928
|
const dispatchGeneration2 = parsedDispatch.generation + 1;
|
|
28322
|
-
await tx.execute(
|
|
28929
|
+
await tx.execute(sql8`set local opengeni.session_inference_claim = '1'`);
|
|
28323
28930
|
const [resumed] = await tx.update(sessionTurns).set({
|
|
28324
28931
|
status: "running",
|
|
28325
28932
|
temporalWorkflowId: workflowId,
|
|
28326
|
-
executionGeneration:
|
|
28933
|
+
executionGeneration: sql8`${sessionTurns.executionGeneration} + 1`,
|
|
28327
28934
|
activeAttemptId: input.attemptId,
|
|
28328
28935
|
metadata: metadataWithTurnDispatchAttempt(activeTurn.metadata, {
|
|
28329
28936
|
id: input.dispatchId,
|
|
28330
28937
|
generation: dispatchGeneration2,
|
|
28331
28938
|
triggerEventId: activeTurn.triggerEventId
|
|
28332
28939
|
}),
|
|
28333
|
-
version:
|
|
28940
|
+
version: sql8`${sessionTurns.version} + 1`,
|
|
28334
28941
|
startedAt: now2,
|
|
28335
28942
|
finishedAt: null,
|
|
28336
28943
|
updatedAt: now2
|
|
@@ -28396,7 +29003,7 @@ async function claimSessionWorkForAttempt(db, workspaceId, input) {
|
|
|
28396
29003
|
).limit(1).for("update");
|
|
28397
29004
|
const rows = await rawRows(
|
|
28398
29005
|
tx,
|
|
28399
|
-
|
|
29006
|
+
sql8`select id, trigger_event_id, metadata from session_turns
|
|
28400
29007
|
where workspace_id = ${workspaceId} and session_id = ${sessionId}
|
|
28401
29008
|
and status = 'queued' and source in ('user', 'api')
|
|
28402
29009
|
and (
|
|
@@ -28440,7 +29047,7 @@ async function claimSessionWorkForAttempt(db, workspaceId, input) {
|
|
|
28440
29047
|
context: {}
|
|
28441
29048
|
};
|
|
28442
29049
|
const [{ position: position2 } = { position: 1 }] = await tx.select({
|
|
28443
|
-
position:
|
|
29050
|
+
position: sql8`coalesce(max(${sessionTurns.position}), 0) + 1`
|
|
28444
29051
|
}).from(sessionTurns).where(
|
|
28445
29052
|
and10(
|
|
28446
29053
|
eq10(sessionTurns.workspaceId, workspaceId),
|
|
@@ -28457,10 +29064,10 @@ async function claimSessionWorkForAttempt(db, workspaceId, input) {
|
|
|
28457
29064
|
and10(
|
|
28458
29065
|
eq10(sessionTurns.workspaceId, workspaceId),
|
|
28459
29066
|
eq10(sessionTurns.sessionId, sessionId),
|
|
28460
|
-
|
|
29067
|
+
sql8`${sessionTurns.startedAt} is not null`
|
|
28461
29068
|
)
|
|
28462
29069
|
).orderBy(desc5(sessionTurns.startedAt), desc5(sessionTurns.createdAt)).limit(1);
|
|
28463
|
-
await tx.execute(
|
|
29070
|
+
await tx.execute(sql8`set local opengeni.session_inference_claim = '1'`);
|
|
28464
29071
|
const [compactionTurn] = await tx.insert(sessionTurns).values({
|
|
28465
29072
|
id: turnId2,
|
|
28466
29073
|
accountId: session.accountId,
|
|
@@ -28558,7 +29165,7 @@ async function claimSessionWorkForAttempt(db, workspaceId, input) {
|
|
|
28558
29165
|
const turnId = crypto.randomUUID();
|
|
28559
29166
|
const triggerEventId = crypto.randomUUID();
|
|
28560
29167
|
const [{ position } = { position: 1 }] = await tx.select({
|
|
28561
|
-
position:
|
|
29168
|
+
position: sql8`coalesce(max(${sessionTurns.position}), 0) + 1`
|
|
28562
29169
|
}).from(sessionTurns).where(
|
|
28563
29170
|
and10(
|
|
28564
29171
|
eq10(sessionTurns.workspaceId, workspaceId),
|
|
@@ -28683,7 +29290,7 @@ async function claimSessionWorkForAttempt(db, workspaceId, input) {
|
|
|
28683
29290
|
and10(
|
|
28684
29291
|
eq10(sessionTurns.workspaceId, workspaceId),
|
|
28685
29292
|
eq10(sessionTurns.sessionId, sessionId),
|
|
28686
|
-
|
|
29293
|
+
sql8`${sessionTurns.startedAt} is not null`
|
|
28687
29294
|
)
|
|
28688
29295
|
).orderBy(desc5(sessionTurns.startedAt), desc5(sessionTurns.createdAt)).limit(1);
|
|
28689
29296
|
const model = typeof goalPolicy?.model === "string" ? goalPolicy.model : latestStarted?.model ?? session.model;
|
|
@@ -28701,7 +29308,7 @@ async function claimSessionWorkForAttempt(db, workspaceId, input) {
|
|
|
28701
29308
|
);
|
|
28702
29309
|
const tools = Array.isArray(goalPolicy?.tools) ? goalPolicy.tools : latestStarted?.tools ?? session.tools;
|
|
28703
29310
|
const sandboxBackend = typeof goalPolicy?.sandboxBackend === "string" ? goalPolicy.sandboxBackend : latestStarted?.sandboxBackend ?? session.sandboxBackend;
|
|
28704
|
-
await tx.execute(
|
|
29311
|
+
await tx.execute(sql8`set local opengeni.session_inference_claim = '1'`);
|
|
28705
29312
|
const [internalTurn] = await tx.insert(sessionTurns).values({
|
|
28706
29313
|
id: turnId,
|
|
28707
29314
|
accountId: session.accountId,
|
|
@@ -28787,18 +29394,18 @@ async function claimSessionWorkForAttempt(db, workspaceId, input) {
|
|
|
28787
29394
|
throw new Error("Turn dispatch generation exhausted; refusing to wrap or reuse it");
|
|
28788
29395
|
}
|
|
28789
29396
|
const dispatchGeneration = queuedDispatch.generation + 1;
|
|
28790
|
-
await tx.execute(
|
|
29397
|
+
await tx.execute(sql8`set local opengeni.session_inference_claim = '1'`);
|
|
28791
29398
|
const [row] = await tx.update(sessionTurns).set({
|
|
28792
29399
|
status: "running",
|
|
28793
29400
|
temporalWorkflowId: workflowId,
|
|
28794
|
-
executionGeneration:
|
|
29401
|
+
executionGeneration: sql8`${sessionTurns.executionGeneration} + 1`,
|
|
28795
29402
|
activeAttemptId: input.attemptId,
|
|
28796
29403
|
metadata: metadataWithTurnDispatchAttempt(queuedTurn?.metadata, {
|
|
28797
29404
|
id: input.dispatchId,
|
|
28798
29405
|
generation: dispatchGeneration,
|
|
28799
29406
|
triggerEventId: queuedTurn.trigger_event_id
|
|
28800
29407
|
}),
|
|
28801
|
-
version:
|
|
29408
|
+
version: sql8`${sessionTurns.version} + 1`,
|
|
28802
29409
|
startedAt: now,
|
|
28803
29410
|
updatedAt: now
|
|
28804
29411
|
}).where(
|
|
@@ -28809,7 +29416,7 @@ async function claimSessionWorkForAttempt(db, workspaceId, input) {
|
|
|
28809
29416
|
}
|
|
28810
29417
|
await registerAttempt(row);
|
|
28811
29418
|
const [{ historyPosition } = { historyPosition: 0 }] = await tx.select({
|
|
28812
|
-
historyPosition:
|
|
29419
|
+
historyPosition: sql8`coalesce(max(${sessionHistoryItems.position}), -1) + 1`
|
|
28813
29420
|
}).from(sessionHistoryItems).where(
|
|
28814
29421
|
and10(
|
|
28815
29422
|
eq10(sessionHistoryItems.workspaceId, workspaceId),
|
|
@@ -29015,7 +29622,7 @@ async function reconcileSessionAttemptQuiescence(db, input) {
|
|
|
29015
29622
|
db,
|
|
29016
29623
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
29017
29624
|
async (scopedDb) => {
|
|
29018
|
-
const rows = await scopedDb.execute(
|
|
29625
|
+
const rows = await scopedDb.execute(sql8`
|
|
29019
29626
|
select
|
|
29020
29627
|
attempt.account_id,
|
|
29021
29628
|
attempt.state,
|
|
@@ -29469,7 +30076,7 @@ async function peekSessionWork(db, workspaceId, sessionId) {
|
|
|
29469
30076
|
isNotNull(sessionHumanInputRequests.expiresAt)
|
|
29470
30077
|
)
|
|
29471
30078
|
).orderBy(
|
|
29472
|
-
|
|
30079
|
+
sql8`${sessionHumanInputRequests.expiresAt} asc nulls last`,
|
|
29473
30080
|
asc5(sessionHumanInputRequests.id)
|
|
29474
30081
|
).limit(1);
|
|
29475
30082
|
return expiringHumanInput?.expiresAt ? {
|
|
@@ -29612,7 +30219,7 @@ async function settleSessionIdleWithParentOutbox(db, workspaceId, sessionId) {
|
|
|
29612
30219
|
return { action: "stale", episodeKey: null, events: [] };
|
|
29613
30220
|
}
|
|
29614
30221
|
const [{ episodeSequence } = { episodeSequence: 0 }] = await tx.select({
|
|
29615
|
-
episodeSequence:
|
|
30222
|
+
episodeSequence: sql8`coalesce(max(${sessionEvents.sequence}), 0)::int`
|
|
29616
30223
|
}).from(sessionEvents).where(
|
|
29617
30224
|
and10(
|
|
29618
30225
|
eq10(sessionEvents.workspaceId, workspaceId),
|
|
@@ -29903,7 +30510,7 @@ async function applySessionTurnSettlement(db, workspaceId, input) {
|
|
|
29903
30510
|
}
|
|
29904
30511
|
}
|
|
29905
30512
|
const [{ maxVersion } = { maxVersion: 0 }] = await tx.select({
|
|
29906
|
-
maxVersion:
|
|
30513
|
+
maxVersion: sql8`coalesce(max(${agentRunStates.stateVersion}), 0)`
|
|
29907
30514
|
}).from(agentRunStates).where(
|
|
29908
30515
|
and10(
|
|
29909
30516
|
eq10(agentRunStates.workspaceId, workspaceId),
|
|
@@ -29949,7 +30556,7 @@ async function applySessionTurnSettlement(db, workspaceId, input) {
|
|
|
29949
30556
|
turnGeneration: turn.executionGeneration,
|
|
29950
30557
|
updatedAt: /* @__PURE__ */ new Date()
|
|
29951
30558
|
},
|
|
29952
|
-
setWhere:
|
|
30559
|
+
setWhere: sql8`
|
|
29953
30560
|
${sessionHumanInputRequests.status} = 'pending'
|
|
29954
30561
|
and ${sessionHumanInputRequests.allowSkip} = ${request.allowSkip}
|
|
29955
30562
|
and ${sessionHumanInputRequests.questions} = ${JSON.stringify(request.questions)}::jsonb
|
|
@@ -30157,7 +30764,7 @@ async function applySessionTurnSettlement(db, workspaceId, input) {
|
|
|
30157
30764
|
const inserted = values.length > 0 ? await tx.insert(sessionEvents).values(values).returning() : [];
|
|
30158
30765
|
const terminal = input.turnStatus === "completed" || input.turnStatus === "cancelled" || input.turnStatus === "failed" || input.turnStatus === "superseded";
|
|
30159
30766
|
if (input.turnStatus === "running") {
|
|
30160
|
-
await tx.execute(
|
|
30767
|
+
await tx.execute(sql8`set local opengeni.session_inference_claim = '1'`);
|
|
30161
30768
|
}
|
|
30162
30769
|
await tx.update(sessionTurns).set({
|
|
30163
30770
|
status: input.turnStatus,
|
|
@@ -30200,7 +30807,7 @@ async function applySessionTurnSettlement(db, workspaceId, input) {
|
|
|
30200
30807
|
);
|
|
30201
30808
|
if (terminal && input.activeTurnId === null) {
|
|
30202
30809
|
const [armedGoal] = await tx.update(sessionGoals).set({
|
|
30203
|
-
continuationWakeRevision:
|
|
30810
|
+
continuationWakeRevision: sql8`${sessionGoals.continuationWakeRevision} + 1`,
|
|
30204
30811
|
updatedAt: now
|
|
30205
30812
|
}).where(
|
|
30206
30813
|
and10(
|
|
@@ -30256,7 +30863,7 @@ async function settleCodexCredentialLeaseLoss(db, input) {
|
|
|
30256
30863
|
return { action: "stale", events: [] };
|
|
30257
30864
|
}
|
|
30258
30865
|
const leaseRows = await tx.execute(
|
|
30259
|
-
|
|
30866
|
+
sql8`
|
|
30260
30867
|
select holder_id, generation from codex_credential_leases
|
|
30261
30868
|
where account_id = ${input.accountId}
|
|
30262
30869
|
and workspace_id = ${input.workspaceId}
|
|
@@ -30382,7 +30989,7 @@ async function settleCodexCredentialLeaseLoss(db, input) {
|
|
|
30382
30989
|
eq10(sessions.activeTurnId, input.turnId)
|
|
30383
30990
|
)
|
|
30384
30991
|
);
|
|
30385
|
-
await tx.execute(
|
|
30992
|
+
await tx.execute(sql8`
|
|
30386
30993
|
delete from codex_credential_leases
|
|
30387
30994
|
where account_id = ${input.accountId}
|
|
30388
30995
|
and workspace_id = ${input.workspaceId}
|
|
@@ -30434,7 +31041,7 @@ async function settleCodexCredentialFailover(db, input) {
|
|
|
30434
31041
|
};
|
|
30435
31042
|
}
|
|
30436
31043
|
const leaseRows = await tx.execute(
|
|
30437
|
-
|
|
31044
|
+
sql8`
|
|
30438
31045
|
select holder_id, generation from codex_credential_leases
|
|
30439
31046
|
where account_id = ${input.accountId}
|
|
30440
31047
|
and workspace_id = ${input.workspaceId}
|
|
@@ -30544,7 +31151,7 @@ async function settleCodexCredentialFailover(db, input) {
|
|
|
30544
31151
|
eq10(sessions.activeTurnId, input.turnId)
|
|
30545
31152
|
)
|
|
30546
31153
|
);
|
|
30547
|
-
await tx.execute(
|
|
31154
|
+
await tx.execute(sql8`
|
|
30548
31155
|
delete from codex_credential_leases
|
|
30549
31156
|
where account_id = ${input.accountId}
|
|
30550
31157
|
and workspace_id = ${input.workspaceId}
|
|
@@ -30610,7 +31217,7 @@ async function requestSessionTurnRecovery(db, workspaceId, input) {
|
|
|
30610
31217
|
input.providerArtifactInvalidation.codexCredentialId
|
|
30611
31218
|
),
|
|
30612
31219
|
isNull3(sessionHistoryItems.providerArtifactInvalidatedAt),
|
|
30613
|
-
|
|
31220
|
+
sql8`${sessionHistoryItems.item} ->> 'type' in ('reasoning', 'compaction')`
|
|
30614
31221
|
)
|
|
30615
31222
|
).returning({ id: sessionHistoryItems.id });
|
|
30616
31223
|
const [latestRunState] = await tx.select({ id: agentRunStates.id }).from(agentRunStates).where(
|
|
@@ -31010,7 +31617,7 @@ async function getActiveSessionTurnForExecution(db, workspaceId, sessionId) {
|
|
|
31010
31617
|
eq10(sessionTurnAttempts.turnId, sessionTurns.id),
|
|
31011
31618
|
inArray5(sessionTurnAttempts.state, ["claimed", "running"]),
|
|
31012
31619
|
inArray5(sessionTurns.status, ["running", "recovering", "waiting_capacity"]),
|
|
31013
|
-
|
|
31620
|
+
sql8`not exists (
|
|
31014
31621
|
select 1
|
|
31015
31622
|
from ${sessionAttemptInterruptions} interruption
|
|
31016
31623
|
where interruption.workspace_id = ${workspaceId}
|
|
@@ -31050,7 +31657,7 @@ async function getSessionTurnForAttempt(db, workspaceId, sessionId, attemptId) {
|
|
|
31050
31657
|
"recovering",
|
|
31051
31658
|
"waiting_capacity"
|
|
31052
31659
|
]),
|
|
31053
|
-
|
|
31660
|
+
sql8`not exists (
|
|
31054
31661
|
select 1
|
|
31055
31662
|
from ${sessionAttemptInterruptions} interruption
|
|
31056
31663
|
where interruption.workspace_id = ${workspaceId}
|
|
@@ -31113,7 +31720,7 @@ async function getSessionQueueSnapshot(db, workspaceId, sessionId) {
|
|
|
31113
31720
|
eq10(sessionSystemUpdates.state, "pending")
|
|
31114
31721
|
)
|
|
31115
31722
|
).orderBy(
|
|
31116
|
-
|
|
31723
|
+
sql8`case when ${sessionSystemUpdates.kind} = 'agent_steer_instruction' then 0 else 1 end`,
|
|
31117
31724
|
asc5(sessionSystemUpdates.createdAt),
|
|
31118
31725
|
asc5(sessionSystemUpdates.id)
|
|
31119
31726
|
);
|
|
@@ -31254,7 +31861,7 @@ async function getSessionSystemUpdateOutboxByDedupeKey(db, input) {
|
|
|
31254
31861
|
);
|
|
31255
31862
|
}
|
|
31256
31863
|
async function claimPendingSessionSystemUpdateOutbox(db, limit = 100) {
|
|
31257
|
-
const rows = await rawRows(db,
|
|
31864
|
+
const rows = await rawRows(db, sql8`select * from opengeni_private.claim_session_system_update_outbox(${limit})`);
|
|
31258
31865
|
return rows.map(mapSystemUpdateOutboxRow);
|
|
31259
31866
|
}
|
|
31260
31867
|
async function enqueueSessionWorkflowWakeInTransaction(tx, input) {
|
|
@@ -31271,13 +31878,13 @@ async function enqueueSessionWorkflowWakeInTransaction(tx, input) {
|
|
|
31271
31878
|
target: sessionWorkflowWakeOutbox.sessionId,
|
|
31272
31879
|
set: {
|
|
31273
31880
|
temporalWorkflowId: input.temporalWorkflowId,
|
|
31274
|
-
wakeRevision:
|
|
31881
|
+
wakeRevision: sql8`${sessionWorkflowWakeOutbox.wakeRevision} + 1`,
|
|
31275
31882
|
reason: input.reason,
|
|
31276
31883
|
attempts: 0,
|
|
31277
31884
|
// Coalescing a delayed retry must never postpone an already-due wake
|
|
31278
31885
|
// owned by another producer. A later revision makes the batch richer;
|
|
31279
31886
|
// it does not revoke the earlier delivery obligation.
|
|
31280
|
-
nextAttemptAt:
|
|
31887
|
+
nextAttemptAt: sql8`least(${sessionWorkflowWakeOutbox.nextAttemptAt}, ${nextAttemptAt.toISOString()}::timestamptz)`,
|
|
31281
31888
|
lastError: null,
|
|
31282
31889
|
updatedAt: now
|
|
31283
31890
|
}
|
|
@@ -31317,7 +31924,7 @@ async function enqueueSessionWorkflowWakeIfRunnable(db, input) {
|
|
|
31317
31924
|
);
|
|
31318
31925
|
}
|
|
31319
31926
|
async function claimPendingSessionWorkflowWakes(db, limit = 100) {
|
|
31320
|
-
const rows = await rawRows(db,
|
|
31927
|
+
const rows = await rawRows(db, sql8`select * from opengeni_private.claim_session_workflow_wakes(${limit})`);
|
|
31321
31928
|
return rows.map((row) => ({
|
|
31322
31929
|
accountId: row.account_id,
|
|
31323
31930
|
workspaceId: row.workspace_id,
|
|
@@ -31389,9 +31996,9 @@ async function markSessionWorkflowWakeDelivered(db, input) {
|
|
|
31389
31996
|
}
|
|
31390
31997
|
}
|
|
31391
31998
|
const [row] = await tx.update(sessionWorkflowWakeOutbox).set({
|
|
31392
|
-
deliveredRevision:
|
|
31393
|
-
attempts:
|
|
31394
|
-
lastError:
|
|
31999
|
+
deliveredRevision: sql8`greatest(${sessionWorkflowWakeOutbox.deliveredRevision}, ${input.wakeRevision})`,
|
|
32000
|
+
attempts: sql8`case when ${sessionWorkflowWakeOutbox.wakeRevision} = ${input.wakeRevision} then 0 else ${sessionWorkflowWakeOutbox.attempts} end`,
|
|
32001
|
+
lastError: sql8`case when ${sessionWorkflowWakeOutbox.wakeRevision} = ${input.wakeRevision} then null else ${sessionWorkflowWakeOutbox.lastError} end`,
|
|
31395
32002
|
updatedAt: /* @__PURE__ */ new Date()
|
|
31396
32003
|
}).where(
|
|
31397
32004
|
and10(
|
|
@@ -31603,7 +32210,7 @@ async function addSessionSystemUpdateWithSourceMutation(db, input, mutateSource)
|
|
|
31603
32210
|
eq10(sessionEvents.workspaceId, input.workspaceId),
|
|
31604
32211
|
eq10(sessionEvents.sessionId, input.sessionId),
|
|
31605
32212
|
eq10(sessionEvents.type, "system.update.pending"),
|
|
31606
|
-
|
|
32213
|
+
sql8`${sessionEvents.payload} ->> 'updateId' = ${existing.id}`
|
|
31607
32214
|
)
|
|
31608
32215
|
).limit(1);
|
|
31609
32216
|
if (!pendingEvent) throw new Error("System-update pending event disappeared");
|
|
@@ -31692,7 +32299,7 @@ async function listSessionSystemUpdatesForTurn(db, workspaceId, sessionId, turnI
|
|
|
31692
32299
|
// materialized goal continuation. Keep all coalesced work in one
|
|
31693
32300
|
// metered inference, but render the winning Steer last so transaction
|
|
31694
32301
|
// timestamps cannot let an older goal prompt override it.
|
|
31695
|
-
|
|
32302
|
+
sql8`case when ${sessionSystemUpdates.kind} = 'agent_steer_instruction' then 1 else 0 end`,
|
|
31696
32303
|
asc5(sessionSystemUpdates.createdAt),
|
|
31697
32304
|
asc5(sessionSystemUpdates.id)
|
|
31698
32305
|
);
|
|
@@ -31954,7 +32561,7 @@ async function appendSessionEventsForTurnAttempt(db, workspaceId, sessionId, tur
|
|
|
31954
32561
|
eq10(sessionEvents.type, "agent.model.usage"),
|
|
31955
32562
|
eq10(sessionEvents.turnAssociation, "current"),
|
|
31956
32563
|
inArray5(
|
|
31957
|
-
|
|
32564
|
+
sql8`${sessionEvents.payload} ->> 'sourceKey'`,
|
|
31958
32565
|
incomingUsageKeys
|
|
31959
32566
|
)
|
|
31960
32567
|
)
|
|
@@ -32084,7 +32691,7 @@ async function appendSessionEventToSandboxGroup(db, workspaceId, sandboxGroupId,
|
|
|
32084
32691
|
const inserted = await tx.insert(sessionEvents).values(values).returning();
|
|
32085
32692
|
const lockedSessionIds = rows.map((row) => row.id);
|
|
32086
32693
|
const updated = await tx.update(sessions).set({
|
|
32087
|
-
lastSequence:
|
|
32694
|
+
lastSequence: sql8`${sessions.lastSequence} + 1`,
|
|
32088
32695
|
...sessionEventTypesAdvanceActivity([input]) ? { updatedAt: /* @__PURE__ */ new Date() } : {}
|
|
32089
32696
|
}).where(
|
|
32090
32697
|
and10(
|
|
@@ -33032,14 +33639,21 @@ export {
|
|
|
33032
33639
|
MEMORY_BLOCK_RECORD_LIMIT,
|
|
33033
33640
|
MEMORY_CORRECT_TOOL_DESCRIPTION,
|
|
33034
33641
|
MEMORY_KIND_SECTION_TITLES,
|
|
33642
|
+
MEMORY_LABEL_MAX_CHARS,
|
|
33643
|
+
MEMORY_LABEL_MAX_COUNT,
|
|
33644
|
+
MEMORY_NAMESPACE_MAX_CHARS,
|
|
33035
33645
|
MEMORY_NEAR_DUP_COSINE_THRESHOLD,
|
|
33036
33646
|
MEMORY_NEAR_DUP_NEIGHBORS,
|
|
33647
|
+
MEMORY_RELATIONSHIP_TYPES,
|
|
33648
|
+
MEMORY_ROLE_KEY_MAX_CHARS,
|
|
33037
33649
|
MEMORY_SAVE_TOOL_DESCRIPTION,
|
|
33038
33650
|
MEMORY_SEARCH_DEFAULT_LIMIT,
|
|
33039
33651
|
MEMORY_SEARCH_MAX_LIMIT,
|
|
33040
33652
|
MEMORY_SEARCH_TOOL_DESCRIPTION,
|
|
33653
|
+
MEMORY_SUBJECT_ID_MAX_CHARS,
|
|
33041
33654
|
MEMORY_TEXT_MAX_CHARS,
|
|
33042
33655
|
MEMORY_VISIBLE_RECORD_CAP,
|
|
33656
|
+
MemoryGovernanceAuthorityError,
|
|
33043
33657
|
NON_RLS_RUNTIME_TABLES,
|
|
33044
33658
|
NewSessionDraftAccessError,
|
|
33045
33659
|
NewSessionDraftConflictError,
|
|
@@ -33139,6 +33753,7 @@ export {
|
|
|
33139
33753
|
applyContextCompaction,
|
|
33140
33754
|
applyCreditDebitUpToBalance,
|
|
33141
33755
|
applyCreditLedgerEntry,
|
|
33756
|
+
applyKnowledgeMemoryOperation,
|
|
33142
33757
|
applySessionTurnSettlement,
|
|
33143
33758
|
approveDeviceEnrollmentRequest,
|
|
33144
33759
|
areGitHubRepositoriesAllowedForWorkspace,
|
|
@@ -33159,6 +33774,7 @@ export {
|
|
|
33159
33774
|
buildCodexTokenResolver,
|
|
33160
33775
|
buildConnectionTokenResolver,
|
|
33161
33776
|
buildHostConnectionTokenResolver,
|
|
33777
|
+
canonicalMemoryRelationship,
|
|
33162
33778
|
canonicalSessionCommandHash,
|
|
33163
33779
|
changePreferenceRegistryScope,
|
|
33164
33780
|
claimCodexResetRedemption,
|
|
@@ -33253,7 +33869,7 @@ export {
|
|
|
33253
33869
|
createWorkspaceEnvironment,
|
|
33254
33870
|
createWorkspaceInstructionPolicyDraft,
|
|
33255
33871
|
databaseFailureCode,
|
|
33256
|
-
|
|
33872
|
+
sql9 as dbSql,
|
|
33257
33873
|
deactivatePreferenceRegistry,
|
|
33258
33874
|
deadLetterHostExportHead,
|
|
33259
33875
|
decodeSessionListCursor,
|
|
@@ -33261,6 +33877,7 @@ export {
|
|
|
33261
33877
|
decryptEnvironmentValue as decryptVariableSetValue,
|
|
33262
33878
|
decryptedCapabilityHeaders,
|
|
33263
33879
|
deferRetainedProcessReconciliation,
|
|
33880
|
+
deferSlackInteractionDelivery,
|
|
33264
33881
|
deleteGitHubInstallationBinding,
|
|
33265
33882
|
deleteRecording,
|
|
33266
33883
|
deleteRig,
|
|
@@ -33409,6 +34026,8 @@ export {
|
|
|
33409
34026
|
grantWorkspaceAccess,
|
|
33410
34027
|
hasAuditableGitHubInstallationAuthority,
|
|
33411
34028
|
hasCreditLedgerEntry,
|
|
34029
|
+
hashMemoryOperationPlan,
|
|
34030
|
+
hashMemoryRevertPlan,
|
|
33412
34031
|
hashMemoryText,
|
|
33413
34032
|
heartbeatCodexCredentialLease,
|
|
33414
34033
|
heartbeatCodexCredentialLeaseUntil,
|
|
@@ -33427,6 +34046,7 @@ export {
|
|
|
33427
34046
|
isCodexBilledModel2 as isCodexBilledModel,
|
|
33428
34047
|
isCodexBilledTurn,
|
|
33429
34048
|
isDatabasePersistenceFailure,
|
|
34049
|
+
isMemoryScopeApplicable,
|
|
33430
34050
|
isMemoryTextTooLong,
|
|
33431
34051
|
isPrivateAddress,
|
|
33432
34052
|
isRetryablePersistenceSqlState,
|
|
@@ -33501,6 +34121,7 @@ export {
|
|
|
33501
34121
|
loadCodexCredentialForRun,
|
|
33502
34122
|
loadConnectionCredentialForBroker,
|
|
33503
34123
|
loadIntegrationOAuthClient,
|
|
34124
|
+
loadSocialConnectionCredential,
|
|
33504
34125
|
loadVariableSetForRun,
|
|
33505
34126
|
loadWorkspaceEnvironmentForRun,
|
|
33506
34127
|
lockSessionEventWriteRows,
|
|
@@ -33530,6 +34151,13 @@ export {
|
|
|
33530
34151
|
newSessionDraftToolsProvided,
|
|
33531
34152
|
nextSessionHistoryPosition,
|
|
33532
34153
|
normalizeBearerScheme,
|
|
34154
|
+
normalizeMemoryLabel,
|
|
34155
|
+
normalizeMemoryLabels,
|
|
34156
|
+
normalizeMemoryNamespace,
|
|
34157
|
+
normalizeMemoryOperationPlan,
|
|
34158
|
+
normalizeMemoryRevertPlan,
|
|
34159
|
+
normalizeMemoryRoleKey,
|
|
34160
|
+
normalizeMemoryScope,
|
|
33533
34161
|
normalizeMemoryText,
|
|
33534
34162
|
orphanedResultRowIndicesForRepair,
|
|
33535
34163
|
peekSessionWork,
|
|
@@ -33577,6 +34205,7 @@ export {
|
|
|
33577
34205
|
recordStartedContextCompaction,
|
|
33578
34206
|
recordStreamAcknowledgment,
|
|
33579
34207
|
recordStripeWebhookEvent,
|
|
34208
|
+
recordSyncedSocialPosts,
|
|
33580
34209
|
recordUsageEvent,
|
|
33581
34210
|
recordWarmingSandboxCreated,
|
|
33582
34211
|
recoverSessionDispatch,
|
|
@@ -33622,6 +34251,7 @@ export {
|
|
|
33622
34251
|
retainedProcessReconciliationProof,
|
|
33623
34252
|
retainedProcessSettlementIdentity,
|
|
33624
34253
|
retireHostExportConsumer,
|
|
34254
|
+
revertKnowledgeMemoryOperation,
|
|
33625
34255
|
revokeApiKey,
|
|
33626
34256
|
revokeConnection,
|
|
33627
34257
|
revokeConnectionWithSlackBotSuccessAudit,
|
|
@@ -33718,6 +34348,7 @@ export {
|
|
|
33718
34348
|
updateSessionMcpApprovalPolicy,
|
|
33719
34349
|
updateSessionMcpServerCredentials,
|
|
33720
34350
|
updateSessionTitle,
|
|
34351
|
+
updateSocialConnectionCredential,
|
|
33721
34352
|
updateVariableSet,
|
|
33722
34353
|
updateWorkspace,
|
|
33723
34354
|
updateWorkspaceEnvironment,
|
|
@@ -33731,6 +34362,7 @@ export {
|
|
|
33731
34362
|
upsertSandboxSessionEnvelope,
|
|
33732
34363
|
upsertSessionGoal,
|
|
33733
34364
|
upsertSessionGoalWithEvent,
|
|
34365
|
+
upsertSocialOAuthConnection,
|
|
33734
34366
|
upsertWorkspaceModelPolicy,
|
|
33735
34367
|
validateHumanInputResponse,
|
|
33736
34368
|
verifyDirectWorkspaceMutationSettlement,
|