@opengeni/worker-bundle 1.0.0-canary.1 → 1.0.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-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 +4 -0
- package/dist/activities/agent-turn/claude-usage-observer.d.ts +58 -0
- package/dist/activities/agent-turn/code-search.d.ts +60 -0
- package/dist/activities/agent-turn/codex-capacity.d.ts +13 -0
- package/dist/activities/agent-turn/codex-plan-entitlement.d.ts +105 -0
- package/dist/activities/agent-turn/codex.d.ts +3 -2
- package/dist/activities/agent-turn/compaction-prep.d.ts +21 -5
- package/dist/activities/agent-turn/credential-leases.d.ts +19 -33
- package/dist/activities/agent-turn/credential-restriction.d.ts +3 -0
- package/dist/activities/agent-turn/errors.d.ts +82 -11
- package/dist/activities/agent-turn/failure-settlement.d.ts +6 -3
- package/dist/activities/agent-turn/final-reply.d.ts +18 -0
- package/dist/activities/agent-turn/finalization-monitor.d.ts +17 -0
- package/dist/activities/agent-turn/finalization.d.ts +4 -2
- package/dist/activities/agent-turn/github-repository-bindings.d.ts +2 -0
- package/dist/activities/agent-turn/governance-model.d.ts +9 -2
- package/dist/activities/agent-turn/history-sink.d.ts +2 -0
- package/dist/activities/agent-turn/history.d.ts +2 -0
- package/dist/activities/agent-turn/input-wait-reply.d.ts +41 -0
- package/dist/activities/agent-turn/media-artifacts.d.ts +5 -3
- package/dist/activities/agent-turn/model-call-admission.d.ts +15 -0
- package/dist/activities/agent-turn/model-usage.d.ts +6 -0
- package/dist/activities/agent-turn/model-wire-dispatch.d.ts +15 -0
- package/dist/activities/agent-turn/optional-repositories.d.ts +59 -0
- package/dist/activities/agent-turn/provider-dispatch-barrier.d.ts +12 -1
- package/dist/activities/agent-turn/quiescence.d.ts +7 -7
- package/dist/activities/agent-turn/recovery-warning.d.ts +9 -0
- package/dist/activities/agent-turn/refresh-credentials.d.ts +6 -0
- package/dist/activities/agent-turn/run-credentials.d.ts +8 -3
- package/dist/activities/agent-turn/sandbox-establish.d.ts +2 -1
- package/dist/activities/agent-turn/sandbox-provision.d.ts +3 -1
- package/dist/activities/agent-turn/sandbox-route.d.ts +3 -20
- package/dist/activities/agent-turn/sandbox-runtime.d.ts +2 -2
- package/dist/activities/agent-turn/session-title.d.ts +34 -2
- package/dist/activities/agent-turn/skill-checkout.d.ts +25 -6
- package/dist/activities/agent-turn/skill-read.d.ts +70 -2
- package/dist/activities/agent-turn/skill-remove.d.ts +14 -0
- package/dist/activities/agent-turn/skill-search.d.ts +3 -1
- package/dist/activities/agent-turn/skill-tools.d.ts +15 -2
- package/dist/activities/agent-turn/skill-transfer.d.ts +18 -6
- package/dist/activities/agent-turn/stream-attempt.d.ts +7 -3
- package/dist/activities/agent-turn/subscription-lease.d.ts +38 -0
- package/dist/activities/agent-turn/tool-environment.d.ts +56 -6
- package/dist/activities/agent-turn/tool-policy.d.ts +43 -0
- package/dist/activities/agent-turn/turn-context.d.ts +29 -0
- package/dist/activities/agent-turn/turn-sandbox-access.d.ts +3 -0
- package/dist/activities/agent-turn/xai-capacity.d.ts +2 -1
- package/dist/activities/automations.d.ts +3 -1
- package/dist/activities/browser-deadline-checkpoint.d.ts +29 -0
- package/dist/activities/codemode-dispatcher.d.ts +9 -2
- package/dist/activities/codex-capacity.d.ts +18 -2
- package/dist/activities/codex-rotation.d.ts +7 -1
- package/dist/activities/context-compaction.d.ts +16 -2
- package/dist/activities/gmail-files.d.ts +32 -0
- package/dist/activities/goals.d.ts +8 -0
- package/dist/activities/knowledge-indexing.d.ts +19 -0
- package/dist/activities/mcp-account-routes.d.ts +3 -0
- package/dist/activities/mcp-credentials.d.ts +12 -13
- package/dist/activities/mcp-operation-authority.d.ts +0 -5
- package/dist/activities/model-call-fact-reconciler.d.ts +34 -0
- package/dist/activities/open-suffix-resume.d.ts +13 -0
- package/dist/activities/parent-wake.d.ts +6 -12
- package/dist/activities/retained-screenshots.d.ts +7 -2
- package/dist/activities/rig-verification.d.ts +2 -3
- package/dist/activities/run-credential-renewal.d.ts +1 -0
- package/dist/activities/run-credentials.d.ts +15 -3
- package/dist/activities/sandbox-images.d.ts +1 -1
- package/dist/activities/sandbox-lease.d.ts +47 -9
- package/dist/activities/scheduled-tasks.d.ts +4 -35
- package/dist/activities/session-state.d.ts +70 -3
- package/dist/activities/types.d.ts +55 -6
- package/dist/activities/workspace-capture.d.ts +2 -0
- package/dist/activities/workspace-credential-provider.d.ts +46 -0
- package/dist/{activities-control-HMFGSKC5.js → activities-control-BNPTRTOE.js} +1896 -418
- package/dist/activities-control-BNPTRTOE.js.map +1 -0
- package/dist/activities-control.d.ts +182 -4
- package/dist/{activities-turn-AP67JADS.js → activities-turn-5LGZOSVU.js} +4476 -1327
- package/dist/activities-turn-5LGZOSVU.js.map +1 -0
- package/dist/activities.d.ts +182 -4
- package/dist/artifact-materializer-entry.js +5 -2
- package/dist/artifact-materializer-entry.js.map +1 -1
- package/dist/artifact-outbox-entry.js +5 -2
- package/dist/artifact-outbox-entry.js.map +1 -1
- package/dist/browser-deadline-checkpoint-contract.d.ts +2 -0
- package/dist/{chunk-A4XQWVZK.js → chunk-3ZTRWDMN.js} +307 -4
- package/dist/chunk-3ZTRWDMN.js.map +1 -0
- package/dist/{chunk-RAMNYSAW.js → chunk-4ER3YXOT.js} +22 -4
- package/dist/chunk-4ER3YXOT.js.map +1 -0
- package/dist/{chunk-CYITU5UH.js → chunk-LJX7Z2KP.js} +1445 -343
- package/dist/chunk-LJX7Z2KP.js.map +1 -0
- package/dist/editable-artifact-materializer-service.d.ts +2 -2
- package/dist/editable-artifact-outbox-service.d.ts +2 -2
- package/dist/host-export-pump.d.ts +3 -1
- package/dist/host-export.d.ts +1 -1
- package/dist/host-export.js +1 -1
- package/dist/http.d.ts +1 -1
- package/dist/index.d.ts +95 -3
- package/dist/index.js +137 -43
- package/dist/index.js.map +1 -1
- package/dist/observability-metrics.d.ts +118 -8
- package/dist/retained-process-diagnostics.d.ts +4 -0
- package/dist/retained-process-retry.d.ts +7 -0
- package/dist/sandbox-resume.d.ts +55 -13
- package/dist/sandbox-routing.d.ts +5 -3
- package/dist/sandbox-snapshot-diagnostics.d.ts +20 -0
- package/dist/session-event-fanout.d.ts +6 -0
- package/dist/warm-capture-holder.d.ts +3 -0
- package/dist/worker-service-lifecycle.d.ts +12 -0
- package/dist/workflow-bundle.js +273 -41
- package/dist/workflows/activities.d.ts +1 -1
- package/dist/workflows/browser-deadline-checkpoint.d.ts +9 -0
- package/dist/workflows/scheduled-tasks.d.ts +4 -0
- package/dist/workflows/session.d.ts +36 -0
- package/dist/workflows.d.ts +1 -0
- package/package.json +21 -19
- package/src/activities/agent-run-admission.ts +17 -1
- package/src/activities/agent-turn/admission.ts +66 -3
- package/src/activities/agent-turn/agent-build.ts +84 -10
- package/src/activities/agent-turn/claim.ts +186 -43
- package/src/activities/agent-turn/claude-usage-observer.ts +221 -0
- package/src/activities/agent-turn/code-search.ts +275 -0
- package/src/activities/agent-turn/codex-capacity.ts +172 -8
- package/src/activities/agent-turn/codex-plan-entitlement.ts +254 -0
- package/src/activities/agent-turn/codex.ts +13 -5
- package/src/activities/agent-turn/compaction-prep.ts +170 -102
- package/src/activities/agent-turn/credential-leases.ts +122 -216
- package/src/activities/agent-turn/credential-restriction.ts +14 -0
- package/src/activities/agent-turn/errors.ts +647 -48
- package/src/activities/agent-turn/failure-settlement.ts +682 -130
- package/src/activities/agent-turn/final-reply.ts +46 -0
- package/src/activities/agent-turn/finalization-monitor.ts +120 -0
- package/src/activities/agent-turn/finalization.ts +146 -43
- package/src/activities/agent-turn/github-repository-bindings.ts +3 -1
- package/src/activities/agent-turn/governance-model.ts +69 -28
- package/src/activities/agent-turn/history-sink.ts +16 -2
- package/src/activities/agent-turn/history.ts +38 -11
- package/src/activities/agent-turn/input-wait-reply.ts +103 -0
- package/src/activities/agent-turn/knowledge-source-tools.ts +2 -0
- package/src/activities/agent-turn/media-artifacts.ts +2 -1
- package/src/activities/agent-turn/model-call-admission.ts +94 -0
- package/src/activities/agent-turn/model-usage.ts +64 -3
- package/src/activities/agent-turn/model-wire-dispatch.ts +27 -0
- package/src/activities/agent-turn/optional-repositories.ts +224 -0
- package/src/activities/agent-turn/provider-dispatch-barrier.ts +22 -0
- package/src/activities/agent-turn/quiescence.ts +10 -7
- package/src/activities/agent-turn/recovery-warning.ts +16 -0
- package/src/activities/agent-turn/refresh-credentials.ts +44 -0
- package/src/activities/agent-turn/run-credentials.ts +116 -55
- package/src/activities/agent-turn/run.ts +320 -93
- package/src/activities/agent-turn/sandbox-establish.ts +84 -8
- package/src/activities/agent-turn/sandbox-provision.ts +3 -1
- package/src/activities/agent-turn/sandbox-route.ts +4 -21
- package/src/activities/agent-turn/sandbox-runtime.ts +343 -18
- package/src/activities/agent-turn/session-title.ts +81 -5
- package/src/activities/agent-turn/skill-checkout.ts +111 -24
- package/src/activities/agent-turn/skill-install.ts +1 -1
- package/src/activities/agent-turn/skill-read.ts +374 -28
- package/src/activities/agent-turn/skill-remove.ts +46 -0
- package/src/activities/agent-turn/skill-save.ts +1 -1
- package/src/activities/agent-turn/skill-search.ts +10 -1
- package/src/activities/agent-turn/skill-selection.ts +4 -0
- package/src/activities/agent-turn/skill-tools.ts +112 -18
- package/src/activities/agent-turn/skill-transfer.ts +68 -23
- package/src/activities/agent-turn/stream-attempt.ts +313 -77
- package/src/activities/agent-turn/subscription-lease.ts +115 -0
- package/src/activities/agent-turn/tool-environment.ts +316 -167
- package/src/activities/agent-turn/tool-policy.ts +80 -1
- package/src/activities/agent-turn/turn-context.ts +35 -0
- package/src/activities/agent-turn/turn-sandbox-access.ts +7 -1
- package/src/activities/agent-turn/xai-capacity.ts +94 -51
- package/src/activities/automations.ts +76 -4
- package/src/activities/browser-deadline-checkpoint.ts +279 -0
- package/src/activities/capabilities.ts +108 -11
- package/src/activities/codemode-dispatcher.ts +36 -8
- package/src/activities/codex-capacity.ts +60 -25
- package/src/activities/codex-rotation.ts +39 -17
- package/src/activities/context-compaction.ts +75 -18
- package/src/activities/gmail-files.ts +88 -0
- package/src/activities/goals.ts +116 -121
- package/src/activities/google-drive-publication.ts +1 -3
- package/src/activities/image-generation-operation.ts +1 -1
- package/src/activities/knowledge-indexing.ts +269 -15
- package/src/activities/knowledge-source-sync.ts +10 -0
- package/src/activities/mcp-account-routes.ts +17 -0
- package/src/activities/mcp-credentials.ts +83 -194
- package/src/activities/mcp-operation-authority.ts +16 -41
- package/src/activities/model-call-fact-reconciler.ts +112 -0
- package/src/activities/open-suffix-resume.ts +15 -2
- package/src/activities/parent-wake.ts +46 -21
- package/src/activities/retained-screenshots.ts +82 -11
- package/src/activities/rig-verification.ts +38 -37
- package/src/activities/run-credential-renewal.ts +13 -1
- package/src/activities/run-credentials.ts +59 -17
- package/src/activities/run-input.ts +25 -16
- package/src/activities/sandbox-images.ts +0 -1
- package/src/activities/sandbox-lease.ts +798 -82
- package/src/activities/scheduled-tasks.ts +550 -178
- package/src/activities/session-state.ts +245 -6
- package/src/activities/site-auth-maintenance.ts +3 -0
- package/src/activities/types.ts +72 -5
- package/src/activities/workflow-wake.ts +2 -17
- package/src/activities/workspace-capture.ts +13 -2
- package/src/activities/workspace-credential-provider.ts +283 -0
- package/src/activities-control.ts +4 -0
- package/src/activities-turn.ts +5 -0
- package/src/activities.ts +13 -0
- package/src/activity-services.ts +16 -4
- package/src/browser-deadline-checkpoint-contract.ts +5 -0
- package/src/editable-artifact-hint-broker.ts +3 -0
- package/src/editable-artifact-materializer-service.ts +7 -3
- package/src/editable-artifact-outbox-service.ts +4 -4
- package/src/github-rest-mcp.ts +1 -2
- package/src/host-export-pump.ts +26 -4
- package/src/host-export.ts +3 -0
- package/src/http.ts +4 -2
- package/src/index.ts +99 -37
- package/src/observability-metrics.ts +510 -5
- package/src/personal-github-git-credentials.ts +2 -1
- package/src/pr-review-credentials.ts +1 -3
- package/src/retained-process-diagnostics.ts +50 -0
- package/src/retained-process-retry.ts +36 -0
- package/src/sandbox-resume.ts +388 -101
- package/src/sandbox-routing.ts +150 -25
- package/src/sandbox-snapshot-diagnostics.ts +112 -0
- package/src/session-event-fanout.ts +23 -0
- package/src/warm-capture-holder.ts +15 -0
- package/src/worker-service-lifecycle.ts +53 -0
- package/src/workflows/activities.ts +16 -1
- package/src/workflows/browser-deadline-checkpoint.ts +50 -0
- package/src/workflows/file-upload-reaper.ts +2 -0
- package/src/workflows/scheduled-tasks.ts +26 -13
- package/src/workflows/session.ts +242 -22
- package/src/workflows.ts +4 -0
- package/dist/activities/agent-turn/knowledge-sources.d.ts +0 -20
- package/dist/activities/packs.d.ts +0 -55
- package/dist/activities-control-HMFGSKC5.js.map +0 -1
- package/dist/activities-turn-AP67JADS.js.map +0 -1
- package/dist/chunk-A4XQWVZK.js.map +0 -1
- package/dist/chunk-CYITU5UH.js.map +0 -1
- package/dist/chunk-RAMNYSAW.js.map +0 -1
- package/src/activities/agent-turn/knowledge-sources.ts +0 -86
- package/src/activities/packs.ts +0 -166
|
@@ -1,8 +1,24 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { errorCodeToJSON } from "@opengeni/agent-proto";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
import {
|
|
4
|
+
BundledSkillId,
|
|
5
|
+
CREDIT_GRANT_CLASSES,
|
|
6
|
+
SandboxBackend,
|
|
7
|
+
type SessionEventType,
|
|
8
|
+
type SkillReadKind,
|
|
9
|
+
type SkillUseSource,
|
|
10
|
+
} from "@opengeni/contracts";
|
|
11
|
+
import {
|
|
12
|
+
ACTIVE_USER_WINDOWS,
|
|
13
|
+
type ActiveUserWindow,
|
|
14
|
+
type CreditGrantTotals,
|
|
15
|
+
type SessionEventAppendPhaseObservation,
|
|
16
|
+
} from "@opengeni/db";
|
|
17
|
+
import {
|
|
18
|
+
natsSubscriptionTerminationCounter,
|
|
19
|
+
type EventBusOptions,
|
|
20
|
+
type EventLogger,
|
|
21
|
+
} from "@opengeni/events";
|
|
6
22
|
import type { Attributes, AttributeValue, Observability } from "@opengeni/observability";
|
|
7
23
|
import type { CompanyBrainContributionReceipt } from "./model-context-contributions";
|
|
8
24
|
import {
|
|
@@ -16,6 +32,7 @@ import {
|
|
|
16
32
|
type RuntimeMetricsHooks,
|
|
17
33
|
type SelfhostedOpObservation,
|
|
18
34
|
type SelfhostedOpObserver,
|
|
35
|
+
type ToolPreparationPhaseMeasurement,
|
|
19
36
|
} from "@opengeni/runtime";
|
|
20
37
|
|
|
21
38
|
export type TurnOutcome = "completed" | "failed" | "cancelled" | "recovering";
|
|
@@ -79,6 +96,16 @@ const CONTEXT_COMPACTIONS_METRIC = {
|
|
|
79
96
|
help: "Total completed context compactions, by trigger.",
|
|
80
97
|
} as const;
|
|
81
98
|
|
|
99
|
+
/** Logger plus the closed-label subscription-termination counter for NATS connections. */
|
|
100
|
+
export function observabilityEventBusOptions(
|
|
101
|
+
observability: Observability,
|
|
102
|
+
): Pick<EventBusOptions, "logger" | "onSubscriptionTerminated"> {
|
|
103
|
+
return {
|
|
104
|
+
logger: observabilityEventLogger(observability),
|
|
105
|
+
onSubscriptionTerminated: natsSubscriptionTerminationCounter(observability),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
82
109
|
export function observabilityEventLogger(observability: Observability): EventLogger {
|
|
83
110
|
return {
|
|
84
111
|
debug: (message, attributes) => observability.debug(message, eventAttributes(attributes)),
|
|
@@ -119,6 +146,10 @@ export function runtimeMetricsHooksForObservability(
|
|
|
119
146
|
): RuntimeMetricsHooks {
|
|
120
147
|
return {
|
|
121
148
|
onModelCall: ({ provider, outcome, durationSeconds }) => {
|
|
149
|
+
completedOperationSpan(observability, "worker.model.call", durationSeconds, {
|
|
150
|
+
provider,
|
|
151
|
+
outcome,
|
|
152
|
+
});
|
|
122
153
|
observability.incrementCounter({
|
|
123
154
|
name: "opengeni_model_calls_total",
|
|
124
155
|
help: "Total model calls by provider and outcome.",
|
|
@@ -151,6 +182,13 @@ export function runtimeMetricsHooksForObservability(
|
|
|
151
182
|
labels: { backend, stage },
|
|
152
183
|
});
|
|
153
184
|
},
|
|
185
|
+
onSandboxReadinessReplacement: ({ backend, outcome }) => {
|
|
186
|
+
observability.incrementCounter({
|
|
187
|
+
name: "opengeni_sandbox_readiness_replacements_total",
|
|
188
|
+
help: "Fresh sandbox command-readiness replacement decisions by backend and outcome.",
|
|
189
|
+
labels: { backend, outcome },
|
|
190
|
+
});
|
|
191
|
+
},
|
|
154
192
|
onSandboxProviderApiThrottle: ({ backend, operation }) => {
|
|
155
193
|
observability.incrementCounter({
|
|
156
194
|
name: "opengeni_sandbox_provider_api_throttles_total",
|
|
@@ -172,6 +210,20 @@ export function runtimeMetricsHooksForObservability(
|
|
|
172
210
|
labels: { outcome, port: String(port) },
|
|
173
211
|
});
|
|
174
212
|
},
|
|
213
|
+
onWorkspaceCapture: ({ backend, outcome, durationSeconds }) => {
|
|
214
|
+
if (!Number.isFinite(durationSeconds) || durationSeconds < 0) return;
|
|
215
|
+
const safeBackend = SandboxBackend.safeParse(backend).success ? backend : "unknown";
|
|
216
|
+
completedOperationSpan(observability, "worker.workspace_capture", durationSeconds, {
|
|
217
|
+
backend: safeBackend,
|
|
218
|
+
outcome,
|
|
219
|
+
});
|
|
220
|
+
observability.observeHistogram({
|
|
221
|
+
name: "opengeni_workspace_capture_duration_seconds",
|
|
222
|
+
help: "Physical warm workspace capture and publication duration, including late settlement after caller timeout.",
|
|
223
|
+
labels: { backend: safeBackend, outcome },
|
|
224
|
+
value: durationSeconds,
|
|
225
|
+
});
|
|
226
|
+
},
|
|
175
227
|
onWorkspaceArchiveObject: ({ outcome, backend }) => {
|
|
176
228
|
observability.incrementCounter({
|
|
177
229
|
name: "opengeni_workspace_archive_object_total",
|
|
@@ -180,6 +232,7 @@ export function runtimeMetricsHooksForObservability(
|
|
|
180
232
|
});
|
|
181
233
|
},
|
|
182
234
|
onMcpToolCall: ({ outcome, durationSeconds }) => {
|
|
235
|
+
completedOperationSpan(observability, "worker.mcp.tool_call", durationSeconds, { outcome });
|
|
183
236
|
observability.incrementCounter({
|
|
184
237
|
name: "opengeni_mcp_tool_calls_total",
|
|
185
238
|
help: "Total physical MCP tool calls by bounded structural outcome.",
|
|
@@ -1013,6 +1066,7 @@ export function recordOpenSandboxKubernetesInventoryGauges(
|
|
|
1013
1066
|
export const SANDBOX_INVENTORY_PROJECTION_DOMAINS = [
|
|
1014
1067
|
"leases",
|
|
1015
1068
|
"checkpoint_artifacts",
|
|
1069
|
+
"recovery_observations",
|
|
1016
1070
|
"rotation_backlog",
|
|
1017
1071
|
"retained_processes",
|
|
1018
1072
|
"expired_drains",
|
|
@@ -1074,6 +1128,106 @@ export function recordCreditBalanceGauges(
|
|
|
1074
1128
|
creditBalanceGaugeAccounts.set(observability, current);
|
|
1075
1129
|
}
|
|
1076
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
|
+
|
|
1179
|
+
/**
|
|
1180
|
+
* The deployment-level runtime switch for the one-time verified signup trial
|
|
1181
|
+
* credit (migration 0521): 1 while it allows grants, 0 when an operator has
|
|
1182
|
+
* disabled it or no revision exists. A grant also needs the API's
|
|
1183
|
+
* OPENGENI_VERIFIED_SIGNUP_TRIAL_CREDITS_ENABLED master opt-in, which
|
|
1184
|
+
* {@link recordVerifiedSignupTrialDeploymentFlagGauge} reports separately.
|
|
1185
|
+
*/
|
|
1186
|
+
export function recordVerifiedSignupTrialSwitchGauge(
|
|
1187
|
+
observability: Observability,
|
|
1188
|
+
grantsEnabled: boolean,
|
|
1189
|
+
): void {
|
|
1190
|
+
observability.setGauge({
|
|
1191
|
+
name: "opengeni_verified_signup_trial_credits_runtime_enabled",
|
|
1192
|
+
help: "Whether the runtime switch allows new verified signup trial credit grants (1) or blocks them (0).",
|
|
1193
|
+
value: grantsEnabled ? 1 : 0,
|
|
1194
|
+
});
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
/**
|
|
1198
|
+
* The deployment-level runtime switch for new managed account sign-ups
|
|
1199
|
+
* (migration 0585): 1 while it allows new accounts (also when no revision
|
|
1200
|
+
* exists), 0 when an operator has paused them. The API additionally honours
|
|
1201
|
+
* its OPENGENI_MANAGED_AUTH_NEW_SIGNUPS_ENABLED ceiling, which this gauge does
|
|
1202
|
+
* not see; `GET /v1/config/client` reports the combined decision.
|
|
1203
|
+
*/
|
|
1204
|
+
export function recordManagedAuthNewSignupsSwitchGauge(
|
|
1205
|
+
observability: Observability,
|
|
1206
|
+
signupsEnabled: boolean,
|
|
1207
|
+
): void {
|
|
1208
|
+
observability.setGauge({
|
|
1209
|
+
name: "opengeni_managed_auth_new_signups_runtime_enabled",
|
|
1210
|
+
help: "Whether the runtime switch allows new managed account sign-ups (1) or has paused them (0).",
|
|
1211
|
+
value: signupsEnabled ? 1 : 0,
|
|
1212
|
+
});
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
/**
|
|
1216
|
+
* The OPENGENI_VERIFIED_SIGNUP_TRIAL_CREDITS_ENABLED master opt-in as this
|
|
1217
|
+
* worker's configuration sees it. The API reads the same shared setting; new
|
|
1218
|
+
* grants happen only while this gauge and the runtime switch gauge are both 1.
|
|
1219
|
+
*/
|
|
1220
|
+
export function recordVerifiedSignupTrialDeploymentFlagGauge(
|
|
1221
|
+
observability: Observability,
|
|
1222
|
+
enabled: boolean,
|
|
1223
|
+
): void {
|
|
1224
|
+
observability.setGauge({
|
|
1225
|
+
name: "opengeni_verified_signup_trial_credits_deployment_enabled",
|
|
1226
|
+
help: "Whether the OPENGENI_VERIFIED_SIGNUP_TRIAL_CREDITS_ENABLED master opt-in is on (1) or off (0) in this deployment's configuration.",
|
|
1227
|
+
value: enabled ? 1 : 0,
|
|
1228
|
+
});
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1077
1231
|
export function recordSandboxOrphansTerminated(observability: Observability, count: number): void {
|
|
1078
1232
|
if (count <= 0) {
|
|
1079
1233
|
return;
|
|
@@ -1149,6 +1303,101 @@ export function recordSandboxDeadlineRotationsRequested(
|
|
|
1149
1303
|
});
|
|
1150
1304
|
}
|
|
1151
1305
|
|
|
1306
|
+
/** Fixed outcomes of legacy retained-command containment: per-candidate
|
|
1307
|
+
* enrollment inspection, then the enrolled drain's exact cold commit. */
|
|
1308
|
+
export const SANDBOX_COMMAND_CONTAINMENT_OUTCOMES = [
|
|
1309
|
+
"idle_enrolled",
|
|
1310
|
+
"deadline_enrolled",
|
|
1311
|
+
"resumed_enrolled",
|
|
1312
|
+
"not_eligible",
|
|
1313
|
+
"inspection_failed",
|
|
1314
|
+
"contained",
|
|
1315
|
+
"provider_missing",
|
|
1316
|
+
] as const;
|
|
1317
|
+
|
|
1318
|
+
export type SandboxCommandContainmentOutcome =
|
|
1319
|
+
(typeof SANDBOX_COMMAND_CONTAINMENT_OUTCOMES)[number];
|
|
1320
|
+
|
|
1321
|
+
export function recordSandboxCommandContainment(
|
|
1322
|
+
observability: Observability,
|
|
1323
|
+
outcome: SandboxCommandContainmentOutcome,
|
|
1324
|
+
): void {
|
|
1325
|
+
observability.incrementCounter({
|
|
1326
|
+
name: "opengeni_sandbox_command_containment_total",
|
|
1327
|
+
help: "Legacy retained-command containment inspections and enrolled drain commits by fixed outcome.",
|
|
1328
|
+
labels: { outcome },
|
|
1329
|
+
});
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
/** Only call after the exact draining->cold commit reports wentCold. The
|
|
1333
|
+
* backend is validated against the closed contract so provider IDs and other
|
|
1334
|
+
* per-sandbox values can never become metric labels. */
|
|
1335
|
+
export function recordSandboxProviderMissingBeforeCapture(
|
|
1336
|
+
observability: Observability,
|
|
1337
|
+
backend: string,
|
|
1338
|
+
): void {
|
|
1339
|
+
const safeBackend = SandboxBackend.safeParse(backend).success ? backend : "unknown";
|
|
1340
|
+
observability.incrementCounter({
|
|
1341
|
+
name: "opengeni_sandbox_provider_missing_before_capture_total",
|
|
1342
|
+
help: "Exact sandbox cold commits after definitive provider disappearance before workspace capture.",
|
|
1343
|
+
labels: { backend: safeBackend },
|
|
1344
|
+
});
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1347
|
+
export function recordSandboxRecoveryObservationGauges(
|
|
1348
|
+
observability: Observability,
|
|
1349
|
+
observations: {
|
|
1350
|
+
providerLosses: number;
|
|
1351
|
+
fallbackSelections: number;
|
|
1352
|
+
freshWorkspaceSelections?: number;
|
|
1353
|
+
},
|
|
1354
|
+
): void {
|
|
1355
|
+
for (const [kind, value] of [
|
|
1356
|
+
["provider_missing_before_capture", observations.providerLosses],
|
|
1357
|
+
["checkpoint_fallback_selected", observations.fallbackSelections],
|
|
1358
|
+
["fresh_workspace_selected", observations.freshWorkspaceSelections ?? 0],
|
|
1359
|
+
] as const) {
|
|
1360
|
+
observability.setGauge({
|
|
1361
|
+
name: "opengeni_sandbox_recovery_observations_recent",
|
|
1362
|
+
help: "Committed sandbox recovery observations in the last 30 minutes by fixed kind.",
|
|
1363
|
+
labels: { kind },
|
|
1364
|
+
value,
|
|
1365
|
+
});
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
|
|
1369
|
+
/** Fixed outcomes for a committed automatic continuity decision after
|
|
1370
|
+
* definitive managed-provider loss: a singleton checkpoint (`selected`), a
|
|
1371
|
+
* shared-group checkpoint (`selected_shared`), or a new empty workspace
|
|
1372
|
+
* (`fresh_workspace`). Call only after the durable authorization committed. */
|
|
1373
|
+
export const SANDBOX_AUTOMATIC_RECOVERY_OUTCOMES = [
|
|
1374
|
+
"selected",
|
|
1375
|
+
"selected_shared",
|
|
1376
|
+
"fresh_workspace",
|
|
1377
|
+
] as const;
|
|
1378
|
+
export type SandboxAutomaticRecoveryOutcome = (typeof SANDBOX_AUTOMATIC_RECOVERY_OUTCOMES)[number];
|
|
1379
|
+
|
|
1380
|
+
export function sandboxAutomaticRecoveryOutcome(input: {
|
|
1381
|
+
lane: "checkpoint" | "fresh_workspace";
|
|
1382
|
+
groupSessionCount: number;
|
|
1383
|
+
}): SandboxAutomaticRecoveryOutcome {
|
|
1384
|
+
if (input.lane === "fresh_workspace") return "fresh_workspace";
|
|
1385
|
+
return input.groupSessionCount > 1 ? "selected_shared" : "selected";
|
|
1386
|
+
}
|
|
1387
|
+
|
|
1388
|
+
export function recordSandboxAutomaticRecoverySelected(
|
|
1389
|
+
observability: Observability,
|
|
1390
|
+
backend: string,
|
|
1391
|
+
outcome: SandboxAutomaticRecoveryOutcome,
|
|
1392
|
+
): void {
|
|
1393
|
+
const safeBackend = SandboxBackend.safeParse(backend).success ? backend : "unknown";
|
|
1394
|
+
observability.incrementCounter({
|
|
1395
|
+
name: "opengeni_sandbox_checkpoint_fallback_total",
|
|
1396
|
+
help: "System-selected continuity after managed provider loss: verified checkpoint or empty workspace.",
|
|
1397
|
+
labels: { backend: safeBackend, outcome },
|
|
1398
|
+
});
|
|
1399
|
+
}
|
|
1400
|
+
|
|
1152
1401
|
export function recordSandboxRotationBacklogGauges(
|
|
1153
1402
|
observability: Observability,
|
|
1154
1403
|
backlog: {
|
|
@@ -1266,6 +1515,7 @@ export function recordExpiredDrainingSandboxLeaseGauges(
|
|
|
1266
1515
|
|
|
1267
1516
|
export const RETAINED_PROCESS_RECONCILIATION_OUTCOMES = [
|
|
1268
1517
|
"claim_failed",
|
|
1518
|
+
"background_recovered",
|
|
1269
1519
|
"proof_exited",
|
|
1270
1520
|
"proof_lost",
|
|
1271
1521
|
"proof_checkpoint_failed",
|
|
@@ -1353,10 +1603,18 @@ export function recordModelRequestPhase(
|
|
|
1353
1603
|
}
|
|
1354
1604
|
|
|
1355
1605
|
export type TurnStartupPhase =
|
|
1606
|
+
| "services_initialization"
|
|
1607
|
+
| "claim_catalog_read"
|
|
1608
|
+
| "claim_atomic"
|
|
1609
|
+
| "claim_session_read"
|
|
1610
|
+
| "claim_capability_settings"
|
|
1611
|
+
| "learning_policy_freeze"
|
|
1612
|
+
| "attachment_authority_projection"
|
|
1356
1613
|
| "claim_and_policy"
|
|
1357
1614
|
| "turn_start_settlement"
|
|
1358
1615
|
| "credential_selection"
|
|
1359
1616
|
| "runtime_preparation"
|
|
1617
|
+
| "session_mcp_settings"
|
|
1360
1618
|
| "sandbox_establish"
|
|
1361
1619
|
| "file_resolution"
|
|
1362
1620
|
| "tool_context_preparation"
|
|
@@ -1386,7 +1644,7 @@ export type TurnStartupPhase =
|
|
|
1386
1644
|
| "history_generated_image_materialization"
|
|
1387
1645
|
| "history_position_load"
|
|
1388
1646
|
| "owned_sandbox_setup"
|
|
1389
|
-
| "
|
|
1647
|
+
| "runtime_stream_initialization"
|
|
1390
1648
|
| "model_request_preparation"
|
|
1391
1649
|
| "model_sdk_serialization"
|
|
1392
1650
|
| "model_prepare_sandbox_agent_preparation"
|
|
@@ -1492,7 +1750,8 @@ export function turnStartupCountBucket(count: number | null): TurnStartupCountBu
|
|
|
1492
1750
|
}
|
|
1493
1751
|
|
|
1494
1752
|
/**
|
|
1495
|
-
* Measure
|
|
1753
|
+
* Measure startup operations, including nested and parallel work. These are
|
|
1754
|
+
* not additive critical-path intervals; use milestones for elapsed latency.
|
|
1496
1755
|
* Every label is a closed or configuration-derived enum; high-cardinality turn,
|
|
1497
1756
|
* session, credential, connection, file, and model identifiers are forbidden.
|
|
1498
1757
|
*/
|
|
@@ -1506,8 +1765,19 @@ export function recordTurnStartupPhase(
|
|
|
1506
1765
|
durationSeconds: number;
|
|
1507
1766
|
count?: number | null;
|
|
1508
1767
|
cache?: TurnStartupCache;
|
|
1768
|
+
/** Trace-only lookup for the completed claim while its execution root is still open. */
|
|
1769
|
+
executionCorrelationId?: string;
|
|
1509
1770
|
},
|
|
1510
1771
|
): void {
|
|
1772
|
+
completedOperationSpan(observability, `worker.prepare.${input.phase}`, input.durationSeconds, {
|
|
1773
|
+
provider: input.provider,
|
|
1774
|
+
backend: input.backend,
|
|
1775
|
+
outcome: input.outcome,
|
|
1776
|
+
...(input.phase === "claim_and_policy" &&
|
|
1777
|
+
/^turn_[0-9a-f]{32}$/.test(input.executionCorrelationId ?? "")
|
|
1778
|
+
? { correlationId: input.executionCorrelationId }
|
|
1779
|
+
: {}),
|
|
1780
|
+
});
|
|
1511
1781
|
observability.observeHistogram({
|
|
1512
1782
|
name: "opengeni_turn_startup_phase_duration_seconds",
|
|
1513
1783
|
help: "Turn startup phase duration before the model response stream begins.",
|
|
@@ -1524,6 +1794,103 @@ export function recordTurnStartupPhase(
|
|
|
1524
1794
|
});
|
|
1525
1795
|
}
|
|
1526
1796
|
|
|
1797
|
+
/** Observe an existing dependency only. Child intervals can overlap and are
|
|
1798
|
+
* not additive; observer failure must never change authority or error identity. */
|
|
1799
|
+
export async function measureTurnStartupPhase<T>(
|
|
1800
|
+
observability: Observability,
|
|
1801
|
+
input: Omit<Parameters<typeof recordTurnStartupPhase>[1], "durationSeconds" | "outcome">,
|
|
1802
|
+
work: () => Promise<T>,
|
|
1803
|
+
): Promise<T> {
|
|
1804
|
+
const started = performance.now();
|
|
1805
|
+
let outcome: TurnStartupOutcome = "failed";
|
|
1806
|
+
try {
|
|
1807
|
+
const result = await work();
|
|
1808
|
+
outcome = "completed";
|
|
1809
|
+
return result;
|
|
1810
|
+
} finally {
|
|
1811
|
+
try {
|
|
1812
|
+
recordTurnStartupPhase(observability, {
|
|
1813
|
+
...input,
|
|
1814
|
+
outcome,
|
|
1815
|
+
durationSeconds: (performance.now() - started) / 1_000,
|
|
1816
|
+
});
|
|
1817
|
+
} catch {
|
|
1818
|
+
// Telemetry is not an execution gate.
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1821
|
+
}
|
|
1822
|
+
|
|
1823
|
+
/** Background MCP preparation must not inflate startup phase distributions. */
|
|
1824
|
+
export function recordToolPreparationPhase(
|
|
1825
|
+
observability: Observability,
|
|
1826
|
+
input: ToolPreparationPhaseMeasurement & { provider: string; backend: string },
|
|
1827
|
+
): void {
|
|
1828
|
+
if (input.execution === "blocking") {
|
|
1829
|
+
recordTurnStartupPhase(observability, {
|
|
1830
|
+
...input,
|
|
1831
|
+
phase: `tool_${input.phase}`,
|
|
1832
|
+
});
|
|
1833
|
+
return;
|
|
1834
|
+
}
|
|
1835
|
+
completedOperationSpan(
|
|
1836
|
+
observability,
|
|
1837
|
+
`worker.tool_prepare.${input.phase}`,
|
|
1838
|
+
input.durationSeconds,
|
|
1839
|
+
{
|
|
1840
|
+
provider: input.provider,
|
|
1841
|
+
backend: input.backend,
|
|
1842
|
+
outcome: input.outcome,
|
|
1843
|
+
},
|
|
1844
|
+
);
|
|
1845
|
+
observability.observeHistogram({
|
|
1846
|
+
name: "opengeni_tool_background_preparation_duration_seconds",
|
|
1847
|
+
help: "Nonblocking MCP preparation operations; may overlap startup and later execution.",
|
|
1848
|
+
buckets: TURN_STARTUP_PHASE_BUCKETS,
|
|
1849
|
+
labels: {
|
|
1850
|
+
phase: input.phase,
|
|
1851
|
+
provider: input.provider,
|
|
1852
|
+
backend: input.backend,
|
|
1853
|
+
outcome: input.outcome,
|
|
1854
|
+
},
|
|
1855
|
+
value: Math.max(0, input.durationSeconds),
|
|
1856
|
+
});
|
|
1857
|
+
}
|
|
1858
|
+
|
|
1859
|
+
/** Completed measurements become siblings under the scoped physical attempt.
|
|
1860
|
+
* They never establish ambient ancestry for work which has already finished. */
|
|
1861
|
+
function completedOperationSpan(
|
|
1862
|
+
observability: Observability,
|
|
1863
|
+
name: string,
|
|
1864
|
+
durationSeconds: number,
|
|
1865
|
+
attributes: {
|
|
1866
|
+
outcome: string;
|
|
1867
|
+
provider?: string;
|
|
1868
|
+
backend?: string;
|
|
1869
|
+
correlationId?: string | undefined;
|
|
1870
|
+
},
|
|
1871
|
+
): void {
|
|
1872
|
+
if (!Number.isFinite(durationSeconds) || durationSeconds < 0) return;
|
|
1873
|
+
try {
|
|
1874
|
+
const failed = [
|
|
1875
|
+
"failed",
|
|
1876
|
+
"error",
|
|
1877
|
+
"provider_declared_error",
|
|
1878
|
+
"auth_needed",
|
|
1879
|
+
"outcome_uncertain",
|
|
1880
|
+
"timeout",
|
|
1881
|
+
"thrown_transport_error",
|
|
1882
|
+
"thrown_protocol_error",
|
|
1883
|
+
].includes(attributes.outcome);
|
|
1884
|
+
observability
|
|
1885
|
+
.startSpan(name, attributes, { startTimeMs: Date.now() - durationSeconds * 1_000 })
|
|
1886
|
+
.end({
|
|
1887
|
+
...(failed ? { error: true } : {}),
|
|
1888
|
+
});
|
|
1889
|
+
} catch {
|
|
1890
|
+
// Observers cannot change the completed model/tool/phase outcome.
|
|
1891
|
+
}
|
|
1892
|
+
}
|
|
1893
|
+
|
|
1527
1894
|
/**
|
|
1528
1895
|
* Explain why a turn did or did not keep provider sandbox work off the
|
|
1529
1896
|
* pre-model critical path. The reason is a closed enum: never attach session,
|
|
@@ -2161,3 +2528,141 @@ export function modelCallAccountContext(input: {
|
|
|
2161
2528
|
accountChangedFromPrevCall,
|
|
2162
2529
|
};
|
|
2163
2530
|
}
|
|
2531
|
+
|
|
2532
|
+
export type CodeSearchCallOutcome =
|
|
2533
|
+
| "completed"
|
|
2534
|
+
| "jev_unavailable"
|
|
2535
|
+
| "jev_rejected"
|
|
2536
|
+
| "workspace_unavailable"
|
|
2537
|
+
| "invalid_arguments"
|
|
2538
|
+
| "breaker_open"
|
|
2539
|
+
| "cancelled"
|
|
2540
|
+
| "failed";
|
|
2541
|
+
|
|
2542
|
+
/** One `code_search` tool call: outcome, wall time and the Jev work it used. */
|
|
2543
|
+
export function recordCodeSearchCall(
|
|
2544
|
+
observability: Observability,
|
|
2545
|
+
input: {
|
|
2546
|
+
outcome: CodeSearchCallOutcome;
|
|
2547
|
+
durationSeconds: number;
|
|
2548
|
+
jevRequests: number;
|
|
2549
|
+
jevCostUsd: number;
|
|
2550
|
+
},
|
|
2551
|
+
): void {
|
|
2552
|
+
observability.incrementCounter({
|
|
2553
|
+
name: "opengeni_code_search_calls_total",
|
|
2554
|
+
help: "Jev-backed code_search tool calls by outcome.",
|
|
2555
|
+
labels: { outcome: input.outcome },
|
|
2556
|
+
});
|
|
2557
|
+
observability.observeHistogram({
|
|
2558
|
+
name: "opengeni_code_search_duration_seconds",
|
|
2559
|
+
help: "Wall time of one code_search tool call.",
|
|
2560
|
+
buckets: [0.5, 1, 2, 4, 8, 15, 30, 60],
|
|
2561
|
+
labels: { outcome: input.outcome },
|
|
2562
|
+
value: Math.max(0, input.durationSeconds),
|
|
2563
|
+
});
|
|
2564
|
+
if (input.jevRequests > 0) {
|
|
2565
|
+
observability.incrementCounter({
|
|
2566
|
+
name: "opengeni_code_search_jev_requests_total",
|
|
2567
|
+
help: "Jev requests made by code_search.",
|
|
2568
|
+
amount: input.jevRequests,
|
|
2569
|
+
});
|
|
2570
|
+
}
|
|
2571
|
+
if (input.jevCostUsd > 0) {
|
|
2572
|
+
observability.incrementCounter({
|
|
2573
|
+
name: "opengeni_code_search_jev_cost_micro_usd_total",
|
|
2574
|
+
help: "Estimated Jev list-price cost of code_search, in micro-USD.",
|
|
2575
|
+
amount: Math.round(input.jevCostUsd * 1_000_000),
|
|
2576
|
+
});
|
|
2577
|
+
}
|
|
2578
|
+
}
|
|
2579
|
+
|
|
2580
|
+
/**
|
|
2581
|
+
* One skill_read call. Labels are closed sets: `skill` is a built-in id or
|
|
2582
|
+
* `custom` for every other Skill, so tenant Skill ids, names, and requested
|
|
2583
|
+
* identifiers never become labels. `source` is `unknown` when the read was
|
|
2584
|
+
* refused before a Skill resolved.
|
|
2585
|
+
*/
|
|
2586
|
+
export function recordSkillRead(
|
|
2587
|
+
observability: Observability,
|
|
2588
|
+
read: {
|
|
2589
|
+
caller: "model" | "codemode";
|
|
2590
|
+
kind: SkillReadKind;
|
|
2591
|
+
source: SkillUseSource | null;
|
|
2592
|
+
/** The resolved Skill id, or the requested identifier when none resolved. */
|
|
2593
|
+
skill: string;
|
|
2594
|
+
},
|
|
2595
|
+
): void {
|
|
2596
|
+
observability.incrementCounter({
|
|
2597
|
+
name: "opengeni_skill_reads_total",
|
|
2598
|
+
help: "skill_read calls by Skill source, built-in Skill id (custom for any other Skill), result kind, and caller.",
|
|
2599
|
+
labels: {
|
|
2600
|
+
source: read.source ?? "unknown",
|
|
2601
|
+
skill: skillReadMetricLabel(read.source, read.skill),
|
|
2602
|
+
kind: read.kind,
|
|
2603
|
+
caller: read.caller,
|
|
2604
|
+
},
|
|
2605
|
+
});
|
|
2606
|
+
}
|
|
2607
|
+
|
|
2608
|
+
/**
|
|
2609
|
+
* One skill_checkout call. Labels are closed sets and never carry Skill ids,
|
|
2610
|
+
* names, or paths. Phases that did not run are not observed.
|
|
2611
|
+
*/
|
|
2612
|
+
export function recordSkillCheckout(
|
|
2613
|
+
observability: Observability,
|
|
2614
|
+
checkout: {
|
|
2615
|
+
outcome: "written" | "unchanged" | "refused" | "failed";
|
|
2616
|
+
selection: "all" | "paths";
|
|
2617
|
+
written: number;
|
|
2618
|
+
unchanged: number;
|
|
2619
|
+
resolveSeconds: number | null;
|
|
2620
|
+
sandboxSeconds: number | null;
|
|
2621
|
+
writeSeconds: number | null;
|
|
2622
|
+
totalSeconds: number;
|
|
2623
|
+
},
|
|
2624
|
+
): void {
|
|
2625
|
+
observability.incrementCounter({
|
|
2626
|
+
name: "opengeni_skill_checkouts_total",
|
|
2627
|
+
help: "skill_checkout calls by outcome and whether they selected specific paths.",
|
|
2628
|
+
labels: { outcome: checkout.outcome, selection: checkout.selection },
|
|
2629
|
+
});
|
|
2630
|
+
const phases = [
|
|
2631
|
+
["resolve", checkout.resolveSeconds],
|
|
2632
|
+
["sandbox", checkout.sandboxSeconds],
|
|
2633
|
+
["write", checkout.writeSeconds],
|
|
2634
|
+
["total", checkout.totalSeconds],
|
|
2635
|
+
] as const;
|
|
2636
|
+
for (const [phase, seconds] of phases) {
|
|
2637
|
+
if (seconds === null) continue;
|
|
2638
|
+
observability.observeHistogram({
|
|
2639
|
+
name: "opengeni_skill_checkout_duration_seconds",
|
|
2640
|
+
help: "Wall time of skill_checkout phases: resolve (authority and Skill read), sandbox (filesystem handle, including lazy box start), write (batched file write), and total.",
|
|
2641
|
+
buckets: [0.05, 0.1, 0.25, 0.5, 1, 2, 4, 8, 15, 30, 60],
|
|
2642
|
+
labels: { phase, outcome: checkout.outcome },
|
|
2643
|
+
value: Math.max(0, seconds),
|
|
2644
|
+
});
|
|
2645
|
+
}
|
|
2646
|
+
for (const [result, amount] of [
|
|
2647
|
+
["written", checkout.written],
|
|
2648
|
+
["unchanged", checkout.unchanged],
|
|
2649
|
+
] as const) {
|
|
2650
|
+
if (amount <= 0) continue;
|
|
2651
|
+
observability.incrementCounter({
|
|
2652
|
+
name: "opengeni_skill_checkout_files_total",
|
|
2653
|
+
help: "Files skill_checkout wrote or found already present with the same content.",
|
|
2654
|
+
labels: { result },
|
|
2655
|
+
amount,
|
|
2656
|
+
});
|
|
2657
|
+
}
|
|
2658
|
+
}
|
|
2659
|
+
|
|
2660
|
+
function skillReadMetricLabel(source: SkillUseSource | null, skill: string): string {
|
|
2661
|
+
if (source !== null && source !== "builtin") return "custom";
|
|
2662
|
+
// A refused read may name a built-in by its plain name.
|
|
2663
|
+
for (const candidate of source === null ? [skill, `builtin:${skill}`] : [skill]) {
|
|
2664
|
+
const parsed = BundledSkillId.safeParse(candidate);
|
|
2665
|
+
if (parsed.success) return parsed.data;
|
|
2666
|
+
}
|
|
2667
|
+
return "custom";
|
|
2668
|
+
}
|
|
@@ -295,6 +295,8 @@ export function personalGitBrokerOrigin(settings: Settings): string | null {
|
|
|
295
295
|
(url.hostname === "host.docker.internal" ||
|
|
296
296
|
url.hostname === cachedDockerBridgeGateway ||
|
|
297
297
|
/^[a-z][a-z0-9-]{0,62}$/iu.test(url.hostname));
|
|
298
|
+
// The `local` and `test` environments accept any origin, which covers the
|
|
299
|
+
// local launcher's Linux Docker sandbox route on the Compose network gateway.
|
|
298
300
|
const privateExecutionOrigin =
|
|
299
301
|
(url.protocol === "http:" &&
|
|
300
302
|
(url.hostname === "127.0.0.1" || url.hostname === "localhost" || dockerPrivateOrigin)) ||
|
|
@@ -329,7 +331,6 @@ function exactPersonalGitHubDelegation(
|
|
|
329
331
|
delegation.providerDomain !== "github.com" ||
|
|
330
332
|
delegation.kind !== "oauth2" ||
|
|
331
333
|
!delegation.originWorkspaceId ||
|
|
332
|
-
!delegation.userDelegation ||
|
|
333
334
|
!delegation.personalGitHubRepositorySelection
|
|
334
335
|
) {
|
|
335
336
|
throw new Error("personal GitHub Git delegation is unavailable");
|
|
@@ -5,7 +5,6 @@ import type {
|
|
|
5
5
|
GitCredentialsRequest,
|
|
6
6
|
} from "@opengeni/contracts";
|
|
7
7
|
import { prReviewRegistrationIdFromCredentialBinding } from "@opengeni/core";
|
|
8
|
-
import { createNativeRemoteMcpCredentialsPort } from "@opengeni/core/remote-mcp-credentials";
|
|
9
8
|
import { decryptVariableSetValue, resolvePrReviewGitCredential, type Database } from "@opengeni/db";
|
|
10
9
|
import {
|
|
11
10
|
createGitHubAppInstallationTokenWithExpiry,
|
|
@@ -19,7 +18,6 @@ export function createStandaloneConnectionCredentialsPort(
|
|
|
19
18
|
db: Database,
|
|
20
19
|
): ConnectionCredentialsPort {
|
|
21
20
|
return {
|
|
22
|
-
...createNativeRemoteMcpCredentialsPort(settings, db),
|
|
23
21
|
gitCredentials: async (request) => await resolveStandaloneGitCredentials(settings, db, request),
|
|
24
22
|
};
|
|
25
23
|
}
|
|
@@ -113,7 +111,7 @@ async function resolveStandaloneGitCredentials(
|
|
|
113
111
|
authority.credentialKind === "managed_github_app" &&
|
|
114
112
|
settings.prReviewGithubAppId !== authority.appId
|
|
115
113
|
) {
|
|
116
|
-
throw new Error("
|
|
114
|
+
throw new Error("Opengeni Lens App identity no longer matches this registration");
|
|
117
115
|
}
|
|
118
116
|
const minted = await createGitHubAppInstallationTokenWithSigningSettings(signingSettings, {
|
|
119
117
|
installationId: request.installationId,
|