feat: ship skill and MCP workflows with signed updater for v0.0.7

This commit is contained in:
xiaohan.yuan committed 2026-10-21 00:04:17 +08:00
1 parent 1b52df0603
commit a01085c656
136 files changed
+18646 -217

No files matched your search

+95
View File
@@ -0,0 +1,95 @@
import assert from 'node:assert/strict'
import { assertRuntimeAvailable, pauseRuntimeStarts, resumeRuntimeStarts, withRuntimeStart } from '../src/main/update-maintenance'
import { createUpdateLifecycle } from '../src/main/update-lifecycle'
let release!: () => void
const running = withRuntimeStart(() => new Promise<void>(resolve => { release = resolve }))
await Promise.resolve()
let paused = false
const pendingPause = pauseRuntimeStarts().then(() => { paused = true })
assert.throws(assertRuntimeAvailable, /准备重启/)
assert.throws(() => withRuntimeStart(async () => undefined), /准备重启/)
await Promise.resolve()
assert.equal(paused, false)
release()
await running
await pendingPause
assert.equal(paused, true)
resumeRuntimeStarts()
assert.doesNotThrow(assertRuntimeAvailable)
await assert.rejects(withRuntimeStart(async () => { throw new Error('failed start') }), /failed start/)
await pauseRuntimeStarts()
resumeRuntimeStarts()
assert.equal(await withRuntimeStart(async () => 42), 42)
console.log('PASS update maintenance: in-flight start drain, new work rejection, resume, rejected-start cleanup')
let resumed = 0
let finishDirectQuiesce!: () => void
let directQuiesceStarted!: () => void
const directQuiesceStart = new Promise<void>(resolve => { directQuiesceStarted = resolve })
let directQuiesceCalls = 0
const directLifecycle = createUpdateLifecycle({
quiesce: () => {
directQuiesceCalls += 1
directQuiesceStarted()
return new Promise<void>(resolve => { finishDirectQuiesce = resolve })
},
restore: () => { throw new Error('successful quiesce must not restore') },
shutdown: async () => undefined,
exit: () => undefined,
log: () => undefined
})
const directInstall = directLifecycle.beforeInstall()
await directQuiesceStart
assert.equal(directQuiesceCalls, 1, 'install starts quiesce without a confirmation port')
let directResolved = false
void directInstall.then(() => { directResolved = true })
await Promise.resolve()
assert.equal(directResolved, false, 'beforeInstall waits for quiesce completion')
await assert.rejects(directLifecycle.beforeInstall(), /上次更新准备仍在结束中/)
assert.equal(directQuiesceCalls, 1, 'concurrent beforeInstall must not start quiesce twice')
finishDirectQuiesce()
assert.equal(await directInstall, true)
let finishQuiesce!: () => void
const deferredLifecycle = createUpdateLifecycle({
quiesce: () => new Promise<void>(resolve => { finishQuiesce = resolve }),
restore: () => { resumed += 1 },
shutdown: async () => undefined,
exit: () => undefined,
log: () => undefined,
prepareTimeoutMs: 2
})
await assert.rejects(deferredLifecycle.beforeInstall(), /清理尚未结束/)
deferredLifecycle.installFailed()
assert.equal(resumed, 0, 'timeout must not resume while old quiesce is still running')
finishQuiesce()
await new Promise(resolve => setTimeout(resolve, 0))
assert.equal(resumed, 1, 'runtime resumes only after timed-out quiesce settles')
let exited = 0
let restarts = 0
let shutdowns = 0
const committedLifecycle = createUpdateLifecycle({
quiesce: async () => undefined,
restore: () => { restarts += 1 },
shutdown: async () => { shutdowns += 1 },
exit: () => { exited += 1 },
log: () => undefined
})
assert.equal(await committedLifecycle.beforeInstall(), true)
await committedLifecycle.quitForUpdate()
committedLifecycle.installFailed()
assert.deepEqual([shutdowns, exited, restarts], [1, 1, 0], 'committed installer exit must never restore work')
await assert.rejects(committedLifecycle.beforeInstall(), /安装器已启动/)
const hungShutdown = createUpdateLifecycle({
quiesce: async () => undefined,
restore: () => { throw new Error('must not restore committed installer') },
shutdown: () => new Promise<void>(() => undefined),
exit: () => { exited += 1 },
log: () => undefined,
quitTimeoutMs: 2
})
await hungShutdown.quitForUpdate()
assert.equal(exited, 2, 'hung shutdown is bounded and still releases the installer PID')
console.log('PASS update lifecycle: direct quiesce, concurrent barrier, timeout recovery, post-launch no-resume commit')