@eldrforge/kodrdriv 0.0.15 → 0.0.18

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 (82) hide show
  1. package/README.md +1 -9
  2. package/dist/arguments.js +38 -63
  3. package/dist/arguments.js.map +1 -1
  4. package/dist/audio/devices.js +284 -0
  5. package/dist/audio/devices.js.map +1 -0
  6. package/dist/audio/index.js +31 -0
  7. package/dist/audio/index.js.map +1 -0
  8. package/dist/audio/processor.js +766 -0
  9. package/dist/audio/processor.js.map +1 -0
  10. package/dist/audio/types.js +16 -0
  11. package/dist/audio/types.js.map +1 -0
  12. package/dist/audio/validation.js +35 -0
  13. package/dist/audio/validation.js.map +1 -0
  14. package/dist/commands/audio-commit.js +59 -634
  15. package/dist/commands/audio-commit.js.map +1 -1
  16. package/dist/commands/audio-review.js +68 -632
  17. package/dist/commands/audio-review.js.map +1 -1
  18. package/dist/commands/commit.js +23 -15
  19. package/dist/commands/commit.js.map +1 -1
  20. package/dist/commands/release.js +20 -12
  21. package/dist/commands/release.js.map +1 -1
  22. package/dist/commands/review.js +64 -13
  23. package/dist/commands/review.js.map +1 -1
  24. package/dist/commands/select-audio.js +265 -0
  25. package/dist/commands/select-audio.js.map +1 -0
  26. package/dist/constants.js +17 -9
  27. package/dist/constants.js.map +1 -1
  28. package/dist/content/issues.js +16 -0
  29. package/dist/content/issues.js.map +1 -1
  30. package/dist/main.js +9 -3
  31. package/dist/main.js.map +1 -1
  32. package/dist/prompt/commit.js +64 -0
  33. package/dist/prompt/commit.js.map +1 -0
  34. package/dist/prompt/personas/you.md +49 -5
  35. package/dist/prompt/release.js +52 -0
  36. package/dist/prompt/release.js.map +1 -0
  37. package/dist/prompt/review.js +64 -0
  38. package/dist/prompt/review.js.map +1 -0
  39. package/dist/types.js +5 -3
  40. package/dist/types.js.map +1 -1
  41. package/dist/util/openai.js +34 -3
  42. package/dist/util/openai.js.map +1 -1
  43. package/package.json +2 -2
  44. package/.kodrdriv/config.yaml +0 -20
  45. package/.kodrdriv/context/content.md +0 -7
  46. package/RELEASE_NOTES.md +0 -14
  47. package/dist/prompt/personas/committer.md +0 -29
  48. package/dist/prompt/personas/reviewer.md +0 -29
  49. package/dist/prompt/prompts.js +0 -160
  50. package/dist/prompt/prompts.js.map +0 -1
  51. package/docs/index.html +0 -17
  52. package/docs/package.json +0 -36
  53. package/docs/pnpm-lock.yaml +0 -3441
  54. package/docs/public/README.md +0 -132
  55. package/docs/public/advanced-usage.md +0 -188
  56. package/docs/public/code-icon.svg +0 -4
  57. package/docs/public/commands.md +0 -136
  58. package/docs/public/configuration.md +0 -274
  59. package/docs/public/examples.md +0 -352
  60. package/docs/public/kodrdriv-logo.svg +0 -62
  61. package/docs/src/App.css +0 -387
  62. package/docs/src/App.tsx +0 -60
  63. package/docs/src/components/DocumentPage.tsx +0 -56
  64. package/docs/src/components/ErrorMessage.tsx +0 -15
  65. package/docs/src/components/LoadingSpinner.tsx +0 -14
  66. package/docs/src/components/MarkdownRenderer.tsx +0 -56
  67. package/docs/src/components/Navigation.css +0 -73
  68. package/docs/src/components/Navigation.tsx +0 -36
  69. package/docs/src/index.css +0 -61
  70. package/docs/src/main.tsx +0 -10
  71. package/docs/src/test/setup.ts +0 -1
  72. package/docs/src/vite-env.d.ts +0 -10
  73. package/docs/tsconfig.node.json +0 -13
  74. package/docs/vite.config.ts +0 -15
  75. package/docs/vitest.config.ts +0 -15
  76. package/eslint.config.mjs +0 -83
  77. package/nodemon.json +0 -14
  78. package/output/kodrdriv/250702-0552-release-notes.md +0 -3
  79. package/pnpm-workspace.yaml +0 -5
  80. package/tsconfig.tsbuildinfo +0 -1
  81. package/vite.config.ts +0 -90
  82. package/vitest.config.ts +0 -24
@@ -0,0 +1,52 @@
1
+ import { Builder } from '@riotprompt/riotprompt';
2
+ import path from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ import { DEFAULT_PERSONA_RELEASER_FILE, DEFAULT_INSTRUCTIONS_RELEASE_FILE } from '../constants.js';
5
+ import { getLogger } from '../logging.js';
6
+
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = path.dirname(__filename);
9
+ /**
10
+ * Build a release prompt using RiotPrompt Builder.
11
+ */ const createPrompt = async ({ overridePath, overrides }, { logContent, diffContent }, { releaseFocus, context, directories } = {})=>{
12
+ const logger = getLogger();
13
+ let builder = Builder.create({
14
+ logger,
15
+ basePath: __dirname,
16
+ overridePath,
17
+ overrides: overrides || false
18
+ });
19
+ // Persona & instructions specific to releases
20
+ builder = await builder.addPersonaPath(DEFAULT_PERSONA_RELEASER_FILE);
21
+ builder = await builder.addInstructionPath(DEFAULT_INSTRUCTIONS_RELEASE_FILE);
22
+ if (releaseFocus) {
23
+ builder = await builder.addContent(releaseFocus, {
24
+ title: 'Release Focus',
25
+ weight: 1.0
26
+ });
27
+ }
28
+ builder = await builder.addContent(logContent, {
29
+ title: 'Log',
30
+ weight: 0.5
31
+ });
32
+ builder = await builder.addContent(diffContent, {
33
+ title: 'Diff',
34
+ weight: 0.5
35
+ });
36
+ // Load additional context directories configured by the user
37
+ if (directories === null || directories === void 0 ? void 0 : directories.length) {
38
+ builder = await builder.loadContext(directories, {
39
+ weight: 0.5
40
+ });
41
+ }
42
+ if (context) {
43
+ builder = await builder.addContext(context, {
44
+ title: 'User Context',
45
+ weight: 1.0
46
+ });
47
+ }
48
+ return await builder.build();
49
+ };
50
+
51
+ export { createPrompt };
52
+ //# sourceMappingURL=release.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"release.js","sources":["../../src/prompt/release.ts"],"sourcesContent":["import { Builder, Prompt } from '@riotprompt/riotprompt';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport { DEFAULT_INSTRUCTIONS_RELEASE_FILE, DEFAULT_PERSONA_RELEASER_FILE } from '../constants';\nimport { getLogger } from '../logging';\nimport { Config as RunConfig } from '../types';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n// Types for the release prompt\nexport type Config = {\n overridePath?: string;\n overrides?: boolean;\n}\n\nexport type Content = {\n logContent: string;\n diffContent: string;\n};\n\nexport type Context = {\n releaseFocus?: string;\n context?: string;\n directories?: string[];\n};\n\n/**\n * Build a release prompt using RiotPrompt Builder.\n */\nexport const createPrompt = async (\n { overridePath, overrides }: Config,\n { logContent, diffContent }: Content,\n { releaseFocus, context, directories }: Context = {}\n): Promise<Prompt> => {\n const logger = getLogger();\n\n let builder: Builder.Instance = Builder.create({\n logger,\n basePath: __dirname,\n overridePath,\n overrides: overrides || false,\n });\n\n // Persona & instructions specific to releases\n builder = await builder.addPersonaPath(DEFAULT_PERSONA_RELEASER_FILE);\n builder = await builder.addInstructionPath(DEFAULT_INSTRUCTIONS_RELEASE_FILE);\n\n if (releaseFocus) {\n builder = await builder.addContent(releaseFocus, { title: 'Release Focus', weight: 1.0 });\n }\n\n builder = await builder.addContent(logContent, { title: 'Log', weight: 0.5 });\n builder = await builder.addContent(diffContent, { title: 'Diff', weight: 0.5 });\n\n // Load additional context directories configured by the user\n if (directories?.length) {\n builder = await builder.loadContext(directories, { weight: 0.5 });\n }\n\n if (context) {\n builder = await builder.addContext(context, { title: 'User Context', weight: 1.0 });\n }\n\n return await builder.build();\n}; "],"names":["__filename","fileURLToPath","url","__dirname","path","dirname","createPrompt","overridePath","overrides","logContent","diffContent","releaseFocus","context","directories","logger","getLogger","builder","Builder","create","basePath","addPersonaPath","DEFAULT_PERSONA_RELEASER_FILE","addInstructionPath","DEFAULT_INSTRUCTIONS_RELEASE_FILE","addContent","title","weight","length","loadContext","addContext","build"],"mappings":";;;;;;AAOA,MAAMA,UAAAA,GAAaC,aAAAA,CAAc,MAAA,CAAA,IAAA,CAAYC,GAAG,CAAA;AAChD,MAAMC,SAAAA,GAAYC,IAAAA,CAAKC,OAAO,CAACL,UAAAA,CAAAA;AAmB/B;;IAGO,MAAMM,YAAAA,GAAe,OACxB,EAAEC,YAAY,EAAEC,SAAS,EAAU,EACnC,EAAEC,UAAU,EAAEC,WAAW,EAAW,EACpC,EAAEC,YAAY,EAAEC,OAAO,EAAEC,WAAW,EAAW,GAAG,EAAE,GAAA;AAEpD,IAAA,MAAMC,MAAAA,GAASC,SAAAA,EAAAA;IAEf,IAAIC,OAAAA,GAA4BC,OAAAA,CAAQC,MAAM,CAAC;AAC3CJ,QAAAA,MAAAA;QACAK,QAAAA,EAAUhB,SAAAA;AACVI,QAAAA,YAAAA;AACAC,QAAAA,SAAAA,EAAWA,SAAAA,IAAa;AAC5B,KAAA,CAAA;;IAGAQ,OAAAA,GAAU,MAAMA,OAAAA,CAAQI,cAAc,CAACC,6BAAAA,CAAAA;IACvCL,OAAAA,GAAU,MAAMA,OAAAA,CAAQM,kBAAkB,CAACC,iCAAAA,CAAAA;AAE3C,IAAA,IAAIZ,YAAAA,EAAc;AACdK,QAAAA,OAAAA,GAAU,MAAMA,OAAAA,CAAQQ,UAAU,CAACb,YAAAA,EAAc;YAAEc,KAAAA,EAAO,eAAA;YAAiBC,MAAAA,EAAQ;AAAI,SAAA,CAAA;AAC3F;AAEAV,IAAAA,OAAAA,GAAU,MAAMA,OAAAA,CAAQQ,UAAU,CAACf,UAAAA,EAAY;QAAEgB,KAAAA,EAAO,KAAA;QAAOC,MAAAA,EAAQ;AAAI,KAAA,CAAA;AAC3EV,IAAAA,OAAAA,GAAU,MAAMA,OAAAA,CAAQQ,UAAU,CAACd,WAAAA,EAAa;QAAEe,KAAAA,EAAO,MAAA;QAAQC,MAAAA,EAAQ;AAAI,KAAA,CAAA;;AAG7E,IAAA,IAAIb,WAAAA,KAAAA,IAAAA,IAAAA,WAAAA,KAAAA,MAAAA,GAAAA,MAAAA,GAAAA,WAAAA,CAAac,MAAM,EAAE;AACrBX,QAAAA,OAAAA,GAAU,MAAMA,OAAAA,CAAQY,WAAW,CAACf,WAAAA,EAAa;YAAEa,MAAAA,EAAQ;AAAI,SAAA,CAAA;AACnE;AAEA,IAAA,IAAId,OAAAA,EAAS;AACTI,QAAAA,OAAAA,GAAU,MAAMA,OAAAA,CAAQa,UAAU,CAACjB,OAAAA,EAAS;YAAEa,KAAAA,EAAO,cAAA;YAAgBC,MAAAA,EAAQ;AAAI,SAAA,CAAA;AACrF;IAEA,OAAO,MAAMV,QAAQc,KAAK,EAAA;AAC9B;;;;"}
@@ -0,0 +1,64 @@
1
+ import { Builder } from '@riotprompt/riotprompt';
2
+ import path from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ import { DEFAULT_PERSONA_YOU_FILE, DEFAULT_INSTRUCTIONS_REVIEW_FILE } from '../constants.js';
5
+ import { getLogger } from '../logging.js';
6
+
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = path.dirname(__filename);
9
+ const createPrompt = async ({ overridePath, overrides }, { notes }, { logContext, diffContext, releaseNotesContext, issuesContext, context, directories } = {})=>{
10
+ const logger = getLogger();
11
+ let builder = Builder.create({
12
+ logger,
13
+ basePath: __dirname,
14
+ overridePath,
15
+ overrides: overrides || false
16
+ });
17
+ builder = await builder.addPersonaPath(DEFAULT_PERSONA_YOU_FILE);
18
+ builder = await builder.addInstructionPath(DEFAULT_INSTRUCTIONS_REVIEW_FILE);
19
+ // Primary review notes supplied by the user
20
+ builder = await builder.addContent(notes, {
21
+ title: 'Review Notes',
22
+ weight: 1.0
23
+ });
24
+ // Additional context directories
25
+ if (directories === null || directories === void 0 ? void 0 : directories.length) {
26
+ builder = await builder.loadContext(directories, {
27
+ weight: 0.5
28
+ });
29
+ }
30
+ if (logContext) {
31
+ builder = await builder.addContext(logContext, {
32
+ title: 'Log Context',
33
+ weight: 0.5
34
+ });
35
+ }
36
+ if (diffContext) {
37
+ builder = await builder.addContext(diffContext, {
38
+ title: 'Diff Context',
39
+ weight: 0.5
40
+ });
41
+ }
42
+ if (releaseNotesContext) {
43
+ builder = await builder.addContext(releaseNotesContext, {
44
+ title: 'Release Notes Context',
45
+ weight: 0.5
46
+ });
47
+ }
48
+ if (issuesContext) {
49
+ builder = await builder.addContext(issuesContext, {
50
+ title: 'Issues Context',
51
+ weight: 0.5
52
+ });
53
+ }
54
+ if (context) {
55
+ builder = await builder.addContext(context, {
56
+ title: 'User Context',
57
+ weight: 1.0
58
+ });
59
+ }
60
+ return await builder.build();
61
+ };
62
+
63
+ export { createPrompt };
64
+ //# sourceMappingURL=review.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review.js","sources":["../../src/prompt/review.ts"],"sourcesContent":["import { Builder, Prompt } from '@riotprompt/riotprompt';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport { DEFAULT_INSTRUCTIONS_REVIEW_FILE, DEFAULT_PERSONA_YOU_FILE } from '../constants';\nimport { getLogger } from '../logging';\nimport { Config as RunConfig } from '../types';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nexport type Config = {\n overridePath?: string;\n overrides?: boolean;\n}\n\nexport type Content = {\n notes: string;\n};\n\nexport type Context = {\n logContext?: string;\n diffContext?: string;\n releaseNotesContext?: string;\n issuesContext?: string;\n context?: string;\n directories?: string[];\n};\n\nexport const createPrompt = async (\n { overridePath, overrides }: Config,\n { notes }: Content,\n { logContext, diffContext, releaseNotesContext, issuesContext, context, directories }: Context = {}\n): Promise<Prompt> => {\n const logger = getLogger();\n\n let builder: Builder.Instance = Builder.create({\n logger,\n basePath: __dirname,\n overridePath,\n overrides: overrides || false,\n });\n\n builder = await builder.addPersonaPath(DEFAULT_PERSONA_YOU_FILE);\n builder = await builder.addInstructionPath(DEFAULT_INSTRUCTIONS_REVIEW_FILE);\n\n // Primary review notes supplied by the user\n builder = await builder.addContent(notes, { title: 'Review Notes', weight: 1.0 });\n\n // Additional context directories\n if (directories?.length) {\n builder = await builder.loadContext(directories, { weight: 0.5 });\n }\n\n if (logContext) {\n builder = await builder.addContext(logContext, { title: 'Log Context', weight: 0.5 });\n }\n if (diffContext) {\n builder = await builder.addContext(diffContext, { title: 'Diff Context', weight: 0.5 });\n }\n if (releaseNotesContext) {\n builder = await builder.addContext(releaseNotesContext, { title: 'Release Notes Context', weight: 0.5 });\n }\n if (issuesContext) {\n builder = await builder.addContext(issuesContext, { title: 'Issues Context', weight: 0.5 });\n }\n if (context) {\n builder = await builder.addContext(context, { title: 'User Context', weight: 1.0 });\n }\n\n return await builder.build();\n}; "],"names":["__filename","fileURLToPath","url","__dirname","path","dirname","createPrompt","overridePath","overrides","notes","logContext","diffContext","releaseNotesContext","issuesContext","context","directories","logger","getLogger","builder","Builder","create","basePath","addPersonaPath","DEFAULT_PERSONA_YOU_FILE","addInstructionPath","DEFAULT_INSTRUCTIONS_REVIEW_FILE","addContent","title","weight","length","loadContext","addContext","build"],"mappings":";;;;;;AAOA,MAAMA,UAAAA,GAAaC,aAAAA,CAAc,MAAA,CAAA,IAAA,CAAYC,GAAG,CAAA;AAChD,MAAMC,SAAAA,GAAYC,IAAAA,CAAKC,OAAO,CAACL,UAAAA,CAAAA;AAoBxB,MAAMM,YAAAA,GAAe,OACxB,EAAEC,YAAY,EAAEC,SAAS,EAAU,EACnC,EAAEC,KAAK,EAAW,EAClB,EAAEC,UAAU,EAAEC,WAAW,EAAEC,mBAAmB,EAAEC,aAAa,EAAEC,OAAO,EAAEC,WAAW,EAAW,GAAG,EAAE,GAAA;AAEnG,IAAA,MAAMC,MAAAA,GAASC,SAAAA,EAAAA;IAEf,IAAIC,OAAAA,GAA4BC,OAAAA,CAAQC,MAAM,CAAC;AAC3CJ,QAAAA,MAAAA;QACAK,QAAAA,EAAUlB,SAAAA;AACVI,QAAAA,YAAAA;AACAC,QAAAA,SAAAA,EAAWA,SAAAA,IAAa;AAC5B,KAAA,CAAA;IAEAU,OAAAA,GAAU,MAAMA,OAAAA,CAAQI,cAAc,CAACC,wBAAAA,CAAAA;IACvCL,OAAAA,GAAU,MAAMA,OAAAA,CAAQM,kBAAkB,CAACC,gCAAAA,CAAAA;;AAG3CP,IAAAA,OAAAA,GAAU,MAAMA,OAAAA,CAAQQ,UAAU,CAACjB,KAAAA,EAAO;QAAEkB,KAAAA,EAAO,cAAA;QAAgBC,MAAAA,EAAQ;AAAI,KAAA,CAAA;;AAG/E,IAAA,IAAIb,WAAAA,KAAAA,IAAAA,IAAAA,WAAAA,KAAAA,MAAAA,GAAAA,MAAAA,GAAAA,WAAAA,CAAac,MAAM,EAAE;AACrBX,QAAAA,OAAAA,GAAU,MAAMA,OAAAA,CAAQY,WAAW,CAACf,WAAAA,EAAa;YAAEa,MAAAA,EAAQ;AAAI,SAAA,CAAA;AACnE;AAEA,IAAA,IAAIlB,UAAAA,EAAY;AACZQ,QAAAA,OAAAA,GAAU,MAAMA,OAAAA,CAAQa,UAAU,CAACrB,UAAAA,EAAY;YAAEiB,KAAAA,EAAO,aAAA;YAAeC,MAAAA,EAAQ;AAAI,SAAA,CAAA;AACvF;AACA,IAAA,IAAIjB,WAAAA,EAAa;AACbO,QAAAA,OAAAA,GAAU,MAAMA,OAAAA,CAAQa,UAAU,CAACpB,WAAAA,EAAa;YAAEgB,KAAAA,EAAO,cAAA;YAAgBC,MAAAA,EAAQ;AAAI,SAAA,CAAA;AACzF;AACA,IAAA,IAAIhB,mBAAAA,EAAqB;AACrBM,QAAAA,OAAAA,GAAU,MAAMA,OAAAA,CAAQa,UAAU,CAACnB,mBAAAA,EAAqB;YAAEe,KAAAA,EAAO,uBAAA;YAAyBC,MAAAA,EAAQ;AAAI,SAAA,CAAA;AAC1G;AACA,IAAA,IAAIf,aAAAA,EAAe;AACfK,QAAAA,OAAAA,GAAU,MAAMA,OAAAA,CAAQa,UAAU,CAAClB,aAAAA,EAAe;YAAEc,KAAAA,EAAO,gBAAA;YAAkBC,MAAAA,EAAQ;AAAI,SAAA,CAAA;AAC7F;AACA,IAAA,IAAId,OAAAA,EAAS;AACTI,QAAAA,OAAAA,GAAU,MAAMA,OAAAA,CAAQa,UAAU,CAACjB,OAAAA,EAAS;YAAEa,KAAAA,EAAO,cAAA;YAAgBC,MAAAA,EAAQ;AAAI,SAAA,CAAA;AACrF;IAEA,OAAO,MAAMV,QAAQc,KAAK,EAAA;AAC9B;;;;"}
package/dist/types.js CHANGED
@@ -5,10 +5,10 @@ const ConfigSchema = z.object({
5
5
  verbose: z.boolean().optional(),
6
6
  debug: z.boolean().optional(),
7
7
  overrides: z.boolean().optional(),
8
- instructions: z.string().optional(),
9
8
  model: z.string().optional(),
10
9
  contextDirectories: z.array(z.string()).optional(),
11
10
  outputDirectory: z.string().optional(),
11
+ preferencesDirectory: z.string().optional(),
12
12
  commit: z.object({
13
13
  add: z.boolean().optional(),
14
14
  cached: z.boolean().optional(),
@@ -20,7 +20,8 @@ const ConfigSchema = z.object({
20
20
  audioCommit: z.object({
21
21
  maxRecordingTime: z.number().optional(),
22
22
  audioDevice: z.string().optional(),
23
- selectAudioDevice: z.boolean().optional()
23
+ file: z.string().optional(),
24
+ keepTemp: z.boolean().optional()
24
25
  }).optional(),
25
26
  release: z.object({
26
27
  from: z.string().optional(),
@@ -54,7 +55,8 @@ const ConfigSchema = z.object({
54
55
  sendit: z.boolean().optional(),
55
56
  maxRecordingTime: z.number().optional(),
56
57
  audioDevice: z.string().optional(),
57
- selectAudioDevice: z.boolean().optional()
58
+ file: z.string().optional(),
59
+ keepTemp: z.boolean().optional()
58
60
  }).optional(),
59
61
  publish: z.object({
60
62
  mergeMethod: z.enum([
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sources":["../src/types.ts"],"sourcesContent":["import * as Cardigantime from '@theunwalked/cardigantime';\nimport { z } from \"zod\";\n\nexport const ConfigSchema = z.object({\n dryRun: z.boolean().optional(),\n verbose: z.boolean().optional(),\n debug: z.boolean().optional(),\n overrides: z.boolean().optional(),\n instructions: z.string().optional(),\n model: z.string().optional(),\n contextDirectories: z.array(z.string()).optional(),\n outputDirectory: z.string().optional(),\n commit: z.object({\n add: z.boolean().optional(),\n cached: z.boolean().optional(),\n sendit: z.boolean().optional(),\n messageLimit: z.number().optional(),\n context: z.string().optional(),\n direction: z.string().optional(),\n }).optional(),\n audioCommit: z.object({\n maxRecordingTime: z.number().optional(),\n audioDevice: z.string().optional(),\n selectAudioDevice: z.boolean().optional(),\n }).optional(),\n release: z.object({\n from: z.string().optional(),\n to: z.string().optional(),\n messageLimit: z.number().optional(),\n context: z.string().optional(),\n }).optional(),\n review: z.object({\n includeCommitHistory: z.boolean().optional(),\n includeRecentDiffs: z.boolean().optional(),\n includeReleaseNotes: z.boolean().optional(),\n includeGithubIssues: z.boolean().optional(),\n commitHistoryLimit: z.number().optional(),\n diffHistoryLimit: z.number().optional(),\n releaseNotesLimit: z.number().optional(),\n githubIssuesLimit: z.number().optional(),\n context: z.string().optional(),\n sendit: z.boolean().optional(),\n note: z.string().optional(),\n }).optional(),\n audioReview: z.object({\n includeCommitHistory: z.boolean().optional(),\n includeRecentDiffs: z.boolean().optional(),\n includeReleaseNotes: z.boolean().optional(),\n includeGithubIssues: z.boolean().optional(),\n commitHistoryLimit: z.number().optional(),\n diffHistoryLimit: z.number().optional(),\n releaseNotesLimit: z.number().optional(),\n githubIssuesLimit: z.number().optional(),\n context: z.string().optional(),\n sendit: z.boolean().optional(),\n maxRecordingTime: z.number().optional(),\n audioDevice: z.string().optional(),\n selectAudioDevice: z.boolean().optional(),\n }).optional(),\n publish: z.object({\n mergeMethod: z.enum(['merge', 'squash', 'rebase']).optional(),\n dependencyUpdatePatterns: z.array(z.string()).optional(),\n requiredEnvVars: z.array(z.string()).optional(),\n linkWorkspacePackages: z.boolean().optional(),\n unlinkWorkspacePackages: z.boolean().optional(),\n }).optional(),\n link: z.object({\n scopeRoots: z.record(z.string(), z.string()).optional(),\n workspaceFile: z.string().optional(),\n dryRun: z.boolean().optional(),\n }).optional(),\n excludedPatterns: z.array(z.string()).optional(),\n});\n\nexport const SecureConfigSchema = z.object({\n openaiApiKey: z.string().optional(),\n});\n\nexport const CommandConfigSchema = z.object({\n commandName: z.string().optional(),\n});\n\nexport type Config = z.infer<typeof ConfigSchema> & Cardigantime.Config;\nexport type SecureConfig = z.infer<typeof SecureConfigSchema>;\nexport type CommandConfig = z.infer<typeof CommandConfigSchema>;\n\nexport type MergeMethod = 'merge' | 'squash' | 'rebase';\n\nexport interface PullRequest {\n html_url: string;\n number: number;\n labels: {\n name: string;\n }[];\n}\n\nexport type ReleaseSummary = {\n title: string;\n body: string;\n}\n\nexport type ReleaseConfig = {\n from?: string;\n to?: string;\n context?: string;\n}\n\nexport type ReviewConfig = {\n includeCommitHistory?: boolean;\n includeRecentDiffs?: boolean;\n includeReleaseNotes?: boolean;\n includeGithubIssues?: boolean;\n commitHistoryLimit?: number;\n diffHistoryLimit?: number;\n releaseNotesLimit?: number;\n githubIssuesLimit?: number;\n context?: string;\n sendit?: boolean;\n note?: string;\n}\n\nexport type AudioReviewConfig = {\n includeCommitHistory?: boolean;\n includeRecentDiffs?: boolean;\n includeReleaseNotes?: boolean;\n includeGithubIssues?: boolean;\n commitHistoryLimit?: number;\n diffHistoryLimit?: number;\n releaseNotesLimit?: number;\n githubIssuesLimit?: number;\n context?: string;\n sendit?: boolean;\n maxRecordingTime?: number;\n audioDevice?: string;\n selectAudioDevice?: boolean;\n}\n\nexport type AudioCommitConfig = {\n maxRecordingTime?: number;\n audioDevice?: string;\n selectAudioDevice?: boolean;\n}\n\nexport type PublishConfig = {\n from?: string;\n to?: string;\n}\n"],"names":["ConfigSchema","z","object","dryRun","boolean","optional","verbose","debug","overrides","instructions","string","model","contextDirectories","array","outputDirectory","commit","add","cached","sendit","messageLimit","number","context","direction","audioCommit","maxRecordingTime","audioDevice","selectAudioDevice","release","from","to","review","includeCommitHistory","includeRecentDiffs","includeReleaseNotes","includeGithubIssues","commitHistoryLimit","diffHistoryLimit","releaseNotesLimit","githubIssuesLimit","note","audioReview","publish","mergeMethod","enum","dependencyUpdatePatterns","requiredEnvVars","linkWorkspacePackages","unlinkWorkspacePackages","link","scopeRoots","record","workspaceFile","excludedPatterns","openaiApiKey","commandName"],"mappings":"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"}
1
+ {"version":3,"file":"types.js","sources":["../src/types.ts"],"sourcesContent":["import * as Cardigantime from '@theunwalked/cardigantime';\nimport { z } from \"zod\";\n\nexport const ConfigSchema = z.object({\n dryRun: z.boolean().optional(),\n verbose: z.boolean().optional(),\n debug: z.boolean().optional(),\n overrides: z.boolean().optional(),\n model: z.string().optional(),\n contextDirectories: z.array(z.string()).optional(),\n outputDirectory: z.string().optional(),\n preferencesDirectory: z.string().optional(),\n commit: z.object({\n add: z.boolean().optional(),\n cached: z.boolean().optional(),\n sendit: z.boolean().optional(),\n messageLimit: z.number().optional(),\n context: z.string().optional(),\n direction: z.string().optional(),\n }).optional(),\n audioCommit: z.object({\n maxRecordingTime: z.number().optional(),\n audioDevice: z.string().optional(),\n file: z.string().optional(),\n keepTemp: z.boolean().optional(),\n }).optional(),\n release: z.object({\n from: z.string().optional(),\n to: z.string().optional(),\n messageLimit: z.number().optional(),\n context: z.string().optional(),\n }).optional(),\n review: z.object({\n includeCommitHistory: z.boolean().optional(),\n includeRecentDiffs: z.boolean().optional(),\n includeReleaseNotes: z.boolean().optional(),\n includeGithubIssues: z.boolean().optional(),\n commitHistoryLimit: z.number().optional(),\n diffHistoryLimit: z.number().optional(),\n releaseNotesLimit: z.number().optional(),\n githubIssuesLimit: z.number().optional(),\n context: z.string().optional(),\n sendit: z.boolean().optional(),\n note: z.string().optional(),\n }).optional(),\n audioReview: z.object({\n includeCommitHistory: z.boolean().optional(),\n includeRecentDiffs: z.boolean().optional(),\n includeReleaseNotes: z.boolean().optional(),\n includeGithubIssues: z.boolean().optional(),\n commitHistoryLimit: z.number().optional(),\n diffHistoryLimit: z.number().optional(),\n releaseNotesLimit: z.number().optional(),\n githubIssuesLimit: z.number().optional(),\n context: z.string().optional(),\n sendit: z.boolean().optional(),\n maxRecordingTime: z.number().optional(),\n audioDevice: z.string().optional(),\n file: z.string().optional(),\n keepTemp: z.boolean().optional(),\n }).optional(),\n publish: z.object({\n mergeMethod: z.enum(['merge', 'squash', 'rebase']).optional(),\n dependencyUpdatePatterns: z.array(z.string()).optional(),\n requiredEnvVars: z.array(z.string()).optional(),\n linkWorkspacePackages: z.boolean().optional(),\n unlinkWorkspacePackages: z.boolean().optional(),\n }).optional(),\n link: z.object({\n scopeRoots: z.record(z.string(), z.string()).optional(),\n workspaceFile: z.string().optional(),\n dryRun: z.boolean().optional(),\n }).optional(),\n excludedPatterns: z.array(z.string()).optional(),\n});\n\nexport const SecureConfigSchema = z.object({\n openaiApiKey: z.string().optional(),\n});\n\nexport const CommandConfigSchema = z.object({\n commandName: z.string().optional(),\n});\n\nexport type Config = z.infer<typeof ConfigSchema> & Cardigantime.Config;\nexport type SecureConfig = z.infer<typeof SecureConfigSchema>;\nexport type CommandConfig = z.infer<typeof CommandConfigSchema>;\n\nexport type MergeMethod = 'merge' | 'squash' | 'rebase';\n\nexport interface PullRequest {\n html_url: string;\n number: number;\n labels: {\n name: string;\n }[];\n}\n\nexport type ReleaseSummary = {\n title: string;\n body: string;\n}\n\nexport type ReleaseConfig = {\n from?: string;\n to?: string;\n context?: string;\n}\n\nexport type ReviewConfig = {\n includeCommitHistory?: boolean;\n includeRecentDiffs?: boolean;\n includeReleaseNotes?: boolean;\n includeGithubIssues?: boolean;\n commitHistoryLimit?: number;\n diffHistoryLimit?: number;\n releaseNotesLimit?: number;\n githubIssuesLimit?: number;\n context?: string;\n sendit?: boolean;\n note?: string;\n}\n\nexport type AudioReviewConfig = {\n includeCommitHistory?: boolean;\n includeRecentDiffs?: boolean;\n includeReleaseNotes?: boolean;\n includeGithubIssues?: boolean;\n commitHistoryLimit?: number;\n diffHistoryLimit?: number;\n releaseNotesLimit?: number;\n githubIssuesLimit?: number;\n context?: string;\n sendit?: boolean;\n maxRecordingTime?: number;\n audioDevice?: string;\n file?: string;\n keepTemp?: boolean;\n}\n\nexport type AudioCommitConfig = {\n maxRecordingTime?: number;\n audioDevice?: string;\n file?: string;\n keepTemp?: boolean;\n}\n\nexport type PublishConfig = {\n from?: string;\n to?: string;\n}\n"],"names":["ConfigSchema","z","object","dryRun","boolean","optional","verbose","debug","overrides","model","string","contextDirectories","array","outputDirectory","preferencesDirectory","commit","add","cached","sendit","messageLimit","number","context","direction","audioCommit","maxRecordingTime","audioDevice","file","keepTemp","release","from","to","review","includeCommitHistory","includeRecentDiffs","includeReleaseNotes","includeGithubIssues","commitHistoryLimit","diffHistoryLimit","releaseNotesLimit","githubIssuesLimit","note","audioReview","publish","mergeMethod","enum","dependencyUpdatePatterns","requiredEnvVars","linkWorkspacePackages","unlinkWorkspacePackages","link","scopeRoots","record","workspaceFile","excludedPatterns","openaiApiKey","commandName"],"mappings":"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"}
@@ -15,13 +15,15 @@ async function createCompletion(messages, options = {
15
15
  const storage = create({
16
16
  log: logger.debug
17
17
  });
18
+ let openai = null;
18
19
  try {
19
20
  var _completion_choices__message_content, _completion_choices__message, _completion_choices_;
20
21
  const apiKey = process.env.OPENAI_API_KEY;
21
22
  if (!apiKey) {
22
23
  throw new OpenAIError('OPENAI_API_KEY environment variable is not set');
23
24
  }
24
- const openai = new OpenAI({
25
+ // Create the client which we'll close in the finally block.
26
+ openai = new OpenAI({
25
27
  apiKey: apiKey
26
28
  });
27
29
  logger.debug('Sending prompt to OpenAI: %j', messages);
@@ -62,6 +64,17 @@ async function createCompletion(messages, options = {
62
64
  } catch (error) {
63
65
  logger.error('Error calling OpenAI API: %s %s', error.message, error.stack);
64
66
  throw new OpenAIError(`Failed to create completion: ${error.message}`);
67
+ } finally{
68
+ // Ensure we close the OpenAI client to release underlying keep-alive sockets
69
+ try {
70
+ // openai.close() returns a promise; awaiting ensures proper cleanup
71
+ // but if it throws we silently ignore as it's best-effort.
72
+ if (openai && typeof openai.close === 'function') {
73
+ await openai.close();
74
+ }
75
+ } catch (closeErr) {
76
+ logger.debug('Failed to close OpenAI client: %s', closeErr.message);
77
+ }
65
78
  }
66
79
  }
67
80
  async function transcribeAudio(filePath, options = {
@@ -71,12 +84,14 @@ async function transcribeAudio(filePath, options = {
71
84
  const storage = create({
72
85
  log: logger.debug
73
86
  });
87
+ let openai = null;
88
+ let audioStream = null;
74
89
  try {
75
90
  const apiKey = process.env.OPENAI_API_KEY;
76
91
  if (!apiKey) {
77
92
  throw new OpenAIError('OPENAI_API_KEY environment variable is not set');
78
93
  }
79
- const openai = new OpenAI({
94
+ openai = new OpenAI({
80
95
  apiKey: apiKey
81
96
  });
82
97
  logger.debug('Transcribing audio file: %s', filePath);
@@ -91,7 +106,7 @@ async function transcribeAudio(filePath, options = {
91
106
  await storage.writeFile(debugFile, JSON.stringify(requestData, null, 2), 'utf8');
92
107
  logger.debug('Wrote request debug file to %s', debugFile);
93
108
  }
94
- const audioStream = await storage.readStream(filePath);
109
+ audioStream = await storage.readStream(filePath);
95
110
  const transcription = await openai.audio.transcriptions.create({
96
111
  model: options.model || "whisper-1",
97
112
  file: audioStream,
@@ -112,6 +127,22 @@ async function transcribeAudio(filePath, options = {
112
127
  } catch (error) {
113
128
  logger.error('Error transcribing audio file: %s %s', error.message, error.stack);
114
129
  throw new OpenAIError(`Failed to transcribe audio: ${error.message}`);
130
+ } finally{
131
+ // Ensure the audio stream is properly closed to release file handles
132
+ try {
133
+ if (audioStream) {
134
+ audioStream.close();
135
+ }
136
+ } catch (streamErr) {
137
+ logger.debug('Failed to close audio read stream: %s', streamErr.message);
138
+ }
139
+ try {
140
+ if (openai && typeof openai.close === 'function') {
141
+ await openai.close();
142
+ }
143
+ } catch (closeErr) {
144
+ logger.debug('Failed to close OpenAI client: %s', closeErr.message);
145
+ }
115
146
  }
116
147
  }
117
148
 
@@ -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';\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 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 const openai = new OpenAI({\n apiKey: apiKey,\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 const completion = await 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 // 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 }\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 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 const 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 const 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 }\n}\n"],"names":["OpenAIError","Error","message","name","createCompletion","messages","options","model","logger","getLogger","storage","Storage","log","debug","completion","apiKey","process","env","OPENAI_API_KEY","openai","OpenAI","debugRequestFile","debugFile","requestData","max_completion_tokens","response_format","responseFormat","writeFile","JSON","stringify","chat","completions","create","debugResponseFile","response","choices","content","trim","substring","parse","error","stack","transcribeAudio","filePath","file","audioStream","readStream","transcription","audio","transcriptions"],"mappings":"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"}
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 });\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 const completion = await 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 // 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 // Ensure we close the OpenAI client to release underlying keep-alive sockets\n try {\n // openai.close() returns a promise; awaiting ensures proper cleanup\n // but if it throws we silently ignore as it's best-effort.\n\n if (openai && typeof (openai as any).close === 'function') {\n await (openai as any).close();\n }\n } catch (closeErr) {\n logger.debug('Failed to close OpenAI client: %s', (closeErr as Error).message);\n }\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 try {\n if (openai && typeof (openai as any).close === 'function') {\n await (openai as any).close();\n }\n } catch (closeErr) {\n logger.debug('Failed to close OpenAI client: %s', (closeErr as Error).message);\n }\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","debugRequestFile","debugFile","requestData","max_completion_tokens","response_format","responseFormat","writeFile","JSON","stringify","chat","completions","create","debugResponseFile","response","choices","content","trim","substring","parse","error","stack","close","closeErr","transcribeAudio","filePath","audioStream","file","readStream","transcription","audio","transcriptions","streamErr"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eldrforge/kodrdriv",
3
- "version": "0.0.15",
3
+ "version": "0.0.18",
4
4
  "description": "Create Intelligent Release Notes or Change Logs from Git",
5
5
  "main": "dist/main.js",
6
6
  "type": "module",
@@ -35,7 +35,7 @@
35
35
  "openai": "^5.8.2",
36
36
  "shell-escape": "^0.2.0",
37
37
  "winston": "^3.17.0",
38
- "zod": "^3.25.67"
38
+ "zod": "^3.25.71"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@eslint/eslintrc": "^3.3.1",
@@ -1,20 +0,0 @@
1
- verbose: false
2
- model: gpt-4.1
3
- contextDirectories:
4
- - .kodrdriv/context
5
- commit:
6
- add: true
7
- cached: true
8
- sendit: true
9
- release:
10
- from: main
11
- to: HEAD
12
- publish:
13
- mergeMethod: squash
14
- dependencyUpdatePatterns: ["@theunwalked/*", "@riotprompt/*"]
15
- requiredEnvVars: ["NODE_AUTH_TOKEN"]
16
- link:
17
- scopeRoots:
18
- "@theunwalked": "../../SemicolonAmbulance"
19
- "@riotprompt": "../../StJustReckoning"
20
- workspaceFile: "pnpm-workspace.yaml"
@@ -1,7 +0,0 @@
1
- KodrDriv is a tool that is designed to help automate the creation of commit messages and release notes. It is also a tool that has been designed to support an opinionated approach to organizing related projects and conducting structured releases with Git. This initial version focuses on pnpm and GitHub, but there are plans to expand coverage over time.
2
-
3
- KodrDriv is available as an module on npmjs.org under @eldrforge/kodrdriv
4
-
5
- The name sometimes sounds like "Coder Driv" or "Coder Riv" but that should be corrected to "KodrDriv"
6
-
7
- Same with the name of the scope "Elder Forge" or "Elderforth" should be corrected to "Edlrforge"
package/RELEASE_NOTES.md DELETED
@@ -1,14 +0,0 @@
1
- This release updates workspace management and CI deployment for projects using pnpm with an opinionated structure. The changes restore explicit workspace scoping and local package link overrides, improving multi-package development while streamlining documentation deployment.
2
-
3
- **Improvements**
4
-
5
- * Restored exclusions for the `docs` directory and local dependency overrides in `pnpm-workspace.yaml` to clarify project boundaries and enable local development workflows for core packages.
6
- * Simplified the `deploy-docs.yml` workflow by removing temporary renaming of the workspace file; documentation builds and deployments now work directly with the refined workspace configuration.
7
-
8
- **Why these changes matter:**
9
-
10
- * Empower clearer separation between core packages and documentation in the monorepo setup.
11
- * Align local development processes and CI deployment behavior.
12
- * Reduce special-casing and ad-hoc workarounds in documentation workflows.
13
-
14
- _No breaking changes or new features are introduced for end users._
@@ -1,29 +0,0 @@
1
- You are an intelligent assistant responsible for generating **high-quality, concise, and structured commit messages** for repositories that may include **code**, **configuration**, or **long-form written content** (e.g., technical docs, policies, onboarding materials).
2
-
3
- ## 🧑‍💻 Persona: GitHub Project Committer
4
-
5
- **Role Title:** GitHub Committer / Core Contributor
6
- **Scope:** Regular contributor with write access; responsible for submitting high-quality commits, maintaining code health, and ensuring clarity and traceability in project history.
7
-
8
- ### 🔑 Responsibilities
9
-
10
- * **Submit Meaningful Commits**
11
- Write clear, purposeful, and well-scoped commits that align with project standards, including thoughtful messages that reflect both technical and contextual intent.
12
-
13
- * **Respect Context**
14
- Incorporate `User Context`, linked issues, and project priorities into commits. Treat commit messages as historical records for collaborators and future maintainers.
15
-
16
- * **Code + Content Awareness**
17
- Committers may work on code, config, docs, or mixed artifacts. Must treat documentation changes with the same level of diligence as code edits.
18
-
19
- ### 🛠 Technical Proficiencies
20
-
21
- * Proficient in project languages and tooling (e.g., TypeScript, Python, Rust, etc.)
22
- * Familiar with Git workflows: feature branching, squash-and-merge, rebase with care
23
- * Uses pre-commit hooks, linting, and test tools before pushing changes
24
-
25
- ### 🧭 Operating Principles
26
-
27
- * Clarity > Brevity > Cleverness
28
- * Commit messages are communication tools, not just logs
29
- * Consider the reader: future teammates, open-source collaborators, or even your future self
@@ -1,29 +0,0 @@
1
- You are an expert software project reviewer who specializes in analyzing spoken feedback to identify actionable issues and improvements.
2
-
3
- ---
4
-
5
- ### 🔑 Responsibilities
6
-
7
- * **Extract Actionable Issues**
8
- Listen to feedback and identify specific, implementable issues that can be addressed in a software project.
9
-
10
- * **Categorize and Prioritize**
11
- Organize issues by type (UI, content, functionality, etc.) and assign appropriate priority levels based on impact.
12
-
13
- * **Provide Clear Suggestions**
14
- Translate vague feedback into concrete, actionable suggestions that developers can implement.
15
-
16
- * **Maintain Focus**
17
- Filter out non-actionable commentary and focus on issues that can meaningfully improve the project.
18
-
19
- ---
20
-
21
- ### 🧠 Analysis Approach
22
-
23
- * ✅ Convert spoken observations into structured, implementable tasks
24
- * ✅ Distinguish between critical issues and minor improvements
25
- * ✅ Provide context and reasoning for priority assignments
26
- * ✅ Focus on user experience and practical functionality
27
- * ❌ Don't include vague or non-specific feedback
28
- * ❌ Don't assume context not provided in the transcription
29
- * ❌ Don't create issues for comments that are purely subjective preferences without clear rationale