-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore(claude): generate release notes
- Loading branch information
1 parent
97e0658
commit 78eafe1
Showing
54 changed files
with
48,631 additions
and
356 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,4 +10,6 @@ node_modules | |
/api | ||
/core | ||
/errors | ||
/serialization | ||
/serialization | ||
.claude_cache | ||
.env |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
const claudeApiKey = ""; | ||
|
||
import * as fs from "fs"; | ||
import * as path from "path"; | ||
import { sendPromptToClaude } from "./claude-ai"; | ||
|
||
let totalCount = 0; | ||
|
||
async function processFile( | ||
filePath: string, | ||
extension: string, | ||
callback: (fileContent: string) => Promise<string>, | ||
apiKey: string | ||
) { | ||
if (path.extname(filePath).toLowerCase() === extension) { | ||
const fileContent = fs.readFileSync(filePath, "utf-8"); | ||
const prompt = await callback(fileContent); | ||
const resultFilePath = `${filePath}.result.md`; | ||
|
||
if (!fs.existsSync(resultFilePath)) { | ||
console.log(`Processing ${filePath}...`); | ||
try { | ||
totalCount++; | ||
if (totalCount > 4) { | ||
console.log("SKIP " + filePath); | ||
return; | ||
} | ||
const claudeResponse = await sendPromptToClaude( | ||
`You are an AI assistant responsible for writing release notes. You'll be given a git diff of a TypeScript Node API, from that write detailed release notes that summarize the changes made in the diff, especially noting any external interface changes in detail. Use backticks to represent code blocks or property names in the output text. Each section of the release notes should have a level-4 header (####). Only write release notes that are relevant to a consumer of the package. Do not reference anything internal-only, do not reference file names. If there are no changes to a section, omit that section from the output. If there are general changes, include them at the start of the output. Relate the changes to the relevant section of the FlatfileClient API, if appropriate, as follows: | ||
Accounts | ||
Agents | ||
Apps | ||
Assistant | ||
Auth | ||
Cells | ||
Commits | ||
DataRetentionPolicies | ||
Documents | ||
Entitlements | ||
Environments | ||
Events | ||
Files | ||
Foreigndb | ||
Guests | ||
Jobs | ||
Mapping | ||
Records | ||
Roles | ||
Secrets | ||
Sheets | ||
Snapshots | ||
Spaces | ||
Users | ||
Versions | ||
Views | ||
Workbooks`, | ||
[{ role: "user", content: prompt }], | ||
apiKey | ||
); | ||
fs.writeFileSync(resultFilePath, claudeResponse); | ||
console.log(`Processed ${filePath} and saved the result to ${resultFilePath}`); | ||
} catch (error) { | ||
console.error(`Error processing ${filePath}: ${error}`); | ||
} | ||
} else { | ||
console.log(`Result file ${resultFilePath} already exists, skipping...`); | ||
} | ||
} | ||
} | ||
|
||
async function processDirectory( | ||
dirPath: string, | ||
extension: string, | ||
callback: (fileContent: string) => Promise<string>, | ||
apiKey: string | ||
) { | ||
const files = fs.readdirSync(dirPath); | ||
const promises: Promise<void>[] = []; | ||
|
||
for (const file of files) { | ||
const filePath = path.join(dirPath, file); | ||
const stats = fs.statSync(filePath); | ||
|
||
if (stats.isDirectory()) { | ||
promises.push(processDirectory(filePath, extension, callback, apiKey)); | ||
} else { | ||
promises.push(processFile(filePath, extension, callback, apiKey)); | ||
} | ||
} | ||
|
||
await Promise.all(promises); | ||
} | ||
|
||
// Usage example | ||
const directoryPath = "./release-notes"; | ||
const fileExtension = ".txt"; | ||
|
||
const promptCallback = async (fileContent: string): Promise<string> => { | ||
// Generate the prompt based on the file content | ||
// This is just an example, you can modify it as needed | ||
return `Generate a summary of changes for the following text diff: ${fileContent}`; | ||
}; | ||
|
||
processDirectory(directoryPath, fileExtension, promptCallback, claudeApiKey).catch((error) => | ||
console.error("Error:", error) | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
import { createHash } from "crypto"; | ||
import fs from "fs/promises"; | ||
import { join } from "path"; | ||
|
||
const CLAUDE_API_URL = "https://api.anthropic.com/v1/messages"; | ||
|
||
async function makeClaudeRequest(system: string, messages: ClaudeMessage[], apiKey: string) { | ||
const headers = { | ||
"Anthropic-Version": "2023-06-01", | ||
"Content-Type": "application/json", | ||
"X-API-Key": apiKey, | ||
}; | ||
|
||
const body = JSON.stringify({ | ||
max_tokens: 4096, | ||
// https://docs.anthropic.com/claude/docs/models-overview | ||
// model: 'claude-3-opus-20240229', | ||
model: "claude-3-sonnet-20240229", | ||
// model: 'claude-3-haiku-20240307' | ||
messages, | ||
system, | ||
}); | ||
|
||
try { | ||
const response = await fetch(CLAUDE_API_URL, { | ||
method: "POST", | ||
headers, | ||
body, | ||
}); | ||
|
||
if (!response.ok) { | ||
console.error(await response.text()); | ||
throw new Error(`HTTP error! status: ${response.status}`); | ||
} | ||
|
||
const data = await response.json(); | ||
|
||
let content = data.content?.[0]?.text; | ||
|
||
if (!content || typeof content !== "string") { | ||
throw new Error("No content found in the API response"); | ||
} | ||
|
||
return content; | ||
} catch (error) { | ||
console.error("Error calling Claude API:", error); | ||
throw error; | ||
} | ||
} | ||
|
||
export interface ClaudeMessage { | ||
role: "assistant" | "user"; | ||
content: string; | ||
} | ||
|
||
export async function sendPromptToClaude( | ||
system: string, | ||
messages: ClaudeMessage[], | ||
apiKey: string, | ||
useCache: boolean = true | ||
): Promise<string> { | ||
const cacheHash = createHash("sha256"); | ||
cacheHash.update(JSON.stringify({ system, messages })); | ||
const cacheKey = cacheHash.digest("hex"); | ||
const cacheDirectory = join(process.cwd(), ".claude_cache"); | ||
await fs.mkdir(cacheDirectory, { recursive: true }); | ||
const cacheFile = join(cacheDirectory, `${cacheKey}.cache.txt`); | ||
if (useCache) { | ||
try { | ||
const cacheStat = await fs.stat(cacheFile); | ||
if (cacheStat.size > 0) { | ||
return JSON.parse( | ||
await fs.readFile(cacheFile, { | ||
encoding: "utf-8", | ||
}) | ||
); | ||
} | ||
} catch (e) { | ||
// assume cache doesn't exist | ||
} | ||
} | ||
const result = await sendPrompt(system, messages, apiKey); | ||
await fs.writeFile(cacheFile, JSON.stringify(result), { | ||
encoding: "utf-8", | ||
}); | ||
return result; | ||
} | ||
|
||
async function sendPrompt(system: string, messages: ClaudeMessage[], apiKey: string): Promise<string> { | ||
let content = await makeClaudeRequest(system, messages, apiKey); | ||
|
||
if (!content || typeof content !== "string") { | ||
throw new Error("No content found in the API response"); | ||
} | ||
|
||
return content; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import fs from "node:fs"; | ||
|
||
const versions = [ | ||
"1.6.3", | ||
"1.6.4", | ||
"1.6.5", | ||
"1.6.6", | ||
"1.6.7", | ||
"1.7.0", | ||
"1.7.1", | ||
"1.7.10", | ||
"1.7.11", | ||
"1.7.2", | ||
"1.7.3", | ||
"1.7.4", | ||
"1.7.5", | ||
"1.7.6", | ||
"1.7.7", | ||
"1.7.8", | ||
"1.8.0", | ||
"1.8.2", | ||
"1.8.3", | ||
"1.8.4", | ||
"1.8.5", | ||
"1.8.6", | ||
"1.8.9", | ||
]; | ||
|
||
let script: string[] = []; | ||
let compareVersion = "1.6.2"; | ||
|
||
for (const version of versions) { | ||
script.push( | ||
`( git diff --no-color -U1 ${compareVersion}..${version} ':!yarn.lock' ) | grep -v '"X-' > release-notes/${version}.diff.txt` | ||
); | ||
compareVersion = version; | ||
} | ||
|
||
fs.writeFileSync("gen-diffs.sh", script.join("\n")); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
( git diff --no-color -U1 1.6.2..1.6.3 ':!yarn.lock' ) | grep -v '"X-' > release-notes/1.6.3.diff.txt | ||
( git diff --no-color -U1 1.6.3..1.6.4 ':!yarn.lock' ) | grep -v '"X-' > release-notes/1.6.4.diff.txt | ||
( git diff --no-color -U1 1.6.4..1.6.5 ':!yarn.lock' ) | grep -v '"X-' > release-notes/1.6.5.diff.txt | ||
( git diff --no-color -U1 1.6.5..1.6.6 ':!yarn.lock' ) | grep -v '"X-' > release-notes/1.6.6.diff.txt | ||
( git diff --no-color -U1 1.6.6..1.6.7 ':!yarn.lock' ) | grep -v '"X-' > release-notes/1.6.7.diff.txt | ||
( git diff --no-color -U1 1.6.7..1.7.0 ':!yarn.lock' ) | grep -v '"X-' > release-notes/1.7.0.diff.txt | ||
( git diff --no-color -U1 1.7.0..1.7.1 ':!yarn.lock' ) | grep -v '"X-' > release-notes/1.7.1.diff.txt | ||
( git diff --no-color -U1 1.7.1..1.7.10 ':!yarn.lock' ) | grep -v '"X-' > release-notes/1.7.10.diff.txt | ||
( git diff --no-color -U1 1.7.10..1.7.11 ':!yarn.lock' ) | grep -v '"X-' > release-notes/1.7.11.diff.txt | ||
( git diff --no-color -U1 1.7.11..1.7.2 ':!yarn.lock' ) | grep -v '"X-' > release-notes/1.7.2.diff.txt | ||
( git diff --no-color -U1 1.7.2..1.7.3 ':!yarn.lock' ) | grep -v '"X-' > release-notes/1.7.3.diff.txt | ||
( git diff --no-color -U1 1.7.3..1.7.4 ':!yarn.lock' ) | grep -v '"X-' > release-notes/1.7.4.diff.txt | ||
( git diff --no-color -U1 1.7.4..1.7.5 ':!yarn.lock' ) | grep -v '"X-' > release-notes/1.7.5.diff.txt | ||
( git diff --no-color -U1 1.7.5..1.7.6 ':!yarn.lock' ) | grep -v '"X-' > release-notes/1.7.6.diff.txt | ||
( git diff --no-color -U1 1.7.6..1.7.7 ':!yarn.lock' ) | grep -v '"X-' > release-notes/1.7.7.diff.txt | ||
( git diff --no-color -U1 1.7.7..1.7.8 ':!yarn.lock' ) | grep -v '"X-' > release-notes/1.7.8.diff.txt | ||
( git diff --no-color -U1 1.7.8..1.8.0 ':!yarn.lock' ) | grep -v '"X-' > release-notes/1.8.0.diff.txt | ||
( git diff --no-color -U1 1.8.0..1.8.2 ':!yarn.lock' ) | grep -v '"X-' > release-notes/1.8.2.diff.txt | ||
( git diff --no-color -U1 1.8.2..1.8.3 ':!yarn.lock' ) | grep -v '"X-' > release-notes/1.8.3.diff.txt | ||
( git diff --no-color -U1 1.8.3..1.8.4 ':!yarn.lock' ) | grep -v '"X-' > release-notes/1.8.4.diff.txt | ||
( git diff --no-color -U1 1.8.4..1.8.5 ':!yarn.lock' ) | grep -v '"X-' > release-notes/1.8.5.diff.txt | ||
( git diff --no-color -U1 1.8.5..1.8.6 ':!yarn.lock' ) | grep -v '"X-' > release-notes/1.8.6.diff.txt | ||
( git diff --no-color -U1 1.8.6..1.8.9 ':!yarn.lock' ) | grep -v '"X-' > release-notes/1.8.9.diff.txt |
Oops, something went wrong.