@shipfox/api-agent 2.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.
- package/.turbo/turbo-build.log +2 -0
- package/.turbo/turbo-type$colon$emit.log +1 -0
- package/.turbo/turbo-type.log +1 -0
- package/CHANGELOG.md +105 -0
- package/LICENSE +21 -0
- package/dist/config.d.ts +13 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +60 -0
- package/dist/config.js.map +1 -0
- package/dist/core/credential-fingerprints.d.ts +10 -0
- package/dist/core/credential-fingerprints.d.ts.map +1 -0
- package/dist/core/credential-fingerprints.js +65 -0
- package/dist/core/credential-fingerprints.js.map +1 -0
- package/dist/core/custom-model-provider-config-service.d.ts +26 -0
- package/dist/core/custom-model-provider-config-service.d.ts.map +1 -0
- package/dist/core/custom-model-provider-config-service.js +390 -0
- package/dist/core/custom-model-provider-config-service.js.map +1 -0
- package/dist/core/custom-provider-url.d.ts +4 -0
- package/dist/core/custom-provider-url.d.ts.map +1 -0
- package/dist/core/custom-provider-url.js +23 -0
- package/dist/core/custom-provider-url.js.map +1 -0
- package/dist/core/discover-custom-model-provider-models.d.ts +3 -0
- package/dist/core/discover-custom-model-provider-models.d.ts.map +1 -0
- package/dist/core/discover-custom-model-provider-models.js +122 -0
- package/dist/core/discover-custom-model-provider-models.js.map +1 -0
- package/dist/core/entities/agent-workspace-settings.d.ts +9 -0
- package/dist/core/entities/agent-workspace-settings.d.ts.map +1 -0
- package/dist/core/entities/agent-workspace-settings.js +3 -0
- package/dist/core/entities/agent-workspace-settings.js.map +1 -0
- package/dist/core/entities/model-provider-config.d.ts +19 -0
- package/dist/core/entities/model-provider-config.d.ts.map +1 -0
- package/dist/core/entities/model-provider-config.js +3 -0
- package/dist/core/entities/model-provider-config.js.map +1 -0
- package/dist/core/errors.d.ts +62 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +80 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/harness/claude.d.ts +6 -0
- package/dist/core/harness/claude.d.ts.map +1 -0
- package/dist/core/harness/claude.js +104 -0
- package/dist/core/harness/claude.js.map +1 -0
- package/dist/core/harness/index.d.ts +4 -0
- package/dist/core/harness/index.d.ts.map +1 -0
- package/dist/core/harness/index.js +5 -0
- package/dist/core/harness/index.js.map +1 -0
- package/dist/core/harness/pi.d.ts +6 -0
- package/dist/core/harness/pi.d.ts.map +1 -0
- package/dist/core/harness/pi.js +16 -0
- package/dist/core/harness/pi.js.map +1 -0
- package/dist/core/harness/registry.d.ts +22 -0
- package/dist/core/harness/registry.d.ts.map +1 -0
- package/dist/core/harness/registry.js +46 -0
- package/dist/core/harness/registry.js.map +1 -0
- package/dist/core/index.d.ts +12 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +11 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/model-provider-catalog.d.ts +3 -0
- package/dist/core/model-provider-catalog.d.ts.map +1 -0
- package/dist/core/model-provider-catalog.js +25 -0
- package/dist/core/model-provider-catalog.js.map +1 -0
- package/dist/core/model-provider-config-service.d.ts +32 -0
- package/dist/core/model-provider-config-service.d.ts.map +1 -0
- package/dist/core/model-provider-config-service.js +133 -0
- package/dist/core/model-provider-config-service.js.map +1 -0
- package/dist/core/model-provider-validation.d.ts +31 -0
- package/dist/core/model-provider-validation.d.ts.map +1 -0
- package/dist/core/model-provider-validation.js +220 -0
- package/dist/core/model-provider-validation.js.map +1 -0
- package/dist/core/resolve-agent-config.d.ts +32 -0
- package/dist/core/resolve-agent-config.d.ts.map +1 -0
- package/dist/core/resolve-agent-config.js +143 -0
- package/dist/core/resolve-agent-config.js.map +1 -0
- package/dist/core/resolve-runtime-credentials.d.ts +21 -0
- package/dist/core/resolve-runtime-credentials.d.ts.map +1 -0
- package/dist/core/resolve-runtime-credentials.js +101 -0
- package/dist/core/resolve-runtime-credentials.js.map +1 -0
- package/dist/core/workspace-agent-defaults-resolver.d.ts +3 -0
- package/dist/core/workspace-agent-defaults-resolver.d.ts.map +1 -0
- package/dist/core/workspace-agent-defaults-resolver.js +26 -0
- package/dist/core/workspace-agent-defaults-resolver.js.map +1 -0
- package/dist/db/agent-defaults-snapshot.d.ts +9 -0
- package/dist/db/agent-defaults-snapshot.d.ts.map +1 -0
- package/dist/db/agent-defaults-snapshot.js +24 -0
- package/dist/db/agent-defaults-snapshot.js.map +1 -0
- package/dist/db/agent-workspace-settings.d.ts +12 -0
- package/dist/db/agent-workspace-settings.d.ts.map +1 -0
- package/dist/db/agent-workspace-settings.js +53 -0
- package/dist/db/agent-workspace-settings.js.map +1 -0
- package/dist/db/db.d.ts +771 -0
- package/dist/db/db.d.ts.map +1 -0
- package/dist/db/db.js +20 -0
- package/dist/db/db.js.map +1 -0
- package/dist/db/index.d.ts +9 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +11 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/model-provider-configs.d.ts +38 -0
- package/dist/db/model-provider-configs.d.ts.map +1 -0
- package/dist/db/model-provider-configs.js +159 -0
- package/dist/db/model-provider-configs.js.map +1 -0
- package/dist/db/schema/agent-workspace-settings.d.ts +97 -0
- package/dist/db/schema/agent-workspace-settings.d.ts.map +1 -0
- package/dist/db/schema/agent-workspace-settings.js +26 -0
- package/dist/db/schema/agent-workspace-settings.js.map +1 -0
- package/dist/db/schema/common.d.ts +2 -0
- package/dist/db/schema/common.d.ts.map +1 -0
- package/dist/db/schema/common.js +4 -0
- package/dist/db/schema/common.js.map +1 -0
- package/dist/db/schema/model-provider-configs.d.ts +296 -0
- package/dist/db/schema/model-provider-configs.d.ts.map +1 -0
- package/dist/db/schema/model-provider-configs.js +52 -0
- package/dist/db/schema/model-provider-configs.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/metrics/index.d.ts +2 -0
- package/dist/metrics/index.d.ts.map +1 -0
- package/dist/metrics/index.js +3 -0
- package/dist/metrics/index.js.map +1 -0
- package/dist/metrics/instance.d.ts +10 -0
- package/dist/metrics/instance.d.ts.map +1 -0
- package/dist/metrics/instance.js +10 -0
- package/dist/metrics/instance.js.map +1 -0
- package/dist/presentation/dto/index.d.ts +2 -0
- package/dist/presentation/dto/index.d.ts.map +1 -0
- package/dist/presentation/dto/index.js +3 -0
- package/dist/presentation/dto/index.js.map +1 -0
- package/dist/presentation/dto/model-provider-config.d.ts +6 -0
- package/dist/presentation/dto/model-provider-config.d.ts.map +1 -0
- package/dist/presentation/dto/model-provider-config.js +32 -0
- package/dist/presentation/dto/model-provider-config.js.map +1 -0
- package/dist/presentation/e2eRoutes/create-model-provider.d.ts +2 -0
- package/dist/presentation/e2eRoutes/create-model-provider.d.ts.map +1 -0
- package/dist/presentation/e2eRoutes/create-model-provider.js +66 -0
- package/dist/presentation/e2eRoutes/create-model-provider.js.map +1 -0
- package/dist/presentation/e2eRoutes/index.d.ts +3 -0
- package/dist/presentation/e2eRoutes/index.d.ts.map +1 -0
- package/dist/presentation/e2eRoutes/index.js +9 -0
- package/dist/presentation/e2eRoutes/index.js.map +1 -0
- package/dist/presentation/index.d.ts +2 -0
- package/dist/presentation/index.d.ts.map +1 -0
- package/dist/presentation/index.js +3 -0
- package/dist/presentation/index.js.map +1 -0
- package/dist/presentation/routes/create-custom-model-provider.d.ts +2 -0
- package/dist/presentation/routes/create-custom-model-provider.d.ts.map +1 -0
- package/dist/presentation/routes/create-custom-model-provider.js +45 -0
- package/dist/presentation/routes/create-custom-model-provider.js.map +1 -0
- package/dist/presentation/routes/delete-model-provider-config.d.ts +2 -0
- package/dist/presentation/routes/delete-model-provider-config.d.ts.map +1 -0
- package/dist/presentation/routes/delete-model-provider-config.js +38 -0
- package/dist/presentation/routes/delete-model-provider-config.js.map +1 -0
- package/dist/presentation/routes/discover-custom-model-provider-models-by-slug.d.ts +2 -0
- package/dist/presentation/routes/discover-custom-model-provider-models-by-slug.d.ts.map +1 -0
- package/dist/presentation/routes/discover-custom-model-provider-models-by-slug.js +37 -0
- package/dist/presentation/routes/discover-custom-model-provider-models-by-slug.js.map +1 -0
- package/dist/presentation/routes/discover-custom-model-provider-models.d.ts +2 -0
- package/dist/presentation/routes/discover-custom-model-provider-models.d.ts.map +1 -0
- package/dist/presentation/routes/discover-custom-model-provider-models.js +31 -0
- package/dist/presentation/routes/discover-custom-model-provider-models.js.map +1 -0
- package/dist/presentation/routes/errors.d.ts +2 -0
- package/dist/presentation/routes/errors.d.ts.map +1 -0
- package/dist/presentation/routes/errors.js +112 -0
- package/dist/presentation/routes/errors.js.map +1 -0
- package/dist/presentation/routes/index.d.ts +3 -0
- package/dist/presentation/routes/index.d.ts.map +1 -0
- package/dist/presentation/routes/index.js +39 -0
- package/dist/presentation/routes/index.js.map +1 -0
- package/dist/presentation/routes/list-model-provider-catalog.d.ts +2 -0
- package/dist/presentation/routes/list-model-provider-catalog.d.ts.map +1 -0
- package/dist/presentation/routes/list-model-provider-catalog.js +18 -0
- package/dist/presentation/routes/list-model-provider-catalog.js.map +1 -0
- package/dist/presentation/routes/list-model-provider-configs.d.ts +2 -0
- package/dist/presentation/routes/list-model-provider-configs.d.ts.map +1 -0
- package/dist/presentation/routes/list-model-provider-configs.js +37 -0
- package/dist/presentation/routes/list-model-provider-configs.js.map +1 -0
- package/dist/presentation/routes/set-default-harness.d.ts +2 -0
- package/dist/presentation/routes/set-default-harness.d.ts.map +1 -0
- package/dist/presentation/routes/set-default-harness.js +38 -0
- package/dist/presentation/routes/set-default-harness.js.map +1 -0
- package/dist/presentation/routes/set-default-model-provider.d.ts +2 -0
- package/dist/presentation/routes/set-default-model-provider.d.ts.map +1 -0
- package/dist/presentation/routes/set-default-model-provider.js +48 -0
- package/dist/presentation/routes/set-default-model-provider.js.map +1 -0
- package/dist/presentation/routes/update-custom-model-provider.d.ts +2 -0
- package/dist/presentation/routes/update-custom-model-provider.d.ts.map +1 -0
- package/dist/presentation/routes/update-custom-model-provider.js +47 -0
- package/dist/presentation/routes/update-custom-model-provider.js.map +1 -0
- package/dist/presentation/routes/update-model-provider-default-model.d.ts +2 -0
- package/dist/presentation/routes/update-model-provider-default-model.d.ts.map +1 -0
- package/dist/presentation/routes/update-model-provider-default-model.js +38 -0
- package/dist/presentation/routes/update-model-provider-default-model.js.map +1 -0
- package/dist/presentation/routes/upsert-model-provider-config.d.ts +2 -0
- package/dist/presentation/routes/upsert-model-provider-config.d.ts.map +1 -0
- package/dist/presentation/routes/upsert-model-provider-config.js +52 -0
- package/dist/presentation/routes/upsert-model-provider-config.js.map +1 -0
- package/dist/tsconfig.test.tsbuildinfo +1 -0
- package/drizzle/0000_daffy_leopardon.sql +28 -0
- package/drizzle/0001_default_harness.sql +1 -0
- package/drizzle/meta/0000_snapshot.json +199 -0
- package/drizzle/meta/0001_snapshot.json +205 -0
- package/drizzle/meta/_journal.json +20 -0
- package/drizzle.config.ts +7 -0
- package/package.json +109 -0
- package/src/config.test.ts +118 -0
- package/src/config.ts +75 -0
- package/src/core/catalog-registry.test.ts +48 -0
- package/src/core/credential-fingerprints.test.ts +34 -0
- package/src/core/credential-fingerprints.ts +84 -0
- package/src/core/custom-model-provider-config-service.ts +537 -0
- package/src/core/custom-provider-url.ts +24 -0
- package/src/core/discover-custom-model-provider-models.ts +147 -0
- package/src/core/entities/agent-workspace-settings.ts +9 -0
- package/src/core/entities/model-provider-config.ts +25 -0
- package/src/core/errors.ts +139 -0
- package/src/core/harness/claude.ts +75 -0
- package/src/core/harness/index.ts +19 -0
- package/src/core/harness/pi.ts +18 -0
- package/src/core/harness/registry.test.ts +281 -0
- package/src/core/harness/registry.ts +108 -0
- package/src/core/index.ts +56 -0
- package/src/core/model-provider-catalog.ts +33 -0
- package/src/core/model-provider-config-service.test.ts +940 -0
- package/src/core/model-provider-config-service.ts +207 -0
- package/src/core/model-provider-validation.test.ts +354 -0
- package/src/core/model-provider-validation.ts +276 -0
- package/src/core/resolve-agent-config.test.ts +441 -0
- package/src/core/resolve-agent-config.ts +272 -0
- package/src/core/resolve-runtime-credentials.test.ts +316 -0
- package/src/core/resolve-runtime-credentials.ts +147 -0
- package/src/core/workspace-agent-defaults-resolver.ts +42 -0
- package/src/db/agent-defaults-snapshot.ts +49 -0
- package/src/db/agent-workspace-settings.test.ts +111 -0
- package/src/db/agent-workspace-settings.ts +92 -0
- package/src/db/db.ts +20 -0
- package/src/db/index.ts +29 -0
- package/src/db/model-provider-configs.test.ts +281 -0
- package/src/db/model-provider-configs.ts +230 -0
- package/src/db/schema/agent-workspace-settings.ts +27 -0
- package/src/db/schema/common.ts +3 -0
- package/src/db/schema/model-provider-configs.ts +80 -0
- package/src/index.ts +43 -0
- package/src/metrics/index.ts +1 -0
- package/src/metrics/instance.ts +18 -0
- package/src/presentation/dto/index.ts +5 -0
- package/src/presentation/dto/model-provider-config.ts +41 -0
- package/src/presentation/e2eRoutes/create-model-provider.test.ts +47 -0
- package/src/presentation/e2eRoutes/create-model-provider.ts +61 -0
- package/src/presentation/e2eRoutes/index.ts +7 -0
- package/src/presentation/index.ts +1 -0
- package/src/presentation/routes/create-custom-model-provider.ts +45 -0
- package/src/presentation/routes/delete-model-provider-config.ts +31 -0
- package/src/presentation/routes/discover-custom-model-provider-models-by-slug.ts +42 -0
- package/src/presentation/routes/discover-custom-model-provider-models.ts +29 -0
- package/src/presentation/routes/errors.ts +122 -0
- package/src/presentation/routes/index.ts +37 -0
- package/src/presentation/routes/list-model-provider-catalog.ts +15 -0
- package/src/presentation/routes/list-model-provider-configs.ts +33 -0
- package/src/presentation/routes/model-provider-catalog.test.ts +73 -0
- package/src/presentation/routes/model-provider-config.test.ts +807 -0
- package/src/presentation/routes/set-default-harness.ts +33 -0
- package/src/presentation/routes/set-default-model-provider.ts +47 -0
- package/src/presentation/routes/update-custom-model-provider.ts +50 -0
- package/src/presentation/routes/update-model-provider-default-model.ts +40 -0
- package/src/presentation/routes/upsert-model-provider-config.ts +53 -0
- package/test/env.ts +8 -0
- package/test/globalSetup.ts +25 -0
- package/test/setup.ts +17 -0
- package/tsconfig.build.json +9 -0
- package/tsconfig.build.tsbuildinfo +1 -0
- package/tsconfig.json +3 -0
- package/tsconfig.test.json +8 -0
- package/vitest.config.ts +11 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AgentThinking,
|
|
3
|
+
CustomAgentModelDto,
|
|
4
|
+
CustomModelProviderHeaderDto,
|
|
5
|
+
ModelProviderApi,
|
|
6
|
+
ModelProviderRef,
|
|
7
|
+
} from '@shipfox/api-agent-dto';
|
|
8
|
+
import {uuidv7PrimaryKey} from '@shipfox/node-drizzle';
|
|
9
|
+
import {sql} from 'drizzle-orm';
|
|
10
|
+
import {
|
|
11
|
+
boolean,
|
|
12
|
+
check,
|
|
13
|
+
jsonb,
|
|
14
|
+
pgEnum,
|
|
15
|
+
pgTable,
|
|
16
|
+
text,
|
|
17
|
+
timestamp,
|
|
18
|
+
uniqueIndex,
|
|
19
|
+
uuid,
|
|
20
|
+
} from 'drizzle-orm/pg-core';
|
|
21
|
+
import type {ModelProviderConfig} from '#core/entities/model-provider-config.js';
|
|
22
|
+
|
|
23
|
+
export const modelProviderConfigKindEnum = pgEnum('model_provider_config_kind', [
|
|
24
|
+
'builtin',
|
|
25
|
+
'custom',
|
|
26
|
+
]);
|
|
27
|
+
|
|
28
|
+
export const modelProviderConfigs = pgTable(
|
|
29
|
+
'model_provider_configs',
|
|
30
|
+
{
|
|
31
|
+
id: uuidv7PrimaryKey(),
|
|
32
|
+
workspaceId: uuid('workspace_id').notNull(),
|
|
33
|
+
providerId: text('provider_id').notNull(),
|
|
34
|
+
kind: modelProviderConfigKindEnum('kind').notNull().default('builtin'),
|
|
35
|
+
displayName: text('display_name'),
|
|
36
|
+
api: text('api').$type<ModelProviderApi>(),
|
|
37
|
+
baseUrl: text('base_url'),
|
|
38
|
+
headers: jsonb('headers').$type<CustomModelProviderHeaderDto[]>(),
|
|
39
|
+
secretHeaderNames: jsonb('secret_header_names').$type<string[]>(),
|
|
40
|
+
models: jsonb('models').$type<CustomAgentModelDto[]>(),
|
|
41
|
+
requiresApiKey: boolean('requires_api_key').notNull().default(false),
|
|
42
|
+
defaultModel: text('default_model'),
|
|
43
|
+
defaultThinking: text('default_thinking').notNull(),
|
|
44
|
+
createdAt: timestamp('created_at', {withTimezone: true}).notNull().defaultNow(),
|
|
45
|
+
updatedAt: timestamp('updated_at', {withTimezone: true}).notNull().defaultNow(),
|
|
46
|
+
},
|
|
47
|
+
(table) => [
|
|
48
|
+
uniqueIndex('model_provider_configs_workspace_provider_unique').on(
|
|
49
|
+
table.workspaceId,
|
|
50
|
+
table.providerId,
|
|
51
|
+
),
|
|
52
|
+
check(
|
|
53
|
+
'model_provider_configs_custom_required_fields',
|
|
54
|
+
sql`${table.kind} <> 'custom' OR (${table.api} IS NOT NULL AND ${table.baseUrl} IS NOT NULL AND ${table.models} IS NOT NULL AND ${table.displayName} IS NOT NULL)`,
|
|
55
|
+
),
|
|
56
|
+
],
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
export type ModelProviderConfigDb = typeof modelProviderConfigs.$inferSelect;
|
|
60
|
+
export type ModelProviderConfigCreateDb = typeof modelProviderConfigs.$inferInsert;
|
|
61
|
+
|
|
62
|
+
export function toModelProviderConfig(row: ModelProviderConfigDb): ModelProviderConfig {
|
|
63
|
+
return {
|
|
64
|
+
id: row.id,
|
|
65
|
+
workspaceId: row.workspaceId,
|
|
66
|
+
providerId: row.providerId as ModelProviderRef,
|
|
67
|
+
kind: row.kind,
|
|
68
|
+
displayName: row.displayName,
|
|
69
|
+
api: row.api,
|
|
70
|
+
baseUrl: row.baseUrl,
|
|
71
|
+
headers: row.headers,
|
|
72
|
+
secretHeaderNames: row.secretHeaderNames,
|
|
73
|
+
models: row.models,
|
|
74
|
+
requiresApiKey: row.requiresApiKey,
|
|
75
|
+
defaultModel: row.defaultModel,
|
|
76
|
+
defaultThinking: row.defaultThinking as AgentThinking,
|
|
77
|
+
createdAt: row.createdAt,
|
|
78
|
+
updatedAt: row.updatedAt,
|
|
79
|
+
};
|
|
80
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type {ShipfoxModule} from '@shipfox/node-module';
|
|
2
|
+
import {db, migrationsPath} from '#db/index.js';
|
|
3
|
+
import {agentE2eRoutes} from '#presentation/e2eRoutes/index.js';
|
|
4
|
+
import {routes} from '#presentation/index.js';
|
|
5
|
+
|
|
6
|
+
export {
|
|
7
|
+
type AgentConfigResolutionContext,
|
|
8
|
+
type AgentDefaultsResolver,
|
|
9
|
+
type AgentWorkspaceSettings,
|
|
10
|
+
buildModelProviderCatalog,
|
|
11
|
+
type ContextualAgentConfig,
|
|
12
|
+
catalogDefaultAgentResolver,
|
|
13
|
+
createCustomModelProviderConfig,
|
|
14
|
+
createWorkspaceAgentDefaultsResolver,
|
|
15
|
+
deleteModelProviderConfig,
|
|
16
|
+
InvalidAgentModelError,
|
|
17
|
+
InvalidCredentialFieldsError,
|
|
18
|
+
type ModelProviderConfig,
|
|
19
|
+
ModelProviderConfigNotFoundError,
|
|
20
|
+
ModelProviderValidationError,
|
|
21
|
+
ModelProviderValidationUnavailableError,
|
|
22
|
+
type ResolvedAgentConfig,
|
|
23
|
+
type ResolveRuntimeCredentialsParams,
|
|
24
|
+
resolveAgentConfig,
|
|
25
|
+
resolveRuntimeCredentials,
|
|
26
|
+
testAndSaveModelProviderConfig,
|
|
27
|
+
UnsupportedModelProviderError,
|
|
28
|
+
updateCustomModelProviderConfig,
|
|
29
|
+
} from '#core/index.js';
|
|
30
|
+
export {
|
|
31
|
+
getAgentWorkspaceSettings,
|
|
32
|
+
getModelProviderConfig,
|
|
33
|
+
listModelProviderConfigs,
|
|
34
|
+
setDefaultModelProvider,
|
|
35
|
+
upsertModelProviderConfig,
|
|
36
|
+
} from '#db/index.js';
|
|
37
|
+
|
|
38
|
+
export const agentModule: ShipfoxModule = {
|
|
39
|
+
name: 'agent',
|
|
40
|
+
database: {db, migrationsPath},
|
|
41
|
+
routes,
|
|
42
|
+
e2eRoutes: [agentE2eRoutes],
|
|
43
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {agentRuntimeConfigResolvedCount, modelProviderValidationCount} from './instance.js';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type {SupportedModelProviderId} from '@shipfox/api-agent-dto';
|
|
2
|
+
import {instanceMetrics} from '@shipfox/node-opentelemetry';
|
|
3
|
+
|
|
4
|
+
const meter = instanceMetrics.getMeter('agent');
|
|
5
|
+
|
|
6
|
+
export const modelProviderValidationCount = meter.createCounter<{
|
|
7
|
+
model_provider: SupportedModelProviderId | 'custom';
|
|
8
|
+
outcome: 'succeeded' | 'failed';
|
|
9
|
+
}>('model_provider_validation_attempted', {
|
|
10
|
+
description: 'Model provider credential test attempts by model provider and outcome',
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export const agentRuntimeConfigResolvedCount = meter.createCounter<{
|
|
14
|
+
source: 'workspace' | 'instance';
|
|
15
|
+
outcome: 'resolved' | 'unavailable' | 'decryption_failed';
|
|
16
|
+
}>('agent_runtime_config_resolved', {
|
|
17
|
+
description: 'Lease-scoped agent runtime credential resolution by source and outcome',
|
|
18
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
CustomModelProviderConfigDto,
|
|
3
|
+
ModelProviderConfigDto,
|
|
4
|
+
ModelProviderConfigResponseDto,
|
|
5
|
+
} from '@shipfox/api-agent-dto';
|
|
6
|
+
import type {ModelProviderConfig} from '#core/index.js';
|
|
7
|
+
|
|
8
|
+
export function toModelProviderConfigDto(config: ModelProviderConfig): ModelProviderConfigDto {
|
|
9
|
+
return {
|
|
10
|
+
kind: 'builtin',
|
|
11
|
+
provider_id: config.providerId,
|
|
12
|
+
default_model: config.defaultModel,
|
|
13
|
+
created_at: config.createdAt.toISOString(),
|
|
14
|
+
updated_at: config.updatedAt.toISOString(),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function toCustomModelProviderConfigDto(
|
|
19
|
+
config: ModelProviderConfig,
|
|
20
|
+
): CustomModelProviderConfigDto {
|
|
21
|
+
return {
|
|
22
|
+
kind: 'custom',
|
|
23
|
+
provider_id: config.providerId,
|
|
24
|
+
display_name: config.displayName ?? config.providerId,
|
|
25
|
+
api: config.api ?? 'openai-responses',
|
|
26
|
+
base_url: config.baseUrl ?? '',
|
|
27
|
+
headers: config.headers ?? [],
|
|
28
|
+
secret_header_names: [...(config.secretHeaderNames ?? [])].sort(),
|
|
29
|
+
models: config.models ?? [],
|
|
30
|
+
default_model: config.defaultModel,
|
|
31
|
+
created_at: config.createdAt.toISOString(),
|
|
32
|
+
updated_at: config.updatedAt.toISOString(),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function toModelProviderConfigResponseDto(
|
|
37
|
+
config: ModelProviderConfig,
|
|
38
|
+
): ModelProviderConfigResponseDto {
|
|
39
|
+
if (config.kind === 'custom') return toCustomModelProviderConfigDto(config);
|
|
40
|
+
return toModelProviderConfigDto(config);
|
|
41
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import {closeApp, createApp} from '@shipfox/node-fastify';
|
|
2
|
+
import {agentE2eRoutes} from './index.js';
|
|
3
|
+
|
|
4
|
+
describe('agent e2e routes', () => {
|
|
5
|
+
afterEach(async () => {
|
|
6
|
+
await closeApp();
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it('rejects malformed workspace ids through route validation', async () => {
|
|
10
|
+
const app = await createApp({routes: [agentE2eRoutes], swagger: false});
|
|
11
|
+
|
|
12
|
+
const res = await app.inject({
|
|
13
|
+
method: 'POST',
|
|
14
|
+
url: '/agent/model-provider',
|
|
15
|
+
payload: {
|
|
16
|
+
workspace_id: 'not-a-uuid',
|
|
17
|
+
provider_id: 'anthropic',
|
|
18
|
+
api_key: 'sk-e2e-placeholder',
|
|
19
|
+
default_model: 'claude-opus-4-8',
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
expect(res.statusCode).toBe(400);
|
|
24
|
+
expect(res.json()).toMatchObject({code: 'validation-error'});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('rejects default models outside the Anthropic catalog', async () => {
|
|
28
|
+
const app = await createApp({routes: [agentE2eRoutes], swagger: false});
|
|
29
|
+
|
|
30
|
+
const res = await app.inject({
|
|
31
|
+
method: 'POST',
|
|
32
|
+
url: '/agent/model-provider',
|
|
33
|
+
payload: {
|
|
34
|
+
workspace_id: crypto.randomUUID(),
|
|
35
|
+
provider_id: 'anthropic',
|
|
36
|
+
api_key: 'sk-e2e-placeholder',
|
|
37
|
+
default_model: 'missing-model',
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
expect(res.statusCode).toBe(400);
|
|
42
|
+
expect(res.json()).toMatchObject({
|
|
43
|
+
code: 'unsupported-model',
|
|
44
|
+
details: {default_model: 'missing-model'},
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
});
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import {DEFAULT_AGENT_THINKING, getModelProviderEntry} from '@shipfox/api-agent-dto';
|
|
2
|
+
import {setSecrets} from '@shipfox/api-secrets';
|
|
3
|
+
import {ClientError, defineRoute} from '@shipfox/node-fastify';
|
|
4
|
+
import {z} from 'zod';
|
|
5
|
+
import {agentSystemNamespace} from '#core/credential-fingerprints.js';
|
|
6
|
+
import {listHarnessProviderModels} from '#core/harness/registry.js';
|
|
7
|
+
import {upsertModelProviderConfig} from '#db/index.js';
|
|
8
|
+
|
|
9
|
+
const createE2eModelProviderBodySchema = z.object({
|
|
10
|
+
workspace_id: z.string().uuid(),
|
|
11
|
+
provider_id: z.literal('anthropic'),
|
|
12
|
+
api_key: z.string().min(1),
|
|
13
|
+
default_model: z.string().min(1).optional(),
|
|
14
|
+
set_as_default: z.boolean().optional(),
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const createE2eModelProviderResponseSchema = z.object({
|
|
18
|
+
provider_id: z.literal('anthropic'),
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
export const createE2eModelProviderRoute = defineRoute({
|
|
22
|
+
method: 'POST',
|
|
23
|
+
path: '/model-provider',
|
|
24
|
+
description: 'Create an Anthropic model provider config for E2E tests.',
|
|
25
|
+
schema: {
|
|
26
|
+
body: createE2eModelProviderBodySchema,
|
|
27
|
+
response: {201: createE2eModelProviderResponseSchema},
|
|
28
|
+
},
|
|
29
|
+
handler: async (request, reply) => {
|
|
30
|
+
const entry = getModelProviderEntry(request.body.provider_id);
|
|
31
|
+
if (entry === undefined || entry.default_model === null) {
|
|
32
|
+
throw new ClientError('Unsupported E2E model provider', 'unsupported-model-provider', {
|
|
33
|
+
status: 400,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
const defaultModel = request.body.default_model ?? entry.default_model;
|
|
37
|
+
const supportedModels = listHarnessProviderModels('claude', request.body.provider_id);
|
|
38
|
+
if (!supportedModels.some((model) => model.id === defaultModel)) {
|
|
39
|
+
throw new ClientError('Unsupported Anthropic default model', 'unsupported-model', {
|
|
40
|
+
status: 400,
|
|
41
|
+
details: {default_model: defaultModel},
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
await setSecrets({
|
|
46
|
+
workspaceId: request.body.workspace_id,
|
|
47
|
+
namespace: agentSystemNamespace(request.body.provider_id),
|
|
48
|
+
values: {API_KEY: request.body.api_key},
|
|
49
|
+
});
|
|
50
|
+
await upsertModelProviderConfig({
|
|
51
|
+
workspaceId: request.body.workspace_id,
|
|
52
|
+
providerId: request.body.provider_id,
|
|
53
|
+
defaultModel,
|
|
54
|
+
defaultThinking: DEFAULT_AGENT_THINKING,
|
|
55
|
+
setAsDefault: request.body.set_as_default,
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
reply.code(201);
|
|
59
|
+
return {provider_id: request.body.provider_id};
|
|
60
|
+
},
|
|
61
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {agentRoutes as routes} from './routes/index.js';
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createCustomModelProviderBodySchema,
|
|
3
|
+
customModelProviderConfigDtoSchema,
|
|
4
|
+
} from '@shipfox/api-agent-dto';
|
|
5
|
+
import {requireWorkspaceAccess} from '@shipfox/api-auth-context';
|
|
6
|
+
import {defineRoute} from '@shipfox/node-fastify';
|
|
7
|
+
import {z} from 'zod';
|
|
8
|
+
import {createCustomModelProviderConfig} from '#core/index.js';
|
|
9
|
+
import {toCustomModelProviderConfigDto} from '#presentation/dto/index.js';
|
|
10
|
+
import {translateModelProviderRouteError} from './errors.js';
|
|
11
|
+
|
|
12
|
+
export const createCustomModelProviderRoute = defineRoute({
|
|
13
|
+
method: 'POST',
|
|
14
|
+
path: '/custom-model-providers',
|
|
15
|
+
description: 'Create a custom model provider configuration for a workspace',
|
|
16
|
+
schema: {
|
|
17
|
+
params: z.object({workspaceId: z.string().uuid()}),
|
|
18
|
+
body: createCustomModelProviderBodySchema,
|
|
19
|
+
response: {
|
|
20
|
+
200: customModelProviderConfigDtoSchema,
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
errorHandler: translateModelProviderRouteError,
|
|
24
|
+
handler: async (request, reply) => {
|
|
25
|
+
const {workspaceId} = request.params;
|
|
26
|
+
const abortController = new AbortController();
|
|
27
|
+
let responseFinished = false;
|
|
28
|
+
reply.raw.on('finish', () => {
|
|
29
|
+
responseFinished = true;
|
|
30
|
+
});
|
|
31
|
+
reply.raw.on('close', () => {
|
|
32
|
+
if (!responseFinished) abortController.abort();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
requireWorkspaceAccess({request, workspaceId});
|
|
36
|
+
|
|
37
|
+
const config = await createCustomModelProviderConfig({
|
|
38
|
+
workspaceId,
|
|
39
|
+
body: request.body,
|
|
40
|
+
signal: abortController.signal,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
return toCustomModelProviderConfigDto(config);
|
|
44
|
+
},
|
|
45
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import {modelProviderRefSchema} from '@shipfox/api-agent-dto';
|
|
2
|
+
import {requireWorkspaceAccess} from '@shipfox/api-auth-context';
|
|
3
|
+
import {ClientError, defineRoute} from '@shipfox/node-fastify';
|
|
4
|
+
import {z} from 'zod';
|
|
5
|
+
import {deleteModelProviderConfig} from '#core/index.js';
|
|
6
|
+
|
|
7
|
+
export const deleteModelProviderConfigRoute = defineRoute({
|
|
8
|
+
method: 'DELETE',
|
|
9
|
+
path: '/model-providers/:providerId',
|
|
10
|
+
description: 'Delete a model provider configuration for a workspace',
|
|
11
|
+
schema: {
|
|
12
|
+
params: z.object({
|
|
13
|
+
workspaceId: z.string().uuid(),
|
|
14
|
+
providerId: modelProviderRefSchema,
|
|
15
|
+
}),
|
|
16
|
+
response: {
|
|
17
|
+
204: z.void(),
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
handler: async (request, reply) => {
|
|
21
|
+
const {workspaceId, providerId} = request.params;
|
|
22
|
+
requireWorkspaceAccess({request, workspaceId});
|
|
23
|
+
|
|
24
|
+
const deleted = await deleteModelProviderConfig({workspaceId, providerId});
|
|
25
|
+
if (!deleted) {
|
|
26
|
+
throw new ClientError('Model provider configuration not found', 'not-found', {status: 404});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
reply.code(204);
|
|
30
|
+
},
|
|
31
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import {
|
|
2
|
+
discoverCustomModelProviderModelsBySlugBodySchema,
|
|
3
|
+
discoverCustomModelProviderModelsResponseSchema,
|
|
4
|
+
modelProviderRefSchema,
|
|
5
|
+
} from '@shipfox/api-agent-dto';
|
|
6
|
+
import {requireWorkspaceAccess} from '@shipfox/api-auth-context';
|
|
7
|
+
import {defineRoute} from '@shipfox/node-fastify';
|
|
8
|
+
import {z} from 'zod';
|
|
9
|
+
import {
|
|
10
|
+
discoverCustomModelProviderModels,
|
|
11
|
+
resolveCustomModelProviderDiscoveryParams,
|
|
12
|
+
} from '#core/index.js';
|
|
13
|
+
import {translateModelProviderRouteError} from './errors.js';
|
|
14
|
+
|
|
15
|
+
export const discoverCustomModelProviderModelsBySlugRoute = defineRoute({
|
|
16
|
+
method: 'POST',
|
|
17
|
+
path: '/custom-model-providers/:slug/discover-models',
|
|
18
|
+
description: 'Discover models for a stored custom model provider configuration',
|
|
19
|
+
schema: {
|
|
20
|
+
params: z.object({
|
|
21
|
+
workspaceId: z.string().uuid(),
|
|
22
|
+
slug: modelProviderRefSchema,
|
|
23
|
+
}),
|
|
24
|
+
body: discoverCustomModelProviderModelsBySlugBodySchema,
|
|
25
|
+
response: {
|
|
26
|
+
200: discoverCustomModelProviderModelsResponseSchema,
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
errorHandler: translateModelProviderRouteError,
|
|
30
|
+
handler: async (request) => {
|
|
31
|
+
const {workspaceId, slug} = request.params;
|
|
32
|
+
requireWorkspaceAccess({request, workspaceId});
|
|
33
|
+
|
|
34
|
+
const discoveryParams = await resolveCustomModelProviderDiscoveryParams({
|
|
35
|
+
workspaceId,
|
|
36
|
+
providerId: slug,
|
|
37
|
+
body: request.body ?? {},
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
return await discoverCustomModelProviderModels(discoveryParams);
|
|
41
|
+
},
|
|
42
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import {
|
|
2
|
+
discoverCustomModelProviderModelsBodySchema,
|
|
3
|
+
discoverCustomModelProviderModelsResponseSchema,
|
|
4
|
+
} from '@shipfox/api-agent-dto';
|
|
5
|
+
import {requireWorkspaceAccess} from '@shipfox/api-auth-context';
|
|
6
|
+
import {defineRoute} from '@shipfox/node-fastify';
|
|
7
|
+
import {z} from 'zod';
|
|
8
|
+
import {discoverCustomModelProviderModels} from '#core/index.js';
|
|
9
|
+
import {translateModelProviderRouteError} from './errors.js';
|
|
10
|
+
|
|
11
|
+
export const discoverCustomModelProviderModelsRoute = defineRoute({
|
|
12
|
+
method: 'POST',
|
|
13
|
+
path: '/custom-model-providers/discover-models',
|
|
14
|
+
description: 'Discover models exposed by a custom model provider endpoint',
|
|
15
|
+
schema: {
|
|
16
|
+
params: z.object({workspaceId: z.string().uuid()}),
|
|
17
|
+
body: discoverCustomModelProviderModelsBodySchema,
|
|
18
|
+
response: {
|
|
19
|
+
200: discoverCustomModelProviderModelsResponseSchema,
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
errorHandler: translateModelProviderRouteError,
|
|
23
|
+
handler: async (request) => {
|
|
24
|
+
const {workspaceId} = request.params;
|
|
25
|
+
requireWorkspaceAccess({request, workspaceId});
|
|
26
|
+
|
|
27
|
+
return await discoverCustomModelProviderModels(request.body);
|
|
28
|
+
},
|
|
29
|
+
});
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import {getModelProviderCredentialKeys} from '@shipfox/api-agent-dto';
|
|
2
|
+
import {SecretValueTooLargeError, WorkspaceSecretCapExceededError} from '@shipfox/api-secrets';
|
|
3
|
+
import {EgressDeniedError} from '@shipfox/node-egress-guard';
|
|
4
|
+
import {ClientError} from '@shipfox/node-fastify';
|
|
5
|
+
import {
|
|
6
|
+
CustomModelProviderConfigNotFoundError,
|
|
7
|
+
CustomModelProviderSlugCollisionError,
|
|
8
|
+
CustomModelProviderStoredSecretBaseUrlChangeError,
|
|
9
|
+
InvalidAgentModelError,
|
|
10
|
+
InvalidCredentialFieldsError,
|
|
11
|
+
InvalidCustomModelProviderHeaderKeepError,
|
|
12
|
+
ModelProviderConfigNotFoundError,
|
|
13
|
+
ModelProviderValidationError,
|
|
14
|
+
UnsupportedModelProviderError,
|
|
15
|
+
} from '#core/index.js';
|
|
16
|
+
|
|
17
|
+
export function translateModelProviderRouteError(error: unknown): never {
|
|
18
|
+
if (error instanceof ModelProviderValidationError) {
|
|
19
|
+
throw new ClientError(error.sanitizedMessage, 'provider-validation-failed', {
|
|
20
|
+
status: 422,
|
|
21
|
+
details: {
|
|
22
|
+
provider_id: error.providerId,
|
|
23
|
+
message: error.sanitizedMessage,
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (error instanceof EgressDeniedError) {
|
|
29
|
+
throw new ClientError('Egress denied', 'egress-denied', {
|
|
30
|
+
status: 400,
|
|
31
|
+
details: {
|
|
32
|
+
reason: error.reason,
|
|
33
|
+
target: error.target,
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (error instanceof CustomModelProviderSlugCollisionError) {
|
|
39
|
+
throw new ClientError('Custom model provider slug already exists', 'slug-collision', {
|
|
40
|
+
status: 409,
|
|
41
|
+
details: {provider_id: error.providerId},
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (error instanceof CustomModelProviderConfigNotFoundError) {
|
|
46
|
+
throw new ClientError('Custom model provider configuration not found', 'not-found', {
|
|
47
|
+
status: 404,
|
|
48
|
+
details: {provider_id: error.providerId},
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (error instanceof InvalidCustomModelProviderHeaderKeepError) {
|
|
53
|
+
throw new ClientError('Invalid kept secret header', 'invalid-header-keep', {
|
|
54
|
+
status: 422,
|
|
55
|
+
details: {provider_id: error.providerId, name: error.headerName},
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (error instanceof CustomModelProviderStoredSecretBaseUrlChangeError) {
|
|
60
|
+
throw new ClientError(
|
|
61
|
+
'Stored custom model provider secrets cannot be reused with a changed base URL',
|
|
62
|
+
'stored-secret-base-url-changed',
|
|
63
|
+
{
|
|
64
|
+
status: 422,
|
|
65
|
+
details: {provider_id: error.providerId},
|
|
66
|
+
},
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (error instanceof InvalidCredentialFieldsError) {
|
|
71
|
+
throw new ClientError('Invalid credential fields', 'invalid-credential-fields', {
|
|
72
|
+
status: 422,
|
|
73
|
+
details: {
|
|
74
|
+
provider_id: error.providerId,
|
|
75
|
+
expected_keys: getModelProviderCredentialKeys(error.providerId) ?? [],
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (error instanceof InvalidAgentModelError) {
|
|
81
|
+
throw new ClientError('Invalid agent model', 'invalid-agent-model', {
|
|
82
|
+
status: 422,
|
|
83
|
+
details: {
|
|
84
|
+
harness: error.harness,
|
|
85
|
+
provider_id: error.providerId,
|
|
86
|
+
model: error.model,
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (error instanceof UnsupportedModelProviderError) {
|
|
92
|
+
throw new ClientError('Provider is not supported', 'provider-unsupported', {
|
|
93
|
+
status: 422,
|
|
94
|
+
details: {provider_id: error.providerId},
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (error instanceof ModelProviderConfigNotFoundError) {
|
|
99
|
+
throw new ClientError('Provider is not configured', 'provider-not-configured', {
|
|
100
|
+
status: 422,
|
|
101
|
+
details: {
|
|
102
|
+
provider_id: error.providerId,
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (error instanceof WorkspaceSecretCapExceededError) {
|
|
108
|
+
throw new ClientError('Workspace secret cap exceeded', 'workspace-secret-cap-exceeded', {
|
|
109
|
+
status: 409,
|
|
110
|
+
details: {cap: error.cap},
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (error instanceof SecretValueTooLargeError) {
|
|
115
|
+
throw new ClientError(error.message, 'value-too-large', {
|
|
116
|
+
status: 400,
|
|
117
|
+
details: {max_bytes: error.maxBytes},
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
throw error;
|
|
122
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import {AUTH_USER} from '@shipfox/api-auth-context';
|
|
2
|
+
import type {RouteGroup} from '@shipfox/node-fastify';
|
|
3
|
+
import {createCustomModelProviderRoute} from './create-custom-model-provider.js';
|
|
4
|
+
import {deleteModelProviderConfigRoute} from './delete-model-provider-config.js';
|
|
5
|
+
import {discoverCustomModelProviderModelsRoute} from './discover-custom-model-provider-models.js';
|
|
6
|
+
import {discoverCustomModelProviderModelsBySlugRoute} from './discover-custom-model-provider-models-by-slug.js';
|
|
7
|
+
import {listModelProviderCatalogRoute} from './list-model-provider-catalog.js';
|
|
8
|
+
import {listModelProviderConfigsRoute} from './list-model-provider-configs.js';
|
|
9
|
+
import {setDefaultHarnessRoute} from './set-default-harness.js';
|
|
10
|
+
import {setDefaultModelProviderRoute} from './set-default-model-provider.js';
|
|
11
|
+
import {updateCustomModelProviderRoute} from './update-custom-model-provider.js';
|
|
12
|
+
import {updateModelProviderDefaultModelRoute} from './update-model-provider-default-model.js';
|
|
13
|
+
import {upsertModelProviderConfigRoute} from './upsert-model-provider-config.js';
|
|
14
|
+
|
|
15
|
+
export const agentRoutes: RouteGroup[] = [
|
|
16
|
+
{
|
|
17
|
+
prefix: '/workspaces/:workspaceId/agent',
|
|
18
|
+
auth: AUTH_USER,
|
|
19
|
+
routes: [
|
|
20
|
+
listModelProviderConfigsRoute,
|
|
21
|
+
createCustomModelProviderRoute,
|
|
22
|
+
discoverCustomModelProviderModelsRoute,
|
|
23
|
+
discoverCustomModelProviderModelsBySlugRoute,
|
|
24
|
+
updateCustomModelProviderRoute,
|
|
25
|
+
upsertModelProviderConfigRoute,
|
|
26
|
+
updateModelProviderDefaultModelRoute,
|
|
27
|
+
deleteModelProviderConfigRoute,
|
|
28
|
+
setDefaultHarnessRoute,
|
|
29
|
+
setDefaultModelProviderRoute,
|
|
30
|
+
],
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
prefix: '/agent',
|
|
34
|
+
auth: AUTH_USER,
|
|
35
|
+
routes: [listModelProviderCatalogRoute],
|
|
36
|
+
},
|
|
37
|
+
];
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {modelProviderCatalogResponseSchema} from '@shipfox/api-agent-dto';
|
|
2
|
+
import {defineRoute} from '@shipfox/node-fastify';
|
|
3
|
+
import {buildModelProviderCatalog} from '#core/index.js';
|
|
4
|
+
|
|
5
|
+
export const listModelProviderCatalogRoute = defineRoute({
|
|
6
|
+
method: 'GET',
|
|
7
|
+
path: '/model-provider-catalog',
|
|
8
|
+
description: 'List available model providers and models',
|
|
9
|
+
schema: {
|
|
10
|
+
response: {
|
|
11
|
+
200: modelProviderCatalogResponseSchema,
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
handler: () => ({providers: buildModelProviderCatalog()}),
|
|
15
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import {listModelProviderConfigsResponseSchema} from '@shipfox/api-agent-dto';
|
|
2
|
+
import {requireWorkspaceAccess} from '@shipfox/api-auth-context';
|
|
3
|
+
import {defineRoute} from '@shipfox/node-fastify';
|
|
4
|
+
import {z} from 'zod';
|
|
5
|
+
import {getAgentWorkspaceSettings, listModelProviderConfigs} from '#db/index.js';
|
|
6
|
+
import {toModelProviderConfigResponseDto} from '#presentation/dto/index.js';
|
|
7
|
+
|
|
8
|
+
export const listModelProviderConfigsRoute = defineRoute({
|
|
9
|
+
method: 'GET',
|
|
10
|
+
path: '/model-providers',
|
|
11
|
+
description: 'List model provider configurations for a workspace',
|
|
12
|
+
schema: {
|
|
13
|
+
params: z.object({workspaceId: z.string().uuid()}),
|
|
14
|
+
response: {
|
|
15
|
+
200: listModelProviderConfigsResponseSchema,
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
handler: async (request) => {
|
|
19
|
+
const {workspaceId} = request.params;
|
|
20
|
+
requireWorkspaceAccess({request, workspaceId});
|
|
21
|
+
|
|
22
|
+
const [configs, settings] = await Promise.all([
|
|
23
|
+
listModelProviderConfigs(workspaceId),
|
|
24
|
+
getAgentWorkspaceSettings(workspaceId),
|
|
25
|
+
]);
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
configs: configs.map(toModelProviderConfigResponseDto),
|
|
29
|
+
default_harness_id: settings?.defaultHarnessId ?? null,
|
|
30
|
+
default_provider_id: settings?.defaultProviderId ?? null,
|
|
31
|
+
};
|
|
32
|
+
},
|
|
33
|
+
});
|