openyida 2026.9.22-beta.2 → 2026.9.22-beta.4
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/lib/auth/dws-sync.js
CHANGED
|
@@ -10,12 +10,19 @@ const FAILURE_STATUSES = new Set([
|
|
|
10
10
|
'dws_identity_unmapped', 'dws_upstream_unavailable', 'dws_policy_rejected', 'dws_session_expired',
|
|
11
11
|
]);
|
|
12
12
|
|
|
13
|
-
function failure(reason) {
|
|
13
|
+
function failure(reason, extra = {}) {
|
|
14
14
|
return new CliError(`DWS sync failed: ${reason}`, {
|
|
15
|
-
code: 'DWS_SYNC_FAILED', details: { reason },
|
|
15
|
+
code: 'DWS_SYNC_FAILED', details: { reason, ...extra },
|
|
16
16
|
});
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
function rateLimitFailure(response, headers = {}) {
|
|
20
|
+
const data = response && (response.data || response.content || response);
|
|
21
|
+
if (!data || !['dws_rate_limited', 'dws_rate_limit_unavailable'].includes(data.status)) { return null; }
|
|
22
|
+
const delay = Number(data.retry_after ?? headers['retry-after']);
|
|
23
|
+
return failure(data.status, { retry_after: Number.isInteger(delay) && delay > 0 && delay <= 60 ? delay : 1 });
|
|
24
|
+
}
|
|
25
|
+
|
|
19
26
|
function readHandoff(input = process.stdin, timeoutMs = 10000) {
|
|
20
27
|
return new Promise((resolve, reject) => {
|
|
21
28
|
if (input.isTTY) { reject(failure('STDIN_REQUIRED')); return; }
|
|
@@ -80,11 +87,13 @@ async function syncDws(options = {}) {
|
|
|
80
87
|
response = await requestJson('POST', `${target.origin}/openapi/cli/v1/auth/dws/token`, {
|
|
81
88
|
...(expectedCorp ? { corpId: expectedCorp } : {}), environment: handoff.environment,
|
|
82
89
|
}, { Authorization: `Bearer ${handoff.accessToken}` }, { timeoutMs: 30000, maxResponseBytes: 65536 });
|
|
83
|
-
} catch {
|
|
84
|
-
throw failure('EXCHANGE_REQUEST_FAILED');
|
|
90
|
+
} catch (error) {
|
|
91
|
+
throw rateLimitFailure(error && error.payload, (error && error.headers) || {}) || failure('EXCHANGE_REQUEST_FAILED');
|
|
85
92
|
} finally {
|
|
86
93
|
delete handoff.accessToken;
|
|
87
94
|
}
|
|
95
|
+
const limited = rateLimitFailure(response);
|
|
96
|
+
if (limited) { throw limited; }
|
|
88
97
|
const data = response && (response.data || response.content || response);
|
|
89
98
|
if (!data || response.success === false || response.ok === false || data.status !== 'ok') {
|
|
90
99
|
throw failure(data && FAILURE_STATUSES.has(data.status) ? data.status : 'EXCHANGE_REJECTED');
|
|
@@ -96,7 +96,9 @@ function compactSkillsDiagnostics(skillsDiagnostics) {
|
|
|
96
96
|
reason: candidate.reason,
|
|
97
97
|
exists: candidate.exists,
|
|
98
98
|
writable: candidate.writable,
|
|
99
|
+
readable: candidate.readable,
|
|
99
100
|
usable: candidate.usable,
|
|
101
|
+
installable: candidate.installable,
|
|
100
102
|
workspace_only: candidate.workspace_only,
|
|
101
103
|
}
|
|
102
104
|
: null;
|
|
@@ -105,6 +107,7 @@ function compactSkillsDiagnostics(skillsDiagnostics) {
|
|
|
105
107
|
schema_version: skillsDiagnostics.schema_version,
|
|
106
108
|
active_tool: skillsDiagnostics.active_tool,
|
|
107
109
|
selected: compactCandidate(skillsDiagnostics.selected),
|
|
110
|
+
install_target: compactCandidate(skillsDiagnostics.install_target),
|
|
108
111
|
candidates: (skillsDiagnostics.candidates || []).map(compactCandidate),
|
|
109
112
|
diagnostics: skillsDiagnostics.diagnostics || {},
|
|
110
113
|
};
|
package/lib/core/copy.js
CHANGED
|
@@ -390,7 +390,7 @@ function run(args = process.argv.slice(3)) {
|
|
|
390
390
|
// 若宿主用户级目录不可写,按 capabilities 诊断降级到工作区可发现目录。
|
|
391
391
|
const activeResult = envResults.find((r) => r.isActive);
|
|
392
392
|
const skillsDiagnostics = buildSkillsDiagnostics({ ...runtimeOptions, projectResolution });
|
|
393
|
-
const selectedSkills = skillsDiagnostics.
|
|
393
|
+
const selectedSkills = skillsDiagnostics.install_target;
|
|
394
394
|
|
|
395
395
|
if (selectedSkills && selectedSkills.path) {
|
|
396
396
|
assertCopyDestinationSafe(packageYidaSkillsDir, selectedSkills.path);
|
package/lib/core/utils.js
CHANGED
|
@@ -670,6 +670,14 @@ function buildSkillsCandidate(destPath, source, scope, reason) {
|
|
|
670
670
|
const parentDir = path.dirname(destPath);
|
|
671
671
|
const nearestWritableBase = nearestExistingAncestor(parentDir);
|
|
672
672
|
const writable = canWritePath(destPath);
|
|
673
|
+
const entryPath = path.join(destPath, 'SKILL.md');
|
|
674
|
+
let readable = false;
|
|
675
|
+
try {
|
|
676
|
+
readable = fs.statSync(entryPath).isFile();
|
|
677
|
+
fs.accessSync(entryPath, fs.constants.R_OK);
|
|
678
|
+
} catch {
|
|
679
|
+
readable = false;
|
|
680
|
+
}
|
|
673
681
|
return {
|
|
674
682
|
path: destPath,
|
|
675
683
|
source,
|
|
@@ -680,7 +688,9 @@ function buildSkillsCandidate(destPath, source, scope, reason) {
|
|
|
680
688
|
parent_exists: fs.existsSync(parentDir),
|
|
681
689
|
nearest_existing_parent: nearestWritableBase,
|
|
682
690
|
writable,
|
|
683
|
-
|
|
691
|
+
readable,
|
|
692
|
+
usable: readable,
|
|
693
|
+
installable: scope !== 'package' && writable,
|
|
684
694
|
workspace_only: scope === 'workspace',
|
|
685
695
|
};
|
|
686
696
|
}
|
|
@@ -787,7 +797,13 @@ function buildSkillsDiagnostics(options = {}) {
|
|
|
787
797
|
);
|
|
788
798
|
}
|
|
789
799
|
|
|
790
|
-
|
|
800
|
+
// Bundled documentation is a read fallback, never an installation destination.
|
|
801
|
+
addCandidate(
|
|
802
|
+
options.bundledSkillsPath || path.resolve(__dirname, '../../yida-skills'),
|
|
803
|
+
'package:yida-skills', 'package', 'bundled_skills_read_fallback'
|
|
804
|
+
);
|
|
805
|
+
const selected = candidates.find((candidate) => candidate.usable) || null;
|
|
806
|
+
const installTarget = candidates.find((candidate) => candidate.installable) || null;
|
|
791
807
|
const diagnostics = {
|
|
792
808
|
config_content_error: configSkillPaths.error,
|
|
793
809
|
fallback: selected && selected.workspace_only
|
|
@@ -808,6 +824,7 @@ function buildSkillsDiagnostics(options = {}) {
|
|
|
808
824
|
}
|
|
809
825
|
: null,
|
|
810
826
|
selected,
|
|
827
|
+
install_target: installTarget,
|
|
811
828
|
candidates,
|
|
812
829
|
diagnostics,
|
|
813
830
|
};
|
package/package.json
CHANGED
|
@@ -11,7 +11,8 @@ description: 宜搭登录态管理。以 OpenYida auth snapshot 为准;默认
|
|
|
11
11
|
- 不要根据 agent 名称、宿主产品、workspace 路径或猜测的环境变量推断认证模式。
|
|
12
12
|
- 先读 `openyida agent-capabilities --summary-json`;只有需要更多信息时,才降级执行 `openyida login --check-only --json`。
|
|
13
13
|
- snapshot 返回 `login.auth_source=env` 或 `failure_reason=env_token_missing` 时,进入运行环境注入 token 模式。凭证只来自运行环境注入的 `OPENYIDA_ACCESS_TOKEN`、`OPENYIDA_REFRESH_TOKEN` 等环境变量。
|
|
14
|
-
-
|
|
14
|
+
- snapshot 明确返回 `credential_source=dws`,或当前任务已由 DWS prepare 交接时,优先使用下文 DWS 恢复流程;不自动改走 OAuth。
|
|
15
|
+
- 除上述 DWS 和 env 注入场景外,其他 `auth_mode=token` 场景使用默认 OAuth token session。
|
|
15
16
|
- 不要从 `.cache/cookies*.json` 推断登录态。
|
|
16
17
|
- 浏览器归属以 `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。
|
|
17
18
|
- `caller_open_url` 模式下,Agent 不要只把 URL 贴给用户然后等待。只有当前宿主没有浏览器工具,或浏览器工具调用失败时,才退回让用户手动打开 URL。
|
|
@@ -42,9 +43,15 @@ openyida login --check-only --json
|
|
|
42
43
|
| `auth_mode=token`,未登录,且 `interactive_login.mode=caller_open_url` | 只执行一次 `openyida login --no-browser`,由 Agent 优先调用沙箱浏览器 / 内置 Browser 打开输出 URL 一次,并等待原命令结束;无浏览器工具或调用失败时才让用户手动打开 |
|
|
43
44
|
| `auth_mode=token`,未登录,且 `interactive_login.mode=unsupported` | 停止并向用户说明当前运行环境没有桌面浏览器或 Agent 浏览器能力 |
|
|
44
45
|
|
|
46
|
+
## DWS 登录态恢复
|
|
47
|
+
|
|
48
|
+
仅当 snapshot 明确 credential_source=dws 或任务已有可信的 DWS 交接上下文时适用,不根据宿主名字或目录猜测。宜搭会话过期/已退出不等于 DWS 已退出。用户授权继续任务时,交回 DWS 路由,通过原任务目录的 dws yida prepare 重新交接;环境与 workdir 沿用已确认值,完成后重新核对用户、组织及 execution。Agent 不读取 token、不自行调用 auth sync-dws 拼接凭据,也不先触发 openyida login。
|
|
49
|
+
|
|
50
|
+
用户明确退出时只完成退出,不立即恢复登录。限流、网络或服务故障、业务权限不足不触发登录恢复循环。DWS 不可用时明确告知需要宿主恢复交接;只有确认 DWS 凭证本身失效,才引导恢复 DWS 登录。写入结果未知时先查询,不能因重新认证重复写入。
|
|
51
|
+
|
|
45
52
|
## Token 模式命令
|
|
46
53
|
|
|
47
|
-
只有 auth snapshot 未返回 env
|
|
54
|
+
只有 auth snapshot 未返回 env 注入模式,且当前任务不属于上述 DWS 交接路径时,才使用 OAuth 登录。
|
|
48
55
|
|
|
49
56
|
```bash
|
|
50
57
|
openyida login
|