fix(typert): close remote gateway review gaps

This commit is contained in:
imccyu
2026-08-06 18:43:31 +08:00
parent 22bec5e63f
commit 1ea5507bf8
11 changed files with 77 additions and 38 deletions

View File

@@ -245,6 +245,22 @@ describe('GoalService creation and replay', () => {
})
describe('GoalService mutations', () => {
it('exposes the supported mutation sequence through Remote wrappers', async () => {
const { ctx, agent } = await harness()
const created = ctx.goals.remoteExportCreate(agent, { objective: 'remote lifecycle' })
const edited = ctx.goals.remoteExportEdit(agent, created.ref, { objective: 'edited remotely' })
const paused = ctx.goals.remoteExportPause(agent, edited)
const resumed = ctx.goals.remoteExportResume(agent, paused)
const completed = ctx.goals.remoteExportComplete(agent, resumed)
const cleared = ctx.goals.remoteExportClear(agent, completed)
expect(edited).toMatchObject({ objective: 'edited remotely', revision: 2 })
expect(paused).toMatchObject({ phase: 'paused', revision: 3 })
expect(resumed).toMatchObject({ phase: 'active', revision: 4 })
expect(completed).toMatchObject({ phase: 'complete', revision: 5 })
expect(cleared).toEqual({ id: created.ref.id, revision: 6 })
})
it('edits with compare-and-set revisions and rejects empty edits', async () => {
const { ctx, agent } = await harness()
const created = ctx.goals.create(agent, { objective: 'old', maxGoalRounds: 4 })

View File

@@ -998,14 +998,16 @@ describe('TypertGatewayService', () => {
}),
})
expect(invalid.status).toBe(200)
await expect(invalid.json()).resolves.toMatchObject({
const invalidBody = await invalid.json() as unknown
expect(invalidBody).toMatchObject({
type: 'server-response',
rpcId: 'rpc-invalid',
result: {
ok: false,
error: { code: 'internal', message: expect.stringContaining('plain-object args field') },
error: { code: 'internal' },
},
})
expect(JSON.stringify(invalidBody)).toContain('plain-object args field')
await removeStrict()
strictActive = false
@@ -1020,14 +1022,16 @@ describe('TypertGatewayService', () => {
}),
})
expect(withdrawn.status).toBe(200)
await expect(withdrawn.json()).resolves.toMatchObject({
const withdrawnBody = await withdrawn.json() as unknown
expect(withdrawnBody).toMatchObject({
type: 'server-response',
rpcId: 'rpc-withdrawn',
result: {
ok: false,
error: { code: 'internal', message: expect.stringContaining('strict definition was withdrawn') },
error: { code: 'internal' },
},
})
expect(JSON.stringify(withdrawnBody)).toContain('strict definition was withdrawn')
const unclaimed = await fetch(`${server.origin}/api/legacy/list`, { method: 'POST' })
expect(unclaimed.status).toBe(404)

View File

@@ -562,7 +562,8 @@ function validateInvocation(descriptor: InvocationDescriptor): void {
}
validateCodec(parameter.codec, `${descriptor.id} parameter ${parameter.name}`)
}
if (descriptor.cancellation !== undefined && descriptor.cancellation.parameter !== 'signal') {
const cancellation = descriptor.cancellation as { readonly parameter: string } | undefined
if (cancellation !== undefined && cancellation.parameter !== 'signal') {
throw new Error(`typert: invocation "${descriptor.id}" cancellation parameter must be "signal"`)
}
if (descriptor.scope !== undefined) {