@opengeni/db 0.18.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-YKWJ7QJ2.js → chunk-SZP6KRLC.js} +2123 -1932
- 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 +1 -0
- package/dist/index.js +1023 -561
- 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 +199 -0
- package/dist/schema.js +5 -1
- package/drizzle/0152_hierarchical_memory_foundation.sql +1589 -0
- package/package.json +1 -1
- package/src/index.ts +10 -5
- 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 +40 -2
- package/dist/chunk-T6RSJT6C.js.map +0 -1
- package/dist/chunk-YKWJ7QJ2.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,
|
|
@@ -176,7 +176,7 @@ import {
|
|
|
176
176
|
ne,
|
|
177
177
|
notInArray,
|
|
178
178
|
or as or3,
|
|
179
|
-
sql as
|
|
179
|
+
sql as sql8
|
|
180
180
|
} from "drizzle-orm";
|
|
181
181
|
|
|
182
182
|
// src/turn-initiator.ts
|
|
@@ -2656,6 +2656,7 @@ async function insertWorkspaceControlEventInTransaction(db, input) {
|
|
|
2656
2656
|
|
|
2657
2657
|
// src/memory-domain.ts
|
|
2658
2658
|
import { createHash as createHash2 } from "crypto";
|
|
2659
|
+
import { stableJson } from "@opengeni/contracts";
|
|
2659
2660
|
var MEMORY_TEXT_MAX_CHARS = 4e3;
|
|
2660
2661
|
var MEMORY_VISIBLE_RECORD_CAP = 2e3;
|
|
2661
2662
|
var MEMORY_ACTIVE_RECORD_CAP = MEMORY_VISIBLE_RECORD_CAP;
|
|
@@ -2666,6 +2667,226 @@ var MEMORY_BLOCK_RECORD_LIMIT = 50;
|
|
|
2666
2667
|
var MEMORY_SEARCH_DEFAULT_LIMIT = 8;
|
|
2667
2668
|
var MEMORY_SEARCH_MAX_LIMIT = 20;
|
|
2668
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
|
+
}
|
|
2669
2890
|
var MEMORY_BLOCK_KIND_ORDER = [
|
|
2670
2891
|
"preference",
|
|
2671
2892
|
"semantic",
|
|
@@ -2783,7 +3004,7 @@ function renderMemoryEntry(record) {
|
|
|
2783
3004
|
}
|
|
2784
3005
|
|
|
2785
3006
|
// src/index.ts
|
|
2786
|
-
import { sql as
|
|
3007
|
+
import { sql as sql9 } from "drizzle-orm";
|
|
2787
3008
|
|
|
2788
3009
|
// src/session-queue-commands.ts
|
|
2789
3010
|
import {
|
|
@@ -2791,7 +3012,7 @@ import {
|
|
|
2791
3012
|
mergeResourceRefs,
|
|
2792
3013
|
ResourceRef,
|
|
2793
3014
|
resourceMountPath,
|
|
2794
|
-
stableJson,
|
|
3015
|
+
stableJson as stableJson2,
|
|
2795
3016
|
turnExecutionPolicyAuditMetadata
|
|
2796
3017
|
} from "@opengeni/contracts";
|
|
2797
3018
|
import { and as and5, asc as asc2, eq as eq5, inArray as inArray2, sql as sql3 } from "drizzle-orm";
|
|
@@ -3004,7 +3225,7 @@ function withCanonicalResourceMountPaths(resources) {
|
|
|
3004
3225
|
...value,
|
|
3005
3226
|
mountPath: resourceMountPath(parsed.data)
|
|
3006
3227
|
};
|
|
3007
|
-
const key =
|
|
3228
|
+
const key = stableJson2(normalized);
|
|
3008
3229
|
if (seen.has(key)) continue;
|
|
3009
3230
|
seen.add(key);
|
|
3010
3231
|
canonical.push(normalized);
|
|
@@ -5638,8 +5859,225 @@ async function getPreferenceRegistryFullContent(db, claims, handle) {
|
|
|
5638
5859
|
});
|
|
5639
5860
|
}
|
|
5640
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
|
+
|
|
5641
6079
|
// src/insights.ts
|
|
5642
|
-
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";
|
|
5643
6081
|
import { alias } from "drizzle-orm/pg-core";
|
|
5644
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;
|
|
5645
6083
|
function dayKeyUtc(value) {
|
|
@@ -5649,7 +6087,7 @@ async function sumUsageQuantityInRange(db, input) {
|
|
|
5649
6087
|
const context = await rlsContextForWorkspace(db, input.workspaceId);
|
|
5650
6088
|
return await withRlsContext(db, context, async (scopedDb) => {
|
|
5651
6089
|
const [{ total } = { total: 0 }] = await scopedDb.select({
|
|
5652
|
-
total:
|
|
6090
|
+
total: sql6`coalesce(sum(${usageEvents.quantity}), 0)`
|
|
5653
6091
|
}).from(usageEvents).where(
|
|
5654
6092
|
and8(
|
|
5655
6093
|
eq8(usageEvents.workspaceId, input.workspaceId),
|
|
@@ -5665,8 +6103,8 @@ async function sumUsageQuantityByDay(db, input) {
|
|
|
5665
6103
|
const context = await rlsContextForWorkspace(db, input.workspaceId);
|
|
5666
6104
|
return await withRlsContext(db, context, async (scopedDb) => {
|
|
5667
6105
|
const rows = await scopedDb.select({
|
|
5668
|
-
day:
|
|
5669
|
-
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)`
|
|
5670
6108
|
}).from(usageEvents).where(
|
|
5671
6109
|
and8(
|
|
5672
6110
|
eq8(usageEvents.workspaceId, input.workspaceId),
|
|
@@ -5674,7 +6112,7 @@ async function sumUsageQuantityByDay(db, input) {
|
|
|
5674
6112
|
gte(usageEvents.occurredAt, input.since),
|
|
5675
6113
|
lt2(usageEvents.occurredAt, input.until)
|
|
5676
6114
|
)
|
|
5677
|
-
).groupBy(
|
|
6115
|
+
).groupBy(sql6`date_trunc('day', ${usageEvents.occurredAt} at time zone 'UTC')`);
|
|
5678
6116
|
return new Map(rows.map((row) => [row.day, Number(row.total)]));
|
|
5679
6117
|
});
|
|
5680
6118
|
}
|
|
@@ -5692,14 +6130,14 @@ async function aggregateModelCallFacts(db, input) {
|
|
|
5692
6130
|
provider: modelCallFacts.provider,
|
|
5693
6131
|
model: modelCallFacts.model,
|
|
5694
6132
|
billingPath: modelCallFacts.billingPath,
|
|
5695
|
-
calls:
|
|
5696
|
-
inputTokens:
|
|
5697
|
-
outputTokens:
|
|
5698
|
-
cachedTokens:
|
|
5699
|
-
cacheWriteTokens:
|
|
5700
|
-
reasoningTokens:
|
|
5701
|
-
totalTokens:
|
|
5702
|
-
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)`
|
|
5703
6141
|
}).from(modelCallFacts).where(and8(...clauses)).groupBy(
|
|
5704
6142
|
modelCallFacts.provider,
|
|
5705
6143
|
modelCallFacts.model,
|
|
@@ -5731,12 +6169,12 @@ async function aggregateModelCallFactsByDay(db, input) {
|
|
|
5731
6169
|
...input.model ? [eq8(modelCallFacts.model, input.model)] : []
|
|
5732
6170
|
];
|
|
5733
6171
|
const rows = await scopedDb.select({
|
|
5734
|
-
day:
|
|
5735
|
-
costMicros:
|
|
5736
|
-
inputTokens:
|
|
5737
|
-
cachedTokens:
|
|
5738
|
-
calls:
|
|
5739
|
-
}).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')`);
|
|
5740
6178
|
return new Map(
|
|
5741
6179
|
rows.map((row) => [
|
|
5742
6180
|
row.day,
|
|
@@ -5755,17 +6193,17 @@ async function aggregateWarmSecondsByGroup(db, input) {
|
|
|
5755
6193
|
const limit = input.limit ?? 24;
|
|
5756
6194
|
return await withRlsContext(db, context, async (scopedDb) => {
|
|
5757
6195
|
const rows = await scopedDb.select({
|
|
5758
|
-
groupId:
|
|
5759
|
-
warmSeconds:
|
|
6196
|
+
groupId: sql6`split_part(${usageEvents.sourceResourceId}, ':', 1)`,
|
|
6197
|
+
warmSeconds: sql6`coalesce(sum(${usageEvents.quantity}), 0)`
|
|
5760
6198
|
}).from(usageEvents).where(
|
|
5761
6199
|
and8(
|
|
5762
6200
|
eq8(usageEvents.workspaceId, input.workspaceId),
|
|
5763
6201
|
eq8(usageEvents.eventType, "sandbox.warm_seconds"),
|
|
5764
6202
|
gte(usageEvents.occurredAt, input.since),
|
|
5765
6203
|
lt2(usageEvents.occurredAt, input.until),
|
|
5766
|
-
|
|
6204
|
+
sql6`${usageEvents.sourceResourceId} is not null`
|
|
5767
6205
|
)
|
|
5768
|
-
).groupBy(
|
|
6206
|
+
).groupBy(sql6`split_part(${usageEvents.sourceResourceId}, ':', 1)`).orderBy(sql6`coalesce(sum(${usageEvents.quantity}), 0) desc`).limit(Math.max(limit * 4, limit));
|
|
5769
6207
|
return rows.filter((row) => UUID_RE.test(row.groupId)).slice(0, limit).map((row) => ({
|
|
5770
6208
|
groupId: row.groupId,
|
|
5771
6209
|
warmSeconds: Number(row.warmSeconds)
|
|
@@ -5805,7 +6243,7 @@ async function countSessionsAttachedToGroups(db, workspaceId, groupIds) {
|
|
|
5805
6243
|
return await withRlsContext(db, context, async (scopedDb) => {
|
|
5806
6244
|
const rows = await scopedDb.select({
|
|
5807
6245
|
groupId: sessions.sandboxGroupId,
|
|
5808
|
-
n:
|
|
6246
|
+
n: sql6`count(*)::int`
|
|
5809
6247
|
}).from(sessions).where(
|
|
5810
6248
|
and8(
|
|
5811
6249
|
eq8(sessions.workspaceId, workspaceId),
|
|
@@ -5834,9 +6272,9 @@ async function aggregateRootSessionDrivers(db, input) {
|
|
|
5834
6272
|
const query = scopedDb.select({
|
|
5835
6273
|
rootSessionId: childSessions.rootSessionId,
|
|
5836
6274
|
title: rootSessions.title,
|
|
5837
|
-
pricedCostMicros:
|
|
5838
|
-
inputTokens:
|
|
5839
|
-
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)`
|
|
5840
6278
|
}).from(modelCallFacts).innerJoin(
|
|
5841
6279
|
childSessions,
|
|
5842
6280
|
and8(
|
|
@@ -5849,7 +6287,7 @@ async function aggregateRootSessionDrivers(db, input) {
|
|
|
5849
6287
|
eq8(rootSessions.workspaceId, childSessions.workspaceId),
|
|
5850
6288
|
eq8(rootSessions.id, childSessions.rootSessionId)
|
|
5851
6289
|
)
|
|
5852
|
-
).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`);
|
|
5853
6291
|
const rows = input.rootSessionIds ? await query : await query.limit(input.limit ?? 8);
|
|
5854
6292
|
return rows.map((row) => ({
|
|
5855
6293
|
rootSessionId: row.rootSessionId,
|
|
@@ -5883,17 +6321,17 @@ async function aggregateScheduleFacts(db, input) {
|
|
|
5883
6321
|
eq8(modelCallFacts.workspaceId, input.workspaceId),
|
|
5884
6322
|
gte(modelCallFacts.occurredAt, input.since),
|
|
5885
6323
|
lt2(modelCallFacts.occurredAt, input.until),
|
|
5886
|
-
|
|
6324
|
+
sql6`${modelCallFacts.scheduledTaskId} is not null`,
|
|
5887
6325
|
...input.provider ? [eq8(modelCallFacts.provider, input.provider)] : [],
|
|
5888
6326
|
...input.model ? [eq8(modelCallFacts.model, input.model)] : []
|
|
5889
6327
|
];
|
|
5890
6328
|
const rows = await scopedDb.select({
|
|
5891
6329
|
scheduledTaskId: modelCallFacts.scheduledTaskId,
|
|
5892
|
-
pricedCostMicros:
|
|
5893
|
-
inputTokens:
|
|
5894
|
-
cachedTokens:
|
|
5895
|
-
calls:
|
|
5896
|
-
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
|
|
5897
6335
|
when bool_or(${modelCallFacts.billingPath} = 'opengeni_credits')
|
|
5898
6336
|
then 'opengeni_credits'
|
|
5899
6337
|
else 'external'
|
|
@@ -5915,7 +6353,7 @@ async function countScheduledTaskFires(db, input) {
|
|
|
5915
6353
|
return await withRlsContext(db, context, async (scopedDb) => {
|
|
5916
6354
|
const rows = await scopedDb.select({
|
|
5917
6355
|
taskId: scheduledTaskRuns.taskId,
|
|
5918
|
-
n:
|
|
6356
|
+
n: sql6`count(*)::int`
|
|
5919
6357
|
}).from(scheduledTaskRuns).where(
|
|
5920
6358
|
and8(
|
|
5921
6359
|
eq8(scheduledTaskRuns.workspaceId, input.workspaceId),
|
|
@@ -5932,21 +6370,21 @@ async function aggregateSessionDepth(db, workspaceId) {
|
|
|
5932
6370
|
return await withRlsContext(db, context, async (scopedDb) => {
|
|
5933
6371
|
const buckets = await scopedDb.select({
|
|
5934
6372
|
depth: sessions.nestedAgentDepth,
|
|
5935
|
-
sessions:
|
|
6373
|
+
sessions: sql6`count(*)::int`
|
|
5936
6374
|
}).from(sessions).where(eq8(sessions.workspaceId, workspaceId)).groupBy(sessions.nestedAgentDepth).orderBy(sessions.nestedAgentDepth);
|
|
5937
6375
|
const [stats] = await scopedDb.select({
|
|
5938
|
-
sessionsTouched:
|
|
5939
|
-
rootSessions:
|
|
5940
|
-
deepestDepth:
|
|
5941
|
-
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)`
|
|
5942
6380
|
}).from(sessions).where(eq8(sessions.workspaceId, workspaceId));
|
|
5943
6381
|
const [deepest] = await scopedDb.select({
|
|
5944
6382
|
title: sessions.title,
|
|
5945
6383
|
depth: sessions.nestedAgentDepth
|
|
5946
6384
|
}).from(sessions).where(eq8(sessions.workspaceId, workspaceId)).orderBy(desc3(sessions.nestedAgentDepth), desc3(sessions.updatedAt)).limit(1);
|
|
5947
6385
|
const [goals] = await scopedDb.select({
|
|
5948
|
-
active:
|
|
5949
|
-
completed:
|
|
6386
|
+
active: sql6`count(*) filter (where ${sessionGoals.status} = 'active')::int`,
|
|
6387
|
+
completed: sql6`count(*) filter (where ${sessionGoals.status} = 'completed')::int`
|
|
5950
6388
|
}).from(sessionGoals).where(eq8(sessionGoals.workspaceId, workspaceId));
|
|
5951
6389
|
return {
|
|
5952
6390
|
buckets: buckets.map((row) => ({
|
|
@@ -5984,7 +6422,7 @@ async function countOnlineMachines(db, workspaceId, heartbeatFreshMs) {
|
|
|
5984
6422
|
const context = await rlsContextForWorkspace(db, workspaceId);
|
|
5985
6423
|
return await withRlsContext(db, context, async (scopedDb) => {
|
|
5986
6424
|
const cutoff = new Date(Date.now() - heartbeatFreshMs);
|
|
5987
|
-
const [{ n } = { n: 0 }] = await scopedDb.select({ n:
|
|
6425
|
+
const [{ n } = { n: 0 }] = await scopedDb.select({ n: sql6`count(*)::int` }).from(enrollments).where(
|
|
5988
6426
|
and8(
|
|
5989
6427
|
eq8(enrollments.workspaceId, workspaceId),
|
|
5990
6428
|
eq8(enrollments.status, "active"),
|
|
@@ -6033,9 +6471,9 @@ async function backfillModelCallFactsFromSessionEvents(db, input) {
|
|
|
6033
6471
|
eq8(sessionEvents.type, "agent.model.usage"),
|
|
6034
6472
|
eq8(sessionEvents.turnAssociation, "current"),
|
|
6035
6473
|
lt2(sessionEvents.occurredAt, until),
|
|
6036
|
-
|
|
6474
|
+
sql6`${sessionEvents.turnId} is not null`,
|
|
6037
6475
|
// Keyset on (occurred_at, id) so same-millisecond bursts cannot be skipped.
|
|
6038
|
-
|
|
6476
|
+
sql6`(${sessionEvents.occurredAt}, ${sessionEvents.id}) > (${cursorOccurredAt}, ${cursorId}::uuid)`
|
|
6039
6477
|
)
|
|
6040
6478
|
).orderBy(sessionEvents.occurredAt, sessionEvents.id).limit(Math.min(batchSize, remaining));
|
|
6041
6479
|
});
|
|
@@ -6996,7 +7434,7 @@ async function cancelResponseBody(response) {
|
|
|
6996
7434
|
}
|
|
6997
7435
|
|
|
6998
7436
|
// src/workspace-artifacts.ts
|
|
6999
|
-
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";
|
|
7000
7438
|
var WorkspaceArtifactNotFoundError = class extends Error {
|
|
7001
7439
|
name = "WorkspaceArtifactNotFoundError";
|
|
7002
7440
|
};
|
|
@@ -7186,7 +7624,7 @@ async function assertAttemptAuthority(scopedDb, input) {
|
|
|
7186
7624
|
if (provenance.some((value) => value === null) || input.sourceToolName === null) {
|
|
7187
7625
|
throw new WorkspaceArtifactOperationError("Artifact attempt provenance is incomplete");
|
|
7188
7626
|
}
|
|
7189
|
-
const rows = await scopedDb.execute(
|
|
7627
|
+
const rows = await scopedDb.execute(sql7`
|
|
7190
7628
|
WITH locked_workspace AS MATERIALIZED (
|
|
7191
7629
|
SELECT workspace.id, workspace.account_id
|
|
7192
7630
|
FROM workspaces workspace
|
|
@@ -7270,7 +7708,7 @@ async function replayForOperation(scopedDb, workspaceId, operationKey) {
|
|
|
7270
7708
|
}
|
|
7271
7709
|
async function lockOperation(scopedDb, workspaceId, operationKey) {
|
|
7272
7710
|
await scopedDb.execute(
|
|
7273
|
-
|
|
7711
|
+
sql7`SELECT pg_advisory_xact_lock(hashtextextended(${`${workspaceId}:${operationKey}`}, 0))`
|
|
7274
7712
|
);
|
|
7275
7713
|
}
|
|
7276
7714
|
function assertCreateReplay(replay) {
|
|
@@ -7620,7 +8058,7 @@ function validateHostExportIdentity(kind, consumerId) {
|
|
|
7620
8058
|
}
|
|
7621
8059
|
async function registerHostExportConsumer(db, input) {
|
|
7622
8060
|
validateHostExportIdentity(input.kind, input.consumerId);
|
|
7623
|
-
await db.execute(
|
|
8061
|
+
await db.execute(sql8`
|
|
7624
8062
|
select opengeni_host_export.register_host_export_consumer(
|
|
7625
8063
|
${input.kind}, ${input.consumerId}
|
|
7626
8064
|
)
|
|
@@ -7628,7 +8066,7 @@ async function registerHostExportConsumer(db, input) {
|
|
|
7628
8066
|
}
|
|
7629
8067
|
async function disableHostExportConsumer(db, input) {
|
|
7630
8068
|
validateHostExportIdentity(input.kind, input.consumerId);
|
|
7631
|
-
await db.execute(
|
|
8069
|
+
await db.execute(sql8`
|
|
7632
8070
|
select opengeni_host_export.disable_host_export_consumer(
|
|
7633
8071
|
${input.kind}, ${input.consumerId}
|
|
7634
8072
|
)
|
|
@@ -7636,7 +8074,7 @@ async function disableHostExportConsumer(db, input) {
|
|
|
7636
8074
|
}
|
|
7637
8075
|
async function retireHostExportConsumer(db, input) {
|
|
7638
8076
|
validateHostExportIdentity(input.kind, input.consumerId);
|
|
7639
|
-
await db.execute(
|
|
8077
|
+
await db.execute(sql8`
|
|
7640
8078
|
select opengeni_host_export.retire_host_export_consumer(
|
|
7641
8079
|
${input.kind}, ${input.consumerId}
|
|
7642
8080
|
)
|
|
@@ -7646,7 +8084,7 @@ async function claimHostExportBatch(db, input) {
|
|
|
7646
8084
|
validateHostExportIdentity(input.kind, input.consumerId);
|
|
7647
8085
|
const claimedRows = await rawRows(
|
|
7648
8086
|
db,
|
|
7649
|
-
|
|
8087
|
+
sql8`
|
|
7650
8088
|
select * from opengeni_host_export.claim_host_export_batch(
|
|
7651
8089
|
${input.kind}, ${input.consumerId}, ${input.leaseToken}::uuid,
|
|
7652
8090
|
${input.leaseHolderId}, ${input.leaseSeconds ?? 60},
|
|
@@ -7663,7 +8101,7 @@ async function claimHostExportBatch(db, input) {
|
|
|
7663
8101
|
}
|
|
7664
8102
|
const roots = await rawRows(
|
|
7665
8103
|
db,
|
|
7666
|
-
|
|
8104
|
+
sql8`
|
|
7667
8105
|
select * from opengeni_host_export.host_export_cursor_roots(
|
|
7668
8106
|
${input.kind}, ${input.consumerId}, ${input.leaseToken}::uuid
|
|
7669
8107
|
)
|
|
@@ -7769,7 +8207,7 @@ async function acknowledgeHostExportBatch(db, input) {
|
|
|
7769
8207
|
validateHostExportIdentity(input.kind, input.consumerId);
|
|
7770
8208
|
const [row] = await rawRows(
|
|
7771
8209
|
db,
|
|
7772
|
-
|
|
8210
|
+
sql8`
|
|
7773
8211
|
select opengeni_host_export.ack_host_export_batch(
|
|
7774
8212
|
${input.kind}, ${input.consumerId}, ${input.leaseToken}::uuid
|
|
7775
8213
|
) as checkpoint
|
|
@@ -7782,7 +8220,7 @@ async function failHostExportBatch(db, input) {
|
|
|
7782
8220
|
validateHostExportIdentity(input.kind, input.consumerId);
|
|
7783
8221
|
const [row] = await rawRows(
|
|
7784
8222
|
db,
|
|
7785
|
-
|
|
8223
|
+
sql8`
|
|
7786
8224
|
select opengeni_host_export.fail_host_export_batch(
|
|
7787
8225
|
${input.kind}, ${input.consumerId}, ${input.leaseToken}::uuid,
|
|
7788
8226
|
${input.error}, ${input.maxFailures ?? 20}
|
|
@@ -7797,7 +8235,7 @@ async function deadLetterHostExportHead(db, input) {
|
|
|
7797
8235
|
const cursor = hostExportCursor(input.cursor);
|
|
7798
8236
|
const [row] = await rawRows(
|
|
7799
8237
|
db,
|
|
7800
|
-
|
|
8238
|
+
sql8`
|
|
7801
8239
|
select opengeni_host_export.dead_letter_host_export_head(
|
|
7802
8240
|
${input.kind}, ${input.consumerId}, ${input.leaseToken}::uuid,
|
|
7803
8241
|
${cursor}::bigint, ${input.reason}
|
|
@@ -7809,7 +8247,7 @@ async function deadLetterHostExportHead(db, input) {
|
|
|
7809
8247
|
}
|
|
7810
8248
|
async function resumeHostExportConsumer(db, input) {
|
|
7811
8249
|
validateHostExportIdentity(input.kind, input.consumerId);
|
|
7812
|
-
await db.execute(
|
|
8250
|
+
await db.execute(sql8`
|
|
7813
8251
|
select opengeni_host_export.resume_host_export_consumer(
|
|
7814
8252
|
${input.kind}, ${input.consumerId}
|
|
7815
8253
|
)
|
|
@@ -7818,7 +8256,7 @@ async function resumeHostExportConsumer(db, input) {
|
|
|
7818
8256
|
async function rewindHostExportConsumer(db, input) {
|
|
7819
8257
|
validateHostExportIdentity(input.kind, input.consumerId);
|
|
7820
8258
|
const checkpoint = hostExportCursor(input.checkpoint);
|
|
7821
|
-
await db.execute(
|
|
8259
|
+
await db.execute(sql8`
|
|
7822
8260
|
select opengeni_host_export.rewind_host_export_consumer(
|
|
7823
8261
|
${input.kind}, ${input.consumerId}, ${checkpoint}::bigint
|
|
7824
8262
|
)
|
|
@@ -7828,7 +8266,7 @@ async function pruneHostExportOutbox(db, input) {
|
|
|
7828
8266
|
validateHostExportKind(input.kind);
|
|
7829
8267
|
const [row] = await rawRows(
|
|
7830
8268
|
db,
|
|
7831
|
-
|
|
8269
|
+
sql8`
|
|
7832
8270
|
select opengeni_host_export.prune_host_export_outbox(
|
|
7833
8271
|
${input.kind}, ${input.graceSeconds ?? 3600}, ${input.limit ?? 1e3}
|
|
7834
8272
|
) as deleted
|
|
@@ -7840,7 +8278,7 @@ async function getHostExportConsumerStatus(db, input) {
|
|
|
7840
8278
|
validateHostExportIdentity(input.kind, input.consumerId);
|
|
7841
8279
|
const [row] = await rawRows(
|
|
7842
8280
|
db,
|
|
7843
|
-
|
|
8281
|
+
sql8`
|
|
7844
8282
|
select * from opengeni_host_export.host_export_consumer_status(
|
|
7845
8283
|
${input.kind}, ${input.consumerId}
|
|
7846
8284
|
)
|
|
@@ -7869,18 +8307,18 @@ async function setRlsContext(db, context) {
|
|
|
7869
8307
|
if (typeof context.accountId !== "string" || context.accountId.trim() === "") {
|
|
7870
8308
|
throw new Error("setRlsContext: a non-empty accountId is required to establish an RLS context");
|
|
7871
8309
|
}
|
|
7872
|
-
await db.execute(
|
|
8310
|
+
await db.execute(sql8`select set_config('opengeni.account_id', ${context.accountId}, true)`);
|
|
7873
8311
|
await db.execute(
|
|
7874
|
-
|
|
8312
|
+
sql8`select set_config('opengeni.workspace_id', ${context.workspaceId ?? ""}, true)`
|
|
7875
8313
|
);
|
|
7876
|
-
await db.execute(
|
|
8314
|
+
await db.execute(sql8`select set_config('opengeni.sandbox_recovery_protocol_v2', '1', true)`);
|
|
7877
8315
|
}
|
|
7878
8316
|
async function withRlsContext(db, context, fn, transactionConfig) {
|
|
7879
8317
|
return await db.transaction(async (tx) => {
|
|
7880
8318
|
const scoped = tx;
|
|
7881
8319
|
await setRlsContext(scoped, context);
|
|
7882
8320
|
const applied = await tx.execute(
|
|
7883
|
-
|
|
8321
|
+
sql8`select
|
|
7884
8322
|
current_setting('opengeni.account_id', true) as account_id,
|
|
7885
8323
|
current_setting('opengeni.workspace_id', true) as workspace_id`
|
|
7886
8324
|
);
|
|
@@ -7939,9 +8377,9 @@ async function setSubjectRlsContext(db, subjectId) {
|
|
|
7939
8377
|
if (!subjectId.trim()) {
|
|
7940
8378
|
throw new Error("setSubjectRlsContext: a non-empty subjectId is required");
|
|
7941
8379
|
}
|
|
7942
|
-
await db.execute(
|
|
8380
|
+
await db.execute(sql8`select set_config('opengeni.subject_id', ${subjectId}, true)`);
|
|
7943
8381
|
const applied = await db.execute(
|
|
7944
|
-
|
|
8382
|
+
sql8`select current_setting('opengeni.subject_id', true) as subject_id`
|
|
7945
8383
|
);
|
|
7946
8384
|
if ((applied[0]?.subject_id ?? "") !== subjectId) {
|
|
7947
8385
|
throw new Error("Authenticated subject RLS context was not applied on the active backend");
|
|
@@ -7950,7 +8388,7 @@ async function setSubjectRlsContext(db, subjectId) {
|
|
|
7950
8388
|
async function withWorkspaceUsageLock(db, workspaceId, fn) {
|
|
7951
8389
|
const context = await rlsContextForWorkspace(db, workspaceId);
|
|
7952
8390
|
return await withRlsContext(db, context, async (scopedDb) => {
|
|
7953
|
-
await scopedDb.execute(
|
|
8391
|
+
await scopedDb.execute(sql8`select pg_advisory_xact_lock(hashtext(${`usage:${workspaceId}`}))`);
|
|
7954
8392
|
return await fn(scopedDb);
|
|
7955
8393
|
});
|
|
7956
8394
|
}
|
|
@@ -8279,7 +8717,7 @@ async function listWorkspacesForSubject(db, subjectId, limit = 100) {
|
|
|
8279
8717
|
}
|
|
8280
8718
|
async function countWorkspacesForAccount(db, accountId) {
|
|
8281
8719
|
const [{ count } = { count: 0 }] = await db.select({
|
|
8282
|
-
count:
|
|
8720
|
+
count: sql8`count(*)::int`
|
|
8283
8721
|
}).from(workspaces).where(eq10(workspaces.accountId, accountId));
|
|
8284
8722
|
return Number(count);
|
|
8285
8723
|
}
|
|
@@ -8357,7 +8795,7 @@ async function updateWorkspaceSettings(db, workspaceId, patch) {
|
|
|
8357
8795
|
async (scopedDb) => await scopedDb.transaction(async (tx) => {
|
|
8358
8796
|
await lockWorkspaceInferenceControl(tx, workspaceId, "update");
|
|
8359
8797
|
const [row2] = await tx.update(workspaces).set({
|
|
8360
|
-
settings: requested === null ?
|
|
8798
|
+
settings: requested === null ? sql8`(${workspaces.settings} - 'maxNestedAgentDepth') || ${JSON.stringify(nextPatch)}::jsonb` : sql8`${workspaces.settings} || ${JSON.stringify(nextPatch)}::jsonb`,
|
|
8361
8799
|
updatedAt: /* @__PURE__ */ new Date()
|
|
8362
8800
|
}).where(eq10(workspaces.id, workspaceId)).returning();
|
|
8363
8801
|
if (!row2) throw new Error(`Workspace not found: ${workspaceId}`);
|
|
@@ -8369,7 +8807,7 @@ async function updateWorkspaceSettings(db, workspaceId, patch) {
|
|
|
8369
8807
|
);
|
|
8370
8808
|
}
|
|
8371
8809
|
const [row] = await db.update(workspaces).set({
|
|
8372
|
-
settings:
|
|
8810
|
+
settings: sql8`${workspaces.settings} || ${JSON.stringify(patch)}::jsonb`,
|
|
8373
8811
|
updatedAt: /* @__PURE__ */ new Date()
|
|
8374
8812
|
}).where(eq10(workspaces.id, workspaceId)).returning();
|
|
8375
8813
|
if (!row) {
|
|
@@ -8456,7 +8894,7 @@ async function getManagedUserByEmail(db, email) {
|
|
|
8456
8894
|
if (binding?.userLookup) {
|
|
8457
8895
|
return await binding.userLookup(db, email);
|
|
8458
8896
|
}
|
|
8459
|
-
const rows = await db.execute(
|
|
8897
|
+
const rows = await db.execute(sql8`
|
|
8460
8898
|
select id from auth_users where lower(email) = lower(${email}) limit 1
|
|
8461
8899
|
`);
|
|
8462
8900
|
return rows[0]?.id ?? null;
|
|
@@ -8494,12 +8932,12 @@ async function listApiKeys(db, workspaceId) {
|
|
|
8494
8932
|
async function countActiveApiKeysForWorkspace(db, workspaceId) {
|
|
8495
8933
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
8496
8934
|
const [{ count } = { count: 0 }] = await scopedDb.select({
|
|
8497
|
-
count:
|
|
8935
|
+
count: sql8`count(*)::int`
|
|
8498
8936
|
}).from(apiKeys).where(
|
|
8499
8937
|
and10(
|
|
8500
8938
|
eq10(apiKeys.workspaceId, workspaceId),
|
|
8501
|
-
|
|
8502
|
-
|
|
8939
|
+
sql8`${apiKeys.revokedAt} is null`,
|
|
8940
|
+
sql8`(${apiKeys.expiresAt} is null or ${apiKeys.expiresAt} > now())`
|
|
8503
8941
|
)
|
|
8504
8942
|
);
|
|
8505
8943
|
return Number(count);
|
|
@@ -8519,12 +8957,12 @@ async function revokeApiKey(db, workspaceId, apiKeyId) {
|
|
|
8519
8957
|
}
|
|
8520
8958
|
async function findActiveApiKeyByHash(db, keyHash) {
|
|
8521
8959
|
return await db.transaction(async (tx) => {
|
|
8522
|
-
await tx.execute(
|
|
8960
|
+
await tx.execute(sql8`select set_config('opengeni.api_key_hash', ${keyHash}, true)`);
|
|
8523
8961
|
const [row] = await tx.select().from(apiKeys).where(
|
|
8524
8962
|
and10(
|
|
8525
8963
|
eq10(apiKeys.keyHash, keyHash),
|
|
8526
|
-
|
|
8527
|
-
|
|
8964
|
+
sql8`${apiKeys.revokedAt} is null`,
|
|
8965
|
+
sql8`(${apiKeys.expiresAt} is null or ${apiKeys.expiresAt} > now())`
|
|
8528
8966
|
)
|
|
8529
8967
|
).limit(1);
|
|
8530
8968
|
if (!row) {
|
|
@@ -8760,7 +9198,7 @@ async function bindAuthorizedGitHubInstallationRepositories(db, input) {
|
|
|
8760
9198
|
async function assertGitHubAuthorityWindowOpen(tx, checkedAt, expiresAt) {
|
|
8761
9199
|
const checkedAtIso = checkedAt.toISOString();
|
|
8762
9200
|
const expiresAtIso = expiresAt.toISOString();
|
|
8763
|
-
const result = await tx.execute(
|
|
9201
|
+
const result = await tx.execute(sql8`
|
|
8764
9202
|
select (
|
|
8765
9203
|
${checkedAtIso}::timestamptz <= clock_timestamp()
|
|
8766
9204
|
and clock_timestamp() < ${expiresAtIso}::timestamptz
|
|
@@ -8893,16 +9331,16 @@ async function recordUsageEvent(db, input) {
|
|
|
8893
9331
|
}).onConflictDoUpdate({
|
|
8894
9332
|
target: usageEvents.idempotencyKey,
|
|
8895
9333
|
set: {
|
|
8896
|
-
sessionId:
|
|
8897
|
-
turnId:
|
|
8898
|
-
turnAttemptId:
|
|
8899
|
-
initiatorKind:
|
|
8900
|
-
initiatorSubjectId:
|
|
8901
|
-
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
|
|
8902
9340
|
when ${usageEvents.initiatorKind} is null then excluded.initiator_context
|
|
8903
9341
|
else ${usageEvents.initiatorContext}
|
|
8904
9342
|
end`,
|
|
8905
|
-
origin:
|
|
9343
|
+
origin: sql8`coalesce(${usageEvents.origin}, excluded.origin)`
|
|
8906
9344
|
}
|
|
8907
9345
|
}).returning();
|
|
8908
9346
|
if (row) {
|
|
@@ -9033,11 +9471,11 @@ async function recordModelCallFact(db, input) {
|
|
|
9033
9471
|
modelCallFacts.sourceKey
|
|
9034
9472
|
],
|
|
9035
9473
|
set: {
|
|
9036
|
-
turnAttemptId:
|
|
9037
|
-
scheduledTaskId:
|
|
9038
|
-
initiatorKind:
|
|
9039
|
-
initiatorSubjectId:
|
|
9040
|
-
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)`
|
|
9041
9479
|
}
|
|
9042
9480
|
}).returning();
|
|
9043
9481
|
if (!row) {
|
|
@@ -9075,7 +9513,7 @@ async function sumUsageQuantity(db, input) {
|
|
|
9075
9513
|
...input.since ? [gt2(usageEvents.occurredAt, input.since)] : []
|
|
9076
9514
|
];
|
|
9077
9515
|
const [{ total } = { total: 0 }] = await scopedDb.select({
|
|
9078
|
-
total:
|
|
9516
|
+
total: sql8`coalesce(sum(${usageEvents.quantity}), 0)`
|
|
9079
9517
|
}).from(usageEvents).where(and10(...clauses));
|
|
9080
9518
|
return Number(total);
|
|
9081
9519
|
});
|
|
@@ -9113,7 +9551,7 @@ async function applyCreditDebitUpToBalance(db, input) {
|
|
|
9113
9551
|
db,
|
|
9114
9552
|
{ accountId: input.accountId, workspaceId: input.workspaceId ?? null },
|
|
9115
9553
|
async (scopedDb) => {
|
|
9116
|
-
await scopedDb.execute(
|
|
9554
|
+
await scopedDb.execute(sql8`select pg_advisory_xact_lock(hashtext(${input.accountId}))`);
|
|
9117
9555
|
const before = await getBillingBalance(scopedDb, input.accountId);
|
|
9118
9556
|
const candidateDebitMicros = Math.min(
|
|
9119
9557
|
input.requestedAmountMicros,
|
|
@@ -9210,7 +9648,7 @@ async function markStripeWebhookProcessed(db, id) {
|
|
|
9210
9648
|
async function getBillingBalance(db, accountId) {
|
|
9211
9649
|
return await withAccountRls(db, accountId, async (scopedDb) => {
|
|
9212
9650
|
const [{ balance } = { balance: 0 }] = await scopedDb.select({
|
|
9213
|
-
balance:
|
|
9651
|
+
balance: sql8`coalesce(sum(${creditLedgerEntries.amountMicros}), 0)`
|
|
9214
9652
|
}).from(creditLedgerEntries).where(eq10(creditLedgerEntries.accountId, accountId));
|
|
9215
9653
|
return {
|
|
9216
9654
|
accountId,
|
|
@@ -9223,7 +9661,7 @@ async function getBillingBalance(db, accountId) {
|
|
|
9223
9661
|
async function countScheduledTasksForWorkspace(db, workspaceId) {
|
|
9224
9662
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
9225
9663
|
const [{ count } = { count: 0 }] = await scopedDb.select({
|
|
9226
|
-
count:
|
|
9664
|
+
count: sql8`count(*)::int`
|
|
9227
9665
|
}).from(scheduledTasks).where(eq10(scheduledTasks.workspaceId, workspaceId));
|
|
9228
9666
|
return Number(count);
|
|
9229
9667
|
});
|
|
@@ -9439,7 +9877,7 @@ async function claimFileUploadCleanup(db, input) {
|
|
|
9439
9877
|
async function claimExpiredFileUploadCleanup(db, input) {
|
|
9440
9878
|
const rows = await rawRows(
|
|
9441
9879
|
db,
|
|
9442
|
-
|
|
9880
|
+
sql8`
|
|
9443
9881
|
select upload_id, account_id, workspace_id, file_id, object_key
|
|
9444
9882
|
from opengeni_private.claim_expired_file_upload_cleanup(
|
|
9445
9883
|
${input.graceMs},
|
|
@@ -9729,7 +10167,7 @@ async function upsertRegistryCapabilityCatalogItem(db, input) {
|
|
|
9729
10167
|
credentialFacts: values.credentialFacts,
|
|
9730
10168
|
tier: values.tier,
|
|
9731
10169
|
provenance: values.provenance,
|
|
9732
|
-
logoAssetPath:
|
|
10170
|
+
logoAssetPath: sql8`coalesce(excluded.logo_asset_path, ${capabilityCatalogItems.logoAssetPath})`,
|
|
9733
10171
|
importBatchId: values.importBatchId,
|
|
9734
10172
|
stale: false,
|
|
9735
10173
|
staleAt: null,
|
|
@@ -9891,7 +10329,7 @@ async function getCapabilityCatalogItem(db, workspaceId, capabilityId) {
|
|
|
9891
10329
|
isNull3(capabilityCatalogItems.workspaceId)
|
|
9892
10330
|
)
|
|
9893
10331
|
)
|
|
9894
|
-
).orderBy(asc5(
|
|
10332
|
+
).orderBy(asc5(sql8`(${capabilityCatalogItems.workspaceId} is null)`)).limit(1);
|
|
9895
10333
|
if (!row) {
|
|
9896
10334
|
return null;
|
|
9897
10335
|
}
|
|
@@ -10117,7 +10555,7 @@ function connectionExactSubject(subjectId) {
|
|
|
10117
10555
|
}
|
|
10118
10556
|
function personalSlackCanonicalConnectionOrder() {
|
|
10119
10557
|
return [
|
|
10120
|
-
|
|
10558
|
+
sql8`case ${connections.status}
|
|
10121
10559
|
when 'active' then 0
|
|
10122
10560
|
when 'needs_reauth' then 1
|
|
10123
10561
|
when 'error' then 2
|
|
@@ -10198,7 +10636,7 @@ async function updateConnectionInScope(db, input) {
|
|
|
10198
10636
|
...input.status !== void 0 ? { status: input.status } : {},
|
|
10199
10637
|
...input.credentialEncrypted !== void 0 ? {
|
|
10200
10638
|
credentialEncrypted: input.credentialEncrypted,
|
|
10201
|
-
version:
|
|
10639
|
+
version: sql8`${connections.version} + 1`,
|
|
10202
10640
|
lastError: null
|
|
10203
10641
|
} : {},
|
|
10204
10642
|
...input.grantedScopes !== void 0 ? { grantedScopes: input.grantedScopes } : {},
|
|
@@ -10231,11 +10669,11 @@ async function revokeConnectionInScope(db, workspaceId, connectionId, updatedByS
|
|
|
10231
10669
|
status: "revoked",
|
|
10232
10670
|
// The version bump invalidates any in-flight refresh's (id, version) CAS,
|
|
10233
10671
|
// so a racing refresh cannot commit and flip the row back to active.
|
|
10234
|
-
version:
|
|
10672
|
+
version: sql8`${connections.version} + 1`,
|
|
10235
10673
|
// Status-only revocation does not replace the verified credential or bot
|
|
10236
10674
|
// identity. Carry the marker to the same new CAS version so the dedicated
|
|
10237
10675
|
// reinstall path can still recognize (but not use) the inactive row.
|
|
10238
|
-
verifiedInstallVersion:
|
|
10676
|
+
verifiedInstallVersion: sql8`case
|
|
10239
10677
|
when ${connections.verifiedInstallAt} is null then null
|
|
10240
10678
|
else ${connections.version} + 1
|
|
10241
10679
|
end`,
|
|
@@ -10263,7 +10701,7 @@ async function revokeConnection(db, workspaceId, connectionId, updatedBySubjectI
|
|
|
10263
10701
|
);
|
|
10264
10702
|
}
|
|
10265
10703
|
async function resolveSlackInstallationRoute(db, slackTeamId) {
|
|
10266
|
-
const rows = await db.execute(
|
|
10704
|
+
const rows = await db.execute(sql8`select * from opengeni_private.resolve_slack_installation(${slackTeamId})`);
|
|
10267
10705
|
const row = rows[0];
|
|
10268
10706
|
return row ? {
|
|
10269
10707
|
accountId: row.account_id,
|
|
@@ -10283,7 +10721,7 @@ async function saveSlackBotUserLink(db, input) {
|
|
|
10283
10721
|
slackTeamId: input.slackTeamId,
|
|
10284
10722
|
subjectId: input.subjectId,
|
|
10285
10723
|
linkedBySubjectId: input.linkedBySubjectId,
|
|
10286
|
-
updatedAt:
|
|
10724
|
+
updatedAt: sql8`now()`
|
|
10287
10725
|
}
|
|
10288
10726
|
}).returning();
|
|
10289
10727
|
if (!row) throw new Error("Slack identity link write returned no row");
|
|
@@ -10337,7 +10775,7 @@ async function enqueueSlackInteractionInbox(db, input) {
|
|
|
10337
10775
|
}
|
|
10338
10776
|
async function claimSlackInteractionInbox(db, claimHolderId, claimLeaseMs) {
|
|
10339
10777
|
const rows = await db.execute(
|
|
10340
|
-
|
|
10778
|
+
sql8`select * from opengeni_private.claim_slack_interaction_inbox(${claimHolderId}::uuid, ${claimLeaseMs})`
|
|
10341
10779
|
);
|
|
10342
10780
|
return rows[0] ? mapSlackInteractionInbox(rows[0]) : null;
|
|
10343
10781
|
}
|
|
@@ -10348,9 +10786,9 @@ async function settleSlackInteractionInbox(db, input) {
|
|
|
10348
10786
|
claimHolderId: null,
|
|
10349
10787
|
claimExpiresAt: null,
|
|
10350
10788
|
retryAt: null,
|
|
10351
|
-
processedAt:
|
|
10789
|
+
processedAt: sql8`now()`,
|
|
10352
10790
|
lastErrorCode: input.errorCode ?? null,
|
|
10353
|
-
updatedAt:
|
|
10791
|
+
updatedAt: sql8`now()`
|
|
10354
10792
|
}).where(
|
|
10355
10793
|
and10(
|
|
10356
10794
|
eq10(slackInteractionInbox.id, input.entry.id),
|
|
@@ -10369,7 +10807,7 @@ async function releaseSlackInteractionInbox(db, input) {
|
|
|
10369
10807
|
claimExpiresAt: null,
|
|
10370
10808
|
retryAt: input.retryAt,
|
|
10371
10809
|
lastErrorCode: input.errorCode,
|
|
10372
|
-
updatedAt:
|
|
10810
|
+
updatedAt: sql8`now()`
|
|
10373
10811
|
}).where(
|
|
10374
10812
|
and10(
|
|
10375
10813
|
eq10(slackInteractionInbox.id, input.entry.id),
|
|
@@ -10422,7 +10860,7 @@ async function getSlackInteractionSessionAccess(db, workspaceId, rootSessionId)
|
|
|
10422
10860
|
}
|
|
10423
10861
|
async function getSlackInteractionSessionAccessForSession(db, input) {
|
|
10424
10862
|
return await withRlsContext(db, input, async (scopedDb) => {
|
|
10425
|
-
const rows = await scopedDb.execute(
|
|
10863
|
+
const rows = await scopedDb.execute(sql8`
|
|
10426
10864
|
with recursive lineage(id, parent_session_id, depth, path, cycle) as (
|
|
10427
10865
|
select
|
|
10428
10866
|
${sessions.id},
|
|
@@ -10481,7 +10919,7 @@ async function getSlackInteractionSessionAccessForSession(db, input) {
|
|
|
10481
10919
|
}
|
|
10482
10920
|
async function bindSlackInteractionSession(db, input) {
|
|
10483
10921
|
return await withRlsContext(db, input, async (scopedDb) => {
|
|
10484
|
-
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(
|
|
10485
10923
|
and10(
|
|
10486
10924
|
eq10(slackInteractions.id, input.id),
|
|
10487
10925
|
eq10(slackInteractions.owningSubjectId, input.owningSubjectId),
|
|
@@ -10543,7 +10981,7 @@ async function claimSlackInteractionProgressDelivery(db, input) {
|
|
|
10543
10981
|
operationId: crypto.randomUUID()
|
|
10544
10982
|
}).returning();
|
|
10545
10983
|
if (!delivery) throw new Error("Slack progress delivery claim returned no row");
|
|
10546
|
-
const [updated] = await scopedDb.update(slackInteractions).set({ progressCount: slot, updatedAt:
|
|
10984
|
+
const [updated] = await scopedDb.update(slackInteractions).set({ progressCount: slot, updatedAt: sql8`now()` }).where(
|
|
10547
10985
|
and10(
|
|
10548
10986
|
eq10(slackInteractions.id, input.interactionId),
|
|
10549
10987
|
eq10(slackInteractions.deliveryClaimHolderId, input.claimHolderId),
|
|
@@ -10565,14 +11003,14 @@ async function rekeySlackInteractionRoute(db, input) {
|
|
|
10565
11003
|
routeKey: input.routeKey,
|
|
10566
11004
|
slackThreadTs: input.slackThreadTs,
|
|
10567
11005
|
ackSlackMessageTs: input.ackSlackMessageTs,
|
|
10568
|
-
updatedAt:
|
|
11006
|
+
updatedAt: sql8`now()`
|
|
10569
11007
|
}).where(eq10(slackInteractions.id, input.id)).returning();
|
|
10570
11008
|
return row ? mapSlackInteraction(row) : null;
|
|
10571
11009
|
});
|
|
10572
11010
|
}
|
|
10573
11011
|
async function claimSlackInteractionDelivery(db, claimHolderId, claimLeaseMs) {
|
|
10574
11012
|
const rows = await db.execute(
|
|
10575
|
-
|
|
11013
|
+
sql8`select * from opengeni_private.claim_slack_interaction_delivery(${claimHolderId}::uuid, ${claimLeaseMs})`
|
|
10576
11014
|
);
|
|
10577
11015
|
return rows[0] ? mapSlackInteraction(rows[0]) : null;
|
|
10578
11016
|
}
|
|
@@ -10583,7 +11021,7 @@ async function reopenSlackInteractionDelivery(db, input) {
|
|
|
10583
11021
|
deliveryAttemptCount: 0,
|
|
10584
11022
|
deliveryRetryAt: null,
|
|
10585
11023
|
deliveryLastErrorCode: null,
|
|
10586
|
-
updatedAt:
|
|
11024
|
+
updatedAt: sql8`now()`
|
|
10587
11025
|
}).where(eq10(slackInteractions.id, input.id)).returning({ id: slackInteractions.id });
|
|
10588
11026
|
return rows.length === 1;
|
|
10589
11027
|
});
|
|
@@ -10596,7 +11034,7 @@ async function advanceSlackInteractionDelivery(db, input) {
|
|
|
10596
11034
|
deliveryAttemptCount: 0,
|
|
10597
11035
|
deliveryRetryAt: null,
|
|
10598
11036
|
deliveryLastErrorCode: null,
|
|
10599
|
-
updatedAt:
|
|
11037
|
+
updatedAt: sql8`now()`
|
|
10600
11038
|
}).where(
|
|
10601
11039
|
and10(
|
|
10602
11040
|
eq10(slackInteractions.id, input.id),
|
|
@@ -10612,7 +11050,7 @@ async function releaseSlackInteractionDelivery(db, input) {
|
|
|
10612
11050
|
const rows = await scopedDb.update(slackInteractions).set({
|
|
10613
11051
|
deliveryClaimHolderId: null,
|
|
10614
11052
|
deliveryClaimExpiresAt: null,
|
|
10615
|
-
updatedAt:
|
|
11053
|
+
updatedAt: sql8`now()`
|
|
10616
11054
|
}).where(
|
|
10617
11055
|
and10(
|
|
10618
11056
|
eq10(slackInteractions.id, input.id),
|
|
@@ -10629,7 +11067,7 @@ async function deferSlackInteractionDelivery(db, input) {
|
|
|
10629
11067
|
deliveryClaimExpiresAt: null,
|
|
10630
11068
|
deliveryRetryAt: input.retryAt,
|
|
10631
11069
|
deliveryLastErrorCode: input.errorCode.slice(0, 128),
|
|
10632
|
-
updatedAt:
|
|
11070
|
+
updatedAt: sql8`now()`
|
|
10633
11071
|
}).where(
|
|
10634
11072
|
and10(
|
|
10635
11073
|
eq10(slackInteractions.id, input.id),
|
|
@@ -10648,7 +11086,7 @@ async function closeSlackInteractionDelivery(db, input) {
|
|
|
10648
11086
|
deliveryClaimExpiresAt: null,
|
|
10649
11087
|
deliveryRetryAt: null,
|
|
10650
11088
|
deliveryLastErrorCode: input.errorCode?.slice(0, 128) ?? null,
|
|
10651
|
-
updatedAt:
|
|
11089
|
+
updatedAt: sql8`now()`
|
|
10652
11090
|
}).where(
|
|
10653
11091
|
and10(
|
|
10654
11092
|
eq10(slackInteractions.id, input.id),
|
|
@@ -10890,7 +11328,7 @@ async function recordSlackBotInstallCallbackFailure(db, input) {
|
|
|
10890
11328
|
await setSubjectRlsContext(scopedDb, input.subjectId);
|
|
10891
11329
|
await assertWorkspaceAccountPairInScope(scopedDb, input.accountId, input.workspaceId);
|
|
10892
11330
|
await scopedDb.execute(
|
|
10893
|
-
|
|
11331
|
+
sql8`select pg_advisory_xact_lock(hashtextextended(${`slack-callback-failure:${input.workspaceId}:${input.callbackDigest}`}, 0))`
|
|
10894
11332
|
);
|
|
10895
11333
|
const [existing] = await scopedDb.select({ id: auditEvents.id }).from(auditEvents).where(
|
|
10896
11334
|
and10(
|
|
@@ -10946,7 +11384,7 @@ async function claimSlackBotPostOperation(db, input) {
|
|
|
10946
11384
|
requestDigest: input.requestDigest,
|
|
10947
11385
|
status: "provider_started",
|
|
10948
11386
|
claimHolderId: input.claimHolderId,
|
|
10949
|
-
claimExpiresAt:
|
|
11387
|
+
claimExpiresAt: sql8`now() + (${claimLeaseMs} * interval '1 millisecond')`,
|
|
10950
11388
|
attemptCount: 1
|
|
10951
11389
|
}).onConflictDoNothing({
|
|
10952
11390
|
target: [
|
|
@@ -10980,16 +11418,16 @@ async function claimSlackBotPostOperation(db, input) {
|
|
|
10980
11418
|
}
|
|
10981
11419
|
const [reclaimed] = await tx.update(slackBotPostOperations).set({
|
|
10982
11420
|
claimHolderId: input.claimHolderId,
|
|
10983
|
-
claimExpiresAt:
|
|
10984
|
-
attemptCount:
|
|
11421
|
+
claimExpiresAt: sql8`now() + (${claimLeaseMs} * interval '1 millisecond')`,
|
|
11422
|
+
attemptCount: sql8`${slackBotPostOperations.attemptCount} + 1`,
|
|
10985
11423
|
lastFailureCode: null,
|
|
10986
|
-
updatedAt:
|
|
11424
|
+
updatedAt: sql8`now()`
|
|
10987
11425
|
}).where(
|
|
10988
11426
|
and10(
|
|
10989
11427
|
eq10(slackBotPostOperations.id, existing.id),
|
|
10990
11428
|
or3(
|
|
10991
11429
|
isNull3(slackBotPostOperations.claimHolderId),
|
|
10992
|
-
lte2(slackBotPostOperations.claimExpiresAt,
|
|
11430
|
+
lte2(slackBotPostOperations.claimExpiresAt, sql8`now()`)
|
|
10993
11431
|
)
|
|
10994
11432
|
)
|
|
10995
11433
|
).returning();
|
|
@@ -11012,7 +11450,7 @@ async function releaseSlackBotPostOperationClaim(db, input) {
|
|
|
11012
11450
|
claimHolderId: null,
|
|
11013
11451
|
claimExpiresAt: null,
|
|
11014
11452
|
lastFailureCode: input.failureCode.slice(0, 128),
|
|
11015
|
-
updatedAt:
|
|
11453
|
+
updatedAt: sql8`now()`
|
|
11016
11454
|
}).where(
|
|
11017
11455
|
and10(
|
|
11018
11456
|
eq10(slackBotPostOperations.workspaceId, input.workspaceId),
|
|
@@ -11057,8 +11495,8 @@ async function completeSlackBotPostOperation(db, input) {
|
|
|
11057
11495
|
lastFailureCode: null,
|
|
11058
11496
|
slackChannelId: input.slackChannelId,
|
|
11059
11497
|
slackMessageTimestamp: input.slackMessageTimestamp,
|
|
11060
|
-
completedAt:
|
|
11061
|
-
updatedAt:
|
|
11498
|
+
completedAt: sql8`now()`,
|
|
11499
|
+
updatedAt: sql8`now()`
|
|
11062
11500
|
}).where(eq10(slackBotPostOperations.id, current.id)).returning();
|
|
11063
11501
|
if (!completed) throw new Error("Slack post completion returned no row");
|
|
11064
11502
|
await tx.insert(auditEvents).values({
|
|
@@ -11121,7 +11559,7 @@ async function claimSlackBotDeleteOperation(db, input) {
|
|
|
11121
11559
|
requestDigest: input.requestDigest,
|
|
11122
11560
|
status: "pending",
|
|
11123
11561
|
claimHolderId: input.claimHolderId,
|
|
11124
|
-
claimExpiresAt:
|
|
11562
|
+
claimExpiresAt: sql8`now() + (${claimLeaseMs} * interval '1 millisecond')`,
|
|
11125
11563
|
attemptCount: 1
|
|
11126
11564
|
}).onConflictDoNothing({
|
|
11127
11565
|
target: [
|
|
@@ -11161,9 +11599,9 @@ async function claimSlackBotDeleteOperation(db, input) {
|
|
|
11161
11599
|
const [reclaimed] = await tx.update(slackBotDeleteOperations).set({
|
|
11162
11600
|
status: nextStatus,
|
|
11163
11601
|
claimHolderId: input.claimHolderId,
|
|
11164
|
-
claimExpiresAt:
|
|
11165
|
-
attemptCount:
|
|
11166
|
-
updatedAt:
|
|
11602
|
+
claimExpiresAt: sql8`now() + (${claimLeaseMs} * interval '1 millisecond')`,
|
|
11603
|
+
attemptCount: sql8`${slackBotDeleteOperations.attemptCount} + 1`,
|
|
11604
|
+
updatedAt: sql8`now()`
|
|
11167
11605
|
}).where(eq10(slackBotDeleteOperations.id, existing.id)).returning();
|
|
11168
11606
|
if (!reclaimed) throw new Error("Slack delete operation reclaim returned no row");
|
|
11169
11607
|
return {
|
|
@@ -11178,7 +11616,7 @@ async function markSlackBotDeleteOperationProviderStarted(db, input) {
|
|
|
11178
11616
|
db,
|
|
11179
11617
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
11180
11618
|
async (scopedDb) => {
|
|
11181
|
-
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(
|
|
11182
11620
|
and10(
|
|
11183
11621
|
eq10(slackBotDeleteOperations.workspaceId, input.workspaceId),
|
|
11184
11622
|
eq10(slackBotDeleteOperations.connectionId, input.connectionId),
|
|
@@ -11204,7 +11642,7 @@ async function releaseSlackBotDeleteOperationClaim(db, input) {
|
|
|
11204
11642
|
claimHolderId: null,
|
|
11205
11643
|
claimExpiresAt: null,
|
|
11206
11644
|
lastFailureCode: input.failureCode.slice(0, 128),
|
|
11207
|
-
updatedAt:
|
|
11645
|
+
updatedAt: sql8`now()`
|
|
11208
11646
|
}).where(
|
|
11209
11647
|
and10(
|
|
11210
11648
|
eq10(slackBotDeleteOperations.workspaceId, input.workspaceId),
|
|
@@ -11249,8 +11687,8 @@ async function completeSlackBotDeleteOperation(db, input) {
|
|
|
11249
11687
|
lastFailureCode: null,
|
|
11250
11688
|
slackChannelId: input.slackChannelId,
|
|
11251
11689
|
slackMessageTimestamp: input.slackMessageTimestamp,
|
|
11252
|
-
completedAt:
|
|
11253
|
-
updatedAt:
|
|
11690
|
+
completedAt: sql8`now()`,
|
|
11691
|
+
updatedAt: sql8`now()`
|
|
11254
11692
|
}).where(eq10(slackBotDeleteOperations.id, current.id)).returning();
|
|
11255
11693
|
if (!completed) throw new Error("Slack delete completion returned no row");
|
|
11256
11694
|
await tx.insert(auditEvents).values({
|
|
@@ -11313,7 +11751,7 @@ async function loadConnectionCredentialForBroker(db, settings, input) {
|
|
|
11313
11751
|
const personalSlackSubjectLookup = !input.connectionId && input.allowSubjectOwned === true && input.providerDomain === "slack.com" && input.kind === "oauth2";
|
|
11314
11752
|
const [row] = await scopedDb.select().from(connections).where(and10(...conditions)).orderBy(
|
|
11315
11753
|
...personalSlackSubjectLookup ? personalSlackCanonicalConnectionOrder() : [
|
|
11316
|
-
desc5(
|
|
11754
|
+
desc5(sql8`(${connections.status} = 'active')`),
|
|
11317
11755
|
desc5(connections.updatedAt)
|
|
11318
11756
|
]
|
|
11319
11757
|
).limit(1);
|
|
@@ -11362,7 +11800,7 @@ async function recordConnectionTokenRefresh(db, input) {
|
|
|
11362
11800
|
lastRefreshAt: input.lastRefreshAt,
|
|
11363
11801
|
status: "active",
|
|
11364
11802
|
lastError: null,
|
|
11365
|
-
version:
|
|
11803
|
+
version: sql8`${connections.version} + 1`,
|
|
11366
11804
|
updatedAt: /* @__PURE__ */ new Date(),
|
|
11367
11805
|
...input.grantedScopes !== void 0 ? { grantedScopes: input.grantedScopes } : {}
|
|
11368
11806
|
};
|
|
@@ -11386,8 +11824,8 @@ async function setConnectionStatus(db, workspaceId, status, lastError, guard) {
|
|
|
11386
11824
|
const updated = await scopedDb.update(connections).set({
|
|
11387
11825
|
status,
|
|
11388
11826
|
lastError,
|
|
11389
|
-
version:
|
|
11390
|
-
verifiedInstallVersion:
|
|
11827
|
+
version: sql8`${connections.version} + 1`,
|
|
11828
|
+
verifiedInstallVersion: sql8`case
|
|
11391
11829
|
when ${connections.verifiedInstallAt} is null then null
|
|
11392
11830
|
else ${connections.version} + 1
|
|
11393
11831
|
end`,
|
|
@@ -11623,7 +12061,7 @@ async function updateKnowledgeMemory(db, workspaceId, memoryId, input, embedder)
|
|
|
11623
12061
|
);
|
|
11624
12062
|
if (willBeVisible) {
|
|
11625
12063
|
const [{ visibleCount } = { visibleCount: 0 }] = await scopedDb.select({
|
|
11626
|
-
visibleCount:
|
|
12064
|
+
visibleCount: sql8`count(*)::int`
|
|
11627
12065
|
}).from(knowledgeMemories).where(
|
|
11628
12066
|
and10(
|
|
11629
12067
|
eq10(knowledgeMemories.workspaceId, workspaceId),
|
|
@@ -11752,7 +12190,7 @@ async function listKnowledgeMemories(db, workspaceId, options = {}) {
|
|
|
11752
12190
|
const query = cleanDbString(options.query);
|
|
11753
12191
|
if (query) {
|
|
11754
12192
|
conditions.push(
|
|
11755
|
-
|
|
12193
|
+
sql8`to_tsvector('simple', ${knowledgeMemories.text}) @@ plainto_tsquery('simple', ${query})`
|
|
11756
12194
|
);
|
|
11757
12195
|
}
|
|
11758
12196
|
const limit = Math.min(Math.max(options.limit ?? 20, 1), 100);
|
|
@@ -11780,17 +12218,21 @@ function memoryVectorLiteral(values) {
|
|
|
11780
12218
|
return `[${values.join(",")}]`;
|
|
11781
12219
|
}
|
|
11782
12220
|
var agentVisibleMemoryStatuses = [...AGENT_VISIBLE_MEMORY_STATUSES];
|
|
11783
|
-
var
|
|
12221
|
+
var visibleTextHashUniqueIndexNames = /* @__PURE__ */ new Set([
|
|
12222
|
+
"knowledge_memories_workspace_visible_text_hash_uq",
|
|
12223
|
+
"knowledge_memories_scope_visible_text_hash_uq"
|
|
12224
|
+
]);
|
|
11784
12225
|
function isVisibleTextHashUniqueViolation(error) {
|
|
11785
12226
|
const candidate = error;
|
|
11786
12227
|
if (!candidate || typeof candidate !== "object") {
|
|
11787
12228
|
return false;
|
|
11788
12229
|
}
|
|
11789
12230
|
const constraint = candidate.constraint ?? candidate.constraint_name;
|
|
11790
|
-
if (candidate.code === "23505" && constraint
|
|
12231
|
+
if (candidate.code === "23505" && visibleTextHashUniqueIndexNames.has(String(constraint))) {
|
|
11791
12232
|
return true;
|
|
11792
12233
|
}
|
|
11793
|
-
|
|
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"))) {
|
|
11794
12236
|
return true;
|
|
11795
12237
|
}
|
|
11796
12238
|
return isVisibleTextHashUniqueViolation(candidate.cause);
|
|
@@ -11852,7 +12294,7 @@ async function resolveWorkspaceMemoryId(scopedDb, workspaceId, rawId) {
|
|
|
11852
12294
|
const matches = await scopedDb.select({ id: knowledgeMemories.id }).from(knowledgeMemories).where(
|
|
11853
12295
|
and10(
|
|
11854
12296
|
eq10(knowledgeMemories.workspaceId, workspaceId),
|
|
11855
|
-
|
|
12297
|
+
sql8`${knowledgeMemories.id}::text like ${`${candidate}%`}`,
|
|
11856
12298
|
ne(knowledgeMemories.status, "archived"),
|
|
11857
12299
|
ne(knowledgeMemories.status, "superseded"),
|
|
11858
12300
|
ne(knowledgeMemories.status, "rejected")
|
|
@@ -12008,14 +12450,14 @@ async function saveWorkspaceMemory(db, input, embedder) {
|
|
|
12008
12450
|
inArray5(knowledgeMemories.status, agentVisibleMemoryStatuses)
|
|
12009
12451
|
)
|
|
12010
12452
|
).orderBy(
|
|
12011
|
-
replacesFullId ?
|
|
12453
|
+
replacesFullId ? sql8`case when ${knowledgeMemories.id} = ${replacesFullId} then 1 else 0 end` : knowledgeMemories.updatedAt
|
|
12012
12454
|
).limit(replacesFullId ? 2 : 1);
|
|
12013
12455
|
const exact = exactMatches.find((row) => row.id !== replacesFullId) ?? exactMatches[0];
|
|
12014
12456
|
if (exact) {
|
|
12015
12457
|
return await dedupeToExisting(exact, "exact");
|
|
12016
12458
|
}
|
|
12017
12459
|
if (embedding && embeddingModel) {
|
|
12018
|
-
const distance =
|
|
12460
|
+
const distance = sql8`${knowledgeMemories.embedding} <=> ${memoryVectorLiteral(embedding)}::vector`;
|
|
12019
12461
|
const neighbours = await scopedDb.select({
|
|
12020
12462
|
id: knowledgeMemories.id,
|
|
12021
12463
|
distance
|
|
@@ -12024,7 +12466,7 @@ async function saveWorkspaceMemory(db, input, embedder) {
|
|
|
12024
12466
|
eq10(knowledgeMemories.workspaceId, input.workspaceId),
|
|
12025
12467
|
inArray5(knowledgeMemories.status, agentVisibleMemoryStatuses),
|
|
12026
12468
|
eq10(knowledgeMemories.embeddingModel, embeddingModel),
|
|
12027
|
-
|
|
12469
|
+
sql8`${knowledgeMemories.embedding} is not null`
|
|
12028
12470
|
)
|
|
12029
12471
|
).orderBy(distance).limit(MEMORY_NEAR_DUP_NEIGHBORS);
|
|
12030
12472
|
const duplicateNeighbours = neighbours.filter(
|
|
@@ -12044,7 +12486,7 @@ async function saveWorkspaceMemory(db, input, embedder) {
|
|
|
12044
12486
|
}
|
|
12045
12487
|
}
|
|
12046
12488
|
const [{ visibleCount } = { visibleCount: 0 }] = await scopedDb.select({
|
|
12047
|
-
visibleCount:
|
|
12489
|
+
visibleCount: sql8`count(*)::int`
|
|
12048
12490
|
}).from(knowledgeMemories).where(
|
|
12049
12491
|
and10(
|
|
12050
12492
|
eq10(knowledgeMemories.workspaceId, input.workspaceId),
|
|
@@ -12229,12 +12671,12 @@ async function searchWorkspaceMemories(db, workspaceId, input, embedder) {
|
|
|
12229
12671
|
if (!vector || vector.length === 0) {
|
|
12230
12672
|
throw new Error("embedder returned no query vector");
|
|
12231
12673
|
}
|
|
12232
|
-
const distance =
|
|
12674
|
+
const distance = sql8`${knowledgeMemories.embedding} <=> ${memoryVectorLiteral(vector)}::vector`;
|
|
12233
12675
|
const rows = await scopedDb.select({ id: knowledgeMemories.id, distance }).from(knowledgeMemories).where(
|
|
12234
12676
|
and10(
|
|
12235
12677
|
...baseConditions,
|
|
12236
12678
|
eq10(knowledgeMemories.embeddingModel, embedder.model),
|
|
12237
|
-
|
|
12679
|
+
sql8`${knowledgeMemories.embedding} is not null`
|
|
12238
12680
|
)
|
|
12239
12681
|
).orderBy(distance).limit(candidateLimit);
|
|
12240
12682
|
for (const row of rows) {
|
|
@@ -12258,11 +12700,11 @@ async function searchWorkspaceMemories(db, workspaceId, input, embedder) {
|
|
|
12258
12700
|
}
|
|
12259
12701
|
}
|
|
12260
12702
|
if (mode === "keyword" || mode === "hybrid") {
|
|
12261
|
-
const rank =
|
|
12703
|
+
const rank = sql8`ts_rank_cd(to_tsvector('simple', ${knowledgeMemories.text}), plainto_tsquery('simple', ${query}))`;
|
|
12262
12704
|
const rows = await scopedDb.select({ id: knowledgeMemories.id, rank }).from(knowledgeMemories).where(
|
|
12263
12705
|
and10(
|
|
12264
12706
|
...baseConditions,
|
|
12265
|
-
|
|
12707
|
+
sql8`to_tsvector('simple', ${knowledgeMemories.text}) @@ plainto_tsquery('simple', ${query})`
|
|
12266
12708
|
)
|
|
12267
12709
|
).orderBy(desc5(rank)).limit(candidateLimit);
|
|
12268
12710
|
for (const row of rows) {
|
|
@@ -12295,7 +12737,7 @@ async function searchWorkspaceMemories(db, workspaceId, input, embedder) {
|
|
|
12295
12737
|
}
|
|
12296
12738
|
const ids = ranked.map((entry) => entry.id);
|
|
12297
12739
|
const bumped = await scopedDb.update(knowledgeMemories).set({
|
|
12298
|
-
usageCount:
|
|
12740
|
+
usageCount: sql8`${knowledgeMemories.usageCount} + 1`,
|
|
12299
12741
|
lastUsedAt: /* @__PURE__ */ new Date()
|
|
12300
12742
|
}).where(
|
|
12301
12743
|
and10(
|
|
@@ -12651,7 +13093,7 @@ async function createScheduledTaskRun(db, input) {
|
|
|
12651
13093
|
};
|
|
12652
13094
|
const [inserted] = input.producerKey ? await scopedDb.insert(scheduledTaskRuns).values(values).onConflictDoNothing({
|
|
12653
13095
|
target: [scheduledTaskRuns.workspaceId, scheduledTaskRuns.producerKey],
|
|
12654
|
-
where:
|
|
13096
|
+
where: sql8`${scheduledTaskRuns.producerKey} is not null`
|
|
12655
13097
|
}).returning() : await scopedDb.insert(scheduledTaskRuns).values(values).returning();
|
|
12656
13098
|
const [row] = inserted ? [inserted] : await scopedDb.select().from(scheduledTaskRuns).where(
|
|
12657
13099
|
and10(
|
|
@@ -12850,7 +13292,7 @@ async function deleteVariableSet(db, workspaceId, variableSetId) {
|
|
|
12850
13292
|
async function countVariableSets(db, workspaceId) {
|
|
12851
13293
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
12852
13294
|
const [{ count } = { count: 0 }] = await scopedDb.select({
|
|
12853
|
-
count:
|
|
13295
|
+
count: sql8`count(*)::int`
|
|
12854
13296
|
}).from(workspaceVariableSets).where(eq10(workspaceVariableSets.workspaceId, workspaceId));
|
|
12855
13297
|
return Number(count);
|
|
12856
13298
|
});
|
|
@@ -12858,7 +13300,7 @@ async function countVariableSets(db, workspaceId) {
|
|
|
12858
13300
|
async function countScheduledTasksUsingVariableSet(db, workspaceId, variableSetId) {
|
|
12859
13301
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
12860
13302
|
const [{ count } = { count: 0 }] = await scopedDb.select({
|
|
12861
|
-
count:
|
|
13303
|
+
count: sql8`count(*)::int`
|
|
12862
13304
|
}).from(scheduledTasks).where(
|
|
12863
13305
|
and10(
|
|
12864
13306
|
eq10(scheduledTasks.workspaceId, workspaceId),
|
|
@@ -12871,7 +13313,7 @@ async function countScheduledTasksUsingVariableSet(db, workspaceId, variableSetI
|
|
|
12871
13313
|
async function countActiveSessionsUsingVariableSet(db, workspaceId, variableSetId) {
|
|
12872
13314
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
12873
13315
|
const [{ count } = { count: 0 }] = await scopedDb.select({
|
|
12874
|
-
count:
|
|
13316
|
+
count: sql8`count(*)::int`
|
|
12875
13317
|
}).from(sessions).where(
|
|
12876
13318
|
and10(
|
|
12877
13319
|
eq10(sessions.workspaceId, workspaceId),
|
|
@@ -12902,7 +13344,7 @@ async function setVariableSetVariable(db, input) {
|
|
|
12902
13344
|
],
|
|
12903
13345
|
set: {
|
|
12904
13346
|
valueEncrypted: input.valueEncrypted,
|
|
12905
|
-
version:
|
|
13347
|
+
version: sql8`${workspaceVariableSetVariables.version} + 1`,
|
|
12906
13348
|
updatedAt: now
|
|
12907
13349
|
}
|
|
12908
13350
|
}).returning({
|
|
@@ -13028,7 +13470,7 @@ async function loadRigActiveAndCount(scopedDb, workspaceId, rigId) {
|
|
|
13028
13470
|
eq10(rigVersions.active, true)
|
|
13029
13471
|
)
|
|
13030
13472
|
).limit(1);
|
|
13031
|
-
const [{ count } = { count: 0 }] = await scopedDb.select({ count:
|
|
13473
|
+
const [{ count } = { count: 0 }] = await scopedDb.select({ count: sql8`count(*)::int` }).from(rigVersions).where(
|
|
13032
13474
|
and10(eq10(rigVersions.workspaceId, workspaceId), eq10(rigVersions.rigId, rigId))
|
|
13033
13475
|
);
|
|
13034
13476
|
return {
|
|
@@ -13101,7 +13543,7 @@ async function loadRigHealthByActiveVersion(scopedDb, workspaceId, activeVersion
|
|
|
13101
13543
|
eq10(auditEvents.workspaceId, workspaceId),
|
|
13102
13544
|
eq10(auditEvents.targetType, "rig"),
|
|
13103
13545
|
inArray5(auditEvents.action, ["rig.verification.passed", "rig.verification.failed"]),
|
|
13104
|
-
inArray5(
|
|
13546
|
+
inArray5(sql8`${auditEvents.metadata}->>'versionId'`, versionIds)
|
|
13105
13547
|
)
|
|
13106
13548
|
);
|
|
13107
13549
|
for (const row of auditRows) {
|
|
@@ -13174,7 +13616,7 @@ async function listRigs(db, workspaceId) {
|
|
|
13174
13616
|
]);
|
|
13175
13617
|
const countRows = await scopedDb.select({
|
|
13176
13618
|
rigId: rigVersions.rigId,
|
|
13177
|
-
count:
|
|
13619
|
+
count: sql8`count(*)::int`
|
|
13178
13620
|
}).from(rigVersions).where(eq10(rigVersions.workspaceId, workspaceId)).groupBy(rigVersions.rigId);
|
|
13179
13621
|
const countByRig = new Map(countRows.map((row) => [row.rigId, Number(row.count)]));
|
|
13180
13622
|
return rows.map((row) => {
|
|
@@ -13276,11 +13718,11 @@ async function deleteRigIfNoActiveSessions(db, workspaceId, rigId) {
|
|
|
13276
13718
|
if (!rig) {
|
|
13277
13719
|
return { deleted: false, activeSessionCount: 0 };
|
|
13278
13720
|
}
|
|
13279
|
-
const [{ count } = { count: 0 }] = await scopedDb.select({ count:
|
|
13721
|
+
const [{ count } = { count: 0 }] = await scopedDb.select({ count: sql8`count(*)::int` }).from(sessions).where(
|
|
13280
13722
|
and10(
|
|
13281
13723
|
eq10(sessions.workspaceId, workspaceId),
|
|
13282
13724
|
eq10(sessions.rigId, rigId),
|
|
13283
|
-
|
|
13725
|
+
sql8`${sessions.status} not in ('failed', 'cancelled')`
|
|
13284
13726
|
)
|
|
13285
13727
|
);
|
|
13286
13728
|
const activeSessionCount = Number(count);
|
|
@@ -13293,13 +13735,13 @@ async function deleteRigIfNoActiveSessions(db, workspaceId, rigId) {
|
|
|
13293
13735
|
}
|
|
13294
13736
|
async function countRigs(db, workspaceId) {
|
|
13295
13737
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
13296
|
-
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));
|
|
13297
13739
|
return Number(count);
|
|
13298
13740
|
});
|
|
13299
13741
|
}
|
|
13300
13742
|
async function countSessionsUsingRig(db, workspaceId, rigId) {
|
|
13301
13743
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
13302
|
-
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)));
|
|
13303
13745
|
return Number(count);
|
|
13304
13746
|
});
|
|
13305
13747
|
}
|
|
@@ -13310,7 +13752,7 @@ async function createRigVersion(db, workspaceId, rigId, input, options = {}) {
|
|
|
13310
13752
|
throw new Error(`Rig not found: ${rigId}`);
|
|
13311
13753
|
}
|
|
13312
13754
|
const [{ max } = { max: 0 }] = await scopedDb.select({
|
|
13313
|
-
max:
|
|
13755
|
+
max: sql8`coalesce(max(${rigVersions.version}), 0)::int`
|
|
13314
13756
|
}).from(rigVersions).where(
|
|
13315
13757
|
and10(eq10(rigVersions.workspaceId, workspaceId), eq10(rigVersions.rigId, rigId))
|
|
13316
13758
|
);
|
|
@@ -13386,7 +13828,7 @@ async function createRigVersionForChangePromotion(db, workspaceId, rigId, change
|
|
|
13386
13828
|
);
|
|
13387
13829
|
}
|
|
13388
13830
|
const [{ max } = { max: 0 }] = await scopedDb.select({
|
|
13389
|
-
max:
|
|
13831
|
+
max: sql8`coalesce(max(${rigVersions.version}), 0)::int`
|
|
13390
13832
|
}).from(rigVersions).where(
|
|
13391
13833
|
and10(eq10(rigVersions.workspaceId, workspaceId), eq10(rigVersions.rigId, rigId))
|
|
13392
13834
|
);
|
|
@@ -13448,20 +13890,20 @@ async function listRigVersionMonitoringSummaries(db, workspaceId, rigId, limit =
|
|
|
13448
13890
|
rigId: rigVersions.rigId,
|
|
13449
13891
|
version: rigVersions.version,
|
|
13450
13892
|
active: rigVersions.active,
|
|
13451
|
-
image:
|
|
13452
|
-
imageOriginalChars:
|
|
13453
|
-
setupScriptBytes:
|
|
13454
|
-
checkCount:
|
|
13455
|
-
credentialHookCount:
|
|
13456
|
-
defaultVariableSetCount:
|
|
13457
|
-
changelog:
|
|
13458
|
-
changelogOriginalChars:
|
|
13459
|
-
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)`,
|
|
13460
13902
|
createdAt: rigVersions.createdAt
|
|
13461
13903
|
}).from(rigVersions).where(
|
|
13462
13904
|
and10(eq10(rigVersions.workspaceId, workspaceId), eq10(rigVersions.rigId, rigId))
|
|
13463
13905
|
).orderBy(desc5(rigVersions.version), desc5(rigVersions.id)).limit(boundedLimit + 1);
|
|
13464
|
-
const [{ total } = { total: 0 }] = await scopedDb.select({ total:
|
|
13906
|
+
const [{ total } = { total: 0 }] = await scopedDb.select({ total: sql8`count(*)::int` }).from(rigVersions).where(
|
|
13465
13907
|
and10(eq10(rigVersions.workspaceId, workspaceId), eq10(rigVersions.rigId, rigId))
|
|
13466
13908
|
);
|
|
13467
13909
|
return {
|
|
@@ -13582,16 +14024,16 @@ async function listRigChangeMonitoringSummaries(db, workspaceId, rigId, limit =
|
|
|
13582
14024
|
baseVersionId: rigChanges.baseVersionId,
|
|
13583
14025
|
kind: rigChanges.kind,
|
|
13584
14026
|
status: rigChanges.status,
|
|
13585
|
-
proposedBy:
|
|
14027
|
+
proposedBy: sql8`left(${rigChanges.proposedBy}, 200)`,
|
|
13586
14028
|
resultVersionId: rigChanges.resultVersionId,
|
|
13587
|
-
commandPreview:
|
|
13588
|
-
commandOriginalChars:
|
|
13589
|
-
payloadBytes:
|
|
13590
|
-
verificationBytes:
|
|
13591
|
-
verificationLogBytes:
|
|
13592
|
-
verificationStartedAt:
|
|
13593
|
-
verificationFinishedAt:
|
|
13594
|
-
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
|
|
13595
14037
|
when ${rigChanges.verification}->>'passed' = 'true' then true
|
|
13596
14038
|
when ${rigChanges.verification}->>'passed' = 'false' then false
|
|
13597
14039
|
else null
|
|
@@ -13601,7 +14043,7 @@ async function listRigChangeMonitoringSummaries(db, workspaceId, rigId, limit =
|
|
|
13601
14043
|
}).from(rigChanges).where(
|
|
13602
14044
|
and10(eq10(rigChanges.workspaceId, workspaceId), eq10(rigChanges.rigId, rigId))
|
|
13603
14045
|
).orderBy(desc5(rigChanges.createdAt), desc5(rigChanges.id)).limit(boundedLimit + 1);
|
|
13604
|
-
const [{ total } = { total: 0 }] = await scopedDb.select({ total:
|
|
14046
|
+
const [{ total } = { total: 0 }] = await scopedDb.select({ total: sql8`count(*)::int` }).from(rigChanges).where(
|
|
13605
14047
|
and10(eq10(rigChanges.workspaceId, workspaceId), eq10(rigChanges.rigId, rigId))
|
|
13606
14048
|
);
|
|
13607
14049
|
return {
|
|
@@ -13784,7 +14226,7 @@ async function upsertCodexSubscriptionCredential(db, input) {
|
|
|
13784
14226
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
13785
14227
|
async (scopedDb) => {
|
|
13786
14228
|
await scopedDb.execute(
|
|
13787
|
-
|
|
14229
|
+
sql8`select pg_advisory_xact_lock(hashtextextended(${`codex-credential-upsert:${input.workspaceId}:${input.chatgptAccountId ?? "null"}`}, 0))`
|
|
13788
14230
|
);
|
|
13789
14231
|
const [existing] = input.chatgptAccountId ? await scopedDb.select({
|
|
13790
14232
|
id: codexSubscriptionCredentials.id,
|
|
@@ -13835,7 +14277,7 @@ async function upsertCodexSubscriptionCredential(db, input) {
|
|
|
13835
14277
|
codexSubscriptionCredentials.workspaceId,
|
|
13836
14278
|
codexSubscriptionCredentials.chatgptAccountId
|
|
13837
14279
|
],
|
|
13838
|
-
targetWhere:
|
|
14280
|
+
targetWhere: sql8`chatgpt_account_id is not null`,
|
|
13839
14281
|
set: {
|
|
13840
14282
|
// account_id MUST be re-asserted on conflict. Omitting it leaves a stale
|
|
13841
14283
|
// account_id on a row whose owning account changed (e.g. a reconnect
|
|
@@ -13851,7 +14293,7 @@ async function upsertCodexSubscriptionCredential(db, input) {
|
|
|
13851
14293
|
// Refresh the derived email; keep an existing user-chosen label (only seed
|
|
13852
14294
|
// it when still null) so a re-connect never clobbers a rename.
|
|
13853
14295
|
accountEmail: input.accountEmail ?? null,
|
|
13854
|
-
label:
|
|
14296
|
+
label: sql8`coalesce(${codexSubscriptionCredentials.label}, ${input.label ?? null})`,
|
|
13855
14297
|
// Ownership follows the most recent connection exactly. A
|
|
13856
14298
|
// configured/delegated/API-key reconnect is intentionally
|
|
13857
14299
|
// nonhuman and clears the prior human owner, making the row
|
|
@@ -13859,7 +14301,7 @@ async function upsertCodexSubscriptionCredential(db, input) {
|
|
|
13859
14301
|
connectedBySubjectId: input.connectedBySubjectId ?? null,
|
|
13860
14302
|
status: "active",
|
|
13861
14303
|
lastError: null,
|
|
13862
|
-
version:
|
|
14304
|
+
version: sql8`${codexSubscriptionCredentials.version} + 1`,
|
|
13863
14305
|
updatedAt: now
|
|
13864
14306
|
}
|
|
13865
14307
|
}).returning({
|
|
@@ -13931,7 +14373,7 @@ async function recordCodexTokenRefresh(db, input) {
|
|
|
13931
14373
|
lastRefreshAt: input.lastRefreshAt,
|
|
13932
14374
|
status: "active",
|
|
13933
14375
|
lastError: null,
|
|
13934
|
-
version:
|
|
14376
|
+
version: sql8`${codexSubscriptionCredentials.version} + 1`,
|
|
13935
14377
|
updatedAt: /* @__PURE__ */ new Date()
|
|
13936
14378
|
}).where(
|
|
13937
14379
|
and10(
|
|
@@ -13945,9 +14387,9 @@ async function recordCodexTokenRefresh(db, input) {
|
|
|
13945
14387
|
}
|
|
13946
14388
|
async function withCodexCredentialRefreshLock(db, workspaceId, credentialId, fn) {
|
|
13947
14389
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
13948
|
-
await scopedDb.execute(
|
|
14390
|
+
await scopedDb.execute(sql8`set local lock_timeout = '30s'`);
|
|
13949
14391
|
await scopedDb.execute(
|
|
13950
|
-
|
|
14392
|
+
sql8`select pg_advisory_xact_lock(hashtextextended(${`codex-refresh:${credentialId}`}, 0))`
|
|
13951
14393
|
);
|
|
13952
14394
|
return await fn(scopedDb);
|
|
13953
14395
|
});
|
|
@@ -13986,7 +14428,7 @@ async function setCodexCredentialStatusById(db, workspaceId, credentialId, statu
|
|
|
13986
14428
|
});
|
|
13987
14429
|
}
|
|
13988
14430
|
async function getCodexCredentialStatusScoped(scopedDb, workspaceId) {
|
|
13989
|
-
await scopedDb.execute(
|
|
14431
|
+
await scopedDb.execute(sql8`
|
|
13990
14432
|
select id from codex_rotation_settings
|
|
13991
14433
|
where workspace_id = ${workspaceId}
|
|
13992
14434
|
for update
|
|
@@ -14133,7 +14575,7 @@ function filterCodexLeaseCandidatesForPolicy(accounts, policyScope, filter) {
|
|
|
14133
14575
|
return { accounts: [...filteredAccounts], unavailableDiagnostics };
|
|
14134
14576
|
}
|
|
14135
14577
|
async function listCodexLeaseCandidatesInTransaction(tx, input) {
|
|
14136
|
-
const rows = await tx.execute(
|
|
14578
|
+
const rows = await tx.execute(sql8`
|
|
14137
14579
|
select
|
|
14138
14580
|
c.id,
|
|
14139
14581
|
c.chatgpt_account_id,
|
|
@@ -14182,13 +14624,13 @@ async function acquireCodexCredentialLease(db, input, select) {
|
|
|
14182
14624
|
db,
|
|
14183
14625
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
14184
14626
|
async (tx) => {
|
|
14185
|
-
await tx.execute(
|
|
14627
|
+
await tx.execute(sql8`
|
|
14186
14628
|
insert into codex_rotation_settings
|
|
14187
14629
|
(account_id, workspace_id, lease_rotation_enabled)
|
|
14188
14630
|
values (${input.accountId}, ${input.workspaceId}, false)
|
|
14189
14631
|
on conflict (workspace_id) do nothing
|
|
14190
14632
|
`);
|
|
14191
|
-
const settingsRows = await tx.execute(
|
|
14633
|
+
const settingsRows = await tx.execute(sql8`
|
|
14192
14634
|
select active_credential_id, rotation_enabled,
|
|
14193
14635
|
lease_rotation_enabled, rotation_strategy
|
|
14194
14636
|
from codex_rotation_settings
|
|
@@ -14199,7 +14641,7 @@ async function acquireCodexCredentialLease(db, input, select) {
|
|
|
14199
14641
|
if (!settingsRow) {
|
|
14200
14642
|
throw new Error(`Codex rotation settings not visible for workspace ${input.workspaceId}`);
|
|
14201
14643
|
}
|
|
14202
|
-
const turns = await tx.execute(
|
|
14644
|
+
const turns = await tx.execute(sql8`
|
|
14203
14645
|
select id, metadata from session_turns
|
|
14204
14646
|
where account_id = ${input.accountId}
|
|
14205
14647
|
and workspace_id = ${input.workspaceId}
|
|
@@ -14211,7 +14653,7 @@ async function acquireCodexCredentialLease(db, input, select) {
|
|
|
14211
14653
|
}
|
|
14212
14654
|
const policyScope = input.resolvePolicyScope?.(turns[0].metadata ?? {}) ?? null;
|
|
14213
14655
|
const continuationRows = input.continuationCredentialId ? await tx.execute(
|
|
14214
|
-
|
|
14656
|
+
sql8`
|
|
14215
14657
|
select frozen_codex_credential_id
|
|
14216
14658
|
from agent_run_states
|
|
14217
14659
|
where account_id = ${input.accountId}
|
|
@@ -14227,13 +14669,13 @@ async function acquireCodexCredentialLease(db, input, select) {
|
|
|
14227
14669
|
const leaseRotationEnabled = settingsRow.rotation_enabled && settingsRow.lease_rotation_enabled;
|
|
14228
14670
|
const rotationStrategy = settingsRow.rotation_strategy;
|
|
14229
14671
|
if (leaseRotationEnabled) {
|
|
14230
|
-
await tx.execute(
|
|
14672
|
+
await tx.execute(sql8`
|
|
14231
14673
|
delete from codex_credential_leases
|
|
14232
14674
|
where workspace_id = ${input.workspaceId} and leased_until <= now()
|
|
14233
14675
|
`);
|
|
14234
14676
|
}
|
|
14235
14677
|
const existingRows = leaseRotationEnabled ? await tx.execute(
|
|
14236
|
-
|
|
14678
|
+
sql8`
|
|
14237
14679
|
select credential_id, holder_id, generation from codex_credential_leases
|
|
14238
14680
|
where workspace_id = ${input.workspaceId}
|
|
14239
14681
|
and turn_id = ${input.turnId}
|
|
@@ -14280,7 +14722,7 @@ async function acquireCodexCredentialLease(db, input, select) {
|
|
|
14280
14722
|
}
|
|
14281
14723
|
if (selected.credentialId === null) {
|
|
14282
14724
|
if (leaseRotationEnabled && existingCredentialId !== null) {
|
|
14283
|
-
await tx.execute(
|
|
14725
|
+
await tx.execute(sql8`
|
|
14284
14726
|
delete from codex_credential_leases
|
|
14285
14727
|
where workspace_id = ${input.workspaceId} and turn_id = ${input.turnId}
|
|
14286
14728
|
`);
|
|
@@ -14310,7 +14752,7 @@ async function acquireCodexCredentialLease(db, input, select) {
|
|
|
14310
14752
|
const advanceActivePointer = input.advanceActivePointer && selected.advanceActivePointer !== false;
|
|
14311
14753
|
if (!leaseRotationEnabled) {
|
|
14312
14754
|
if (advanceActivePointer && activeCredentialId !== selected.credentialId) {
|
|
14313
|
-
await tx.execute(
|
|
14755
|
+
await tx.execute(sql8`
|
|
14314
14756
|
update codex_rotation_settings
|
|
14315
14757
|
set active_credential_id = ${selected.credentialId}, updated_at = now()
|
|
14316
14758
|
where account_id = ${input.accountId} and workspace_id = ${input.workspaceId}
|
|
@@ -14333,7 +14775,7 @@ async function acquireCodexCredentialLease(db, input, select) {
|
|
|
14333
14775
|
}
|
|
14334
14776
|
const reused = existingCredentialId === selected.credentialId;
|
|
14335
14777
|
const leaseRows = await tx.execute(
|
|
14336
|
-
|
|
14778
|
+
sql8`
|
|
14337
14779
|
insert into codex_credential_leases
|
|
14338
14780
|
(account_id, workspace_id, credential_id, turn_id, holder_id, generation, leased_until)
|
|
14339
14781
|
values
|
|
@@ -14356,7 +14798,7 @@ async function acquireCodexCredentialLease(db, input, select) {
|
|
|
14356
14798
|
throw new Error("Codex credential lease insert returned no expiry");
|
|
14357
14799
|
}
|
|
14358
14800
|
if (!reused) {
|
|
14359
|
-
await tx.execute(
|
|
14801
|
+
await tx.execute(sql8`
|
|
14360
14802
|
update codex_subscription_credentials
|
|
14361
14803
|
set selection_count = selection_count + 1,
|
|
14362
14804
|
last_selected_at = now()
|
|
@@ -14366,7 +14808,7 @@ async function acquireCodexCredentialLease(db, input, select) {
|
|
|
14366
14808
|
`);
|
|
14367
14809
|
}
|
|
14368
14810
|
if (advanceActivePointer && activeCredentialId !== selected.credentialId) {
|
|
14369
|
-
await tx.execute(
|
|
14811
|
+
await tx.execute(sql8`
|
|
14370
14812
|
update codex_rotation_settings
|
|
14371
14813
|
set active_credential_id = ${selected.credentialId}, updated_at = now()
|
|
14372
14814
|
where account_id = ${input.accountId} and workspace_id = ${input.workspaceId}
|
|
@@ -14426,7 +14868,7 @@ function codexCapacityPolicyHashFromTurnMetadata(metadata) {
|
|
|
14426
14868
|
return typeof value === "string" && value.length > 0 ? value : null;
|
|
14427
14869
|
}
|
|
14428
14870
|
async function lockExistingCodexRotationSettingsForCapacity(tx, workspaceId) {
|
|
14429
|
-
const rows = await tx.execute(
|
|
14871
|
+
const rows = await tx.execute(sql8`
|
|
14430
14872
|
select account_id, active_credential_id, rotation_enabled,
|
|
14431
14873
|
lease_rotation_enabled, rotation_strategy
|
|
14432
14874
|
from codex_rotation_settings
|
|
@@ -14484,7 +14926,7 @@ async function armCodexCapacityWait(db, input) {
|
|
|
14484
14926
|
eq10(sessionGoals.sessionId, input.sessionId)
|
|
14485
14927
|
)
|
|
14486
14928
|
).for("update").limit(1) : [];
|
|
14487
|
-
const leaseRows = input.leaseFence ? await tx.execute(
|
|
14929
|
+
const leaseRows = input.leaseFence ? await tx.execute(sql8`
|
|
14488
14930
|
select holder_id, generation
|
|
14489
14931
|
from codex_credential_leases
|
|
14490
14932
|
where account_id = ${input.accountId}
|
|
@@ -14660,7 +15102,7 @@ async function armCodexCapacityWait(db, input) {
|
|
|
14660
15102
|
throw new Error("Codex capacity session changed during atomic arm");
|
|
14661
15103
|
}
|
|
14662
15104
|
if (input.leaseFence) {
|
|
14663
|
-
await tx.execute(
|
|
15105
|
+
await tx.execute(sql8`
|
|
14664
15106
|
delete from codex_credential_leases
|
|
14665
15107
|
where account_id = ${input.accountId}
|
|
14666
15108
|
and workspace_id = ${input.workspaceId}
|
|
@@ -14701,7 +15143,7 @@ async function withCodexCapacityMutation(db, input, mutate) {
|
|
|
14701
15143
|
return { result: mutation.result, wakeTargets: [] };
|
|
14702
15144
|
}
|
|
14703
15145
|
const rows = await tx.update(codexCapacityWaiters).set({
|
|
14704
|
-
wakeRevision:
|
|
15146
|
+
wakeRevision: sql8`${codexCapacityWaiters.wakeRevision} + 1`,
|
|
14705
15147
|
lastWakeReason: input.reason,
|
|
14706
15148
|
updatedAt: /* @__PURE__ */ new Date()
|
|
14707
15149
|
}).where(
|
|
@@ -14755,7 +15197,7 @@ async function listPendingCodexCapacityWakeTargets(db, workspaceId) {
|
|
|
14755
15197
|
and10(
|
|
14756
15198
|
eq10(codexCapacityWaiters.workspaceId, workspaceId),
|
|
14757
15199
|
eq10(codexCapacityWaiters.status, "waiting"),
|
|
14758
|
-
|
|
15200
|
+
sql8`${codexCapacityWaiters.wakeRevision} > ${codexCapacityWaiters.observedWakeRevision}`
|
|
14759
15201
|
)
|
|
14760
15202
|
);
|
|
14761
15203
|
return rows.map(({ waiter: row, workflowWakeRevision }) => ({
|
|
@@ -15113,7 +15555,7 @@ async function reconcileCodexCapacityWait(db, input, decide, policy) {
|
|
|
15113
15555
|
}
|
|
15114
15556
|
async function heartbeatCodexCredentialLeaseUntil(db, accountId, workspaceId, turnId, holderId, generation, leaseTtlMs = CODEX_CREDENTIAL_LEASE_TTL_MS) {
|
|
15115
15557
|
return await withRlsContext(db, { accountId, workspaceId }, async (scopedDb) => {
|
|
15116
|
-
const rows = await scopedDb.execute(
|
|
15558
|
+
const rows = await scopedDb.execute(sql8`
|
|
15117
15559
|
update codex_credential_leases
|
|
15118
15560
|
set leased_until = now() + (${leaseTtlMs} * interval '1 millisecond'),
|
|
15119
15561
|
updated_at = now()
|
|
@@ -15157,7 +15599,7 @@ async function quarantineCodexCredentialForLease(db, input) {
|
|
|
15157
15599
|
db,
|
|
15158
15600
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
15159
15601
|
async (scopedDb) => await scopedDb.transaction(async (tx) => {
|
|
15160
|
-
const leaseRows = await tx.execute(
|
|
15602
|
+
const leaseRows = await tx.execute(sql8`
|
|
15161
15603
|
select id from codex_credential_leases
|
|
15162
15604
|
where account_id = ${input.accountId}
|
|
15163
15605
|
and workspace_id = ${input.workspaceId}
|
|
@@ -15282,7 +15724,7 @@ async function updateCodexAllocatorEligibility(db, input) {
|
|
|
15282
15724
|
const changedAt = /* @__PURE__ */ new Date();
|
|
15283
15725
|
const [updated] = await tx.update(codexSubscriptionCredentials).set({
|
|
15284
15726
|
allocatorEnabled: input.enabled,
|
|
15285
|
-
allocatorVersion:
|
|
15727
|
+
allocatorVersion: sql8`${codexSubscriptionCredentials.allocatorVersion} + 1`,
|
|
15286
15728
|
allocatorUpdatedBySubjectId: input.subjectId,
|
|
15287
15729
|
allocatorUpdatedAt: changedAt
|
|
15288
15730
|
// Deliberately no credential version/updatedAt write.
|
|
@@ -15452,7 +15894,7 @@ async function adoptCodexResetRedemptionAttempt(db, input) {
|
|
|
15452
15894
|
if (attempt.status !== "provider_started" && attempt.status !== "completed") {
|
|
15453
15895
|
return { kind: "conflict" };
|
|
15454
15896
|
}
|
|
15455
|
-
const claim = await tx.execute(
|
|
15897
|
+
const claim = await tx.execute(sql8`
|
|
15456
15898
|
select claim_expires_at > now() as claim_live
|
|
15457
15899
|
from codex_reset_redemption_attempts
|
|
15458
15900
|
where workspace_id = ${input.workspaceId} and id = ${input.attemptId}
|
|
@@ -15462,7 +15904,7 @@ async function adoptCodexResetRedemptionAttempt(db, input) {
|
|
|
15462
15904
|
browserSessionHash: input.browserSessionHash,
|
|
15463
15905
|
claimHolderId: null,
|
|
15464
15906
|
claimExpiresAt: null,
|
|
15465
|
-
updatedAt:
|
|
15907
|
+
updatedAt: sql8`now()`
|
|
15466
15908
|
}).where(eq10(codexResetRedemptionAttempts.id, input.attemptId)).returning();
|
|
15467
15909
|
if (!adopted) throw new Error("Codex redemption adoption returned no row");
|
|
15468
15910
|
return {
|
|
@@ -15485,10 +15927,10 @@ async function claimCodexResetRedemption(db, input) {
|
|
|
15485
15927
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
15486
15928
|
async (scopedDb) => await scopedDb.transaction(async (tx) => {
|
|
15487
15929
|
await tx.execute(
|
|
15488
|
-
|
|
15930
|
+
sql8`select pg_advisory_xact_lock(hashtextextended(${`codex-reset-attempt:${input.id}`}, 0))`
|
|
15489
15931
|
);
|
|
15490
15932
|
await tx.execute(
|
|
15491
|
-
|
|
15933
|
+
sql8`select pg_advisory_xact_lock(hashtextextended(${`codex-reset-credit:${input.workspaceId}:${input.credentialId}:${input.creditId}`}, 0))`
|
|
15492
15934
|
);
|
|
15493
15935
|
const [credential] = await tx.select({
|
|
15494
15936
|
connectedBySubjectId: codexSubscriptionCredentials.connectedBySubjectId,
|
|
@@ -15520,7 +15962,7 @@ async function claimCodexResetRedemption(db, input) {
|
|
|
15520
15962
|
if (credential.status !== "active") {
|
|
15521
15963
|
return { kind: "forbidden" };
|
|
15522
15964
|
}
|
|
15523
|
-
const claimState = await tx.execute(
|
|
15965
|
+
const claimState = await tx.execute(sql8`
|
|
15524
15966
|
select claim_expires_at > now() as claim_live
|
|
15525
15967
|
from codex_reset_redemption_attempts
|
|
15526
15968
|
where workspace_id = ${input.workspaceId} and id = ${input.id}
|
|
@@ -15530,10 +15972,10 @@ async function claimCodexResetRedemption(db, input) {
|
|
|
15530
15972
|
}
|
|
15531
15973
|
const [reclaimed] = await tx.update(codexResetRedemptionAttempts).set({
|
|
15532
15974
|
claimHolderId: input.claimHolderId,
|
|
15533
|
-
claimExpiresAt:
|
|
15975
|
+
claimExpiresAt: sql8`now() + (${claimTtlMs} * interval '1 millisecond')`,
|
|
15534
15976
|
confirmationExpiresAt: input.confirmationExpiresAt,
|
|
15535
15977
|
lastFailureKind: null,
|
|
15536
|
-
retryCount:
|
|
15978
|
+
retryCount: sql8`${codexResetRedemptionAttempts.retryCount} + 1`,
|
|
15537
15979
|
updatedAt: now
|
|
15538
15980
|
}).where(eq10(codexResetRedemptionAttempts.id, input.id)).returning();
|
|
15539
15981
|
if (!reclaimed) throw new Error("Codex redemption reclaim returned no row");
|
|
@@ -15545,7 +15987,7 @@ async function claimCodexResetRedemption(db, input) {
|
|
|
15545
15987
|
if (credential.status !== "active" || credential.connectedBySubjectId !== input.subjectId) {
|
|
15546
15988
|
return { kind: "forbidden" };
|
|
15547
15989
|
}
|
|
15548
|
-
const [creditAttempt] = await tx.execute(
|
|
15990
|
+
const [creditAttempt] = await tx.execute(sql8`
|
|
15549
15991
|
select id, status, claim_expires_at > now() as claim_live
|
|
15550
15992
|
from codex_reset_redemption_attempts
|
|
15551
15993
|
where workspace_id = ${input.workspaceId}
|
|
@@ -15564,7 +16006,7 @@ async function claimCodexResetRedemption(db, input) {
|
|
|
15564
16006
|
eq10(codexResetRedemptionAttempts.workspaceId, input.workspaceId),
|
|
15565
16007
|
eq10(codexResetRedemptionAttempts.id, creditAttempt.id),
|
|
15566
16008
|
eq10(codexResetRedemptionAttempts.status, "processing"),
|
|
15567
|
-
|
|
16009
|
+
sql8`(${codexResetRedemptionAttempts.claimExpiresAt} is null or ${codexResetRedemptionAttempts.claimExpiresAt} <= now())`
|
|
15568
16010
|
)
|
|
15569
16011
|
).returning({ id: codexResetRedemptionAttempts.id });
|
|
15570
16012
|
if (removed.length !== 1) return { kind: "conflict" };
|
|
@@ -15579,7 +16021,7 @@ async function claimCodexResetRedemption(db, input) {
|
|
|
15579
16021
|
creditId: input.creditId,
|
|
15580
16022
|
status: "processing",
|
|
15581
16023
|
claimHolderId: input.claimHolderId,
|
|
15582
|
-
claimExpiresAt:
|
|
16024
|
+
claimExpiresAt: sql8`now() + (${claimTtlMs} * interval '1 millisecond')`,
|
|
15583
16025
|
confirmationExpiresAt: input.confirmationExpiresAt
|
|
15584
16026
|
}).returning();
|
|
15585
16027
|
if (!created) throw new Error("Codex redemption claim returned no row");
|
|
@@ -15623,7 +16065,7 @@ async function fenceCodexResetRedemptionSend(db, input) {
|
|
|
15623
16065
|
if (attempt.status === "completed") {
|
|
15624
16066
|
return { kind: "not_ready", reason: "already_completed" };
|
|
15625
16067
|
}
|
|
15626
|
-
const [liveness] = await tx.execute(
|
|
16068
|
+
const [liveness] = await tx.execute(sql8`
|
|
15627
16069
|
select claim_expires_at > now() as claim_live,
|
|
15628
16070
|
confirmation_expires_at > now() as confirmation_live
|
|
15629
16071
|
from codex_reset_redemption_attempts
|
|
@@ -15637,10 +16079,10 @@ async function fenceCodexResetRedemptionSend(db, input) {
|
|
|
15637
16079
|
} else {
|
|
15638
16080
|
const [ready] = await tx.update(codexResetRedemptionAttempts).set({
|
|
15639
16081
|
status: "provider_started",
|
|
15640
|
-
providerStartedAt:
|
|
15641
|
-
claimExpiresAt:
|
|
16082
|
+
providerStartedAt: sql8`coalesce(${codexResetRedemptionAttempts.providerStartedAt}, now())`,
|
|
16083
|
+
claimExpiresAt: sql8`now() + (${sendLeaseMs} * interval '1 millisecond')`,
|
|
15642
16084
|
lastFailureKind: null,
|
|
15643
|
-
updatedAt:
|
|
16085
|
+
updatedAt: sql8`now()`
|
|
15644
16086
|
}).where(eq10(codexResetRedemptionAttempts.id, input.attemptId)).returning();
|
|
15645
16087
|
if (!ready) throw new Error("Codex redemption send fence returned no row");
|
|
15646
16088
|
return {
|
|
@@ -15655,7 +16097,7 @@ async function fenceCodexResetRedemptionSend(db, input) {
|
|
|
15655
16097
|
claimHolderId: null,
|
|
15656
16098
|
claimExpiresAt: null,
|
|
15657
16099
|
lastFailureKind: `send_fence_${reason}`,
|
|
15658
|
-
updatedAt:
|
|
16100
|
+
updatedAt: sql8`now()`
|
|
15659
16101
|
}).where(eq10(codexResetRedemptionAttempts.id, input.attemptId));
|
|
15660
16102
|
}
|
|
15661
16103
|
return { kind: "not_ready", reason };
|
|
@@ -15694,7 +16136,7 @@ async function releaseCodexResetRedemptionClaim(db, input) {
|
|
|
15694
16136
|
eq10(codexResetRedemptionAttempts.workspaceId, input.workspaceId),
|
|
15695
16137
|
eq10(codexResetRedemptionAttempts.id, input.attemptId),
|
|
15696
16138
|
eq10(codexResetRedemptionAttempts.claimHolderId, input.claimHolderId),
|
|
15697
|
-
|
|
16139
|
+
sql8`${codexResetRedemptionAttempts.status} <> 'completed'`
|
|
15698
16140
|
)
|
|
15699
16141
|
).returning({ id: codexResetRedemptionAttempts.id });
|
|
15700
16142
|
return rows.length === 1;
|
|
@@ -15710,7 +16152,7 @@ async function completeCodexResetRedemption(db, input) {
|
|
|
15710
16152
|
{ workspaceId: input.workspaceId, reason: "codex_reset_credit_redeemed" },
|
|
15711
16153
|
async (tx) => {
|
|
15712
16154
|
await tx.execute(
|
|
15713
|
-
|
|
16155
|
+
sql8`select pg_advisory_xact_lock(hashtextextended(${`codex-reset-attempt:${input.attemptId}`}, 0))`
|
|
15714
16156
|
);
|
|
15715
16157
|
const [current] = await tx.select().from(codexResetRedemptionAttempts).where(
|
|
15716
16158
|
and10(
|
|
@@ -15866,7 +16308,7 @@ async function ensureCodexRotationSettings(db, accountId, workspaceId) {
|
|
|
15866
16308
|
}
|
|
15867
16309
|
async function setActiveCodexCredential(db, workspaceId, credentialId) {
|
|
15868
16310
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
15869
|
-
await scopedDb.execute(
|
|
16311
|
+
await scopedDb.execute(sql8`
|
|
15870
16312
|
select id from codex_rotation_settings
|
|
15871
16313
|
where workspace_id = ${workspaceId}
|
|
15872
16314
|
for update
|
|
@@ -15886,7 +16328,7 @@ async function setActiveCodexCredential(db, workspaceId, credentialId) {
|
|
|
15886
16328
|
}
|
|
15887
16329
|
async function setInitialActiveCodexCredential(db, workspaceId, credentialId) {
|
|
15888
16330
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
15889
|
-
await scopedDb.execute(
|
|
16331
|
+
await scopedDb.execute(sql8`
|
|
15890
16332
|
select id from codex_rotation_settings
|
|
15891
16333
|
where workspace_id = ${workspaceId}
|
|
15892
16334
|
for update
|
|
@@ -15942,13 +16384,13 @@ async function countConsecutiveReactiveRotations(db, workspaceId, sessionId) {
|
|
|
15942
16384
|
eq10(sessionEvents.workspaceId, workspaceId),
|
|
15943
16385
|
eq10(sessionEvents.sessionId, sessionId),
|
|
15944
16386
|
eq10(sessionEvents.type, "turn.failed"),
|
|
15945
|
-
|
|
16387
|
+
sql8`${sessionEvents.payload} ->> 'rotated' = 'true'`
|
|
15946
16388
|
];
|
|
15947
16389
|
if (lastOk) {
|
|
15948
|
-
conditions.push(
|
|
16390
|
+
conditions.push(sql8`${sessionEvents.sequence} > ${lastOk.sequence}`);
|
|
15949
16391
|
}
|
|
15950
16392
|
const [{ rotated } = { rotated: 0 }] = await scopedDb.select({
|
|
15951
|
-
rotated:
|
|
16393
|
+
rotated: sql8`count(*)::int`
|
|
15952
16394
|
}).from(sessionEvents).where(and10(...conditions));
|
|
15953
16395
|
return Number(rotated);
|
|
15954
16396
|
});
|
|
@@ -16070,7 +16512,7 @@ async function recordSessionActiveCodexCredential(db, workspaceId, sessionId, cr
|
|
|
16070
16512
|
}
|
|
16071
16513
|
async function disconnectCodexAccount(db, workspaceId, credentialId) {
|
|
16072
16514
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
16073
|
-
await scopedDb.execute(
|
|
16515
|
+
await scopedDb.execute(sql8`
|
|
16074
16516
|
select id from codex_rotation_settings
|
|
16075
16517
|
where workspace_id = ${workspaceId}
|
|
16076
16518
|
for update
|
|
@@ -16309,7 +16751,7 @@ async function updateSessionMcpServerCredentialsInTransaction(tx, input) {
|
|
|
16309
16751
|
for (const update of input.updates) {
|
|
16310
16752
|
const [row] = await tx.update(sessionMcpServers).set({
|
|
16311
16753
|
headersEncrypted: update.headersEncrypted,
|
|
16312
|
-
credentialVersion:
|
|
16754
|
+
credentialVersion: sql8`${sessionMcpServers.credentialVersion} + 1`,
|
|
16313
16755
|
updatedAt: /* @__PURE__ */ new Date()
|
|
16314
16756
|
}).where(
|
|
16315
16757
|
and10(
|
|
@@ -16485,7 +16927,7 @@ async function lockWorkspaceForSessionCreate(tx, workspaceId, accountId) {
|
|
|
16485
16927
|
if (workspace.accountId !== accountId) {
|
|
16486
16928
|
throw new Error(`Workspace ${workspaceId} does not belong to account ${accountId}`);
|
|
16487
16929
|
}
|
|
16488
|
-
const [deploymentPolicy] = await tx.execute(
|
|
16930
|
+
const [deploymentPolicy] = await tx.execute(sql8`
|
|
16489
16931
|
select
|
|
16490
16932
|
max_nested_agent_depth as "maxNestedAgentDepth",
|
|
16491
16933
|
policy_source as "policySource"
|
|
@@ -16598,7 +17040,7 @@ async function existingSessionForCreateKey(tx, workspaceId, createIdempotencyKey
|
|
|
16598
17040
|
}
|
|
16599
17041
|
async function lockSessionCreateIdempotencyKey(tx, workspaceId, createIdempotencyKey) {
|
|
16600
17042
|
await tx.execute(
|
|
16601
|
-
|
|
17043
|
+
sql8`select pg_advisory_xact_lock(hashtext(${`session-create:${workspaceId}:${createIdempotencyKey}`}))`
|
|
16602
17044
|
);
|
|
16603
17045
|
}
|
|
16604
17046
|
async function existingSpawnDenialForKey(tx, workspaceId, createIdempotencyKey) {
|
|
@@ -16628,7 +17070,7 @@ async function recordSessionSpawnDenial(tx, input, decision) {
|
|
|
16628
17070
|
idempotencyKey: input.createIdempotencyKey ?? null
|
|
16629
17071
|
}).onConflictDoNothing({
|
|
16630
17072
|
target: [sessionSpawnDenials.workspaceId, sessionSpawnDenials.idempotencyKey],
|
|
16631
|
-
where:
|
|
17073
|
+
where: sql8`${sessionSpawnDenials.idempotencyKey} is not null`
|
|
16632
17074
|
}).returning();
|
|
16633
17075
|
if (inserted) return mapSessionSpawnDenial(inserted);
|
|
16634
17076
|
const key = input.createIdempotencyKey;
|
|
@@ -16945,12 +17387,12 @@ function sessionPersonalStateLockKey(workspaceId, subjectId) {
|
|
|
16945
17387
|
}
|
|
16946
17388
|
async function lockSessionPersonalStateShared(db, workspaceId, subjectId) {
|
|
16947
17389
|
await db.execute(
|
|
16948
|
-
|
|
17390
|
+
sql8`select pg_advisory_xact_lock_shared(hashtextextended(${sessionPersonalStateLockKey(workspaceId, subjectId)}, 0))`
|
|
16949
17391
|
);
|
|
16950
17392
|
}
|
|
16951
17393
|
async function lockSessionPersonalStateExclusive(db, workspaceId, subjectId) {
|
|
16952
17394
|
await db.execute(
|
|
16953
|
-
|
|
17395
|
+
sql8`select pg_advisory_xact_lock(hashtextextended(${sessionPersonalStateLockKey(workspaceId, subjectId)}, 0))`
|
|
16954
17396
|
);
|
|
16955
17397
|
}
|
|
16956
17398
|
function mapSessionPin(row) {
|
|
@@ -17036,7 +17478,7 @@ async function sessionTreeStatsForSessions(db, workspaceId, rootIds) {
|
|
|
17036
17478
|
}
|
|
17037
17479
|
const rows = await rawRows(
|
|
17038
17480
|
db,
|
|
17039
|
-
|
|
17481
|
+
sql8`
|
|
17040
17482
|
select
|
|
17041
17483
|
root.id as "rootId",
|
|
17042
17484
|
stats."directChildren",
|
|
@@ -17130,7 +17572,7 @@ async function sessionTreeStatsForSessions(db, workspaceId, rootIds) {
|
|
|
17130
17572
|
from numbered
|
|
17131
17573
|
) stats
|
|
17132
17574
|
where root.workspace_id = ${workspaceId}
|
|
17133
|
-
and ${inArray5(
|
|
17575
|
+
and ${inArray5(sql8`root.id`, uniqueRootIds)}
|
|
17134
17576
|
`
|
|
17135
17577
|
);
|
|
17136
17578
|
return new Map(
|
|
@@ -17151,7 +17593,7 @@ async function sessionTreeStatsForSessions(db, workspaceId, rootIds) {
|
|
|
17151
17593
|
}
|
|
17152
17594
|
function sessionFilters(options) {
|
|
17153
17595
|
const filters = [
|
|
17154
|
-
|
|
17596
|
+
sql8`not exists (
|
|
17155
17597
|
select 1
|
|
17156
17598
|
from ${slackInteractions} private_slack_interaction
|
|
17157
17599
|
where private_slack_interaction.workspace_id = ${sessions.workspaceId}
|
|
@@ -17181,7 +17623,7 @@ function sessionFilters(options) {
|
|
|
17181
17623
|
return filters;
|
|
17182
17624
|
}
|
|
17183
17625
|
function sessionAuthorizationScopeFilter(scope) {
|
|
17184
|
-
if (scope.kind === "all") return
|
|
17626
|
+
if (scope.kind === "all") return sql8`true`;
|
|
17185
17627
|
if (scope.rootSessionIds.length > SESSION_AUTHORIZATION_LIST_SCOPE_MAX_IDS || scope.sessionIds.length > SESSION_AUTHORIZATION_LIST_SCOPE_MAX_IDS) {
|
|
17186
17628
|
throw new RangeError(
|
|
17187
17629
|
`Session authorization scope exceeds ${SESSION_AUTHORIZATION_LIST_SCOPE_MAX_IDS} ids per field`
|
|
@@ -17189,14 +17631,14 @@ function sessionAuthorizationScopeFilter(scope) {
|
|
|
17189
17631
|
}
|
|
17190
17632
|
const rootIds = [...new Set(scope.rootSessionIds)];
|
|
17191
17633
|
const sessionIds = [...new Set(scope.sessionIds)];
|
|
17192
|
-
if (rootIds.length === 0 && sessionIds.length === 0) return
|
|
17193
|
-
const exact = sessionIds.length > 0 ? inArray5(sessions.id, sessionIds) :
|
|
17194
|
-
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 (
|
|
17195
17637
|
with recursive authorized_sessions(id) as (
|
|
17196
17638
|
select root.id
|
|
17197
17639
|
from ${sessions} root
|
|
17198
17640
|
where root.workspace_id = ${sessions.workspaceId}
|
|
17199
|
-
and ${inArray5(
|
|
17641
|
+
and ${inArray5(sql8`root.id`, rootIds)}
|
|
17200
17642
|
|
|
17201
17643
|
union
|
|
17202
17644
|
|
|
@@ -17207,7 +17649,7 @@ function sessionAuthorizationScopeFilter(scope) {
|
|
|
17207
17649
|
and child.parent_session_id = parent.id
|
|
17208
17650
|
)
|
|
17209
17651
|
select id from authorized_sessions
|
|
17210
|
-
)` :
|
|
17652
|
+
)` : sql8`false`;
|
|
17211
17653
|
return or3(exact, descendants);
|
|
17212
17654
|
}
|
|
17213
17655
|
async function sessionIdsCoveredByAuthorizationRoots(db, workspaceId, sessionIds, scope) {
|
|
@@ -17232,7 +17674,7 @@ var SESSION_LIST_SNAPSHOT_REUSE_MS = 5e3;
|
|
|
17232
17674
|
var SESSION_LIST_SNAPSHOT_MAX_IDS = 5e3;
|
|
17233
17675
|
var SESSION_LIST_SNAPSHOT_MAX_ACTIVE_PER_SUBJECT = 32;
|
|
17234
17676
|
var SESSION_LIST_SERIALIZATION_MAX_ATTEMPTS = 3;
|
|
17235
|
-
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;
|
|
17236
17678
|
function sessionParentFilter(parentSessionId) {
|
|
17237
17679
|
return parentSessionId === void 0 ? "all" : parentSessionId === null ? "null" : parentSessionId;
|
|
17238
17680
|
}
|
|
@@ -17245,7 +17687,7 @@ function sessionListSnapshotLockKey(workspaceId, subjectId) {
|
|
|
17245
17687
|
}
|
|
17246
17688
|
async function lockSessionListSnapshotCreation(db, workspaceId, subjectId) {
|
|
17247
17689
|
await db.execute(
|
|
17248
|
-
|
|
17690
|
+
sql8`select pg_advisory_xact_lock(hashtextextended(${sessionListSnapshotLockKey(workspaceId, subjectId)}, 0))`
|
|
17249
17691
|
);
|
|
17250
17692
|
}
|
|
17251
17693
|
function encodeSessionListCursor(cursor) {
|
|
@@ -17264,7 +17706,7 @@ function decodeSessionListCursor(value) {
|
|
|
17264
17706
|
const parentSessionFilter = parsed.parentSessionFilter;
|
|
17265
17707
|
const search = parsed.search;
|
|
17266
17708
|
const offset = parsed.offset;
|
|
17267
|
-
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)) {
|
|
17268
17710
|
return null;
|
|
17269
17711
|
}
|
|
17270
17712
|
return {
|
|
@@ -17280,7 +17722,7 @@ function decodeSessionListCursor(value) {
|
|
|
17280
17722
|
async function reapExpiredSessionListSnapshots(db, limit = 500) {
|
|
17281
17723
|
const rows = await rawRows(
|
|
17282
17724
|
db,
|
|
17283
|
-
|
|
17725
|
+
sql8`select opengeni_private.reap_expired_session_list_snapshots(${limit}) as deleted_count`
|
|
17284
17726
|
);
|
|
17285
17727
|
return Number(rows[0]?.deleted_count ?? 0);
|
|
17286
17728
|
}
|
|
@@ -17445,7 +17887,7 @@ async function listSessionsForSubject(db, workspaceId, options) {
|
|
|
17445
17887
|
if (ordinaryIds.length > limit) {
|
|
17446
17888
|
let snapshot = reusableSnapshot;
|
|
17447
17889
|
if (!snapshot) {
|
|
17448
|
-
await tx.execute(
|
|
17890
|
+
await tx.execute(sql8`
|
|
17449
17891
|
delete from ${sessionListSnapshots} snapshot
|
|
17450
17892
|
where snapshot.workspace_id = ${workspaceId}
|
|
17451
17893
|
and snapshot.subject_id = ${options.subjectId}
|
|
@@ -17577,7 +18019,7 @@ async function getSessionForSubject(db, workspaceId, sessionId, subjectId, relat
|
|
|
17577
18019
|
and10(
|
|
17578
18020
|
eq10(sessions.workspaceId, workspaceId),
|
|
17579
18021
|
eq10(sessions.id, sessionId),
|
|
17580
|
-
|
|
18022
|
+
sql8`not exists (
|
|
17581
18023
|
select 1
|
|
17582
18024
|
from ${slackInteractions} private_slack_interaction
|
|
17583
18025
|
where private_slack_interaction.workspace_id = ${sessions.workspaceId}
|
|
@@ -17665,7 +18107,7 @@ async function setSessionPin(db, input) {
|
|
|
17665
18107
|
const [updated] = await tx.update(sessionPins).set({
|
|
17666
18108
|
pinned: input.pinned,
|
|
17667
18109
|
pinnedAt: input.pinned ? /* @__PURE__ */ new Date() : null,
|
|
17668
|
-
version:
|
|
18110
|
+
version: sql8`${sessionPins.version} + 1`
|
|
17669
18111
|
}).where(
|
|
17670
18112
|
and10(
|
|
17671
18113
|
eq10(sessionPins.workspaceId, input.workspaceId),
|
|
@@ -17747,7 +18189,7 @@ function normalizeSessionActivityRevision(value, label) {
|
|
|
17747
18189
|
return revision.toString();
|
|
17748
18190
|
}
|
|
17749
18191
|
async function lockWorkspaceSessionActivityRevision(db, workspaceId) {
|
|
17750
|
-
await db.execute(
|
|
18192
|
+
await db.execute(sql8`
|
|
17751
18193
|
insert into ${workspaceSessionActivityRevisions} (
|
|
17752
18194
|
workspace_id, account_id, revision
|
|
17753
18195
|
)
|
|
@@ -17756,7 +18198,7 @@ async function lockWorkspaceSessionActivityRevision(db, workspaceId) {
|
|
|
17756
18198
|
where ${workspaces.id} = ${workspaceId}
|
|
17757
18199
|
on conflict (workspace_id) do nothing
|
|
17758
18200
|
`);
|
|
17759
|
-
const rows = await db.execute(
|
|
18201
|
+
const rows = await db.execute(sql8`
|
|
17760
18202
|
select revision::text as revision
|
|
17761
18203
|
from ${workspaceSessionActivityRevisions}
|
|
17762
18204
|
where workspace_id = ${workspaceId}
|
|
@@ -17785,7 +18227,7 @@ async function listSessionDiscoverySummaries(db, workspaceId, options) {
|
|
|
17785
18227
|
}
|
|
17786
18228
|
const snapshotAt = options.cursor?.snapshotAt ?? (await rawRows(
|
|
17787
18229
|
scopedDb,
|
|
17788
|
-
|
|
18230
|
+
sql8`select to_char(statement_timestamp() at time zone 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.US"Z"') as value`
|
|
17789
18231
|
))[0].value;
|
|
17790
18232
|
const needsUpdatedSnapshot = orderBy === "updatedAt" && options.cursor?.snapshotRevision === void 0;
|
|
17791
18233
|
if (needsUpdatedSnapshot) {
|
|
@@ -17800,13 +18242,13 @@ async function listSessionDiscoverySummaries(db, workspaceId, options) {
|
|
|
17800
18242
|
throw new Error("sessions_list created-order cursor cannot carry activity revisions");
|
|
17801
18243
|
}
|
|
17802
18244
|
const cursorPredicate = options.cursor ? orderBy === "updatedAt" ? or3(
|
|
17803
|
-
|
|
18245
|
+
sql8`${sessions.activityRevision} < ${cursorSortRevision}::text::bigint`,
|
|
17804
18246
|
and10(
|
|
17805
|
-
|
|
18247
|
+
sql8`${sessions.activityRevision} = ${cursorSortRevision}::text::bigint`,
|
|
17806
18248
|
or3(
|
|
17807
|
-
|
|
18249
|
+
sql8`${sessions.updatedAt} < ${options.cursor.sortAt}::text::timestamptz`,
|
|
17808
18250
|
and10(
|
|
17809
|
-
|
|
18251
|
+
sql8`${sessions.updatedAt} = ${options.cursor.sortAt}::text::timestamptz`,
|
|
17810
18252
|
lt4(sessions.id, options.cursor.id)
|
|
17811
18253
|
)
|
|
17812
18254
|
)
|
|
@@ -17815,9 +18257,9 @@ async function listSessionDiscoverySummaries(db, workspaceId, options) {
|
|
|
17815
18257
|
// Cast through text deliberately. postgres.js otherwise infers a
|
|
17816
18258
|
// timestamptz parameter and serializes this exact cursor string via
|
|
17817
18259
|
// JS Date, which discards PostgreSQL's sub-millisecond precision.
|
|
17818
|
-
|
|
18260
|
+
sql8`${sessions.createdAt} < ${options.cursor.sortAt}::text::timestamptz`,
|
|
17819
18261
|
and10(
|
|
17820
|
-
|
|
18262
|
+
sql8`${sessions.createdAt} = ${options.cursor.sortAt}::text::timestamptz`,
|
|
17821
18263
|
lt4(sessions.id, options.cursor.id)
|
|
17822
18264
|
)
|
|
17823
18265
|
) : void 0;
|
|
@@ -17826,23 +18268,23 @@ async function listSessionDiscoverySummaries(db, workspaceId, options) {
|
|
|
17826
18268
|
snapshotFilters.push(sessionAuthorizationScopeFilter(options.authorizationScope));
|
|
17827
18269
|
}
|
|
17828
18270
|
snapshotFilters.push(
|
|
17829
|
-
orderBy === "updatedAt" ?
|
|
18271
|
+
orderBy === "updatedAt" ? sql8`${sessions.activityRevision} <= ${snapshotRevision}::text::bigint` : sql8`${sessions.createdAt} <= ${snapshotAt}::text::timestamptz`
|
|
17830
18272
|
);
|
|
17831
18273
|
if (updatedAfter !== null) {
|
|
17832
18274
|
snapshotFilters.push(
|
|
17833
|
-
|
|
18275
|
+
sql8`${sessions.activityRevision} > ${updatedAfter}::text::bigint`
|
|
17834
18276
|
);
|
|
17835
18277
|
}
|
|
17836
18278
|
const rows = await scopedDb.select({
|
|
17837
18279
|
id: sessions.id,
|
|
17838
|
-
title:
|
|
17839
|
-
titleOriginalChars:
|
|
18280
|
+
title: sql8`left(${sessions.title}, ${SESSION_DISCOVERY_CONTROL_TITLE_MAX_CHARS})`,
|
|
18281
|
+
titleOriginalChars: sql8`char_length(${sessions.title})::integer`,
|
|
17840
18282
|
parentSessionId: sessions.parentSessionId,
|
|
17841
18283
|
status: sessions.status,
|
|
17842
18284
|
createdAt: sessions.createdAt,
|
|
17843
18285
|
updatedAt: sessions.updatedAt,
|
|
17844
|
-
sortRevision: orderBy === "updatedAt" ?
|
|
17845
|
-
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"')`
|
|
17846
18288
|
}).from(sessions).where(and10(...snapshotFilters, cursorPredicate)).orderBy(
|
|
17847
18289
|
...orderBy === "updatedAt" ? [
|
|
17848
18290
|
desc5(sessions.activityRevision),
|
|
@@ -17853,7 +18295,7 @@ async function listSessionDiscoverySummaries(db, workspaceId, options) {
|
|
|
17853
18295
|
const hasMore = rows.length > limit;
|
|
17854
18296
|
const page = rows.slice(0, limit);
|
|
17855
18297
|
const ids = page.map((row) => row.id);
|
|
17856
|
-
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));
|
|
17857
18299
|
if (ids.length === 0) {
|
|
17858
18300
|
return {
|
|
17859
18301
|
sessions: [],
|
|
@@ -17878,8 +18320,8 @@ async function listSessionDiscoverySummaries(db, workspaceId, options) {
|
|
|
17878
18320
|
const goals = await scopedDb.select({
|
|
17879
18321
|
sessionId: sessionGoals.sessionId,
|
|
17880
18322
|
status: sessionGoals.status,
|
|
17881
|
-
text:
|
|
17882
|
-
textOriginalChars:
|
|
18323
|
+
text: sql8`left(${sessionGoals.text}, ${SESSION_DISCOVERY_GOAL_MAX_CHARS})`,
|
|
18324
|
+
textOriginalChars: sql8`char_length(${sessionGoals.text})::integer`
|
|
17883
18325
|
}).from(sessionGoals).where(
|
|
17884
18326
|
and10(
|
|
17885
18327
|
eq10(sessionGoals.workspaceId, workspaceId),
|
|
@@ -17889,7 +18331,7 @@ async function listSessionDiscoverySummaries(db, workspaceId, options) {
|
|
|
17889
18331
|
const goalsBySession = new Map(goals.map((goal) => [goal.sessionId, goal]));
|
|
17890
18332
|
const queueCounts = await scopedDb.select({
|
|
17891
18333
|
sessionId: sessionTurns.sessionId,
|
|
17892
|
-
count:
|
|
18334
|
+
count: sql8`count(*)::int`
|
|
17893
18335
|
}).from(sessionTurns).where(
|
|
17894
18336
|
and10(
|
|
17895
18337
|
eq10(sessionTurns.workspaceId, workspaceId),
|
|
@@ -17907,12 +18349,12 @@ async function listSessionDiscoverySummaries(db, workspaceId, options) {
|
|
|
17907
18349
|
// Extract only the bounded textual preview in PostgreSQL. Selecting
|
|
17908
18350
|
// the JSON payload here would re-materialize the exact multi-MB
|
|
17909
18351
|
// event bodies this compact discovery path exists to avoid.
|
|
17910
|
-
preview:
|
|
18352
|
+
preview: sql8`left(coalesce(
|
|
17911
18353
|
${sessionEvents.payload}->>'text',
|
|
17912
18354
|
${sessionEvents.payload}->>'message',
|
|
17913
18355
|
${sessionEvents.payload}->>'content'
|
|
17914
18356
|
), ${SESSION_DISCOVERY_MESSAGE_MAX_CHARS})`,
|
|
17915
|
-
previewOriginalChars:
|
|
18357
|
+
previewOriginalChars: sql8`char_length(coalesce(
|
|
17916
18358
|
${sessionEvents.payload}->>'text',
|
|
17917
18359
|
${sessionEvents.payload}->>'message',
|
|
17918
18360
|
${sessionEvents.payload}->>'content'
|
|
@@ -17984,7 +18426,7 @@ async function listSessionDiscoverySummaries(db, workspaceId, options) {
|
|
|
17984
18426
|
}
|
|
17985
18427
|
async function getSessionRootId(db, workspaceId, sessionId) {
|
|
17986
18428
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
17987
|
-
const rows = await scopedDb.execute(
|
|
18429
|
+
const rows = await scopedDb.execute(sql8`
|
|
17988
18430
|
with recursive lineage(id, parent_session_id, depth, path, cycle) as (
|
|
17989
18431
|
select
|
|
17990
18432
|
${sessions.id},
|
|
@@ -18028,7 +18470,7 @@ async function getSessionRootId(db, workspaceId, sessionId) {
|
|
|
18028
18470
|
async function getSessionLineage(db, workspaceId, sessionId) {
|
|
18029
18471
|
const descendantLimit = 200;
|
|
18030
18472
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
18031
|
-
const rootRows = await scopedDb.execute(
|
|
18473
|
+
const rootRows = await scopedDb.execute(sql8`
|
|
18032
18474
|
select id from ${sessions}
|
|
18033
18475
|
where ${sessions.workspaceId} = ${workspaceId} and ${sessions.id} = ${sessionId}
|
|
18034
18476
|
limit 1
|
|
@@ -18036,7 +18478,7 @@ async function getSessionLineage(db, workspaceId, sessionId) {
|
|
|
18036
18478
|
if (rootRows.length === 0) {
|
|
18037
18479
|
return null;
|
|
18038
18480
|
}
|
|
18039
|
-
const ancestorLineageRows = await scopedDb.execute(
|
|
18481
|
+
const ancestorLineageRows = await scopedDb.execute(sql8`
|
|
18040
18482
|
with recursive ancestors(id, parent_session_id, depth, path, cycle) as (
|
|
18041
18483
|
select ${sessions.id}, ${sessions.parentSessionId}, 0, array[${sessions.id}], false
|
|
18042
18484
|
from ${sessions}
|
|
@@ -18064,7 +18506,7 @@ async function getSessionLineage(db, workspaceId, sessionId) {
|
|
|
18064
18506
|
throw new Error(`session lineage for ${sessionId} has no valid workspace root`);
|
|
18065
18507
|
}
|
|
18066
18508
|
const ancestorRows = ancestorLineageRows.filter((row) => row.depth > 0);
|
|
18067
|
-
const childRows = await scopedDb.execute(
|
|
18509
|
+
const childRows = await scopedDb.execute(sql8`
|
|
18068
18510
|
with recursive descendants(id, parent_session_id, depth, path) as (
|
|
18069
18511
|
select child.id, child.parent_session_id, 1, array[${sessionId}, child.id]
|
|
18070
18512
|
from ${sessions} child
|
|
@@ -18128,7 +18570,7 @@ async function getSessionLineage(db, workspaceId, sessionId) {
|
|
|
18128
18570
|
async function countActiveSessionsForWorkspace(db, workspaceId) {
|
|
18129
18571
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
18130
18572
|
const [{ count } = { count: 0 }] = await scopedDb.select({
|
|
18131
|
-
count:
|
|
18573
|
+
count: sql8`count(*)::int`
|
|
18132
18574
|
}).from(sessions).where(
|
|
18133
18575
|
and10(
|
|
18134
18576
|
eq10(sessions.workspaceId, workspaceId),
|
|
@@ -18257,48 +18699,48 @@ async function listSessionEventPage(db, workspaceId, sessionId, options = {}) {
|
|
|
18257
18699
|
});
|
|
18258
18700
|
}
|
|
18259
18701
|
function sessionEventProjectionSelect(payloadMode = "full") {
|
|
18260
|
-
const typeInvalid =
|
|
18702
|
+
const typeInvalid = sql8`(
|
|
18261
18703
|
octet_length(${sessionEvents.type}) > ${SESSION_EVENT_TYPE_MAX_BYTES}
|
|
18262
18704
|
or position(E'\\n' in ${sessionEvents.type}) > 0
|
|
18263
18705
|
or position(E'\\r' in ${sessionEvents.type}) > 0
|
|
18264
18706
|
)`;
|
|
18265
|
-
const clientEventIdInvalid =
|
|
18707
|
+
const clientEventIdInvalid = sql8`(
|
|
18266
18708
|
${sessionEvents.clientEventId} is not null
|
|
18267
18709
|
and octet_length(${sessionEvents.clientEventId})
|
|
18268
18710
|
> ${SESSION_EVENT_CLIENT_EVENT_ID_MAX_BYTES}
|
|
18269
18711
|
)`;
|
|
18270
|
-
const turnAssociationInvalid =
|
|
18712
|
+
const turnAssociationInvalid = sql8`(
|
|
18271
18713
|
${sessionEvents.turnAssociation} is not null
|
|
18272
18714
|
and ${sessionEvents.turnAssociation} not in (
|
|
18273
18715
|
'current', 'late_rejected', 'duplicate'
|
|
18274
18716
|
)
|
|
18275
18717
|
)`;
|
|
18276
|
-
const duplicateReasonInvalid =
|
|
18718
|
+
const duplicateReasonInvalid = sql8`(
|
|
18277
18719
|
${sessionEvents.duplicateReason} is not null
|
|
18278
18720
|
and octet_length(${sessionEvents.duplicateReason})
|
|
18279
18721
|
> ${SESSION_EVENT_DUPLICATE_REASON_MAX_BYTES}
|
|
18280
18722
|
)`;
|
|
18281
|
-
const envelopeInvalid =
|
|
18723
|
+
const envelopeInvalid = sql8`(
|
|
18282
18724
|
${typeInvalid} or ${clientEventIdInvalid}
|
|
18283
18725
|
or ${turnAssociationInvalid} or ${duplicateReasonInvalid}
|
|
18284
18726
|
)`;
|
|
18285
|
-
const projectedType =
|
|
18727
|
+
const projectedType = sql8`case
|
|
18286
18728
|
when ${typeInvalid} then 'session.event.envelope_omitted'
|
|
18287
18729
|
else ${sessionEvents.type}
|
|
18288
18730
|
end`;
|
|
18289
|
-
const projectedClientEventId =
|
|
18731
|
+
const projectedClientEventId = sql8`case
|
|
18290
18732
|
when ${clientEventIdInvalid} then left(${sessionEvents.clientEventId}, 256)
|
|
18291
18733
|
else ${sessionEvents.clientEventId}
|
|
18292
18734
|
end`;
|
|
18293
|
-
const projectedTurnAssociation =
|
|
18735
|
+
const projectedTurnAssociation = sql8`case
|
|
18294
18736
|
when ${turnAssociationInvalid} then null
|
|
18295
18737
|
else ${sessionEvents.turnAssociation}
|
|
18296
18738
|
end`;
|
|
18297
|
-
const projectedDuplicateReason =
|
|
18739
|
+
const projectedDuplicateReason = sql8`case
|
|
18298
18740
|
when ${duplicateReasonInvalid} then left(${sessionEvents.duplicateReason}, 1024)
|
|
18299
18741
|
else ${sessionEvents.duplicateReason}
|
|
18300
18742
|
end`;
|
|
18301
|
-
const projectedEnvelopeFields =
|
|
18743
|
+
const projectedEnvelopeFields = sql8`(
|
|
18302
18744
|
'[]'::jsonb
|
|
18303
18745
|
|| case when ${typeInvalid} then jsonb_build_array(jsonb_build_object(
|
|
18304
18746
|
'field', 'type',
|
|
@@ -18321,7 +18763,7 @@ function sessionEventProjectionSelect(payloadMode = "full") {
|
|
|
18321
18763
|
'deliveredBytes', octet_length(${projectedDuplicateReason})
|
|
18322
18764
|
)) else '[]'::jsonb end
|
|
18323
18765
|
)`;
|
|
18324
|
-
const projectedPayload =
|
|
18766
|
+
const projectedPayload = sql8`case
|
|
18325
18767
|
when ${envelopeInvalid} then jsonb_build_object(
|
|
18326
18768
|
'preview', '[legacy event envelope normalized at bounded database read boundary]',
|
|
18327
18769
|
'originalEventBytes', octet_length(row_to_json(${sessionEvents})::text),
|
|
@@ -18335,14 +18777,14 @@ function sessionEventProjectionSelect(payloadMode = "full") {
|
|
|
18335
18777
|
)
|
|
18336
18778
|
else opengeni_private.project_session_event_payload(${sessionEvents.payload})
|
|
18337
18779
|
end`;
|
|
18338
|
-
const projectedPayloadBytes =
|
|
18339
|
-
const selectedPayload = payloadMode === "none" ?
|
|
18780
|
+
const projectedPayloadBytes = sql8`octet_length((${projectedPayload})::text)`;
|
|
18781
|
+
const selectedPayload = payloadMode === "none" ? sql8`jsonb_build_object(
|
|
18340
18782
|
'_monitoring', jsonb_build_object(
|
|
18341
18783
|
'payloadMode', 'none',
|
|
18342
18784
|
'payloadOmitted', true,
|
|
18343
18785
|
'projectedPayloadBytes', ${projectedPayloadBytes}
|
|
18344
18786
|
)
|
|
18345
|
-
)` : payloadMode === "summary" ?
|
|
18787
|
+
)` : payloadMode === "summary" ? sql8`case
|
|
18346
18788
|
when ${projectedPayloadBytes} <= 4096 then ${projectedPayload}
|
|
18347
18789
|
else jsonb_build_object(
|
|
18348
18790
|
'_monitoring', jsonb_build_object(
|
|
@@ -18442,7 +18884,7 @@ async function reserveToolspaceCallForAttempt(db, input) {
|
|
|
18442
18884
|
return { reserved: false, reason: "budget_exhausted" };
|
|
18443
18885
|
}
|
|
18444
18886
|
const [row] = await tx.update(sessionTurns).set({
|
|
18445
|
-
toolspaceCallCount:
|
|
18887
|
+
toolspaceCallCount: sql8`${sessionTurns.toolspaceCallCount} + 1`
|
|
18446
18888
|
}).where(
|
|
18447
18889
|
and10(
|
|
18448
18890
|
eq10(sessionTurns.workspaceId, input.workspaceId),
|
|
@@ -18450,7 +18892,7 @@ async function reserveToolspaceCallForAttempt(db, input) {
|
|
|
18450
18892
|
eq10(sessionTurns.id, input.turnId),
|
|
18451
18893
|
eq10(sessionTurns.executionGeneration, input.executionGeneration),
|
|
18452
18894
|
eq10(sessionTurns.activeAttemptId, input.attemptId),
|
|
18453
|
-
|
|
18895
|
+
sql8`${sessionTurns.toolspaceCallCount} < ${input.limit}`
|
|
18454
18896
|
)
|
|
18455
18897
|
).returning({ count: sessionTurns.toolspaceCallCount });
|
|
18456
18898
|
if (!row) {
|
|
@@ -19223,7 +19665,7 @@ async function recordPendingSessionToolCallResult(db, input) {
|
|
|
19223
19665
|
}).where(
|
|
19224
19666
|
and10(
|
|
19225
19667
|
eq10(sessionPendingToolCalls.id, pending.id),
|
|
19226
|
-
|
|
19668
|
+
sql8`${sessionPendingToolCalls.resultItem} is null`
|
|
19227
19669
|
)
|
|
19228
19670
|
).returning({ id: sessionPendingToolCalls.id });
|
|
19229
19671
|
return {
|
|
@@ -19253,7 +19695,7 @@ async function clearDurablePendingSessionToolCalls(db, input) {
|
|
|
19253
19695
|
eq10(sessionPendingToolCalls.sessionId, input.sessionId),
|
|
19254
19696
|
eq10(sessionPendingToolCalls.turnId, input.turnId),
|
|
19255
19697
|
inArray5(sessionPendingToolCalls.callId, input.callIds),
|
|
19256
|
-
|
|
19698
|
+
sql8`${sessionPendingToolCalls.resultItem} is not null`
|
|
19257
19699
|
)
|
|
19258
19700
|
).for("update");
|
|
19259
19701
|
if (pending.length === 0) return { accepted: true, cleared: 0 };
|
|
@@ -19320,7 +19762,7 @@ async function getActiveSessionHistoryItems(db, workspaceId, sessionId) {
|
|
|
19320
19762
|
async function countActiveSessionHistoryItems(db, workspaceId, sessionId) {
|
|
19321
19763
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
19322
19764
|
const [row] = await scopedDb.select({
|
|
19323
|
-
count:
|
|
19765
|
+
count: sql8`count(*)`
|
|
19324
19766
|
}).from(sessionHistoryItems).where(
|
|
19325
19767
|
and10(
|
|
19326
19768
|
eq10(sessionHistoryItems.workspaceId, workspaceId),
|
|
@@ -19403,7 +19845,7 @@ async function applyContextCompaction(db, input) {
|
|
|
19403
19845
|
return { applied: false, reason: fence.reason };
|
|
19404
19846
|
}
|
|
19405
19847
|
const [{ maxPosition } = { maxPosition: -1 }] = await tx.select({
|
|
19406
|
-
maxPosition:
|
|
19848
|
+
maxPosition: sql8`coalesce(max(${sessionHistoryItems.position}), -1)`
|
|
19407
19849
|
}).from(sessionHistoryItems).where(
|
|
19408
19850
|
and10(
|
|
19409
19851
|
eq10(sessionHistoryItems.workspaceId, input.workspaceId),
|
|
@@ -19577,7 +20019,7 @@ async function recordSkippedContextCompaction(db, input) {
|
|
|
19577
20019
|
async function nextSessionHistoryPosition(db, workspaceId, sessionId) {
|
|
19578
20020
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
19579
20021
|
const [row] = await scopedDb.select({
|
|
19580
|
-
maxPosition:
|
|
20022
|
+
maxPosition: sql8`max(${sessionHistoryItems.position})`
|
|
19581
20023
|
}).from(sessionHistoryItems).where(
|
|
19582
20024
|
and10(
|
|
19583
20025
|
eq10(sessionHistoryItems.workspaceId, workspaceId),
|
|
@@ -19648,7 +20090,7 @@ async function clearSessionContext(db, input) {
|
|
|
19648
20090
|
)
|
|
19649
20091
|
).returning({ id: sessionHistoryItems.id });
|
|
19650
20092
|
const [{ maxPosition } = { maxPosition: -1 }] = await tx.select({
|
|
19651
|
-
maxPosition:
|
|
20093
|
+
maxPosition: sql8`coalesce(max(${sessionHistoryItems.position}), -1)`
|
|
19652
20094
|
}).from(sessionHistoryItems).where(
|
|
19653
20095
|
and10(
|
|
19654
20096
|
eq10(sessionHistoryItems.workspaceId, input.workspaceId),
|
|
@@ -19685,7 +20127,7 @@ async function clearSessionContext(db, input) {
|
|
|
19685
20127
|
async function countSessionHistoryItems(db, workspaceId, sessionId) {
|
|
19686
20128
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
19687
20129
|
const [row] = await scopedDb.select({
|
|
19688
|
-
count:
|
|
20130
|
+
count: sql8`count(*)`
|
|
19689
20131
|
}).from(sessionHistoryItems).where(
|
|
19690
20132
|
and10(
|
|
19691
20133
|
eq10(sessionHistoryItems.workspaceId, workspaceId),
|
|
@@ -19857,7 +20299,7 @@ async function abandonRecordingForTurnAttempt(db, input) {
|
|
|
19857
20299
|
eq10(sessionEvents.turnAttemptId, input.attemptId),
|
|
19858
20300
|
eq10(sessionEvents.turnAssociation, "current"),
|
|
19859
20301
|
eq10(sessionEvents.type, "recording.started"),
|
|
19860
|
-
eq10(
|
|
20302
|
+
eq10(sql8`${sessionEvents.payload} ->> 'recordingId'`, input.recordingId)
|
|
19861
20303
|
)
|
|
19862
20304
|
).limit(1);
|
|
19863
20305
|
if (!started) return false;
|
|
@@ -20244,20 +20686,20 @@ function archiveProjectionFromResumeState(resumeState) {
|
|
|
20244
20686
|
};
|
|
20245
20687
|
}
|
|
20246
20688
|
async function recomputeAndStampLease(tx, leaseId, leaseTtlMs, setLiveness) {
|
|
20247
|
-
const counts = await tx.execute(
|
|
20689
|
+
const counts = await tx.execute(sql8`
|
|
20248
20690
|
select count(*)::int as total,
|
|
20249
20691
|
count(*) filter (where kind = 'turn')::int as turns,
|
|
20250
20692
|
count(*) filter (where kind = 'viewer')::int as viewers
|
|
20251
20693
|
from sandbox_lease_holders where lease_id = ${leaseId}
|
|
20252
20694
|
`);
|
|
20253
20695
|
const c = counts[0];
|
|
20254
|
-
const updated = await tx.execute(
|
|
20696
|
+
const updated = await tx.execute(sql8`
|
|
20255
20697
|
update sandbox_leases set
|
|
20256
20698
|
refcount = ${c.total},
|
|
20257
20699
|
turn_holders = ${c.turns},
|
|
20258
20700
|
viewer_holders = ${c.viewers},
|
|
20259
20701
|
expires_at = now() + (${String(leaseTtlMs)} || ' milliseconds')::interval,
|
|
20260
|
-
${setLiveness ?
|
|
20702
|
+
${setLiveness ? sql8`liveness = ${setLiveness},` : sql8``}
|
|
20261
20703
|
updated_at = now()
|
|
20262
20704
|
where id = ${leaseId}
|
|
20263
20705
|
returning *
|
|
@@ -20265,7 +20707,7 @@ async function recomputeAndStampLease(tx, leaseId, leaseTtlMs, setLiveness) {
|
|
|
20265
20707
|
return updated[0];
|
|
20266
20708
|
}
|
|
20267
20709
|
async function upsertLeaseHolder(tx, leaseId, accountId, workspaceId, kind, holderId, subjectId) {
|
|
20268
|
-
await tx.execute(
|
|
20710
|
+
await tx.execute(sql8`
|
|
20269
20711
|
insert into sandbox_lease_holders
|
|
20270
20712
|
(account_id, workspace_id, lease_id, kind, holder_id, subject_id, last_heartbeat_at)
|
|
20271
20713
|
values (${accountId}, ${workspaceId}, ${leaseId}, ${kind}, ${holderId}, ${subjectId}, now())
|
|
@@ -20288,7 +20730,7 @@ async function acquireLeaseOnce(db, input) {
|
|
|
20288
20730
|
const tx = txRaw;
|
|
20289
20731
|
const image = input.image ?? null;
|
|
20290
20732
|
const rigVersionId = input.rigVersionId ?? null;
|
|
20291
|
-
await tx.execute(
|
|
20733
|
+
await tx.execute(sql8`
|
|
20292
20734
|
insert into sandbox_leases
|
|
20293
20735
|
(account_id, workspace_id, sandbox_group_id, liveness, backend, os, image, rig_version_id, expires_at)
|
|
20294
20736
|
values
|
|
@@ -20296,7 +20738,7 @@ async function acquireLeaseOnce(db, input) {
|
|
|
20296
20738
|
now() + (${String(input.leaseTtlMs)} || ' milliseconds')::interval)
|
|
20297
20739
|
on conflict (workspace_id, sandbox_group_id) do nothing
|
|
20298
20740
|
`);
|
|
20299
|
-
const rows = await tx.execute(
|
|
20741
|
+
const rows = await tx.execute(sql8`
|
|
20300
20742
|
select *, (liveness = 'draining' and expires_at <= now()) as draining_expired
|
|
20301
20743
|
from sandbox_leases
|
|
20302
20744
|
where workspace_id = ${workspaceId} and sandbox_group_id = ${sandboxGroupId}
|
|
@@ -20306,7 +20748,7 @@ async function acquireLeaseOnce(db, input) {
|
|
|
20306
20748
|
if (!row) throw new Error(`Lease row vanished post-insert: ${sandboxGroupId}`);
|
|
20307
20749
|
const liveness = row.liveness;
|
|
20308
20750
|
if (kind === "viewer" && Number(row.turn_holders) === 0) {
|
|
20309
|
-
const workspaceRows = await tx.execute(
|
|
20751
|
+
const workspaceRows = await tx.execute(sql8`
|
|
20310
20752
|
select sandbox_viewer_force_drain_reason
|
|
20311
20753
|
from workspaces
|
|
20312
20754
|
where id = ${workspaceId}
|
|
@@ -20328,7 +20770,7 @@ async function acquireLeaseOnce(db, input) {
|
|
|
20328
20770
|
const imageConflict = image !== null && row.image !== null && row.image !== image;
|
|
20329
20771
|
const rigConflict = rigVersionId !== null && row.rig_version_id !== null && row.rig_version_id !== rigVersionId;
|
|
20330
20772
|
if (liveness !== "cold" && (imageConflict || rigConflict)) {
|
|
20331
|
-
const others = await tx.execute(
|
|
20773
|
+
const others = await tx.execute(sql8`
|
|
20332
20774
|
select count(*)::int as n from sandbox_lease_holders
|
|
20333
20775
|
where lease_id = ${row.id} and not (kind = ${kind} and holder_id = ${holderId})
|
|
20334
20776
|
`);
|
|
@@ -20347,7 +20789,7 @@ async function acquireLeaseOnce(db, input) {
|
|
|
20347
20789
|
rigVersionId
|
|
20348
20790
|
);
|
|
20349
20791
|
}
|
|
20350
|
-
const rotating = await tx.execute(
|
|
20792
|
+
const rotating = await tx.execute(sql8`
|
|
20351
20793
|
update sandbox_leases set
|
|
20352
20794
|
rotation_requested_at = coalesce(rotation_requested_at, now()),
|
|
20353
20795
|
rotation_reason = coalesce(rotation_reason, 'operator'),
|
|
@@ -20375,11 +20817,11 @@ async function acquireLeaseOnce(db, input) {
|
|
|
20375
20817
|
lease: mapLeaseRow(row)
|
|
20376
20818
|
};
|
|
20377
20819
|
}
|
|
20378
|
-
const casRows = await tx.execute(
|
|
20820
|
+
const casRows = await tx.execute(sql8`
|
|
20379
20821
|
update sandbox_leases set
|
|
20380
20822
|
liveness = 'warming',
|
|
20381
|
-
${image !== null ?
|
|
20382
|
-
${rigVersionId !== null ?
|
|
20823
|
+
${image !== null ? sql8`image = ${image},` : sql8``}
|
|
20824
|
+
${rigVersionId !== null ? sql8`rig_version_id = ${rigVersionId},` : sql8``}
|
|
20383
20825
|
updated_at = now()
|
|
20384
20826
|
where id = ${row.id} and liveness = 'cold'
|
|
20385
20827
|
returning id
|
|
@@ -20443,7 +20885,7 @@ async function beginSandboxRematerialization(db, input) {
|
|
|
20443
20885
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
20444
20886
|
async (scopedDb) => await scopedDb.transaction(async (txRaw) => {
|
|
20445
20887
|
const tx = txRaw;
|
|
20446
|
-
const rows = await tx.execute(
|
|
20888
|
+
const rows = await tx.execute(sql8`
|
|
20447
20889
|
select * from sandbox_leases
|
|
20448
20890
|
where workspace_id = ${input.workspaceId}
|
|
20449
20891
|
and sandbox_group_id = ${input.sandboxGroupId}
|
|
@@ -20531,7 +20973,7 @@ async function beginSandboxRematerialization(db, input) {
|
|
|
20531
20973
|
}
|
|
20532
20974
|
};
|
|
20533
20975
|
const degradedResumeState = resumeStateWithRecovery(workingResumeState, degraded);
|
|
20534
|
-
const degradedRows = await tx.execute(
|
|
20976
|
+
const degradedRows = await tx.execute(sql8`
|
|
20535
20977
|
update sandbox_leases set
|
|
20536
20978
|
resume_state = ${JSON.stringify(degradedResumeState)}::jsonb,
|
|
20537
20979
|
resume_backend_id = coalesce(resume_backend_id, backend),
|
|
@@ -20551,7 +20993,7 @@ async function beginSandboxRematerialization(db, input) {
|
|
|
20551
20993
|
}
|
|
20552
20994
|
let checkpointArtifact = null;
|
|
20553
20995
|
if (workingRow.current_checkpoint_artifact_id !== null) {
|
|
20554
|
-
const artifactRows = await tx.execute(
|
|
20996
|
+
const artifactRows = await tx.execute(sql8`
|
|
20555
20997
|
select id, account_id, workspace_id, sandbox_group_id,
|
|
20556
20998
|
source_lease_id, source_workspace_generation, provenance, provider_backend,
|
|
20557
20999
|
provider_binding_key, provider_binding, object_kind, object_id,
|
|
@@ -20593,7 +21035,7 @@ async function beginSandboxRematerialization(db, input) {
|
|
|
20593
21035
|
verifiedAt: null
|
|
20594
21036
|
}
|
|
20595
21037
|
};
|
|
20596
|
-
const degradedRows = await tx.execute(
|
|
21038
|
+
const degradedRows = await tx.execute(sql8`
|
|
20597
21039
|
update sandbox_leases set
|
|
20598
21040
|
resume_state = ${JSON.stringify(
|
|
20599
21041
|
resumeStateWithRecovery(workingResumeState, degraded)
|
|
@@ -20659,10 +21101,10 @@ async function beginSandboxRematerialization(db, input) {
|
|
|
20659
21101
|
const resumeStateJson = JSON.stringify(
|
|
20660
21102
|
resumeStateWithRecovery(workingResumeState, recovery)
|
|
20661
21103
|
);
|
|
20662
|
-
const updated = await tx.execute(
|
|
21104
|
+
const updated = await tx.execute(sql8`
|
|
20663
21105
|
update sandbox_leases set
|
|
20664
21106
|
resume_state = ${resumeStateJson}::jsonb,
|
|
20665
|
-
${importedArchiveGeneration ?
|
|
21107
|
+
${importedArchiveGeneration ? sql8`archive_generation = workspace_generation,` : sql8``}
|
|
20666
21108
|
updated_at = now()
|
|
20667
21109
|
where id = ${row.id}
|
|
20668
21110
|
and liveness = 'warming'
|
|
@@ -20686,7 +21128,7 @@ async function markSandboxRestoreVerifying(db, input) {
|
|
|
20686
21128
|
db,
|
|
20687
21129
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
20688
21130
|
async (scopedDb) => {
|
|
20689
|
-
const rows = await scopedDb.execute(
|
|
21131
|
+
const rows = await scopedDb.execute(sql8`
|
|
20690
21132
|
update sandbox_leases set
|
|
20691
21133
|
resume_state = jsonb_set(resume_state, '{opengeniRecovery,restore,status}', '"verifying"'::jsonb),
|
|
20692
21134
|
updated_at = now()
|
|
@@ -20708,7 +21150,7 @@ async function failSandboxRematerialization(db, input) {
|
|
|
20708
21150
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
20709
21151
|
async (scopedDb) => await scopedDb.transaction(async (txRaw) => {
|
|
20710
21152
|
const tx = txRaw;
|
|
20711
|
-
const rows = await tx.execute(
|
|
21153
|
+
const rows = await tx.execute(sql8`
|
|
20712
21154
|
select * from sandbox_leases
|
|
20713
21155
|
where workspace_id = ${input.workspaceId}
|
|
20714
21156
|
and sandbox_group_id = ${input.sandboxGroupId}
|
|
@@ -20741,7 +21183,7 @@ async function failSandboxRematerialization(db, input) {
|
|
|
20741
21183
|
}
|
|
20742
21184
|
};
|
|
20743
21185
|
const resumeStateJson = JSON.stringify(archiveOnlyResumeState(row, recovery));
|
|
20744
|
-
const updated = await tx.execute(
|
|
21186
|
+
const updated = await tx.execute(sql8`
|
|
20745
21187
|
update sandbox_leases set
|
|
20746
21188
|
liveness = 'cold',
|
|
20747
21189
|
instance_id = null,
|
|
@@ -20773,7 +21215,7 @@ async function markSandboxProviderReady(db, input) {
|
|
|
20773
21215
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
20774
21216
|
async (scopedDb) => await scopedDb.transaction(async (txRaw) => {
|
|
20775
21217
|
const tx = txRaw;
|
|
20776
|
-
const rows = await tx.execute(
|
|
21218
|
+
const rows = await tx.execute(sql8`
|
|
20777
21219
|
select * from sandbox_leases
|
|
20778
21220
|
where workspace_id = ${input.workspaceId}
|
|
20779
21221
|
and sandbox_group_id = ${input.sandboxGroupId}
|
|
@@ -20806,7 +21248,7 @@ async function markSandboxProviderReady(db, input) {
|
|
|
20806
21248
|
}
|
|
20807
21249
|
};
|
|
20808
21250
|
const resumeStateJson = JSON.stringify(resumeStateWithRecovery(row.resume_state, recovery));
|
|
20809
|
-
const updated = await tx.execute(
|
|
21251
|
+
const updated = await tx.execute(sql8`
|
|
20810
21252
|
update sandbox_leases set resume_state = ${resumeStateJson}::jsonb, updated_at = now()
|
|
20811
21253
|
where id = ${row.id}
|
|
20812
21254
|
and liveness = 'warm'
|
|
@@ -20824,7 +21266,7 @@ async function commitWarmingToWarm(db, input) {
|
|
|
20824
21266
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
20825
21267
|
async (scopedDb) => await scopedDb.transaction(async (txRaw) => {
|
|
20826
21268
|
const tx = txRaw;
|
|
20827
|
-
const rows = await tx.execute(
|
|
21269
|
+
const rows = await tx.execute(sql8`
|
|
20828
21270
|
select * from sandbox_leases
|
|
20829
21271
|
where workspace_id = ${input.workspaceId}
|
|
20830
21272
|
and sandbox_group_id = ${input.sandboxGroupId}
|
|
@@ -20913,7 +21355,7 @@ async function commitWarmingToWarm(db, input) {
|
|
|
20913
21355
|
row.resume_state
|
|
20914
21356
|
);
|
|
20915
21357
|
const resumeStateJson = JSON.stringify(resumeStateWithRecovery(withArchives, recovery));
|
|
20916
|
-
const updated = await tx.execute(
|
|
21358
|
+
const updated = await tx.execute(sql8`
|
|
20917
21359
|
update sandbox_leases set
|
|
20918
21360
|
liveness = 'warm',
|
|
20919
21361
|
instance_id = ${input.instanceId},
|
|
@@ -20946,7 +21388,7 @@ async function recordWarmingSandboxCreated(db, input) {
|
|
|
20946
21388
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
20947
21389
|
async (scopedDb) => await scopedDb.transaction(async (txRaw) => {
|
|
20948
21390
|
const tx = txRaw;
|
|
20949
|
-
const rows = await tx.execute(
|
|
21391
|
+
const rows = await tx.execute(sql8`
|
|
20950
21392
|
select * from sandbox_leases
|
|
20951
21393
|
where workspace_id = ${input.workspaceId}
|
|
20952
21394
|
and sandbox_group_id = ${input.sandboxGroupId}
|
|
@@ -20989,7 +21431,7 @@ async function recordWarmingSandboxCreated(db, input) {
|
|
|
20989
21431
|
if (providerCreatedAt && providerDeadlineAt && providerDeadlineAt.getTime() <= providerCreatedAt.getTime()) {
|
|
20990
21432
|
throw new Error("Provider deadline must be later than provider creation");
|
|
20991
21433
|
}
|
|
20992
|
-
const updated = await tx.execute(
|
|
21434
|
+
const updated = await tx.execute(sql8`
|
|
20993
21435
|
update sandbox_leases set
|
|
20994
21436
|
instance_id = ${input.instanceId},
|
|
20995
21437
|
resume_backend_id = ${input.resumeBackendId ?? null},
|
|
@@ -21064,18 +21506,18 @@ function archiveSessionState(row) {
|
|
|
21064
21506
|
return sessionState && typeof sessionState === "object" ? sessionState : null;
|
|
21065
21507
|
}
|
|
21066
21508
|
async function readColdLostSnapshotRowsTx(tx, input) {
|
|
21067
|
-
const timestampRows = await tx.execute(
|
|
21509
|
+
const timestampRows = await tx.execute(sql8`
|
|
21068
21510
|
select transaction_timestamp() as snapshot_at
|
|
21069
21511
|
`);
|
|
21070
21512
|
const [sessionRows, leaseRows] = await Promise.all([
|
|
21071
|
-
tx.execute(
|
|
21513
|
+
tx.execute(sql8`
|
|
21072
21514
|
select id, status, sandbox_group_id, active_sandbox_id, active_epoch
|
|
21073
21515
|
from sessions
|
|
21074
21516
|
where account_id = ${input.accountId}
|
|
21075
21517
|
and workspace_id = ${input.workspaceId}
|
|
21076
21518
|
and id = ${input.sessionId}
|
|
21077
21519
|
`),
|
|
21078
|
-
tx.execute(
|
|
21520
|
+
tx.execute(sql8`
|
|
21079
21521
|
select * from sandbox_leases
|
|
21080
21522
|
where account_id = ${input.accountId}
|
|
21081
21523
|
and workspace_id = ${input.workspaceId}
|
|
@@ -21099,7 +21541,7 @@ async function readColdLostSnapshotRowsTx(tx, input) {
|
|
|
21099
21541
|
};
|
|
21100
21542
|
}
|
|
21101
21543
|
const [processes, admissions, ptys, holders, interruptions] = await Promise.all([
|
|
21102
|
-
tx.execute(
|
|
21544
|
+
tx.execute(sql8`
|
|
21103
21545
|
select id,
|
|
21104
21546
|
session_id as "sessionId",
|
|
21105
21547
|
parent_admission_id as "parentAdmissionId",
|
|
@@ -21132,7 +21574,7 @@ async function readColdLostSnapshotRowsTx(tx, input) {
|
|
|
21132
21574
|
))
|
|
21133
21575
|
order by id
|
|
21134
21576
|
`),
|
|
21135
|
-
tx.execute(
|
|
21577
|
+
tx.execute(sql8`
|
|
21136
21578
|
select id,
|
|
21137
21579
|
session_id as "sessionId",
|
|
21138
21580
|
actor_kind as "actorKind",
|
|
@@ -21167,7 +21609,7 @@ async function readColdLostSnapshotRowsTx(tx, input) {
|
|
|
21167
21609
|
))
|
|
21168
21610
|
order by id
|
|
21169
21611
|
`),
|
|
21170
|
-
tx.execute(
|
|
21612
|
+
tx.execute(sql8`
|
|
21171
21613
|
select id,
|
|
21172
21614
|
session_id as "sessionId",
|
|
21173
21615
|
retained_process_id as "retainedProcessId",
|
|
@@ -21195,7 +21637,7 @@ async function readColdLostSnapshotRowsTx(tx, input) {
|
|
|
21195
21637
|
))
|
|
21196
21638
|
order by id
|
|
21197
21639
|
`),
|
|
21198
|
-
tx.execute(
|
|
21640
|
+
tx.execute(sql8`
|
|
21199
21641
|
select holder.id,
|
|
21200
21642
|
holder.kind,
|
|
21201
21643
|
holder.holder_id,
|
|
@@ -21217,7 +21659,7 @@ async function readColdLostSnapshotRowsTx(tx, input) {
|
|
|
21217
21659
|
and holder.lease_id = ${lease.id}
|
|
21218
21660
|
order by holder.kind, holder.holder_id
|
|
21219
21661
|
`),
|
|
21220
|
-
tx.execute(
|
|
21662
|
+
tx.execute(sql8`
|
|
21221
21663
|
select interruption.id,
|
|
21222
21664
|
interruption.session_id as "sessionId",
|
|
21223
21665
|
interruption.operation_id as "operationId",
|
|
@@ -21851,7 +22293,7 @@ function evaluateColdLostSnapshot(input, rows, database, options = { requireRead
|
|
|
21851
22293
|
};
|
|
21852
22294
|
}
|
|
21853
22295
|
async function readColdLostDatabasePostureTx(tx) {
|
|
21854
|
-
const postureRows = await tx.execute(
|
|
22296
|
+
const postureRows = await tx.execute(sql8`
|
|
21855
22297
|
select current_user as role,
|
|
21856
22298
|
coalesce((select rolsuper from pg_roles where rolname = current_user), true) as role_superuser,
|
|
21857
22299
|
coalesce((select rolbypassrls from pg_roles where rolname = current_user), true) as role_bypass_rls,
|
|
@@ -21902,7 +22344,7 @@ async function previewColdLostLeaseInstanceBlockers(db, input) {
|
|
|
21902
22344
|
}
|
|
21903
22345
|
var LOST_PROVIDER_PROCESS_REASON = "provider_instance_lost";
|
|
21904
22346
|
async function lockExactLostProviderWorkspaceBlockersTx(tx, input) {
|
|
21905
|
-
await tx.execute(
|
|
22347
|
+
await tx.execute(sql8`
|
|
21906
22348
|
select id from sandbox_retained_processes
|
|
21907
22349
|
where account_id = ${input.accountId}
|
|
21908
22350
|
and workspace_id = ${input.workspaceId}
|
|
@@ -21914,7 +22356,7 @@ async function lockExactLostProviderWorkspaceBlockersTx(tx, input) {
|
|
|
21914
22356
|
order by id
|
|
21915
22357
|
for update
|
|
21916
22358
|
`);
|
|
21917
|
-
await tx.execute(
|
|
22359
|
+
await tx.execute(sql8`
|
|
21918
22360
|
select id from sandbox_workspace_mutation_admissions
|
|
21919
22361
|
where account_id = ${input.accountId}
|
|
21920
22362
|
and workspace_id = ${input.workspaceId}
|
|
@@ -21926,7 +22368,7 @@ async function lockExactLostProviderWorkspaceBlockersTx(tx, input) {
|
|
|
21926
22368
|
order by id
|
|
21927
22369
|
for update
|
|
21928
22370
|
`);
|
|
21929
|
-
await tx.execute(
|
|
22371
|
+
await tx.execute(sql8`
|
|
21930
22372
|
select id from sandbox_pty_sessions
|
|
21931
22373
|
where account_id = ${input.accountId}
|
|
21932
22374
|
and workspace_id = ${input.workspaceId}
|
|
@@ -21993,7 +22435,7 @@ async function settleExactLostProviderWorkspaceBlockersTx(tx, input) {
|
|
|
21993
22435
|
)
|
|
21994
22436
|
)
|
|
21995
22437
|
).returning({ holderId: sandboxLeaseHolders.holderId });
|
|
21996
|
-
await tx.execute(
|
|
22438
|
+
await tx.execute(sql8`
|
|
21997
22439
|
update sandbox_leases as lease set
|
|
21998
22440
|
refcount = counts.total,
|
|
21999
22441
|
turn_holders = counts.turns,
|
|
@@ -22021,7 +22463,7 @@ async function markWarmLeaseInstanceLost(db, input) {
|
|
|
22021
22463
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
22022
22464
|
async (scopedDb) => await scopedDb.transaction(async (txRaw) => {
|
|
22023
22465
|
const tx = txRaw;
|
|
22024
|
-
const observedRows = await tx.execute(
|
|
22466
|
+
const observedRows = await tx.execute(sql8`
|
|
22025
22467
|
select * from sandbox_leases
|
|
22026
22468
|
where workspace_id = ${input.workspaceId}
|
|
22027
22469
|
and sandbox_group_id = ${input.sandboxGroupId}
|
|
@@ -22042,7 +22484,7 @@ async function markWarmLeaseInstanceLost(db, input) {
|
|
|
22042
22484
|
lostInstanceId: input.expectedInstanceId
|
|
22043
22485
|
};
|
|
22044
22486
|
await lockExactLostProviderWorkspaceBlockersTx(tx, blockerScope);
|
|
22045
|
-
const currentRows = await tx.execute(
|
|
22487
|
+
const currentRows = await tx.execute(sql8`
|
|
22046
22488
|
select * from sandbox_leases
|
|
22047
22489
|
where workspace_id = ${input.workspaceId}
|
|
22048
22490
|
and sandbox_group_id = ${input.sandboxGroupId}
|
|
@@ -22089,7 +22531,7 @@ async function markWarmLeaseInstanceLost(db, input) {
|
|
|
22089
22531
|
};
|
|
22090
22532
|
const coldResumeState = archiveOnlyResumeState(current, recovery);
|
|
22091
22533
|
const coldResumeStateJson = JSON.stringify(coldResumeState);
|
|
22092
|
-
const updatedRows = await tx.execute(
|
|
22534
|
+
const updatedRows = await tx.execute(sql8`
|
|
22093
22535
|
update sandbox_leases set
|
|
22094
22536
|
liveness = 'cold',
|
|
22095
22537
|
instance_id = null,
|
|
@@ -22195,7 +22637,7 @@ async function reconcileColdLostLeaseInstanceBlockers(db, input) {
|
|
|
22195
22637
|
lostInstanceId: input.expectedLostInstanceId
|
|
22196
22638
|
};
|
|
22197
22639
|
await lockExactLostProviderWorkspaceBlockersTx(tx, blockerScope);
|
|
22198
|
-
const currentRows = await tx.execute(
|
|
22640
|
+
const currentRows = await tx.execute(sql8`
|
|
22199
22641
|
select * from sandbox_leases
|
|
22200
22642
|
where workspace_id = ${input.workspaceId}
|
|
22201
22643
|
and sandbox_group_id = ${input.sandboxGroupId}
|
|
@@ -22225,7 +22667,7 @@ async function reconcileColdLostLeaseInstanceBlockers(db, input) {
|
|
|
22225
22667
|
return { status: "blocked", preview: currentPreview };
|
|
22226
22668
|
}
|
|
22227
22669
|
const settlement = await settleExactLostProviderWorkspaceBlockersTx(tx, blockerScope);
|
|
22228
|
-
const refreshedRows = await tx.execute(
|
|
22670
|
+
const refreshedRows = await tx.execute(sql8`
|
|
22229
22671
|
select * from sandbox_leases where id = ${current.id}
|
|
22230
22672
|
`);
|
|
22231
22673
|
const refreshed = refreshedRows[0];
|
|
@@ -22244,7 +22686,7 @@ async function failWarmingToCold(db, input) {
|
|
|
22244
22686
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
22245
22687
|
async (scopedDb) => await scopedDb.transaction(async (txRaw) => {
|
|
22246
22688
|
const tx = txRaw;
|
|
22247
|
-
const rows = await tx.execute(
|
|
22689
|
+
const rows = await tx.execute(sql8`
|
|
22248
22690
|
select * from sandbox_leases
|
|
22249
22691
|
where workspace_id = ${input.workspaceId}
|
|
22250
22692
|
and sandbox_group_id = ${input.sandboxGroupId}
|
|
@@ -22284,7 +22726,7 @@ async function failWarmingToCold(db, input) {
|
|
|
22284
22726
|
}
|
|
22285
22727
|
};
|
|
22286
22728
|
const resumeStateJson = hasArchive ? JSON.stringify(archiveOnlyResumeState(row, recovery)) : null;
|
|
22287
|
-
await tx.execute(
|
|
22729
|
+
await tx.execute(sql8`
|
|
22288
22730
|
update sandbox_leases set
|
|
22289
22731
|
liveness = 'cold',
|
|
22290
22732
|
instance_id = null,
|
|
@@ -22318,18 +22760,18 @@ async function releaseLeaseHolder(db, input) {
|
|
|
22318
22760
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
22319
22761
|
async (scopedDb) => await scopedDb.transaction(async (txRaw) => {
|
|
22320
22762
|
const tx = txRaw;
|
|
22321
|
-
const rows = await tx.execute(
|
|
22763
|
+
const rows = await tx.execute(sql8`
|
|
22322
22764
|
select * from sandbox_leases
|
|
22323
22765
|
where workspace_id = ${input.workspaceId} and sandbox_group_id = ${input.sandboxGroupId}
|
|
22324
22766
|
for update
|
|
22325
22767
|
`);
|
|
22326
22768
|
const row = rows[0];
|
|
22327
22769
|
if (!row) return null;
|
|
22328
|
-
await tx.execute(
|
|
22770
|
+
await tx.execute(sql8`
|
|
22329
22771
|
delete from sandbox_lease_holders
|
|
22330
22772
|
where lease_id = ${row.id} and kind = ${input.kind} and holder_id = ${input.holderId}
|
|
22331
22773
|
`);
|
|
22332
|
-
const counts = await tx.execute(
|
|
22774
|
+
const counts = await tx.execute(sql8`
|
|
22333
22775
|
select count(*)::int as total,
|
|
22334
22776
|
count(*) filter (where kind = 'turn')::int as turns,
|
|
22335
22777
|
count(*) filter (where kind = 'viewer')::int as viewers
|
|
@@ -22338,10 +22780,10 @@ async function releaseLeaseHolder(db, input) {
|
|
|
22338
22780
|
const c = counts[0];
|
|
22339
22781
|
const enterDraining = row.liveness === "warm" && c.total === 0 && c.turns === 0;
|
|
22340
22782
|
const drainGraceMs = row.rotation_requested_at ? 0 : input.idleGraceMs;
|
|
22341
|
-
const updated = await tx.execute(
|
|
22783
|
+
const updated = await tx.execute(sql8`
|
|
22342
22784
|
update sandbox_leases set
|
|
22343
22785
|
refcount = ${c.total}, turn_holders = ${c.turns}, viewer_holders = ${c.viewers},
|
|
22344
|
-
${enterDraining ?
|
|
22786
|
+
${enterDraining ? sql8`liveness = 'draining', expires_at = now() + (${String(drainGraceMs)} || ' milliseconds')::interval,` : sql8``}
|
|
22345
22787
|
updated_at = now()
|
|
22346
22788
|
where id = ${row.id}
|
|
22347
22789
|
returning *
|
|
@@ -22350,7 +22792,7 @@ async function releaseLeaseHolder(db, input) {
|
|
|
22350
22792
|
})
|
|
22351
22793
|
);
|
|
22352
22794
|
}
|
|
22353
|
-
var LIVE_CANONICAL_TURN_HOLDER_PREDICATE =
|
|
22795
|
+
var LIVE_CANONICAL_TURN_HOLDER_PREDICATE = sql8`
|
|
22354
22796
|
(
|
|
22355
22797
|
holder.kind <> 'turn'
|
|
22356
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}$'
|
|
@@ -22373,7 +22815,7 @@ var LIVE_CANONICAL_TURN_HOLDER_PREDICATE = sql7`
|
|
|
22373
22815
|
)
|
|
22374
22816
|
`;
|
|
22375
22817
|
async function touchLiveLeaseHolder(tx, input) {
|
|
22376
|
-
const updated = await tx.execute(
|
|
22818
|
+
const updated = await tx.execute(sql8`
|
|
22377
22819
|
update sandbox_lease_holders as holder set last_heartbeat_at = now()
|
|
22378
22820
|
where holder.lease_id = (
|
|
22379
22821
|
select id from sandbox_leases
|
|
@@ -22394,7 +22836,7 @@ async function heartbeatLeaseHolder(db, input) {
|
|
|
22394
22836
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
22395
22837
|
async (scopedDb) => await scopedDb.transaction(async (txRaw) => {
|
|
22396
22838
|
const tx = txRaw;
|
|
22397
|
-
const leases = await tx.execute(
|
|
22839
|
+
const leases = await tx.execute(sql8`
|
|
22398
22840
|
select id from sandbox_leases
|
|
22399
22841
|
where workspace_id = ${input.workspaceId}
|
|
22400
22842
|
and sandbox_group_id = ${input.sandboxGroupId}
|
|
@@ -22409,7 +22851,7 @@ async function heartbeatLeaseHolder(db, input) {
|
|
|
22409
22851
|
holderId: input.holderId
|
|
22410
22852
|
});
|
|
22411
22853
|
if (!holderAlive) return false;
|
|
22412
|
-
const leaseRows = await tx.execute(
|
|
22854
|
+
const leaseRows = await tx.execute(sql8`
|
|
22413
22855
|
update sandbox_leases set
|
|
22414
22856
|
expires_at = now() + (${String(input.leaseTtlMs)} || ' milliseconds')::interval,
|
|
22415
22857
|
updated_at = now()
|
|
@@ -22445,13 +22887,13 @@ async function reapStaleLeaseHolders(db, input) {
|
|
|
22445
22887
|
input.workspaceId,
|
|
22446
22888
|
async (scopedDb) => await scopedDb.transaction(async (txRaw) => {
|
|
22447
22889
|
const tx = txRaw;
|
|
22448
|
-
await tx.execute(
|
|
22890
|
+
await tx.execute(sql8`
|
|
22449
22891
|
select id from sandbox_leases
|
|
22450
22892
|
where workspace_id = ${input.workspaceId}
|
|
22451
22893
|
order by id
|
|
22452
22894
|
for update
|
|
22453
22895
|
`);
|
|
22454
|
-
const reaped = await tx.execute(
|
|
22896
|
+
const reaped = await tx.execute(sql8`
|
|
22455
22897
|
delete from sandbox_lease_holders
|
|
22456
22898
|
where id in (
|
|
22457
22899
|
select id from sandbox_lease_holders
|
|
@@ -22467,7 +22909,7 @@ async function reapStaleLeaseHolders(db, input) {
|
|
|
22467
22909
|
const reapedDirect = reaped.filter(
|
|
22468
22910
|
(row) => row.kind === "direct"
|
|
22469
22911
|
).length;
|
|
22470
|
-
const reapedTurnRows = input.turnHolderTtlMs && input.turnHolderTtlMs > 0 ? await tx.execute(
|
|
22912
|
+
const reapedTurnRows = input.turnHolderTtlMs && input.turnHolderTtlMs > 0 ? await tx.execute(sql8`
|
|
22471
22913
|
delete from sandbox_lease_holders
|
|
22472
22914
|
where id in (
|
|
22473
22915
|
select id from sandbox_lease_holders
|
|
@@ -22477,7 +22919,7 @@ async function reapStaleLeaseHolders(db, input) {
|
|
|
22477
22919
|
)
|
|
22478
22920
|
returning lease_id
|
|
22479
22921
|
`) : [];
|
|
22480
|
-
await tx.execute(
|
|
22922
|
+
await tx.execute(sql8`
|
|
22481
22923
|
update sandbox_leases L set
|
|
22482
22924
|
refcount = c.total,
|
|
22483
22925
|
turn_holders = c.turns,
|
|
@@ -22500,7 +22942,7 @@ async function reapStaleLeaseHolders(db, input) {
|
|
|
22500
22942
|
) c
|
|
22501
22943
|
where L.id = c.id and L.workspace_id = ${input.workspaceId}
|
|
22502
22944
|
`);
|
|
22503
|
-
const expiredWarming = await tx.execute(
|
|
22945
|
+
const expiredWarming = await tx.execute(sql8`
|
|
22504
22946
|
select * from sandbox_leases
|
|
22505
22947
|
where workspace_id = ${input.workspaceId}
|
|
22506
22948
|
and liveness = 'warming' and expires_at < now() and instance_id is null
|
|
@@ -22533,7 +22975,7 @@ async function reapStaleLeaseHolders(db, input) {
|
|
|
22533
22975
|
verifiedAt: null
|
|
22534
22976
|
}
|
|
22535
22977
|
}) : null;
|
|
22536
|
-
const reset = await tx.execute(
|
|
22978
|
+
const reset = await tx.execute(sql8`
|
|
22537
22979
|
update sandbox_leases set
|
|
22538
22980
|
liveness = 'cold', instance_id = null,
|
|
22539
22981
|
lease_epoch = lease_epoch + 1,
|
|
@@ -22553,7 +22995,7 @@ async function reapStaleLeaseHolders(db, input) {
|
|
|
22553
22995
|
`);
|
|
22554
22996
|
warmingReset += reset.length;
|
|
22555
22997
|
}
|
|
22556
|
-
const warmingDrain = await tx.execute(
|
|
22998
|
+
const warmingDrain = await tx.execute(sql8`
|
|
22557
22999
|
update sandbox_leases set
|
|
22558
23000
|
liveness = 'draining',
|
|
22559
23001
|
refcount = 0,
|
|
@@ -22570,7 +23012,7 @@ async function reapStaleLeaseHolders(db, input) {
|
|
|
22570
23012
|
`);
|
|
22571
23013
|
const drainable = await rawRows(
|
|
22572
23014
|
tx,
|
|
22573
|
-
|
|
23015
|
+
sql8`
|
|
22574
23016
|
select sandbox_group_id, instance_id, lease_epoch from sandbox_leases
|
|
22575
23017
|
where workspace_id = ${input.workspaceId}
|
|
22576
23018
|
and liveness = 'draining' and expires_at < now() and refcount = 0
|
|
@@ -22595,10 +23037,10 @@ async function reapStaleLeaseHoldersGlobal(db, input) {
|
|
|
22595
23037
|
let rows;
|
|
22596
23038
|
const runCurrentReaper = async () => await db.transaction(async (txRaw) => {
|
|
22597
23039
|
const tx = txRaw;
|
|
22598
|
-
await tx.execute(
|
|
23040
|
+
await tx.execute(sql8`select set_config('opengeni.sandbox_recovery_protocol_v2', '1', true)`);
|
|
22599
23041
|
return await rawRows(
|
|
22600
23042
|
tx,
|
|
22601
|
-
|
|
23043
|
+
sql8`
|
|
22602
23044
|
select workspace_id, sandbox_group_id, instance_id, lease_epoch
|
|
22603
23045
|
from opengeni_private.reap_sandbox_leases(${input.viewerHolderTtlMs}, ${input.turnHolderTtlMs ?? 0}, ${input.idleGraceMs})
|
|
22604
23046
|
`
|
|
@@ -22606,10 +23048,10 @@ async function reapStaleLeaseHoldersGlobal(db, input) {
|
|
|
22606
23048
|
});
|
|
22607
23049
|
const runLegacyReaper = async () => await db.transaction(async (txRaw) => {
|
|
22608
23050
|
const tx = txRaw;
|
|
22609
|
-
await tx.execute(
|
|
23051
|
+
await tx.execute(sql8`select set_config('opengeni.sandbox_recovery_protocol_v2', '1', true)`);
|
|
22610
23052
|
return await rawRows(
|
|
22611
23053
|
tx,
|
|
22612
|
-
|
|
23054
|
+
sql8`
|
|
22613
23055
|
select workspace_id, sandbox_group_id, instance_id, lease_epoch
|
|
22614
23056
|
from opengeni_private.reap_sandbox_leases(${input.viewerHolderTtlMs}, ${input.idleGraceMs})
|
|
22615
23057
|
`
|
|
@@ -22639,7 +23081,7 @@ async function reapStaleLeaseHoldersGlobal(db, input) {
|
|
|
22639
23081
|
async function listMeterableWarmLeases(db) {
|
|
22640
23082
|
const rows = await rawRows(
|
|
22641
23083
|
db,
|
|
22642
|
-
|
|
23084
|
+
sql8`
|
|
22643
23085
|
select account_id, workspace_id, sandbox_group_id, lease_epoch, backend
|
|
22644
23086
|
from opengeni_private.list_meterable_warm_leases()
|
|
22645
23087
|
`
|
|
@@ -22655,7 +23097,7 @@ async function listMeterableWarmLeases(db) {
|
|
|
22655
23097
|
async function listSandboxViewerForceDrainWorkspaceIds(db) {
|
|
22656
23098
|
const rows = await rawRows(
|
|
22657
23099
|
db,
|
|
22658
|
-
|
|
23100
|
+
sql8`select workspace_id
|
|
22659
23101
|
from opengeni_private.list_sandbox_viewer_force_drain_workspaces()`
|
|
22660
23102
|
);
|
|
22661
23103
|
return rows.map((row) => row.workspace_id);
|
|
@@ -22663,7 +23105,7 @@ async function listSandboxViewerForceDrainWorkspaceIds(db) {
|
|
|
22663
23105
|
async function countQueuedTurns(db) {
|
|
22664
23106
|
const rows = await rawRows(
|
|
22665
23107
|
db,
|
|
22666
|
-
|
|
23108
|
+
sql8`
|
|
22667
23109
|
select opengeni_private.count_queued_turns() as count
|
|
22668
23110
|
`
|
|
22669
23111
|
);
|
|
@@ -22678,7 +23120,7 @@ async function countSandboxLeasesByLiveness(db) {
|
|
|
22678
23120
|
};
|
|
22679
23121
|
const rows = await rawRows(
|
|
22680
23122
|
db,
|
|
22681
|
-
|
|
23123
|
+
sql8`
|
|
22682
23124
|
select liveness, count
|
|
22683
23125
|
from opengeni_private.count_sandbox_leases_by_liveness()
|
|
22684
23126
|
`
|
|
@@ -22693,7 +23135,7 @@ async function countSandboxLeasesByLiveness(db) {
|
|
|
22693
23135
|
async function listCreditBalancesByAccount(db) {
|
|
22694
23136
|
const rows = await rawRows(
|
|
22695
23137
|
db,
|
|
22696
|
-
|
|
23138
|
+
sql8`
|
|
22697
23139
|
select account_id, balance_micros
|
|
22698
23140
|
from opengeni_private.credit_balance_by_account()
|
|
22699
23141
|
`
|
|
@@ -22706,7 +23148,7 @@ async function listCreditBalancesByAccount(db) {
|
|
|
22706
23148
|
async function listLiveModalSandboxLeaseAttributions(db) {
|
|
22707
23149
|
const rows = await rawRows(
|
|
22708
23150
|
db,
|
|
22709
|
-
|
|
23151
|
+
sql8`
|
|
22710
23152
|
select lease_id, workspace_id, sandbox_group_id, instance_id, liveness
|
|
22711
23153
|
from opengeni_private.list_live_modal_sandbox_leases()
|
|
22712
23154
|
`
|
|
@@ -22724,7 +23166,7 @@ async function reArmDrainingLease(db, input) {
|
|
|
22724
23166
|
db,
|
|
22725
23167
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
22726
23168
|
async (scopedDb) => {
|
|
22727
|
-
const rows = await scopedDb.execute(
|
|
23169
|
+
const rows = await scopedDb.execute(sql8`
|
|
22728
23170
|
update sandbox_leases set
|
|
22729
23171
|
liveness = 'warm',
|
|
22730
23172
|
expires_at = now() + (${String(input.leaseTtlMs)} || ' milliseconds')::interval,
|
|
@@ -22745,7 +23187,7 @@ async function confirmDrainCold(db, input) {
|
|
|
22745
23187
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
22746
23188
|
async (scopedDb) => await scopedDb.transaction(async (txRaw) => {
|
|
22747
23189
|
const tx = txRaw;
|
|
22748
|
-
const observedRows = await tx.execute(
|
|
23190
|
+
const observedRows = await tx.execute(sql8`
|
|
22749
23191
|
select * from sandbox_leases
|
|
22750
23192
|
where workspace_id = ${input.workspaceId}
|
|
22751
23193
|
and sandbox_group_id = ${input.sandboxGroupId}
|
|
@@ -22765,7 +23207,7 @@ async function confirmDrainCold(db, input) {
|
|
|
22765
23207
|
if (blockerScope) {
|
|
22766
23208
|
await lockExactLostProviderWorkspaceBlockersTx(tx, blockerScope);
|
|
22767
23209
|
}
|
|
22768
|
-
const locked = await tx.execute(
|
|
23210
|
+
const locked = await tx.execute(sql8`
|
|
22769
23211
|
select * from sandbox_leases
|
|
22770
23212
|
where workspace_id = ${input.workspaceId}
|
|
22771
23213
|
and sandbox_group_id = ${input.sandboxGroupId}
|
|
@@ -22810,7 +23252,7 @@ async function confirmDrainCold(db, input) {
|
|
|
22810
23252
|
};
|
|
22811
23253
|
const preserveRecovery = hasArchive || restoreStatus === "unrecoverable";
|
|
22812
23254
|
const resumeStateJson = preserveRecovery ? JSON.stringify(archiveOnlyResumeState(row, recovery)) : null;
|
|
22813
|
-
const rows = await tx.execute(
|
|
23255
|
+
const rows = await tx.execute(sql8`
|
|
22814
23256
|
update sandbox_leases set
|
|
22815
23257
|
liveness = 'cold',
|
|
22816
23258
|
instance_id = null,
|
|
@@ -23150,7 +23592,7 @@ async function advanceWorkspaceGenerationForAuthorityOnce(db, authority, operati
|
|
|
23150
23592
|
async (scopedDb) => await scopedDb.transaction(async (txRaw) => {
|
|
23151
23593
|
const tx = txRaw;
|
|
23152
23594
|
const locked = await lockWorkspaceMutationAuthorityTx(tx, authority);
|
|
23153
|
-
const rows = await tx.execute(
|
|
23595
|
+
const rows = await tx.execute(sql8`
|
|
23154
23596
|
with advanced as (
|
|
23155
23597
|
update sandbox_leases as lease set
|
|
23156
23598
|
workspace_generation = lease.workspace_generation + 1,
|
|
@@ -23198,7 +23640,7 @@ async function advanceWorkspaceGenerationForAuthorityOnce(db, authority, operati
|
|
|
23198
23640
|
`);
|
|
23199
23641
|
const row = rows[0];
|
|
23200
23642
|
if (!row) {
|
|
23201
|
-
const current = await tx.execute(
|
|
23643
|
+
const current = await tx.execute(sql8`
|
|
23202
23644
|
select lease.workspace_generation,
|
|
23203
23645
|
(
|
|
23204
23646
|
lease.account_id = ${locked.accountId}
|
|
@@ -23316,7 +23758,7 @@ async function advanceWorkspaceGenerationForRetainedProcess(db, input) {
|
|
|
23316
23758
|
);
|
|
23317
23759
|
}
|
|
23318
23760
|
async function selectExactAdmissionForUpdate(tx, input) {
|
|
23319
|
-
const rows = await tx.execute(
|
|
23761
|
+
const rows = await tx.execute(sql8`
|
|
23320
23762
|
select * from sandbox_workspace_mutation_admissions
|
|
23321
23763
|
where id = ${input.admissionId}
|
|
23322
23764
|
and account_id = ${input.accountId}
|
|
@@ -23379,7 +23821,7 @@ async function verifyResolvedAdmissionAuthority(tx, authority, admission) {
|
|
|
23379
23821
|
detail: "Workspace mutation output rejected because its active route moved"
|
|
23380
23822
|
};
|
|
23381
23823
|
}
|
|
23382
|
-
const [identity] = await tx.execute(
|
|
23824
|
+
const [identity] = await tx.execute(sql8`
|
|
23383
23825
|
select
|
|
23384
23826
|
(
|
|
23385
23827
|
lease.account_id = ${authority.accountId}
|
|
@@ -23447,7 +23889,7 @@ async function verifyWorkspaceMutationSettlementForAuthority(db, authorityInput,
|
|
|
23447
23889
|
};
|
|
23448
23890
|
}
|
|
23449
23891
|
if (!admission.settled_at) {
|
|
23450
|
-
await tx.execute(
|
|
23892
|
+
await tx.execute(sql8`
|
|
23451
23893
|
update sandbox_workspace_mutation_admissions set
|
|
23452
23894
|
provider_outcome = ${input.outcome}, settled_at = now()
|
|
23453
23895
|
where id = ${input.admission.id} and settled_at is null
|
|
@@ -23618,7 +24060,7 @@ async function retainWorkspaceMutationProcess(db, input) {
|
|
|
23618
24060
|
"Settled workspace mutation cannot be promoted to a retained process"
|
|
23619
24061
|
);
|
|
23620
24062
|
}
|
|
23621
|
-
const processLeases = await tx.execute(
|
|
24063
|
+
const processLeases = await tx.execute(sql8`
|
|
23622
24064
|
select id from sandbox_leases
|
|
23623
24065
|
where id = ${admission.lease_id}
|
|
23624
24066
|
for update
|
|
@@ -23630,7 +24072,7 @@ async function retainWorkspaceMutationProcess(db, input) {
|
|
|
23630
24072
|
);
|
|
23631
24073
|
}
|
|
23632
24074
|
const processHolderId = `process:${input.processId}`;
|
|
23633
|
-
await tx.execute(
|
|
24075
|
+
await tx.execute(sql8`
|
|
23634
24076
|
insert into sandbox_lease_holders
|
|
23635
24077
|
(account_id, workspace_id, lease_id, kind, holder_id, subject_id,
|
|
23636
24078
|
last_heartbeat_at)
|
|
@@ -23663,11 +24105,11 @@ async function retainWorkspaceMutationProcess(db, input) {
|
|
|
23663
24105
|
providerSessionId: input.providerSessionId,
|
|
23664
24106
|
state: "active"
|
|
23665
24107
|
}).returning();
|
|
23666
|
-
await tx.execute(
|
|
24108
|
+
await tx.execute(sql8`
|
|
23667
24109
|
update sandbox_workspace_mutation_admissions set provider_outcome = 'retained'
|
|
23668
24110
|
where id = ${admission.id} and provider_outcome is null and settled_at is null
|
|
23669
24111
|
`);
|
|
23670
|
-
await tx.execute(
|
|
24112
|
+
await tx.execute(sql8`
|
|
23671
24113
|
update sandbox_leases as lease set
|
|
23672
24114
|
refcount = counts.total,
|
|
23673
24115
|
turn_holders = counts.turns,
|
|
@@ -23726,7 +24168,7 @@ async function claimTerminalRetainedProcesses(db, input) {
|
|
|
23726
24168
|
}
|
|
23727
24169
|
const rows = await rawRows(
|
|
23728
24170
|
db,
|
|
23729
|
-
|
|
24171
|
+
sql8`
|
|
23730
24172
|
select account_id, workspace_id, session_id, process_id, claim_id,
|
|
23731
24173
|
owner_state, owner_attempt_outcome
|
|
23732
24174
|
from opengeni_private.claim_terminal_retained_processes(
|
|
@@ -23938,7 +24380,7 @@ async function deferRetainedProcessReconciliation(db, input) {
|
|
|
23938
24380
|
async function countActiveRetainedProcessesByOwnerState(db) {
|
|
23939
24381
|
const rows = await rawRows(
|
|
23940
24382
|
db,
|
|
23941
|
-
|
|
24383
|
+
sql8`
|
|
23942
24384
|
select owner_state, active_count, terminal_owner_count
|
|
23943
24385
|
from opengeni_private.count_active_retained_processes_by_owner_state()
|
|
23944
24386
|
`
|
|
@@ -23952,7 +24394,7 @@ async function countActiveRetainedProcessesByOwnerState(db) {
|
|
|
23952
24394
|
async function countExpiredDrainingSandboxLeases(db) {
|
|
23953
24395
|
const rows = await rawRows(
|
|
23954
24396
|
db,
|
|
23955
|
-
|
|
24397
|
+
sql8`
|
|
23956
24398
|
select backend, age_bucket, count
|
|
23957
24399
|
from opengeni_private.count_expired_draining_sandbox_leases()
|
|
23958
24400
|
`
|
|
@@ -24026,7 +24468,7 @@ async function settleRetainedProcess(db, input) {
|
|
|
24026
24468
|
"Retained process settlement conflicts with checkpointed provider proof"
|
|
24027
24469
|
);
|
|
24028
24470
|
}
|
|
24029
|
-
const admissions = await tx.execute(
|
|
24471
|
+
const admissions = await tx.execute(sql8`
|
|
24030
24472
|
select * from sandbox_workspace_mutation_admissions
|
|
24031
24473
|
where id = ${process.parentAdmissionId}
|
|
24032
24474
|
and account_id = ${input.accountId}
|
|
@@ -24050,7 +24492,7 @@ async function settleRetainedProcess(db, input) {
|
|
|
24050
24492
|
"Retained process parent admission is not open"
|
|
24051
24493
|
);
|
|
24052
24494
|
}
|
|
24053
|
-
const leases = await tx.execute(
|
|
24495
|
+
const leases = await tx.execute(sql8`
|
|
24054
24496
|
select * from sandbox_leases
|
|
24055
24497
|
where id = ${process.leaseId}
|
|
24056
24498
|
and account_id = ${input.accountId}
|
|
@@ -24098,39 +24540,39 @@ async function settleRetainedProcess(db, input) {
|
|
|
24098
24540
|
"Retained process changed while its row was locked"
|
|
24099
24541
|
);
|
|
24100
24542
|
}
|
|
24101
|
-
await tx.execute(
|
|
24543
|
+
await tx.execute(sql8`
|
|
24102
24544
|
update sandbox_workspace_mutation_admissions set
|
|
24103
24545
|
provider_outcome = ${input.outcome === "exited" ? "resolved" : "rejected"},
|
|
24104
24546
|
settled_at = now()
|
|
24105
24547
|
where id = ${process.parentAdmissionId}
|
|
24106
24548
|
and provider_outcome = 'retained' and settled_at is null
|
|
24107
24549
|
`);
|
|
24108
|
-
await tx.execute(
|
|
24550
|
+
await tx.execute(sql8`
|
|
24109
24551
|
delete from sandbox_lease_holders
|
|
24110
24552
|
where lease_id = ${process.leaseId}
|
|
24111
24553
|
and account_id = ${input.accountId}
|
|
24112
24554
|
and workspace_id = ${input.workspaceId}
|
|
24113
24555
|
and kind = 'process' and holder_id = ${process.holderId}
|
|
24114
24556
|
`);
|
|
24115
|
-
const [counts] = await tx.execute(
|
|
24557
|
+
const [counts] = await tx.execute(sql8`
|
|
24116
24558
|
select count(*)::int as total,
|
|
24117
24559
|
count(*) filter (where kind = 'turn')::int as turns,
|
|
24118
24560
|
count(*) filter (where kind = 'viewer')::int as viewers
|
|
24119
24561
|
from sandbox_lease_holders where lease_id = ${process.leaseId}
|
|
24120
24562
|
`);
|
|
24121
24563
|
const enterDraining = processOwnsCurrentLease && (counts?.total ?? 0) === 0;
|
|
24122
|
-
await tx.execute(
|
|
24564
|
+
await tx.execute(sql8`
|
|
24123
24565
|
update sandbox_leases set
|
|
24124
24566
|
refcount = ${counts?.total ?? 0},
|
|
24125
24567
|
turn_holders = ${counts?.turns ?? 0},
|
|
24126
24568
|
viewer_holders = ${counts?.viewers ?? 0},
|
|
24127
|
-
${enterDraining ?
|
|
24569
|
+
${enterDraining ? sql8`liveness = case when liveness = 'warm' then 'draining' else liveness end,
|
|
24128
24570
|
expires_at = case when liveness = 'warm'
|
|
24129
24571
|
then case when rotation_requested_at is not null
|
|
24130
24572
|
then now()
|
|
24131
24573
|
else now() + (${String(input.idleGraceMs)} || ' milliseconds')::interval
|
|
24132
24574
|
end
|
|
24133
|
-
else expires_at end,` :
|
|
24575
|
+
else expires_at end,` : sql8``}
|
|
24134
24576
|
updated_at = now()
|
|
24135
24577
|
where id = ${process.leaseId}
|
|
24136
24578
|
and sandbox_group_id = ${process.sandboxGroupId}
|
|
@@ -24144,14 +24586,14 @@ async function readWorkspaceArchiveCapturePreflight(db, input) {
|
|
|
24144
24586
|
db,
|
|
24145
24587
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
24146
24588
|
async (scopedDb) => {
|
|
24147
|
-
const rows = await scopedDb.execute(
|
|
24589
|
+
const rows = await scopedDb.execute(sql8`
|
|
24148
24590
|
select lease.* from sandbox_leases as lease
|
|
24149
24591
|
where lease.workspace_id = ${input.workspaceId}
|
|
24150
24592
|
and lease.sandbox_group_id = ${input.sandboxGroupId}
|
|
24151
24593
|
and lease.liveness = ${input.liveness}
|
|
24152
24594
|
and lease.lease_epoch = ${input.expectedEpoch}
|
|
24153
24595
|
and lease.instance_id = ${input.expectedInstanceId}
|
|
24154
|
-
${input.liveness === "draining" ?
|
|
24596
|
+
${input.liveness === "draining" ? sql8`and lease.refcount = 0` : sql8``}
|
|
24155
24597
|
and not exists (
|
|
24156
24598
|
select 1
|
|
24157
24599
|
from sandbox_workspace_mutation_admissions as admission
|
|
@@ -24241,7 +24683,7 @@ async function claimWorkspaceArchiveCapture(db, input) {
|
|
|
24241
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"));
|
|
24242
24684
|
if (!attemptMayCapture) return { status: "attempt_fenced" };
|
|
24243
24685
|
}
|
|
24244
|
-
const rows = await scopedDb.execute(
|
|
24686
|
+
const rows = await scopedDb.execute(sql8`
|
|
24245
24687
|
select lease.*
|
|
24246
24688
|
from sandbox_leases lease
|
|
24247
24689
|
where lease.account_id = ${input.accountId}
|
|
@@ -24256,7 +24698,7 @@ async function claimWorkspaceArchiveCapture(db, input) {
|
|
|
24256
24698
|
if (row.archive_capture_id !== null) {
|
|
24257
24699
|
return { status: "capture_in_progress" };
|
|
24258
24700
|
}
|
|
24259
|
-
const holderCounts = input.warmAttempt ? await scopedDb.execute(
|
|
24701
|
+
const holderCounts = input.warmAttempt ? await scopedDb.execute(sql8`
|
|
24260
24702
|
select
|
|
24261
24703
|
count(*)::integer as total,
|
|
24262
24704
|
count(*) filter (
|
|
@@ -24265,7 +24707,7 @@ async function claimWorkspaceArchiveCapture(db, input) {
|
|
|
24265
24707
|
)::integer as exact
|
|
24266
24708
|
from sandbox_lease_holders
|
|
24267
24709
|
where lease_id = ${row.id}
|
|
24268
|
-
`) : await scopedDb.execute(
|
|
24710
|
+
`) : await scopedDb.execute(sql8`
|
|
24269
24711
|
select count(*)::integer as total, 0::integer as exact
|
|
24270
24712
|
from sandbox_lease_holders
|
|
24271
24713
|
where lease_id = ${row.id}
|
|
@@ -24277,7 +24719,7 @@ async function claimWorkspaceArchiveCapture(db, input) {
|
|
|
24277
24719
|
if ((holderCounts[0]?.total ?? 0) !== expectedHolderCount) {
|
|
24278
24720
|
return { status: "holder_in_progress" };
|
|
24279
24721
|
}
|
|
24280
|
-
const unsettled = await scopedDb.execute(
|
|
24722
|
+
const unsettled = await scopedDb.execute(sql8`
|
|
24281
24723
|
select exists (
|
|
24282
24724
|
select 1
|
|
24283
24725
|
from sandbox_workspace_mutation_admissions admission
|
|
@@ -24311,7 +24753,7 @@ async function claimWorkspaceArchiveCapture(db, input) {
|
|
|
24311
24753
|
}
|
|
24312
24754
|
const startedAt = /* @__PURE__ */ new Date();
|
|
24313
24755
|
const deadlineAt = new Date(startedAt.getTime() + input.captureTimeoutMs);
|
|
24314
|
-
const claimed = await scopedDb.execute(
|
|
24756
|
+
const claimed = await scopedDb.execute(sql8`
|
|
24315
24757
|
update sandbox_leases set
|
|
24316
24758
|
archive_capture_id = ${input.captureId}::uuid,
|
|
24317
24759
|
archive_capture_generation = workspace_generation,
|
|
@@ -24352,7 +24794,7 @@ async function releaseWorkspaceArchiveCapture(db, input) {
|
|
|
24352
24794
|
db,
|
|
24353
24795
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
24354
24796
|
async (scopedDb) => {
|
|
24355
|
-
const rows = await scopedDb.execute(
|
|
24797
|
+
const rows = await scopedDb.execute(sql8`
|
|
24356
24798
|
update sandbox_leases set
|
|
24357
24799
|
archive_capture_id = null,
|
|
24358
24800
|
archive_capture_generation = null,
|
|
@@ -24380,7 +24822,7 @@ async function replaceExpiredWorkspaceArchiveCapture(db, input) {
|
|
|
24380
24822
|
db,
|
|
24381
24823
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
24382
24824
|
async (scopedDb) => {
|
|
24383
|
-
const rows = await scopedDb.execute(
|
|
24825
|
+
const rows = await scopedDb.execute(sql8`
|
|
24384
24826
|
update sandbox_leases as lease set
|
|
24385
24827
|
archive_capture_id = ${input.captureId}::uuid,
|
|
24386
24828
|
archive_capture_generation = lease.workspace_generation,
|
|
@@ -24482,7 +24924,7 @@ async function registerSandboxCheckpointArtifact(db, input) {
|
|
|
24482
24924
|
db,
|
|
24483
24925
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
24484
24926
|
async (scopedDb) => {
|
|
24485
|
-
const inserted = await scopedDb.execute(
|
|
24927
|
+
const inserted = await scopedDb.execute(sql8`
|
|
24486
24928
|
insert into sandbox_checkpoint_artifacts (
|
|
24487
24929
|
account_id, workspace_id, sandbox_group_id, source_lease_id,
|
|
24488
24930
|
source_lease_epoch, source_instance_id, source_workspace_generation,
|
|
@@ -24502,7 +24944,7 @@ async function registerSandboxCheckpointArtifact(db, input) {
|
|
|
24502
24944
|
do nothing
|
|
24503
24945
|
returning id, state, object_id
|
|
24504
24946
|
`);
|
|
24505
|
-
const row = inserted[0] ?? (await scopedDb.execute(
|
|
24947
|
+
const row = inserted[0] ?? (await scopedDb.execute(sql8`
|
|
24506
24948
|
select id, state, object_id, account_id, workspace_id,
|
|
24507
24949
|
sandbox_group_id, source_lease_id, source_lease_epoch,
|
|
24508
24950
|
source_instance_id, source_workspace_generation, provenance,
|
|
@@ -24515,7 +24957,7 @@ async function registerSandboxCheckpointArtifact(db, input) {
|
|
|
24515
24957
|
limit 1
|
|
24516
24958
|
for update
|
|
24517
24959
|
`))[0];
|
|
24518
|
-
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)) {
|
|
24519
24961
|
throw new SandboxCheckpointArtifactRegistrationConflictError(
|
|
24520
24962
|
"Modal checkpoint object identity collision"
|
|
24521
24963
|
);
|
|
@@ -24542,7 +24984,7 @@ async function markSandboxCheckpointArtifactDeletePending(db, input) {
|
|
|
24542
24984
|
db,
|
|
24543
24985
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
24544
24986
|
async (scopedDb) => {
|
|
24545
|
-
const rows = await scopedDb.execute(
|
|
24987
|
+
const rows = await scopedDb.execute(sql8`
|
|
24546
24988
|
update sandbox_checkpoint_artifacts artifact set
|
|
24547
24989
|
state = 'delete_pending',
|
|
24548
24990
|
delete_after = now(),
|
|
@@ -24564,7 +25006,7 @@ async function markSandboxCheckpointArtifactDeletePending(db, input) {
|
|
|
24564
25006
|
async function claimSandboxCheckpointArtifactsForGc(db, input) {
|
|
24565
25007
|
const rows = await rawRows(
|
|
24566
25008
|
db,
|
|
24567
|
-
|
|
25009
|
+
sql8`select * from opengeni_private.claim_sandbox_checkpoint_artifacts(
|
|
24568
25010
|
${input.claimId}::uuid, ${input.limit}, ${input.claimTtlMs}
|
|
24569
25011
|
)`
|
|
24570
25012
|
);
|
|
@@ -24581,7 +25023,7 @@ async function claimSandboxCheckpointArtifactsForGc(db, input) {
|
|
|
24581
25023
|
async function settleSandboxCheckpointArtifactGc(db, input) {
|
|
24582
25024
|
const rows = await rawRows(
|
|
24583
25025
|
db,
|
|
24584
|
-
|
|
25026
|
+
sql8`select opengeni_private.settle_sandbox_checkpoint_artifact(
|
|
24585
25027
|
${input.artifactId}::uuid, ${input.claimId}::uuid, ${input.deleted},
|
|
24586
25028
|
${input.error?.slice(0, 4e3) ?? null}, ${input.retryAfterMs}
|
|
24587
25029
|
) as settled`
|
|
@@ -24591,7 +25033,7 @@ async function settleSandboxCheckpointArtifactGc(db, input) {
|
|
|
24591
25033
|
async function pruneDeletedSandboxCheckpointArtifacts(db, retentionMs, limit) {
|
|
24592
25034
|
const rows = await rawRows(
|
|
24593
25035
|
db,
|
|
24594
|
-
|
|
25036
|
+
sql8`select opengeni_private.prune_deleted_sandbox_checkpoint_artifacts(
|
|
24595
25037
|
${retentionMs}, ${limit}
|
|
24596
25038
|
) as pruned`
|
|
24597
25039
|
);
|
|
@@ -24600,7 +25042,7 @@ async function pruneDeletedSandboxCheckpointArtifacts(db, retentionMs, limit) {
|
|
|
24600
25042
|
async function requestDueSandboxRotationsGlobal(db, leadMs, limit) {
|
|
24601
25043
|
const rows = await rawRows(
|
|
24602
25044
|
db,
|
|
24603
|
-
|
|
25045
|
+
sql8`select opengeni_private.request_due_sandbox_rotations(
|
|
24604
25046
|
${leadMs}, ${limit}
|
|
24605
25047
|
) as requested`
|
|
24606
25048
|
);
|
|
@@ -24621,7 +25063,7 @@ async function countSandboxCheckpointArtifactsByState(db) {
|
|
|
24621
25063
|
);
|
|
24622
25064
|
const rows = await rawRows(
|
|
24623
25065
|
db,
|
|
24624
|
-
|
|
25066
|
+
sql8`select state, count
|
|
24625
25067
|
from opengeni_private.sandbox_checkpoint_artifact_inventory()`
|
|
24626
25068
|
);
|
|
24627
25069
|
for (const row of rows) {
|
|
@@ -24632,7 +25074,7 @@ async function countSandboxCheckpointArtifactsByState(db) {
|
|
|
24632
25074
|
return counts;
|
|
24633
25075
|
}
|
|
24634
25076
|
async function readSandboxRotationBacklog(db) {
|
|
24635
|
-
const rows = await rawRows(db,
|
|
25077
|
+
const rows = await rawRows(db, sql8`select * from opengeni_private.sandbox_rotation_backlog()`);
|
|
24636
25078
|
const row = rows[0];
|
|
24637
25079
|
return {
|
|
24638
25080
|
requested: Number(row?.requested ?? 0),
|
|
@@ -24643,7 +25085,7 @@ async function readSandboxRotationBacklog(db) {
|
|
|
24643
25085
|
};
|
|
24644
25086
|
}
|
|
24645
25087
|
async function listLegacyModalCheckpointSlots(db, limit = 100) {
|
|
24646
|
-
const rows = await rawRows(db,
|
|
25088
|
+
const rows = await rawRows(db, sql8`select * from opengeni_private.list_legacy_modal_checkpoint_slots(${limit})`);
|
|
24647
25089
|
return rows.flatMap((row) => {
|
|
24648
25090
|
const descriptor = parseArchiveRevision(row.descriptor);
|
|
24649
25091
|
return descriptor?.version === 2 ? [
|
|
@@ -24675,7 +25117,7 @@ async function adoptLegacyModalCheckpointArtifact(db, input) {
|
|
|
24675
25117
|
db,
|
|
24676
25118
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
24677
25119
|
async (scopedDb) => {
|
|
24678
|
-
const leaseRows = await scopedDb.execute(
|
|
25120
|
+
const leaseRows = await scopedDb.execute(sql8`
|
|
24679
25121
|
select lease.id, lease.current_checkpoint_artifact_id,
|
|
24680
25122
|
lease.previous_checkpoint_artifact_id
|
|
24681
25123
|
from sandbox_leases lease
|
|
@@ -24687,16 +25129,16 @@ async function adoptLegacyModalCheckpointArtifact(db, input) {
|
|
|
24687
25129
|
and lease.workspace_generation = ${input.workspaceGeneration}
|
|
24688
25130
|
and lease.backend = 'modal'
|
|
24689
25131
|
and lease.liveness in ('warming', 'warm', 'draining')
|
|
24690
|
-
${input.rematerializationId ?
|
|
25132
|
+
${input.rematerializationId ? sql8`and lease.liveness = 'warming'
|
|
24691
25133
|
and lease.resume_state #>> '{opengeniRecovery,restore,rematerializationId}' =
|
|
24692
25134
|
${input.rematerializationId}
|
|
24693
25135
|
and lease.resume_state #>> '{opengeniRecovery,restore,status}' in
|
|
24694
|
-
('restoring', 'verifying')` :
|
|
24695
|
-
and ${input.slot === "current" ?
|
|
25136
|
+
('restoring', 'verifying')` : sql8``}
|
|
25137
|
+
and ${input.slot === "current" ? sql8`lease.archive_generation = lease.workspace_generation
|
|
24696
25138
|
and lease.resume_state #>> '{sessionState,workspaceArchive}' =
|
|
24697
25139
|
${input.archiveBase64}
|
|
24698
25140
|
and lease.resume_state #> '{sessionState,workspaceArchiveMeta}' =
|
|
24699
|
-
${JSON.stringify(input.descriptor)}::jsonb` :
|
|
25141
|
+
${JSON.stringify(input.descriptor)}::jsonb` : sql8`lease.resume_state #>> '{sessionState,workspaceArchivePrev}' =
|
|
24700
25142
|
${input.archiveBase64}
|
|
24701
25143
|
and lease.resume_state #> '{sessionState,workspaceArchivePrevMeta}' =
|
|
24702
25144
|
${JSON.stringify(input.descriptor)}::jsonb`}
|
|
@@ -24706,7 +25148,7 @@ async function adoptLegacyModalCheckpointArtifact(db, input) {
|
|
|
24706
25148
|
if (!lease) return false;
|
|
24707
25149
|
const existingReference = input.slot === "current" ? lease.current_checkpoint_artifact_id : lease.previous_checkpoint_artifact_id;
|
|
24708
25150
|
if (existingReference !== null) {
|
|
24709
|
-
const exact = await scopedDb.execute(
|
|
25151
|
+
const exact = await scopedDb.execute(sql8`
|
|
24710
25152
|
select artifact.id
|
|
24711
25153
|
from sandbox_checkpoint_artifacts artifact
|
|
24712
25154
|
where artifact.id = ${existingReference}::uuid
|
|
@@ -24730,7 +25172,7 @@ async function adoptLegacyModalCheckpointArtifact(db, input) {
|
|
|
24730
25172
|
`);
|
|
24731
25173
|
return exact.length === 1;
|
|
24732
25174
|
}
|
|
24733
|
-
const inserted = await scopedDb.execute(
|
|
25175
|
+
const inserted = await scopedDb.execute(sql8`
|
|
24734
25176
|
insert into sandbox_checkpoint_artifacts (
|
|
24735
25177
|
account_id, workspace_id, sandbox_group_id, source_lease_id,
|
|
24736
25178
|
source_lease_epoch, source_instance_id, source_workspace_generation,
|
|
@@ -24750,7 +25192,7 @@ async function adoptLegacyModalCheckpointArtifact(db, input) {
|
|
|
24750
25192
|
do nothing
|
|
24751
25193
|
returning id, state
|
|
24752
25194
|
`);
|
|
24753
|
-
const artifact = inserted[0] ?? (await scopedDb.execute(
|
|
25195
|
+
const artifact = inserted[0] ?? (await scopedDb.execute(sql8`
|
|
24754
25196
|
select id, state, account_id, workspace_id, sandbox_group_id,
|
|
24755
25197
|
source_lease_id, source_lease_epoch, source_instance_id,
|
|
24756
25198
|
source_workspace_generation, provenance, archive_base64,
|
|
@@ -24762,7 +25204,7 @@ async function adoptLegacyModalCheckpointArtifact(db, input) {
|
|
|
24762
25204
|
limit 1
|
|
24763
25205
|
for update
|
|
24764
25206
|
`))[0];
|
|
24765
|
-
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);
|
|
24766
25208
|
if (!artifact || !exactExisting || artifact.state === "deleted") {
|
|
24767
25209
|
throw new SandboxCheckpointArtifactRegistrationConflictError(
|
|
24768
25210
|
"Modal checkpoint object identity collision"
|
|
@@ -24773,7 +25215,7 @@ async function adoptLegacyModalCheckpointArtifact(db, input) {
|
|
|
24773
25215
|
"Legacy Modal checkpoint is already owned by another archive slot"
|
|
24774
25216
|
);
|
|
24775
25217
|
}
|
|
24776
|
-
const published = await scopedDb.execute(
|
|
25218
|
+
const published = await scopedDb.execute(sql8`
|
|
24777
25219
|
update sandbox_checkpoint_artifacts set
|
|
24778
25220
|
state = ${input.slot}, published_at = coalesce(published_at, now()),
|
|
24779
25221
|
delete_after = null, last_delete_error = null, updated_at = now()
|
|
@@ -24783,12 +25225,12 @@ async function adoptLegacyModalCheckpointArtifact(db, input) {
|
|
|
24783
25225
|
if (published.length !== 1) {
|
|
24784
25226
|
throw new Error("Legacy Modal checkpoint adoption lost its locked provider object");
|
|
24785
25227
|
}
|
|
24786
|
-
const attached = await scopedDb.execute(
|
|
25228
|
+
const attached = await scopedDb.execute(sql8`
|
|
24787
25229
|
update sandbox_leases lease set
|
|
24788
|
-
${input.slot === "current" ?
|
|
25230
|
+
${input.slot === "current" ? sql8`current_checkpoint_artifact_id = ${artifact.id}::uuid` : sql8`previous_checkpoint_artifact_id = ${artifact.id}::uuid`},
|
|
24789
25231
|
updated_at = now()
|
|
24790
25232
|
where lease.id = ${input.leaseId}::uuid
|
|
24791
|
-
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`}
|
|
24792
25234
|
returning lease.id
|
|
24793
25235
|
`);
|
|
24794
25236
|
if (attached.length !== 1) {
|
|
@@ -24810,7 +25252,7 @@ async function persistDrainSnapshot(db, input) {
|
|
|
24810
25252
|
db,
|
|
24811
25253
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
24812
25254
|
async (scopedDb) => {
|
|
24813
|
-
const guard = await scopedDb.execute(
|
|
25255
|
+
const guard = await scopedDb.execute(sql8`
|
|
24814
25256
|
select
|
|
24815
25257
|
resume_state #>> '{sessionState,workspaceArchive}' as prior_archive,
|
|
24816
25258
|
resume_state #>> '{sessionState,workspaceArchivePrev}' as prior_archive_prev,
|
|
@@ -24858,7 +25300,7 @@ async function persistDrainSnapshot(db, input) {
|
|
|
24858
25300
|
const priorArchive = guard[0].prior_archive ?? null;
|
|
24859
25301
|
const priorArchivePrev = guard[0].prior_archive_prev ?? null;
|
|
24860
25302
|
if (input.workspaceArchive === null) {
|
|
24861
|
-
await scopedDb.execute(
|
|
25303
|
+
await scopedDb.execute(sql8`
|
|
24862
25304
|
update sandbox_leases set
|
|
24863
25305
|
archive_capture_id = null,
|
|
24864
25306
|
archive_capture_generation = null,
|
|
@@ -24929,7 +25371,7 @@ function rotateWorkspaceArchives(input) {
|
|
|
24929
25371
|
};
|
|
24930
25372
|
}
|
|
24931
25373
|
async function foldWorkspaceArchiveOntoLease(scopedDb, input) {
|
|
24932
|
-
const livenessGuard = input.livenessGuard === "draining" ?
|
|
25374
|
+
const livenessGuard = input.livenessGuard === "draining" ? sql8`lease.liveness = 'draining' and lease.refcount = 0` : sql8`lease.liveness = 'warm'`;
|
|
24933
25375
|
const archiveAtIso = input.workspaceArchiveMeta?.capturedAt ?? input.archiveAtIso ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
24934
25376
|
const base = input.resumeState && typeof input.resumeState === "object" ? input.resumeState : {};
|
|
24935
25377
|
const currentSession = base.sessionState && typeof base.sessionState === "object" ? base.sessionState : {};
|
|
@@ -24960,7 +25402,7 @@ async function foldWorkspaceArchiveOntoLease(scopedDb, input) {
|
|
|
24960
25402
|
archive: archiveProjectionFromResumeState(folded)
|
|
24961
25403
|
};
|
|
24962
25404
|
const foldedJson = JSON.stringify(folded);
|
|
24963
|
-
const rows = await scopedDb.execute(
|
|
25405
|
+
const rows = await scopedDb.execute(sql8`
|
|
24964
25406
|
update sandbox_leases as lease set
|
|
24965
25407
|
resume_state = ${foldedJson}::jsonb,
|
|
24966
25408
|
archive_generation = ${input.expectedWorkspaceGeneration},
|
|
@@ -25022,7 +25464,7 @@ async function foldWorkspaceArchiveOntoLease(scopedDb, input) {
|
|
|
25022
25464
|
`);
|
|
25023
25465
|
if (rows.length === 0) return false;
|
|
25024
25466
|
if (input.checkpointArtifactId) {
|
|
25025
|
-
await scopedDb.execute(
|
|
25467
|
+
await scopedDb.execute(sql8`
|
|
25026
25468
|
update sandbox_checkpoint_artifacts set
|
|
25027
25469
|
state = 'current', published_at = coalesce(published_at, now()),
|
|
25028
25470
|
delete_after = null, last_delete_error = null, updated_at = now()
|
|
@@ -25030,7 +25472,7 @@ async function foldWorkspaceArchiveOntoLease(scopedDb, input) {
|
|
|
25030
25472
|
`);
|
|
25031
25473
|
}
|
|
25032
25474
|
if (input.previousCheckpointArtifactId && input.previousCheckpointArtifactId !== input.checkpointArtifactId) {
|
|
25033
|
-
await scopedDb.execute(
|
|
25475
|
+
await scopedDb.execute(sql8`
|
|
25034
25476
|
update sandbox_checkpoint_artifacts set
|
|
25035
25477
|
state = 'previous', delete_after = null, last_delete_error = null,
|
|
25036
25478
|
updated_at = now()
|
|
@@ -25045,12 +25487,12 @@ async function foldWorkspaceArchiveOntoLease(scopedDb, input) {
|
|
|
25045
25487
|
(id) => id !== null && id !== input.checkpointArtifactId && id !== input.previousCheckpointArtifactId
|
|
25046
25488
|
);
|
|
25047
25489
|
if (evictedArtifactIds.length > 0) {
|
|
25048
|
-
await scopedDb.execute(
|
|
25490
|
+
await scopedDb.execute(sql8`
|
|
25049
25491
|
update sandbox_checkpoint_artifacts set
|
|
25050
25492
|
state = 'delete_pending', delete_after = now(), updated_at = now()
|
|
25051
|
-
where id in (${
|
|
25052
|
-
evictedArtifactIds.map((id) =>
|
|
25053
|
-
|
|
25493
|
+
where id in (${sql8.join(
|
|
25494
|
+
evictedArtifactIds.map((id) => sql8`${id}::uuid`),
|
|
25495
|
+
sql8`, `
|
|
25054
25496
|
)})
|
|
25055
25497
|
and state in ('current', 'previous', 'candidate', 'delete_failed')
|
|
25056
25498
|
`);
|
|
@@ -25106,7 +25548,7 @@ async function persistWarmSnapshot(db, input) {
|
|
|
25106
25548
|
archiveRevision: null
|
|
25107
25549
|
};
|
|
25108
25550
|
}
|
|
25109
|
-
const guard = await scopedDb.execute(
|
|
25551
|
+
const guard = await scopedDb.execute(sql8`
|
|
25110
25552
|
select
|
|
25111
25553
|
resume_state #>> '{sessionState,workspaceArchive}' as prior_archive,
|
|
25112
25554
|
resume_state #>> '{sessionState,workspaceArchivePrev}' as prior_archive_prev,
|
|
@@ -25221,7 +25663,7 @@ async function getMaterializedSandboxFileResources(db, input) {
|
|
|
25221
25663
|
db,
|
|
25222
25664
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
25223
25665
|
async (scopedDb) => {
|
|
25224
|
-
const rows = await scopedDb.execute(
|
|
25666
|
+
const rows = await scopedDb.execute(sql8`
|
|
25225
25667
|
select coalesce(
|
|
25226
25668
|
jsonb_path_query_array(
|
|
25227
25669
|
resume_state,
|
|
@@ -25251,7 +25693,7 @@ async function markSandboxFileResourcesMaterialized(db, input) {
|
|
|
25251
25693
|
db,
|
|
25252
25694
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
25253
25695
|
async (scopedDb) => {
|
|
25254
|
-
const rows = await scopedDb.execute(
|
|
25696
|
+
const rows = await scopedDb.execute(sql8`
|
|
25255
25697
|
update sandbox_leases set
|
|
25256
25698
|
resume_state = jsonb_set(
|
|
25257
25699
|
case when jsonb_typeof(resume_state) = 'object' then resume_state else '{}'::jsonb end,
|
|
@@ -25295,7 +25737,7 @@ async function markSandboxFileResourcesMaterialized(db, input) {
|
|
|
25295
25737
|
}
|
|
25296
25738
|
);
|
|
25297
25739
|
}
|
|
25298
|
-
var WORKSPACE_CAPTURE_COLUMNS =
|
|
25740
|
+
var WORKSPACE_CAPTURE_COLUMNS = sql8`
|
|
25299
25741
|
id, session_id, turn_id, revision, lease_epoch, state,
|
|
25300
25742
|
manifest_key, tree_index_key, blob_keys, size_bytes, stats, captured_at
|
|
25301
25743
|
`;
|
|
@@ -25345,7 +25787,7 @@ async function commitWorkspaceCaptureRevision(db, input) {
|
|
|
25345
25787
|
return null;
|
|
25346
25788
|
}
|
|
25347
25789
|
const capturedAt = input.capturedAt ?? /* @__PURE__ */ new Date();
|
|
25348
|
-
const rows = await tx.execute(
|
|
25790
|
+
const rows = await tx.execute(sql8`
|
|
25349
25791
|
insert into workspace_captures
|
|
25350
25792
|
(account_id, workspace_id, session_id, turn_id, revision, lease_epoch, state,
|
|
25351
25793
|
manifest_key, tree_index_key, blob_keys, size_bytes, stats, captured_at)
|
|
@@ -25427,7 +25869,7 @@ async function insertFailedWorkspaceCapture(db, input) {
|
|
|
25427
25869
|
}
|
|
25428
25870
|
async function latestWorkspaceCapture(db, workspaceId, sessionId) {
|
|
25429
25871
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
25430
|
-
const rows = await scopedDb.execute(
|
|
25872
|
+
const rows = await scopedDb.execute(sql8`
|
|
25431
25873
|
select ${WORKSPACE_CAPTURE_COLUMNS} from workspace_captures
|
|
25432
25874
|
where session_id = ${sessionId}
|
|
25433
25875
|
order by revision desc
|
|
@@ -25438,7 +25880,7 @@ async function latestWorkspaceCapture(db, workspaceId, sessionId) {
|
|
|
25438
25880
|
}
|
|
25439
25881
|
async function sessionLatestWorkspaceCapture(db, workspaceId, sessionId) {
|
|
25440
25882
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
25441
|
-
const rows = await scopedDb.execute(
|
|
25883
|
+
const rows = await scopedDb.execute(sql8`
|
|
25442
25884
|
select
|
|
25443
25885
|
sessions.id as found_session_id,
|
|
25444
25886
|
capture.id as capture_id,
|
|
@@ -25488,7 +25930,7 @@ async function sessionLatestWorkspaceCapture(db, workspaceId, sessionId) {
|
|
|
25488
25930
|
}
|
|
25489
25931
|
async function workspaceCaptureAtRevision(db, workspaceId, sessionId, revision) {
|
|
25490
25932
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
25491
|
-
const rows = await scopedDb.execute(
|
|
25933
|
+
const rows = await scopedDb.execute(sql8`
|
|
25492
25934
|
select ${WORKSPACE_CAPTURE_COLUMNS} from workspace_captures
|
|
25493
25935
|
where session_id = ${sessionId} and revision = ${revision}
|
|
25494
25936
|
limit 1
|
|
@@ -25518,7 +25960,7 @@ function computeWorkspaceCaptureGcPlan(rows, keepN) {
|
|
|
25518
25960
|
}
|
|
25519
25961
|
async function planWorkspaceCaptureGc(db, input) {
|
|
25520
25962
|
return await withWorkspaceRls(db, input.workspaceId, async (scopedDb) => {
|
|
25521
|
-
const rows = await scopedDb.execute(
|
|
25963
|
+
const rows = await scopedDb.execute(sql8`
|
|
25522
25964
|
select id, revision, manifest_key, tree_index_key, blob_keys
|
|
25523
25965
|
from workspace_captures
|
|
25524
25966
|
where session_id = ${input.sessionId}
|
|
@@ -25540,11 +25982,11 @@ async function planWorkspaceCaptureGc(db, input) {
|
|
|
25540
25982
|
async function deleteWorkspaceCaptureRows(db, input) {
|
|
25541
25983
|
if (input.rowIds.length === 0) return 0;
|
|
25542
25984
|
return await withWorkspaceRls(db, input.workspaceId, async (scopedDb) => {
|
|
25543
|
-
const result = await scopedDb.execute(
|
|
25985
|
+
const result = await scopedDb.execute(sql8`
|
|
25544
25986
|
delete from workspace_captures
|
|
25545
|
-
where id in (${
|
|
25546
|
-
input.rowIds.map((id) =>
|
|
25547
|
-
|
|
25987
|
+
where id in (${sql8.join(
|
|
25988
|
+
input.rowIds.map((id) => sql8`${id}`),
|
|
25989
|
+
sql8`, `
|
|
25548
25990
|
)})
|
|
25549
25991
|
returning id
|
|
25550
25992
|
`);
|
|
@@ -25553,7 +25995,7 @@ async function deleteWorkspaceCaptureRows(db, input) {
|
|
|
25553
25995
|
}
|
|
25554
25996
|
async function readLease(db, workspaceId, sandboxGroupId) {
|
|
25555
25997
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
25556
|
-
const rows = await scopedDb.execute(
|
|
25998
|
+
const rows = await scopedDb.execute(sql8`
|
|
25557
25999
|
select * from sandbox_leases
|
|
25558
26000
|
where workspace_id = ${workspaceId} and sandbox_group_id = ${sandboxGroupId}
|
|
25559
26001
|
limit 1
|
|
@@ -25566,7 +26008,7 @@ async function recordLeaseDataPlaneUrl(db, input) {
|
|
|
25566
26008
|
db,
|
|
25567
26009
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
25568
26010
|
async (scopedDb) => {
|
|
25569
|
-
const rows = await scopedDb.execute(
|
|
26011
|
+
const rows = await scopedDb.execute(sql8`
|
|
25570
26012
|
update sandbox_leases set
|
|
25571
26013
|
data_plane_url = ${input.dataPlaneUrl ?? null},
|
|
25572
26014
|
updated_at = now()
|
|
@@ -25584,7 +26026,7 @@ async function recordLeaseTerminalDataPlaneUrl(db, input) {
|
|
|
25584
26026
|
db,
|
|
25585
26027
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
25586
26028
|
async (scopedDb) => {
|
|
25587
|
-
const rows = await scopedDb.execute(
|
|
26029
|
+
const rows = await scopedDb.execute(sql8`
|
|
25588
26030
|
update sandbox_leases set
|
|
25589
26031
|
terminal_data_plane_url = ${input.terminalDataPlaneUrl ?? null},
|
|
25590
26032
|
updated_at = now()
|
|
@@ -25783,7 +26225,7 @@ async function setEnrollmentDisplayState(db, input) {
|
|
|
25783
26225
|
// null-safe inequality (a plain `ne` skips NULL rows).
|
|
25784
26226
|
or3(
|
|
25785
26227
|
ne(enrollments.hasDisplay, input.hasDisplay),
|
|
25786
|
-
|
|
26228
|
+
sql8`${enrollments.desktopUnavailableReason} IS DISTINCT FROM ${input.desktopUnavailableReason}`
|
|
25787
26229
|
)
|
|
25788
26230
|
)
|
|
25789
26231
|
).returning({ id: enrollments.id });
|
|
@@ -25864,7 +26306,7 @@ async function createDeviceEnrollmentRequest(db, input) {
|
|
|
25864
26306
|
);
|
|
25865
26307
|
}
|
|
25866
26308
|
async function getDeviceEnrollmentRequestByDeviceCode(db, deviceCode) {
|
|
25867
|
-
const resolved = await db.execute(
|
|
26309
|
+
const resolved = await db.execute(sql8`
|
|
25868
26310
|
select account_id, workspace_id from opengeni_private.resolve_device_enrollment_request(${deviceCode})
|
|
25869
26311
|
`);
|
|
25870
26312
|
const ctx = resolved[0];
|
|
@@ -25893,7 +26335,7 @@ async function getPendingDeviceEnrollmentRequestByUserCode(db, workspaceId, user
|
|
|
25893
26335
|
});
|
|
25894
26336
|
}
|
|
25895
26337
|
async function getPendingDeviceEnrollmentRequestByUserCodeGlobal(db, userCode) {
|
|
25896
|
-
const resolved = await db.execute(
|
|
26338
|
+
const resolved = await db.execute(sql8`
|
|
25897
26339
|
select account_id, workspace_id from opengeni_private.resolve_pending_device_enrollment_by_user_code(${userCode})
|
|
25898
26340
|
`);
|
|
25899
26341
|
const ctx = resolved[0];
|
|
@@ -26143,11 +26585,11 @@ async function setActiveSandbox(db, input) {
|
|
|
26143
26585
|
db,
|
|
26144
26586
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
26145
26587
|
async (scopedDb) => {
|
|
26146
|
-
const rows = await scopedDb.execute(
|
|
26588
|
+
const rows = await scopedDb.execute(sql8`
|
|
26147
26589
|
update sessions set
|
|
26148
26590
|
active_sandbox_id = ${input.targetSandboxId},
|
|
26149
26591
|
active_epoch = active_epoch + 1,
|
|
26150
|
-
working_dir = ${input.workingDir === void 0 ?
|
|
26592
|
+
working_dir = ${input.workingDir === void 0 ? sql8`working_dir` : input.workingDir},
|
|
26151
26593
|
updated_at = now()
|
|
26152
26594
|
where workspace_id = ${input.workspaceId} and id = ${input.sessionId}
|
|
26153
26595
|
and active_epoch = ${input.expectedEpoch}
|
|
@@ -26311,7 +26753,7 @@ async function recordStreamAcknowledgment(db, input) {
|
|
|
26311
26753
|
db,
|
|
26312
26754
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
26313
26755
|
async (scopedDb) => {
|
|
26314
|
-
const rows = await scopedDb.execute(
|
|
26756
|
+
const rows = await scopedDb.execute(sql8`
|
|
26315
26757
|
insert into session_stream_acknowledgments
|
|
26316
26758
|
(account_id, workspace_id, sandbox_group_id, subject_id,
|
|
26317
26759
|
acknowledged_unredacted, acknowledged_shared, acknowledged_at, updated_at)
|
|
@@ -26337,7 +26779,7 @@ async function recordStreamAcknowledgment(db, input) {
|
|
|
26337
26779
|
}
|
|
26338
26780
|
async function getStreamAcknowledgment(db, input) {
|
|
26339
26781
|
return await withWorkspaceRls(db, input.workspaceId, async (scopedDb) => {
|
|
26340
|
-
const rows = await scopedDb.execute(
|
|
26782
|
+
const rows = await scopedDb.execute(sql8`
|
|
26341
26783
|
select acknowledged_unredacted, acknowledged_shared
|
|
26342
26784
|
from session_stream_acknowledgments
|
|
26343
26785
|
where workspace_id = ${input.workspaceId}
|
|
@@ -26356,7 +26798,7 @@ async function listSessionIdsInGroup(db, workspaceId, sandboxGroupId) {
|
|
|
26356
26798
|
return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {
|
|
26357
26799
|
const rows = await rawRows(
|
|
26358
26800
|
scopedDb,
|
|
26359
|
-
|
|
26801
|
+
sql8`
|
|
26360
26802
|
select id from sessions
|
|
26361
26803
|
where workspace_id = ${workspaceId} and sandbox_group_id = ${sandboxGroupId}
|
|
26362
26804
|
order by created_at asc
|
|
@@ -26387,7 +26829,7 @@ async function accrueWarmSeconds(db, input) {
|
|
|
26387
26829
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
26388
26830
|
async (scopedDb) => await scopedDb.transaction(async (txRaw) => {
|
|
26389
26831
|
const tx = txRaw;
|
|
26390
|
-
const rows = await tx.execute(
|
|
26832
|
+
const rows = await tx.execute(sql8`
|
|
26391
26833
|
select *,
|
|
26392
26834
|
case when last_meter_at is null then null
|
|
26393
26835
|
else floor(extract(epoch from (now() - last_meter_at)))::int end as meter_elapsed_s
|
|
@@ -26401,7 +26843,7 @@ async function accrueWarmSeconds(db, input) {
|
|
|
26401
26843
|
return none;
|
|
26402
26844
|
}
|
|
26403
26845
|
if (row.last_meter_at == null) {
|
|
26404
|
-
await tx.execute(
|
|
26846
|
+
await tx.execute(sql8`
|
|
26405
26847
|
update sandbox_leases set last_meter_at = now(), updated_at = now()
|
|
26406
26848
|
where id = ${row.id}
|
|
26407
26849
|
`);
|
|
@@ -26413,7 +26855,7 @@ async function accrueWarmSeconds(db, input) {
|
|
|
26413
26855
|
}
|
|
26414
26856
|
const tick = Number(row.last_meter_tick) + 1;
|
|
26415
26857
|
const costMicros = Math.round(elapsedS * Math.max(0, input.warmRateMicrosPerSecond));
|
|
26416
|
-
await tx.execute(
|
|
26858
|
+
await tx.execute(sql8`
|
|
26417
26859
|
insert into usage_events
|
|
26418
26860
|
(account_id, workspace_id, subject_id, event_type, quantity, unit,
|
|
26419
26861
|
source_resource_type, source_resource_id, idempotency_key, occurred_at)
|
|
@@ -26426,7 +26868,7 @@ async function accrueWarmSeconds(db, input) {
|
|
|
26426
26868
|
on conflict (idempotency_key) do nothing
|
|
26427
26869
|
`);
|
|
26428
26870
|
if (costMicros > 0) {
|
|
26429
|
-
await tx.execute(
|
|
26871
|
+
await tx.execute(sql8`
|
|
26430
26872
|
insert into usage_events
|
|
26431
26873
|
(account_id, workspace_id, subject_id, event_type, quantity, unit,
|
|
26432
26874
|
source_resource_type, source_resource_id, idempotency_key, occurred_at)
|
|
@@ -26439,7 +26881,7 @@ async function accrueWarmSeconds(db, input) {
|
|
|
26439
26881
|
on conflict (idempotency_key) do nothing
|
|
26440
26882
|
`);
|
|
26441
26883
|
}
|
|
26442
|
-
await tx.execute(
|
|
26884
|
+
await tx.execute(sql8`
|
|
26443
26885
|
update sandbox_leases set
|
|
26444
26886
|
last_meter_at = now(), last_meter_tick = ${tick}, updated_at = now()
|
|
26445
26887
|
where id = ${row.id}
|
|
@@ -26471,7 +26913,7 @@ async function forceDrainOverLimitViewerOnlyBoxes(db, input) {
|
|
|
26471
26913
|
} else if (input.maxWarmSecondsPerWorkspace > 0) {
|
|
26472
26914
|
const since = input.capWindowStart ?? startOfUtcMonthDefault();
|
|
26473
26915
|
const [{ total } = { total: 0 }] = await scopedDb.select({
|
|
26474
|
-
total:
|
|
26916
|
+
total: sql8`coalesce(sum(${usageEvents.quantity}), 0)`
|
|
26475
26917
|
}).from(usageEvents).where(
|
|
26476
26918
|
and10(
|
|
26477
26919
|
eq10(usageEvents.workspaceId, input.workspaceId),
|
|
@@ -26484,7 +26926,7 @@ async function forceDrainOverLimitViewerOnlyBoxes(db, input) {
|
|
|
26484
26926
|
}
|
|
26485
26927
|
}
|
|
26486
26928
|
if (!reason) {
|
|
26487
|
-
await scopedDb.execute(
|
|
26929
|
+
await scopedDb.execute(sql8`
|
|
26488
26930
|
update workspaces set
|
|
26489
26931
|
sandbox_viewer_force_drain_reason = null,
|
|
26490
26932
|
sandbox_viewer_force_drain_requested_at = null,
|
|
@@ -26494,7 +26936,7 @@ async function forceDrainOverLimitViewerOnlyBoxes(db, input) {
|
|
|
26494
26936
|
`);
|
|
26495
26937
|
return { overLimit: false, reason: null, drained: [] };
|
|
26496
26938
|
}
|
|
26497
|
-
await scopedDb.execute(
|
|
26939
|
+
await scopedDb.execute(sql8`
|
|
26498
26940
|
update workspaces set
|
|
26499
26941
|
sandbox_viewer_force_drain_reason = ${reason},
|
|
26500
26942
|
sandbox_viewer_force_drain_requested_at =
|
|
@@ -26510,14 +26952,14 @@ async function forceDrainOverLimitViewerOnlyBoxes(db, input) {
|
|
|
26510
26952
|
or sandbox_viewer_force_drain_requested_at is null
|
|
26511
26953
|
)
|
|
26512
26954
|
`);
|
|
26513
|
-
await scopedDb.execute(
|
|
26955
|
+
await scopedDb.execute(sql8`
|
|
26514
26956
|
select id from sandbox_leases
|
|
26515
26957
|
where workspace_id = ${input.workspaceId}
|
|
26516
26958
|
and liveness = 'warm' and turn_holders = 0
|
|
26517
26959
|
order by id
|
|
26518
26960
|
for update
|
|
26519
26961
|
`);
|
|
26520
|
-
await scopedDb.execute(
|
|
26962
|
+
await scopedDb.execute(sql8`
|
|
26521
26963
|
delete from sandbox_lease_holders h
|
|
26522
26964
|
where h.kind = 'viewer'
|
|
26523
26965
|
and h.lease_id in (
|
|
@@ -26528,7 +26970,7 @@ async function forceDrainOverLimitViewerOnlyBoxes(db, input) {
|
|
|
26528
26970
|
`);
|
|
26529
26971
|
const drained = await rawRows(
|
|
26530
26972
|
scopedDb,
|
|
26531
|
-
|
|
26973
|
+
sql8`
|
|
26532
26974
|
update sandbox_leases set
|
|
26533
26975
|
liveness = 'draining',
|
|
26534
26976
|
refcount = 0, turn_holders = 0, viewer_holders = 0,
|
|
@@ -26564,7 +27006,7 @@ async function saveRunState(db, input) {
|
|
|
26564
27006
|
});
|
|
26565
27007
|
if (!allowed.allowed) return false;
|
|
26566
27008
|
const [{ maxVersion } = { maxVersion: 0 }] = await tx.select({
|
|
26567
|
-
maxVersion:
|
|
27009
|
+
maxVersion: sql8`coalesce(max(${agentRunStates.stateVersion}), 0)`
|
|
26568
27010
|
}).from(agentRunStates).where(
|
|
26569
27011
|
and10(
|
|
26570
27012
|
eq10(agentRunStates.workspaceId, input.workspaceId),
|
|
@@ -26656,7 +27098,7 @@ async function getSessionGoalWithContinuation(db, workspaceId, sessionId) {
|
|
|
26656
27098
|
// accepted while a goal turn is running can have a lower normalized
|
|
26657
27099
|
// queue position; that future human turn must not hide the live goal
|
|
26658
27100
|
// attempt in this projection.
|
|
26659
|
-
|
|
27101
|
+
sql8`case when ${sessionTurns.id} = ${session.activeTurnId} then 0 else 1 end`,
|
|
26660
27102
|
asc5(sessionTurns.position),
|
|
26661
27103
|
asc5(sessionTurns.createdAt)
|
|
26662
27104
|
).limit(1);
|
|
@@ -26666,8 +27108,8 @@ async function getSessionGoalWithContinuation(db, workspaceId, sessionId) {
|
|
|
26666
27108
|
eq10(sessionSystemUpdates.sessionId, sessionId),
|
|
26667
27109
|
eq10(sessionSystemUpdates.kind, "goal_continuation"),
|
|
26668
27110
|
eq10(sessionSystemUpdates.state, "pending"),
|
|
26669
|
-
|
|
26670
|
-
|
|
27111
|
+
sql8`${sessionSystemUpdates.payload} ->> 'goalId' = ${goal.id}`,
|
|
27112
|
+
sql8`(
|
|
26671
27113
|
jsonb_typeof(${sessionSystemUpdates.payload} -> 'goalVersion') = 'number'
|
|
26672
27114
|
and ${sessionSystemUpdates.payload} ->> 'goalVersion' ~ '^[1-9][0-9]*$'
|
|
26673
27115
|
and ${sessionSystemUpdates.payload} ->> 'goalVersion' = ${goal.version.toString()}
|
|
@@ -26913,7 +27355,7 @@ async function updateSessionGoal(db, workspaceId, sessionId, input) {
|
|
|
26913
27355
|
const [row] = await scopedDb.update(sessionGoals).set({
|
|
26914
27356
|
...input.text !== void 0 ? { text: input.text } : {},
|
|
26915
27357
|
...input.successCriteria !== void 0 ? { successCriteria: input.successCriteria } : {},
|
|
26916
|
-
version:
|
|
27358
|
+
version: sql8`${sessionGoals.version} + 1`,
|
|
26917
27359
|
noProgressStreak: 0,
|
|
26918
27360
|
updatedAt: /* @__PURE__ */ new Date()
|
|
26919
27361
|
}).where(
|
|
@@ -27050,8 +27492,8 @@ async function updateSessionTitle(db, input) {
|
|
|
27050
27492
|
and10(
|
|
27051
27493
|
eq10(sessions.workspaceId, input.workspaceId),
|
|
27052
27494
|
eq10(sessions.id, input.sessionId),
|
|
27053
|
-
|
|
27054
|
-
...input.source === "agent" ? [
|
|
27495
|
+
sql8`${sessions.title} is distinct from ${input.title}`,
|
|
27496
|
+
...input.source === "agent" ? [sql8`${sessions.titleSource} is distinct from 'user'`] : []
|
|
27055
27497
|
)
|
|
27056
27498
|
).returning({ title: sessions.title });
|
|
27057
27499
|
if (row) {
|
|
@@ -27210,7 +27652,7 @@ async function turnHasFailureCodeTx(tx, workspaceId, sessionId, turnId, code) {
|
|
|
27210
27652
|
eq10(sessionEvents.sessionId, sessionId),
|
|
27211
27653
|
eq10(sessionEvents.turnId, turnId),
|
|
27212
27654
|
eq10(sessionEvents.type, "turn.failed"),
|
|
27213
|
-
|
|
27655
|
+
sql8`${sessionEvents.payload} ->> 'code' = ${code}`
|
|
27214
27656
|
)
|
|
27215
27657
|
).limit(1);
|
|
27216
27658
|
return Boolean(failure);
|
|
@@ -27220,7 +27662,7 @@ async function latestFinishedTurnHasFailureCodeTx(tx, workspaceId, sessionId, co
|
|
|
27220
27662
|
and10(
|
|
27221
27663
|
eq10(sessionTurns.workspaceId, workspaceId),
|
|
27222
27664
|
eq10(sessionTurns.sessionId, sessionId),
|
|
27223
|
-
|
|
27665
|
+
sql8`${sessionTurns.finishedAt} is not null`
|
|
27224
27666
|
)
|
|
27225
27667
|
).orderBy(desc5(sessionTurns.position), desc5(sessionTurns.createdAt)).limit(1);
|
|
27226
27668
|
return latestFinished ? await turnHasFailureCodeTx(tx, workspaceId, sessionId, latestFinished.id, code) : false;
|
|
@@ -27273,7 +27715,7 @@ async function evaluateGoalContinuation(db, input) {
|
|
|
27273
27715
|
and10(
|
|
27274
27716
|
eq10(sessionTurns.workspaceId, input.workspaceId),
|
|
27275
27717
|
eq10(sessionTurns.sessionId, input.sessionId),
|
|
27276
|
-
|
|
27718
|
+
sql8`${sessionTurns.finishedAt} is not null`
|
|
27277
27719
|
)
|
|
27278
27720
|
).orderBy(desc5(sessionTurns.position), desc5(sessionTurns.createdAt)).limit(1);
|
|
27279
27721
|
const contextCompactionFailure = latestFinished ? await turnHasFailureCodeTx(
|
|
@@ -27296,18 +27738,18 @@ async function evaluateGoalContinuation(db, input) {
|
|
|
27296
27738
|
noProgressStreak = 0;
|
|
27297
27739
|
} else if (lastFinished) {
|
|
27298
27740
|
const [{ rotatedFailures } = { rotatedFailures: 0 }] = await tx.select({
|
|
27299
|
-
rotatedFailures:
|
|
27741
|
+
rotatedFailures: sql8`count(*)::int`
|
|
27300
27742
|
}).from(sessionEvents).where(
|
|
27301
27743
|
and10(
|
|
27302
27744
|
eq10(sessionEvents.workspaceId, input.workspaceId),
|
|
27303
27745
|
eq10(sessionEvents.turnId, row.lastContinuationTurnId),
|
|
27304
27746
|
eq10(sessionEvents.type, "turn.failed"),
|
|
27305
|
-
|
|
27747
|
+
sql8`${sessionEvents.payload} ->> 'rotated' = 'true'`
|
|
27306
27748
|
)
|
|
27307
27749
|
);
|
|
27308
27750
|
rotatedFailover = Number(rotatedFailures) > 0;
|
|
27309
27751
|
const [{ toolCalls } = { toolCalls: 0 }] = await tx.select({
|
|
27310
|
-
toolCalls:
|
|
27752
|
+
toolCalls: sql8`count(*)::int`
|
|
27311
27753
|
}).from(sessionEvents).where(
|
|
27312
27754
|
and10(
|
|
27313
27755
|
eq10(sessionEvents.workspaceId, input.workspaceId),
|
|
@@ -27320,13 +27762,13 @@ async function evaluateGoalContinuation(db, input) {
|
|
|
27320
27762
|
noProgressStreak = 0;
|
|
27321
27763
|
} else {
|
|
27322
27764
|
const [{ backpressureFailures } = { backpressureFailures: 0 }] = await tx.select({
|
|
27323
|
-
backpressureFailures:
|
|
27765
|
+
backpressureFailures: sql8`count(*)::int`
|
|
27324
27766
|
}).from(sessionEvents).where(
|
|
27325
27767
|
and10(
|
|
27326
27768
|
eq10(sessionEvents.workspaceId, input.workspaceId),
|
|
27327
27769
|
eq10(sessionEvents.turnId, row.lastContinuationTurnId),
|
|
27328
27770
|
eq10(sessionEvents.type, "turn.failed"),
|
|
27329
|
-
|
|
27771
|
+
sql8`${sessionEvents.payload} ->> 'recovery' = 'goal_continuation'`
|
|
27330
27772
|
)
|
|
27331
27773
|
);
|
|
27332
27774
|
if (Number(backpressureFailures) === 0) {
|
|
@@ -27431,7 +27873,7 @@ async function materializeGoalContinuation(db, input) {
|
|
|
27431
27873
|
if (!goalRead || goalRead.status !== "active" || session.status === "cancelled" || effectiveControl.state !== "active") {
|
|
27432
27874
|
return { action: "none", events: [] };
|
|
27433
27875
|
}
|
|
27434
|
-
const malformedGoalVersionEvidence =
|
|
27876
|
+
const malformedGoalVersionEvidence = sql8`
|
|
27435
27877
|
jsonb_build_object(
|
|
27436
27878
|
'reason', 'malformed_goal_version',
|
|
27437
27879
|
'rawGoalVersion', ${sessionSystemUpdates.payload} ->> 'goalVersion',
|
|
@@ -27444,7 +27886,7 @@ async function materializeGoalContinuation(db, input) {
|
|
|
27444
27886
|
deliveredTurnId: null,
|
|
27445
27887
|
deliveredAt: null,
|
|
27446
27888
|
summary: "Malformed goal continuation quarantined: malformed_goal_version",
|
|
27447
|
-
payload:
|
|
27889
|
+
payload: sql8`
|
|
27448
27890
|
(
|
|
27449
27891
|
case
|
|
27450
27892
|
when jsonb_typeof(${sessionSystemUpdates.payload}) = 'object'
|
|
@@ -27463,7 +27905,7 @@ async function materializeGoalContinuation(db, input) {
|
|
|
27463
27905
|
)
|
|
27464
27906
|
)
|
|
27465
27907
|
`,
|
|
27466
|
-
lineage:
|
|
27908
|
+
lineage: sql8`
|
|
27467
27909
|
(
|
|
27468
27910
|
case
|
|
27469
27911
|
when jsonb_typeof(${sessionSystemUpdates.lineage}) = 'object'
|
|
@@ -27479,8 +27921,8 @@ async function materializeGoalContinuation(db, input) {
|
|
|
27479
27921
|
eq10(sessionSystemUpdates.sessionId, input.sessionId),
|
|
27480
27922
|
eq10(sessionSystemUpdates.kind, "goal_continuation"),
|
|
27481
27923
|
eq10(sessionSystemUpdates.state, "pending"),
|
|
27482
|
-
|
|
27483
|
-
|
|
27924
|
+
sql8`${sessionSystemUpdates.payload} ->> 'goalId' = ${goalRead.id}`,
|
|
27925
|
+
sql8`(
|
|
27484
27926
|
jsonb_typeof(${sessionSystemUpdates.payload} -> 'goalVersion') = 'number'
|
|
27485
27927
|
and ${sessionSystemUpdates.payload} ->> 'goalVersion' ~ '^[1-9][0-9]*$'
|
|
27486
27928
|
and ${sessionSystemUpdates.payload} ->> 'goalVersion' = ${goalRead.version.toString()}
|
|
@@ -27524,8 +27966,8 @@ async function materializeGoalContinuation(db, input) {
|
|
|
27524
27966
|
eq10(sessionSystemUpdates.sessionId, input.sessionId),
|
|
27525
27967
|
eq10(sessionSystemUpdates.kind, "goal_continuation"),
|
|
27526
27968
|
eq10(sessionSystemUpdates.state, "pending"),
|
|
27527
|
-
|
|
27528
|
-
|
|
27969
|
+
sql8`${sessionSystemUpdates.payload} ->> 'goalId' = ${goalRead.id}`,
|
|
27970
|
+
sql8`(
|
|
27529
27971
|
jsonb_typeof(${sessionSystemUpdates.payload} -> 'goalVersion') = 'number'
|
|
27530
27972
|
and ${sessionSystemUpdates.payload} ->> 'goalVersion' ~ '^[1-9][0-9]*$'
|
|
27531
27973
|
and ${sessionSystemUpdates.payload} ->> 'goalVersion' = ${goalRead.version.toString()}
|
|
@@ -27554,7 +27996,7 @@ async function materializeGoalContinuation(db, input) {
|
|
|
27554
27996
|
let goalWakeRevision = goalRead.continuationWakeRevision;
|
|
27555
27997
|
if (goalWakeRevision <= goalRead.continuationObservedRevision) {
|
|
27556
27998
|
const [repaired] = await tx.update(sessionGoals).set({
|
|
27557
|
-
continuationWakeRevision:
|
|
27999
|
+
continuationWakeRevision: sql8`${sessionGoals.continuationWakeRevision} + 1`,
|
|
27558
28000
|
updatedAt: /* @__PURE__ */ new Date()
|
|
27559
28001
|
}).where(eq10(sessionGoals.id, goalRead.id)).returning({
|
|
27560
28002
|
revision: sessionGoals.continuationWakeRevision
|
|
@@ -28281,7 +28723,7 @@ async function claimSessionWorkForAttempt(db, workspaceId, input) {
|
|
|
28281
28723
|
return;
|
|
28282
28724
|
}
|
|
28283
28725
|
const [{ position } = { position: 0 }] = await tx.select({
|
|
28284
|
-
position:
|
|
28726
|
+
position: sql8`coalesce(max(${sessionHistoryItems.position}), -1) + 1`
|
|
28285
28727
|
}).from(sessionHistoryItems).where(
|
|
28286
28728
|
and10(
|
|
28287
28729
|
eq10(sessionHistoryItems.workspaceId, workspaceId),
|
|
@@ -28440,19 +28882,19 @@ async function claimSessionWorkForAttempt(db, workspaceId, input) {
|
|
|
28440
28882
|
}
|
|
28441
28883
|
const now2 = /* @__PURE__ */ new Date();
|
|
28442
28884
|
const dispatchGeneration2 = parsedDispatch.generation + 1;
|
|
28443
|
-
await tx.execute(
|
|
28885
|
+
await tx.execute(sql8`set local opengeni.session_inference_claim = '1'`);
|
|
28444
28886
|
const [resumed] = await tx.update(sessionTurns).set({
|
|
28445
28887
|
status: "running",
|
|
28446
28888
|
triggerEventId: input.trigger.triggerEventId,
|
|
28447
28889
|
temporalWorkflowId: workflowId,
|
|
28448
|
-
executionGeneration:
|
|
28890
|
+
executionGeneration: sql8`${sessionTurns.executionGeneration} + 1`,
|
|
28449
28891
|
activeAttemptId: input.attemptId,
|
|
28450
28892
|
metadata: metadataWithTurnDispatchAttempt(activeTurn.metadata, {
|
|
28451
28893
|
id: input.dispatchId,
|
|
28452
28894
|
generation: dispatchGeneration2,
|
|
28453
28895
|
triggerEventId: input.trigger.triggerEventId
|
|
28454
28896
|
}),
|
|
28455
|
-
version:
|
|
28897
|
+
version: sql8`${sessionTurns.version} + 1`,
|
|
28456
28898
|
startedAt: now2,
|
|
28457
28899
|
finishedAt: null,
|
|
28458
28900
|
updatedAt: now2
|
|
@@ -28484,18 +28926,18 @@ async function claimSessionWorkForAttempt(db, workspaceId, input) {
|
|
|
28484
28926
|
}
|
|
28485
28927
|
const now2 = /* @__PURE__ */ new Date();
|
|
28486
28928
|
const dispatchGeneration2 = parsedDispatch.generation + 1;
|
|
28487
|
-
await tx.execute(
|
|
28929
|
+
await tx.execute(sql8`set local opengeni.session_inference_claim = '1'`);
|
|
28488
28930
|
const [resumed] = await tx.update(sessionTurns).set({
|
|
28489
28931
|
status: "running",
|
|
28490
28932
|
temporalWorkflowId: workflowId,
|
|
28491
|
-
executionGeneration:
|
|
28933
|
+
executionGeneration: sql8`${sessionTurns.executionGeneration} + 1`,
|
|
28492
28934
|
activeAttemptId: input.attemptId,
|
|
28493
28935
|
metadata: metadataWithTurnDispatchAttempt(activeTurn.metadata, {
|
|
28494
28936
|
id: input.dispatchId,
|
|
28495
28937
|
generation: dispatchGeneration2,
|
|
28496
28938
|
triggerEventId: activeTurn.triggerEventId
|
|
28497
28939
|
}),
|
|
28498
|
-
version:
|
|
28940
|
+
version: sql8`${sessionTurns.version} + 1`,
|
|
28499
28941
|
startedAt: now2,
|
|
28500
28942
|
finishedAt: null,
|
|
28501
28943
|
updatedAt: now2
|
|
@@ -28561,7 +29003,7 @@ async function claimSessionWorkForAttempt(db, workspaceId, input) {
|
|
|
28561
29003
|
).limit(1).for("update");
|
|
28562
29004
|
const rows = await rawRows(
|
|
28563
29005
|
tx,
|
|
28564
|
-
|
|
29006
|
+
sql8`select id, trigger_event_id, metadata from session_turns
|
|
28565
29007
|
where workspace_id = ${workspaceId} and session_id = ${sessionId}
|
|
28566
29008
|
and status = 'queued' and source in ('user', 'api')
|
|
28567
29009
|
and (
|
|
@@ -28605,7 +29047,7 @@ async function claimSessionWorkForAttempt(db, workspaceId, input) {
|
|
|
28605
29047
|
context: {}
|
|
28606
29048
|
};
|
|
28607
29049
|
const [{ position: position2 } = { position: 1 }] = await tx.select({
|
|
28608
|
-
position:
|
|
29050
|
+
position: sql8`coalesce(max(${sessionTurns.position}), 0) + 1`
|
|
28609
29051
|
}).from(sessionTurns).where(
|
|
28610
29052
|
and10(
|
|
28611
29053
|
eq10(sessionTurns.workspaceId, workspaceId),
|
|
@@ -28622,10 +29064,10 @@ async function claimSessionWorkForAttempt(db, workspaceId, input) {
|
|
|
28622
29064
|
and10(
|
|
28623
29065
|
eq10(sessionTurns.workspaceId, workspaceId),
|
|
28624
29066
|
eq10(sessionTurns.sessionId, sessionId),
|
|
28625
|
-
|
|
29067
|
+
sql8`${sessionTurns.startedAt} is not null`
|
|
28626
29068
|
)
|
|
28627
29069
|
).orderBy(desc5(sessionTurns.startedAt), desc5(sessionTurns.createdAt)).limit(1);
|
|
28628
|
-
await tx.execute(
|
|
29070
|
+
await tx.execute(sql8`set local opengeni.session_inference_claim = '1'`);
|
|
28629
29071
|
const [compactionTurn] = await tx.insert(sessionTurns).values({
|
|
28630
29072
|
id: turnId2,
|
|
28631
29073
|
accountId: session.accountId,
|
|
@@ -28723,7 +29165,7 @@ async function claimSessionWorkForAttempt(db, workspaceId, input) {
|
|
|
28723
29165
|
const turnId = crypto.randomUUID();
|
|
28724
29166
|
const triggerEventId = crypto.randomUUID();
|
|
28725
29167
|
const [{ position } = { position: 1 }] = await tx.select({
|
|
28726
|
-
position:
|
|
29168
|
+
position: sql8`coalesce(max(${sessionTurns.position}), 0) + 1`
|
|
28727
29169
|
}).from(sessionTurns).where(
|
|
28728
29170
|
and10(
|
|
28729
29171
|
eq10(sessionTurns.workspaceId, workspaceId),
|
|
@@ -28848,7 +29290,7 @@ async function claimSessionWorkForAttempt(db, workspaceId, input) {
|
|
|
28848
29290
|
and10(
|
|
28849
29291
|
eq10(sessionTurns.workspaceId, workspaceId),
|
|
28850
29292
|
eq10(sessionTurns.sessionId, sessionId),
|
|
28851
|
-
|
|
29293
|
+
sql8`${sessionTurns.startedAt} is not null`
|
|
28852
29294
|
)
|
|
28853
29295
|
).orderBy(desc5(sessionTurns.startedAt), desc5(sessionTurns.createdAt)).limit(1);
|
|
28854
29296
|
const model = typeof goalPolicy?.model === "string" ? goalPolicy.model : latestStarted?.model ?? session.model;
|
|
@@ -28866,7 +29308,7 @@ async function claimSessionWorkForAttempt(db, workspaceId, input) {
|
|
|
28866
29308
|
);
|
|
28867
29309
|
const tools = Array.isArray(goalPolicy?.tools) ? goalPolicy.tools : latestStarted?.tools ?? session.tools;
|
|
28868
29310
|
const sandboxBackend = typeof goalPolicy?.sandboxBackend === "string" ? goalPolicy.sandboxBackend : latestStarted?.sandboxBackend ?? session.sandboxBackend;
|
|
28869
|
-
await tx.execute(
|
|
29311
|
+
await tx.execute(sql8`set local opengeni.session_inference_claim = '1'`);
|
|
28870
29312
|
const [internalTurn] = await tx.insert(sessionTurns).values({
|
|
28871
29313
|
id: turnId,
|
|
28872
29314
|
accountId: session.accountId,
|
|
@@ -28952,18 +29394,18 @@ async function claimSessionWorkForAttempt(db, workspaceId, input) {
|
|
|
28952
29394
|
throw new Error("Turn dispatch generation exhausted; refusing to wrap or reuse it");
|
|
28953
29395
|
}
|
|
28954
29396
|
const dispatchGeneration = queuedDispatch.generation + 1;
|
|
28955
|
-
await tx.execute(
|
|
29397
|
+
await tx.execute(sql8`set local opengeni.session_inference_claim = '1'`);
|
|
28956
29398
|
const [row] = await tx.update(sessionTurns).set({
|
|
28957
29399
|
status: "running",
|
|
28958
29400
|
temporalWorkflowId: workflowId,
|
|
28959
|
-
executionGeneration:
|
|
29401
|
+
executionGeneration: sql8`${sessionTurns.executionGeneration} + 1`,
|
|
28960
29402
|
activeAttemptId: input.attemptId,
|
|
28961
29403
|
metadata: metadataWithTurnDispatchAttempt(queuedTurn?.metadata, {
|
|
28962
29404
|
id: input.dispatchId,
|
|
28963
29405
|
generation: dispatchGeneration,
|
|
28964
29406
|
triggerEventId: queuedTurn.trigger_event_id
|
|
28965
29407
|
}),
|
|
28966
|
-
version:
|
|
29408
|
+
version: sql8`${sessionTurns.version} + 1`,
|
|
28967
29409
|
startedAt: now,
|
|
28968
29410
|
updatedAt: now
|
|
28969
29411
|
}).where(
|
|
@@ -28974,7 +29416,7 @@ async function claimSessionWorkForAttempt(db, workspaceId, input) {
|
|
|
28974
29416
|
}
|
|
28975
29417
|
await registerAttempt(row);
|
|
28976
29418
|
const [{ historyPosition } = { historyPosition: 0 }] = await tx.select({
|
|
28977
|
-
historyPosition:
|
|
29419
|
+
historyPosition: sql8`coalesce(max(${sessionHistoryItems.position}), -1) + 1`
|
|
28978
29420
|
}).from(sessionHistoryItems).where(
|
|
28979
29421
|
and10(
|
|
28980
29422
|
eq10(sessionHistoryItems.workspaceId, workspaceId),
|
|
@@ -29180,7 +29622,7 @@ async function reconcileSessionAttemptQuiescence(db, input) {
|
|
|
29180
29622
|
db,
|
|
29181
29623
|
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
29182
29624
|
async (scopedDb) => {
|
|
29183
|
-
const rows = await scopedDb.execute(
|
|
29625
|
+
const rows = await scopedDb.execute(sql8`
|
|
29184
29626
|
select
|
|
29185
29627
|
attempt.account_id,
|
|
29186
29628
|
attempt.state,
|
|
@@ -29634,7 +30076,7 @@ async function peekSessionWork(db, workspaceId, sessionId) {
|
|
|
29634
30076
|
isNotNull(sessionHumanInputRequests.expiresAt)
|
|
29635
30077
|
)
|
|
29636
30078
|
).orderBy(
|
|
29637
|
-
|
|
30079
|
+
sql8`${sessionHumanInputRequests.expiresAt} asc nulls last`,
|
|
29638
30080
|
asc5(sessionHumanInputRequests.id)
|
|
29639
30081
|
).limit(1);
|
|
29640
30082
|
return expiringHumanInput?.expiresAt ? {
|
|
@@ -29777,7 +30219,7 @@ async function settleSessionIdleWithParentOutbox(db, workspaceId, sessionId) {
|
|
|
29777
30219
|
return { action: "stale", episodeKey: null, events: [] };
|
|
29778
30220
|
}
|
|
29779
30221
|
const [{ episodeSequence } = { episodeSequence: 0 }] = await tx.select({
|
|
29780
|
-
episodeSequence:
|
|
30222
|
+
episodeSequence: sql8`coalesce(max(${sessionEvents.sequence}), 0)::int`
|
|
29781
30223
|
}).from(sessionEvents).where(
|
|
29782
30224
|
and10(
|
|
29783
30225
|
eq10(sessionEvents.workspaceId, workspaceId),
|
|
@@ -30068,7 +30510,7 @@ async function applySessionTurnSettlement(db, workspaceId, input) {
|
|
|
30068
30510
|
}
|
|
30069
30511
|
}
|
|
30070
30512
|
const [{ maxVersion } = { maxVersion: 0 }] = await tx.select({
|
|
30071
|
-
maxVersion:
|
|
30513
|
+
maxVersion: sql8`coalesce(max(${agentRunStates.stateVersion}), 0)`
|
|
30072
30514
|
}).from(agentRunStates).where(
|
|
30073
30515
|
and10(
|
|
30074
30516
|
eq10(agentRunStates.workspaceId, workspaceId),
|
|
@@ -30114,7 +30556,7 @@ async function applySessionTurnSettlement(db, workspaceId, input) {
|
|
|
30114
30556
|
turnGeneration: turn.executionGeneration,
|
|
30115
30557
|
updatedAt: /* @__PURE__ */ new Date()
|
|
30116
30558
|
},
|
|
30117
|
-
setWhere:
|
|
30559
|
+
setWhere: sql8`
|
|
30118
30560
|
${sessionHumanInputRequests.status} = 'pending'
|
|
30119
30561
|
and ${sessionHumanInputRequests.allowSkip} = ${request.allowSkip}
|
|
30120
30562
|
and ${sessionHumanInputRequests.questions} = ${JSON.stringify(request.questions)}::jsonb
|
|
@@ -30322,7 +30764,7 @@ async function applySessionTurnSettlement(db, workspaceId, input) {
|
|
|
30322
30764
|
const inserted = values.length > 0 ? await tx.insert(sessionEvents).values(values).returning() : [];
|
|
30323
30765
|
const terminal = input.turnStatus === "completed" || input.turnStatus === "cancelled" || input.turnStatus === "failed" || input.turnStatus === "superseded";
|
|
30324
30766
|
if (input.turnStatus === "running") {
|
|
30325
|
-
await tx.execute(
|
|
30767
|
+
await tx.execute(sql8`set local opengeni.session_inference_claim = '1'`);
|
|
30326
30768
|
}
|
|
30327
30769
|
await tx.update(sessionTurns).set({
|
|
30328
30770
|
status: input.turnStatus,
|
|
@@ -30365,7 +30807,7 @@ async function applySessionTurnSettlement(db, workspaceId, input) {
|
|
|
30365
30807
|
);
|
|
30366
30808
|
if (terminal && input.activeTurnId === null) {
|
|
30367
30809
|
const [armedGoal] = await tx.update(sessionGoals).set({
|
|
30368
|
-
continuationWakeRevision:
|
|
30810
|
+
continuationWakeRevision: sql8`${sessionGoals.continuationWakeRevision} + 1`,
|
|
30369
30811
|
updatedAt: now
|
|
30370
30812
|
}).where(
|
|
30371
30813
|
and10(
|
|
@@ -30421,7 +30863,7 @@ async function settleCodexCredentialLeaseLoss(db, input) {
|
|
|
30421
30863
|
return { action: "stale", events: [] };
|
|
30422
30864
|
}
|
|
30423
30865
|
const leaseRows = await tx.execute(
|
|
30424
|
-
|
|
30866
|
+
sql8`
|
|
30425
30867
|
select holder_id, generation from codex_credential_leases
|
|
30426
30868
|
where account_id = ${input.accountId}
|
|
30427
30869
|
and workspace_id = ${input.workspaceId}
|
|
@@ -30547,7 +30989,7 @@ async function settleCodexCredentialLeaseLoss(db, input) {
|
|
|
30547
30989
|
eq10(sessions.activeTurnId, input.turnId)
|
|
30548
30990
|
)
|
|
30549
30991
|
);
|
|
30550
|
-
await tx.execute(
|
|
30992
|
+
await tx.execute(sql8`
|
|
30551
30993
|
delete from codex_credential_leases
|
|
30552
30994
|
where account_id = ${input.accountId}
|
|
30553
30995
|
and workspace_id = ${input.workspaceId}
|
|
@@ -30599,7 +31041,7 @@ async function settleCodexCredentialFailover(db, input) {
|
|
|
30599
31041
|
};
|
|
30600
31042
|
}
|
|
30601
31043
|
const leaseRows = await tx.execute(
|
|
30602
|
-
|
|
31044
|
+
sql8`
|
|
30603
31045
|
select holder_id, generation from codex_credential_leases
|
|
30604
31046
|
where account_id = ${input.accountId}
|
|
30605
31047
|
and workspace_id = ${input.workspaceId}
|
|
@@ -30709,7 +31151,7 @@ async function settleCodexCredentialFailover(db, input) {
|
|
|
30709
31151
|
eq10(sessions.activeTurnId, input.turnId)
|
|
30710
31152
|
)
|
|
30711
31153
|
);
|
|
30712
|
-
await tx.execute(
|
|
31154
|
+
await tx.execute(sql8`
|
|
30713
31155
|
delete from codex_credential_leases
|
|
30714
31156
|
where account_id = ${input.accountId}
|
|
30715
31157
|
and workspace_id = ${input.workspaceId}
|
|
@@ -30775,7 +31217,7 @@ async function requestSessionTurnRecovery(db, workspaceId, input) {
|
|
|
30775
31217
|
input.providerArtifactInvalidation.codexCredentialId
|
|
30776
31218
|
),
|
|
30777
31219
|
isNull3(sessionHistoryItems.providerArtifactInvalidatedAt),
|
|
30778
|
-
|
|
31220
|
+
sql8`${sessionHistoryItems.item} ->> 'type' in ('reasoning', 'compaction')`
|
|
30779
31221
|
)
|
|
30780
31222
|
).returning({ id: sessionHistoryItems.id });
|
|
30781
31223
|
const [latestRunState] = await tx.select({ id: agentRunStates.id }).from(agentRunStates).where(
|
|
@@ -31175,7 +31617,7 @@ async function getActiveSessionTurnForExecution(db, workspaceId, sessionId) {
|
|
|
31175
31617
|
eq10(sessionTurnAttempts.turnId, sessionTurns.id),
|
|
31176
31618
|
inArray5(sessionTurnAttempts.state, ["claimed", "running"]),
|
|
31177
31619
|
inArray5(sessionTurns.status, ["running", "recovering", "waiting_capacity"]),
|
|
31178
|
-
|
|
31620
|
+
sql8`not exists (
|
|
31179
31621
|
select 1
|
|
31180
31622
|
from ${sessionAttemptInterruptions} interruption
|
|
31181
31623
|
where interruption.workspace_id = ${workspaceId}
|
|
@@ -31215,7 +31657,7 @@ async function getSessionTurnForAttempt(db, workspaceId, sessionId, attemptId) {
|
|
|
31215
31657
|
"recovering",
|
|
31216
31658
|
"waiting_capacity"
|
|
31217
31659
|
]),
|
|
31218
|
-
|
|
31660
|
+
sql8`not exists (
|
|
31219
31661
|
select 1
|
|
31220
31662
|
from ${sessionAttemptInterruptions} interruption
|
|
31221
31663
|
where interruption.workspace_id = ${workspaceId}
|
|
@@ -31278,7 +31720,7 @@ async function getSessionQueueSnapshot(db, workspaceId, sessionId) {
|
|
|
31278
31720
|
eq10(sessionSystemUpdates.state, "pending")
|
|
31279
31721
|
)
|
|
31280
31722
|
).orderBy(
|
|
31281
|
-
|
|
31723
|
+
sql8`case when ${sessionSystemUpdates.kind} = 'agent_steer_instruction' then 0 else 1 end`,
|
|
31282
31724
|
asc5(sessionSystemUpdates.createdAt),
|
|
31283
31725
|
asc5(sessionSystemUpdates.id)
|
|
31284
31726
|
);
|
|
@@ -31419,7 +31861,7 @@ async function getSessionSystemUpdateOutboxByDedupeKey(db, input) {
|
|
|
31419
31861
|
);
|
|
31420
31862
|
}
|
|
31421
31863
|
async function claimPendingSessionSystemUpdateOutbox(db, limit = 100) {
|
|
31422
|
-
const rows = await rawRows(db,
|
|
31864
|
+
const rows = await rawRows(db, sql8`select * from opengeni_private.claim_session_system_update_outbox(${limit})`);
|
|
31423
31865
|
return rows.map(mapSystemUpdateOutboxRow);
|
|
31424
31866
|
}
|
|
31425
31867
|
async function enqueueSessionWorkflowWakeInTransaction(tx, input) {
|
|
@@ -31436,13 +31878,13 @@ async function enqueueSessionWorkflowWakeInTransaction(tx, input) {
|
|
|
31436
31878
|
target: sessionWorkflowWakeOutbox.sessionId,
|
|
31437
31879
|
set: {
|
|
31438
31880
|
temporalWorkflowId: input.temporalWorkflowId,
|
|
31439
|
-
wakeRevision:
|
|
31881
|
+
wakeRevision: sql8`${sessionWorkflowWakeOutbox.wakeRevision} + 1`,
|
|
31440
31882
|
reason: input.reason,
|
|
31441
31883
|
attempts: 0,
|
|
31442
31884
|
// Coalescing a delayed retry must never postpone an already-due wake
|
|
31443
31885
|
// owned by another producer. A later revision makes the batch richer;
|
|
31444
31886
|
// it does not revoke the earlier delivery obligation.
|
|
31445
|
-
nextAttemptAt:
|
|
31887
|
+
nextAttemptAt: sql8`least(${sessionWorkflowWakeOutbox.nextAttemptAt}, ${nextAttemptAt.toISOString()}::timestamptz)`,
|
|
31446
31888
|
lastError: null,
|
|
31447
31889
|
updatedAt: now
|
|
31448
31890
|
}
|
|
@@ -31482,7 +31924,7 @@ async function enqueueSessionWorkflowWakeIfRunnable(db, input) {
|
|
|
31482
31924
|
);
|
|
31483
31925
|
}
|
|
31484
31926
|
async function claimPendingSessionWorkflowWakes(db, limit = 100) {
|
|
31485
|
-
const rows = await rawRows(db,
|
|
31927
|
+
const rows = await rawRows(db, sql8`select * from opengeni_private.claim_session_workflow_wakes(${limit})`);
|
|
31486
31928
|
return rows.map((row) => ({
|
|
31487
31929
|
accountId: row.account_id,
|
|
31488
31930
|
workspaceId: row.workspace_id,
|
|
@@ -31554,9 +31996,9 @@ async function markSessionWorkflowWakeDelivered(db, input) {
|
|
|
31554
31996
|
}
|
|
31555
31997
|
}
|
|
31556
31998
|
const [row] = await tx.update(sessionWorkflowWakeOutbox).set({
|
|
31557
|
-
deliveredRevision:
|
|
31558
|
-
attempts:
|
|
31559
|
-
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`,
|
|
31560
32002
|
updatedAt: /* @__PURE__ */ new Date()
|
|
31561
32003
|
}).where(
|
|
31562
32004
|
and10(
|
|
@@ -31768,7 +32210,7 @@ async function addSessionSystemUpdateWithSourceMutation(db, input, mutateSource)
|
|
|
31768
32210
|
eq10(sessionEvents.workspaceId, input.workspaceId),
|
|
31769
32211
|
eq10(sessionEvents.sessionId, input.sessionId),
|
|
31770
32212
|
eq10(sessionEvents.type, "system.update.pending"),
|
|
31771
|
-
|
|
32213
|
+
sql8`${sessionEvents.payload} ->> 'updateId' = ${existing.id}`
|
|
31772
32214
|
)
|
|
31773
32215
|
).limit(1);
|
|
31774
32216
|
if (!pendingEvent) throw new Error("System-update pending event disappeared");
|
|
@@ -31857,7 +32299,7 @@ async function listSessionSystemUpdatesForTurn(db, workspaceId, sessionId, turnI
|
|
|
31857
32299
|
// materialized goal continuation. Keep all coalesced work in one
|
|
31858
32300
|
// metered inference, but render the winning Steer last so transaction
|
|
31859
32301
|
// timestamps cannot let an older goal prompt override it.
|
|
31860
|
-
|
|
32302
|
+
sql8`case when ${sessionSystemUpdates.kind} = 'agent_steer_instruction' then 1 else 0 end`,
|
|
31861
32303
|
asc5(sessionSystemUpdates.createdAt),
|
|
31862
32304
|
asc5(sessionSystemUpdates.id)
|
|
31863
32305
|
);
|
|
@@ -32119,7 +32561,7 @@ async function appendSessionEventsForTurnAttempt(db, workspaceId, sessionId, tur
|
|
|
32119
32561
|
eq10(sessionEvents.type, "agent.model.usage"),
|
|
32120
32562
|
eq10(sessionEvents.turnAssociation, "current"),
|
|
32121
32563
|
inArray5(
|
|
32122
|
-
|
|
32564
|
+
sql8`${sessionEvents.payload} ->> 'sourceKey'`,
|
|
32123
32565
|
incomingUsageKeys
|
|
32124
32566
|
)
|
|
32125
32567
|
)
|
|
@@ -32249,7 +32691,7 @@ async function appendSessionEventToSandboxGroup(db, workspaceId, sandboxGroupId,
|
|
|
32249
32691
|
const inserted = await tx.insert(sessionEvents).values(values).returning();
|
|
32250
32692
|
const lockedSessionIds = rows.map((row) => row.id);
|
|
32251
32693
|
const updated = await tx.update(sessions).set({
|
|
32252
|
-
lastSequence:
|
|
32694
|
+
lastSequence: sql8`${sessions.lastSequence} + 1`,
|
|
32253
32695
|
...sessionEventTypesAdvanceActivity([input]) ? { updatedAt: /* @__PURE__ */ new Date() } : {}
|
|
32254
32696
|
}).where(
|
|
32255
32697
|
and10(
|
|
@@ -33197,14 +33639,21 @@ export {
|
|
|
33197
33639
|
MEMORY_BLOCK_RECORD_LIMIT,
|
|
33198
33640
|
MEMORY_CORRECT_TOOL_DESCRIPTION,
|
|
33199
33641
|
MEMORY_KIND_SECTION_TITLES,
|
|
33642
|
+
MEMORY_LABEL_MAX_CHARS,
|
|
33643
|
+
MEMORY_LABEL_MAX_COUNT,
|
|
33644
|
+
MEMORY_NAMESPACE_MAX_CHARS,
|
|
33200
33645
|
MEMORY_NEAR_DUP_COSINE_THRESHOLD,
|
|
33201
33646
|
MEMORY_NEAR_DUP_NEIGHBORS,
|
|
33647
|
+
MEMORY_RELATIONSHIP_TYPES,
|
|
33648
|
+
MEMORY_ROLE_KEY_MAX_CHARS,
|
|
33202
33649
|
MEMORY_SAVE_TOOL_DESCRIPTION,
|
|
33203
33650
|
MEMORY_SEARCH_DEFAULT_LIMIT,
|
|
33204
33651
|
MEMORY_SEARCH_MAX_LIMIT,
|
|
33205
33652
|
MEMORY_SEARCH_TOOL_DESCRIPTION,
|
|
33653
|
+
MEMORY_SUBJECT_ID_MAX_CHARS,
|
|
33206
33654
|
MEMORY_TEXT_MAX_CHARS,
|
|
33207
33655
|
MEMORY_VISIBLE_RECORD_CAP,
|
|
33656
|
+
MemoryGovernanceAuthorityError,
|
|
33208
33657
|
NON_RLS_RUNTIME_TABLES,
|
|
33209
33658
|
NewSessionDraftAccessError,
|
|
33210
33659
|
NewSessionDraftConflictError,
|
|
@@ -33304,6 +33753,7 @@ export {
|
|
|
33304
33753
|
applyContextCompaction,
|
|
33305
33754
|
applyCreditDebitUpToBalance,
|
|
33306
33755
|
applyCreditLedgerEntry,
|
|
33756
|
+
applyKnowledgeMemoryOperation,
|
|
33307
33757
|
applySessionTurnSettlement,
|
|
33308
33758
|
approveDeviceEnrollmentRequest,
|
|
33309
33759
|
areGitHubRepositoriesAllowedForWorkspace,
|
|
@@ -33324,6 +33774,7 @@ export {
|
|
|
33324
33774
|
buildCodexTokenResolver,
|
|
33325
33775
|
buildConnectionTokenResolver,
|
|
33326
33776
|
buildHostConnectionTokenResolver,
|
|
33777
|
+
canonicalMemoryRelationship,
|
|
33327
33778
|
canonicalSessionCommandHash,
|
|
33328
33779
|
changePreferenceRegistryScope,
|
|
33329
33780
|
claimCodexResetRedemption,
|
|
@@ -33418,7 +33869,7 @@ export {
|
|
|
33418
33869
|
createWorkspaceEnvironment,
|
|
33419
33870
|
createWorkspaceInstructionPolicyDraft,
|
|
33420
33871
|
databaseFailureCode,
|
|
33421
|
-
|
|
33872
|
+
sql9 as dbSql,
|
|
33422
33873
|
deactivatePreferenceRegistry,
|
|
33423
33874
|
deadLetterHostExportHead,
|
|
33424
33875
|
decodeSessionListCursor,
|
|
@@ -33575,6 +34026,8 @@ export {
|
|
|
33575
34026
|
grantWorkspaceAccess,
|
|
33576
34027
|
hasAuditableGitHubInstallationAuthority,
|
|
33577
34028
|
hasCreditLedgerEntry,
|
|
34029
|
+
hashMemoryOperationPlan,
|
|
34030
|
+
hashMemoryRevertPlan,
|
|
33578
34031
|
hashMemoryText,
|
|
33579
34032
|
heartbeatCodexCredentialLease,
|
|
33580
34033
|
heartbeatCodexCredentialLeaseUntil,
|
|
@@ -33593,6 +34046,7 @@ export {
|
|
|
33593
34046
|
isCodexBilledModel2 as isCodexBilledModel,
|
|
33594
34047
|
isCodexBilledTurn,
|
|
33595
34048
|
isDatabasePersistenceFailure,
|
|
34049
|
+
isMemoryScopeApplicable,
|
|
33596
34050
|
isMemoryTextTooLong,
|
|
33597
34051
|
isPrivateAddress,
|
|
33598
34052
|
isRetryablePersistenceSqlState,
|
|
@@ -33697,6 +34151,13 @@ export {
|
|
|
33697
34151
|
newSessionDraftToolsProvided,
|
|
33698
34152
|
nextSessionHistoryPosition,
|
|
33699
34153
|
normalizeBearerScheme,
|
|
34154
|
+
normalizeMemoryLabel,
|
|
34155
|
+
normalizeMemoryLabels,
|
|
34156
|
+
normalizeMemoryNamespace,
|
|
34157
|
+
normalizeMemoryOperationPlan,
|
|
34158
|
+
normalizeMemoryRevertPlan,
|
|
34159
|
+
normalizeMemoryRoleKey,
|
|
34160
|
+
normalizeMemoryScope,
|
|
33700
34161
|
normalizeMemoryText,
|
|
33701
34162
|
orphanedResultRowIndicesForRepair,
|
|
33702
34163
|
peekSessionWork,
|
|
@@ -33790,6 +34251,7 @@ export {
|
|
|
33790
34251
|
retainedProcessReconciliationProof,
|
|
33791
34252
|
retainedProcessSettlementIdentity,
|
|
33792
34253
|
retireHostExportConsumer,
|
|
34254
|
+
revertKnowledgeMemoryOperation,
|
|
33793
34255
|
revokeApiKey,
|
|
33794
34256
|
revokeConnection,
|
|
33795
34257
|
revokeConnectionWithSlackBotSuccessAudit,
|