@opengeni/worker-bundle 3.2.2 → 3.4.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/activities/agent-turn/admission.d.ts +1 -1
- package/dist/{activities-control-LC7WXEIX.js → activities-control-EWP3UDZP.js} +5 -5
- package/dist/{activities-turn-PEDPUZI4.js → activities-turn-COUX2R3A.js} +17 -4
- package/dist/activities-turn-COUX2R3A.js.map +1 -0
- package/dist/artifact-materializer-entry.js +1 -0
- package/dist/artifact-materializer-entry.js.map +1 -1
- package/dist/artifact-outbox-entry.js +3 -1
- package/dist/artifact-outbox-entry.js.map +1 -1
- package/dist/{chunk-5NNS4327.js → chunk-BX3KRGDM.js} +10 -4
- package/dist/{chunk-5NNS4327.js.map → chunk-BX3KRGDM.js.map} +1 -1
- package/dist/{chunk-NQDVJ6RI.js → chunk-PFCSGZGA.js} +10 -5
- package/dist/{chunk-NQDVJ6RI.js.map → chunk-PFCSGZGA.js.map} +1 -1
- package/dist/{chunk-O7HT4LHX.js → chunk-PG66GHGH.js} +3 -3
- package/dist/{chunk-436TOEBL.js → chunk-XUIWRRTY.js} +5 -4
- package/dist/chunk-XUIWRRTY.js.map +1 -0
- package/dist/editable-artifact-outbox-dispatcher.d.ts +2 -0
- package/dist/index.js +30 -5
- package/dist/index.js.map +1 -1
- package/dist/internal-maintenance.d.ts +3 -1
- package/dist/observability-metrics.d.ts +14 -0
- package/dist/{sandbox-lease-F47EDHHY.js → sandbox-lease-XBZWILZ3.js} +4 -4
- package/dist/sandbox-routing.d.ts +1 -0
- package/package.json +26 -26
- package/src/activities/agent-turn/run.ts +15 -0
- package/src/activities/agent-turn/sandbox-establish.ts +2 -0
- package/src/activity-services.ts +3 -0
- package/src/editable-artifact-materializer-service.ts +3 -0
- package/src/editable-artifact-outbox-dispatcher.ts +5 -0
- package/src/editable-artifact-outbox-service.ts +3 -0
- package/src/index.ts +6 -0
- package/src/internal-maintenance.ts +24 -0
- package/src/observability-metrics.ts +20 -3
- package/src/sandbox-routing.ts +6 -0
- package/dist/activities-turn-PEDPUZI4.js.map +0 -1
- package/dist/chunk-436TOEBL.js.map +0 -1
- /package/dist/{activities-control-LC7WXEIX.js.map → activities-control-EWP3UDZP.js.map} +0 -0
- /package/dist/{chunk-O7HT4LHX.js.map → chunk-PG66GHGH.js.map} +0 -0
- /package/dist/{sandbox-lease-F47EDHHY.js.map → sandbox-lease-XBZWILZ3.js.map} +0 -0
|
@@ -14,7 +14,9 @@ export declare const SITE_AUTH_MAINTENANCE_WORKFLOW_ID = "opengeni-site-auth-mai
|
|
|
14
14
|
export declare const SITE_AUTH_MAINTENANCE_PERIOD_MS: number;
|
|
15
15
|
/** The Schedule earlier releases used to drive the sandbox lease reaper. */
|
|
16
16
|
export declare const SANDBOX_REAPER_SCHEDULE_ID = "opengeni-sandbox-lease-reaper";
|
|
17
|
-
|
|
17
|
+
/** Small bounded DB-only pass; no Temporal execution for plan maintenance. */
|
|
18
|
+
export declare const SUBSCRIPTION_PLAN_MAINTENANCE_PERIOD_MS = 60000;
|
|
19
|
+
export declare const INTERNAL_MAINTENANCE_JOBS: readonly ["session-workflow-wake-dispatcher", "knowledge-indexing", "site-auth-maintenance", "sandbox-lease-reaper", "sandbox-idle-checkpoint", "browser-deadline-checkpoint", "subscription-plan-maintenance"];
|
|
18
20
|
export type InternalMaintenanceJob = (typeof INTERNAL_MAINTENANCE_JOBS)[number];
|
|
19
21
|
type WorkflowStarter = Pick<TemporalClient["workflow"], "start" | "signalWithStart">;
|
|
20
22
|
type ScheduleDeleter = {
|
|
@@ -423,11 +423,25 @@ export declare function recordModelCreditsCharged(observability: Observability |
|
|
|
423
423
|
* Provider ids come from the resolved provider registry; phase/outcome are closed
|
|
424
424
|
* enums. This function never performs I/O outside the in-memory metrics registry.
|
|
425
425
|
*/
|
|
426
|
+
/**
|
|
427
|
+
* How a model request reached its provider, where the provider has more than
|
|
428
|
+
* one transport (Codex: a new or reused Responses WebSocket, or HTTP). Empty
|
|
429
|
+
* for providers with a single transport.
|
|
430
|
+
*/
|
|
431
|
+
export type ModelRequestTransportLabel = "" | "websocket_new" | "websocket_reused" | "http";
|
|
432
|
+
/** The bounded metric label for how a Codex request was carried. */
|
|
433
|
+
export declare function codexRequestTransportLabel(transport: {
|
|
434
|
+
kind: "websocket";
|
|
435
|
+
connection: "new" | "reused";
|
|
436
|
+
} | {
|
|
437
|
+
kind: "http";
|
|
438
|
+
}): ModelRequestTransportLabel;
|
|
426
439
|
export declare function recordModelRequestPhase(observability: Observability, input: {
|
|
427
440
|
provider: string;
|
|
428
441
|
phase: "headers" | "first_byte" | "terminal";
|
|
429
442
|
outcome?: "completed" | "failed" | "timed_out";
|
|
430
443
|
durationSeconds: number;
|
|
444
|
+
transport?: ModelRequestTransportLabel;
|
|
431
445
|
}): void;
|
|
432
446
|
export type TurnStartupPhase = "services_initialization" | "claim_catalog_read" | "claim_atomic" | "claim_session_read" | "claim_capability_settings" | "learning_policy_freeze" | "attachment_authority_projection" | "claim_and_policy" | "turn_start_settlement" | "credential_selection" | "runtime_preparation" | "session_mcp_settings" | "sandbox_establish" | "file_resolution" | "tool_context_preparation" | "tool_preparation" | "tool_server_construction" | "tool_required_connect" | "tool_optional_connect" | "tool_attempt_catalog_build" | "tool_attempt_catalog_persist" | "tool_workspace_gateway_catalog_build" | "post_tool_preparation" | "agent_construction" | "post_agent_preparation" | "file_materialization" | "history_preparation" | "history_system_update_load" | "history_current_attachment_resolution" | "history_durable_history_load" | "history_sandbox_envelope_load" | "history_canonical_projection" | "history_provider_projection" | "history_attachment_ref_projection" | "history_screenshot_materialization" | "history_model_attachment_projection" | "history_runtime_input_assembly" | "history_artifact_candidate_scan" | "history_generated_image_materialization" | "history_position_load" | "owned_sandbox_setup" | "runtime_stream_initialization" | "model_request_preparation" | "model_sdk_serialization" | "model_prepare_sandbox_agent_preparation" | "model_prepare_sandbox_agent_manifest_inventory" | "model_prepare_sandbox_session_manifest_inventory" | "model_prepare_sandbox_manifest_apply" | "model_prepare_sandbox_entry_materialization" | "model_prepare_sandbox_running_check" | "model_prepare_sandbox_start" | "model_prepare_sandbox_client_create" | "model_prepare_sandbox_client_resume" | "model_prepare_sandbox_client_delete" | "model_prepare_sandbox_client_state_serialize" | "model_prepare_sandbox_client_reuse_check" | "model_prepare_sandbox_workspace_mutation_admission" | "model_prepare_sandbox_workspace_mutation_provider" | "model_prepare_sandbox_workspace_mutation_settlement" | "model_prepare_sandbox_first_routed_resolution_other" | "model_prepare_sandbox_first_routed_mutation_admission" | "model_prepare_sandbox_first_routed_provider_operation" | "model_prepare_sandbox_first_routed_mutation_settlement" | "model_prepare_sandbox_first_routed_other" | "model_prepare_sandbox_snapshot_wait" | "model_prepare_runner_before_first_sandbox_operation" | "model_prepare_sdk_after_first_sandbox_operation" | "model_prepare_runner_before_mcp_tools" | "model_prepare_mcp_tools_snapshot" | "model_prepare_mcp_tools_before_input_filter" | "model_prepare_mcp_tools_before_repository_skill_discovery" | "model_prepare_repository_skill_discovery" | "model_prepare_repository_skill_discovery_before_input_filter" | "model_prepare_input_filter_base" | "model_prepare_input_filter_genesis" | "model_prepare_input_filter_host" | "model_prepare_input_filter_tool_output" | "model_prepare_input_filter_modality" | "model_prepare_input_filter_context" | "model_prepare_responses_input_conversion" | "model_prepare_responses_request_build" | "model_credential_resolution" | "model_wire_normalization" | "model_request_audit" | "stream_bootstrap";
|
|
433
447
|
export type TurnStartupOutcome = "completed" | "failed";
|
|
@@ -36,10 +36,10 @@ import {
|
|
|
36
36
|
sandboxLeaseTelemetryKey,
|
|
37
37
|
terminateProviderBox,
|
|
38
38
|
verifyDockerDrainCaptureFence
|
|
39
|
-
} from "./chunk-
|
|
40
|
-
import "./chunk-
|
|
39
|
+
} from "./chunk-PG66GHGH.js";
|
|
40
|
+
import "./chunk-PFCSGZGA.js";
|
|
41
41
|
import "./chunk-24GP3BX5.js";
|
|
42
|
-
import "./chunk-
|
|
42
|
+
import "./chunk-BX3KRGDM.js";
|
|
43
43
|
import "./chunk-W2QSM5HR.js";
|
|
44
44
|
import "./chunk-PZ5AY32C.js";
|
|
45
45
|
export {
|
|
@@ -81,4 +81,4 @@ export {
|
|
|
81
81
|
terminateProviderBox,
|
|
82
82
|
verifyDockerDrainCaptureFence
|
|
83
83
|
};
|
|
84
|
-
//# sourceMappingURL=sandbox-lease-
|
|
84
|
+
//# sourceMappingURL=sandbox-lease-XBZWILZ3.js.map
|
|
@@ -183,6 +183,7 @@ export type SelfhostedTurnSessionArgs = {
|
|
|
183
183
|
operationCpuQuotaSupported: boolean;
|
|
184
184
|
/** Feature advertisement only; refreshed by exact live admission for each operation. */
|
|
185
185
|
transactionalFsWriteSupported?: boolean;
|
|
186
|
+
browserControlHttpSupported?: boolean;
|
|
186
187
|
/** The active pointer's epoch — the control-op fence echoed to the agent. */
|
|
187
188
|
epoch: number;
|
|
188
189
|
/** The run's declared sandbox environment (the SAME object fed to buildAgent +
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengeni/worker-bundle",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.0",
|
|
4
4
|
"description": "Opengeni worker entry and reusable embedded lifecycle, shipped with a release-coherent pre-bundled Temporal workflow artifact.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -56,31 +56,31 @@
|
|
|
56
56
|
"@1password/sdk": "0.5.0",
|
|
57
57
|
"@keeper-security/secrets-manager-core": "17.6.0",
|
|
58
58
|
"@llamaindex/liteparse": "2.14.2",
|
|
59
|
-
"@opengeni/agent-proto": "3.
|
|
60
|
-
"@opengeni/capabilities": "3.
|
|
61
|
-
"@opengeni/codemode": "3.
|
|
62
|
-
"@opengeni/codex": "3.
|
|
63
|
-
"@opengeni/config": "3.
|
|
64
|
-
"@opengeni/contracts": "3.
|
|
65
|
-
"@opengeni/core": "3.
|
|
66
|
-
"@opengeni/db": "3.
|
|
67
|
-
"@opengeni/documents": "3.
|
|
68
|
-
"@opengeni/events": "3.
|
|
69
|
-
"@opengeni/github": "3.
|
|
70
|
-
"@opengeni/interaction": "3.
|
|
71
|
-
"@opengeni/jev": "3.
|
|
72
|
-
"@opengeni/network": "3.
|
|
73
|
-
"@opengeni/observability": "3.
|
|
74
|
-
"@opengeni/runtime": "3.
|
|
75
|
-
"@opengeni/sdk": "3.
|
|
76
|
-
"@opengeni/storage": "3.
|
|
77
|
-
"@opengeni/subscriptions": "3.
|
|
78
|
-
"@opengeni/tool-gateway": "3.
|
|
79
|
-
"@opengeni/vaults": "3.
|
|
80
|
-
"@opengeni/vaults-keeper": "3.
|
|
81
|
-
"@opengeni/vaults-onepassword": "3.
|
|
82
|
-
"@opengeni/vaults-protonpass": "3.
|
|
83
|
-
"@opengeni/xai-subscription": "3.
|
|
59
|
+
"@opengeni/agent-proto": "3.4.0",
|
|
60
|
+
"@opengeni/capabilities": "3.4.0",
|
|
61
|
+
"@opengeni/codemode": "3.4.0",
|
|
62
|
+
"@opengeni/codex": "3.4.0",
|
|
63
|
+
"@opengeni/config": "3.4.0",
|
|
64
|
+
"@opengeni/contracts": "3.4.0",
|
|
65
|
+
"@opengeni/core": "3.4.0",
|
|
66
|
+
"@opengeni/db": "3.4.0",
|
|
67
|
+
"@opengeni/documents": "3.4.0",
|
|
68
|
+
"@opengeni/events": "3.4.0",
|
|
69
|
+
"@opengeni/github": "3.4.0",
|
|
70
|
+
"@opengeni/interaction": "3.4.0",
|
|
71
|
+
"@opengeni/jev": "3.4.0",
|
|
72
|
+
"@opengeni/network": "3.4.0",
|
|
73
|
+
"@opengeni/observability": "3.4.0",
|
|
74
|
+
"@opengeni/runtime": "3.4.0",
|
|
75
|
+
"@opengeni/sdk": "3.4.0",
|
|
76
|
+
"@opengeni/storage": "3.4.0",
|
|
77
|
+
"@opengeni/subscriptions": "3.4.0",
|
|
78
|
+
"@opengeni/tool-gateway": "3.4.0",
|
|
79
|
+
"@opengeni/vaults": "3.4.0",
|
|
80
|
+
"@opengeni/vaults-keeper": "3.4.0",
|
|
81
|
+
"@opengeni/vaults-onepassword": "3.4.0",
|
|
82
|
+
"@opengeni/vaults-protonpass": "3.4.0",
|
|
83
|
+
"@opengeni/xai-subscription": "3.4.0",
|
|
84
84
|
"@temporalio/activity": "^1.17.0",
|
|
85
85
|
"@temporalio/client": "^1.17.0",
|
|
86
86
|
"@temporalio/worker": "^1.17.0",
|
|
@@ -61,9 +61,11 @@ import type {
|
|
|
61
61
|
RunAgentTurnResult,
|
|
62
62
|
} from "../types";
|
|
63
63
|
import {
|
|
64
|
+
codexRequestTransportLabel,
|
|
64
65
|
makeMachineOpObserver,
|
|
65
66
|
modelRequestLifecycleMetricsFor,
|
|
66
67
|
recordModelRequestPhase,
|
|
68
|
+
type ModelRequestTransportLabel,
|
|
67
69
|
recordCompanyBrainContributions,
|
|
68
70
|
recordTurnStartupPhase,
|
|
69
71
|
measureTurnStartupPhase,
|
|
@@ -805,6 +807,7 @@ export function createRunAgentTurnActivity(services: () => Promise<ActivityServi
|
|
|
805
807
|
resolvedToken = token;
|
|
806
808
|
return token;
|
|
807
809
|
};
|
|
810
|
+
const codexRequestTransports = new Map<string, ModelRequestTransportLabel>();
|
|
808
811
|
const creditGuard = createCodexCreditGuard({
|
|
809
812
|
...(coreUsageReader ? { fetchUsage: coreUsageReader } : {}),
|
|
810
813
|
canSpendCredits: async () => {
|
|
@@ -924,8 +927,20 @@ export function createRunAgentTurnActivity(services: () => Promise<ActivityServi
|
|
|
924
927
|
? "terminal"
|
|
925
928
|
: null;
|
|
926
929
|
if (!phase) return;
|
|
930
|
+
// The transport is known once headers arrive; later
|
|
931
|
+
// phases of the same request carry the same label.
|
|
932
|
+
const transportKey = `${event.requestId}:${event.transportAttempt}`;
|
|
933
|
+
if (event.transport) {
|
|
934
|
+
codexRequestTransports.set(
|
|
935
|
+
transportKey,
|
|
936
|
+
codexRequestTransportLabel(event.transport),
|
|
937
|
+
);
|
|
938
|
+
}
|
|
939
|
+
const transport = codexRequestTransports.get(transportKey);
|
|
940
|
+
if (phase === "terminal") codexRequestTransports.delete(transportKey);
|
|
927
941
|
recordModelRequestPhase(observability, {
|
|
928
942
|
provider: "codex-subscription",
|
|
943
|
+
...(transport ? { transport } : {}),
|
|
929
944
|
phase,
|
|
930
945
|
...(event.phase === "completed"
|
|
931
946
|
? { outcome: "completed" as const }
|
|
@@ -542,6 +542,8 @@ export async function establishTurnSandbox(deps: EstablishTurnSandboxDeps): Prom
|
|
|
542
542
|
liveMachineEnrollment?.agentCapabilities.operationCpuQuota === true,
|
|
543
543
|
transactionalFsWriteSupported:
|
|
544
544
|
liveMachineEnrollment?.agentCapabilities.transactionalFsWrite === true,
|
|
545
|
+
browserControlHttpSupported:
|
|
546
|
+
liveMachineEnrollment?.agentCapabilities.browserControlHttp === true,
|
|
545
547
|
// Carried for shared machines too: the audience can narrow to Only me
|
|
546
548
|
// mid-turn, and each operation then rechecks this authority.
|
|
547
549
|
...(fileAuthoritySubjectId
|
package/src/activity-services.ts
CHANGED
|
@@ -45,6 +45,9 @@ export function createSharedActivityServices(
|
|
|
45
45
|
: createDb(settings.databaseUrl, {
|
|
46
46
|
...(searchPath ? { searchPath } : {}),
|
|
47
47
|
rlsStrategy: settings.rlsStrategy,
|
|
48
|
+
...(settings.databasePreparedStatements === undefined
|
|
49
|
+
? {}
|
|
50
|
+
: { preparedStatements: settings.databasePreparedStatements }),
|
|
48
51
|
});
|
|
49
52
|
const controlPlaneAuth = resolveNatsControlPlaneAuth(settings);
|
|
50
53
|
const db = dependencies.db ?? dbClient!.db;
|
|
@@ -162,6 +162,9 @@ export async function createProductionEditableArtifactMaterializerService(
|
|
|
162
162
|
const dbClient = createDb(options.databaseUrl, {
|
|
163
163
|
...(searchPath ? { searchPath } : {}),
|
|
164
164
|
...(options.settings.rlsStrategy ? { rlsStrategy: options.settings.rlsStrategy } : {}),
|
|
165
|
+
...(options.settings.databasePreparedStatements === undefined
|
|
166
|
+
? {}
|
|
167
|
+
: { preparedStatements: options.settings.databasePreparedStatements }),
|
|
165
168
|
max: Math.max(2, concurrency + 1),
|
|
166
169
|
});
|
|
167
170
|
let created = false;
|
|
@@ -43,6 +43,8 @@ export type EditableArtifactOutboxWorkerOptions = Readonly<{
|
|
|
43
43
|
dispatcherDatabaseUrl: string;
|
|
44
44
|
databaseSearchPath?: string;
|
|
45
45
|
databasePoolSize?: number;
|
|
46
|
+
/** Unset → decided from the URL; see `CreateDbOptions.preparedStatements`. */
|
|
47
|
+
databasePreparedStatements?: boolean;
|
|
46
48
|
natsUrl: string;
|
|
47
49
|
natsAuth: EditableArtifactHintNatsAuth;
|
|
48
50
|
owner?: string;
|
|
@@ -121,6 +123,9 @@ export async function createEditableArtifactOutboxWorker(
|
|
|
121
123
|
const database = createDb(dispatcherDatabaseUrl, {
|
|
122
124
|
max: databasePoolSize,
|
|
123
125
|
...(options.databaseSearchPath ? { searchPath: options.databaseSearchPath } : {}),
|
|
126
|
+
...(options.databasePreparedStatements === undefined
|
|
127
|
+
? {}
|
|
128
|
+
: { preparedStatements: options.databasePreparedStatements }),
|
|
124
129
|
});
|
|
125
130
|
let broker: ConfirmedNatsEditableArtifactHintBroker;
|
|
126
131
|
try {
|
|
@@ -94,6 +94,9 @@ export async function createProductionEditableArtifactOutboxService(
|
|
|
94
94
|
...(options.databasePoolSize === undefined
|
|
95
95
|
? {}
|
|
96
96
|
: { databasePoolSize: options.databasePoolSize }),
|
|
97
|
+
...(options.settings.databasePreparedStatements === undefined
|
|
98
|
+
? {}
|
|
99
|
+
: { databasePreparedStatements: options.settings.databasePreparedStatements }),
|
|
97
100
|
natsUrl: options.natsUrl,
|
|
98
101
|
natsAuth: options.natsAuth,
|
|
99
102
|
owner: options.owner,
|
package/src/index.ts
CHANGED
|
@@ -1078,9 +1078,14 @@ export async function startWorker() {
|
|
|
1078
1078
|
const onRetry = (event: Parameters<typeof logStartupDependencyRetry>[1]) =>
|
|
1079
1079
|
logStartupDependencyRetry(observability, event);
|
|
1080
1080
|
const searchPath = dbSearchPath(settings);
|
|
1081
|
+
const preparedStatements =
|
|
1082
|
+
settings.databasePreparedStatements === undefined
|
|
1083
|
+
? {}
|
|
1084
|
+
: { preparedStatements: settings.databasePreparedStatements };
|
|
1081
1085
|
const dbClient = createDb(settings.databaseUrl, {
|
|
1082
1086
|
...(searchPath ? { searchPath } : {}),
|
|
1083
1087
|
rlsStrategy: settings.rlsStrategy,
|
|
1088
|
+
...preparedStatements,
|
|
1084
1089
|
});
|
|
1085
1090
|
// Readiness must prove PostgreSQL independently of activity demand. Sharing
|
|
1086
1091
|
// the default application pool makes the probe wait behind live turns when
|
|
@@ -1090,6 +1095,7 @@ export async function startWorker() {
|
|
|
1090
1095
|
const readinessDbClient = createDb(settings.databaseUrl, {
|
|
1091
1096
|
...(searchPath ? { searchPath } : {}),
|
|
1092
1097
|
rlsStrategy: settings.rlsStrategy,
|
|
1098
|
+
...preparedStatements,
|
|
1093
1099
|
max: 1,
|
|
1094
1100
|
});
|
|
1095
1101
|
const databasePosture = {
|
|
@@ -10,11 +10,13 @@ import {
|
|
|
10
10
|
automaticSessionTitleFanoutDue,
|
|
11
11
|
browserDeadlineCheckpointDue,
|
|
12
12
|
knowledgeIndexDue,
|
|
13
|
+
maintainSubscriptionPlans,
|
|
13
14
|
sandboxIdleCheckpointDue,
|
|
14
15
|
sandboxLeaseReaperDue,
|
|
15
16
|
sandboxMaintenanceDue,
|
|
16
17
|
sessionWorkflowWakesDue,
|
|
17
18
|
siteAuthMaintenanceDue,
|
|
19
|
+
subscriptionPlanMaintenanceDue,
|
|
18
20
|
workspacePauseTimerDue,
|
|
19
21
|
type Database,
|
|
20
22
|
} from "@opengeni/db";
|
|
@@ -53,6 +55,8 @@ export const SITE_AUTH_MAINTENANCE_WORKFLOW_ID = "opengeni-site-auth-maintenance
|
|
|
53
55
|
export const SITE_AUTH_MAINTENANCE_PERIOD_MS = 60 * 1_000;
|
|
54
56
|
/** The Schedule earlier releases used to drive the sandbox lease reaper. */
|
|
55
57
|
export const SANDBOX_REAPER_SCHEDULE_ID = "opengeni-sandbox-lease-reaper";
|
|
58
|
+
/** Small bounded DB-only pass; no Temporal execution for plan maintenance. */
|
|
59
|
+
export const SUBSCRIPTION_PLAN_MAINTENANCE_PERIOD_MS = 60_000;
|
|
56
60
|
|
|
57
61
|
export const INTERNAL_MAINTENANCE_JOBS = [
|
|
58
62
|
"session-workflow-wake-dispatcher",
|
|
@@ -61,6 +65,7 @@ export const INTERNAL_MAINTENANCE_JOBS = [
|
|
|
61
65
|
"sandbox-lease-reaper",
|
|
62
66
|
"sandbox-idle-checkpoint",
|
|
63
67
|
"browser-deadline-checkpoint",
|
|
68
|
+
"subscription-plan-maintenance",
|
|
64
69
|
] as const;
|
|
65
70
|
export type InternalMaintenanceJob = (typeof INTERNAL_MAINTENANCE_JOBS)[number];
|
|
66
71
|
|
|
@@ -139,6 +144,25 @@ export async function internalMaintenanceCadences(input: {
|
|
|
139
144
|
const jobs = new Set(input.jobs ?? INTERNAL_MAINTENANCE_JOBS);
|
|
140
145
|
const taskQueue = settings.temporalTaskQueue;
|
|
141
146
|
const cadences: MaintenanceCadence[] = [];
|
|
147
|
+
if (settings.subscriptionPlansEnabled && jobs.has("subscription-plan-maintenance")) {
|
|
148
|
+
cadences.push({
|
|
149
|
+
job: "subscription-plan-maintenance",
|
|
150
|
+
periodMs: SUBSCRIPTION_PLAN_MAINTENANCE_PERIOD_MS,
|
|
151
|
+
hasWork: async () => await subscriptionPlanMaintenanceDue(db),
|
|
152
|
+
start: async () => {
|
|
153
|
+
const result = await maintainSubscriptionPlans(db, {
|
|
154
|
+
onError: (error, accountId) =>
|
|
155
|
+
observability.warn("Subscription plan maintenance account failed", {
|
|
156
|
+
accountId,
|
|
157
|
+
error: error instanceof Error ? error.message : String(error),
|
|
158
|
+
}),
|
|
159
|
+
});
|
|
160
|
+
if (result.failedAccounts > 0)
|
|
161
|
+
throw new Error(`${result.failedAccounts} subscription plan maintenance accounts failed`);
|
|
162
|
+
return "started";
|
|
163
|
+
},
|
|
164
|
+
});
|
|
165
|
+
}
|
|
142
166
|
if (jobs.has("session-workflow-wake-dispatcher")) {
|
|
143
167
|
const { repairMissedSessionWorkflowWakes } = await import("./activities/parent-wake");
|
|
144
168
|
cadences.push({
|
|
@@ -2194,6 +2194,21 @@ const MODEL_REQUEST_PHASE_BUCKETS = [
|
|
|
2194
2194
|
* Provider ids come from the resolved provider registry; phase/outcome are closed
|
|
2195
2195
|
* enums. This function never performs I/O outside the in-memory metrics registry.
|
|
2196
2196
|
*/
|
|
2197
|
+
/**
|
|
2198
|
+
* How a model request reached its provider, where the provider has more than
|
|
2199
|
+
* one transport (Codex: a new or reused Responses WebSocket, or HTTP). Empty
|
|
2200
|
+
* for providers with a single transport.
|
|
2201
|
+
*/
|
|
2202
|
+
export type ModelRequestTransportLabel = "" | "websocket_new" | "websocket_reused" | "http";
|
|
2203
|
+
|
|
2204
|
+
/** The bounded metric label for how a Codex request was carried. */
|
|
2205
|
+
export function codexRequestTransportLabel(
|
|
2206
|
+
transport: { kind: "websocket"; connection: "new" | "reused" } | { kind: "http" },
|
|
2207
|
+
): ModelRequestTransportLabel {
|
|
2208
|
+
if (transport.kind === "http") return "http";
|
|
2209
|
+
return transport.connection === "reused" ? "websocket_reused" : "websocket_new";
|
|
2210
|
+
}
|
|
2211
|
+
|
|
2197
2212
|
export function recordModelRequestPhase(
|
|
2198
2213
|
observability: Observability,
|
|
2199
2214
|
input: {
|
|
@@ -2201,19 +2216,21 @@ export function recordModelRequestPhase(
|
|
|
2201
2216
|
phase: "headers" | "first_byte" | "terminal";
|
|
2202
2217
|
outcome?: "completed" | "failed" | "timed_out";
|
|
2203
2218
|
durationSeconds: number;
|
|
2219
|
+
transport?: ModelRequestTransportLabel;
|
|
2204
2220
|
},
|
|
2205
2221
|
): void {
|
|
2206
2222
|
const outcome = input.outcome ?? "";
|
|
2223
|
+
const transport = input.transport ?? "";
|
|
2207
2224
|
observability.incrementCounter({
|
|
2208
2225
|
name: "opengeni_model_request_phases_total",
|
|
2209
|
-
help: "Provider model-request lifecycle phases by bounded phase and
|
|
2210
|
-
labels: { provider: input.provider, phase: input.phase, outcome },
|
|
2226
|
+
help: "Provider model-request lifecycle phases by bounded phase, outcome and transport.",
|
|
2227
|
+
labels: { provider: input.provider, phase: input.phase, outcome, transport },
|
|
2211
2228
|
});
|
|
2212
2229
|
observability.observeHistogram({
|
|
2213
2230
|
name: "opengeni_model_request_phase_duration_seconds",
|
|
2214
2231
|
help: "Monotonic seconds from provider dispatch to a model-request lifecycle phase.",
|
|
2215
2232
|
buckets: MODEL_REQUEST_PHASE_BUCKETS,
|
|
2216
|
-
labels: { provider: input.provider, phase: input.phase },
|
|
2233
|
+
labels: { provider: input.provider, phase: input.phase, transport },
|
|
2217
2234
|
value: Math.max(0, input.durationSeconds),
|
|
2218
2235
|
});
|
|
2219
2236
|
}
|
package/src/sandbox-routing.ts
CHANGED
|
@@ -1038,6 +1038,7 @@ export function wrapTurnBoxWithRouting(
|
|
|
1038
1038
|
connectionInstanceId: command.connectionInstanceId,
|
|
1039
1039
|
opId: command.opId,
|
|
1040
1040
|
command: command.command,
|
|
1041
|
+
...(command.abandoned ? { abandoned: true } : {}),
|
|
1041
1042
|
});
|
|
1042
1043
|
return { commandId: adopted.id };
|
|
1043
1044
|
},
|
|
@@ -1337,6 +1338,7 @@ export function wrapLazyTurnBoxWithRouting(
|
|
|
1337
1338
|
connectionInstanceId: command.connectionInstanceId,
|
|
1338
1339
|
opId: command.opId,
|
|
1339
1340
|
command: command.command,
|
|
1341
|
+
...(command.abandoned ? { abandoned: true } : {}),
|
|
1340
1342
|
});
|
|
1341
1343
|
return { commandId: adopted.id };
|
|
1342
1344
|
},
|
|
@@ -1542,6 +1544,7 @@ export type SelfhostedTurnSessionArgs = {
|
|
|
1542
1544
|
operationCpuQuotaSupported: boolean;
|
|
1543
1545
|
/** Feature advertisement only; refreshed by exact live admission for each operation. */
|
|
1544
1546
|
transactionalFsWriteSupported?: boolean;
|
|
1547
|
+
browserControlHttpSupported?: boolean;
|
|
1545
1548
|
/** The active pointer's epoch — the control-op fence echoed to the agent. */
|
|
1546
1549
|
epoch: number;
|
|
1547
1550
|
/** The run's declared sandbox environment (the SAME object fed to buildAgent +
|
|
@@ -1618,6 +1621,7 @@ export function connectionBindingFor(
|
|
|
1618
1621
|
operationResourcePolicySupported: enrollment.agentCapabilities.operationResourcePolicy === true,
|
|
1619
1622
|
operationCpuQuotaSupported: enrollment.agentCapabilities.operationCpuQuota === true,
|
|
1620
1623
|
transactionalFsWriteSupported: enrollment.agentCapabilities.transactionalFsWrite === true,
|
|
1624
|
+
browserControlHttpSupported: enrollment.agentCapabilities.browserControlHttp === true,
|
|
1621
1625
|
};
|
|
1622
1626
|
}
|
|
1623
1627
|
|
|
@@ -1693,6 +1697,7 @@ export async function establishSelfhostedTurnSession(
|
|
|
1693
1697
|
operationResourcePolicySupported: args.operationResourcePolicySupported,
|
|
1694
1698
|
operationCpuQuotaSupported: args.operationCpuQuotaSupported,
|
|
1695
1699
|
transactionalFsWriteSupported: args.transactionalFsWriteSupported === true,
|
|
1700
|
+
browserControlHttpSupported: args.browserControlHttpSupported === true,
|
|
1696
1701
|
resolveOperationAdmission: async () => {
|
|
1697
1702
|
// The machine's audience can change in place during a turn. Read the
|
|
1698
1703
|
// current scope on every admitted operation: a machine that is Only me now
|
|
@@ -1747,6 +1752,7 @@ export async function establishSelfhostedTurnSession(
|
|
|
1747
1752
|
connectionInstanceId: command.connectionInstanceId,
|
|
1748
1753
|
opId: command.opId,
|
|
1749
1754
|
command: command.command,
|
|
1755
|
+
...(command.abandoned ? { abandoned: true } : {}),
|
|
1750
1756
|
});
|
|
1751
1757
|
return { commandId: adopted.id };
|
|
1752
1758
|
},
|