Merge remote-tracking branch 'origin/master' into codex/web-queue-actions

# Conflicts:
#	packages/core/agent-loop/src/agent.ts
This commit is contained in:
kingwl
2026-07-30 03:33:41 +08:00
99 changed files with 1436 additions and 558 deletions

View File

@@ -381,7 +381,7 @@ class SkillWatchManager {
const current = await resolveRootWatchMode(state.root.path)
// A child unlink can publish an empty catalog before root unlinkDir arrives.
// Discovery therefore revalidates the retained handle independently.
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- watcher callbacks can mark unhealthy while the probe awaits
// oxlint-disable-next-line typescript/no-unnecessary-condition -- watcher callbacks can mark unhealthy while the probe awaits
if (!state.unhealthy && sameWatchMode(watcher.mode, current)) return
}
await this.replaceWatcher(state)
@@ -398,7 +398,7 @@ class SkillWatchManager {
/* v8 ignore next -- The loop returns no handle only when teardown wins between awaited probes. */
if (watcher === undefined) return
/* v8 ignore start -- Post-open teardown is timing-dependent; the disposal race has an explicit integration test. */
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- teardown can race awaited watcher startup
// oxlint-disable-next-line typescript/no-unnecessary-condition -- teardown can race awaited watcher startup
if (this.closing || state.owners.size === 0) {
await this.closeWatcher(watcher)
return
@@ -407,7 +407,7 @@ class SkillWatchManager {
state.watcher = watcher
state.unhealthy = false
} catch (error) {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- teardown can race awaited watcher startup
// oxlint-disable-next-line typescript/no-unnecessary-condition -- teardown can race awaited watcher startup
if (!this.closing) {
state.unhealthy = true
this.ctx.logger.warn(`skill-local: failed to watch ${state.root.path}: ${errorMessage(error)}`)

View File

@@ -267,7 +267,7 @@ export class SkillService extends Service {
invalidateCache()
}
}, 'skills.registerProvider()')
// eslint-disable-next-line @typescript-eslint/no-misused-promises -- synchronous cleanup; preserve exact disposer identity
// oxlint-disable-next-line typescript/no-misused-promises -- synchronous cleanup; preserve exact disposer identity
return dispose
} catch (error) {
lifecycle.abort(error)
@@ -307,7 +307,7 @@ export class SkillService extends Service {
invalidateCache()
}
}, 'skills.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

@@ -761,7 +761,7 @@ describe('SkillService registry', () => {
const warnings: string[] = []
ctx.logger.warn = ((message: unknown) => { warnings.push(String(message)) }) as typeof ctx.logger.warn
const disposeThrowing = ctx.on('skills/change', () => { throw new Error('observer threw') })
// eslint-disable-next-line @typescript-eslint/no-misused-promises -- deliberate rejection proves notification containment
// oxlint-disable-next-line typescript/no-misused-promises -- deliberate rejection proves notification containment
const disposeRejecting = ctx.on('skills/change', () => Promise.reject(new Error('observer rejected')))
let observed = 0
const disposeObserver = ctx.on('skills/change', () => { observed += 1 })
@@ -907,7 +907,7 @@ describe('SkillService registry', () => {
name: 'hostile-failure',
list() {
// Deliberately violate the provider contract to prove containment is total.
// eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
// oxlint-disable-next-line typescript/prefer-promise-reject-errors
return Promise.reject(hostileFailure)
},
async get() {

View File

@@ -268,7 +268,7 @@ function catalogHistory(agent: Agent): { visibleDigest?: string; published: bool
let published = false
for (let index = events.length - 1; index >= 0; index -= 1) {
// The loop bounds prove the read-only event view contains this index.
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
// oxlint-disable-next-line typescript/no-non-null-assertion
const event = events[index]!
if (event.type !== 'user/message'
|| event.data.source.kind !== 'plugin'