Merge branch 'dev' into feat/dialog-esc-click

This commit is contained in:
Akshar Patel
2026-01-31 00:56:18 -05:00
committed by GitHub
12 changed files with 50 additions and 32 deletions

View File

@@ -1,21 +1,15 @@
name: beta
on:
push:
branches: [dev]
pull_request:
types: [opened, synchronize, labeled, unlabeled]
workflow_dispatch:
schedule:
- cron: "0 * * * *"
jobs:
sync:
if: |
github.event_name == 'push' ||
(github.event_name == 'pull_request' &&
contains(github.event.pull_request.labels.*.name, 'contributor'))
runs-on: blacksmith-4vcpu-ubuntu-2404
permissions:
contents: write
pull-requests: write
steps:
- name: Checkout repository
uses: actions/checkout@v4

View File

@@ -1,6 +1,9 @@
name: test
on:
push:
branches:
- dev
pull_request:
workflow_dispatch:
jobs:

View File

@@ -345,8 +345,9 @@ export function Autocomplete(props: {
const results: AutocompleteOption[] = [...command.slashes()]
for (const serverCommand of sync.data.command) {
const label = serverCommand.source === "mcp" ? ":mcp" : serverCommand.source === "skill" ? ":skill" : ""
results.push({
display: "/" + serverCommand.name + (serverCommand.mcp ? " (MCP)" : ""),
display: "/" + serverCommand.name + label,
description: serverCommand.description,
onSelect: () => {
const newText = "/" + serverCommand.name + " "

View File

@@ -6,6 +6,7 @@ import { Identifier } from "../id/id"
import PROMPT_INITIALIZE from "./template/initialize.txt"
import PROMPT_REVIEW from "./template/review.txt"
import { MCP } from "../mcp"
import { Skill } from "../skill"
export namespace Command {
export const Event = {
@@ -26,7 +27,7 @@ export namespace Command {
description: z.string().optional(),
agent: z.string().optional(),
model: z.string().optional(),
mcp: z.boolean().optional(),
source: z.enum(["command", "mcp", "skill"]).optional(),
// workaround for zod not supporting async functions natively so we use getters
// https://zod.dev/v4/changelog?id=zfunction
template: z.promise(z.string()).or(z.string()),
@@ -94,7 +95,7 @@ export namespace Command {
for (const [name, prompt] of Object.entries(await MCP.prompts())) {
result[name] = {
name,
mcp: true,
source: "mcp",
description: prompt.description,
get template() {
// since a getter can't be async we need to manually return a promise here
@@ -118,6 +119,21 @@ export namespace Command {
}
}
// Add skills as invokable commands
for (const skill of await Skill.all()) {
// Skip if a command with this name already exists
if (result[skill.name]) continue
result[skill.name] = {
name: skill.name,
description: skill.description,
source: "skill",
get template() {
return skill.content
},
hints: [],
}
}
return result
})

View File

@@ -2,7 +2,9 @@ import { Instance } from "../project/instance"
export namespace Env {
const state = Instance.state(() => {
return process.env as Record<string, string | undefined>
// Create a shallow copy to isolate environment per instance
// Prevents parallel tests from interfering with each other's env vars
return { ...process.env } as Record<string, string | undefined>
})
export function get(key: string) {

View File

@@ -214,8 +214,8 @@ export namespace Ripgrep {
input.signal?.throwIfAborted()
const args = [await filepath(), "--files", "--glob=!.git/*"]
if (input.follow !== false) args.push("--follow")
if (input.hidden !== false) args.push("--hidden")
if (input.follow) args.push("--follow")
if (input.hidden) args.push("--hidden")
if (input.maxDepth !== undefined) args.push(`--max-depth=${input.maxDepth}`)
if (input.glob) {
for (const g of input.glob) {
@@ -381,7 +381,7 @@ export namespace Ripgrep {
follow?: boolean
}) {
const args = [`${await filepath()}`, "--json", "--hidden", "--glob='!.git/*'"]
if (input.follow !== false) args.push("--follow")
if (input.follow) args.push("--follow")
if (input.glob) {
for (const g of input.glob) {

View File

@@ -83,7 +83,11 @@ export namespace ProviderTransform {
return msg
})
}
if (model.providerID === "mistral" || model.api.id.toLowerCase().includes("mistral")) {
if (
model.providerID === "mistral" ||
model.api.id.toLowerCase().includes("mistral") ||
model.api.id.toLocaleLowerCase().includes("devstral")
) {
const result: ModelMessage[] = []
for (let i = 0; i < msgs.length; i++) {
const msg = msgs[i]

View File

@@ -18,6 +18,7 @@ export namespace Skill {
name: z.string(),
description: z.string(),
location: z.string(),
content: z.string(),
})
export type Info = z.infer<typeof Info>
@@ -74,6 +75,7 @@ export namespace Skill {
name: parsed.data.name,
description: parsed.data.description,
location: match,
content: md.content,
}
}

View File

@@ -37,15 +37,7 @@ export const GrepTool = Tool.define("grep", {
await assertExternalDirectory(ctx, searchPath, { kind: "directory" })
const rgPath = await Ripgrep.filepath()
const args = [
"-nH",
"--hidden",
"--follow",
"--no-messages",
"--field-match-separator=|",
"--regexp",
params.pattern,
]
const args = ["-nH", "--hidden", "--no-messages", "--field-match-separator=|", "--regexp", params.pattern]
if (params.include) {
args.push("--glob", params.include)
}

View File

@@ -2,7 +2,6 @@ import path from "path"
import z from "zod"
import { Tool } from "./tool"
import { Skill } from "../skill"
import { ConfigMarkdown } from "../config/markdown"
import { PermissionNext } from "../permission/next"
export const SkillTool = Tool.define("skill", async (ctx) => {
@@ -62,7 +61,7 @@ export const SkillTool = Tool.define("skill", async (ctx) => {
always: [params.name],
metadata: {},
})
const content = (await ConfigMarkdown.parse(skill.location)).content
const content = skill.content
const dir = path.dirname(skill.location)
// Format output similar to plugin pattern

View File

@@ -2116,7 +2116,7 @@ export type Command = {
description?: string
agent?: string
model?: string
mcp?: boolean
source?: "command" | "mcp" | "skill"
template: string
subtask?: boolean
hints: Array<string>
@@ -4913,6 +4913,7 @@ export type AppSkillsResponses = {
name: string
description: string
location: string
content: string
}>
}

View File

@@ -5723,9 +5723,12 @@
},
"location": {
"type": "string"
},
"content": {
"type": "string"
}
},
"required": ["name", "description", "location"]
"required": ["name", "description", "location", "content"]
}
}
}
@@ -10770,8 +10773,9 @@
"model": {
"type": "string"
},
"mcp": {
"type": "boolean"
"source": {
"type": "string",
"enum": ["command", "mcp", "skill"]
},
"template": {
"anyOf": [