Skip to content
Merged
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions packages/core/src/tools/skill.ts
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,12 @@ class SkillToolInvocation extends BaseToolInvocation<SkillParams, ToolResult> {
// track via `onSkillLoaded` — no skill body was loaded, and
// conflating the two would inflate skill telemetry /
// `/context` skill-token attribution with command runs.
if (typeof content === 'object' && 'error' in content) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] The new { error: string } branch (lines 464-469) has no test coverage. The disabled-skill execute guard describe block covers string-return, null-executor, null-return, and throw scenarios, but none exercise commandExecutor returning { error: '...' }.

The non-disabled path has an analogous test (logs prompt attribution when executor returns an error in skill.test.ts), proving the pattern is testable. Without a test, a future refactor that breaks the type guard or the return shape would go undetected.

Consider adding a test to the disabled-skill execute guard describe block:

it('returns the error message when commandExecutor returns an error object for a disabled skill', async () => {
  vi.mocked(config.getDisabledSkillNames).mockReturnValue(
    new Set(['mytool']),
  );
  const executor = vi.fn().mockResolvedValue({
    error: 'Blocked by policy',
  });
  vi.mocked(config.getModelInvocableCommandsExecutor).mockReturnValue(
    executor,
  );

  const invocation = (
    skillTool as SkillToolWithProtectedMethods
  ).createInvocation({ skill: 'mytool' });
  const result = await invocation.execute();

  expect(mockSkillManager.loadSkillForRuntime).not.toHaveBeenCalled();
  expect(executor).toHaveBeenCalledWith('mytool');
  const llmText = partToString(result.llmContent);
  expect(llmText).toBe('Blocked by policy');
  expect(result.returnDisplay).toBe('Blocked by policy');
});

— qwen3.7-max via Qwen Code /review

return {
llmContent: content.error,
returnDisplay: content.error,
};
}
return {
llmContent: [{ text: content }],
returnDisplay: `Delegated to command: ${this.params.skill}`,
Expand Down
Loading