@opengeni/worker-bundle 2.2.0 → 2.2.1-canary.36927100590001
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/activities/agent-run-admission.d.ts +3 -1
- package/dist/activities/agent-turn/admission.d.ts +24 -3
- package/dist/activities/agent-turn/agent-build.d.ts +1 -0
- package/dist/activities/agent-turn/claude-usage-observer.d.ts +13 -1
- package/dist/activities/agent-turn/compaction-prep.d.ts +20 -0
- package/dist/activities/agent-turn/credential-restriction.d.ts +3 -0
- package/dist/activities/agent-turn/final-reply.d.ts +18 -0
- package/dist/activities/agent-turn/governance-model.d.ts +6 -0
- package/dist/activities/agent-turn/model-call-admission.d.ts +15 -0
- package/dist/activities/agent-turn/run-credentials.d.ts +4 -0
- package/dist/activities/agent-turn/sandbox-establish.d.ts +1 -0
- package/dist/activities/agent-turn/session-title.d.ts +3 -1
- package/dist/activities/agent-turn/stream-attempt.d.ts +1 -0
- package/dist/activities/agent-turn/turn-context.d.ts +1 -0
- package/dist/activities/automations.d.ts +3 -1
- package/dist/activities/browser-deadline-checkpoint.d.ts +29 -0
- package/dist/activities/goals.d.ts +8 -0
- package/dist/activities/run-credentials.d.ts +4 -2
- package/dist/activities/scheduled-tasks.d.ts +4 -35
- package/dist/activities/types.d.ts +4 -1
- package/dist/activities/workspace-capture.d.ts +2 -0
- package/dist/{activities-control-MHNA3CYV.js → activities-control-4F2A734B.js} +502 -133
- package/dist/activities-control-4F2A734B.js.map +1 -0
- package/dist/activities-control.d.ts +30 -0
- package/dist/{activities-turn-FQ5OO2WW.js → activities-turn-TESOIOEX.js} +696 -251
- package/dist/activities-turn-TESOIOEX.js.map +1 -0
- package/dist/activities.d.ts +30 -0
- package/dist/browser-deadline-checkpoint-contract.d.ts +2 -0
- package/dist/{chunk-RZAAGRFQ.js → chunk-4PJTUBWQ.js} +220 -88
- package/dist/chunk-4PJTUBWQ.js.map +1 -0
- package/dist/{chunk-IJZU752L.js → chunk-YG27NEMX.js} +34 -1
- package/dist/chunk-YG27NEMX.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +46 -24
- package/dist/index.js.map +1 -1
- package/dist/observability-metrics.d.ts +16 -1
- package/dist/sandbox-resume.d.ts +4 -1
- package/dist/workflow-bundle.js +89 -21
- package/dist/workflows/browser-deadline-checkpoint.d.ts +9 -0
- package/dist/workflows/scheduled-tasks.d.ts +4 -0
- package/dist/workflows.d.ts +1 -0
- package/package.json +21 -20
- package/src/activities/agent-run-admission.ts +17 -1
- package/src/activities/agent-turn/admission.ts +64 -1
- package/src/activities/agent-turn/agent-build.ts +24 -3
- package/src/activities/agent-turn/claim.ts +69 -15
- package/src/activities/agent-turn/claude-usage-observer.ts +33 -1
- package/src/activities/agent-turn/compaction-prep.ts +67 -16
- package/src/activities/agent-turn/credential-restriction.ts +14 -0
- package/src/activities/agent-turn/errors.ts +55 -0
- package/src/activities/agent-turn/failure-settlement.ts +26 -6
- package/src/activities/agent-turn/final-reply.ts +46 -0
- package/src/activities/agent-turn/governance-model.ts +12 -0
- package/src/activities/agent-turn/model-call-admission.ts +94 -0
- package/src/activities/agent-turn/run-credentials.ts +20 -3
- package/src/activities/agent-turn/run.ts +44 -5
- package/src/activities/agent-turn/sandbox-establish.ts +9 -5
- package/src/activities/agent-turn/session-title.ts +8 -2
- package/src/activities/agent-turn/stream-attempt.ts +144 -38
- package/src/activities/agent-turn/tool-environment.ts +55 -39
- package/src/activities/agent-turn/turn-context.ts +1 -0
- package/src/activities/automations.ts +78 -4
- package/src/activities/browser-deadline-checkpoint.ts +279 -0
- package/src/activities/capabilities.ts +52 -14
- package/src/activities/goals.ts +95 -98
- package/src/activities/knowledge-indexing.ts +29 -0
- package/src/activities/open-suffix-resume.ts +2 -1
- package/src/activities/run-credentials.ts +22 -16
- package/src/activities/sandbox-lease.ts +22 -0
- package/src/activities/scheduled-tasks.ts +172 -38
- package/src/activities/site-auth-maintenance.ts +1 -0
- package/src/activities/types.ts +4 -0
- package/src/activities/workspace-capture.ts +13 -2
- package/src/activities/workspace-credential-provider.ts +12 -0
- package/src/activities-control.ts +2 -0
- package/src/activities.ts +3 -0
- package/src/browser-deadline-checkpoint-contract.ts +5 -0
- package/src/index.ts +53 -25
- package/src/observability-metrics.ts +55 -1
- package/src/sandbox-resume.ts +23 -8
- package/src/sandbox-routing.ts +4 -2
- package/src/workflows/browser-deadline-checkpoint.ts +50 -0
- package/src/workflows/scheduled-tasks.ts +26 -13
- package/src/workflows.ts +4 -0
- package/dist/activities-control-MHNA3CYV.js.map +0 -1
- package/dist/activities-turn-FQ5OO2WW.js.map +0 -1
- package/dist/chunk-IJZU752L.js.map +0 -1
- package/dist/chunk-RZAAGRFQ.js.map +0 -1
|
@@ -2,12 +2,18 @@ import { createHash } from "node:crypto";
|
|
|
2
2
|
import { errorCodeToJSON } from "@opengeni/agent-proto";
|
|
3
3
|
import {
|
|
4
4
|
BundledSkillId,
|
|
5
|
+
CREDIT_GRANT_CLASSES,
|
|
5
6
|
SandboxBackend,
|
|
6
7
|
type SessionEventType,
|
|
7
8
|
type SkillReadKind,
|
|
8
9
|
type SkillUseSource,
|
|
9
10
|
} from "@opengeni/contracts";
|
|
10
|
-
import
|
|
11
|
+
import {
|
|
12
|
+
ACTIVE_USER_WINDOWS,
|
|
13
|
+
type ActiveUserWindow,
|
|
14
|
+
type CreditGrantTotals,
|
|
15
|
+
type SessionEventAppendPhaseObservation,
|
|
16
|
+
} from "@opengeni/db";
|
|
11
17
|
import {
|
|
12
18
|
natsSubscriptionTerminationCounter,
|
|
13
19
|
type EventBusOptions,
|
|
@@ -1122,6 +1128,54 @@ export function recordCreditBalanceGauges(
|
|
|
1122
1128
|
creditBalanceGaugeAccounts.set(observability, current);
|
|
1123
1129
|
}
|
|
1124
1130
|
|
|
1131
|
+
/**
|
|
1132
|
+
* Distinct managed people with authenticated browser activity in each fixed
|
|
1133
|
+
* window (migration 0565 presence). Every control worker publishes the same
|
|
1134
|
+
* global value, so dashboards must aggregate with `max()` across pods, never
|
|
1135
|
+
* `sum()`. API keys, services and embedded hosts are never counted.
|
|
1136
|
+
*/
|
|
1137
|
+
export function recordActiveUserGauges(
|
|
1138
|
+
observability: Observability,
|
|
1139
|
+
counts: Record<ActiveUserWindow, number>,
|
|
1140
|
+
): void {
|
|
1141
|
+
for (const window of ACTIVE_USER_WINDOWS) {
|
|
1142
|
+
observability.setGauge({
|
|
1143
|
+
name: "opengeni_active_users",
|
|
1144
|
+
help: "Distinct managed users with authenticated activity within the window (global; use max across pods).",
|
|
1145
|
+
labels: { window },
|
|
1146
|
+
value: counts[window],
|
|
1147
|
+
});
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
/**
|
|
1152
|
+
* Positive credit grants observed by the ledger trigger since migration 0565,
|
|
1153
|
+
* by closed class. These are cumulative database totals published as gauges by
|
|
1154
|
+
* every control worker: aggregate with `max()` across pods, then `increase()`.
|
|
1155
|
+
* Counting in the database covers the grants no application process writes:
|
|
1156
|
+
* the verified-signup trial grant (a setup trigger) and operator grants.
|
|
1157
|
+
*/
|
|
1158
|
+
export function recordCreditGrantGauges(
|
|
1159
|
+
observability: Observability,
|
|
1160
|
+
totals: CreditGrantTotals,
|
|
1161
|
+
): void {
|
|
1162
|
+
for (const grantClass of CREDIT_GRANT_CLASSES) {
|
|
1163
|
+
const total = totals[grantClass];
|
|
1164
|
+
observability.setGauge({
|
|
1165
|
+
name: "opengeni_credit_grants_total",
|
|
1166
|
+
help: "Positive credit grants observed in the ledger since migration 0565, by grant class (global cumulative; use max across pods).",
|
|
1167
|
+
labels: { grant_class: grantClass },
|
|
1168
|
+
value: total.count,
|
|
1169
|
+
});
|
|
1170
|
+
observability.setGauge({
|
|
1171
|
+
name: "opengeni_credit_granted_micros_total",
|
|
1172
|
+
help: "Credit micros granted in the ledger since migration 0565, by grant class (global cumulative; use max across pods).",
|
|
1173
|
+
labels: { grant_class: grantClass },
|
|
1174
|
+
value: total.micros,
|
|
1175
|
+
});
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1125
1179
|
/**
|
|
1126
1180
|
* The deployment-level runtime switch for the one-time verified signup trial
|
|
1127
1181
|
* credit (migration 0521): 1 while it allows grants, 0 when an operator has
|
package/src/sandbox-resume.ts
CHANGED
|
@@ -210,6 +210,9 @@ export type ResumeBoxIds = {
|
|
|
210
210
|
* never conflicts).
|
|
211
211
|
*/
|
|
212
212
|
image?: string;
|
|
213
|
+
/** Deployment/workspace image pins apply only to new creates; an existing
|
|
214
|
+
* group keeps its image. Omission preserves explicit image matching (B3). */
|
|
215
|
+
imagePolicy?: "require_match" | "new_creates_only";
|
|
213
216
|
/**
|
|
214
217
|
* RIG IS SHARED STATE (M3): the frozen rig version this run rides. Threaded to
|
|
215
218
|
* acquireLease, which stamps it on the cold-create and conflicts on a live box
|
|
@@ -445,9 +448,10 @@ export async function waitForSandboxExecReadiness(
|
|
|
445
448
|
established: EstablishedSandboxSession,
|
|
446
449
|
timeoutMs = MODAL_EXEC_READINESS_TIMEOUT_MS,
|
|
447
450
|
identity: { sandboxGroupId?: string | null } = {},
|
|
451
|
+
signal?: AbortSignal,
|
|
448
452
|
): Promise<void> {
|
|
449
453
|
try {
|
|
450
|
-
await verifySandboxExecReadiness(established, timeoutMs);
|
|
454
|
+
await verifySandboxExecReadiness(established, timeoutMs, signal);
|
|
451
455
|
} catch (error) {
|
|
452
456
|
if (error instanceof SandboxExecReadinessError && error.code === "exec_probe_timeout") {
|
|
453
457
|
throw new SandboxExecReadinessTimeoutError(established.backendId, timeoutMs, {
|
|
@@ -1347,11 +1351,12 @@ async function resumeBoxForTurnOnce(
|
|
|
1347
1351
|
},
|
|
1348
1352
|
os,
|
|
1349
1353
|
// IMAGE IS SHARED STATE (B3): thread the resolved image so the lease stamps it +
|
|
1350
|
-
// conflicts on a live box already running a different image. A
|
|
1354
|
+
// conflicts on a live box already running a different required image. A
|
|
1351
1355
|
// SandboxImageConflictError propagates while another holder is active; a
|
|
1352
1356
|
// solo change requests a capture-and-drain rotation and this attempt retries
|
|
1353
1357
|
// after the cold successor can safely stamp the new image.
|
|
1354
1358
|
...(ids.image ? { image: ids.image } : {}),
|
|
1359
|
+
...(ids.imagePolicy ? { imagePolicy: ids.imagePolicy } : {}),
|
|
1355
1360
|
// RIG IS SHARED STATE (M3): thread the frozen rig version so the lease stamps it
|
|
1356
1361
|
// + conflicts on a live box under a different rig. A SandboxRigConflictError
|
|
1357
1362
|
// propagates while another holder is active; a solo change uses the same
|
|
@@ -1917,9 +1922,14 @@ async function resumeBoxForTurnOnce(
|
|
|
1917
1922
|
sandboxGroupId: ids.sandboxGroupId,
|
|
1918
1923
|
});
|
|
1919
1924
|
} else {
|
|
1920
|
-
await waitForSandboxExecReadiness(
|
|
1921
|
-
|
|
1922
|
-
|
|
1925
|
+
await waitForSandboxExecReadiness(
|
|
1926
|
+
established,
|
|
1927
|
+
MODAL_EXEC_READINESS_TIMEOUT_MS,
|
|
1928
|
+
{
|
|
1929
|
+
sandboxGroupId: ids.sandboxGroupId,
|
|
1930
|
+
},
|
|
1931
|
+
cancellationSignal,
|
|
1932
|
+
);
|
|
1923
1933
|
}
|
|
1924
1934
|
await maybeRenewProviderExpiration(true);
|
|
1925
1935
|
throwIfReleasedOrCancelled();
|
|
@@ -2117,9 +2127,14 @@ async function resumeBoxForTurnOnce(
|
|
|
2117
2127
|
if (services.verifyAttachedSandboxReadiness) {
|
|
2118
2128
|
await services.verifyAttachedSandboxReadiness(established);
|
|
2119
2129
|
} else {
|
|
2120
|
-
await waitForSandboxExecReadiness(
|
|
2121
|
-
|
|
2122
|
-
|
|
2130
|
+
await waitForSandboxExecReadiness(
|
|
2131
|
+
established,
|
|
2132
|
+
MODAL_EXEC_READINESS_TIMEOUT_MS,
|
|
2133
|
+
{
|
|
2134
|
+
sandboxGroupId: ids.sandboxGroupId,
|
|
2135
|
+
},
|
|
2136
|
+
cancellationSignal,
|
|
2137
|
+
);
|
|
2123
2138
|
}
|
|
2124
2139
|
providerRenewalTarget = {
|
|
2125
2140
|
backend: ids.backend,
|
package/src/sandbox-routing.ts
CHANGED
|
@@ -496,7 +496,7 @@ function afterPersistableHomeMutation(
|
|
|
496
496
|
op: string;
|
|
497
497
|
backend: ResolvedActiveBackend;
|
|
498
498
|
admission: unknown;
|
|
499
|
-
outcome: "resolved" | "rejected";
|
|
499
|
+
outcome: "resolved" | "rejected" | "outcome_unknown";
|
|
500
500
|
result?: unknown;
|
|
501
501
|
retainedProcess?: RoutingRetainedProcess;
|
|
502
502
|
}) => Promise<void | RoutingMutationSettlementResult>)
|
|
@@ -523,7 +523,7 @@ function afterPersistableHomeMutation(
|
|
|
523
523
|
) {
|
|
524
524
|
throw new Error("Persistable home mutation settlement lacked its bound admission");
|
|
525
525
|
}
|
|
526
|
-
if (outcome === "resolved" && retainedProcess) {
|
|
526
|
+
if ((outcome === "resolved" || outcome === "outcome_unknown") && retainedProcess) {
|
|
527
527
|
try {
|
|
528
528
|
await retainWorkspaceProviderCommand(services.db, {
|
|
529
529
|
accountId: fence.accountId,
|
|
@@ -582,6 +582,8 @@ function afterPersistableHomeMutation(
|
|
|
582
582
|
}
|
|
583
583
|
return;
|
|
584
584
|
}
|
|
585
|
+
if (outcome === "outcome_unknown")
|
|
586
|
+
throw new Error("Outcome-unknown command settlement requires its exact retained invocation");
|
|
585
587
|
await verifyWorkspaceMutationSettlement(services.db, {
|
|
586
588
|
accountId: fence.accountId,
|
|
587
589
|
workspaceId: ids.workspaceId,
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ParentClosePolicy,
|
|
3
|
+
WorkflowIdReusePolicy,
|
|
4
|
+
log,
|
|
5
|
+
proxyActivities,
|
|
6
|
+
startChild,
|
|
7
|
+
workflowInfo,
|
|
8
|
+
} from "@temporalio/workflow";
|
|
9
|
+
import type { BrowserDeadlineCheckpointTarget } from "@opengeni/db";
|
|
10
|
+
import type * as activities from "../activities";
|
|
11
|
+
|
|
12
|
+
const inventory = proxyActivities<Pick<typeof activities, "listDueBrowserCheckpoints">>({
|
|
13
|
+
startToCloseTimeout: "5 minutes",
|
|
14
|
+
heartbeatTimeout: "20 seconds",
|
|
15
|
+
});
|
|
16
|
+
const checkpoint = proxyActivities<Pick<typeof activities, "checkpointBrowserBeforeDeadline">>({
|
|
17
|
+
startToCloseTimeout: "25 minutes",
|
|
18
|
+
heartbeatTimeout: "20 seconds",
|
|
19
|
+
retry: { initialInterval: "1 second", maximumInterval: "30 seconds" },
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
export async function browserDeadlineCheckpointWorkflow(target: BrowserDeadlineCheckpointTarget) {
|
|
23
|
+
return await checkpoint.checkpointBrowserBeforeDeadline(target);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Runs from the existing lease-sweep dispatch. Inventory never performs provider
|
|
27
|
+
* I/O; each exact browser has an independent durable capture/cleanup child. */
|
|
28
|
+
export async function browserDeadlineCheckpointSweepWorkflow(): Promise<void> {
|
|
29
|
+
const targets = await inventory.listDueBrowserCheckpoints();
|
|
30
|
+
await Promise.all(
|
|
31
|
+
targets.map(async (target) => {
|
|
32
|
+
try {
|
|
33
|
+
await startChild(browserDeadlineCheckpointWorkflow, {
|
|
34
|
+
workflowId: `browser-deadline:${target.browserSessionId}:${target.leaseEpoch}:${target.controllerGeneration}`,
|
|
35
|
+
taskQueue: workflowInfo().taskQueue,
|
|
36
|
+
workflowIdReusePolicy: WorkflowIdReusePolicy.ALLOW_DUPLICATE,
|
|
37
|
+
parentClosePolicy: ParentClosePolicy.ABANDON,
|
|
38
|
+
args: [target],
|
|
39
|
+
});
|
|
40
|
+
} catch (error) {
|
|
41
|
+
if (error instanceof Error && error.name === "WorkflowExecutionAlreadyStartedError") return;
|
|
42
|
+
// Another sweep retries start; it cannot retire the browser's authority.
|
|
43
|
+
log.warn("browser deadline checkpoint child start deferred", {
|
|
44
|
+
browserSessionId: target.browserSessionId,
|
|
45
|
+
error: error instanceof Error ? error.name : "unknown",
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
}),
|
|
49
|
+
);
|
|
50
|
+
}
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
WorkflowIdReusePolicy,
|
|
8
8
|
} from "@temporalio/workflow";
|
|
9
9
|
import type { TurnInitiator } from "@opengeni/contracts";
|
|
10
|
+
import type { DispatchScheduledTaskRunInput } from "../activities/types";
|
|
10
11
|
import { scheduledTaskActivity } from "./activities";
|
|
11
12
|
import {
|
|
12
13
|
knowledgeSourceSyncWake,
|
|
@@ -26,14 +27,38 @@ export type ScheduledTaskFireWorkflowInput = ScheduledTaskFireWorkflowBase &
|
|
|
26
27
|
triggerType: "scheduled";
|
|
27
28
|
agentRunUsageIdempotencyKey?: never;
|
|
28
29
|
initiator?: never;
|
|
30
|
+
credentialRestriction?: never;
|
|
29
31
|
}
|
|
30
32
|
| {
|
|
31
33
|
triggerType: "manual" | "initial" | "provider_event" | "retry" | "repair";
|
|
32
34
|
agentRunUsageIdempotencyKey: string;
|
|
33
35
|
initiator: TurnInitiator;
|
|
36
|
+
credentialRestriction?: "developer_setup";
|
|
34
37
|
}
|
|
35
38
|
);
|
|
36
39
|
|
|
40
|
+
export function scheduledTaskDispatchInput(
|
|
41
|
+
input: ScheduledTaskFireWorkflowInput,
|
|
42
|
+
producerKey: string,
|
|
43
|
+
): DispatchScheduledTaskRunInput {
|
|
44
|
+
const base = {
|
|
45
|
+
workspaceId: input.workspaceId,
|
|
46
|
+
taskId: input.taskId,
|
|
47
|
+
producerKey,
|
|
48
|
+
};
|
|
49
|
+
return input.triggerType !== "scheduled"
|
|
50
|
+
? {
|
|
51
|
+
...base,
|
|
52
|
+
triggerType: input.triggerType,
|
|
53
|
+
agentRunUsageIdempotencyKey: input.agentRunUsageIdempotencyKey,
|
|
54
|
+
initiator: input.initiator,
|
|
55
|
+
...(input.credentialRestriction === "developer_setup"
|
|
56
|
+
? { credentialRestriction: input.credentialRestriction }
|
|
57
|
+
: {}),
|
|
58
|
+
}
|
|
59
|
+
: { ...base, triggerType: "scheduled" };
|
|
60
|
+
}
|
|
61
|
+
|
|
37
62
|
export async function scheduledTaskFireWorkflow(
|
|
38
63
|
input: ScheduledTaskFireWorkflowInput,
|
|
39
64
|
): Promise<void> {
|
|
@@ -47,20 +72,8 @@ export async function scheduledTaskFireWorkflow(
|
|
|
47
72
|
) {
|
|
48
73
|
return;
|
|
49
74
|
}
|
|
50
|
-
const base = {
|
|
51
|
-
workspaceId: input.workspaceId,
|
|
52
|
-
taskId: input.taskId,
|
|
53
|
-
producerKey: workflowInfo().workflowId,
|
|
54
|
-
};
|
|
55
75
|
const result = await scheduledTaskActivity.dispatchScheduledTaskRun(
|
|
56
|
-
input.
|
|
57
|
-
? {
|
|
58
|
-
...base,
|
|
59
|
-
triggerType: input.triggerType,
|
|
60
|
-
agentRunUsageIdempotencyKey: input.agentRunUsageIdempotencyKey,
|
|
61
|
-
initiator: input.initiator,
|
|
62
|
-
}
|
|
63
|
-
: { ...base, triggerType: "scheduled" },
|
|
76
|
+
scheduledTaskDispatchInput(input, workflowInfo().workflowId),
|
|
64
77
|
);
|
|
65
78
|
if (result.action !== "knowledge_source_sync") return;
|
|
66
79
|
|
package/src/workflows.ts
CHANGED
|
@@ -28,6 +28,10 @@ export {
|
|
|
28
28
|
sandboxReaperWorkflowV2,
|
|
29
29
|
} from "./workflows/sandbox-reaper";
|
|
30
30
|
export { fileUploadReaperWorkflow } from "./workflows/file-upload-reaper";
|
|
31
|
+
export {
|
|
32
|
+
browserDeadlineCheckpointWorkflow,
|
|
33
|
+
browserDeadlineCheckpointSweepWorkflow,
|
|
34
|
+
} from "./workflows/browser-deadline-checkpoint";
|
|
31
35
|
export { siteAuthMaintenanceWorkflow } from "./workflows/site-auth-maintenance";
|
|
32
36
|
export {
|
|
33
37
|
videoGenerationWorkflow,
|