fix: read draft-only scripts in global chat

This commit is contained in:
centdix
2026-05-20 15:10:22 +02:00
parent 63cf688849
commit 7196568e86
2 changed files with 64 additions and 6 deletions
@@ -53,6 +53,7 @@ vi.mock('$lib/gen', async () => {
ScriptService: wrapService(actual.ScriptService, {
existsScriptByPath: vi.fn(async () => false),
getScriptByPath: vi.fn(),
getScriptByPathWithDraft: vi.fn(),
listScripts: vi.fn(async () => [])
}),
FlowService: wrapService(actual.FlowService, {
@@ -227,10 +228,42 @@ describe('global AI tools', () => {
summary: 'Hello script',
language: 'bun',
value: content,
isDraft: false
isDraft: true
})
})
it('reads backend draft-only scripts through the draft-aware endpoint', async () => {
const content = 'export async function main() {\n\treturn "db draft"\n}'
vi.mocked(ScriptService.getScriptByPathWithDraft).mockResolvedValueOnce({
hash: 'draft-hash',
path: 'f/scripts/backend-draft',
summary: 'Backend draft',
description: '',
content,
language: 'bun',
draft_only: true
} as any)
const raw = await callGlobalTool('read_workspace_item', {
type: 'script',
path: 'f/scripts/backend-draft'
})
expect(JSON.parse(raw)).toMatchObject({
type: 'script',
path: 'f/scripts/backend-draft',
summary: 'Backend draft',
language: 'bun',
value: content,
isDraft: true
})
expect(ScriptService.getScriptByPathWithDraft).toHaveBeenCalledWith({
workspace: WORKSPACE,
path: 'f/scripts/backend-draft'
})
expect(ScriptService.getScriptByPath).not.toHaveBeenCalled()
})
it('reads a live UserDraft editor baseline as current context without marking it draft', async () => {
const content = 'export async function main() {\n\treturn "open editor"\n}'
const handle = UserDraft.use<any>('script', 'f/scripts/open-editor', { workspace: WORKSPACE })
@@ -631,7 +664,7 @@ describe('global AI tools', () => {
schedule: '0 0 12 * * *',
timezone: 'UTC'
}),
isDraft: false
isDraft: true
})
})
@@ -794,7 +827,7 @@ describe('global AI tools', () => {
})
const item = JSON.parse(raw)
expect(item.isDraft).toBe(false)
expect(item.isDraft).toBe(true)
expect(item.value).toMatchObject({
modules: [
{
@@ -25,6 +25,7 @@ import type {
ListableVariable,
NewSchedule,
NewScript,
NewScriptWithDraft,
Schedule,
Script,
ScriptLang
@@ -523,17 +524,30 @@ function itemMatchesPathPrefix(
return !pathPrefix || item.path.startsWith(pathPrefix)
}
function scriptToItem(script: Script, includeValue: boolean): WorkspaceItem {
type ScriptItemSource = Pick<NewScript, 'path' | 'summary' | 'language' | 'content'> & {
draft_only?: boolean
}
function scriptToItem(
script: ScriptItemSource,
includeValue: boolean,
isDraft = script.draft_only === true
): WorkspaceItem {
return {
type: 'script',
path: script.path,
summary: script.summary,
language: script.language,
value: includeValue ? script.content : undefined,
isDraft: false
isDraft
}
}
function scriptWithDraftToItem(script: NewScriptWithDraft, includeValue: boolean): WorkspaceItem {
const draft = script.draft
return scriptToItem(draft ?? script, includeValue, draft !== undefined || script.draft_only === true)
}
function flowToItem(flow: Flow, includeValue: boolean): WorkspaceItem {
return {
type: 'flow',
@@ -964,7 +978,10 @@ async function readWorkspaceItem(
): Promise<WorkspaceItem> {
switch (type) {
case 'script':
return scriptToItem(await ScriptService.getScriptByPath({ workspace, path }), true)
return scriptWithDraftToItem(
await ScriptService.getScriptByPathWithDraft({ workspace, path }),
true
)
case 'flow':
return flowToItem(await FlowService.getFlowByPath({ workspace, path }), true)
case 'schedule':
@@ -1322,6 +1339,14 @@ export const globalTools: Tool<{}>[] = [
toolCallbacks.setToolStatus(toolId, { content: message, error: message })
return JSON.stringify({ success: false, error: message })
}
const draftItem = getGlobalDraft(workspace, parsed.type, parsed.path, parsed.trigger_kind)
if (draftItem) {
toolCallbacks.setToolStatus(toolId, {
content: `Read AI draft ${parsed.type} "${parsed.path}"`
})
return JSON.stringify(serializeWorkspaceItemForRead(draftItem), null, 2)
}
const currentItem = getGlobalCurrentItem(
workspace,
parsed.type,