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:
Tianyi Cui
2026-06-11 14:02:47 +08:00
parent 2b447625fa
commit d2fb352f3e
21 changed files with 214 additions and 86 deletions

View File

@@ -67,7 +67,7 @@ describe('agent loop', () => {
// derived history: user + assistant
const messages = agent.session.deriveMessages()
expect(messages.map(m => m.role)).toEqual(['user', 'assistant'])
expect(messages[1].content).toEqual([{ type: 'text', text: 'hello there' }])
expect(messages[1]!.content).toEqual([{ type: 'text', text: 'hello there' }])
})
it('round-trips tool calls: model requests tool → executes → result in next request', async () => {
@@ -93,7 +93,7 @@ describe('agent loop', () => {
expect(adapter.requests).toHaveLength(2)
// the second request's derived history contains the tool result
const secondMessages = adapter.requests[1].messages
const secondMessages = adapter.requests[1]!.messages
const toolResultMessage = secondMessages.find(m =>
m.content.some(b => b.type === 'tool-result'))
expect(toolResultMessage).toBeDefined()
@@ -125,8 +125,8 @@ describe('agent loop', () => {
await waitForIdle(ctx, agent)
const request = adapter.requests[0]
expect(request.system).toBe('You are a test agent.\n\nAgent-specific suffix.')
expect(request.tools?.map(t => t.name)).toEqual(['noop'])
expect(request!.system).toBe('You are a test agent.\n\nAgent-specific suffix.')
expect(request!.tools?.map(t => t.name)).toEqual(['noop'])
})
it('records raw chunks for replay and emits agent/stream-chunk', async () => {
@@ -185,7 +185,7 @@ describe('agent loop', () => {
// the second model request saw the steering content
const secondRequest = adapter.requests[1]
const flat = JSON.stringify(secondRequest.messages)
const flat = JSON.stringify(secondRequest!.messages)
expect(flat).toContain('change of plans')
})
@@ -212,7 +212,7 @@ describe('agent loop', () => {
send(agent, 'go')
await waitForIdle(ctx, agent)
const flat = JSON.stringify(adapter.requests[0].messages)
const flat = JSON.stringify(adapter.requests[0]!.messages)
expect(flat).toContain('file changed: a.ts')
expect(flat).toContain('<context source=\\"plugin\\">')
})
@@ -276,7 +276,7 @@ describe('agent loop', () => {
send(agent, 'hi')
await waitForIdle(ctx, agent)
expect(adapter.requests[0].model).toBe('other-model')
expect(adapter.requests[0]!.model).toBe('other-model')
})
it('abort() mid-stream ends the turn with reason aborted', async () => {
@@ -356,7 +356,7 @@ describe('agent loop', () => {
await waitForIdle(ctx, agent)
expect(errors).toHaveLength(1)
expect(errors[0].message).toContain('script exhausted')
expect(errors[0]!.message).toContain('script exhausted')
expect(reasons[0]).toMatchObject({ kind: 'error' })
expect(agent.session.events.some(e => e.type === 'error')).toBe(true)
})