feat(web-search): wire hosted plugin composition

This commit is contained in:
2026-09-01 02:39:16 +08:00
parent 68cb2e73be
commit 60e6a8eeb3
9 changed files with 361 additions and 6 deletions

View File

@@ -880,4 +880,58 @@ describe('CodingConversationTimeline', () => {
expect(document.querySelector('[data-node-id="tool-changed-file-feature"]')).toBeNull();
expect(screen.queryByText(/回滚|revert/i)).not.toBeInTheDocument();
});
it('renders receipt-unavailable as a generic billing state without parsing Web Search payloads', async () => {
const { codingConversationStore } = await import('@/stores/coding-conversations');
const { CodingConversationTimeline } = await import(
'@/pages/Chat/CodingConversationTimeline'
);
const base = createProductSnapshot('conversation-web-search-billing', 1);
const snapshot = {
...base,
nodes: [{
kind: 'tool' as const,
id: 'tool-web-search-billing',
toolCallId: 'call-web-search-billing',
toolName: 'makelore_web_search',
title: '搜索网络',
inputText: '{"query":"Makelore"}',
status: 'error' as const,
output: [],
details: {
schema: 'makelore-capability.v1' as const,
plugin_id: 'makelore.web-search',
plugin_version: '1.0.0',
capability_id: 'web-search.search',
operation: 'search',
request_id: 'pi:run-a:resource-a',
success: false,
status: 503,
code: 'plugin_receipt_unavailable',
error: 'Web Search billing status could not be synchronized',
retryable: false,
billing: { mode: 'platform_metered' as const, status: 'receipt_unavailable' as const },
payload_schema: 'web-search.v1',
data: null,
},
}],
};
codingConversationStore.getState().applySnapshotEvent({
type: 'snapshot',
conversationId: 'conversation-web-search-billing',
workerGeneration: 1,
seq: snapshot.cursor.seq,
snapshot,
});
render(<CodingConversationTimeline conversationId="conversation-web-search-billing" />);
const process = screen.getByTestId('coding-process-group');
fireEvent.click(process.querySelector('summary')!);
const tool = document.querySelector('[data-node-id="tool-web-search-billing"]')!;
fireEvent.click(tool.querySelector('summary')!);
const details = within(tool as HTMLElement).getByTestId('tool-details');
expect(within(details).getByText('收费状态未同步,请勿重复发起')).toBeVisible();
expect(within(details).queryByText(/来源|搜索结果|Makelore\.com/u)).not.toBeInTheDocument();
});
});