@eldrforge/kodrdriv 0.0.1
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.
- package/.gitcarve/config.yaml +11 -0
- package/.gitcarve/context/people/context.md +5 -0
- package/.gitcarve/context/projects/context.md +3 -0
- package/.gitcarve/instructions/INACTIVE-release-pre.md +1 -0
- package/LICENSE +190 -0
- package/README.md +337 -0
- package/dist/arguments.js +252 -0
- package/dist/arguments.js.map +1 -0
- package/dist/commands/commit.js +54 -0
- package/dist/commands/commit.js.map +1 -0
- package/dist/commands/release.js +27 -0
- package/dist/commands/release.js.map +1 -0
- package/dist/constants.js +95 -0
- package/dist/constants.js.map +1 -0
- package/dist/content/diff.js +53 -0
- package/dist/content/diff.js.map +1 -0
- package/dist/content/log.js +34 -0
- package/dist/content/log.js.map +1 -0
- package/dist/error/ExitError.js +9 -0
- package/dist/error/ExitError.js.map +1 -0
- package/dist/logging.js +46 -0
- package/dist/logging.js.map +1 -0
- package/dist/main.js +53 -0
- package/dist/main.js.map +1 -0
- package/dist/prompt/instructions/commit.md +48 -0
- package/dist/prompt/instructions/release.md +31 -0
- package/dist/prompt/personas/you.md +11 -0
- package/dist/prompt/prompts.js +55 -0
- package/dist/prompt/prompts.js.map +1 -0
- package/dist/types.js +29 -0
- package/dist/types.js.map +1 -0
- package/dist/util/child.js +11 -0
- package/dist/util/child.js.map +1 -0
- package/dist/util/openai.js +55 -0
- package/dist/util/openai.js.map +1 -0
- package/dist/util/storage.js +126 -0
- package/dist/util/storage.js.map +1 -0
- package/eslint.config.mjs +82 -0
- package/nodemon.json +14 -0
- package/package.json +74 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/vite.config.ts +90 -0
- package/vitest.config.ts +21 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { ExitError } from '../error/ExitError.js';
|
|
3
|
+
import { getLogger } from '../logging.js';
|
|
4
|
+
import { run } from '../util/child.js';
|
|
5
|
+
|
|
6
|
+
const create = async (options)=>{
|
|
7
|
+
const logger = getLogger();
|
|
8
|
+
async function get() {
|
|
9
|
+
try {
|
|
10
|
+
logger.verbose('Gathering change information from Git');
|
|
11
|
+
try {
|
|
12
|
+
logger.debug('Executing git log');
|
|
13
|
+
const { stdout, stderr } = await run(`git log ${options.from}..${options.to}`);
|
|
14
|
+
if (stderr) {
|
|
15
|
+
logger.warn('Git log produced stderr: %s', stderr);
|
|
16
|
+
}
|
|
17
|
+
logger.debug('Git log output: %s', stdout);
|
|
18
|
+
return stdout;
|
|
19
|
+
} catch (error) {
|
|
20
|
+
logger.error('Failed to execute git log: %s', error.message);
|
|
21
|
+
throw error;
|
|
22
|
+
}
|
|
23
|
+
} catch (error) {
|
|
24
|
+
logger.error('Error occurred during gather change phase: %s %s', error.message, error.stack);
|
|
25
|
+
throw new ExitError('Error occurred during gather change phase');
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
get
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export { create };
|
|
34
|
+
//# sourceMappingURL=log.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log.js","sources":["../../src/content/log.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { ExitError } from '../error/ExitError';\nimport { getLogger } from '../logging';\nimport { run } from '../util/child';\n\nexport interface Instance {\n get(): Promise<string>;\n}\n\nexport const create = async (options: { from: string, to: string }): Promise<Instance> => {\n const logger = getLogger();\n\n async function get(): Promise<string> {\n try {\n logger.verbose('Gathering change information from Git');\n\n try {\n logger.debug('Executing git log');\n const { stdout, stderr } = await run(`git log ${options.from}..${options.to}`);\n if (stderr) {\n logger.warn('Git log produced stderr: %s', stderr);\n }\n logger.debug('Git log output: %s', stdout);\n return stdout;\n } catch (error: any) {\n logger.error('Failed to execute git log: %s', error.message);\n throw error;\n }\n } catch (error: any) {\n logger.error('Error occurred during gather change phase: %s %s', error.message, error.stack);\n throw new ExitError('Error occurred during gather change phase');\n }\n }\n\n return { get };\n}\n\n"],"names":["create","options","logger","getLogger","get","verbose","debug","stdout","stderr","run","from","to","warn","error","message","stack","ExitError"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExitError.js","sources":["../../src/error/ExitError.ts"],"sourcesContent":["export class ExitError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ExitError';\n }\n}\n"],"names":["ExitError","Error","constructor","message","name"],"mappings":"AAAO,MAAMA,SAAkBC,SAAAA,KAAAA,CAAAA;AAC3BC,IAAAA,WAAAA,CAAYC,OAAe,CAAE;AACzB,QAAA,KAAK,CAACA,OAAAA,CAAAA;QACN,IAAI,CAACC,IAAI,GAAG,WAAA;AAChB;AACJ;;;;"}
|
package/dist/logging.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import winston from 'winston';
|
|
2
|
+
import { DATE_FORMAT_YEAR_MONTH_DAY_HOURS_MINUTES_SECONDS, PROGRAM_NAME } from './constants.js';
|
|
3
|
+
|
|
4
|
+
const createLogger = (level = 'info')=>{
|
|
5
|
+
let format = winston.format.combine(winston.format.timestamp({
|
|
6
|
+
format: DATE_FORMAT_YEAR_MONTH_DAY_HOURS_MINUTES_SECONDS
|
|
7
|
+
}), winston.format.errors({
|
|
8
|
+
stack: true
|
|
9
|
+
}), winston.format.splat(), winston.format.json());
|
|
10
|
+
let transports = [
|
|
11
|
+
new winston.transports.Console({
|
|
12
|
+
format: winston.format.combine(winston.format.colorize(), winston.format.printf(({ timestamp, level, message, ...meta })=>{
|
|
13
|
+
const metaStr = Object.keys(meta).length ? ` ${JSON.stringify(meta)}` : '';
|
|
14
|
+
return `${timestamp} ${level}: ${message}${metaStr}`;
|
|
15
|
+
}))
|
|
16
|
+
})
|
|
17
|
+
];
|
|
18
|
+
if (level === 'info') {
|
|
19
|
+
format = winston.format.combine(winston.format.errors({
|
|
20
|
+
stack: true
|
|
21
|
+
}), winston.format.splat());
|
|
22
|
+
transports = [
|
|
23
|
+
new winston.transports.Console({
|
|
24
|
+
format: winston.format.combine(winston.format.colorize(), winston.format.printf(({ level, message })=>{
|
|
25
|
+
return `${level}: ${message}`;
|
|
26
|
+
}))
|
|
27
|
+
})
|
|
28
|
+
];
|
|
29
|
+
}
|
|
30
|
+
return winston.createLogger({
|
|
31
|
+
level,
|
|
32
|
+
format,
|
|
33
|
+
defaultMeta: {
|
|
34
|
+
service: PROGRAM_NAME
|
|
35
|
+
},
|
|
36
|
+
transports
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
let logger = createLogger();
|
|
40
|
+
const setLogLevel = (level)=>{
|
|
41
|
+
logger = createLogger(level);
|
|
42
|
+
};
|
|
43
|
+
const getLogger = ()=>logger;
|
|
44
|
+
|
|
45
|
+
export { getLogger, setLogLevel };
|
|
46
|
+
//# sourceMappingURL=logging.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logging.js","sources":["../src/logging.ts"],"sourcesContent":["import winston from 'winston';\nimport { DATE_FORMAT_YEAR_MONTH_DAY_HOURS_MINUTES_SECONDS, PROGRAM_NAME } from './constants';\n\nexport interface LogContext {\n [key: string]: any;\n}\n\nconst createLogger = (level: string = 'info') => {\n\n let format = winston.format.combine(\n winston.format.timestamp({ format: DATE_FORMAT_YEAR_MONTH_DAY_HOURS_MINUTES_SECONDS }),\n winston.format.errors({ stack: true }),\n winston.format.splat(),\n winston.format.json()\n );\n\n let transports = [\n new winston.transports.Console({\n format: winston.format.combine(\n winston.format.colorize(),\n winston.format.printf(({ timestamp, level, message, ...meta }) => {\n const metaStr = Object.keys(meta).length ? ` ${JSON.stringify(meta)}` : '';\n return `${timestamp} ${level}: ${message}${metaStr}`;\n })\n )\n })\n ];\n\n if (level === 'info') {\n format = winston.format.combine(\n winston.format.errors({ stack: true }),\n winston.format.splat(),\n );\n\n transports = [\n new winston.transports.Console({\n format: winston.format.combine(\n winston.format.colorize(),\n winston.format.printf(({ level, message }) => {\n return `${level}: ${message}`;\n })\n )\n })\n ];\n }\n\n return winston.createLogger({\n level,\n format,\n defaultMeta: { service: PROGRAM_NAME },\n transports,\n });\n};\n\nlet logger = createLogger();\n\nexport const setLogLevel = (level: string) => {\n logger = createLogger(level);\n};\n\nexport const getLogger = () => logger; "],"names":["createLogger","level","format","winston","combine","timestamp","DATE_FORMAT_YEAR_MONTH_DAY_HOURS_MINUTES_SECONDS","errors","stack","splat","json","transports","Console","colorize","printf","message","meta","metaStr","Object","keys","length","JSON","stringify","defaultMeta","service","PROGRAM_NAME","logger","setLogLevel","getLogger"],"mappings":";;;AAOA,MAAMA,YAAAA,GAAe,CAACC,KAAAA,GAAgB,MAAM,GAAA;IAExC,IAAIC,MAAAA,GAASC,OAAQD,CAAAA,MAAM,CAACE,OAAO,CAC/BD,OAAQD,CAAAA,MAAM,CAACG,SAAS,CAAC;QAAEH,MAAQI,EAAAA;AAAiD,KAAA,CAAA,EACpFH,OAAQD,CAAAA,MAAM,CAACK,MAAM,CAAC;QAAEC,KAAO,EAAA;KAC/BL,CAAAA,EAAAA,OAAAA,CAAQD,MAAM,CAACO,KAAK,IACpBN,OAAQD,CAAAA,MAAM,CAACQ,IAAI,EAAA,CAAA;AAGvB,IAAA,IAAIC,UAAa,GAAA;AACb,QAAA,IAAIR,OAAQQ,CAAAA,UAAU,CAACC,OAAO,CAAC;YAC3BV,MAAQC,EAAAA,OAAAA,CAAQD,MAAM,CAACE,OAAO,CAC1BD,QAAQD,MAAM,CAACW,QAAQ,EAAA,EACvBV,OAAQD,CAAAA,MAAM,CAACY,MAAM,CAAC,CAAC,EAAET,SAAS,EAAEJ,KAAK,EAAEc,OAAO,EAAE,GAAGC,IAAM,EAAA,GAAA;AACzD,gBAAA,MAAMC,OAAUC,GAAAA,MAAAA,CAAOC,IAAI,CAACH,MAAMI,MAAM,GAAG,CAAC,CAAC,EAAEC,IAAAA,CAAKC,SAAS,CAACN,OAAO,GAAG,EAAA;gBACxE,OAAO,CAAA,EAAGX,UAAU,CAAC,EAAEJ,MAAM,EAAE,EAAEc,UAAUE,OAAS,CAAA,CAAA;AACxD,aAAA,CAAA;AAER,SAAA;AACH,KAAA;AAED,IAAA,IAAIhB,UAAU,MAAQ,EAAA;QAClBC,MAASC,GAAAA,OAAAA,CAAQD,MAAM,CAACE,OAAO,CAC3BD,OAAQD,CAAAA,MAAM,CAACK,MAAM,CAAC;YAAEC,KAAO,EAAA;SAC/BL,CAAAA,EAAAA,OAAAA,CAAQD,MAAM,CAACO,KAAK,EAAA,CAAA;QAGxBE,UAAa,GAAA;AACT,YAAA,IAAIR,OAAQQ,CAAAA,UAAU,CAACC,OAAO,CAAC;gBAC3BV,MAAQC,EAAAA,OAAAA,CAAQD,MAAM,CAACE,OAAO,CAC1BD,OAAQD,CAAAA,MAAM,CAACW,QAAQ,EAAA,EACvBV,QAAQD,MAAM,CAACY,MAAM,CAAC,CAAC,EAAEb,KAAK,EAAEc,OAAO,EAAE,GAAA;AACrC,oBAAA,OAAO,CAAGd,EAAAA,KAAAA,CAAM,EAAE,EAAEc,OAAS,CAAA,CAAA;AACjC,iBAAA,CAAA;AAER,aAAA;AACH,SAAA;AACL;IAEA,OAAOZ,OAAAA,CAAQH,YAAY,CAAC;AACxBC,QAAAA,KAAAA;AACAC,QAAAA,MAAAA;QACAqB,WAAa,EAAA;YAAEC,OAASC,EAAAA;AAAa,SAAA;AACrCd,QAAAA;AACJ,KAAA,CAAA;AACJ,CAAA;AAEA,IAAIe,MAAS1B,GAAAA,YAAAA,EAAAA;AAEN,MAAM2B,cAAc,CAAC1B,KAAAA,GAAAA;AACxByB,IAAAA,MAAAA,GAAS1B,YAAaC,CAAAA,KAAAA,CAAAA;AAC1B;AAEO,MAAM2B,SAAY,GAAA,IAAMF;;;;"}
|
package/dist/main.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import * as Cardigantime from '@theunwalked/cardigantime';
|
|
3
|
+
import 'dotenv/config';
|
|
4
|
+
import { configure } from './arguments.js';
|
|
5
|
+
import { execute } from './commands/commit.js';
|
|
6
|
+
import { execute as execute$1 } from './commands/release.js';
|
|
7
|
+
import { DEFAULT_CONFIG_DIR, COMMAND_COMMIT, COMMAND_RELEASE } from './constants.js';
|
|
8
|
+
import { getLogger, setLogLevel } from './logging.js';
|
|
9
|
+
import { ConfigSchema } from './types.js';
|
|
10
|
+
|
|
11
|
+
async function main() {
|
|
12
|
+
const cardigantime = Cardigantime.create({
|
|
13
|
+
defaults: {
|
|
14
|
+
configDirectory: DEFAULT_CONFIG_DIR
|
|
15
|
+
},
|
|
16
|
+
configShape: ConfigSchema.shape,
|
|
17
|
+
logger: getLogger()
|
|
18
|
+
});
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
20
|
+
const [runConfig, secureConfig, commandConfig] = await configure(cardigantime); // Pass cardigantime instance
|
|
21
|
+
// Set log level based on verbose flag
|
|
22
|
+
if (runConfig.verbose) {
|
|
23
|
+
setLogLevel('verbose');
|
|
24
|
+
}
|
|
25
|
+
if (runConfig.debug) {
|
|
26
|
+
setLogLevel('debug');
|
|
27
|
+
}
|
|
28
|
+
const logger = getLogger();
|
|
29
|
+
try {
|
|
30
|
+
// Get the command from Commander
|
|
31
|
+
const command = process.argv[2];
|
|
32
|
+
let commandName = commandConfig.commandName;
|
|
33
|
+
// If we have a specific command argument, use that
|
|
34
|
+
if (command === 'commit' || command === 'release') {
|
|
35
|
+
commandName = command;
|
|
36
|
+
}
|
|
37
|
+
let summary = '';
|
|
38
|
+
if (commandName === COMMAND_COMMIT) {
|
|
39
|
+
summary = await execute(runConfig);
|
|
40
|
+
} else if (commandName === COMMAND_RELEASE) {
|
|
41
|
+
summary = await execute$1(runConfig);
|
|
42
|
+
}
|
|
43
|
+
// eslint-disable-next-line no-console
|
|
44
|
+
console.log(`\n\n${summary}\n\n`);
|
|
45
|
+
} catch (error) {
|
|
46
|
+
logger.error('Exiting due to Error: %s, %s', error.message, error.stack);
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
main();
|
|
51
|
+
|
|
52
|
+
export { main };
|
|
53
|
+
//# sourceMappingURL=main.js.map
|
package/dist/main.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.js","sources":["../src/main.ts"],"sourcesContent":["#!/usr/bin/env node\nimport * as Cardigantime from '@theunwalked/cardigantime';\nimport 'dotenv/config';\nimport * as Arguments from './arguments';\nimport * as Commit from './commands/commit';\nimport * as Release from './commands/release';\nimport { COMMAND_COMMIT, COMMAND_RELEASE, DEFAULT_CONFIG_DIR } from './constants';\nimport { getLogger, setLogLevel } from './logging';\nimport { CommandConfig } from 'types';\nimport { Config, ConfigSchema, SecureConfig } from './types';\n\nexport async function main() {\n\n const cardigantime = Cardigantime.create<typeof ConfigSchema.shape>({\n defaults: {\n configDirectory: DEFAULT_CONFIG_DIR, // Default directory for config file\n },\n configShape: ConfigSchema.shape, // Pass the Zod shape for validation\n logger: getLogger(), // Optional: Pass logger instance\n });\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const [runConfig, secureConfig, commandConfig]: [Config, SecureConfig, CommandConfig] = await Arguments.configure(cardigantime); // Pass cardigantime instance\n\n // Set log level based on verbose flag\n if (runConfig.verbose) {\n setLogLevel('verbose');\n }\n if (runConfig.debug) {\n setLogLevel('debug');\n }\n\n const logger = getLogger();\n\n try {\n // Get the command from Commander\n const command = process.argv[2];\n let commandName = commandConfig.commandName;\n\n // If we have a specific command argument, use that\n if (command === 'commit' || command === 'release') {\n commandName = command;\n }\n\n let summary: string = '';\n\n if (commandName === COMMAND_COMMIT) {\n summary = await Commit.execute(runConfig);\n } else if (commandName === COMMAND_RELEASE) {\n summary = await Release.execute(runConfig);\n }\n\n // eslint-disable-next-line no-console\n console.log(`\\n\\n${summary}\\n\\n`);\n\n } catch (error: any) {\n logger.error('Exiting due to Error: %s, %s', error.message, error.stack);\n process.exit(1);\n }\n}\n\nmain();"],"names":["main","cardigantime","Cardigantime","create","defaults","configDirectory","DEFAULT_CONFIG_DIR","configShape","ConfigSchema","shape","logger","getLogger","runConfig","secureConfig","commandConfig","Arguments","verbose","setLogLevel","debug","command","process","argv","commandName","summary","COMMAND_COMMIT","Commit","COMMAND_RELEASE","Release","console","log","error","message","stack","exit"],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
Task #1: Create a commit message for the changes that are in the content.
|
|
2
|
+
|
|
3
|
+
Task #2: When creating the commit message, use data in the context to help you relate the changes to information about people, projects, issues, and other entities.
|
|
4
|
+
|
|
5
|
+
This commit message is for someone who knows what the project is and what it does so don't summarize the project.
|
|
6
|
+
|
|
7
|
+
Don't start the commit message with a sentence that refers to the project. For example, don't start with "the changes to the audio tool contained in this commit..." Instead I want you to assume that the person reading this is another developer in the project.
|
|
8
|
+
|
|
9
|
+
Also, use you understanding of the code to try to explain what is happening in the change. Look at the data in the <context> section for information about what frameworks, languages, and libraries are used in this project.
|
|
10
|
+
|
|
11
|
+
### Please Be Concise and Direct
|
|
12
|
+
|
|
13
|
+
The first sentence should be a short summary of the change, and the rest of the commit message should discuss more detailed changes.
|
|
14
|
+
|
|
15
|
+
If the commit contains a large number of changes or changes in different areas, try to list the changes in a way that is easy to understand.
|
|
16
|
+
|
|
17
|
+
If the commit contains a smaller number of changes you can just state what the changes are quickly. Don't write a long message if there are only changes for a single file.
|
|
18
|
+
|
|
19
|
+
Do not end the commit message with something vague like "These changes aim to improve overall efficiency." If a statement isn't directly related to the change, do not include it.
|
|
20
|
+
|
|
21
|
+
### Output Format
|
|
22
|
+
|
|
23
|
+
This commit message should be a single paragraph followed by a list of changes if the change is substantial.
|
|
24
|
+
|
|
25
|
+
Also, don't start with a header in Markdown. The first paragraph or single sentence should just be plain text.
|
|
26
|
+
|
|
27
|
+
#### Example Output: Small change in a single file
|
|
28
|
+
|
|
29
|
+
Example #1: A small change to a single file.
|
|
30
|
+
|
|
31
|
+
"Updated the package.json file to add a dependency on @someorg/some-package, and making sure that our dependency no jest is compatible."
|
|
32
|
+
|
|
33
|
+
Exmaple #2: A larger change to a single file.
|
|
34
|
+
|
|
35
|
+
"Refactored the methods in BlabberService.java to ensure that the code is more straightforward. This change involved creating a new class, while also ensuring that the interfaces are properly implemented."
|
|
36
|
+
|
|
37
|
+
Example #3: A change that affects a small number of files.
|
|
38
|
+
|
|
39
|
+
"Implemented new unit tests for WalkingService.ts, and updated the README.md file to include information about the new tests. This commit also makes sure that the libraries for testing are updated. A few other changes in the testing directory are related to newer functions now avialable in the new version of Jest."
|
|
40
|
+
|
|
41
|
+
Example #4: A large change that affects multiples files and which also includes several different types of changes.
|
|
42
|
+
|
|
43
|
+
"A number of changes have been made, primarily focusing on updating the \`package.json\` to include new dependencies.
|
|
44
|
+
|
|
45
|
+
- Added the dependency \`@riotprompt/riotprompt\` with version \`^0.0.2\` to enhance command-line prompt functionality.
|
|
46
|
+
- Included the \`glob\` module with version \`^11.0.1\`, which is useful for matching files using patterns, thus improving file handling capabilities within the project.
|
|
47
|
+
|
|
48
|
+
This commit is an effort to streamline file operations and introduce improved interactive features for users of the command - line interface.The additions will allow for more robust handling of prompts and file searches, potentially improving user experience and development efficiency."
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
Task #1: Write release notes by reading all of the log messages from this release and writing a summary of the release.
|
|
2
|
+
|
|
3
|
+
Task #2: Provide a detailed list of changes involved in this release, and make sure that the release notes are directly related to the content in the log messages.
|
|
4
|
+
|
|
5
|
+
Task #3: Use the content in the <context> section to help you write the release notes and to help make connections with people, projects, issues, features, and other information.
|
|
6
|
+
|
|
7
|
+
### Output Restrictions
|
|
8
|
+
|
|
9
|
+
- Do not mention and people or contributors in the release notes. For example, do not say, "Thanks to John Doe for this feature." Release notes are to be impersonal and not focused on indiviudals.
|
|
10
|
+
|
|
11
|
+
- Do not use marketing language about how "significant" a release is, or how the release is going to "streamline process" for "Improved usability." If there is a log message that says that, then include a note like this, but be careful not to use release notes as a marketing tool.
|
|
12
|
+
|
|
13
|
+
- If the release is very simple, keep the release notes short and simple. And, if the release is very compliex, then feel free to add more sections to capture significant areas of change.
|
|
14
|
+
|
|
15
|
+
### Output Format
|
|
16
|
+
|
|
17
|
+
## Release: Create a Title for this Release
|
|
18
|
+
|
|
19
|
+
(summarize the release in two paragraphs)
|
|
20
|
+
|
|
21
|
+
## New Features
|
|
22
|
+
|
|
23
|
+
Identify some of the latest changes that have been made
|
|
24
|
+
|
|
25
|
+
## Other Improvements
|
|
26
|
+
|
|
27
|
+
Identify some of the things that are related to the build or some behind-the-scenes changes.
|
|
28
|
+
|
|
29
|
+
### Use the Context
|
|
30
|
+
|
|
31
|
+
Use the context to help you write the release notes and to help make connections with people, projects, issues, features, and other information.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# You
|
|
2
|
+
|
|
3
|
+
## Traits
|
|
4
|
+
|
|
5
|
+
You are a developer who is contributing to a project that is using Git for source control.
|
|
6
|
+
|
|
7
|
+
You are an expert at writing documentation for projects, and you are an expert developer who is familiar with the codebase and all of the languages and frameworks used in the project.
|
|
8
|
+
|
|
9
|
+
## Instructions
|
|
10
|
+
|
|
11
|
+
You are being asked to write documents that capture the details of changes that have been made to a git project.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Formatter, Builder } from '@riotprompt/riotprompt';
|
|
2
|
+
import { DEFAULT_PERSONA_YOU_FILE, DEFAULT_INSTRUCTIONS_RELEASE_FILE, DEFAULT_INSTRUCTIONS_COMMIT_FILE } from '../constants.js';
|
|
3
|
+
import { getLogger } from '../logging.js';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = path.dirname(__filename);
|
|
9
|
+
const create = (model, runConfig)=>{
|
|
10
|
+
const logger = getLogger();
|
|
11
|
+
const createCommitPrompt = async (content)=>{
|
|
12
|
+
let builder = Builder.create({
|
|
13
|
+
logger,
|
|
14
|
+
basePath: __dirname,
|
|
15
|
+
overridePath: runConfig === null || runConfig === void 0 ? void 0 : runConfig.configDirectory,
|
|
16
|
+
overrides: (runConfig === null || runConfig === void 0 ? void 0 : runConfig.overrides) || false
|
|
17
|
+
});
|
|
18
|
+
builder = await builder.addPersonaPath(DEFAULT_PERSONA_YOU_FILE);
|
|
19
|
+
builder = await builder.addInstructionPath(DEFAULT_INSTRUCTIONS_COMMIT_FILE);
|
|
20
|
+
builder = await builder.addContent(content);
|
|
21
|
+
if (runConfig.contextDirectories) {
|
|
22
|
+
builder = await builder.loadContext(runConfig.contextDirectories);
|
|
23
|
+
}
|
|
24
|
+
const prompt = await builder.build();
|
|
25
|
+
return prompt;
|
|
26
|
+
};
|
|
27
|
+
const createReleasePrompt = async (content)=>{
|
|
28
|
+
let builder = Builder.create({
|
|
29
|
+
logger,
|
|
30
|
+
basePath: __dirname,
|
|
31
|
+
overridePath: runConfig === null || runConfig === void 0 ? void 0 : runConfig.configDirectory,
|
|
32
|
+
overrides: (runConfig === null || runConfig === void 0 ? void 0 : runConfig.overrides) || false
|
|
33
|
+
});
|
|
34
|
+
builder = await builder.addPersonaPath(DEFAULT_PERSONA_YOU_FILE);
|
|
35
|
+
builder = await builder.addInstructionPath(DEFAULT_INSTRUCTIONS_RELEASE_FILE);
|
|
36
|
+
builder = await builder.addContent(content);
|
|
37
|
+
if (runConfig.contextDirectories) {
|
|
38
|
+
builder = await builder.loadContext(runConfig.contextDirectories);
|
|
39
|
+
}
|
|
40
|
+
const prompt = await builder.build();
|
|
41
|
+
return prompt;
|
|
42
|
+
};
|
|
43
|
+
const format = (prompt)=>{
|
|
44
|
+
const formatter = Formatter.create();
|
|
45
|
+
return formatter.formatPrompt(model, prompt);
|
|
46
|
+
};
|
|
47
|
+
return {
|
|
48
|
+
createCommitPrompt,
|
|
49
|
+
createReleasePrompt,
|
|
50
|
+
format
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export { create };
|
|
55
|
+
//# sourceMappingURL=prompts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.js","sources":["../../src/prompt/prompts.ts"],"sourcesContent":["import { Builder, Formatter, Model, Prompt, Request } from '@riotprompt/riotprompt';\nimport { DEFAULT_INSTRUCTIONS_COMMIT_FILE, DEFAULT_INSTRUCTIONS_RELEASE_FILE, DEFAULT_PERSONA_YOU_FILE } from '../constants';\nimport { Config as RunConfig } from '../types';\nimport { getLogger } from '../logging';\nimport { fileURLToPath } from 'url';\nimport path from 'path';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nexport interface Factory {\n createCommitPrompt: (content: string) => Promise<Prompt>;\n createReleasePrompt: (content: string) => Promise<Prompt>;\n format: (prompt: Prompt) => Request;\n}\n\nexport const create = (model: Model, runConfig: RunConfig): Factory => {\n\n const logger = getLogger();\n\n const createCommitPrompt = async (content: string): Promise<Prompt> => {\n let builder: Builder.Instance = Builder.create({ logger, basePath: __dirname, overridePath: runConfig?.configDirectory, overrides: runConfig?.overrides || false });\n builder = await builder.addPersonaPath(DEFAULT_PERSONA_YOU_FILE);\n builder = await builder.addInstructionPath(DEFAULT_INSTRUCTIONS_COMMIT_FILE);\n builder = await builder.addContent(content);\n if (runConfig.contextDirectories) {\n builder = await builder.loadContext(runConfig.contextDirectories);\n }\n\n const prompt = await builder.build();\n return prompt;\n };\n\n const createReleasePrompt = async (content: string): Promise<Prompt> => {\n let builder: Builder.Instance = Builder.create({ logger, basePath: __dirname, overridePath: runConfig?.configDirectory, overrides: runConfig?.overrides || false });\n builder = await builder.addPersonaPath(DEFAULT_PERSONA_YOU_FILE);\n builder = await builder.addInstructionPath(DEFAULT_INSTRUCTIONS_RELEASE_FILE);\n builder = await builder.addContent(content);\n if (runConfig.contextDirectories) {\n builder = await builder.loadContext(runConfig.contextDirectories);\n }\n\n const prompt = await builder.build();\n return prompt;\n }\n\n const format = (prompt: Prompt): Request => {\n const formatter = Formatter.create();\n return formatter.formatPrompt(model, prompt);\n };\n\n return {\n createCommitPrompt,\n createReleasePrompt,\n format,\n };\n}\n\n"],"names":["__filename","fileURLToPath","url","__dirname","path","dirname","create","model","runConfig","logger","getLogger","createCommitPrompt","content","builder","Builder","basePath","overridePath","configDirectory","overrides","addPersonaPath","DEFAULT_PERSONA_YOU_FILE","addInstructionPath","DEFAULT_INSTRUCTIONS_COMMIT_FILE","addContent","contextDirectories","loadContext","prompt","build","createReleasePrompt","DEFAULT_INSTRUCTIONS_RELEASE_FILE","format","formatter","Formatter","formatPrompt"],"mappings":";;;;;;AAOA,MAAMA,UAAAA,GAAaC,aAAc,CAAA,MAAA,CAAA,IAAA,CAAYC,GAAG,CAAA;AAChD,MAAMC,SAAAA,GAAYC,IAAKC,CAAAA,OAAO,CAACL,UAAAA,CAAAA;AAQxB,MAAMM,MAAS,GAAA,CAACC,KAAcC,EAAAA,SAAAA,GAAAA;AAEjC,IAAA,MAAMC,MAASC,GAAAA,SAAAA,EAAAA;AAEf,IAAA,MAAMC,qBAAqB,OAAOC,OAAAA,GAAAA;QAC9B,IAAIC,OAAAA,GAA4BC,OAAQR,CAAAA,MAAM,CAAC;AAAEG,YAAAA,MAAAA;YAAQM,QAAUZ,EAAAA,SAAAA;AAAWa,YAAAA,YAAY,EAAER,SAAAA,KAAAA,IAAAA,IAAAA,SAAAA,KAAAA,MAAAA,GAAAA,MAAAA,GAAAA,SAAAA,CAAWS,eAAe;AAAEC,YAAAA,SAAAA,EAAWV,CAAAA,SAAAA,KAAAA,IAAAA,IAAAA,SAAAA,KAAAA,MAAAA,GAAAA,MAAAA,GAAAA,SAAAA,CAAWU,SAAS,KAAI;AAAM,SAAA,CAAA;QACjKL,OAAU,GAAA,MAAMA,OAAQM,CAAAA,cAAc,CAACC,wBAAAA,CAAAA;QACvCP,OAAU,GAAA,MAAMA,OAAQQ,CAAAA,kBAAkB,CAACC,gCAAAA,CAAAA;QAC3CT,OAAU,GAAA,MAAMA,OAAQU,CAAAA,UAAU,CAACX,OAAAA,CAAAA;QACnC,IAAIJ,SAAAA,CAAUgB,kBAAkB,EAAE;AAC9BX,YAAAA,OAAAA,GAAU,MAAMA,OAAAA,CAAQY,WAAW,CAACjB,UAAUgB,kBAAkB,CAAA;AACpE;QAEA,MAAME,MAAAA,GAAS,MAAMb,OAAAA,CAAQc,KAAK,EAAA;QAClC,OAAOD,MAAAA;AACX,KAAA;AAEA,IAAA,MAAME,sBAAsB,OAAOhB,OAAAA,GAAAA;QAC/B,IAAIC,OAAAA,GAA4BC,OAAQR,CAAAA,MAAM,CAAC;AAAEG,YAAAA,MAAAA;YAAQM,QAAUZ,EAAAA,SAAAA;AAAWa,YAAAA,YAAY,EAAER,SAAAA,KAAAA,IAAAA,IAAAA,SAAAA,KAAAA,MAAAA,GAAAA,MAAAA,GAAAA,SAAAA,CAAWS,eAAe;AAAEC,YAAAA,SAAAA,EAAWV,CAAAA,SAAAA,KAAAA,IAAAA,IAAAA,SAAAA,KAAAA,MAAAA,GAAAA,MAAAA,GAAAA,SAAAA,CAAWU,SAAS,KAAI;AAAM,SAAA,CAAA;QACjKL,OAAU,GAAA,MAAMA,OAAQM,CAAAA,cAAc,CAACC,wBAAAA,CAAAA;QACvCP,OAAU,GAAA,MAAMA,OAAQQ,CAAAA,kBAAkB,CAACQ,iCAAAA,CAAAA;QAC3ChB,OAAU,GAAA,MAAMA,OAAQU,CAAAA,UAAU,CAACX,OAAAA,CAAAA;QACnC,IAAIJ,SAAAA,CAAUgB,kBAAkB,EAAE;AAC9BX,YAAAA,OAAAA,GAAU,MAAMA,OAAAA,CAAQY,WAAW,CAACjB,UAAUgB,kBAAkB,CAAA;AACpE;QAEA,MAAME,MAAAA,GAAS,MAAMb,OAAAA,CAAQc,KAAK,EAAA;QAClC,OAAOD,MAAAA;AACX,KAAA;AAEA,IAAA,MAAMI,SAAS,CAACJ,MAAAA,GAAAA;QACZ,MAAMK,SAAAA,GAAYC,UAAU1B,MAAM,EAAA;QAClC,OAAOyB,SAAAA,CAAUE,YAAY,CAAC1B,KAAOmB,EAAAA,MAAAA,CAAAA;AACzC,KAAA;IAEA,OAAO;AACHf,QAAAA,kBAAAA;AACAiB,QAAAA,mBAAAA;AACAE,QAAAA;AACJ,KAAA;AACJ;;;;"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
const ConfigSchema = z.object({
|
|
4
|
+
dryRun: z.boolean().optional(),
|
|
5
|
+
verbose: z.boolean().optional(),
|
|
6
|
+
debug: z.boolean().optional(),
|
|
7
|
+
overrides: z.boolean().optional(),
|
|
8
|
+
instructions: z.string().optional(),
|
|
9
|
+
model: z.string().optional(),
|
|
10
|
+
contextDirectories: z.array(z.string()).optional(),
|
|
11
|
+
commit: z.object({
|
|
12
|
+
cached: z.boolean().optional(),
|
|
13
|
+
sendit: z.boolean().optional()
|
|
14
|
+
}).optional(),
|
|
15
|
+
release: z.object({
|
|
16
|
+
from: z.string().optional(),
|
|
17
|
+
to: z.string().optional()
|
|
18
|
+
}).optional(),
|
|
19
|
+
excludedPatterns: z.array(z.string()).optional()
|
|
20
|
+
});
|
|
21
|
+
z.object({
|
|
22
|
+
openaiApiKey: z.string().optional()
|
|
23
|
+
});
|
|
24
|
+
z.object({
|
|
25
|
+
commandName: z.string().optional()
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
export { ConfigSchema };
|
|
29
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +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 commit: z.object({\n cached: z.boolean().optional(),\n sendit: z.boolean().optional(),\n }).optional(),\n release: z.object({\n from: z.string().optional(),\n to: z.string().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"],"names":["ConfigSchema","z","object","dryRun","boolean","optional","verbose","debug","overrides","instructions","string","model","contextDirectories","array","commit","cached","sendit","release","from","to","excludedPatterns","openaiApiKey","commandName"],"mappings":";;AAGaA,MAAAA,YAAAA,GAAeC,CAAEC,CAAAA,MAAM,CAAC;IACjCC,MAAQF,EAAAA,CAAAA,CAAEG,OAAO,EAAA,CAAGC,QAAQ,EAAA;IAC5BC,OAASL,EAAAA,CAAAA,CAAEG,OAAO,EAAA,CAAGC,QAAQ,EAAA;IAC7BE,KAAON,EAAAA,CAAAA,CAAEG,OAAO,EAAA,CAAGC,QAAQ,EAAA;IAC3BG,SAAWP,EAAAA,CAAAA,CAAEG,OAAO,EAAA,CAAGC,QAAQ,EAAA;IAC/BI,YAAcR,EAAAA,CAAAA,CAAES,MAAM,EAAA,CAAGL,QAAQ,EAAA;IACjCM,KAAOV,EAAAA,CAAAA,CAAES,MAAM,EAAA,CAAGL,QAAQ,EAAA;AAC1BO,IAAAA,kBAAAA,EAAoBX,EAAEY,KAAK,CAACZ,CAAES,CAAAA,MAAM,IAAIL,QAAQ,EAAA;IAChDS,MAAQb,EAAAA,CAAAA,CAAEC,MAAM,CAAC;QACba,MAAQd,EAAAA,CAAAA,CAAEG,OAAO,EAAA,CAAGC,QAAQ,EAAA;QAC5BW,MAAQf,EAAAA,CAAAA,CAAEG,OAAO,EAAA,CAAGC,QAAQ;AAChC,KAAA,CAAA,CAAGA,QAAQ,EAAA;IACXY,OAAShB,EAAAA,CAAAA,CAAEC,MAAM,CAAC;QACdgB,IAAMjB,EAAAA,CAAAA,CAAES,MAAM,EAAA,CAAGL,QAAQ,EAAA;QACzBc,EAAIlB,EAAAA,CAAAA,CAAES,MAAM,EAAA,CAAGL,QAAQ;AAC3B,KAAA,CAAA,CAAGA,QAAQ,EAAA;AACXe,IAAAA,gBAAAA,EAAkBnB,EAAEY,KAAK,CAACZ,CAAES,CAAAA,MAAM,IAAIL,QAAQ;AAClD,CAAG;AAE+BJ,CAAEC,CAAAA,MAAM,CAAC;IACvCmB,YAAcpB,EAAAA,CAAAA,CAAES,MAAM,EAAA,CAAGL,QAAQ;AACrC,CAAG;AAEgCJ,CAAEC,CAAAA,MAAM,CAAC;IACxCoB,WAAarB,EAAAA,CAAAA,CAAES,MAAM,EAAA,CAAGL,QAAQ;AACpC,CAAG;;;;"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { exec } from 'child_process';
|
|
3
|
+
import util from 'util';
|
|
4
|
+
|
|
5
|
+
async function run(command, options = {}) {
|
|
6
|
+
const execPromise = util.promisify(exec);
|
|
7
|
+
return execPromise(command, options);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export { run };
|
|
11
|
+
//# sourceMappingURL=child.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"child.js","sources":["../../src/util/child.ts"],"sourcesContent":["#!/usr/bin/env node\nimport child_process, { exec } from 'child_process';\nimport util from 'util';\n\nexport async function run(command: string, options: child_process.ExecOptions = {}): Promise<{ stdout: string; stderr: string }> {\n const execPromise = util.promisify(exec);\n return execPromise(command, options);\n}"],"names":["run","command","options","execPromise","util","promisify","exec"],"mappings":";;;;AAIO,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAeA,GAAIC,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAe,EAAEC,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAqC,EAAE,CAAA,CAAA,CAAA;CAC9E,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAMC,WAAAA,CAAcC,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAKC,CAAAA,CAAS,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAACC,IAAAA,CAAAA,CAAAA;AACnC,CAAA,CAAA,CAAA,CAAA,OAAOH,YAAYF,CAASC,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,OAAAA,CAAAA,CAAAA;AAChC,CAAA;;"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { OpenAI } from 'openai';
|
|
2
|
+
import { create } from './storage.js';
|
|
3
|
+
import { getLogger } from '../logging.js';
|
|
4
|
+
|
|
5
|
+
class OpenAIError extends Error {
|
|
6
|
+
constructor(message){
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = 'OpenAIError';
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
async function createCompletion(messages, options = {
|
|
12
|
+
model: "gpt-4o-mini"
|
|
13
|
+
}) {
|
|
14
|
+
const logger = getLogger();
|
|
15
|
+
const storage = create({
|
|
16
|
+
log: logger.debug
|
|
17
|
+
});
|
|
18
|
+
try {
|
|
19
|
+
var _completion_choices__message_content, _completion_choices__message, _completion_choices_;
|
|
20
|
+
const apiKey = process.env.OPENAI_API_KEY;
|
|
21
|
+
if (!apiKey) {
|
|
22
|
+
throw new OpenAIError('OPENAI_API_KEY environment variable is not set');
|
|
23
|
+
}
|
|
24
|
+
const openai = new OpenAI({
|
|
25
|
+
apiKey: apiKey
|
|
26
|
+
});
|
|
27
|
+
logger.debug('Sending prompt to OpenAI: %j', messages);
|
|
28
|
+
const completion = await openai.chat.completions.create({
|
|
29
|
+
model: options.model || "gpt-4o-mini",
|
|
30
|
+
messages,
|
|
31
|
+
max_completion_tokens: 10000,
|
|
32
|
+
response_format: options.responseFormat
|
|
33
|
+
});
|
|
34
|
+
if (options.debug && options.debugFile) {
|
|
35
|
+
await storage.writeFile(options.debugFile, JSON.stringify(completion, null, 2), 'utf8');
|
|
36
|
+
logger.debug('Wrote debug file to %s', options.debugFile);
|
|
37
|
+
}
|
|
38
|
+
const response = (_completion_choices_ = completion.choices[0]) === null || _completion_choices_ === void 0 ? void 0 : (_completion_choices__message = _completion_choices_.message) === null || _completion_choices__message === void 0 ? void 0 : (_completion_choices__message_content = _completion_choices__message.content) === null || _completion_choices__message_content === void 0 ? void 0 : _completion_choices__message_content.trim();
|
|
39
|
+
if (!response) {
|
|
40
|
+
throw new OpenAIError('No response received from OpenAI');
|
|
41
|
+
}
|
|
42
|
+
logger.debug('Received response from OpenAI: %s...', response.substring(0, 30));
|
|
43
|
+
if (options.responseFormat) {
|
|
44
|
+
return JSON.parse(response);
|
|
45
|
+
} else {
|
|
46
|
+
return response;
|
|
47
|
+
}
|
|
48
|
+
} catch (error) {
|
|
49
|
+
logger.error('Error calling OpenAI API: %s %s', error.message, error.stack);
|
|
50
|
+
throw new OpenAIError(`Failed to create completion: ${error.message}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export { OpenAIError, createCompletion };
|
|
55
|
+
//# sourceMappingURL=openai.js.map
|
|
@@ -0,0 +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 } = { 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 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 if (options.debug && options.debugFile) {\n await storage.writeFile(options.debugFile, JSON.stringify(completion, null, 2), 'utf8');\n logger.debug('Wrote debug file to %s', options.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 } = { 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 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 if (options.debug && options.debugFile) {\n await storage.writeFile(options.debugFile, JSON.stringify(transcription, null, 2), 'utf8');\n logger.debug('Wrote debug file to %s', options.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","constructor","message","name","createCompletion","messages","options","model","logger","getLogger","storage","Storage","log","debug","completion","apiKey","process","env","OPENAI_API_KEY","openai","OpenAI","chat","completions","create","max_completion_tokens","response_format","responseFormat","debugFile","writeFile","JSON","stringify","response","choices","content","trim","substring","parse","error","stack"],"mappings":";;;;AAQO,MAAMA,WAAoBC,SAAAA,KAAAA,CAAAA;AAC7BC,IAAAA,WAAAA,CAAYC,OAAe,CAAE;AACzB,QAAA,KAAK,CAACA,OAAAA,CAAAA;QACN,IAAI,CAACC,IAAI,GAAG,aAAA;AAChB;AACJ;AAEO,eAAeC,gBAAAA,CAAiBC,QAAsC,EAAEC,OAAyF,GAAA;IAAEC,KAAO,EAAA;AAAc,CAAC,EAAA;AAC5L,IAAA,MAAMC,MAASC,GAAAA,SAAAA,EAAAA;IACf,MAAMC,OAAAA,GAAUC,MAAc,CAAC;AAAEC,QAAAA,GAAAA,EAAKJ,OAAOK;AAAM,KAAA,CAAA;IACnD,IAAI;AAwBiBC,QAAAA,IAAAA,oCAAAA,EAAAA,4BAAAA,EAAAA,oBAAAA;AAvBjB,QAAA,MAAMC,MAASC,GAAAA,OAAAA,CAAQC,GAAG,CAACC,cAAc;AACzC,QAAA,IAAI,CAACH,MAAQ,EAAA;AACT,YAAA,MAAM,IAAIhB,WAAY,CAAA,gDAAA,CAAA;AAC1B;QAEA,MAAMoB,MAAAA,GAAS,IAAIC,MAAO,CAAA;YACtBL,MAAQA,EAAAA;AACZ,SAAA,CAAA;QAEAP,MAAOK,CAAAA,KAAK,CAAC,8BAAgCR,EAAAA,QAAAA,CAAAA;QAE7C,MAAMS,UAAAA,GAAa,MAAMK,MAAOE,CAAAA,IAAI,CAACC,WAAW,CAACC,MAAM,CAAC;YACpDhB,KAAOD,EAAAA,OAAAA,CAAQC,KAAK,IAAI,aAAA;AACxBF,YAAAA,QAAAA;YACAmB,qBAAuB,EAAA,KAAA;AACvBC,YAAAA,eAAAA,EAAiBnB,QAAQoB;AAC7B,SAAA,CAAA;AAEA,QAAA,IAAIpB,OAAQO,CAAAA,KAAK,IAAIP,OAAAA,CAAQqB,SAAS,EAAE;YACpC,MAAMjB,OAAAA,CAAQkB,SAAS,CAACtB,OAAQqB,CAAAA,SAAS,EAAEE,IAAAA,CAAKC,SAAS,CAAChB,UAAY,EAAA,IAAA,EAAM,CAAI,CAAA,EAAA,MAAA,CAAA;AAChFN,YAAAA,MAAAA,CAAOK,KAAK,CAAC,wBAA0BP,EAAAA,OAAAA,CAAQqB,SAAS,CAAA;AAC5D;AAEA,QAAA,MAAMI,YAAWjB,oBAAAA,GAAAA,UAAAA,CAAWkB,OAAO,CAAC,CAAA,CAAE,cAArBlB,oBAAAA,KAAAA,KAAAA,CAAAA,GAAAA,KAAAA,CAAAA,GAAAA,CAAAA,4BAAAA,GAAAA,qBAAuBZ,OAAO,MAAA,IAAA,IAA9BY,oDAAAA,oCAAAA,GAAAA,4BAAAA,CAAgCmB,OAAO,MAAvCnB,IAAAA,IAAAA,oCAAAA,KAAAA,KAAAA,CAAAA,GAAAA,KAAAA,CAAAA,GAAAA,qCAAyCoB,IAAI,EAAA;AAC9D,QAAA,IAAI,CAACH,QAAU,EAAA;AACX,YAAA,MAAM,IAAIhC,WAAY,CAAA,kCAAA,CAAA;AAC1B;AAEAS,QAAAA,MAAAA,CAAOK,KAAK,CAAC,sCAAA,EAAwCkB,QAASI,CAAAA,SAAS,CAAC,CAAG,EAAA,EAAA,CAAA,CAAA;QAC3E,IAAI7B,OAAAA,CAAQoB,cAAc,EAAE;YACxB,OAAOG,IAAAA,CAAKO,KAAK,CAACL,QAAAA,CAAAA;SACf,MAAA;YACH,OAAOA,QAAAA;AACX;AAEJ,KAAA,CAAE,OAAOM,KAAY,EAAA;AACjB7B,QAAAA,MAAAA,CAAO6B,KAAK,CAAC,iCAAA,EAAmCA,MAAMnC,OAAO,EAAEmC,MAAMC,KAAK,CAAA;AAC1E,QAAA,MAAM,IAAIvC,WAAY,CAAA,CAAC,6BAA6B,EAAEsC,KAAAA,CAAMnC,OAAO,CAAE,CAAA,CAAA;AACzE;AACJ;;;;"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import { glob } from 'glob';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import crypto from 'crypto';
|
|
5
|
+
|
|
6
|
+
// eslint-disable-next-line no-restricted-imports
|
|
7
|
+
const create = (params)=>{
|
|
8
|
+
// eslint-disable-next-line no-console
|
|
9
|
+
const log = params.log || console.log;
|
|
10
|
+
const exists = async (path)=>{
|
|
11
|
+
try {
|
|
12
|
+
await fs.promises.stat(path);
|
|
13
|
+
return true;
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
15
|
+
} catch (error) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
const isDirectory = async (path)=>{
|
|
20
|
+
const stats = await fs.promises.stat(path);
|
|
21
|
+
if (!stats.isDirectory()) {
|
|
22
|
+
log(`${path} is not a directory`);
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
return true;
|
|
26
|
+
};
|
|
27
|
+
const isFile = async (path)=>{
|
|
28
|
+
const stats = await fs.promises.stat(path);
|
|
29
|
+
if (!stats.isFile()) {
|
|
30
|
+
log(`${path} is not a file`);
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
return true;
|
|
34
|
+
};
|
|
35
|
+
const isReadable = async (path)=>{
|
|
36
|
+
try {
|
|
37
|
+
await fs.promises.access(path, fs.constants.R_OK);
|
|
38
|
+
} catch (error) {
|
|
39
|
+
log(`${path} is not readable: %s %s`, error.message, error.stack);
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
return true;
|
|
43
|
+
};
|
|
44
|
+
const isWritable = async (path)=>{
|
|
45
|
+
try {
|
|
46
|
+
await fs.promises.access(path, fs.constants.W_OK);
|
|
47
|
+
} catch (error) {
|
|
48
|
+
log(`${path} is not writable: %s %s`, error.message, error.stack);
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
return true;
|
|
52
|
+
};
|
|
53
|
+
const isFileReadable = async (path)=>{
|
|
54
|
+
return await exists(path) && await isFile(path) && await isReadable(path);
|
|
55
|
+
};
|
|
56
|
+
const isDirectoryWritable = async (path)=>{
|
|
57
|
+
return await exists(path) && await isDirectory(path) && await isWritable(path);
|
|
58
|
+
};
|
|
59
|
+
const isDirectoryReadable = async (path)=>{
|
|
60
|
+
return await exists(path) && await isDirectory(path) && await isReadable(path);
|
|
61
|
+
};
|
|
62
|
+
const createDirectory = async (path)=>{
|
|
63
|
+
try {
|
|
64
|
+
await fs.promises.mkdir(path, {
|
|
65
|
+
recursive: true
|
|
66
|
+
});
|
|
67
|
+
} catch (mkdirError) {
|
|
68
|
+
throw new Error(`Failed to create output directory ${path}: ${mkdirError.message} ${mkdirError.stack}`);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
const readFile = async (path, encoding)=>{
|
|
72
|
+
return await fs.promises.readFile(path, {
|
|
73
|
+
encoding: encoding
|
|
74
|
+
});
|
|
75
|
+
};
|
|
76
|
+
const writeFile = async (path, data, encoding)=>{
|
|
77
|
+
await fs.promises.writeFile(path, data, {
|
|
78
|
+
encoding: encoding
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
const forEachFileIn = async (directory, callback, options = {
|
|
82
|
+
pattern: '*.*'
|
|
83
|
+
})=>{
|
|
84
|
+
try {
|
|
85
|
+
const files = await glob(options.pattern, {
|
|
86
|
+
cwd: directory,
|
|
87
|
+
nodir: true
|
|
88
|
+
});
|
|
89
|
+
for (const file of files){
|
|
90
|
+
await callback(path.join(directory, file));
|
|
91
|
+
}
|
|
92
|
+
} catch (err) {
|
|
93
|
+
throw new Error(`Failed to glob pattern ${options.pattern} in ${directory}: ${err.message}`);
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
const readStream = async (path)=>{
|
|
97
|
+
return fs.createReadStream(path);
|
|
98
|
+
};
|
|
99
|
+
const hashFile = async (path, length)=>{
|
|
100
|
+
const file = await readFile(path, 'utf8');
|
|
101
|
+
return crypto.createHash('sha256').update(file).digest('hex').slice(0, length);
|
|
102
|
+
};
|
|
103
|
+
const listFiles = async (directory)=>{
|
|
104
|
+
return await fs.promises.readdir(directory);
|
|
105
|
+
};
|
|
106
|
+
return {
|
|
107
|
+
exists,
|
|
108
|
+
isDirectory,
|
|
109
|
+
isFile,
|
|
110
|
+
isReadable,
|
|
111
|
+
isWritable,
|
|
112
|
+
isFileReadable,
|
|
113
|
+
isDirectoryWritable,
|
|
114
|
+
isDirectoryReadable,
|
|
115
|
+
createDirectory,
|
|
116
|
+
readFile,
|
|
117
|
+
readStream,
|
|
118
|
+
writeFile,
|
|
119
|
+
forEachFileIn,
|
|
120
|
+
hashFile,
|
|
121
|
+
listFiles
|
|
122
|
+
};
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
export { create };
|
|
126
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sources":["../../src/util/storage.ts"],"sourcesContent":["// eslint-disable-next-line no-restricted-imports\nimport * as fs from 'fs';\nimport { glob } from 'glob';\nimport path from 'path';\nimport crypto from 'crypto';\n/**\n * This module exists to isolate filesystem operations from the rest of the codebase.\n * This makes testing easier by avoiding direct fs mocking in jest configuration.\n * \n * Additionally, abstracting storage operations allows for future flexibility - \n * this export utility may need to work with storage systems other than the local filesystem\n * (e.g. S3, Google Cloud Storage, etc).\n */\n\nexport interface Utility {\n exists: (path: string) => Promise<boolean>;\n isDirectory: (path: string) => Promise<boolean>;\n isFile: (path: string) => Promise<boolean>;\n isReadable: (path: string) => Promise<boolean>;\n isWritable: (path: string) => Promise<boolean>;\n isFileReadable: (path: string) => Promise<boolean>;\n isDirectoryWritable: (path: string) => Promise<boolean>;\n isDirectoryReadable: (path: string) => Promise<boolean>;\n createDirectory: (path: string) => Promise<void>;\n readFile: (path: string, encoding: string) => Promise<string>;\n readStream: (path: string) => Promise<fs.ReadStream>;\n writeFile: (path: string, data: string | Buffer, encoding: string) => Promise<void>;\n forEachFileIn: (directory: string, callback: (path: string) => Promise<void>, options?: { pattern: string }) => Promise<void>;\n hashFile: (path: string, length: number) => Promise<string>;\n listFiles: (directory: string) => Promise<string[]>;\n}\n\nexport const create = (params: { log?: (message: string, ...args: any[]) => void }): Utility => {\n\n // eslint-disable-next-line no-console\n const log = params.log || console.log;\n\n const exists = async (path: string): Promise<boolean> => {\n try {\n await fs.promises.stat(path);\n return true;\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (error: any) {\n return false;\n }\n }\n\n const isDirectory = async (path: string): Promise<boolean> => {\n const stats = await fs.promises.stat(path);\n if (!stats.isDirectory()) {\n log(`${path} is not a directory`);\n return false;\n }\n return true;\n }\n\n const isFile = async (path: string): Promise<boolean> => {\n const stats = await fs.promises.stat(path);\n if (!stats.isFile()) {\n log(`${path} is not a file`);\n return false;\n }\n return true;\n }\n\n const isReadable = async (path: string): Promise<boolean> => {\n try {\n await fs.promises.access(path, fs.constants.R_OK);\n } catch (error: any) {\n log(`${path} is not readable: %s %s`, error.message, error.stack);\n return false;\n }\n return true;\n }\n\n const isWritable = async (path: string): Promise<boolean> => {\n try {\n await fs.promises.access(path, fs.constants.W_OK);\n } catch (error: any) {\n log(`${path} is not writable: %s %s`, error.message, error.stack);\n return false;\n }\n return true;\n }\n\n const isFileReadable = async (path: string): Promise<boolean> => {\n return await exists(path) && await isFile(path) && await isReadable(path);\n }\n\n const isDirectoryWritable = async (path: string): Promise<boolean> => {\n return await exists(path) && await isDirectory(path) && await isWritable(path);\n }\n\n const isDirectoryReadable = async (path: string): Promise<boolean> => {\n return await exists(path) && await isDirectory(path) && await isReadable(path);\n }\n\n const createDirectory = async (path: string): Promise<void> => {\n try {\n await fs.promises.mkdir(path, { recursive: true });\n } catch (mkdirError: any) {\n throw new Error(`Failed to create output directory ${path}: ${mkdirError.message} ${mkdirError.stack}`);\n }\n }\n\n const readFile = async (path: string, encoding: string): Promise<string> => {\n return await fs.promises.readFile(path, { encoding: encoding as BufferEncoding });\n }\n\n const writeFile = async (path: string, data: string | Buffer, encoding: string): Promise<void> => {\n await fs.promises.writeFile(path, data, { encoding: encoding as BufferEncoding });\n }\n\n const forEachFileIn = async (directory: string, callback: (file: string) => Promise<void>, options: { pattern: string | string[] } = { pattern: '*.*' }): Promise<void> => {\n try {\n const files = await glob(options.pattern, { cwd: directory, nodir: true });\n for (const file of files) {\n await callback(path.join(directory, file));\n }\n } catch (err: any) {\n throw new Error(`Failed to glob pattern ${options.pattern} in ${directory}: ${err.message}`);\n }\n }\n\n const readStream = async (path: string): Promise<fs.ReadStream> => {\n return fs.createReadStream(path);\n }\n\n const hashFile = async (path: string, length: number): Promise<string> => {\n const file = await readFile(path, 'utf8');\n return crypto.createHash('sha256').update(file).digest('hex').slice(0, length);\n }\n\n const listFiles = async (directory: string): Promise<string[]> => {\n return await fs.promises.readdir(directory);\n }\n\n return {\n exists,\n isDirectory,\n isFile,\n isReadable,\n isWritable,\n isFileReadable,\n isDirectoryWritable,\n isDirectoryReadable,\n createDirectory,\n readFile,\n readStream,\n writeFile,\n forEachFileIn,\n hashFile,\n listFiles,\n };\n}"],"names":["create","params","log","console","exists","path","fs","promises","stat","error","isDirectory","stats","isFile","isReadable","access","constants","R_OK","message","stack","isWritable","W_OK","isFileReadable","isDirectoryWritable","isDirectoryReadable","createDirectory","mkdir","recursive","mkdirError","Error","readFile","encoding","writeFile","data","forEachFileIn","directory","callback","options","pattern","files","glob","cwd","nodir","file","join","err","readStream","createReadStream","hashFile","length","crypto","createHash","update","digest","slice","listFiles","readdir"],"mappings":"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"}
|