@shipfox/api-definitions 6.0.0 → 8.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 (94) hide show
  1. package/.turbo/turbo-build.log +11 -13
  2. package/CHANGELOG.md +27 -0
  3. package/dist/config.d.ts +0 -4
  4. package/dist/config.d.ts.map +1 -1
  5. package/dist/config.js +1 -14
  6. package/dist/config.js.map +1 -1
  7. package/dist/core/index.d.ts +1 -1
  8. package/dist/core/index.d.ts.map +1 -1
  9. package/dist/core/index.js.map +1 -1
  10. package/dist/core/integrations.d.ts +1 -1
  11. package/dist/core/integrations.d.ts.map +1 -1
  12. package/dist/core/integrations.js +1 -1
  13. package/dist/core/integrations.js.map +1 -1
  14. package/dist/core/parse-definition.d.ts +3 -3
  15. package/dist/core/parse-definition.d.ts.map +1 -1
  16. package/dist/core/parse-definition.js.map +1 -1
  17. package/dist/core/sync-definitions.d.ts +2 -0
  18. package/dist/core/sync-definitions.d.ts.map +1 -1
  19. package/dist/core/sync-definitions.js +9 -3
  20. package/dist/core/sync-definitions.js.map +1 -1
  21. package/dist/core/validate-definition.d.ts +3 -3
  22. package/dist/core/validate-definition.d.ts.map +1 -1
  23. package/dist/core/validate-definition.js +3 -3
  24. package/dist/core/validate-definition.js.map +1 -1
  25. package/dist/core/workflow-model/normalize-jobs.d.ts +2 -2
  26. package/dist/core/workflow-model/normalize-jobs.d.ts.map +1 -1
  27. package/dist/core/workflow-model/normalize-jobs.js +9 -11
  28. package/dist/core/workflow-model/normalize-jobs.js.map +1 -1
  29. package/dist/core/workflow-model/normalize-workflow-document.d.ts +3 -3
  30. package/dist/core/workflow-model/normalize-workflow-document.d.ts.map +1 -1
  31. package/dist/core/workflow-model/normalize-workflow-document.js +2 -4
  32. package/dist/core/workflow-model/normalize-workflow-document.js.map +1 -1
  33. package/dist/index.d.ts +5 -3
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +3 -2
  36. package/dist/index.js.map +1 -1
  37. package/dist/presentation/routes/create-definition.d.ts +4 -2
  38. package/dist/presentation/routes/create-definition.d.ts.map +1 -1
  39. package/dist/presentation/routes/create-definition.js +5 -1
  40. package/dist/presentation/routes/create-definition.js.map +1 -1
  41. package/dist/presentation/routes/get-definition.d.ts +1 -1
  42. package/dist/presentation/routes/get-definition.d.ts.map +1 -1
  43. package/dist/presentation/routes/get-definition.js.map +1 -1
  44. package/dist/presentation/routes/index.js +2 -2
  45. package/dist/presentation/routes/index.js.map +1 -1
  46. package/dist/presentation/routes/list-definitions.d.ts +1 -1
  47. package/dist/presentation/routes/list-definitions.d.ts.map +1 -1
  48. package/dist/presentation/routes/list-definitions.js.map +1 -1
  49. package/dist/presentation/routes/project-access.d.ts +1 -1
  50. package/dist/presentation/routes/project-access.d.ts.map +1 -1
  51. package/dist/presentation/routes/project-access.js.map +1 -1
  52. package/dist/presentation/routes/validate-definition.d.ts +2 -1
  53. package/dist/presentation/routes/validate-definition.d.ts.map +1 -1
  54. package/dist/presentation/routes/validate-definition.js +26 -22
  55. package/dist/presentation/routes/validate-definition.js.map +1 -1
  56. package/dist/temporal/activities/sync-activities.d.ts +3 -2
  57. package/dist/temporal/activities/sync-activities.d.ts.map +1 -1
  58. package/dist/temporal/activities/sync-activities.js +8 -7
  59. package/dist/temporal/activities/sync-activities.js.map +1 -1
  60. package/dist/temporal/workflows/index.bundle.js +17195 -3337
  61. package/dist/tsconfig.test.tsbuildinfo +1 -1
  62. package/package.json +10 -28
  63. package/src/config.ts +1 -19
  64. package/src/core/index.ts +4 -1
  65. package/src/core/integrations.ts +1 -1
  66. package/src/core/parse-definition.test.ts +6 -1
  67. package/src/core/parse-definition.ts +3 -3
  68. package/src/core/sync-definitions.test.ts +9 -2
  69. package/src/core/sync-definitions.ts +13 -6
  70. package/src/core/validate-definition.test.ts +18 -4
  71. package/src/core/validate-definition.ts +5 -6
  72. package/src/core/workflow-model/normalize-jobs.ts +22 -23
  73. package/src/core/workflow-model/normalize-workflow-document.test.ts +37 -18
  74. package/src/core/workflow-model/normalize-workflow-document.ts +4 -9
  75. package/src/db/definitions.test.ts +2 -1
  76. package/src/db/schema/definitions.test.ts +2 -1
  77. package/src/index.ts +7 -4
  78. package/src/presentation/dto/definition.test.ts +2 -1
  79. package/src/presentation/routes/create-definition.test.ts +10 -3
  80. package/src/presentation/routes/create-definition.ts +7 -3
  81. package/src/presentation/routes/get-definition.test.ts +1 -1
  82. package/src/presentation/routes/get-definition.ts +1 -1
  83. package/src/presentation/routes/index.test.ts +6 -2
  84. package/src/presentation/routes/index.ts +2 -2
  85. package/src/presentation/routes/list-definitions.test.ts +1 -1
  86. package/src/presentation/routes/list-definitions.ts +1 -1
  87. package/src/presentation/routes/project-access.ts +1 -1
  88. package/src/presentation/routes/validate-definition.test.ts +8 -2
  89. package/src/presentation/routes/validate-definition.ts +27 -22
  90. package/src/temporal/activities/sync-activities.test.ts +19 -8
  91. package/src/temporal/activities/sync-activities.ts +16 -6
  92. package/test/agent-validation-catalog.ts +25 -0
  93. package/test/factories/definition.ts +2 -1
  94. package/tsconfig.build.tsbuildinfo +1 -1
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@shipfox/api-definitions",
3
3
  "license": "MIT",
4
- "version": "6.0.0",
4
+ "version": "8.0.0",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/ShipfoxHQ/shipfox.git",
@@ -30,44 +30,26 @@
30
30
  "js-yaml": "^4.1.0",
31
31
  "yaml": "^2.8.3",
32
32
  "zod": "^4.4.3",
33
- "@shipfox/api-agent-dto": "6.0.0",
34
- "@shipfox/api-auth-context": "6.0.0",
33
+ "@shipfox/api-agent-dto": "8.0.0",
34
+ "@shipfox/api-auth-context": "7.1.0",
35
35
  "@shipfox/api-definitions-dto": "6.0.0",
36
- "@shipfox/api-integration-core-dto": "6.0.0",
37
- "@shipfox/api-projects-dto": "6.0.0",
36
+ "@shipfox/api-integration-core-dto": "8.0.0",
37
+ "@shipfox/api-projects-dto": "8.0.0",
38
38
  "@shipfox/api-secrets-dto": "6.0.0",
39
39
  "@shipfox/config": "1.2.2",
40
40
  "@shipfox/expression": "1.1.3",
41
41
  "@shipfox/inter-module": "0.2.0",
42
42
  "@shipfox/node-drizzle": "0.3.2",
43
- "@shipfox/node-fastify": "0.2.4",
44
- "@shipfox/node-module": "0.4.0",
45
- "@shipfox/node-opentelemetry": "0.5.2",
43
+ "@shipfox/node-fastify": "0.3.0",
44
+ "@shipfox/node-error-monitoring": "0.2.0",
45
+ "@shipfox/node-module": "0.5.0",
46
+ "@shipfox/node-opentelemetry": "0.6.0",
46
47
  "@shipfox/node-outbox": "0.2.4",
47
48
  "@shipfox/node-postgres": "0.4.2",
48
- "@shipfox/node-temporal": "0.3.2",
49
+ "@shipfox/node-temporal": "0.4.0",
49
50
  "@shipfox/runner-labels": "0.1.1",
50
51
  "@shipfox/workflow-document": "2.1.1"
51
52
  },
52
- "devDependencies": {
53
- "@temporalio/client": "1.18.1",
54
- "@temporalio/testing": "1.18.1",
55
- "@temporalio/worker": "1.18.1",
56
- "@types/js-yaml": "^4.0.9",
57
- "@types/pg": "^8.15.5",
58
- "drizzle-kit": "^0.31.10",
59
- "fastify": "^5.3.3",
60
- "fastify-type-provider-zod": "^6.0.0",
61
- "fishery": "^2.4.0",
62
- "@shipfox/api-integration-core": "6.0.0",
63
- "@shipfox/biome": "1.8.2",
64
- "@shipfox/depcruise": "1.0.2",
65
- "@shipfox/regex": "0.2.2",
66
- "@shipfox/swc": "1.2.6",
67
- "@shipfox/ts-config": "1.3.8",
68
- "@shipfox/typescript": "1.1.7",
69
- "@shipfox/vitest": "1.2.3"
70
- },
71
53
  "scripts": {
72
54
  "build": "shipfox-swc && shipfox-temporal-bundle dist/temporal/workflows/index.js",
73
55
  "check": "shipfox-biome-check",
package/src/config.ts CHANGED
@@ -1,8 +1,4 @@
1
- import {
2
- buildHarnessToolDeploymentConfig,
3
- type HarnessToolDeploymentConfig,
4
- } from '@shipfox/api-agent-dto';
5
- import {bool, createConfig, str} from '@shipfox/config';
1
+ import {createConfig, str} from '@shipfox/config';
6
2
  import {findInvalidLabels, MAX_RUNNER_LABELS, parseLabelList} from '@shipfox/runner-labels';
7
3
 
8
4
  export const config = createConfig({
@@ -10,14 +6,6 @@ export const config = createConfig({
10
6
  desc: 'Default runner label(s) applied to workflow jobs that do not declare a "runner" at the job or workflow level. Set it to a comma-separated list, for example ubuntu-latest or ubuntu-latest,node-22. Leave it empty to require every workflow job to declare runner labels explicitly; with no value set, a job without a runner fails definition validation.',
11
7
  default: '',
12
8
  }),
13
- AGENT_PI_ENABLED_TOOL_PACKAGES: str({
14
- desc: 'Comma-separated optional Pi tool packages enabled for this deployment. Defaults to pi-web-access so Pi web access is available. Set it to an empty value to enable only Pi built-in tools. Accepted values: pi-web-access.',
15
- default: 'pi-web-access',
16
- }),
17
- AGENT_PI_WEB_SEARCH_ENABLED: bool({
18
- desc: 'Enables Pi web search tools when pi-web-access is enabled. Set it to false to disable web_search and get_search_content while keeping fetch_content available.',
19
- default: true,
20
- }),
21
9
  });
22
10
 
23
11
  export function parseDefinitionDefaultRunnerLabels(value: string): readonly string[] {
@@ -42,9 +30,3 @@ export function parseDefinitionDefaultRunnerLabels(value: string): readonly stri
42
30
  export const definitionDefaultRunnerLabels = parseDefinitionDefaultRunnerLabels(
43
31
  config.DEFINITION_DEFAULT_RUNNER_LABEL,
44
32
  );
45
-
46
- export const definitionHarnessToolDeploymentConfig: HarnessToolDeploymentConfig =
47
- buildHarnessToolDeploymentConfig({
48
- piEnabledToolPackages: config.AGENT_PI_ENABLED_TOOL_PACKAGES,
49
- piWebSearchEnabled: config.AGENT_PI_WEB_SEARCH_ENABLED,
50
- });
package/src/core/index.ts CHANGED
@@ -1,5 +1,8 @@
1
1
  export type * from './entities/index.js';
2
- export {DefinitionParseError, DefinitionSyncPermanentError} from './errors.js';
2
+ export {
3
+ DefinitionParseError,
4
+ DefinitionSyncPermanentError,
5
+ } from './errors.js';
3
6
  export {parseDefinition} from './parse-definition.js';
4
7
  export {
5
8
  classifySyncFailure,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  type IntegrationsModuleClient,
3
3
  integrationsInterModuleContract,
4
- } from '@shipfox/api-integration-core-dto';
4
+ } from '@shipfox/api-integration-core-dto/inter-module';
5
5
 
6
6
  export type DefinitionsSourceControl = {
7
7
  resolveRepository: IntegrationsModuleClient['resolveSourceRepository'];
@@ -1,11 +1,16 @@
1
1
  import {readFileSync} from 'node:fs';
2
2
  import {dirname, resolve} from 'node:path';
3
3
  import {fileURLToPath} from 'node:url';
4
+ import {agentValidationCatalog} from '#test/agent-validation-catalog.js';
4
5
  import {DefinitionParseError} from './errors.js';
5
- import {parseDefinition} from './parse-definition.js';
6
+ import {parseDefinition as parseDefinitionBase} from './parse-definition.js';
6
7
 
7
8
  const fixturesDir = resolve(dirname(fileURLToPath(import.meta.url)), '../../test/fixtures');
8
9
 
10
+ function parseDefinition(yaml: string, options = {}) {
11
+ return parseDefinitionBase(yaml, {agentValidationCatalog, ...options});
12
+ }
13
+
9
14
  function readFixture(name: string): string {
10
15
  return readFileSync(resolve(fixturesDir, name), 'utf-8');
11
16
  }
@@ -1,4 +1,4 @@
1
- import type {HarnessToolDeploymentConfig} from '@shipfox/api-agent-dto';
1
+ import type {AgentValidationCatalog} from '@shipfox/api-agent-dto/inter-module';
2
2
  import type {IntegrationValidationContext} from './entities/integration-context.js';
3
3
  import type {WorkflowDefinitionPayload} from './entities/workflow-definition.js';
4
4
  import {DefinitionParseError} from './errors.js';
@@ -6,9 +6,9 @@ import {validateDefinition} from './validate-definition.js';
6
6
 
7
7
  export function parseDefinition(
8
8
  yamlString: string,
9
- options?: {
9
+ options: {
10
10
  defaultRunnerLabels?: readonly string[];
11
- harnessToolDeploymentConfig?: HarnessToolDeploymentConfig;
11
+ agentValidationCatalog: AgentValidationCatalog;
12
12
  integrationValidationContext?: IntegrationValidationContext;
13
13
  },
14
14
  ): WorkflowDefinitionPayload {
@@ -1,16 +1,23 @@
1
1
  import type {IntegrationSourceControlService} from '@shipfox/api-integration-core';
2
- import {integrationsInterModuleContract} from '@shipfox/api-integration-core-dto';
2
+ import {integrationsInterModuleContract} from '@shipfox/api-integration-core-dto/inter-module';
3
3
  import {createInterModuleKnownError} from '@shipfox/inter-module';
4
4
  import {LOWERCASE_SHA256_HEX_RE} from '@shipfox/regex';
5
+ import {agentValidationCatalog} from '#test/agent-validation-catalog.js';
5
6
  import type {IntegrationValidationContext} from './entities/integration-context.js';
6
7
  import {DefinitionSyncPermanentError} from './errors.js';
7
8
  import {
8
9
  classifySyncFailure,
9
10
  discoverWorkflowFiles,
10
- fetchAndParseWorkflows,
11
+ fetchAndParseWorkflows as fetchAndParseWorkflowsBase,
11
12
  resolveSyncSource,
12
13
  } from './sync-definitions.js';
13
14
 
15
+ function fetchAndParseWorkflows(
16
+ params: Omit<Parameters<typeof fetchAndParseWorkflowsBase>[0], 'agentValidationCatalog'>,
17
+ ) {
18
+ return fetchAndParseWorkflowsBase({...params, agentValidationCatalog});
19
+ }
20
+
14
21
  const validYaml = `
15
22
  name: CI
16
23
  runner: ubuntu-latest
@@ -1,8 +1,7 @@
1
1
  import {createHash} from 'node:crypto';
2
- import {
3
- integrationsInterModuleContract,
4
- MAX_REPOSITORY_FILE_BYTES,
5
- } from '@shipfox/api-integration-core-dto';
2
+ import type {AgentValidationCatalog} from '@shipfox/api-agent-dto/inter-module';
3
+ import {MAX_REPOSITORY_FILE_BYTES} from '@shipfox/api-integration-core-dto';
4
+ import {integrationsInterModuleContract} from '@shipfox/api-integration-core-dto/inter-module';
6
5
  import {isInterModuleKnownError} from '@shipfox/inter-module';
7
6
  import {boundedMap} from '@shipfox/node-module';
8
7
  import type {IntegrationValidationContext} from './entities/integration-context.js';
@@ -84,6 +83,7 @@ export interface FetchAndParseWorkflowsParams extends SyncSourceContext {
84
83
  ref: string;
85
84
  paths: string[];
86
85
  onProgress?: ((path: string) => void) | undefined;
86
+ agentValidationCatalog: AgentValidationCatalog;
87
87
  loadIntegrationValidationContext?: (() => Promise<IntegrationValidationContext>) | undefined;
88
88
  }
89
89
 
@@ -112,7 +112,11 @@ export async function fetchAndParseWorkflows(
112
112
  }
113
113
 
114
114
  return {
115
- ...parseWorkflowSnapshot({path: snapshot.path, content: snapshot.content}),
115
+ ...parseWorkflowSnapshot({
116
+ path: snapshot.path,
117
+ content: snapshot.content,
118
+ agentValidationCatalog: params.agentValidationCatalog,
119
+ }),
116
120
  rawContent: snapshot.content,
117
121
  };
118
122
  },
@@ -131,6 +135,7 @@ export async function fetchAndParseWorkflows(
131
135
  parseWorkflowSnapshot({
132
136
  path: entry.path,
133
137
  content: entry.rawContent,
138
+ agentValidationCatalog: params.agentValidationCatalog,
134
139
  integrationValidationContext,
135
140
  }),
136
141
  );
@@ -140,12 +145,14 @@ function parseWorkflowSnapshot(params: {
140
145
  path: string;
141
146
  content: string;
142
147
  integrationValidationContext?: IntegrationValidationContext | undefined;
148
+ agentValidationCatalog: AgentValidationCatalog;
143
149
  }): ParsedWorkflow {
144
150
  try {
145
151
  const definition =
146
152
  params.integrationValidationContext === undefined
147
- ? parseDefinition(params.content)
153
+ ? parseDefinition(params.content, {agentValidationCatalog: params.agentValidationCatalog})
148
154
  : parseDefinition(params.content, {
155
+ agentValidationCatalog: params.agentValidationCatalog,
149
156
  integrationValidationContext: params.integrationValidationContext,
150
157
  });
151
158
  const contentHash = sha256Hex(params.content);
@@ -1,4 +1,9 @@
1
- import {validateDefinition} from './validate-definition.js';
1
+ import {agentValidationCatalog} from '#test/agent-validation-catalog.js';
2
+ import {validateDefinition as validateDefinitionBase} from './validate-definition.js';
3
+
4
+ function validateDefinition(yaml: string, options = {}) {
5
+ return validateDefinitionBase(yaml, {agentValidationCatalog, ...options});
6
+ }
2
7
 
3
8
  describe('validateDefinition', () => {
4
9
  test('valid YAML returns { valid: true, definition }', () => {
@@ -129,9 +134,18 @@ jobs:
129
134
  `;
130
135
 
131
136
  const result = validateDefinition(yaml, {
132
- harnessToolDeploymentConfig: {
133
- pi: {enabledToolPackages: ['pi-web-access'], webSearchEnabled: false},
134
- claude: {enabledToolPackages: []},
137
+ agentValidationCatalog: {
138
+ ...agentValidationCatalog,
139
+ harnesses: agentValidationCatalog.harnesses.map((harness) => {
140
+ if (harness.id !== 'pi') return harness;
141
+ return {
142
+ ...harness,
143
+ effective_tools: harness.effective_tools.filter(
144
+ (tool) =>
145
+ tool === 'fetch_content' || !['web_search', 'get_search_content'].includes(tool),
146
+ ),
147
+ };
148
+ }),
135
149
  },
136
150
  });
137
151
 
@@ -1,6 +1,6 @@
1
- import type {HarnessToolDeploymentConfig} from '@shipfox/api-agent-dto';
1
+ import type {AgentValidationCatalog} from '@shipfox/api-agent-dto/inter-module';
2
2
  import {InvalidWorkflowDocumentError} from '@shipfox/workflow-document';
3
- import {definitionDefaultRunnerLabels, definitionHarnessToolDeploymentConfig} from '../config.js';
3
+ import {definitionDefaultRunnerLabels} from '../config.js';
4
4
  import type {IntegrationValidationContext} from './entities/integration-context.js';
5
5
  import type {WorkflowDefinitionPayload} from './entities/workflow-definition.js';
6
6
  import {InvalidWorkflowModelError, normalizeWorkflowDocument} from './workflow-model/index.js';
@@ -16,16 +16,15 @@ export function validateDefinition(
16
16
  yamlContent: string,
17
17
  options: {
18
18
  defaultRunnerLabels?: readonly string[];
19
- harnessToolDeploymentConfig?: HarnessToolDeploymentConfig;
19
+ agentValidationCatalog: AgentValidationCatalog;
20
20
  integrationValidationContext?: IntegrationValidationContext;
21
- } = {},
21
+ },
22
22
  ): ValidationResult {
23
23
  try {
24
24
  const {document, stepSourceLocations} = parseWorkflowYamlWithLocations(yamlContent);
25
25
  const model = normalizeWorkflowDocument(document, {
26
26
  defaultRunnerLabels: options.defaultRunnerLabels ?? definitionDefaultRunnerLabels,
27
- harnessToolDeploymentConfig:
28
- options.harnessToolDeploymentConfig ?? definitionHarnessToolDeploymentConfig,
27
+ agentValidationCatalog: options.agentValidationCatalog,
29
28
  integrationValidationContext: options.integrationValidationContext,
30
29
  stepSourceLocations,
31
30
  });
@@ -1,10 +1,4 @@
1
- import {
2
- agentThinkingByHarness,
3
- getHarnessDescriptor,
4
- getModelProviderEntry,
5
- type HarnessToolDeploymentConfig,
6
- listEnabledHarnessTools,
7
- } from '@shipfox/api-agent-dto';
1
+ import type {AgentValidationCatalog} from '@shipfox/api-agent-dto/inter-module';
8
2
  import {
9
3
  type AvailabilitySite,
10
4
  buildTypedRootsEnvironment,
@@ -53,7 +47,7 @@ import {issue} from './validation-issue.js';
53
47
 
54
48
  export interface NormalizeContext {
55
49
  readonly defaultRunnerLabels: readonly string[];
56
- readonly harnessToolDeploymentConfig: HarnessToolDeploymentConfig;
50
+ readonly agentValidationCatalog: AgentValidationCatalog;
57
51
  readonly integrationValidationContext?: IntegrationValidationContext | undefined;
58
52
  }
59
53
 
@@ -719,7 +713,7 @@ function normalizeAgentStep(params: {
719
713
  stepIndex: params.stepIndex,
720
714
  issues: params.issues,
721
715
  validateLiteralProvider: providerTemplate === undefined,
722
- harnessToolDeploymentConfig: params.context.harnessToolDeploymentConfig,
716
+ agentValidationCatalog: params.context.agentValidationCatalog,
723
717
  });
724
718
  const integrations = normalizeAgentIntegrations({
725
719
  integrations: params.step.integrations,
@@ -755,7 +749,7 @@ function validateAgentStep(params: {
755
749
  stepIndex: number;
756
750
  issues: WorkflowModelValidationIssue[];
757
751
  validateLiteralProvider: boolean;
758
- harnessToolDeploymentConfig: HarnessToolDeploymentConfig;
752
+ agentValidationCatalog: AgentValidationCatalog;
759
753
  }): void {
760
754
  validateHarnessThinking(params);
761
755
  validateHarnessTools(params);
@@ -764,7 +758,7 @@ function validateAgentStep(params: {
764
758
  const providerId = params.step.provider;
765
759
  if (providerId === undefined) return;
766
760
 
767
- const provider = getModelProviderEntry(providerId);
761
+ const provider = params.agentValidationCatalog.providers.find((entry) => entry.id === providerId);
768
762
  const harness = params.step.harness;
769
763
  if (provider === undefined && harness === 'pi') return;
770
764
 
@@ -782,15 +776,19 @@ function validateAgentStep(params: {
782
776
 
783
777
  if (harness === undefined) return;
784
778
 
785
- const descriptor = getHarnessDescriptor(harness);
786
- if (descriptor.supportedProviderIds.includes(providerId)) return;
779
+ const descriptor = params.agentValidationCatalog.harnesses.find((entry) => entry.id === harness);
780
+ if (descriptor?.supported_provider_ids.includes(providerId)) return;
787
781
 
788
782
  params.issues.push(
789
783
  issue({
790
784
  code: 'harness-provider-incompatible',
791
- message: `Harness "${harness}" does not support provider: ${providerId}. Supported providers: ${descriptor.supportedProviderIds.join(', ')}.`,
785
+ message: `Harness "${harness}" does not support provider: ${providerId}. Supported providers: ${descriptor?.supported_provider_ids.join(', ') ?? ''}.`,
792
786
  path: ['jobs', params.sourceName, 'steps', params.stepIndex, 'provider'],
793
- details: {harness, provider: providerId, supportedProviders: descriptor.supportedProviderIds},
787
+ details: {
788
+ harness,
789
+ provider: providerId,
790
+ supportedProviders: descriptor?.supported_provider_ids ?? [],
791
+ },
794
792
  }),
795
793
  );
796
794
  }
@@ -800,7 +798,7 @@ function validateHarnessTools(params: {
800
798
  sourceName: string;
801
799
  stepIndex: number;
802
800
  issues: WorkflowModelValidationIssue[];
803
- harnessToolDeploymentConfig: HarnessToolDeploymentConfig;
801
+ agentValidationCatalog: AgentValidationCatalog;
804
802
  }): void {
805
803
  const {harness, tools} = params.step;
806
804
  if (tools === undefined) return;
@@ -818,9 +816,9 @@ function validateHarnessTools(params: {
818
816
  return;
819
817
  }
820
818
 
821
- const supportedTools = listEnabledHarnessTools(harness, params.harnessToolDeploymentConfig).map(
822
- (tool) => tool.name,
823
- );
819
+ const supportedTools =
820
+ params.agentValidationCatalog.harnesses.find((entry) => entry.id === harness)
821
+ ?.effective_tools ?? [];
824
822
  const supportedToolSet = new Set(supportedTools);
825
823
 
826
824
  tools.forEach((tool, toolIndex) => {
@@ -842,14 +840,15 @@ function validateHarnessThinking(params: {
842
840
  sourceName: string;
843
841
  stepIndex: number;
844
842
  issues: WorkflowModelValidationIssue[];
843
+ agentValidationCatalog: AgentValidationCatalog;
845
844
  }): void {
846
845
  const {harness, thinking} = params.step;
847
846
  if (harness === undefined || thinking === undefined) return;
848
847
 
849
- const thinkingSchema = agentThinkingByHarness[harness];
850
- if (thinkingSchema.safeParse(thinking).success) return;
851
-
852
- const supportedLevels = thinkingSchema.options;
848
+ const supportedLevels =
849
+ params.agentValidationCatalog.harnesses.find((entry) => entry.id === harness)
850
+ ?.thinking_levels ?? [];
851
+ if (supportedLevels.includes(thinking)) return;
853
852
  params.issues.push(
854
853
  issue({
855
854
  code: 'harness-thinking-incompatible',
@@ -1,4 +1,5 @@
1
1
  import type {WorkflowDocument} from '@shipfox/workflow-document';
2
+ import {agentValidationCatalog} from '#test/agent-validation-catalog.js';
2
3
  import type {IntegrationValidationContext} from '../entities/integration-context.js';
3
4
  import {InvalidWorkflowModelError} from './invalid-workflow-model-error.js';
4
5
  import {DEFAULT_JOB_CHECKOUT} from './normalize-job-checkout.js';
@@ -6,14 +7,22 @@ import {normalizeWorkflowDocument as normalizeWorkflowDocumentBase} from './norm
6
7
 
7
8
  function normalizeWorkflowDocument(
8
9
  document: WorkflowDocument,
9
- options?: Parameters<typeof normalizeWorkflowDocumentBase>[1],
10
+ options?: Omit<Parameters<typeof normalizeWorkflowDocumentBase>[1], 'agentValidationCatalog'> &
11
+ Partial<Pick<Parameters<typeof normalizeWorkflowDocumentBase>[1], 'agentValidationCatalog'>>,
10
12
  ) {
11
- return normalizeWorkflowDocumentBase({runner: 'ubuntu-latest', ...document}, options);
13
+ return normalizeWorkflowDocumentBase(
14
+ {runner: 'ubuntu-latest', ...document},
15
+ {
16
+ agentValidationCatalog: options?.agentValidationCatalog ?? agentValidationCatalog,
17
+ ...options,
18
+ },
19
+ );
12
20
  }
13
21
 
14
22
  function expectInvalid(
15
23
  document: WorkflowDocument,
16
- options?: Parameters<typeof normalizeWorkflowDocumentBase>[1],
24
+ options?: Omit<Parameters<typeof normalizeWorkflowDocumentBase>[1], 'agentValidationCatalog'> &
25
+ Partial<Pick<Parameters<typeof normalizeWorkflowDocumentBase>[1], 'agentValidationCatalog'>>,
17
26
  ): InvalidWorkflowModelError {
18
27
  try {
19
28
  normalizeWorkflowDocument(document, options);
@@ -578,12 +587,7 @@ describe('normalizeWorkflowDocument', () => {
578
587
  },
579
588
  };
580
589
 
581
- const error = expectInvalid(document, {
582
- harnessToolDeploymentConfig: {
583
- pi: {enabledToolPackages: ['pi-web-access'], webSearchEnabled: true},
584
- claude: {enabledToolPackages: []},
585
- },
586
- });
590
+ const error = expectInvalid(document);
587
591
 
588
592
  expect(error.issues).toEqual([
589
593
  {
@@ -670,9 +674,20 @@ describe('normalizeWorkflowDocument', () => {
670
674
  };
671
675
 
672
676
  const error = expectInvalid(document, {
673
- harnessToolDeploymentConfig: {
674
- pi: {enabledToolPackages: ['pi-web-access'], webSearchEnabled: false},
675
- claude: {enabledToolPackages: []},
677
+ agentValidationCatalog: {
678
+ ...agentValidationCatalog,
679
+ harnesses: agentValidationCatalog.harnesses.map((harness) =>
680
+ harness.id === 'pi'
681
+ ? {
682
+ ...harness,
683
+ effective_tools: harness.effective_tools.filter(
684
+ (tool) =>
685
+ tool === 'fetch_content' ||
686
+ !['web_search', 'get_search_content'].includes(tool),
687
+ ),
688
+ }
689
+ : harness,
690
+ ),
676
691
  },
677
692
  });
678
693
 
@@ -1169,7 +1184,7 @@ describe('normalizeWorkflowDocument', () => {
1169
1184
  };
1170
1185
 
1171
1186
  try {
1172
- normalizeWorkflowDocumentBase(document);
1187
+ normalizeWorkflowDocumentBase(document, {agentValidationCatalog});
1173
1188
  expect.fail('Expected InvalidWorkflowModelError');
1174
1189
  } catch (error) {
1175
1190
  expect(error).toBeInstanceOf(InvalidWorkflowModelError);
@@ -1193,6 +1208,7 @@ describe('normalizeWorkflowDocument', () => {
1193
1208
  };
1194
1209
 
1195
1210
  const model = normalizeWorkflowDocumentBase(document, {
1211
+ agentValidationCatalog,
1196
1212
  defaultRunnerLabels: [' Ubuntu ', 'ubuntu'],
1197
1213
  });
1198
1214
 
@@ -1211,7 +1227,10 @@ describe('normalizeWorkflowDocument', () => {
1211
1227
  };
1212
1228
 
1213
1229
  try {
1214
- normalizeWorkflowDocumentBase(document, {defaultRunnerLabels: ['ubuntu-latest']});
1230
+ normalizeWorkflowDocumentBase(document, {
1231
+ agentValidationCatalog,
1232
+ defaultRunnerLabels: ['ubuntu-latest'],
1233
+ });
1215
1234
  expect.fail('Expected InvalidWorkflowModelError');
1216
1235
  } catch (error) {
1217
1236
  expect(error).toBeInstanceOf(InvalidWorkflowModelError);
@@ -1253,7 +1272,7 @@ describe('normalizeWorkflowDocument', () => {
1253
1272
  };
1254
1273
 
1255
1274
  try {
1256
- normalizeWorkflowDocumentBase(document);
1275
+ normalizeWorkflowDocumentBase(document, {agentValidationCatalog});
1257
1276
  expect.fail('Expected InvalidWorkflowModelError');
1258
1277
  } catch (error) {
1259
1278
  expect(error).toBeInstanceOf(InvalidWorkflowModelError);
@@ -1279,7 +1298,7 @@ describe('normalizeWorkflowDocument', () => {
1279
1298
  };
1280
1299
 
1281
1300
  try {
1282
- normalizeWorkflowDocumentBase(document);
1301
+ normalizeWorkflowDocumentBase(document, {agentValidationCatalog});
1283
1302
  expect.fail('Expected InvalidWorkflowModelError');
1284
1303
  } catch (error) {
1285
1304
  expect(error).toBeInstanceOf(InvalidWorkflowModelError);
@@ -1349,7 +1368,7 @@ describe('normalizeWorkflowDocument', () => {
1349
1368
  };
1350
1369
 
1351
1370
  try {
1352
- normalizeWorkflowDocumentBase(document);
1371
+ normalizeWorkflowDocumentBase(document, {agentValidationCatalog});
1353
1372
  expect.fail('Expected InvalidWorkflowModelError');
1354
1373
  } catch (error) {
1355
1374
  expect(error).toBeInstanceOf(InvalidWorkflowModelError);
@@ -1378,7 +1397,7 @@ describe('normalizeWorkflowDocument', () => {
1378
1397
  },
1379
1398
  };
1380
1399
 
1381
- const model = normalizeWorkflowDocumentBase(document);
1400
+ const model = normalizeWorkflowDocumentBase(document, {agentValidationCatalog});
1382
1401
 
1383
1402
  expect(model.jobs[0]?.runner).toHaveLength(20);
1384
1403
  });
@@ -1,7 +1,4 @@
1
- import {
2
- DEFAULT_HARNESS_TOOL_DEPLOYMENT_CONFIG,
3
- type HarnessToolDeploymentConfig,
4
- } from '@shipfox/api-agent-dto';
1
+ import type {AgentValidationCatalog} from '@shipfox/api-agent-dto/inter-module';
5
2
  import {canonicalizeLabels} from '@shipfox/runner-labels';
6
3
  import type {WorkflowDocument} from '@shipfox/workflow-document';
7
4
  import type {IntegrationValidationContext} from '../entities/integration-context.js';
@@ -20,18 +17,16 @@ export function normalizeWorkflowDocument(
20
17
  document: WorkflowDocument,
21
18
  options: {
22
19
  defaultRunnerLabels?: readonly string[] | undefined;
23
- harnessToolDeploymentConfig?: HarnessToolDeploymentConfig | undefined;
20
+ agentValidationCatalog: AgentValidationCatalog;
24
21
  integrationValidationContext?: IntegrationValidationContext | undefined;
25
22
  stepSourceLocations?: WorkflowStepSourceLocationMap | undefined;
26
- } = {},
23
+ },
27
24
  ): WorkflowModel {
28
25
  const issues: WorkflowModelValidationIssue[] = [];
29
26
  const defaultRunnerLabels = canonicalizeLabels(options.defaultRunnerLabels);
30
- const harnessToolDeploymentConfig =
31
- options.harnessToolDeploymentConfig ?? DEFAULT_HARNESS_TOOL_DEPLOYMENT_CONFIG;
32
27
  const context = {
33
28
  defaultRunnerLabels,
34
- harnessToolDeploymentConfig,
29
+ agentValidationCatalog: options.agentValidationCatalog,
35
30
  integrationValidationContext: options.integrationValidationContext,
36
31
  };
37
32
  const jobIdBySourceName = mapJobIds(document, issues);
@@ -18,6 +18,7 @@ import {
18
18
  import {sql} from 'drizzle-orm';
19
19
  import type {WorkflowDefinitionPayload} from '#core/entities/workflow-definition.js';
20
20
  import {normalizeWorkflowDocument} from '#core/workflow-model/index.js';
21
+ import {agentValidationCatalog} from '#test/agent-validation-catalog.js';
21
22
  import {db} from './db.js';
22
23
  import {
23
24
  applyVcsDefinitionsBatch,
@@ -82,7 +83,7 @@ function definitionFields(name = 'Test Workflow'): WorkflowDefinitionPayload {
82
83
  function definitionFieldsForDocument(
83
84
  document: WorkflowDefinitionPayload['document'],
84
85
  ): WorkflowDefinitionPayload {
85
- return {document, model: normalizeWorkflowDocument(document)};
86
+ return {document, model: normalizeWorkflowDocument(document, {agentValidationCatalog})};
86
87
  }
87
88
 
88
89
  async function listOutboxRowsForProject(projectId: string) {
@@ -1,4 +1,5 @@
1
1
  import {normalizeWorkflowDocument} from '#core/workflow-model/index.js';
2
+ import {agentValidationCatalog} from '#test/agent-validation-catalog.js';
2
3
  import type {DefinitionDb} from './definitions.js';
3
4
  import {toDefinition} from './definitions.js';
4
5
 
@@ -21,7 +22,7 @@ describe('toDefinition', () => {
21
22
  sha: null,
22
23
  ref: null,
23
24
  name: 'Manual workflow',
24
- definition: {document, model: normalizeWorkflowDocument(document)},
25
+ definition: {document, model: normalizeWorkflowDocument(document, {agentValidationCatalog})},
25
26
  contentHash: null,
26
27
  fetchedAt: new Date('2026-06-09T10:00:00.000Z'),
27
28
  createdAt: new Date('2026-06-09T10:00:01.000Z'),
package/src/index.ts CHANGED
@@ -1,17 +1,18 @@
1
1
  import {dirname, resolve} from 'node:path';
2
2
  import {fileURLToPath} from 'node:url';
3
+ import type {AgentInterModuleClient} from '@shipfox/api-agent-dto/inter-module';
3
4
  import {
4
5
  DEFINITION_RESOLVED,
5
6
  type DefinitionsEventMap,
6
7
  definitionsEventSchemas,
7
8
  } from '@shipfox/api-definitions-dto';
8
- import type {IntegrationsModuleClient} from '@shipfox/api-integration-core-dto';
9
- import type {ProjectsModuleClient} from '@shipfox/api-projects-dto';
9
+ import type {IntegrationsModuleClient} from '@shipfox/api-integration-core-dto/inter-module';
10
10
  import {
11
11
  PROJECT_SOURCE_BOUND,
12
12
  PROJECT_SOURCE_COMMIT_OBSERVED,
13
13
  type ProjectsEventMap,
14
14
  } from '@shipfox/api-projects-dto';
15
+ import type {ProjectsModuleClient} from '@shipfox/api-projects-dto/inter-module';
15
16
  import {type ShipfoxModule, subscriberFactory} from '@shipfox/node-module';
16
17
  import {logger} from '@shipfox/node-opentelemetry';
17
18
  import {createDefinitionsSourceControl} from '#core/integrations.js';
@@ -48,11 +49,13 @@ const subscriber = subscriberFactory<DefinitionsEventMap & ProjectsEventMap>();
48
49
 
49
50
  export interface CreateDefinitionsModuleOptions {
50
51
  projects: ProjectsModuleClient;
52
+ agent: AgentInterModuleClient;
51
53
  integrations: IntegrationsModuleClient;
52
54
  }
53
55
 
54
56
  export function createDefinitionsModule({
55
57
  projects,
58
+ agent,
56
59
  integrations,
57
60
  }: CreateDefinitionsModuleOptions): ShipfoxModule {
58
61
  const sourceControl = createDefinitionsSourceControl(integrations);
@@ -60,7 +63,7 @@ export function createDefinitionsModule({
60
63
  return {
61
64
  name: 'definitions',
62
65
  database: {db, migrationsPath},
63
- routes: createDefinitionRoutes({projects, integrations}),
66
+ routes: createDefinitionRoutes({projects, agent, integrations}),
64
67
  publishers: [
65
68
  {name: 'definitions', table: definitionsOutbox, db, eventSchemas: definitionsEventSchemas},
66
69
  ],
@@ -76,7 +79,7 @@ export function createDefinitionsModule({
76
79
  {
77
80
  taskQueue: DEFINITIONS_TASK_QUEUE,
78
81
  workflowsPath,
79
- activities: () => createDefinitionSyncActivities(sourceControl, integrations),
82
+ activities: () => createDefinitionSyncActivities(sourceControl, agent, integrations),
80
83
  workflows: [],
81
84
  },
82
85
  ],