@eldrforge/kodrdriv 0.0.24 → 0.0.26

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.
@@ -1,6 +1,7 @@
1
1
  import { Octokit } from '@octokit/rest';
2
2
  import { getLogger } from '../logging.js';
3
3
  import { run } from './child.js';
4
+ import { promptConfirmation } from './stdin.js';
4
5
 
5
6
  const getOctokit = ()=>{
6
7
  const logger = getLogger();
@@ -67,11 +68,48 @@ const findOpenPullRequestByHeadRef = async (head)=>{
67
68
  }
68
69
  };
69
70
  const delay = (ms)=>new Promise((resolve)=>setTimeout(resolve, ms));
70
- const waitForPullRequestChecks = async (prNumber)=>{
71
+ // Check if repository has GitHub Actions workflows configured
72
+ const hasWorkflowsConfigured = async ()=>{
73
+ const octokit = getOctokit();
74
+ const { owner, repo } = await getRepoDetails();
75
+ try {
76
+ const response = await octokit.actions.listRepoWorkflows({
77
+ owner,
78
+ repo
79
+ });
80
+ return response.data.workflows.length > 0;
81
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
82
+ } catch (error) {
83
+ // If we can't check workflows (e.g., no Actions permission), assume they might exist
84
+ return true;
85
+ }
86
+ };
87
+ const waitForPullRequestChecks = async (prNumber, options = {})=>{
71
88
  const octokit = getOctokit();
72
89
  const { owner, repo } = await getRepoDetails();
73
90
  const logger = getLogger();
91
+ const timeout = options.timeout || 300000; // 5 minutes default timeout
92
+ const skipUserConfirmation = options.skipUserConfirmation || false;
93
+ const startTime = Date.now();
94
+ let consecutiveNoChecksCount = 0;
95
+ const maxConsecutiveNoChecks = 6; // 6 consecutive checks (1 minute) with no checks before asking user
74
96
  while(true){
97
+ const elapsedTime = Date.now() - startTime;
98
+ // Check for timeout
99
+ if (elapsedTime > timeout) {
100
+ logger.warn(`Timeout reached (${timeout / 1000}s) while waiting for PR #${prNumber} checks.`);
101
+ if (!skipUserConfirmation) {
102
+ const proceedWithoutChecks = await promptConfirmation(`⚠️ Timeout reached while waiting for PR #${prNumber} checks.\n` + `This might indicate that no checks are configured for this repository.\n` + `Do you want to proceed with merging the PR without waiting for checks?`);
103
+ if (proceedWithoutChecks) {
104
+ logger.info('User chose to proceed without waiting for checks.');
105
+ return;
106
+ } else {
107
+ throw new Error(`Timeout waiting for PR #${prNumber} checks. User chose not to proceed.`);
108
+ }
109
+ } else {
110
+ throw new Error(`Timeout waiting for PR #${prNumber} checks (${timeout / 1000}s)`);
111
+ }
112
+ }
75
113
  const pr = await octokit.pulls.get({
76
114
  owner,
77
115
  repo,
@@ -84,10 +122,37 @@ const waitForPullRequestChecks = async (prNumber)=>{
84
122
  });
85
123
  const checkRuns = checkRunsResponse.data.check_runs;
86
124
  if (checkRuns.length === 0) {
87
- logger.info(`PR #${prNumber}: No checks found. Waiting...`);
125
+ consecutiveNoChecksCount++;
126
+ logger.info(`PR #${prNumber}: No checks found (${consecutiveNoChecksCount}/${maxConsecutiveNoChecks}). Waiting...`);
127
+ // After several consecutive "no checks" responses, check if workflows are configured
128
+ if (consecutiveNoChecksCount >= maxConsecutiveNoChecks) {
129
+ logger.info(`No checks detected for ${maxConsecutiveNoChecks} consecutive attempts. Checking repository configuration...`);
130
+ const hasWorkflows = await hasWorkflowsConfigured();
131
+ if (!hasWorkflows) {
132
+ logger.warn(`No GitHub Actions workflows found in repository ${owner}/${repo}.`);
133
+ if (!skipUserConfirmation) {
134
+ const proceedWithoutChecks = await promptConfirmation(`⚠️ No GitHub Actions workflows or checks are configured for this repository.\n` + `PR #${prNumber} will never have status checks to wait for.\n` + `Do you want to proceed with merging the PR without checks?`);
135
+ if (proceedWithoutChecks) {
136
+ logger.info('User chose to proceed without checks (no workflows configured).');
137
+ return;
138
+ } else {
139
+ throw new Error(`No checks configured for PR #${prNumber}. User chose not to proceed.`);
140
+ }
141
+ } else {
142
+ // In non-interactive mode, proceed if no workflows are configured
143
+ logger.info('No workflows configured, proceeding without checks.');
144
+ return;
145
+ }
146
+ } else {
147
+ logger.info('GitHub Actions workflows are configured. Continuing to wait for checks...');
148
+ consecutiveNoChecksCount = 0; // Reset counter since workflows exist
149
+ }
150
+ }
88
151
  await delay(10000);
89
152
  continue;
90
153
  }
154
+ // Reset the no-checks counter since we found some checks
155
+ consecutiveNoChecksCount = 0;
91
156
  const failingChecks = checkRuns.filter((cr)=>cr.conclusion && [
92
157
  'failure',
93
158
  'timed_out',
@@ -1 +1 @@
1
- {"version":3,"file":"github.js","sources":["../../src/util/github.ts"],"sourcesContent":["import { Octokit } from '@octokit/rest';\nimport { getLogger } from '../logging';\nimport { PullRequest, MergeMethod } from '../types';\nimport { run } from './child';\n\nexport const getOctokit = (): Octokit => {\n const logger = getLogger();\n const token = process.env.GITHUB_TOKEN;\n\n if (!token) {\n logger.error('GITHUB_TOKEN environment variable is not set.');\n throw new Error('GITHUB_TOKEN is not set.');\n }\n\n return new Octokit({\n auth: token,\n });\n};\n\nexport const getCurrentBranchName = async (): Promise<string> => {\n const { stdout } = await run('git rev-parse --abbrev-ref HEAD');\n return stdout.trim();\n};\n\nexport const getRepoDetails = async (): Promise<{ owner: string; repo: string }> => {\n const { stdout } = await run('git remote get-url origin');\n const url = stdout.trim();\n // git@github.com:owner/repo.git or https://github.com/owner/repo.git\n const match = url.match(/github\\.com[/:]([\\w-]+)\\/([\\w.-]+)\\.git/);\n if (!match) {\n throw new Error(`Could not parse repository owner and name from origin URL: \"${url}\". Expected format: git@github.com:owner/repo.git or https://github.com/owner/repo.git`);\n }\n return { owner: match[1], repo: match[2] };\n};\n\nexport const createPullRequest = async (\n title: string,\n body: string,\n head: string,\n base: string = 'main'\n): Promise<PullRequest> => {\n const octokit = getOctokit();\n const { owner, repo } = await getRepoDetails();\n\n const response = await octokit.pulls.create({\n owner,\n repo,\n title,\n body,\n head,\n base,\n });\n\n return response.data;\n};\n\nexport const findOpenPullRequestByHeadRef = async (head: string): Promise<PullRequest | null> => {\n const octokit = getOctokit();\n const { owner, repo } = await getRepoDetails();\n const logger = getLogger();\n\n try {\n logger.debug(`Searching for open pull requests with head: ${owner}:${head} in ${owner}/${repo}`);\n\n const response = await octokit.pulls.list({\n owner,\n repo,\n state: 'open',\n head: `${owner}:${head}`,\n });\n\n logger.debug(`Found ${response.data.length} open pull requests`);\n return response.data[0] ?? null;\n } catch (error: any) {\n logger.error(`Failed to find open pull requests: ${error.message}`);\n if (error.status === 404) {\n logger.error(`Repository ${owner}/${repo} not found or access denied. Please check your GITHUB_TOKEN permissions.`);\n }\n throw error;\n }\n};\n\nconst delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));\n\nexport const waitForPullRequestChecks = async (prNumber: number): Promise<void> => {\n const octokit = getOctokit();\n const { owner, repo } = await getRepoDetails();\n const logger = getLogger();\n\n while (true) {\n const pr = await octokit.pulls.get({\n owner,\n repo,\n pull_number: prNumber,\n });\n\n const checkRunsResponse = await octokit.checks.listForRef({\n owner,\n repo,\n ref: pr.data.head.sha,\n });\n\n const checkRuns = checkRunsResponse.data.check_runs;\n\n if (checkRuns.length === 0) {\n logger.info(`PR #${prNumber}: No checks found. Waiting...`);\n await delay(10000);\n continue;\n }\n\n const failingChecks = checkRuns.filter(\n (cr) => cr.conclusion && ['failure', 'timed_out', 'cancelled'].includes(cr.conclusion)\n );\n\n if (failingChecks.length > 0) {\n logger.error(`PR #${prNumber} has failing checks:`);\n for (const check of failingChecks) {\n logger.error(`- ${check.name}: ${check.conclusion}`);\n }\n throw new Error(`PR #${prNumber} checks failed.`);\n }\n\n const allChecksCompleted = checkRuns.every((cr) => cr.status === 'completed');\n\n if (allChecksCompleted) {\n logger.info(`All checks for PR #${prNumber} have completed successfully.`);\n return;\n }\n\n const completedCount = checkRuns.filter(cr => cr.status === 'completed').length;\n logger.info(`PR #${prNumber} checks: ${completedCount}/${checkRuns.length} completed. Waiting...`);\n\n await delay(10000); // wait 10 seconds\n }\n};\n\nexport const mergePullRequest = async (prNumber: number, mergeMethod: MergeMethod = 'squash'): Promise<void> => {\n const octokit = getOctokit();\n const { owner, repo } = await getRepoDetails();\n const logger = getLogger();\n\n logger.info(`Merging PR #${prNumber} using ${mergeMethod} method...`);\n const pr = await octokit.pulls.get({\n owner,\n repo,\n pull_number: prNumber,\n });\n const headBranch = pr.data.head.ref;\n\n await octokit.pulls.merge({\n owner,\n repo,\n pull_number: prNumber,\n merge_method: mergeMethod,\n });\n logger.info(`PR #${prNumber} merged using ${mergeMethod} method.`);\n\n logger.info(`Deleting branch ${headBranch}...`);\n await octokit.git.deleteRef({\n owner,\n repo,\n ref: `heads/${headBranch}`,\n });\n logger.info(`Branch ${headBranch} deleted.`);\n};\n\nexport const createRelease = async (tagName: string, title: string, notes: string): Promise<void> => {\n const octokit = getOctokit();\n const { owner, repo } = await getRepoDetails();\n const logger = getLogger();\n\n logger.info(`Creating release for tag ${tagName}...`);\n await octokit.repos.createRelease({\n owner,\n repo,\n tag_name: tagName,\n name: title,\n body: notes,\n });\n logger.info(`Release ${tagName} created.`);\n};\n\nexport const getOpenIssues = async (limit: number = 20): Promise<string> => {\n const octokit = getOctokit();\n const { owner, repo } = await getRepoDetails();\n const logger = getLogger();\n\n try {\n logger.debug(`Fetching up to ${limit} open GitHub issues...`);\n\n const response = await octokit.issues.listForRepo({\n owner,\n repo,\n state: 'open',\n per_page: Math.min(limit, 100), // GitHub API limit\n sort: 'updated',\n direction: 'desc',\n });\n\n const issues = response.data.filter(issue => !issue.pull_request); // Filter out PRs\n\n if (issues.length === 0) {\n logger.debug('No open issues found');\n return '';\n }\n\n const issueStrings = issues.slice(0, limit).map(issue => {\n const labels = issue.labels.map(label =>\n typeof label === 'string' ? label : label.name\n ).join(', ');\n\n return [\n `Issue #${issue.number}: ${issue.title}`,\n `Labels: ${labels || 'none'}`,\n `Created: ${issue.created_at}`,\n `Updated: ${issue.updated_at}`,\n `Body: ${issue.body?.substring(0, 500) || 'No description'}${issue.body && issue.body.length > 500 ? '...' : ''}`,\n '---'\n ].join('\\n');\n });\n\n logger.debug(`Fetched ${issues.length} open issues`);\n return issueStrings.join('\\n\\n');\n } catch (error: any) {\n logger.warn('Failed to fetch GitHub issues: %s', error.message);\n return '';\n }\n};\n\nexport const createIssue = async (\n title: string,\n body: string,\n labels?: string[]\n): Promise<{ number: number; html_url: string }> => {\n const octokit = getOctokit();\n const { owner, repo } = await getRepoDetails();\n\n const response = await octokit.issues.create({\n owner,\n repo,\n title,\n body,\n labels: labels || [],\n });\n\n return {\n number: response.data.number,\n html_url: response.data.html_url,\n };\n}; "],"names":["getOctokit","logger","getLogger","token","process","env","GITHUB_TOKEN","error","Error","Octokit","auth","getCurrentBranchName","stdout","run","trim","getRepoDetails","url","match","owner","repo","createPullRequest","title","body","head","base","octokit","response","pulls","create","data","findOpenPullRequestByHeadRef","debug","list","state","length","message","status","delay","ms","Promise","resolve","setTimeout","waitForPullRequestChecks","prNumber","pr","get","pull_number","checkRunsResponse","checks","listForRef","ref","sha","checkRuns","check_runs","info","failingChecks","filter","cr","conclusion","includes","check","name","allChecksCompleted","every","completedCount","mergePullRequest","mergeMethod","headBranch","merge","merge_method","git","deleteRef","createRelease","tagName","notes","repos","tag_name","getOpenIssues","limit","issues","listForRepo","per_page","Math","min","sort","direction","issue","pull_request","issueStrings","slice","map","labels","label","join","number","created_at","updated_at","substring","warn","createIssue","html_url"],"mappings":"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"}
1
+ {"version":3,"file":"github.js","sources":["../../src/util/github.ts"],"sourcesContent":["import { Octokit } from '@octokit/rest';\nimport { getLogger } from '../logging';\nimport { PullRequest, MergeMethod } from '../types';\nimport { run } from './child';\nimport { promptConfirmation } from './stdin';\n\nexport const getOctokit = (): Octokit => {\n const logger = getLogger();\n const token = process.env.GITHUB_TOKEN;\n\n if (!token) {\n logger.error('GITHUB_TOKEN environment variable is not set.');\n throw new Error('GITHUB_TOKEN is not set.');\n }\n\n return new Octokit({\n auth: token,\n });\n};\n\nexport const getCurrentBranchName = async (): Promise<string> => {\n const { stdout } = await run('git rev-parse --abbrev-ref HEAD');\n return stdout.trim();\n};\n\nexport const getRepoDetails = async (): Promise<{ owner: string; repo: string }> => {\n const { stdout } = await run('git remote get-url origin');\n const url = stdout.trim();\n // git@github.com:owner/repo.git or https://github.com/owner/repo.git\n const match = url.match(/github\\.com[/:]([\\w-]+)\\/([\\w.-]+)\\.git/);\n if (!match) {\n throw new Error(`Could not parse repository owner and name from origin URL: \"${url}\". Expected format: git@github.com:owner/repo.git or https://github.com/owner/repo.git`);\n }\n return { owner: match[1], repo: match[2] };\n};\n\nexport const createPullRequest = async (\n title: string,\n body: string,\n head: string,\n base: string = 'main'\n): Promise<PullRequest> => {\n const octokit = getOctokit();\n const { owner, repo } = await getRepoDetails();\n\n const response = await octokit.pulls.create({\n owner,\n repo,\n title,\n body,\n head,\n base,\n });\n\n return response.data;\n};\n\nexport const findOpenPullRequestByHeadRef = async (head: string): Promise<PullRequest | null> => {\n const octokit = getOctokit();\n const { owner, repo } = await getRepoDetails();\n const logger = getLogger();\n\n try {\n logger.debug(`Searching for open pull requests with head: ${owner}:${head} in ${owner}/${repo}`);\n\n const response = await octokit.pulls.list({\n owner,\n repo,\n state: 'open',\n head: `${owner}:${head}`,\n });\n\n logger.debug(`Found ${response.data.length} open pull requests`);\n return response.data[0] ?? null;\n } catch (error: any) {\n logger.error(`Failed to find open pull requests: ${error.message}`);\n if (error.status === 404) {\n logger.error(`Repository ${owner}/${repo} not found or access denied. Please check your GITHUB_TOKEN permissions.`);\n }\n throw error;\n }\n};\n\nconst delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));\n\n// Check if repository has GitHub Actions workflows configured\nconst hasWorkflowsConfigured = async (): Promise<boolean> => {\n const octokit = getOctokit();\n const { owner, repo } = await getRepoDetails();\n\n try {\n const response = await octokit.actions.listRepoWorkflows({\n owner,\n repo,\n });\n\n return response.data.workflows.length > 0;\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (error: any) {\n // If we can't check workflows (e.g., no Actions permission), assume they might exist\n return true;\n }\n};\n\nexport const waitForPullRequestChecks = async (prNumber: number, options: { timeout?: number; skipUserConfirmation?: boolean } = {}): Promise<void> => {\n const octokit = getOctokit();\n const { owner, repo } = await getRepoDetails();\n const logger = getLogger();\n const timeout = options.timeout || 300000; // 5 minutes default timeout\n const skipUserConfirmation = options.skipUserConfirmation || false;\n\n const startTime = Date.now();\n let consecutiveNoChecksCount = 0;\n const maxConsecutiveNoChecks = 6; // 6 consecutive checks (1 minute) with no checks before asking user\n\n while (true) {\n const elapsedTime = Date.now() - startTime;\n\n // Check for timeout\n if (elapsedTime > timeout) {\n logger.warn(`Timeout reached (${timeout / 1000}s) while waiting for PR #${prNumber} checks.`);\n\n if (!skipUserConfirmation) {\n const proceedWithoutChecks = await promptConfirmation(\n `⚠️ Timeout reached while waiting for PR #${prNumber} checks.\\n` +\n `This might indicate that no checks are configured for this repository.\\n` +\n `Do you want to proceed with merging the PR without waiting for checks?`\n );\n\n if (proceedWithoutChecks) {\n logger.info('User chose to proceed without waiting for checks.');\n return;\n } else {\n throw new Error(`Timeout waiting for PR #${prNumber} checks. User chose not to proceed.`);\n }\n } else {\n throw new Error(`Timeout waiting for PR #${prNumber} checks (${timeout / 1000}s)`);\n }\n }\n\n const pr = await octokit.pulls.get({\n owner,\n repo,\n pull_number: prNumber,\n });\n\n const checkRunsResponse = await octokit.checks.listForRef({\n owner,\n repo,\n ref: pr.data.head.sha,\n });\n\n const checkRuns = checkRunsResponse.data.check_runs;\n\n if (checkRuns.length === 0) {\n consecutiveNoChecksCount++;\n logger.info(`PR #${prNumber}: No checks found (${consecutiveNoChecksCount}/${maxConsecutiveNoChecks}). Waiting...`);\n\n // After several consecutive \"no checks\" responses, check if workflows are configured\n if (consecutiveNoChecksCount >= maxConsecutiveNoChecks) {\n logger.info(`No checks detected for ${maxConsecutiveNoChecks} consecutive attempts. Checking repository configuration...`);\n\n const hasWorkflows = await hasWorkflowsConfigured();\n\n if (!hasWorkflows) {\n logger.warn(`No GitHub Actions workflows found in repository ${owner}/${repo}.`);\n\n if (!skipUserConfirmation) {\n const proceedWithoutChecks = await promptConfirmation(\n `⚠️ No GitHub Actions workflows or checks are configured for this repository.\\n` +\n `PR #${prNumber} will never have status checks to wait for.\\n` +\n `Do you want to proceed with merging the PR without checks?`\n );\n\n if (proceedWithoutChecks) {\n logger.info('User chose to proceed without checks (no workflows configured).');\n return;\n } else {\n throw new Error(`No checks configured for PR #${prNumber}. User chose not to proceed.`);\n }\n } else {\n // In non-interactive mode, proceed if no workflows are configured\n logger.info('No workflows configured, proceeding without checks.');\n return;\n }\n } else {\n logger.info('GitHub Actions workflows are configured. Continuing to wait for checks...');\n consecutiveNoChecksCount = 0; // Reset counter since workflows exist\n }\n }\n\n await delay(10000);\n continue;\n }\n\n // Reset the no-checks counter since we found some checks\n consecutiveNoChecksCount = 0;\n\n const failingChecks = checkRuns.filter(\n (cr) => cr.conclusion && ['failure', 'timed_out', 'cancelled'].includes(cr.conclusion)\n );\n\n if (failingChecks.length > 0) {\n logger.error(`PR #${prNumber} has failing checks:`);\n for (const check of failingChecks) {\n logger.error(`- ${check.name}: ${check.conclusion}`);\n }\n throw new Error(`PR #${prNumber} checks failed.`);\n }\n\n const allChecksCompleted = checkRuns.every((cr) => cr.status === 'completed');\n\n if (allChecksCompleted) {\n logger.info(`All checks for PR #${prNumber} have completed successfully.`);\n return;\n }\n\n const completedCount = checkRuns.filter(cr => cr.status === 'completed').length;\n logger.info(`PR #${prNumber} checks: ${completedCount}/${checkRuns.length} completed. Waiting...`);\n\n await delay(10000); // wait 10 seconds\n }\n};\n\nexport const mergePullRequest = async (prNumber: number, mergeMethod: MergeMethod = 'squash'): Promise<void> => {\n const octokit = getOctokit();\n const { owner, repo } = await getRepoDetails();\n const logger = getLogger();\n\n logger.info(`Merging PR #${prNumber} using ${mergeMethod} method...`);\n const pr = await octokit.pulls.get({\n owner,\n repo,\n pull_number: prNumber,\n });\n const headBranch = pr.data.head.ref;\n\n await octokit.pulls.merge({\n owner,\n repo,\n pull_number: prNumber,\n merge_method: mergeMethod,\n });\n logger.info(`PR #${prNumber} merged using ${mergeMethod} method.`);\n\n logger.info(`Deleting branch ${headBranch}...`);\n await octokit.git.deleteRef({\n owner,\n repo,\n ref: `heads/${headBranch}`,\n });\n logger.info(`Branch ${headBranch} deleted.`);\n};\n\nexport const createRelease = async (tagName: string, title: string, notes: string): Promise<void> => {\n const octokit = getOctokit();\n const { owner, repo } = await getRepoDetails();\n const logger = getLogger();\n\n logger.info(`Creating release for tag ${tagName}...`);\n await octokit.repos.createRelease({\n owner,\n repo,\n tag_name: tagName,\n name: title,\n body: notes,\n });\n logger.info(`Release ${tagName} created.`);\n};\n\nexport const getOpenIssues = async (limit: number = 20): Promise<string> => {\n const octokit = getOctokit();\n const { owner, repo } = await getRepoDetails();\n const logger = getLogger();\n\n try {\n logger.debug(`Fetching up to ${limit} open GitHub issues...`);\n\n const response = await octokit.issues.listForRepo({\n owner,\n repo,\n state: 'open',\n per_page: Math.min(limit, 100), // GitHub API limit\n sort: 'updated',\n direction: 'desc',\n });\n\n const issues = response.data.filter(issue => !issue.pull_request); // Filter out PRs\n\n if (issues.length === 0) {\n logger.debug('No open issues found');\n return '';\n }\n\n const issueStrings = issues.slice(0, limit).map(issue => {\n const labels = issue.labels.map(label =>\n typeof label === 'string' ? label : label.name\n ).join(', ');\n\n return [\n `Issue #${issue.number}: ${issue.title}`,\n `Labels: ${labels || 'none'}`,\n `Created: ${issue.created_at}`,\n `Updated: ${issue.updated_at}`,\n `Body: ${issue.body?.substring(0, 500) || 'No description'}${issue.body && issue.body.length > 500 ? '...' : ''}`,\n '---'\n ].join('\\n');\n });\n\n logger.debug(`Fetched ${issues.length} open issues`);\n return issueStrings.join('\\n\\n');\n } catch (error: any) {\n logger.warn('Failed to fetch GitHub issues: %s', error.message);\n return '';\n }\n};\n\nexport const createIssue = async (\n title: string,\n body: string,\n labels?: string[]\n): Promise<{ number: number; html_url: string }> => {\n const octokit = getOctokit();\n const { owner, repo } = await getRepoDetails();\n\n const response = await octokit.issues.create({\n owner,\n repo,\n title,\n body,\n labels: labels || [],\n });\n\n return {\n number: response.data.number,\n html_url: response.data.html_url,\n };\n}; "],"names":["getOctokit","logger","getLogger","token","process","env","GITHUB_TOKEN","error","Error","Octokit","auth","getCurrentBranchName","stdout","run","trim","getRepoDetails","url","match","owner","repo","createPullRequest","title","body","head","base","octokit","response","pulls","create","data","findOpenPullRequestByHeadRef","debug","list","state","length","message","status","delay","ms","Promise","resolve","setTimeout","hasWorkflowsConfigured","actions","listRepoWorkflows","workflows","waitForPullRequestChecks","prNumber","options","timeout","skipUserConfirmation","startTime","Date","now","consecutiveNoChecksCount","maxConsecutiveNoChecks","elapsedTime","warn","proceedWithoutChecks","promptConfirmation","info","pr","get","pull_number","checkRunsResponse","checks","listForRef","ref","sha","checkRuns","check_runs","hasWorkflows","failingChecks","filter","cr","conclusion","includes","check","name","allChecksCompleted","every","completedCount","mergePullRequest","mergeMethod","headBranch","merge","merge_method","git","deleteRef","createRelease","tagName","notes","repos","tag_name","getOpenIssues","limit","issues","listForRepo","per_page","Math","min","sort","direction","issue","pull_request","issueStrings","slice","map","labels","label","join","number","created_at","updated_at","substring","createIssue","html_url"],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import { OpenAI } from 'openai';
2
2
  import { create } from './storage.js';
3
3
  import { getLogger } from '../logging.js';
4
+ import { archiveAudio } from './general.js';
4
5
 
5
6
  class OpenAIError extends Error {
6
7
  constructor(message){
@@ -124,6 +125,14 @@ async function transcribeAudio(filePath, options = {
124
125
  throw new OpenAIError('No transcription received from OpenAI');
125
126
  }
126
127
  logger.debug('Received transcription from OpenAI: %s', response);
128
+ // Archive the audio file and transcription
129
+ try {
130
+ const outputDir = options.outputDirectory || 'output';
131
+ await archiveAudio(filePath, response.text, outputDir);
132
+ } catch (archiveError) {
133
+ // Don't fail the transcription if archiving fails, just log the error
134
+ logger.warn('Failed to archive audio file: %s', archiveError.message);
135
+ }
127
136
  return response;
128
137
  } catch (error) {
129
138
  logger.error('Error transcribing audio file: %s %s', error.message, error.stack);
@@ -1 +1 @@
1
- {"version":3,"file":"openai.js","sources":["../../src/util/openai.ts"],"sourcesContent":["import { OpenAI } from 'openai';\nimport { ChatCompletionMessageParam } from 'openai/resources';\nimport * as Storage from './storage';\nimport { getLogger } from '../logging';\n// eslint-disable-next-line no-restricted-imports\nimport fs from 'fs';\n\nexport interface Transcription {\n text: string;\n}\n\nexport class OpenAIError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'OpenAIError';\n }\n}\n\nexport async function createCompletion(messages: ChatCompletionMessageParam[], options: { responseFormat?: any, model?: string, debug?: boolean, debugFile?: string, debugRequestFile?: string, debugResponseFile?: string } = { model: \"gpt-4o-mini\" }): Promise<string | any> {\n const logger = getLogger();\n const storage = Storage.create({ log: logger.debug });\n let openai: OpenAI | null = null;\n try {\n const apiKey = process.env.OPENAI_API_KEY;\n if (!apiKey) {\n throw new OpenAIError('OPENAI_API_KEY environment variable is not set');\n }\n\n // Create the client which we'll close in the finally block.\n openai = new OpenAI({\n apiKey: apiKey,\n timeout: 180000, // 180 seconds timeout\n });\n\n logger.debug('Sending prompt to OpenAI: %j', messages);\n\n // Save request debug file if enabled\n if (options.debug && (options.debugRequestFile || options.debugFile)) {\n const requestData = {\n model: options.model || \"gpt-4o-mini\",\n messages,\n max_completion_tokens: 10000,\n response_format: options.responseFormat,\n };\n const debugFile = options.debugRequestFile || options.debugFile;\n await storage.writeFile(debugFile!, JSON.stringify(requestData, null, 2), 'utf8');\n logger.debug('Wrote request debug file to %s', debugFile);\n }\n\n // Add timeout wrapper to the OpenAI API call\n const completionPromise = openai.chat.completions.create({\n model: options.model || \"gpt-4o-mini\",\n messages,\n max_completion_tokens: 10000,\n response_format: options.responseFormat,\n });\n\n const timeoutPromise = new Promise<never>((_, reject) => {\n setTimeout(() => reject(new OpenAIError('OpenAI API call timed out after 180 seconds')), 180000);\n });\n\n const completion = await Promise.race([completionPromise, timeoutPromise]);\n\n // Save response debug file if enabled\n if (options.debug && (options.debugResponseFile || options.debugFile)) {\n const debugFile = options.debugResponseFile || options.debugFile;\n await storage.writeFile(debugFile!, JSON.stringify(completion, null, 2), 'utf8');\n logger.debug('Wrote response debug file to %s', debugFile);\n }\n\n const response = completion.choices[0]?.message?.content?.trim();\n if (!response) {\n throw new OpenAIError('No response received from OpenAI');\n }\n\n logger.debug('Received response from OpenAI: %s...', response.substring(0, 30));\n if (options.responseFormat) {\n return JSON.parse(response);\n } else {\n return response;\n }\n\n } catch (error: any) {\n logger.error('Error calling OpenAI API: %s %s', error.message, error.stack);\n throw new OpenAIError(`Failed to create completion: ${error.message}`);\n } finally {\n // OpenAI client cleanup is handled automatically by the library\n // No manual cleanup needed for newer versions\n }\n}\n\nexport async function transcribeAudio(filePath: string, options: { model?: string, debug?: boolean, debugFile?: string, debugRequestFile?: string, debugResponseFile?: string } = { model: \"whisper-1\" }): Promise<Transcription> {\n const logger = getLogger();\n const storage = Storage.create({ log: logger.debug });\n let openai: OpenAI | null = null;\n let audioStream: fs.ReadStream | null = null;\n try {\n const apiKey = process.env.OPENAI_API_KEY;\n if (!apiKey) {\n throw new OpenAIError('OPENAI_API_KEY environment variable is not set');\n }\n\n openai = new OpenAI({\n apiKey: apiKey,\n });\n\n logger.debug('Transcribing audio file: %s', filePath);\n\n // Save request debug file if enabled\n if (options.debug && (options.debugRequestFile || options.debugFile)) {\n const requestData = {\n model: options.model || \"whisper-1\",\n file: filePath, // Can't serialize the stream, so just save the file path\n response_format: \"json\",\n };\n const debugFile = options.debugRequestFile || options.debugFile;\n await storage.writeFile(debugFile!, JSON.stringify(requestData, null, 2), 'utf8');\n logger.debug('Wrote request debug file to %s', debugFile);\n }\n\n audioStream = await storage.readStream(filePath);\n const transcription = await openai.audio.transcriptions.create({\n model: options.model || \"whisper-1\",\n file: audioStream,\n response_format: \"json\",\n });\n\n // Save response debug file if enabled\n if (options.debug && (options.debugResponseFile || options.debugFile)) {\n const debugFile = options.debugResponseFile || options.debugFile;\n await storage.writeFile(debugFile!, JSON.stringify(transcription, null, 2), 'utf8');\n logger.debug('Wrote response debug file to %s', debugFile);\n }\n\n const response = transcription;\n if (!response) {\n throw new OpenAIError('No transcription received from OpenAI');\n }\n\n logger.debug('Received transcription from OpenAI: %s', response);\n return response;\n\n } catch (error: any) {\n logger.error('Error transcribing audio file: %s %s', error.message, error.stack);\n throw new OpenAIError(`Failed to transcribe audio: ${error.message}`);\n } finally {\n // Ensure the audio stream is properly closed to release file handles\n try {\n if (audioStream) {\n audioStream.close();\n }\n } catch (streamErr) {\n logger.debug('Failed to close audio read stream: %s', (streamErr as Error).message);\n }\n // OpenAI client cleanup is handled automatically by the library\n // No manual cleanup needed for newer versions\n }\n}\n"],"names":["OpenAIError","Error","message","name","createCompletion","messages","options","model","logger","getLogger","storage","Storage","log","debug","openai","completion","apiKey","process","env","OPENAI_API_KEY","OpenAI","timeout","debugRequestFile","debugFile","requestData","max_completion_tokens","response_format","responseFormat","writeFile","JSON","stringify","completionPromise","chat","completions","create","timeoutPromise","Promise","_","reject","setTimeout","race","debugResponseFile","response","choices","content","trim","substring","parse","error","stack","transcribeAudio","filePath","audioStream","file","readStream","transcription","audio","transcriptions","close","streamErr"],"mappings":";;;;AAWO,MAAMA,WAAAA,SAAoBC,KAAAA,CAAAA;AAC7B,IAAA,WAAA,CAAYC,OAAe,CAAE;AACzB,QAAA,KAAK,CAACA,OAAAA,CAAAA;QACN,IAAI,CAACC,IAAI,GAAG,aAAA;AAChB,IAAA;AACJ;AAEO,eAAeC,gBAAAA,CAAiBC,QAAsC,EAAEC,OAAAA,GAAgJ;IAAEC,KAAAA,EAAO;AAAc,CAAC,EAAA;AACnP,IAAA,MAAMC,MAAAA,GAASC,SAAAA,EAAAA;IACf,MAAMC,OAAAA,GAAUC,MAAc,CAAC;AAAEC,QAAAA,GAAAA,EAAKJ,OAAOK;AAAM,KAAA,CAAA;AACnD,IAAA,IAAIC,MAAAA,GAAwB,IAAA;IAC5B,IAAI;AAgDiBC,QAAAA,IAAAA,oCAAAA,EAAAA,4BAAAA,EAAAA,oBAAAA;AA/CjB,QAAA,MAAMC,MAAAA,GAASC,OAAAA,CAAQC,GAAG,CAACC,cAAc;AACzC,QAAA,IAAI,CAACH,MAAAA,EAAQ;AACT,YAAA,MAAM,IAAIhB,WAAAA,CAAY,gDAAA,CAAA;AAC1B,QAAA;;AAGAc,QAAAA,MAAAA,GAAS,IAAIM,MAAAA,CAAO;YAChBJ,MAAAA,EAAQA,MAAAA;YACRK,OAAAA,EAAS;AACb,SAAA,CAAA;QAEAb,MAAAA,CAAOK,KAAK,CAAC,8BAAA,EAAgCR,QAAAA,CAAAA;;QAG7C,IAAIC,OAAAA,CAAQO,KAAK,KAAKP,OAAAA,CAAQgB,gBAAgB,IAAIhB,OAAAA,CAAQiB,SAAQ,CAAA,EAAI;AAClE,YAAA,MAAMC,WAAAA,GAAc;gBAChBjB,KAAAA,EAAOD,OAAAA,CAAQC,KAAK,IAAI,aAAA;AACxBF,gBAAAA,QAAAA;gBACAoB,qBAAAA,EAAuB,KAAA;AACvBC,gBAAAA,eAAAA,EAAiBpB,QAAQqB;AAC7B,aAAA;AACA,YAAA,MAAMJ,SAAAA,GAAYjB,OAAAA,CAAQgB,gBAAgB,IAAIhB,QAAQiB,SAAS;YAC/D,MAAMb,OAAAA,CAAQkB,SAAS,CAACL,SAAAA,EAAYM,KAAKC,SAAS,CAACN,WAAAA,EAAa,IAAA,EAAM,CAAA,CAAA,EAAI,MAAA,CAAA;YAC1EhB,MAAAA,CAAOK,KAAK,CAAC,gCAAA,EAAkCU,SAAAA,CAAAA;AACnD,QAAA;;AAGA,QAAA,MAAMQ,oBAAoBjB,MAAAA,CAAOkB,IAAI,CAACC,WAAW,CAACC,MAAM,CAAC;YACrD3B,KAAAA,EAAOD,OAAAA,CAAQC,KAAK,IAAI,aAAA;AACxBF,YAAAA,QAAAA;YACAoB,qBAAAA,EAAuB,KAAA;AACvBC,YAAAA,eAAAA,EAAiBpB,QAAQqB;AAC7B,SAAA,CAAA;AAEA,QAAA,MAAMQ,cAAAA,GAAiB,IAAIC,OAAAA,CAAe,CAACC,CAAAA,EAAGC,MAAAA,GAAAA;AAC1CC,YAAAA,UAAAA,CAAW,IAAMD,MAAAA,CAAO,IAAItC,WAAAA,CAAY,6CAAA,CAAA,CAAA,EAAiD,MAAA,CAAA;AAC7F,QAAA,CAAA,CAAA;AAEA,QAAA,MAAMe,UAAAA,GAAa,MAAMqB,OAAAA,CAAQI,IAAI,CAAC;AAACT,YAAAA,iBAAAA;AAAmBI,YAAAA;AAAe,SAAA,CAAA;;QAGzE,IAAI7B,OAAAA,CAAQO,KAAK,KAAKP,OAAAA,CAAQmC,iBAAiB,IAAInC,OAAAA,CAAQiB,SAAQ,CAAA,EAAI;AACnE,YAAA,MAAMA,SAAAA,GAAYjB,OAAAA,CAAQmC,iBAAiB,IAAInC,QAAQiB,SAAS;YAChE,MAAMb,OAAAA,CAAQkB,SAAS,CAACL,SAAAA,EAAYM,KAAKC,SAAS,CAACf,UAAAA,EAAY,IAAA,EAAM,CAAA,CAAA,EAAI,MAAA,CAAA;YACzEP,MAAAA,CAAOK,KAAK,CAAC,iCAAA,EAAmCU,SAAAA,CAAAA;AACpD,QAAA;AAEA,QAAA,MAAMmB,YAAW3B,oBAAAA,GAAAA,UAAAA,CAAW4B,OAAO,CAAC,CAAA,CAAE,cAArB5B,oBAAAA,KAAAA,KAAAA,CAAAA,GAAAA,KAAAA,CAAAA,GAAAA,CAAAA,4BAAAA,GAAAA,qBAAuBb,OAAO,MAAA,IAAA,IAA9Ba,oDAAAA,oCAAAA,GAAAA,4BAAAA,CAAgC6B,OAAO,MAAA,IAAA,IAAvC7B,oCAAAA,KAAAA,KAAAA,CAAAA,GAAAA,KAAAA,CAAAA,GAAAA,qCAAyC8B,IAAI,EAAA;AAC9D,QAAA,IAAI,CAACH,QAAAA,EAAU;AACX,YAAA,MAAM,IAAI1C,WAAAA,CAAY,kCAAA,CAAA;AAC1B,QAAA;AAEAQ,QAAAA,MAAAA,CAAOK,KAAK,CAAC,sCAAA,EAAwC6B,QAAAA,CAASI,SAAS,CAAC,CAAA,EAAG,EAAA,CAAA,CAAA;QAC3E,IAAIxC,OAAAA,CAAQqB,cAAc,EAAE;YACxB,OAAOE,IAAAA,CAAKkB,KAAK,CAACL,QAAAA,CAAAA;QACtB,CAAA,MAAO;YACH,OAAOA,QAAAA;AACX,QAAA;AAEJ,IAAA,CAAA,CAAE,OAAOM,KAAAA,EAAY;AACjBxC,QAAAA,MAAAA,CAAOwC,KAAK,CAAC,iCAAA,EAAmCA,MAAM9C,OAAO,EAAE8C,MAAMC,KAAK,CAAA;AAC1E,QAAA,MAAM,IAAIjD,WAAAA,CAAY,CAAC,6BAA6B,EAAEgD,KAAAA,CAAM9C,OAAO,CAAA,CAAE,CAAA;IACzE,CAAA,QAAU;;;AAGV,IAAA;AACJ;AAEO,eAAegD,eAAAA,CAAgBC,QAAgB,EAAE7C,OAAAA,GAA0H;IAAEC,KAAAA,EAAO;AAAY,CAAC,EAAA;AACpM,IAAA,MAAMC,MAAAA,GAASC,SAAAA,EAAAA;IACf,MAAMC,OAAAA,GAAUC,MAAc,CAAC;AAAEC,QAAAA,GAAAA,EAAKJ,OAAOK;AAAM,KAAA,CAAA;AACnD,IAAA,IAAIC,MAAAA,GAAwB,IAAA;AAC5B,IAAA,IAAIsC,WAAAA,GAAoC,IAAA;IACxC,IAAI;AACA,QAAA,MAAMpC,MAAAA,GAASC,OAAAA,CAAQC,GAAG,CAACC,cAAc;AACzC,QAAA,IAAI,CAACH,MAAAA,EAAQ;AACT,YAAA,MAAM,IAAIhB,WAAAA,CAAY,gDAAA,CAAA;AAC1B,QAAA;AAEAc,QAAAA,MAAAA,GAAS,IAAIM,MAAAA,CAAO;YAChBJ,MAAAA,EAAQA;AACZ,SAAA,CAAA;QAEAR,MAAAA,CAAOK,KAAK,CAAC,6BAAA,EAA+BsC,QAAAA,CAAAA;;QAG5C,IAAI7C,OAAAA,CAAQO,KAAK,KAAKP,OAAAA,CAAQgB,gBAAgB,IAAIhB,OAAAA,CAAQiB,SAAQ,CAAA,EAAI;AAClE,YAAA,MAAMC,WAAAA,GAAc;gBAChBjB,KAAAA,EAAOD,OAAAA,CAAQC,KAAK,IAAI,WAAA;gBACxB8C,IAAAA,EAAMF,QAAAA;gBACNzB,eAAAA,EAAiB;AACrB,aAAA;AACA,YAAA,MAAMH,SAAAA,GAAYjB,OAAAA,CAAQgB,gBAAgB,IAAIhB,QAAQiB,SAAS;YAC/D,MAAMb,OAAAA,CAAQkB,SAAS,CAACL,SAAAA,EAAYM,KAAKC,SAAS,CAACN,WAAAA,EAAa,IAAA,EAAM,CAAA,CAAA,EAAI,MAAA,CAAA;YAC1EhB,MAAAA,CAAOK,KAAK,CAAC,gCAAA,EAAkCU,SAAAA,CAAAA;AACnD,QAAA;QAEA6B,WAAAA,GAAc,MAAM1C,OAAAA,CAAQ4C,UAAU,CAACH,QAAAA,CAAAA;QACvC,MAAMI,aAAAA,GAAgB,MAAMzC,MAAAA,CAAO0C,KAAK,CAACC,cAAc,CAACvB,MAAM,CAAC;YAC3D3B,KAAAA,EAAOD,OAAAA,CAAQC,KAAK,IAAI,WAAA;YACxB8C,IAAAA,EAAMD,WAAAA;YACN1B,eAAAA,EAAiB;AACrB,SAAA,CAAA;;QAGA,IAAIpB,OAAAA,CAAQO,KAAK,KAAKP,OAAAA,CAAQmC,iBAAiB,IAAInC,OAAAA,CAAQiB,SAAQ,CAAA,EAAI;AACnE,YAAA,MAAMA,SAAAA,GAAYjB,OAAAA,CAAQmC,iBAAiB,IAAInC,QAAQiB,SAAS;YAChE,MAAMb,OAAAA,CAAQkB,SAAS,CAACL,SAAAA,EAAYM,KAAKC,SAAS,CAACyB,aAAAA,EAAe,IAAA,EAAM,CAAA,CAAA,EAAI,MAAA,CAAA;YAC5E/C,MAAAA,CAAOK,KAAK,CAAC,iCAAA,EAAmCU,SAAAA,CAAAA;AACpD,QAAA;AAEA,QAAA,MAAMmB,QAAAA,GAAWa,aAAAA;AACjB,QAAA,IAAI,CAACb,QAAAA,EAAU;AACX,YAAA,MAAM,IAAI1C,WAAAA,CAAY,uCAAA,CAAA;AAC1B,QAAA;QAEAQ,MAAAA,CAAOK,KAAK,CAAC,wCAAA,EAA0C6B,QAAAA,CAAAA;QACvD,OAAOA,QAAAA;AAEX,IAAA,CAAA,CAAE,OAAOM,KAAAA,EAAY;AACjBxC,QAAAA,MAAAA,CAAOwC,KAAK,CAAC,sCAAA,EAAwCA,MAAM9C,OAAO,EAAE8C,MAAMC,KAAK,CAAA;AAC/E,QAAA,MAAM,IAAIjD,WAAAA,CAAY,CAAC,4BAA4B,EAAEgD,KAAAA,CAAM9C,OAAO,CAAA,CAAE,CAAA;IACxE,CAAA,QAAU;;QAEN,IAAI;AACA,YAAA,IAAIkD,WAAAA,EAAa;AACbA,gBAAAA,WAAAA,CAAYM,KAAK,EAAA;AACrB,YAAA;AACJ,QAAA,CAAA,CAAE,OAAOC,SAAAA,EAAW;AAChBnD,YAAAA,MAAAA,CAAOK,KAAK,CAAC,uCAAA,EAA0C8C,UAAoBzD,OAAO,CAAA;AACtF,QAAA;;;AAGJ,IAAA;AACJ;;;;"}
1
+ {"version":3,"file":"openai.js","sources":["../../src/util/openai.ts"],"sourcesContent":["import { OpenAI } from 'openai';\nimport { ChatCompletionMessageParam } from 'openai/resources';\nimport * as Storage from './storage';\nimport { getLogger } from '../logging';\nimport { archiveAudio } from './general';\n// eslint-disable-next-line no-restricted-imports\nimport fs from 'fs';\n\nexport interface Transcription {\n text: string;\n}\n\nexport class OpenAIError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'OpenAIError';\n }\n}\n\nexport async function createCompletion(messages: ChatCompletionMessageParam[], options: { responseFormat?: any, model?: string, debug?: boolean, debugFile?: string, debugRequestFile?: string, debugResponseFile?: string } = { model: \"gpt-4o-mini\" }): Promise<string | any> {\n const logger = getLogger();\n const storage = Storage.create({ log: logger.debug });\n let openai: OpenAI | null = null;\n try {\n const apiKey = process.env.OPENAI_API_KEY;\n if (!apiKey) {\n throw new OpenAIError('OPENAI_API_KEY environment variable is not set');\n }\n\n // Create the client which we'll close in the finally block.\n openai = new OpenAI({\n apiKey: apiKey,\n timeout: 180000, // 180 seconds timeout\n });\n\n logger.debug('Sending prompt to OpenAI: %j', messages);\n\n // Save request debug file if enabled\n if (options.debug && (options.debugRequestFile || options.debugFile)) {\n const requestData = {\n model: options.model || \"gpt-4o-mini\",\n messages,\n max_completion_tokens: 10000,\n response_format: options.responseFormat,\n };\n const debugFile = options.debugRequestFile || options.debugFile;\n await storage.writeFile(debugFile!, JSON.stringify(requestData, null, 2), 'utf8');\n logger.debug('Wrote request debug file to %s', debugFile);\n }\n\n // Add timeout wrapper to the OpenAI API call\n const completionPromise = openai.chat.completions.create({\n model: options.model || \"gpt-4o-mini\",\n messages,\n max_completion_tokens: 10000,\n response_format: options.responseFormat,\n });\n\n const timeoutPromise = new Promise<never>((_, reject) => {\n setTimeout(() => reject(new OpenAIError('OpenAI API call timed out after 180 seconds')), 180000);\n });\n\n const completion = await Promise.race([completionPromise, timeoutPromise]);\n\n // Save response debug file if enabled\n if (options.debug && (options.debugResponseFile || options.debugFile)) {\n const debugFile = options.debugResponseFile || options.debugFile;\n await storage.writeFile(debugFile!, JSON.stringify(completion, null, 2), 'utf8');\n logger.debug('Wrote response debug file to %s', debugFile);\n }\n\n const response = completion.choices[0]?.message?.content?.trim();\n if (!response) {\n throw new OpenAIError('No response received from OpenAI');\n }\n\n logger.debug('Received response from OpenAI: %s...', response.substring(0, 30));\n if (options.responseFormat) {\n return JSON.parse(response);\n } else {\n return response;\n }\n\n } catch (error: any) {\n logger.error('Error calling OpenAI API: %s %s', error.message, error.stack);\n throw new OpenAIError(`Failed to create completion: ${error.message}`);\n } finally {\n // OpenAI client cleanup is handled automatically by the library\n // No manual cleanup needed for newer versions\n }\n}\n\nexport async function transcribeAudio(filePath: string, options: { model?: string, debug?: boolean, debugFile?: string, debugRequestFile?: string, debugResponseFile?: string, outputDirectory?: string } = { model: \"whisper-1\" }): Promise<Transcription> {\n const logger = getLogger();\n const storage = Storage.create({ log: logger.debug });\n let openai: OpenAI | null = null;\n let audioStream: fs.ReadStream | null = null;\n try {\n const apiKey = process.env.OPENAI_API_KEY;\n if (!apiKey) {\n throw new OpenAIError('OPENAI_API_KEY environment variable is not set');\n }\n\n openai = new OpenAI({\n apiKey: apiKey,\n });\n\n logger.debug('Transcribing audio file: %s', filePath);\n\n // Save request debug file if enabled\n if (options.debug && (options.debugRequestFile || options.debugFile)) {\n const requestData = {\n model: options.model || \"whisper-1\",\n file: filePath, // Can't serialize the stream, so just save the file path\n response_format: \"json\",\n };\n const debugFile = options.debugRequestFile || options.debugFile;\n await storage.writeFile(debugFile!, JSON.stringify(requestData, null, 2), 'utf8');\n logger.debug('Wrote request debug file to %s', debugFile);\n }\n\n audioStream = await storage.readStream(filePath);\n const transcription = await openai.audio.transcriptions.create({\n model: options.model || \"whisper-1\",\n file: audioStream,\n response_format: \"json\",\n });\n\n // Save response debug file if enabled\n if (options.debug && (options.debugResponseFile || options.debugFile)) {\n const debugFile = options.debugResponseFile || options.debugFile;\n await storage.writeFile(debugFile!, JSON.stringify(transcription, null, 2), 'utf8');\n logger.debug('Wrote response debug file to %s', debugFile);\n }\n\n const response = transcription;\n if (!response) {\n throw new OpenAIError('No transcription received from OpenAI');\n }\n\n logger.debug('Received transcription from OpenAI: %s', response);\n\n // Archive the audio file and transcription\n try {\n const outputDir = options.outputDirectory || 'output';\n await archiveAudio(filePath, response.text, outputDir);\n } catch (archiveError: any) {\n // Don't fail the transcription if archiving fails, just log the error\n logger.warn('Failed to archive audio file: %s', archiveError.message);\n }\n\n return response;\n\n } catch (error: any) {\n logger.error('Error transcribing audio file: %s %s', error.message, error.stack);\n throw new OpenAIError(`Failed to transcribe audio: ${error.message}`);\n } finally {\n // Ensure the audio stream is properly closed to release file handles\n try {\n if (audioStream) {\n audioStream.close();\n }\n } catch (streamErr) {\n logger.debug('Failed to close audio read stream: %s', (streamErr as Error).message);\n }\n // OpenAI client cleanup is handled automatically by the library\n // No manual cleanup needed for newer versions\n }\n}\n"],"names":["OpenAIError","Error","message","name","createCompletion","messages","options","model","logger","getLogger","storage","Storage","log","debug","openai","completion","apiKey","process","env","OPENAI_API_KEY","OpenAI","timeout","debugRequestFile","debugFile","requestData","max_completion_tokens","response_format","responseFormat","writeFile","JSON","stringify","completionPromise","chat","completions","create","timeoutPromise","Promise","_","reject","setTimeout","race","debugResponseFile","response","choices","content","trim","substring","parse","error","stack","transcribeAudio","filePath","audioStream","file","readStream","transcription","audio","transcriptions","outputDir","outputDirectory","archiveAudio","text","archiveError","warn","close","streamErr"],"mappings":"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"}
@@ -96,6 +96,38 @@ async function readStdin() {
96
96
  process.stdin.resume();
97
97
  });
98
98
  }
99
+ // Function to prompt user for confirmation (y/n)
100
+ async function promptConfirmation(message) {
101
+ // In test environment, return true by default
102
+ if (process.env.NODE_ENV === 'test' || process.env.VITEST === 'true') {
103
+ return true;
104
+ }
105
+ // Use process.stdout.write instead of console.log to avoid linter issues
106
+ process.stdout.write(message + '\n');
107
+ process.stdout.write('Please enter "y" for yes or "n" for no: ');
108
+ return new Promise((resolve)=>{
109
+ const handleInput = (chunk)=>{
110
+ const input = chunk.toString().trim().toLowerCase();
111
+ if (input === 'y' || input === 'yes') {
112
+ cleanup();
113
+ resolve(true);
114
+ } else if (input === 'n' || input === 'no') {
115
+ cleanup();
116
+ resolve(false);
117
+ } else {
118
+ process.stdout.write('Please enter "y" for yes or "n" for no: ');
119
+ // Continue listening for input
120
+ }
121
+ };
122
+ const cleanup = ()=>{
123
+ process.stdin.removeListener('data', handleInput);
124
+ process.stdin.pause();
125
+ };
126
+ process.stdin.setEncoding('utf8');
127
+ process.stdin.on('data', handleInput);
128
+ process.stdin.resume();
129
+ });
130
+ }
99
131
 
100
- export { readStdin };
132
+ export { promptConfirmation, readStdin };
101
133
  //# sourceMappingURL=stdin.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"stdin.js","sources":["../../src/util/stdin.ts"],"sourcesContent":["// Function to read from STDIN if available\nexport async function readStdin(): Promise<string | null> {\n // In test environment, allow mocking to work by skipping TTY check\n if (process.env.NODE_ENV === 'test' || process.env.VITEST === 'true') {\n return new Promise((resolve) => {\n let input = '';\n let hasData = false;\n let resolved = false;\n\n const timeout = setTimeout(() => {\n if (!hasData && !resolved) {\n resolved = true;\n cleanup();\n resolve(null);\n }\n }, 10); // Very short timeout for tests\n\n const onData = (chunk: string) => {\n hasData = true;\n clearTimeout(timeout);\n input += chunk;\n };\n\n const onEnd = () => {\n if (!resolved) {\n resolved = true;\n cleanup();\n resolve(input.trim() || null);\n }\n };\n\n const onError = () => {\n if (!resolved) {\n resolved = true;\n clearTimeout(timeout);\n cleanup();\n resolve(null);\n }\n };\n\n const cleanup = () => {\n process.stdin.removeListener('data', onData);\n process.stdin.removeListener('end', onEnd);\n process.stdin.removeListener('error', onError);\n process.stdin.pause();\n };\n\n process.stdin.setEncoding('utf8');\n process.stdin.on('data', onData);\n process.stdin.on('end', onEnd);\n process.stdin.on('error', onError);\n process.stdin.resume();\n });\n }\n\n return new Promise((resolve) => {\n // Check if stdin is TTY (interactive terminal)\n if (process.stdin.isTTY) {\n resolve(null);\n return;\n }\n\n let input = '';\n let hasData = false;\n let resolved = false;\n\n const timeout = setTimeout(() => {\n if (!hasData && !resolved) {\n resolved = true;\n cleanup();\n resolve(null);\n }\n }, 100); // Short timeout to detect if data is available\n\n const onData = (chunk: string) => {\n hasData = true;\n clearTimeout(timeout);\n input += chunk;\n };\n\n const onEnd = () => {\n if (!resolved) {\n resolved = true;\n cleanup();\n resolve(input.trim() || null);\n }\n };\n\n const onError = () => {\n if (!resolved) {\n resolved = true;\n clearTimeout(timeout);\n cleanup();\n resolve(null);\n }\n };\n\n const cleanup = () => {\n process.stdin.removeListener('data', onData);\n process.stdin.removeListener('end', onEnd);\n process.stdin.removeListener('error', onError);\n process.stdin.pause();\n };\n\n process.stdin.setEncoding('utf8');\n process.stdin.on('data', onData);\n process.stdin.on('end', onEnd);\n process.stdin.on('error', onError);\n\n // If no data comes in quickly, assume no stdin\n process.stdin.resume();\n });\n} "],"names":["readStdin","process","env","NODE_ENV","VITEST","Promise","resolve","input","hasData","resolved","timeout","setTimeout","cleanup","onData","chunk","clearTimeout","onEnd","trim","onError","stdin","removeListener","pause","setEncoding","on","resume","isTTY"],"mappings":"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"}
1
+ {"version":3,"file":"stdin.js","sources":["../../src/util/stdin.ts"],"sourcesContent":["\n// Function to read from STDIN if available\nexport async function readStdin(): Promise<string | null> {\n // In test environment, allow mocking to work by skipping TTY check\n if (process.env.NODE_ENV === 'test' || process.env.VITEST === 'true') {\n return new Promise((resolve) => {\n let input = '';\n let hasData = false;\n let resolved = false;\n\n const timeout = setTimeout(() => {\n if (!hasData && !resolved) {\n resolved = true;\n cleanup();\n resolve(null);\n }\n }, 10); // Very short timeout for tests\n\n const onData = (chunk: string) => {\n hasData = true;\n clearTimeout(timeout);\n input += chunk;\n };\n\n const onEnd = () => {\n if (!resolved) {\n resolved = true;\n cleanup();\n resolve(input.trim() || null);\n }\n };\n\n const onError = () => {\n if (!resolved) {\n resolved = true;\n clearTimeout(timeout);\n cleanup();\n resolve(null);\n }\n };\n\n const cleanup = () => {\n process.stdin.removeListener('data', onData);\n process.stdin.removeListener('end', onEnd);\n process.stdin.removeListener('error', onError);\n process.stdin.pause();\n };\n\n process.stdin.setEncoding('utf8');\n process.stdin.on('data', onData);\n process.stdin.on('end', onEnd);\n process.stdin.on('error', onError);\n process.stdin.resume();\n });\n }\n\n return new Promise((resolve) => {\n // Check if stdin is TTY (interactive terminal)\n if (process.stdin.isTTY) {\n resolve(null);\n return;\n }\n\n let input = '';\n let hasData = false;\n let resolved = false;\n\n const timeout = setTimeout(() => {\n if (!hasData && !resolved) {\n resolved = true;\n cleanup();\n resolve(null);\n }\n }, 100); // Short timeout to detect if data is available\n\n const onData = (chunk: string) => {\n hasData = true;\n clearTimeout(timeout);\n input += chunk;\n };\n\n const onEnd = () => {\n if (!resolved) {\n resolved = true;\n cleanup();\n resolve(input.trim() || null);\n }\n };\n\n const onError = () => {\n if (!resolved) {\n resolved = true;\n clearTimeout(timeout);\n cleanup();\n resolve(null);\n }\n };\n\n const cleanup = () => {\n process.stdin.removeListener('data', onData);\n process.stdin.removeListener('end', onEnd);\n process.stdin.removeListener('error', onError);\n process.stdin.pause();\n };\n\n process.stdin.setEncoding('utf8');\n process.stdin.on('data', onData);\n process.stdin.on('end', onEnd);\n process.stdin.on('error', onError);\n\n // If no data comes in quickly, assume no stdin\n process.stdin.resume();\n });\n}\n\n// Function to prompt user for confirmation (y/n)\nexport async function promptConfirmation(message: string): Promise<boolean> {\n // In test environment, return true by default\n if (process.env.NODE_ENV === 'test' || process.env.VITEST === 'true') {\n return true;\n }\n\n // Use process.stdout.write instead of console.log to avoid linter issues\n process.stdout.write(message + '\\n');\n process.stdout.write('Please enter \"y\" for yes or \"n\" for no: ');\n\n return new Promise((resolve) => {\n const handleInput = (chunk: string) => {\n const input = chunk.toString().trim().toLowerCase();\n\n if (input === 'y' || input === 'yes') {\n cleanup();\n resolve(true);\n } else if (input === 'n' || input === 'no') {\n cleanup();\n resolve(false);\n } else {\n process.stdout.write('Please enter \"y\" for yes or \"n\" for no: ');\n // Continue listening for input\n }\n };\n\n const cleanup = () => {\n process.stdin.removeListener('data', handleInput);\n process.stdin.pause();\n };\n\n process.stdin.setEncoding('utf8');\n process.stdin.on('data', handleInput);\n process.stdin.resume();\n });\n} "],"names":["readStdin","process","env","NODE_ENV","VITEST","Promise","resolve","input","hasData","resolved","timeout","setTimeout","cleanup","onData","chunk","clearTimeout","onEnd","trim","onError","stdin","removeListener","pause","setEncoding","on","resume","isTTY","promptConfirmation","message","stdout","write","handleInput","toString","toLowerCase"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eldrforge/kodrdriv",
3
- "version": "0.0.24",
3
+ "version": "0.0.26",
4
4
  "description": "Create Intelligent Release Notes or Change Logs from Git",
5
5
  "main": "dist/main.js",
6
6
  "type": "module",
@@ -23,7 +23,7 @@
23
23
  "dependencies": {
24
24
  "@octokit/rest": "^22.0.0",
25
25
  "@riotprompt/riotprompt": "^0.0.7",
26
- "@theunwalked/cardigantime": "^0.0.14",
26
+ "@theunwalked/cardigantime": "^0.0.15",
27
27
  "@theunwalked/unplayable": "^0.0.20",
28
28
  "audify": "^1.9.0",
29
29
  "commander": "^14.0.0",