const fs = require('fs'); const manual = JSON.parse(fs.readFileSync(process.argv[2], 'utf8')); function render(schema, indent) { if (!schema) return 'unknown'; const pad = ' '.repeat(indent); const padIn = ' '.repeat(indent + 1); if (schema.enum) return schema.enum.map(v => JSON.stringify(v)).join(' | '); switch (schema.type) { case 'array': return render(schema.items, indent) + '[]'; case 'object': { if (!schema.properties) return 'Record'; const req = schema.required || []; const lines = Object.entries(schema.properties).map(([k, v]) => { const opt = req.includes(k) ? '' : '?'; let line = `${padIn}${k}${opt}: ${render(v, indent + 1)};`; const notes = []; if (v.description) notes.push(v.description); if (v.default !== undefined) notes.push(`default: ${JSON.stringify(v.default)}`); if (notes.length) line += ` // ${notes.join(' — ')}`; return line; }); return `{\n${lines.join('\n')}\n${pad}}`; } case undefined: return 'unknown'; default: return schema.type; } } const groups = [ ['Scene graph', ['nodeGetTree', 'nodeGetAtPath', 'nodeCreate', 'nodeCreatePrimitive', 'nodeOperate']], ['Components', ['nodeComponentsGet', 'nodeComponentAdd', 'nodeComponentRemove', 'nodeGetAvailableComponentTypes']], ['Inspector (types & properties)', ['inspectorGetInstanceDefinition', 'inspectorGetSettingsDefinition', 'inspectorGetInstanceProperties', 'inspectorGetSettingsProperties', 'inspectorSetInstanceProperties', 'inspectorSetSettingsProperties']], ['Assets', ['assetGetTree', 'assetGetAtPath', 'assetCreate', 'assetImport', 'assetOperate', 'assetGetPreview']], ['Editor', ['editorOperate', 'editorGetLogs', 'editorGetScenePreview']], ]; const byName = new Map(manual.tools.map(t => [t.name, t])); const out = []; out.push('# Code Mode tool reference (`CocosEditor`)'); out.push(''); out.push('Generated from the live UTCP manual served by the `cocos-code-mode` extension'); out.push(`(UTCP ${manual.utcp_version}, ${manual.tools.length} tools). Regenerate with the command in`); out.push('[CODE_MODE_SETUP.md](CODE_MODE_SETUP.md) whenever the extension is updated.'); out.push(''); out.push('All tools are called as `CocosEditor.({ ... })` inside a `utcp run` script.'); out.push('Calls look synchronous — the host bridges the async work, so no `await` is needed.'); out.push(''); out.push('## Conventions'); out.push(''); out.push('Nodes, components and assets are passed around as UUID handles:'); out.push(''); out.push('```ts'); out.push('interface IInstanceReference { id: string; type?: string; } // e.g. { id: "a1b2…", type: "cc.Sprite" }'); out.push('```'); out.push(''); out.push('Work **discover, then act**: get the tree, get the type definition, then set properties by name.'); out.push('Never guess property names — `inspectorGetInstanceDefinition` returns the real TypeScript class.'); out.push(''); const seen = new Set(); for (const [title, names] of groups) { out.push(`## ${title}`); out.push(''); for (const name of names) { const t = byName.get(name); if (!t) continue; seen.add(name); out.push(`### \`${name}\``); out.push(''); out.push(t.description); out.push(''); out.push('```ts'); out.push(`CocosEditor.${name}(args: ${render(t.inputs, 0)}): ${render(t.outputs, 0)}`); out.push('```'); out.push(''); } } const rest = manual.tools.filter(t => !seen.has(t.name)); if (rest.length) { out.push('## Other'); out.push(''); for (const t of rest) { out.push(`### \`${t.name}\``); out.push(''); out.push(t.description); out.push(''); out.push('```ts'); out.push(`CocosEditor.${t.name}(args: ${render(t.inputs, 0)}): ${render(t.outputs, 0)}`); out.push('```'); out.push(''); } } fs.writeFileSync(process.argv[3], out.join('\n')); console.log('wrote', process.argv[3], out.length, 'lines');