@shipfox/api-agent 5.0.0 → 7.1.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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +43 -0
- package/dist/core/custom-model-provider-config-service.d.ts +4 -0
- package/dist/core/custom-model-provider-config-service.d.ts.map +1 -1
- package/dist/core/custom-model-provider-config-service.js +36 -17
- package/dist/core/custom-model-provider-config-service.js.map +1 -1
- package/dist/core/model-provider-config-service.d.ts +4 -0
- package/dist/core/model-provider-config-service.d.ts.map +1 -1
- package/dist/core/model-provider-config-service.js +27 -9
- package/dist/core/model-provider-config-service.js.map +1 -1
- package/dist/core/resolve-runtime-credentials.d.ts +6 -2
- package/dist/core/resolve-runtime-credentials.d.ts.map +1 -1
- package/dist/core/resolve-runtime-credentials.js +10 -5
- package/dist/core/resolve-runtime-credentials.js.map +1 -1
- package/dist/core/secrets-client.d.ts +4 -0
- package/dist/core/secrets-client.d.ts.map +1 -0
- package/dist/core/secrets-client.js +6 -0
- package/dist/core/secrets-client.js.map +1 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -13
- package/dist/index.js.map +1 -1
- package/dist/presentation/e2eRoutes/create-model-provider.d.ts +2 -1
- package/dist/presentation/e2eRoutes/create-model-provider.d.ts.map +1 -1
- package/dist/presentation/e2eRoutes/create-model-provider.js +46 -45
- package/dist/presentation/e2eRoutes/create-model-provider.js.map +1 -1
- package/dist/presentation/e2eRoutes/index.d.ts +2 -0
- package/dist/presentation/e2eRoutes/index.d.ts.map +1 -1
- package/dist/presentation/e2eRoutes/index.js +9 -6
- package/dist/presentation/e2eRoutes/index.js.map +1 -1
- package/dist/presentation/index.d.ts +1 -1
- package/dist/presentation/index.d.ts.map +1 -1
- package/dist/presentation/index.js +1 -1
- package/dist/presentation/index.js.map +1 -1
- package/dist/presentation/inter-module.d.ts +7 -0
- package/dist/presentation/inter-module.d.ts.map +1 -0
- package/dist/presentation/inter-module.js +45 -0
- package/dist/presentation/inter-module.js.map +1 -0
- package/dist/presentation/routes/create-custom-model-provider.d.ts +2 -1
- package/dist/presentation/routes/create-custom-model-provider.d.ts.map +1 -1
- package/dist/presentation/routes/create-custom-model-provider.js +39 -35
- package/dist/presentation/routes/create-custom-model-provider.js.map +1 -1
- package/dist/presentation/routes/delete-model-provider-config.d.ts +2 -1
- package/dist/presentation/routes/delete-model-provider-config.d.ts.map +1 -1
- package/dist/presentation/routes/delete-model-provider-config.js +33 -29
- package/dist/presentation/routes/delete-model-provider-config.js.map +1 -1
- package/dist/presentation/routes/discover-custom-model-provider-models-by-slug.d.ts +2 -1
- package/dist/presentation/routes/discover-custom-model-provider-models-by-slug.d.ts.map +1 -1
- package/dist/presentation/routes/discover-custom-model-provider-models-by-slug.js +32 -28
- package/dist/presentation/routes/discover-custom-model-provider-models-by-slug.js.map +1 -1
- package/dist/presentation/routes/errors.d.ts.map +1 -1
- package/dist/presentation/routes/errors.js +13 -12
- package/dist/presentation/routes/errors.js.map +1 -1
- package/dist/presentation/routes/index.d.ts +2 -0
- package/dist/presentation/routes/index.d.ts.map +1 -1
- package/dist/presentation/routes/index.js +32 -29
- package/dist/presentation/routes/index.js.map +1 -1
- package/dist/presentation/routes/update-custom-model-provider.d.ts +2 -1
- package/dist/presentation/routes/update-custom-model-provider.d.ts.map +1 -1
- package/dist/presentation/routes/update-custom-model-provider.js +41 -37
- package/dist/presentation/routes/update-custom-model-provider.js.map +1 -1
- package/dist/presentation/routes/upsert-model-provider-config.d.ts +2 -1
- package/dist/presentation/routes/upsert-model-provider-config.d.ts.map +1 -1
- package/dist/presentation/routes/upsert-model-provider-config.js +46 -42
- package/dist/presentation/routes/upsert-model-provider-config.js.map +1 -1
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +12 -18
- package/src/core/custom-model-provider-config-service.ts +63 -35
- package/src/core/model-provider-config-service.test.ts +1 -3
- package/src/core/model-provider-config-service.ts +31 -16
- package/src/core/resolve-runtime-credentials.test.ts +3 -3
- package/src/core/resolve-runtime-credentials.ts +22 -8
- package/src/core/secrets-client.ts +13 -0
- package/src/index.ts +13 -8
- package/src/presentation/e2eRoutes/create-model-provider.ts +41 -39
- package/src/presentation/e2eRoutes/index.ts +6 -4
- package/src/presentation/index.ts +1 -1
- package/src/presentation/inter-module.ts +78 -0
- package/src/presentation/routes/create-custom-model-provider.ts +36 -30
- package/src/presentation/routes/delete-model-provider-config.ts +25 -22
- package/src/presentation/routes/discover-custom-model-provider-models-by-slug.ts +31 -25
- package/src/presentation/routes/errors.ts +11 -11
- package/src/presentation/routes/index.ts +32 -27
- package/src/presentation/routes/model-provider-config.test.ts +1 -1
- package/src/presentation/routes/update-custom-model-provider.ts +40 -34
- package/src/presentation/routes/upsert-model-provider-config.ts +43 -37
- package/test/fixtures/secrets-client.ts +80 -0
- package/test/globalSetup.ts +0 -9
- package/test/setup.ts +8 -0
- package/tsconfig.build.tsbuildinfo +1 -1
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
$ shipfox-swc
|
|
2
|
-
Successfully compiled:
|
|
2
|
+
Successfully compiled: 50 files with swc (541.72ms)
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,48 @@
|
|
|
1
1
|
# @shipfox/api-agent
|
|
2
2
|
|
|
3
|
+
## 7.1.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- ac42c96: Adds boundary-owned reporting for unexpected API runtime failures while preserving expected client and provider outcomes.
|
|
8
|
+
- Updated dependencies [ac42c96]
|
|
9
|
+
- Updated dependencies [6ce08c0]
|
|
10
|
+
- @shipfox/node-error-monitoring@0.2.0
|
|
11
|
+
- @shipfox/node-fastify@0.3.0
|
|
12
|
+
- @shipfox/node-module@0.5.0
|
|
13
|
+
- @shipfox/node-opentelemetry@0.6.0
|
|
14
|
+
- @shipfox/api-auth-context@7.1.0
|
|
15
|
+
|
|
16
|
+
## 6.0.0
|
|
17
|
+
|
|
18
|
+
### Minor Changes
|
|
19
|
+
|
|
20
|
+
- a42b575: Exposes Secrets through its inter-module contract and migrates Agent, integrations, and Workflows consumers.
|
|
21
|
+
|
|
22
|
+
### Patch Changes
|
|
23
|
+
|
|
24
|
+
- 0bb82a4: Adds the Agent and Integrations inter-module APIs, moving Workflows agent configuration, runtime credential resolution, and integration consumers behind producer-owned clients.
|
|
25
|
+
- f73da5d: Enforces bounded API context imports and routes inter-module consumers through producer contracts.
|
|
26
|
+
- Updated dependencies [0bb82a4]
|
|
27
|
+
- Updated dependencies [54ce48b]
|
|
28
|
+
- Updated dependencies [c0162b0]
|
|
29
|
+
- Updated dependencies [7ac43a4]
|
|
30
|
+
- Updated dependencies [a01e917]
|
|
31
|
+
- Updated dependencies [a42b575]
|
|
32
|
+
- Updated dependencies [8bdc149]
|
|
33
|
+
- Updated dependencies [3810996]
|
|
34
|
+
- Updated dependencies [b00ed29]
|
|
35
|
+
- Updated dependencies [8aa7cd3]
|
|
36
|
+
- Updated dependencies [81f9544]
|
|
37
|
+
- @shipfox/api-agent-dto@6.0.0
|
|
38
|
+
- @shipfox/node-module@0.4.0
|
|
39
|
+
- @shipfox/node-drizzle@0.3.2
|
|
40
|
+
- @shipfox/redact@0.2.3
|
|
41
|
+
- @shipfox/api-secrets-dto@6.0.0
|
|
42
|
+
- @shipfox/api-auth-context@6.0.0
|
|
43
|
+
- @shipfox/node-fastify@0.2.4
|
|
44
|
+
- @shipfox/inter-module@0.2.0
|
|
45
|
+
|
|
3
46
|
## 5.0.0
|
|
4
47
|
|
|
5
48
|
### Patch Changes
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type CreateCustomModelProviderBodyDto, type DiscoverCustomModelProviderModelsBodyDto, type DiscoverCustomModelProviderModelsBySlugBodyDto, type ModelProviderRef, type UpdateCustomModelProviderBodyDto } from '@shipfox/api-agent-dto';
|
|
2
2
|
import type { ModelProviderConfig } from './entities/model-provider-config.js';
|
|
3
3
|
import { probeCustomModelProviderCredentials } from './model-provider-validation.js';
|
|
4
|
+
import { type AgentSecretsClient } from './secrets-client.js';
|
|
4
5
|
export interface CreateCustomModelProviderConfigParams {
|
|
5
6
|
workspaceId: string;
|
|
6
7
|
body: CreateCustomModelProviderBodyDto;
|
|
@@ -15,6 +16,7 @@ export interface UpdateCustomModelProviderConfigParams {
|
|
|
15
16
|
}
|
|
16
17
|
export interface CustomModelProviderConfigServiceOptions {
|
|
17
18
|
probe?: typeof probeCustomModelProviderCredentials | undefined;
|
|
19
|
+
secrets?: AgentSecretsClient | undefined;
|
|
18
20
|
}
|
|
19
21
|
export declare function createCustomModelProviderConfig(params: CreateCustomModelProviderConfigParams, options?: CustomModelProviderConfigServiceOptions): Promise<ModelProviderConfig>;
|
|
20
22
|
export declare function updateCustomModelProviderConfig(params: UpdateCustomModelProviderConfigParams, options?: CustomModelProviderConfigServiceOptions): Promise<ModelProviderConfig>;
|
|
@@ -22,5 +24,7 @@ export declare function resolveCustomModelProviderDiscoveryParams(params: {
|
|
|
22
24
|
workspaceId: string;
|
|
23
25
|
providerId: ModelProviderRef;
|
|
24
26
|
body: DiscoverCustomModelProviderModelsBySlugBodyDto;
|
|
27
|
+
}, options?: {
|
|
28
|
+
secrets?: AgentSecretsClient | undefined;
|
|
25
29
|
}): Promise<DiscoverCustomModelProviderModelsBodyDto>;
|
|
26
30
|
//# sourceMappingURL=custom-model-provider-config-service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"custom-model-provider-config-service.d.ts","sourceRoot":"","sources":["../../src/core/custom-model-provider-config-service.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,gCAAgC,EAKrC,KAAK,wCAAwC,EAC7C,KAAK,8CAA8C,EACnD,KAAK,gBAAgB,EACrB,KAAK,gCAAgC,EAEtC,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"custom-model-provider-config-service.d.ts","sourceRoot":"","sources":["../../src/core/custom-model-provider-config-service.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,gCAAgC,EAKrC,KAAK,wCAAwC,EAC7C,KAAK,8CAA8C,EACnD,KAAK,gBAAgB,EACrB,KAAK,gCAAgC,EAEtC,MAAM,wBAAwB,CAAC;AAiBhC,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,qCAAqC,CAAC;AAQ7E,OAAO,EAEL,mCAAmC,EAEpC,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAC,KAAK,kBAAkB,EAA4B,MAAM,qBAAqB,CAAC;AAEvF,MAAM,WAAW,qCAAqC;IACpD,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,gCAAgC,CAAC;IACvC,YAAY,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACnC,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;CAClC;AAED,MAAM,WAAW,qCAAqC;IACpD,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,gBAAgB,CAAC;IAC7B,IAAI,EAAE,gCAAgC,CAAC;IACvC,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;CAClC;AAED,MAAM,WAAW,uCAAuC;IACtD,KAAK,CAAC,EAAE,OAAO,mCAAmC,GAAG,SAAS,CAAC;IAC/D,OAAO,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;CAC1C;AASD,wBAAsB,+BAA+B,CACnD,MAAM,EAAE,qCAAqC,EAC7C,OAAO,GAAE,uCAA4C,GACpD,OAAO,CAAC,mBAAmB,CAAC,CA0E9B;AAED,wBAAsB,+BAA+B,CACnD,MAAM,EAAE,qCAAqC,EAC7C,OAAO,GAAE,uCAA4C,GACpD,OAAO,CAAC,mBAAmB,CAAC,CA+G9B;AAED,wBAAsB,yCAAyC,CAC7D,MAAM,EAAE;IACN,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,gBAAgB,CAAC;IAC7B,IAAI,EAAE,8CAA8C,CAAC;CACtD,EACD,OAAO,GAAE;IAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAA;CAAM,GACvD,OAAO,CAAC,wCAAwC,CAAC,CA4BnD"}
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import { DEFAULT_AGENT_THINKING } from '@shipfox/api-agent-dto';
|
|
2
|
-
import { deleteSecrets, getSecretsByNamespace, setSecrets } from '@shipfox/api-secrets';
|
|
3
2
|
import { assertEgressAllowed } from '@shipfox/node-egress-guard';
|
|
3
|
+
import { reportError } from '@shipfox/node-error-monitoring';
|
|
4
|
+
import { logger } from '@shipfox/node-opentelemetry';
|
|
4
5
|
import { deleteModelProviderConfig, getModelProviderConfig, insertCustomModelProviderConfig, upsertModelProviderConfig } from '#db/index.js';
|
|
5
6
|
import { agentSystemNamespace, customCredentialsToStoreValues, customCredentialToStoreKey, storeValuesToCustomRuntimeCredentials } from './credential-fingerprints.js';
|
|
6
7
|
import { normalizeCustomProviderBaseUrl } from './custom-provider-url.js';
|
|
7
8
|
import { CustomModelProviderConfigNotFoundError, CustomModelProviderSlugCollisionError, CustomModelProviderStoredSecretBaseUrlChangeError, InvalidAgentModelError, InvalidCustomModelProviderHeaderKeepError } from './errors.js';
|
|
8
9
|
import { egressPolicy, probeCustomModelProviderCredentials, runProviderProbe } from './model-provider-validation.js';
|
|
10
|
+
import { requireAgentSecretsClient } from './secrets-client.js';
|
|
9
11
|
export async function createCustomModelProviderConfig(params, options = {}) {
|
|
10
12
|
const probe = options.probe ?? probeCustomModelProviderCredentials;
|
|
13
|
+
const secrets = requireAgentSecretsClient(options.secrets);
|
|
11
14
|
const existing = await getModelProviderConfig({
|
|
12
15
|
workspaceId: params.workspaceId,
|
|
13
16
|
providerId: params.body.slug
|
|
@@ -61,7 +64,7 @@ export async function createCustomModelProviderConfig(params, options = {}) {
|
|
|
61
64
|
throw new CustomModelProviderSlugCollisionError(params.workspaceId, params.body.slug);
|
|
62
65
|
}
|
|
63
66
|
try {
|
|
64
|
-
await setSecrets({
|
|
67
|
+
await secrets.setSecrets({
|
|
65
68
|
workspaceId: params.workspaceId,
|
|
66
69
|
namespace: agentSystemNamespace(params.body.slug),
|
|
67
70
|
values: customCredentialsToStoreValues(secretCredentials)
|
|
@@ -72,7 +75,7 @@ export async function createCustomModelProviderConfig(params, options = {}) {
|
|
|
72
75
|
workspaceId: params.workspaceId,
|
|
73
76
|
providerId: params.body.slug
|
|
74
77
|
});
|
|
75
|
-
await deleteSecrets({
|
|
78
|
+
await secrets.deleteSecrets({
|
|
76
79
|
workspaceId: params.workspaceId,
|
|
77
80
|
namespace: agentSystemNamespace(params.body.slug)
|
|
78
81
|
});
|
|
@@ -81,8 +84,9 @@ export async function createCustomModelProviderConfig(params, options = {}) {
|
|
|
81
84
|
}
|
|
82
85
|
export async function updateCustomModelProviderConfig(params, options = {}) {
|
|
83
86
|
const probe = options.probe ?? probeCustomModelProviderCredentials;
|
|
87
|
+
const secrets = requireAgentSecretsClient(options.secrets);
|
|
84
88
|
const existing = await getExistingCustomConfig(params.workspaceId, params.providerId);
|
|
85
|
-
const existingSecrets = await getCustomProviderSecrets({
|
|
89
|
+
const existingSecrets = await getCustomProviderSecrets(secrets, {
|
|
86
90
|
workspaceId: params.workspaceId,
|
|
87
91
|
providerId: params.providerId
|
|
88
92
|
});
|
|
@@ -136,7 +140,7 @@ export async function updateCustomModelProviderConfig(params, options = {}) {
|
|
|
136
140
|
signal: params.signal
|
|
137
141
|
});
|
|
138
142
|
const namespace = agentSystemNamespace(params.providerId);
|
|
139
|
-
await setSecrets({
|
|
143
|
+
await secrets.setSecrets({
|
|
140
144
|
workspaceId: params.workspaceId,
|
|
141
145
|
namespace,
|
|
142
146
|
values: customCredentialsToStoreValues(newSecretCredentials)
|
|
@@ -158,15 +162,29 @@ export async function updateCustomModelProviderConfig(params, options = {}) {
|
|
|
158
162
|
defaultThinking: existing.defaultThinking
|
|
159
163
|
});
|
|
160
164
|
} catch (error) {
|
|
161
|
-
await rollbackCustomProviderSecretUpdate({
|
|
165
|
+
await rollbackCustomProviderSecretUpdate(secrets, {
|
|
162
166
|
workspaceId: params.workspaceId,
|
|
163
167
|
namespace,
|
|
164
168
|
existingSecrets,
|
|
165
169
|
attemptedSecrets: newSecretCredentials
|
|
166
|
-
}).catch(()=>
|
|
170
|
+
}).catch((rollbackError)=>{
|
|
171
|
+
logger().error({
|
|
172
|
+
err: rollbackError,
|
|
173
|
+
workspaceId: params.workspaceId,
|
|
174
|
+
providerId: params.providerId
|
|
175
|
+
}, 'Failed to roll back custom model provider secrets');
|
|
176
|
+
reportError(rollbackError, {
|
|
177
|
+
boundary: 'agent.cleanup',
|
|
178
|
+
operation: 'rollback-secret-update',
|
|
179
|
+
extra: {
|
|
180
|
+
workspaceId: params.workspaceId,
|
|
181
|
+
providerId: params.providerId
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
});
|
|
167
185
|
throw error;
|
|
168
186
|
}
|
|
169
|
-
await pruneStaleCustomHeaderSecrets({
|
|
187
|
+
await pruneStaleCustomHeaderSecrets(secrets, {
|
|
170
188
|
workspaceId: params.workspaceId,
|
|
171
189
|
providerId: params.providerId,
|
|
172
190
|
existingSecrets,
|
|
@@ -175,9 +193,10 @@ export async function updateCustomModelProviderConfig(params, options = {}) {
|
|
|
175
193
|
});
|
|
176
194
|
return updated;
|
|
177
195
|
}
|
|
178
|
-
export async function resolveCustomModelProviderDiscoveryParams(params) {
|
|
196
|
+
export async function resolveCustomModelProviderDiscoveryParams(params, options = {}) {
|
|
197
|
+
const secrets = requireAgentSecretsClient(options.secrets);
|
|
179
198
|
const existing = await getExistingCustomConfig(params.workspaceId, params.providerId);
|
|
180
|
-
const existingSecrets = await getCustomProviderSecrets({
|
|
199
|
+
const existingSecrets = await getCustomProviderSecrets(secrets, {
|
|
181
200
|
workspaceId: params.workspaceId,
|
|
182
201
|
providerId: params.providerId
|
|
183
202
|
});
|
|
@@ -325,8 +344,8 @@ function selectProbeModel(models, defaultModel) {
|
|
|
325
344
|
if (!model) throw new Error('Custom model provider must include at least one model.');
|
|
326
345
|
return model;
|
|
327
346
|
}
|
|
328
|
-
async function getCustomProviderSecrets(params) {
|
|
329
|
-
const values = await getSecretsByNamespace({
|
|
347
|
+
async function getCustomProviderSecrets(secrets, params) {
|
|
348
|
+
const { values } = await secrets.getSecretsByNamespace({
|
|
330
349
|
workspaceId: params.workspaceId,
|
|
331
350
|
namespace: agentSystemNamespace(params.providerId)
|
|
332
351
|
});
|
|
@@ -345,7 +364,7 @@ function assertStoredSecretsNotReusedAfterBaseUrlChange(params) {
|
|
|
345
364
|
function normalizedUrl(value) {
|
|
346
365
|
return normalizeCustomProviderBaseUrl(value);
|
|
347
366
|
}
|
|
348
|
-
async function rollbackCustomProviderSecretUpdate(params) {
|
|
367
|
+
async function rollbackCustomProviderSecretUpdate(secrets, params) {
|
|
349
368
|
const attemptedKeys = Object.keys(params.attemptedSecrets);
|
|
350
369
|
if (attemptedKeys.length === 0) return;
|
|
351
370
|
const secretsToRestore = Object.fromEntries(attemptedKeys.flatMap((key)=>{
|
|
@@ -358,7 +377,7 @@ async function rollbackCustomProviderSecretUpdate(params) {
|
|
|
358
377
|
];
|
|
359
378
|
}));
|
|
360
379
|
if (Object.keys(secretsToRestore).length > 0) {
|
|
361
|
-
await setSecrets({
|
|
380
|
+
await secrets.setSecrets({
|
|
362
381
|
workspaceId: params.workspaceId,
|
|
363
382
|
namespace: params.namespace,
|
|
364
383
|
values: customCredentialsToStoreValues(secretsToRestore)
|
|
@@ -366,18 +385,18 @@ async function rollbackCustomProviderSecretUpdate(params) {
|
|
|
366
385
|
}
|
|
367
386
|
const newKeys = attemptedKeys.filter((key)=>params.existingSecrets[key] === undefined);
|
|
368
387
|
if (newKeys.length === 0) return;
|
|
369
|
-
await deleteSecrets({
|
|
388
|
+
await secrets.deleteSecrets({
|
|
370
389
|
workspaceId: params.workspaceId,
|
|
371
390
|
namespace: params.namespace,
|
|
372
391
|
keys: newKeys.map(customCredentialToStoreKey)
|
|
373
392
|
});
|
|
374
393
|
}
|
|
375
|
-
async function pruneStaleCustomHeaderSecrets(params) {
|
|
394
|
+
async function pruneStaleCustomHeaderSecrets(secrets, params) {
|
|
376
395
|
if (!params.replaceHeaders) return;
|
|
377
396
|
const nextKeys = new Set(Object.keys(params.newSecrets));
|
|
378
397
|
const staleKeys = Object.keys(params.existingSecrets).filter((key)=>key.startsWith('header:') && !nextKeys.has(key));
|
|
379
398
|
if (staleKeys.length === 0) return;
|
|
380
|
-
await deleteSecrets({
|
|
399
|
+
await secrets.deleteSecrets({
|
|
381
400
|
workspaceId: params.workspaceId,
|
|
382
401
|
namespace: agentSystemNamespace(params.providerId),
|
|
383
402
|
keys: staleKeys.map(customCredentialToStoreKey)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/custom-model-provider-config-service.ts"],"sourcesContent":["import {\n type CreateCustomModelProviderBodyDto,\n type CustomAgentModelDto,\n type CustomModelProviderHeaderDto,\n type CustomModelProviderHeaderRequestDto,\n DEFAULT_AGENT_THINKING,\n type DiscoverCustomModelProviderModelsBodyDto,\n type DiscoverCustomModelProviderModelsBySlugBodyDto,\n type ModelProviderRef,\n type UpdateCustomModelProviderBodyDto,\n type UpdateCustomModelProviderHeaderRequestDto,\n} from '@shipfox/api-agent-dto';\nimport {deleteSecrets, getSecretsByNamespace, setSecrets} from '@shipfox/api-secrets';\nimport {assertEgressAllowed} from '@shipfox/node-egress-guard';\nimport {\n deleteModelProviderConfig,\n getModelProviderConfig,\n insertCustomModelProviderConfig,\n upsertModelProviderConfig,\n} from '#db/index.js';\nimport {\n agentSystemNamespace,\n customCredentialsToStoreValues,\n customCredentialToStoreKey,\n storeValuesToCustomRuntimeCredentials,\n} from './credential-fingerprints.js';\nimport {normalizeCustomProviderBaseUrl} from './custom-provider-url.js';\nimport type {ModelProviderConfig} from './entities/model-provider-config.js';\nimport {\n CustomModelProviderConfigNotFoundError,\n CustomModelProviderSlugCollisionError,\n CustomModelProviderStoredSecretBaseUrlChangeError,\n InvalidAgentModelError,\n InvalidCustomModelProviderHeaderKeepError,\n} from './errors.js';\nimport {\n egressPolicy,\n probeCustomModelProviderCredentials,\n runProviderProbe,\n} from './model-provider-validation.js';\n\nexport interface CreateCustomModelProviderConfigParams {\n workspaceId: string;\n body: CreateCustomModelProviderBodyDto;\n setAsDefault?: boolean | undefined;\n signal?: AbortSignal | undefined;\n}\n\nexport interface UpdateCustomModelProviderConfigParams {\n workspaceId: string;\n providerId: ModelProviderRef;\n body: UpdateCustomModelProviderBodyDto;\n signal?: AbortSignal | undefined;\n}\n\nexport interface CustomModelProviderConfigServiceOptions {\n probe?: typeof probeCustomModelProviderCredentials | undefined;\n}\n\ninterface SplitHeaders {\n plaintextHeaders: CustomModelProviderHeaderDto[];\n secretHeaderNames: string[];\n secretCredentials: Record<string, string>;\n runtimeHeaders: Record<string, string>;\n}\n\nexport async function createCustomModelProviderConfig(\n params: CreateCustomModelProviderConfigParams,\n options: CustomModelProviderConfigServiceOptions = {},\n): Promise<ModelProviderConfig> {\n const probe = options.probe ?? probeCustomModelProviderCredentials;\n\n const existing = await getModelProviderConfig({\n workspaceId: params.workspaceId,\n providerId: params.body.slug,\n });\n if (existing !== undefined) {\n throw new CustomModelProviderSlugCollisionError(params.workspaceId, params.body.slug);\n }\n\n const splitHeaders = splitCustomHeaders(params.body.headers ?? []);\n const secretCredentials = {\n ...(params.body.api_key ? {api_key: params.body.api_key} : {}),\n ...splitHeaders.secretCredentials,\n };\n const probeModel = selectProbeModel(params.body.models, params.body.default_model ?? null);\n\n await assertEgressAllowed(params.body.base_url, egressPolicy());\n await runProviderProbe({\n probe,\n args: {\n providerId: params.body.slug,\n api: params.body.api,\n baseUrl: params.body.base_url,\n model: probeModel,\n apiKey: params.body.api_key,\n headers: splitHeaders.runtimeHeaders,\n ...(params.signal ? {signal: params.signal} : {}),\n },\n metricLabel: 'custom',\n providerId: params.body.slug,\n secrets: Object.values(secretCredentials),\n signal: params.signal,\n });\n\n const config = await insertCustomModelProviderConfig({\n workspaceId: params.workspaceId,\n providerId: params.body.slug,\n kind: 'custom',\n displayName: params.body.display_name,\n api: params.body.api,\n baseUrl: params.body.base_url,\n headers: splitHeaders.plaintextHeaders,\n secretHeaderNames: splitHeaders.secretHeaderNames,\n models: params.body.models,\n requiresApiKey: params.body.api_key !== undefined,\n defaultModel: params.body.default_model ?? null,\n defaultThinking: DEFAULT_AGENT_THINKING,\n setAsDefault: params.setAsDefault,\n });\n if (!config) {\n throw new CustomModelProviderSlugCollisionError(params.workspaceId, params.body.slug);\n }\n\n try {\n await setSecrets({\n workspaceId: params.workspaceId,\n namespace: agentSystemNamespace(params.body.slug),\n values: customCredentialsToStoreValues(secretCredentials),\n });\n return config;\n } catch (error) {\n await deleteModelProviderConfig({\n workspaceId: params.workspaceId,\n providerId: params.body.slug,\n });\n await deleteSecrets({\n workspaceId: params.workspaceId,\n namespace: agentSystemNamespace(params.body.slug),\n });\n throw error;\n }\n}\n\nexport async function updateCustomModelProviderConfig(\n params: UpdateCustomModelProviderConfigParams,\n options: CustomModelProviderConfigServiceOptions = {},\n): Promise<ModelProviderConfig> {\n const probe = options.probe ?? probeCustomModelProviderCredentials;\n\n const existing = await getExistingCustomConfig(params.workspaceId, params.providerId);\n const existingSecrets = await getCustomProviderSecrets({\n workspaceId: params.workspaceId,\n providerId: params.providerId,\n });\n const nextModels = params.body.models ?? existing.models ?? [];\n const nextDefaultModel = resolveNextDefaultModel(\n params.providerId,\n existing.defaultModel,\n nextModels,\n params.body,\n );\n const nextApi = params.body.api ?? existing.api ?? 'openai-responses';\n const nextBaseUrl = params.body.base_url ?? existing.baseUrl ?? '';\n const nextDisplayName = params.body.display_name ?? existing.displayName ?? params.providerId;\n assertStoredSecretsNotReusedAfterBaseUrlChange({\n body: params.body,\n existing,\n existingSecrets,\n providerId: params.providerId,\n });\n const nextHeaders = resolveNextHeaders({\n requestHeaders: params.body.headers,\n existing,\n existingSecrets,\n providerId: params.providerId,\n });\n const nextApiKey = params.body.api_key ?? existingSecrets.api_key;\n const newSecretCredentials = {\n ...(params.body.api_key ? {api_key: params.body.api_key} : {}),\n ...nextHeaders.newSecretCredentials,\n };\n const probeSecretCredentials = {\n ...(nextApiKey ? {api_key: nextApiKey} : {}),\n ...nextHeaders.probeSecretCredentials,\n };\n\n await assertEgressAllowed(nextBaseUrl, egressPolicy());\n await runProviderProbe({\n probe,\n args: {\n providerId: params.providerId,\n api: nextApi,\n baseUrl: nextBaseUrl,\n model: selectProbeModel(nextModels, nextDefaultModel),\n apiKey: nextApiKey,\n headers: nextHeaders.runtimeHeaders,\n ...(params.signal ? {signal: params.signal} : {}),\n },\n metricLabel: 'custom',\n providerId: params.providerId,\n secrets: Object.values(probeSecretCredentials),\n signal: params.signal,\n });\n\n const namespace = agentSystemNamespace(params.providerId);\n await setSecrets({\n workspaceId: params.workspaceId,\n namespace,\n values: customCredentialsToStoreValues(newSecretCredentials),\n });\n\n let updated: ModelProviderConfig;\n try {\n updated = await upsertModelProviderConfig({\n workspaceId: params.workspaceId,\n providerId: params.providerId,\n kind: 'custom',\n displayName: nextDisplayName,\n api: nextApi,\n baseUrl: nextBaseUrl,\n headers: nextHeaders.plaintextHeaders,\n secretHeaderNames: nextHeaders.secretHeaderNames,\n models: nextModels,\n requiresApiKey: existing.requiresApiKey || params.body.api_key !== undefined,\n defaultModel: nextDefaultModel,\n defaultThinking: existing.defaultThinking,\n });\n } catch (error) {\n await rollbackCustomProviderSecretUpdate({\n workspaceId: params.workspaceId,\n namespace,\n existingSecrets,\n attemptedSecrets: newSecretCredentials,\n }).catch(() => undefined);\n throw error;\n }\n\n await pruneStaleCustomHeaderSecrets({\n workspaceId: params.workspaceId,\n providerId: params.providerId,\n existingSecrets,\n newSecrets: newSecretCredentials,\n replaceHeaders: params.body.headers !== undefined,\n });\n\n return updated;\n}\n\nexport async function resolveCustomModelProviderDiscoveryParams(params: {\n workspaceId: string;\n providerId: ModelProviderRef;\n body: DiscoverCustomModelProviderModelsBySlugBodyDto;\n}): Promise<DiscoverCustomModelProviderModelsBodyDto> {\n const existing = await getExistingCustomConfig(params.workspaceId, params.providerId);\n const existingSecrets = await getCustomProviderSecrets({\n workspaceId: params.workspaceId,\n providerId: params.providerId,\n });\n assertStoredSecretsNotReusedAfterBaseUrlChange({\n body: params.body,\n existing,\n existingSecrets,\n providerId: params.providerId,\n });\n const headers = resolveNextHeaders({\n requestHeaders: params.body.headers,\n existing,\n existingSecrets,\n providerId: params.providerId,\n });\n\n return {\n api: params.body.api ?? existing.api ?? 'openai-responses',\n base_url: params.body.base_url ?? existing.baseUrl ?? '',\n ...((params.body.api_key ?? existingSecrets.api_key)\n ? {api_key: params.body.api_key ?? existingSecrets.api_key}\n : {}),\n headers: Object.entries(headers.runtimeHeaders).map(([name, value]) => ({name, value})),\n };\n}\n\nasync function getExistingCustomConfig(\n workspaceId: string,\n providerId: ModelProviderRef,\n): Promise<ModelProviderConfig> {\n const existing = await getModelProviderConfig({workspaceId, providerId});\n if (existing?.kind !== 'custom') {\n throw new CustomModelProviderConfigNotFoundError(workspaceId, providerId);\n }\n return existing;\n}\n\nfunction splitCustomHeaders(headers: CustomModelProviderHeaderRequestDto[]): SplitHeaders {\n const plaintextHeaders: CustomModelProviderHeaderDto[] = [];\n const secretHeaderNames: string[] = [];\n const secretCredentials: Record<string, string> = {};\n const runtimeHeaders: Record<string, string> = {};\n\n for (const header of headers) {\n runtimeHeaders[header.name] = header.value;\n if (header.secret) {\n secretHeaderNames.push(header.name);\n secretCredentials[`header:${header.name}`] = header.value;\n } else {\n plaintextHeaders.push({name: header.name, value: header.value});\n }\n }\n\n return {plaintextHeaders, secretHeaderNames, secretCredentials, runtimeHeaders};\n}\n\nfunction resolveNextHeaders(params: {\n requestHeaders: UpdateCustomModelProviderHeaderRequestDto[] | undefined;\n existing: ModelProviderConfig;\n existingSecrets: Record<string, string>;\n providerId: ModelProviderRef;\n}): {\n plaintextHeaders: CustomModelProviderHeaderDto[];\n secretHeaderNames: string[];\n runtimeHeaders: Record<string, string>;\n probeSecretCredentials: Record<string, string>;\n newSecretCredentials: Record<string, string>;\n} {\n if (params.requestHeaders !== undefined) {\n return splitUpdateHeaders({\n requestHeaders: params.requestHeaders,\n existingSecrets: params.existingSecrets,\n providerId: params.providerId,\n });\n }\n\n const runtimeHeaders: Record<string, string> = {};\n for (const header of params.existing.headers ?? []) {\n runtimeHeaders[header.name] = header.value;\n }\n\n const probeSecretCredentials: Record<string, string> = {};\n for (const [key, value] of Object.entries(params.existingSecrets)) {\n if (!key.startsWith('header:')) continue;\n const name = key.slice('header:'.length);\n runtimeHeaders[name] = value;\n probeSecretCredentials[key] = value;\n }\n\n return {\n plaintextHeaders: params.existing.headers ?? [],\n secretHeaderNames:\n params.existing.secretHeaderNames ?? secretHeaderNamesFromCredentials(params.existingSecrets),\n runtimeHeaders,\n probeSecretCredentials,\n newSecretCredentials: {},\n };\n}\n\nfunction splitUpdateHeaders(params: {\n requestHeaders: UpdateCustomModelProviderHeaderRequestDto[];\n existingSecrets: Record<string, string>;\n providerId: ModelProviderRef;\n}): {\n plaintextHeaders: CustomModelProviderHeaderDto[];\n secretHeaderNames: string[];\n runtimeHeaders: Record<string, string>;\n probeSecretCredentials: Record<string, string>;\n newSecretCredentials: Record<string, string>;\n} {\n const plaintextHeaders: CustomModelProviderHeaderDto[] = [];\n const secretHeaderNames: string[] = [];\n const runtimeHeaders: Record<string, string> = {};\n const probeSecretCredentials: Record<string, string> = {};\n const newSecretCredentials: Record<string, string> = {};\n\n for (const header of params.requestHeaders) {\n if (header.keep === true) {\n const key = `header:${header.name}`;\n const value = params.existingSecrets[key];\n if (value === undefined) {\n throw new InvalidCustomModelProviderHeaderKeepError(params.providerId, header.name);\n }\n runtimeHeaders[header.name] = value;\n secretHeaderNames.push(header.name);\n probeSecretCredentials[key] = value;\n newSecretCredentials[key] = value;\n continue;\n }\n\n const value = header.value;\n if (value === undefined) {\n throw new InvalidCustomModelProviderHeaderKeepError(params.providerId, header.name);\n }\n runtimeHeaders[header.name] = value;\n if (header.secret) {\n const key = `header:${header.name}`;\n secretHeaderNames.push(header.name);\n probeSecretCredentials[key] = value;\n newSecretCredentials[key] = value;\n } else {\n plaintextHeaders.push({name: header.name, value});\n }\n }\n\n return {\n plaintextHeaders,\n secretHeaderNames,\n runtimeHeaders,\n probeSecretCredentials,\n newSecretCredentials,\n };\n}\n\nfunction resolveNextDefaultModel(\n providerId: ModelProviderRef,\n existingDefaultModel: string | null,\n models: CustomAgentModelDto[],\n body: UpdateCustomModelProviderBodyDto,\n): string | null {\n if (!('default_model' in body)) {\n if (existingDefaultModel === null) return null;\n return models.some((model) => model.id === existingDefaultModel) ? existingDefaultModel : null;\n }\n\n const requestedDefaultModel = body.default_model ?? null;\n if (requestedDefaultModel === null) return null;\n if (models.some((model) => model.id === requestedDefaultModel)) return requestedDefaultModel;\n throw new InvalidAgentModelError('pi', providerId, requestedDefaultModel);\n}\n\nfunction selectProbeModel(\n models: CustomAgentModelDto[],\n defaultModel: string | null,\n): CustomAgentModelDto {\n const model = models.find((candidate) => candidate.id === defaultModel) ?? models[0];\n if (!model) throw new Error('Custom model provider must include at least one model.');\n return model;\n}\n\nasync function getCustomProviderSecrets(params: {\n workspaceId: string;\n providerId: ModelProviderRef;\n}): Promise<Record<string, string>> {\n const values = await getSecretsByNamespace({\n workspaceId: params.workspaceId,\n namespace: agentSystemNamespace(params.providerId),\n });\n return storeValuesToCustomRuntimeCredentials(values);\n}\n\nfunction assertStoredSecretsNotReusedAfterBaseUrlChange(params: {\n body: UpdateCustomModelProviderBodyDto | DiscoverCustomModelProviderModelsBySlugBodyDto;\n existing: ModelProviderConfig;\n existingSecrets: Record<string, string>;\n providerId: ModelProviderRef;\n}): void {\n if (\n params.body.base_url === undefined ||\n normalizedUrl(params.body.base_url) === normalizedUrl(params.existing.baseUrl ?? '')\n ) {\n return;\n }\n\n const reusesStoredApiKey =\n params.existingSecrets.api_key !== undefined && params.body.api_key === undefined;\n const reusesStoredSecretHeader =\n params.body.headers === undefined\n ? Object.keys(params.existingSecrets).some((key) => key.startsWith('header:'))\n : params.body.headers.some((header) => header.keep === true);\n\n if (reusesStoredApiKey || reusesStoredSecretHeader) {\n throw new CustomModelProviderStoredSecretBaseUrlChangeError(params.providerId);\n }\n}\n\nfunction normalizedUrl(value: string): string {\n return normalizeCustomProviderBaseUrl(value);\n}\n\nasync function rollbackCustomProviderSecretUpdate(params: {\n workspaceId: string;\n namespace: string;\n existingSecrets: Record<string, string>;\n attemptedSecrets: Record<string, string>;\n}): Promise<void> {\n const attemptedKeys = Object.keys(params.attemptedSecrets);\n if (attemptedKeys.length === 0) return;\n\n const secretsToRestore = Object.fromEntries(\n attemptedKeys.flatMap((key) => {\n const value = params.existingSecrets[key];\n return value === undefined ? [] : [[key, value]];\n }),\n );\n if (Object.keys(secretsToRestore).length > 0) {\n await setSecrets({\n workspaceId: params.workspaceId,\n namespace: params.namespace,\n values: customCredentialsToStoreValues(secretsToRestore),\n });\n }\n\n const newKeys = attemptedKeys.filter((key) => params.existingSecrets[key] === undefined);\n if (newKeys.length === 0) return;\n\n await deleteSecrets({\n workspaceId: params.workspaceId,\n namespace: params.namespace,\n keys: newKeys.map(customCredentialToStoreKey),\n });\n}\n\nasync function pruneStaleCustomHeaderSecrets(params: {\n workspaceId: string;\n providerId: ModelProviderRef;\n existingSecrets: Record<string, string>;\n newSecrets: Record<string, string>;\n replaceHeaders: boolean;\n}): Promise<void> {\n if (!params.replaceHeaders) return;\n\n const nextKeys = new Set(Object.keys(params.newSecrets));\n const staleKeys = Object.keys(params.existingSecrets).filter(\n (key) => key.startsWith('header:') && !nextKeys.has(key),\n );\n if (staleKeys.length === 0) return;\n\n await deleteSecrets({\n workspaceId: params.workspaceId,\n namespace: agentSystemNamespace(params.providerId),\n keys: staleKeys.map(customCredentialToStoreKey),\n });\n}\n\nfunction secretHeaderNamesFromCredentials(credentials: Record<string, string>): string[] {\n return Object.keys(credentials)\n .filter((key) => key.startsWith('header:'))\n .map((key) => key.slice('header:'.length))\n .sort();\n}\n"],"names":["DEFAULT_AGENT_THINKING","deleteSecrets","getSecretsByNamespace","setSecrets","assertEgressAllowed","deleteModelProviderConfig","getModelProviderConfig","insertCustomModelProviderConfig","upsertModelProviderConfig","agentSystemNamespace","customCredentialsToStoreValues","customCredentialToStoreKey","storeValuesToCustomRuntimeCredentials","normalizeCustomProviderBaseUrl","CustomModelProviderConfigNotFoundError","CustomModelProviderSlugCollisionError","CustomModelProviderStoredSecretBaseUrlChangeError","InvalidAgentModelError","InvalidCustomModelProviderHeaderKeepError","egressPolicy","probeCustomModelProviderCredentials","runProviderProbe","createCustomModelProviderConfig","params","options","probe","existing","workspaceId","providerId","body","slug","undefined","splitHeaders","splitCustomHeaders","headers","secretCredentials","api_key","probeModel","selectProbeModel","models","default_model","base_url","args","api","baseUrl","model","apiKey","runtimeHeaders","signal","metricLabel","secrets","Object","values","config","kind","displayName","display_name","plaintextHeaders","secretHeaderNames","requiresApiKey","defaultModel","defaultThinking","setAsDefault","namespace","error","updateCustomModelProviderConfig","getExistingCustomConfig","existingSecrets","getCustomProviderSecrets","nextModels","nextDefaultModel","resolveNextDefaultModel","nextApi","nextBaseUrl","nextDisplayName","assertStoredSecretsNotReusedAfterBaseUrlChange","nextHeaders","resolveNextHeaders","requestHeaders","nextApiKey","newSecretCredentials","probeSecretCredentials","updated","rollbackCustomProviderSecretUpdate","attemptedSecrets","catch","pruneStaleCustomHeaderSecrets","newSecrets","replaceHeaders","resolveCustomModelProviderDiscoveryParams","entries","map","name","value","header","secret","push","splitUpdateHeaders","key","startsWith","slice","length","secretHeaderNamesFromCredentials","keep","existingDefaultModel","some","id","requestedDefaultModel","find","candidate","Error","normalizedUrl","reusesStoredApiKey","reusesStoredSecretHeader","keys","attemptedKeys","secretsToRestore","fromEntries","flatMap","newKeys","filter","nextKeys","Set","staleKeys","has","credentials","sort"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/core/custom-model-provider-config-service.ts"],"sourcesContent":["import {\n type CreateCustomModelProviderBodyDto,\n type CustomAgentModelDto,\n type CustomModelProviderHeaderDto,\n type CustomModelProviderHeaderRequestDto,\n DEFAULT_AGENT_THINKING,\n type DiscoverCustomModelProviderModelsBodyDto,\n type DiscoverCustomModelProviderModelsBySlugBodyDto,\n type ModelProviderRef,\n type UpdateCustomModelProviderBodyDto,\n type UpdateCustomModelProviderHeaderRequestDto,\n} from '@shipfox/api-agent-dto';\nimport {assertEgressAllowed} from '@shipfox/node-egress-guard';\nimport {reportError} from '@shipfox/node-error-monitoring';\nimport {logger} from '@shipfox/node-opentelemetry';\nimport {\n deleteModelProviderConfig,\n getModelProviderConfig,\n insertCustomModelProviderConfig,\n upsertModelProviderConfig,\n} from '#db/index.js';\nimport {\n agentSystemNamespace,\n customCredentialsToStoreValues,\n customCredentialToStoreKey,\n storeValuesToCustomRuntimeCredentials,\n} from './credential-fingerprints.js';\nimport {normalizeCustomProviderBaseUrl} from './custom-provider-url.js';\nimport type {ModelProviderConfig} from './entities/model-provider-config.js';\nimport {\n CustomModelProviderConfigNotFoundError,\n CustomModelProviderSlugCollisionError,\n CustomModelProviderStoredSecretBaseUrlChangeError,\n InvalidAgentModelError,\n InvalidCustomModelProviderHeaderKeepError,\n} from './errors.js';\nimport {\n egressPolicy,\n probeCustomModelProviderCredentials,\n runProviderProbe,\n} from './model-provider-validation.js';\nimport {type AgentSecretsClient, requireAgentSecretsClient} from './secrets-client.js';\n\nexport interface CreateCustomModelProviderConfigParams {\n workspaceId: string;\n body: CreateCustomModelProviderBodyDto;\n setAsDefault?: boolean | undefined;\n signal?: AbortSignal | undefined;\n}\n\nexport interface UpdateCustomModelProviderConfigParams {\n workspaceId: string;\n providerId: ModelProviderRef;\n body: UpdateCustomModelProviderBodyDto;\n signal?: AbortSignal | undefined;\n}\n\nexport interface CustomModelProviderConfigServiceOptions {\n probe?: typeof probeCustomModelProviderCredentials | undefined;\n secrets?: AgentSecretsClient | undefined;\n}\n\ninterface SplitHeaders {\n plaintextHeaders: CustomModelProviderHeaderDto[];\n secretHeaderNames: string[];\n secretCredentials: Record<string, string>;\n runtimeHeaders: Record<string, string>;\n}\n\nexport async function createCustomModelProviderConfig(\n params: CreateCustomModelProviderConfigParams,\n options: CustomModelProviderConfigServiceOptions = {},\n): Promise<ModelProviderConfig> {\n const probe = options.probe ?? probeCustomModelProviderCredentials;\n const secrets = requireAgentSecretsClient(options.secrets);\n\n const existing = await getModelProviderConfig({\n workspaceId: params.workspaceId,\n providerId: params.body.slug,\n });\n if (existing !== undefined) {\n throw new CustomModelProviderSlugCollisionError(params.workspaceId, params.body.slug);\n }\n\n const splitHeaders = splitCustomHeaders(params.body.headers ?? []);\n const secretCredentials = {\n ...(params.body.api_key ? {api_key: params.body.api_key} : {}),\n ...splitHeaders.secretCredentials,\n };\n const probeModel = selectProbeModel(params.body.models, params.body.default_model ?? null);\n\n await assertEgressAllowed(params.body.base_url, egressPolicy());\n await runProviderProbe({\n probe,\n args: {\n providerId: params.body.slug,\n api: params.body.api,\n baseUrl: params.body.base_url,\n model: probeModel,\n apiKey: params.body.api_key,\n headers: splitHeaders.runtimeHeaders,\n ...(params.signal ? {signal: params.signal} : {}),\n },\n metricLabel: 'custom',\n providerId: params.body.slug,\n secrets: Object.values(secretCredentials),\n signal: params.signal,\n });\n\n const config = await insertCustomModelProviderConfig({\n workspaceId: params.workspaceId,\n providerId: params.body.slug,\n kind: 'custom',\n displayName: params.body.display_name,\n api: params.body.api,\n baseUrl: params.body.base_url,\n headers: splitHeaders.plaintextHeaders,\n secretHeaderNames: splitHeaders.secretHeaderNames,\n models: params.body.models,\n requiresApiKey: params.body.api_key !== undefined,\n defaultModel: params.body.default_model ?? null,\n defaultThinking: DEFAULT_AGENT_THINKING,\n setAsDefault: params.setAsDefault,\n });\n if (!config) {\n throw new CustomModelProviderSlugCollisionError(params.workspaceId, params.body.slug);\n }\n\n try {\n await secrets.setSecrets({\n workspaceId: params.workspaceId,\n namespace: agentSystemNamespace(params.body.slug),\n values: customCredentialsToStoreValues(secretCredentials),\n });\n return config;\n } catch (error) {\n await deleteModelProviderConfig({\n workspaceId: params.workspaceId,\n providerId: params.body.slug,\n });\n await secrets.deleteSecrets({\n workspaceId: params.workspaceId,\n namespace: agentSystemNamespace(params.body.slug),\n });\n throw error;\n }\n}\n\nexport async function updateCustomModelProviderConfig(\n params: UpdateCustomModelProviderConfigParams,\n options: CustomModelProviderConfigServiceOptions = {},\n): Promise<ModelProviderConfig> {\n const probe = options.probe ?? probeCustomModelProviderCredentials;\n const secrets = requireAgentSecretsClient(options.secrets);\n\n const existing = await getExistingCustomConfig(params.workspaceId, params.providerId);\n const existingSecrets = await getCustomProviderSecrets(secrets, {\n workspaceId: params.workspaceId,\n providerId: params.providerId,\n });\n const nextModels = params.body.models ?? existing.models ?? [];\n const nextDefaultModel = resolveNextDefaultModel(\n params.providerId,\n existing.defaultModel,\n nextModels,\n params.body,\n );\n const nextApi = params.body.api ?? existing.api ?? 'openai-responses';\n const nextBaseUrl = params.body.base_url ?? existing.baseUrl ?? '';\n const nextDisplayName = params.body.display_name ?? existing.displayName ?? params.providerId;\n assertStoredSecretsNotReusedAfterBaseUrlChange({\n body: params.body,\n existing,\n existingSecrets,\n providerId: params.providerId,\n });\n const nextHeaders = resolveNextHeaders({\n requestHeaders: params.body.headers,\n existing,\n existingSecrets,\n providerId: params.providerId,\n });\n const nextApiKey = params.body.api_key ?? existingSecrets.api_key;\n const newSecretCredentials = {\n ...(params.body.api_key ? {api_key: params.body.api_key} : {}),\n ...nextHeaders.newSecretCredentials,\n };\n const probeSecretCredentials = {\n ...(nextApiKey ? {api_key: nextApiKey} : {}),\n ...nextHeaders.probeSecretCredentials,\n };\n\n await assertEgressAllowed(nextBaseUrl, egressPolicy());\n await runProviderProbe({\n probe,\n args: {\n providerId: params.providerId,\n api: nextApi,\n baseUrl: nextBaseUrl,\n model: selectProbeModel(nextModels, nextDefaultModel),\n apiKey: nextApiKey,\n headers: nextHeaders.runtimeHeaders,\n ...(params.signal ? {signal: params.signal} : {}),\n },\n metricLabel: 'custom',\n providerId: params.providerId,\n secrets: Object.values(probeSecretCredentials),\n signal: params.signal,\n });\n\n const namespace = agentSystemNamespace(params.providerId);\n await secrets.setSecrets({\n workspaceId: params.workspaceId,\n namespace,\n values: customCredentialsToStoreValues(newSecretCredentials),\n });\n\n let updated: ModelProviderConfig;\n try {\n updated = await upsertModelProviderConfig({\n workspaceId: params.workspaceId,\n providerId: params.providerId,\n kind: 'custom',\n displayName: nextDisplayName,\n api: nextApi,\n baseUrl: nextBaseUrl,\n headers: nextHeaders.plaintextHeaders,\n secretHeaderNames: nextHeaders.secretHeaderNames,\n models: nextModels,\n requiresApiKey: existing.requiresApiKey || params.body.api_key !== undefined,\n defaultModel: nextDefaultModel,\n defaultThinking: existing.defaultThinking,\n });\n } catch (error) {\n await rollbackCustomProviderSecretUpdate(secrets, {\n workspaceId: params.workspaceId,\n namespace,\n existingSecrets,\n attemptedSecrets: newSecretCredentials,\n }).catch((rollbackError) => {\n logger().error(\n {err: rollbackError, workspaceId: params.workspaceId, providerId: params.providerId},\n 'Failed to roll back custom model provider secrets',\n );\n reportError(rollbackError, {\n boundary: 'agent.cleanup',\n operation: 'rollback-secret-update',\n extra: {workspaceId: params.workspaceId, providerId: params.providerId},\n });\n });\n throw error;\n }\n\n await pruneStaleCustomHeaderSecrets(secrets, {\n workspaceId: params.workspaceId,\n providerId: params.providerId,\n existingSecrets,\n newSecrets: newSecretCredentials,\n replaceHeaders: params.body.headers !== undefined,\n });\n\n return updated;\n}\n\nexport async function resolveCustomModelProviderDiscoveryParams(\n params: {\n workspaceId: string;\n providerId: ModelProviderRef;\n body: DiscoverCustomModelProviderModelsBySlugBodyDto;\n },\n options: {secrets?: AgentSecretsClient | undefined} = {},\n): Promise<DiscoverCustomModelProviderModelsBodyDto> {\n const secrets = requireAgentSecretsClient(options.secrets);\n const existing = await getExistingCustomConfig(params.workspaceId, params.providerId);\n const existingSecrets = await getCustomProviderSecrets(secrets, {\n workspaceId: params.workspaceId,\n providerId: params.providerId,\n });\n assertStoredSecretsNotReusedAfterBaseUrlChange({\n body: params.body,\n existing,\n existingSecrets,\n providerId: params.providerId,\n });\n const headers = resolveNextHeaders({\n requestHeaders: params.body.headers,\n existing,\n existingSecrets,\n providerId: params.providerId,\n });\n\n return {\n api: params.body.api ?? existing.api ?? 'openai-responses',\n base_url: params.body.base_url ?? existing.baseUrl ?? '',\n ...((params.body.api_key ?? existingSecrets.api_key)\n ? {api_key: params.body.api_key ?? existingSecrets.api_key}\n : {}),\n headers: Object.entries(headers.runtimeHeaders).map(([name, value]) => ({name, value})),\n };\n}\n\nasync function getExistingCustomConfig(\n workspaceId: string,\n providerId: ModelProviderRef,\n): Promise<ModelProviderConfig> {\n const existing = await getModelProviderConfig({workspaceId, providerId});\n if (existing?.kind !== 'custom') {\n throw new CustomModelProviderConfigNotFoundError(workspaceId, providerId);\n }\n return existing;\n}\n\nfunction splitCustomHeaders(headers: CustomModelProviderHeaderRequestDto[]): SplitHeaders {\n const plaintextHeaders: CustomModelProviderHeaderDto[] = [];\n const secretHeaderNames: string[] = [];\n const secretCredentials: Record<string, string> = {};\n const runtimeHeaders: Record<string, string> = {};\n\n for (const header of headers) {\n runtimeHeaders[header.name] = header.value;\n if (header.secret) {\n secretHeaderNames.push(header.name);\n secretCredentials[`header:${header.name}`] = header.value;\n } else {\n plaintextHeaders.push({name: header.name, value: header.value});\n }\n }\n\n return {plaintextHeaders, secretHeaderNames, secretCredentials, runtimeHeaders};\n}\n\nfunction resolveNextHeaders(params: {\n requestHeaders: UpdateCustomModelProviderHeaderRequestDto[] | undefined;\n existing: ModelProviderConfig;\n existingSecrets: Record<string, string>;\n providerId: ModelProviderRef;\n}): {\n plaintextHeaders: CustomModelProviderHeaderDto[];\n secretHeaderNames: string[];\n runtimeHeaders: Record<string, string>;\n probeSecretCredentials: Record<string, string>;\n newSecretCredentials: Record<string, string>;\n} {\n if (params.requestHeaders !== undefined) {\n return splitUpdateHeaders({\n requestHeaders: params.requestHeaders,\n existingSecrets: params.existingSecrets,\n providerId: params.providerId,\n });\n }\n\n const runtimeHeaders: Record<string, string> = {};\n for (const header of params.existing.headers ?? []) {\n runtimeHeaders[header.name] = header.value;\n }\n\n const probeSecretCredentials: Record<string, string> = {};\n for (const [key, value] of Object.entries(params.existingSecrets)) {\n if (!key.startsWith('header:')) continue;\n const name = key.slice('header:'.length);\n runtimeHeaders[name] = value;\n probeSecretCredentials[key] = value;\n }\n\n return {\n plaintextHeaders: params.existing.headers ?? [],\n secretHeaderNames:\n params.existing.secretHeaderNames ?? secretHeaderNamesFromCredentials(params.existingSecrets),\n runtimeHeaders,\n probeSecretCredentials,\n newSecretCredentials: {},\n };\n}\n\nfunction splitUpdateHeaders(params: {\n requestHeaders: UpdateCustomModelProviderHeaderRequestDto[];\n existingSecrets: Record<string, string>;\n providerId: ModelProviderRef;\n}): {\n plaintextHeaders: CustomModelProviderHeaderDto[];\n secretHeaderNames: string[];\n runtimeHeaders: Record<string, string>;\n probeSecretCredentials: Record<string, string>;\n newSecretCredentials: Record<string, string>;\n} {\n const plaintextHeaders: CustomModelProviderHeaderDto[] = [];\n const secretHeaderNames: string[] = [];\n const runtimeHeaders: Record<string, string> = {};\n const probeSecretCredentials: Record<string, string> = {};\n const newSecretCredentials: Record<string, string> = {};\n\n for (const header of params.requestHeaders) {\n if (header.keep === true) {\n const key = `header:${header.name}`;\n const value = params.existingSecrets[key];\n if (value === undefined) {\n throw new InvalidCustomModelProviderHeaderKeepError(params.providerId, header.name);\n }\n runtimeHeaders[header.name] = value;\n secretHeaderNames.push(header.name);\n probeSecretCredentials[key] = value;\n newSecretCredentials[key] = value;\n continue;\n }\n\n const value = header.value;\n if (value === undefined) {\n throw new InvalidCustomModelProviderHeaderKeepError(params.providerId, header.name);\n }\n runtimeHeaders[header.name] = value;\n if (header.secret) {\n const key = `header:${header.name}`;\n secretHeaderNames.push(header.name);\n probeSecretCredentials[key] = value;\n newSecretCredentials[key] = value;\n } else {\n plaintextHeaders.push({name: header.name, value});\n }\n }\n\n return {\n plaintextHeaders,\n secretHeaderNames,\n runtimeHeaders,\n probeSecretCredentials,\n newSecretCredentials,\n };\n}\n\nfunction resolveNextDefaultModel(\n providerId: ModelProviderRef,\n existingDefaultModel: string | null,\n models: CustomAgentModelDto[],\n body: UpdateCustomModelProviderBodyDto,\n): string | null {\n if (!('default_model' in body)) {\n if (existingDefaultModel === null) return null;\n return models.some((model) => model.id === existingDefaultModel) ? existingDefaultModel : null;\n }\n\n const requestedDefaultModel = body.default_model ?? null;\n if (requestedDefaultModel === null) return null;\n if (models.some((model) => model.id === requestedDefaultModel)) return requestedDefaultModel;\n throw new InvalidAgentModelError('pi', providerId, requestedDefaultModel);\n}\n\nfunction selectProbeModel(\n models: CustomAgentModelDto[],\n defaultModel: string | null,\n): CustomAgentModelDto {\n const model = models.find((candidate) => candidate.id === defaultModel) ?? models[0];\n if (!model) throw new Error('Custom model provider must include at least one model.');\n return model;\n}\n\nasync function getCustomProviderSecrets(\n secrets: AgentSecretsClient,\n params: {\n workspaceId: string;\n providerId: ModelProviderRef;\n },\n): Promise<Record<string, string>> {\n const {values} = await secrets.getSecretsByNamespace({\n workspaceId: params.workspaceId,\n namespace: agentSystemNamespace(params.providerId),\n });\n return storeValuesToCustomRuntimeCredentials(values);\n}\n\nfunction assertStoredSecretsNotReusedAfterBaseUrlChange(params: {\n body: UpdateCustomModelProviderBodyDto | DiscoverCustomModelProviderModelsBySlugBodyDto;\n existing: ModelProviderConfig;\n existingSecrets: Record<string, string>;\n providerId: ModelProviderRef;\n}): void {\n if (\n params.body.base_url === undefined ||\n normalizedUrl(params.body.base_url) === normalizedUrl(params.existing.baseUrl ?? '')\n ) {\n return;\n }\n\n const reusesStoredApiKey =\n params.existingSecrets.api_key !== undefined && params.body.api_key === undefined;\n const reusesStoredSecretHeader =\n params.body.headers === undefined\n ? Object.keys(params.existingSecrets).some((key) => key.startsWith('header:'))\n : params.body.headers.some((header) => header.keep === true);\n\n if (reusesStoredApiKey || reusesStoredSecretHeader) {\n throw new CustomModelProviderStoredSecretBaseUrlChangeError(params.providerId);\n }\n}\n\nfunction normalizedUrl(value: string): string {\n return normalizeCustomProviderBaseUrl(value);\n}\n\nasync function rollbackCustomProviderSecretUpdate(\n secrets: AgentSecretsClient,\n params: {\n workspaceId: string;\n namespace: string;\n existingSecrets: Record<string, string>;\n attemptedSecrets: Record<string, string>;\n },\n): Promise<void> {\n const attemptedKeys = Object.keys(params.attemptedSecrets);\n if (attemptedKeys.length === 0) return;\n\n const secretsToRestore = Object.fromEntries(\n attemptedKeys.flatMap((key) => {\n const value = params.existingSecrets[key];\n return value === undefined ? [] : [[key, value]];\n }),\n );\n if (Object.keys(secretsToRestore).length > 0) {\n await secrets.setSecrets({\n workspaceId: params.workspaceId,\n namespace: params.namespace,\n values: customCredentialsToStoreValues(secretsToRestore),\n });\n }\n\n const newKeys = attemptedKeys.filter((key) => params.existingSecrets[key] === undefined);\n if (newKeys.length === 0) return;\n\n await secrets.deleteSecrets({\n workspaceId: params.workspaceId,\n namespace: params.namespace,\n keys: newKeys.map(customCredentialToStoreKey),\n });\n}\n\nasync function pruneStaleCustomHeaderSecrets(\n secrets: AgentSecretsClient,\n params: {\n workspaceId: string;\n providerId: ModelProviderRef;\n existingSecrets: Record<string, string>;\n newSecrets: Record<string, string>;\n replaceHeaders: boolean;\n },\n): Promise<void> {\n if (!params.replaceHeaders) return;\n\n const nextKeys = new Set(Object.keys(params.newSecrets));\n const staleKeys = Object.keys(params.existingSecrets).filter(\n (key) => key.startsWith('header:') && !nextKeys.has(key),\n );\n if (staleKeys.length === 0) return;\n\n await secrets.deleteSecrets({\n workspaceId: params.workspaceId,\n namespace: agentSystemNamespace(params.providerId),\n keys: staleKeys.map(customCredentialToStoreKey),\n });\n}\n\nfunction secretHeaderNamesFromCredentials(credentials: Record<string, string>): string[] {\n return Object.keys(credentials)\n .filter((key) => key.startsWith('header:'))\n .map((key) => key.slice('header:'.length))\n .sort();\n}\n"],"names":["DEFAULT_AGENT_THINKING","assertEgressAllowed","reportError","logger","deleteModelProviderConfig","getModelProviderConfig","insertCustomModelProviderConfig","upsertModelProviderConfig","agentSystemNamespace","customCredentialsToStoreValues","customCredentialToStoreKey","storeValuesToCustomRuntimeCredentials","normalizeCustomProviderBaseUrl","CustomModelProviderConfigNotFoundError","CustomModelProviderSlugCollisionError","CustomModelProviderStoredSecretBaseUrlChangeError","InvalidAgentModelError","InvalidCustomModelProviderHeaderKeepError","egressPolicy","probeCustomModelProviderCredentials","runProviderProbe","requireAgentSecretsClient","createCustomModelProviderConfig","params","options","probe","secrets","existing","workspaceId","providerId","body","slug","undefined","splitHeaders","splitCustomHeaders","headers","secretCredentials","api_key","probeModel","selectProbeModel","models","default_model","base_url","args","api","baseUrl","model","apiKey","runtimeHeaders","signal","metricLabel","Object","values","config","kind","displayName","display_name","plaintextHeaders","secretHeaderNames","requiresApiKey","defaultModel","defaultThinking","setAsDefault","setSecrets","namespace","error","deleteSecrets","updateCustomModelProviderConfig","getExistingCustomConfig","existingSecrets","getCustomProviderSecrets","nextModels","nextDefaultModel","resolveNextDefaultModel","nextApi","nextBaseUrl","nextDisplayName","assertStoredSecretsNotReusedAfterBaseUrlChange","nextHeaders","resolveNextHeaders","requestHeaders","nextApiKey","newSecretCredentials","probeSecretCredentials","updated","rollbackCustomProviderSecretUpdate","attemptedSecrets","catch","rollbackError","err","boundary","operation","extra","pruneStaleCustomHeaderSecrets","newSecrets","replaceHeaders","resolveCustomModelProviderDiscoveryParams","entries","map","name","value","header","secret","push","splitUpdateHeaders","key","startsWith","slice","length","secretHeaderNamesFromCredentials","keep","existingDefaultModel","some","id","requestedDefaultModel","find","candidate","Error","getSecretsByNamespace","normalizedUrl","reusesStoredApiKey","reusesStoredSecretHeader","keys","attemptedKeys","secretsToRestore","fromEntries","flatMap","newKeys","filter","nextKeys","Set","staleKeys","has","credentials","sort"],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type ModelProviderRef, type SupportedModelProviderId } from '@shipfox/api-agent-dto';
|
|
2
2
|
import type { ModelProviderConfig } from './entities/model-provider-config.js';
|
|
3
3
|
import { probeModelProviderCredentials } from './model-provider-validation.js';
|
|
4
|
+
import { type AgentSecretsClient } from './secrets-client.js';
|
|
4
5
|
export interface TestAndSaveModelProviderConfigParams {
|
|
5
6
|
workspaceId: string;
|
|
6
7
|
providerId: SupportedModelProviderId;
|
|
@@ -12,6 +13,7 @@ export interface TestAndSaveModelProviderConfigParams {
|
|
|
12
13
|
}
|
|
13
14
|
export interface TestAndSaveModelProviderConfigOptions {
|
|
14
15
|
probe?: typeof probeModelProviderCredentials;
|
|
16
|
+
secrets?: AgentSecretsClient | undefined;
|
|
15
17
|
pruneStaleSecrets?: ((params: {
|
|
16
18
|
workspaceId: string;
|
|
17
19
|
namespace: string;
|
|
@@ -28,5 +30,7 @@ export declare function updateModelProviderConfigDefaultModel(params: UpdateMode
|
|
|
28
30
|
export declare function deleteModelProviderConfig(params: {
|
|
29
31
|
workspaceId: string;
|
|
30
32
|
providerId: ModelProviderRef;
|
|
33
|
+
}, options?: {
|
|
34
|
+
secrets?: AgentSecretsClient | undefined;
|
|
31
35
|
}): Promise<boolean>;
|
|
32
36
|
//# sourceMappingURL=model-provider-config-service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-provider-config-service.d.ts","sourceRoot":"","sources":["../../src/core/model-provider-config-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,gBAAgB,EAErB,KAAK,wBAAwB,EAC9B,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"model-provider-config-service.d.ts","sourceRoot":"","sources":["../../src/core/model-provider-config-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,gBAAgB,EAErB,KAAK,wBAAwB,EAC9B,MAAM,wBAAwB,CAAC;AAUhC,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,qCAAqC,CAAC;AAQ7E,OAAO,EAAC,6BAA6B,EAAmB,MAAM,gCAAgC,CAAC;AAC/F,OAAO,EAAC,KAAK,kBAAkB,EAA4B,MAAM,qBAAqB,CAAC;AAEvF,MAAM,WAAW,oCAAoC;IACnD,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,wBAAwB,CAAC;IACrC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACzC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACrC,YAAY,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACnC,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;CAClC;AAED,MAAM,WAAW,qCAAqC;IACpD,KAAK,CAAC,EAAE,OAAO,6BAA6B,CAAC;IAC7C,OAAO,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;IACzC,iBAAiB,CAAC,EACd,CAAC,CAAC,MAAM,EAAE;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,EAAE,CAAA;KAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,GAC7F,SAAS,CAAC;CACf;AAED,MAAM,WAAW,2CAA2C;IAC1D,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,gBAAgB,CAAC;IAC7B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,wBAAsB,8BAA8B,CAClD,MAAM,EAAE,oCAAoC,EAC5C,OAAO,GAAE,qCAA0C,GAClD,OAAO,CAAC,mBAAmB,CAAC,CAuE9B;AAED,wBAAsB,qCAAqC,CACzD,MAAM,EAAE,2CAA2C,GAClD,OAAO,CAAC,mBAAmB,CAAC,CAwC9B;AAED,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,gBAAgB,CAAA;CAAC,EAC3D,OAAO,GAAE;IAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAA;CAAM,GACvD,OAAO,CAAC,OAAO,CAAC,CAQlB"}
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { DEFAULT_AGENT_THINKING, getModelProviderEntry, modelProviderCredentialKeysMatch } from '@shipfox/api-agent-dto';
|
|
2
|
-
import {
|
|
2
|
+
import { reportError } from '@shipfox/node-error-monitoring';
|
|
3
|
+
import { logger } from '@shipfox/node-opentelemetry';
|
|
3
4
|
import { deleteModelProviderConfig as deleteModelProviderConfigRow, getModelProviderConfig, updateModelProviderDefaultModel, upsertModelProviderConfig } from '#db/index.js';
|
|
4
5
|
import { agentSystemNamespace, credentialsToStoreValues } from './credential-fingerprints.js';
|
|
5
6
|
import { InvalidAgentModelError, InvalidCredentialFieldsError, ModelProviderConfigNotFoundError, UnsupportedModelProviderError } from './errors.js';
|
|
6
7
|
import { buildModelProviderCatalog } from './model-provider-catalog.js';
|
|
7
8
|
import { probeModelProviderCredentials, runProviderProbe } from './model-provider-validation.js';
|
|
9
|
+
import { requireAgentSecretsClient } from './secrets-client.js';
|
|
8
10
|
export async function testAndSaveModelProviderConfig(params, options = {}) {
|
|
9
11
|
const probe = options.probe ?? probeModelProviderCredentials;
|
|
12
|
+
const secrets = requireAgentSecretsClient(options.secrets);
|
|
10
13
|
const entry = getModelProviderEntry(params.providerId);
|
|
11
14
|
if (entry === undefined || entry.support_status !== 'supported') {
|
|
12
15
|
throw new UnsupportedModelProviderError(params.providerId);
|
|
@@ -35,10 +38,10 @@ export async function testAndSaveModelProviderConfig(params, options = {}) {
|
|
|
35
38
|
secrets: Object.values(params.credentials),
|
|
36
39
|
signal: params.signal
|
|
37
40
|
});
|
|
38
|
-
const pruneStaleSecrets = options.pruneStaleSecrets ?? pruneStaleProviderCredentialSecrets;
|
|
41
|
+
const pruneStaleSecrets = options.pruneStaleSecrets ?? ((input)=>pruneStaleProviderCredentialSecrets(secrets, input));
|
|
39
42
|
const namespace = agentSystemNamespace(params.providerId);
|
|
40
43
|
const values = credentialsToStoreValues(params.providerId, params.credentials);
|
|
41
|
-
await setSecrets({
|
|
44
|
+
await secrets.setSecrets({
|
|
42
45
|
workspaceId: params.workspaceId,
|
|
43
46
|
namespace,
|
|
44
47
|
values,
|
|
@@ -55,7 +58,21 @@ export async function testAndSaveModelProviderConfig(params, options = {}) {
|
|
|
55
58
|
workspaceId: params.workspaceId,
|
|
56
59
|
namespace,
|
|
57
60
|
expectedKeys: Object.keys(values)
|
|
58
|
-
}).catch(()=>
|
|
61
|
+
}).catch((error)=>{
|
|
62
|
+
logger().error({
|
|
63
|
+
err: error,
|
|
64
|
+
workspaceId: params.workspaceId,
|
|
65
|
+
providerId: params.providerId
|
|
66
|
+
}, 'Failed to prune stale model provider secrets');
|
|
67
|
+
reportError(error, {
|
|
68
|
+
boundary: 'agent.cleanup',
|
|
69
|
+
operation: 'prune-stale-secrets',
|
|
70
|
+
extra: {
|
|
71
|
+
workspaceId: params.workspaceId,
|
|
72
|
+
providerId: params.providerId
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
});
|
|
59
76
|
return config;
|
|
60
77
|
}
|
|
61
78
|
export async function updateModelProviderConfigDefaultModel(params) {
|
|
@@ -93,9 +110,10 @@ export async function updateModelProviderConfigDefaultModel(params) {
|
|
|
93
110
|
if (!config) throw new ModelProviderConfigNotFoundError(params.workspaceId, params.providerId);
|
|
94
111
|
return config;
|
|
95
112
|
}
|
|
96
|
-
export async function deleteModelProviderConfig(params) {
|
|
113
|
+
export async function deleteModelProviderConfig(params, options = {}) {
|
|
114
|
+
const secrets = requireAgentSecretsClient(options.secrets);
|
|
97
115
|
const deleted = await deleteModelProviderConfigRow(params);
|
|
98
|
-
await deleteSecrets({
|
|
116
|
+
await secrets.deleteSecrets({
|
|
99
117
|
workspaceId: params.workspaceId,
|
|
100
118
|
namespace: agentSystemNamespace(params.providerId)
|
|
101
119
|
});
|
|
@@ -115,15 +133,15 @@ function resolveDefaultModel(providerId, requestedModel) {
|
|
|
115
133
|
storedModel: requestedModel ?? null
|
|
116
134
|
};
|
|
117
135
|
}
|
|
118
|
-
async function pruneStaleProviderCredentialSecrets(params) {
|
|
119
|
-
const stored = await getSecretsByNamespace({
|
|
136
|
+
async function pruneStaleProviderCredentialSecrets(secrets, params) {
|
|
137
|
+
const { values: stored } = await secrets.getSecretsByNamespace({
|
|
120
138
|
workspaceId: params.workspaceId,
|
|
121
139
|
namespace: params.namespace
|
|
122
140
|
});
|
|
123
141
|
const expected = new Set(params.expectedKeys);
|
|
124
142
|
const staleKeys = Object.keys(stored).filter((key)=>!expected.has(key));
|
|
125
143
|
if (staleKeys.length === 0) return;
|
|
126
|
-
await deleteSecrets({
|
|
144
|
+
await secrets.deleteSecrets({
|
|
127
145
|
workspaceId: params.workspaceId,
|
|
128
146
|
namespace: params.namespace,
|
|
129
147
|
keys: staleKeys
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/model-provider-config-service.ts"],"sourcesContent":["import {\n DEFAULT_AGENT_THINKING,\n getModelProviderEntry,\n type ModelProviderRef,\n modelProviderCredentialKeysMatch,\n type SupportedModelProviderId,\n} from '@shipfox/api-agent-dto';\nimport {deleteSecrets, getSecretsByNamespace, setSecrets} from '@shipfox/api-secrets';\nimport {\n deleteModelProviderConfig as deleteModelProviderConfigRow,\n getModelProviderConfig,\n updateModelProviderDefaultModel,\n upsertModelProviderConfig,\n} from '#db/index.js';\nimport {agentSystemNamespace, credentialsToStoreValues} from './credential-fingerprints.js';\nimport type {ModelProviderConfig} from './entities/model-provider-config.js';\nimport {\n InvalidAgentModelError,\n InvalidCredentialFieldsError,\n ModelProviderConfigNotFoundError,\n UnsupportedModelProviderError,\n} from './errors.js';\nimport {buildModelProviderCatalog} from './model-provider-catalog.js';\nimport {probeModelProviderCredentials, runProviderProbe} from './model-provider-validation.js';\n\nexport interface TestAndSaveModelProviderConfigParams {\n workspaceId: string;\n providerId: SupportedModelProviderId;\n defaultModel?: string | null | undefined;\n credentials: Record<string, string>;\n editedBy?: string | null | undefined;\n setAsDefault?: boolean | undefined;\n signal?: AbortSignal | undefined;\n}\n\nexport interface TestAndSaveModelProviderConfigOptions {\n probe?: typeof probeModelProviderCredentials;\n pruneStaleSecrets?:\n | ((params: {workspaceId: string; namespace: string; expectedKeys: string[]}) => Promise<void>)\n | undefined;\n}\n\nexport interface UpdateModelProviderConfigDefaultModelParams {\n workspaceId: string;\n providerId: ModelProviderRef;\n defaultModel: string | null;\n}\n\nexport async function testAndSaveModelProviderConfig(\n params: TestAndSaveModelProviderConfigParams,\n options: TestAndSaveModelProviderConfigOptions = {},\n): Promise<ModelProviderConfig> {\n const probe = options.probe ?? probeModelProviderCredentials;\n const entry = getModelProviderEntry(params.providerId);\n if (entry === undefined || entry.support_status !== 'supported') {\n throw new UnsupportedModelProviderError(params.providerId);\n }\n if (entry.default_model === null) throw new UnsupportedModelProviderError(params.providerId);\n\n if (!modelProviderCredentialKeysMatch(params.providerId, params.credentials)) {\n throw new InvalidCredentialFieldsError(params.providerId);\n }\n\n const existingConfig = await getModelProviderConfig({\n workspaceId: params.workspaceId,\n providerId: params.providerId,\n });\n const modelSelection = resolveDefaultModel(\n params.providerId,\n params.defaultModel !== undefined ? params.defaultModel : existingConfig?.defaultModel,\n );\n\n await runProviderProbe({\n probe,\n args: {\n providerId: params.providerId,\n model: modelSelection.probeModel,\n credentials: params.credentials,\n ...(params.signal ? {signal: params.signal} : {}),\n },\n metricLabel: params.providerId,\n providerId: params.providerId,\n secrets: Object.values(params.credentials),\n signal: params.signal,\n });\n const pruneStaleSecrets = options.pruneStaleSecrets ?? pruneStaleProviderCredentialSecrets;\n const namespace = agentSystemNamespace(params.providerId);\n const values = credentialsToStoreValues(params.providerId, params.credentials);\n await setSecrets({\n workspaceId: params.workspaceId,\n namespace,\n values,\n editedBy: params.editedBy,\n });\n\n const config = await upsertModelProviderConfig({\n workspaceId: params.workspaceId,\n providerId: params.providerId,\n defaultModel: modelSelection.storedModel,\n defaultThinking: DEFAULT_AGENT_THINKING,\n setAsDefault: params.setAsDefault,\n });\n\n await pruneStaleSecrets({\n workspaceId: params.workspaceId,\n namespace,\n expectedKeys: Object.keys(values),\n }).catch(() => undefined);\n\n return config;\n}\n\nexport async function updateModelProviderConfigDefaultModel(\n params: UpdateModelProviderConfigDefaultModelParams,\n): Promise<ModelProviderConfig> {\n const existingConfig = await getModelProviderConfig({\n workspaceId: params.workspaceId,\n providerId: params.providerId,\n });\n if (!existingConfig) {\n throw new ModelProviderConfigNotFoundError(params.workspaceId, params.providerId);\n }\n if (existingConfig.kind === 'custom') {\n if (\n params.defaultModel !== null &&\n !existingConfig.models?.some((model) => model.id === params.defaultModel)\n ) {\n throw new InvalidAgentModelError('pi', params.providerId, params.defaultModel);\n }\n\n const config = await updateModelProviderDefaultModel({\n workspaceId: params.workspaceId,\n providerId: params.providerId,\n defaultModel: params.defaultModel,\n });\n if (!config) throw new ModelProviderConfigNotFoundError(params.workspaceId, params.providerId);\n return config;\n }\n\n const providerId = params.providerId as SupportedModelProviderId;\n const entry = getModelProviderEntry(providerId);\n if (entry === undefined || entry.support_status !== 'supported') {\n throw new UnsupportedModelProviderError(params.providerId);\n }\n if (entry.default_model === null) throw new UnsupportedModelProviderError(params.providerId);\n\n const modelSelection = resolveDefaultModel(providerId, params.defaultModel);\n const config = await updateModelProviderDefaultModel({\n workspaceId: params.workspaceId,\n providerId: params.providerId,\n defaultModel: modelSelection.storedModel,\n });\n if (!config) throw new ModelProviderConfigNotFoundError(params.workspaceId, params.providerId);\n return config;\n}\n\nexport async function deleteModelProviderConfig(params: {\n workspaceId: string;\n providerId: ModelProviderRef;\n}): Promise<boolean> {\n const deleted = await deleteModelProviderConfigRow(params);\n await deleteSecrets({\n workspaceId: params.workspaceId,\n namespace: agentSystemNamespace(params.providerId),\n });\n return deleted;\n}\n\nfunction resolveDefaultModel(\n providerId: SupportedModelProviderId,\n requestedModel: string | null | undefined,\n): {probeModel: string; storedModel: string | null} {\n const catalogEntry = buildModelProviderCatalog().find((entry) => entry.id === providerId);\n if (\n catalogEntry === undefined ||\n catalogEntry.support_status !== 'supported' ||\n catalogEntry.default_model === null\n ) {\n throw new UnsupportedModelProviderError(providerId);\n }\n\n const model = requestedModel ?? catalogEntry.default_model;\n if (!catalogEntry.models.some((candidate) => candidate.id === model)) {\n throw new InvalidAgentModelError('pi', providerId, model);\n }\n return {probeModel: model, storedModel: requestedModel ?? null};\n}\n\nasync function pruneStaleProviderCredentialSecrets(params: {\n workspaceId: string;\n namespace: string;\n expectedKeys: string[];\n}): Promise<void> {\n const stored = await getSecretsByNamespace({\n workspaceId: params.workspaceId,\n namespace: params.namespace,\n });\n const expected = new Set(params.expectedKeys);\n const staleKeys = Object.keys(stored).filter((key) => !expected.has(key));\n if (staleKeys.length === 0) return;\n\n await deleteSecrets({\n workspaceId: params.workspaceId,\n namespace: params.namespace,\n keys: staleKeys,\n });\n}\n"],"names":["DEFAULT_AGENT_THINKING","getModelProviderEntry","modelProviderCredentialKeysMatch","deleteSecrets","getSecretsByNamespace","setSecrets","deleteModelProviderConfig","deleteModelProviderConfigRow","getModelProviderConfig","updateModelProviderDefaultModel","upsertModelProviderConfig","agentSystemNamespace","credentialsToStoreValues","InvalidAgentModelError","InvalidCredentialFieldsError","ModelProviderConfigNotFoundError","UnsupportedModelProviderError","buildModelProviderCatalog","probeModelProviderCredentials","runProviderProbe","testAndSaveModelProviderConfig","params","options","probe","entry","providerId","undefined","support_status","default_model","credentials","existingConfig","workspaceId","modelSelection","resolveDefaultModel","defaultModel","args","model","probeModel","signal","metricLabel","secrets","Object","values","pruneStaleSecrets","pruneStaleProviderCredentialSecrets","namespace","editedBy","config","storedModel","defaultThinking","setAsDefault","expectedKeys","keys","catch","updateModelProviderConfigDefaultModel","kind","models","some","id","deleted","requestedModel","catalogEntry","find","candidate","stored","expected","Set","staleKeys","filter","key","has","length"],"mappings":"AAAA,SACEA,sBAAsB,EACtBC,qBAAqB,EAErBC,gCAAgC,QAE3B,yBAAyB;AAChC,SAAQC,aAAa,EAAEC,qBAAqB,EAAEC,UAAU,QAAO,uBAAuB;AACtF,SACEC,6BAA6BC,4BAA4B,EACzDC,sBAAsB,EACtBC,+BAA+B,EAC/BC,yBAAyB,QACpB,eAAe;AACtB,SAAQC,oBAAoB,EAAEC,wBAAwB,QAAO,+BAA+B;AAE5F,SACEC,sBAAsB,EACtBC,4BAA4B,EAC5BC,gCAAgC,EAChCC,6BAA6B,QACxB,cAAc;AACrB,SAAQC,yBAAyB,QAAO,8BAA8B;AACtE,SAAQC,6BAA6B,EAAEC,gBAAgB,QAAO,iCAAiC;AAyB/F,OAAO,eAAeC,+BACpBC,MAA4C,EAC5CC,UAAiD,CAAC,CAAC;IAEnD,MAAMC,QAAQD,QAAQC,KAAK,IAAIL;IAC/B,MAAMM,QAAQvB,sBAAsBoB,OAAOI,UAAU;IACrD,IAAID,UAAUE,aAAaF,MAAMG,cAAc,KAAK,aAAa;QAC/D,MAAM,IAAIX,8BAA8BK,OAAOI,UAAU;IAC3D;IACA,IAAID,MAAMI,aAAa,KAAK,MAAM,MAAM,IAAIZ,8BAA8BK,OAAOI,UAAU;IAE3F,IAAI,CAACvB,iCAAiCmB,OAAOI,UAAU,EAAEJ,OAAOQ,WAAW,GAAG;QAC5E,MAAM,IAAIf,6BAA6BO,OAAOI,UAAU;IAC1D;IAEA,MAAMK,iBAAiB,MAAMtB,uBAAuB;QAClDuB,aAAaV,OAAOU,WAAW;QAC/BN,YAAYJ,OAAOI,UAAU;IAC/B;IACA,MAAMO,iBAAiBC,oBACrBZ,OAAOI,UAAU,EACjBJ,OAAOa,YAAY,KAAKR,YAAYL,OAAOa,YAAY,GAAGJ,gBAAgBI;IAG5E,MAAMf,iBAAiB;QACrBI;QACAY,MAAM;YACJV,YAAYJ,OAAOI,UAAU;YAC7BW,OAAOJ,eAAeK,UAAU;YAChCR,aAAaR,OAAOQ,WAAW;YAC/B,GAAIR,OAAOiB,MAAM,GAAG;gBAACA,QAAQjB,OAAOiB,MAAM;YAAA,IAAI,CAAC,CAAC;QAClD;QACAC,aAAalB,OAAOI,UAAU;QAC9BA,YAAYJ,OAAOI,UAAU;QAC7Be,SAASC,OAAOC,MAAM,CAACrB,OAAOQ,WAAW;QACzCS,QAAQjB,OAAOiB,MAAM;IACvB;IACA,MAAMK,oBAAoBrB,QAAQqB,iBAAiB,IAAIC;IACvD,MAAMC,YAAYlC,qBAAqBU,OAAOI,UAAU;IACxD,MAAMiB,SAAS9B,yBAAyBS,OAAOI,UAAU,EAAEJ,OAAOQ,WAAW;IAC7E,MAAMxB,WAAW;QACf0B,aAAaV,OAAOU,WAAW;QAC/Bc;QACAH;QACAI,UAAUzB,OAAOyB,QAAQ;IAC3B;IAEA,MAAMC,SAAS,MAAMrC,0BAA0B;QAC7CqB,aAAaV,OAAOU,WAAW;QAC/BN,YAAYJ,OAAOI,UAAU;QAC7BS,cAAcF,eAAegB,WAAW;QACxCC,iBAAiBjD;QACjBkD,cAAc7B,OAAO6B,YAAY;IACnC;IAEA,MAAMP,kBAAkB;QACtBZ,aAAaV,OAAOU,WAAW;QAC/Bc;QACAM,cAAcV,OAAOW,IAAI,CAACV;IAC5B,GAAGW,KAAK,CAAC,IAAM3B;IAEf,OAAOqB;AACT;AAEA,OAAO,eAAeO,sCACpBjC,MAAmD;IAEnD,MAAMS,iBAAiB,MAAMtB,uBAAuB;QAClDuB,aAAaV,OAAOU,WAAW;QAC/BN,YAAYJ,OAAOI,UAAU;IAC/B;IACA,IAAI,CAACK,gBAAgB;QACnB,MAAM,IAAIf,iCAAiCM,OAAOU,WAAW,EAAEV,OAAOI,UAAU;IAClF;IACA,IAAIK,eAAeyB,IAAI,KAAK,UAAU;QACpC,IACElC,OAAOa,YAAY,KAAK,QACxB,CAACJ,eAAe0B,MAAM,EAAEC,KAAK,CAACrB,QAAUA,MAAMsB,EAAE,KAAKrC,OAAOa,YAAY,GACxE;YACA,MAAM,IAAIrB,uBAAuB,MAAMQ,OAAOI,UAAU,EAAEJ,OAAOa,YAAY;QAC/E;QAEA,MAAMa,SAAS,MAAMtC,gCAAgC;YACnDsB,aAAaV,OAAOU,WAAW;YAC/BN,YAAYJ,OAAOI,UAAU;YAC7BS,cAAcb,OAAOa,YAAY;QACnC;QACA,IAAI,CAACa,QAAQ,MAAM,IAAIhC,iCAAiCM,OAAOU,WAAW,EAAEV,OAAOI,UAAU;QAC7F,OAAOsB;IACT;IAEA,MAAMtB,aAAaJ,OAAOI,UAAU;IACpC,MAAMD,QAAQvB,sBAAsBwB;IACpC,IAAID,UAAUE,aAAaF,MAAMG,cAAc,KAAK,aAAa;QAC/D,MAAM,IAAIX,8BAA8BK,OAAOI,UAAU;IAC3D;IACA,IAAID,MAAMI,aAAa,KAAK,MAAM,MAAM,IAAIZ,8BAA8BK,OAAOI,UAAU;IAE3F,MAAMO,iBAAiBC,oBAAoBR,YAAYJ,OAAOa,YAAY;IAC1E,MAAMa,SAAS,MAAMtC,gCAAgC;QACnDsB,aAAaV,OAAOU,WAAW;QAC/BN,YAAYJ,OAAOI,UAAU;QAC7BS,cAAcF,eAAegB,WAAW;IAC1C;IACA,IAAI,CAACD,QAAQ,MAAM,IAAIhC,iCAAiCM,OAAOU,WAAW,EAAEV,OAAOI,UAAU;IAC7F,OAAOsB;AACT;AAEA,OAAO,eAAezC,0BAA0Be,MAG/C;IACC,MAAMsC,UAAU,MAAMpD,6BAA6Bc;IACnD,MAAMlB,cAAc;QAClB4B,aAAaV,OAAOU,WAAW;QAC/Bc,WAAWlC,qBAAqBU,OAAOI,UAAU;IACnD;IACA,OAAOkC;AACT;AAEA,SAAS1B,oBACPR,UAAoC,EACpCmC,cAAyC;IAEzC,MAAMC,eAAe5C,4BAA4B6C,IAAI,CAAC,CAACtC,QAAUA,MAAMkC,EAAE,KAAKjC;IAC9E,IACEoC,iBAAiBnC,aACjBmC,aAAalC,cAAc,KAAK,eAChCkC,aAAajC,aAAa,KAAK,MAC/B;QACA,MAAM,IAAIZ,8BAA8BS;IAC1C;IAEA,MAAMW,QAAQwB,kBAAkBC,aAAajC,aAAa;IAC1D,IAAI,CAACiC,aAAaL,MAAM,CAACC,IAAI,CAAC,CAACM,YAAcA,UAAUL,EAAE,KAAKtB,QAAQ;QACpE,MAAM,IAAIvB,uBAAuB,MAAMY,YAAYW;IACrD;IACA,OAAO;QAACC,YAAYD;QAAOY,aAAaY,kBAAkB;IAAI;AAChE;AAEA,eAAehB,oCAAoCvB,MAIlD;IACC,MAAM2C,SAAS,MAAM5D,sBAAsB;QACzC2B,aAAaV,OAAOU,WAAW;QAC/Bc,WAAWxB,OAAOwB,SAAS;IAC7B;IACA,MAAMoB,WAAW,IAAIC,IAAI7C,OAAO8B,YAAY;IAC5C,MAAMgB,YAAY1B,OAAOW,IAAI,CAACY,QAAQI,MAAM,CAAC,CAACC,MAAQ,CAACJ,SAASK,GAAG,CAACD;IACpE,IAAIF,UAAUI,MAAM,KAAK,GAAG;IAE5B,MAAMpE,cAAc;QAClB4B,aAAaV,OAAOU,WAAW;QAC/Bc,WAAWxB,OAAOwB,SAAS;QAC3BO,MAAMe;IACR;AACF"}
|
|
1
|
+
{"version":3,"sources":["../../src/core/model-provider-config-service.ts"],"sourcesContent":["import {\n DEFAULT_AGENT_THINKING,\n getModelProviderEntry,\n type ModelProviderRef,\n modelProviderCredentialKeysMatch,\n type SupportedModelProviderId,\n} from '@shipfox/api-agent-dto';\nimport {reportError} from '@shipfox/node-error-monitoring';\nimport {logger} from '@shipfox/node-opentelemetry';\nimport {\n deleteModelProviderConfig as deleteModelProviderConfigRow,\n getModelProviderConfig,\n updateModelProviderDefaultModel,\n upsertModelProviderConfig,\n} from '#db/index.js';\nimport {agentSystemNamespace, credentialsToStoreValues} from './credential-fingerprints.js';\nimport type {ModelProviderConfig} from './entities/model-provider-config.js';\nimport {\n InvalidAgentModelError,\n InvalidCredentialFieldsError,\n ModelProviderConfigNotFoundError,\n UnsupportedModelProviderError,\n} from './errors.js';\nimport {buildModelProviderCatalog} from './model-provider-catalog.js';\nimport {probeModelProviderCredentials, runProviderProbe} from './model-provider-validation.js';\nimport {type AgentSecretsClient, requireAgentSecretsClient} from './secrets-client.js';\n\nexport interface TestAndSaveModelProviderConfigParams {\n workspaceId: string;\n providerId: SupportedModelProviderId;\n defaultModel?: string | null | undefined;\n credentials: Record<string, string>;\n editedBy?: string | null | undefined;\n setAsDefault?: boolean | undefined;\n signal?: AbortSignal | undefined;\n}\n\nexport interface TestAndSaveModelProviderConfigOptions {\n probe?: typeof probeModelProviderCredentials;\n secrets?: AgentSecretsClient | undefined;\n pruneStaleSecrets?:\n | ((params: {workspaceId: string; namespace: string; expectedKeys: string[]}) => Promise<void>)\n | undefined;\n}\n\nexport interface UpdateModelProviderConfigDefaultModelParams {\n workspaceId: string;\n providerId: ModelProviderRef;\n defaultModel: string | null;\n}\n\nexport async function testAndSaveModelProviderConfig(\n params: TestAndSaveModelProviderConfigParams,\n options: TestAndSaveModelProviderConfigOptions = {},\n): Promise<ModelProviderConfig> {\n const probe = options.probe ?? probeModelProviderCredentials;\n const secrets = requireAgentSecretsClient(options.secrets);\n const entry = getModelProviderEntry(params.providerId);\n if (entry === undefined || entry.support_status !== 'supported') {\n throw new UnsupportedModelProviderError(params.providerId);\n }\n if (entry.default_model === null) throw new UnsupportedModelProviderError(params.providerId);\n\n if (!modelProviderCredentialKeysMatch(params.providerId, params.credentials)) {\n throw new InvalidCredentialFieldsError(params.providerId);\n }\n\n const existingConfig = await getModelProviderConfig({\n workspaceId: params.workspaceId,\n providerId: params.providerId,\n });\n const modelSelection = resolveDefaultModel(\n params.providerId,\n params.defaultModel !== undefined ? params.defaultModel : existingConfig?.defaultModel,\n );\n\n await runProviderProbe({\n probe,\n args: {\n providerId: params.providerId,\n model: modelSelection.probeModel,\n credentials: params.credentials,\n ...(params.signal ? {signal: params.signal} : {}),\n },\n metricLabel: params.providerId,\n providerId: params.providerId,\n secrets: Object.values(params.credentials),\n signal: params.signal,\n });\n const pruneStaleSecrets =\n options.pruneStaleSecrets ?? ((input) => pruneStaleProviderCredentialSecrets(secrets, input));\n const namespace = agentSystemNamespace(params.providerId);\n const values = credentialsToStoreValues(params.providerId, params.credentials);\n await secrets.setSecrets({\n workspaceId: params.workspaceId,\n namespace,\n values,\n editedBy: params.editedBy,\n });\n\n const config = await upsertModelProviderConfig({\n workspaceId: params.workspaceId,\n providerId: params.providerId,\n defaultModel: modelSelection.storedModel,\n defaultThinking: DEFAULT_AGENT_THINKING,\n setAsDefault: params.setAsDefault,\n });\n\n await pruneStaleSecrets({\n workspaceId: params.workspaceId,\n namespace,\n expectedKeys: Object.keys(values),\n }).catch((error) => {\n logger().error(\n {err: error, workspaceId: params.workspaceId, providerId: params.providerId},\n 'Failed to prune stale model provider secrets',\n );\n reportError(error, {\n boundary: 'agent.cleanup',\n operation: 'prune-stale-secrets',\n extra: {workspaceId: params.workspaceId, providerId: params.providerId},\n });\n });\n\n return config;\n}\n\nexport async function updateModelProviderConfigDefaultModel(\n params: UpdateModelProviderConfigDefaultModelParams,\n): Promise<ModelProviderConfig> {\n const existingConfig = await getModelProviderConfig({\n workspaceId: params.workspaceId,\n providerId: params.providerId,\n });\n if (!existingConfig) {\n throw new ModelProviderConfigNotFoundError(params.workspaceId, params.providerId);\n }\n if (existingConfig.kind === 'custom') {\n if (\n params.defaultModel !== null &&\n !existingConfig.models?.some((model) => model.id === params.defaultModel)\n ) {\n throw new InvalidAgentModelError('pi', params.providerId, params.defaultModel);\n }\n\n const config = await updateModelProviderDefaultModel({\n workspaceId: params.workspaceId,\n providerId: params.providerId,\n defaultModel: params.defaultModel,\n });\n if (!config) throw new ModelProviderConfigNotFoundError(params.workspaceId, params.providerId);\n return config;\n }\n\n const providerId = params.providerId as SupportedModelProviderId;\n const entry = getModelProviderEntry(providerId);\n if (entry === undefined || entry.support_status !== 'supported') {\n throw new UnsupportedModelProviderError(params.providerId);\n }\n if (entry.default_model === null) throw new UnsupportedModelProviderError(params.providerId);\n\n const modelSelection = resolveDefaultModel(providerId, params.defaultModel);\n const config = await updateModelProviderDefaultModel({\n workspaceId: params.workspaceId,\n providerId: params.providerId,\n defaultModel: modelSelection.storedModel,\n });\n if (!config) throw new ModelProviderConfigNotFoundError(params.workspaceId, params.providerId);\n return config;\n}\n\nexport async function deleteModelProviderConfig(\n params: {workspaceId: string; providerId: ModelProviderRef},\n options: {secrets?: AgentSecretsClient | undefined} = {},\n): Promise<boolean> {\n const secrets = requireAgentSecretsClient(options.secrets);\n const deleted = await deleteModelProviderConfigRow(params);\n await secrets.deleteSecrets({\n workspaceId: params.workspaceId,\n namespace: agentSystemNamespace(params.providerId),\n });\n return deleted;\n}\n\nfunction resolveDefaultModel(\n providerId: SupportedModelProviderId,\n requestedModel: string | null | undefined,\n): {probeModel: string; storedModel: string | null} {\n const catalogEntry = buildModelProviderCatalog().find((entry) => entry.id === providerId);\n if (\n catalogEntry === undefined ||\n catalogEntry.support_status !== 'supported' ||\n catalogEntry.default_model === null\n ) {\n throw new UnsupportedModelProviderError(providerId);\n }\n\n const model = requestedModel ?? catalogEntry.default_model;\n if (!catalogEntry.models.some((candidate) => candidate.id === model)) {\n throw new InvalidAgentModelError('pi', providerId, model);\n }\n return {probeModel: model, storedModel: requestedModel ?? null};\n}\n\nasync function pruneStaleProviderCredentialSecrets(\n secrets: AgentSecretsClient,\n params: {workspaceId: string; namespace: string; expectedKeys: string[]},\n): Promise<void> {\n const {values: stored} = await secrets.getSecretsByNamespace({\n workspaceId: params.workspaceId,\n namespace: params.namespace,\n });\n const expected = new Set(params.expectedKeys);\n const staleKeys = Object.keys(stored).filter((key) => !expected.has(key));\n if (staleKeys.length === 0) return;\n\n await secrets.deleteSecrets({\n workspaceId: params.workspaceId,\n namespace: params.namespace,\n keys: staleKeys,\n });\n}\n"],"names":["DEFAULT_AGENT_THINKING","getModelProviderEntry","modelProviderCredentialKeysMatch","reportError","logger","deleteModelProviderConfig","deleteModelProviderConfigRow","getModelProviderConfig","updateModelProviderDefaultModel","upsertModelProviderConfig","agentSystemNamespace","credentialsToStoreValues","InvalidAgentModelError","InvalidCredentialFieldsError","ModelProviderConfigNotFoundError","UnsupportedModelProviderError","buildModelProviderCatalog","probeModelProviderCredentials","runProviderProbe","requireAgentSecretsClient","testAndSaveModelProviderConfig","params","options","probe","secrets","entry","providerId","undefined","support_status","default_model","credentials","existingConfig","workspaceId","modelSelection","resolveDefaultModel","defaultModel","args","model","probeModel","signal","metricLabel","Object","values","pruneStaleSecrets","input","pruneStaleProviderCredentialSecrets","namespace","setSecrets","editedBy","config","storedModel","defaultThinking","setAsDefault","expectedKeys","keys","catch","error","err","boundary","operation","extra","updateModelProviderConfigDefaultModel","kind","models","some","id","deleted","deleteSecrets","requestedModel","catalogEntry","find","candidate","stored","getSecretsByNamespace","expected","Set","staleKeys","filter","key","has","length"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type AgentRuntimeCredentialsResponseDto, type AgentThinking, type Harness, type ModelProviderRef, type SupportedModelProviderId } from '@shipfox/api-agent-dto';
|
|
2
|
-
import {
|
|
2
|
+
import { type AgentSecretsClient } from './secrets-client.js';
|
|
3
3
|
export interface ResolveRuntimeCredentialsParams {
|
|
4
4
|
workspaceId: string;
|
|
5
5
|
harness: Harness;
|
|
@@ -13,7 +13,11 @@ interface RuntimeCredentialsConfig {
|
|
|
13
13
|
}
|
|
14
14
|
interface ResolveRuntimeCredentialsOptions {
|
|
15
15
|
runtimeConfig?: RuntimeCredentialsConfig | undefined;
|
|
16
|
-
|
|
16
|
+
secrets?: AgentSecretsClient | undefined;
|
|
17
|
+
getCredentialBag?: ((params: {
|
|
18
|
+
workspaceId: string;
|
|
19
|
+
namespace: string;
|
|
20
|
+
}) => Promise<Record<string, string>>) | undefined;
|
|
17
21
|
}
|
|
18
22
|
export declare function resolveRuntimeCredentials(params: ResolveRuntimeCredentialsParams, options?: ResolveRuntimeCredentialsOptions): Promise<AgentRuntimeCredentialsResponseDto>;
|
|
19
23
|
export declare function getInstanceDefaultModelProviderApiKeyField(providerId: ModelProviderRef): 'api_key' | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-runtime-credentials.d.ts","sourceRoot":"","sources":["../../src/core/resolve-runtime-credentials.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,kCAAkC,EACvC,KAAK,aAAa,EAElB,KAAK,OAAO,EACZ,KAAK,gBAAgB,EAErB,KAAK,wBAAwB,EAC9B,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"resolve-runtime-credentials.d.ts","sourceRoot":"","sources":["../../src/core/resolve-runtime-credentials.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,kCAAkC,EACvC,KAAK,aAAa,EAElB,KAAK,OAAO,EACZ,KAAK,gBAAgB,EAErB,KAAK,wBAAwB,EAC9B,MAAM,wBAAwB,CAAC;AAahC,OAAO,EAAC,KAAK,kBAAkB,EAA4B,MAAM,qBAAqB,CAAC;AAEvF,MAAM,WAAW,+BAA+B;IAC9C,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,aAAa,CAAC;CACzB;AAED,UAAU,wBAAwB;IAChC,sBAAsB,CAAC,EAAE,wBAAwB,GAAG,SAAS,CAAC;IAC9D,8BAA8B,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACrD;AAED,UAAU,gCAAgC;IACxC,aAAa,CAAC,EAAE,wBAAwB,GAAG,SAAS,CAAC;IACrD,OAAO,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;IACzC,gBAAgB,CAAC,EACb,CAAC,CAAC,MAAM,EAAE;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAC,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,GACvF,SAAS,CAAC;CACf;AAED,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,+BAA+B,EACvC,OAAO,CAAC,EAAE,gCAAgC,GACzC,OAAO,CAAC,kCAAkC,CAAC,CA0D7C;AAED,wBAAgB,0CAA0C,CACxD,UAAU,EAAE,gBAAgB,GAC3B,SAAS,GAAG,SAAS,CAQvB"}
|