mirror of
https://fastgit.cc/https://github.com/anomalyco/opencode
synced 2026-04-21 05:10:58 +08:00
feat: enable oxlint suspicious category, fix 24 violations (#22727)
This commit is contained in:
@@ -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",
|
||||
@@ -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"]
|
||||
}
|
||||
|
||||
@@ -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") {
|
||||
@@ -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`)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ export namespace BusEvent {
|
||||
properties: def.properties,
|
||||
})
|
||||
.meta({
|
||||
ref: "Event" + "." + def.type,
|
||||
ref: `Event.${def.type}`,
|
||||
})
|
||||
})
|
||||
.toArray()
|
||||
|
||||
@@ -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 },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 },
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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`)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -339,7 +339,7 @@ export const TuiRoutes = lazy(() =>
|
||||
properties: def.properties,
|
||||
})
|
||||
.meta({
|
||||
ref: "Event" + "." + def.type,
|
||||
ref: `Event.${def.type}`,
|
||||
})
|
||||
}),
|
||||
),
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -273,7 +273,7 @@ export function payloads() {
|
||||
data: def.schema,
|
||||
})
|
||||
.meta({
|
||||
ref: "SyncEvent" + "." + def.type,
|
||||
ref: `SyncEvent.${def.type}`,
|
||||
})
|
||||
})
|
||||
.toArray()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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({
|
||||
|
||||
Reference in New Issue
Block a user