@minus-ai/create-skill 0.1.0-beta.13 → 0.1.0-beta.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.mjs +15 -8
- package/package.json +1 -1
- package/templates/conftest.py.tpl +5 -0
- package/templates/frontend-package.json.tpl +1 -1
- package/templates/pipeline-reference.py.tpl +14 -0
- package/templates/pyproject.toml.tpl +7 -0
- package/templates/root-package.json.tpl +5 -7
- package/templates/test_pipeline.py.tpl +35 -0
package/index.mjs
CHANGED
|
@@ -520,7 +520,11 @@ async function main() {
|
|
|
520
520
|
const vars = { skillId: skillResult.id, folder, className, displayName, description, namespace, port, nodeVersion, nodeMajor: String(NODE_MAJOR_FLOOR) }
|
|
521
521
|
|
|
522
522
|
// Backend files (pipeline.py from input-type subdir)
|
|
523
|
-
|
|
523
|
+
// 末尾统一追加 SDK 参考速查(纯注释单源模板),各场景模板不各自复制
|
|
524
|
+
writeOut(
|
|
525
|
+
join(targetDir, 'pipeline.py'),
|
|
526
|
+
render(readTemplate('pipeline.py.tpl', inputType), vars) + readTemplate('pipeline-reference.py.tpl')
|
|
527
|
+
)
|
|
524
528
|
writeOut(join(targetDir, 'server.py'), render(readTemplate('server.py.tpl'), vars))
|
|
525
529
|
writeOut(join(targetDir, 'pyproject.toml'), render(readTemplate('pyproject.toml.tpl'), vars))
|
|
526
530
|
writeOut(join(targetDir, '.env.example'), render(readTemplate('env.example.tpl'), vars))
|
|
@@ -597,9 +601,11 @@ ${templateDocs[inputType] || templateDocs.custom}
|
|
|
597
601
|
|
|
598
602
|
写代码前必须先了解 SDK 提供的能力,优先使用 SDK 已有的组件和方法,不要手写。
|
|
599
603
|
|
|
604
|
+
⛔ 下面凡是 \`${platformUrl}/runtime/...\` 的远程文档,**一律用 \`curl -sSL '<url>'\` 抓取,不要用 WebFetch**:平台文档是 http + 非标准端口地址,WebFetch 连不上(TCP 层 ECONNREFUSED,与 http/https 无关),会把可达的文档误判成"读不到"而停止写代码。\`curl -sSL\` 走系统网络栈并自动跟随重定向,是唯一可靠取法;只有 \`curl\` 真的失败(连不上 / 非 2xx)才说明文档不可达。
|
|
605
|
+
|
|
600
606
|
### 开发手册
|
|
601
|
-
|
|
602
|
-
-
|
|
607
|
+
写前端代码前,用 curl 抓取以下开发手册:
|
|
608
|
+
- \`curl -sSL '${platformUrl}/runtime/frontend-guide/doc.md'\`
|
|
603
609
|
- 手册包含:前后端数据契约(StepOutcome → StepRenderCtx)、Widget 选型与用法(defineWidgetStep、内置 Interactive/Display Widget)、自定义 Widget 开发、多语言接入。
|
|
604
610
|
|
|
605
611
|
### 后端 SDK 参考
|
|
@@ -608,9 +614,9 @@ ${templateDocs[inputType] || templateDocs.custom}
|
|
|
608
614
|
- \`PipelineContext\`:读 \`.venv/**/minus_ai_sdk/pipeline/context.py\`
|
|
609
615
|
|
|
610
616
|
### 前端 SDK 参考
|
|
611
|
-
@minus/* 包通过平台 CDN
|
|
612
|
-
- Widget
|
|
613
|
-
-
|
|
617
|
+
@minus/* 包通过平台 CDN 加载,本地无源码。写前端代码前,用 curl 抓取以下文档了解可用 API:
|
|
618
|
+
- Widget 框架:\`curl -sSL '${platformUrl}/runtime/widget-framework/docs.md'\`
|
|
619
|
+
- 平台组件:\`curl -sSL '${platformUrl}/runtime/platform-widgets/docs.md'\`
|
|
614
620
|
|
|
615
621
|
修改前端代码后,同步更新 \`frontend/src/locales/\` 下的多语言文件。
|
|
616
622
|
|
|
@@ -624,9 +630,10 @@ ${templateDocs[inputType] || templateDocs.custom}
|
|
|
624
630
|
// README.md
|
|
625
631
|
writeOut(join(targetDir, 'README.md'), render(readTemplate('README.md.tpl'), vars))
|
|
626
632
|
|
|
627
|
-
// frontend/assets/ 和 tests/
|
|
633
|
+
// frontend/assets/ 和 tests/ 目录(pytest 骨架:新 skill 天生带测试)
|
|
628
634
|
writeOut(join(targetDir, 'frontend', 'assets', '.gitkeep'), '')
|
|
629
|
-
writeOut(join(targetDir, 'tests', '.
|
|
635
|
+
writeOut(join(targetDir, 'tests', 'conftest.py'), render(readTemplate('conftest.py.tpl'), vars))
|
|
636
|
+
writeOut(join(targetDir, 'tests', 'test_pipeline.py'), render(readTemplate('test_pipeline.py.tpl'), vars))
|
|
630
637
|
|
|
631
638
|
const rootPkgContent = render(readTemplate('root-package.json.tpl'), vars)
|
|
632
639
|
const fePkgContent = render(readTemplate('frontend-package.json.tpl'), vars)
|
package/package.json
CHANGED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
# ──────────────────────────────────────────────────────────────────────────────
|
|
4
|
+
# SDK 参考(纯注释,读懂后可整段删除)
|
|
5
|
+
#
|
|
6
|
+
# StepOutcome 三态与 ctx 能力(entry_params / previous_outputs / last_user_input /
|
|
7
|
+
# sif / llm / upload_file)的权威定义和用法,读已安装 SDK 的模块头注释与 docstring:
|
|
8
|
+
# .venv/**/minus_ai_sdk/pipeline/context.py
|
|
9
|
+
# .venv/**/minus_ai_sdk/pipeline/outcome.py
|
|
10
|
+
# 不要凭记忆写签名——以上述源码为准(SDK 会原地更新,文档随包发布永不过期)。
|
|
11
|
+
#
|
|
12
|
+
# 唯一容易写反的语义:StepOutcome.input_required 暂停后,用户提交的内容
|
|
13
|
+
# 挂在「下一步」的 ctx.last_user_input,而不是重跑本步。
|
|
14
|
+
# ──────────────────────────────────────────────────────────────────────────────
|
|
@@ -9,9 +9,16 @@ dependencies = [
|
|
|
9
9
|
"uvicorn[standard]",
|
|
10
10
|
]
|
|
11
11
|
|
|
12
|
+
[project.optional-dependencies]
|
|
13
|
+
dev = ["pytest", "pytest-asyncio"]
|
|
14
|
+
|
|
12
15
|
[tool.setuptools]
|
|
13
16
|
py-modules = ["pipeline", "server"]
|
|
14
17
|
|
|
15
18
|
[tool.uv]
|
|
16
19
|
# SDK wheel 可能在同一版本号下更新过,安装时绕过本地缓存强制重新下载
|
|
17
20
|
reinstall-package = ["minus-ai-sdk-python"]
|
|
21
|
+
|
|
22
|
+
[tool.pytest.ini_options]
|
|
23
|
+
asyncio_mode = "auto"
|
|
24
|
+
testpaths = ["tests"]
|
|
@@ -12,14 +12,12 @@
|
|
|
12
12
|
},
|
|
13
13
|
"workspaces": ["frontend"],
|
|
14
14
|
"scripts": {
|
|
15
|
-
"dev": "minus-dev
|
|
16
|
-
"dev:backend": "minus-dev
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"build": "cd frontend && pnpm run build"
|
|
15
|
+
"dev": "minus-dev --port {{port}}",
|
|
16
|
+
"dev:backend": "minus-dev --port {{port}} --backend-only",
|
|
17
|
+
"build": "cd frontend && pnpm run build",
|
|
18
|
+
"test": ".venv/bin/pytest tests"
|
|
20
19
|
},
|
|
21
20
|
"devDependencies": {
|
|
22
|
-
"@minus-ai/dev-vite-plugin": "^0.1.0-beta.
|
|
23
|
-
"concurrently": "^9.1.2"
|
|
21
|
+
"@minus-ai/dev-vite-plugin": "^0.1.0-beta.14"
|
|
24
22
|
}
|
|
25
23
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""pipeline step 函数的 payload 结构测试骨架。
|
|
2
|
+
|
|
3
|
+
约定(与平台测试体系一致):
|
|
4
|
+
- 直接调用 step 函数,不起 HTTP/SSE;外部 API 用 monkeypatch mock。
|
|
5
|
+
- 断言 payload 的关键字段 + 类型,不断言会漂移的具体数据值。
|
|
6
|
+
运行:.venv/bin/pytest(需先 .venv/bin/pip install pytest pytest-asyncio)
|
|
7
|
+
"""
|
|
8
|
+
from types import SimpleNamespace
|
|
9
|
+
|
|
10
|
+
import pipeline as pl
|
|
11
|
+
from minus_ai_sdk import StepOutcome
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class FakeContext:
|
|
15
|
+
"""鸭子类型 PipelineContext:step 函数常用的成员。"""
|
|
16
|
+
|
|
17
|
+
def __init__(self, entry_params=None, last_user_input=None, previous_outputs=None):
|
|
18
|
+
self.entry_params = entry_params or {}
|
|
19
|
+
self.last_user_input = last_user_input or {}
|
|
20
|
+
self.previous_outputs = previous_outputs or {}
|
|
21
|
+
self.sif = SimpleNamespace() # 外部 API 客户端按需 monkeypatch
|
|
22
|
+
self.emitted = []
|
|
23
|
+
|
|
24
|
+
async def emit(self, message_type, payload=None):
|
|
25
|
+
self.emitted.append((message_type, payload))
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
async def test_step_1_returns_valid_outcome():
|
|
29
|
+
ctx = FakeContext(entry_params={})
|
|
30
|
+
outcome = await pl.{{className}}.step_1(SimpleNamespace(), ctx)
|
|
31
|
+
assert isinstance(outcome, StepOutcome)
|
|
32
|
+
assert isinstance(outcome.payload, dict)
|
|
33
|
+
# TODO: 按你的 step payload 契约补充关键字段断言,例如:
|
|
34
|
+
# assert outcome.kind.value == "input_required"
|
|
35
|
+
# assert isinstance(outcome.payload["rows"], list)
|