openyida 2026.10.21 → 2026.10.22-beta.0
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 +24 -3
- package/bin/yida.js +4 -0
- package/lib/app/canvas-compile.js +8 -0
- package/lib/app/page-linter.js +10 -0
- package/lib/app/responsive-layout-guard.js +82 -0
- package/lib/auth/qwenwork-client.js +190 -0
- package/lib/auth/qwenwork.js +37 -0
- package/lib/core/command-manifest.js +18 -10
- package/lib/core/locales/en.js +63 -4
- package/lib/core/locales/zh.js +62 -3
- package/lib/core/query-data.js +40 -2
- package/lib/core/sample.js +3 -0
- package/lib/feedback/feedback.js +2 -1
- package/lib/feedback/github-setup.js +97 -0
- package/lib/feedback/github.js +17 -8
- package/lib/feedback/report.js +35 -15
- package/lib/integration/integration-triggers.js +8 -3
- package/lib/process/configure-process.js +8 -2
- package/lib/process/process-tasks.js +175 -0
- package/lib/process/services/process-actor-config.js +3 -0
- package/lib/process/services/process-compiler.js +15 -0
- package/lib/process/services/process-dynamic-actors.js +165 -0
- package/lib/samples/openyida-scaffold/canvas-nav/mixed.jsx +1 -1
- package/lib/samples/openyida-scaffold/canvas-nav/shared.jsx +1 -1
- package/lib/samples/openyida-scaffold/canvas-nav/side.jsx +1 -1
- package/lib/samples/openyida-scaffold/canvas-nav/sidebar.jsx +36 -24
- package/lib/samples/openyida-scaffold/canvas-nav/top.jsx +1 -1
- package/lib/samples/openyida-scaffold/canvas-responsive-layout.jsx +104 -0
- package/package.json +1 -1
- package/scripts/postinstall.js +1 -0
- package/yida-skills/SKILL.md +5 -2
- package/yida-skills/skills/yida-canvas-custom-page/SKILL.md +5 -1
- package/yida-skills/skills/yida-custom-page/SKILL.md +6 -2
- package/yida-skills/skills/yida-data-management/SKILL.md +24 -3
- package/yida-skills/skills/yida-data-management/references/process-task-transfer.md +53 -0
- package/yida-skills/skills/yida-density/SKILL.md +6 -1
- package/yida-skills/skills/yida-design/SKILL.md +1 -1
- package/yida-skills/skills/yida-design/references/responsive-layout.md +69 -22
- package/yida-skills/skills/yida-design/references/task-driven-visual-design.md +2 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/SKILL.md +1 -0
- 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/workflow/output-design.md +2 -2
- package/yida-skills/skills/yida-design/workflow/step-1-read-brief.md +2 -0
- package/yida-skills/skills/yida-design/workflow/step-4-wireframe-interaction.md +10 -10
- package/yida-skills/skills/yida-feedback/SKILL.md +22 -5
- package/yida-skills/skills/yida-feedback/references/github-contribution.md +14 -8
- package/yida-skills/skills/yida-feedback/references/github-setup.md +74 -0
- package/yida-skills/skills/yida-feedback/references/report-input.md +10 -2
- package/yida-skills/skills/yida-feedback/references/user-interaction.md +19 -2
- package/yida-skills/skills/yida-flow-node-config/SKILL.md +1 -1
- package/yida-skills/skills/yida-flow-node-config/references/actors.md +4 -0
- package/yida-skills/skills/yida-flow-node-config/references/dynamic-actors.md +84 -0
- package/yida-skills/skills/yida-integration/SKILL.md +1 -0
- package/yida-skills/skills/yida-integration/references/triggers.md +14 -1
- package/yida-skills/skills/yida-login/SKILL.md +12 -0
- package/yida-skills/skills/yida-prd/SKILL.md +1 -0
- package/yida-skills/skills-index.json +13 -4
package/lib/core/locales/en.js
CHANGED
|
@@ -4,6 +4,17 @@
|
|
|
4
4
|
'use strict';
|
|
5
5
|
|
|
6
6
|
module.exports = {
|
|
7
|
+
qwenwork: {
|
|
8
|
+
credential_missing: 'No cloud Agent credential is available. Run this command inside the QwenWork cloud execution environment.',
|
|
9
|
+
gateway_missing: 'QWENWORK_GATEWAY_URL or MULE_GATEWAY_URL is required.',
|
|
10
|
+
invalid_url: 'The QwenWork gateway must use HTTPS (HTTP is allowed only for loopback) and contain no credentials, query or fragment.',
|
|
11
|
+
request_failed: 'The QwenWork request failed. Check the stage and HTTP status in the diagnostic details.',
|
|
12
|
+
request_timeout: 'The QwenWork request timed out.',
|
|
13
|
+
invalid_response: 'QwenWork returned an invalid authentication or identity response.',
|
|
14
|
+
identity_mismatch: 'The returned QwenWork identity does not match the cloud execution context or exchanged credential.',
|
|
15
|
+
expired_token: 'QwenWork returned an expired user credential.',
|
|
16
|
+
usage: 'Usage: openyida auth qwenwork user-info [--json]',
|
|
17
|
+
},
|
|
7
18
|
print_template: {
|
|
8
19
|
'description': 'Manage native YiDA print templates, generate document layouts, back up, restore and request PDFs',
|
|
9
20
|
'error': 'Print template operation failed: {0}',
|
|
@@ -39,7 +50,10 @@ module.exports = {
|
|
|
39
50
|
integration_update_v2: {'usage': 'integration update <appType> <formUuid> <processCode> --patch patch.json [--dry-run] [--expect fingerprint] [--publish]'},
|
|
40
51
|
|
|
41
52
|
conditional_actors: { unavailable: 'Conditional actors are unavailable or could not be verified.', invalid: 'Invalid conditional actors: {0}' },
|
|
42
|
-
integration_triggers: {
|
|
53
|
+
integration_triggers: {
|
|
54
|
+
invalid: 'Invalid automation trigger: {0}',
|
|
55
|
+
end_required: 'Choose the timer end condition: set schedule.maxCount (1–100) for a run count or schedule.expireDate (expiry in milliseconds) for a specified time. For long-running schedules, choose a distant expiry and show the actual date in the configuration summary.',
|
|
56
|
+
},
|
|
43
57
|
permission_conditions: { invalid: 'Invalid permission conditions: {0}' },
|
|
44
58
|
agent: {
|
|
45
59
|
preflight_cli_detected: 'CLI detected; runtime will discover and report login, protocol and model status.',
|
|
@@ -477,7 +491,7 @@ Examples:
|
|
|
477
491
|
login_usage: 'Usage: openyida login [entryUrl|--public|--alibaba|--intl] [--no-browser] [--check-only] [--json] [--client-id <clientId>]',
|
|
478
492
|
login_example: 'Examples:\n openyida login # Automatically open the browser via OAuth loopback login\n openyida login --no-browser # Let the caller handle the authorization URL\n openyida login --check-only --json # Check token auth status only\n openyida login --intl # Login against the international environment\n OPENYIDA_NO_BROWSER=1 openyida login # Suppress auto-opening the browser with an environment variable\n openyida auth login # Login alias',
|
|
479
493
|
login_unsupported_option: 'Removed legacy login option is no longer supported: {0}. Use token/OAuth login; env token mode reads only OPENYIDA_* tokens.',
|
|
480
|
-
auth_usage: 'Usage: openyida auth <status|login|refresh|logout|profiles|profile switch>',
|
|
494
|
+
auth_usage: 'Usage: openyida auth <status|login|refresh|logout|profiles|profile switch|qwenwork user-info> [--json]',
|
|
481
495
|
auth_example: 'Examples:\n openyida auth status # View login status\n openyida auth profiles # List existing login profiles\n openyida auth profile switch <auth_profile> # Switch current project to an existing profile\n openyida auth login # Add a profile when the target does not exist\n openyida auth refresh # Refresh login session\n openyida auth logout # Unbind current project auth\n openyida auth logout --profile <auth_profile> # Delete a shared profile explicitly',
|
|
482
496
|
org_usage: 'Usage: openyida org <list|switch> [--json] [--corp-id <corpId>]',
|
|
483
497
|
org_example: 'Examples:\n openyida org list --json # List accessible organizations\n openyida org switch --corp-id dingXXX # Switch existing profiles first; login to add one if missing',
|
|
@@ -1132,7 +1146,7 @@ Examples:
|
|
|
1132
1146
|
|
|
1133
1147
|
import_example2: ' openyida import ./yida-export.json "Quality Traceability System (Production)"',
|
|
1134
1148
|
exec_failed: '\n❌ Execution failed: {0}',
|
|
1135
|
-
auth_usage: 'Usage: openyida auth <status|login|refresh|logout|profiles|profile switch>',
|
|
1149
|
+
auth_usage: 'Usage: openyida auth <status|login|refresh|logout|profiles|profile switch|qwenwork user-info> [--json]',
|
|
1136
1150
|
auth_example: 'Examples:\n openyida auth status # View login status\n openyida auth profiles # List existing login profiles\n openyida auth profile switch <auth_profile> # Switch current project to an existing profile\n openyida auth login # Add a profile when the target does not exist\n openyida auth refresh # Refresh login session\n openyida auth logout # Unbind current project auth\n openyida auth logout --profile <auth_profile> # Delete a shared profile explicitly',
|
|
1137
1151
|
org_usage: 'Usage: openyida org <list|switch> [--json] [--corp-id <corpId>]',
|
|
1138
1152
|
org_example: 'Examples:\n openyida org list --json # List accessible organizations\n openyida org switch --corp-id dingXXX # Switch existing profiles first; login to add one if missing',
|
|
@@ -1531,6 +1545,10 @@ Examples:
|
|
|
1531
1545
|
lint_setstate_non_timestamp: 'this.setState writes a non-timestamp field. Custom page business state should live in _customState and be updated via forceUpdate()/setCustomState(); this.setState should only carry the timestamp contract field',
|
|
1532
1546
|
lint_self_binding_missing: 'renderJsx uses this without declaring var self = this;. Add var self = this; at the top of renderJsx and use self inside closures/callbacks to avoid losing this',
|
|
1533
1547
|
lint_echarts_dom_ready: 'echarts.init is not wrapped in setTimeout; the container may not be mounted yet so the chart may not render. Use setTimeout(function(){ /* echarts.init */ }, 300)',
|
|
1548
|
+
lint_resize_observer_cleanup: 'ResizeObserver has no disconnect()/unobserve() cleanup and may keep measuring after unmount. Release it from the effect or lifecycle cleanup.',
|
|
1549
|
+
lint_responsive_viewport_only: 'Layout changes only from viewport width, so a narrow desktop sidebar, drawer, or iframe may not degrade. Measure the content container with @container or a cleaned-up ResizeObserver. Add openyida-responsive-viewport-ok only for intentional viewport-owned behavior.',
|
|
1550
|
+
lint_responsive_fixed_width: 'A fixed width of %spx may overflow a narrow container. Prefer max-width, minmax(0, 1fr), or local scrolling. Add openyida-responsive-fixed-width-ok only for an intentional fixed canvas.',
|
|
1551
|
+
lint_responsive_page_scale: 'Whole-page scale/zoom was detected. Responsive layouts should reflow content while preserving readable text and touch targets. Add openyida-responsive-scale-ok only for an intentionally scaled local visualization.',
|
|
1534
1552
|
lint_yida_api_catch: 'this.utils.yida API call has no detected .catch(); add error handling and toast the user',
|
|
1535
1553
|
lint_echarts_legacy_map_china: 'ECharts 5 no longer supports echarts/map/js/china.js. Load DataV GeoJSON and call echarts.registerMap("china", geoJson) instead',
|
|
1536
1554
|
lint_echarts_rich_label_formatter: 'ECharts label.formatter returning rich text templates is unstable in Yida custom pages; prefer plain formatter strings or precomputed label text',
|
|
@@ -2331,6 +2349,16 @@ module.exports.app_theme = {
|
|
|
2331
2349
|
module.exports.help.cmd_app_theme_snapshot = 'Archive application theme settings and CSS (read-only)';
|
|
2332
2350
|
module.exports.help.cmd_app_theme_restore = 'Check or restore an application theme snapshot (supported exact values only)';
|
|
2333
2351
|
|
|
2352
|
+
Object.assign(module.exports.process_tasks || (module.exports.process_tasks = {}), {
|
|
2353
|
+
arguments_invalid: 'Invalid arguments: query requires appType and --process-inst-id; transfer also requires --form-uuid, --to-user-id, --expect-form-name and --expect-form-type process. taskId must be a positive integer; unknown options are not supported.',
|
|
2354
|
+
query_failed: 'Process task query failed; no transfer was performed.',
|
|
2355
|
+
response_invalid: 'The task response structure, task ID or process ownership could not be verified.',
|
|
2356
|
+
not_running: 'The specified task is not running in the target process, or no running task exists; no transfer was performed.',
|
|
2357
|
+
ambiguous: 'Multiple running tasks exist. Query the task list and specify --task-id; no transfer was performed.',
|
|
2358
|
+
rejected: 'The platform rejected the administrator transfer. Check permissions and task status.',
|
|
2359
|
+
result_unknown: 'The administrator transfer result is unknown. Use nextStep to read the tasks; do not automatically retry the transfer.',
|
|
2360
|
+
unverified: 'The transfer was accepted, but readback could not verify the recipient. Use nextStep to read the tasks; do not automatically retry the transfer.',
|
|
2361
|
+
});
|
|
2334
2362
|
module.exports.data_manage_style = {
|
|
2335
2363
|
'usage': 'openyida data-manage-style guide [--json]\nopenyida data-manage-style list [--json]\nopenyida data-manage-style generate --app APP_ID --form FORM-ID --style <id> --base-css <snapshot/theme.css> --output <new.css> [--focus balanced|actions] [--field-id <actualId>]... [--emphasize-field <actualId>]... [--tag-field <selectFieldId>]... [--follow-shell] [--json]',
|
|
2336
2364
|
'data_style_invalid': 'Invalid style parameters; use actual app/form/field IDs and a style returned by list.',
|
|
@@ -2427,6 +2455,26 @@ Object.assign(module.exports.help, {'cmd_formula_contracts': 'Show formula forma
|
|
|
2427
2455
|
Object.assign(module.exports.formula_v2, {'parallel_formula': 'Use conditions/rules or all:true for parallel branches; expression is currently supported only for route branches.'});
|
|
2428
2456
|
|
|
2429
2457
|
module.exports.feedback_report = {
|
|
2458
|
+
body: {
|
|
2459
|
+
summary: 'Your goal',
|
|
2460
|
+
actual: 'What happened',
|
|
2461
|
+
expected: 'Expected result',
|
|
2462
|
+
incident: 'Environment when the problem occurred',
|
|
2463
|
+
command: 'Related operation',
|
|
2464
|
+
steps: 'How to reproduce',
|
|
2465
|
+
impact: 'Impact',
|
|
2466
|
+
evidence: 'Observed evidence',
|
|
2467
|
+
attempts: 'Attempts and results',
|
|
2468
|
+
cause: 'Cause and confidence',
|
|
2469
|
+
cause_evidence: 'Evidence for assessment',
|
|
2470
|
+
next: 'Next verification',
|
|
2471
|
+
screenshots: 'Screenshots',
|
|
2472
|
+
review_image: 'Review image before sharing',
|
|
2473
|
+
limitations: 'Test limitations',
|
|
2474
|
+
generator: 'Report generator environment (not the incident environment)',
|
|
2475
|
+
unknown: 'Unknown / not verified',
|
|
2476
|
+
draft: 'Local draft — not submitted. Review text and screenshots for customer data, credentials and private information before sharing.',
|
|
2477
|
+
},
|
|
2430
2478
|
comparison: 'Test pass/fail requires a command, actual result and evidence.',
|
|
2431
2479
|
screenshots: 'Choose at most five PNG/JPEG/WebP screenshots of at most 10 MiB each.',
|
|
2432
2480
|
text: 'Feedback text fields must be strings of at most 12000 characters.',
|
|
@@ -2514,7 +2562,18 @@ module.exports.task_center = {
|
|
|
2514
2562
|
};
|
|
2515
2563
|
|
|
2516
2564
|
module.exports.feedback_github = {
|
|
2517
|
-
|
|
2565
|
+
setup_inspect_installation: 'Installation is unverified. Check gh --version, package-manager state or reopen the terminal before deciding to retry; keep the draft.',
|
|
2566
|
+
setup_check_execution: 'gh could not run. Check execution permissions or the local environment; do not reinstall or switch accounts automatically.',
|
|
2567
|
+
setup_confirm_install: 'GitHub CLI can be installed. Explain the plan and obtain consent before openyida feedback github setup --install --confirm --json; the web option remains available.',
|
|
2568
|
+
setup_manual_install: 'Automatic installation is unavailable. Use the official instructions, an existing connector or the web; keep the draft.',
|
|
2569
|
+
setup_ready: 'GitHub CLI and the current account are verified. Resume the draft; confirm public content and required permissions before submission.',
|
|
2570
|
+
setup_browser_login: 'GitHub CLI is available and login is required. With consent, guide browser authorization, then rerun setup --json to verify.',
|
|
2571
|
+
setup_check_account: 'GitHub CLI is available, but the account is unverified. Check network, authorization or rate limits; do not infer a missing account or reinstall.',
|
|
2572
|
+
setup_consent: 'Use --install --confirm only after consent to install GitHub CLI and required dependencies in the package manager default location. Windows accepts WinGet source/package agreements and may need user-approved system permissions. No automatic manager installation, privilege escalation or login.',
|
|
2573
|
+
setup_privacy: 'Installation is not consent to publish. The user authorizes in the browser; never request passwords, codes or tokens. If gh cannot store credentials securely, use the web or a secure connector. Keep account and tool diagnostics out of feedback reports.',
|
|
2574
|
+
usage: 'Usage: openyida feedback github setup [--install --confirm] [--json]; openyida feedback github <status|star|fork> [--confirm] [--json]',
|
|
2518
2575
|
confirmation: 'Star or Fork requires the user to explicitly choose that action before --confirm. Neither is required to submit an Issue.',
|
|
2519
2576
|
failed: 'The GitHub action could not be verified. Inspect its status before retrying; this does not block Issue submission.',
|
|
2520
2577
|
};
|
|
2578
|
+
|
|
2579
|
+
module.exports.process_dynamic_actors = { invalid: 'Invalid process actor configuration. Check details.reason, selection range and actual member fields.' };
|
package/lib/core/locales/zh.js
CHANGED
|
@@ -4,6 +4,17 @@
|
|
|
4
4
|
'use strict';
|
|
5
5
|
|
|
6
6
|
module.exports = {
|
|
7
|
+
qwenwork: {
|
|
8
|
+
credential_missing: '未发现云端 Agent 凭证,请在千问办公云端执行环境中运行此命令。',
|
|
9
|
+
gateway_missing: '缺少 QWENWORK_GATEWAY_URL 或 MULE_GATEWAY_URL。',
|
|
10
|
+
invalid_url: '千问网关必须使用 HTTPS(仅回环地址允许 HTTP),且不能包含账号密码、查询参数或片段。',
|
|
11
|
+
request_failed: '千问接口请求失败,请查看诊断信息中的阶段和 HTTP 状态码。',
|
|
12
|
+
request_timeout: '千问接口请求超时。',
|
|
13
|
+
invalid_response: '千问返回的认证或身份响应格式不正确。',
|
|
14
|
+
identity_mismatch: '千问返回的用户身份与云端执行上下文或兑换凭证不一致。',
|
|
15
|
+
expired_token: '千问返回的用户凭证已过期。',
|
|
16
|
+
usage: '用法:openyida auth qwenwork user-info [--json]',
|
|
17
|
+
},
|
|
7
18
|
print_template: {
|
|
8
19
|
'description': '管理宜搭原生打印模板、按字段生成多种单据、备份恢复与生成PDF',
|
|
9
20
|
'error': '打印模板操作失败:{0}',
|
|
@@ -39,7 +50,10 @@ module.exports = {
|
|
|
39
50
|
integration_update_v2: {'usage': 'integration update <appType> <formUuid> <processCode> --patch patch.json [--dry-run] [--expect fingerprint] [--publish]'},
|
|
40
51
|
|
|
41
52
|
conditional_actors: { unavailable: 'Conditional actors are unavailable or could not be verified.', invalid: 'Invalid conditional actors: {0}' },
|
|
42
|
-
integration_triggers: {
|
|
53
|
+
integration_triggers: {
|
|
54
|
+
invalid: 'Invalid automation trigger: {0}',
|
|
55
|
+
end_required: '请选择定时任务的结束条件:触发次数填写 schedule.maxCount(1–100),指定时间填写 schedule.expireDate(截止时间的毫秒时间戳)。长期运行可选择较远的截止日期,并在配置摘要中展示实际日期。',
|
|
56
|
+
},
|
|
43
57
|
permission_conditions: { invalid: '数据权限条件无效:{0}' },
|
|
44
58
|
agent: {
|
|
45
59
|
preflight_cli_detected: 'CLI 已发现;登录、协议和模型状态由 runtime 检测并上报。',
|
|
@@ -1104,7 +1118,7 @@ openyida - 宜搭命令行工具
|
|
|
1104
1118
|
// ── lib/import-app.js ──────────────────────────────
|
|
1105
1119
|
import_example2: ' openyida import ./yida-export.json "质量追溯系统(生产环境)"',
|
|
1106
1120
|
exec_failed: '\n❌ 执行失败: {0}',
|
|
1107
|
-
auth_usage: '用法: openyida auth <status|login|refresh|logout|profiles|profile switch>',
|
|
1121
|
+
auth_usage: '用法: openyida auth <status|login|refresh|logout|profiles|profile switch|qwenwork user-info> [--json]',
|
|
1108
1122
|
auth_example: '示例:\n openyida auth status # 查看登录状态\n openyida auth profiles # 列出已有登录 profile\n openyida auth profile switch <auth_profile> # 切换当前项目到已有 profile\n openyida auth login # 目标 profile 不存在时登录新增\n openyida auth refresh # 刷新登录态\n openyida auth logout # 解绑当前项目登录态\n openyida auth logout --profile <auth_profile> # 删除指定共享 profile',
|
|
1109
1123
|
org_usage: '用法: openyida org <list|switch> [--json] [--corp-id <corpId>]',
|
|
1110
1124
|
org_example: '示例:\n openyida org list --json # 列出可访问的组织\n openyida org switch --corp-id dingXXX # 优先切换已有 profile;不存在时登录新增',
|
|
@@ -1528,6 +1542,10 @@ openyida - 宜搭命令行工具
|
|
|
1528
1542
|
lint_setstate_non_timestamp: '检测到 this.setState 写入非 timestamp 字段。业务态应写入 _customState 并调用 forceUpdate()/setCustomState() 触发重渲染;this.setState 仅用于 timestamp 契约字段',
|
|
1529
1543
|
lint_self_binding_missing: 'renderJsx 内使用了 this 但未声明 var self = this;。请在 renderJsx 开头加入 var self = this;,闭包/回调内改用 self,避免 this 指向丢失',
|
|
1530
1544
|
lint_echarts_dom_ready: 'echarts.init 未包裹在 setTimeout 中,容器可能尚未挂载导致图表不渲染。建议 setTimeout(function(){ /* echarts.init */ }, 300)',
|
|
1545
|
+
lint_resize_observer_cleanup: 'ResizeObserver 缺少 disconnect()/unobserve() 清理,页面卸载后可能继续测量。请在 effect 或生命周期清理函数中释放 observer。',
|
|
1546
|
+
lint_responsive_viewport_only: '布局只依据视口宽度变化,桌面侧栏、抽屉或 iframe 窄容器可能无法降级。请用 @container 或带清理的 ResizeObserver 测量实际内容容器;若确实是视口级行为,添加 openyida-responsive-viewport-ok 说明。',
|
|
1547
|
+
lint_responsive_fixed_width: '检测到固定宽度 %spx,窄容器可能产生整页横向溢出。请改用 max-width、minmax(0, 1fr) 或局部滚动;确有固定画布需求时添加 openyida-responsive-fixed-width-ok 说明。',
|
|
1548
|
+
lint_responsive_page_scale: '检测到 scale/zoom 整体缩放。响应式布局应重排内容并保留可读字号和点击区域;仅局部可视化确需缩放时添加 openyida-responsive-scale-ok 说明。',
|
|
1531
1549
|
lint_yida_api_catch: 'this.utils.yida API 调用未检测到 .catch(),请补充错误处理并 toast 给用户',
|
|
1532
1550
|
lint_echarts_legacy_map_china: 'ECharts 5 已废弃 echarts/map/js/china.js,请加载 DataV GeoJSON 后调用 echarts.registerMap("china", geoJson)',
|
|
1533
1551
|
lint_echarts_rich_label_formatter: 'ECharts label.formatter 返回 rich text 模板在宜搭自定义页面环境不稳定,建议使用普通 formatter 字符串或预先拼好的标签文本',
|
|
@@ -2285,6 +2303,16 @@ module.exports.app_theme = {
|
|
|
2285
2303
|
module.exports.help.cmd_app_theme_snapshot = '保存应用主题配置与 CSS 快照(只读)';
|
|
2286
2304
|
module.exports.help.cmd_app_theme_restore = '检查或恢复应用主题快照(仅支持可精确恢复的配置)';
|
|
2287
2305
|
|
|
2306
|
+
Object.assign(module.exports.process_tasks || (module.exports.process_tasks = {}), {
|
|
2307
|
+
arguments_invalid: '参数无效:查询需要 appType 和 --process-inst-id;转交还需要 --form-uuid、--to-user-id、--expect-form-name 和 --expect-form-type process。taskId 必须为正整数,不能使用未知参数。',
|
|
2308
|
+
query_failed: '流程任务查询失败,未执行转交。',
|
|
2309
|
+
response_invalid: '流程任务响应结构、任务 ID 或实例归属无法验证,未继续操作。',
|
|
2310
|
+
not_running: '指定任务不是目标流程的当前运行任务,或流程没有运行中任务,未执行转交。',
|
|
2311
|
+
ambiguous: '流程有多个运行中任务,请查询任务列表并明确传入 --task-id,未执行转交。',
|
|
2312
|
+
rejected: '平台拒绝了管理员转交请求,请核对权限与任务状态。',
|
|
2313
|
+
result_unknown: '管理员转交结果未知,请按 nextStep 只读查询,禁止自动重试转交。',
|
|
2314
|
+
unverified: '转交请求已被接受,但回读未能确认接收人,请按 nextStep 只读查询,禁止自动重试转交。',
|
|
2315
|
+
});
|
|
2288
2316
|
module.exports.data_manage_style = {
|
|
2289
2317
|
'usage': 'openyida data-manage-style guide [--json]\nopenyida data-manage-style list [--json]\nopenyida data-manage-style generate --app APP_ID --form FORM-ID --style <id> --base-css <snapshot/theme.css> --output <new.css> [--focus balanced|actions] [--field-id <actualId>]... [--emphasize-field <actualId>]... [--tag-field <selectFieldId>]... [--follow-shell] [--json]',
|
|
2290
2318
|
'data_style_invalid': '数据管理样式参数无效;请使用真实应用、表单和字段 ID,以及 list 返回的样式。',
|
|
@@ -2381,6 +2409,26 @@ Object.assign(module.exports.help, {'cmd_formula_contracts': '查看公式保存
|
|
|
2381
2409
|
Object.assign(module.exports.formula_v2, {'parallel_formula': '并行分支使用 conditions/rules 或 all:true;expression 目前只适用于 route 分支。'});
|
|
2382
2410
|
|
|
2383
2411
|
module.exports.feedback_report = {
|
|
2412
|
+
body: {
|
|
2413
|
+
summary: '想完成什么',
|
|
2414
|
+
actual: '实际发生了什么',
|
|
2415
|
+
expected: '希望看到什么结果',
|
|
2416
|
+
incident: '问题发生时的环境',
|
|
2417
|
+
command: '相关操作',
|
|
2418
|
+
steps: '怎样重现',
|
|
2419
|
+
impact: '影响',
|
|
2420
|
+
evidence: '已观察的证据',
|
|
2421
|
+
attempts: '尝试过的方法与结果',
|
|
2422
|
+
cause: '可能的原因及确认程度',
|
|
2423
|
+
cause_evidence: '判断依据',
|
|
2424
|
+
next: '下一步验证',
|
|
2425
|
+
screenshots: '问题截图',
|
|
2426
|
+
review_image: '公开前请检查图片',
|
|
2427
|
+
limitations: '尚未验证的范围',
|
|
2428
|
+
generator: '报告生成环境(不代表问题发生时)',
|
|
2429
|
+
unknown: '未知 / 尚未确认',
|
|
2430
|
+
draft: '本地草稿,尚未提交。请检查文字和截图,确认没有客户数据、凭证或内部信息后再公开。',
|
|
2431
|
+
},
|
|
2384
2432
|
comparison: '测试通过或失败须提供真实命令、实际结果及证据。',
|
|
2385
2433
|
screenshots: '截图须为明确选择的 PNG/JPEG/WebP,每张至多 10 MiB,最多 5 张。',
|
|
2386
2434
|
text: '反馈文本字段须为不超过 12000 字符的字符串。',
|
|
@@ -2468,7 +2516,18 @@ module.exports.task_center = {
|
|
|
2468
2516
|
};
|
|
2469
2517
|
|
|
2470
2518
|
module.exports.feedback_github = {
|
|
2471
|
-
|
|
2519
|
+
setup_inspect_installation: '安装结果尚未核实。先检查 gh --version、包管理器状态或重新打开终端,再决定是否重试;草稿仍保留。',
|
|
2520
|
+
setup_check_execution: 'gh 暂时无法运行。请检查执行权限或本机环境;不要重复安装或更换账号。',
|
|
2521
|
+
setup_confirm_install: '可安装 GitHub CLI。先说明安装计划并取得用户同意,再执行 openyida feedback github setup --install --confirm --json;也可使用网页。',
|
|
2522
|
+
setup_manual_install: '当前没有可用的自动安装方式。可查看官方安装说明、使用已有连接器或网页,草稿仍保留。',
|
|
2523
|
+
setup_ready: 'GitHub CLI 和当前账号已验证。继续原草稿,提交前仍需核对公开内容和所需权限。',
|
|
2524
|
+
setup_browser_login: 'GitHub CLI 已可用,需要登录。用户同意后引导浏览器授权,完成后再次运行 setup --json 核实。',
|
|
2525
|
+
setup_check_account: 'GitHub CLI 已可用,但当前账号尚未核实。先检查网络、授权或限流;不要据此判断用户没有账号或要求重新安装。',
|
|
2526
|
+
setup_consent: '仅在用户同意安装 GitHub CLI 及其必要依赖后使用 --install --confirm。使用包管理器默认位置;Windows 安装会接受 WinGet 来源和软件协议,可能需要用户批准系统权限。不自动安装包管理器、提权或登录。',
|
|
2527
|
+
setup_privacy: '安装不代表同意公开提交。浏览器授权由用户完成;不索取密码、验证码或 Token。若 gh 无法安全保存凭证,改用网页或安全连接器;账号和工具诊断不写入反馈报告。',
|
|
2528
|
+
usage: '用法:openyida feedback github setup [--install --confirm] [--json]; openyida feedback github <status|star|fork> [--confirm] [--json]',
|
|
2472
2529
|
confirmation: 'Star 或 Fork 需要用户明确选择后再传入 --confirm;提交 Issue 不要求这两项操作。',
|
|
2473
2530
|
failed: 'GitHub 操作未能核实完成,请先查询状态;这不影响提交 Issue。',
|
|
2474
2531
|
};
|
|
2532
|
+
|
|
2533
|
+
module.exports.process_dynamic_actors = { invalid: '流程人员来源配置无效,请按 details.reason 检查来源、范围与真实成员字段。' };
|
package/lib/core/query-data.js
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* query form / get form / create form / update form / delete form / query subform
|
|
9
9
|
* query process / get process / create process / update process
|
|
10
10
|
* query operation-records / execute task / query tasks
|
|
11
|
+
* query process-tasks / transfer task (administrator)
|
|
11
12
|
*/
|
|
12
13
|
|
|
13
14
|
'use strict';
|
|
@@ -22,6 +23,7 @@ const { queryByCurrentApprover, validateApproverOptions } = require('./process-a
|
|
|
22
23
|
const { buildComponentAliasMaps } = require('../app/get-schema');
|
|
23
24
|
const { readFormMode } = require('../app/services/form-mode-service');
|
|
24
25
|
const { fetchFormPageList } = require('../app/form-navigation');
|
|
26
|
+
const processTasks = require('../process/process-tasks');
|
|
25
27
|
|
|
26
28
|
const USAGE = `openyida data - Unified Yida data CLI
|
|
27
29
|
|
|
@@ -39,6 +41,8 @@ Usage:
|
|
|
39
41
|
openyida data create process <appType> <formUuid> --process-code <processCode> (--data-json <JSON>|--data-file .cache/openyida/data.json) --expect-form-name <name> --expect-form-type process [--dept-id ID] [--resolve-aliases]
|
|
40
42
|
openyida data update process <appType> --process-inst-id <processInstanceId> --form-uuid <formUuid> (--data-json <JSON>|--data-file .cache/openyida/data.json) --expect-form-name <name> --expect-form-type process [--resolve-aliases]
|
|
41
43
|
openyida data query operation-records <appType> --process-inst-id <processInstanceId>
|
|
44
|
+
openyida data query process-tasks <appType> --process-inst-id <processInstanceId> [--json]
|
|
45
|
+
openyida data transfer task <appType> --process-inst-id <processInstanceId> --form-uuid <formUuid> --to-user-id <userId> --expect-form-name <name> --expect-form-type process [--remark <text>] [--task-id <taskId>] [--json]
|
|
42
46
|
openyida data execute task <appType> --task-id <taskId> --process-inst-id <processInstanceId> --form-uuid <formUuid> --expect-form-name <name> --expect-form-type process --out-result <AGREE|DISAGREE> --remark <text> [--data-json JSON|--data-file .cache/openyida/data.json] [--resolve-aliases] [--no-execute-expressions y]
|
|
43
47
|
|
|
44
48
|
openyida data query tasks <appType> --type <todo|created|done|submitted|cc> [--transport app-v1|app-query] [--page N] [--size N] [--keyword TEXT] [--normalized] [--process-codes JSON] [--instance-status STATUS]
|
|
@@ -69,6 +73,8 @@ const SUPPORTED_DATA_COMMANDS = new Set([
|
|
|
69
73
|
'query:operation-records',
|
|
70
74
|
'execute:task',
|
|
71
75
|
'query:tasks',
|
|
76
|
+
'query:process-tasks',
|
|
77
|
+
'transfer:task',
|
|
72
78
|
]);
|
|
73
79
|
|
|
74
80
|
const MUTATION_DATA_COMMANDS = new Set([
|
|
@@ -78,6 +84,7 @@ const MUTATION_DATA_COMMANDS = new Set([
|
|
|
78
84
|
'create:process',
|
|
79
85
|
'update:process',
|
|
80
86
|
'execute:task',
|
|
87
|
+
'transfer:task',
|
|
81
88
|
]);
|
|
82
89
|
|
|
83
90
|
function fail(message) {
|
|
@@ -149,6 +156,10 @@ function validateDataCommandBeforeAuth(action, resource, positionals, options) {
|
|
|
149
156
|
);
|
|
150
157
|
}
|
|
151
158
|
|
|
159
|
+
if ((action === 'query' && resource === 'process-tasks') || action === 'transfer') {
|
|
160
|
+
processTasks.validateArguments(positionals, options, action === 'transfer');
|
|
161
|
+
}
|
|
162
|
+
|
|
152
163
|
if (MUTATION_DATA_COMMANDS.has(`${action}:${resource}`)) {
|
|
153
164
|
requireOption(options, 'expect_form_name');
|
|
154
165
|
requireOption(options, 'expect_form_type');
|
|
@@ -203,7 +214,7 @@ function ensureSession() {
|
|
|
203
214
|
return authRef;
|
|
204
215
|
}
|
|
205
216
|
|
|
206
|
-
function parseCliOptions(tokens) {
|
|
217
|
+
function parseCliOptions(tokens, strict = false) {
|
|
207
218
|
const positionals = [];
|
|
208
219
|
const options = {};
|
|
209
220
|
|
|
@@ -211,6 +222,9 @@ function parseCliOptions(tokens) {
|
|
|
211
222
|
const token = tokens[i];
|
|
212
223
|
if (token.startsWith('--')) {
|
|
213
224
|
const key = token.slice(2).replace(/-/g, '_');
|
|
225
|
+
if (strict && Object.prototype.hasOwnProperty.call(options, key)) {
|
|
226
|
+
parseError(t('process_tasks.arguments_invalid'));
|
|
227
|
+
}
|
|
214
228
|
const next = tokens[i + 1];
|
|
215
229
|
if (next && !next.startsWith('--')) {
|
|
216
230
|
options[key] = next;
|
|
@@ -1512,6 +1526,24 @@ async function queryTasks(positionals, options, session) {
|
|
|
1512
1526
|
printResult(options.normalized ? { success: true, content: normalized } : result);
|
|
1513
1527
|
}
|
|
1514
1528
|
|
|
1529
|
+
async function transferProcessTask(positionals, options, session) {
|
|
1530
|
+
const [appType] = positionals;
|
|
1531
|
+
const target = await requireExpectedFormTarget(session, appType, options.form_uuid, options);
|
|
1532
|
+
const record = await readProcessInstance(session, appType, options.process_inst_id);
|
|
1533
|
+
requireInstanceTarget(record, target, options.process_inst_id,
|
|
1534
|
+
['processInstanceId', 'processInstId', 'instanceId']);
|
|
1535
|
+
const instanceStatus = record.processInstanceStatus || record.instanceStatus;
|
|
1536
|
+
if (instanceStatus && instanceStatus !== 'RUNNING') {
|
|
1537
|
+
dataError('DATA_PROCESS_TASK_NOT_RUNNING', t('process_tasks.not_running'), {
|
|
1538
|
+
retryable: false, retrySafe: true, sideEffectState: 'none',
|
|
1539
|
+
});
|
|
1540
|
+
}
|
|
1541
|
+
printResult(await processTasks.transferTask(createYidaClient({ authRef: session }), {
|
|
1542
|
+
appType, formUuid: options.form_uuid, processInstanceId: options.process_inst_id,
|
|
1543
|
+
taskId: options.task_id, toUserId: options.to_user_id, remark: options.remark,
|
|
1544
|
+
}));
|
|
1545
|
+
}
|
|
1546
|
+
|
|
1515
1547
|
async function run(args) {
|
|
1516
1548
|
if (args.length < 2) {
|
|
1517
1549
|
parseError('缺少必填参数 action 或 resource');
|
|
@@ -1519,7 +1551,8 @@ async function run(args) {
|
|
|
1519
1551
|
|
|
1520
1552
|
const action = args[0];
|
|
1521
1553
|
const resource = args[1];
|
|
1522
|
-
const
|
|
1554
|
+
const strict = action === 'transfer' || (action === 'query' && resource === 'process-tasks');
|
|
1555
|
+
const { positionals, options } = parseCliOptions(args.slice(2), strict);
|
|
1523
1556
|
|
|
1524
1557
|
if (
|
|
1525
1558
|
action === 'query' &&
|
|
@@ -1551,6 +1584,11 @@ async function run(args) {
|
|
|
1551
1584
|
if (action === 'query' && resource === 'operation-records') {return queryOperationRecords(positionals, options, session);}
|
|
1552
1585
|
if (action === 'execute' && resource === 'task') {return executeTask(positionals, options, session);}
|
|
1553
1586
|
if (action === 'query' && resource === 'tasks') {return queryTasks(positionals, options, session);}
|
|
1587
|
+
if (action === 'query' && resource === 'process-tasks') {
|
|
1588
|
+
return printResult(await processTasks.queryProcessTasks(
|
|
1589
|
+
createYidaClient({ authRef: session }), positionals[0], options.process_inst_id));
|
|
1590
|
+
}
|
|
1591
|
+
if (action === 'transfer' && resource === 'task') {return transferProcessTask(positionals, options, session);}
|
|
1554
1592
|
|
|
1555
1593
|
dataError('DATA_COMMAND_UNSUPPORTED', t('query_data.command_unsupported', action, resource));
|
|
1556
1594
|
}
|
package/lib/core/sample.js
CHANGED
|
@@ -60,6 +60,7 @@ const SAMPLES = {
|
|
|
60
60
|
'canvas-theme': 'canvas-theme-provider.template.jsx',
|
|
61
61
|
'canvas-navigation': 'canvas-navigation.jsx',
|
|
62
62
|
'canvas-view-state': 'canvas-view-state.jsx',
|
|
63
|
+
'canvas-responsive-layout': 'canvas-responsive-layout.jsx',
|
|
63
64
|
'canvas-admin-entry': 'canvas-admin-entry.jsx',
|
|
64
65
|
'canvas-nav-side': 'canvas-nav/side.jsx',
|
|
65
66
|
'canvas-nav-top': 'canvas-nav/top.jsx',
|
|
@@ -109,6 +110,7 @@ const SAMPLE_OUTPUT_FILENAMES = {
|
|
|
109
110
|
'openyida-page-template/form-open-container': 'form-open-container.jsx',
|
|
110
111
|
'openyida-page-template/canvas-dialog': 'canvas-dialog.jsx',
|
|
111
112
|
'openyida-page-template/canvas-theme': 'canvas-theme.jsx',
|
|
113
|
+
'openyida-page-template/canvas-responsive-layout': 'canvas-responsive-layout.jsx',
|
|
112
114
|
'yida-design/app-theme': 'app-theme.css',
|
|
113
115
|
};
|
|
114
116
|
|
|
@@ -116,6 +118,7 @@ const SAMPLE_HINTS = {
|
|
|
116
118
|
'openyida-page-template/canvas-admin-entry': '已包含统一跳转 helper;在 CanvasThemeProvider 内渲染 CanvasAdminWorkbenchButton,填写当前 appType 与真实 workbenchFormUuid。身份读取当前应用 loginUser.isAppAdmin,未知时隐藏;默认不跳开发后台或猜测管理首页。',
|
|
117
119
|
'openyida-page-template/canvas-navigation': '先从资源回读填写 appType、目标类型与页面 ID;本页 Tab 用 selectView,独立前台用 custom,管理入口用 page,表单入口接 openForm;按钮和链接共用 buildCanvasPageUrl。',
|
|
118
120
|
'openyida-page-template/canvas-theme': '以 CanvasThemeProvider 包住业务组件;Tabs 用于内容切换,Segmented/Radio 用于筛选,Button 用于动作。默认轻底选中态与可读文字,controls 可供自绘控件复用;避免内层固定色覆盖。保留内置加载遮罩防闪边样式;旧页面需更新 Provider 并重新发布。',
|
|
121
|
+
'openyida-page-template/canvas-responsive-layout': '合并 useContainerLayout 与 ResponsiveLayout;按实际内容容器重排筛选栏和主辅面板,宽表仅局部滚动,图表按 data-chart-width resize。业务状态放在布局壳之上,断点切换不得修改 key 或重挂载。',
|
|
119
122
|
'openyida-page-template/canvas-nav-top': '顶部默认贴顶通栏;长页先合并 canvas-nav-content,CanvasNav 传 headerOnly,有首屏背景时传 overlay;悬浮外观仅显式 floating=true。',
|
|
120
123
|
'openyida-page-template/canvas-nav-content': '合并 CanvasNavigationContent;长页用 layout=document,CanvasNav 传 headerOnly/overlay;默认 sticky,受宿主限制时用 navigationPosition=fixed。工作区用 workspace,宿主已分配高度时传 height。',
|
|
121
124
|
'openyida-page-template/canvas-nav-data': '页内展示用 mode=local(key/viewKey/targetType=local),不请求平台菜单;platform 需真实资源 ID;independent 或声明 access 时必须接入真实 resolveAccess。保留 PRD 顺序与分组。',
|
package/lib/feedback/feedback.js
CHANGED
|
@@ -51,6 +51,7 @@ function printUsage() {
|
|
|
51
51
|
openyida feedback setup <appType> [--name "OpenYida 体验反馈"] [--path /o/openyida-feedback] [--open|--no-open]
|
|
52
52
|
openyida feedback setup --create-app [--app-name "OpenYida 体验反馈"] [--name "OpenYida 体验反馈"]
|
|
53
53
|
openyida feedback report --input <summary.json> --output-dir <new-directory>
|
|
54
|
+
openyida feedback github setup [--install --confirm] [--json]
|
|
54
55
|
openyida feedback github <status|star|fork> [--confirm] [--json]
|
|
55
56
|
openyida feedback url [--tool Codex] [--model gpt-5] [--command publish] [--diagnostics "..."]
|
|
56
57
|
openyida feedback dismiss --today|--forever|--reset
|
|
@@ -58,7 +59,7 @@ function printUsage() {
|
|
|
58
59
|
|
|
59
60
|
说明:
|
|
60
61
|
${t('feedback_report.help')}
|
|
61
|
-
setup 会在宜搭创建一个公开反馈表单,并写入本地 .cache/openyida/feedback/config.json。
|
|
62
|
+
feedback setup 会在宜搭创建一个公开反馈表单,并写入本地 .cache/openyida/feedback/config.json。
|
|
62
63
|
url 只生成带脱敏元数据的填写链接,不提交任何网络请求。
|
|
63
64
|
dismiss/status 只读写本地提醒状态。
|
|
64
65
|
`);
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { spawnSync } = require('child_process');
|
|
4
|
+
const { t } = require('../core/i18n');
|
|
5
|
+
|
|
6
|
+
const INSTALL_URL = 'https://github.com/cli/cli#installation';
|
|
7
|
+
const LOGIN_COMMAND = 'gh auth login --hostname github.com --web --skip-ssh-key';
|
|
8
|
+
|
|
9
|
+
/** Fixed argv only. Capture diagnostics privately, including package-manager failures. */
|
|
10
|
+
function invoke(binary, args, options, installing = false) {
|
|
11
|
+
try {
|
|
12
|
+
return (options.spawnSyncFn || spawnSync)(binary, args, {
|
|
13
|
+
shell: false, encoding: 'utf8', timeout: installing ? 300000 : 15000,
|
|
14
|
+
maxBuffer: 1024 * 1024, stdio: ['ignore', 'pipe', 'pipe'], windowsHide: true,
|
|
15
|
+
env: { ...(options.env || process.env), GH_HOST: 'github.com', GH_PROMPT_DISABLED: '1',
|
|
16
|
+
GIT_TERMINAL_PROMPT: '0', HOMEBREW_NO_AUTO_UPDATE: '1', HOMEBREW_NO_INSTALL_CLEANUP: '1',
|
|
17
|
+
HOMEBREW_NO_INSTALL_UPGRADE: '1', HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: '1', HOMEBREW_NO_SUDO: '1',
|
|
18
|
+
...(installing ? { HOMEBREW_NO_ASK: '1' } : {}) },
|
|
19
|
+
});
|
|
20
|
+
} catch { return { status: null }; }
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function toolState(options) {
|
|
24
|
+
const result = invoke('gh', ['--version'], options);
|
|
25
|
+
if (result.error?.code === 'ENOENT') { return { state: 'missing', version: null }; }
|
|
26
|
+
const version = String(result.stdout || '').match(/^gh version (\d+\.\d+\.\d+)\b/)?.[1];
|
|
27
|
+
return result.status === 0 && !result.error && version
|
|
28
|
+
? { state: 'available', version } : { state: 'unverified', version: null };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function installPlan(options) {
|
|
32
|
+
const platform = options.platform || process.platform;
|
|
33
|
+
const binary = platform === 'win32' ? 'winget' : ['darwin', 'linux'].includes(platform) ? 'brew' : null;
|
|
34
|
+
if (!binary) { return { available: false, reason: 'unsupported_platform', url: INSTALL_URL }; }
|
|
35
|
+
const probe = invoke(binary, ['--version'], options);
|
|
36
|
+
if (probe.error || probe.status !== 0) {
|
|
37
|
+
return { available: false, reason: probe.error?.code === 'ENOENT' ? 'manager_missing' : 'manager_unverified', url: INSTALL_URL };
|
|
38
|
+
}
|
|
39
|
+
const args = binary === 'brew' ? ['install', 'homebrew/core/gh']
|
|
40
|
+
: ['install', '--id', 'GitHub.cli', '--exact', '--source', 'winget', '--no-upgrade', '--disable-interactivity',
|
|
41
|
+
'--accept-source-agreements', '--accept-package-agreements'];
|
|
42
|
+
return { available: true, binary, args, url: INSTALL_URL, requiresConsent: true };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function accountState(options) {
|
|
46
|
+
const result = invoke('gh', ['api', '--hostname', 'github.com', '--method', 'GET', 'user'], options);
|
|
47
|
+
if (result.status === 4 && !result.error) { return { state: 'login_required', login: null }; }
|
|
48
|
+
let account;
|
|
49
|
+
try { account = JSON.parse(result.stdout); } catch { /* Unknown response stays unverified. */ }
|
|
50
|
+
if (result.status === 0 && !result.error && account?.type === 'User'
|
|
51
|
+
&& /^[A-Za-z0-9][A-Za-z0-9-]{0,38}$/.test(account.login || '')) {
|
|
52
|
+
return { state: 'verified', login: account.login };
|
|
53
|
+
}
|
|
54
|
+
return { state: 'unverified', login: null };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Called only after the router validates consent and the managed-run boundary. */
|
|
58
|
+
function setup(parsed, options) {
|
|
59
|
+
let tool = toolState(options);
|
|
60
|
+
const installation = { attempted: false, state: 'not_requested', plan: null };
|
|
61
|
+
if (tool.state === 'missing') {
|
|
62
|
+
installation.plan = installPlan(options);
|
|
63
|
+
if (parsed.install) {
|
|
64
|
+
installation.state = 'unavailable';
|
|
65
|
+
if (installation.plan.available) {
|
|
66
|
+
installation.attempted = true;
|
|
67
|
+
const result = invoke(installation.plan.binary, installation.plan.args, options, true);
|
|
68
|
+
tool = toolState(options);
|
|
69
|
+
installation.state = result.status === 0 && !result.error && tool.state === 'available'
|
|
70
|
+
? 'verified' : 'unverified';
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
} else if (parsed.install) {
|
|
74
|
+
installation.state = tool.state === 'available' ? 'already_available' : 'unavailable';
|
|
75
|
+
}
|
|
76
|
+
const account = tool.state === 'available' ? accountState(options) : { state: 'not_checked', login: null };
|
|
77
|
+
const ready = tool.state === 'available' && account.state === 'verified';
|
|
78
|
+
const nextStep = installation.state === 'unverified' ? 'inspect_installation'
|
|
79
|
+
: tool.state === 'unverified' ? 'check_execution'
|
|
80
|
+
: tool.state === 'missing' ? (installation.plan?.available ? 'confirm_install' : 'manual_install')
|
|
81
|
+
: ready ? 'ready' : account.state === 'login_required' ? 'browser_login' : 'check_account';
|
|
82
|
+
return {
|
|
83
|
+
success: !parsed.install || ['verified', 'already_available'].includes(installation.state),
|
|
84
|
+
action: 'setup', tool, account, ready, installation, nextStep,
|
|
85
|
+
message: t(`feedback_github.setup_${nextStep}`),
|
|
86
|
+
consentNotice: t('feedback_github.setup_consent'),
|
|
87
|
+
privacyNotice: t('feedback_github.setup_privacy'),
|
|
88
|
+
authorization: { performed: false, requiresSeparateConsent: true,
|
|
89
|
+
command: tool.state === 'available' && !ready ? LOGIN_COMMAND : null,
|
|
90
|
+
url: 'https://cli.github.com/manual/gh_auth_login' },
|
|
91
|
+
links: { install: INSTALL_URL, signup: 'https://github.com/signup', issue: 'https://github.com/openyida/openyida/issues/new' },
|
|
92
|
+
submissionPerformed: false, publicConfirmationRequired: true,
|
|
93
|
+
inspectBeforeRetry: installation.state === 'unverified',
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
module.exports = { setup };
|
package/lib/feedback/github.js
CHANGED
|
@@ -11,15 +11,18 @@ const links = Object.freeze({ repository: `https://github.com/${REPOSITORY}`,
|
|
|
11
11
|
/** Parse explicit account actions; submitting an Issue never implies Star or Fork consent. */
|
|
12
12
|
function parseArgs(args = []) {
|
|
13
13
|
const [action, ...flags] = args;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|| (
|
|
14
|
+
const install = flags.includes('--install');
|
|
15
|
+
if (!['status', 'star', 'fork', 'setup'].includes(action) || new Set(flags).size !== flags.length
|
|
16
|
+
|| flags.some(flag => !['--json', '--confirm', '--install'].includes(flag))
|
|
17
|
+
|| (install && action !== 'setup')
|
|
18
|
+
|| (action === 'status' && flags.includes('--confirm'))
|
|
19
|
+
|| (action === 'setup' && !install && flags.includes('--confirm'))) {
|
|
17
20
|
throw new CliError(t('feedback_github.usage'), { code: 'FEEDBACK_GITHUB_USAGE' });
|
|
18
21
|
}
|
|
19
|
-
if (
|
|
20
|
-
throw new CliError(t('feedback_github.confirmation'), { code: 'FEEDBACK_GITHUB_CONFIRMATION_REQUIRED' });
|
|
22
|
+
if ((['star', 'fork'].includes(action) || install) && !flags.includes('--confirm')) {
|
|
23
|
+
throw new CliError(t(install ? 'feedback_github.setup_consent' : 'feedback_github.confirmation'), { code: 'FEEDBACK_GITHUB_CONFIRMATION_REQUIRED' });
|
|
21
24
|
}
|
|
22
|
-
return { action, confirm: flags.includes('--confirm') };
|
|
25
|
+
return { action, confirm: flags.includes('--confirm'), ...(action === 'setup' ? { install } : {}) };
|
|
23
26
|
}
|
|
24
27
|
|
|
25
28
|
/** Run gh against github.com only. Never expose its raw output or credential diagnostics. */
|
|
@@ -90,10 +93,12 @@ function inspect(options) {
|
|
|
90
93
|
|
|
91
94
|
/** Execute one explicitly authorized action, then read it back. No retry, clone, remote change or Issue submission. */
|
|
92
95
|
function execute(parsed, options = {}) {
|
|
93
|
-
const
|
|
96
|
+
const validated = parseArgs([parsed.action, ...(parsed.confirm === true ? ['--confirm'] : []), ...(parsed.install === true ? ['--install'] : [])]);
|
|
97
|
+
const { action } = validated;
|
|
94
98
|
if ((options.env || process.env).OPENYIDA_MANAGED_RUN === '1') {
|
|
95
99
|
throw new CliError(t('feedback_github.failed'), { code: 'FEEDBACK_GITHUB_MANAGED_DENIED' });
|
|
96
100
|
}
|
|
101
|
+
if (action === 'setup') { return require('./github-setup').setup(validated, options); }
|
|
97
102
|
const result = inspect(options);
|
|
98
103
|
if (action === 'status') { return result; }
|
|
99
104
|
const fail = (stage, mutationPerformed = false) => {
|
|
@@ -124,7 +129,11 @@ function execute(parsed, options = {}) {
|
|
|
124
129
|
/** CLI entrypoint. The confirmation flag attests to the user's explicit choice of this action. */
|
|
125
130
|
function run(args = []) {
|
|
126
131
|
const parsed = parseArgs(args);
|
|
127
|
-
|
|
132
|
+
const result = execute(parsed);
|
|
133
|
+
if (result.success === false) {
|
|
134
|
+
throw new CliError(result.message, { code: 'FEEDBACK_GITHUB_SETUP_FAILED', details: result });
|
|
135
|
+
}
|
|
136
|
+
console.log(JSON.stringify(result, null, 2));
|
|
128
137
|
}
|
|
129
138
|
|
|
130
139
|
module.exports = { parseArgs, execute, run };
|