"use strict";
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation and GitHub. All rights reserved.
 *--------------------------------------------------------------------------------------------*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.contentType = exports.PromptRenderer = exports.MetadataMap = exports.PromptElement = exports.JSONTree = void 0;
exports.renderPrompt = renderPrompt;
exports.renderElementJSON = renderElementJSON;
const mode_1 = require("./output/mode");
const promptRenderer_1 = require("./promptRenderer");
const tokenizer_1 = require("./tokenizer/tokenizer");
__exportStar(require("./htmlTracer"), exports);
exports.JSONTree = require("./jsonTypes");
__exportStar(require("./output/mode"), exports);
__exportStar(require("./promptElements"), exports);
__exportStar(require("./results"), exports);
__exportStar(require("./tracer"), exports);
__exportStar(require("./tsx-globals"), exports);
__exportStar(require("./types"), exports);
var promptElement_1 = require("./promptElement");
Object.defineProperty(exports, "PromptElement", { enumerable: true, get: function () { return promptElement_1.PromptElement; } });
var promptRenderer_2 = require("./promptRenderer");
Object.defineProperty(exports, "MetadataMap", { enumerable: true, get: function () { return promptRenderer_2.MetadataMap; } });
Object.defineProperty(exports, "PromptRenderer", { enumerable: true, get: function () { return promptRenderer_2.PromptRenderer; } });
async function renderPrompt(ctor, props, endpoint, tokenizerMetadata, progress, token, mode = mode_1.OutputMode.VSCode) {
    let tokenizer = 'countTokens' in tokenizerMetadata
        ? new tokenizer_1.VSCodeTokenizer((text, token) => tokenizerMetadata.countTokens(text, token), mode)
        : tokenizerMetadata;
    const renderer = new promptRenderer_1.PromptRenderer(endpoint, ctor, props, tokenizer);
    const renderResult = await renderer.render(progress, token);
    const usedContext = renderer.getUsedContext();
    return { ...renderResult, usedContext };
}
/**
 * Content type of the return value from {@link renderElementJSON}.
 * When responding to a tool invocation, the tool should set this as the
 * content type in the returned data:
 *
 * ```ts
 * import { contentType } from '@vscode/prompt-tsx';
 *
 * async function doToolInvocation(): vscode.LanguageModelToolResult {
 *   return {
 *     [contentType]: await renderElementJSON(...),
 *     toString: () => '...',
 *   };
 * }
 * ```
 */
exports.contentType = 'application/vnd.codechat.prompt+json.1';
/**
 * Renders a prompt element to a serializable state. This type be returned in
 * tools results and reused in subsequent render calls via the `<Tool />`
 * element.
 *
 * In this mode, message chunks are not pruned from the tree; budget
 * information is used only to hint to the elements how many tokens they should
 * consume when rendered.
 *
 * @template P - The type of the prompt element props.
 * @param ctor - The constructor of the prompt element.
 * @param props - The props for the prompt element.
 * @param budgetInformation - Information about the token budget.
 * `vscode.LanguageModelToolInvocationOptions` is assignable to this object.
 * @param token - The cancellation token for cancelling the operation.
 * @returns A promise that resolves to an object containing the serialized data.
 */
function renderElementJSON(ctor, props, budgetInformation, token) {
    const renderer = new promptRenderer_1.PromptRenderer({ modelMaxPromptTokens: budgetInformation?.tokenBudget ?? Number.MAX_SAFE_INTEGER }, ctor, props, 
    // note: if tokenBudget is given, countTokens is also give and vise-versa.
    // `1` is used only as a dummy fallback to avoid errors if no/unlimited budget is provided.
    {
        mode: mode_1.OutputMode.Raw,
        countMessageTokens(message) {
            throw new Error('Tools may only return text, not messages.'); // for now...
        },
        tokenLength(part, token) {
            if (part.type === mode_1.Raw.ChatCompletionContentPartKind.Text) {
                return Promise.resolve(budgetInformation?.countTokens(part.text, token) ?? Promise.resolve(1));
            }
            return Promise.resolve(1);
        },
    });
    return renderer.renderElementJSON(token);
}
