dsh-crwu-workbench 0.0.15 → 0.0.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/CHANGELOG.md +42 -0
- package/bin/darwin-arm64/crwu +0 -0
- package/bin/manifest.json +6 -6
- package/bin/win32-x64/crwu.exe +0 -0
- package/lib/client.js +19 -3
- package/lib/index.js +140 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,13 @@
|
|
|
7
7
|
`cordis_define` + `cordis_run` 装配,版本号用 DSH 的 `pkg-N`);它已在本仓收尾时删除
|
|
8
8
|
(见 `0.0.1` 一节),下面 `legacy · pkg-43` 及更早的记录是它的历史。
|
|
9
9
|
|
|
10
|
+
## package · 0.0.16 · 2026-09-29 · fix · Windows 氚云扫码临时目录回退
|
|
11
|
+
|
|
12
|
+
- 随包 `crwu.exe` 的 `h3yun session login` 在系统 `%TEMP%` 被 Windows 安全策略拒绝时,
|
|
13
|
+
自动回退到 `%LOCALAPPDATA%\crwu\scan-tmp\crwu-scan-*`;登录结束仍清理临时 profile。
|
|
14
|
+
- 回退只针对权限错误,且不改变 OS 凭据存储边界;若用户缓存目录也被拒绝,保留两段错误供
|
|
15
|
+
Defender/企业安全软件排查。
|
|
16
|
+
|
|
10
17
|
## package · 0.0.15 · 2026-09-28
|
|
11
18
|
|
|
12
19
|
**协议 18:本机访问从「调用方声明提权」改成「具名操作 + 版本化授权收据」,
|
|
@@ -213,6 +220,41 @@
|
|
|
213
220
|
② `crwu_audit_case_bootstrap` 的 `caseDir` 虽被钉在本轮案例目录,但 `objectId` 仍是提交进来的 ——
|
|
214
221
|
子会话可以用**别的** objectId 把别人的记录取进自己的案例目录;现在审核子会话调用它一律拒绝。
|
|
215
222
|
|
|
223
|
+
### G 段:登录失败归因 ——「登录必须写工作区之外」不再是原文(2026-09-29)
|
|
224
|
+
|
|
225
|
+
**症状**:员工第一次用(Windows 与 macOS 都报)时,点「扫码登录氚云」「钉钉登录」浏览器起不来;
|
|
226
|
+
面板给的却是 CLI 的原话 —— 氚云 `mkdir C:\…\Temp\crwu-scan-1799287186: Access is denied.`
|
|
227
|
+
(看着像 crwu 坏了)、钉钉 `acquiring file lock: …\.dws\.data.lock: Access is denied.`
|
|
228
|
+
(看着像 dws 自己的 bug)。
|
|
229
|
+
|
|
230
|
+
**根因(两条入口同一条边界)**:登录**必须写工作区之外的路径** ——
|
|
231
|
+
|
|
232
|
+
| 入口 | 必须写的东西 |
|
|
233
|
+
| --- | --- |
|
|
234
|
+
| `crwu h3yun session login` | `$TMPDIR`/`%TEMP%` 下的临时浏览器 profile(`crwu-scan-*`),再经 CDP 读会话 |
|
|
235
|
+
| `dws auth login`(含 `--device`) | `<HOME>/.dws/.data.lock`(拿登录态之前先抢文件锁) |
|
|
236
|
+
| 两者收尾 | 操作系统凭据存储(钥匙串 / Credential Manager) |
|
|
237
|
+
|
|
238
|
+
宿主按完全访问跑、操作系统的 ACL/受限令牌仍然拒绝时报的就是上面那两句;受限沙箱下浏览器即使
|
|
239
|
+
起来了也会在几毫秒内 renderer 崩溃(CDP 只回 `close 1006` / `Target crashed`)。
|
|
240
|
+
|
|
241
|
+
- **新增纯函数判据** `src/host/system/login-failure.ts`:`loginFailureAdvice()` / `describeLoginAdvice()`。
|
|
242
|
+
顺序是「结构化事实优先,文本最后」:① `runnerFailed` → ② 提权被降级(`requested !== resolved`)
|
|
243
|
+
→ ③ `denied === true` 或实际跑在受限模式 → ④ **事实干净但原文点名了登录必须写的工作区外目标
|
|
244
|
+
且带拒绝字样**(Windows 实测就是这一形态)。
|
|
245
|
+
- **第 ④ 条是 `sandboxDenialNote()` 的唯一例外**,判据本身变强了:目标不是"任意路径",而是登录
|
|
246
|
+
流程必须写的那几个已知目标。**目标词与拒绝字样必须同时命中** —— 只命中一个不归因(否则
|
|
247
|
+
`secret not found in keyring` 这种"真没条目 / 钥匙串被锁"会被说成"去切完全权限")。
|
|
248
|
+
- **`dwsLogin` 以前完全不做归因**(只有 `runDws` 做),现在两条登录都返回 `sandboxBlocked` + `advice`,
|
|
249
|
+
并把「在输入框下方的访问模式里选「完全权限」再点一次」写进 `error`,**原始报错保留**在末尾。
|
|
250
|
+
- **设备码不再是"退路"**:它同样要抢 `~/.dws` 的锁,所以按钮文案改回「设备码登录(无浏览器时)」,
|
|
251
|
+
归因文案里明说"在这个模式下也走不通"。
|
|
252
|
+
- **界面**:「账号连接」页在登录按钮下方**先说前置条件**(`envLoginSandboxHint`);
|
|
253
|
+
被归因时不再追加 stdout 尾巴(否则那句「正在打开浏览器窗口…」会把真正的动作挤掉)。
|
|
254
|
+
|
|
255
|
+
**已证伪**:把第 ④ 条整段关掉 → 7 条变红;把「目标词」那一半去掉(只认拒绝字样)→
|
|
256
|
+
误报用例变红。`cp` 还原后转绿。
|
|
257
|
+
|
|
216
258
|
### 测试
|
|
217
259
|
|
|
218
260
|
新增/扩写的测试文件:`host-access-consent` / `host-access-broker` / `host-access-classify` /
|
package/bin/darwin-arm64/crwu
CHANGED
|
Binary file
|
package/bin/manifest.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": "crwu.plugin-bin-manifest.v1",
|
|
3
|
-
"generatedAt": "2026-09-
|
|
3
|
+
"generatedAt": "2026-09-29T07:54:23.331Z",
|
|
4
4
|
"platforms": [
|
|
5
5
|
{
|
|
6
6
|
"platform": "darwin-arm64",
|
|
@@ -12,9 +12,9 @@
|
|
|
12
12
|
"source": "repo-build",
|
|
13
13
|
"sourceVersion": "0.0.1",
|
|
14
14
|
"target": "darwin/arm64",
|
|
15
|
-
"buildCommit": "
|
|
15
|
+
"buildCommit": "6769a60cf2b4262793fc10492a7fa4ff2658fee7",
|
|
16
16
|
"size": 7351330,
|
|
17
|
-
"sha256": "
|
|
17
|
+
"sha256": "4a406f33795444b2f2ae36c62efb3fce4b040f94458d01b6815b51122525a192"
|
|
18
18
|
},
|
|
19
19
|
{
|
|
20
20
|
"tool": "ossutil",
|
|
@@ -50,9 +50,9 @@
|
|
|
50
50
|
"source": "repo-build",
|
|
51
51
|
"sourceVersion": "0.0.1",
|
|
52
52
|
"target": "windows/amd64",
|
|
53
|
-
"buildCommit": "
|
|
54
|
-
"size":
|
|
55
|
-
"sha256": "
|
|
53
|
+
"buildCommit": "6769a60cf2b4262793fc10492a7fa4ff2658fee7",
|
|
54
|
+
"size": 8124928,
|
|
55
|
+
"sha256": "8142ef5bd35eddcdc43bcf0c3180a626494efc08a5517043724e97c965ecfa58"
|
|
56
56
|
},
|
|
57
57
|
{
|
|
58
58
|
"tool": "ossutil",
|
package/bin/win32-x64/crwu.exe
CHANGED
|
Binary file
|
package/lib/client.js
CHANGED
|
@@ -2519,6 +2519,12 @@ body[data-ds-dark-theme] .crwu-audit-root {
|
|
|
2519
2519
|
envOssReasonNoSecret: "凭据文件里没有 AccessKey Secret",
|
|
2520
2520
|
envOssOssutilMissing: "插件内置的 ossutil 不可用:这不是凭据问题,是插件包不完整 —— 需要重新安装插件",
|
|
2521
2521
|
envLoginH3yun: "扫码登录氚云",
|
|
2522
|
+
/**
|
|
2523
|
+
* 登录按钮的**前置条件**(2026-09-29 员工实测):两条登录命令都要写工作区之外的路径 ——
|
|
2524
|
+
* 临时浏览器 profile、`<HOME>/.dws` 的登录态、操作系统凭据存储。文件策略不给时一条都走不通,
|
|
2525
|
+
* 而这一点在前端看不出来(表现只是"浏览器没起来")。说在点之前,别让员工靠试错发现。
|
|
2526
|
+
*/
|
|
2527
|
+
envLoginSandboxHint: "登录需要在工作区之外起临时浏览器 / 更新登录态文件。若报「拒绝访问」,请把输入框下方的访问模式切到「完全权限」再点一次。",
|
|
2522
2528
|
envDetailsTitle: "排查详情(维护者看)",
|
|
2523
2529
|
envDetailsTools: "插件内置组件明细",
|
|
2524
2530
|
envDetailsRuntime: "DSH 脚本运行时明细",
|
|
@@ -3103,7 +3109,7 @@ body[data-ds-dark-theme] .crwu-audit-root {
|
|
|
3103
3109
|
runCardSummary: "中瑞世联工作台:环境自检 → 报告审核(单条)→ 自动上云 → 直接开云端审核意见。",
|
|
3104
3110
|
relogin: "氚云登录",
|
|
3105
3111
|
dwsLogin: "钉钉登录",
|
|
3106
|
-
dwsLoginDevice: "
|
|
3112
|
+
dwsLoginDevice: "设备码登录(无浏览器时)",
|
|
3107
3113
|
stopAudit: "停止这条审核",
|
|
3108
3114
|
stopPhaseRequested: "正在请求停止审核…",
|
|
3109
3115
|
stopPhaseAborting: "正在取消子会话…",
|
|
@@ -6094,6 +6100,10 @@ body[data-ds-dark-theme] .crwu-audit-root {
|
|
|
6094
6100
|
})]
|
|
6095
6101
|
})
|
|
6096
6102
|
}),
|
|
6103
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6104
|
+
className: WORKBENCH_CLASSES.muted,
|
|
6105
|
+
children: zhCN.envLoginSandboxHint
|
|
6106
|
+
}),
|
|
6097
6107
|
props.loginMessage === void 0 || props.loginMessage === "" ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6098
6108
|
className: WORKBENCH_CLASSES.itemFix,
|
|
6099
6109
|
style: { whiteSpace: "pre-wrap" },
|
|
@@ -11161,6 +11171,10 @@ body[data-ds-dark-theme] .crwu-audit-root {
|
|
|
11161
11171
|
* 这两条命令会开浏览器、等人扫码(宿主侧超时 5 分钟),所以:成功也要给一句话,
|
|
11162
11172
|
* 失败必须带原因,CLI 打到 stdout 的 URL / 设备码 / 提示原样带出来 —— 浏览器打不开时,
|
|
11163
11173
|
* 那串 URL 就是员工唯一能自己走下去的路。
|
|
11174
|
+
*
|
|
11175
|
+
* `sandboxBlocked` 是 **Host 的归因事实**(登录必须写工作区之外的路径):为真时
|
|
11176
|
+
* `error` 里已经是一句人话 + 下一步动作,这里不再追加 stdout 尾巴 —— 那只会是一句
|
|
11177
|
+
* 「正在打开浏览器窗口…」,把真正的动作挤到看不见。
|
|
11164
11178
|
*/
|
|
11165
11179
|
const runLogin = react.useCallback(async (label, call) => {
|
|
11166
11180
|
setLoginMessage(`${label}:正在等待浏览器授权…(最多 5 分钟)`);
|
|
@@ -11171,8 +11185,10 @@ body[data-ds-dark-theme] .crwu-audit-root {
|
|
|
11171
11185
|
if (result.ok) lines.push(`${label}:命令已执行完成,请刷新查看结果。`);
|
|
11172
11186
|
else if (result.timedOut === true) lines.push(`${label}:等待超时(5 分钟)。若浏览器没有自动打开,请重试或改用设备码登录。`);
|
|
11173
11187
|
else lines.push(`${label}失败:${result.error || result.stderrTail || "未知原因"}`);
|
|
11174
|
-
|
|
11175
|
-
|
|
11188
|
+
if (result.sandboxBlocked !== true) {
|
|
11189
|
+
const detail = (result.stdoutTail ?? "").trim() || (result.stderrTail ?? "").trim();
|
|
11190
|
+
if (detail !== "") lines.push(detail);
|
|
11191
|
+
}
|
|
11176
11192
|
setLoginMessage(lines.join("\n"));
|
|
11177
11193
|
} catch (cause) {
|
|
11178
11194
|
if (mounted.current) setLoginMessage(`${label}失败:${describe(cause)}`);
|
package/lib/index.js
CHANGED
|
@@ -231,7 +231,7 @@ const PLUGIN_INJECT = [
|
|
|
231
231
|
* 还会让打包器的 JSON 插件成为隐式依赖。代价是升版本时要同时改这里 ——
|
|
232
232
|
* `tests/unit/host-package.test.mjs` 有一条断言盯着它必须等于 `package.json` 的 version。
|
|
233
233
|
*/
|
|
234
|
-
const PLUGIN_VERSION = "0.0.
|
|
234
|
+
const PLUGIN_VERSION = "0.0.16";
|
|
235
235
|
/**
|
|
236
236
|
* `ping` / `boot` 应答里的版本指纹,形如 `pkg-0.0.5`。
|
|
237
237
|
*
|
|
@@ -12056,6 +12056,120 @@ function parseSessionOutput(stdout) {
|
|
|
12056
12056
|
return sessionView(doc);
|
|
12057
12057
|
}
|
|
12058
12058
|
//#endregion
|
|
12059
|
+
//#region src/host/system/login-failure.ts
|
|
12060
|
+
/** 完全访问模式的字面量;只在**结构化事实**里比较。 */
|
|
12061
|
+
const FULL_ACCESS = "danger-full-access";
|
|
12062
|
+
/**
|
|
12063
|
+
* 这一条命令**必须**能写的工作区外目标(大小写不敏感的子串)。
|
|
12064
|
+
*
|
|
12065
|
+
* 刻意保守:只登记登录流程真正会碰的东西。多写一个词就会把别的失败误判成沙箱问题。
|
|
12066
|
+
*/
|
|
12067
|
+
const LOGIN_TARGETS = {
|
|
12068
|
+
h3yun: ["crwu-scan-", "crwu-scan"],
|
|
12069
|
+
dws: [".dws", ".data.lock"]
|
|
12070
|
+
};
|
|
12071
|
+
/** 两个入口共有的目标:操作系统凭据存储。 */
|
|
12072
|
+
const CREDENTIAL_STORE_TARGETS = [
|
|
12073
|
+
"keyring",
|
|
12074
|
+
"credential store",
|
|
12075
|
+
"credential-store",
|
|
12076
|
+
"钥匙串",
|
|
12077
|
+
"凭据存储"
|
|
12078
|
+
];
|
|
12079
|
+
/** 拒绝字样。命中它**且**命中目标词才算归因。 */
|
|
12080
|
+
const DENIED_MARKERS = [
|
|
12081
|
+
"access is denied",
|
|
12082
|
+
"access denied",
|
|
12083
|
+
"permission denied",
|
|
12084
|
+
"operation not permitted",
|
|
12085
|
+
"eacces",
|
|
12086
|
+
"eperm",
|
|
12087
|
+
"拒绝访问",
|
|
12088
|
+
"不允许",
|
|
12089
|
+
"被拒绝"
|
|
12090
|
+
];
|
|
12091
|
+
const REASONS = {
|
|
12092
|
+
h3yun: "氚云扫码登录要在工作区之外起一个临时浏览器配置目录(crwu-scan-*),当前文件策略把它挡下了",
|
|
12093
|
+
dws: "钉钉登录要先更新 <HOME>/.dws 里的登录态,当前文件策略把它挡下了"
|
|
12094
|
+
};
|
|
12095
|
+
const ACTIONS = {
|
|
12096
|
+
h3yun: "在输入框下方的访问模式里选「完全权限」(或输入 /permission danger-full-access),回到「账号连接」再点一次「扫码登录氚云」。",
|
|
12097
|
+
dws: "在输入框下方的访问模式里选「完全权限」(或输入 /permission danger-full-access),回到「账号连接」再点一次「钉钉登录」。设备码登录同样要更新 <HOME>/.dws 的登录态,在这个模式下也走不通。"
|
|
12098
|
+
};
|
|
12099
|
+
function textList(values) {
|
|
12100
|
+
return values.map((value) => text(value)).filter((value) => value !== "").join("\n").toLowerCase();
|
|
12101
|
+
}
|
|
12102
|
+
/** 命中拒绝字样,且原文点名了该入口**必须写**的工作区外目标。 */
|
|
12103
|
+
function deniedOutsideWorkspace(kind, facts) {
|
|
12104
|
+
const blob = textList([
|
|
12105
|
+
facts.stderr,
|
|
12106
|
+
facts.stdout,
|
|
12107
|
+
facts.error
|
|
12108
|
+
]);
|
|
12109
|
+
if (blob === "") return false;
|
|
12110
|
+
if (!DENIED_MARKERS.some((marker) => blob.includes(marker))) return false;
|
|
12111
|
+
return [...LOGIN_TARGETS[kind], ...CREDENTIAL_STORE_TARGETS].some((target) => blob.includes(target));
|
|
12112
|
+
}
|
|
12113
|
+
/** 一条没有归因的结论(调用方据此原样回原始错误)。 */
|
|
12114
|
+
function none() {
|
|
12115
|
+
return {
|
|
12116
|
+
blocked: false,
|
|
12117
|
+
reason: "",
|
|
12118
|
+
action: ""
|
|
12119
|
+
};
|
|
12120
|
+
}
|
|
12121
|
+
/**
|
|
12122
|
+
* 判据入口:给一次登录失败的事实,回答"是不是本机访问被挡在工作区之外"。
|
|
12123
|
+
*
|
|
12124
|
+
* 纯函数:没有 IO、没有时间、没有平台分支 —— 平台差异全部体现在传进来的事实里。
|
|
12125
|
+
*/
|
|
12126
|
+
function loginFailureAdvice(kind, facts) {
|
|
12127
|
+
const sandbox = facts.sandbox;
|
|
12128
|
+
const requested = text(sandbox?.requested);
|
|
12129
|
+
const resolved = text(sandbox?.resolved);
|
|
12130
|
+
const ran = text(sandbox?.ran);
|
|
12131
|
+
const confined = (value) => value !== "" && value !== FULL_ACCESS;
|
|
12132
|
+
if (sandbox?.runnerFailed === true) return {
|
|
12133
|
+
blocked: true,
|
|
12134
|
+
reason: "DSH 的沙箱 runner 在命令跑起来之前就失败了(不是命令本身的业务失败)",
|
|
12135
|
+
action: ACTIONS[kind]
|
|
12136
|
+
};
|
|
12137
|
+
if (requested !== "" && resolved !== "" && requested !== resolved) return {
|
|
12138
|
+
blocked: true,
|
|
12139
|
+
reason: `提权请求被降级:请求 ${requested},执行器实际按 ${resolved} 跑`,
|
|
12140
|
+
action: ACTIONS[kind]
|
|
12141
|
+
};
|
|
12142
|
+
if (sandbox?.denied === true) return {
|
|
12143
|
+
blocked: true,
|
|
12144
|
+
reason: `DSH 沙箱拒绝了这次操作(${ran || resolved || requested || "当前模式"})`,
|
|
12145
|
+
action: ACTIONS[kind]
|
|
12146
|
+
};
|
|
12147
|
+
if (confined(resolved) || confined(ran)) return {
|
|
12148
|
+
blocked: true,
|
|
12149
|
+
reason: `登录进程实际跑在 ${ran || resolved} 下,写不了工作区之外的登录目标`,
|
|
12150
|
+
action: ACTIONS[kind]
|
|
12151
|
+
};
|
|
12152
|
+
if (deniedOutsideWorkspace(kind, facts)) return {
|
|
12153
|
+
blocked: true,
|
|
12154
|
+
reason: REASONS[kind],
|
|
12155
|
+
action: ACTIONS[kind]
|
|
12156
|
+
};
|
|
12157
|
+
return none();
|
|
12158
|
+
}
|
|
12159
|
+
/**
|
|
12160
|
+
* 把归因拼成一句给员工看的话(界面直接显示 `error`)。
|
|
12161
|
+
*
|
|
12162
|
+
* `original` 必须是**命令自己的原话**(stderr / 脱离沙箱前的错误),不是别的归因函数
|
|
12163
|
+
* 已经加工过的句子 —— 否则同一句"沙箱挡住了"会出现两次,员工会以为是两个故障。
|
|
12164
|
+
*/
|
|
12165
|
+
function describeLoginAdvice(kind, advice, original) {
|
|
12166
|
+
if (!advice.blocked) return text(original);
|
|
12167
|
+
const head = `本机访问被挡在工作区之外:${advice.reason}。`;
|
|
12168
|
+
const body = text(original).trim();
|
|
12169
|
+
const evidence = body === "" ? "" : `(原始报错:${body.slice(0, 300)})`;
|
|
12170
|
+
return `${head}${advice.action}${evidence}`;
|
|
12171
|
+
}
|
|
12172
|
+
//#endregion
|
|
12059
12173
|
//#region src/host/system/ops.ts
|
|
12060
12174
|
/**
|
|
12061
12175
|
* 把文本写进系统剪贴板。
|
|
@@ -12145,10 +12259,22 @@ async function dwsLogin(deps, args) {
|
|
|
12145
12259
|
timeoutMs: 3e5,
|
|
12146
12260
|
summary: "dws auth login"
|
|
12147
12261
|
});
|
|
12262
|
+
const advice = loginFailureAdvice("dws", {
|
|
12263
|
+
error: run.error,
|
|
12264
|
+
stdout: run.stdout,
|
|
12265
|
+
stderr: run.stderr,
|
|
12266
|
+
exitCode: run.exitCode,
|
|
12267
|
+
timedOut: run.timedOut,
|
|
12268
|
+
sandbox: run.sandbox
|
|
12269
|
+
});
|
|
12270
|
+
const raw = text(run.stderr).trim() || text(run.error).trim();
|
|
12271
|
+
const error = run.ok ? "" : advice.blocked ? describeLoginAdvice("dws", advice, raw) : describeFailure(run);
|
|
12148
12272
|
return {
|
|
12149
12273
|
ok: run.ok,
|
|
12150
|
-
error
|
|
12274
|
+
error,
|
|
12151
12275
|
timedOut: run.timedOut,
|
|
12276
|
+
sandboxBlocked: advice.blocked,
|
|
12277
|
+
advice: advice.blocked ? advice.action : "",
|
|
12152
12278
|
...tails(run)
|
|
12153
12279
|
};
|
|
12154
12280
|
}
|
|
@@ -12166,10 +12292,21 @@ async function relogin(deps) {
|
|
|
12166
12292
|
source: "panel",
|
|
12167
12293
|
platform: deps.platform
|
|
12168
12294
|
});
|
|
12295
|
+
const advice = loginFailureAdvice("h3yun", {
|
|
12296
|
+
error: run.error,
|
|
12297
|
+
stdout: run.stdout,
|
|
12298
|
+
stderr: run.stderr,
|
|
12299
|
+
exitCode: run.exitCode,
|
|
12300
|
+
timedOut: run.timedOut,
|
|
12301
|
+
sandbox: run.sandbox
|
|
12302
|
+
});
|
|
12303
|
+
const error = run.ok ? "" : advice.blocked ? describeLoginAdvice("h3yun", advice, text(run.stderr)) : run.error;
|
|
12169
12304
|
return {
|
|
12170
12305
|
ok: run.ok,
|
|
12171
|
-
error
|
|
12306
|
+
error,
|
|
12172
12307
|
timedOut: run.timedOut,
|
|
12308
|
+
sandboxBlocked: advice.blocked,
|
|
12309
|
+
advice: advice.blocked ? advice.action : "",
|
|
12173
12310
|
session: parseSessionOutput(run.stdout),
|
|
12174
12311
|
...tails(run)
|
|
12175
12312
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-crwu-workbench",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.16",
|
|
4
4
|
"description": "中瑞世联工作台 / CRWU audit workbench for DeepSeek Harness: pick a pending audit report, dispatch one AI audit subagent, watch and stop/restart it, auto-upload deliverables to Aliyun OSS.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"deepseek-harness",
|