fix: resolve all linting issues in command files

Refactored createIssue, createTask, and onboardMentee commands to
extract helper functions, fix JSDoc descriptions, correct type
handling, and satisfy all ESLint rules. Also fixed object-shorthand
mixing in index.ts and the naming convention in anthropic.ts.
This commit is contained in:
2026-03-03 10:19:41 -08:00
parent 9df2d9ddc4
commit d0aaa7ec2f
5 changed files with 174 additions and 107 deletions
+83 -51
View File
@@ -4,19 +4,94 @@
* @author Naomi Carrigan
*/
import { MessageFlags } from "discord.js";
import { MessageFlags, type ChatInputCommandInteraction } from "discord.js";
import { ids } from "../config/ids.js";
import { anthropic } from "../utils/anthropic.js";
import { logger } from "../utils/logger.js";
import type { ChatInputCommandInteraction } from "discord.js";
interface LeantimeResponse {
error?: { message: string };
result?: number;
}
const taskSystemPrompt = "You are a helpful assistant that creates"
+ " well-structured task descriptions. Be concise and actionable."
+ " Return only the description text with no extra formatting or headers.";
/**
* @param interaction
* Generates an AI-augmented task description using Claude.
* @param description - Optional additional context for the task.
* @param title - The subject of the Leantime task.
* @returns The generated task description text.
*/
const generateTaskDescription = async(
description: string,
title: string,
): Promise<string> => {
const aiResponse = await anthropic.messages.create({
// eslint-disable-next-line @typescript-eslint/naming-convention -- Anthropic API field.
max_tokens: 500,
messages: [
{
content: `Create a clear, concise task description for a personal productivity board.\n\nTask title: ${title}${description === ""
? ""
: `\nAdditional context: ${description}`}`,
role: "user",
},
],
model: "claude-haiku-4-5-20251001",
system: taskSystemPrompt,
});
const [ firstContent ] = aiResponse.content;
return firstContent.type === "text"
? firstContent.text
: description;
};
/**
* Posts a task to the Leantime board via JSON-RPC.
* @param description - Body copy for the Leantime task.
* @param priority - The task priority level.
* @param title - The headline for the Leantime task.
* @returns The Leantime API response.
*/
const postLeantimeTask = async(
description: string,
priority: number,
title: string,
): Promise<LeantimeResponse> => {
const response = await fetch("https://board.nhcarrigan.com/api/jsonrpc", {
body: JSON.stringify({
id: `amari-task-${Date.now().toString()}`,
jsonrpc: "2.0",
method: "leantime.rpc.tickets.addTicket",
params: {
values: {
description: description,
editorId: "1",
headline: title,
priority: priority.toString(),
projectId: "1",
type: "task",
},
},
}),
headers: {
// eslint-disable-next-line @typescript-eslint/naming-convention -- HTTP header name.
"Content-Type": "application/json",
// eslint-disable-next-line @typescript-eslint/naming-convention -- HTTP header name.
"x-api-key": process.env.LEANTIME_KEY ?? "",
},
method: "POST",
});
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Required to type Response.json() output.
const data = await response.json() as LeantimeResponse;
return data;
};
/**
* Creates a Leantime task using AI-augmented description content.
* @param interaction - The Discord slash command interaction.
*/
export const createTask = async(
interaction: ChatInputCommandInteraction,
@@ -35,51 +110,8 @@ export const createTask = async(
await interaction.deferReply({ ephemeral: true });
const aiResponse = await anthropic.messages.create({
max_tokens: 500,
messages: [
{
content: `Create a clear, concise task description for a personal productivity board.\n\nTask title: ${title}${description
? `\nAdditional context: ${description}`
: ""}`,
role: "user",
},
],
model: "claude-haiku-4-5-20251001",
system: "You are a helpful assistant that creates well-structured task descriptions. Be concise and actionable. Return only the description text with no extra formatting or headers.",
});
const firstContent = aiResponse.content[0];
const augmentedDesc = firstContent.type === "text"
? firstContent.text
: description;
const response = await fetch("https://board.nhcarrigan.com/api/jsonrpc", {
body: JSON.stringify({
id: `amari-task-${Date.now().toString()}`,
jsonrpc: "2.0",
method: "leantime.rpc.tickets.addTicket",
params: {
values: {
description: augmentedDesc,
editorId: "1",
headline: title,
priority: priority.toString(),
projectId: "1",
type: "task",
},
},
}),
headers: {
"Content-Type": "application/json",
"x-api-key": process.env.LEANTIME_KEY ?? "",
},
method: "POST",
});
const data: LeantimeResponse = await response.json();
const augmentedDesc = await generateTaskDescription(description, title);
const data = await postLeantimeTask(augmentedDesc, priority, title);
if (data.error !== undefined) {
await interaction.editReply({
@@ -89,9 +121,9 @@ export const createTask = async(
}
const taskId = data.result;
const taskUrl = taskId !== undefined
? `https://board.nhcarrigan.com/dashboard/home#/tickets/showTicket/${taskId.toString()}`
: "https://board.nhcarrigan.com";
const taskUrl = taskId === undefined
? "https://board.nhcarrigan.com"
: `https://board.nhcarrigan.com/dashboard/home#/tickets/showTicket/${taskId.toString()}`;
await logger.metric("created_task", 1, { title });
await interaction.editReply({