import { normalizeToolArgumentsForModel } from "./copilot-gemini-tool-arguments.js";
import { ExtensionRunner, wrapRegisteredTools } from "./extensions/index.js";
import { createSyntheticSourceInfo } from "./source-info.js";
import { createAllToolDefinitions, defaultToolNames } from "./tools/index.js";
import { createToolDefinitionFromAgentTool } from "./tools/tool-definition-wrapper.js";
import { createSessionAsyncDeliveryHandler } from "./async/session-manager.js";
export function _refreshToolRegistry(options) {
    const previousRegistryNames = new Set(this._toolRegistry.keys());
    const previousActiveToolNames = this.getActiveToolNames();
    const allowedToolNames = this._allowedToolNames;
    const excludedToolNames = this._excludedToolNames;
    const isExposedTool = (name) => {
        if (allowedToolNames && !allowedToolNames.has(name)) {
            return false;
        }
        if (excludedToolNames?.has(name)) {
            return false;
        }
        return true;
    };
    const registeredTools = this._extensionRunner.getAllRegisteredTools();
    const allCustomTools = [
        ...registeredTools,
        ...this._customTools.map((definition) => ({
            definition,
            sourceInfo: createSyntheticSourceInfo(`<sdk:${definition.name}>`, { source: "sdk" }),
        })),
    ].filter((tool) => isExposedTool(tool.definition.name));
    const definitionRegistry = new Map(Array.from(this._baseToolDefinitions.entries())
        .filter(([name]) => isExposedTool(name))
        .map(([name, definition]) => [
        name,
        {
            definition,
            sourceInfo: createSyntheticSourceInfo(`<builtin:${name}>`, { source: "builtin" }),
        },
    ]));
    for (const tool of allCustomTools) {
        definitionRegistry.set(tool.definition.name, {
            definition: tool.definition,
            sourceInfo: tool.sourceInfo,
        });
    }
    this._toolDefinitions = definitionRegistry;
    this._toolPromptSnippets = new Map(Array.from(definitionRegistry.values())
        .map(({ definition }) => {
        const snippet = this._normalizePromptSnippet(definition.promptSnippet);
        return snippet ? [definition.name, snippet] : undefined;
    })
        .filter((entry) => entry !== undefined));
    this._toolPromptGuidelines = new Map(Array.from(definitionRegistry.values())
        .map(({ definition }) => {
        const guidelines = this._normalizePromptGuidelines(definition.promptGuidelines);
        return guidelines.length > 0 ? [definition.name, guidelines] : undefined;
    })
        .filter((entry) => entry !== undefined));
    const runner = this._extensionRunner;
    const wrappedExtensionTools = wrapRegisteredTools(allCustomTools, runner);
    const wrappedBuiltInTools = wrapRegisteredTools(Array.from(this._baseToolDefinitions.values())
        .filter((definition) => isExposedTool(definition.name))
        .map((definition) => ({
        definition,
        sourceInfo: createSyntheticSourceInfo(`<builtin:${definition.name}>`, { source: "builtin" }),
    })), runner);
    const toolRegistry = new Map(wrappedBuiltInTools.map((tool) => [tool.name, tool]));
    for (const tool of wrappedExtensionTools) {
        toolRegistry.set(tool.name, tool);
    }
    // GitHub Copilot Gemini serializes array/object tool-call arguments as
    // flattened `name[index]` keys (confirmed on the raw CAPI wire). Reconstruct
    // them into proper arrays/objects before per-tool preparation and schema
    // validation, so tool calls (notably structured_output) don't fail and loop.
    // Gated to Copilot Gemini at call time via this.model; a no-op otherwise.
    // `prepareArguments` is a plain function field (no `this` binding), and the
    // `{ ...tool }` spread assumes AgentTools are plain objects — matching the
    // existing tool-definition-wrapper pattern; a class-instance tool would lose
    // prototype members here.
    this._toolRegistry = new Map(Array.from(toolRegistry, ([name, tool]) => {
        const basePrepareArguments = tool.prepareArguments;
        const prepareArguments = (args) => {
            const normalized = normalizeToolArgumentsForModel(args, this.model, tool.parameters);
            return basePrepareArguments ? basePrepareArguments(normalized) : normalized;
        };
        return [name, { ...tool, prepareArguments }];
    }));
    const nextActiveToolNames = (options?.activeToolNames ? [...options.activeToolNames] : [...previousActiveToolNames]).filter((name) => isExposedTool(name));
    if (allowedToolNames) {
        for (const toolName of this._toolRegistry.keys()) {
            if (allowedToolNames.has(toolName)) {
                nextActiveToolNames.push(toolName);
            }
        }
    }
    else if (options?.includeAllExtensionTools) {
        for (const tool of wrappedExtensionTools) {
            nextActiveToolNames.push(tool.name);
        }
    }
    else if (!options?.activeToolNames) {
        for (const toolName of this._toolRegistry.keys()) {
            if (!previousRegistryNames.has(toolName)) {
                nextActiveToolNames.push(toolName);
            }
        }
    }
    this.setActiveToolsByName([...new Set(nextActiveToolNames)]);
}
export function _buildRuntime(options) {
    const autoResizeImages = this.settingsManager.getImageAutoResize();
    const shellCommandPrefix = this.settingsManager.getShellCommandPrefix();
    const shellPath = this.settingsManager.getShellPath();
    const isAllowedBuiltinTool = (name) => {
        if (this._allowedToolNames && !this._allowedToolNames.has(name))
            return false;
        if (this._excludedToolNames?.has(name))
            return false;
        return true;
    };
    const activeBuiltinTools = (options.activeToolNames ?? [...defaultToolNames]).filter(isAllowedBuiltinTool);
    const baseToolDefinitions = this._baseToolsOverride
        ? Object.fromEntries(Object.entries(this._baseToolsOverride).map(([name, tool]) => [
            name,
            createToolDefinitionFromAgentTool(tool),
        ]))
        : createAllToolDefinitions(this._cwd, {
            read: { autoResizeImages },
            bash: {
                commandPrefix: shellCommandPrefix,
                shellPath,
                interceptorEnabled: () => this.settingsManager.getBashInterceptorEnabled(),
                availableTools: activeBuiltinTools,
                asyncJobManager: this._asyncJobManager,
                asyncJobDeliveryHandler: createSessionAsyncDeliveryHandler(this, this._asyncJobManager, this._asyncJobManagerSessionId),
                asyncJobSessionId: this._asyncJobManagerSessionId,
                interceptor: async (context) => {
                    const result = await this._extensionRunner.emitUserBash({
                        type: "user_bash",
                        command: context.command,
                        excludeFromContext: false,
                        cwd: context.cwd,
                    });
                    return result;
                },
            },
            search: {
                contextBefore: this.settingsManager.getSearchContextBefore(),
                contextAfter: this.settingsManager.getSearchContextAfter(),
            },
        });
    this._baseToolDefinitions = new Map(Object.entries(baseToolDefinitions).map(([name, tool]) => [name, tool]));
    const extensionsResult = this._resourceLoader.getExtensions();
    if (options.flagValues) {
        for (const [name, value] of options.flagValues) {
            extensionsResult.runtime.flagValues.set(name, value);
        }
    }
    this._extensionRunner = new ExtensionRunner(extensionsResult.extensions, extensionsResult.runtime, this._cwd, this.sessionManager, this._modelRegistry, this._orchestrationContext);
    if (this._extensionRunnerRef) {
        this._extensionRunnerRef.current = this._extensionRunner;
    }
    this._bindExtensionCore(this._extensionRunner);
    this._applyExtensionBindings(this._extensionRunner);
    const defaultActiveToolNames = this._baseToolsOverride
        ? Object.keys(this._baseToolsOverride)
        : [...defaultToolNames];
    const baseActiveToolNames = options.activeToolNames ?? defaultActiveToolNames;
    this._refreshToolRegistry({
        activeToolNames: baseActiveToolNames,
        includeAllExtensionTools: options.includeAllExtensionTools,
    });
}
export const agentSessionToolRegistryMethods = {
    _refreshToolRegistry,
    _buildRuntime,
};
//# sourceMappingURL=agent-session-tool-registry.js.map