feat: 支持 Python 代码节点 main 返回输出

- 自动传入节点输入并映射 main 返回字典,兼容历史 _result

- 限制脚本输出缓冲并补充运行时与编辑器测试

- 同步 Python 帮助、占位提示和独立可执行补全片段
This commit is contained in:
2026-08-03 11:16:03 +08:00
parent 51dbfd41b6
commit 1bf755f6c4
5 changed files with 267 additions and 17 deletions

View File

@@ -71,6 +71,36 @@ describe('codeCompletion utils', () => {
);
});
it('should prefer main return snippets for python output', () => {
const completions = createBusinessCompletions('python', []);
const mainCompletion = completions.find((item) => item.label === 'main');
const resultCompletion = completions.find(
(item) => item.label === 'result-object',
);
expect(mainCompletion).toMatchObject({
type: 'snippet',
detail: '代码节点入口',
boost: 1000,
});
expect(String(mainCompletion?.apply)).toContain('def main(inputs):');
expect(String(mainCompletion?.apply)).toContain('return {');
expect(String(resultCompletion?.apply)).toContain('def main(inputs):');
expect(String(resultCompletion?.apply)).toContain(
"return {'message': 'ok', 'data': inputs.get('data')}",
);
});
it('should provide standalone python snippets', () => {
const completions = createBusinessCompletions('python', []);
const snippets = completions.filter((item) => item.type === 'snippet');
expect(snippets).toHaveLength(4);
for (const snippet of snippets) {
expect(String(snippet.apply)).toMatch(/^def main\(inputs\):\n /);
}
});
it('should detect blocked nodes for comment/string/property contexts', () => {
expect(shouldSkipBusinessCompletion('Comment')).toBe(true);
expect(shouldSkipBusinessCompletion('LineComment')).toBe(true);

View File

@@ -60,21 +60,29 @@ const PYTHON_SNIPPETS: Array<{
insert: string;
detail: string;
}> = [
{
label: 'main',
detail: '代码节点入口',
insert:
"def main(inputs):\n return {\n 'output': inputs.get('input'),\n }",
},
{
label: 'if-else',
detail: '条件分支',
insert:
"if condition:\n _result['value'] = value\nelse:\n _result['value'] = None",
"def main(inputs):\n condition = inputs.get('condition')\n value = inputs.get('value')\n if condition:\n return {'value': value}\n return {'value': None}",
},
{
label: 'for-loop',
detail: '遍历数组',
insert: "for item in items:\n # TODO\n pass\n_result['done'] = True",
insert:
"def main(inputs):\n result = []\n for item in inputs.get('items', []):\n result.append(item)\n return {'result': result}",
},
{
label: 'result-object',
detail: '返回对象',
insert: "_result['message'] = 'ok'\n_result['data'] = data",
insert:
"def main(inputs):\n return {'message': 'ok', 'data': inputs.get('data')}",
},
];