@clawos-dev/clawd 0.2.456 → 0.2.458
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/dist/cli.cjs
CHANGED
|
@@ -46240,9 +46240,19 @@ function reduceSessionInner(state, input, deps) {
|
|
|
46240
46240
|
resetReadyGate(next);
|
|
46241
46241
|
const queueEffects = [];
|
|
46242
46242
|
clearQueuedSends(next, queueEffects);
|
|
46243
|
+
const eventEffects = [
|
|
46244
|
+
...pushEventToBufferInPlace(next, { kind: "error", message: input.message }, deps),
|
|
46245
|
+
...pushEventToBufferInPlace(next, { kind: "turn_end" }, deps)
|
|
46246
|
+
// 丢掉 turn_end 顺带产出的 append-turn-duration:那条 effect 会往用户真实的 CC
|
|
46247
|
+
// jsonl 追加一行 turn_duration(runner.ts case 'append-turn-duration',resume 场景
|
|
46248
|
+
// toolSessionId 已 stamp 时会真落盘)。它的用途是"SDK 模式 CC 不写 turn 边界、
|
|
46249
|
+
// daemon 补写",而这里 CC 根本没跑过这一轮——补边界等于往历史里插一个空 turn,
|
|
46250
|
+
// 且不可回滚。proc-exit 的 interrupted 注入走同一条路但语义不同:那边 turn 真发生过。
|
|
46251
|
+
].filter((e) => e.kind !== "append-turn-duration");
|
|
46243
46252
|
return {
|
|
46244
46253
|
state: next,
|
|
46245
46254
|
effects: [
|
|
46255
|
+
...eventEffects,
|
|
46246
46256
|
{
|
|
46247
46257
|
kind: "emit-frame",
|
|
46248
46258
|
frame: {
|
|
@@ -46429,6 +46439,15 @@ init_stdout_splitter();
|
|
|
46429
46439
|
init_permission_stdio();
|
|
46430
46440
|
init_claude_history();
|
|
46431
46441
|
|
|
46442
|
+
// src/tools/spawn-error.ts
|
|
46443
|
+
function describeSpawnError(err, fallbackBin, cwd, pathEnv = process.env.PATH) {
|
|
46444
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
46445
|
+
const e = err;
|
|
46446
|
+
if (e?.code !== "ENOENT") return message;
|
|
46447
|
+
const bin = typeof e.path === "string" && e.path ? e.path : fallbackBin;
|
|
46448
|
+
return `\u8D77\u4E0D\u4E86 ${bin}\uFF1APATH \u91CC\u6CA1\u6709\u5B83\uFF0C\u6216\u5DE5\u4F5C\u76EE\u5F55\u4E0D\u5B58\u5728\u3002\u5DE5\u4F5C\u76EE\u5F55\uFF1A${cwd || "(\u672A\u77E5)"}\uFF5Cclawd \u770B\u5230\u7684 PATH\uFF1A${pathEnv || "(\u7A7A)"}`;
|
|
46449
|
+
}
|
|
46450
|
+
|
|
46432
46451
|
// src/persona/mcp-secret-render.ts
|
|
46433
46452
|
var import_node_fs7 = __toESM(require("fs"), 1);
|
|
46434
46453
|
var import_node_path6 = __toESM(require("path"), 1);
|
|
@@ -47009,7 +47028,10 @@ var SessionRunner = class {
|
|
|
47009
47028
|
if (this.proc !== proc) return;
|
|
47010
47029
|
const message = err.message;
|
|
47011
47030
|
this.hooks.logger?.error("claude spawn failed", { message });
|
|
47012
|
-
this.input({
|
|
47031
|
+
this.input({
|
|
47032
|
+
kind: "proc-error",
|
|
47033
|
+
message: describeSpawnError(err, this.hooks.adapter.id, this.state.file.cwd)
|
|
47034
|
+
});
|
|
47013
47035
|
});
|
|
47014
47036
|
}
|
|
47015
47037
|
/**
|
|
@@ -51770,7 +51792,8 @@ function createCodexSession(ctx, sink, deps = {}) {
|
|
|
51770
51792
|
proc.on("error", (err) => {
|
|
51771
51793
|
const message = err.message;
|
|
51772
51794
|
deps.logger?.error("codex app-server spawn failed", { message });
|
|
51773
|
-
|
|
51795
|
+
const described = describeSpawnError(err, cmd, ctx.cwd);
|
|
51796
|
+
sink.onError(described === message ? `codex app-server spawn failed: ${message}` : described);
|
|
51774
51797
|
});
|
|
51775
51798
|
proc.on("exit", (code) => finish(code));
|
|
51776
51799
|
const ready = (async () => {
|
|
@@ -63908,7 +63931,7 @@ function computeMethodAccess(args) {
|
|
|
63908
63931
|
}
|
|
63909
63932
|
|
|
63910
63933
|
// src/version.ts
|
|
63911
|
-
var version = "0.2.
|
|
63934
|
+
var version = "0.2.458".length > 0 ? "0.2.458" : "dev";
|
|
63912
63935
|
|
|
63913
63936
|
// src/cli-probe/probe.ts
|
|
63914
63937
|
var fs70 = __toESM(require("fs"), 1);
|
|
@@ -19,17 +19,27 @@
|
|
|
19
19
|
S_ACCESS_ALIAS=clawd-fc
|
|
20
20
|
|
|
21
21
|
# 分层加载阿里云 AK 进 env:shared demo(OTA 每次启动覆盖)→ 本机 .local override(永不被覆盖)。
|
|
22
|
+
#
|
|
23
|
+
# 两种来源,**文件优先、env 兜底**:
|
|
24
|
+
# - 本机:`$KIT_DIR/.secrets/aliyun.env`(+ 可选 .local),OTA 刷新;
|
|
25
|
+
# - 云上容器:没有 `.secrets/`(`cloud-host/provision/build-image.mjs` 刻意把它剔出镜像层
|
|
26
|
+
# ——镜像要分发,凭据进层就洗不掉了),AK 由 gateway 经 **MCP server 的 per-server env**
|
|
27
|
+
# 交到调用本脚本的那个进程里(M1b Step 9)。这条分支不落盘是有意的:写成文件的话
|
|
28
|
+
# agent 一个 `cat` 就看见了,而 env 只有这个子进程有。
|
|
22
29
|
ensure_aliyun_env() {
|
|
23
30
|
local kit="${KIT_DIR:?ensure_aliyun_env 需要调用方先设 KIT_DIR}"
|
|
24
|
-
[ -f "$kit/.secrets/aliyun.env" ]
|
|
25
|
-
|
|
31
|
+
if [ -f "$kit/.secrets/aliyun.env" ]; then
|
|
32
|
+
set -a; . "$kit/.secrets/aliyun.env"; set +a
|
|
33
|
+
# aliyun.env.local: 本机个人 override(永远不被 OTA 覆盖,见 refreshDeployKit)。有就后 source 覆盖 env。
|
|
34
|
+
# 写成 if 而不是 `[ -f ] && { }`:后者在函数末尾会把「文件不存在」变成函数返回 1,调用方 set -e 直接中止。
|
|
35
|
+
if [ -f "$kit/.secrets/aliyun.env.local" ]; then
|
|
36
|
+
set -a; . "$kit/.secrets/aliyun.env.local"; set +a
|
|
37
|
+
fi
|
|
38
|
+
elif [ -n "${ALIBABA_CLOUD_ACCESS_KEY_ID:-}" ] && [ -n "${ALIBABA_CLOUD_ACCESS_KEY_SECRET:-}" ]; then
|
|
39
|
+
: # 云上:值已经在本进程 env 里,不落文件
|
|
40
|
+
else
|
|
41
|
+
echo "❌ 缺 $kit/.secrets/aliyun.env(clawd ship 的共享 demo 凭证,OTA 自动刷新),env 里也没有 ALIBABA_CLOUD_ACCESS_KEY_ID/_SECRET。参考 .secrets/aliyun.env.example 填写。" >&2
|
|
26
42
|
return 1
|
|
27
|
-
}
|
|
28
|
-
set -a; . "$kit/.secrets/aliyun.env"; set +a
|
|
29
|
-
# aliyun.env.local: 本机个人 override(永远不被 OTA 覆盖,见 refreshDeployKit)。有就后 source 覆盖 env。
|
|
30
|
-
# 写成 if 而不是 `[ -f ] && { }`:后者在函数末尾会把「文件不存在」变成函数返回 1,调用方 set -e 直接中止。
|
|
31
|
-
if [ -f "$kit/.secrets/aliyun.env.local" ]; then
|
|
32
|
-
set -a; . "$kit/.secrets/aliyun.env.local"; set +a
|
|
33
43
|
fi
|
|
34
44
|
export ALIBABA_CLOUD_REGION_ID="${REGION:?config.env 缺 REGION}"
|
|
35
45
|
}
|
|
@@ -182,11 +182,70 @@ describe('ensure_credentials', () => {
|
|
|
182
182
|
expect(kitAccessYaml()).toContain("AccountID: '5566778899001122'")
|
|
183
183
|
})
|
|
184
184
|
|
|
185
|
-
it('
|
|
185
|
+
it('缺共享凭证文件、env 里也没有 AK 时 fail-loud', () => {
|
|
186
186
|
rmSync(join(box.kit, '.secrets', 'aliyun.env'))
|
|
187
187
|
expect(() => runInKit('ensure_credentials')).toThrow()
|
|
188
188
|
expect(existsSync(join(box.kit, '.s-home', '.s', 'access.yaml'))).toBe(false)
|
|
189
189
|
})
|
|
190
|
+
|
|
191
|
+
// 云上分支(persona 上云 M1b Step 9):容器里没有 `.secrets/`——`build-image.mjs` 刻意把它
|
|
192
|
+
// 剔出镜像层(镜像要分发,凭据进层洗不掉)。AK 由 gateway 经 **MCP server 的 per-server env**
|
|
193
|
+
// 交到调用本脚本的那个子进程里,不落文件:写成文件的话 agent 一个 `cat` 就看见了。
|
|
194
|
+
it('没有 .secrets/aliyun.env 但 env 里有 AK 时用 env(云上容器那条路)', () => {
|
|
195
|
+
rmSync(join(box.kit, '.secrets', 'aliyun.env'))
|
|
196
|
+
const out = execFileSync(
|
|
197
|
+
'bash',
|
|
198
|
+
[
|
|
199
|
+
'-c',
|
|
200
|
+
`set -euo pipefail
|
|
201
|
+
KIT_DIR="${box.kit}"
|
|
202
|
+
REGION=cn-hangzhou
|
|
203
|
+
source "$KIT_DIR/scripts/ensure-credentials.sh"
|
|
204
|
+
ensure_credentials
|
|
205
|
+
printf 'ok %s\\n' "$ALIBABA_CLOUD_ACCESS_KEY_ID"`,
|
|
206
|
+
],
|
|
207
|
+
{
|
|
208
|
+
env: {
|
|
209
|
+
...process.env,
|
|
210
|
+
HOME: box.home,
|
|
211
|
+
PATH: `${box.bin}:${process.env.PATH}`,
|
|
212
|
+
ALIBABA_CLOUD_ACCESS_KEY_ID: 'LTAI-FROM-ENV',
|
|
213
|
+
ALIBABA_CLOUD_ACCESS_KEY_SECRET: 'secret-from-env',
|
|
214
|
+
},
|
|
215
|
+
encoding: 'utf8',
|
|
216
|
+
},
|
|
217
|
+
)
|
|
218
|
+
expect(out).toContain('ok LTAI-FROM-ENV')
|
|
219
|
+
// 走 env 分支照样把凭证落进 kit 私有 s-home(publish 用的是那份 profile),仍不碰用户全局
|
|
220
|
+
expect(kitAccessYaml()).toContain('LTAI-FROM-ENV')
|
|
221
|
+
expect(userAccessYaml()).toContain('LTAI-USER-OWN-KEY')
|
|
222
|
+
})
|
|
223
|
+
|
|
224
|
+
it('文件在就优先用文件(云上那条只是兜底,不能反过来盖掉本机 shared 凭证)', () => {
|
|
225
|
+
const out = execFileSync(
|
|
226
|
+
'bash',
|
|
227
|
+
[
|
|
228
|
+
'-c',
|
|
229
|
+
`set -euo pipefail
|
|
230
|
+
KIT_DIR="${box.kit}"
|
|
231
|
+
REGION=cn-hangzhou
|
|
232
|
+
source "$KIT_DIR/scripts/ensure-credentials.sh"
|
|
233
|
+
ensure_aliyun_env
|
|
234
|
+
printf 'id=%s\\n' "$ALIBABA_CLOUD_ACCESS_KEY_ID"`,
|
|
235
|
+
],
|
|
236
|
+
{
|
|
237
|
+
env: {
|
|
238
|
+
...process.env,
|
|
239
|
+
HOME: box.home,
|
|
240
|
+
PATH: `${box.bin}:${process.env.PATH}`,
|
|
241
|
+
ALIBABA_CLOUD_ACCESS_KEY_ID: 'LTAI-FROM-ENV',
|
|
242
|
+
ALIBABA_CLOUD_ACCESS_KEY_SECRET: 'secret-from-env',
|
|
243
|
+
},
|
|
244
|
+
encoding: 'utf8',
|
|
245
|
+
},
|
|
246
|
+
)
|
|
247
|
+
expect(out).not.toContain('LTAI-FROM-ENV')
|
|
248
|
+
})
|
|
190
249
|
})
|
|
191
250
|
|
|
192
251
|
describe('publish.sh', () => {
|