fix: 遥测改用 TELEMETRY_ENDPOINT,不复用 hookUrl

hookUrl 是 agent 业务回调,不用于 debug。新增独立的 TELEMETRY_ENDPOINT
指向 3202 /api/v1/tasks/telemetry,fire-and-forget 上报执行结果到 Loki。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
ywkj 2026-04-20 07:46:41 +08:00
parent 01fcb90505
commit d932bb81d0
1 changed files with 11 additions and 42 deletions

View File

@ -1,7 +1,6 @@
#!/usr/bin/env bun #!/usr/bin/env bun
import type { Command } from '../src/index.ts'; import type { Command } from '../src/index.ts';
import { run } from '../src/index.ts'; import { run } from '../src/index.ts';
import { createSkillClient } from '../src/auth-cli.ts';
const SKILL_NAME = 'my-skill'; // TODO: replace with actual skill name const SKILL_NAME = 'my-skill'; // TODO: replace with actual skill name
@ -16,14 +15,14 @@ Config: ~/.openclaw/.env (CLIENT_KEY)
`); `);
} }
async function reportHook( function reportTelemetry(payload: object): void {
hookUrl: string, const endpoint = process.env.TELEMETRY_ENDPOINT;
hookToken: string | undefined, if (!endpoint) return;
payload: object, fetch(endpoint, {
): Promise<void> { method: 'POST',
const headers: Record<string, string> = { 'Content-Type': 'application/json' }; headers: { 'Content-Type': 'application/json' },
if (hookToken) headers['Authorization'] = `Bearer ${hookToken}`; body: JSON.stringify(payload),
await fetch(hookUrl, { method: 'POST', headers, body: JSON.stringify(payload) }); }).catch(() => {});
} }
async function main(): Promise<void> { async function main(): Promise<void> {
@ -45,19 +44,6 @@ async function main(): Promise<void> {
if (positionals.length < 1) { printUsage(); process.exit(1); } if (positionals.length < 1) { printUsage(); process.exit(1); }
const command = positionals[0] as Command; const command = positionals[0] as Command;
// Exchange CLIENT_KEY for session — gives us hookUrl for telemetry
let hookUrl: string | undefined;
let hookToken: string | undefined;
try {
const client = createSkillClient({ dryRun });
const session = await client.session();
hookUrl = session.hookUrl;
hookToken = session.hookToken;
} catch {
// Auth failure is non-fatal for telemetry; skill still runs
}
const startMs = Date.now(); const startMs = Date.now();
let result: Awaited<ReturnType<typeof run>>; let result: Awaited<ReturnType<typeof run>>;
@ -65,30 +51,13 @@ async function main(): Promise<void> {
result = await run(command, positionals.slice(1), dryRun); result = await run(command, positionals.slice(1), dryRun);
} catch (err) { } catch (err) {
const error = err instanceof Error ? err.message : String(err); const error = err instanceof Error ? err.message : String(err);
const failed = { status: 'failed' as const, command, dryRun, error }; console.log(JSON.stringify({ status: 'failed', command, dryRun, error }, null, 2));
console.log(JSON.stringify(failed, null, 2)); if (!dryRun) reportTelemetry({ skill: SKILL_NAME, command, status: 'failed', durationMs: Date.now() - startMs, error });
if (hookUrl && !dryRun) {
reportHook(hookUrl, hookToken, {
skill: SKILL_NAME, command, status: 'failed',
durationMs: Date.now() - startMs, error,
}).catch(() => {});
}
process.exit(1); process.exit(1);
} }
console.log(JSON.stringify(result, null, 2)); console.log(JSON.stringify(result, null, 2));
if (!dryRun) reportTelemetry({ skill: SKILL_NAME, command, status: result.status, durationMs: Date.now() - startMs, error: (result as any).error });
// Fire-and-forget telemetry — never delays output
if (hookUrl && !dryRun) {
reportHook(hookUrl, hookToken, {
skill: SKILL_NAME,
command,
status: result.status,
durationMs: Date.now() - startMs,
error: (result as any).error,
}).catch(() => {});
}
} }
main().catch((err) => { main().catch((err) => {