style: 完成所有文件的lint

This commit is contained in:
claude-code-best
2026-05-01 21:39:30 +08:00
parent d136872cc9
commit 6182015005
1333 changed files with 68255 additions and 77882 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +1,11 @@
import { mock, describe, expect, test } from "bun:test";
import { mock, describe, expect, test } from 'bun:test'
// Mock heavy deps
mock.module("src/utils/model/agent.js", () => ({
mock.module('src/utils/model/agent.js', () => ({
getDefaultSubagentModel: () => undefined,
}));
}))
mock.module("src/utils/settings/constants.js", () => ({
mock.module('src/utils/settings/constants.js', () => ({
getSourceDisplayName: (source: string) => source,
getSourceDisplayNameLowercase: (source: string) => source,
getSourceDisplayNameCapitalized: (source: string) => source,
@@ -15,133 +15,131 @@ mock.module("src/utils/settings/constants.js", () => ({
parseSettingSourcesFlag: () => [],
getEnabledSettingSources: () => [],
isSettingSourceEnabled: () => true,
SETTING_SOURCES: ["localSettings", "userSettings", "projectSettings"],
SOURCES: ["localSettings", "userSettings", "projectSettings"],
CLAUDE_CODE_SETTINGS_SCHEMA_URL: "https://json.schemastore.org/claude-code-settings.json",
}));
SETTING_SOURCES: ['localSettings', 'userSettings', 'projectSettings'],
SOURCES: ['localSettings', 'userSettings', 'projectSettings'],
CLAUDE_CODE_SETTINGS_SCHEMA_URL:
'https://json.schemastore.org/claude-code-settings.json',
}))
const {
resolveAgentOverrides,
compareAgentsByName,
AGENT_SOURCE_GROUPS,
} = await import("../agentDisplay");
const { resolveAgentOverrides, compareAgentsByName, AGENT_SOURCE_GROUPS } =
await import('../agentDisplay')
function makeAgent(agentType: string, source: string): any {
return { agentType, source, name: agentType };
return { agentType, source, name: agentType }
}
describe("resolveAgentOverrides", () => {
test("marks no overrides when all agents active", () => {
const agents = [makeAgent("builder", "userSettings")];
const result = resolveAgentOverrides(agents, agents);
expect(result).toHaveLength(1);
expect(result[0].overriddenBy).toBeUndefined();
});
describe('resolveAgentOverrides', () => {
test('marks no overrides when all agents active', () => {
const agents = [makeAgent('builder', 'userSettings')]
const result = resolveAgentOverrides(agents, agents)
expect(result).toHaveLength(1)
expect(result[0].overriddenBy).toBeUndefined()
})
test("marks inactive agent as overridden", () => {
test('marks inactive agent as overridden', () => {
const allAgents = [
makeAgent("builder", "projectSettings"),
makeAgent("builder", "userSettings"),
];
const activeAgents = [makeAgent("builder", "userSettings")];
const result = resolveAgentOverrides(allAgents, activeAgents);
const projectAgent = result.find(
(a: any) => a.source === "projectSettings",
);
expect(projectAgent?.overriddenBy).toBe("userSettings");
});
makeAgent('builder', 'projectSettings'),
makeAgent('builder', 'userSettings'),
]
const activeAgents = [makeAgent('builder', 'userSettings')]
const result = resolveAgentOverrides(allAgents, activeAgents)
const projectAgent = result.find((a: any) => a.source === 'projectSettings')
expect(projectAgent?.overriddenBy).toBe('userSettings')
})
test("overriddenBy shows the overriding agent source", () => {
const allAgents = [makeAgent("tester", "localSettings")];
const activeAgents = [makeAgent("tester", "policySettings")];
const result = resolveAgentOverrides(allAgents, activeAgents);
expect(result[0].overriddenBy).toBe("policySettings");
});
test('overriddenBy shows the overriding agent source', () => {
const allAgents = [makeAgent('tester', 'localSettings')]
const activeAgents = [makeAgent('tester', 'policySettings')]
const result = resolveAgentOverrides(allAgents, activeAgents)
expect(result[0].overriddenBy).toBe('policySettings')
})
test("deduplicates agents by (agentType, source)", () => {
test('deduplicates agents by (agentType, source)', () => {
const agents = [
makeAgent("builder", "userSettings"),
makeAgent("builder", "userSettings"), // duplicate
];
const result = resolveAgentOverrides(agents, agents.slice(0, 1));
expect(result).toHaveLength(1);
});
makeAgent('builder', 'userSettings'),
makeAgent('builder', 'userSettings'), // duplicate
]
const result = resolveAgentOverrides(agents, agents.slice(0, 1))
expect(result).toHaveLength(1)
})
test("preserves agent definition properties", () => {
const agents = [{ agentType: "a", source: "userSettings", name: "Agent A" }] as any[];
const result = resolveAgentOverrides(agents, agents);
expect((result[0] as any).name).toBe("Agent A");
expect(result[0].agentType).toBe("a");
});
test("handles empty arrays", () => {
expect(resolveAgentOverrides([], [])).toEqual([]);
});
test("handles agent from git worktree (duplicate detection)", () => {
test('preserves agent definition properties', () => {
const agents = [
makeAgent("builder", "projectSettings"),
makeAgent("builder", "projectSettings"),
makeAgent("builder", "localSettings"),
];
const result = resolveAgentOverrides(agents, agents.slice(0, 1));
{ agentType: 'a', source: 'userSettings', name: 'Agent A' },
] as any[]
const result = resolveAgentOverrides(agents, agents)
expect((result[0] as any).name).toBe('Agent A')
expect(result[0].agentType).toBe('a')
})
test('handles empty arrays', () => {
expect(resolveAgentOverrides([], [])).toEqual([])
})
test('handles agent from git worktree (duplicate detection)', () => {
const agents = [
makeAgent('builder', 'projectSettings'),
makeAgent('builder', 'projectSettings'),
makeAgent('builder', 'localSettings'),
]
const result = resolveAgentOverrides(agents, agents.slice(0, 1))
// Deduped: projectSettings appears once, localSettings once
expect(result).toHaveLength(2);
});
});
expect(result).toHaveLength(2)
})
})
describe("compareAgentsByName", () => {
test("sorts alphabetically ascending", () => {
const a = makeAgent("alpha", "userSettings");
const b = makeAgent("beta", "userSettings");
expect(compareAgentsByName(a, b)).toBeLessThan(0);
});
describe('compareAgentsByName', () => {
test('sorts alphabetically ascending', () => {
const a = makeAgent('alpha', 'userSettings')
const b = makeAgent('beta', 'userSettings')
expect(compareAgentsByName(a, b)).toBeLessThan(0)
})
test("returns negative when a.name < b.name", () => {
const a = makeAgent("a", "s");
const b = makeAgent("b", "s");
expect(compareAgentsByName(a, b)).toBeLessThan(0);
});
test('returns negative when a.name < b.name', () => {
const a = makeAgent('a', 's')
const b = makeAgent('b', 's')
expect(compareAgentsByName(a, b)).toBeLessThan(0)
})
test("returns positive when a.name > b.name", () => {
const a = makeAgent("z", "s");
const b = makeAgent("a", "s");
expect(compareAgentsByName(a, b)).toBeGreaterThan(0);
});
test('returns positive when a.name > b.name', () => {
const a = makeAgent('z', 's')
const b = makeAgent('a', 's')
expect(compareAgentsByName(a, b)).toBeGreaterThan(0)
})
test("returns 0 for same name", () => {
const a = makeAgent("same", "s");
const b = makeAgent("same", "s");
expect(compareAgentsByName(a, b)).toBe(0);
});
test('returns 0 for same name', () => {
const a = makeAgent('same', 's')
const b = makeAgent('same', 's')
expect(compareAgentsByName(a, b)).toBe(0)
})
test("is case-insensitive (sensitivity: base)", () => {
const a = makeAgent("Alpha", "s");
const b = makeAgent("alpha", "s");
expect(compareAgentsByName(a, b)).toBe(0);
});
});
test('is case-insensitive (sensitivity: base)', () => {
const a = makeAgent('Alpha', 's')
const b = makeAgent('alpha', 's')
expect(compareAgentsByName(a, b)).toBe(0)
})
})
describe("AGENT_SOURCE_GROUPS", () => {
test("contains expected source groups in order", () => {
expect(AGENT_SOURCE_GROUPS).toHaveLength(7);
describe('AGENT_SOURCE_GROUPS', () => {
test('contains expected source groups in order', () => {
expect(AGENT_SOURCE_GROUPS).toHaveLength(7)
expect(AGENT_SOURCE_GROUPS[0]).toEqual({
label: "User agents",
source: "userSettings",
});
label: 'User agents',
source: 'userSettings',
})
expect(AGENT_SOURCE_GROUPS[6]).toEqual({
label: "Built-in agents",
source: "built-in",
});
});
label: 'Built-in agents',
source: 'built-in',
})
})
test("has unique labels", () => {
const labels = AGENT_SOURCE_GROUPS.map((g) => g.label);
expect(new Set(labels).size).toBe(labels.length);
});
test('has unique labels', () => {
const labels = AGENT_SOURCE_GROUPS.map(g => g.label)
expect(new Set(labels).size).toBe(labels.length)
})
test("has unique sources", () => {
const sources = AGENT_SOURCE_GROUPS.map((g) => g.source);
expect(new Set(sources).size).toBe(sources.length);
});
});
test('has unique sources', () => {
const sources = AGENT_SOURCE_GROUPS.map(g => g.source)
expect(new Set(sources).size).toBe(sources.length)
})
})

View File

@@ -1,69 +1,72 @@
import { mock, describe, expect, test } from "bun:test";
import { debugMock } from "../../../../../../tests/mocks/debug";
import { mock, describe, expect, test } from 'bun:test'
import { debugMock } from '../../../../../../tests/mocks/debug'
// ─── Mocks for agentToolUtils.ts dependencies ───
// Only mock modules that are truly unavailable or cause side effects.
// Do NOT mock common/shared modules (zod/v4, bootstrap/state, etc.) to avoid
// corrupting the module cache for other test files in the same Bun process.
const noop = () => {};
const noop = () => {}
mock.module("bun:bundle", () => ({ feature: () => false }));
mock.module('bun:bundle', () => ({ feature: () => false }))
mock.module("src/constants/tools.js", () => ({
mock.module('src/constants/tools.js', () => ({
ALL_AGENT_DISALLOWED_TOOLS: new Set(),
ASYNC_AGENT_ALLOWED_TOOLS: new Set(),
CUSTOM_AGENT_DISALLOWED_TOOLS: new Set(),
IN_PROCESS_TEAMMATE_ALLOWED_TOOLS: new Set(),
}));
}))
mock.module("src/services/AgentSummary/agentSummary.js", () => ({
mock.module('src/services/AgentSummary/agentSummary.js', () => ({
startAgentSummarization: noop,
}));
}))
mock.module("src/services/analytics/index.js", () => ({
mock.module('src/services/analytics/index.js', () => ({
logEvent: noop,
logEventAsync: async () => {},
stripProtoFields: (v: any) => v,
attachAnalyticsSink: noop,
_resetForTesting: noop,
AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS: undefined,
}));
}))
mock.module("src/services/api/dumpPrompts.js", () => ({
mock.module('src/services/api/dumpPrompts.js', () => ({
clearDumpState: noop,
}));
}))
mock.module("src/Tool.js", () => ({
mock.module('src/Tool.js', () => ({
toolMatchesName: () => false,
findToolByName: noop,
}));
}))
// messages.ts is complex - provide stubs for all named exports
mock.module("src/utils/messages.ts", () => ({
mock.module('src/utils/messages.ts', () => ({
extractTextContent: (content: any[]) =>
content?.filter?.((b: any) => b.type === "text")?.map?.((b: any) => b.text)?.join("") ?? "",
content
?.filter?.((b: any) => b.type === 'text')
?.map?.((b: any) => b.text)
?.join('') ?? '',
getLastAssistantMessage: () => null,
SYNTHETIC_MESSAGES: new Set(),
INTERRUPT_MESSAGE: "",
INTERRUPT_MESSAGE_FOR_TOOL_USE: "",
CANCEL_MESSAGE: "",
REJECT_MESSAGE: "",
REJECT_MESSAGE_WITH_REASON_PREFIX: "",
SUBAGENT_REJECT_MESSAGE: "",
SUBAGENT_REJECT_MESSAGE_WITH_REASON_PREFIX: "",
PLAN_REJECTION_PREFIX: "",
DENIAL_WORKAROUND_GUIDANCE: "",
NO_RESPONSE_REQUESTED: "",
SYNTHETIC_TOOL_RESULT_PLACEHOLDER: "",
SYNTHETIC_MODEL: "",
INTERRUPT_MESSAGE: '',
INTERRUPT_MESSAGE_FOR_TOOL_USE: '',
CANCEL_MESSAGE: '',
REJECT_MESSAGE: '',
REJECT_MESSAGE_WITH_REASON_PREFIX: '',
SUBAGENT_REJECT_MESSAGE: '',
SUBAGENT_REJECT_MESSAGE_WITH_REASON_PREFIX: '',
PLAN_REJECTION_PREFIX: '',
DENIAL_WORKAROUND_GUIDANCE: '',
NO_RESPONSE_REQUESTED: '',
SYNTHETIC_TOOL_RESULT_PLACEHOLDER: '',
SYNTHETIC_MODEL: '',
AUTO_REJECT_MESSAGE: noop,
DONT_ASK_REJECT_MESSAGE: noop,
withMemoryCorrectionHint: (s: string) => s,
deriveShortMessageId: () => "",
deriveShortMessageId: () => '',
isClassifierDenial: () => false,
buildYoloRejectionMessage: () => "",
buildClassifierUnavailableMessage: () => "",
buildYoloRejectionMessage: () => '',
buildClassifierUnavailableMessage: () => '',
isEmptyMessageText: () => true,
createAssistantMessage: noop,
createAssistantAPIErrorMessage: noop,
@@ -72,9 +75,9 @@ mock.module("src/utils/messages.ts", () => ({
createUserInterruptionMessage: noop,
createSyntheticUserCaveatMessage: noop,
formatCommandInputTags: noop,
}));
}))
mock.module("src/tasks/LocalAgentTask/LocalAgentTask.js", () => ({
mock.module('src/tasks/LocalAgentTask/LocalAgentTask.js', () => ({
completeAgentTask: noop,
createActivityDescriptionResolver: () => ({}),
createProgressTracker: () => ({}),
@@ -86,11 +89,11 @@ mock.module("src/tasks/LocalAgentTask/LocalAgentTask.js", () => ({
killAsyncAgent: noop,
updateAgentProgress: noop,
updateProgressFromMessage: noop,
}));
}))
mock.module("src/utils/debug.ts", debugMock);
mock.module('src/utils/debug.ts', debugMock)
mock.module("src/utils/errors.js", () => ({
mock.module('src/utils/errors.js', () => ({
ClaudeError: class extends Error {},
MalformedCommandError: class extends Error {},
AbortError: class extends Error {},
@@ -100,142 +103,137 @@ mock.module("src/utils/errors.js", () => ({
TelemetrySafeError_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS: class extends Error {},
isAbortError: () => false,
hasExactErrorMessage: () => false,
toError: (e: any) => e instanceof Error ? e : new Error(String(e)),
toError: (e: any) => (e instanceof Error ? e : new Error(String(e))),
errorMessage: (e: any) => String(e),
getErrnoCode: () => undefined,
isENOENT: () => false,
getErrnoPath: () => undefined,
shortErrorStack: () => "",
shortErrorStack: () => '',
isFsInaccessible: () => false,
classifyAxiosError: () => ({ category: "unknown" }),
}));
classifyAxiosError: () => ({ category: 'unknown' }),
}))
mock.module("src/utils/forkedAgent.js", () => ({}));
mock.module('src/utils/forkedAgent.js', () => ({}))
mock.module("src/utils/permissions/yoloClassifier.js", () => ({
buildTranscriptForClassifier: () => "",
mock.module('src/utils/permissions/yoloClassifier.js', () => ({
buildTranscriptForClassifier: () => '',
classifyYoloAction: () => null,
}));
}))
mock.module("src/utils/task/sdkProgress.js", () => ({
mock.module('src/utils/task/sdkProgress.js', () => ({
emitTaskProgress: noop,
}));
}))
mock.module("src/utils/tokens.js", () => ({
mock.module('src/utils/tokens.js', () => ({
getTokenCountFromUsage: () => 0,
}));
}))
mock.module("src/tools/ExitPlanModeTool/constants.js", () => ({
EXIT_PLAN_MODE_V2_TOOL_NAME: "exit_plan_mode",
}));
mock.module('src/tools/ExitPlanModeTool/constants.js', () => ({
EXIT_PLAN_MODE_V2_TOOL_NAME: 'exit_plan_mode',
}))
mock.module("src/tools/AgentTool/constants.js", () => ({
AGENT_TOOL_NAME: "agent",
LEGACY_AGENT_TOOL_NAME: "task",
}));
mock.module('src/tools/AgentTool/constants.js', () => ({
AGENT_TOOL_NAME: 'agent',
LEGACY_AGENT_TOOL_NAME: 'task',
}))
mock.module("src/tools/AgentTool/loadAgentsDir.js", () => ({}));
mock.module('src/tools/AgentTool/loadAgentsDir.js', () => ({}))
mock.module("src/state/AppState.js", () => ({}));
mock.module('src/state/AppState.js', () => ({}))
mock.module("src/types/ids.js", () => ({
mock.module('src/types/ids.js', () => ({
asAgentId: (id: string) => id,
}));
}))
// Break circular dep
mock.module("src/tools/AgentTool/AgentTool.tsx", () => ({
mock.module('src/tools/AgentTool/AgentTool.tsx', () => ({
AgentTool: {},
inputSchema: {},
outputSchema: {},
default: {},
}));
}))
const {
countToolUses,
getLastToolUseName,
} = await import("../agentToolUtils");
const { countToolUses, getLastToolUseName } = await import('../agentToolUtils')
function makeAssistantMessage(content: any[]): any {
return { type: "assistant", message: { content } };
return { type: 'assistant', message: { content } }
}
function makeUserMessage(text: string): any {
return { type: "user", message: { content: text } };
return { type: 'user', message: { content: text } }
}
describe("countToolUses", () => {
test("counts tool_use blocks in messages", () => {
describe('countToolUses', () => {
test('counts tool_use blocks in messages', () => {
const messages = [
makeAssistantMessage([
{ type: "tool_use", name: "Read" },
{ type: "text", text: "hello" },
{ type: 'tool_use', name: 'Read' },
{ type: 'text', text: 'hello' },
]),
];
expect(countToolUses(messages)).toBe(1);
});
]
expect(countToolUses(messages)).toBe(1)
})
test("returns 0 for messages without tool_use", () => {
test('returns 0 for messages without tool_use', () => {
const messages = [makeAssistantMessage([{ type: 'text', text: 'hello' }])]
expect(countToolUses(messages)).toBe(0)
})
test('returns 0 for empty array', () => {
expect(countToolUses([])).toBe(0)
})
test('counts multiple tool_use blocks across messages', () => {
const messages = [
makeAssistantMessage([{ type: "text", text: "hello" }]),
];
expect(countToolUses(messages)).toBe(0);
});
makeAssistantMessage([{ type: 'tool_use', name: 'Read' }]),
makeUserMessage('ok'),
makeAssistantMessage([{ type: 'tool_use', name: 'Write' }]),
]
expect(countToolUses(messages)).toBe(2)
})
test("returns 0 for empty array", () => {
expect(countToolUses([])).toBe(0);
});
test("counts multiple tool_use blocks across messages", () => {
const messages = [
makeAssistantMessage([{ type: "tool_use", name: "Read" }]),
makeUserMessage("ok"),
makeAssistantMessage([{ type: "tool_use", name: "Write" }]),
];
expect(countToolUses(messages)).toBe(2);
});
test("counts tool_use in single message with multiple blocks", () => {
test('counts tool_use in single message with multiple blocks', () => {
const messages = [
makeAssistantMessage([
{ type: "tool_use", name: "Read" },
{ type: "tool_use", name: "Grep" },
{ type: "tool_use", name: "Write" },
{ type: 'tool_use', name: 'Read' },
{ type: 'tool_use', name: 'Grep' },
{ type: 'tool_use', name: 'Write' },
]),
];
expect(countToolUses(messages)).toBe(3);
});
});
]
expect(countToolUses(messages)).toBe(3)
})
})
describe("getLastToolUseName", () => {
test("returns last tool name from assistant message", () => {
describe('getLastToolUseName', () => {
test('returns last tool name from assistant message', () => {
const msg = makeAssistantMessage([
{ type: "tool_use", name: "Read" },
{ type: "tool_use", name: "Write" },
]);
expect(getLastToolUseName(msg)).toBe("Write");
});
{ type: 'tool_use', name: 'Read' },
{ type: 'tool_use', name: 'Write' },
])
expect(getLastToolUseName(msg)).toBe('Write')
})
test("returns undefined for message without tool_use", () => {
const msg = makeAssistantMessage([{ type: "text", text: "hello" }]);
expect(getLastToolUseName(msg)).toBeUndefined();
});
test('returns undefined for message without tool_use', () => {
const msg = makeAssistantMessage([{ type: 'text', text: 'hello' }])
expect(getLastToolUseName(msg)).toBeUndefined()
})
test("returns the last tool when multiple tool_uses present", () => {
test('returns the last tool when multiple tool_uses present', () => {
const msg = makeAssistantMessage([
{ type: "tool_use", name: "Read" },
{ type: "tool_use", name: "Grep" },
{ type: "tool_use", name: "Edit" },
]);
expect(getLastToolUseName(msg)).toBe("Edit");
});
{ type: 'tool_use', name: 'Read' },
{ type: 'tool_use', name: 'Grep' },
{ type: 'tool_use', name: 'Edit' },
])
expect(getLastToolUseName(msg)).toBe('Edit')
})
test("returns undefined for non-assistant message", () => {
const msg = makeUserMessage("hello");
expect(getLastToolUseName(msg)).toBeUndefined();
});
test('returns undefined for non-assistant message', () => {
const msg = makeUserMessage('hello')
expect(getLastToolUseName(msg)).toBeUndefined()
})
test("handles message with null content", () => {
const msg = { type: "assistant", message: { content: null } } as any;
expect(getLastToolUseName(msg)).toBeUndefined();
});
});
test('handles message with null content', () => {
const msg = { type: 'assistant', message: { content: null } } as any
expect(getLastToolUseName(msg)).toBeUndefined()
})
})

View File

@@ -67,7 +67,9 @@ describe('filterIncompleteToolCalls', () => {
uuid: 'u1',
message: {
role: 'user',
content: [{ type: 'tool_result', tool_use_id: 'done', content: 'ok' }],
content: [
{ type: 'tool_result', tool_use_id: 'done', content: 'ok' },
],
},
},
] as unknown as Message[]
@@ -100,7 +102,9 @@ describe('filterIncompleteToolCalls', () => {
uuid: 'u1',
message: {
role: 'user',
content: [{ type: 'tool_result', tool_use_id: 'done', content: 'ok' }],
content: [
{ type: 'tool_result', tool_use_id: 'done', content: 'ok' },
],
},
},
] as unknown as Message[]

View File

@@ -1,9 +1,6 @@
import { join, normalize, sep } from 'path'
import { getProjectRoot } from 'src/bootstrap/state.js'
import {
buildMemoryPrompt,
ensureMemoryDirExists,
} from 'src/memdir/memdir.js'
import { buildMemoryPrompt, ensureMemoryDirExists } from 'src/memdir/memdir.js'
import { getMemoryBaseDir } from 'src/memdir/paths.js'
import { getCwd } from 'src/utils/cwd.js'
import { findCanonicalGitRoot } from 'src/utils/git.js'

View File

@@ -302,14 +302,16 @@ export function finalizeAgentTool(
// Extract text content from the agent's response. If the final assistant
// message is a pure tool_use block (loop exited mid-turn), fall back to
// the most recent assistant message that has text content.
let content = (lastAssistantMessage.message?.content as ContentItem[] ?? []).filter(
_ => _.type === 'text',
)
let content = (
(lastAssistantMessage.message?.content as ContentItem[]) ?? []
).filter(_ => _.type === 'text')
if (content.length === 0) {
for (let i = agentMessages.length - 1; i >= 0; i--) {
const m = agentMessages[i]!
if (m.type !== 'assistant') continue
const textBlocks = (m.message?.content as ContentItem[] ?? []).filter(_ => _.type === 'text')
const textBlocks = ((m.message?.content as ContentItem[]) ?? []).filter(
_ => _.type === 'text',
)
if (textBlocks.length > 0) {
content = textBlocks
break
@@ -317,7 +319,11 @@ export function finalizeAgentTool(
}
}
const totalTokens = getTokenCountFromUsage(lastAssistantMessage.message?.usage as Parameters<typeof getTokenCountFromUsage>[0])
const totalTokens = getTokenCountFromUsage(
lastAssistantMessage.message?.usage as Parameters<
typeof getTokenCountFromUsage
>[0],
)
const totalToolUseCount = countToolUses(agentMessages)
logEvent('tengu_agent_tool_completed', {
@@ -363,7 +369,9 @@ export function finalizeAgentTool(
*/
export function getLastToolUseName(message: MessageType): string | undefined {
if (message.type !== 'assistant') return undefined
const block = (message.message?.content as ContentItem[] ?? []).findLast(b => b.type === 'tool_use')
const block = ((message.message?.content as ContentItem[]) ?? []).findLast(
b => b.type === 'tool_use',
)
return block?.type === 'tool_use' ? block.name : undefined
}
@@ -492,7 +500,10 @@ export function extractPartialResult(
for (let i = messages.length - 1; i >= 0; i--) {
const m = messages[i]!
if (m.type !== 'assistant') continue
const text = extractTextContent(m.message?.content as ContentItem[] ?? [], '\n')
const text = extractTextContent(
(m.message?.content as ContentItem[]) ?? [],
'\n',
)
if (text) {
return text
}

View File

@@ -1,2 +1,2 @@
// Auto-generated type stub — replace with real implementation
export type BASH_TOOL_NAME = any;
export type BASH_TOOL_NAME = any

View File

@@ -1,2 +1,2 @@
// Auto-generated type stub — replace with real implementation
export type EXIT_PLAN_MODE_TOOL_NAME = any;
export type EXIT_PLAN_MODE_TOOL_NAME = any

View File

@@ -1,2 +1,2 @@
// Auto-generated type stub — replace with real implementation
export type FILE_EDIT_TOOL_NAME = any;
export type FILE_EDIT_TOOL_NAME = any

View File

@@ -1,2 +1,2 @@
// Auto-generated type stub — replace with real implementation
export type FILE_READ_TOOL_NAME = any;
export type FILE_READ_TOOL_NAME = any

View File

@@ -1,2 +1,2 @@
// Auto-generated type stub — replace with real implementation
export type FILE_WRITE_TOOL_NAME = any;
export type FILE_WRITE_TOOL_NAME = any

View File

@@ -1,2 +1,2 @@
// Auto-generated type stub — replace with real implementation
export type GLOB_TOOL_NAME = any;
export type GLOB_TOOL_NAME = any

View File

@@ -1,2 +1,2 @@
// Auto-generated type stub — replace with real implementation
export type GREP_TOOL_NAME = any;
export type GREP_TOOL_NAME = any

View File

@@ -1,2 +1,2 @@
// Auto-generated type stub — replace with real implementation
export type NOTEBOOK_EDIT_TOOL_NAME = any;
export type NOTEBOOK_EDIT_TOOL_NAME = any

View File

@@ -1,2 +1,2 @@
// Auto-generated type stub — replace with real implementation
export type SEND_MESSAGE_TOOL_NAME = any;
export type SEND_MESSAGE_TOOL_NAME = any

View File

@@ -1,2 +1,2 @@
// Auto-generated type stub — replace with real implementation
export type WEB_FETCH_TOOL_NAME = any;
export type WEB_FETCH_TOOL_NAME = any

View File

@@ -1,2 +1,2 @@
// Auto-generated type stub — replace with real implementation
export type WEB_SEARCH_TOOL_NAME = any;
export type WEB_SEARCH_TOOL_NAME = any

View File

@@ -1,2 +1,2 @@
// Auto-generated type stub — replace with real implementation
export type isUsing3PServices = any;
export type isUsing3PServices = any

View File

@@ -1,2 +1,2 @@
// Auto-generated type stub — replace with real implementation
export type hasEmbeddedSearchTools = any;
export type hasEmbeddedSearchTools = any

View File

@@ -1,2 +1,2 @@
// Auto-generated type stub — replace with real implementation
export type getSettings_DEPRECATED = any;
export type getSettings_DEPRECATED = any

View File

@@ -115,14 +115,20 @@ export function buildForkedMessages(
uuid: randomUUID(),
message: {
...assistantMessage.message,
content: [...(Array.isArray(assistantMessage.message.content) ? assistantMessage.message.content : [])],
content: [
...(Array.isArray(assistantMessage.message.content)
? assistantMessage.message.content
: []),
],
},
}
// Collect all tool_use blocks from the assistant message
const toolUseBlocks = (Array.isArray(assistantMessage.message.content) ? assistantMessage.message.content : []).filter(
(block): block is BetaToolUseBlock => block.type === 'tool_use',
)
const toolUseBlocks = (
Array.isArray(assistantMessage.message.content)
? assistantMessage.message.content
: []
).filter((block): block is BetaToolUseBlock => block.type === 'tool_use')
if (toolUseBlocks.length === 0) {
logForDebugging(

View File

@@ -1,4 +1,4 @@
// Auto-generated type stub — replace with real implementation
export type buildTool = any;
export type ToolDef = any;
export type toolMatchesName = any;
export type buildTool = any
export type ToolDef = any
export type toolMatchesName = any

View File

@@ -1,2 +1,2 @@
// Auto-generated type stub — replace with real implementation
export type ConfigurableShortcutHint = any;
export type ConfigurableShortcutHint = any

View File

@@ -1,3 +1,3 @@
// Auto-generated type stub — replace with real implementation
export type CtrlOToExpand = any;
export type SubAgentProvider = any;
export type CtrlOToExpand = any
export type SubAgentProvider = any

View File

@@ -1,2 +1,2 @@
// Auto-generated type stub — replace with real implementation
export type Byline = any;
export type Byline = any

View File

@@ -1,2 +1,2 @@
// Auto-generated type stub — replace with real implementation
export type KeyboardShortcutHint = any;
export type KeyboardShortcutHint = any

View File

@@ -1,3 +1,3 @@
// Auto-generated type stub — replace with real implementation
export type Message = any;
export type NormalizedUserMessage = any;
export type Message = any
export type NormalizedUserMessage = any

View File

@@ -1,2 +1,2 @@
// Auto-generated type stub — replace with real implementation
export type logForDebugging = any;
export type logForDebugging = any

View File

@@ -1,2 +1,2 @@
// Auto-generated type stub — replace with real implementation
export type getQuerySourceForAgent = any;
export type getQuerySourceForAgent = any

View File

@@ -1,2 +1,2 @@
// Auto-generated type stub — replace with real implementation
export type SettingSource = any;
export type SettingSource = any