Skip to content

Commit 90e3e0f

Browse files
author
WordClaw Agent
committed
feat: inherit definition strategy config into agent runs
1 parent 8fda030 commit 90e3e0f

File tree

2 files changed

+82
-3
lines changed

2 files changed

+82
-3
lines changed

src/__tests__/api-tenant.test.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,4 +479,69 @@ describe('Multi-Tenant Domain Isolation Tests', () => {
479479
}
480480
}
481481
});
482+
483+
it('agent-run creation from definition inherits strategy config and definition runType', async () => {
484+
let domain1DefinitionId: number | null = null;
485+
let domain1RunId: number | null = null;
486+
487+
try {
488+
const createDefinition = await fastify.inject({
489+
method: 'POST',
490+
url: '/api/agent-run-definitions',
491+
headers: { 'x-api-key': rawKey1 },
492+
payload: {
493+
name: `d1-inherit-${crypto.randomUUID().slice(0, 8)}`,
494+
runType: 'quality_refiner',
495+
strategyConfig: {
496+
maxCandidates: 5,
497+
safeMode: true
498+
},
499+
active: true
500+
}
501+
});
502+
expect(createDefinition.statusCode).toBe(201);
503+
domain1DefinitionId = JSON.parse(createDefinition.payload).data.id as number;
504+
505+
const createRun = await fastify.inject({
506+
method: 'POST',
507+
url: '/api/agent-runs',
508+
headers: { 'x-api-key': rawKey1 },
509+
payload: {
510+
goal: 'Run from template',
511+
definitionId: domain1DefinitionId,
512+
runType: 'review_backlog_manager',
513+
metadata: {
514+
safeMode: false,
515+
operator: 'tenant-test'
516+
}
517+
}
518+
});
519+
expect(createRun.statusCode).toBe(201);
520+
521+
const runPayload = JSON.parse(createRun.payload) as {
522+
data: {
523+
id: number;
524+
runType: string;
525+
definitionId: number | null;
526+
metadata: Record<string, unknown> | null;
527+
};
528+
};
529+
domain1RunId = runPayload.data.id;
530+
531+
expect(runPayload.data.definitionId).toBe(domain1DefinitionId);
532+
expect(runPayload.data.runType).toBe('quality_refiner');
533+
expect(runPayload.data.metadata).toEqual({
534+
maxCandidates: 5,
535+
safeMode: false,
536+
operator: 'tenant-test'
537+
});
538+
} finally {
539+
if (domain1RunId) {
540+
await db.delete(agentRuns).where(eq(agentRuns.id, domain1RunId));
541+
}
542+
if (domain1DefinitionId) {
543+
await db.delete(agentRunDefinitions).where(eq(agentRunDefinitions.id, domain1DefinitionId));
544+
}
545+
}
546+
});
482547
});

src/services/agent-runs.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ function clampOffset(offset?: number): number {
100100
return Math.max(0, offset);
101101
}
102102

103+
function isRecord(value: unknown): value is Record<string, unknown> {
104+
return value !== null && typeof value === 'object' && !Array.isArray(value);
105+
}
106+
103107
function isUniqueViolation(error: unknown, constraintName: string): boolean {
104108
const visited = new Set<unknown>();
105109
let candidate: unknown = error;
@@ -365,6 +369,7 @@ export class AgentRunService {
365369

366370
let definitionId: number | null = null;
367371
let inferredRunType: string | null = null;
372+
let baseMetadata: Record<string, unknown> = {};
368373

369374
if (input.definitionId !== undefined) {
370375
const [definition] = await db.select()
@@ -383,9 +388,16 @@ export class AgentRunService {
383388

384389
definitionId = definition.id;
385390
inferredRunType = definition.runType;
391+
if (isRecord(definition.strategyConfig)) {
392+
baseMetadata = definition.strategyConfig;
393+
}
386394
}
387395

388-
const runType = input.runType?.trim() || inferredRunType || 'review_backlog_manager';
396+
const runType = inferredRunType || input.runType?.trim() || 'review_backlog_manager';
397+
const metadata = {
398+
...baseMetadata,
399+
...(input.metadata ?? {})
400+
};
389401
const status: AgentRunStatus = input.requireApproval ? 'waiting_approval' : 'queued';
390402

391403
const created = await db.transaction(async (tx) => {
@@ -396,7 +408,7 @@ export class AgentRunService {
396408
runType,
397409
status,
398410
requestedBy: input.requestedBy,
399-
metadata: input.metadata ?? null
411+
metadata: Object.keys(metadata).length > 0 ? metadata : null
400412
}).returning();
401413

402414
await tx.insert(agentRunSteps).values({
@@ -416,7 +428,9 @@ export class AgentRunService {
416428
status: newRun.status,
417429
goal: newRun.goal,
418430
runType: newRun.runType,
419-
requestedBy: newRun.requestedBy
431+
requestedBy: newRun.requestedBy,
432+
definitionId: newRun.definitionId,
433+
metadata: newRun.metadata
420434
}
421435
});
422436

0 commit comments

Comments
 (0)