Support routine variables in titles

This commit is contained in:
dotta 2026-04-07 16:31:14 -05:00
parent 372421ef0b
commit 1de5fb9316
7 changed files with 41 additions and 17 deletions

View file

@ -332,7 +332,7 @@ describeEmbeddedPostgres("routine service live-execution coalescing", () => {
projectId,
goalId: null,
parentIssueId: null,
title: "repo triage",
title: "repo triage for {{repo}}",
description: "Review {{repo}} for {{priority}} bugs",
assigneeAgentId: agentId,
priority: "medium",
@ -346,6 +346,7 @@ describeEmbeddedPostgres("routine service live-execution coalescing", () => {
},
{},
);
expect(variableRoutine.variables.map((variable) => variable.name)).toEqual(["repo", "priority"]);
const run = await svc.runRoutine(variableRoutine.id, {
source: "manual",
@ -353,7 +354,7 @@ describeEmbeddedPostgres("routine service live-execution coalescing", () => {
});
const storedIssue = await db
.select({ description: issues.description })
.select({ title: issues.title, description: issues.description })
.from(issues)
.where(eq(issues.id, run.linkedIssueId!))
.then((rows) => rows[0] ?? null);
@ -363,6 +364,7 @@ describeEmbeddedPostgres("routine service live-execution coalescing", () => {
.where(eq(routineRuns.id, run.id))
.then((rows) => rows[0] ?? null);
expect(storedIssue?.title).toBe("repo triage for paperclip");
expect(storedIssue?.description).toBe("Review paperclip for high bugs");
expect(storedRun?.triggerPayload).toEqual({
variables: {

View file

@ -675,6 +675,7 @@ export function routineService(db: Db, deps: { heartbeat?: IssueAssignmentWakeup
executionWorkspaceSettings?: Record<string, unknown> | null;
}) {
const resolvedVariables = resolveRoutineVariableValues(input.routine.variables ?? [], input);
const title = interpolateRoutineTemplate(input.routine.title, resolvedVariables) ?? input.routine.title;
const description = interpolateRoutineTemplate(input.routine.description, resolvedVariables);
const triggerPayload = mergeRoutineRunPayload(input.payload, resolvedVariables);
const run = await db.transaction(async (tx) => {
@ -748,7 +749,7 @@ export function routineService(db: Db, deps: { heartbeat?: IssueAssignmentWakeup
projectId: input.routine.projectId,
goalId: input.routine.goalId,
parentId: input.routine.parentIssueId,
title: input.routine.title,
title,
description,
status: "todo",
priority: input.routine.priority,
@ -996,7 +997,7 @@ export function routineService(db: Db, deps: { heartbeat?: IssueAssignmentWakeup
if (input.goalId) await assertGoal(companyId, input.goalId);
if (input.parentIssueId) await assertParentIssue(companyId, input.parentIssueId);
const variables = syncRoutineVariablesWithTemplate(
input.description,
[input.title, input.description],
sanitizeRoutineVariableInputs(input.variables),
);
assertRoutineVariableDefinitions(variables);
@ -1029,9 +1030,10 @@ export function routineService(db: Db, deps: { heartbeat?: IssueAssignmentWakeup
if (!existing) return null;
const nextProjectId = patch.projectId ?? existing.projectId;
const nextAssigneeAgentId = patch.assigneeAgentId ?? existing.assigneeAgentId;
const nextTitle = patch.title ?? existing.title;
const nextDescription = patch.description === undefined ? existing.description : patch.description;
const nextVariables = syncRoutineVariablesWithTemplate(
nextDescription,
[nextTitle, nextDescription],
patch.variables === undefined ? existing.variables : sanitizeRoutineVariableInputs(patch.variables),
);
if (patch.projectId) await assertProject(existing.companyId, nextProjectId);
@ -1060,7 +1062,7 @@ export function routineService(db: Db, deps: { heartbeat?: IssueAssignmentWakeup
projectId: nextProjectId,
goalId: patch.goalId === undefined ? existing.goalId : patch.goalId,
parentIssueId: patch.parentIssueId === undefined ? existing.parentIssueId : patch.parentIssueId,
title: patch.title ?? existing.title,
title: nextTitle,
description: nextDescription,
assigneeAgentId: nextAssigneeAgentId,
priority: patch.priority ?? existing.priority,