Skip to content
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
22 changes: 21 additions & 1 deletion .oxlintrc.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
{
"$schema": "https://raw.githubusercontent.com/nicolo-ribaudo/oxc-project.github.io/refs/heads/json-schema/src/public/.oxlintrc.schema.json",
"categories": {
"suspicious": "warn"
},
"rules": {
// Effect uses `function*` with Effect.gen/Effect.fnUntraced that don't always yield
"require-yield": "off",
Expand All @@ -10,7 +13,24 @@
// Intentional control char matching (ANSI escapes, null byte sanitization)
"no-control-regex": "off",
// SST and plugin tools require triple-slash references
"triple-slash-reference": "off"
"triple-slash-reference": "off",

// Suspicious category: suppress noisy rules
// Effect's nested function* closures inherently shadow outer scope
"no-shadow": "off",
// Namespace-heavy codebase makes this too noisy
"unicorn/consistent-function-scoping": "off",
// Opinionated — .sort()/.reverse() mutation is fine in this codebase
"unicorn/no-array-sort": "off",
"unicorn/no-array-reverse": "off",
// Not relevant — this isn't a DOM event handler codebase
"unicorn/prefer-add-event-listener": "off",
// Bundler handles module resolution
"unicorn/require-module-specifiers": "off",
// postMessage target origin not relevant for this codebase
"unicorn/require-post-message-target-origin": "off",
// Side-effectful constructors are intentional in some places
"no-new": "off"
},
"ignorePatterns": ["**/node_modules", "**/dist", "**/.build", "**/.sst", "**/*.d.ts"]
}
4 changes: 2 additions & 2 deletions github/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,7 @@ async function subscribeSessionEvents() {
? JSON.stringify(part.state.input)
: "Unknown"
console.log()
console.log(color + `|`, "\x1b[0m\x1b[2m" + ` ${tool.padEnd(7, " ")}`, "", "\x1b[0m" + title)
console.log(`${color}|`, `\x1b[0m\x1b[2m ${tool.padEnd(7, " ")}`, "", `\x1b[0m${title}`)
}

if (part.type === "text") {
Expand Down Expand Up @@ -776,7 +776,7 @@ async function assertPermissions() {
console.log(` permission: ${permission}`)
} catch (error) {
console.error(`Failed to check permissions: ${error}`)
throw new Error(`Failed to check permissions for user ${actor}: ${error}`)
throw new Error(`Failed to check permissions for user ${actor}: ${error}`, { cause: error })
}

if (!["admin", "write"].includes(permission)) throw new Error(`User ${actor} does not have write permissions`)
Expand Down
1 change: 1 addition & 0 deletions packages/app/src/context/global-sdk.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ export const { use: useGlobalSDK, provider: GlobalSDKProvider } = createSimpleCo
if (started) return run
started = true
run = (async () => {
// oxlint-disable-next-line no-unmodified-loop-condition -- `started` is set to false by stop() which also aborts; both flags are checked to allow graceful exit
while (!abort.signal.aborted && started) {
attempt = new AbortController()
lastEventAt = Date.now()
Expand Down
2 changes: 2 additions & 0 deletions packages/app/src/utils/runtime-adapters.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ describe("runtime adapters", () => {
})

test("resolves speech recognition constructor with webkit precedence", () => {
// oxlint-disable-next-line no-extraneous-class
class SpeechCtor {}
// oxlint-disable-next-line no-extraneous-class
class WebkitCtor {}
const ctor = getSpeechRecognitionCtor({
SpeechRecognition: SpeechCtor,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export function ReloadSection() {
}
const info = billingInfo()!
setStore("show", true)
setStore("reload", info.reload ? true : true)
setStore("reload", true)
setStore("reloadAmount", info.reloadAmount.toString())
setStore("reloadTrigger", info.reloadTrigger.toString())
}
Expand Down
2 changes: 1 addition & 1 deletion packages/desktop-electron/src/main/apps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export function wslPath(path: string, mode: "windows" | "linux" | null): string
const output = execFileSync("wsl", ["-e", "wslpath", flag, path])
return output.toString().trim()
} catch (error) {
throw new Error(`Failed to run wslpath: ${String(error)}`)
throw new Error(`Failed to run wslpath: ${String(error)}`, { cause: error })
}
}

Expand Down
1 change: 1 addition & 0 deletions packages/function/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ type Env = {
}

export class SyncServer extends DurableObject<Env> {
// oxlint-disable-next-line no-useless-constructor
constructor(ctx: DurableObjectState, env: Env) {
super(ctx, env)
}
Expand Down
2 changes: 1 addition & 1 deletion packages/opencode/script/postinstall.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ function findBinary() {

return { binaryPath, binaryName }
} catch (error) {
throw new Error(`Could not find package ${packageName}: ${error.message}`)
throw new Error(`Could not find package ${packageName}: ${error.message}`, { cause: error })
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/opencode/src/bus/bus-event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export namespace BusEvent {
properties: def.properties,
})
.meta({
ref: "Event" + "." + def.type,
ref: `Event.${def.type}`,
})
})
.toArray()
Expand Down
1 change: 1 addition & 0 deletions packages/opencode/src/cli/cmd/debug/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ function parseToolParams(input?: string) {
} catch (evalError) {
throw new Error(
`Failed to parse --params. Use JSON or a JS object literal. JSON error: ${jsonError}. Eval error: ${evalError}.`,
{ cause: evalError },
)
}
}
Expand Down
3 changes: 2 additions & 1 deletion packages/opencode/src/cli/cmd/github.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1031,6 +1031,7 @@ export const GithubRunCommand = cmd({
console.error("Failed to get OIDC token:", error instanceof Error ? error.message : error)
throw new Error(
"Could not fetch an OIDC token. Make sure to add `id-token: write` to your workflow permissions.",
{ cause: error },
)
}
}
Expand Down Expand Up @@ -1221,7 +1222,7 @@ export const GithubRunCommand = cmd({
console.log(` permission: ${permission}`)
} catch (error) {
console.error(`Failed to check permissions: ${error}`)
throw new Error(`Failed to check permissions for user ${actor}: ${error}`)
throw new Error(`Failed to check permissions for user ${actor}: ${error}`, { cause: error })
}

if (!["admin", "write"].includes(permission)) throw new Error(`User ${actor} does not have write permissions`)
Expand Down
2 changes: 1 addition & 1 deletion packages/opencode/src/cli/cmd/web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export const WebCommand = cmd({
describe: "start opencode server and open web interface",
handler: async (args) => {
if (!Flag.OPENCODE_SERVER_PASSWORD) {
UI.println(UI.Style.TEXT_WARNING_BOLD + "! " + "OPENCODE_SERVER_PASSWORD is not set; server is unsecured.")
UI.println(UI.Style.TEXT_WARNING_BOLD + "! OPENCODE_SERVER_PASSWORD is not set; server is unsecured.")
}
const opts = await resolveNetworkOptions(args)
const server = await Server.listen(opts)
Expand Down
2 changes: 1 addition & 1 deletion packages/opencode/src/patch/patch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ export function deriveNewContentsFromChunks(filePath: string, chunks: UpdateFile
try {
originalContent = readFileSync(filePath, "utf-8")
} catch (error) {
throw new Error(`Failed to read file ${filePath}: ${error}`)
throw new Error(`Failed to read file ${filePath}: ${error}`, { cause: error })
}

let originalLines = originalContent.split("\n")
Expand Down
2 changes: 1 addition & 1 deletion packages/opencode/src/server/instance/tui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ export const TuiRoutes = lazy(() =>
properties: def.properties,
})
.meta({
ref: "Event" + "." + def.type,
ref: `Event.${def.type}`,
})
}),
),
Expand Down
3 changes: 1 addition & 2 deletions packages/opencode/src/session/prompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,8 +260,7 @@ export namespace SessionPrompt {
messageID: userMessage.info.id,
sessionID: userMessage.info.sessionID,
type: "text",
text:
BUILD_SWITCH + "\n\n" + `A plan file exists at ${plan}. You should execute on the plan defined within it`,
text: `${BUILD_SWITCH}\n\nA plan file exists at ${plan}. You should execute on the plan defined within it`,
synthetic: true,
})
userMessage.parts.push(part)
Expand Down
2 changes: 1 addition & 1 deletion packages/opencode/src/sync/sync-event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ export function payloads() {
data: def.schema,
})
.meta({
ref: "SyncEvent" + "." + def.type,
ref: `SyncEvent.${def.type}`,
})
})
.toArray()
Expand Down
2 changes: 1 addition & 1 deletion packages/opencode/src/tool/read.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ export const ReadTool = Tool.define(
)
}

let output = [`<path>${filepath}</path>`, `<type>file</type>`, "<content>" + "\n"].join("\n")
let output = [`<path>${filepath}</path>`, `<type>file</type>`, "<content>\n"].join("\n")
output += file.raw.map((line, i) => `${i + file.offset}: ${line}`).join("\n")

const last = file.offset + file.raw.length - 1
Expand Down
2 changes: 1 addition & 1 deletion packages/opencode/src/tool/tool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export namespace Tool {
) {
return () =>
Effect.gen(function* () {
const toolInfo = init instanceof Function ? { ...(yield* init()) } : { ...init }
const toolInfo = typeof init === "function" ? { ...(yield* init()) } : { ...init }
const execute = toolInfo.execute
toolInfo.execute = (args, ctx) => {
const attrs = {
Expand Down
3 changes: 3 additions & 0 deletions packages/opencode/test/mcp/lifecycle.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ function getOrCreateClientState(name?: string): MockClientState {
class MockStdioTransport {
stderr: null = null
pid = 12345
// oxlint-disable-next-line no-useless-constructor
constructor(_opts: any) {}
async start() {
if (connectShouldHang) return new Promise<void>(() => {}) // never resolves
Expand All @@ -64,6 +65,7 @@ class MockStdioTransport {
}

class MockStreamableHTTP {
// oxlint-disable-next-line no-useless-constructor
constructor(_url: URL, _opts?: any) {}
async start() {
if (connectShouldHang) return new Promise<void>(() => {}) // never resolves
Expand All @@ -76,6 +78,7 @@ class MockStreamableHTTP {
}

class MockSSE {
// oxlint-disable-next-line no-useless-constructor
constructor(_url: URL, _opts?: any) {}
async start() {
if (connectShouldHang) return new Promise<void>(() => {}) // never resolves
Expand Down
11 changes: 5 additions & 6 deletions packages/opencode/test/session/prompt.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,11 @@ function chat(text: string) {
function hanging(ready: () => void) {
const encoder = new TextEncoder()
let timer: ReturnType<typeof setTimeout> | undefined
const first =
`data: ${JSON.stringify({
id: "chatcmpl-1",
object: "chat.completion.chunk",
choices: [{ delta: { role: "assistant" } }],
})}` + "\n\n"
const first = `data: ${JSON.stringify({
id: "chatcmpl-1",
object: "chat.completion.chunk",
choices: [{ delta: { role: "assistant" } }],
})}\n\n`
const rest =
[
`data: ${JSON.stringify({
Expand Down
Loading