Skip to content
Open
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
38ba22d
feat(telemetry): Phase 2 — tool.blocked_on_user + hook spans
doudouOUC May 19, 2026
6767469
fix(telemetry): address #4321 review — Copilot inline + code-reviewer…
doudouOUC May 19, 2026
32f94d3
fix(telemetry): close autoApprove blocked-span leak + cover three new…
doudouOUC May 19, 2026
68dea8a
fix(telemetry): revert autoApprove catch finalizeBlockedSpan (#4321 c…
doudouOUC May 19, 2026
2b227b0
fix(telemetry): split tool.failure_kind labels + cover proceed_once d…
doudouOUC May 19, 2026
cc3f7fc
fix(telemetry): address #4321 wenshao Critical + bot summary nits
doudouOUC May 19, 2026
f9ff554
refactor(telemetry): extract withHookSpan helper + drop dead finalize…
doudouOUC May 19, 2026
eafe688
fix(telemetry): hook span error tracking + TTL cleanup safety + call_…
doudouOUC May 19, 2026
574f645
fix(telemetry): close hookError plumbing gaps from final pre-merge audit
doudouOUC May 19, 2026
48e78d6
test(telemetry): cover #4321 rethrow path + 2 of the new failure_kind…
doudouOUC May 19, 2026
9cbbdfc
fix(telemetry): adopt 4 wenshao Critical/Suggestion findings on PR #4321
doudouOUC May 20, 2026
31921a9
fix(telemetry): adopt 7 DeepSeek /review findings on PR #4321
doudouOUC May 20, 2026
fc509d5
fix(telemetry): adopt 3 wenshao /review findings on PR #4321
doudouOUC May 20, 2026
f0befac
fix(telemetry): adopt 7 wenshao /review round-3 findings on PR #4321
doudouOUC May 20, 2026
8716069
fix(telemetry): polish 2 wenshao /review round-4 nits on PR #4321
doudouOUC May 20, 2026
e7dd8aa
fix(telemetry): adopt 4 wenshao /review round-5 findings on PR #4321
doudouOUC May 20, 2026
51cb97c
fix(telemetry): adopt 1 wenshao /review round-6 finding on PR #4321
doudouOUC May 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,417 changes: 1,417 additions & 0 deletions packages/core/src/core/coreToolScheduler.test.ts

Large diffs are not rendered by default.

686 changes: 633 additions & 53 deletions packages/core/src/core/coreToolScheduler.ts

Large diffs are not rendered by default.

16 changes: 13 additions & 3 deletions packages/core/src/core/toolHookTriggers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,13 @@ describe('toolHookTriggers', () => {
'auto',
);

expect(result).toEqual({ shouldProceed: true });
// #4321 review: hookError surfaces the swallowed transport error so
// observers (telemetry spans, debug logs) can distinguish a failed
// hook from a successful "allow" decision.
expect(result).toEqual({
shouldProceed: true,
hookError: 'Network error',
});
});
});

Expand Down Expand Up @@ -338,7 +344,9 @@ describe('toolHookTriggers', () => {
'auto',
);

expect(result).toEqual({ shouldStop: false });
// #4321 review: hookError now surfaced to caller (see PreToolUse parallel test).
expect(result.shouldStop).toBe(false);
expect(result.hookError).toBeDefined();
});
});

Expand Down Expand Up @@ -429,7 +437,9 @@ describe('toolHookTriggers', () => {
'error message',
);

expect(result).toEqual({});
// #4321 review: hookError now surfaced to caller.
expect(result.hookError).toBeDefined();
expect(result.additionalContext).toBeUndefined();
});
});

Expand Down
51 changes: 38 additions & 13 deletions packages/core/src/core/toolHookTriggers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ export interface PreToolUseHookResult {
blockType?: 'denied' | 'ask' | 'stop';
/** Additional context to add */
additionalContext?: string;
/**
* Set when the hook helper caught and absorbed a transport / dispatch
* error. The tool execution still proceeds (existing non-blocking
* contract), but observers (telemetry spans, debug logs) can detect
* that the hook itself failed instead of treating the safe-default
* response as a successful "allow" decision (#4321 review).
*/
hookError?: string;
}

/**
Expand All @@ -55,6 +63,8 @@ export interface PostToolUseHookResult {
stopReason?: string;
/** Additional context to append to tool response */
additionalContext?: string;
/** See PreToolUseHookResult.hookError. */
hookError?: string;
}

/**
Expand All @@ -63,6 +73,8 @@ export interface PostToolUseHookResult {
export interface PostToolUseFailureHookResult {
/** Additional context about the failure */
additionalContext?: string;
/** See PreToolUseHookResult.hookError. */
hookError?: string;
}

/**
Expand Down Expand Up @@ -107,7 +119,15 @@ export async function firePreToolUseHook(
);

if (!response.success || !response.output) {
return { shouldProceed: true };
// Hook runner reported failure (URL validation, fn exception,
// prompt-runner crash, ...). The `response.error` from the runner
// is the canonical cause — forward it so telemetry and operators
// see the actual failure instead of a fake "allow" success
// (#4321 review silent-failure-hunter HIGH).
const message = response.error?.message;
return message
? { shouldProceed: true, hookError: message }
: { shouldProceed: true };
}

const preToolOutput = createHookOutput(
Expand Down Expand Up @@ -155,10 +175,9 @@ export async function firePreToolUseHook(
};
} catch (error) {
// Hook errors should not block tool execution
debugLogger.warn(
`PreToolUse hook error for ${toolName}: ${error instanceof Error ? error.message : String(error)}`,
);
return { shouldProceed: true };
const message = error instanceof Error ? error.message : String(error);
debugLogger.warn(`PreToolUse hook error for ${toolName}: ${message}`);
return { shouldProceed: true, hookError: message };
}
}

Expand Down Expand Up @@ -207,7 +226,11 @@ export async function firePostToolUseHook(
);

if (!response.success || !response.output) {
return { shouldStop: false };
// See firePreToolUseHook for the rationale.
const message = response.error?.message;
return message
? { shouldStop: false, hookError: message }
: { shouldStop: false };
}

const postToolOutput = createHookOutput(
Expand All @@ -232,10 +255,9 @@ export async function firePostToolUseHook(
};
} catch (error) {
// Hook errors should not affect tool result
debugLogger.warn(
`PostToolUse hook error for ${toolName}: ${error instanceof Error ? error.message : String(error)}`,
);
return { shouldStop: false };
const message = error instanceof Error ? error.message : String(error);
debugLogger.warn(`PostToolUse hook error for ${toolName}: ${message}`);
return { shouldStop: false, hookError: message };
}
}

Expand Down Expand Up @@ -287,7 +309,9 @@ export async function firePostToolUseFailureHook(
);

if (!response.success || !response.output) {
return {};
// See firePreToolUseHook for the rationale.
const message = response.error?.message;
return message ? { hookError: message } : {};
}

const failureOutput = createHookOutput(
Expand All @@ -301,10 +325,11 @@ export async function firePostToolUseFailureHook(
};
} catch (error) {
// Hook errors should not affect error handling
const message = error instanceof Error ? error.message : String(error);
debugLogger.warn(
`PostToolUseFailure hook error for ${toolName}: ${error instanceof Error ? error.message : String(error)}`,
`PostToolUseFailure hook error for ${toolName}: ${message}`,
);
return {};
return { hookError: message };
}
}

Expand Down
4 changes: 4 additions & 0 deletions packages/core/src/telemetry/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,7 @@ export const SPAN_INTERACTION = 'qwen-code.interaction';
export const SPAN_LLM_REQUEST = 'qwen-code.llm_request';
export const SPAN_TOOL = 'qwen-code.tool';
export const SPAN_TOOL_EXECUTION = 'qwen-code.tool.execution';
/** Brackets the time a tool spends in `awaiting_approval` waiting on the user. */
export const SPAN_TOOL_BLOCKED_ON_USER = 'qwen-code.tool.blocked_on_user';
/** Wraps each pre/post-tool-use hook fire site for per-hook latency / decision tracking. */
export const SPAN_HOOK = 'qwen-code.hook';
9 changes: 9 additions & 0 deletions packages/core/src/telemetry/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,13 +146,22 @@ export {
runInToolSpanContext,
startToolExecutionSpan,
endToolExecutionSpan,
startToolBlockedOnUserSpan,
endToolBlockedOnUserSpan,
startHookSpan,
endHookSpan,
getActiveInteractionSpan,
} from './session-tracing.js';
export type {
StartInteractionOptions,
EndInteractionOptions,
LLMRequestMetadata,
ToolSpanMetadata,
ToolBlockedDecision,
ToolBlockedSource,
HookEvent,
StartHookSpanOptions,
HookSpanMetadata,
} from './session-tracing.js';
export {
addUserPromptAttributes,
Expand Down
Loading
Loading