Skip to content

Commit

Permalink
feat: 🎨 add linter doc and enhance parser logging (#890)
Browse files Browse the repository at this point in the history
  • Loading branch information
pelikhan authored Nov 22, 2024
1 parent 0124c5b commit d3c016c
Show file tree
Hide file tree
Showing 9 changed files with 109 additions and 8 deletions.
Binary file added docs/src/assets/lint-copilot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/src/assets/lint-copilot.png.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Screenshot of a TypeScript file in a code editor showing a class named "Greeter" with a constructor and a method. The editor highlights four problems: missing semicolons on lines 5 and 9, an empty function on line 18, and a suggestion to add a type annotation on line 20. The right panel displays these issues with red and yellow icons.
2 changes: 1 addition & 1 deletion docs/src/content/docs/samples/gcm.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Git Commit Message
description: Generate a commit message for all staged changes
sidebar:
order: 0
order: 10
---

import { Code } from "@astrojs/starlight/components"
Expand Down
2 changes: 1 addition & 1 deletion docs/src/content/docs/samples/iat.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Image Alt Textify
description: Generate alt text for images in markdown files
sidebar:
order: 1
order: 5
---

import { Code } from "@astrojs/starlight/components"
Expand Down
97 changes: 97 additions & 0 deletions docs/src/content/docs/samples/lint.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
---
title: "Lint"
description: "An Easy Universal Linter"
keywords: ["genai", "linter", "script", "coding", "best practices"]
sidebar:
order: 2
---
import { Image } from "astro:assets"
import { Code } from "astro/components"
import src from "../../../assets/lint-copilot.png"
import alt from "../../../assets/lint-copilot.png.txt?raw"
import code from "../../../../../packages/sample/genaisrc/lint.genai.mjs?raw"

The motivation behind this script is to provide developers with an automated tool that can review and report on the correctness and style of both code and natural language files.
It leverages the power of LLM to inspect code or documents in new ways.

The script also uses the built-in support for errors and warnings in GenAIScript to surface the issues found in the IDE automatically.

<Image src={src} alt={alt} loading="lazy" />


### Script Breakdown

Below is a step-by-step explanation of the script:

```ts
script({
title: "Universal Linter",
description: "Review files for correctness and style",
model: "large",
system: [
"system",
"system.assistant",
"system.annotations",
"system.safety_jailbreak",
"system.safety_harmful_content",
],
})
```

- **`script({...})`**: This function initializes a GenAI script.
- **`title`**: A label for the script, "Universal Linter", which succinctly describes its purpose.
- **`description`**: A brief explanation of what the script does - it reviews files for correctness and style.
- **`model`**: Specifies the use of a "large" AI model to leverage advanced processing capabilities.
- **`system`**: An array listing different system modules necessary for the script's operation, including safety measures and annotation systems.

The script also contains a prompt block:

```ts wrap
$`## Task
You are Linty, an linter for all known programming languages and natural languages.
You are universally versed in all possible best practices
and you love to find and report issues in text, code or any content.
Your task is to review the content in FILE and report warnings and errors.
## Rules
- for each file in FILE, use best practices based on the file extension to review the content. For example, for a ".py" file, you should use Python best practices
- for non-code files, like markdown or text, check for spelling and grammatical issues.
- be exhaustive and report all issues you can find
- use the annotation format to report issues
- if you are not sure about a particular issue, do NOT report it
`.role("system")
```

- **`$``Task`**: Begins a prompt section where the AI's task is defined.
- **`You are Linty...`**: Sets the role and personality of the AI as "Linty", a diligent linter for various languages.
- **`Your task...`**: Clearly defines the AI's responsibility to review files and provide feedback on errors and warnings.
- **`Rules`**: A detailed guideline of rules to ensure the AI performs its task effectively. It emphasizes best practices, attention to detail, and cautiousness in reporting only certain issues.

Finally, the script specifies files to be processed:

```ts
def("FILE", env.files, { lineNumbers: true })
```

- **`def("FILE", env.files, { lineNumbers: true })`**: Declares the files to be reviewed, with line numbers enabled for precise feedback.

### Running the Script

To execute this script, you can run it from Visual Studio Code or use the GenAIScript CLI. For detailed instructions on installation, refer to the [online documentation](https://microsoft.github.io/genaiscript/getting-started).

```bash
npx --yes genaiscript run lint
```

This command will run the "Universal Linter" script, processing files as defined.

By following the steps outlined above, you can leverage the power of GenAI to automate the linting process for your projects, ensuring high standards in your code and document files. Happy linting! 🎉

## Full Source

The full source code is available at [https://github.com/microsoft/genaiscript/blob/main/packages/sample/genaisrc/lint.genai.mts](https://github.com/microsoft/genaiscript/blob/main/packages/sample/genaisrc/lint.genai.mts).

<Code code={code} wrap={true} lang="ts" title="lint.genai.mts" />
7 changes: 5 additions & 2 deletions packages/core/src/parser.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Importing utility functions and constants from other files
import { strcmp } from "./util" // String comparison function
import { logVerbose, strcmp } from "./util" // String comparison function
import { Project, PromptScript } from "./ast" // Class imports
import { defaultPrompts } from "./default_prompts" // Default prompt data
import { parsePromptScript } from "./template" // Function to parse scripts
Expand Down Expand Up @@ -93,7 +93,10 @@ export async function parseProject(options: { scriptFiles: string[] }) {
// Process each script file, parsing its content and updating the project
for (const f of scriptFiles) {
const tmpl = await parsePromptScript(f, await readText(f), prj)
if (!tmpl) continue // Skip if no template is parsed
if (!tmpl) {
logVerbose(`skipping invalid script file: ${f}`)
continue
} // Skip if no template is parsed
delete deflPr[tmpl.id] // Remove the parsed template from defaults
prj.templates.push(tmpl) // Add to project templates
}
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ class Checker<T extends PromptLike> {

if (!this.keyFound) this.verror(`unhandled key: ${this.key}`)

if (numdiag == this.diagnostics.length) obj[key] = this.val
if (numdiag === this.diagnostics.length) obj[key] = this.val
}

return obj
Expand Down
2 changes: 1 addition & 1 deletion packages/vscode/src/chatparticipant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export async function activateChatParticipant(state: ExtensionState) {

const { project } = state
const templates = project.templates
.filter((s) => !s.system && !s.unlisted)
.filter((s) => !s.isSystem && !s.unlisted)
.sort((a, b) => a.id.localeCompare(b.id))

const mdHelp = () =>
Expand Down
4 changes: 2 additions & 2 deletions packages/vscode/src/prompttree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class PromptTreeDataProvider
item.id = `genaiscript.promptCategory.${element}`
return item
} else {
const { id, title, description = "" } = element
const { id, filename, title, description = "" } = element
const ai = this.state.aiRequest
const { computing, options, progress } = ai || {}
const { template } = options || {}
Expand All @@ -33,7 +33,7 @@ class PromptTreeDataProvider
title,
vscode.TreeItemCollapsibleState.None
)
item.id = `genaiscript.prompts.${id}`
item.id = `genaiscript.prompts.${filename || id}`
item.contextValue = element.filename ? `prompt` : `prompt.builtin`
item.description = generating
? `${progress?.tokensSoFar || 0} tokens`
Expand Down

0 comments on commit d3c016c

Please sign in to comment.