@shipfox/api-workflows 13.0.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.
- package/.turbo/turbo-build.log +4 -4
- package/CHANGELOG.md +15 -0
- package/dist/core/errors.d.ts +9 -1
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +5 -1
- package/dist/core/errors.js.map +1 -1
- package/dist/core/job-execution.d.ts.map +1 -1
- package/dist/core/job-execution.js +12 -2
- package/dist/core/job-execution.js.map +1 -1
- package/dist/core/step-config/agent.d.ts.map +1 -1
- package/dist/core/step-config/agent.js +9 -1
- package/dist/core/step-config/agent.js.map +1 -1
- package/dist/presentation/dto/step.d.ts.map +1 -1
- package/dist/presentation/dto/step.js +14 -0
- package/dist/presentation/dto/step.js.map +1 -1
- package/dist/presentation/routes/agent-runtime-config.d.ts.map +1 -1
- package/dist/presentation/routes/agent-runtime-config.js +22 -0
- package/dist/presentation/routes/agent-runtime-config.js.map +1 -1
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/src/core/errors.ts +17 -2
- package/src/core/job-execution.test.ts +54 -0
- package/src/core/job-execution.ts +6 -1
- package/src/core/step-config/agent.ts +8 -1
- package/src/core/step-config/complete-step-dispatch-config.test.ts +37 -0
- package/src/presentation/dto/step.test.ts +8 -0
- package/src/presentation/dto/step.ts +9 -0
- package/src/presentation/routes/agent-runtime-config.test.ts +84 -2
- package/src/presentation/routes/agent-runtime-config.ts +24 -0
- package/tsconfig.build.tsbuildinfo +1 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shipfox/api-workflows",
|
|
3
3
|
"license": "MIT",
|
|
4
|
-
"version": "13.
|
|
4
|
+
"version": "13.1.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/ShipfoxHQ/shipfox.git",
|
|
@@ -25,14 +25,14 @@
|
|
|
25
25
|
"zod": "^4.4.3",
|
|
26
26
|
"@shipfox/api-auth-context": "12.2.0",
|
|
27
27
|
"@shipfox/api-auth-dto": "12.0.0",
|
|
28
|
-
"@shipfox/api-agent-dto": "
|
|
28
|
+
"@shipfox/api-agent-dto": "13.1.0",
|
|
29
29
|
"@shipfox/annotations-dto": "12.3.0",
|
|
30
30
|
"@shipfox/api-definitions-dto": "12.3.0",
|
|
31
31
|
"@shipfox/api-projects-dto": "12.2.0",
|
|
32
32
|
"@shipfox/api-integration-core-dto": "12.2.0",
|
|
33
33
|
"@shipfox/api-runners-dto": "13.0.0",
|
|
34
34
|
"@shipfox/api-secrets-dto": "12.0.0",
|
|
35
|
-
"@shipfox/api-workflows-dto": "13.
|
|
35
|
+
"@shipfox/api-workflows-dto": "13.1.0",
|
|
36
36
|
"@shipfox/api-workspaces-dto": "12.0.0",
|
|
37
37
|
"@shipfox/config": "1.2.4",
|
|
38
38
|
"@shipfox/inter-module": "0.2.3",
|
package/src/core/errors.ts
CHANGED
|
@@ -38,13 +38,28 @@ export class WorkspaceNotFoundError extends Error {
|
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
export interface AgentConfigUnresolvableErrorOptions {
|
|
42
|
+
readonly cause?: unknown;
|
|
43
|
+
readonly message?: string;
|
|
44
|
+
readonly code?: string;
|
|
45
|
+
readonly managedProviderId?: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
41
48
|
export class AgentConfigUnresolvableError extends Error {
|
|
49
|
+
readonly code?: string | undefined;
|
|
50
|
+
readonly managedProviderId?: string | undefined;
|
|
51
|
+
|
|
42
52
|
constructor(
|
|
43
53
|
readonly definitionId: string,
|
|
44
|
-
options?:
|
|
54
|
+
options?: AgentConfigUnresolvableErrorOptions | undefined,
|
|
45
55
|
) {
|
|
46
|
-
super(
|
|
56
|
+
super(
|
|
57
|
+
options?.message ?? `Agent configuration cannot be resolved for definition ${definitionId}`,
|
|
58
|
+
options?.cause === undefined ? undefined : {cause: options.cause},
|
|
59
|
+
);
|
|
47
60
|
this.name = 'AgentConfigUnresolvableError';
|
|
61
|
+
this.code = options?.code;
|
|
62
|
+
this.managedProviderId = options?.managedProviderId;
|
|
48
63
|
}
|
|
49
64
|
}
|
|
50
65
|
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type AgentInterModuleClient,
|
|
3
|
+
agentInterModuleContract,
|
|
4
|
+
} from '@shipfox/api-agent-dto/inter-module';
|
|
1
5
|
import {
|
|
2
6
|
WORKFLOWS_JOB_STEPS_SETTLED,
|
|
3
7
|
WORKFLOWS_STEP_ATTEMPT_TERMINATED,
|
|
@@ -10,6 +14,7 @@ import {
|
|
|
10
14
|
parseWorkflowTemplate,
|
|
11
15
|
planInterpolationField,
|
|
12
16
|
} from '@shipfox/expression';
|
|
17
|
+
import {createInterModuleKnownError} from '@shipfox/inter-module';
|
|
13
18
|
import {and, eq, sql} from 'drizzle-orm';
|
|
14
19
|
import {db} from '#db/db.js';
|
|
15
20
|
import {workflowsOutbox} from '#db/schema/outbox.js';
|
|
@@ -322,6 +327,55 @@ describe('nextStepForJob', () => {
|
|
|
322
327
|
});
|
|
323
328
|
});
|
|
324
329
|
|
|
330
|
+
test('reports managed provider policy failures as agent config errors', async () => {
|
|
331
|
+
const {jobId, steps} = await arrangeJobWithSteps(1);
|
|
332
|
+
const pending = steps[0];
|
|
333
|
+
if (!pending) throw new Error('Expected pending step');
|
|
334
|
+
await db()
|
|
335
|
+
.update(stepsTable)
|
|
336
|
+
.set({
|
|
337
|
+
config: {},
|
|
338
|
+
configPlan: {
|
|
339
|
+
agent: {
|
|
340
|
+
prompt: {segments: [{kind: 'literal', value: 'Review the change.'}]},
|
|
341
|
+
},
|
|
342
|
+
},
|
|
343
|
+
})
|
|
344
|
+
.where(eq(stepsTable.id, pending.id));
|
|
345
|
+
|
|
346
|
+
const agent = {
|
|
347
|
+
getValidationCatalog: vi.fn(),
|
|
348
|
+
resolveAgentConfig: vi.fn().mockRejectedValue(
|
|
349
|
+
createInterModuleKnownError(
|
|
350
|
+
agentInterModuleContract.methods.resolveAgentConfig,
|
|
351
|
+
'agent-config-invalid',
|
|
352
|
+
{
|
|
353
|
+
message: 'This instance only supports provider `shipfox`.',
|
|
354
|
+
managed_provider_id: 'shipfox',
|
|
355
|
+
},
|
|
356
|
+
),
|
|
357
|
+
),
|
|
358
|
+
resolveRuntimeCredentials: vi.fn(),
|
|
359
|
+
} as unknown as AgentInterModuleClient;
|
|
360
|
+
|
|
361
|
+
const next = await nextStepForJob(jobId, agent);
|
|
362
|
+
|
|
363
|
+
expect(next).toEqual({kind: 'done', status: 'failed'});
|
|
364
|
+
const after = await getStepsByJobId(jobId);
|
|
365
|
+
expect(after[0]).toMatchObject({
|
|
366
|
+
status: 'failed',
|
|
367
|
+
error: {
|
|
368
|
+
message: 'This instance only supports provider `shipfox`.',
|
|
369
|
+
reason: 'agent_config_invalid',
|
|
370
|
+
field: 'agent',
|
|
371
|
+
source: 'agent',
|
|
372
|
+
code: 'workspace-providers-disabled',
|
|
373
|
+
managedProviderId: 'shipfox',
|
|
374
|
+
agentConfigIssue: 'provider_unsupported',
|
|
375
|
+
},
|
|
376
|
+
});
|
|
377
|
+
});
|
|
378
|
+
|
|
325
379
|
test('all steps succeeded → {done, succeeded}', async () => {
|
|
326
380
|
const {jobId, steps} = await arrangeJobWithSteps(2);
|
|
327
381
|
for (const step of steps) {
|
|
@@ -339,11 +339,16 @@ function dispatchConfigError(error: DispatchConfigError): Record<string, unknown
|
|
|
339
339
|
};
|
|
340
340
|
}
|
|
341
341
|
|
|
342
|
+
const isManagedProviderPolicyFailure =
|
|
343
|
+
error.code === 'workspace-providers-disabled' && error.managedProviderId !== undefined;
|
|
342
344
|
return {
|
|
343
345
|
message: error.message,
|
|
344
|
-
reason: 'config_unresolvable',
|
|
346
|
+
reason: isManagedProviderPolicyFailure ? 'agent_config_invalid' : 'config_unresolvable',
|
|
345
347
|
field: 'agent',
|
|
346
348
|
source: 'agent',
|
|
349
|
+
...(error.code === undefined ? {} : {code: error.code}),
|
|
350
|
+
...(error.managedProviderId === undefined ? {} : {managedProviderId: error.managedProviderId}),
|
|
351
|
+
...(isManagedProviderPolicyFailure ? {agentConfigIssue: 'provider_unsupported'} : {}),
|
|
347
352
|
};
|
|
348
353
|
}
|
|
349
354
|
|
|
@@ -185,7 +185,14 @@ export async function completeAgentDefaults(params: {
|
|
|
185
185
|
isInterModuleKnownError(agentInterModuleContract.methods.resolveAgentConfig, error) &&
|
|
186
186
|
error.code === 'agent-config-invalid'
|
|
187
187
|
) {
|
|
188
|
-
|
|
188
|
+
const managedProviderId = error.details.managed_provider_id;
|
|
189
|
+
throw new AgentConfigUnresolvableError(params.definitionId, {
|
|
190
|
+
cause: error,
|
|
191
|
+
...(error.details.message === undefined ? {} : {message: error.details.message}),
|
|
192
|
+
...(managedProviderId === undefined
|
|
193
|
+
? {}
|
|
194
|
+
: {code: 'workspace-providers-disabled', managedProviderId}),
|
|
195
|
+
});
|
|
189
196
|
}
|
|
190
197
|
throw error;
|
|
191
198
|
}
|
|
@@ -453,6 +453,43 @@ describe('completeStepDispatchConfig', () => {
|
|
|
453
453
|
await expect(act()).rejects.toThrow(AgentConfigUnresolvableError);
|
|
454
454
|
});
|
|
455
455
|
|
|
456
|
+
it('preserves managed provider policy details in unresolvable agent config errors', async () => {
|
|
457
|
+
const pending = step({
|
|
458
|
+
type: 'agent',
|
|
459
|
+
config: {},
|
|
460
|
+
configPlan: {
|
|
461
|
+
agent: {
|
|
462
|
+
prompt: plannedField('Review the change.'),
|
|
463
|
+
},
|
|
464
|
+
},
|
|
465
|
+
});
|
|
466
|
+
const failingResolver: AgentDefaultsResolver = () => {
|
|
467
|
+
throw createInterModuleKnownError(
|
|
468
|
+
agentInterModuleContract.methods.resolveAgentConfig,
|
|
469
|
+
'agent-config-invalid',
|
|
470
|
+
{
|
|
471
|
+
message: 'This instance only supports provider `shipfox`.',
|
|
472
|
+
managed_provider_id: 'shipfox',
|
|
473
|
+
},
|
|
474
|
+
);
|
|
475
|
+
};
|
|
476
|
+
|
|
477
|
+
const act = () =>
|
|
478
|
+
completeStepDispatchConfig({
|
|
479
|
+
step: pending,
|
|
480
|
+
context,
|
|
481
|
+
resolveAgentDefaults: failingResolver,
|
|
482
|
+
definitionId: 'def-1',
|
|
483
|
+
});
|
|
484
|
+
|
|
485
|
+
await expect(act()).rejects.toMatchObject({
|
|
486
|
+
name: 'AgentConfigUnresolvableError',
|
|
487
|
+
message: 'This instance only supports provider `shipfox`.',
|
|
488
|
+
code: 'workspace-providers-disabled',
|
|
489
|
+
managedProviderId: 'shipfox',
|
|
490
|
+
});
|
|
491
|
+
});
|
|
492
|
+
|
|
456
493
|
it('throws when a server-side segment still survives dispatch', async () => {
|
|
457
494
|
const pending = step({
|
|
458
495
|
config: {},
|
|
@@ -43,12 +43,16 @@ describe('fromStepErrorDto', () => {
|
|
|
43
43
|
it('persists the machine-readable agent config issue in camelCase', () => {
|
|
44
44
|
const persisted = fromStepErrorDto({
|
|
45
45
|
message: 'Missing credentials',
|
|
46
|
+
code: 'workspace-providers-disabled',
|
|
47
|
+
managed_provider_id: 'shipfox',
|
|
46
48
|
reason: 'agent_config_invalid',
|
|
47
49
|
agent_config_issue: 'provider_not_configured',
|
|
48
50
|
});
|
|
49
51
|
|
|
50
52
|
expect(persisted).toEqual({
|
|
51
53
|
message: 'Missing credentials',
|
|
54
|
+
code: 'workspace-providers-disabled',
|
|
55
|
+
managedProviderId: 'shipfox',
|
|
52
56
|
reason: 'agent_config_invalid',
|
|
53
57
|
agentConfigIssue: 'provider_not_configured',
|
|
54
58
|
});
|
|
@@ -180,6 +184,8 @@ describe('toStepDto error category', () => {
|
|
|
180
184
|
type: 'agent',
|
|
181
185
|
error: {
|
|
182
186
|
message: 'Unknown provider "foo" for agent step.',
|
|
187
|
+
code: 'workspace-providers-disabled',
|
|
188
|
+
managedProviderId: 'shipfox',
|
|
183
189
|
reason: 'agent_config_invalid',
|
|
184
190
|
agentConfigIssue: 'provider_unsupported',
|
|
185
191
|
},
|
|
@@ -188,6 +194,8 @@ describe('toStepDto error category', () => {
|
|
|
188
194
|
|
|
189
195
|
expect(dto.error).toEqual({
|
|
190
196
|
message: 'Unknown provider "foo" for agent step.',
|
|
197
|
+
code: 'workspace-providers-disabled',
|
|
198
|
+
managed_provider_id: 'shipfox',
|
|
191
199
|
reason: 'agent_config_invalid',
|
|
192
200
|
agent_config_issue: 'provider_unsupported',
|
|
193
201
|
category: 'user',
|
|
@@ -22,6 +22,9 @@ function toStepErrorDto(
|
|
|
22
22
|
): StepErrorDto {
|
|
23
23
|
if (error === null) return null;
|
|
24
24
|
const message = typeof error.message === 'string' ? error.message : '';
|
|
25
|
+
const code = typeof error.code === 'string' ? error.code : undefined;
|
|
26
|
+
const managedProviderId =
|
|
27
|
+
typeof error.managedProviderId === 'string' ? error.managedProviderId : undefined;
|
|
25
28
|
const exitCode = error.exitCode;
|
|
26
29
|
const signal = typeof error.signal === 'string' ? error.signal : undefined;
|
|
27
30
|
const field = typeof error.field === 'string' ? error.field : undefined;
|
|
@@ -30,6 +33,8 @@ function toStepErrorDto(
|
|
|
30
33
|
const agentConfigIssue = agentConfigIssueSchema.safeParse(error.agentConfigIssue);
|
|
31
34
|
return {
|
|
32
35
|
message,
|
|
36
|
+
...(code === undefined ? {} : {code}),
|
|
37
|
+
...(managedProviderId === undefined ? {} : {managed_provider_id: managedProviderId}),
|
|
33
38
|
...(exitCode === null || typeof exitCode === 'number' ? {exit_code: exitCode} : {}),
|
|
34
39
|
...(signal === undefined ? {} : {signal}),
|
|
35
40
|
...(reason.success ? {reason: reason.data} : {}),
|
|
@@ -48,6 +53,10 @@ export function fromStepErrorDto(error: StepErrorDto | undefined): Record<string
|
|
|
48
53
|
if (!error) return null;
|
|
49
54
|
return {
|
|
50
55
|
message: error.message,
|
|
56
|
+
...(error.code === undefined ? {} : {code: error.code}),
|
|
57
|
+
...(error.managed_provider_id === undefined
|
|
58
|
+
? {}
|
|
59
|
+
: {managedProviderId: error.managed_provider_id}),
|
|
51
60
|
...(error.exit_code === null || typeof error.exit_code === 'number'
|
|
52
61
|
? {exitCode: error.exit_code}
|
|
53
62
|
: {}),
|
|
@@ -8,10 +8,15 @@ import {closeApp, createApp, type FastifyInstance} from '@shipfox/node-fastify';
|
|
|
8
8
|
import {createCapturingLogger} from '@shipfox/node-log/test';
|
|
9
9
|
import {eq} from 'drizzle-orm';
|
|
10
10
|
import type {StepStatus} from '#core/entities/step.js';
|
|
11
|
-
import {db} from '#db/db.js';
|
|
11
|
+
import {db, withTransaction} from '#db/db.js';
|
|
12
12
|
import {jobs} from '#db/schema/jobs.js';
|
|
13
13
|
import {steps as stepsTable} from '#db/schema/steps.js';
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
createWorkflowRun,
|
|
16
|
+
getJobsByWorkflowRunId,
|
|
17
|
+
getStepsByJobId,
|
|
18
|
+
insertRunningStepAttempt,
|
|
19
|
+
} from '#db/workflow-runs.js';
|
|
15
20
|
import {workflowModel} from '#test/factories/workflow-model.js';
|
|
16
21
|
import {insertRunningJobLease, mintActiveLeaseToken} from '#test/fixtures/active-lease-token.js';
|
|
17
22
|
import {resolveTestAgentDefaults} from '#test/fixtures/agent-inter-module.js';
|
|
@@ -115,6 +120,13 @@ describe('GET /runs/jobs/current/agent-runtime-config', () => {
|
|
|
115
120
|
thinking: 'xhigh',
|
|
116
121
|
credentials: {api_key: 'sk-workspace-secret'},
|
|
117
122
|
});
|
|
123
|
+
expect(resolveRuntimeCredentials).toHaveBeenCalledWith(
|
|
124
|
+
expect.objectContaining({
|
|
125
|
+
workspaceId: run.workspaceId,
|
|
126
|
+
runId: run.id,
|
|
127
|
+
stepAttemptId: expect.any(String),
|
|
128
|
+
}),
|
|
129
|
+
);
|
|
118
130
|
});
|
|
119
131
|
|
|
120
132
|
test('derives the credential workspace from the leased job instead of hostile lease claims', async () => {
|
|
@@ -288,6 +300,63 @@ describe('GET /runs/jobs/current/agent-runtime-config', () => {
|
|
|
288
300
|
expect(res.json().code).toBe('model-provider-not-configured');
|
|
289
301
|
});
|
|
290
302
|
|
|
303
|
+
test('returns managed provider policy details when workspace providers are disabled', async () => {
|
|
304
|
+
const {job, step} = await createRunningAgentStep();
|
|
305
|
+
resolveRuntimeCredentials.mockRejectedValueOnce(
|
|
306
|
+
createInterModuleKnownError(
|
|
307
|
+
agentInterModuleContract.methods.resolveRuntimeCredentials,
|
|
308
|
+
'workspace-providers-disabled',
|
|
309
|
+
{
|
|
310
|
+
message: 'This instance only supports provider `shipfox`.',
|
|
311
|
+
managed_provider_id: 'shipfox',
|
|
312
|
+
},
|
|
313
|
+
),
|
|
314
|
+
);
|
|
315
|
+
const token = await mintActiveLeaseToken({jobId: job.id});
|
|
316
|
+
|
|
317
|
+
const res = await app.inject({
|
|
318
|
+
method: 'GET',
|
|
319
|
+
url: runtimeConfigUrl(step.id, step.currentAttempt),
|
|
320
|
+
headers: {authorization: `Bearer ${token}`},
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
expect(res.statusCode).toBe(422);
|
|
324
|
+
expect(res.json()).toMatchObject({
|
|
325
|
+
code: 'workspace-providers-disabled',
|
|
326
|
+
details: {
|
|
327
|
+
message: 'This instance only supports provider `shipfox`.',
|
|
328
|
+
managed_provider_id: 'shipfox',
|
|
329
|
+
},
|
|
330
|
+
});
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
test('includes a fallback message when managed provider details omit one', async () => {
|
|
334
|
+
const {job, step} = await createRunningAgentStep();
|
|
335
|
+
resolveRuntimeCredentials.mockRejectedValueOnce(
|
|
336
|
+
createInterModuleKnownError(
|
|
337
|
+
agentInterModuleContract.methods.resolveRuntimeCredentials,
|
|
338
|
+
'workspace-providers-disabled',
|
|
339
|
+
{managed_provider_id: 'shipfox'},
|
|
340
|
+
),
|
|
341
|
+
);
|
|
342
|
+
const token = await mintActiveLeaseToken({jobId: job.id});
|
|
343
|
+
|
|
344
|
+
const res = await app.inject({
|
|
345
|
+
method: 'GET',
|
|
346
|
+
url: runtimeConfigUrl(step.id, step.currentAttempt),
|
|
347
|
+
headers: {authorization: `Bearer ${token}`},
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
expect(res.statusCode).toBe(422);
|
|
351
|
+
expect(res.json()).toMatchObject({
|
|
352
|
+
code: 'workspace-providers-disabled',
|
|
353
|
+
details: {
|
|
354
|
+
message: 'Workspace provider configuration is disabled',
|
|
355
|
+
managed_provider_id: 'shipfox',
|
|
356
|
+
},
|
|
357
|
+
});
|
|
358
|
+
});
|
|
359
|
+
|
|
291
360
|
test('returns 409 and reports when workspace credentials cannot be decrypted', async () => {
|
|
292
361
|
const {job, step} = await createRunningAgentStep();
|
|
293
362
|
resolveRuntimeCredentials.mockRejectedValueOnce(
|
|
@@ -420,6 +489,19 @@ async function createStep(params: {
|
|
|
420
489
|
const step = stepRows.find((candidate) => candidate.type === params.targetType);
|
|
421
490
|
if (!step) throw new Error(`createStep: ${params.targetType} step not found`);
|
|
422
491
|
await db().update(stepsTable).set({status: params.status}).where(eq(stepsTable.id, step.id));
|
|
492
|
+
if (params.status === 'running') {
|
|
493
|
+
await withTransaction((tx) =>
|
|
494
|
+
insertRunningStepAttempt(
|
|
495
|
+
{
|
|
496
|
+
jobExecutionId: step.jobExecutionId,
|
|
497
|
+
stepId: step.id,
|
|
498
|
+
attempt: step.currentAttempt,
|
|
499
|
+
config: step.config,
|
|
500
|
+
},
|
|
501
|
+
tx,
|
|
502
|
+
),
|
|
503
|
+
);
|
|
504
|
+
}
|
|
423
505
|
|
|
424
506
|
return {
|
|
425
507
|
run,
|
|
@@ -13,6 +13,7 @@ import {isInterModuleKnownError} from '@shipfox/inter-module';
|
|
|
13
13
|
import {captureException} from '@shipfox/node-error-monitoring';
|
|
14
14
|
import {ClientError, defineRoute} from '@shipfox/node-fastify';
|
|
15
15
|
import {ZodError} from 'zod';
|
|
16
|
+
import {getStepAttemptDetail} from '#db/index.js';
|
|
16
17
|
import {loadRunningLeasedStep} from './leased-step.js';
|
|
17
18
|
|
|
18
19
|
export function createAgentRuntimeConfigRoute(params: {
|
|
@@ -63,6 +64,22 @@ export function createAgentRuntimeConfigRoute(params: {
|
|
|
63
64
|
},
|
|
64
65
|
);
|
|
65
66
|
}
|
|
67
|
+
if (
|
|
68
|
+
isInterModuleKnownError(
|
|
69
|
+
agentInterModuleContract.methods.resolveRuntimeCredentials,
|
|
70
|
+
error,
|
|
71
|
+
) &&
|
|
72
|
+
error.code === 'workspace-providers-disabled'
|
|
73
|
+
) {
|
|
74
|
+
const message = error.details.message ?? 'Workspace provider configuration is disabled';
|
|
75
|
+
throw new ClientError(message, 'workspace-providers-disabled', {
|
|
76
|
+
status: 422,
|
|
77
|
+
details: {
|
|
78
|
+
managed_provider_id: error.details.managed_provider_id,
|
|
79
|
+
message,
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
}
|
|
66
83
|
throw error;
|
|
67
84
|
},
|
|
68
85
|
handler: async (request, reply) => {
|
|
@@ -91,8 +108,15 @@ export function createAgentRuntimeConfigRoute(params: {
|
|
|
91
108
|
throw error;
|
|
92
109
|
}
|
|
93
110
|
|
|
111
|
+
const stepAttempt = await getStepAttemptDetail({stepId, attempt});
|
|
112
|
+
if (!stepAttempt) {
|
|
113
|
+
throw new ClientError('Step attempt not found', 'step-attempt-not-found', {status: 409});
|
|
114
|
+
}
|
|
115
|
+
|
|
94
116
|
const runtimeConfig = await params.agent.resolveRuntimeCredentials({
|
|
95
117
|
workspaceId,
|
|
118
|
+
runId: stepAttempt.workflowRunId,
|
|
119
|
+
stepAttemptId: stepAttempt.attempt.id,
|
|
96
120
|
harness: agentConfig.harness,
|
|
97
121
|
provider: agentConfig.provider,
|
|
98
122
|
model: agentConfig.model,
|