@shipfox/api-agent 5.0.0 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +30 -0
  3. package/dist/core/custom-model-provider-config-service.d.ts +4 -0
  4. package/dist/core/custom-model-provider-config-service.d.ts.map +1 -1
  5. package/dist/core/custom-model-provider-config-service.js +19 -16
  6. package/dist/core/custom-model-provider-config-service.js.map +1 -1
  7. package/dist/core/model-provider-config-service.d.ts +4 -0
  8. package/dist/core/model-provider-config-service.d.ts.map +1 -1
  9. package/dist/core/model-provider-config-service.js +10 -8
  10. package/dist/core/model-provider-config-service.js.map +1 -1
  11. package/dist/core/resolve-runtime-credentials.d.ts +6 -2
  12. package/dist/core/resolve-runtime-credentials.d.ts.map +1 -1
  13. package/dist/core/resolve-runtime-credentials.js +10 -5
  14. package/dist/core/resolve-runtime-credentials.js.map +1 -1
  15. package/dist/core/secrets-client.d.ts +4 -0
  16. package/dist/core/secrets-client.d.ts.map +1 -0
  17. package/dist/core/secrets-client.js +6 -0
  18. package/dist/core/secrets-client.js.map +1 -0
  19. package/dist/index.d.ts +4 -1
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +19 -13
  22. package/dist/index.js.map +1 -1
  23. package/dist/presentation/e2eRoutes/create-model-provider.d.ts +2 -1
  24. package/dist/presentation/e2eRoutes/create-model-provider.d.ts.map +1 -1
  25. package/dist/presentation/e2eRoutes/create-model-provider.js +46 -45
  26. package/dist/presentation/e2eRoutes/create-model-provider.js.map +1 -1
  27. package/dist/presentation/e2eRoutes/index.d.ts +2 -0
  28. package/dist/presentation/e2eRoutes/index.d.ts.map +1 -1
  29. package/dist/presentation/e2eRoutes/index.js +9 -6
  30. package/dist/presentation/e2eRoutes/index.js.map +1 -1
  31. package/dist/presentation/index.d.ts +1 -1
  32. package/dist/presentation/index.d.ts.map +1 -1
  33. package/dist/presentation/index.js +1 -1
  34. package/dist/presentation/index.js.map +1 -1
  35. package/dist/presentation/inter-module.d.ts +7 -0
  36. package/dist/presentation/inter-module.d.ts.map +1 -0
  37. package/dist/presentation/inter-module.js +45 -0
  38. package/dist/presentation/inter-module.js.map +1 -0
  39. package/dist/presentation/routes/create-custom-model-provider.d.ts +2 -1
  40. package/dist/presentation/routes/create-custom-model-provider.d.ts.map +1 -1
  41. package/dist/presentation/routes/create-custom-model-provider.js +39 -35
  42. package/dist/presentation/routes/create-custom-model-provider.js.map +1 -1
  43. package/dist/presentation/routes/delete-model-provider-config.d.ts +2 -1
  44. package/dist/presentation/routes/delete-model-provider-config.d.ts.map +1 -1
  45. package/dist/presentation/routes/delete-model-provider-config.js +33 -29
  46. package/dist/presentation/routes/delete-model-provider-config.js.map +1 -1
  47. package/dist/presentation/routes/discover-custom-model-provider-models-by-slug.d.ts +2 -1
  48. package/dist/presentation/routes/discover-custom-model-provider-models-by-slug.d.ts.map +1 -1
  49. package/dist/presentation/routes/discover-custom-model-provider-models-by-slug.js +32 -28
  50. package/dist/presentation/routes/discover-custom-model-provider-models-by-slug.js.map +1 -1
  51. package/dist/presentation/routes/errors.d.ts.map +1 -1
  52. package/dist/presentation/routes/errors.js +13 -12
  53. package/dist/presentation/routes/errors.js.map +1 -1
  54. package/dist/presentation/routes/index.d.ts +2 -0
  55. package/dist/presentation/routes/index.d.ts.map +1 -1
  56. package/dist/presentation/routes/index.js +32 -29
  57. package/dist/presentation/routes/index.js.map +1 -1
  58. package/dist/presentation/routes/update-custom-model-provider.d.ts +2 -1
  59. package/dist/presentation/routes/update-custom-model-provider.d.ts.map +1 -1
  60. package/dist/presentation/routes/update-custom-model-provider.js +41 -37
  61. package/dist/presentation/routes/update-custom-model-provider.js.map +1 -1
  62. package/dist/presentation/routes/upsert-model-provider-config.d.ts +2 -1
  63. package/dist/presentation/routes/upsert-model-provider-config.d.ts.map +1 -1
  64. package/dist/presentation/routes/upsert-model-provider-config.js +46 -42
  65. package/dist/presentation/routes/upsert-model-provider-config.js.map +1 -1
  66. package/dist/tsconfig.test.tsbuildinfo +1 -1
  67. package/package.json +11 -8
  68. package/src/core/custom-model-provider-config-service.ts +50 -34
  69. package/src/core/model-provider-config-service.test.ts +1 -3
  70. package/src/core/model-provider-config-service.ts +18 -15
  71. package/src/core/resolve-runtime-credentials.test.ts +3 -3
  72. package/src/core/resolve-runtime-credentials.ts +22 -8
  73. package/src/core/secrets-client.ts +13 -0
  74. package/src/index.ts +13 -8
  75. package/src/presentation/e2eRoutes/create-model-provider.ts +41 -39
  76. package/src/presentation/e2eRoutes/index.ts +6 -4
  77. package/src/presentation/index.ts +1 -1
  78. package/src/presentation/inter-module.ts +78 -0
  79. package/src/presentation/routes/create-custom-model-provider.ts +36 -30
  80. package/src/presentation/routes/delete-model-provider-config.ts +25 -22
  81. package/src/presentation/routes/discover-custom-model-provider-models-by-slug.ts +31 -25
  82. package/src/presentation/routes/errors.ts +11 -11
  83. package/src/presentation/routes/index.ts +32 -27
  84. package/src/presentation/routes/model-provider-config.test.ts +1 -1
  85. package/src/presentation/routes/update-custom-model-provider.ts +40 -34
  86. package/src/presentation/routes/upsert-model-provider-config.ts +43 -37
  87. package/test/fixtures/secrets-client.ts +80 -0
  88. package/test/globalSetup.ts +0 -9
  89. package/test/setup.ts +8 -0
  90. package/tsconfig.build.tsbuildinfo +1 -1
@@ -1,2 +1,2 @@
1
1
  $ shipfox-swc
2
- Successfully compiled: 48 files with swc (101.45ms)
2
+ Successfully compiled: 50 files with swc (536.61ms)
package/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # @shipfox/api-agent
2
2
 
3
+ ## 6.0.0
4
+
5
+ ### Minor Changes
6
+
7
+ - a42b575: Exposes Secrets through its inter-module contract and migrates Agent, integrations, and Workflows consumers.
8
+
9
+ ### Patch Changes
10
+
11
+ - 0bb82a4: Adds the Agent and Integrations inter-module APIs, moving Workflows agent configuration, runtime credential resolution, and integration consumers behind producer-owned clients.
12
+ - f73da5d: Enforces bounded API context imports and routes inter-module consumers through producer contracts.
13
+ - Updated dependencies [0bb82a4]
14
+ - Updated dependencies [54ce48b]
15
+ - Updated dependencies [c0162b0]
16
+ - Updated dependencies [7ac43a4]
17
+ - Updated dependencies [a01e917]
18
+ - Updated dependencies [a42b575]
19
+ - Updated dependencies [8bdc149]
20
+ - Updated dependencies [3810996]
21
+ - Updated dependencies [b00ed29]
22
+ - Updated dependencies [8aa7cd3]
23
+ - Updated dependencies [81f9544]
24
+ - @shipfox/api-agent-dto@6.0.0
25
+ - @shipfox/node-module@0.4.0
26
+ - @shipfox/node-drizzle@0.3.2
27
+ - @shipfox/redact@0.2.3
28
+ - @shipfox/api-secrets-dto@6.0.0
29
+ - @shipfox/api-auth-context@6.0.0
30
+ - @shipfox/node-fastify@0.2.4
31
+ - @shipfox/inter-module@0.2.0
32
+
3
33
  ## 5.0.0
4
34
 
5
35
  ### 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;AAgBhC,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,qCAAqC,CAAC;AAQ7E,OAAO,EAEL,mCAAmC,EAEpC,MAAM,gCAAgC,CAAC;AAExC,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;CAChE;AASD,wBAAsB,+BAA+B,CACnD,MAAM,EAAE,qCAAqC,EAC7C,OAAO,GAAE,uCAA4C,GACpD,OAAO,CAAC,mBAAmB,CAAC,CAyE9B;AAED,wBAAsB,+BAA+B,CACnD,MAAM,EAAE,qCAAqC,EAC7C,OAAO,GAAE,uCAA4C,GACpD,OAAO,CAAC,mBAAmB,CAAC,CAoG9B;AAED,wBAAsB,yCAAyC,CAAC,MAAM,EAAE;IACtE,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,gBAAgB,CAAC;IAC7B,IAAI,EAAE,8CAA8C,CAAC;CACtD,GAAG,OAAO,CAAC,wCAAwC,CAAC,CA2BpD"}
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;AAehC,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,CAqG9B;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,14 @@
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';
4
3
  import { deleteModelProviderConfig, getModelProviderConfig, insertCustomModelProviderConfig, upsertModelProviderConfig } from '#db/index.js';
5
4
  import { agentSystemNamespace, customCredentialsToStoreValues, customCredentialToStoreKey, storeValuesToCustomRuntimeCredentials } from './credential-fingerprints.js';
6
5
  import { normalizeCustomProviderBaseUrl } from './custom-provider-url.js';
7
6
  import { CustomModelProviderConfigNotFoundError, CustomModelProviderSlugCollisionError, CustomModelProviderStoredSecretBaseUrlChangeError, InvalidAgentModelError, InvalidCustomModelProviderHeaderKeepError } from './errors.js';
8
7
  import { egressPolicy, probeCustomModelProviderCredentials, runProviderProbe } from './model-provider-validation.js';
8
+ import { requireAgentSecretsClient } from './secrets-client.js';
9
9
  export async function createCustomModelProviderConfig(params, options = {}) {
10
10
  const probe = options.probe ?? probeCustomModelProviderCredentials;
11
+ const secrets = requireAgentSecretsClient(options.secrets);
11
12
  const existing = await getModelProviderConfig({
12
13
  workspaceId: params.workspaceId,
13
14
  providerId: params.body.slug
@@ -61,7 +62,7 @@ export async function createCustomModelProviderConfig(params, options = {}) {
61
62
  throw new CustomModelProviderSlugCollisionError(params.workspaceId, params.body.slug);
62
63
  }
63
64
  try {
64
- await setSecrets({
65
+ await secrets.setSecrets({
65
66
  workspaceId: params.workspaceId,
66
67
  namespace: agentSystemNamespace(params.body.slug),
67
68
  values: customCredentialsToStoreValues(secretCredentials)
@@ -72,7 +73,7 @@ export async function createCustomModelProviderConfig(params, options = {}) {
72
73
  workspaceId: params.workspaceId,
73
74
  providerId: params.body.slug
74
75
  });
75
- await deleteSecrets({
76
+ await secrets.deleteSecrets({
76
77
  workspaceId: params.workspaceId,
77
78
  namespace: agentSystemNamespace(params.body.slug)
78
79
  });
@@ -81,8 +82,9 @@ export async function createCustomModelProviderConfig(params, options = {}) {
81
82
  }
82
83
  export async function updateCustomModelProviderConfig(params, options = {}) {
83
84
  const probe = options.probe ?? probeCustomModelProviderCredentials;
85
+ const secrets = requireAgentSecretsClient(options.secrets);
84
86
  const existing = await getExistingCustomConfig(params.workspaceId, params.providerId);
85
- const existingSecrets = await getCustomProviderSecrets({
87
+ const existingSecrets = await getCustomProviderSecrets(secrets, {
86
88
  workspaceId: params.workspaceId,
87
89
  providerId: params.providerId
88
90
  });
@@ -136,7 +138,7 @@ export async function updateCustomModelProviderConfig(params, options = {}) {
136
138
  signal: params.signal
137
139
  });
138
140
  const namespace = agentSystemNamespace(params.providerId);
139
- await setSecrets({
141
+ await secrets.setSecrets({
140
142
  workspaceId: params.workspaceId,
141
143
  namespace,
142
144
  values: customCredentialsToStoreValues(newSecretCredentials)
@@ -158,7 +160,7 @@ export async function updateCustomModelProviderConfig(params, options = {}) {
158
160
  defaultThinking: existing.defaultThinking
159
161
  });
160
162
  } catch (error) {
161
- await rollbackCustomProviderSecretUpdate({
163
+ await rollbackCustomProviderSecretUpdate(secrets, {
162
164
  workspaceId: params.workspaceId,
163
165
  namespace,
164
166
  existingSecrets,
@@ -166,7 +168,7 @@ export async function updateCustomModelProviderConfig(params, options = {}) {
166
168
  }).catch(()=>undefined);
167
169
  throw error;
168
170
  }
169
- await pruneStaleCustomHeaderSecrets({
171
+ await pruneStaleCustomHeaderSecrets(secrets, {
170
172
  workspaceId: params.workspaceId,
171
173
  providerId: params.providerId,
172
174
  existingSecrets,
@@ -175,9 +177,10 @@ export async function updateCustomModelProviderConfig(params, options = {}) {
175
177
  });
176
178
  return updated;
177
179
  }
178
- export async function resolveCustomModelProviderDiscoveryParams(params) {
180
+ export async function resolveCustomModelProviderDiscoveryParams(params, options = {}) {
181
+ const secrets = requireAgentSecretsClient(options.secrets);
179
182
  const existing = await getExistingCustomConfig(params.workspaceId, params.providerId);
180
- const existingSecrets = await getCustomProviderSecrets({
183
+ const existingSecrets = await getCustomProviderSecrets(secrets, {
181
184
  workspaceId: params.workspaceId,
182
185
  providerId: params.providerId
183
186
  });
@@ -325,8 +328,8 @@ function selectProbeModel(models, defaultModel) {
325
328
  if (!model) throw new Error('Custom model provider must include at least one model.');
326
329
  return model;
327
330
  }
328
- async function getCustomProviderSecrets(params) {
329
- const values = await getSecretsByNamespace({
331
+ async function getCustomProviderSecrets(secrets, params) {
332
+ const { values } = await secrets.getSecretsByNamespace({
330
333
  workspaceId: params.workspaceId,
331
334
  namespace: agentSystemNamespace(params.providerId)
332
335
  });
@@ -345,7 +348,7 @@ function assertStoredSecretsNotReusedAfterBaseUrlChange(params) {
345
348
  function normalizedUrl(value) {
346
349
  return normalizeCustomProviderBaseUrl(value);
347
350
  }
348
- async function rollbackCustomProviderSecretUpdate(params) {
351
+ async function rollbackCustomProviderSecretUpdate(secrets, params) {
349
352
  const attemptedKeys = Object.keys(params.attemptedSecrets);
350
353
  if (attemptedKeys.length === 0) return;
351
354
  const secretsToRestore = Object.fromEntries(attemptedKeys.flatMap((key)=>{
@@ -358,7 +361,7 @@ async function rollbackCustomProviderSecretUpdate(params) {
358
361
  ];
359
362
  }));
360
363
  if (Object.keys(secretsToRestore).length > 0) {
361
- await setSecrets({
364
+ await secrets.setSecrets({
362
365
  workspaceId: params.workspaceId,
363
366
  namespace: params.namespace,
364
367
  values: customCredentialsToStoreValues(secretsToRestore)
@@ -366,18 +369,18 @@ async function rollbackCustomProviderSecretUpdate(params) {
366
369
  }
367
370
  const newKeys = attemptedKeys.filter((key)=>params.existingSecrets[key] === undefined);
368
371
  if (newKeys.length === 0) return;
369
- await deleteSecrets({
372
+ await secrets.deleteSecrets({
370
373
  workspaceId: params.workspaceId,
371
374
  namespace: params.namespace,
372
375
  keys: newKeys.map(customCredentialToStoreKey)
373
376
  });
374
377
  }
375
- async function pruneStaleCustomHeaderSecrets(params) {
378
+ async function pruneStaleCustomHeaderSecrets(secrets, params) {
376
379
  if (!params.replaceHeaders) return;
377
380
  const nextKeys = new Set(Object.keys(params.newSecrets));
378
381
  const staleKeys = Object.keys(params.existingSecrets).filter((key)=>key.startsWith('header:') && !nextKeys.has(key));
379
382
  if (staleKeys.length === 0) return;
380
- await deleteSecrets({
383
+ await secrets.deleteSecrets({
381
384
  workspaceId: params.workspaceId,
382
385
  namespace: agentSystemNamespace(params.providerId),
383
386
  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 {\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(() => undefined);\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","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","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;AAShC,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,qCAAqC,CAAC;AAQ7E,OAAO,EAAC,6BAA6B,EAAmB,MAAM,gCAAgC,CAAC;AAE/F,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,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,CA2D9B;AAED,wBAAsB,qCAAqC,CACzD,MAAM,EAAE,2CAA2C,GAClD,OAAO,CAAC,mBAAmB,CAAC,CAwC9B;AAED,wBAAsB,yBAAyB,CAAC,MAAM,EAAE;IACtD,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,gBAAgB,CAAC;CAC9B,GAAG,OAAO,CAAC,OAAO,CAAC,CAOnB"}
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;AAQhC,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,CA6D9B;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,13 @@
1
1
  import { DEFAULT_AGENT_THINKING, getModelProviderEntry, modelProviderCredentialKeysMatch } from '@shipfox/api-agent-dto';
2
- import { deleteSecrets, getSecretsByNamespace, setSecrets } from '@shipfox/api-secrets';
3
2
  import { deleteModelProviderConfig as deleteModelProviderConfigRow, getModelProviderConfig, updateModelProviderDefaultModel, upsertModelProviderConfig } from '#db/index.js';
4
3
  import { agentSystemNamespace, credentialsToStoreValues } from './credential-fingerprints.js';
5
4
  import { InvalidAgentModelError, InvalidCredentialFieldsError, ModelProviderConfigNotFoundError, UnsupportedModelProviderError } from './errors.js';
6
5
  import { buildModelProviderCatalog } from './model-provider-catalog.js';
7
6
  import { probeModelProviderCredentials, runProviderProbe } from './model-provider-validation.js';
7
+ import { requireAgentSecretsClient } from './secrets-client.js';
8
8
  export async function testAndSaveModelProviderConfig(params, options = {}) {
9
9
  const probe = options.probe ?? probeModelProviderCredentials;
10
+ const secrets = requireAgentSecretsClient(options.secrets);
10
11
  const entry = getModelProviderEntry(params.providerId);
11
12
  if (entry === undefined || entry.support_status !== 'supported') {
12
13
  throw new UnsupportedModelProviderError(params.providerId);
@@ -35,10 +36,10 @@ export async function testAndSaveModelProviderConfig(params, options = {}) {
35
36
  secrets: Object.values(params.credentials),
36
37
  signal: params.signal
37
38
  });
38
- const pruneStaleSecrets = options.pruneStaleSecrets ?? pruneStaleProviderCredentialSecrets;
39
+ const pruneStaleSecrets = options.pruneStaleSecrets ?? ((input)=>pruneStaleProviderCredentialSecrets(secrets, input));
39
40
  const namespace = agentSystemNamespace(params.providerId);
40
41
  const values = credentialsToStoreValues(params.providerId, params.credentials);
41
- await setSecrets({
42
+ await secrets.setSecrets({
42
43
  workspaceId: params.workspaceId,
43
44
  namespace,
44
45
  values,
@@ -93,9 +94,10 @@ export async function updateModelProviderConfigDefaultModel(params) {
93
94
  if (!config) throw new ModelProviderConfigNotFoundError(params.workspaceId, params.providerId);
94
95
  return config;
95
96
  }
96
- export async function deleteModelProviderConfig(params) {
97
+ export async function deleteModelProviderConfig(params, options = {}) {
98
+ const secrets = requireAgentSecretsClient(options.secrets);
97
99
  const deleted = await deleteModelProviderConfigRow(params);
98
- await deleteSecrets({
100
+ await secrets.deleteSecrets({
99
101
  workspaceId: params.workspaceId,
100
102
  namespace: agentSystemNamespace(params.providerId)
101
103
  });
@@ -115,15 +117,15 @@ function resolveDefaultModel(providerId, requestedModel) {
115
117
  storedModel: requestedModel ?? null
116
118
  };
117
119
  }
118
- async function pruneStaleProviderCredentialSecrets(params) {
119
- const stored = await getSecretsByNamespace({
120
+ async function pruneStaleProviderCredentialSecrets(secrets, params) {
121
+ const { values: stored } = await secrets.getSecretsByNamespace({
120
122
  workspaceId: params.workspaceId,
121
123
  namespace: params.namespace
122
124
  });
123
125
  const expected = new Set(params.expectedKeys);
124
126
  const staleKeys = Object.keys(stored).filter((key)=>!expected.has(key));
125
127
  if (staleKeys.length === 0) return;
126
- await deleteSecrets({
128
+ await secrets.deleteSecrets({
127
129
  workspaceId: params.workspaceId,
128
130
  namespace: params.namespace,
129
131
  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":"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"}
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 {\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(() => 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(\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","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","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 { getSecretsByNamespace } from '@shipfox/api-secrets';
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
- getCredentialBag?: typeof getSecretsByNamespace | undefined;
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;AAChC,OAAO,EAAC,qBAAqB,EAAwB,MAAM,sBAAsB,CAAC;AAYlF,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,gBAAgB,CAAC,EAAE,OAAO,qBAAqB,GAAG,SAAS,CAAC;CAC7D;AAED,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,+BAA+B,EACvC,OAAO,CAAC,EAAE,gCAAgC,GACzC,OAAO,CAAC,kCAAkC,CAAC,CAiD7C;AAED,wBAAgB,0CAA0C,CACxD,UAAU,EAAE,gBAAgB,GAC3B,SAAS,GAAG,SAAS,CAQvB"}
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"}
@@ -1,23 +1,28 @@
1
1
  import { getModelProviderEntry, modelProviderCredentialKeysMatch } from '@shipfox/api-agent-dto';
2
- import { getSecretsByNamespace, SecretDecryptionError } from '@shipfox/api-secrets';
2
+ import { secretsInterModuleContract } from '@shipfox/api-secrets-dto/inter-module';
3
+ import { isInterModuleKnownError } from '@shipfox/inter-module';
3
4
  import { config } from '#config.js';
4
5
  import { getModelProviderConfig } from '#db/index.js';
5
6
  import { agentRuntimeConfigResolvedCount } from '#metrics/index.js';
6
7
  import { agentSystemNamespace, storeValuesToCustomRuntimeCredentials, storeValuesToRuntimeCredentials } from './credential-fingerprints.js';
7
8
  import { ModelProviderConfigNotFoundError } from './errors.js';
9
+ import { requireAgentSecretsClient } from './secrets-client.js';
8
10
  export async function resolveRuntimeCredentials(params, options) {
9
11
  const runtimeConfig = options?.runtimeConfig ?? config;
10
- const getCredentialBag = options?.getCredentialBag ?? getSecretsByNamespace;
12
+ const secrets = options?.secrets;
11
13
  const providerConfig = await getModelProviderConfig({
12
14
  workspaceId: params.workspaceId,
13
15
  providerId: params.provider
14
16
  });
15
17
  if (providerConfig) {
16
18
  try {
17
- const values = await getCredentialBag({
19
+ const values = options?.getCredentialBag ? await options.getCredentialBag({
18
20
  workspaceId: params.workspaceId,
19
21
  namespace: agentSystemNamespace(params.provider)
20
- });
22
+ }) : (await requireAgentSecretsClient(secrets).getSecretsByNamespace({
23
+ workspaceId: params.workspaceId,
24
+ namespace: agentSystemNamespace(params.provider)
25
+ })).values;
21
26
  if (providerConfig.kind === 'custom') {
22
27
  const credentials = storeValuesToCustomRuntimeCredentials(values);
23
28
  agentRuntimeConfigResolvedCount.add(1, {
@@ -37,7 +42,7 @@ export async function resolveRuntimeCredentials(params, options) {
37
42
  });
38
43
  return toResponse(params, credentials, providerConfig);
39
44
  } catch (error) {
40
- if (error instanceof SecretDecryptionError) {
45
+ if (isInterModuleKnownError(secretsInterModuleContract.methods.getSecretsByNamespace, error)) {
41
46
  agentRuntimeConfigResolvedCount.add(1, {
42
47
  source: 'workspace',
43
48
  outcome: 'decryption_failed'