Spaces:
Paused
Paused
| /** | |
| * Tool calling 开关:开启后注入 tool schema(单轮);可选「多轮 & mock」做回灌。 | |
| * 「Config tools」打开 toolConfigDialog。 | |
| */ | |
| import { tr } from '../../shared/lang/i18n-lite'; | |
| import { lsReadBool, lsWriteBool } from '../../shared/storage/localStorageHelpers'; | |
| import { showEditableToolConfigDialog } from './toolConfigDialog'; | |
| import { | |
| cloneToolConfig, | |
| EMPTY_TOOL_CONFIG, | |
| readToolConfigFromLs, | |
| writeToolConfigToLs, | |
| type ToolConfig, | |
| } from './toolConfig'; | |
| const MOUNT_ID = 'tool_calling_options_mount'; | |
| export type ToolCallingOptionsRowOptions = { | |
| enableToolCallingStorageKey: string; | |
| multiTurnStorageKey: string; | |
| toolConfigStorageKey: string; | |
| onStateChange: () => void; | |
| }; | |
| /** 缓存 draft 还原;`multiTurnMockEnabled` 为 Chat draft 字段别名。 */ | |
| export type ToolCallingDraftRestore = { | |
| toolCallingEnabled?: boolean; | |
| multiTurnEnabled?: boolean; | |
| multiTurnMockEnabled?: boolean; | |
| toolConfig?: ToolConfig; | |
| }; | |
| export type ToolCallingOptionsRowApi = { | |
| isToolCallingEnabled: () => boolean; | |
| isMultiTurnEnabled: () => boolean; | |
| getCurrentToolConfig: () => ToolConfig; | |
| isToolCallingConfigReady: () => boolean; | |
| restoreFromDraft: (draft: ToolCallingDraftRestore) => void; | |
| syncSubUi: () => void; | |
| }; | |
| type ToolCallingRowElements = { | |
| enableInput: HTMLInputElement; | |
| multiTurnInput: HTMLInputElement; | |
| multiTurnRow: HTMLLabelElement; | |
| configBtn: HTMLButtonElement; | |
| }; | |
| function mountToolCallingOptionsRow(mount: HTMLElement): ToolCallingRowElements { | |
| const row = document.createElement('div'); | |
| row.className = 'options-row chat-enable-tool-calling-row'; | |
| const group = document.createElement('span'); | |
| group.className = 'options-group'; | |
| const enableLabel = document.createElement('label'); | |
| enableLabel.className = 'options-label'; | |
| const enableInput = document.createElement('input'); | |
| enableInput.type = 'checkbox'; | |
| enableInput.id = 'tool_calling_enable'; | |
| enableLabel.htmlFor = enableInput.id; | |
| const enableText = document.createElement('span'); | |
| enableText.textContent = tr('Tool use'); | |
| enableLabel.append(enableInput, enableText); | |
| const multiTurnRow = document.createElement('label'); | |
| multiTurnRow.className = 'options-label'; | |
| multiTurnRow.id = 'tool_calling_multi_turn_row'; | |
| multiTurnRow.hidden = true; | |
| const multiTurnInput = document.createElement('input'); | |
| multiTurnInput.type = 'checkbox'; | |
| multiTurnInput.id = 'tool_calling_multi_turn'; | |
| multiTurnInput.checked = true; | |
| multiTurnRow.htmlFor = multiTurnInput.id; | |
| const multiTurnText = document.createElement('span'); | |
| multiTurnText.textContent = tr('Multi-turn'); | |
| multiTurnRow.append(multiTurnInput, multiTurnText); | |
| const configBtn = document.createElement('button'); | |
| configBtn.type = 'button'; | |
| configBtn.id = 'tool_calling_config_btn'; | |
| configBtn.className = 'text-action-btn'; | |
| configBtn.hidden = true; | |
| configBtn.textContent = tr('Config tools'); | |
| group.append(enableLabel, multiTurnRow, configBtn); | |
| row.append(group); | |
| mount.replaceChildren(row); | |
| return { enableInput, multiTurnInput, multiTurnRow, configBtn }; | |
| } | |
| export function createToolCallingOptionsRow( | |
| options: ToolCallingOptionsRowOptions | |
| ): ToolCallingOptionsRowApi { | |
| const mount = document.getElementById(MOUNT_ID); | |
| if (!mount) { | |
| throw new Error(`createToolCallingOptionsRow: missing #${MOUNT_ID}`); | |
| } | |
| const { enableInput, multiTurnInput, multiTurnRow, configBtn } = | |
| mountToolCallingOptionsRow(mount); | |
| let currentToolConfig: ToolConfig = readToolConfigFromLs(options.toolConfigStorageKey); | |
| const isToolCallingEnabled = (): boolean => enableInput.checked; | |
| const isMultiTurnEnabled = (): boolean => multiTurnInput.checked; | |
| const getCurrentToolConfig = (): ToolConfig => currentToolConfig; | |
| const isToolCallingConfigReady = (): boolean => | |
| !isToolCallingEnabled() || currentToolConfig.entries.length > 0; | |
| const persistToolConfig = (config: ToolConfig): void => { | |
| currentToolConfig = cloneToolConfig(config); | |
| writeToolConfigToLs(options.toolConfigStorageKey, currentToolConfig); | |
| options.onStateChange(); | |
| }; | |
| const syncSubUi = (): void => { | |
| const on = isToolCallingEnabled(); | |
| configBtn.hidden = !on; | |
| multiTurnRow.hidden = !on; | |
| }; | |
| const restoreFromDraft = (draft: ToolCallingDraftRestore): void => { | |
| enableInput.checked = draft.toolCallingEnabled ?? false; | |
| lsWriteBool(options.enableToolCallingStorageKey, enableInput.checked); | |
| const multiTurn = draft.multiTurnEnabled ?? draft.multiTurnMockEnabled ?? true; | |
| multiTurnInput.checked = multiTurn; | |
| lsWriteBool(options.multiTurnStorageKey, multiTurnInput.checked); | |
| const next = draft.toolConfig | |
| ? cloneToolConfig(draft.toolConfig) | |
| : cloneToolConfig(EMPTY_TOOL_CONFIG); | |
| currentToolConfig = next; | |
| writeToolConfigToLs(options.toolConfigStorageKey, next); | |
| syncSubUi(); | |
| options.onStateChange(); | |
| }; | |
| enableInput.checked = lsReadBool(options.enableToolCallingStorageKey, false); | |
| enableInput.addEventListener('change', () => { | |
| lsWriteBool(options.enableToolCallingStorageKey, enableInput.checked); | |
| syncSubUi(); | |
| options.onStateChange(); | |
| }); | |
| multiTurnInput.checked = lsReadBool(options.multiTurnStorageKey, true); | |
| multiTurnInput.addEventListener('change', () => { | |
| lsWriteBool(options.multiTurnStorageKey, multiTurnInput.checked); | |
| options.onStateChange(); | |
| }); | |
| configBtn.addEventListener('click', () => { | |
| showEditableToolConfigDialog(getCurrentToolConfig(), persistToolConfig); | |
| }); | |
| syncSubUi(); | |
| return { | |
| isToolCallingEnabled, | |
| isMultiTurnEnabled, | |
| getCurrentToolConfig, | |
| isToolCallingConfigReady, | |
| restoreFromDraft, | |
| syncSubUi, | |
| }; | |
| } | |