@shipfox/api-agent-dto 12.2.0 → 13.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +11 -0
  3. package/dist/index.d.ts +1 -1
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +1 -1
  6. package/dist/index.js.map +1 -1
  7. package/dist/inter-module.d.ts +14 -1
  8. package/dist/inter-module.d.ts.map +1 -1
  9. package/dist/inter-module.js +11 -2
  10. package/dist/inter-module.js.map +1 -1
  11. package/dist/schemas/catalog.d.ts +26 -78
  12. package/dist/schemas/catalog.d.ts.map +1 -1
  13. package/dist/schemas/catalog.js +26 -5
  14. package/dist/schemas/catalog.js.map +1 -1
  15. package/dist/schemas/index.d.ts +3 -2
  16. package/dist/schemas/index.d.ts.map +1 -1
  17. package/dist/schemas/index.js +3 -2
  18. package/dist/schemas/index.js.map +1 -1
  19. package/dist/schemas/managed-provider.d.ts +32 -0
  20. package/dist/schemas/managed-provider.d.ts.map +1 -0
  21. package/dist/schemas/managed-provider.js +8 -0
  22. package/dist/schemas/managed-provider.js.map +1 -0
  23. package/dist/schemas/runtime-config.d.ts +9 -0
  24. package/dist/schemas/runtime-config.d.ts.map +1 -1
  25. package/dist/schemas/runtime-config.js +7 -2
  26. package/dist/schemas/runtime-config.js.map +1 -1
  27. package/dist/tsconfig.test.tsbuildinfo +1 -1
  28. package/package.json +1 -1
  29. package/src/index.ts +9 -0
  30. package/src/inter-module.ts +12 -1
  31. package/src/schemas/catalog.test.ts +38 -0
  32. package/src/schemas/catalog.ts +22 -2
  33. package/src/schemas/index.ts +11 -0
  34. package/src/schemas/managed-provider.ts +36 -0
  35. package/src/schemas/runtime-config.test.ts +19 -0
  36. package/src/schemas/runtime-config.ts +13 -1
  37. package/tsconfig.build.tsbuildinfo +1 -1
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@shipfox/api-agent-dto",
3
3
  "license": "MIT",
4
- "version": "12.2.0",
4
+ "version": "13.1.0",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/ShipfoxHQ/shipfox.git",
package/src/index.ts CHANGED
@@ -14,6 +14,7 @@ export {
14
14
  agentThinkingSchema,
15
15
  buildHarnessToolDeploymentConfig,
16
16
  CLAUDE_HARNESS,
17
+ type ClaudeRuntimeConfigDto,
17
18
  type CreateCustomModelProviderBodyDto,
18
19
  type CustomAgentModelDto,
19
20
  type CustomModelProviderConfigDto,
@@ -21,6 +22,7 @@ export {
21
22
  type CustomModelProviderHeaderRequestDto,
22
23
  type CustomModelProviderRuntimeConfigDto,
23
24
  claudeAgentThinkingSchema,
25
+ claudeRuntimeConfigSchema,
24
26
  createCustomModelProviderBodySchema,
25
27
  customAgentModelSchema,
26
28
  customModelProviderConfigDtoSchema,
@@ -64,6 +66,10 @@ export {
64
66
  listModelProviderConfigsResponseSchema,
65
67
  listSupportedModelProviders,
66
68
  MAX_MODEL_COUNT,
69
+ type ManagedModelApi,
70
+ type ManagedModelEntry,
71
+ type ManagedModelProvider,
72
+ type ManagedProviderRuntimeConfig,
67
73
  type MaterializedAgentIntegrationConfigDto,
68
74
  type MaterializedAgentIntegrationToolConfigDto,
69
75
  type MaterializedAgentStepConfigDto,
@@ -80,6 +86,7 @@ export {
80
86
  type ModelProviderId,
81
87
  type ModelProviderRef,
82
88
  type ModelProviderSupportStatus,
89
+ managedModelApiSchema,
83
90
  materializedAgentIntegrationSchema,
84
91
  materializedAgentIntegrationToolSchema,
85
92
  materializedAgentStepConfigSchema,
@@ -119,4 +126,6 @@ export {
119
126
  updateCustomModelProviderHeaderRequestSchema,
120
127
  updateModelProviderConfigBodySchema,
121
128
  updateModelProviderDefaultModelBodySchema,
129
+ type WorkspaceProvidersPolicy,
130
+ workspaceProvidersPolicySchema,
122
131
  } from '#schemas/index.js';
@@ -55,11 +55,18 @@ export const agentInterModuleContract = defineInterModuleContract({
55
55
  resolveAgentConfig: {
56
56
  input: z.object({workspaceId: z.string().uuid().nullable(), config: agentConfigInputSchema}),
57
57
  output: resolvedAgentConfigSchema,
58
- errors: {'agent-config-invalid': z.object({})},
58
+ errors: {
59
+ 'agent-config-invalid': z.object({
60
+ message: z.string().min(1).optional(),
61
+ managed_provider_id: modelProviderRefSchema.optional(),
62
+ }),
63
+ },
59
64
  },
60
65
  resolveRuntimeCredentials: {
61
66
  input: z.object({
62
67
  workspaceId: z.string().uuid(),
68
+ runId: z.string().uuid(),
69
+ stepAttemptId: z.string().uuid(),
63
70
  harness: harnessSchema,
64
71
  provider: modelProviderRefSchema,
65
72
  model: z.string(),
@@ -69,6 +76,10 @@ export const agentInterModuleContract = defineInterModuleContract({
69
76
  errors: {
70
77
  'model-provider-not-configured': z.object({}),
71
78
  'model-provider-credentials-invalid': z.object({}),
79
+ 'workspace-providers-disabled': z.object({
80
+ message: z.string().min(1).optional(),
81
+ managed_provider_id: modelProviderRefSchema,
82
+ }),
72
83
  },
73
84
  },
74
85
  },
@@ -5,6 +5,7 @@ import {
5
5
  listSupportedModelProviders,
6
6
  MODEL_PROVIDER_CATALOG_SEED,
7
7
  modelProviderCatalogEntrySchema,
8
+ modelProviderCatalogResponseSchema,
8
9
  modelProviderCatalogSeedSchema,
9
10
  } from './catalog.js';
10
11
  import {
@@ -13,6 +14,16 @@ import {
13
14
  UNSUPPORTED_MODEL_PROVIDER_IDS,
14
15
  } from './model-provider-id.js';
15
16
 
17
+ const managedProviderCatalogEntry = {
18
+ id: 'shipfox-managed',
19
+ label: 'Shipfox Managed',
20
+ support_status: 'supported',
21
+ default_model: 'managed-claude',
22
+ credential_fields: [],
23
+ unsupported_reason: null,
24
+ models: [{id: 'managed-claude', label: 'Managed Claude'}],
25
+ };
26
+
16
27
  describe('model provider catalog', () => {
17
28
  it('parses the catalog seed', () => {
18
29
  const parsed = modelProviderCatalogSeedSchema.array().parse(MODEL_PROVIDER_CATALOG_SEED);
@@ -152,6 +163,33 @@ describe('model provider catalog', () => {
152
163
  expect(parsed).toHaveLength(37);
153
164
  });
154
165
 
166
+ it('parses a managed provider response entry', () => {
167
+ const parsed = modelProviderCatalogEntrySchema.parse(managedProviderCatalogEntry);
168
+
169
+ expect(parsed.id).toBe('shipfox-managed');
170
+ });
171
+
172
+ it('parses enabled and disabled policies through the full catalog response', () => {
173
+ for (const workspaceProviders of ['enabled', 'disabled'] as const) {
174
+ const parsed = modelProviderCatalogResponseSchema.parse({
175
+ providers: [managedProviderCatalogEntry],
176
+ workspace_providers: workspaceProviders,
177
+ });
178
+
179
+ expect(parsed.workspace_providers).toBe(workspaceProviders);
180
+ }
181
+ });
182
+
183
+ it('rejects an invalid workspace provider policy in the full catalog response', () => {
184
+ const parse = () =>
185
+ modelProviderCatalogResponseSchema.parse({
186
+ providers: [managedProviderCatalogEntry],
187
+ workspace_providers: 'invalid',
188
+ });
189
+
190
+ expect(parse).toThrow();
191
+ });
192
+
155
193
  it('rejects a supported response entry without models', () => {
156
194
  const supportedEntry = getModelProviderEntry('openai');
157
195
  if (supportedEntry === undefined) throw new Error('Missing OpenAI catalog entry');
@@ -10,8 +10,10 @@ import {
10
10
  thinkingLevelsForHarness,
11
11
  } from '@shipfox/workflow-document';
12
12
  import {z} from 'zod';
13
+ import {managedModelApiSchema} from './managed-provider.js';
13
14
  import {
14
15
  type ModelProviderId,
16
+ modelProviderRefSchema,
15
17
  providerIdSchema,
16
18
  SUPPORTED_MODEL_PROVIDER_IDS,
17
19
  type SupportedModelProviderId,
@@ -34,6 +36,7 @@ export {
34
36
  export const agentModelOptionSchema = z.object({
35
37
  id: z.string().min(1),
36
38
  label: z.string().min(1),
39
+ api: managedModelApiSchema.optional(),
37
40
  });
38
41
 
39
42
  export type AgentModelOptionDto = z.infer<typeof agentModelOptionSchema>;
@@ -50,6 +53,10 @@ export const modelProviderSupportStatusSchema = z.enum(['supported', 'unsupporte
50
53
 
51
54
  export type ModelProviderSupportStatus = z.infer<typeof modelProviderSupportStatusSchema>;
52
55
 
56
+ export const workspaceProvidersPolicySchema = z.enum(['enabled', 'disabled']);
57
+
58
+ export type WorkspaceProvidersPolicy = z.infer<typeof workspaceProvidersPolicySchema>;
59
+
53
60
  const supportedModelProviderIds = new Set<string>(SUPPORTED_MODEL_PROVIDER_IDS);
54
61
  const unsupportedModelProviderIds = new Set<string>(UNSUPPORTED_MODEL_PROVIDER_IDS);
55
62
 
@@ -67,12 +74,24 @@ export const modelProviderCatalogSeedSchema =
67
74
 
68
75
  export type ModelProviderCatalogSeedDto = z.infer<typeof modelProviderCatalogSeedSchema>;
69
76
 
70
- export const modelProviderCatalogEntrySchema = modelProviderCatalogSeedBaseSchema
77
+ const modelProviderCatalogEntryBaseSchema = z.object({
78
+ id: modelProviderRefSchema,
79
+ label: z.string().min(1),
80
+ support_status: modelProviderSupportStatusSchema,
81
+ default_model: z.string().min(1).nullable(),
82
+ credential_fields: z.array(modelProviderCredentialFieldSchema),
83
+ unsupported_reason: z.string().min(1).nullable(),
84
+ });
85
+
86
+ export const modelProviderCatalogEntrySchema = modelProviderCatalogEntryBaseSchema
71
87
  .extend({
72
88
  models: z.array(agentModelOptionSchema),
73
89
  })
74
90
  .superRefine((entry, ctx) => {
75
- validateCatalogSeedEntry(entry, ctx);
91
+ const seedId = providerIdSchema.safeParse(entry.id);
92
+ if (seedId.success) {
93
+ validateCatalogSeedEntry({...entry, id: seedId.data}, ctx);
94
+ }
76
95
 
77
96
  if (entry.support_status === 'supported') {
78
97
  if (entry.models.length === 0) {
@@ -105,6 +124,7 @@ export type ModelProviderCatalogEntryDto = z.infer<typeof modelProviderCatalogEn
105
124
 
106
125
  export const modelProviderCatalogResponseSchema = z.object({
107
126
  providers: z.array(modelProviderCatalogEntrySchema),
127
+ workspace_providers: workspaceProvidersPolicySchema.optional(),
108
128
  });
109
129
 
110
130
  export type ModelProviderCatalogResponseDto = z.infer<typeof modelProviderCatalogResponseSchema>;
@@ -25,6 +25,8 @@ export {
25
25
  modelProviderSupportStatusSchema,
26
26
  piAgentThinkingSchema,
27
27
  thinkingLevelsForHarness,
28
+ type WorkspaceProvidersPolicy,
29
+ workspaceProvidersPolicySchema,
28
30
  } from './catalog.js';
29
31
  export {
30
32
  type CreateCustomModelProviderBodyDto,
@@ -79,6 +81,13 @@ export {
79
81
  PI_HARNESS_TOOL_PACKAGE_NAMES,
80
82
  parsePiEnabledToolPackages,
81
83
  } from './harness.js';
84
+ export {
85
+ type ManagedModelApi,
86
+ type ManagedModelEntry,
87
+ type ManagedModelProvider,
88
+ type ManagedProviderRuntimeConfig,
89
+ managedModelApiSchema,
90
+ } from './managed-provider.js';
82
91
  export {
83
92
  AGENT_INTEGRATION_MCP_AUTH,
84
93
  AGENT_INTEGRATION_MCP_ENDPOINT,
@@ -127,6 +136,8 @@ export {
127
136
  export {
128
137
  type AgentRuntimeCredentialsResponseDto,
129
138
  agentRuntimeCredentialsResponseSchema,
139
+ type ClaudeRuntimeConfigDto,
140
+ claudeRuntimeConfigSchema,
130
141
  } from './runtime-config.js';
131
142
  export {
132
143
  type SetDefaultHarnessBodyDto,
@@ -0,0 +1,36 @@
1
+ import type {AgentThinking} from '@shipfox/workflow-document';
2
+ import {z} from 'zod';
3
+
4
+ export const managedModelApiSchema = z.enum([
5
+ 'anthropic-messages',
6
+ 'openai-responses',
7
+ 'openai-completions',
8
+ ]);
9
+
10
+ export type ManagedModelApi = z.infer<typeof managedModelApiSchema>;
11
+
12
+ export interface ManagedModelEntry {
13
+ readonly id: string;
14
+ readonly label: string;
15
+ readonly api: ManagedModelApi;
16
+ }
17
+
18
+ export interface ManagedProviderRuntimeConfig {
19
+ readonly api: ManagedModelApi;
20
+ readonly baseUrl: string;
21
+ readonly credentials: Record<string, string>;
22
+ }
23
+
24
+ export interface ManagedModelProvider {
25
+ readonly id: string;
26
+ readonly label: string;
27
+ readonly models: readonly ManagedModelEntry[];
28
+ readonly defaultModel: string;
29
+ readonly defaultThinking?: AgentThinking | undefined;
30
+ readonly resolveCredentials: (params: {
31
+ workspaceId: string;
32
+ runId: string;
33
+ stepAttemptId: string;
34
+ model: string;
35
+ }) => Promise<ManagedProviderRuntimeConfig>;
36
+ }
@@ -34,6 +34,25 @@ describe('agentRuntimeCredentialsResponseSchema', () => {
34
34
  expect(parsed.custom_provider?.api).toBe('openai-responses');
35
35
  });
36
36
 
37
+ it('parses managed Claude runtime credentials without a custom provider descriptor', () => {
38
+ const parsed = agentRuntimeCredentialsResponseSchema.parse({
39
+ harness: 'claude',
40
+ provider_id: 'shipfox',
41
+ model: 'managed-claude',
42
+ thinking: 'high',
43
+ credentials: {api_key: 'managed-token'},
44
+ claude: {
45
+ base_url: 'https://gateway.example.test',
46
+ auth_token: 'managed-token',
47
+ },
48
+ });
49
+
50
+ expect(parsed.claude).toEqual({
51
+ base_url: 'https://gateway.example.test',
52
+ auth_token: 'managed-token',
53
+ });
54
+ });
55
+
37
56
  it('rejects a custom model provider descriptor without key intent', () => {
38
57
  const parse = () =>
39
58
  agentRuntimeCredentialsResponseSchema.parse({
@@ -6,6 +6,13 @@ import {isReservedModelProviderId, modelProviderRefSchema} from './model-provide
6
6
  const credentialKeySchema = z.string().min(1);
7
7
  const credentialValueSchema = z.string().min(1);
8
8
 
9
+ export const claudeRuntimeConfigSchema = z.object({
10
+ base_url: z.string().url().max(2048),
11
+ auth_token: credentialValueSchema,
12
+ });
13
+
14
+ export type ClaudeRuntimeConfigDto = z.infer<typeof claudeRuntimeConfigSchema>;
15
+
9
16
  /**
10
17
  * Lease-scoped runtime credentials. The credential values are secrets and must
11
18
  * never be written to logs, traces, client state, or generic catalog surfaces.
@@ -18,9 +25,14 @@ export const agentRuntimeCredentialsResponseSchema = z
18
25
  thinking: agentThinkingSchema,
19
26
  credentials: z.record(credentialKeySchema, credentialValueSchema),
20
27
  custom_provider: customModelProviderRuntimeConfigSchema.optional(),
28
+ claude: claudeRuntimeConfigSchema.optional(),
21
29
  })
22
30
  .superRefine((response, ctx) => {
23
- if (isReservedModelProviderId(response.provider_id) || response.custom_provider !== undefined) {
31
+ if (
32
+ isReservedModelProviderId(response.provider_id) ||
33
+ response.custom_provider !== undefined ||
34
+ response.claude !== undefined
35
+ ) {
24
36
  return;
25
37
  }
26
38