openyida 2026.10.15-2 → 2026.10.16
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/token-auth.js +27 -1
- package/lib/auth/token-store.js +29 -3
- package/lib/core/locales/en.js +2 -0
- package/lib/core/locales/zh.js +2 -0
- package/lib/core/utils.js +5 -0
- package/package.json +1 -1
- package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-fine-lines/app_theme.css +3 -3
- package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-fine-lines/design.md +3 -2
package/lib/auth/token-auth.js
CHANGED
|
@@ -229,6 +229,26 @@ function createTokenAuthRequiredError(reason, sourceError) {
|
|
|
229
229
|
);
|
|
230
230
|
}
|
|
231
231
|
|
|
232
|
+
function createAuthProfileSelectionError(status) {
|
|
233
|
+
const reason = status.failure_reason || status.status;
|
|
234
|
+
if (!['profile_required', 'profile_not_found'].includes(reason)) {return null;}
|
|
235
|
+
const { CliError } = require('../core/cli-error');
|
|
236
|
+
const { t } = require('../core/i18n');
|
|
237
|
+
return new CliError(t(`common.auth_${reason}`), {
|
|
238
|
+
code: reason === 'profile_required' ? 'AUTH_PROFILE_REQUIRED' : 'AUTH_PROFILE_NOT_FOUND',
|
|
239
|
+
details: {
|
|
240
|
+
authMode: 'token',
|
|
241
|
+
status: reason,
|
|
242
|
+
failure_reason: reason,
|
|
243
|
+
auth_profile: status.auth_profile,
|
|
244
|
+
candidate_count: status.candidate_count,
|
|
245
|
+
candidates: status.candidates,
|
|
246
|
+
next_step: status.next_step,
|
|
247
|
+
next_step_commands: status.next_step_commands,
|
|
248
|
+
},
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
|
|
232
252
|
function createTokenRefreshFailedError(reason, sourceError) {
|
|
233
253
|
const { CliError } = require('../core/cli-error');
|
|
234
254
|
return new CliError(
|
|
@@ -630,7 +650,12 @@ async function tokenLogout(options = {}) {
|
|
|
630
650
|
}
|
|
631
651
|
|
|
632
652
|
async function getAccessToken(options = {}) {
|
|
633
|
-
|
|
653
|
+
const resolution = resolveTokenSession(options);
|
|
654
|
+
let session = resolution.session;
|
|
655
|
+
if (!session) {
|
|
656
|
+
const selectionError = createAuthProfileSelectionError(resolution);
|
|
657
|
+
if (selectionError) {throw selectionError;}
|
|
658
|
+
}
|
|
634
659
|
// Do not reject a token from local expiry metadata. The business endpoint is
|
|
635
660
|
// the authority: requestWithAutoLogin refreshes only after it rejects the
|
|
636
661
|
// access token, then retries with the newly persisted local session.
|
|
@@ -675,4 +700,5 @@ module.exports = {
|
|
|
675
700
|
resolveTokenBaseUrl,
|
|
676
701
|
isRefreshAuthRequired,
|
|
677
702
|
createTokenRefreshFailedError,
|
|
703
|
+
createAuthProfileSelectionError,
|
|
678
704
|
};
|
package/lib/auth/token-store.js
CHANGED
|
@@ -472,12 +472,31 @@ function saveAuthProfilePointer(session, options = {}) {
|
|
|
472
472
|
return pointer;
|
|
473
473
|
}
|
|
474
474
|
|
|
475
|
-
function
|
|
476
|
-
const
|
|
477
|
-
|
|
475
|
+
function getWorkspaceAuthProfilePointerFilePath(options = {}) {
|
|
476
|
+
const root = path.resolve(resolveProjectRoot(options));
|
|
477
|
+
const workspace = path.dirname(root);
|
|
478
|
+
if (isEnvTokenAuthMode(options.env || process.env) || path.basename(root) !== 'project' ||
|
|
479
|
+
fs.existsSync(path.join(workspace, 'config.json'))) {
|
|
478
480
|
return null;
|
|
479
481
|
}
|
|
480
482
|
try {
|
|
483
|
+
// Only bridge the conventional workspace -> workspace/project transition.
|
|
484
|
+
// A symlinked project belongs to its own workspace, not its lexical parent.
|
|
485
|
+
if (fs.realpathSync(root) !== path.join(fs.realpathSync(workspace), 'project')) {return null;}
|
|
486
|
+
return getAuthProfilePointerFilePath({ ...options, projectRoot: workspace, envName: resolveEnvName(options) });
|
|
487
|
+
} catch {return null;}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
function loadAuthProfilePointer(options = {}) {
|
|
491
|
+
try {
|
|
492
|
+
let pointerFile = getAuthProfilePointerFilePath(options);
|
|
493
|
+
// An explicit child selection (including an unbound/corrupt pointer) wins.
|
|
494
|
+
// Reading inherited metadata never copies credentials or writes a pointer.
|
|
495
|
+
if (!fs.existsSync(pointerFile)) {
|
|
496
|
+
if (fs.existsSync(getTokenFilePath(options))) {return null;}
|
|
497
|
+
pointerFile = getWorkspaceAuthProfilePointerFilePath(options);
|
|
498
|
+
}
|
|
499
|
+
if (!pointerFile || !fs.existsSync(pointerFile)) {return null;}
|
|
481
500
|
const pointer = JSON.parse(fs.readFileSync(pointerFile, 'utf8'));
|
|
482
501
|
if (!pointer || typeof pointer !== 'object' || !pointer.auth_profile) {
|
|
483
502
|
return null;
|
|
@@ -491,6 +510,13 @@ function loadAuthProfilePointer(options = {}) {
|
|
|
491
510
|
function clearAuthProfilePointer(options = {}) {
|
|
492
511
|
try {
|
|
493
512
|
const pointerFile = getAuthProfilePointerFilePath(options);
|
|
513
|
+
const workspacePointerFile = getWorkspaceAuthProfilePointerFilePath(options);
|
|
514
|
+
if (workspacePointerFile && fs.existsSync(workspacePointerFile)) {
|
|
515
|
+
// Detaching this project must not revive its inherited workspace choice
|
|
516
|
+
// on the next command, or clear another project's workspace selection.
|
|
517
|
+
writeJsonFileAtomic(pointerFile, { version: AUTH_PROFILE_VERSION, detached: true });
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
494
520
|
if (fs.existsSync(pointerFile)) {
|
|
495
521
|
fs.unlinkSync(pointerFile);
|
|
496
522
|
}
|
package/lib/core/locales/en.js
CHANGED
|
@@ -1016,6 +1016,8 @@ Examples:
|
|
|
1016
1016
|
data_check_failed: ' ⚠️ Data check failed, proceeding with modification',
|
|
1017
1017
|
},
|
|
1018
1018
|
common: {
|
|
1019
|
+
auth_profile_required: 'Multiple organizations have saved credentials. Run openyida auth profiles, then openyida auth profile switch <auth_profile> to select this project\'s organization.',
|
|
1020
|
+
auth_profile_not_found: 'The requested organization credentials were not found. Run openyida auth profiles to inspect saved organizations and select the correct profile.',
|
|
1019
1021
|
auth_identity_changed: 'Authentication identity changed during preflight; no write was issued.',
|
|
1020
1022
|
http_status: ' HTTP status: {0}',
|
|
1021
1023
|
http_response: ' HTTP response: {0}',
|
package/lib/core/locales/zh.js
CHANGED
|
@@ -987,6 +987,8 @@ openyida - 宜搭命令行工具
|
|
|
987
987
|
data_check_failed: ' ⚠️ 数据量检查失败,继续执行修改',
|
|
988
988
|
},
|
|
989
989
|
common: {
|
|
990
|
+
auth_profile_required: '已有多个组织的登录凭证,请执行 openyida auth profiles,并用 openyida auth profile switch <auth_profile> 选择本项目的组织。',
|
|
991
|
+
auth_profile_not_found: '未找到指定组织的登录凭证,请执行 openyida auth profiles 核对已有组织,再选择正确的登录凭证。',
|
|
990
992
|
auth_identity_changed: '校验期间登录身份发生变化,本次未发起写入。',
|
|
991
993
|
http_status: ' HTTP 状态码: {0}',
|
|
992
994
|
http_response: ' HTTP 响应: {0}',
|
package/lib/core/utils.js
CHANGED
|
@@ -960,6 +960,11 @@ function triggerLogin(options = {}) {
|
|
|
960
960
|
if (tokenAuthData) {
|
|
961
961
|
return tokenAuthData;
|
|
962
962
|
}
|
|
963
|
+
const { createAuthProfileSelectionError } = require('../auth/token-auth');
|
|
964
|
+
const selectionError = createAuthProfileSelectionError(getAuthStatus({
|
|
965
|
+
...options, projectRoot: options.projectRoot || findProjectRoot(),
|
|
966
|
+
}));
|
|
967
|
+
if (selectionError) {throw selectionError;}
|
|
963
968
|
const { CliError } = require('./cli-error');
|
|
964
969
|
throw new CliError(
|
|
965
970
|
'not_logged_in: token auth is unavailable. Run openyida login first.',
|
package/package.json
CHANGED
package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-fine-lines/app_theme.css
CHANGED
|
@@ -106,8 +106,8 @@
|
|
|
106
106
|
--corner-3: 2px;
|
|
107
107
|
--corner-4: 2px;
|
|
108
108
|
--corner-5: 2px;
|
|
109
|
-
--corner-circle:
|
|
110
|
-
--corner-semicircle:
|
|
109
|
+
--corner-circle: 999px;
|
|
110
|
+
--corner-semicircle: var(--corner-2);
|
|
111
111
|
|
|
112
112
|
/* 阴影 */
|
|
113
113
|
--shadow-1: 0px 2px 4px 0px rgba(0, 0, 0, 0.12);
|
|
@@ -158,7 +158,7 @@
|
|
|
158
158
|
/* 卡片 */
|
|
159
159
|
--pod-card-padding: 20px;
|
|
160
160
|
--pod-card-border-radius: var(--pod-xl-border-radius, 20px);
|
|
161
|
-
--pod-card-border:
|
|
161
|
+
--pod-card-border: 1px solid var(--color-line1-1);
|
|
162
162
|
--pod-card-spacing: var(--pod-md-gap-pad-margin);
|
|
163
163
|
|
|
164
164
|
/* 导航:顶导与侧导布局 */
|
package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-fine-lines/design.md
CHANGED
|
@@ -11,6 +11,7 @@ tokens:
|
|
|
11
11
|
"--pod-app-root-bg-image": "none" # 仅作用于根节点;本主题不使用背景图
|
|
12
12
|
"--pod-page-bg-color": "#FFFFFF" # neutral-gray;白色内容画布
|
|
13
13
|
"--pod-card-bg-color": "#FFFFFF" # neutral-gray;一级内容表面
|
|
14
|
+
"--pod-card-border": "1px solid var(--color-line1-1)"
|
|
14
15
|
"--pod-table-cell-color": "var(--pod-card-bg-color)" # 表格正文跟随卡片表面
|
|
15
16
|
"--pod-shell-padding": "0px"
|
|
16
17
|
navigation:
|
|
@@ -112,8 +113,8 @@ tokens:
|
|
|
112
113
|
"--corner-3": 2px # 气泡、浮层、弹窗外轮廓
|
|
113
114
|
"--corner-4": 2px # 小型嵌入摘要与内部组合容器
|
|
114
115
|
"--corner-5": 2px # 卡片、独立面板与抽屉外轮廓
|
|
115
|
-
"--corner-circle":
|
|
116
|
-
"--corner-semicircle":
|
|
116
|
+
"--corner-circle": 999px # 等宽高头像、图例圆点
|
|
117
|
+
"--corner-semicircle": "var(--corner-2)" # 胶囊按钮、计数标记、进度条圆头
|
|
117
118
|
shadow:
|
|
118
119
|
"--shadow-1": "0px 2px 4px 0px rgba(0, 0, 0, 0.12)"
|
|
119
120
|
"--shadow-2": "0px 4px 20px -1px rgba(0, 0, 0, 0.16)"
|