openyida 2026.9.11 → 2026.9.12
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/README.md +7 -5
- package/bin/yida.js +1 -0
- package/lib/ai/ai.js +2 -0
- package/lib/app/compile.js +39 -1
- package/lib/app/update-app.js +17 -2
- package/lib/asset/ai-image.js +37 -65
- package/lib/asset/asset-cmd.js +151 -110
- package/lib/asset/asset-plan.js +105 -0
- package/lib/asset/asset-resolve.js +343 -225
- package/lib/asset/asset-status.js +20 -31
- package/lib/asset/attachment-upload.js +29 -0
- package/lib/asset/host-capabilities.js +91 -0
- package/lib/asset/image-metadata.js +104 -0
- package/lib/asset/url-verify.js +90 -130
- package/lib/core/agent-capabilities.js +11 -0
- package/lib/core/command-manifest.js +25 -11
- package/lib/core/locales/en.js +6 -2
- package/lib/core/locales/zh.js +6 -2
- package/lib/design-plan/materialize.js +7 -9
- package/lib/design-plan/normalize.js +11 -1
- package/lib/process/services/process-actions.js +145 -0
- package/lib/process/services/process-compiler.js +4 -30
- package/lib/process/services/process-view-verifier.js +31 -0
- package/package.json +1 -1
- package/scripts/postinstall.js +1 -1
- package/yida-skills/SKILL.md +3 -2
- package/yida-skills/skills/yida-app/SKILL.md +1 -1
- package/yida-skills/skills/yida-app/workflow/step-2-design.md +11 -1
- package/yida-skills/skills/yida-app/workflow/step-3-create-or-reuse-app.md +21 -1
- package/yida-skills/skills/yida-app/workflow/step-5-seed-records.md +11 -7
- package/yida-skills/skills/yida-app/workflow/step-7-page-code.md +4 -0
- package/yida-skills/skills/yida-canvas-custom-page/SKILL.md +5 -3
- package/yida-skills/skills/yida-canvas-custom-page/references/component-library-guide.md +1 -1
- package/yida-skills/skills/yida-canvas-custom-page/references/page-generation-guide.md +3 -27
- package/yida-skills/skills/yida-canvas-table-form/SKILL.md +1 -1
- package/yida-skills/skills/yida-create-app/SKILL.md +4 -4
- package/yida-skills/skills/yida-create-process/SKILL.md +2 -0
- package/yida-skills/skills/yida-custom-page/references/assets-guide.md +9 -12
- package/yida-skills/skills/yida-design/SKILL.md +1 -0
- package/yida-skills/skills/yida-design/references/ask-human-interaction-contract.md +4 -4
- package/yida-skills/skills/yida-design/references/asset-workflow.md +14 -53
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/references/build-plan-compact-schema.md +1 -1
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/references/build-plan-schema.md +21 -4
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/scripts/render_build_plan.py +1 -2
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/scripts/validate_design_themes.py +1 -1
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/README.md +1 -1
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/airy-media-grid.md +1 -1
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/airy-modular-clarity.md +1 -1
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/airy-structured-clarity.md +1 -1
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/ambient-halo-layered.md +1 -1
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/dark-focus-layered.md +1 -1
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/dark-luminous-modular.md +1 -1
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/deep-stage-duotone.md +1 -1
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/hairline-runway-clarity.md +1 -1
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/high-contrast-modular.md +1 -1
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/interlocked-vivid-modules.md +1 -1
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/matrix-grid-focus.md +1 -1
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/media-rail-inspector.md +1 -1
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/mist-layered-signal.md +1 -1
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/modular-rail-signal.md +1 -1
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/mono-grid-signal.md +2 -2
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/ribbon-ledger-lift.md +1 -1
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/segmented-meter-clarity.md +1 -1
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/split-rail-precision.md +1 -1
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/status-framed-media-grid.md +1 -1
- package/yida-skills/skills/yida-design/workflow/output-design.md +4 -0
- package/yida-skills/skills/yida-design/workflow/step-4-wireframe-interaction.md +1 -1
- package/yida-skills/skills/yida-design/workflow/step-5-visual-states.md +2 -1
- package/yida-skills/skills/yida-image-assets/SKILL.md +91 -0
- package/yida-skills/skills/yida-image-assets/references/manifest-contract.md +87 -0
- package/yida-skills/skills/yida-image-assets/references/source-policy.md +19 -0
- package/yida-skills/skills/yida-nav-shell/references/nav-shell-patterns.md +1 -1
- package/yida-skills/skills/yida-prd/workflow/output-prd.md +2 -2
- package/yida-skills/skills/yida-process-rule/SKILL.md +6 -1
- package/yida-skills/skills/yida-process-rule/references/approval-actions.md +48 -0
- package/yida-skills/skills/yida-rechart/SKILL.md +1 -1
- package/yida-skills/skills/yida-requirement-analysis/SKILL.md +1 -1
- package/yida-skills/skills/yida-requirement-analysis/workflow/prepare-brief.md +22 -13
- package/yida-skills/skills-index.json +18 -1
package/README.md
CHANGED
|
@@ -210,6 +210,8 @@ openyida data create form APP_XXX FORM_XXX --expect-form-name 客户 --expect-fo
|
|
|
210
210
|
openyida get-permission APP_XXX FORM_XXX
|
|
211
211
|
```
|
|
212
212
|
|
|
213
|
+
Append and forward permissions are configured in the process definition through `nodes[].actions.normalActions/appendActions`. Both `create-process` and `configure-process` compile these settings into matching designer and runtime properties. See [approval action configuration](yida-skills/skills/yida-process-rule/references/approval-actions.md) for the JSON example, defaults, and verification limits.
|
|
214
|
+
|
|
213
215
|
`configure-process` 的流程 JSON 中,审批人可配置为发起人、指定成员、指定角色、部门主管或直属主管,例如:
|
|
214
216
|
|
|
215
217
|
```json
|
|
@@ -431,7 +433,7 @@ Run `openyida --help` or `openyida <command> --help` for detailed usage.
|
|
|
431
433
|
| `openyida create-page <appType> "<name>" [--mode dashboard] [--hide-nav] [--locale zh_CN\|en_US\|ja_JP] [--open\|--no-open]` | Create a custom display page |
|
|
432
434
|
| `openyida build-page <sourceFile> [--output file\|--write]` | Build Yida-compatible page source |
|
|
433
435
|
| `openyida check-page <src> [--compat]` | Check custom page standards |
|
|
434
|
-
| `openyida compile <src
|
|
436
|
+
| `openyida compile <src> [--canvas] [--json]` | Compile custom page locally |
|
|
435
437
|
| `openyida publish <src> <appType> <formUuid> [--health-check] [--force] [--canvas] [--auto-nav-order] [--open\|--no-open]` | Compile and publish custom page |
|
|
436
438
|
| `openyida update-form-config <appType> <formUuid> <true\|false\|keep> "<title>" [--locale zh_CN\|en_US\|ja_JP]` | Update form configuration |
|
|
437
439
|
| `openyida get-form-config <appType> <formUuid> [--json]` | Query form configuration |
|
|
@@ -454,8 +456,8 @@ Run `openyida --help` or `openyida <command> --help` for detailed usage.
|
|
|
454
456
|
|
|
455
457
|
| Command | Description |
|
|
456
458
|
|---------|-------------|
|
|
457
|
-
| `openyida configure-process <appType> <formUuid> <definition> [processCode] [--replace]` | Configure and publish process rules |
|
|
458
|
-
| `openyida create-process <appType> ... [--replace]` | Create process form (all-in-one) |
|
|
459
|
+
| `openyida configure-process <appType> <formUuid> <definition> [processCode] [--replace]` | Configure and publish process rules; Supports append/forward via JSON nodes[].actions.normalActions/appendActions |
|
|
460
|
+
| `openyida create-process <appType> ... [--replace]` | Create process form (all-in-one); Supports append/forward via JSON nodes[].actions.normalActions/appendActions |
|
|
459
461
|
| `openyida ai-form-setting <get\|fields\|models\|enable\|disable\|save> <appType> ...` | Manage process form AI approval prompts |
|
|
460
462
|
| `openyida process preview <appType> ...` | Preview process instance (visual flowchart) |
|
|
461
463
|
|
|
@@ -529,7 +531,7 @@ Run `openyida --help` or `openyida <command> --help` for detailed usage.
|
|
|
529
531
|
| `openyida batch <file>\|--commands "cmd1 ; cmd2" [--stop-on-error] [--json]` | Run OpenYida commands in batch |
|
|
530
532
|
| `openyida flash-to-prd --file <path> --name "<project>"` | Convert flash notes or meeting notes to a PRD prompt |
|
|
531
533
|
| `openyida ai <text\|image> [options]` | Call Yida AI text and image recognition APIs |
|
|
532
|
-
| `openyida asset <status\|resolve\|
|
|
534
|
+
| `openyida asset <status\|resolve\|sources> [options]` | Detect asset capability / resolve materials |
|
|
533
535
|
| `openyida cdn-config [options]` | Configure CDN / OSS upload |
|
|
534
536
|
| `openyida cdn-upload <image-path>` | Upload image to CDN |
|
|
535
537
|
| `openyida cdn-refresh [options]` | Refresh CDN cache |
|
|
@@ -560,7 +562,7 @@ The runner rejects public generic echo services such as httpbin and example.com.
|
|
|
560
562
|
|
|
561
563
|
The opt-in `node scripts/e2e-real/connector/action-update-runner.js` regression uses the owner-confirmed login-free `www.aliwork.com` fixture and a single owned NONE-auth connector containing a target action plus one preservation sentinel. Enable it with `OPENYIDA_E2E=1 OPENYIDA_E2E_CONNECTOR_ACTION_UPDATE=1`. It verifies isolated `currentPage`, `pageSize`, `userLanguage`, `searchFieldJson`, and dynamic `_stamp` edits, restores each field and the final baseline, and persists only response structure, data count, and SHA-256. It never stores response row values or auth/profile/corp identifiers, never retries unknown writes, and intentionally leaves the owned connector as a `cleanup_blocked` residual because no proven delete API exists.
|
|
562
564
|
|
|
563
|
-
`openyida asset resolve --
|
|
565
|
+
`openyida asset resolve --input manifest-draft.json --manifest asset-manifest.json --json` validates every image slot and writes a traceable manifest. Search assets only accept Unsplash/Pexels; draft results exit with code 2. Use `--offline` to block URL checks and uploads.
|
|
564
566
|
|
|
565
567
|
#### Environment and Localization
|
|
566
568
|
|
package/bin/yida.js
CHANGED
|
@@ -496,6 +496,7 @@ const MANIFEST_HELP_PATHS = Object.freeze({
|
|
|
496
496
|
data: ['data'],
|
|
497
497
|
report: ['report'],
|
|
498
498
|
'create-process': ['create-process'],
|
|
499
|
+
'configure-process': ['configure-process'],
|
|
499
500
|
'create-report': ['create-report'],
|
|
500
501
|
'append-chart': ['append-chart'],
|
|
501
502
|
'save-share-config': ['save-share-config'],
|
package/lib/ai/ai.js
CHANGED
|
@@ -31,6 +31,7 @@ const IMAGE_MIME_TYPES = {
|
|
|
31
31
|
'.gif': 'image/gif',
|
|
32
32
|
'.webp': 'image/webp',
|
|
33
33
|
'.bmp': 'image/bmp',
|
|
34
|
+
'.svg': 'image/svg+xml',
|
|
34
35
|
};
|
|
35
36
|
|
|
36
37
|
function printHelp() {
|
|
@@ -500,6 +501,7 @@ module.exports = {
|
|
|
500
501
|
getAuthRef,
|
|
501
502
|
callTextFromAI,
|
|
502
503
|
uploadImageForAI,
|
|
504
|
+
inferAppType,
|
|
503
505
|
invokeImageRecognition,
|
|
504
506
|
normalizeImageResult,
|
|
505
507
|
parseArgs,
|
package/lib/app/compile.js
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const { compileSource } = require('./page-compiler');
|
|
6
|
+
const { compileCanvasPageSource } = require('./services/canvas-page-compiler');
|
|
7
|
+
const { loadPageSource } = require('./services/page-source-loader');
|
|
6
8
|
const { runLintCheck } = require('./page-linter');
|
|
7
9
|
const { buildPageFile, shouldBuildPageSource } = require('./page-compat');
|
|
8
10
|
const { warnLargePageSource } = require('./page-size-guard');
|
|
@@ -23,7 +25,20 @@ async function run(args) {
|
|
|
23
25
|
|
|
24
26
|
const skipLint = args.includes('--skip-lint');
|
|
25
27
|
const compat = args.includes('--compat') || args.includes('--modern');
|
|
26
|
-
const
|
|
28
|
+
const canvas = args.includes('--canvas');
|
|
29
|
+
const json = args.includes('--json');
|
|
30
|
+
const filteredArgs = args.filter(arg => ![
|
|
31
|
+
'--skip-lint',
|
|
32
|
+
'--compat',
|
|
33
|
+
'--modern',
|
|
34
|
+
'--canvas',
|
|
35
|
+
'--json',
|
|
36
|
+
].includes(arg));
|
|
37
|
+
if (filteredArgs.length < 1) {
|
|
38
|
+
throwUsage(t('cli.compile_usage'), t('cli.compile_example'), {
|
|
39
|
+
code: 'COMPILE_INVALID_ARGUMENTS',
|
|
40
|
+
});
|
|
41
|
+
}
|
|
27
42
|
let sourcePath = path.resolve(filteredArgs[0]);
|
|
28
43
|
if (!fs.existsSync(sourcePath)) {
|
|
29
44
|
throwCommandError(t('publish.source_not_found', sourcePath), {
|
|
@@ -32,6 +47,29 @@ async function run(args) {
|
|
|
32
47
|
});
|
|
33
48
|
}
|
|
34
49
|
|
|
50
|
+
if (canvas || /\.canvas\.(?:jsx?|tsx?)$/i.test(sourcePath)) {
|
|
51
|
+
const workspaceRoot = process.cwd();
|
|
52
|
+
const relativeSourcePath = path.relative(workspaceRoot, sourcePath);
|
|
53
|
+
const loadedSource = loadPageSource(relativeSourcePath, { workspaceRoot });
|
|
54
|
+
const compiled = compileCanvasPageSource(loadedSource);
|
|
55
|
+
const payload = {
|
|
56
|
+
ok: true,
|
|
57
|
+
pageType: 'canvas',
|
|
58
|
+
sourcePath: fs.realpathSync(sourcePath),
|
|
59
|
+
profile: compiled.profile,
|
|
60
|
+
inputHash: compiled.inputHash,
|
|
61
|
+
sourceHash: compiled.sourceHash,
|
|
62
|
+
compiledHash: compiled.compiledHash,
|
|
63
|
+
importedModules: JSON.parse(compiled.importedModules),
|
|
64
|
+
};
|
|
65
|
+
if (json) {
|
|
66
|
+
console.log(JSON.stringify(payload));
|
|
67
|
+
} else {
|
|
68
|
+
info(JSON.stringify(payload, null, 2));
|
|
69
|
+
}
|
|
70
|
+
return payload;
|
|
71
|
+
}
|
|
72
|
+
|
|
35
73
|
const initialSourceCode = fs.readFileSync(sourcePath, 'utf-8');
|
|
36
74
|
warnLargePageSource(initialSourceCode, sourcePath);
|
|
37
75
|
if (shouldBuildPageSource(initialSourceCode, sourcePath, { modern: compat })) {
|
package/lib/app/update-app.js
CHANGED
|
@@ -221,6 +221,16 @@ function normalizeLayoutDirection(layoutDirection) {
|
|
|
221
221
|
return normalized;
|
|
222
222
|
}
|
|
223
223
|
|
|
224
|
+
/** 与 yc-utils 的应用配置归一化一致;不应用详情页 Shell 的 top_fold 覆盖。 */
|
|
225
|
+
function normalizeStoredLayoutDirection(layoutDirection, navType) {
|
|
226
|
+
if (SUPPORTED_LAYOUT_DIRECTIONS.includes(layoutDirection)) {return layoutDirection;}
|
|
227
|
+
if (layoutDirection === 'hoz') {return navType === 'top_side' ? 'l_shape' : 'top';}
|
|
228
|
+
if (layoutDirection === 'ver') {return 'side';}
|
|
229
|
+
if (navType === 'top_fold') {return 'top';}
|
|
230
|
+
if (navType === 'top_side') {return 'l_shape';}
|
|
231
|
+
return 'side';
|
|
232
|
+
}
|
|
233
|
+
|
|
224
234
|
function pickAppField(currentApp, fieldName, configName) {
|
|
225
235
|
if (currentApp[fieldName] !== undefined && currentApp[fieldName] !== null) {
|
|
226
236
|
return currentApp[fieldName];
|
|
@@ -296,6 +306,8 @@ function buildUpdateAppPostData(params, currentApp = {}, authRef) {
|
|
|
296
306
|
const currentCustomThemeStyle = pickAppField(currentApp, 'customThemeStyle', 'CUSTOM_THEME_STYLE');
|
|
297
307
|
const addWaterMark = pickAppField(currentApp, 'addWaterMark', 'ADDWATERMARK');
|
|
298
308
|
const sentryMode = pickAppField(currentApp, 'sentryMode', 'SENTRY_MODE');
|
|
309
|
+
const currentNavType = currentApp.navType || (currentApp.config && currentApp.config.NAVTYPE);
|
|
310
|
+
const currentLayoutDirection = currentApp.layoutDirection || (currentApp.config && currentApp.config.LAY_OUT_DIRECTION);
|
|
299
311
|
if (params.colour === 'custom' && !params.themeColor && !currentThemeColor) {
|
|
300
312
|
throw new Error(t('update_app.custom_theme_color_required'));
|
|
301
313
|
}
|
|
@@ -319,9 +331,10 @@ function buildUpdateAppPostData(params, currentApp = {}, authRef) {
|
|
|
319
331
|
mode: currentApp.mode || (currentApp.config && currentApp.config.APPMODE) || 'normal',
|
|
320
332
|
type: currentApp.type || (currentApp.config && currentApp.config.APPTYPE) || 'single',
|
|
321
333
|
navTheme: params.navTheme || currentApp.navTheme || (currentApp.config && currentApp.config.NAV_THEME) || 'light',
|
|
322
|
-
navType: currentApp.navType || (currentApp.config && currentApp.config.NAVTYPE) || 'top_side',
|
|
323
334
|
navLayout: currentApp.navLayout || (currentApp.config && currentApp.config.NAVLAYOUT) || 'auto',
|
|
324
|
-
layoutDirection: params.layoutDirection
|
|
335
|
+
layoutDirection: params.layoutDirection
|
|
336
|
+
? normalizeLayoutDirection(params.layoutDirection)
|
|
337
|
+
: normalizeStoredLayoutDirection(currentLayoutDirection, currentNavType),
|
|
325
338
|
homepageLogo: currentApp.homepageLogo || (currentApp.config && currentApp.config.HOMEPAGELOGO) || '',
|
|
326
339
|
logoSource: params.logoSource || currentApp.logoSource || (currentApp.config && currentApp.config.LOGO_SOURCE) || 'appIcon',
|
|
327
340
|
logoLink: currentApp.logoLink || (currentApp.config && currentApp.config.LOGOLINK) || '',
|
|
@@ -346,6 +359,8 @@ function buildUpdateAppPostData(params, currentApp = {}, authRef) {
|
|
|
346
359
|
pageFooter: currentApp.pageFooter || '',
|
|
347
360
|
};
|
|
348
361
|
|
|
362
|
+
// ThemeNavSetting 保存现有 navType;新布局由 layoutDirection 控制,不反写或补造旧字段。
|
|
363
|
+
if (currentNavType) {postDataObj.navType = currentNavType;}
|
|
349
364
|
if (addWaterMark !== undefined && addWaterMark !== null) {
|
|
350
365
|
postDataObj.addWaterMark = addWaterMark;
|
|
351
366
|
}
|
package/lib/asset/ai-image.js
CHANGED
|
@@ -1,89 +1,60 @@
|
|
|
1
1
|
|
|
2
|
-
/**
|
|
3
|
-
* ai-image.js - 图片素材来源能力检测(诚实降级 + 引导本地 agent)
|
|
4
|
-
*
|
|
5
|
-
* P3 素材工具化的关键澄清:openyida 本身没有内置「文生图」API,
|
|
6
|
-
* `openyida ai` 只支持文生文与识图,不能凭空生成图片 URL。
|
|
7
|
-
*
|
|
8
|
-
* 因此本模块不假装能生成图片,而是:
|
|
9
|
-
* 1. 诚实地检测「是否存在内置图片生成能力」(目前恒为 false);
|
|
10
|
-
* 2. 把「生成/寻找素材」这件事交回给正在驱动本 CLI 的智能体(Claude/Codex 等),
|
|
11
|
-
* 由 skill 文档引导它:能自己生成就生成,否则去免费素材库搜真实图片;
|
|
12
|
-
* 3. 提供推荐的免费/可商用素材库清单与使用纪律,供 skill / agent 参考。
|
|
13
|
-
*
|
|
14
|
-
* 无论走哪条路,候选素材都交给 asset resolve 统一解析;有 CDN 时再转存,
|
|
15
|
-
* 绝不把编造的 URL 直接写进页面。
|
|
16
|
-
*
|
|
17
|
-
* 用法:
|
|
18
|
-
* const { detectImageGenerator, getFreeStockLibraries, getMaterialSourcingGuidance } = require('./ai-image');
|
|
19
|
-
* const g = detectImageGenerator(); // { available:false, reason, delegateToAgent:true }
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
2
|
'use strict';
|
|
23
3
|
|
|
24
|
-
/**
|
|
25
|
-
* 推荐的免费 / 可商用图片素材库
|
|
26
|
-
* 说明:这些站点提供免费可商用(多为 CC0 / 自有免费授权)的高质量图片,
|
|
27
|
-
* 适合官网 Hero、产品图、场景配图。agent 应优先从这里取真实图片 URL,
|
|
28
|
-
* 取到后交给 `openyida asset resolve` 统一处理。
|
|
29
|
-
*/
|
|
30
4
|
const FREE_STOCK_LIBRARIES = [
|
|
31
5
|
{
|
|
32
6
|
name: 'Unsplash',
|
|
33
7
|
site: 'https://unsplash.com',
|
|
34
|
-
license: 'Unsplash License
|
|
35
|
-
bestFor: '
|
|
36
|
-
directImageHint:
|
|
37
|
-
|
|
8
|
+
license: '遵守 Unsplash License 和 API Guidelines',
|
|
9
|
+
bestFor: 'Hero、生活方式和场景图',
|
|
10
|
+
directImageHint: '使用 API 返回的 images.unsplash.com URL。',
|
|
11
|
+
deliveryPolicy: '下载授权图片后上传宜搭附件;保留署名和 download_location 记录。',
|
|
38
12
|
},
|
|
39
13
|
{
|
|
40
14
|
name: 'Pexels',
|
|
41
15
|
site: 'https://www.pexels.com',
|
|
42
|
-
license: 'Pexels License
|
|
43
|
-
bestFor: '
|
|
16
|
+
license: '遵守 Pexels License 和 API Guidelines',
|
|
17
|
+
bestFor: '产品、办公、人物和场景图',
|
|
44
18
|
directImageHint: 'images.pexels.com/photos/... 形式为图片直链。',
|
|
45
|
-
|
|
46
|
-
{
|
|
47
|
-
name: 'Pixabay',
|
|
48
|
-
site: 'https://pixabay.com',
|
|
49
|
-
license: 'Pixabay Content License(免费可商用)',
|
|
50
|
-
bestFor: '插画、矢量、照片综合库',
|
|
51
|
-
directImageHint: 'cdn.pixabay.com/photo/... 形式为图片直链。',
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
name: 'Undraw',
|
|
55
|
-
site: 'https://undraw.co/illustrations',
|
|
56
|
-
license: 'unDraw open-source license(免费可商用,可改色)',
|
|
57
|
-
bestFor: '扁平风品牌插画、空状态/引导插画(SVG,可随品牌色变量着色)',
|
|
58
|
-
directImageHint: '导出 SVG 或使用官方 CDN SVG 直链。',
|
|
19
|
+
deliveryPolicy: '下载后上传宜搭附件;保留 Pexels 链接和摄影师信息。',
|
|
59
20
|
},
|
|
60
21
|
];
|
|
61
22
|
|
|
62
23
|
/**
|
|
63
24
|
* 检测是否存在「内置图片生成能力」。
|
|
64
25
|
*
|
|
65
|
-
*
|
|
66
|
-
* 由
|
|
26
|
+
* openyida 无内置文生图连接器。宿主能力未确认时返回 available:null,
|
|
27
|
+
* 由 Agent 检查真实工具清单。
|
|
67
28
|
*
|
|
68
29
|
* @param {object} [options]
|
|
69
|
-
* @
|
|
70
|
-
* @returns {{ available: boolean, reason: string, delegateToAgent: boolean }}
|
|
30
|
+
* @returns {{ status: string, available: boolean|null, reason: string, delegateToAgent: boolean }}
|
|
71
31
|
*/
|
|
72
32
|
function detectImageGenerator(options = {}) {
|
|
73
|
-
|
|
33
|
+
const capability = options.hostCapabilities && options.hostCapabilities.image_generation;
|
|
34
|
+
if (capability && capability.status === 'available') {
|
|
74
35
|
return {
|
|
36
|
+
status: 'available',
|
|
75
37
|
available: true,
|
|
76
|
-
reason: '
|
|
38
|
+
reason: '当前宿主可生成图片;生成后交给 asset resolve。',
|
|
39
|
+
delegateToAgent: true,
|
|
40
|
+
source: capability.source || 'host_capability',
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
if (capability && capability.status === 'unavailable') {
|
|
44
|
+
return {
|
|
45
|
+
status: 'unavailable',
|
|
46
|
+
available: false,
|
|
47
|
+
reason: '当前宿主不支持图片生成。',
|
|
77
48
|
delegateToAgent: false,
|
|
49
|
+
source: capability.source,
|
|
78
50
|
};
|
|
79
51
|
}
|
|
80
52
|
return {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
'图片素材应由智能体自行生成,或到免费素材库(Unsplash/Pexels 等)检索真实图片,' +
|
|
85
|
-
'再交给 `openyida asset resolve` 解析、(有 CDN 时)转存 CDN 后回填 spec。',
|
|
53
|
+
status: 'unknown',
|
|
54
|
+
available: null,
|
|
55
|
+
reason: '当前宿主未确认图片生成能力。',
|
|
86
56
|
delegateToAgent: true,
|
|
57
|
+
source: (capability && capability.source) || 'host_tool_inventory_required',
|
|
87
58
|
};
|
|
88
59
|
}
|
|
89
60
|
|
|
@@ -102,17 +73,18 @@ function getFreeStockLibraries() {
|
|
|
102
73
|
function getMaterialSourcingGuidance() {
|
|
103
74
|
return {
|
|
104
75
|
steps: [
|
|
105
|
-
'1.
|
|
106
|
-
'2.
|
|
107
|
-
'3.
|
|
108
|
-
'4.
|
|
109
|
-
'5.
|
|
76
|
+
'1. 先用用户提供的素材。',
|
|
77
|
+
'2. 再从 Unsplash / Pexels 搜图。',
|
|
78
|
+
'3. 仍有缺口时使用宿主生图。',
|
|
79
|
+
'4. 最后使用中性占位并保持 draft。',
|
|
80
|
+
'5. 所有候选图通过 asset resolve 写入 manifest。',
|
|
110
81
|
],
|
|
111
82
|
libraries: getFreeStockLibraries(),
|
|
112
83
|
rules: [
|
|
113
|
-
'
|
|
114
|
-
'
|
|
115
|
-
'
|
|
84
|
+
'不编造图片 URL;按 manifest 的页面状态继续,只使用当前页 materialStatus=final 的图片。',
|
|
85
|
+
'默认下载并上传宜搭图片附件;超过 20 MiB 保留原链接;不额外探测 URL,下载失败跳过并记录缺口。',
|
|
86
|
+
'联网搜图仅使用 Unsplash / Pexels。',
|
|
87
|
+
'来源不明时使用中性占位或宿主生成图。',
|
|
116
88
|
],
|
|
117
89
|
};
|
|
118
90
|
}
|