Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Commentor #723

Merged
merged 11 commits into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"demux",
"devcontainers",
"dockerode",
"docstrings",
"doptions",
"Entra",
"Evals",
Expand Down
4 changes: 4 additions & 0 deletions docs/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ export default defineConfig({
label: "Case Studies",
autogenerate: { directory: "case-studies" },
},
{
label: "Samples",
autogenerate: { directory: "samples" },
},
{
label: "Guides",
autogenerate: { directory: "guides" },
Expand Down
6 changes: 3 additions & 3 deletions docs/genaisrc/genaiscript.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ See [configuration](/genaiscript/getting-started/configuration).

## Files

`run` takes one or more [glob](https://en.wikipedia.org/wiki/Glob_(programming)) patterns to match files in the workspace.
`run` takes one or more [glob](<https://en.wikipedia.org/wiki/Glob_(programming)>) patterns to match files in the workspace.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incorrect link format, angle brackets should not be used in markdown links.

generated by pr-docs-review-commit link_format


```bash sh
npx genaiscript run <script> "**/*.md" "**/*.ts"
Expand Down Expand Up @@ -150,7 +150,7 @@ permissions:
pull-requests: write
```

- set the `GITHUB_TOKEN` secret in the `env` when running the cli
- set the `GITHUB_TOKEN` secret in the `env` when running the cli

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incorrect indentation, there should be no leading spaces before the bullet point.

generated by pr-docs-review-commit indentation


```yaml
- run: npx --yes genaiscript run ... -prc --out-trace $GITHUB_STEP_SUMMARY
Expand Down
2 changes: 1 addition & 1 deletion docs/src/content/docs/reference/scripts/system.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ index N in the above snippets, and then be prefixed with exactly the same whites
the original snippets above. See also the following examples of the expected response format.

CHANGELOG:
\`\`\`
\`\`\`changelog

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incorrect code fence; 'changelog' language specifier should be removed.

generated by pr-docs-review-commit incorrect_code_fence

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changelog format has been changed from a generic code block to a specific 'changelog' code block, which may not be recognized by the rendering engine or may alter the intended presentation.

generated by pr-docs-review-commit invalid_changelog_format

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing language specifier for the code fence, it should specify the language for syntax highlighting.

generated by pr-docs-review-commit code_fence_lang

ChangeLog:1@<file>
Description: <summary>.
OriginalCode@4-6:
Expand Down
79 changes: 79 additions & 0 deletions docs/src/content/docs/samples/cmt.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
---
title: Commenter
description: Adds comments to your code
sidebar:
order: 20
---

import { Code } from "@astrojs/starlight/components"
import source from "../../../../../packages/vscode/genaisrc/cmt.genai.mts?raw"

Inspired by [a tweet](https://x.com/mckaywrigley/status/1838321570969981308), this script automates adding comments to source code.

```ts title="cmt.genai.mts"
script({
title: "Source Code Comment Generator",
description: `Add comments to source code to make it more understandable for AI systems or human developers.
Modified from https://x.com/mckaywrigley/status/1838321570969981308.
`,
})
```

### Getting Files to Process

The user can select which files to comment or, if nothing is selected, we'll use Git to find all modified files.

```ts
let files = env.files
if (files.length === 0) {
files = await Promise.all(
(await host.exec("git status --porcelain")).stdout
.split("\n")
.filter((filename) => /^ [M|U]/.test(filename))
.map(
async (filename) =>
await workspace.readText(filename.replace(/^ [M|U] /, ""))
)
)
}
```

### Processing Each File

We process each file separately, to avoid exploding the token context and keep the AI focused.
We can use [inline prompts](/genaiscript/reference/scripts/inline-prompts) to make inner queries.

```ts
for (const file of files) {
console.log(`processing ${file.filename}`)
... add comments
... save changes
}
```

### The Prompt for Adding Comments

Within the `addComments` function, we prompt GenAI to add comments. We do this twice to increase the likelihood of generating useful comments.

```ts
const res = await runPrompt(
(ctx) => {
ctx.$`You can add comments to this code...`
},
{ system: ["system", "system.files"] }
)
```

We provide a detailed set of instructions to the AI for how to analyze and comment on the code.

## How to Run the Script

To run this script, you'll first need to install the GenAIScript CLI. [Follow the installation guide here](https://microsoft.github.io/genaiscript/getting-started/installation).

```shell
genaiscript run cmt
```

## Full source ([GitHub](https://github.com/microsoft/genaiscript/blob/main/packages/vscode/genaisrc/cmt.genai.mts))

<Code code={source} wrap={true} lang="ts" title="cmt.genai.mts" />
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
---
title: Git Commit Message
description: Generate a commit message for all staged changes
sidebar:
order: 0
---

import { Code } from "@astrojs/starlight/components"
import source from "../../../../../../../packages/vscode/genaisrc/gcm.genai.mts?raw"
import source from "../../../../../packages/vscode/genaisrc/gcm.genai.mts?raw"

The `gcm` script provides a guided flow to create commit with generated messages.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
---
title: Image Alt Textify
description: Generate alt text for images in markdown files
sidebar:
order: 1
---

import { Code } from "@astrojs/starlight/components"
import source from "../../../../../../../packages/vscode/genaisrc/iat.genai.mts?raw"
import source from "../../../../../packages/vscode/genaisrc/iat.genai.mts?raw"

Have you ever stumbled upon a beautiful image in a Markdown file and wondered what it depicts?
Or perhaps you're aiming to make your content more accessible by providing descriptive alt text for all the visuals? πŸ–ΌοΈβœ¨
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
title: "Pull Request Descriptor"
description: "Generate a pull request description from the git diff"
keywords: ["GenAI", "pull request", "software development", "git"]
sidebar:
order: 3
---

import { Code } from "@astrojs/starlight/components"
import source from "../../../../../../../packages/vscode/genaisrc/prd.genai.mts?raw"
import source from "../../../../../packages/vscode/genaisrc/prd.genai.mts?raw"

Pull requests are an integral part of collaborative software development. They allow developers to review code changes before merging them into the main codebase. Creating informative and concise pull request descriptions can be a time-consuming task, especially when dealing with large or complex changes. This is where GenAI comes in, streamlining the process with a smart script that generates pull request descriptions automatically. πŸš€

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
---
title: Reviewer
description: Review the current files or changes
sidebar:
order: 5
---

import { Code } from "@astrojs/starlight/components"
import source from "../../../../../../../packages/vscode/genaisrc/rv.genai.mts?raw"
import source from "../../../../../packages/vscode/genaisrc/rv.genai.mts?raw"

Let's delve into the "Reviewer" script, which automates the code review process, making it a breeze for developers.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
---
title: Search and transform
description: Search for a pattern in files and apply a LLM transformation the match
sidebar:
order: 25
---

import { Code } from "@astrojs/starlight/components"
import source from "../../../../../../../packages/vscode/genaisrc/st.genai.mts?raw"
import source from "../../../../../packages/vscode/genaisrc/st.genai.mts?raw"

Search And Replace is a powerful tool in the developer toolbelt that can save you time and effort...
if you can forumlate the right regular expression.
Expand Down
6 changes: 3 additions & 3 deletions genaisrc/genaiscript.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions packages/auto/genaiscript.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 22 additions & 7 deletions packages/core/src/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,40 +5,48 @@ import { CHANGE } from "./constants"
import { TraceOptions } from "./trace"
import { CORE_VERSION } from "./version"

// Represents a cache entry with a hashed identifier, key, and value
export type CacheEntry<K, V> = { sha: string; key: K; val: V }

// A cache class that manages entries stored in JSONL format
export class JSONLineCache<K, V> extends EventTarget {
private _entries: Record<string, CacheEntry<K, V>>
// Constructor is private to enforce the use of byName factory method
private constructor(public readonly name: string) {
super()
}

// Factory method to create or retrieve an existing cache by name
static byName<K, V>(name: string): JSONLineCache<K, V> {
name = name.replace(/[^a-z0-9_]/gi, "_")
name = name.replace(/[^a-z0-9_]/gi, "_") // Sanitize name to valid identifier
const key = "cacheKV." + name
if (host.userState[key]) return host.userState[key]
if (host.userState[key]) return host.userState[key] // Return if already exists
const r = new JSONLineCache<K, V>(name)
host.userState[key] = r
return r
}

// Get the folder path for the cache storage
private folder() {
return dotGenaiscriptPath("cache", this.name)
}
// Get the full path to the cache file
private path() {
return host.resolvePath(this.folder(), "db.jsonl")
}
// Initialize the cache by loading entries from the file
private async initialize() {
if (this._entries) return
this._entries = {}
await host.createDirectory(this.folder())
const objs: CacheEntry<K, V>[] = await readJSONL(this.path())
let numdup = 0
for (const obj of objs) {
if (this._entries[obj.sha]) numdup++
if (this._entries[obj.sha]) numdup++ // Count duplicates
this._entries[obj.sha] = obj
}
if (2 * numdup > objs.length) {
// Rewrite file if too many duplicates; preserves entry order
// if too many duplicates, rewrite the file
// keep the order of entries
await writeJSONL(
Expand All @@ -48,43 +56,50 @@ export class JSONLineCache<K, V> extends EventTarget {
}
}

// Retrieve all keys from the cache
async keys(): Promise<K[]> {
await this.initialize()
return Object.values(this._entries).map((kv) => kv.key)
}
// Retrieve all entries from the cache
async entries(): Promise<CacheEntry<K, V>[]> {
await this.initialize()
return Object.values(this._entries).map((e) => ({ ...e }))
}
// Retrieve a specific entry by its SHA identifier
async getEntryBySha(sha: string) {
await this.initialize()
return this._entries[sha]
}
// Get the value associated with a specific key
async get(key: K): Promise<V> {
if (key === undefined) return undefined
await this.initialize()
const sha = await keySHA(key)
return this._entries[sha]?.val
}
// Set a key-value pair in the cache, triggering change event
async set(key: K, val: V, options?: TraceOptions) {
const { trace } = options || {}
await this.initialize()
const sha = await keySHA(key)
const ent = { sha, key, val }
const ex = this._entries[sha]
if (ex && JSON.stringify(ex) == JSON.stringify(ent)) return
if (ex && JSON.stringify(ex) == JSON.stringify(ent)) return // No change
this._entries[sha] = ent
await appendJSONL(this.path(), [ent])
await appendJSONL(this.path(), [ent]) // Append new entry to file
trace?.item(`cache ${this.name} set`)
this.dispatchEvent(new Event(CHANGE))
this.dispatchEvent(new Event(CHANGE)) // Notify listeners of change
}
// Compute SHA for a given key
async getKeySHA(key: K) {
await this.initialize()
const sha = await keySHA(key)
return sha
}
}
// Compute the SHA256 hash of a key for uniqueness
async function keySHA(key: any) {
if (typeof key != "string") key = JSON.stringify(key) + CORE_VERSION
if (typeof key != "string") key = JSON.stringify(key) + CORE_VERSION // Normalize key
return await sha256string(key)
}
Loading
Loading