const require_constants = require("../../constants.cjs");
let _langchain_core_singletons = require("@langchain/core/singletons");
let _langchain_core_callbacks_manager = require("@langchain/core/callbacks/manager");
//#region src/pregel/utils/config.ts
const COPIABLE_KEYS = [
	"tags",
	"metadata",
	"callbacks",
	"configurable"
];
const CONFIG_KEYS = [
	"tags",
	"metadata",
	"callbacks",
	"runName",
	"maxConcurrency",
	"recursionLimit",
	"configurable",
	"runId",
	"outputKeys",
	"streamMode",
	"store",
	"writer",
	"interrupt",
	"context",
	"interruptBefore",
	"interruptAfter",
	"checkpointDuring",
	"durability",
	"signal",
	"heartbeat",
	"executionInfo",
	"serverInfo",
	"control"
];
const DEFAULT_RECURSION_LIMIT = 25;
const PROPAGATE_TO_METADATA = new Set([
	"thread_id",
	"checkpoint_id",
	"checkpoint_ns",
	"task_id",
	"run_id",
	"assistant_id",
	"graph_id"
]);
function propagateConfigurableToMetadata(configurable, metadata) {
	if (!configurable) return metadata;
	const result = metadata ?? {};
	for (const key of PROPAGATE_TO_METADATA) {
		if (key in result) continue;
		const value = configurable[key];
		if (value !== void 0) result[key] = value;
	}
	return result;
}
/**
* Drop langgraph's internal `seq:step*` bookkeeping tags.
*
* `seq:step:N` tags are added internally to mark sequence steps; everything
* else (user-supplied tags and any other framework tags) is kept. Returns the
* surviving tags, or `undefined` if none remain. Shared by the stream handlers
* (e.g. {@link mapDebugTasks}) so the same tag set is surfaced consistently.
*/
function filterToUserTags(tags) {
	if (tags == null || tags.length === 0) return void 0;
	const filtered = tags.filter((tag) => !tag.startsWith("seq:step"));
	return filtered.length > 0 ? filtered : void 0;
}
/**
* Merge two `callbacks` values across configs.
*
* A `callbacks` value may be `undefined`, an array of handlers, or a
* {@link CallbackManager}, so merging two of them has six cases. This
* mirrors the callbacks branch of langchain-core's `mergeConfigs` and
* langgraph's `_merge_callbacks`, so a handler bound via
* `.withConfig({ callbacks: [...] })` is preserved when a later config
* (e.g. `streamEvents` injecting its own internal handler) is merged on
* top instead of overwriting it.
*/
function mergeCallbacks(base, provided) {
	if (provided === void 0) return base;
	if (base === void 0) return Array.isArray(provided) ? [...provided] : provided.copy();
	if (Array.isArray(provided)) {
		if (Array.isArray(base)) return base.concat(provided);
		const manager = base.copy();
		for (const callback of provided) manager.addHandler((0, _langchain_core_callbacks_manager.ensureHandler)(callback), true);
		return manager;
	}
	if (Array.isArray(base)) {
		const manager = provided.copy();
		for (const callback of base) manager.addHandler((0, _langchain_core_callbacks_manager.ensureHandler)(callback), true);
		return manager;
	}
	return new _langchain_core_callbacks_manager.CallbackManager(provided._parentRunId, {
		handlers: base.handlers.concat(provided.handlers),
		inheritableHandlers: base.inheritableHandlers.concat(provided.inheritableHandlers),
		tags: Array.from(new Set(base.tags.concat(provided.tags))),
		inheritableTags: Array.from(new Set(base.inheritableTags.concat(provided.inheritableTags))),
		metadata: {
			...base.metadata,
			...provided.metadata
		},
		inheritableMetadata: {
			...base.inheritableMetadata,
			...provided.inheritableMetadata
		}
	});
}
/**
* True when the caller is starting a fresh top-level run (invoke-time
* `thread_id`, no active nesting keys). In that case the ambient `configurable`
* from `AsyncLocalStorage` cannot be trusted per-key — it may belong to another
* concurrent invocation on a shared singleton agent (scratchpad/task-input as
* well as arbitrary user keys like `tenant_id`/`user_id`). The whole ambient
* `configurable` is therefore ignored; any value the caller actually wants for
* this run arrives through the explicit (bound + invoke-time) configs instead.
*
* Only the last caller-supplied config is treated as invoke-time options.
* Earlier entries are graph-bound defaults from `.withConfig()` / compile and
* must not count — a child graph bound with `thread_id` and invoked from a
* parent task without a fresh config still needs ambient nesting keys from ALS.
*/
function isRootLevelExplicitInvoke(configs) {
	let invokeConfig;
	for (let i = configs.length - 1; i >= 0; i -= 1) if (configs[i] !== void 0) {
		invokeConfig = configs[i];
		break;
	}
	const hasInvokeTimeThreadId = invokeConfig?.configurable?.thread_id !== void 0;
	const hasExplicitNesting = configs.some((c) => c?.configurable?.[require_constants.CONFIG_KEY_READ] !== void 0);
	const hasAmbientNesting = (_langchain_core_singletons.AsyncLocalStorageProviderSingleton.getRunnableConfig()?.configurable)?.[require_constants.CONFIG_KEY_READ] !== void 0;
	return hasInvokeTimeThreadId && !hasExplicitNesting && !hasAmbientNesting;
}
function ensureLangGraphConfig(...configs) {
	const empty = {
		tags: [],
		metadata: {},
		callbacks: void 0,
		recursionLimit: DEFAULT_RECURSION_LIMIT,
		configurable: {}
	};
	const skipImplicitConfigurable = isRootLevelExplicitInvoke(configs);
	const implicitConfig = _langchain_core_singletons.AsyncLocalStorageProviderSingleton.getRunnableConfig();
	if (implicitConfig !== void 0) {
		for (const [k, v] of Object.entries(implicitConfig)) if (v !== void 0) {
			if (k === "configurable" && skipImplicitConfigurable) continue;
			if (COPIABLE_KEYS.includes(k)) {
				let copiedValue;
				if (Array.isArray(v)) copiedValue = [...v];
				else if (typeof v === "object") if (k === "callbacks" && "copy" in v && typeof v.copy === "function") copiedValue = v.copy();
				else copiedValue = { ...v };
				else copiedValue = v;
				empty[k] = copiedValue;
			} else empty[k] = v;
		}
	}
	for (const config of configs) {
		if (config === void 0) continue;
		for (const [k, v] of Object.entries(config)) {
			if (v === void 0 || !CONFIG_KEYS.includes(k)) continue;
			if (k === "configurable") empty.configurable = {
				...empty.configurable,
				...v
			};
			else if (k === "metadata") empty.metadata = {
				...empty.metadata,
				...v
			};
			else if (k === "tags") empty.tags = [...empty.tags ?? [], ...v];
			else if (k === "callbacks") empty.callbacks = mergeCallbacks(empty.callbacks, v);
			else empty[k] = v;
		}
	}
	empty.metadata = propagateConfigurableToMetadata(empty.configurable, empty.metadata) ?? {};
	return empty;
}
/**
* A helper utility function that returns the {@link BaseStore} that was set when the graph was initialized
*
* @returns a reference to the {@link BaseStore} that was set when the graph was initialized
*/
function getStore(config) {
	const runConfig = config ?? _langchain_core_singletons.AsyncLocalStorageProviderSingleton.getRunnableConfig();
	if (runConfig === void 0) throw new Error(["Config not retrievable. This is likely because you are running in an environment without support for AsyncLocalStorage.", "If you're running `getStore` in such environment, pass the `config` from the node function directly."].join("\n"));
	return runConfig?.store;
}
/**
* A helper utility function that returns the {@link LangGraphRunnableConfig#writer} if "custom" stream mode is enabled, otherwise undefined.
*
* @returns a reference to the {@link LangGraphRunnableConfig#writer} if "custom" stream mode is enabled, otherwise undefined
*/
function getWriter(config) {
	const runConfig = config ?? _langchain_core_singletons.AsyncLocalStorageProviderSingleton.getRunnableConfig();
	if (runConfig === void 0) throw new Error(["Config not retrievable. This is likely because you are running in an environment without support for AsyncLocalStorage.", "If you're running `getWriter` in such environment, pass the `config` from the node function directly."].join("\n"));
	return runConfig?.writer || runConfig?.configurable?.writer;
}
/**
* A helper utility function that returns the {@link LangGraphRunnableConfig} that was set when the graph was initialized.
*
* Note: This only works when running in an environment that supports node:async_hooks and AsyncLocalStorage. If you're running this in a
* web environment, access the LangGraphRunnableConfig from the node function directly.
*
* @returns the {@link LangGraphRunnableConfig} that was set when the graph was initialized
*/
function getConfig() {
	return _langchain_core_singletons.AsyncLocalStorageProviderSingleton.getRunnableConfig();
}
/**
* A helper utility function that returns the input for the currently executing
* task.
*
* Note: When called without arguments, this relies on `node:async_hooks` /
* `AsyncLocalStorage`, which is available in many JavaScript environments
* (Node.js, Deno, Cloudflare Workers) but not in web browsers. In environments
* without `AsyncLocalStorage` support, pass the `config` that your node/tool
* function receives directly, e.g. `getCurrentTaskInput(config)`.
*
* Tip: Inside a tool run by a `ToolNode`, prefer reading graph state from
* `runtime.state` on the second tool argument (typed as `ToolRuntime` from
* `@langchain/core/tools`). It works in every runtime, including web browsers.
*
* @param config - Optional {@link LangGraphRunnableConfig} to read the task
* input from. Provide this when running in an environment without
* `AsyncLocalStorage` support (e.g. web browsers).
* @returns the input for the currently executing task
*/
function getCurrentTaskInput(config) {
	const runConfig = config ?? _langchain_core_singletons.AsyncLocalStorageProviderSingleton.getRunnableConfig();
	if (runConfig === void 0) throw new Error(["Config not retrievable. This is likely because you are running in an environment without support for AsyncLocalStorage.", "If you're running `getCurrentTaskInput` in such environment, pass the `config` from the node function directly."].join("\n"));
	if (runConfig.configurable?.["__pregel_scratchpad"]?.currentTaskInput === void 0) throw new Error("BUG: internal scratchpad not initialized.");
	return runConfig.configurable[require_constants.CONFIG_KEY_SCRATCHPAD].currentTaskInput;
}
function recastCheckpointNamespace(namespace) {
	return namespace.split("|").filter((part) => !part.match(/^\d+$/)).map((part) => part.split(":")[0]).join("|");
}
function getParentCheckpointNamespace(namespace) {
	const parts = namespace.split("|");
	while (parts.length > 1 && parts[parts.length - 1].match(/^\d+$/)) parts.pop();
	return parts.slice(0, -1).join("|");
}
//#endregion
exports.ensureLangGraphConfig = ensureLangGraphConfig;
exports.filterToUserTags = filterToUserTags;
exports.getConfig = getConfig;
exports.getCurrentTaskInput = getCurrentTaskInput;
exports.getParentCheckpointNamespace = getParentCheckpointNamespace;
exports.getStore = getStore;
exports.getWriter = getWriter;
exports.propagateConfigurableToMetadata = propagateConfigurableToMetadata;
exports.recastCheckpointNamespace = recastCheckpointNamespace;

//# sourceMappingURL=config.cjs.map