openyida 2026.10.23-beta.1 → 2026.10.23-beta.2

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.
@@ -3,7 +3,7 @@
3
3
  const os = require('node:os');
4
4
  const path = require('node:path');
5
5
  const config = require('../package.json').openyidaLocalBeta;
6
- // 仅本地 beta 消费包内测试默认值,真实凭据仍由原认证模块管理。
6
+ // PRE beta 消费包内测试默认值,真实凭据仍由原认证模块管理。
7
7
  process.env.OPENYIDA_ENDPOINT ||= config.baseUrl;
8
8
  process.env.OPENYIDA_ENV ||= config.environment;
9
9
  process.env.OPENYIDA_AUTH_DIR ||= path.join(os.homedir(), '.openyida', config.authDirectory);
@@ -114,13 +114,8 @@ async function loginQwenWork(options = {}) {
114
114
  if (!['user', 'project'].includes(session.persistence_scope) || !restored ||
115
115
  restored.access_token !== value.access_token || restored.base_url !== baseUrl ||
116
116
  restored.corp_id !== value.corp_id || restored.user_id !== value.user_id) { throw fail('PERSISTENCE_FAILED'); }
117
- // 结果只包含状态和身份元数据,真实宜搭凭据不返回主进程或工具结果。
118
- return {
119
- ok: true, status: 'ok', auth_mode: 'token', can_auto_use: true,
120
- auth_source: session.auth_source, auth_store: session.auth_store,
121
- persistence_scope: session.persistence_scope, auth_profile: session.auth_profile,
122
- base_url: baseUrl, expires_at: expiresAt, corp_id: value.corp_id, user_id: value.user_id,
123
- };
117
+ // 身份、环境和存储细节仅用于内部校验,不进入模型可见的登录结果。
118
+ return { ok: true, status: 'ok', can_auto_use: true };
124
119
  }
125
120
 
126
121
  async function run(args, options = {}) {
@@ -138,7 +133,7 @@ async function run(args, options = {}) {
138
133
  parsed[key] = value;
139
134
  }
140
135
  const result = await loginQwenWork({ ...options, ...parsed });
141
- console.log(JSON.stringify(result));
136
+ if (args.includes('--json') && !args.includes('--quiet') && (options.env || process.env).YIDA_QUIET !== '1') { console.log(JSON.stringify(result)); }
142
137
  return result;
143
138
  }
144
139
 
@@ -230,15 +230,16 @@ function buildAuthPath(login, env = process.env, runtime = null) {
230
230
  ? 'STOP_AND_REQUEST_ENV_TOKEN'
231
231
  : 'RUN_OPENYIDA_LOGIN_IF_USER_APPROVES',
232
232
  };
233
- // 仅当前活跃宿主为千问办公桌面端时,beta 才提供桌面换票指引。
233
+ // 桌面换票仅由当前活跃宿主和发行配置共同启用,不影响其他宿主的认证路径。
234
234
  if (localBeta?.desktopTicketLogin && runtime?.tool === 'qwenwork' && runtime?.subtype === 'qwenwork_desktop' && !envTokenSession) {
235
235
  authPath.auth_runtime = 'qwenwork_desktop_exchange_ticket';
236
236
  authPath.interactive_login_allowed = false;
237
237
  authPath.missing_token_action = 'RUN_OPENYIDA_LOGIN_QWENWORK';
238
- if (!authPath.can_auto_use) {
239
- authPath.next_step = 'Run standalone openyida login-qwenwork --json in the current QwenWork desktop, then continue the business command. Do not start OAuth or edit environment files.';
240
- authPath.next_step_commands = ['openyida login-qwenwork --json'];
241
- }
238
+ for (const key of ['auth_profile', 'corp_id', 'corp_name', 'user_id', 'user_name', 'store', 'persistence_scope', 'warning']) { delete authPath[key]; }
239
+ authPath.next_step = authPath.can_auto_use
240
+ ? 'Silently continue the requested business operation. Do not announce login or identity details.'
241
+ : 'Silently run standalone openyida login-qwenwork --json, then continue the requested business operation. Do not narrate login, add shell operators, start OAuth, or edit environment files.';
242
+ authPath.next_step_commands = authPath.can_auto_use ? [] : ['openyida login-qwenwork --json'];
242
243
  }
243
244
  return authPath;
244
245
  }
@@ -249,6 +250,7 @@ function buildInteractiveLogin(auth, runtime) {
249
250
  mode: 'desktop_ticket', browser_default: 'not_required', browser_owner: 'none',
250
251
  recommended_command: auth.can_auto_use ? null : 'openyida login-qwenwork --json',
251
252
  agent_action: auth.can_auto_use ? 'continue_business_command' : 'run_standalone_login_qwenwork_and_wait',
253
+ user_visible: false, success_action: 'continue_business_command_without_message',
252
254
  reason: 'qwenwork_desktop_pre_beta', completion_signal: 'process_exit_and_final_json', playwright_required: false,
253
255
  };
254
256
  }
@@ -329,6 +331,13 @@ function buildBuilderPath(login, projectRoot, manifest, env = process.env, runti
329
331
  auth,
330
332
  runtime,
331
333
  interactive_login: buildInteractiveLogin(auth, runtime),
334
+ communication: runtime.tool === 'qwenwork' && runtime.subtype === 'qwenwork_desktop' ? {
335
+ preparation_visibility: 'silent',
336
+ completion_content: 'business_result_and_business_link_only',
337
+ disclose_authentication_identity_environment: false,
338
+ report_preparation_only_when_user_action_is_required: true,
339
+ bundled_skill_path: path.resolve(__dirname, '../../yida-skills'),
340
+ } : undefined,
332
341
  environment_check_simplification: {
333
342
  contract_role: 'machine_readable_builder_runtime_not_yida_agent_business_logic',
334
343
  minimal_probe_commands: [
@@ -450,6 +459,7 @@ function compactBuilderPath(builderPath) {
450
459
  auth,
451
460
  runtime: builderPath.runtime,
452
461
  interactive_login: builderPath.interactive_login,
462
+ communication: builderPath.communication,
453
463
  environment_check_simplification: {
454
464
  minimal_probe_commands: environment.minimal_probe_commands,
455
465
  can_skip_default_exploration_when_summary_ok: environment.can_skip_default_exploration_when_summary_ok,
@@ -619,7 +629,9 @@ function buildAgentCapabilitiesSummary() {
619
629
  schema_version: 1,
620
630
  name: 'openyida-agent-capabilities-summary',
621
631
  version,
622
- login: compactLogin(loginStatus),
632
+ login: builderPath.auth.auth_runtime === 'qwenwork_desktop_exchange_ticket'
633
+ ? { status: loginStatus.status, can_auto_use: loginStatus.can_auto_use === true }
634
+ : compactLogin(loginStatus),
623
635
  workdir: projectRoot,
624
636
  workdir_exists: !!projectResolution.exists,
625
637
  workdir_source: projectResolution.source,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openyida",
3
- "version": "2026.10.23-beta.1",
3
+ "version": "2026.10.23-beta.2",
4
4
  "description": "OpenYida CLI - 宜搭低代码 AI 开发工具(安装即用,零配置)",
5
5
  "bin": {
6
6
  "openyida": "bin/yida-pre-beta.js",
@@ -2,22 +2,39 @@
2
2
  const fs = require('node:fs');
3
3
  const os = require('node:os');
4
4
  const path = require('node:path');
5
- const version = require('../package.json').version;
6
- const source = path.resolve(__dirname, '../yida-skills');
7
- const explicit = process.argv.indexOf('--target-dir');
8
- const target = explicit < 0 ? path.join(os.homedir(), '.qwenworkcn', 'skills', 'yida-skills') : path.resolve(process.argv[explicit + 1]);
9
- if (explicit < 0 && !fs.existsSync(path.join(os.homedir(), '.qwenworkcn'))) process.exit(0);
10
- // 备份留在技能扫描目录之外,避免旧指引再次被宿主加载。
11
- const backup = explicit < 0 ? path.join(os.homedir(), '.qwenworkcn', '.openyida-beta-backups', version + '-' + Date.now()) : target + '.previous-' + Date.now();
12
- const stage = target + '.installing-' + Date.now();
13
- fs.mkdirSync(path.dirname(target), { recursive: true });
14
- fs.cpSync(source, stage, { recursive: true });
15
- let moved = false;
16
- try {
17
- if (fs.existsSync(target)) { fs.mkdirSync(path.dirname(backup), { recursive: true }); fs.renameSync(target, backup); moved = true; }
18
- fs.renameSync(stage, target);
19
- } catch (error) {
20
- if (moved && !fs.existsSync(target)) fs.renameSync(backup, target);
21
- throw error;
5
+
6
+ /** 技能复制属于可选安装步骤,权限不足时保留旧目录,CLI 仍可使用随包技能。 */
7
+ function install(options = {}) {
8
+ const io = options.fs || fs;
9
+ const home = options.home || os.homedir();
10
+ const root = path.join(home, '.qwenworkcn');
11
+ if (!options.target && !io.existsSync(root)) { return { status: 'skipped' }; }
12
+ const source = options.source || path.resolve(__dirname, '../yida-skills');
13
+ const target = options.target || path.join(root, 'skills', 'yida-skills');
14
+ const unique = `${Date.now()}-${process.pid}`;
15
+ const backup = path.join(options.backupRoot || path.join(options.target ? path.dirname(target) : root, '.openyida-beta-backups'), unique);
16
+ const stage = path.join(path.dirname(target), `.openyida-installing-${unique}`);
17
+ let moved = false;
18
+ try {
19
+ io.mkdirSync(path.dirname(target), { recursive: true });
20
+ io.cpSync(source, stage, { recursive: true });
21
+ if (io.existsSync(target)) {
22
+ io.mkdirSync(path.dirname(backup), { recursive: true });
23
+ io.renameSync(target, backup);
24
+ moved = true;
25
+ }
26
+ io.renameSync(stage, target);
27
+ return { status: 'updated' };
28
+ } catch {
29
+ // 可选复制失败不使 npm 回滚;旧技能已移动时先恢复,备份始终保留在扫描目录外。
30
+ try { if (moved && !io.existsSync(target)) { io.renameSync(backup, target); } } catch { /* 保留备份,避免覆盖现有内容。 */ }
31
+ try { io.rmSync(stage, { recursive: true, force: true }); } catch { /* 权限不足时不扩大清理范围。 */ }
32
+ return { status: 'skipped' };
33
+ }
22
34
  }
23
- console.log(JSON.stringify({ status: 'ok', version, qwenwork_skills_updated: true, default_environment: 'pre' }));
35
+
36
+ if (require.main === module) {
37
+ const index = process.argv.indexOf('--target-dir');
38
+ install(index >= 0 && process.argv[index + 1] ? { target: path.resolve(process.argv[index + 1]) } : {});
39
+ }
40
+ module.exports = { install };
@@ -6,17 +6,6 @@ description: >
6
6
  重要路由规则:完整应用/系统/平台的从零搭建、已有 app 但没有任何页面、或已有 app/page 需要补成完整业务系统时,必须先加载 yida-app 子技能作为编排入口。已有资源的单点改字段、改页面、发布、权限或数据任务按对应子技能路由。
7
7
  ---
8
8
 
9
- ## 本地 PRE beta 验收配置
10
-
11
- 本包是本地联调 beta,默认环境为 PRE,登录态目录独立,无需添加或切换环境。
12
- 先执行一次 `openyida agent-capabilities --summary-json`。
13
- 只有结果明确满足 `runtime.tool=qwenwork` 且 `runtime.subtype=qwenwork_desktop`,并且 `builder_path.interactive_login.mode=desktop_ticket` 时,才使用千问办公桌面免登。
14
- 如果该条件成立且 `login.can_auto_use=false`,单独执行 `openyida login-qwenwork --json`;这条 Bash 命令不要拼接 cd、env、管道或重定向。成功后直接继续用户要求的业务操作。
15
- 不是千问办公桌面宿主,或 runtime 缺失时,不执行该命令;按原认证快照处理。不得仅根据安装目录或产品名推断当前宿主。
16
- 千问办公桌面换票失败时报告错误,不回退 OAuth,不手改环境配置,不选择生产 profile,不读取或展示 Token。
17
- 用户只要求空白应用时,完成认证与工作目录准备后执行 `openyida create-app --name "<用户要求的名称>"`,无需设计表单、页面或主题。
18
-
19
-
20
9
  # 宜搭应用开发指南
21
10
 
22
11
  在执行宜搭应用/页面/审批流等任务前先确认环境与登录态,再根据用户需求和已解析的 app/page/form/process 等上下文资源,分析任务属于完整搭建、已有资源补齐还是单点任务,并加载对应子技能执行。
@@ -90,6 +79,10 @@ Fast / Plan 选定的主题和主色属于整个应用:导航、原生页、
90
79
 
91
80
  每项待办对应一个阶段,直接使用上方短标题。创建应用、表单、数据、图片、页面和发布分别展示。执行中保持标题与列表顺序稳定,完成后标记完成并保留记录。图片准备与表单、页面搭建可同时进行,列表顺序仅用于展示。业务细节写在进度消息中,任务编号、命令、路径、授权依据和耗时写入内部执行记录;用户要求的耗时统计集中放入报告。素材采集与应用创建同时进行时,进度描述统一为“素材采集&应用创建”;单独进行时使用对应阶段名称。图片数量、用途及任务详情归入内部执行记录。
92
81
 
82
+ ## 千问办公桌面端的后台准备
83
+
84
+ 当前快照确认运行于千问办公桌面端时,安装、环境检查和自动登录按[后台准备规则](references/qwenwork-desktop-login.md)静默执行。用户只需要看到业务进度和业务结果。
85
+
93
86
  ## 执行步骤
94
87
 
95
88
  ### Step 1:环境与登录态确认
@@ -0,0 +1,33 @@
1
+ # 千问办公桌面端后台准备
2
+
3
+ ## 用户沟通
4
+
5
+ 安装、版本核验、环境检查、自动登录和登录恢复均为内部准备,不加入用户可见的步骤、待办或完成总结,也不播报「免登成功」「正在换票」等状态。准备完成后直接继续用户请求的业务操作。
6
+
7
+ 登录命令和能力快照的 JSON 仅用于内部判断。不向用户展示或解释认证方式、环境名、后端域名、用户 ID、组织 ID、profile、凭据路径、有效期和令牌,即使掩码后也不展示。最终只交付用户需要的业务结果、应用名称和应用访问链接;应用链接属于业务交付,可正常展示。
8
+
9
+ 仅在确实需要用户操作才能继续时,用一句普通语言说明阻塞和所需操作,不展开协议、接口、路径或内部错误细节。用户明确要求排障或查看认证信息时,再按其指定范围说明。
10
+
11
+ ## 安装与技能
12
+
13
+ 用户指定版本时先安装该版本,再做一次能力检查。镜像尚未同步时,直接使用官方 npm 源安装;短暂的下载 404 先重试核验,不据此断言包已损坏或擅自换成正式版。随包技能通过能力快照的 `builder_path.communication.bundled_skill_path` 定位,安装后优先读取该版本技能。
14
+
15
+ 配套技能复制是可选步骤。宿主技能目录写入受限时保留旧目录,CLI 安装继续完成,使用包内技能;不要求用户修改沙箱规则,不反复申请宿主目录权限。
16
+
17
+ ## 自动登录
18
+
19
+ 只以当前 `openyida agent-capabilities --summary-json` 的 `runtime.tool=qwenwork`、`runtime.subtype=qwenwork_desktop` 和 `builder_path.interactive_login.mode=desktop_ticket` 判断桌面换票能力。安装目录、产品名称和历史会话不能替代当前快照。
20
+
21
+ 快照显示登录可用时直接执行用户请求;登录不可用且上述条件全部成立时,单独执行下面一条命令,成功后直接继续业务操作:
22
+
23
+ ```bash
24
+ openyida login-qwenwork --json
25
+ ```
26
+
27
+ 这条命令不拼接 `cd`、`env`、重定向、管道、`head`、`echo` 或任何其他 Shell 命令;执行工具已提供退出状态,无需追加输出。专用命令只消费本次私有通道的短期一次性兑换票,不调用或递归进入普通 `login`。
28
+
29
+ 真实宜搭凭据仅由 CLI 校验并持久化,不读取、填写或展示任何令牌、兑换票和认证文件。保持包内配置及实际认证 origin,不根据历史记忆猜测环境等价或切换到其他环境、组织。凭据过期时重新执行专用命令;票据缺失、过期、重放、签发或消费失败时停止,不回退 OAuth、直接凭据或手改环境文件。
30
+
31
+ 多组织确实需要用户选择时,仅询问完成业务操作所需的组织,不由模型猜测。其他宿主继续遵循原认证快照。
32
+
33
+ 用户只要求新建空白应用时,直接创建该应用,无需展开 PRD、表单、页面或主题设计。创建命令以当前版本契约为准,成功后只交付应用名称和访问链接。
@@ -1,12 +1,6 @@
1
- ## 本地 PRE beta 验收配置
2
-
3
- 本包是本地联调 beta,默认环境为 PRE,登录态目录独立,无需添加或切换环境。
4
- 先执行一次 `openyida agent-capabilities --summary-json`。
5
- 只有结果明确满足 `runtime.tool=qwenwork` 且 `runtime.subtype=qwenwork_desktop`,并且 `builder_path.interactive_login.mode=desktop_ticket` 时,才使用千问办公桌面免登。
6
- 如果该条件成立且 `login.can_auto_use=false`,单独执行 `openyida login-qwenwork --json`;这条 Bash 命令不要拼接 cd、env、管道或重定向。成功后直接继续用户要求的业务操作。
7
- 不是千问办公桌面宿主,或 runtime 缺失时,不执行该命令;按原认证快照处理。不得仅根据安装目录或产品名推断当前宿主。
8
- 千问办公桌面换票失败时报告错误,不回退 OAuth,不手改环境配置,不选择生产 profile,不读取或展示 Token。
9
- 用户只要求空白应用时,完成认证与工作目录准备后执行 `openyida create-app --name "<用户要求的名称>"`,无需设计表单、页面或主题。
1
+ ## 千问办公桌面端
2
+
3
+ 当前快照确认运行于千问办公桌面端时,遵循[后台准备规则](qwenwork-desktop-login.md),静默完成下述准备,不向用户逐项播报。
10
4
 
11
5
  # 环境准备与登录检测
12
6
 
@@ -3,17 +3,6 @@ name: yida-login
3
3
  description: 宜搭登录态管理。以 OpenYida auth snapshot 为准;默认 OAuth token,snapshot 返回 env 注入状态时使用运行环境注入 token。
4
4
  ---
5
5
 
6
- ## 本地 PRE beta 验收配置
7
-
8
- 本包是本地联调 beta,默认环境为 PRE,登录态目录独立,无需添加或切换环境。
9
- 先执行一次 `openyida agent-capabilities --summary-json`。
10
- 只有结果明确满足 `runtime.tool=qwenwork` 且 `runtime.subtype=qwenwork_desktop`,并且 `builder_path.interactive_login.mode=desktop_ticket` 时,才使用千问办公桌面免登。
11
- 如果该条件成立且 `login.can_auto_use=false`,单独执行 `openyida login-qwenwork --json`;这条 Bash 命令不要拼接 cd、env、管道或重定向。成功后直接继续用户要求的业务操作。
12
- 不是千问办公桌面宿主,或 runtime 缺失时,不执行该命令;按原认证快照处理。不得仅根据安装目录或产品名推断当前宿主。
13
- 千问办公桌面换票失败时报告错误,不回退 OAuth,不手改环境配置,不选择生产 profile,不读取或展示 Token。
14
- 用户只要求空白应用时,完成认证与工作目录准备后执行 `openyida create-app --name "<用户要求的名称>"`,无需设计表单、页面或主题。
15
-
16
-
17
6
  # yida-login
18
7
 
19
8
  ## 模式
@@ -27,21 +16,11 @@ description: 宜搭登录态管理。以 OpenYida auth snapshot 为准;默认
27
16
  - 浏览器归属以 `builder_path.interactive_login.mode` 为准:`not_required` 不触发 OAuth;`cli_auto_open` 执行 `openyida login` 并等待;`caller_open_url` 执行 `openyida login --no-browser`,由 Agent 优先调用沙箱浏览器 / 内置 Browser 打开 CLI 输出的授权 URL 一次;`unsupported` 停止并说明没有可用浏览器能力,不要默认安装 Playwright。
28
17
  - `caller_open_url` 模式下,Agent 不要只把 URL 贴给用户然后等待。只有当前宿主没有浏览器工具,或浏览器工具调用失败时,才退回让用户手动打开 URL。
29
18
 
30
- ## 千问办公专用免登命令(显式使用)
19
+ ## 千问办公桌面端的后台登录
31
20
 
32
- 先以 `openyida agent-capabilities --summary-json` 的 `runtime.tool=qwenwork`、`runtime.subtype=qwenwork_desktop` 确认当前活跃宿主确实是千问办公桌面端;仅安装过千问办公、存在相关目录或会话提到产品名均不能作为判断依据。仅当上述宿主条件成立、用户已选择桌面免登且当前桌面宿主已接入 v2 一次性票据能力时,独立执行:
33
-
34
- ```bash
35
- openyida login-qwenwork --json
36
- ```
21
+ 先以当前快照的 `runtime.tool=qwenwork`、`runtime.subtype=qwenwork_desktop` 和 `builder_path.interactive_login.mode=desktop_ticket` 确认桌面换票能力。满足条件后,按[后台准备规则](../../references/qwenwork-desktop-login.md)静默补齐登录态,随后继续业务操作。
37
22
 
38
- - 此命令是独立入口,直接消费兑换票,不调用、重启或递归进入普通 login。普通 login 的任何参数都不会触发桌面免登;旧 login --qwenwork 已停用。
39
- - 主进程只签发最长 300 秒的 exchange_ticket,不接收真实宜搭 access token。CLI 从本次私有环境读取票据,在沙箱内向原 HTTPS origin 消费,再校验并持久化宜搭凭据。
40
- - 不读取、打印或手工填写千问 Token、宜搭 Token 或兑换票。真实宜搭凭据不得返回主进程、Hook 或工具结果。
41
- - 不与 cd、管道、重定向或其他命令拼接;多组织时由用户指定真实宜搭 --corp-id。可使用隔离新版 CLI 的绝对路径入口。
42
- - 缺票据、签发失败、身份切换、过期、重放或消费存储不可用时停止,不改用直接凭据交付或 OAuth。
43
- - 成功后保留原 origin、有效期和宜搭身份;后续新进程无需继续注入票据。没有 refresh token,凭据过期后重新执行专用命令。
44
- - 合成测试或旧 v1 部署成功不能代替真实 PRE v2、当前桌面 JWT 和安装版验收。
23
+ 普通 `login` 不触发桌面换票;其他宿主继续遵循下方认证规则。票据协议和研发验证见仓库的 `docs/guides/qwenwork-desktop-login.md`。
45
24
 
46
25
  ## 前置检查
47
26