feat: unify execution and add workspace file imports

Remove Ask/Execute modes and general product tool approvals so requests use the selected runtime, enabled capabilities, and execution account permissions. Migrate retired application metadata while preserving user content.

Retire the Results page while retaining conversation images and stored artifacts. Add local and remote workspace file imports, timestamps and sorting, improve image discovery and saving, and refine workspace navigation and supervision responsiveness. Include the accompanying web-search changes, tests, probes, and product documentation.

Remote imports require an updated Agent. Existing artifacts are not automatically copied into project directories. Validation evidence and outstanding failures remain documented in feature progress files; no full test suite or real-model calls were rerun for this commit.

Release note: Run requests without switching work modes, import files into a selected local or remote workspace folder, sort workspace files by date, and keep using conversation images after removal of the Results page.
This commit is contained in:
mesalogo
2026-10-04 20:02:59 +08:00
parent 0cd5da33f4
commit 56ebd40bd8
374 changed files with 7075 additions and 6224 deletions
+159 -68
View File
@@ -21,7 +21,6 @@ import {
conversationSnapshotSchema,
conversationSetPinnedSchema,
expertCreateSchema,
normalizeInteractiveWorkMode,
persistedProjectExecutionSpaceSchema,
projectCreateSchema,
scheduleCreateSchema
@@ -56,7 +55,6 @@ import type {
HeartbeatCreateInput,
HeartbeatSummaryOutput,
HeartbeatUpdateInput,
LegacyWorkMode,
LocalConversationSaveBatch,
MemoryCreateInput,
ModelUsageCallInput,
@@ -138,7 +136,14 @@ import {
SUBAGENT_PROGRESS_STORAGE_SCHEMA_VERSION
} from './subagent-progress-storage'
export const ASSISTANT_DATABASE_SCHEMA_VERSION = 59
export const ASSISTANT_DATABASE_SCHEMA_VERSION = 60
function withoutHistoricalWorkMode(value: unknown): unknown {
if (!value || typeof value !== 'object' || Array.isArray(value)) return value
const { workMode: obsolete, ...current } = value as Record<string, unknown>
void obsolete
return current
}
/**
* Messages startup recovery may have to end (schema 58): still streaming, or
* metadata naming an unfinished tool/subagent (pending, running, queued) or
@@ -204,7 +209,6 @@ export type RecoverableRemoteTask = {
currentUserMessageId: string
currentAssistantMessageId: string
instructions: string
workMode: 'ask' | 'execute'
status: 'running' | 'waiting_approval' | 'interrupted'
}
@@ -213,7 +217,6 @@ type ProjectRow = {
name: string
description: string
root_path: string
default_work_mode: LegacyWorkMode
runtime_selection_json: string | null
kind: AssistantProject['kind']
channel: ProjectChannel | null
@@ -254,7 +257,6 @@ type TaskRow = {
origin: AssistantTask['origin']
status: AssistantTask['status']
active_run_status?: 'pending' | 'running' | null
work_mode: LegacyWorkMode
progress: number | null
created_at: string
started_at: string | null
@@ -698,9 +700,6 @@ function toProject(row: ProjectRow): AssistantProject {
description: row.description,
rootPath,
executionSpace: executionSpace.data,
defaultWorkMode: normalizeInteractiveWorkMode(
row.default_work_mode
),
runtimeSelection,
kind: row.kind,
channel: row.channel ?? undefined,
@@ -762,7 +761,6 @@ function toTask(row: TaskRow): AssistantTask {
: row.origin === 'schedule' && row.status === 'queued'
? 'idle'
: row.status,
workMode: normalizeInteractiveWorkMode(row.work_mode),
progress: row.progress ?? undefined,
createdAt: row.created_at,
startedAt: row.started_at ?? undefined,
@@ -889,7 +887,6 @@ function toSchedule(row: ScheduleWithTaskRow): AssistantSchedule {
const template = JSON.parse(row.task_template_json) as {
title: string
prompt: string
workMode: LegacyWorkMode
runtimeSelection?: unknown
}
const runtimeSelection = optionalAgentRuntimeSelectionSchema.safeParse(
@@ -905,7 +902,6 @@ function toSchedule(row: ScheduleWithTaskRow): AssistantSchedule {
conversationId: row.conversation_id,
title: template.title,
prompt: template.prompt,
workMode: normalizeInteractiveWorkMode(template.workMode),
runtimeSelection: runtimeSelection.success
? runtimeSelection.data
: undefined,
@@ -1162,7 +1158,7 @@ function validateRemoteTaskEvent(
throw new TypeError('kind must be a string')
}
const kind = input.kind.slice(0, 64)
const payloadJson = JSON.stringify(input.payload)
const payloadJson = JSON.stringify(withoutHistoricalWorkMode(input.payload))
if (typeof payloadJson !== 'string') {
throw new TypeError('Task event payload must be JSON serializable')
}
@@ -1243,7 +1239,6 @@ function interruptActiveToolBlocks(
}
const conversationContextStateSchema = conversationSnapshotSchema.pick({
workMode: true,
knowledgeLibraryIds: true,
knowledgeRetrievalMode: true,
storyGraphEnabled: true,
@@ -1255,7 +1250,7 @@ function parseConversationContextState(
value: string | null
): Pick<
ConversationSnapshot,
'workMode' | 'knowledgeLibraryIds' | 'knowledgeRetrievalMode' | 'storyGraphEnabled' | 'contextMetrics' | 'contextCompressionState'
'knowledgeLibraryIds' | 'knowledgeRetrievalMode' | 'storyGraphEnabled' | 'contextMetrics' | 'contextCompressionState'
> {
if (!value) {
return {}
@@ -1273,17 +1268,15 @@ function parseConversationContextState(
function serializeConversationContextState(
conversation: Pick<
ConversationSnapshot,
'workMode' | 'knowledgeLibraryIds' | 'knowledgeRetrievalMode' | 'storyGraphEnabled' | 'contextMetrics' | 'contextCompressionState'
'knowledgeLibraryIds' | 'knowledgeRetrievalMode' | 'storyGraphEnabled' | 'contextMetrics' | 'contextCompressionState'
>
): string | null {
return conversation.workMode !== undefined ||
conversation.knowledgeLibraryIds !== undefined ||
return conversation.knowledgeLibraryIds !== undefined ||
conversation.knowledgeRetrievalMode !== undefined ||
conversation.storyGraphEnabled !== undefined ||
conversation.contextMetrics ||
conversation.contextCompressionState
? JSON.stringify({
workMode: conversation.workMode,
knowledgeLibraryIds: conversation.knowledgeLibraryIds,
knowledgeRetrievalMode: conversation.knowledgeRetrievalMode,
storyGraphEnabled: conversation.storyGraphEnabled,
@@ -1616,7 +1609,6 @@ function reduceRecoveredAgentEvent(
childTaskId: event.childTaskId,
routingMode: event.routingMode,
runtimeCallId: event.runtimeCallId,
workMode: event.workMode,
state: event.state,
reason: event.reason,
progress: event.progress,
@@ -2079,6 +2071,7 @@ export class AssistantDatabase {
private activityHistoryRepository?: { database: DatabaseSync; repository: ActivityHistoryRepository }
private executionTiming?: ExecutionTiming
private readonlyReader?: ReadonlyQueryReader
private supervisionWorker?: ReadonlyQueryReader
private checkpointWorker?: Worker
private readonlyWorkerPath?: string
private foldedSearchConnection?: DatabaseSync
@@ -2280,7 +2273,6 @@ export class AssistantDatabase {
name: builtInDefaultProjectSeedName,
description: builtInDefaultProjectSeedDescription,
rootPath: defaultRootPath,
defaultWorkMode: 'ask'
},
true
)
@@ -2520,6 +2512,8 @@ export class AssistantDatabase {
this.executionTiming = undefined
this.readonlyReader?.close()
this.readonlyReader = undefined
this.supervisionWorker?.close()
this.supervisionWorker = undefined
this.foldedSearchConnection = undefined
this.activityHistoryRepository = undefined
this.database?.close()
@@ -2636,10 +2630,10 @@ export class AssistantDatabase {
)
const insert = database.prepare(
`INSERT INTO projects
(id, name, description, root_path, default_work_mode,
(id, name, description, root_path,
runtime_selection_json, kind, channel, status, created_at,
updated_at)
VALUES (?, ?, ?, ?, 'ask', ?, 'channel', ?, 'active', ?, ?)`
VALUES (?, ?, ?, ?, ?, 'channel', ?, 'active', ?, ?)`
)
const insertExecutionSpace = database.prepare(
`INSERT INTO project_execution_spaces
@@ -2701,17 +2695,16 @@ export class AssistantDatabase {
database
.prepare(
`INSERT INTO projects
(id, name, description, root_path, default_work_mode,
(id, name, description, root_path,
runtime_selection_json, kind, channel, built_in_default,
status, created_at, updated_at)
VALUES (?, ?, ?, ?, ?, ?, 'user', NULL, ?, 'active', ?, ?)`
VALUES (?, ?, ?, ?, ?, 'user', NULL, ?, 'active', ?, ?)`
)
.run(
id,
input.name,
input.description,
input.rootPath,
input.defaultWorkMode,
serializeRuntimeSelection(input.runtimeSelection),
builtInDefault ? 1 : 0,
now,
@@ -2753,7 +2746,7 @@ export class AssistantDatabase {
.prepare(
`UPDATE projects
SET name = ?, description = ?, root_path = ?,
default_work_mode = ?, runtime_selection_json = ?,
runtime_selection_json = ?,
updated_at = ?
WHERE id = ?`
)
@@ -2761,7 +2754,6 @@ export class AssistantDatabase {
current.kind === 'channel' ? current.name : input.name,
input.description,
input.rootPath,
input.defaultWorkMode,
// The settings form always sends the full layer; absent means follow global.
serializeRuntimeSelection(input.runtimeSelection),
new Date().toISOString(),
@@ -2802,17 +2794,16 @@ export class AssistantDatabase {
database
.prepare(
`INSERT INTO projects
(id, name, description, root_path, default_work_mode,
(id, name, description, root_path,
runtime_selection_json, kind, channel, built_in_default,
status, created_at, updated_at)
VALUES (?, ?, ?, ?, ?, ?, 'user', NULL, 0, 'active', ?, ?)`
VALUES (?, ?, ?, ?, ?, 'user', NULL, 0, 'active', ?, ?)`
)
.run(
id,
normalized.project.name,
normalized.project.description,
normalized.executionSpace.remoteRootPath,
normalized.project.defaultWorkMode,
serializeRuntimeSelection(normalized.project.runtimeSelection),
now,
now
@@ -2894,7 +2885,7 @@ export class AssistantDatabase {
.prepare(
`UPDATE projects
SET name = ?, description = ?, root_path = ?,
default_work_mode = ?, runtime_selection_json = ?,
runtime_selection_json = ?,
updated_at = ?
WHERE id = ? AND kind = 'user' AND channel IS NULL
AND updated_at = ?`
@@ -2903,7 +2894,6 @@ export class AssistantDatabase {
normalized.project.name,
normalized.project.description,
normalized.executionSpace.remoteRootPath,
normalized.project.defaultWorkMode,
serializeRuntimeSelection(normalized.project.runtimeSelection),
updatedAt,
projectId,
@@ -3396,10 +3386,10 @@ export class AssistantDatabase {
const insertConversation = database.prepare(
`INSERT INTO conversations
(id, project_id, runtime_selection_json, knowledge_retrieval_mode,
context_state_json, work_mode, title,
context_state_json, title,
branch_source_conversation_id, branch_source_title, status,
created_at, updated_at, timing_incomplete)
VALUES (?, ?, ?, ?, ?, 'ask', ?, ?, ?, 'active', ?, ?, 1)`
VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'active', ?, ?, 1)`
)
const insertMessage = database.prepare(
`INSERT INTO messages
@@ -3459,10 +3449,10 @@ export class AssistantDatabase {
const insertConversation = database.prepare(
`INSERT INTO conversations
(id, project_id, runtime_selection_json, knowledge_retrieval_mode,
context_state_json, work_mode, title,
context_state_json, title,
branch_source_conversation_id, branch_source_title, status,
created_at, updated_at)
VALUES (?, ?, ?, ?, ?, 'ask', ?, ?, ?, 'active', ?, ?)`
VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'active', ?, ?)`
)
const updateConversation = database.prepare(
`UPDATE conversations
@@ -3675,10 +3665,10 @@ export class AssistantDatabase {
.prepare(
`INSERT INTO conversations
(id, project_id, runtime_selection_json,
knowledge_retrieval_mode, context_state_json, work_mode,
knowledge_retrieval_mode, context_state_json,
title, branch_source_conversation_id, branch_source_title,
status, created_at, updated_at)
VALUES (?, ?, ?, ?, ?, 'ask', ?, ?, ?, 'active', ?, ?)`
VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'active', ?, ?)`
)
.run(
destinationConversationId,
@@ -3879,10 +3869,10 @@ export class AssistantDatabase {
database
.prepare(
`INSERT INTO conversations
(id, project_id, runtime_selection_json, work_mode, title, status,
(id, project_id, runtime_selection_json, title, status,
channel, external_account_id, external_conversation_id,
conversation_type, account_display, created_at, updated_at)
VALUES (?, ?, ?, 'ask', ?, 'active', ?, ?, ?, ?, ?, ?, ?)`
VALUES (?, ?, ?, ?, 'active', ?, ?, ?, ?, ?, ?, ?)`
)
.run(
id,
@@ -5291,7 +5281,6 @@ export class AssistantDatabase {
routingMode?: AssistantTask['routingMode']
title: string
instructions: string
workMode: 'ask' | 'execute'
origin?: AssistantTask['origin']
status?: Exclude<AssistantTask['status'], 'idle'>
visible?: boolean
@@ -5352,14 +5341,14 @@ export class AssistantDatabase {
`INSERT INTO tasks
(id, project_id, conversation_id, parent_task_id, expert_id,
routing_mode, title, instructions, origin, status, priority,
work_mode, progress, created_at, started_at, visible,
progress, created_at, started_at, visible,
remote_recoverable, current_user_message_id,
current_assistant_message_id)
VALUES (?, ?, ?, COALESCE((
SELECT parent.id FROM schedule_runs sr
JOIN tasks parent ON parent.schedule_id = sr.schedule_id
WHERE sr.id = ?
), ?), ?, ?, ?, ?, ?, ?, 0, ?, NULL, ?, ?, ?,
), ?), ?, ?, ?, ?, ?, ?, 0, NULL, ?, ?, ?,
?, ?, ?)`
)
.run(
@@ -5374,7 +5363,6 @@ export class AssistantDatabase {
input.instructions,
input.origin ?? 'user',
status,
input.workMode,
now,
status === 'running' ? now : null,
Number(input.visible ?? true),
@@ -5566,7 +5554,7 @@ export class AssistantDatabase {
.run(
taskId,
status,
JSON.stringify({ workMode: input.workMode }),
'{}',
now
)
database.exec('COMMIT')
@@ -5584,7 +5572,7 @@ export class AssistantDatabase {
conversation_id AS conversationId,
current_user_message_id AS currentUserMessageId,
current_assistant_message_id AS currentAssistantMessageId,
instructions, work_mode AS workMode, status
instructions, status
FROM tasks
WHERE remote_recoverable = 1
AND status IN ('running', 'waiting_approval', 'interrupted')
@@ -5603,7 +5591,6 @@ export class AssistantDatabase {
assistantIdSchema.parse(candidate.currentUserMessageId)
assistantIdSchema.parse(candidate.currentAssistantMessageId)
if (
!['ask', 'execute'].includes(candidate.workMode) ||
!['running', 'waiting_approval', 'interrupted'].includes(
candidate.status
)
@@ -5884,9 +5871,9 @@ export class AssistantDatabase {
.prepare(
`INSERT OR IGNORE INTO tasks
(id, project_id, conversation_id, title, instructions, origin,
status, priority, work_mode, created_at, started_at, completed_at,
status, priority, created_at, started_at, completed_at,
visible)
VALUES (?, NULL, ?, ?, ?, 'assistant', 'completed', 0, 'ask', ?, ?, ?, 0)`
VALUES (?, NULL, ?, ?, ?, 'assistant', 'completed', 0, ?, ?, ?, 0)`
)
.run(
taskId,
@@ -6128,7 +6115,7 @@ export class AssistantDatabase {
payload: unknown
): void {
const database = this.requireDatabase()
const payloadJson = this.subagentProgress!.serialize(taskId, kind, payload)
const payloadJson = this.subagentProgress!.serialize(taskId, kind, withoutHistoricalWorkMode(payload))
const result = database
.prepare(
`INSERT INTO task_events
@@ -7607,15 +7594,14 @@ export class AssistantDatabase {
database
.prepare(
`INSERT INTO conversations
(id, project_id, runtime_selection_json, work_mode, title,
(id, project_id, runtime_selection_json, title,
status, created_at, updated_at)
VALUES (?, ?, ?, ?, ?, 'active', ?, ?)`
VALUES (?, ?, ?, ?, 'active', ?, ?)`
)
.run(
conversationId,
projectId,
null,
'ask',
parsed.title,
now,
now
@@ -7634,8 +7620,7 @@ export class AssistantDatabase {
projectId,
JSON.stringify({
title: parsed.title,
prompt: parsed.prompt,
workMode: parsed.workMode
prompt: parsed.prompt
}),
JSON.stringify({ type: parsed.recurrence }),
parsed.runImmediately ? now : parsed.nextRunAt,
@@ -7651,10 +7636,10 @@ export class AssistantDatabase {
`INSERT INTO tasks
(id, project_id, conversation_id, schedule_id,
parent_task_id, expert_id, routing_mode, title,
instructions, origin, status, work_mode, progress,
instructions, origin, status, progress,
created_at, started_at, completed_at, error)
VALUES (?, ?, ?, ?, NULL, NULL, NULL, ?, ?,
'schedule', 'queued', ?, NULL, ?, NULL, NULL, NULL)`
'schedule', 'queued', NULL, ?, NULL, NULL, NULL)`
)
.run(
taskId,
@@ -7663,7 +7648,6 @@ export class AssistantDatabase {
scheduleId,
parsed.title,
parsed.prompt,
parsed.workMode,
now
)
if (parsed.runImmediately) {
@@ -9546,10 +9530,10 @@ export class AssistantDatabase {
const insertTask = database.prepare(
`INSERT INTO tasks
(id, project_id, conversation_id, schedule_id, title,
instructions, origin, status, priority, work_mode,
instructions, origin, status, priority,
progress, created_at, started_at, completed_at, error)
VALUES (?, ?, NULL, NULL, ?, ?, 'assistant', 'paused', 0,
'ask', NULL, ?, NULL, NULL, NULL)`
NULL, ?, NULL, NULL, NULL)`
)
for (const task of output.followUpTasks) {
const taskId = randomUUID()
@@ -11143,7 +11127,7 @@ export class AssistantDatabase {
let template: {
title?: unknown
prompt?: unknown
workMode?: LegacyWorkMode
workMode?: 'ask' | 'plan' | 'execute'
} = {}
try {
template = JSON.parse(
@@ -11163,9 +11147,7 @@ export class AssistantDatabase {
template.prompt.trim()
? template.prompt.trim().slice(0, 100_000)
: title
const workMode = normalizeInteractiveWorkMode(
template.workMode
)
const workMode = template.workMode === 'execute' ? 'execute' : 'ask'
const existing = findTask.get(schedule.id) as
| { id: string; conversation_id: string | null }
| undefined
@@ -12238,6 +12220,78 @@ export class AssistantDatabase {
database.exec('PRAGMA user_version = 59; COMMIT;')
} catch (error) { database.exec('ROLLBACK'); throw error }
}
if (version.user_version < 60) {
// Run after the historical migrations that still require the SQL columns,
// and before startup recovery parses messages with the current contracts.
const targets = [
['conversations', 'context_state_json'],
['schedules', 'task_template_json'],
['conversation_queue_items', 'payload_json'],
['task_events', 'payload_json'],
['messages', 'metadata_json']
] as const
const bytesBefore = this.databasePath === ':memory:' ? 0 : statSync(this.databasePath).size
let processed = 0
for (const [table, column] of targets) {
const select = database.prepare(`SELECT rowid AS position, ${column} AS payload
FROM ${table} WHERE rowid > ? AND ${column} IS NOT NULL ORDER BY rowid LIMIT 32`)
const update = database.prepare(`UPDATE ${table} SET ${column} = ? WHERE rowid = ?`)
let after = 0
for (;;) {
if (isCancelled?.()) throw new DOMException('Upgrade cancelled', 'AbortError')
const rows = select.all(after) as Array<{ position: number; payload: string }>
if (!rows.length) break
database.exec('BEGIN IMMEDIATE')
try {
for (const row of rows) {
let payload: Record<string, unknown>
let original: string
try {
const value: unknown = JSON.parse(row.payload)
if (!value || typeof value !== 'object' || Array.isArray(value)) throw new Error('Expected object')
payload = value as Record<string, unknown>
original = JSON.stringify(payload)
if (table === 'messages') {
if (payload.subagents !== undefined) {
if (!Array.isArray(payload.subagents) || payload.subagents.some(
item => !item || typeof item !== 'object' || Array.isArray(item)
)) throw new Error('Expected subagent objects')
payload.subagents = payload.subagents.map(withoutHistoricalWorkMode)
}
} else {
delete payload.workMode
if (table === 'conversation_queue_items' && payload.input !== undefined) {
if (!payload.input || typeof payload.input !== 'object' || Array.isArray(payload.input)) {
throw new Error('Expected queue input object')
}
payload.input = withoutHistoricalWorkMode(payload.input)
}
}
} catch {
throw new Error(`Invalid execution metadata: ${table}.${column} row ${row.position}`)
}
const json = JSON.stringify(payload)
if (json !== original) update.run(json, row.position)
after = row.position
}
database.exec('COMMIT')
} catch (error) { database.exec('ROLLBACK'); throw error }
processed += rows.length
onProgress?.({ stage: 'converting', processed, total: 0, bytesBefore })
}
}
if (isCancelled?.()) throw new DOMException('Upgrade cancelled', 'AbortError')
database.exec('BEGIN IMMEDIATE')
try {
database.exec(`
ALTER TABLE projects DROP COLUMN default_work_mode;
ALTER TABLE conversations DROP COLUMN work_mode;
ALTER TABLE tasks DROP COLUMN work_mode;
PRAGMA user_version = 60;
COMMIT;
`)
} catch (error) { database.exec('ROLLBACK'); throw error }
}
}
supervisionExperiences(): SupervisionExperienceStore {
@@ -12248,8 +12302,45 @@ export class AssistantDatabase {
return new SupervisionStoryStore(this.requireDatabase())
}
supervisionReviewStore(): SupervisionReviewStore {
return new SupervisionReviewStore(this.requireDatabase())
supervisionReviewStore(signal?: AbortSignal): SupervisionReviewStore {
return new SupervisionReviewStore(this.requireDatabase(), signal)
}
async initializeSupervisionReview(runId: string, state: import('./supervision-review-store').ReviewState, signal: AbortSignal): Promise<void> {
const store = this.supervisionReviewStore()
store.prepareInitialization(runId, state)
await this.runSupervisionWorker('initialize', [runId, state], signal)
}
async resumeSupervisionReview(runId: string, signal: AbortSignal): Promise<void> {
await this.runSupervisionWorker('resume', [runId], signal)
}
private async runSupervisionWorker(op: 'initialize' | 'resume', args: unknown[], signal: AbortSignal): Promise<void> {
if (this.databasePath === ':memory:') {
const store = this.supervisionReviewStore()
if (op === 'resume') store.resume(String(args[0]), signal)
else store.initializeSources(String(args[0]), args[1] as import('./supervision-review-store').ReviewState, signal)
return
}
// Fail explicitly when packaging/startup is broken; never freeze Main as a fallback.
if (!this.readonlyWorkerPath) throw new Error('Supervision worker is not configured')
this.supervisionWorker ??= new ReadonlyQueryReader('supervision', this.databasePath, this.readonlyWorkerPath)
await this.supervisionWorker.call(op, args, signal)
}
async supervisionContext(request: SupervisionRunRequest, signal?: AbortSignal): Promise<{ summary: string | undefined; background: ReviewBatch['evidence'] }> {
const reader = this.readonlyQueryReader()
if (reader) return reader.call('reviewContext', [request], signal)
if (this.databasePath !== ':memory:') throw new Error('Supervision worker is not configured')
return { summary: this.reviewSummary(request.scope, 'supervisor'), background: this.reviewBackground(request.scope) }
}
async supervisionCandidates(request: SupervisionRunRequest): Promise<ReturnType<AssistantDatabase['listSupervisionCandidates']>> {
const reader = this.readonlyQueryReader()
if (reader) return reader.call('reviewCandidates', [request])
if (this.databasePath !== ':memory:') throw new Error('Supervision worker is not configured')
return this.listSupervisionCandidates(request)
}
supervisionSuggestions(): SupervisionSuggestionStore {
@@ -12275,7 +12366,7 @@ export class AssistantDatabase {
// A stalled story is resumed through a paused follow-up task, like an open item.
if (suggestion.kind === 'open_item' || suggestion.kind === 'stalled') {
const task = this.createTask({ id: randomUUID(), projectId, title: suggestion.title.slice(0, 200), instructions: suggestion.detail,
workMode: 'ask', origin: 'assistant', status: 'paused' })
origin: 'assistant', status: 'paused' })
store.resolve(id, 'accepted', { taskId: task.id })
} else if (suggestion.kind === 'convention') {
let memoryId = suggestion.memoryId ?? undefined