( input: GenerateInput, fs: TextEditorFsCallbacks | undefined, )
| 838 | } |
| 839 | |
| 840 | function buildWorkspaceBrief( |
| 841 | input: GenerateInput, |
| 842 | fs: TextEditorFsCallbacks | undefined, |
| 843 | ): string | null { |
| 844 | if (!fs) return null; |
| 845 | const files = workspaceFiles(fs); |
| 846 | const sources = sourceCandidates(files, fs); |
| 847 | const hasDesignMd = fs.view('DESIGN.md') !== null; |
| 848 | const hasAgentsMd = fs.view('AGENTS.md') !== null; |
| 849 | const hasSettingsJson = fs.view('.codesign/settings.json') !== null; |
| 850 | const attachmentCount = input.attachments?.length ?? 0; |
| 851 | const imageCount = (input.attachments ?? []).filter((file) => |
| 852 | file.mediaType?.startsWith('image/'), |
| 853 | ).length; |
| 854 | const currentDesignName = input.currentDesignName?.trim(); |
| 855 | const needsTitle = isAutoDesignName(currentDesignName); |
| 856 | const hasReferenceUrl = input.referenceUrl !== null && input.referenceUrl !== undefined; |
| 857 | const hasReferenceMaterials = |
| 858 | attachmentCount > 0 || |
| 859 | hasReferenceUrl || |
| 860 | (input.designSystem !== null && input.designSystem !== undefined); |
| 861 | const lines = [ |
| 862 | 'Workspace context:', |
| 863 | currentDesignName |
| 864 | ? `- Current design title: ${currentDesignName}${needsTitle ? ' (auto-generated; call set_title before other tools).' : '.'}` |
| 865 | : '- Current design title: unknown.', |
| 866 | sources.length > 0 |
| 867 | ? `- Existing source candidates: ${sources.join(', ')}` |
| 868 | : `- No existing design source was found. Create ${DEFAULT_SOURCE_ENTRY} for visual/web work, or create the requested document/handoff file for document-first work.`, |
| 869 | `- DESIGN.md: ${hasDesignMd ? 'present; treat it as the design baton for this workspace.' : 'absent.'}`, |
| 870 | `- AGENTS.md: ${hasAgentsMd ? 'present' : 'absent'}`, |
| 871 | `- .codesign/settings.json: ${hasSettingsJson ? 'present' : 'absent'}`, |
| 872 | `- Reference materials: attached file(s): ${attachmentCount}; image file(s): ${imageCount}; reference URL: ${hasReferenceUrl ? 'yes' : 'no'}; linked design-system scan: ${input.designSystem ? 'yes' : 'no'}.`, |
| 873 | ]; |
| 874 | lines.push( |
| 875 | needsTitle |
| 876 | ? sources.length > 0 |
| 877 | ? 'This workspace has source files, but the visible design title is still an auto-generated placeholder. First call `set_title` once, then inspect/view/edit. Preserve and extend existing source unless the user explicitly asks for a rebuild.' |
| 878 | : `This is an empty auto-named workspace. First call \`set_title\` once, then create ${DEFAULT_SOURCE_ENTRY} for visual/web work or the requested document file for document-first work. Use set_todos for multi-step work.` |
| 879 | : sources.length > 0 |
| 880 | ? 'Before editing existing source files, inspect the workspace when available, then view the current source file. Use set_todos when the edit has multiple steps. Existing-source sequence: optional `set_todos` -> `inspect_workspace` when available -> `view` the source -> `str_replace`/`insert`. For continuation or existing-source turns, do not call `set_title`; preserve and extend the current design unless the user explicitly asks for a rebuild.' |
| 881 | : `This is an empty workspace. For visual/web work, create ${DEFAULT_SOURCE_ENTRY} when the first pass is ready; for document-first work, create the requested document file. Use set_todos for multi-step work.`, |
| 882 | ); |
| 883 | if (hasDesignMd) { |
| 884 | lines.push( |
| 885 | 'DESIGN.md is present; read and preserve it as the design baton before changing visual tokens.', |
| 886 | ); |
| 887 | } else if (sources.length > 0) { |
| 888 | lines.push( |
| 889 | 'If stable visual decisions emerge across screens, reference-driven work, componentization, or prototype work, create or update a minimal DESIGN.md.', |
| 890 | ); |
| 891 | } |
| 892 | if (hasReferenceMaterials) { |
| 893 | lines.push( |
| 894 | 'Reference materials are available; extract design cues before writing or editing source.', |
| 895 | ); |
| 896 | } |
| 897 | return lines.join('\n'); |
no test coverage detected