/**
 * COM execute_code provider — local-agent ToolDefinition wrapper.
 *
 * Delegates all execution to `executeComLocally()` from com-executor.ts.
 * This file owns the ToolDefinition shape (name, schema, description, prompt guidelines).
 * The actual XLL communication, result parsing, and approval flow live in the executor.
 */
import { Type } from '@sinclair/typebox';
import { EXECUTE_CODE } from '../../../../tool-names.js';
import { truncateOutput } from '../../../../utils/truncate.js';
import { buildLocalExcelHttpUrl, parseExcelHttpPort } from '../../../xll/http-url.js';
import { executeComLocally } from './executor.js';
const TOOL_NAME = EXECUTE_CODE;
const NO_OUTPUT_FALLBACK = '(no output)';
function buildToolContent(text, approvalSummaries) {
    return [
        ...(approvalSummaries ?? []).map((summary) => ({ type: 'text', text: summary })),
        { type: 'text', text }
    ];
}
const TOOL_DESCRIPTION = `\
Execute Python code in Excel via the COM API. This tool is ONLY for interacting with Excel workbooks.
The code runs in an isolated namespace with access to the Excel COM API via \`app\` (an Excel.Application COM object, same API as VBA).
Execution is sandboxed and state does not persist. You MUST re-initialize needed objects (e.g. wb = Workbook(...)) at the start of every call
Stdout/stderr are captured. Use print() liberally to verify intermediate results — silent failures are common in COM

**Python sandbox contract** 
- Common helpers are pre-injected: \`app\`, \`Workbook\`, \`Worksheet\`, and spreadsheet utility helpers. Standard Python builtins (loops, math, string ops, print, try/except) work normally.
- Imports are generally allowed, but dangerous system/runtime modules are blocked. Do NOT try to import or use modules for process control, network access, native loading, package installation, or other system scripting in this channel.
- This channel is not for package installation or general system scripting. Do NOT try to \`pip install\`, spawn processes, make network calls, load native libraries, or mutate arbitrary files here. Use the bash tool instead.

**IMPORTANT**: Your code should be simple and efficient. Minimize code duplication.
- Be mindful of code length, errors accumulate quickly if you write too much code.
- Minimize comments. Print instead. Prints should be concise and to the point.
- For read operations, prefer reading large ranges to grab richer context instead of iteratively reading over small ranges. You can read a maximum of 3000 cells at a time.

Working with addresses:
- Use Excel-style addresses (e.g., "A1", "B5") instead of row and column indices
- Use sheet name and the cell address, e.g. "Sheet1!A1" or "Sheet2!B2:C4" to refer to cells and ranges across sheets
- To convert between letters and indices, use helper functions. Methods that takes an Excel-style range or address can only take a single range or address, not multiples (e.g., avoid "A1:B2,C3:D4").
`;
const schema = Type.Object({
    description: Type.String({
        description: 'Short description of what the code does for non-technical users. You MUST reference ranges for any read / write operation. Use this notation for reads and writes, including the brackets: <Workbook:Sheet!Range>. Omit range if operating on the whole sheet or workbook.'
    }),
    code: Type.String({
        description: 'Python code to execute in Excel. `app` (Excel.Application) is already available — do NOT import xl_app. Use print() to return values.'
    })
});
export function createExcelExecTool(httpPort, approval, observability) {
    const excelHttpUrl = httpPort === undefined ? undefined : buildLocalExcelHttpUrl(parseExcelHttpPort(httpPort));
    const assertSpreadsheetPolicy = (ctx) => {
        const spreadsheetPolicy = ctx?.permissionPolicy?.spreadsheet;
        if (!spreadsheetPolicy || spreadsheetPolicy.mutationBehavior !== 'deny') {
            return;
        }
        throw new Error('Spreadsheet execution is denied by the current permission policy.');
    };
    return {
        name: TOOL_NAME,
        label: 'Excel exec',
        isReadOnly: false,
        description: TOOL_DESCRIPTION,
        parameters: schema,
        async execute(_toolCallId, { code, description: _description }, signal, _onUpdate, ctx) {
            assertSpreadsheetPolicy(ctx);
            const { result, outcome, approvalSummaries } = await executeComLocally(excelHttpUrl, code, {
                approval,
                observability,
                ctx: ctx,
                signal: signal ?? undefined
            });
            if (outcome === 'revert-failed') {
                return {
                    content: [
                        {
                            type: 'text',
                            text: 'Revert failed — changes are still applied in Excel. You may need to undo manually (Ctrl+Z).'
                        }
                    ],
                    details: result
                };
            }
            if (outcome === 'reverted') {
                return {
                    content: [{ type: 'text', text: 'Changes reverted by user.' }],
                    details: result
                };
            }
            if (outcome === 'rejected') {
                return {
                    content: [{ type: 'text', text: 'Excel operation rejected by user.' }],
                    details: result
                };
            }
            if (outcome === 'failed' || !result.ok) {
                const error = result.error ?? 'Unknown error from Excel';
                const output = result.output;
                const text = output ? `${error}\n\nPartial output before error:\n${output}` : error;
                return {
                    content: buildToolContent(text, approvalSummaries),
                    isError: true,
                    details: result
                };
            }
            return {
                content: buildToolContent(truncateOutput(result.output ?? NO_OUTPUT_FALLBACK), approvalSummaries),
                details: result
            };
        }
    };
}
//# sourceMappingURL=tool.js.map