Skip to content

Commit d420e73

Browse files
committed
fix: add missing tools for automation generation and status generation
1 parent 81cb0b3 commit d420e73

File tree

8 files changed

+190
-1
lines changed

8 files changed

+190
-1
lines changed

apps/api/src/workflows/schedules/generate-schedule/generate-schedule.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,14 @@ import type { Db } from "../../../db/db";
44
import { createOrganizationScheduleTool } from "../../tools/create-organization-schedule-tool";
55
import { getDiscordIntegrationTool } from "../../tools/get-discord-integration-tool";
66
import { getGithubIntegrationTool } from "../../tools/get-github-integration-tool";
7+
import { getGitlabIntegrationTool } from "../../tools/get-gitlab-integration-tool";
8+
import { getLinearIntegrationTool } from "../../tools/get-linear-integration-tool";
79
import { getSlackIntegrationTool } from "../../tools/get-slack-integration-tool";
810
import { listOrganizationDiscordChannelsTool } from "../../tools/list-organization-discord-channels-tool";
11+
import { listOrganizationGithubRepositoriesTool } from "../../tools/list-organization-github-repositories-tool";
12+
import { listOrganizationGitlabProjectsTool } from "../../tools/list-organization-gitlab-projects-tool";
13+
import { listOrganizationLinearProjectsTool } from "../../tools/list-organization-linear-projects-tool";
14+
import { listOrganizationLinearTeamsTool } from "../../tools/list-organization-linear-teams-tool";
915
import { listOrganizationMembersTool } from "../../tools/list-organization-members-tool";
1016
import { listOrganizationSlackChannelsTool } from "../../tools/list-organization-slack-channels-tool";
1117
import { listOrganizationTeamsTool } from "../../tools/list-organization-teams-tool";
@@ -50,11 +56,17 @@ Request: "${naturalLanguageRequest}"`,
5056
tools: {
5157
listOrganizationTeams: listOrganizationTeamsTool(db),
5258
listOrganizationMembers: listOrganizationMembersTool(db),
59+
listOrganizationGithubRepositories: listOrganizationGithubRepositoriesTool(db),
5360
listOrganizationSlackChannels: listOrganizationSlackChannelsTool(db),
5461
listOrganizationDiscordChannels: listOrganizationDiscordChannelsTool(db),
62+
listOrganizationGitlabProjects: listOrganizationGitlabProjectsTool(db),
63+
listOrganizationLinearTeams: listOrganizationLinearTeamsTool(db),
64+
listOrganizationLinearProjects: listOrganizationLinearProjectsTool(db),
5565
getSlackIntegration: getSlackIntegrationTool(db),
5666
getDiscordIntegration: getDiscordIntegrationTool(db),
5767
getGithubIntegration: getGithubIntegrationTool(db),
68+
getGitlabIntegration: getGitlabIntegrationTool(db),
69+
getLinearIntegration: getLinearIntegrationTool(db),
5870
createOrganizationSchedule: createOrganizationScheduleTool(db),
5971
},
6072
});

apps/api/src/workflows/schedules/generate-schedule/system-prompt.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,13 @@ GENERATE TARGETS (for generateUpdates): array generateFor[] where each item is o
3131
UsingActivityFrom is an array of discriminated objects (not strings). Each item is exactly one of:
3232
- { type: "anyIntegration", value: "anyIntegration" }
3333
- { type: "anyGithub", value: "anyGithub" }
34+
- { type: "anyGitlab", value: "anyGitlab" }
3435
- { type: "anySlack", value: "anySlack" }
3536
- { type: "anyDiscord", value: "anyDiscord" }
3637
- { type: "anyLinear", value: "anyLinear" }
3738
- { type: "slackChannel", value: slackChannelId }
3839
- { type: "githubRepository", value: githubRepositoryId }
40+
- { type: "gitlabProject", value: gitlabProjectId }
3941
- { type: "discordChannel", value: discordChannelId }
4042
- { type: "linearTeam", value: linearTeamId }
4143
- { type: "linearProject", value: linearProjectId }
@@ -45,11 +47,13 @@ SUMMARY TARGETS (for sendSummaries): array summaryFor[] where each item is one o
4547
- { type: "member", value: memberId }
4648
- { type: "team", value: teamId }
4749
- { type: "anyGithub", value: "anyGithub" }
50+
- { type: "anyGitlab", value: "anyGitlab" }
4851
- { type: "anySlack", value: "anySlack" }
4952
- { type: "anyDiscord", value: "anyDiscord" }
5053
- { type: "anyLinear", value: "anyLinear" }
5154
- { type: "slackChannel", value: slackChannelId }
5255
- { type: "githubRepository", value: githubRepositoryId }
56+
- { type: "gitlabProject", value: gitlabProjectId }
5357
- { type: "discordChannel", value: discordChannelId }
5458
- { type: "linearTeam", value: linearTeamId }
5559
- { type: "linearProject", value: linearProjectId }
@@ -61,12 +65,14 @@ RULES:
6165
- For generation: add { type: "organization", value: organizationSlug, usingActivityFrom: [...] }
6266
* If a specific team is mentioned (e.g., "Engineering team"), resolve to { type: "team", value: teamId }
6367
* If a specific person is mentioned, resolve to { type: "member", value: memberId }
64-
- Never invent IDs. Use list tools to resolve: members, teams, Slack/Discord channels. Use integration tools for github/slack/discord integration IDs.
68+
- Never invent IDs. Use list tools to resolve: members, teams, Slack/Discord channels. Use integration tools for github/slack/discord/gitlab/linear integration IDs.
6569
- Validate timezone and time format; if missing, default timezone to UTC and timeOfDay to 09:00.
6670
- If recurrence not specified, default to daily.
6771
- If weekly/monthly, ensure the correct day value exists; if not provided, choose the nearest valid future day based on current day.
6872
- For send routes (slackChannel/discordChannel), resolve channels by exact name match; prefer public channels when multiple; if ambiguity remains, pick the first and proceed.
6973
- If you cannot resolve a specific GitHub repository, prefer { type: "anyGithub", value: "anyGithub" }.
74+
- If you cannot resolve a specific GitLab project, prefer { type: "anyGitlab", value: "anyGitlab" }.
75+
- If you cannot resolve a specific Linear team or project, prefer { type: "anyLinear", value: "anyLinear" }.
7076
- After constructing a typed config, call create-organization-schedule (this will also create the initial run if active).
7177
- Return the created schedule id and the initial run id from the tool response.
7278
`;

apps/api/src/workflows/status-updates/generate-status-update/generate-status-update.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,15 @@ import { getDiscordServerTool } from "../../tools/get-discord-server-tool";
1212
import { getDiscordUserTool } from "../../tools/get-discord-user-tool";
1313
import { getExistingStatusUpdateItemsTool } from "../../tools/get-existing-status-update-items-tool";
1414
import { getGithubEventDetailTool } from "../../tools/get-github-event-detail-tool";
15+
import { getGithubIntegrationTool } from "../../tools/get-github-integration-tool";
1516
import { getGithubRepositoryTool } from "../../tools/get-github-repository-tool";
1617
import { getGithubUserTool } from "../../tools/get-github-user-tool";
1718
import { getGitlabEventDetailTool } from "../../tools/get-gitlab-event-detail-tool";
19+
import { getGitlabIntegrationTool } from "../../tools/get-gitlab-integration-tool";
1820
import { getGitlabProjectTool } from "../../tools/get-gitlab-project-tool";
1921
import { getGitlabUserTool } from "../../tools/get-gitlab-user-tool";
2022
import { getLinearEventDetailTool } from "../../tools/get-linear-event-detail-tool";
23+
import { getLinearIntegrationTool } from "../../tools/get-linear-integration-tool";
2124
import { getLinearIssueTool } from "../../tools/get-linear-issue-tool";
2225
import { getLinearProjectTool } from "../../tools/get-linear-project-tool";
2326
import { getLinearTeamTool } from "../../tools/get-linear-team-tool";
@@ -127,11 +130,13 @@ Available integrations: ${JSON.stringify(availableIntegrations)}.`,
127130
getGitHubEventDetail: getGithubEventDetailTool(db),
128131
getGitHubUser: getGithubUserTool(db),
129132
getGitHubRepository: getGithubRepositoryTool(db),
133+
getGithubIntegration: getGithubIntegrationTool(db),
130134

131135
getMemberGitlabEvents: getMemberGitlabEventsTool(db),
132136
getGitlabEventDetail: getGitlabEventDetailTool(db),
133137
getGitlabUser: getGitlabUserTool(db),
134138
getGitlabProject: getGitlabProjectTool(db),
139+
getGitlabIntegration: getGitlabIntegrationTool(db),
135140

136141
getMemberSlackEvents: getMemberSlackEventsTool(db),
137142
getSlackEventDetail: getSlackEventDetailTool(db),
@@ -152,6 +157,7 @@ Available integrations: ${JSON.stringify(availableIntegrations)}.`,
152157
getLinearTeam: getLinearTeamTool(db),
153158
getLinearProject: getLinearProjectTool(db),
154159
getLinearIssue: getLinearIssueTool(db),
160+
getLinearIntegration: getLinearIntegrationTool(db),
155161
},
156162
});
157163

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { tool } from "ai";
2+
import { eq } from "drizzle-orm";
3+
import { z } from "zod";
4+
import * as schema from "../../db";
5+
import type { Db } from "../../db/db";
6+
7+
export function getLinearIntegrationTool(db: Db) {
8+
return tool({
9+
description: `Get Linear integration details including team info for constructing links or defaults.`,
10+
parameters: z.object({
11+
organizationId: z.string().describe("The organization ID to get the Linear integration for"),
12+
}),
13+
execute: async (params) => {
14+
const integration = await db
15+
.select({
16+
id: schema.linearIntegration.id,
17+
teamId: schema.linearIntegration.teamId,
18+
teamName: schema.linearIntegration.teamName,
19+
teamKey: schema.linearIntegration.teamKey,
20+
createdAt: schema.linearIntegration.createdAt,
21+
updatedAt: schema.linearIntegration.updatedAt,
22+
})
23+
.from(schema.linearIntegration)
24+
.where(eq(schema.linearIntegration.organizationId, params.organizationId))
25+
.limit(1);
26+
return integration[0] || null;
27+
},
28+
});
29+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { tool } from "ai";
2+
import { eq } from "drizzle-orm";
3+
import { z } from "zod";
4+
import * as schema from "../../db";
5+
import type { Db } from "../../db/db";
6+
7+
export function listOrganizationGithubRepositoriesTool(db: Db) {
8+
return tool({
9+
description: `List GitHub repositories for an organization's GitHub integration. Use to map names to repository IDs.`,
10+
parameters: z.object({
11+
organizationId: z.string().describe("The organization ID that owns the GitHub integration"),
12+
}),
13+
execute: async (params) => {
14+
const repositories = await db
15+
.select({
16+
id: schema.githubRepository.id,
17+
repoId: schema.githubRepository.repoId,
18+
name: schema.githubRepository.name,
19+
owner: schema.githubRepository.owner,
20+
fullName: schema.githubRepository.fullName,
21+
private: schema.githubRepository.private,
22+
htmlUrl: schema.githubRepository.htmlUrl,
23+
createdAt: schema.githubRepository.createdAt,
24+
})
25+
.from(schema.githubRepository)
26+
.innerJoin(
27+
schema.githubIntegration,
28+
eq(schema.githubRepository.integrationId, schema.githubIntegration.id),
29+
)
30+
.where(eq(schema.githubIntegration.organizationId, params.organizationId));
31+
32+
return repositories;
33+
},
34+
});
35+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { tool } from "ai";
2+
import { eq } from "drizzle-orm";
3+
import { z } from "zod";
4+
import * as schema from "../../db";
5+
import type { Db } from "../../db/db";
6+
7+
export function listOrganizationGitlabProjectsTool(db: Db) {
8+
return tool({
9+
description: `List GitLab projects for an organization's GitLab integration. Use to map names to project IDs.`,
10+
parameters: z.object({
11+
organizationId: z.string().describe("The organization ID that owns the GitLab integration"),
12+
}),
13+
execute: async (params) => {
14+
const projects = await db
15+
.select({
16+
id: schema.gitlabProject.id,
17+
projectId: schema.gitlabProject.projectId,
18+
name: schema.gitlabProject.name,
19+
pathWithNamespace: schema.gitlabProject.pathWithNamespace,
20+
visibility: schema.gitlabProject.visibility,
21+
webUrl: schema.gitlabProject.webUrl,
22+
createdAt: schema.gitlabProject.createdAt,
23+
})
24+
.from(schema.gitlabProject)
25+
.innerJoin(
26+
schema.gitlabIntegration,
27+
eq(schema.gitlabProject.integrationId, schema.gitlabIntegration.id),
28+
)
29+
.where(eq(schema.gitlabIntegration.organizationId, params.organizationId));
30+
31+
return projects;
32+
},
33+
});
34+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { tool } from "ai";
2+
import { eq } from "drizzle-orm";
3+
import { z } from "zod";
4+
import * as schema from "../../db";
5+
import type { Db } from "../../db/db";
6+
7+
export function listOrganizationLinearProjectsTool(db: Db) {
8+
return tool({
9+
description: `List Linear projects for an organization's Linear integration. Use to map project names to IDs.`,
10+
parameters: z.object({
11+
organizationId: z.string().describe("The organization ID that owns the Linear integration"),
12+
}),
13+
execute: async (params) => {
14+
const projects = await db
15+
.select({
16+
id: schema.linearProject.id,
17+
projectId: schema.linearProject.projectId,
18+
teamId: schema.linearProject.teamId,
19+
name: schema.linearProject.name,
20+
key: schema.linearProject.key,
21+
createdAt: schema.linearProject.createdAt,
22+
})
23+
.from(schema.linearProject)
24+
.innerJoin(
25+
schema.linearIntegration,
26+
eq(schema.linearProject.integrationId, schema.linearIntegration.id),
27+
)
28+
.where(eq(schema.linearIntegration.organizationId, params.organizationId));
29+
30+
return projects;
31+
},
32+
});
33+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { tool } from "ai";
2+
import { eq } from "drizzle-orm";
3+
import { z } from "zod";
4+
import * as schema from "../../db";
5+
import type { Db } from "../../db/db";
6+
7+
export function listOrganizationLinearTeamsTool(db: Db) {
8+
return tool({
9+
description: `List Linear teams for an organization's Linear integration. Use to map team names to IDs.`,
10+
parameters: z.object({
11+
organizationId: z.string().describe("The organization ID that owns the Linear integration"),
12+
}),
13+
execute: async (params) => {
14+
const teams = await db
15+
.select({
16+
id: schema.linearTeam.id,
17+
teamId: schema.linearTeam.teamId,
18+
name: schema.linearTeam.name,
19+
key: schema.linearTeam.key,
20+
timezone: schema.linearTeam.timezone,
21+
private: schema.linearTeam.private,
22+
createdAt: schema.linearTeam.createdAt,
23+
})
24+
.from(schema.linearTeam)
25+
.innerJoin(
26+
schema.linearIntegration,
27+
eq(schema.linearTeam.integrationId, schema.linearIntegration.id),
28+
)
29+
.where(eq(schema.linearIntegration.organizationId, params.organizationId));
30+
31+
return teams;
32+
},
33+
});
34+
}

0 commit comments

Comments
 (0)