@opengeni/db 4.0.0-canary.0 → 4.0.0-canary.2
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/canonical-human-identities.js +3 -3
- package/dist/{chunk-2XEZK4LF.js → chunk-7YZP2CSL.js} +23 -1
- package/dist/chunk-7YZP2CSL.js.map +1 -0
- package/dist/{chunk-P6NSEG2S.js → chunk-B5Y3TCSP.js} +2 -2
- package/dist/{chunk-CJROYHSC.js → chunk-CQF6G4IF.js} +3 -3
- package/dist/chunk-DUB3LUVM.js +4145 -0
- package/dist/chunk-DUB3LUVM.js.map +1 -0
- package/dist/{chunk-3RI33YQN.js → chunk-FRIYCNK2.js} +3 -1
- package/dist/{chunk-3RI33YQN.js.map → chunk-FRIYCNK2.js.map} +1 -1
- package/dist/{chunk-RZNOSEMC.js → chunk-L2QFSPFP.js} +2 -2
- package/dist/{chunk-NLFHMPUB.js → chunk-NPKBYGAK.js} +2 -2
- package/dist/{chunk-QM6YOWHZ.js → chunk-PWJJKCTF.js} +85 -4
- package/dist/chunk-PWJJKCTF.js.map +1 -0
- package/dist/{chunk-MX6V5F65.js → chunk-VU2IK37Y.js} +2 -2
- package/dist/{chunk-UFAMOUWL.js → chunk-XIYAXH47.js} +2 -2
- package/dist/editable-artifact-durable-export.js +2 -2
- package/dist/editable-artifacts.js +3 -3
- package/dist/index.d.ts +113 -7
- package/dist/index.js +9392 -11506
- package/dist/index.js.map +1 -1
- package/dist/managed-auth-session-sets.js +3 -3
- package/dist/migrate.d.ts +6 -0
- package/dist/migrate.js +3 -1
- package/dist/migration-runner-settings.d.ts +10 -0
- package/dist/new-session-drafts.d.ts +2 -0
- package/dist/provision-roles.js +1 -1
- package/dist/runtime-posture.d.ts +2 -2
- package/dist/schema.d.ts +270 -9
- package/dist/schema.js +3 -1
- package/dist/session-background-commands.d.ts +83 -0
- package/dist/session-background-commands.js +18 -3
- package/dist/session-command-output.d.ts +17 -0
- package/dist/session-command-output.js +130 -0
- package/dist/session-command-output.js.map +1 -0
- package/dist/session-event-slices.d.ts +28 -0
- package/dist/session-event-slices.js +225 -0
- package/dist/session-event-slices.js.map +1 -0
- package/dist/session-mcp-progress.d.ts +12 -0
- package/dist/session-tenancy.js +3 -3
- package/dist/site-publication-request.d.ts +18 -0
- package/dist/video-generation.js +3 -3
- package/dist/workspace-artifacts.d.ts +34 -4
- package/dist/xai-subscription.d.ts +2 -0
- package/drizzle/0407_connected_command_tracking_retirement.sql +245 -0
- package/drizzle/0408_scheduled_session_target_index.sql +4 -0
- package/drizzle/0409_new_session_draft_project_provenance.sql +321 -0
- package/drizzle/0410_new_session_draft_project_provenance_index.sql +5 -0
- package/drizzle/0411_new_session_draft_project_provenance_backfill.sql +53 -0
- package/drizzle/0412_new_session_draft_project_provenance_validation.sql +30 -0
- package/drizzle/0413_session_filter_activity.sql +96 -0
- package/drizzle/0414_scheduled_generated_producer_materialization.sql +287 -0
- package/drizzle/0415_command_completion_observation.sql +9 -0
- package/drizzle/0416_scheduled_inherited_tool_admission.sql +27 -0
- package/drizzle/0417_command_runner_failure_metadata.sql +17 -0
- package/drizzle/0418_site_direct_uploads.sql +151 -0
- package/drizzle/0419_background_command_launch_authority.sql +56 -0
- package/package.json +14 -6
- package/src/index.ts +1691 -217
- package/src/migrate.ts +10 -2
- package/src/migration-runner-settings.ts +21 -0
- package/src/new-session-drafts.ts +105 -1
- package/src/runtime-posture.ts +2 -0
- package/src/schema.ts +97 -3
- package/src/session-background-commands.ts +320 -4
- package/src/session-command-output.ts +158 -0
- package/src/session-control.ts +53 -21
- package/src/session-event-slices.ts +310 -0
- package/src/session-mcp-progress.ts +67 -0
- package/src/site-publication-request.ts +32 -0
- package/src/workspace-artifacts.ts +95 -96
- package/src/xai-subscription.ts +8 -0
- package/dist/chunk-2XEZK4LF.js.map +0 -1
- package/dist/chunk-N5VXJ4I2.js +0 -589
- package/dist/chunk-N5VXJ4I2.js.map +0 -1
- package/dist/chunk-QM6YOWHZ.js.map +0 -1
- /package/dist/{chunk-P6NSEG2S.js.map → chunk-B5Y3TCSP.js.map} +0 -0
- /package/dist/{chunk-CJROYHSC.js.map → chunk-CQF6G4IF.js.map} +0 -0
- /package/dist/{chunk-RZNOSEMC.js.map → chunk-L2QFSPFP.js.map} +0 -0
- /package/dist/{chunk-NLFHMPUB.js.map → chunk-NPKBYGAK.js.map} +0 -0
- /package/dist/{chunk-MX6V5F65.js.map → chunk-VU2IK37Y.js.map} +0 -0
- /package/dist/{chunk-UFAMOUWL.js.map → chunk-XIYAXH47.js.map} +0 -0
package/dist/chunk-N5VXJ4I2.js
DELETED
|
@@ -1,589 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
withRlsContext,
|
|
3
|
-
withSessionActivityRlsContext
|
|
4
|
-
} from "./chunk-UFAMOUWL.js";
|
|
5
|
-
import {
|
|
6
|
-
sandboxRetainedProcesses,
|
|
7
|
-
sessionBackgroundCommands,
|
|
8
|
-
sessionEvents,
|
|
9
|
-
sessions
|
|
10
|
-
} from "./chunk-QM6YOWHZ.js";
|
|
11
|
-
|
|
12
|
-
// src/session-background-commands.ts
|
|
13
|
-
import { and, desc, eq, inArray, sql } from "drizzle-orm";
|
|
14
|
-
var SESSION_BACKGROUND_COMMAND_REASON_MAX_BYTES = 512;
|
|
15
|
-
function boundedSessionBackgroundCommandReason(value, label) {
|
|
16
|
-
const normalized = value.trim();
|
|
17
|
-
let bounded = "";
|
|
18
|
-
let bytes = 0;
|
|
19
|
-
for (const character of normalized) {
|
|
20
|
-
const characterBytes = Buffer.byteLength(character, "utf8");
|
|
21
|
-
if (bytes + characterBytes > SESSION_BACKGROUND_COMMAND_REASON_MAX_BYTES) break;
|
|
22
|
-
bounded += character;
|
|
23
|
-
bytes += characterBytes;
|
|
24
|
-
}
|
|
25
|
-
if (!bounded) throw new Error(`${label} must not be empty`);
|
|
26
|
-
return bounded;
|
|
27
|
-
}
|
|
28
|
-
function commandPreview(value) {
|
|
29
|
-
const normalized = value.replace(/\s+/g, " ").trim();
|
|
30
|
-
return Array.from(normalized).slice(0, 512).join("");
|
|
31
|
-
}
|
|
32
|
-
function mapCommand(row) {
|
|
33
|
-
return {
|
|
34
|
-
id: row.id,
|
|
35
|
-
workspaceId: row.workspaceId,
|
|
36
|
-
sessionId: row.sessionId,
|
|
37
|
-
provider: row.provider,
|
|
38
|
-
state: row.state,
|
|
39
|
-
commandPreview: row.commandPreview,
|
|
40
|
-
cancelRequestedAt: row.cancelRequestedAt?.toISOString() ?? null,
|
|
41
|
-
exitCode: row.exitCode ?? null,
|
|
42
|
-
settlementReason: row.settlementReason ?? null,
|
|
43
|
-
startedAt: row.startedAt.toISOString(),
|
|
44
|
-
settledAt: row.settledAt?.toISOString() ?? null,
|
|
45
|
-
updatedAt: row.updatedAt.toISOString()
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
async function backgroundCommandActivityForSessions(db, input) {
|
|
49
|
-
if (input.sessionIds.length === 0) return /* @__PURE__ */ new Map();
|
|
50
|
-
return await withRlsContext(
|
|
51
|
-
db,
|
|
52
|
-
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
53
|
-
async (scopedDb) => {
|
|
54
|
-
const rows = await scopedDb.select({
|
|
55
|
-
sessionId: sessionBackgroundCommands.sessionId,
|
|
56
|
-
count: sql`count(*)::int`,
|
|
57
|
-
stoppingCount: sql`count(*) filter (where ${sessionBackgroundCommands.state} = 'stopping')::int`
|
|
58
|
-
}).from(sessionBackgroundCommands).where(
|
|
59
|
-
and(
|
|
60
|
-
eq(sessionBackgroundCommands.workspaceId, input.workspaceId),
|
|
61
|
-
inArray(sessionBackgroundCommands.sessionId, input.sessionIds),
|
|
62
|
-
inArray(sessionBackgroundCommands.state, ["running", "stopping"])
|
|
63
|
-
)
|
|
64
|
-
).groupBy(sessionBackgroundCommands.sessionId);
|
|
65
|
-
return new Map(
|
|
66
|
-
rows.map((row) => [
|
|
67
|
-
row.sessionId,
|
|
68
|
-
{
|
|
69
|
-
state: Number(row.stoppingCount) > 0 ? "stopping" : "running",
|
|
70
|
-
count: Number(row.count)
|
|
71
|
-
}
|
|
72
|
-
])
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
);
|
|
76
|
-
}
|
|
77
|
-
async function listSessionBackgroundCommands(db, input) {
|
|
78
|
-
return await withRlsContext(
|
|
79
|
-
db,
|
|
80
|
-
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
81
|
-
async (scopedDb) => {
|
|
82
|
-
const rows = await scopedDb.select().from(sessionBackgroundCommands).where(
|
|
83
|
-
and(
|
|
84
|
-
eq(sessionBackgroundCommands.workspaceId, input.workspaceId),
|
|
85
|
-
eq(sessionBackgroundCommands.sessionId, input.sessionId)
|
|
86
|
-
)
|
|
87
|
-
).orderBy(
|
|
88
|
-
desc(sessionBackgroundCommands.startedAt),
|
|
89
|
-
desc(sessionBackgroundCommands.id)
|
|
90
|
-
).limit(1e3);
|
|
91
|
-
return rows.map(mapCommand);
|
|
92
|
-
}
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
|
-
async function insertManagedSessionBackgroundCommandInTransaction(db, input) {
|
|
96
|
-
const [process] = await db.select({
|
|
97
|
-
accountId: sandboxRetainedProcesses.accountId,
|
|
98
|
-
workspaceId: sandboxRetainedProcesses.workspaceId,
|
|
99
|
-
sessionId: sandboxRetainedProcesses.sessionId,
|
|
100
|
-
state: sandboxRetainedProcesses.state
|
|
101
|
-
}).from(sandboxRetainedProcesses).where(eq(sandboxRetainedProcesses.id, input.retainedProcessId)).for("update").limit(1);
|
|
102
|
-
if (!process || process.accountId !== input.accountId || process.workspaceId !== input.workspaceId || process.sessionId !== input.sessionId || process.state !== "active") {
|
|
103
|
-
throw new Error("Managed background command requires its exact active retained process");
|
|
104
|
-
}
|
|
105
|
-
const [row] = await db.insert(sessionBackgroundCommands).values({
|
|
106
|
-
id: input.commandId,
|
|
107
|
-
accountId: input.accountId,
|
|
108
|
-
workspaceId: input.workspaceId,
|
|
109
|
-
sessionId: input.sessionId,
|
|
110
|
-
provider: "managed",
|
|
111
|
-
state: "running",
|
|
112
|
-
retainedProcessId: input.retainedProcessId,
|
|
113
|
-
commandPreview: commandPreview(input.command)
|
|
114
|
-
}).onConflictDoUpdate({
|
|
115
|
-
target: sessionBackgroundCommands.retainedProcessId,
|
|
116
|
-
targetWhere: sql`${sessionBackgroundCommands.retainedProcessId} is not null`,
|
|
117
|
-
set: { updatedAt: /* @__PURE__ */ new Date() }
|
|
118
|
-
}).returning();
|
|
119
|
-
if (!row) throw new Error("Managed background command adoption returned no row");
|
|
120
|
-
if (row.accountId !== input.accountId || row.workspaceId !== input.workspaceId || row.sessionId !== input.sessionId || row.provider !== "managed" || row.retainedProcessId !== input.retainedProcessId) {
|
|
121
|
-
throw new Error("Managed background command adoption conflicted with another identity");
|
|
122
|
-
}
|
|
123
|
-
return mapCommand(row);
|
|
124
|
-
}
|
|
125
|
-
async function insertConnectedMachineSessionBackgroundCommandInTransaction(db, input) {
|
|
126
|
-
const [row] = await db.insert(sessionBackgroundCommands).values({
|
|
127
|
-
id: input.commandId,
|
|
128
|
-
accountId: input.accountId,
|
|
129
|
-
workspaceId: input.workspaceId,
|
|
130
|
-
sessionId: input.sessionId,
|
|
131
|
-
provider: "connected_machine",
|
|
132
|
-
state: "running",
|
|
133
|
-
controlWorkspaceId: input.controlWorkspaceId,
|
|
134
|
-
enrollmentId: input.enrollmentId,
|
|
135
|
-
connectionInstanceId: input.connectionInstanceId,
|
|
136
|
-
opId: input.opId,
|
|
137
|
-
commandPreview: commandPreview(input.command)
|
|
138
|
-
}).onConflictDoUpdate({
|
|
139
|
-
target: [
|
|
140
|
-
sessionBackgroundCommands.controlWorkspaceId,
|
|
141
|
-
sessionBackgroundCommands.enrollmentId,
|
|
142
|
-
sessionBackgroundCommands.connectionInstanceId,
|
|
143
|
-
sessionBackgroundCommands.opId
|
|
144
|
-
],
|
|
145
|
-
targetWhere: sql`${sessionBackgroundCommands.provider} = 'connected_machine'`,
|
|
146
|
-
set: { updatedAt: /* @__PURE__ */ new Date() }
|
|
147
|
-
}).returning();
|
|
148
|
-
if (!row) throw new Error("Connected Machine background command adoption returned no row");
|
|
149
|
-
if (row.accountId !== input.accountId || row.workspaceId !== input.workspaceId || row.sessionId !== input.sessionId || row.provider !== "connected_machine" || row.controlWorkspaceId !== input.controlWorkspaceId || row.enrollmentId !== input.enrollmentId || row.connectionInstanceId !== input.connectionInstanceId || row.opId !== input.opId) {
|
|
150
|
-
throw new Error(
|
|
151
|
-
"Connected Machine background command adoption conflicted with another identity"
|
|
152
|
-
);
|
|
153
|
-
}
|
|
154
|
-
return mapCommand(row);
|
|
155
|
-
}
|
|
156
|
-
async function claimConnectedMachineSessionBackgroundCommands(db, input) {
|
|
157
|
-
if (!Number.isSafeInteger(input.limit) || input.limit < 1 || input.limit > 100) {
|
|
158
|
-
throw new Error("Connected command reconciliation limit must be between 1 and 100");
|
|
159
|
-
}
|
|
160
|
-
if (!Number.isSafeInteger(input.claimTtlMs) || input.claimTtlMs < 0 || input.claimTtlMs > 36e5) {
|
|
161
|
-
throw new Error("Connected command reconciliation claim TTL is invalid");
|
|
162
|
-
}
|
|
163
|
-
const rows = await db.execute(sql`
|
|
164
|
-
select account_id as "accountId",
|
|
165
|
-
workspace_id as "workspaceId",
|
|
166
|
-
session_id as "sessionId",
|
|
167
|
-
command_id as "commandId",
|
|
168
|
-
claim_id as "claimId",
|
|
169
|
-
command_state as "commandState",
|
|
170
|
-
control_workspace_id as "controlWorkspaceId",
|
|
171
|
-
enrollment_id as "enrollmentId",
|
|
172
|
-
connection_instance_id as "connectionInstanceId",
|
|
173
|
-
op_id as "opId",
|
|
174
|
-
reconcile_attempts as "reconcileAttempts",
|
|
175
|
-
reconcile_proof_outcome as "reconcileProofOutcome",
|
|
176
|
-
reconcile_proof_exit_code as "reconcileProofExitCode",
|
|
177
|
-
reconcile_proof_reason as "reconcileProofReason",
|
|
178
|
-
reconcile_proof_observed_at as "reconcileProofObservedAt"
|
|
179
|
-
from opengeni_private.claim_connected_machine_background_commands(
|
|
180
|
-
${input.claimId}::uuid, ${input.limit}::integer, ${input.claimTtlMs}::bigint
|
|
181
|
-
)
|
|
182
|
-
`);
|
|
183
|
-
return rows.map((row) => {
|
|
184
|
-
if (row.commandState !== "running" && row.commandState !== "stopping") {
|
|
185
|
-
throw new Error(`Connected command claim returned invalid state ${row.commandState}`);
|
|
186
|
-
}
|
|
187
|
-
const proof = row.reconcileProofOutcome === null ? null : row.reconcileProofOutcome === "exited" || row.reconcileProofOutcome === "lost" ? {
|
|
188
|
-
outcome: row.reconcileProofOutcome,
|
|
189
|
-
exitCode: row.reconcileProofExitCode === null ? null : Number(row.reconcileProofExitCode),
|
|
190
|
-
reason: row.reconcileProofReason,
|
|
191
|
-
observedAt: row.reconcileProofObservedAt instanceof Date ? row.reconcileProofObservedAt : new Date(row.reconcileProofObservedAt)
|
|
192
|
-
} : (() => {
|
|
193
|
-
throw new Error(
|
|
194
|
-
`Connected command claim returned invalid proof ${row.reconcileProofOutcome}`
|
|
195
|
-
);
|
|
196
|
-
})();
|
|
197
|
-
return {
|
|
198
|
-
commandId: row.commandId,
|
|
199
|
-
accountId: row.accountId,
|
|
200
|
-
workspaceId: row.workspaceId,
|
|
201
|
-
sessionId: row.sessionId,
|
|
202
|
-
claimId: row.claimId,
|
|
203
|
-
state: row.commandState,
|
|
204
|
-
controlWorkspaceId: row.controlWorkspaceId,
|
|
205
|
-
enrollmentId: row.enrollmentId,
|
|
206
|
-
connectionInstanceId: row.connectionInstanceId,
|
|
207
|
-
opId: row.opId,
|
|
208
|
-
reconcileAttempts: Number(row.reconcileAttempts),
|
|
209
|
-
proof
|
|
210
|
-
};
|
|
211
|
-
});
|
|
212
|
-
}
|
|
213
|
-
function connectedClaimIdentityWhere(claim) {
|
|
214
|
-
return and(
|
|
215
|
-
eq(sessionBackgroundCommands.id, claim.commandId),
|
|
216
|
-
eq(sessionBackgroundCommands.accountId, claim.accountId),
|
|
217
|
-
eq(sessionBackgroundCommands.workspaceId, claim.workspaceId),
|
|
218
|
-
eq(sessionBackgroundCommands.sessionId, claim.sessionId),
|
|
219
|
-
eq(sessionBackgroundCommands.provider, "connected_machine"),
|
|
220
|
-
eq(sessionBackgroundCommands.controlWorkspaceId, claim.controlWorkspaceId),
|
|
221
|
-
eq(sessionBackgroundCommands.enrollmentId, claim.enrollmentId),
|
|
222
|
-
eq(sessionBackgroundCommands.connectionInstanceId, claim.connectionInstanceId),
|
|
223
|
-
eq(sessionBackgroundCommands.opId, claim.opId),
|
|
224
|
-
eq(sessionBackgroundCommands.reconcileClaimId, claim.claimId),
|
|
225
|
-
inArray(sessionBackgroundCommands.state, ["running", "stopping"])
|
|
226
|
-
);
|
|
227
|
-
}
|
|
228
|
-
async function recordConnectedMachineBackgroundCommandProof(db, input) {
|
|
229
|
-
const reason = boundedSessionBackgroundCommandReason(
|
|
230
|
-
input.proof.reason,
|
|
231
|
-
"Connected command proof reason"
|
|
232
|
-
);
|
|
233
|
-
if (input.proof.outcome === "exited" && input.proof.exitCode === null) {
|
|
234
|
-
throw new Error("Connected command exit proof requires an exit code");
|
|
235
|
-
}
|
|
236
|
-
if (input.proof.outcome === "lost" && input.proof.exitCode !== null) {
|
|
237
|
-
throw new Error("Connected command loss proof cannot carry an exit code");
|
|
238
|
-
}
|
|
239
|
-
await withRlsContext(
|
|
240
|
-
db,
|
|
241
|
-
{ accountId: input.claim.accountId, workspaceId: input.claim.workspaceId },
|
|
242
|
-
async (scopedDb) => {
|
|
243
|
-
const [current] = await scopedDb.select().from(sessionBackgroundCommands).where(connectedClaimIdentityWhere(input.claim)).for("update").limit(1);
|
|
244
|
-
if (!current) throw new Error("Connected command proof was fenced by newer lifecycle state");
|
|
245
|
-
if (current.reconcileProofOutcome !== null) {
|
|
246
|
-
const observedAt = current.reconcileProofObservedAt?.getTime() ?? null;
|
|
247
|
-
if (current.reconcileProofOutcome !== input.proof.outcome || current.reconcileProofExitCode !== input.proof.exitCode || current.reconcileProofReason !== reason || observedAt !== input.proof.observedAt.getTime()) {
|
|
248
|
-
throw new Error("Connected command reconciliation proof conflicts with durable proof");
|
|
249
|
-
}
|
|
250
|
-
return;
|
|
251
|
-
}
|
|
252
|
-
const rows = await scopedDb.update(sessionBackgroundCommands).set({
|
|
253
|
-
reconcileProofOutcome: input.proof.outcome,
|
|
254
|
-
reconcileProofExitCode: input.proof.exitCode,
|
|
255
|
-
reconcileProofReason: reason,
|
|
256
|
-
reconcileProofObservedAt: input.proof.observedAt,
|
|
257
|
-
lastReconcileOutcome: `proof_${input.proof.outcome}`,
|
|
258
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
259
|
-
}).where(connectedClaimIdentityWhere(input.claim)).returning({ id: sessionBackgroundCommands.id });
|
|
260
|
-
if (rows.length !== 1) {
|
|
261
|
-
throw new Error("Connected command proof lost its exact claim during checkpoint");
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
);
|
|
265
|
-
}
|
|
266
|
-
async function deferConnectedMachineBackgroundCommandReconciliation(db, input) {
|
|
267
|
-
if (!Number.isSafeInteger(input.retryAfterMs) || input.retryAfterMs < 0) {
|
|
268
|
-
throw new Error("Connected command reconciliation retry delay is invalid");
|
|
269
|
-
}
|
|
270
|
-
const outcome = input.outcome.trim().slice(0, 64);
|
|
271
|
-
if (!outcome) throw new Error("Connected command reconciliation outcome must not be empty");
|
|
272
|
-
return await withRlsContext(
|
|
273
|
-
db,
|
|
274
|
-
{ accountId: input.claim.accountId, workspaceId: input.claim.workspaceId },
|
|
275
|
-
async (scopedDb) => {
|
|
276
|
-
const rows = await scopedDb.update(sessionBackgroundCommands).set({
|
|
277
|
-
reconcileAfter: new Date(Date.now() + input.retryAfterMs),
|
|
278
|
-
reconcileClaimId: null,
|
|
279
|
-
reconcileClaimedAt: null,
|
|
280
|
-
lastReconcileOutcome: outcome,
|
|
281
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
282
|
-
}).where(connectedClaimIdentityWhere(input.claim)).returning({ id: sessionBackgroundCommands.id });
|
|
283
|
-
return rows.length === 1;
|
|
284
|
-
}
|
|
285
|
-
);
|
|
286
|
-
}
|
|
287
|
-
async function settleClaimedConnectedMachineBackgroundCommandWithMutation(db, input, mutateTerminal) {
|
|
288
|
-
return await withSessionActivityRlsContext(
|
|
289
|
-
db,
|
|
290
|
-
{ accountId: input.claim.accountId, workspaceId: input.claim.workspaceId },
|
|
291
|
-
async (tx) => {
|
|
292
|
-
await mutateTerminal.prepare(tx);
|
|
293
|
-
const rows = await tx.execute(sql`
|
|
294
|
-
update ${sessionBackgroundCommands} command set
|
|
295
|
-
state = command.reconcile_proof_outcome,
|
|
296
|
-
exit_code = case
|
|
297
|
-
when command.reconcile_proof_outcome = 'exited'
|
|
298
|
-
then command.reconcile_proof_exit_code
|
|
299
|
-
else null
|
|
300
|
-
end,
|
|
301
|
-
settlement_reason = command.reconcile_proof_reason,
|
|
302
|
-
settled_at = command.reconcile_proof_observed_at,
|
|
303
|
-
reconcile_claim_id = null,
|
|
304
|
-
reconcile_claimed_at = null,
|
|
305
|
-
last_reconcile_outcome = 'settled_' || command.reconcile_proof_outcome,
|
|
306
|
-
updated_at = clock_timestamp()
|
|
307
|
-
where command.id = ${input.claim.commandId}
|
|
308
|
-
and command.account_id = ${input.claim.accountId}
|
|
309
|
-
and command.workspace_id = ${input.claim.workspaceId}
|
|
310
|
-
and command.session_id = ${input.claim.sessionId}
|
|
311
|
-
and command.provider = 'connected_machine'
|
|
312
|
-
and command.control_workspace_id = ${input.claim.controlWorkspaceId}
|
|
313
|
-
and command.enrollment_id = ${input.claim.enrollmentId}
|
|
314
|
-
and command.connection_instance_id = ${input.claim.connectionInstanceId}
|
|
315
|
-
and command.op_id = ${input.claim.opId}
|
|
316
|
-
and command.reconcile_claim_id = ${input.claim.claimId}
|
|
317
|
-
and command.state in ('running', 'stopping')
|
|
318
|
-
and command.reconcile_proof_outcome in ('exited', 'lost')
|
|
319
|
-
and command.reconcile_proof_observed_at is not null
|
|
320
|
-
returning command.id
|
|
321
|
-
`);
|
|
322
|
-
if (rows.length !== 1) return false;
|
|
323
|
-
const [row] = await tx.select().from(sessionBackgroundCommands).where(eq(sessionBackgroundCommands.id, input.claim.commandId)).limit(1);
|
|
324
|
-
if (!row) throw new Error("Settled Connected Machine command disappeared");
|
|
325
|
-
await mutateTerminal.commit(tx, mapCommand(row));
|
|
326
|
-
return true;
|
|
327
|
-
}
|
|
328
|
-
);
|
|
329
|
-
}
|
|
330
|
-
async function requestSessionBackgroundCommandCancellation(db, input) {
|
|
331
|
-
return await withRlsContext(
|
|
332
|
-
db,
|
|
333
|
-
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
334
|
-
async (scopedDb) => await scopedDb.transaction(async (tx) => {
|
|
335
|
-
const [current] = await tx.select().from(sessionBackgroundCommands).where(
|
|
336
|
-
and(
|
|
337
|
-
eq(sessionBackgroundCommands.workspaceId, input.workspaceId),
|
|
338
|
-
eq(sessionBackgroundCommands.sessionId, input.sessionId),
|
|
339
|
-
eq(sessionBackgroundCommands.id, input.commandId)
|
|
340
|
-
)
|
|
341
|
-
).for("update").limit(1);
|
|
342
|
-
if (!current) return { command: null, accepted: false };
|
|
343
|
-
if (current.state !== "running") {
|
|
344
|
-
return { command: mapCommand(current), accepted: false };
|
|
345
|
-
}
|
|
346
|
-
const [updated] = await tx.update(sessionBackgroundCommands).set({
|
|
347
|
-
state: "stopping",
|
|
348
|
-
cancelRequestedAt: /* @__PURE__ */ new Date(),
|
|
349
|
-
cancelRequestedBy: input.subjectId.slice(0, 1024),
|
|
350
|
-
reconcileAfter: /* @__PURE__ */ new Date(),
|
|
351
|
-
reconcileClaimId: null,
|
|
352
|
-
reconcileClaimedAt: null,
|
|
353
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
354
|
-
}).where(eq(sessionBackgroundCommands.id, current.id)).returning();
|
|
355
|
-
if (current.retainedProcessId) {
|
|
356
|
-
await tx.update(sandboxRetainedProcesses).set({ reconcileAfter: /* @__PURE__ */ new Date(), lastReconcileOutcome: "cancel_requested" }).where(
|
|
357
|
-
and(
|
|
358
|
-
eq(sandboxRetainedProcesses.id, current.retainedProcessId),
|
|
359
|
-
eq(sandboxRetainedProcesses.state, "active"),
|
|
360
|
-
sql`${sandboxRetainedProcesses.reconcileClaimId} is null`
|
|
361
|
-
)
|
|
362
|
-
);
|
|
363
|
-
}
|
|
364
|
-
return { command: mapCommand(updated), accepted: true };
|
|
365
|
-
})
|
|
366
|
-
);
|
|
367
|
-
}
|
|
368
|
-
async function requestSessionBackgroundCommandCancellationsInTransaction(db, input) {
|
|
369
|
-
const rootSessionIds = [...new Set(input.rootSessionIds)];
|
|
370
|
-
if (rootSessionIds.length === 0) return 0;
|
|
371
|
-
const rows = await db.execute(sql`
|
|
372
|
-
with recursive roots(id) as (
|
|
373
|
-
values ${sql.join(
|
|
374
|
-
rootSessionIds.map((sessionId) => sql`(${sessionId}::uuid)`),
|
|
375
|
-
sql`, `
|
|
376
|
-
)}
|
|
377
|
-
), subtree(id, path, cycle) as (
|
|
378
|
-
select session.id, array[session.id]::uuid[], false
|
|
379
|
-
from roots root
|
|
380
|
-
join ${sessions} session
|
|
381
|
-
on session.workspace_id = ${input.workspaceId}
|
|
382
|
-
and session.id = root.id
|
|
383
|
-
union all
|
|
384
|
-
select child.id, parent.path || child.id, child.id = any(parent.path)
|
|
385
|
-
from subtree parent
|
|
386
|
-
join ${sessions} child
|
|
387
|
-
on child.workspace_id = ${input.workspaceId}
|
|
388
|
-
and child.parent_session_id = parent.id
|
|
389
|
-
where not parent.cycle
|
|
390
|
-
), stopped as (
|
|
391
|
-
update ${sessionBackgroundCommands} command set
|
|
392
|
-
state = 'stopping',
|
|
393
|
-
cancel_requested_at = clock_timestamp(),
|
|
394
|
-
cancel_requested_by = left(${input.subjectId}, 1024),
|
|
395
|
-
reconcile_after = clock_timestamp(),
|
|
396
|
-
reconcile_claim_id = null,
|
|
397
|
-
reconcile_claimed_at = null,
|
|
398
|
-
updated_at = clock_timestamp()
|
|
399
|
-
where command.workspace_id = ${input.workspaceId}
|
|
400
|
-
and command.session_id in (select id from subtree where not cycle)
|
|
401
|
-
and command.state = 'running'
|
|
402
|
-
returning command.retained_process_id
|
|
403
|
-
), nudged as (
|
|
404
|
-
update ${sandboxRetainedProcesses} process set
|
|
405
|
-
reconcile_after = clock_timestamp(),
|
|
406
|
-
reconcile_claim_id = null,
|
|
407
|
-
reconcile_claimed_at = null,
|
|
408
|
-
last_reconcile_outcome = 'cancel_requested'
|
|
409
|
-
where process.id in (
|
|
410
|
-
select stopped.retained_process_id
|
|
411
|
-
from stopped
|
|
412
|
-
where stopped.retained_process_id is not null
|
|
413
|
-
)
|
|
414
|
-
and process.state = 'active'
|
|
415
|
-
returning process.id
|
|
416
|
-
)
|
|
417
|
-
select count(*)::integer as "commandCount" from stopped
|
|
418
|
-
`);
|
|
419
|
-
return Number(rows[0]?.commandCount ?? 0);
|
|
420
|
-
}
|
|
421
|
-
async function requestWorkspaceBackgroundCommandCancellationsInTransaction(db, input) {
|
|
422
|
-
const rows = await db.execute(sql`
|
|
423
|
-
with stopped as (
|
|
424
|
-
update ${sessionBackgroundCommands} command set
|
|
425
|
-
state = 'stopping',
|
|
426
|
-
cancel_requested_at = clock_timestamp(),
|
|
427
|
-
cancel_requested_by = left(${input.subjectId}, 1024),
|
|
428
|
-
reconcile_after = clock_timestamp(),
|
|
429
|
-
reconcile_claim_id = null,
|
|
430
|
-
reconcile_claimed_at = null,
|
|
431
|
-
updated_at = clock_timestamp()
|
|
432
|
-
where command.workspace_id = ${input.workspaceId}
|
|
433
|
-
and command.state = 'running'
|
|
434
|
-
returning command.retained_process_id
|
|
435
|
-
), nudged as (
|
|
436
|
-
update ${sandboxRetainedProcesses} process set
|
|
437
|
-
reconcile_after = clock_timestamp(),
|
|
438
|
-
reconcile_claim_id = null,
|
|
439
|
-
reconcile_claimed_at = null,
|
|
440
|
-
last_reconcile_outcome = 'cancel_requested'
|
|
441
|
-
where process.id in (
|
|
442
|
-
select stopped.retained_process_id
|
|
443
|
-
from stopped
|
|
444
|
-
where stopped.retained_process_id is not null
|
|
445
|
-
)
|
|
446
|
-
and process.state = 'active'
|
|
447
|
-
returning process.id
|
|
448
|
-
)
|
|
449
|
-
select count(*)::integer as "commandCount" from stopped
|
|
450
|
-
`);
|
|
451
|
-
return Number(rows[0]?.commandCount ?? 0);
|
|
452
|
-
}
|
|
453
|
-
async function settleSessionBackgroundCommandForRetainedProcessInTransaction(tx, input, mutateTerminal) {
|
|
454
|
-
const reason = boundedSessionBackgroundCommandReason(
|
|
455
|
-
input.reason,
|
|
456
|
-
"Managed command settlement reason"
|
|
457
|
-
);
|
|
458
|
-
await mutateTerminal.prepare(tx);
|
|
459
|
-
const [updatedRow] = await tx.update(sessionBackgroundCommands).set({
|
|
460
|
-
state: input.outcome,
|
|
461
|
-
exitCode: input.outcome === "exited" ? input.exitCode : null,
|
|
462
|
-
settlementReason: reason,
|
|
463
|
-
settledAt: /* @__PURE__ */ new Date(),
|
|
464
|
-
reconcileClaimId: null,
|
|
465
|
-
reconcileClaimedAt: null,
|
|
466
|
-
lastReconcileOutcome: `settled_${input.outcome}`,
|
|
467
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
468
|
-
}).where(
|
|
469
|
-
and(
|
|
470
|
-
eq(sessionBackgroundCommands.workspaceId, input.workspaceId),
|
|
471
|
-
eq(sessionBackgroundCommands.sessionId, input.sessionId),
|
|
472
|
-
eq(sessionBackgroundCommands.retainedProcessId, input.retainedProcessId),
|
|
473
|
-
inArray(sessionBackgroundCommands.state, ["running", "stopping"])
|
|
474
|
-
)
|
|
475
|
-
).returning();
|
|
476
|
-
let row = updatedRow;
|
|
477
|
-
if (!row) {
|
|
478
|
-
const [current] = await tx.select().from(sessionBackgroundCommands).where(
|
|
479
|
-
and(
|
|
480
|
-
eq(sessionBackgroundCommands.workspaceId, input.workspaceId),
|
|
481
|
-
eq(sessionBackgroundCommands.sessionId, input.sessionId),
|
|
482
|
-
eq(sessionBackgroundCommands.retainedProcessId, input.retainedProcessId)
|
|
483
|
-
)
|
|
484
|
-
).for("update").limit(1);
|
|
485
|
-
if (!current) return null;
|
|
486
|
-
if (current.state !== input.outcome || current.exitCode !== (input.outcome === "exited" ? input.exitCode : null)) {
|
|
487
|
-
throw new Error("Managed background command terminal state conflicts with process proof");
|
|
488
|
-
}
|
|
489
|
-
const [existingEvent] = await tx.select({ id: sessionEvents.id }).from(sessionEvents).where(
|
|
490
|
-
and(
|
|
491
|
-
eq(sessionEvents.workspaceId, input.workspaceId),
|
|
492
|
-
eq(sessionEvents.sessionId, input.sessionId),
|
|
493
|
-
eq(sessionEvents.type, "session.command.finished"),
|
|
494
|
-
sql`${sessionEvents.payload} ->> 'commandId' = ${current.id}`
|
|
495
|
-
)
|
|
496
|
-
).limit(1);
|
|
497
|
-
if (existingEvent) return mapCommand(current);
|
|
498
|
-
row = current;
|
|
499
|
-
}
|
|
500
|
-
const command = mapCommand(row);
|
|
501
|
-
await mutateTerminal.commit(tx, command);
|
|
502
|
-
return command;
|
|
503
|
-
}
|
|
504
|
-
async function settleConnectedMachineSessionBackgroundCommandWithMutation(db, input, mutateTerminal) {
|
|
505
|
-
const reason = boundedSessionBackgroundCommandReason(
|
|
506
|
-
input.reason,
|
|
507
|
-
"Connected command settlement reason"
|
|
508
|
-
);
|
|
509
|
-
if (input.outcome === "exited" && input.exitCode === null) {
|
|
510
|
-
throw new Error("Connected command exit settlement requires an exit code");
|
|
511
|
-
}
|
|
512
|
-
if (input.outcome === "lost" && input.exitCode !== null) {
|
|
513
|
-
throw new Error("Connected command loss settlement cannot carry an exit code");
|
|
514
|
-
}
|
|
515
|
-
return await withSessionActivityRlsContext(
|
|
516
|
-
db,
|
|
517
|
-
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
518
|
-
async (tx) => {
|
|
519
|
-
await mutateTerminal.prepare(tx);
|
|
520
|
-
const settledAt = /* @__PURE__ */ new Date();
|
|
521
|
-
const [row] = await tx.update(sessionBackgroundCommands).set({
|
|
522
|
-
state: input.outcome,
|
|
523
|
-
exitCode: input.outcome === "exited" ? input.exitCode : null,
|
|
524
|
-
settlementReason: reason,
|
|
525
|
-
settledAt,
|
|
526
|
-
reconcileClaimId: null,
|
|
527
|
-
reconcileClaimedAt: null,
|
|
528
|
-
reconcileProofOutcome: input.outcome,
|
|
529
|
-
reconcileProofExitCode: input.outcome === "exited" ? input.exitCode : null,
|
|
530
|
-
reconcileProofReason: reason,
|
|
531
|
-
reconcileProofObservedAt: settledAt,
|
|
532
|
-
lastReconcileOutcome: `settled_${input.outcome}`,
|
|
533
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
534
|
-
}).where(
|
|
535
|
-
and(
|
|
536
|
-
eq(sessionBackgroundCommands.workspaceId, input.workspaceId),
|
|
537
|
-
eq(sessionBackgroundCommands.sessionId, input.sessionId),
|
|
538
|
-
eq(sessionBackgroundCommands.id, input.commandId),
|
|
539
|
-
eq(sessionBackgroundCommands.provider, "connected_machine"),
|
|
540
|
-
eq(sessionBackgroundCommands.controlWorkspaceId, input.controlWorkspaceId),
|
|
541
|
-
eq(sessionBackgroundCommands.enrollmentId, input.enrollmentId),
|
|
542
|
-
eq(sessionBackgroundCommands.connectionInstanceId, input.connectionInstanceId),
|
|
543
|
-
eq(sessionBackgroundCommands.opId, input.opId),
|
|
544
|
-
inArray(sessionBackgroundCommands.state, ["running", "stopping"])
|
|
545
|
-
)
|
|
546
|
-
).returning();
|
|
547
|
-
if (!row) return null;
|
|
548
|
-
const command = mapCommand(row);
|
|
549
|
-
await mutateTerminal.commit(tx, command);
|
|
550
|
-
return command;
|
|
551
|
-
}
|
|
552
|
-
);
|
|
553
|
-
}
|
|
554
|
-
async function getSessionBackgroundCommand(db, input) {
|
|
555
|
-
return await withRlsContext(
|
|
556
|
-
db,
|
|
557
|
-
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
558
|
-
async (scopedDb) => {
|
|
559
|
-
const [row] = await scopedDb.select().from(sessionBackgroundCommands).where(
|
|
560
|
-
and(
|
|
561
|
-
eq(sessionBackgroundCommands.workspaceId, input.workspaceId),
|
|
562
|
-
eq(sessionBackgroundCommands.sessionId, input.sessionId),
|
|
563
|
-
eq(sessionBackgroundCommands.id, input.commandId)
|
|
564
|
-
)
|
|
565
|
-
).limit(1);
|
|
566
|
-
return row ? mapCommand(row) : null;
|
|
567
|
-
}
|
|
568
|
-
);
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
export {
|
|
572
|
-
SESSION_BACKGROUND_COMMAND_REASON_MAX_BYTES,
|
|
573
|
-
boundedSessionBackgroundCommandReason,
|
|
574
|
-
backgroundCommandActivityForSessions,
|
|
575
|
-
listSessionBackgroundCommands,
|
|
576
|
-
insertManagedSessionBackgroundCommandInTransaction,
|
|
577
|
-
insertConnectedMachineSessionBackgroundCommandInTransaction,
|
|
578
|
-
claimConnectedMachineSessionBackgroundCommands,
|
|
579
|
-
recordConnectedMachineBackgroundCommandProof,
|
|
580
|
-
deferConnectedMachineBackgroundCommandReconciliation,
|
|
581
|
-
settleClaimedConnectedMachineBackgroundCommandWithMutation,
|
|
582
|
-
requestSessionBackgroundCommandCancellation,
|
|
583
|
-
requestSessionBackgroundCommandCancellationsInTransaction,
|
|
584
|
-
requestWorkspaceBackgroundCommandCancellationsInTransaction,
|
|
585
|
-
settleSessionBackgroundCommandForRetainedProcessInTransaction,
|
|
586
|
-
settleConnectedMachineSessionBackgroundCommandWithMutation,
|
|
587
|
-
getSessionBackgroundCommand
|
|
588
|
-
};
|
|
589
|
-
//# sourceMappingURL=chunk-N5VXJ4I2.js.map
|