refactor: migrate linting to Oxlint

This commit is contained in:
Turtle
2026-07-29 14:32:11 +08:00
parent 1f242753ec
commit 95a995968b
88 changed files with 1026 additions and 616 deletions

View File

@@ -221,7 +221,7 @@ export class ReactLoopAgent implements Agent {
if (this.abort !== undefined || !this.queued.some(item => item.wakeup)) return
// The some() guard above proves the queue is non-empty; the non-null
// assertion expresses that invariant.
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
// oxlint-disable-next-line typescript/no-non-null-assertion
const { message } = this.queued.shift()!
const inheritedOutboxLength = this.outbox.length
@@ -368,7 +368,7 @@ export class ReactLoopAgent implements Agent {
outcome.failure, requestFailureHistory, outcome.retryPolicy, signal,
() => Promise.resolve<RequestErrorAction>(undefined),
)
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- signal can abort while recovery is awaited.
// oxlint-disable-next-line typescript/no-unnecessary-condition -- signal can abort while recovery is awaited.
if (action?.kind === 'retry' && !signal.aborted) {
retryFailures = Object.freeze([...requestFailureHistory, outcome.failure])
}
@@ -584,7 +584,7 @@ export class ReactLoopAgent implements Agent {
const maxTokens = this.options.maxTokens
const seedConfig = deepFreeze(structuredClone(
this.requestHeaderLogged
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- the instance logged the header it now folds
// oxlint-disable-next-line typescript/no-non-null-assertion -- the instance logged the header it now folds
? persistedConfig!
: {
...route,

View File

@@ -78,7 +78,7 @@ export async function executeToolCalls(
let concluded = false
while (next < planned.length) {
// Commit before classifying again so registry changes affect unstarted calls.
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- bounded by the loop condition
// oxlint-disable-next-line typescript/no-non-null-assertion -- bounded by the loop condition
const first = planned[next]!
const mode = ctx.tools.executionMode(first.exec).kind
const group = mode === 'parallel' ? planned.slice(next) : [first]
@@ -141,7 +141,7 @@ async function runGroup(
const result = slot.needsPost
? await ctx.tools[TOOL_REGISTRY_SCHEDULER].finalize(slot.exec, slot.result)
: ctx.tools[TOOL_REGISTRY_SCHEDULER].finish(slot.exec, slot.result)
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- bounded index
// oxlint-disable-next-line typescript/no-non-null-assertion -- bounded index
appendToolResult(session, turn, step, call!.block, result, callSeqs[committed]!)
for (const context of result.additionalContexts ?? []) acceptContext(context)
concluded ||= result.concludesTurn === true
@@ -152,7 +152,7 @@ async function runGroup(
const inFlight = new Map<number, Promise<number>>()
const startCall = async (index: number): Promise<void> => {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- bounded index
// oxlint-disable-next-line typescript/no-non-null-assertion -- bounded index
const call = group[index]!
callSeqs[index] = appendToolCall(session, turn, step, call.block)
started++
@@ -181,7 +181,7 @@ async function runGroup(
const fillPool = async (): Promise<void> => {
while (!aborted && nextToStart < group.length && inFlight.size < maxParallelToolCalls) {
// Re-read later modes after ordered commits so registry changes can create a barrier.
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- bounded by the loop condition
// oxlint-disable-next-line typescript/no-non-null-assertion -- bounded by the loop condition
const nextCall = group[nextToStart]!
if (nextToStart > 0 && mode === 'parallel'
&& ctx.tools.executionMode(nextCall.exec).kind !== 'parallel') break

View File

@@ -249,7 +249,7 @@ describe('config-driven session id', () => {
const failures: unknown[] = []
ctx.on('agent-loop/config-start-failed', () => { throw unrenderable })
// Deliberately violate the normal Error-only rejection rule to exercise the unknown boundary.
// eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
// oxlint-disable-next-line typescript/prefer-promise-reject-errors
ctx.on('agent-loop/config-start-failed', () => Promise.reject(unrenderable) as never)
ctx.on('agent-loop/config-start-failed', (_sessionId, error) => { failures.push(error) })
vi.spyOn(ctx.sessionPersistence, 'list').mockRejectedValue(unrenderable)

View File

@@ -108,12 +108,12 @@ export function agentEvents(ctx: Context, agent: Agent): AgentEventDispatch {
}
},
async serial(name, ...rest) {
// eslint-disable-next-line @typescript-eslint/unbound-method -- the events mixin accessor returns a pre-bound function
// oxlint-disable-next-line typescript/unbound-method -- the events mixin accessor returns a pre-bound function
const serial = ctx.serial as (thisArg: Scoped<Agent>, name: string, ...args: unknown[]) => Promise<never>
return await serial(carrier, name, agent, ...rest)
},
waterfall(name, ...rest) {
// eslint-disable-next-line @typescript-eslint/unbound-method -- the events mixin accessor returns a pre-bound function
// oxlint-disable-next-line typescript/unbound-method -- the events mixin accessor returns a pre-bound function
const waterfall = ctx.waterfall as (thisArg: Scoped<Agent>, name: string, ...args: unknown[]) => never
return waterfall(carrier, name, agent, ...rest)
},

View File

@@ -328,7 +328,7 @@ export class AgentRegistry extends Service {
// caller's composite effect can yield it for in-order teardown; the
// loop's constructor effect returns it directly, identity-nesting the
// registration under that effect.
// eslint-disable-next-line @typescript-eslint/no-misused-promises -- synchronous cleanup; direct return preserves disposer identity
// oxlint-disable-next-line typescript/no-misused-promises -- synchronous cleanup; direct return preserves disposer identity
return dispose
}
@@ -355,7 +355,7 @@ export class AgentRegistry extends Service {
// capability and need no Cordis tracker magic.
const { target } = this.requireFactory()
const receiver = getTraceable(ownerCtx, target)
// eslint-disable-next-line @typescript-eslint/unbound-method -- Reflect.apply intentionally supplies the caller-traced receiver
// oxlint-disable-next-line typescript/unbound-method -- Reflect.apply intentionally supplies the caller-traced receiver
return Reflect.apply(target.createAgent, receiver, [ownerCtx, options])
}
@@ -370,7 +370,7 @@ export class AgentRegistry extends Service {
const ownerCtx = this.ctx
const { target } = this.requireFactory()
const receiver = getTraceable(ownerCtx, target)
// eslint-disable-next-line @typescript-eslint/unbound-method -- Reflect.apply intentionally supplies the caller-traced receiver
// oxlint-disable-next-line typescript/unbound-method -- Reflect.apply intentionally supplies the caller-traced receiver
return Reflect.apply(target.resume, receiver, [ownerCtx, options])
}
@@ -397,7 +397,7 @@ export class AgentRegistry extends Service {
yield this.enter(agent, this.ctx.agent)
this.announce(agent)
}.bind(this), 'agents.register()')
// eslint-disable-next-line @typescript-eslint/no-misused-promises -- synchronous cleanup; direct return preserves disposer identity
// oxlint-disable-next-line typescript/no-misused-promises -- synchronous cleanup; direct return preserves disposer identity
return dispose
}

View File

@@ -241,7 +241,7 @@ export class ScopedLayers<L extends ScopeLayer> {
}
if (notify) this.onChange()
}.bind(this), options.label)
// eslint-disable-next-line @typescript-eslint/no-misused-promises -- exact synchronous disposer preserves Cordis effect identity
// oxlint-disable-next-line typescript/no-misused-promises -- exact synchronous disposer preserves Cordis effect identity
return dispose
}
}

View File

@@ -596,7 +596,7 @@ export class Session {
for (const seq of nodes.slice(this.derivedNodes)) {
// Surface sequences are built from this.log — seq is always a valid
// index by construction. The non-null assertion expresses that invariant.
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
// oxlint-disable-next-line typescript/no-non-null-assertion
const msg = this.deriveEventMessage(this.log[seq]!)
// A surface node is one of the five message-producing types, but an
// empty-content assistant/message (a max-tokens step that hosts only
@@ -911,7 +911,7 @@ export class SessionStore extends Service {
} catch (error: unknown) {
// Preserve the listener's exact rejection value; flush is a caller-owned
// failure boundary, and Cordis listeners may throw arbitrary values.
// eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
// oxlint-disable-next-line typescript/prefer-promise-reject-errors
return Promise.reject(error)
}
}))

View File

@@ -340,7 +340,7 @@ export class SurfaceManager implements SessionSurface {
/** Fold events appended since the previous access. */
private _processDelta(): void {
for (let i = this._lastProcessedSeq + 1; i < this.log.length; i++) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- bounded by the loop condition
// oxlint-disable-next-line typescript/no-non-null-assertion -- bounded by the loop condition
applySurfaceEvent(this._state, this.log[i]!, i, this.log)
this._lastProcessedSeq = i
}

View File

@@ -86,7 +86,7 @@ describe('packChunkRuns', () => {
['a block-index switch', [...deltaRun('text-delta', 2), ...deltaRun('text-delta', 1, 2, 7)]],
['a step switch', deltaRun('text-delta', 3).map((e, k) => k === 2 ? chunkEvent(e.seq, e.time, (e.data as { chunk: StreamChunk }).chunk, 1, 2) : e)],
])('breaks a run on %s (both halves too short to pack)', (_label, events) => {
expect(packChunkRuns(events as SessionEvent[])).toStrictEqual(events)
expect(packChunkRuns(events)).toStrictEqual(events)
})
it('breaks a tool-call run on call-id or name change', () => {

View File

@@ -546,19 +546,19 @@ export function defineTool<const S extends ParameterSchemaSpec, const O extends
options: DefineToolOptions<S, O>,
): ToolDefinition {
// Object-literal methods do not use `this`; retaining references is safe.
// eslint-disable-next-line @typescript-eslint/unbound-method
// oxlint-disable-next-line typescript/unbound-method
const userExecute = options.execute
// eslint-disable-next-line @typescript-eslint/unbound-method
// oxlint-disable-next-line typescript/unbound-method
const userFinalizeContent = options.finalizeContent
// eslint-disable-next-line @typescript-eslint/unbound-method
// oxlint-disable-next-line typescript/unbound-method
const userRender = options.output.render
// eslint-disable-next-line @typescript-eslint/unbound-method
// oxlint-disable-next-line typescript/unbound-method
const userPresentationMeta = options.output.presentationMeta
// eslint-disable-next-line @typescript-eslint/unbound-method
// oxlint-disable-next-line typescript/unbound-method
const userPresentCall = options.presentCall
// eslint-disable-next-line @typescript-eslint/unbound-method
// oxlint-disable-next-line typescript/unbound-method
const userPresentResult = options.presentResult
// eslint-disable-next-line @typescript-eslint/unbound-method
// oxlint-disable-next-line typescript/unbound-method
const userIsConcurrencySafe = options.isConcurrencySafe
if (options.timeoutMs !== undefined && (!Number.isFinite(options.timeoutMs) || options.timeoutMs <= 0)) {
throw new Error(`defineTool(${options.name}): timeoutMs must be a positive finite number`)

View File

@@ -27,7 +27,7 @@ export type ContentToolFixtureOptions<S extends ParameterSchemaSpec> = Omit<
export function defineContentToolFixture<const S extends ParameterSchemaSpec>(
options: ContentToolFixtureOptions<S>,
): ToolDefinition {
// eslint-disable-next-line @typescript-eslint/unbound-method
// oxlint-disable-next-line typescript/unbound-method
const execute = options.execute
return defineTool({
...options,