mirror of
https://github.com/deepseek-ai/deepseek-harness
synced 2026-08-15 21:04:50 +00:00
Enable maximum-strict TypeScript across our packages
tsconfig.base.json adds noUncheckedIndexedAccess, exactOptionalPropertyTypes, noImplicitOverride, noFallthroughCasesInSwitch, noUnusedLocals, and noUnusedParameters on top of strict. Vendored packages opt out of the new flags locally (their tsconfigs are ours to regenerate; their source is not), keeping upstream-sync friendliness. Our code fixed accordingly: index accesses acknowledge undefined (assembler flush cursors, lastTurnNumber); optional properties are omitted instead of set-to-undefined (GenerateResult.usage, ToolDefinition.strict, GenerateOptions.system/tools, error payloads via an errorData helper); Session.onAppend is explicitly `(…) => void | undefined`; tests and examples updated for unused parameters and indexed access.
This commit is contained in:
@@ -18,6 +18,19 @@ import type { LoopAgent } from './agent.ts'
|
||||
/** An Error with an optional machine-readable code (e.g., from LlmError or a throwing plugin). */
|
||||
type CodedError = Error & { code?: string }
|
||||
|
||||
/** Normalize an arbitrary thrown value into a (possibly coded) Error. */
|
||||
function toError(error: unknown): CodedError {
|
||||
return error instanceof Error ? error : new Error(String(error))
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the `{ message, code? }` part of an error payload, omitting the
|
||||
* `code` key entirely when absent (exactOptionalPropertyTypes-correct).
|
||||
*/
|
||||
function errorData(err: CodedError): { message: string; code?: string } {
|
||||
return { message: err.message, ...typeof err.code === 'string' ? { code: err.code } : {} }
|
||||
}
|
||||
|
||||
/**
|
||||
* Ambient handles the loop driver receives from the agent. Decouples the
|
||||
* pure function `runLoop` from the mutable LoopAgent fields, making the
|
||||
@@ -79,8 +92,8 @@ export async function runLoop(ctx: Context, agent: LoopAgent, handle: LoopHandle
|
||||
// Backstop: a throwing emit listener (turn boundaries) or a broken
|
||||
// finalizer must not kill the driver. Record what we can and move on.
|
||||
try {
|
||||
const err: CodedError = error instanceof Error ? error : new Error(String(error))
|
||||
session.append('error', { turn, step: 0, message: err.message, code: err.code })
|
||||
const err = toError(error)
|
||||
session.append('error', { turn, step: 0, ...errorData(err) })
|
||||
ctx.emit('agent/error', agent, turn, 0, err)
|
||||
} catch { /* the error path itself is broken; nothing left to do */ }
|
||||
}
|
||||
@@ -146,9 +159,9 @@ async function runTurn(ctx: Context, agent: LoopAgent, handle: LoopHandle, turn:
|
||||
reason = { kind: 'aborted', reason: String(abort.signal.reason ?? 'aborted') }
|
||||
} else {
|
||||
const coded = error as CodedError
|
||||
session.append('error', { turn, step, message: coded.message, code: coded.code })
|
||||
session.append('error', { turn, step, ...errorData(coded) })
|
||||
ctx.emit('agent/error', agent, turn, step, error)
|
||||
reason = { kind: 'error', message: coded.message, code: coded.code }
|
||||
reason = { kind: 'error', ...errorData(coded) }
|
||||
}
|
||||
break
|
||||
}
|
||||
@@ -168,10 +181,10 @@ async function runTurn(ctx: Context, agent: LoopAgent, handle: LoopHandle, turn:
|
||||
)
|
||||
} catch (error: unknown) {
|
||||
// A broken continuation plugin ends the turn, not the loop.
|
||||
const err: CodedError = error instanceof Error ? error : new Error(String(error))
|
||||
session.append('error', { turn, step, message: err.message, code: err.code })
|
||||
const err = toError(error)
|
||||
session.append('error', { turn, step, ...errorData(err) })
|
||||
ctx.emit('agent/error', agent, turn, step, err)
|
||||
reason = { kind: 'error', message: err.message, code: err.code }
|
||||
reason = { kind: 'error', ...errorData(err) }
|
||||
break
|
||||
}
|
||||
|
||||
@@ -194,8 +207,8 @@ async function runTurn(ctx: Context, agent: LoopAgent, handle: LoopHandle, turn:
|
||||
try {
|
||||
await ctx.parallel('session/flush', session)
|
||||
} catch (error: unknown) {
|
||||
const err: CodedError = error instanceof Error ? error : new Error(String(error))
|
||||
session.append('error', { turn, step, message: err.message, code: err.code })
|
||||
const err = toError(error)
|
||||
session.append('error', { turn, step, ...errorData(err) })
|
||||
ctx.emit('agent/error', agent, turn, step, err)
|
||||
}
|
||||
}
|
||||
@@ -229,8 +242,8 @@ async function runStep(
|
||||
let request: GenerateOptions = {
|
||||
model: options.model ?? '',
|
||||
messages: session.deriveMessages(),
|
||||
system: system || undefined,
|
||||
tools: assembly.tools.length > 0 ? assembly.tools : undefined,
|
||||
...system ? { system } : {},
|
||||
...assembly.tools.length > 0 ? { tools: assembly.tools } : {},
|
||||
signal,
|
||||
}
|
||||
request = await ctx.waterfall('agent/request', agent, turn, step, request, async () => request)
|
||||
@@ -293,7 +306,7 @@ async function runStep(
|
||||
/** The last turn number in a (possibly seeded) session log, or 0. */
|
||||
function lastTurnNumber(session: Session): number {
|
||||
for (let index = session.events.length - 1; index >= 0; index--) {
|
||||
const event = session.events[index]
|
||||
const event = session.events[index]!
|
||||
if (event.type === 'turn/start') return event.data.turn
|
||||
}
|
||||
return 0
|
||||
|
||||
Reference in New Issue
Block a user