mirror of
https://git.openapi.site/https://github.com/desirecore/market.git
synced 2026-10-20 23:24:56 +08:00
## 中文 新增按需调用的内置技能 `app-developer`(应用开发与发布):中英正文、sidecar、MIT 许可、静态与服务两个通用工作台示例,以及作者接口与分发参考,并登记进 `builtin-skills.json`。作者管理优先使用 AppManage 的有限动作,执行前须通过 `authoring_capabilities` 确认 `app-authoring-v1`,能力不可用时停止受影响的操作;外部 Node/Docker 运行时、托管、Git 服务与数据库的条款和可能费用已在发现文案、compatibility 与正文披露。另将 dev-environment-setup 探测参考中的三处用户 home 示例改为通用路径。 与 #220、#212 合入后的 main 解决 manifest 冲突:技能总数 144,市场版本 1.5.13。验证:catalog 与 i18n 校验 0 errors / 106 warnings(含新技能尚未 ref-bound review 的治理提醒),translate --check 与 git diff --check 通过;远端 validate、translate、CodeQL 通过。Copilot 因额度用尽未能审查。 ## English Add the on-demand builtin `app-developer` skill (application development and publishing): English/Chinese bodies, sidecar, MIT license, static and service workbench examples, plus authoring-interface and distribution references, registered in `builtin-skills.json`. Authoring prefers AppManage's finite actions and must confirm `app-authoring-v1` through `authoring_capabilities` first, stopping affected operations when the capability is unavailable. External Node/Docker runtime, hosting, Git service and database terms and possible costs are disclosed. Three user-home examples in the dev-environment-setup probe reference are neutralized. The manifest conflict with main after #220 and #212 is resolved: 144 skills, market version 1.5.13. Catalog and i18n validation report 0 errors with 106 warnings (including the new skill's pending ref-bound review notice); translate --check and git diff --check pass; remote validate, translate and CodeQL passed. Copilot could not review because of its quota limit.
35 lines
2.9 KiB
JavaScript
35 lines
2.9 KiB
JavaScript
/** 教学清单生成器:读取显式inputs,固定原始字节;不是平台自动build/install器。 */
|
||
import { createHash } from 'node:crypto'
|
||
import { lstatSync, readFileSync, writeFileSync } from 'node:fs'
|
||
import { resolve, join } from 'node:path'
|
||
|
||
if (!process.argv[2]) throw new Error('example_directory_required')
|
||
const directory = resolve(process.argv[2])
|
||
const input = JSON.parse(readFileSync(join(directory, 'release-inputs.json'), 'utf8'))
|
||
const hash = bytes => createHash('sha256').update(bytes).digest('hex')
|
||
const canonical = value => Array.isArray(value) ? value.map(canonical) : value && typeof value === 'object'
|
||
? Object.fromEntries(Object.keys(value).sort().map(key => [key, canonical(value[key])])) : value
|
||
const files = input.files.map(file => {
|
||
if (typeof file.path !== 'string' || /[\\\x00-\x1f?#:]/.test(file.path) || file.path.startsWith('/') ||
|
||
file.path.split('/').some(part => !part || part === '.' || part === '..') || file.path === 'app-release.json') throw new Error('invalid_payload_path')
|
||
const parts = file.path.split('/')
|
||
for (let i = 1; i <= parts.length; i++) if (lstatSync(join(directory, ...parts.slice(0, i))).isSymbolicLink()) throw new Error('payload_link_rejected')
|
||
const bytes = readFileSync(join(directory, file.path))
|
||
return { path: file.path, role: file.role, sha256: hash(bytes), size: bytes.length }
|
||
}).sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0)
|
||
if (new Set(files.map(file => file.path)).size !== files.length) throw new Error('duplicate_payload_path')
|
||
if (!files.some(file => file.path === 'application.json' && file.role === 'definition') ||
|
||
!files.some(file => file.path === '说明.md') ||
|
||
(input.dataContractPath && !files.some(file => file.path === input.dataContractPath && file.role === 'data-contract'))) throw new Error('missing_declared_payload')
|
||
const definition = JSON.parse(readFileSync(join(directory, 'application.json'), 'utf8'))
|
||
const manifest = { schemaVersion: 1, canonicalization: 'app-release-c14n-v1', definition, delivery: input.delivery, files,
|
||
source: { kind: 'worktree', sha256: hash(JSON.stringify(canonical(files))) }, supportedPlatforms: input.supportedPlatforms,
|
||
minimumClientVersion: '10.0.180', requiredCapabilities: input.requiredCapabilities,
|
||
...(input.dataContractPath ? { dataContract: JSON.parse(readFileSync(join(directory, input.dataContractPath), 'utf8')) } : {}),
|
||
...(input.bridgeCapabilities ? { bridgeCapabilities: input.bridgeCapabilities } : {}),
|
||
...(input.viewStateContract ? { viewStateContract: input.viewStateContract } : {}),
|
||
instructionsPath: '说明.md' }
|
||
manifest.releaseDigest = hash(JSON.stringify(canonical(manifest)))
|
||
writeFileSync(join(directory, 'app-release.json'), JSON.stringify(manifest, null, 2) + '\n')
|
||
console.log(JSON.stringify({ appId: definition.id, version: definition.version, releaseDigest: manifest.releaseDigest, files: files.length }))
|