feat: show runtime checklists and support remote Continue

Display native OpenCode and Continue checklists alongside scheduled tasks, preserving request ownership, explicit clears and saved progress. Bundle both remote runtimes and support managed Continue installation, model routing, cancellation and restart continuation.

Validation: real local and Linux remote model checks, full Electron remote Continue flows, typecheck and lint passed. Full suite: 4707 passed, 67 skipped, one OpenCode compaction failure passed targeted rerun.

Release note: Display native execution checklists above conversations and support managed remote Continue projects with saved progress and cancellation recovery.
This commit is contained in:
mesalogo
2026-09-19 10:47:27 +08:00
parent 164e89253a
commit c7a93803c9
78 changed files with 2266 additions and 238 deletions
+18 -9
View File
@@ -80,6 +80,16 @@ export const agentPackageFileSchema = z
})
.strict()
const packagedRuntimeSchema = z.object({
runtimeId: z.enum(['opencode', 'continue']),
provider: z.enum(['opencode', 'continue']),
version: semanticVersionSchema,
bundleDigest: sha256DigestSchema,
protocol: agentProtocolVersionSchema
}).strict().refine(value => value.runtimeId === value.provider, {
message: 'Runtime provider must match its identity'
})
const agentPackageDescriptorObjectSchema = z
.object({
format: z.literal(AGENT_PACKAGE_FORMAT),
@@ -92,15 +102,8 @@ const agentPackageDescriptorObjectSchema = z
architecture: agentArchitectureSchema,
signingKeyId: signingKeyIdSchema,
agentProtocol: agentProtocolVersionSchema,
remoteRuntime: z
.object({
runtimeId: z.literal('opencode'),
provider: z.literal('opencode'),
version: semanticVersionSchema,
bundleDigest: sha256DigestSchema,
protocol: agentProtocolVersionSchema
})
.strict(),
remoteRuntime: packagedRuntimeSchema,
additionalRuntimes: z.array(packagedRuntimeSchema).max(1).optional(),
contentDigest: sha256DigestSchema,
files: z
.array(agentPackageFileSchema)
@@ -112,6 +115,9 @@ const agentPackageDescriptorObjectSchema = z
export const agentPackageDescriptorSchema =
agentPackageDescriptorObjectSchema
.superRefine((descriptor, context) => {
if (descriptor.additionalRuntimes?.some(runtime => runtime.runtimeId === descriptor.remoteRuntime.runtimeId)) {
context.addIssue({ code: 'custom', path: ['additionalRuntimes'], message: 'Duplicate packaged Runtime' })
}
const paths = descriptor.files.map((file) => file.path)
if (new Set(paths).size !== paths.length) {
context.addIssue({
@@ -152,6 +158,9 @@ export const agentPackageCatalogEntrySchema =
})
.strict()
.superRefine((entry, context) => {
if (entry.additionalRuntimes?.some(runtime => runtime.runtimeId === entry.remoteRuntime.runtimeId)) {
context.addIssue({ code: 'custom', path: ['additionalRuntimes'], message: 'Duplicate packaged Runtime' })
}
if (
entry.archive !==
agentPackageArchiveName(entry.version, entry.architecture, entry.platform)
+2
View File
@@ -1,4 +1,5 @@
import { z } from 'zod'
import { runtimeChecklistSchema } from './runtime-checklist'
import { externalKnowledgeLocatorSchema } from './external-knowledge-contracts'
import { agentRuntimeSelectionSchema } from './runtime-selection-contracts'
import { sshHostIdSchema } from './ssh-host-contracts'
@@ -367,6 +368,7 @@ export const conversationMessageSchema = z
role: z.enum(['user', 'assistant']),
content: z.string(),
reasoning: z.string().optional(),
runtimeChecklist: runtimeChecklistSchema.optional(),
blocks: conversationMessageBlocksSchema.optional(),
displayCaptureTruncated: z.boolean().optional(),
createdAt: z.number().int().nonnegative(),
+1
View File
@@ -1251,6 +1251,7 @@ export const subagentEventSchema = z.union([
export type SubagentEvent = z.infer<typeof subagentEventSchema>
export type AgentEvent =
| { type: 'checklist'; requestId: string; checklist: import('./runtime-checklist').RuntimeChecklist }
| {
requestId: string
type: 'status'
+6 -4
View File
@@ -218,7 +218,7 @@ export async function verifyPublishedRuntimeBundle(
'Published Runtime entrypoint metadata changed'
)
}
await assertElfArchitecture(
if (manifest.provider === 'opencode') await assertElfArchitecture(
executablePath,
options.architecture,
'Runtime executable',
@@ -414,13 +414,15 @@ export function assertRuntimeManifestMatchesLock(
lock: RemoteRuntimeLock,
architecture: AgentArchitecture
): void {
const expected = lock.runtimes.opencode
const expected = manifest.runtimeId === 'opencode' ? lock.runtimes.opencode
: manifest.runtimeId === 'continue' ? lock.runtimes.continue : undefined
if (!expected) throw new Error('Runtime manifest does not match a locked profile')
const target = manifest.platform === 'darwin'
? expected.targets['darwin-arm64']
: expected.targets[architecture]
if (
target === undefined ||
manifest.runtimeId !== 'opencode' ||
manifest.runtimeId !== expected.provider ||
manifest.provider !== expected.provider ||
manifest.runtimeVersion !== expected.version ||
manifest.architecture !== architecture ||
@@ -725,4 +727,4 @@ async function assertElfArchitecture(
} finally {
await handle.close()
}
}
}
+19 -2
View File
@@ -42,6 +42,9 @@ export const remoteRuntimeProviderKindSchema = z.enum([
'continue'
])
export const managedRemoteRuntimeIdSchema = z.enum(['opencode', 'continue'])
export type ManagedRemoteRuntimeId = z.infer<typeof managedRemoteRuntimeIdSchema>
export const remoteRuntimeArchitectureSchema = agentArchitectureSchema
export const remoteRuntimeAllowedEnvironmentNameSchema = z.enum([
@@ -80,7 +83,7 @@ const npmPackageIntegritySchema = z
export const remoteRuntimeSourcePackageSchema = z
.object({
name: z.string().regex(/^[a-z0-9][a-z0-9._-]{0,127}$/u),
name: z.string().regex(/^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]{0,127}$/u),
integrity: npmPackageIntegritySchema
})
.strict()
@@ -262,7 +265,21 @@ export const remoteRuntimeLockSchema = z
})
.strict()
})
.strict()
.strict(),
continue: z.object({
version: componentVersionSchema,
provider: z.literal('continue'),
entrypoint: z.literal('lib/continue/dist/cn.js'),
entrypointIdentity: z.literal('continue-acp'),
argvPrefix: z.tuple([]),
allowedEnvironmentNames: z.array(remoteRuntimeAllowedEnvironmentNameSchema),
protocol: agentProtocolVersionSchema,
targets: z.object({
x64: remoteRuntimeLockedTargetSchema,
arm64: remoteRuntimeLockedTargetSchema,
'darwin-arm64': remoteRuntimeLockedTargetSchema.optional()
}).strict()
}).strict().optional()
})
.strict()
})
+19
View File
@@ -0,0 +1,19 @@
import { describe, expect, it } from 'vitest'
import { parseContinueChecklist, runtimeChecklistSchema } from './runtime-checklist'
describe('native runtime checklist', () => {
it('preserves long lists, duplicate items and explicit clears', () => {
const content = 'task'.repeat(1500)
expect(parseContinueChecklist('Checklist', { checklist: `- [ ] ${content}\n- [X] ${content}` })).toEqual({
source: 'continue', items: [{ content, status: 'pending' }, { content, status: 'completed' }]
})
expect(runtimeChecklistSchema.parse(parseContinueChecklist('Checklist', '{"checklist":""}'))).toEqual({ source: 'continue', items: [] })
})
it('rejects unrelated tools and malformed lists without clearing', () => {
for (const input of [{}, { checklist: [] }, { checklist: '- [ ] valid\ninvalid' }, { checklist: '- [ ] ' }, '{']) {
expect(parseContinueChecklist('Checklist', input)).toBeUndefined()
}
expect(parseContinueChecklist('checklist', { checklist: '' })).toBeUndefined()
expect(runtimeChecklistSchema.safeParse({ source: 'opencode', items: [{ content: 'x', status: 'done' }] }).success).toBe(false)
})
})
+31
View File
@@ -0,0 +1,31 @@
import { z } from 'zod'
export const runtimeChecklistSchema = z.object({
source: z.enum(['opencode', 'continue']),
items: z.array(z.object({
content: z.string().trim().min(1),
status: z.enum(['pending', 'in_progress', 'completed', 'cancelled']),
priority: z.enum(['low', 'medium', 'high']).optional()
}).strict())
}).strict()
export type RuntimeChecklist = z.infer<typeof runtimeChecklistSchema>
// Only the native Checklist argument uses this syntax. Invalid input is not a clear.
export function parseContinueChecklist(name: string, input: unknown): RuntimeChecklist | undefined {
if (name !== 'Checklist') return undefined
try {
const args = typeof input === 'string' ? JSON.parse(input) : input
if (!args || typeof args.checklist !== 'string') return undefined
const items: RuntimeChecklist['items'] = []
for (const line of args.checklist.split(/\r?\n/u)) {
if (!line.trim()) continue
const match = /^\s*- \[([ xX])\]\s+(.+?)\s*$/u.exec(line)
if (!match || !match[2]?.trim()) return undefined
items.push({ content: match[2]!, status: match[1] === ' ' ? 'pending' : 'completed' })
}
return { source: 'continue', items }
} catch {
return undefined
}
}
+2 -2
View File
@@ -312,8 +312,8 @@ export const sshHostRemoteEnvironmentSchema = z
.array(
z
.object({
runtimeId: z.literal('opencode'),
provider: z.literal('opencode'),
runtimeId: z.enum(['opencode', 'continue']),
provider: z.enum(['opencode', 'continue']),
state: sshHostRemoteEnvironmentStateSchema,
expected: sshHostRemoteEnvironmentVersionSchema,
installed: