@opengeni/core 3.0.1 → 3.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/access/index.d.ts +131 -7
- package/dist/access/service-initiator.d.ts +3 -0
- package/dist/application/archived-session-imports.d.ts +6 -0
- package/dist/application/composer-submit.d.ts +1 -1
- package/dist/application/connect-operation.d.ts +6 -0
- package/dist/application/external-workspace-members.d.ts +13 -1
- package/dist/application/modal-native-live-declaration-join.d.ts +37 -0
- package/dist/application/modal-native-original-configuration.d.ts +79 -0
- package/dist/application/modal-native-worker-host-transport.d.ts +297 -0
- package/dist/application/new-session-drafts.d.ts +29 -2
- package/dist/application/organization-privacy.d.ts +57 -0
- package/dist/application/prepared-mcp-connection.d.ts +31 -0
- package/dist/application/sandbox-recovery.d.ts +58 -0
- package/dist/application/session-commands.d.ts +3 -0
- package/dist/application/session-tenancy.d.ts +13 -4
- package/dist/billing/agent-run-admission.d.ts +21 -0
- package/dist/billing/limits.d.ts +27 -1
- package/dist/billing/model-call-admission.d.ts +34 -0
- package/dist/billing/model-usage-settlement.d.ts +112 -0
- package/dist/canonical-human-identities.js +1 -1
- package/dist/{chunk-VCZFFEPB.js → chunk-7T2SZ7BI.js} +16 -2
- package/dist/chunk-7T2SZ7BI.js.map +1 -0
- package/dist/{chunk-ZYCNLYGH.js → chunk-OMJFIIWK.js} +178 -12
- package/dist/chunk-OMJFIIWK.js.map +1 -0
- package/dist/{chunk-H7X52RI2.js → chunk-QI2M2B2K.js} +83 -8
- package/dist/chunk-QI2M2B2K.js.map +1 -0
- package/dist/{chunk-OF65T3PM.js → chunk-TTWTXQB2.js} +94 -6
- package/dist/chunk-TTWTXQB2.js.map +1 -0
- package/dist/codex-model-availability.d.ts +55 -0
- package/dist/default-session-model.d.ts +192 -0
- package/dist/dependencies.d.ts +41 -7
- package/dist/developer-setup-credential-ceiling.d.ts +10 -0
- package/dist/domain/agent-config-resolution.d.ts +49 -0
- package/dist/domain/automations.d.ts +8 -1
- package/dist/domain/capabilities.d.ts +112 -8
- package/dist/domain/connection-account-selection-error.d.ts +8 -0
- package/dist/domain/connector-tool-permissions.d.ts +62 -0
- package/dist/domain/direct-model-provider.d.ts +3 -0
- package/dist/domain/editable-artifacts/agent-application.d.ts +10 -1
- package/dist/domain/editable-artifacts/durable-export.d.ts +22 -1
- package/dist/domain/editable-artifacts/ports.d.ts +10 -0
- package/dist/domain/editable-artifacts/service.d.ts +3 -1
- package/dist/domain/editable-artifacts/types.d.ts +1 -1
- package/dist/domain/encryption-key.d.ts +12 -0
- package/dist/domain/insights-timing.d.ts +16 -0
- package/dist/domain/insights-usage.d.ts +27 -0
- package/dist/domain/insights.d.ts +21 -3
- package/dist/domain/knowledge-files.d.ts +1 -1
- package/dist/domain/knowledge-preparation.d.ts +10 -0
- package/dist/domain/knowledge-preparation.test.d.ts +1 -0
- package/dist/domain/knowledge-search.d.ts +15 -76
- package/dist/domain/mcp-account-bindings.d.ts +17 -0
- package/dist/domain/mcp-account-routes.d.ts +21 -0
- package/dist/domain/native-mcp-connection-admission.d.ts +3 -0
- package/dist/domain/organization-integration-catalog.d.ts +15 -0
- package/dist/domain/personal-connection-delegations.d.ts +73 -12
- package/dist/domain/pr-review.d.ts +121 -6
- package/dist/domain/realtime-voice-billing.d.ts +103 -0
- package/dist/domain/resources.d.ts +17 -1
- package/dist/domain/scheduled-task-access.d.ts +265 -0
- package/dist/domain/scheduled-task-account-audit.d.ts +27 -0
- package/dist/domain/scheduled-task-audience.d.ts +70 -0
- package/dist/domain/scheduled-tasks.d.ts +61 -18
- package/dist/domain/session-connection-accounts.d.ts +53 -0
- package/dist/domain/session-file-access.d.ts +4 -0
- package/dist/domain/session-native-connection-replacement.d.ts +14 -0
- package/dist/domain/session-start-timing.d.ts +7 -0
- package/dist/domain/session-tool-policy.d.ts +102 -4
- package/dist/domain/sessions.d.ts +179 -15
- package/dist/domain/site-audience.d.ts +52 -0
- package/dist/domain/skills.d.ts +29 -1
- package/dist/domain/slack-bot.d.ts +46 -1
- package/dist/domain/slack-publication-secret-safety.d.ts +1 -1
- package/dist/domain/vaults/index.d.ts +7 -0
- package/dist/domain/vaults/mapping.d.ts +25 -0
- package/dist/domain/vaults/provider-registry.d.ts +72 -0
- package/dist/domain/vaults/provider-sync.d.ts +176 -0
- package/dist/domain/vaults/provider-writes.d.ts +57 -0
- package/dist/domain/vaults/secret-resolver.d.ts +34 -0
- package/dist/domain/vaults/types.d.ts +24 -0
- package/dist/domain/vaults/vault-service.d.ts +35 -0
- package/dist/domain/voice-input-billing.d.ts +77 -0
- package/dist/domain/web-search-billing.d.ts +51 -0
- package/dist/domain/workspace-credits.d.ts +7 -0
- package/dist/editable-artifact-live/application.d.ts +2 -1
- package/dist/editable-artifact-live/server.d.ts +5 -1
- package/dist/editable-artifact-live/ticket.d.ts +2 -1
- package/dist/editable-artifact-live/types.d.ts +9 -0
- package/dist/editable-artifact-live.js +2 -2
- package/dist/editable-artifacts.js +10 -2
- package/dist/goal-admission.d.ts +627 -0
- package/dist/host-session-usage-limit.d.ts +15 -0
- package/dist/index.d.ts +43 -8
- package/dist/index.js +22682 -11743
- package/dist/index.js.map +1 -1
- package/dist/managed-session.d.ts +110 -7
- package/dist/model-call.d.ts +58 -0
- package/dist/model-catalog.d.ts +29 -3
- package/dist/model-provider-credentials.d.ts +43 -0
- package/dist/product-usage-metrics.d.ts +30 -0
- package/dist/rigs/index.d.ts +1 -13
- package/dist/sandbox/fleet.d.ts +58 -4
- package/dist/sandbox/routing.d.ts +42 -2
- package/dist/sandbox/runtime-settings.d.ts +27 -17
- package/dist/session-authorization.d.ts +10 -0
- package/dist/session-usage-limit-metrics.d.ts +60 -0
- package/dist/session-usage-limits.d.ts +89 -0
- package/dist/site-agent-clamp.d.ts +71 -0
- package/dist/site-session-origin.d.ts +39 -2
- package/dist/transcription.d.ts +120 -3
- package/dist/turn-surface.d.ts +20 -0
- package/dist/user-presence.d.ts +32 -0
- package/dist/workflow-wake-contract.d.ts +13 -1
- package/package.json +15 -22
- package/src/access/index.ts +961 -38
- package/src/access/service-initiator.ts +50 -0
- package/src/application/api-integration-servers.ts +9 -0
- package/src/application/archived-session-imports.ts +161 -0
- package/src/application/composer-submit.ts +3 -2
- package/src/application/connect-authority.ts +3 -3
- package/src/application/connect-operation.ts +37 -3
- package/src/application/external-continuation.ts +20 -3
- package/src/application/external-link-work-admission.ts +3 -0
- package/src/application/external-workspace-members.ts +51 -3
- package/src/application/modal-native-live-declaration-join.ts +196 -0
- package/src/application/modal-native-original-configuration.ts +261 -0
- package/src/application/modal-native-worker-host-transport.ts +263 -0
- package/src/application/new-session-drafts.ts +172 -55
- package/src/application/organization-privacy.ts +161 -0
- package/src/application/prepared-mcp-connection.ts +133 -0
- package/src/application/sandbox-recovery.ts +78 -0
- package/src/application/session-commands.ts +73 -1
- package/src/application/session-mcp-credential-rotation.ts +61 -18
- package/src/application/session-tenancy.ts +262 -44
- package/src/application/user-resource-grants.ts +1 -29
- package/src/billing/agent-run-admission.ts +117 -0
- package/src/billing/limits.ts +138 -14
- package/src/billing/model-call-admission.ts +118 -0
- package/src/billing/model-usage-settlement.ts +472 -0
- package/src/codex-model-availability.ts +264 -0
- package/src/default-session-model.ts +692 -0
- package/src/dependencies.ts +48 -6
- package/src/developer-setup-credential-ceiling.ts +60 -0
- package/src/domain/agent-config-resolution.ts +148 -0
- package/src/domain/automations.ts +76 -2
- package/src/domain/capabilities.ts +830 -181
- package/src/domain/connection-account-selection-error.ts +19 -0
- package/src/domain/connector-tool-permissions.ts +572 -0
- package/src/domain/direct-model-provider.ts +62 -0
- package/src/domain/editable-artifacts/agent-application.ts +44 -6
- package/src/domain/editable-artifacts/durable-export.ts +100 -5
- package/src/domain/editable-artifacts/in-memory.ts +6 -0
- package/src/domain/editable-artifacts/ports.ts +11 -0
- package/src/domain/editable-artifacts/service.ts +20 -0
- package/src/domain/editable-artifacts/types.ts +1 -1
- package/src/domain/encryption-key.ts +26 -0
- package/src/domain/file-owner.ts +16 -1
- package/src/domain/github-action-policies.ts +1 -1
- package/src/domain/github-skill-source.ts +3 -1
- package/src/domain/insights-timing.ts +95 -0
- package/src/domain/insights-usage.ts +67 -0
- package/src/domain/insights.ts +167 -43
- package/src/domain/knowledge-files.ts +10 -3
- package/src/domain/knowledge-messages.ts +1 -0
- package/src/domain/knowledge-preparation.test.ts +276 -0
- package/src/domain/knowledge-preparation.ts +147 -0
- package/src/domain/knowledge-search.test.ts +617 -5
- package/src/domain/knowledge-search.ts +240 -23
- package/src/domain/mcp-account-bindings.ts +169 -0
- package/src/domain/mcp-account-routes.ts +152 -0
- package/src/domain/native-mcp-connection-admission.ts +14 -0
- package/src/domain/organization-integration-catalog.ts +88 -0
- package/src/domain/personal-connection-delegations.ts +399 -257
- package/src/domain/pr-review.ts +24 -8
- package/src/domain/realtime-voice-billing.ts +425 -0
- package/src/domain/resources.ts +50 -4
- package/src/domain/scheduled-task-access.ts +1089 -0
- package/src/domain/scheduled-task-account-audit.ts +90 -0
- package/src/domain/scheduled-task-audience.ts +249 -0
- package/src/domain/scheduled-tasks.ts +1313 -374
- package/src/domain/session-connection-accounts.ts +239 -0
- package/src/domain/session-file-access.ts +47 -0
- package/src/domain/session-native-connection-replacement.ts +64 -0
- package/src/domain/session-start-timing.ts +60 -0
- package/src/domain/session-tool-policy.ts +489 -14
- package/src/domain/sessions.ts +2254 -717
- package/src/domain/site-audience.ts +130 -0
- package/src/domain/skills.ts +9 -0
- package/src/domain/slack-bot.ts +141 -4
- package/src/domain/slack-publication-secret-safety.ts +1 -1
- package/src/domain/vaults/index.ts +19 -0
- package/src/domain/vaults/mapping.ts +190 -0
- package/src/domain/vaults/provider-registry.ts +201 -0
- package/src/domain/vaults/provider-sync.ts +531 -0
- package/src/domain/vaults/provider-writes.ts +288 -0
- package/src/domain/vaults/secret-resolver.ts +464 -0
- package/src/domain/vaults/types.ts +26 -0
- package/src/domain/vaults/vault-service.ts +1316 -0
- package/src/domain/voice-input-billing.ts +330 -0
- package/src/domain/web-search-billing.ts +169 -0
- package/src/domain/workspace-credits.ts +13 -0
- package/src/editable-artifact-live/application.ts +8 -1
- package/src/editable-artifact-live/server.ts +154 -6
- package/src/editable-artifact-live/ticket.ts +86 -1
- package/src/editable-artifact-live/types.ts +10 -0
- package/src/goal-admission.ts +220 -0
- package/src/host-session-usage-limit.ts +25 -0
- package/src/index.ts +75 -11
- package/src/managed-session.ts +137 -6
- package/src/model-call.ts +79 -0
- package/src/model-catalog.ts +345 -91
- package/src/model-provider-credentials.ts +394 -0
- package/src/product-usage-metrics.ts +101 -0
- package/src/rigs/index.ts +23 -111
- package/src/sandbox/fleet.ts +253 -28
- package/src/sandbox/routing.ts +204 -43
- package/src/sandbox/runtime-settings.ts +159 -85
- package/src/session-authorization.ts +172 -23
- package/src/session-usage-limit-metrics.ts +95 -0
- package/src/session-usage-limits.ts +415 -0
- package/src/site-agent-clamp.ts +226 -0
- package/src/site-session-origin.ts +84 -5
- package/src/transcription.ts +123 -4
- package/src/turn-surface.ts +47 -0
- package/src/user-presence.ts +134 -0
- package/src/workflow-wake-contract.ts +14 -1
- package/dist/application/host-mcp-owner.d.ts +0 -6
- package/dist/application/host-mcp-resolvers.d.ts +0 -13
- package/dist/chunk-5WZYFL45.js +0 -266
- package/dist/chunk-5WZYFL45.js.map +0 -1
- package/dist/chunk-H7X52RI2.js.map +0 -1
- package/dist/chunk-OF65T3PM.js.map +0 -1
- package/dist/chunk-VCZFFEPB.js.map +0 -1
- package/dist/chunk-ZYCNLYGH.js.map +0 -1
- package/dist/domain/connection-authority.d.ts +0 -97
- package/dist/domain/connection-authority.js +0 -169
- package/dist/domain/connection-authority.js.map +0 -1
- package/dist/domain/environments.d.ts +0 -33
- package/dist/domain/host-mcp-authority-source-admission.d.ts +0 -10
- package/dist/domain/host-mcp-task-admission.d.ts +0 -18
- package/dist/domain/packs.d.ts +0 -59
- package/dist/domain/product-integration-pack.d.ts +0 -44
- package/dist/domain/product-integration-skill.gen.d.ts +0 -5
- package/dist/remote-mcp-credentials.d.ts +0 -23
- package/dist/remote-mcp-credentials.js +0 -11
- package/dist/remote-mcp-credentials.js.map +0 -1
- package/src/application/host-mcp-owner.ts +0 -41
- package/src/application/host-mcp-resolvers.ts +0 -84
- package/src/domain/connection-authority.ts +0 -329
- package/src/domain/environments.ts +0 -120
- package/src/domain/host-mcp-authority-source-admission.ts +0 -25
- package/src/domain/host-mcp-task-admission.ts +0 -121
- package/src/domain/packs.ts +0 -699
- package/src/domain/product-integration-pack.ts +0 -42
- package/src/domain/product-integration-skill.gen.ts +0 -52
- package/src/remote-mcp-credentials.ts +0 -361
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CLAUDE_CONNECTION_KINDS,
|
|
3
|
+
claudeProviderId,
|
|
4
|
+
withClaudeConnectionCatalog,
|
|
5
|
+
withClaudeConnectionCredential,
|
|
6
|
+
withDirectModelProviders,
|
|
7
|
+
type Settings,
|
|
8
|
+
WORKSPACE_GATEWAY_MODEL_ID_PREFIX,
|
|
9
|
+
WORKSPACE_OPENROUTER_MODEL_ID_PREFIX,
|
|
10
|
+
withCodexCatalogProvider,
|
|
11
|
+
withWorkspaceGatewayCatalogProvider,
|
|
12
|
+
withWorkspaceGatewayCredential,
|
|
13
|
+
withWorkspaceOpenRouterCatalogProvider,
|
|
14
|
+
withWorkspaceOpenRouterCredential,
|
|
15
|
+
withOrganizationGatewayCatalogProvider,
|
|
16
|
+
withOrganizationGatewayCredential,
|
|
17
|
+
withOrganizationOpenRouterCatalogProvider,
|
|
18
|
+
withOrganizationOpenRouterCredential,
|
|
19
|
+
ORGANIZATION_GATEWAY_MODEL_ID_PREFIX,
|
|
20
|
+
ORGANIZATION_OPENROUTER_MODEL_ID_PREFIX,
|
|
21
|
+
ORGANIZATION_OPPER_MODEL_ID_PREFIX,
|
|
22
|
+
WORKSPACE_OPPER_MODEL_ID_PREFIX,
|
|
23
|
+
withOrganizationOpperCatalogProvider,
|
|
24
|
+
withOrganizationOpperCredential,
|
|
25
|
+
withWorkspaceOpperCatalogProvider,
|
|
26
|
+
withWorkspaceOpperCredential,
|
|
27
|
+
withXaiSubscriptionCatalogProvider,
|
|
28
|
+
} from "@opengeni/config";
|
|
29
|
+
import {
|
|
30
|
+
getWorkspaceGatewayCustomModelForExecution,
|
|
31
|
+
getWorkspaceOpenRouterCustomModelForExecution,
|
|
32
|
+
listWorkspaceGatewayCustomModels,
|
|
33
|
+
listWorkspaceOpenRouterCustomModels,
|
|
34
|
+
loadDirectModelProviderConnection,
|
|
35
|
+
workspaceCodexSubscriptionActive,
|
|
36
|
+
loadWorkspaceVercelAiGatewayApiKey,
|
|
37
|
+
loadWorkspaceOpenRouterApiKey,
|
|
38
|
+
loadWorkspaceOpperApiKey,
|
|
39
|
+
listOrganizationModelProviderCustomModelsForWorkspace,
|
|
40
|
+
getOrganizationModelProviderCustomModelForExecution,
|
|
41
|
+
loadOrganizationModelProviderApiKey,
|
|
42
|
+
listWorkspaceProviderCustomModels,
|
|
43
|
+
getWorkspaceProviderCustomModelForExecution,
|
|
44
|
+
loadWorkspaceProviderApiKey,
|
|
45
|
+
type Database,
|
|
46
|
+
} from "@opengeni/db";
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Execution-time provider overlays for one workspace: subscription catalog
|
|
50
|
+
* providers plus the decrypted workspace and organization provider keys a
|
|
51
|
+
* model call needs. Agent turns (worker claim) and stateless single model
|
|
52
|
+
* calls (API) apply the same overlays, so both resolve a model to the same
|
|
53
|
+
* provider and credential.
|
|
54
|
+
*/
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* When the workspace has an active Codex subscription connected and the feature
|
|
58
|
+
* is enabled, inject a synthetic "codex-subscription" registry provider so a
|
|
59
|
+
* `codex/<slug>` model id routes through the ChatGPT backend. No secrets touch
|
|
60
|
+
* this overlay (metadata-only read); the per-request bearer is resolved later via
|
|
61
|
+
* codexRequestStorage. Idempotent and a no-op when not applicable.
|
|
62
|
+
*/
|
|
63
|
+
export async function settingsWithCodexCredential(
|
|
64
|
+
db: Database,
|
|
65
|
+
workspaceId: string,
|
|
66
|
+
settings: Settings,
|
|
67
|
+
activeOverride?: boolean,
|
|
68
|
+
): Promise<Settings> {
|
|
69
|
+
// Same active-credential predicate the billing bypass uses, so provider
|
|
70
|
+
// injection and billing can never disagree on what an "active codex" turn is.
|
|
71
|
+
// The caller may pass `activeOverride` (a single, shared read; P2-b) so routing
|
|
72
|
+
// and billing decide from the exact same observation, immune to a concurrent
|
|
73
|
+
// disconnect/reconnect landing between two independent reads.
|
|
74
|
+
const active =
|
|
75
|
+
activeOverride ?? (await workspaceCodexSubscriptionActive(db, settings, workspaceId));
|
|
76
|
+
if (!active) {
|
|
77
|
+
return settings; // disabled / not connected / needs_relogin / error -> leave settings unchanged
|
|
78
|
+
}
|
|
79
|
+
const withProvider = withCodexProvider(settings);
|
|
80
|
+
return withProvider;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Pure: append the synthetic codex-subscription provider, idempotently. */
|
|
84
|
+
export function withCodexProvider(settings: Settings): Settings {
|
|
85
|
+
return withCodexCatalogProvider(settings);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Pure: append the synthetic SuperGrok/xAI subscription provider,
|
|
90
|
+
* idempotently. The overlay is catalogue metadata only; the exact account,
|
|
91
|
+
* authority snapshot, and bearer remain frozen later at turn admission.
|
|
92
|
+
*/
|
|
93
|
+
export function withXaiSubscriptionProvider(settings: Settings): Settings {
|
|
94
|
+
return withXaiSubscriptionCatalogProvider(settings);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export async function settingsWithWorkspaceGatewayCredential(
|
|
98
|
+
db: Database,
|
|
99
|
+
accountId: string,
|
|
100
|
+
workspaceId: string,
|
|
101
|
+
settings: Settings,
|
|
102
|
+
retainedProductModelId?: string | null,
|
|
103
|
+
): Promise<Settings> {
|
|
104
|
+
const activeCustomModels = await listWorkspaceGatewayCustomModels(db, {
|
|
105
|
+
accountId,
|
|
106
|
+
workspaceId,
|
|
107
|
+
});
|
|
108
|
+
const retainedUpstreamModelId = retainedProductModelId?.startsWith(
|
|
109
|
+
WORKSPACE_GATEWAY_MODEL_ID_PREFIX,
|
|
110
|
+
)
|
|
111
|
+
? retainedProductModelId.slice(WORKSPACE_GATEWAY_MODEL_ID_PREFIX.length)
|
|
112
|
+
: null;
|
|
113
|
+
const retainedCustomModel = retainedUpstreamModelId
|
|
114
|
+
? await getWorkspaceGatewayCustomModelForExecution(db, {
|
|
115
|
+
accountId,
|
|
116
|
+
workspaceId,
|
|
117
|
+
upstreamModelId: retainedUpstreamModelId,
|
|
118
|
+
})
|
|
119
|
+
: null;
|
|
120
|
+
const customModels =
|
|
121
|
+
retainedCustomModel &&
|
|
122
|
+
!activeCustomModels.some(
|
|
123
|
+
(model) => model.upstreamModelId === retainedCustomModel.upstreamModelId,
|
|
124
|
+
)
|
|
125
|
+
? [...activeCustomModels, retainedCustomModel]
|
|
126
|
+
: activeCustomModels;
|
|
127
|
+
const catalogSettings = withWorkspaceGatewayCatalogProvider(settings, customModels);
|
|
128
|
+
const apiKey = await loadWorkspaceVercelAiGatewayApiKey(
|
|
129
|
+
db,
|
|
130
|
+
settings,
|
|
131
|
+
workspaceId,
|
|
132
|
+
retainedProductModelId,
|
|
133
|
+
);
|
|
134
|
+
return apiKey
|
|
135
|
+
? withWorkspaceGatewayCredential(catalogSettings, apiKey, customModels)
|
|
136
|
+
: catalogSettings;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export async function settingsWithWorkspaceOpenRouterCredential(
|
|
140
|
+
db: Database,
|
|
141
|
+
accountId: string,
|
|
142
|
+
workspaceId: string,
|
|
143
|
+
settings: Settings,
|
|
144
|
+
retainedProductModelId?: string | null,
|
|
145
|
+
): Promise<Settings> {
|
|
146
|
+
const activeCustomModels = await listWorkspaceOpenRouterCustomModels(db, {
|
|
147
|
+
accountId,
|
|
148
|
+
workspaceId,
|
|
149
|
+
});
|
|
150
|
+
const retainedUpstreamModelId = retainedProductModelId?.startsWith(
|
|
151
|
+
WORKSPACE_OPENROUTER_MODEL_ID_PREFIX,
|
|
152
|
+
)
|
|
153
|
+
? retainedProductModelId.slice(WORKSPACE_OPENROUTER_MODEL_ID_PREFIX.length)
|
|
154
|
+
: null;
|
|
155
|
+
const retainedCustomModel = retainedUpstreamModelId
|
|
156
|
+
? await getWorkspaceOpenRouterCustomModelForExecution(db, {
|
|
157
|
+
accountId,
|
|
158
|
+
workspaceId,
|
|
159
|
+
upstreamModelId: retainedUpstreamModelId,
|
|
160
|
+
})
|
|
161
|
+
: null;
|
|
162
|
+
const customModels =
|
|
163
|
+
retainedCustomModel &&
|
|
164
|
+
!activeCustomModels.some(
|
|
165
|
+
(model) => model.upstreamModelId === retainedCustomModel.upstreamModelId,
|
|
166
|
+
)
|
|
167
|
+
? [...activeCustomModels, retainedCustomModel]
|
|
168
|
+
: activeCustomModels;
|
|
169
|
+
const catalogSettings = withWorkspaceOpenRouterCatalogProvider(settings, customModels);
|
|
170
|
+
const apiKey = await loadWorkspaceOpenRouterApiKey(
|
|
171
|
+
db,
|
|
172
|
+
settings,
|
|
173
|
+
workspaceId,
|
|
174
|
+
retainedProductModelId,
|
|
175
|
+
);
|
|
176
|
+
return apiKey
|
|
177
|
+
? withWorkspaceOpenRouterCredential(catalogSettings, apiKey, customModels)
|
|
178
|
+
: catalogSettings;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/** Overlay the workspace Opper catalog and, when active, its decrypted key. */
|
|
182
|
+
export async function settingsWithWorkspaceOpperCredential(
|
|
183
|
+
db: Database,
|
|
184
|
+
accountId: string,
|
|
185
|
+
workspaceId: string,
|
|
186
|
+
settings: Settings,
|
|
187
|
+
retainedProductModelId?: string | null,
|
|
188
|
+
): Promise<Settings> {
|
|
189
|
+
const activeCustomModels = await listWorkspaceProviderCustomModels(db, {
|
|
190
|
+
accountId,
|
|
191
|
+
workspaceId,
|
|
192
|
+
providerKind: "opper",
|
|
193
|
+
});
|
|
194
|
+
const retainedUpstreamModelId = retainedProductModelId?.startsWith(
|
|
195
|
+
WORKSPACE_OPPER_MODEL_ID_PREFIX,
|
|
196
|
+
)
|
|
197
|
+
? retainedProductModelId.slice(WORKSPACE_OPPER_MODEL_ID_PREFIX.length)
|
|
198
|
+
: null;
|
|
199
|
+
const retainedCustomModel = retainedUpstreamModelId
|
|
200
|
+
? await getWorkspaceProviderCustomModelForExecution(db, {
|
|
201
|
+
accountId,
|
|
202
|
+
workspaceId,
|
|
203
|
+
providerKind: "opper",
|
|
204
|
+
upstreamModelId: retainedUpstreamModelId,
|
|
205
|
+
})
|
|
206
|
+
: null;
|
|
207
|
+
const customModels =
|
|
208
|
+
retainedCustomModel &&
|
|
209
|
+
!activeCustomModels.some(
|
|
210
|
+
(model) => model.upstreamModelId === retainedCustomModel.upstreamModelId,
|
|
211
|
+
)
|
|
212
|
+
? [...activeCustomModels, retainedCustomModel]
|
|
213
|
+
: activeCustomModels;
|
|
214
|
+
const catalogSettings = withWorkspaceOpperCatalogProvider(settings, customModels);
|
|
215
|
+
const apiKey = await loadWorkspaceOpperApiKey(db, settings, workspaceId, retainedProductModelId);
|
|
216
|
+
return apiKey
|
|
217
|
+
? withWorkspaceOpperCredential(catalogSettings, apiKey, customModels)
|
|
218
|
+
: catalogSettings;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export async function settingsWithOrganizationProviderCredentials(
|
|
222
|
+
db: Database,
|
|
223
|
+
accountId: string,
|
|
224
|
+
workspaceId: string,
|
|
225
|
+
settings: Settings,
|
|
226
|
+
retainedProductModelId?: string | null,
|
|
227
|
+
): Promise<Settings> {
|
|
228
|
+
const buildModels = async (
|
|
229
|
+
providerKind: "vercel_gateway" | "openrouter" | "anthropic" | "claude_subscription" | "opper",
|
|
230
|
+
prefix: string,
|
|
231
|
+
) => {
|
|
232
|
+
const active = await listOrganizationModelProviderCustomModelsForWorkspace(db, {
|
|
233
|
+
accountId,
|
|
234
|
+
workspaceId,
|
|
235
|
+
providerKind,
|
|
236
|
+
});
|
|
237
|
+
const upstreamModelId = retainedProductModelId?.startsWith(prefix)
|
|
238
|
+
? retainedProductModelId.slice(prefix.length)
|
|
239
|
+
: null;
|
|
240
|
+
const retained = upstreamModelId
|
|
241
|
+
? await getOrganizationModelProviderCustomModelForExecution(db, {
|
|
242
|
+
accountId,
|
|
243
|
+
workspaceId,
|
|
244
|
+
providerKind,
|
|
245
|
+
upstreamModelId,
|
|
246
|
+
})
|
|
247
|
+
: null;
|
|
248
|
+
return retained && !active.some((model) => model.id === retained.id)
|
|
249
|
+
? [...active, retained]
|
|
250
|
+
: active;
|
|
251
|
+
};
|
|
252
|
+
const gatewayModels = await buildModels("vercel_gateway", ORGANIZATION_GATEWAY_MODEL_ID_PREFIX);
|
|
253
|
+
const openRouterModels = await buildModels("openrouter", ORGANIZATION_OPENROUTER_MODEL_ID_PREFIX);
|
|
254
|
+
const gatewayKey = await loadOrganizationModelProviderApiKey(db, settings, {
|
|
255
|
+
accountId,
|
|
256
|
+
workspaceId,
|
|
257
|
+
providerKind: "vercel_gateway",
|
|
258
|
+
});
|
|
259
|
+
const gatewaySettings = gatewayKey
|
|
260
|
+
? withOrganizationGatewayCredential(settings, gatewayKey, gatewayModels)
|
|
261
|
+
: withOrganizationGatewayCatalogProvider(settings, gatewayModels);
|
|
262
|
+
const openRouterKey = await loadOrganizationModelProviderApiKey(db, settings, {
|
|
263
|
+
accountId,
|
|
264
|
+
workspaceId,
|
|
265
|
+
providerKind: "openrouter",
|
|
266
|
+
});
|
|
267
|
+
const openRouterSettings = openRouterKey
|
|
268
|
+
? withOrganizationOpenRouterCredential(gatewaySettings, openRouterKey, openRouterModels)
|
|
269
|
+
: withOrganizationOpenRouterCatalogProvider(gatewaySettings, openRouterModels);
|
|
270
|
+
const opperModels = await buildModels("opper", ORGANIZATION_OPPER_MODEL_ID_PREFIX);
|
|
271
|
+
const opperKey = await loadOrganizationModelProviderApiKey(db, settings, {
|
|
272
|
+
accountId,
|
|
273
|
+
workspaceId,
|
|
274
|
+
providerKind: "opper",
|
|
275
|
+
});
|
|
276
|
+
let result = opperKey
|
|
277
|
+
? withOrganizationOpperCredential(openRouterSettings, opperKey, opperModels)
|
|
278
|
+
: withOrganizationOpperCatalogProvider(openRouterSettings, opperModels);
|
|
279
|
+
for (const kind of CLAUDE_CONNECTION_KINDS) {
|
|
280
|
+
if (kind === "claude_subscription" && !settings.claudeSubscriptionEnabled) continue;
|
|
281
|
+
const models = await buildModels(kind, claudeProviderId(kind) + "/");
|
|
282
|
+
result = withClaudeConnectionCatalog(result, { [kind]: { models } });
|
|
283
|
+
const credential =
|
|
284
|
+
kind === "claude_subscription"
|
|
285
|
+
? null
|
|
286
|
+
: await loadOrganizationModelProviderApiKey(db, settings, {
|
|
287
|
+
accountId,
|
|
288
|
+
workspaceId,
|
|
289
|
+
providerKind: kind,
|
|
290
|
+
});
|
|
291
|
+
if (credential)
|
|
292
|
+
result = withClaudeConnectionCredential(result, kind, credential, "organization", undefined);
|
|
293
|
+
const workspaceModels = await listWorkspaceProviderCustomModels(db, {
|
|
294
|
+
accountId,
|
|
295
|
+
workspaceId,
|
|
296
|
+
providerKind: kind,
|
|
297
|
+
});
|
|
298
|
+
const workspacePrefix = claudeProviderId(kind, "workspace") + "/";
|
|
299
|
+
const workspaceModelId = retainedProductModelId?.startsWith(workspacePrefix)
|
|
300
|
+
? retainedProductModelId
|
|
301
|
+
: null;
|
|
302
|
+
if (workspaceModelId) {
|
|
303
|
+
const retained = await getWorkspaceProviderCustomModelForExecution(db, {
|
|
304
|
+
accountId,
|
|
305
|
+
workspaceId,
|
|
306
|
+
providerKind: kind,
|
|
307
|
+
upstreamModelId: workspaceModelId.slice(workspacePrefix.length),
|
|
308
|
+
});
|
|
309
|
+
if (retained && !workspaceModels.some((model) => model.id === retained.id))
|
|
310
|
+
workspaceModels.push(retained);
|
|
311
|
+
}
|
|
312
|
+
result = withClaudeConnectionCatalog(
|
|
313
|
+
result,
|
|
314
|
+
{ [kind]: { models: workspaceModels } },
|
|
315
|
+
"workspace",
|
|
316
|
+
);
|
|
317
|
+
const workspaceCredential =
|
|
318
|
+
kind === "claude_subscription"
|
|
319
|
+
? null
|
|
320
|
+
: await loadWorkspaceProviderApiKey(db, settings, workspaceId, kind, workspaceModelId);
|
|
321
|
+
if (workspaceCredential)
|
|
322
|
+
result = withClaudeConnectionCredential(
|
|
323
|
+
result,
|
|
324
|
+
kind,
|
|
325
|
+
workspaceCredential,
|
|
326
|
+
"workspace",
|
|
327
|
+
undefined,
|
|
328
|
+
);
|
|
329
|
+
}
|
|
330
|
+
return result;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Apply every execution overlay in the order the worker claim uses, then
|
|
335
|
+
* install the selected customer direct connection when the model names one.
|
|
336
|
+
* `codexSubscriptionActive` is the caller's single readiness observation, so
|
|
337
|
+
* routing and billing decide from the same read.
|
|
338
|
+
*/
|
|
339
|
+
export async function settingsWithModelProviderCredentials(
|
|
340
|
+
db: Database,
|
|
341
|
+
input: {
|
|
342
|
+
accountId: string;
|
|
343
|
+
workspaceId: string;
|
|
344
|
+
settings: Settings;
|
|
345
|
+
productModelId: string | null | undefined;
|
|
346
|
+
codexSubscriptionActive: boolean;
|
|
347
|
+
},
|
|
348
|
+
): Promise<Settings> {
|
|
349
|
+
const { accountId, workspaceId, productModelId } = input;
|
|
350
|
+
const codexSettings = await settingsWithCodexCredential(
|
|
351
|
+
db,
|
|
352
|
+
workspaceId,
|
|
353
|
+
input.settings,
|
|
354
|
+
input.codexSubscriptionActive,
|
|
355
|
+
);
|
|
356
|
+
const xaiSettings = codexSettings.supergrokSubscriptionEnabled
|
|
357
|
+
? withXaiSubscriptionProvider(codexSettings)
|
|
358
|
+
: codexSettings;
|
|
359
|
+
const gatewaySettings = await settingsWithWorkspaceGatewayCredential(
|
|
360
|
+
db,
|
|
361
|
+
accountId,
|
|
362
|
+
workspaceId,
|
|
363
|
+
xaiSettings,
|
|
364
|
+
productModelId,
|
|
365
|
+
);
|
|
366
|
+
const openRouterSettings = await settingsWithWorkspaceOpenRouterCredential(
|
|
367
|
+
db,
|
|
368
|
+
accountId,
|
|
369
|
+
workspaceId,
|
|
370
|
+
gatewaySettings,
|
|
371
|
+
productModelId,
|
|
372
|
+
);
|
|
373
|
+
const workspaceProviderSettings = await settingsWithWorkspaceOpperCredential(
|
|
374
|
+
db,
|
|
375
|
+
accountId,
|
|
376
|
+
workspaceId,
|
|
377
|
+
openRouterSettings,
|
|
378
|
+
productModelId,
|
|
379
|
+
);
|
|
380
|
+
const capabilitySettings = await settingsWithOrganizationProviderCredentials(
|
|
381
|
+
db,
|
|
382
|
+
accountId,
|
|
383
|
+
workspaceId,
|
|
384
|
+
workspaceProviderSettings,
|
|
385
|
+
productModelId,
|
|
386
|
+
);
|
|
387
|
+
const direct = await loadDirectModelProviderConnection(
|
|
388
|
+
db,
|
|
389
|
+
capabilitySettings,
|
|
390
|
+
workspaceId,
|
|
391
|
+
productModelId ?? "",
|
|
392
|
+
);
|
|
393
|
+
return direct ? withDirectModelProviders(capabilitySettings, [direct]) : capabilitySettings;
|
|
394
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { SESSION_TURN_SURFACES, type SessionTurnSurface } from "@opengeni/contracts";
|
|
2
|
+
import type { Observability } from "@opengeni/observability";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Live, content-free product usage counters recorded where work is accepted.
|
|
6
|
+
* Every label is a closed set: the product surface (or `unknown` when no
|
|
7
|
+
* surface was captured), who created a session (`subject` or `service`), and
|
|
8
|
+
* whether the session is a root. No workspace, user, model or text value ever
|
|
9
|
+
* becomes a label.
|
|
10
|
+
*/
|
|
11
|
+
export type ProductUsageMetricsSink = Pick<Observability, "incrementCounter">;
|
|
12
|
+
|
|
13
|
+
export const PRODUCT_USAGE_SURFACE_LABELS = [...SESSION_TURN_SURFACES, "unknown"] as const;
|
|
14
|
+
export type ProductUsageSurfaceLabel = (typeof PRODUCT_USAGE_SURFACE_LABELS)[number];
|
|
15
|
+
export const SESSION_CREATED_BY_KINDS = ["subject", "service"] as const;
|
|
16
|
+
export type SessionCreatedByKind = (typeof SESSION_CREATED_BY_KINDS)[number];
|
|
17
|
+
|
|
18
|
+
const SESSIONS_CREATED_METRIC = {
|
|
19
|
+
name: "opengeni_sessions_created_total",
|
|
20
|
+
help: "Sessions created by product surface, creator kind, and whether they are root sessions.",
|
|
21
|
+
} as const;
|
|
22
|
+
const USER_MESSAGES_METRIC = {
|
|
23
|
+
name: "opengeni_user_messages_total",
|
|
24
|
+
help: "Accepted user messages and scheduled prompts by product surface.",
|
|
25
|
+
} as const;
|
|
26
|
+
|
|
27
|
+
export function productUsageSurfaceLabel(
|
|
28
|
+
surface: SessionTurnSurface | null | undefined,
|
|
29
|
+
): ProductUsageSurfaceLabel {
|
|
30
|
+
return surface && (SESSION_TURN_SURFACES as readonly string[]).includes(surface)
|
|
31
|
+
? surface
|
|
32
|
+
: "unknown";
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function sessionCreatedByKind(kind: string | null | undefined): SessionCreatedByKind {
|
|
36
|
+
return kind === "subject" ? "subject" : "service";
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Count one newly created session. Never throws; replays must not call it. */
|
|
40
|
+
export function recordSessionCreated(
|
|
41
|
+
sink: ProductUsageMetricsSink | null | undefined,
|
|
42
|
+
input: {
|
|
43
|
+
surface: SessionTurnSurface | null | undefined;
|
|
44
|
+
createdByKind: string | null | undefined;
|
|
45
|
+
parentSessionId: string | null | undefined;
|
|
46
|
+
},
|
|
47
|
+
): void {
|
|
48
|
+
try {
|
|
49
|
+
sink?.incrementCounter({
|
|
50
|
+
...SESSIONS_CREATED_METRIC,
|
|
51
|
+
labels: {
|
|
52
|
+
surface: productUsageSurfaceLabel(input.surface),
|
|
53
|
+
created_by_kind: sessionCreatedByKind(input.createdByKind),
|
|
54
|
+
root: input.parentSessionId ? "false" : "true",
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
} catch {
|
|
58
|
+
// Telemetry must never change the create outcome.
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Count one newly accepted user message. Never throws; replays must not call it. */
|
|
63
|
+
export function recordUserMessageAccepted(
|
|
64
|
+
sink: ProductUsageMetricsSink | null | undefined,
|
|
65
|
+
input: { surface: SessionTurnSurface | null | undefined },
|
|
66
|
+
): void {
|
|
67
|
+
try {
|
|
68
|
+
sink?.incrementCounter({
|
|
69
|
+
...USER_MESSAGES_METRIC,
|
|
70
|
+
labels: { surface: productUsageSurfaceLabel(input.surface) },
|
|
71
|
+
});
|
|
72
|
+
} catch {
|
|
73
|
+
// Telemetry must never change the send outcome.
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Publish every closed series at zero so dashboards can tell a quiet surface
|
|
79
|
+
* from missing instrumentation. Never throws.
|
|
80
|
+
*/
|
|
81
|
+
export function registerProductUsageMetricBaselines(
|
|
82
|
+
sink: ProductUsageMetricsSink | null | undefined,
|
|
83
|
+
): void {
|
|
84
|
+
if (!sink) return;
|
|
85
|
+
try {
|
|
86
|
+
for (const surface of PRODUCT_USAGE_SURFACE_LABELS) {
|
|
87
|
+
sink.incrementCounter({ ...USER_MESSAGES_METRIC, labels: { surface }, amount: 0 });
|
|
88
|
+
for (const createdByKind of SESSION_CREATED_BY_KINDS) {
|
|
89
|
+
for (const root of ["true", "false"]) {
|
|
90
|
+
sink.incrementCounter({
|
|
91
|
+
...SESSIONS_CREATED_METRIC,
|
|
92
|
+
labels: { surface, created_by_kind: createdByKind, root },
|
|
93
|
+
amount: 0,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
} catch {
|
|
99
|
+
// Telemetry only; series appear on their first real increment.
|
|
100
|
+
}
|
|
101
|
+
}
|