@shipfox/api-agent 12.2.0 → 14.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 (132) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +30 -0
  3. package/dist/config.d.ts +5 -1
  4. package/dist/config.d.ts.map +1 -1
  5. package/dist/config.js +75 -7
  6. package/dist/config.js.map +1 -1
  7. package/dist/core/errors.d.ts +4 -0
  8. package/dist/core/errors.d.ts.map +1 -1
  9. package/dist/core/errors.js +6 -0
  10. package/dist/core/errors.js.map +1 -1
  11. package/dist/core/index.d.ts +2 -1
  12. package/dist/core/index.d.ts.map +1 -1
  13. package/dist/core/index.js +2 -1
  14. package/dist/core/index.js.map +1 -1
  15. package/dist/core/model-provider-catalog.d.ts +5 -2
  16. package/dist/core/model-provider-catalog.d.ts.map +1 -1
  17. package/dist/core/model-provider-catalog.js +33 -1
  18. package/dist/core/model-provider-catalog.js.map +1 -1
  19. package/dist/core/resolve-agent-config.d.ts +4 -2
  20. package/dist/core/resolve-agent-config.d.ts.map +1 -1
  21. package/dist/core/resolve-agent-config.js +86 -31
  22. package/dist/core/resolve-agent-config.js.map +1 -1
  23. package/dist/core/resolve-runtime-credentials.d.ts +6 -2
  24. package/dist/core/resolve-runtime-credentials.d.ts.map +1 -1
  25. package/dist/core/resolve-runtime-credentials.js +60 -3
  26. package/dist/core/resolve-runtime-credentials.js.map +1 -1
  27. package/dist/core/validation-catalog.d.ts +2 -1
  28. package/dist/core/validation-catalog.d.ts.map +1 -1
  29. package/dist/core/validation-catalog.js +65 -17
  30. package/dist/core/validation-catalog.js.map +1 -1
  31. package/dist/core/workspace-agent-defaults-resolver.d.ts +2 -1
  32. package/dist/core/workspace-agent-defaults-resolver.d.ts.map +1 -1
  33. package/dist/core/workspace-agent-defaults-resolver.js +4 -2
  34. package/dist/core/workspace-agent-defaults-resolver.js.map +1 -1
  35. package/dist/core/workspace-provider-policy.d.ts +7 -0
  36. package/dist/core/workspace-provider-policy.d.ts.map +1 -0
  37. package/dist/core/workspace-provider-policy.js +10 -0
  38. package/dist/core/workspace-provider-policy.js.map +1 -0
  39. package/dist/index.d.ts +3 -1
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/index.js +15 -4
  42. package/dist/index.js.map +1 -1
  43. package/dist/presentation/e2eRoutes/create-model-provider.d.ts +2 -1
  44. package/dist/presentation/e2eRoutes/create-model-provider.d.ts.map +1 -1
  45. package/dist/presentation/e2eRoutes/create-model-provider.js +7 -1
  46. package/dist/presentation/e2eRoutes/create-model-provider.js.map +1 -1
  47. package/dist/presentation/e2eRoutes/index.d.ts +2 -1
  48. package/dist/presentation/e2eRoutes/index.d.ts.map +1 -1
  49. package/dist/presentation/e2eRoutes/index.js +4 -2
  50. package/dist/presentation/e2eRoutes/index.js.map +1 -1
  51. package/dist/presentation/inter-module.d.ts +3 -0
  52. package/dist/presentation/inter-module.d.ts.map +1 -1
  53. package/dist/presentation/inter-module.js +22 -6
  54. package/dist/presentation/inter-module.js.map +1 -1
  55. package/dist/presentation/routes/create-custom-model-provider.d.ts +2 -1
  56. package/dist/presentation/routes/create-custom-model-provider.d.ts.map +1 -1
  57. package/dist/presentation/routes/create-custom-model-provider.js +5 -2
  58. package/dist/presentation/routes/create-custom-model-provider.js.map +1 -1
  59. package/dist/presentation/routes/delete-model-provider-config.d.ts +2 -1
  60. package/dist/presentation/routes/delete-model-provider-config.d.ts.map +1 -1
  61. package/dist/presentation/routes/delete-model-provider-config.js +7 -2
  62. package/dist/presentation/routes/delete-model-provider-config.js.map +1 -1
  63. package/dist/presentation/routes/discover-custom-model-provider-models-by-slug.d.ts +2 -1
  64. package/dist/presentation/routes/discover-custom-model-provider-models-by-slug.d.ts.map +1 -1
  65. package/dist/presentation/routes/discover-custom-model-provider-models-by-slug.js +5 -2
  66. package/dist/presentation/routes/discover-custom-model-provider-models-by-slug.js.map +1 -1
  67. package/dist/presentation/routes/discover-custom-model-provider-models.d.ts +2 -0
  68. package/dist/presentation/routes/discover-custom-model-provider-models.d.ts.map +1 -1
  69. package/dist/presentation/routes/discover-custom-model-provider-models.js +29 -23
  70. package/dist/presentation/routes/discover-custom-model-provider-models.js.map +1 -1
  71. package/dist/presentation/routes/errors.d.ts.map +1 -1
  72. package/dist/presentation/routes/errors.js +10 -1
  73. package/dist/presentation/routes/errors.js.map +1 -1
  74. package/dist/presentation/routes/index.d.ts +5 -1
  75. package/dist/presentation/routes/index.d.ts.map +1 -1
  76. package/dist/presentation/routes/index.js +21 -14
  77. package/dist/presentation/routes/index.js.map +1 -1
  78. package/dist/presentation/routes/list-model-provider-catalog.d.ts +5 -0
  79. package/dist/presentation/routes/list-model-provider-catalog.d.ts.map +1 -1
  80. package/dist/presentation/routes/list-model-provider-catalog.js +21 -13
  81. package/dist/presentation/routes/list-model-provider-catalog.js.map +1 -1
  82. package/dist/presentation/routes/set-default-model-provider.d.ts +2 -0
  83. package/dist/presentation/routes/set-default-model-provider.d.ts.map +1 -1
  84. package/dist/presentation/routes/set-default-model-provider.js +44 -38
  85. package/dist/presentation/routes/set-default-model-provider.js.map +1 -1
  86. package/dist/presentation/routes/update-custom-model-provider.d.ts +2 -1
  87. package/dist/presentation/routes/update-custom-model-provider.d.ts.map +1 -1
  88. package/dist/presentation/routes/update-custom-model-provider.js +5 -2
  89. package/dist/presentation/routes/update-custom-model-provider.js.map +1 -1
  90. package/dist/presentation/routes/update-model-provider-default-model.d.ts +2 -0
  91. package/dist/presentation/routes/update-model-provider-default-model.d.ts.map +1 -1
  92. package/dist/presentation/routes/update-model-provider-default-model.js +35 -29
  93. package/dist/presentation/routes/update-model-provider-default-model.js.map +1 -1
  94. package/dist/presentation/routes/upsert-model-provider-config.d.ts +2 -1
  95. package/dist/presentation/routes/upsert-model-provider-config.d.ts.map +1 -1
  96. package/dist/presentation/routes/upsert-model-provider-config.js +5 -2
  97. package/dist/presentation/routes/upsert-model-provider-config.js.map +1 -1
  98. package/dist/tsconfig.test.tsbuildinfo +1 -1
  99. package/package.json +2 -2
  100. package/src/config.test.ts +196 -4
  101. package/src/config.ts +100 -9
  102. package/src/core/errors.ts +7 -0
  103. package/src/core/index.ts +5 -0
  104. package/src/core/model-provider-catalog.test.ts +30 -0
  105. package/src/core/model-provider-catalog.ts +41 -1
  106. package/src/core/resolve-agent-config.test.ts +92 -0
  107. package/src/core/resolve-agent-config.ts +152 -43
  108. package/src/core/resolve-runtime-credentials.test.ts +289 -1
  109. package/src/core/resolve-runtime-credentials.ts +69 -3
  110. package/src/core/validation-catalog.test.ts +54 -0
  111. package/src/core/validation-catalog.ts +124 -19
  112. package/src/core/workspace-agent-defaults-resolver.ts +7 -2
  113. package/src/core/workspace-provider-policy.ts +19 -0
  114. package/src/index.ts +25 -4
  115. package/src/presentation/e2eRoutes/create-model-provider.ts +11 -1
  116. package/src/presentation/e2eRoutes/index.ts +9 -2
  117. package/src/presentation/inter-module.test.ts +51 -0
  118. package/src/presentation/inter-module.ts +38 -6
  119. package/src/presentation/routes/create-custom-model-provider.ts +10 -2
  120. package/src/presentation/routes/delete-model-provider-config.ts +12 -2
  121. package/src/presentation/routes/discover-custom-model-provider-models-by-slug.ts +7 -1
  122. package/src/presentation/routes/discover-custom-model-provider-models.ts +30 -18
  123. package/src/presentation/routes/errors.ts +11 -0
  124. package/src/presentation/routes/index.ts +32 -14
  125. package/src/presentation/routes/list-model-provider-catalog.ts +32 -11
  126. package/src/presentation/routes/model-provider-catalog.test.ts +49 -1
  127. package/src/presentation/routes/model-provider-config.test.ts +62 -1
  128. package/src/presentation/routes/set-default-model-provider.ts +42 -31
  129. package/src/presentation/routes/update-custom-model-provider.ts +10 -2
  130. package/src/presentation/routes/update-model-provider-default-model.ts +37 -26
  131. package/src/presentation/routes/upsert-model-provider-config.ts +10 -2
  132. package/tsconfig.build.tsbuildinfo +1 -1
@@ -5,14 +5,17 @@ import {
5
5
  DEFAULT_HARNESS,
6
6
  getHarnessDescriptor,
7
7
  type Harness,
8
+ type ManagedModelEntry,
9
+ type ManagedModelProvider,
8
10
  type ModelProviderRef,
9
- type SupportedModelProviderId,
11
+ type WorkspaceProvidersPolicy,
10
12
  } from '@shipfox/api-agent-dto';
11
13
  import {
12
14
  InvalidAgentModelError,
13
15
  UnsupportedHarnessProviderError,
14
16
  UnsupportedHarnessThinkingError,
15
17
  UnsupportedModelProviderError,
18
+ WorkspaceProvidersDisabledError,
16
19
  } from './errors.js';
17
20
  import {listHarnessProviderModels} from './harness/index.js';
18
21
  import {getModelProviderEntry} from './model-provider-policy.js';
@@ -38,9 +41,11 @@ export interface AgentConfigResolutionContext {
38
41
  readonly workspaceDefaultHarnessId?: Harness | null | undefined;
39
42
  readonly workspaceDefaultProviderId?: ModelProviderRef | null | undefined;
40
43
  readonly workspaceProviderConfigs?: ReadonlyMap<ModelProviderRef, WorkspaceProviderDefaults>;
41
- readonly instanceDefaultProvider?: SupportedModelProviderId | undefined;
44
+ readonly instanceDefaultProvider?: ModelProviderRef | undefined;
42
45
  readonly instanceDefaultModel?: string | undefined;
43
46
  readonly instanceDefaultThinking?: AgentThinking | undefined;
47
+ readonly managedProvider?: ManagedModelProvider | undefined;
48
+ readonly workspaceProviders?: WorkspaceProvidersPolicy | undefined;
44
49
  }
45
50
 
46
51
  interface WorkspaceProviderDefaults {
@@ -50,6 +55,15 @@ interface WorkspaceProviderDefaults {
50
55
  readonly models?: readonly CustomAgentModelDto[] | null | undefined;
51
56
  }
52
57
 
58
+ interface ManagedProviderDefaults {
59
+ readonly kind: 'managed';
60
+ readonly defaultModel: string;
61
+ readonly defaultThinking?: AgentThinking | undefined;
62
+ readonly models: readonly ManagedModelEntry[];
63
+ }
64
+
65
+ type ProviderDefaults = WorkspaceProviderDefaults | ManagedProviderDefaults;
66
+
53
67
  type ModelCandidateResolver = () => string | null | undefined;
54
68
 
55
69
  export function resolveAgentConfig(
@@ -58,15 +72,15 @@ export function resolveAgentConfig(
58
72
  ): ResolvedAgentConfig {
59
73
  const harness = step.harness ?? ctx.workspaceDefaultHarnessId ?? DEFAULT_HARNESS;
60
74
  const provider = resolveProvider(step, ctx, harness);
61
- const workspaceProviderConfig = ctx.workspaceProviderConfigs?.get(provider);
75
+ const providerConfig = getProviderConfig(provider, ctx);
62
76
  const model = resolveModel({
63
77
  step,
64
78
  ctx,
65
79
  harness,
66
80
  provider,
67
- workspaceProviderConfig,
81
+ providerConfig,
68
82
  });
69
- const thinking = resolveThinking({step, ctx, harness, provider, workspaceProviderConfig});
83
+ const thinking = resolveThinking({step, ctx, harness, provider, providerConfig});
70
84
 
71
85
  return {harness, provider, model, thinking};
72
86
  }
@@ -80,13 +94,35 @@ function resolveProvider(
80
94
  harness: Harness,
81
95
  ): ModelProviderRef {
82
96
  const descriptor = getHarnessDescriptor(harness);
97
+ if (ctx.workspaceProviders === 'disabled') {
98
+ const managedProvider = ctx.managedProvider;
99
+ if (managedProvider === undefined) {
100
+ throw new Error(
101
+ 'workspace provider configuration is disabled but no managed provider is registered',
102
+ );
103
+ }
104
+ if (step.provider !== undefined && step.provider !== managedProvider.id) {
105
+ throw new WorkspaceProvidersDisabledError(managedProvider.id);
106
+ }
107
+
108
+ const providerConfig = getProviderConfig(managedProvider.id, ctx);
109
+ if (!isHarnessCompatible(harness, managedProvider.id, providerConfig)) {
110
+ throw new UnsupportedHarnessProviderError(
111
+ harness,
112
+ managedProvider.id,
113
+ supportedProviderIds(harness, descriptor, ctx),
114
+ );
115
+ }
116
+ return managedProvider.id;
117
+ }
118
+
83
119
  if (step.provider !== undefined) {
84
120
  const provider = resolveSupportedProvider(step.provider, ctx);
85
- if (!isHarnessCompatible(harness, provider, ctx.workspaceProviderConfigs?.get(provider))) {
121
+ if (!isHarnessCompatible(harness, provider, getProviderConfig(provider, ctx))) {
86
122
  throw new UnsupportedHarnessProviderError(
87
123
  harness,
88
124
  step.provider,
89
- descriptor.supportedProviderIds,
125
+ supportedProviderIds(harness, descriptor, ctx),
90
126
  );
91
127
  }
92
128
  return provider;
@@ -100,8 +136,8 @@ function resolveProvider(
100
136
  for (const candidate of candidates) {
101
137
  if (candidate === undefined || candidate === null) continue;
102
138
 
103
- const workspaceProviderConfig = ctx.workspaceProviderConfigs?.get(candidate);
104
- if (!isHarnessCompatible(harness, candidate, workspaceProviderConfig)) continue;
139
+ const providerConfig = getProviderConfig(candidate, ctx);
140
+ if (!isHarnessCompatible(harness, candidate, providerConfig)) continue;
105
141
 
106
142
  return resolveSupportedProvider(candidate, ctx);
107
143
  }
@@ -113,6 +149,8 @@ function resolveSupportedProvider(
113
149
  provider: string,
114
150
  ctx: AgentConfigResolutionContext,
115
151
  ): ModelProviderRef {
152
+ if (ctx.managedProvider?.id === provider) return provider;
153
+
116
154
  const workspaceProviderConfig = ctx.workspaceProviderConfigs?.get(provider);
117
155
  if (workspaceProviderConfig?.kind === 'custom') return provider;
118
156
 
@@ -120,7 +158,7 @@ function resolveSupportedProvider(
120
158
  if (entry === undefined || entry.support_status !== 'supported') {
121
159
  throw new UnsupportedModelProviderError(provider);
122
160
  }
123
- return provider as SupportedModelProviderId;
161
+ return provider;
124
162
  }
125
163
 
126
164
  function resolveModel(params: {
@@ -128,23 +166,30 @@ function resolveModel(params: {
128
166
  ctx: AgentConfigResolutionContext;
129
167
  harness: Harness;
130
168
  provider: ModelProviderRef;
131
- workspaceProviderConfig: WorkspaceProviderDefaults | undefined;
169
+ providerConfig: ProviderDefaults | undefined;
132
170
  }): string {
171
+ const providerConfig = params.providerConfig;
172
+
133
173
  if (params.step.model !== undefined) {
134
- validateModel(
135
- params.harness,
136
- params.provider,
137
- params.step.model,
138
- params.workspaceProviderConfig,
139
- );
174
+ validateModel(params.harness, params.provider, params.step.model, params.providerConfig);
140
175
  return params.step.model;
141
176
  }
142
177
 
143
- const candidates: ModelCandidateResolver[] = [() => params.workspaceProviderConfig?.defaultModel];
144
- if (params.workspaceProviderConfig?.kind === 'custom') {
145
- candidates.push(() => customDefaultModel(params.workspaceProviderConfig));
178
+ const candidates: ModelCandidateResolver[] = [];
179
+ if (providerConfig?.kind === 'custom') {
180
+ candidates.push(
181
+ () => providerConfig.defaultModel,
182
+ () => customDefaultModel(providerConfig),
183
+ );
184
+ } else if (providerConfig?.kind === 'managed') {
185
+ candidates.push(
186
+ () => instanceDefaultModel(params.provider, params.ctx),
187
+ () => providerConfig.defaultModel,
188
+ () => managedDefaultModel(params.harness, providerConfig),
189
+ );
146
190
  } else {
147
191
  candidates.push(
192
+ () => providerConfig?.defaultModel,
148
193
  () => instanceDefaultModel(params.provider, params.ctx),
149
194
  () => catalogDefaultModel(params.harness, params.provider),
150
195
  );
@@ -153,9 +198,7 @@ function resolveModel(params: {
153
198
  for (const resolveCandidate of candidates) {
154
199
  const candidate = resolveCandidate();
155
200
  if (candidate === undefined || candidate === null) continue;
156
- if (
157
- modelIsAvailable(params.harness, params.provider, candidate, params.workspaceProviderConfig)
158
- ) {
201
+ if (modelIsAvailable(params.harness, params.provider, candidate, params.providerConfig)) {
159
202
  return candidate;
160
203
  }
161
204
  }
@@ -164,7 +207,7 @@ function resolveModel(params: {
164
207
  }
165
208
 
166
209
  function catalogDefaultModel(harness: Harness, provider: ModelProviderRef): string {
167
- const catalogModels = listProviderModels(harness, provider);
210
+ const catalogModels = listProviderModels(harness, provider, undefined);
168
211
  const entry = getModelProviderEntry(provider);
169
212
  if (entry === undefined || entry.support_status !== 'supported') {
170
213
  throw new UnsupportedModelProviderError(provider);
@@ -195,20 +238,25 @@ function instanceDefaultThinking(
195
238
  return provider === ctx.instanceDefaultProvider ? ctx.instanceDefaultThinking : undefined;
196
239
  }
197
240
 
198
- function customDefaultModel(
199
- workspaceProviderConfig: WorkspaceProviderDefaults | undefined,
241
+ function customDefaultModel(providerConfig: ProviderDefaults | undefined): string | undefined {
242
+ if (providerConfig?.kind !== 'custom') return undefined;
243
+ return providerConfig.models?.[0]?.id;
244
+ }
245
+
246
+ function managedDefaultModel(
247
+ harness: Harness,
248
+ providerConfig: ManagedProviderDefaults,
200
249
  ): string | undefined {
201
- if (workspaceProviderConfig?.kind !== 'custom') return undefined;
202
- return workspaceProviderConfig.models?.[0]?.id;
250
+ return listManagedProviderModels(harness, providerConfig)[0]?.id;
203
251
  }
204
252
 
205
253
  function validateModel(
206
254
  harness: Harness,
207
255
  provider: ModelProviderRef,
208
256
  model: string,
209
- workspaceProviderConfig: WorkspaceProviderDefaults | undefined,
257
+ providerConfig: ProviderDefaults | undefined,
210
258
  ): void {
211
- if (modelIsAvailable(harness, provider, model, workspaceProviderConfig)) return;
259
+ if (modelIsAvailable(harness, provider, model, providerConfig)) return;
212
260
  throw new InvalidAgentModelError(harness, provider, model);
213
261
  }
214
262
 
@@ -216,25 +264,37 @@ function modelIsAvailable(
216
264
  harness: Harness,
217
265
  provider: ModelProviderRef,
218
266
  model: string,
219
- workspaceProviderConfig: WorkspaceProviderDefaults | undefined,
267
+ providerConfig: ProviderDefaults | undefined,
220
268
  ): boolean {
221
- if (workspaceProviderConfig?.kind === 'custom') {
222
- return workspaceProviderConfig.models?.some((candidate) => candidate.id === model) ?? false;
269
+ if (providerConfig?.kind === 'custom') {
270
+ return providerConfig.models?.some((candidate) => candidate.id === model) ?? false;
223
271
  }
224
272
 
225
- return listProviderModels(harness, provider).some((candidate) => candidate.id === model);
273
+ return listProviderModels(harness, provider, providerConfig).some(
274
+ (candidate) => candidate.id === model,
275
+ );
226
276
  }
227
277
 
228
- function listProviderModels(harness: Harness, provider: ModelProviderRef): readonly {id: string}[] {
278
+ function listProviderModels(
279
+ harness: Harness,
280
+ provider: ModelProviderRef,
281
+ providerConfig: ProviderDefaults | undefined,
282
+ ): readonly {id: string}[] {
283
+ if (providerConfig?.kind === 'managed') {
284
+ return listManagedProviderModels(harness, providerConfig);
285
+ }
229
286
  return listHarnessProviderModels(harness, provider);
230
287
  }
231
288
 
232
289
  function isHarnessCompatible(
233
290
  harness: Harness,
234
291
  provider: ModelProviderRef,
235
- workspaceProviderConfig: WorkspaceProviderDefaults | undefined,
292
+ providerConfig: ProviderDefaults | undefined,
236
293
  ): boolean {
237
- if (workspaceProviderConfig?.kind === 'custom') return harness === 'pi';
294
+ if (providerConfig?.kind === 'custom') return harness === 'pi';
295
+ if (providerConfig?.kind === 'managed') {
296
+ return listManagedProviderModels(harness, providerConfig).length > 0;
297
+ }
238
298
 
239
299
  return getHarnessDescriptor(harness).supportedProviderIds.includes(provider);
240
300
  }
@@ -244,7 +304,7 @@ function resolveThinking(params: {
244
304
  ctx: AgentConfigResolutionContext;
245
305
  harness: Harness;
246
306
  provider: ModelProviderRef;
247
- workspaceProviderConfig: WorkspaceProviderDefaults | undefined;
307
+ providerConfig: ProviderDefaults | undefined;
248
308
  }): AgentThinking {
249
309
  const thinkingSchema = agentThinkingByHarness[params.harness];
250
310
  const descriptor = getHarnessDescriptor(params.harness);
@@ -261,14 +321,63 @@ function resolveThinking(params: {
261
321
  return parsed.data;
262
322
  }
263
323
 
264
- const candidates = [
265
- params.workspaceProviderConfig?.defaultThinking,
266
- instanceDefaultThinking(params.provider, params.ctx),
267
- descriptor.defaultThinking,
268
- ];
324
+ const candidates =
325
+ params.providerConfig?.kind === 'managed'
326
+ ? [
327
+ instanceDefaultThinking(params.provider, params.ctx),
328
+ params.providerConfig.defaultThinking,
329
+ descriptor.defaultThinking,
330
+ ]
331
+ : [
332
+ params.providerConfig?.defaultThinking,
333
+ instanceDefaultThinking(params.provider, params.ctx),
334
+ descriptor.defaultThinking,
335
+ ];
269
336
  for (const candidate of candidates) {
270
337
  if (candidate !== undefined && thinkingSchema.safeParse(candidate).success) return candidate;
271
338
  }
272
339
 
273
340
  return descriptor.defaultThinking;
274
341
  }
342
+
343
+ function getProviderConfig(
344
+ provider: ModelProviderRef,
345
+ ctx: AgentConfigResolutionContext,
346
+ ): ProviderDefaults | undefined {
347
+ if (ctx.managedProvider?.id === provider) {
348
+ return {
349
+ kind: 'managed',
350
+ defaultModel: ctx.managedProvider.defaultModel,
351
+ defaultThinking: ctx.managedProvider.defaultThinking,
352
+ models: ctx.managedProvider.models,
353
+ };
354
+ }
355
+
356
+ return ctx.workspaceProviderConfigs?.get(provider);
357
+ }
358
+
359
+ function listManagedProviderModels(
360
+ harness: Harness,
361
+ providerConfig: ManagedProviderDefaults,
362
+ ): readonly ManagedModelEntry[] {
363
+ return providerConfig.models.filter((model) => managedModelSupportsHarness(harness, model));
364
+ }
365
+
366
+ function managedModelSupportsHarness(harness: Harness, model: ManagedModelEntry): boolean {
367
+ return harness === 'pi' || model.api === 'anthropic-messages';
368
+ }
369
+
370
+ function supportedProviderIds(
371
+ harness: Harness,
372
+ descriptor: ReturnType<typeof getHarnessDescriptor>,
373
+ ctx: AgentConfigResolutionContext,
374
+ ): readonly string[] {
375
+ if (
376
+ ctx.managedProvider === undefined ||
377
+ !ctx.managedProvider.models.some((model) => managedModelSupportsHarness(harness, model))
378
+ ) {
379
+ return descriptor.supportedProviderIds;
380
+ }
381
+
382
+ return [...descriptor.supportedProviderIds, ctx.managedProvider.id];
383
+ }