@happyvertical/github-actions 0.74.8

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.
Files changed (65) hide show
  1. package/AGENT.md +33 -0
  2. package/LICENSE +7 -0
  3. package/README.md +147 -0
  4. package/dist/cli/claude-context.d.ts +3 -0
  5. package/dist/cli/claude-context.d.ts.map +1 -0
  6. package/dist/cli/claude-context.js +21 -0
  7. package/dist/cli/claude-context.js.map +1 -0
  8. package/dist/cli.d.ts +18 -0
  9. package/dist/cli.d.ts.map +1 -0
  10. package/dist/cli.js +325 -0
  11. package/dist/cli.js.map +1 -0
  12. package/dist/index-v2-CqFKwTm8.js +687 -0
  13. package/dist/index-v2-CqFKwTm8.js.map +1 -0
  14. package/dist/index.d.ts +19 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +637 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/labels-cli.d.ts +20 -0
  19. package/dist/labels-cli.d.ts.map +1 -0
  20. package/dist/planning/analyze.d.ts +13 -0
  21. package/dist/planning/analyze.d.ts.map +1 -0
  22. package/dist/planning/comment.d.ts +15 -0
  23. package/dist/planning/comment.d.ts.map +1 -0
  24. package/dist/planning/definition-of-ready.d.ts +15 -0
  25. package/dist/planning/definition-of-ready.d.ts.map +1 -0
  26. package/dist/planning/index.d.ts +14 -0
  27. package/dist/planning/index.d.ts.map +1 -0
  28. package/dist/planning/types.d.ts +71 -0
  29. package/dist/planning/types.d.ts.map +1 -0
  30. package/dist/shared/adapters.d.ts +11 -0
  31. package/dist/shared/adapters.d.ts.map +1 -0
  32. package/dist/shared/ai.d.ts +43 -0
  33. package/dist/shared/ai.d.ts.map +1 -0
  34. package/dist/shared/github.d.ts +52 -0
  35. package/dist/shared/github.d.ts.map +1 -0
  36. package/dist/shared/index.d.ts +9 -0
  37. package/dist/shared/index.d.ts.map +1 -0
  38. package/dist/shared/labels.d.ts +35 -0
  39. package/dist/shared/labels.d.ts.map +1 -0
  40. package/dist/shared/projects.d.ts +34 -0
  41. package/dist/shared/projects.d.ts.map +1 -0
  42. package/dist/triage/analyze.d.ts +12 -0
  43. package/dist/triage/analyze.d.ts.map +1 -0
  44. package/dist/triage/comment.d.ts +17 -0
  45. package/dist/triage/comment.d.ts.map +1 -0
  46. package/dist/triage/duplicates.d.ts +12 -0
  47. package/dist/triage/duplicates.d.ts.map +1 -0
  48. package/dist/triage/github.d.ts +5 -0
  49. package/dist/triage/github.d.ts.map +1 -0
  50. package/dist/triage/index-v2.d.ts +19 -0
  51. package/dist/triage/index-v2.d.ts.map +1 -0
  52. package/dist/triage/index.d.ts +13 -0
  53. package/dist/triage/index.d.ts.map +1 -0
  54. package/dist/triage/label-v2.d.ts +20 -0
  55. package/dist/triage/label-v2.d.ts.map +1 -0
  56. package/dist/triage/label.d.ts +16 -0
  57. package/dist/triage/label.d.ts.map +1 -0
  58. package/dist/triage/project-v2.d.ts +12 -0
  59. package/dist/triage/project-v2.d.ts.map +1 -0
  60. package/dist/triage/project.d.ts +7 -0
  61. package/dist/triage/project.d.ts.map +1 -0
  62. package/dist/triage/types.d.ts +64 -0
  63. package/dist/triage/types.d.ts.map +1 -0
  64. package/metadata.json +30 -0
  65. package/package.json +58 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-v2-CqFKwTm8.js","sources":["../src/shared/adapters.ts","../src/shared/ai.ts","../src/shared/labels.ts","../src/triage/analyze.ts","../src/triage/github.ts","../src/triage/comment.ts","../src/triage/duplicates.ts","../src/triage/label-v2.ts","../src/triage/project-v2.ts","../src/triage/index-v2.ts"],"sourcesContent":["/**\n * Adapters for @happyvertical/repos and @happyvertical/projects\n *\n * These functions adapt the standardized interfaces from @happyvertical/repos and @happyvertical/projects\n * to work with the triage context structure used in this package.\n */\n\nimport type { IProject } from '@happyvertical/projects';\nimport { getProject } from '@happyvertical/projects';\nimport type { IRepository } from '@happyvertical/repos';\nimport { getRepository } from '@happyvertical/repos';\n\n/**\n * Create a repository client from GitHub context\n */\nexport async function createRepository(\n token: string,\n owner: string,\n repo: string,\n): Promise<IRepository> {\n return getRepository({\n type: 'github',\n owner,\n repo,\n token,\n });\n}\n\n/**\n * Create a project client from configuration\n */\nexport async function createProject(\n token: string,\n projectId: string,\n statusFieldId: string,\n statusOptions: Record<string, string>,\n): Promise<IProject> {\n return getProject({\n type: 'github',\n projectId,\n token,\n statusFieldId,\n statusOptions,\n });\n}\n","/**\n * AI Client Wrapper\n *\n * Provides a unified interface for AI API calls.\n * Supports GitHub Models API (default) and other providers.\n */\n\nexport interface AIMessage {\n role: 'system' | 'user' | 'assistant';\n content: string;\n}\n\nexport interface AICompletionOptions {\n model?: string;\n temperature?: number;\n maxTokens?: number;\n}\n\n/**\n * Call GitHub Models API (available to all GitHub users)\n */\nexport async function callGitHubModels(\n token: string,\n messages: AIMessage[],\n options: AICompletionOptions = {},\n): Promise<string> {\n const model = options.model || 'gpt-4o-mini';\n const temperature = options.temperature ?? 0.3;\n const maxTokens = options.maxTokens ?? 1000;\n\n const response = await fetch(\n `https://models.inference.ai.azure.com/chat/completions`,\n {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n model,\n messages,\n temperature,\n max_tokens: maxTokens,\n }),\n },\n );\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(\n `GitHub Models API error: ${response.status} ${response.statusText}\\n${error}`,\n );\n }\n\n const result = (await response.json()) as {\n choices: { message: { content: string } }[];\n };\n\n return result.choices[0].message.content;\n}\n\n/**\n * Call OpenAI API directly\n */\nexport async function callOpenAI(\n apiKey: string,\n messages: AIMessage[],\n options: AICompletionOptions = {},\n): Promise<string> {\n const model = options.model || 'gpt-4o-mini';\n const temperature = options.temperature ?? 0.3;\n const maxTokens = options.maxTokens ?? 1000;\n\n const response = await fetch('https://api.openai.com/v1/chat/completions', {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${apiKey}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n model,\n messages,\n temperature,\n max_tokens: maxTokens,\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(\n `OpenAI API error: ${response.status} ${response.statusText}\\n${error}`,\n );\n }\n\n const result = (await response.json()) as {\n choices: { message: { content: string } }[];\n };\n\n return result.choices[0].message.content;\n}\n\n/**\n * Call Anthropic Claude API\n */\nexport async function callAnthropic(\n apiKey: string,\n messages: AIMessage[],\n options: AICompletionOptions = {},\n): Promise<string> {\n const model = options.model || 'claude-3-5-sonnet-20241022';\n const temperature = options.temperature ?? 0.3;\n const maxTokens = options.maxTokens ?? 1000;\n\n // Extract system message\n const systemMessage = messages.find((m) => m.role === 'system');\n const conversationMessages = messages.filter((m) => m.role !== 'system');\n\n const response = await fetch('https://api.anthropic.com/v1/messages', {\n method: 'POST',\n headers: {\n 'x-api-key': apiKey,\n 'anthropic-version': '2023-06-01',\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n model,\n max_tokens: maxTokens,\n temperature,\n system: systemMessage?.content,\n messages: conversationMessages,\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(\n `Anthropic API error: ${response.status} ${response.statusText}\\n${error}`,\n );\n }\n\n const result = (await response.json()) as {\n content: { text: string }[];\n };\n\n return result.content[0].text;\n}\n\n/**\n * Unified AI completion function\n *\n * Automatically selects provider based on available environment variables:\n * - GITHUB_TOKEN → GitHub Models (default)\n * - OPENAI_API_KEY → OpenAI\n * - ANTHROPIC_API_KEY → Anthropic\n */\nexport async function getAICompletion(\n messages: AIMessage[],\n options: AICompletionOptions = {},\n): Promise<string> {\n // Try GitHub Models first (available to all GitHub users)\n if (process.env.GITHUB_TOKEN) {\n return callGitHubModels(process.env.GITHUB_TOKEN, messages, options);\n }\n\n // Fall back to OpenAI\n if (process.env.OPENAI_API_KEY) {\n return callOpenAI(process.env.OPENAI_API_KEY, messages, options);\n }\n\n // Fall back to Anthropic\n if (process.env.ANTHROPIC_API_KEY) {\n return callAnthropic(process.env.ANTHROPIC_API_KEY, messages, options);\n }\n\n throw new Error(\n 'No AI API credentials found. Set GITHUB_TOKEN, OPENAI_API_KEY, or ANTHROPIC_API_KEY environment variable.',\n );\n}\n\n/**\n * Parse JSON from AI response\n *\n * Handles markdown code blocks and extracts JSON\n */\nexport function parseAIJson<T>(response: string): T {\n // Remove markdown code blocks if present\n let cleaned = response.trim();\n if (cleaned.startsWith('```json')) {\n cleaned = cleaned.slice(7);\n } else if (cleaned.startsWith('```')) {\n cleaned = cleaned.slice(3);\n }\n if (cleaned.endsWith('```')) {\n cleaned = cleaned.slice(0, -3);\n }\n cleaned = cleaned.trim();\n\n try {\n return JSON.parse(cleaned) as T;\n } catch (error) {\n throw new Error(\n `Failed to parse AI response as JSON: ${(error as Error).message}\\n\\nResponse: ${response}`,\n );\n }\n}\n","/**\n * Standard Label Definitions and Management\n *\n * Defines the organization-wide standard label set for kanban workflow.\n */\n\nexport interface LabelDefinition {\n name: string;\n color: string;\n description: string;\n}\n\n/**\n * Standard label set organized by category\n */\nexport const STANDARD_LABELS: Record<string, LabelDefinition[]> = {\n type: [\n {\n name: 'type: bug',\n color: 'd73a4a',\n description: \"Something isn't working\",\n },\n {\n name: 'type: feature',\n color: '0075ca',\n description: 'New feature or enhancement',\n },\n {\n name: 'type: docs',\n color: '0075ca',\n description: 'Documentation improvements',\n },\n {\n name: 'type: maintenance',\n color: '6c757d',\n description: 'Maintenance and refactoring',\n },\n {\n name: 'type: research',\n color: 'a371f7',\n description: 'Research and investigation',\n },\n {\n name: 'type: question',\n color: 'd876e3',\n description: 'Question or discussion',\n },\n ],\n priority: [\n {\n name: 'priority: critical',\n color: 'b60205',\n description: 'Critical priority, needs immediate attention',\n },\n {\n name: 'priority: high',\n color: 'd93f0b',\n description: 'High priority',\n },\n {\n name: 'priority: medium',\n color: 'fbca04',\n description: 'Medium priority (default)',\n },\n {\n name: 'priority: low',\n color: 'fef2c0',\n description: 'Low priority',\n },\n {\n name: 'priority: icebox',\n color: 'e1e4e8',\n description: 'Future consideration, keep in Backlog',\n },\n ],\n size: [\n {\n name: 'size: xs',\n color: 'c2e0c6',\n description: 'Extra small (< 2 hours)',\n },\n {\n name: 'size: s',\n color: '7bd88f',\n description: 'Small (2-4 hours)',\n },\n {\n name: 'size: m',\n color: '3fb950',\n description: 'Medium (~1 day)',\n },\n {\n name: 'size: l',\n color: '2ea043',\n description: 'Large (2-3 days)',\n },\n {\n name: 'size: xl',\n color: '1a7f37',\n description: 'Extra large (> 3 days)',\n },\n ],\n status: [\n {\n name: 'status: blocked',\n color: 'd73a4a',\n description: 'Blocked by external dependency',\n },\n {\n name: 'status: help-wanted',\n color: '008672',\n description: 'Community contributions welcome',\n },\n {\n name: 'status: good-first-issue',\n color: '7057ff',\n description: 'Good for newcomers',\n },\n ],\n};\n\n/**\n * Area labels are repository-specific, so we provide a template\n */\nexport const AREA_LABEL_TEMPLATE: LabelDefinition[] = [\n {\n name: 'area: core',\n color: 'fbca04',\n description: 'Core functionality',\n },\n {\n name: 'area: api',\n color: 'fbca04',\n description: 'API-related',\n },\n {\n name: 'area: ui',\n color: 'fbca04',\n description: 'User interface',\n },\n {\n name: 'area: cli',\n color: 'fbca04',\n description: 'Command-line interface',\n },\n {\n name: 'area: docs',\n color: 'fbca04',\n description: 'Documentation',\n },\n {\n name: 'area: infra',\n color: 'fbca04',\n description: 'Infrastructure and deployment',\n },\n {\n name: 'area: tests',\n color: 'fbca04',\n description: 'Testing infrastructure',\n },\n];\n\n/**\n * Get all standard labels as a flat array\n */\nexport function getAllStandardLabels(): LabelDefinition[] {\n return Object.values(STANDARD_LABELS).flat();\n}\n\n/**\n * Get labels by category\n */\nexport function getLabelsByCategory(category: string): LabelDefinition[] {\n return STANDARD_LABELS[category] || [];\n}\n\n/**\n * Map old label names to new standard names\n */\nexport const LABEL_MIGRATIONS: Record<string, string> = {\n bug: 'type: bug',\n feature: 'type: feature',\n enhancement: 'type: feature',\n documentation: 'type: docs',\n question: 'type: question',\n 'tech-debt': 'type: maintenance',\n epic: 'type: feature',\n};\n\n/**\n * Migrate old label to new standard label\n */\nexport function migrateLabel(oldLabel: string): string {\n return LABEL_MIGRATIONS[oldLabel] || oldLabel;\n}\n","/**\n * GitHub Models AI Analysis\n */\n\nimport { getAICompletion, parseAIJson } from '../shared/ai.js';\nimport type { AIAnalysis, TriageContext } from './types.js';\n\nconst VALID_TYPES = [\n 'bug',\n 'feature',\n 'docs',\n 'maintenance',\n 'research',\n 'question',\n] as const;\nconst VALID_PRIORITIES = [\n 'critical',\n 'high',\n 'medium',\n 'low',\n 'icebox',\n] as const;\nconst VALID_SIZES = ['xs', 's', 'm', 'l', 'xl'] as const;\n\nfunction validateAIAnalysis(parsed: unknown): AIAnalysis {\n if (!parsed || typeof parsed !== 'object') {\n throw new Error('AI response is not a valid object');\n }\n\n const response = parsed as Record<string, unknown>;\n\n // Validate required fields exist\n if (!response.type || typeof response.type !== 'string') {\n throw new Error('AI response missing required field: type');\n }\n if (!response.priority || typeof response.priority !== 'string') {\n throw new Error('AI response missing required field: priority');\n }\n if (!response.size || typeof response.size !== 'string') {\n throw new Error('AI response missing required field: size');\n }\n if (!response.reasoning || typeof response.reasoning !== 'string') {\n throw new Error('AI response missing required field: reasoning');\n }\n\n // Validate enum values\n if (!VALID_TYPES.includes(response.type as never)) {\n throw new Error(`Invalid type: ${response.type}`);\n }\n if (!VALID_PRIORITIES.includes(response.priority as never)) {\n throw new Error(`Invalid priority: ${response.priority}`);\n }\n if (!VALID_SIZES.includes(response.size as never)) {\n throw new Error(`Invalid size: ${response.size}`);\n }\n\n // Validate optional affected_packages field\n if (response.affected_packages !== undefined) {\n if (!Array.isArray(response.affected_packages)) {\n throw new Error('affected_packages must be an array');\n }\n if (!response.affected_packages.every((pkg) => typeof pkg === 'string')) {\n throw new Error('affected_packages must contain only strings');\n }\n }\n\n // All validations passed - construct validated object\n return {\n type: response.type,\n priority: response.priority,\n size: response.size,\n reasoning: response.reasoning,\n ...(response.affected_packages && {\n affected_packages: response.affected_packages,\n }),\n } as AIAnalysis;\n}\n\n/**\n * Analyze a GitHub issue using AI to determine type, priority, size, and affected packages.\n *\n * Sends the issue details to the configured AI provider and validates the structured response.\n *\n * @param context - Triage context with issue details and repository config\n * @returns Validated AI analysis with type, priority, size, and reasoning\n * @throws If the AI response cannot be parsed or fails validation\n */\nexport async function analyzeIssue(\n context: TriageContext,\n): Promise<AIAnalysis> {\n const prompt = buildAnalysisPrompt(context);\n\n const response = await getAICompletion([\n {\n role: 'system',\n content:\n 'You are an expert GitHub issue triager. Analyze issues and provide structured triage information in JSON format.',\n },\n {\n role: 'user',\n content: prompt,\n },\n ]);\n\n const parsed = parseAIJson(response);\n return validateAIAnalysis(parsed);\n}\n\nfunction buildAnalysisPrompt(context: TriageContext): string {\n const { config, issueNumber, issueTitle, issueBody, issueAuthor } = context;\n\n let prompt = `Analyze this GitHub issue and provide triage information for our kanban workflow.\n\nRepository: ${context.owner}/${context.repo} (${config.repoDescription})\n\nIssue #${issueNumber}\nTitle: ${issueTitle}\nBody: ${issueBody || '(empty)'}\nAuthor: ${issueAuthor}\n\nDetermine:\n1. **type**: One of: bug, feature, docs, maintenance, research, question\n2. **priority**: critical, high, medium, low, icebox\n - Use \"icebox\" for low priority or future consideration items\n3. **size**: Estimated effort: xs (<2hr), s (2-4hr), m (~1day), l (2-3days), xl (>3days)`;\n\n if (config.packagePattern) {\n prompt += `\n4. **affected_packages**: List of ${config.packagePattern} packages affected`;\n if (config.packageExamples && config.packageExamples.length > 0) {\n prompt += ` (e.g., ${JSON.stringify(config.packageExamples)})`;\n }\n prompt += `\n5. **reasoning**: Brief explanation of your analysis (2-3 sentences)`;\n } else {\n prompt += `\n4. **reasoning**: Brief explanation of your analysis (2-3 sentences)`;\n }\n\n prompt += `\n\nReturn JSON in this exact format:\n{\n \"type\": \"bug|feature|docs|maintenance|research|question\",\n \"priority\": \"critical|high|medium|low|icebox\",\n \"size\": \"xs|s|m|l|xl\",`;\n\n if (config.packagePattern) {\n prompt += `\n \"affected_packages\": [\"package names\"],`;\n }\n\n prompt += `\n \"reasoning\": \"explanation here\"\n}`;\n\n return prompt;\n}\n","/**\n * GitHub API Helper Functions\n */\n\nimport https from 'node:https';\n\nexport async function githubAPI(\n token: string,\n method: string,\n path: string,\n data: unknown = null,\n): Promise<unknown> {\n return new Promise((resolve, reject) => {\n const options: https.RequestOptions = {\n hostname: 'api.github.com',\n path,\n method,\n headers: {\n Authorization: `token ${token}`,\n Accept: 'application/vnd.github+json',\n 'User-Agent': 'happyvertical-github-actions',\n 'X-GitHub-Api-Version': '2022-11-28',\n },\n };\n\n if (data) {\n options.headers = {\n ...options.headers,\n 'Content-Type': 'application/json',\n };\n }\n\n const req = https.request(options, (res) => {\n let body = '';\n res.on('data', (chunk) => (body += chunk));\n res.on('end', () => {\n if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {\n resolve(body ? JSON.parse(body) : null);\n } else {\n reject(new Error(`GitHub API error: ${res.statusCode} ${body}`));\n }\n });\n });\n\n req.on('error', reject);\n if (data) req.write(JSON.stringify(data));\n req.end();\n });\n}\n","/**\n * Issue Comment Posting\n */\n\nimport { githubAPI } from './github.js';\nimport type { AIAnalysis, DuplicateIssue, TriageContext } from './types.js';\n\n/**\n * Post a structured triage comment on the issue with AI analysis results and duplicate links.\n *\n * @param context - Triage context with repo info and issue number\n * @param analysis - AI analysis results (type, priority, size, reasoning)\n * @param duplicates - Array of potential duplicate issues to include in the comment\n */\nexport async function postTriageComment(\n context: TriageContext,\n analysis: AIAnalysis,\n duplicates: DuplicateIssue[],\n): Promise<void> {\n const comment = buildTriageComment(context, analysis, duplicates);\n const path = `/repos/${context.owner}/${context.repo}/issues/${context.issueNumber}/comments`;\n\n try {\n await githubAPI(context.token, 'POST', path, { body: comment });\n console.log('Posted triage comment');\n } catch (error) {\n console.error('Error posting comment:', (error as Error).message);\n throw error;\n }\n}\n\n/**\n * Post a comment indicating that automated triage failed, prompting manual triage.\n *\n * @param context - Triage context with repo info and issue number\n * @param error - The error that caused triage to fail\n */\nexport async function postErrorComment(\n context: TriageContext,\n error: Error,\n): Promise<void> {\n const comment = `## 🤖 AI Triage Failed\\n\\nAutomated triage encountered an error:\\n\\`\\`\\`\\n${error.message}\\n\\`\\`\\`\\n\\nPlease triage this issue manually.`;\n const path = `/repos/${context.owner}/${context.repo}/issues/${context.issueNumber}/comments`;\n\n try {\n await githubAPI(context.token, 'POST', path, { body: comment });\n } catch (err) {\n console.error('Error posting error comment:', (err as Error).message);\n }\n}\n\nfunction buildTriageComment(\n context: TriageContext,\n analysis: AIAnalysis,\n duplicates: DuplicateIssue[],\n): string {\n let comment = `## 🤖 AI Triage\\n\\n`;\n comment += `**Type**: \\`${analysis.type}\\`\\n`;\n comment += `**Priority**: \\`${analysis.priority}\\`\\n`;\n comment += `**Size**: \\`${analysis.size}\\`\\n\\n`;\n\n if (analysis.affected_packages && analysis.affected_packages.length > 0) {\n const packages = analysis.affected_packages\n .map((p) => `\\`${p}\\``)\n .join(', ');\n comment += `**Affected Packages**: ${packages}\\n\\n`;\n }\n\n comment += `**Analysis**: ${analysis.reasoning}\\n\\n`;\n\n if (duplicates.length > 0) {\n comment += `### ⚠️ Potential Duplicates\\n\\n`;\n duplicates.forEach((dup) => {\n comment += `- #${dup.number}: ${dup.title}\\n`;\n });\n comment += `\\n`;\n }\n\n comment += `---\\n`;\n comment += `*This triage was performed automatically using GitHub Models API. Please review and adjust labels as needed.*`;\n\n return comment;\n}\n","/**\n * Duplicate Issue Detection\n */\n\nimport { githubAPI } from './github.js';\nimport type { DuplicateIssue, TriageContext } from './types.js';\n\n/**\n * Search for potential duplicate issues using GitHub Search API.\n *\n * Extracts keywords from the issue title and searches the repository for similar issues.\n * The current issue is excluded from results.\n *\n * @param context - Triage context with issue details and repo info\n * @returns Array of potentially duplicate issues (up to 4)\n */\nexport async function searchDuplicates(\n context: TriageContext,\n): Promise<DuplicateIssue[]> {\n const keywords = context.issueTitle.split(' ').slice(0, 5).join(' ');\n const query = `repo:${context.owner}/${context.repo} is:issue ${keywords}`;\n const path = `/search/issues?q=${encodeURIComponent(query)}&per_page=5`;\n\n try {\n const result = (await githubAPI(context.token, 'GET', path, null)) as {\n items: DuplicateIssue[];\n };\n\n // Exclude the current issue from results\n return result.items.filter((issue) => issue.number !== context.issueNumber);\n } catch (error) {\n console.error('Error searching for duplicates:', (error as Error).message);\n return [];\n }\n}\n","/**\n * Issue Labeling (Refactored to use @happyvertical/repos)\n */\n\nimport { createRepository } from '../shared/adapters.js';\nimport type { TriageContext } from './types.js';\n\n/**\n * Apply labels to an issue using `@happyvertical/repos`.\n *\n * @param context - Triage context with token and repo info\n * @param labels - Label names to apply\n */\nexport async function applyLabels(\n context: TriageContext,\n labels: string[],\n): Promise<void> {\n if (labels.length === 0) {\n console.log('No labels to apply');\n return;\n }\n\n try {\n const repo = await createRepository(\n context.token,\n context.owner,\n context.repo,\n );\n await repo.addLabels(context.issueNumber, labels);\n console.log(`Applied labels: ${labels.join(', ')}`);\n } catch (error) {\n console.error('Error applying labels:', (error as Error).message);\n throw error;\n }\n}\n\n/**\n * Remove an `agent: <type>` label from an issue. Silently ignores 404 errors.\n *\n * @param context - Triage context with token and repo info\n * @param agentType - Agent type suffix (e.g., \"triage\", \"planning\")\n */\nexport async function removeAgentLabel(\n context: TriageContext,\n agentType: string,\n): Promise<void> {\n const label = `agent: ${agentType}`;\n try {\n const repo = await createRepository(\n context.token,\n context.owner,\n context.repo,\n );\n await repo.removeLabel(context.issueNumber, label);\n console.log(`Removed label: ${label}`);\n } catch (error) {\n // Ignore if label doesn't exist\n if (!(error as Error).message.includes('404')) {\n console.error('Error removing label:', (error as Error).message);\n }\n }\n}\n\nexport function getTypeLabel(type: string): string {\n return `type: ${type}`;\n}\n\nexport function getPriorityLabel(priority: string): string {\n return `priority: ${priority}`;\n}\n\nexport function getSizeLabel(size: string): string {\n return `size: ${size}`;\n}\n\nexport function getAgentLabel(agentType: string): string {\n return `agent: ${agentType}`;\n}\n","/**\n * GitHub Project Board Management (Refactored to use @happyvertical/projects)\n */\n\nimport { createProject, createRepository } from '../shared/adapters.js';\nimport type { TriageContext } from './types.js';\n\n/**\n * Update an issue's status on the GitHub Projects V2 board using `@happyvertical/projects`.\n *\n * Adds the issue to the project if not already present, then sets the status field.\n * No-ops if project integration is disabled or the status name is not configured.\n *\n * @param context - Triage context with project config\n * @param statusName - Target status name (must exist in `config.statusOptions`)\n */\nexport async function updateProjectStatus(\n context: TriageContext,\n statusName: string,\n): Promise<void> {\n if (!context.config.projectEnabled) {\n console.log('Project board integration disabled');\n return;\n }\n\n if (!context.config.projectId || !context.config.statusFieldId) {\n console.log('Project configuration missing');\n return;\n }\n\n if (\n !context.config.statusOptions ||\n !context.config.statusOptions[statusName]\n ) {\n console.log(`Status \"${statusName}\" not configured`);\n return;\n }\n\n try {\n const repo = await createRepository(\n context.token,\n context.owner,\n context.repo,\n );\n\n const project = await createProject(\n context.token,\n context.config.projectId,\n context.config.statusFieldId,\n context.config.statusOptions,\n );\n\n // Get issue node ID\n const issue = await repo.getIssue(context.issueNumber);\n\n // Try to find existing project item\n const items = await project.listItems();\n let itemId = items.find(\n (item: { contentId: string; id: string }) => item.contentId === issue.id,\n )?.id;\n\n // Add to project if not already there\n if (!itemId) {\n console.log('Issue not in project, adding...');\n const item = await project.addItem(issue.id);\n itemId = item.id;\n }\n\n // Update status\n await project.updateItemStatus(itemId, statusName);\n console.log(`Updated project status to: ${statusName}`);\n } catch (error) {\n console.error('Error updating project status:', (error as Error).message);\n throw error;\n }\n}\n","/**\n * Issue Triage Orchestration (Refactored to use @happyvertical/repos and @happyvertical/projects)\n */\n\nimport { analyzeIssue } from './analyze.js';\nimport { postErrorComment, postTriageComment } from './comment.js';\nimport { searchDuplicates } from './duplicates.js';\nimport {\n applyLabels,\n getAgentLabel,\n getPriorityLabel,\n getSizeLabel,\n getTypeLabel,\n removeAgentLabel,\n} from './label-v2.js';\nimport { updateProjectStatus } from './project-v2.js';\nimport type { TriageContext, TriageResult } from './types.js';\n\nexport { analyzeIssue } from './analyze.js';\nexport { postErrorComment, postTriageComment } from './comment.js';\nexport { searchDuplicates } from './duplicates.js';\nexport {\n applyLabels,\n getAgentLabel,\n getPriorityLabel,\n getSizeLabel,\n getTypeLabel,\n removeAgentLabel,\n} from './label-v2.js';\nexport { updateProjectStatus } from './project-v2.js';\nexport * from './types.js';\n\n/**\n * Run the full issue triage workflow using `@happyvertical/repos`.\n *\n * Applies an agent label, runs AI analysis, searches for duplicates,\n * applies type/priority/size labels, posts a triage comment, and\n * optionally updates the project board status.\n *\n * @param context - Triage context including token, repo info, issue details, and config\n * @returns Result indicating success/failure with analysis and duplicate data\n */\nexport async function triageIssue(\n context: TriageContext,\n): Promise<TriageResult> {\n console.log(`Triaging issue #${context.issueNumber}: ${context.issueTitle}`);\n\n try {\n // Apply agent: triage label\n await applyLabels(context, [getAgentLabel('triage')]);\n\n // Get AI analysis\n console.log('Calling AI for analysis...');\n const analysis = await analyzeIssue(context);\n console.log('AI Analysis:', JSON.stringify(analysis, null, 2));\n\n // Search for duplicates\n console.log('Searching for potential duplicates...');\n const duplicates = await searchDuplicates(context);\n console.log(`Found ${duplicates.length} potential duplicates`);\n\n // Apply type, priority, and size labels\n const labels: string[] = [\n getTypeLabel(analysis.type),\n getPriorityLabel(analysis.priority),\n getSizeLabel(analysis.size),\n ];\n\n await applyLabels(context, labels);\n\n // Post triage comment\n await postTriageComment(context, analysis, duplicates);\n\n // Remove agent: triage label\n await removeAgentLabel(context, 'triage');\n\n // Move to Backlog status\n if (context.config.projectEnabled) {\n console.log('Moving issue to Backlog...');\n await updateProjectStatus(context, 'Backlog');\n }\n\n console.log('✅ Triage complete!');\n\n return {\n success: true,\n analysis,\n duplicates,\n };\n } catch (error) {\n console.error('❌ Triage failed:', (error as Error).message);\n console.error((error as Error).stack);\n\n // Post error comment\n await postErrorComment(context, error as Error);\n\n return {\n success: false,\n error: (error as Error).message,\n };\n }\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @happyvertical/github-actions - Reusable GitHub Actions Utilities
3
+ *
4
+ * Provides modular, testable utilities for GitHub Actions workflows including:
5
+ * - Issue triage with AI analysis
6
+ * - Duplicate detection
7
+ * - Auto-labeling
8
+ * - Project board management
9
+ * - Planning workflow automation
10
+ * - Testing and review automation
11
+ */
12
+ export * from './planning/index.js';
13
+ export * from './shared/adapters.js';
14
+ export * from './shared/index.js';
15
+ export * as legacy from './triage/index.js';
16
+ export * from './triage/index-v2.js';
17
+ /** @internal */
18
+ export declare const PACKAGE_VERSION_INITIALIZED = true;
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAElC,OAAO,KAAK,MAAM,MAAM,mBAAmB,CAAC;AAE5C,cAAc,sBAAsB,CAAC;AAErC,gBAAgB;AAChB,eAAO,MAAM,2BAA2B,OAAO,CAAC"}