惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Apple Machine Learning Research
Apple Machine Learning Research
The GitHub Blog
The GitHub Blog
Hugging Face - Blog
Hugging Face - Blog
阮一峰的网络日志
阮一峰的网络日志
爱范儿
爱范儿
量子位
宝玉的分享
宝玉的分享
人人都是产品经理
人人都是产品经理
博客园_首页
博客园 - 【当耐特】
Last Week in AI
Last Week in AI
Martin Fowler
Martin Fowler
Microsoft Azure Blog
Microsoft Azure Blog
美团技术团队
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
aimingoo的专栏
aimingoo的专栏
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
GbyAI
GbyAI
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
腾讯CDC

Recent Commits to openclaw:main

fix(diagnostics): harden observability exports and smokes (#85371) · openclaw/openclaw@7f05be0 fix(stepfun): drop stale auth choice metadata test(e2e): sample kitchen sink RSS on Windows · openclaw/openclaw@73c1e37 test(plugins): fail gauntlet on load diagnostics fix(build): preserve tsdown heap floor · openclaw/openclaw@9ff1a43 fix(tools): honor config apiKey in media tool preflight (#85570) · openclaw/openclaw@31c269f fix(e2e): support macOS script wrappers fix(ci): scope changed shrinkwrap checks · openclaw/openclaw@743fd4c chore(ui): refresh fa control ui locale chore(ui): refresh nl control ui locale · openclaw/openclaw@908464b chore(ui): refresh vi control ui locale · openclaw/openclaw@62b75f4 chore(ui): refresh th control ui locale · openclaw/openclaw@fc4ba31 chore(ui): refresh id control ui locale · openclaw/openclaw@5b1bdd1 chore(ui): refresh pl control ui locale · openclaw/openclaw@534d4b1 chore(ui): refresh uk control ui locale · openclaw/openclaw@055c3bd chore(ui): refresh ar control ui locale · openclaw/openclaw@89c5a68 chore(ui): refresh it control ui locale · openclaw/openclaw@44ca805 chore(ui): refresh tr control ui locale chore(ui): refresh fr control ui locale · openclaw/openclaw@2240b0e chore(ui): refresh ko control ui locale · openclaw/openclaw@5fa250b chore(ui): refresh ja-JP control ui locale · openclaw/openclaw@f4ea401 chore(ui): refresh es control ui locale · openclaw/openclaw@751dde0 chore(ui): refresh de control ui locale · openclaw/openclaw@72a9b5b chore(ui): refresh pt-BR control ui locale · openclaw/openclaw@501b6e0 chore(ui): refresh zh-CN control ui locale chore(ui): refresh zh-TW control ui locale · openclaw/openclaw@88dee79 Add Slack approval QA checkpoints (#85141) fix(agents): mirror internal ui message tool replies (#85564) perf(whatsapp): narrow runtime setter entry (#85589) · openclaw/openclaw@463929d fix: smooth chat focus mode layout · openclaw/openclaw@bb5abef Fix Telegram missing harness spool poison (#85605) · openclaw/openclaw@b745082 fix(session): surface previous-transcript archive failures on /new ro… · openclaw/openclaw@679a46d Policy: add agent workspace conformance checks (#85096) · openclaw/openclaw@a94f344 fix(installer): fail failed Windows git builds · openclaw/openclaw@2edd6e2 fix(codex): honor node exec policy for native surfaces (#85534) · openclaw/openclaw@e0405ec fix(qa-lab): stabilize codex runtime parity fixtures fix(github): preserve sufficient proof against negative relabel (#85567) · openclaw/openclaw@6b52dff docs: add changelog for context pressure preflight · openclaw/openclaw@5ca734f Fix context pressure preflight for tool-heavy sessions (#85541) · openclaw/openclaw@c08400e fix(doctor): classify codex asset notice as info (#85119) · openclaw/openclaw@959b935 fix(ui): keep chat picker search current (#85547) fix: preserve message-tool delivery evidence · openclaw/openclaw@f022b05 fix(codex): add API key paste auth (#85533) fix: satisfy openai video test typecheck · openclaw/openclaw@743caed fix: route openai video edits to edits endpoint · openclaw/openclaw@6c3fcb8 fix(qmd): normalize direct file collection paths (#65212) · openclaw/openclaw@227b4bf fix(testbox): preserve clean sparse checkouts · openclaw/openclaw@58e9628 fix(ui): run ui script through junction paths (#85525) · openclaw/openclaw@ad19dd8 docs: fix troubleshooting logs link (#85545) · openclaw/openclaw@60582b6 Revert chat session picker inline search (#85527) · openclaw/openclaw@d69bcfd fix: preserve guarded video operation cleanup · openclaw/openclaw@ed7d99a fix: honor openai video provider request network policy fix: retry guarded video downloads · openclaw/openclaw@efbf9f3 fix: thread openai video request policy · openclaw/openclaw@31b5145 docs(changelog): note heartbeat message-tool fix · openclaw/openclaw@c127334 fix: use fs-safe trash for agent delete (#84394) · openclaw/openclaw@951bbe6 Fix heartbeat message-tool delivery policy (#85357) · openclaw/openclaw@bd9c78f Scope config preflight note suppression (#84439) · openclaw/openclaw@91d85e7 fix(cron): document best-effort edit delivery mode (#84526) fix(dreaming): open report cards from memory palace (#85144) · openclaw/openclaw@2e15830 fix(openai-codex): preserve image input capability (#85393) · openclaw/openclaw@49ce171 fix(codex): stabilize heartbeat dynamic tool schema (#84681) · openclaw/openclaw@c52daa4 docs: absorb small documentation PRs · openclaw/openclaw@658be7f fix(scripts): preserve bws resolver parse errors (#85528) · openclaw/openclaw@13a4c57 fix(telegram): honor outbound media max bytes (#83478) · openclaw/openclaw@f2d4f93 fix(skills): restore executable bit on bundled whisper script + relea… · openclaw/openclaw@1dd3b52 fix(google): print Gemini OAuth URL before browser launch (#71469) · openclaw/openclaw@2d5bda9 docs: absorb contributor documentation fixes docs: tighten landable bug sweep gates · openclaw/openclaw@8f86383 fix: reuse provider auth lookup facts (#85499) · openclaw/openclaw@299ed80 fix: keep session picker focus separate · openclaw/openclaw@7e12370 feat: start onboarding for fresh CLI installs (#85519) · openclaw/openclaw@464ffc1 docs: refresh contributor docs · openclaw/openclaw@64d13c0 fix(update): prepack npm git update specs · openclaw/openclaw@84f6b5c fix: simplify chat session search · openclaw/openclaw@7e16a50 fix: use native mac settings sidebar · openclaw/openclaw@0556958 chore: ignore antigravity cli state · openclaw/openclaw@dd07fb4 fix(media): replace Gemini CLI fallback with sandboxed Antigravity (#… · openclaw/openclaw@0622fb6 docs: add bugbash landing changelog entries · openclaw/openclaw@faad2b0 fix(diffs): continue after card hydration errors (#84775) · openclaw/openclaw@9b5c281 fix(proxy): add missing clientSocket error handler in CONNECT tunnel … · openclaw/openclaw@e008bc9 fix(memory): report qmd workspace cwd probe failures (#63167) · openclaw/openclaw@7134a95 fix(agents): handle parallel tool call deltas in openai-completions s… test: align release validation package acceptance check (#85515) · openclaw/openclaw@423f525 fix: recover stuck Codex compaction · openclaw/openclaw@44d5330 docs: require visual proof for control ui e2e (#85513) · openclaw/openclaw@8174bfc Policy: add gateway exposure checks (#81981) · openclaw/openclaw@dcc5e45 ci: unblock advisory Tideclaw alpha release checks · openclaw/openclaw@dcfc7e5 fix(installer): tolerate WSL UNC launch cwd · openclaw/openclaw@684a9b2 docs: absorb docs sweep · openclaw/openclaw@bb5010b fix: cancel stale provider auth prewarms (#85503) · openclaw/openclaw@60e3749 Add TUI PTY integration coverage (#85485) · openclaw/openclaw@0a50cbd fix(security): escape entry.id in HTML export to prevent attribute XS… · openclaw/openclaw@7bc4a33 fix: guard openai-completions tool payload with supportsTools compat … · openclaw/openclaw@76a025c fix(slack): surface auth.test failure + normalize explicit-bot mentio… · openclaw/openclaw@995a020 chore(release): bump version to 2026.5.22 fix(ui): keep chat session search inline (#85490) · openclaw/openclaw@2601453 Policy: add secret and auth conformance checks (#81974) · openclaw/openclaw@c85feac fix(delivery): log failDelivery errors instead of silently swallowing… · openclaw/openclaw@f75789f fix(cli): validate debug proxy numeric options (#84260) · openclaw/openclaw@5c866a1
feat(diagnostics): trace gateway secret preparation (#83019) · openclaw/openclaw@4f0c902
samzong · 2026-05-23 · via Recent Commits to openclaw:main

@@ -1,9 +1,10 @@

1-

import { mkdtempSync, rmSync, writeFileSync } from "node:fs";

1+

import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";

22

import { tmpdir } from "node:os";

33

import path from "node:path";

44

import { afterEach, describe, expect, it, vi } from "vitest";

55

import { loadAuthProfileStoreWithoutExternalProfiles } from "../agents/auth-profiles.js";

66

import type { ConfigFileSnapshot, OpenClawConfig } from "../config/types.js";

7+

import { measureDiagnosticsTimelineSpan } from "../infra/diagnostics-timeline.js";

78

import type { PreparedSecretsRuntimeSnapshot, SecretResolverWarning } from "../secrets/runtime.js";

89

import { KNOWN_WEAK_GATEWAY_TOKEN_PLACEHOLDERS } from "./known-weak-gateway-secrets.js";

910

import {

@@ -115,6 +116,14 @@ function runtimeSecretsActivatorForTest(params: {

115116

});

116117

}

117118119+

function readTimelineEvents(filePath: string): Array<Record<string, unknown>> {

120+

return readFileSync(filePath, "utf8")

121+

.trim()

122+

.split(/\r?\n/u)

123+

.filter(Boolean)

124+

.map((line) => JSON.parse(line) as Record<string, unknown>);

125+

}

126+118127

function installGatewayStartupSecretsRuntimeMock(state: GatewayStartupSecretsRuntimeMock) {

119128

(

120129

globalThis as typeof globalThis & {

@@ -206,6 +215,122 @@ describe("gateway startup config secret preflight", () => {

206215

]);

207216

});

208217218+

it("emits sanitized diagnostics timeline spans for secrets preparation", async () => {

219+

const root = mkdtempSync(path.join(tmpdir(), "openclaw-startup-secrets-timeline-"));

220+

const timelinePath = path.join(root, "timeline.jsonl");

221+

const previousDiagnostics = process.env.OPENCLAW_DIAGNOSTICS;

222+

const previousTimelinePath = process.env.OPENCLAW_DIAGNOSTICS_TIMELINE_PATH;

223+

process.env.OPENCLAW_DIAGNOSTICS = "timeline";

224+

process.env.OPENCLAW_DIAGNOSTICS_TIMELINE_PATH = timelinePath;

225+

try {

226+

const config = gatewaySecretRefSnapshot().config;

227+

const prepareRuntimeSecretsSnapshot = vi.fn(async ({ config }) => preparedSnapshot(config));

228+229+

const activateRuntimeSecrets = createRuntimeSecretsActivator({

230+

logSecrets: {

231+

info: vi.fn(),

232+

warn: vi.fn(),

233+

error: vi.fn(),

234+

},

235+

emitStateEvent: vi.fn(),

236+

prepareRuntimeSecretsSnapshot,

237+

activateRuntimeSecretsSnapshot: vi.fn(),

238+

});

239+240+

await activateRuntimeSecrets(config, { reason: "startup", activate: false });

241+242+

const events = readTimelineEvents(timelinePath);

243+

expect(events).toHaveLength(2);

244+

expect(events.map((event) => event.type)).toEqual(["span.start", "span.end"]);

245+

for (const event of events) {

246+

expect(event.name).toBe("secrets.prepare");

247+

expect(event.phase).toBe("startup");

248+

expect(event.attributes).toEqual({

249+

activate: false,

250+

gatewayAuthSecretRef: true,

251+

reason: "startup",

252+

});

253+

}

254+

expect(JSON.stringify(events)).not.toContain("GATEWAY_TOKEN_REF");

255+

} finally {

256+

if (previousDiagnostics === undefined) {

257+

delete process.env.OPENCLAW_DIAGNOSTICS;

258+

} else {

259+

process.env.OPENCLAW_DIAGNOSTICS = previousDiagnostics;

260+

}

261+

if (previousTimelinePath === undefined) {

262+

delete process.env.OPENCLAW_DIAGNOSTICS_TIMELINE_PATH;

263+

} else {

264+

process.env.OPENCLAW_DIAGNOSTICS_TIMELINE_PATH = previousTimelinePath;

265+

}

266+

rmSync(root, { force: true, recursive: true });

267+

}

268+

});

269+270+

it("omits secret preparation error messages from diagnostics timeline spans", async () => {

271+

const root = mkdtempSync(path.join(tmpdir(), "openclaw-startup-secrets-timeline-"));

272+

const timelinePath = path.join(root, "timeline.jsonl");

273+

const previousDiagnostics = process.env.OPENCLAW_DIAGNOSTICS;

274+

const previousTimelinePath = process.env.OPENCLAW_DIAGNOSTICS_TIMELINE_PATH;

275+

process.env.OPENCLAW_DIAGNOSTICS = "timeline";

276+

process.env.OPENCLAW_DIAGNOSTICS_TIMELINE_PATH = timelinePath;

277+

try {

278+

const prepareRuntimeSecretsSnapshot = vi.fn(async () => {

279+

throw new Error('Secret provider "default" is not configured for GATEWAY_TOKEN_REF.');

280+

});

281+282+

const activateRuntimeSecrets = createRuntimeSecretsActivator({

283+

logSecrets: {

284+

info: vi.fn(),

285+

warn: vi.fn(),

286+

error: vi.fn(),

287+

},

288+

emitStateEvent: vi.fn(),

289+

prepareRuntimeSecretsSnapshot,

290+

activateRuntimeSecretsSnapshot: vi.fn(),

291+

});

292+293+

await expect(

294+

prepareGatewayStartupConfig({

295+

configSnapshot: gatewaySecretRefSnapshot(),

296+

activateRuntimeSecrets,

297+

measure: (name, run, options) =>

298+

measureDiagnosticsTimelineSpan(name, run, {

299+

env: process.env,

300+

omitErrorMessage: options?.omitErrorMessage,

301+

phase: "startup",

302+

}),

303+

}),

304+

).rejects.toThrow("Startup failed: required secrets are unavailable.");

305+306+

const events = readTimelineEvents(timelinePath);

307+

const errorEvents = events.filter((event) => event.type === "span.error");

308+

expect(errorEvents.map((event) => event.name)).toEqual([

309+

"secrets.prepare",

310+

"config.auth.secret-preflight",

311+

]);

312+

for (const event of errorEvents) {

313+

expect(event.phase).toBe("startup");

314+

expect(event.errorName).toBe("Error");

315+

expect(event.errorMessage).toBeUndefined();

316+

}

317+

expect(JSON.stringify(events)).not.toContain("GATEWAY_TOKEN_REF");

318+

expect(JSON.stringify(events)).not.toContain("default");

319+

} finally {

320+

if (previousDiagnostics === undefined) {

321+

delete process.env.OPENCLAW_DIAGNOSTICS;

322+

} else {

323+

process.env.OPENCLAW_DIAGNOSTICS = previousDiagnostics;

324+

}

325+

if (previousTimelinePath === undefined) {

326+

delete process.env.OPENCLAW_DIAGNOSTICS_TIMELINE_PATH;

327+

} else {

328+

process.env.OPENCLAW_DIAGNOSTICS_TIMELINE_PATH = previousTimelinePath;

329+

}

330+

rmSync(root, { force: true, recursive: true });

331+

}

332+

});

333+209334

it("wraps startup secret activation failures without emitting reload state events", async () => {

210335

const error = new Error('Environment variable "OPENAI_API_KEY" is missing or empty.');

211336

const prepareRuntimeSecretsSnapshot = vi.fn(async () => {