diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 00000000..93771ecc
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,3 @@
+# Check out text files with LF on every platform, overriding core.autocrlf.
+# The build writes LF, so CRLF checkouts make every dist/ file look modified.
+* text=auto eol=lf
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index eaa89887..88d9f2a6 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -38,10 +38,9 @@ jobs:
with:
node-version: ${{ matrix.node }}
# No `cache: npm`: that needs a lockfile, and this repo gitignores one.
- # Measured, caching ~/.npm would buy nothing anyway - install time is
- # node-gyp compiling better-sqlite3, not downloads (see the PR body).
- # Installing cold every run also keeps the native-install path that
- # issues #100/#102/#105/#125/#135/#162 are about under real test.
+ # Installing cold every run keeps the native dependency path that
+ # issues #100/#102/#105/#125/#135/#162 are about under real test,
+ # including the bundled better-sqlite3 N-API platform binary.
# No lockfile is committed, so `npm ci` cannot be used. Dependency ranges
# resolve fresh on every run; see the PR body for the caveat this implies.
diff --git a/.mcp.json b/.mcp.json
index 46558f39..426fa096 100644
--- a/.mcp.json
+++ b/.mcp.json
@@ -11,6 +11,8 @@
"PERSONAL_SUPERPOWERS_DIR",
"XDG_CONFIG_HOME",
"EPISODIC_MEMORY_DB_PATH",
+ "EPISODIC_MEMORY_MODEL_CACHE_DIR",
+ "EPISODIC_MEMORY_OFFLINE",
"CONVERSATION_SEARCH_EXCLUDE_PROJECTS"
]
}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 511074ff..5347f567 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [Unreleased]
+
+### Fixed
+
+- Native database installs now use the N-API-based `better-sqlite3` 13.x line, so switching Node versions no longer leaves an ABI-specific binding behind. This also avoids a Node 24.19-24.21 cleanup-hook crash caused by rebuilding the old 12.x addon from source. Install verification now performs a real sqlite-vec write and nearest-neighbor query, and the MCP integration test covers text search, vector search, and reading the returned archive.
+
## [1.6.0] - 2026-09-08
Adds a fifth conversation source, an off switch for automatic syncing, and two fixes for real-world resource problems.
diff --git a/README.md b/README.md
index ee952317..c27d7aac 100644
--- a/README.md
+++ b/README.md
@@ -301,12 +301,26 @@ Codex summarization requires `codex-cli 0.130.0` or newer. If Codex app-server s
| Component | Uses custom config? |
|-----------|---------------------|
| Summarization | Yes (up to 10 calls/sync) |
-| Embeddings | No (local Transformers.js) |
+| Embeddings | Optional cache and offline settings (local Transformers.js) |
| Search | No (local SQLite) |
| MCP tools | No |
Summaries are display-only: they decorate search results and are never embedded or searched, so `EPISODIC_MEMORY_SKIP_SUMMARIES=1` costs you that line of context and nothing else.
+### Embedding model cache and offline mode
+
+Embedding computation is local, but a fresh installation may download its model
+on first use. Model files are cached under the durable Episodic Memory
+configuration directory in `models/`, outside npm-owned `node_modules`, so an
+upgrade or dependency reinstall does not discard them. Set
+`EPISODIC_MEMORY_MODEL_CACHE_DIR` to an absolute path to use a different or
+pre-seeded cache.
+
+Set `EPISODIC_MEMORY_OFFLINE=1` to forbid remote model downloads. In that mode,
+seed the model cache before indexing or semantic search; a missing model fails
+with an explicit cache/offline error rather than silently fetching it. Other
+values retain the normal first-install download behavior.
+
## Commands
### `episodic-memory sync`
@@ -411,7 +425,7 @@ open output.html
1. **Sync** - Copies conversation files from Claude Code and Codex transcript directories to archive; exports opencode sessions from SQLite into generated JSONL transcripts
2. **Parse** - Extracts user-agent exchanges from Claude Code JSONL, Codex rollout JSONL, or opencode transcript JSONL
-3. **Embed** - Generates vector embeddings using Transformers.js (local, offline)
+3. **Embed** - Generates vectors locally with Transformers.js after the model is available
4. **Index** - Stores in SQLite with sqlite-vec for fast similarity search
5. **Search** - Semantic search using vector similarity or exact text matching
@@ -519,6 +533,12 @@ npm test
npm run build
```
+`npm test` prepares the embedding model once in the ignored
+`tmp/test-model-cache` directory, then runs test workers without remote model
+downloads. A fresh test run may download the public model; setting
+`EPISODIC_MEMORY_OFFLINE=1` requires a pre-seeded test cache instead. This does
+not change the production model cache or summarization routes.
+
## License
MIT
diff --git a/dist/embeddings.js b/dist/embeddings.js
index efc41dc4..80fd0b77 100644
--- a/dist/embeddings.js
+++ b/dist/embeddings.js
@@ -1,3 +1,4 @@
+import { getModelCacheDir } from './paths.js';
/**
* Embedding model configuration.
*
@@ -65,6 +66,8 @@ export class EmbeddingsUnavailableError extends Error {
export async function initEmbeddings() {
if (embeddingPipeline)
return;
+ const modelCacheDir = getModelCacheDir();
+ const offline = process.env.EPISODIC_MEMORY_OFFLINE === '1';
// Load @huggingface/transformers lazily. Its module graph eagerly requires
// `sharp`, so a static top-level import would crash *every* consumer of this
// file at import time on hosts where sharp's native binding can't load —
@@ -73,9 +76,11 @@ export async function initEmbeddings() {
let pipeline;
try {
const transformers = await import('@huggingface/transformers');
- // Disable progress callbacks / remote cache to prevent stdout pollution in
- // MCP context, where stdout is reserved for JSON-RPC communication.
+ // Keep model files in durable operator-owned state. Offline mode is an
+ // explicit choice; a fresh default install can still fetch its model.
+ transformers.env.cacheDir = modelCacheDir;
transformers.env.allowLocalModels = true;
+ transformers.env.allowRemoteModels = !offline;
transformers.env.useBrowserCache = false;
pipeline = transformers.pipeline;
}
@@ -97,7 +102,15 @@ export async function initEmbeddings() {
interOpNumThreads: 1,
};
}
- embeddingPipeline = await pipeline('feature-extraction', MODEL_ID, options);
+ try {
+ embeddingPipeline = await pipeline('feature-extraction', MODEL_ID, options);
+ }
+ catch (error) {
+ const message = offline
+ ? 'Embedding model unavailable in the local cache while EPISODIC_MEMORY_OFFLINE=1; pre-seed the model cache or disable offline mode.'
+ : 'Embedding model unavailable; check the model cache and remote model access.';
+ throw new EmbeddingsUnavailableError(message, { cause: error });
+ }
console.error('Embedding model loaded');
}
export async function generateEmbedding(text) {
diff --git a/dist/mcp-server.js b/dist/mcp-server.js
index e3a9adac..c8ca7b19 100644
--- a/dist/mcp-server.js
+++ b/dist/mcp-server.js
@@ -469,9 +469,9 @@ var require_codegen = __commonJS({
}
};
var Throw = class extends Node {
- constructor(error61) {
+ constructor(error62) {
super();
- this.error = error61;
+ this.error = error62;
}
render({ _n }) {
return `throw ${this.error};` + _n;
@@ -708,9 +708,9 @@ var require_codegen = __commonJS({
}
};
var Catch = class extends BlockNode {
- constructor(error61) {
+ constructor(error62) {
super();
- this.error = error61;
+ this.error = error62;
}
render(opts) {
return `catch(${this.error})` + super.render(opts);
@@ -901,9 +901,9 @@ var require_codegen = __commonJS({
this._blockNode(node2);
this.code(tryBody);
if (catchCode) {
- const error61 = this.name("e");
- this._currNode = node2.catch = new Catch(error61);
- catchCode(error61);
+ const error62 = this.name("e");
+ this._currNode = node2.catch = new Catch(error62);
+ catchCode(error62);
}
if (finallyCode) {
this._currNode = node2.finally = new Finally();
@@ -912,8 +912,8 @@ var require_codegen = __commonJS({
return this._endBlockNode(Catch, Finally);
}
// `throw` statement
- throw(error61) {
- return this._leafNode(new Throw(error61));
+ throw(error62) {
+ return this._leafNode(new Throw(error62));
}
// start self-balancing block
block(body, nodeCount) {
@@ -1269,10 +1269,10 @@ var require_errors = __commonJS({
exports.keyword$DataError = {
message: ({ keyword, schemaType }) => schemaType ? (0, codegen_1.str)`"${keyword}" keyword must be ${schemaType} ($data)` : (0, codegen_1.str)`"${keyword}" keyword is invalid ($data)`
};
- function reportError(cxt, error61 = exports.keywordError, errorPaths, overrideAllErrors) {
+ function reportError(cxt, error62 = exports.keywordError, errorPaths, overrideAllErrors) {
const { it } = cxt;
const { gen, compositeRule, allErrors } = it;
- const errObj = errorObjectCode(cxt, error61, errorPaths);
+ const errObj = errorObjectCode(cxt, error62, errorPaths);
if (overrideAllErrors !== null && overrideAllErrors !== void 0 ? overrideAllErrors : compositeRule || allErrors) {
addError(gen, errObj);
} else {
@@ -1280,10 +1280,10 @@ var require_errors = __commonJS({
}
}
exports.reportError = reportError;
- function reportExtraError(cxt, error61 = exports.keywordError, errorPaths) {
+ function reportExtraError(cxt, error62 = exports.keywordError, errorPaths) {
const { it } = cxt;
const { gen, compositeRule, allErrors } = it;
- const errObj = errorObjectCode(cxt, error61, errorPaths);
+ const errObj = errorObjectCode(cxt, error62, errorPaths);
addError(gen, errObj);
if (!(compositeRule || allErrors)) {
returnErrors(it, names_1.default.vErrors);
@@ -1334,19 +1334,19 @@ var require_errors = __commonJS({
schema: new codegen_1.Name("schema"),
parentSchema: new codegen_1.Name("parentSchema")
};
- function errorObjectCode(cxt, error61, errorPaths) {
+ function errorObjectCode(cxt, error62, errorPaths) {
const { createErrors } = cxt.it;
if (createErrors === false)
return (0, codegen_1._)`{}`;
- return errorObject(cxt, error61, errorPaths);
+ return errorObject(cxt, error62, errorPaths);
}
- function errorObject(cxt, error61, errorPaths = {}) {
+ function errorObject(cxt, error62, errorPaths = {}) {
const { gen, it } = cxt;
const keyValues = [
errorInstancePath(it, errorPaths),
errorSchemaPath(cxt, errorPaths)
];
- extraErrorProps(cxt, error61, keyValues);
+ extraErrorProps(cxt, error62, keyValues);
return gen.object(...keyValues);
}
function errorInstancePath({ errorPath }, { instancePath }) {
@@ -1775,13 +1775,13 @@ var require_code2 = __commonJS({
exports.callValidateCode = callValidateCode;
var newRegExp = (0, codegen_1._)`new RegExp`;
function usePattern({ gen, it: { opts } }, pattern) {
- const u3 = opts.unicodeRegExp ? "u" : "";
+ const u = opts.unicodeRegExp ? "u" : "";
const { regExp } = opts.code;
- const rx = regExp(pattern, u3);
+ const rx = regExp(pattern, u);
return gen.scopeValue("pattern", {
key: rx.toString(),
ref: rx,
- code: (0, codegen_1._)`${regExp.code === "new RegExp" ? newRegExp : (0, util_2.useFunc)(gen, regExp)}(${pattern}, ${u3})`
+ code: (0, codegen_1._)`${regExp.code === "new RegExp" ? newRegExp : (0, util_2.useFunc)(gen, regExp)}(${pattern}, ${u})`
});
}
exports.usePattern = usePattern;
@@ -1878,13 +1878,13 @@ var require_keyword = __commonJS({
modifyData(cxt);
reportErrs(() => cxt.error());
} else {
- const ruleErrs = def.async ? validateAsync2() : validateSync();
+ const ruleErrs = def.async ? validateAsync3() : validateSync();
if (def.modifying)
modifyData(cxt);
reportErrs(() => addErrs(cxt, ruleErrs));
}
}
- function validateAsync2() {
+ function validateAsync3() {
const ruleErrs = gen.let("ruleErrs", null);
gen.try(() => assignValid((0, codegen_1._)`await `), (e) => gen.assign(valid, false).if((0, codegen_1._)`${e} instanceof ${it.ValidationError}`, () => gen.assign(ruleErrs, (0, codegen_1._)`${e}.errors`), () => gen.throw(e)));
return ruleErrs;
@@ -4144,13 +4144,14 @@ var require_fast_uri = __commonJS({
if (!malformedIPLiteral) {
malformedHost = canonicalizeHost(parsed, options, schemeHandler, isIP);
}
- if (!schemeHandler || schemeHandler && !schemeHandler.skipNormalize) {
- if (uri.indexOf("%") !== -1) {
- if (parsed.host !== void 0 && !malformedIPLiteral) {
- const host = isIP ? parsed.host : normalizePercentEncoding(parsed.host, true);
- parsed.host = reescapeHostDelimiters(host, isIP);
- }
+ if (uri.indexOf("%") !== -1 && parsed.host !== void 0 && !malformedIPLiteral) {
+ let host = isIP ? parsed.host : normalizePercentEncoding(parsed.host, true);
+ if (!isIP) {
+ host = normalizePercentEncoding(host.toLowerCase());
}
+ parsed.host = reescapeHostDelimiters(host, isIP);
+ }
+ if (!schemeHandler || schemeHandler && !schemeHandler.skipNormalize) {
if (parsed.path) {
parsed.path = normalizePathEncoding(parsed.path);
}
@@ -5010,7 +5011,7 @@ var require_limitNumber = __commonJS({
exclusiveMaximum: { okStr: "<", ok: ops.LT, fail: ops.GTE },
exclusiveMinimum: { okStr: ">", ok: ops.GT, fail: ops.LTE }
};
- var error61 = {
+ var error62 = {
message: ({ keyword, schemaCode }) => (0, codegen_1.str)`must be ${KWDs[keyword].okStr} ${schemaCode}`,
params: ({ keyword, schemaCode }) => (0, codegen_1._)`{comparison: ${KWDs[keyword].okStr}, limit: ${schemaCode}}`
};
@@ -5019,7 +5020,7 @@ var require_limitNumber = __commonJS({
type: "number",
schemaType: "number",
$data: true,
- error: error61,
+ error: error62,
code(cxt) {
const { keyword, data, schemaCode } = cxt;
cxt.fail$data((0, codegen_1._)`${data} ${KWDs[keyword].fail} ${schemaCode} || isNaN(${data})`);
@@ -5035,7 +5036,7 @@ var require_multipleOf = __commonJS({
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var codegen_1 = require_codegen();
- var error61 = {
+ var error62 = {
message: ({ schemaCode }) => (0, codegen_1.str)`must be multiple of ${schemaCode}`,
params: ({ schemaCode }) => (0, codegen_1._)`{multipleOf: ${schemaCode}}`
};
@@ -5044,7 +5045,7 @@ var require_multipleOf = __commonJS({
type: "number",
schemaType: "number",
$data: true,
- error: error61,
+ error: error62,
code(cxt) {
const { gen, data, schemaCode, it } = cxt;
const prec = it.opts.multipleOfPrecision;
@@ -5091,7 +5092,7 @@ var require_limitLength = __commonJS({
var codegen_1 = require_codegen();
var util_1 = require_util();
var ucs2length_1 = require_ucs2length();
- var error61 = {
+ var error62 = {
message({ keyword, schemaCode }) {
const comp = keyword === "maxLength" ? "more" : "fewer";
return (0, codegen_1.str)`must NOT have ${comp} than ${schemaCode} characters`;
@@ -5103,7 +5104,7 @@ var require_limitLength = __commonJS({
type: "string",
schemaType: "number",
$data: true,
- error: error61,
+ error: error62,
code(cxt) {
const { keyword, data, schemaCode, it } = cxt;
const op = keyword === "maxLength" ? codegen_1.operators.GT : codegen_1.operators.LT;
@@ -5123,7 +5124,7 @@ var require_pattern = __commonJS({
var code_1 = require_code2();
var util_1 = require_util();
var codegen_1 = require_codegen();
- var error61 = {
+ var error62 = {
message: ({ schemaCode }) => (0, codegen_1.str)`must match pattern "${schemaCode}"`,
params: ({ schemaCode }) => (0, codegen_1._)`{pattern: ${schemaCode}}`
};
@@ -5132,15 +5133,15 @@ var require_pattern = __commonJS({
type: "string",
schemaType: "string",
$data: true,
- error: error61,
+ error: error62,
code(cxt) {
const { gen, data, $data, schema, schemaCode, it } = cxt;
- const u3 = it.opts.unicodeRegExp ? "u" : "";
+ const u = it.opts.unicodeRegExp ? "u" : "";
if ($data) {
const { regExp } = it.opts.code;
const regExpCode = regExp.code === "new RegExp" ? (0, codegen_1._)`new RegExp` : (0, util_1.useFunc)(gen, regExp);
const valid = gen.let("valid");
- gen.try(() => gen.assign(valid, (0, codegen_1._)`${regExpCode}(${schemaCode}, ${u3}).test(${data})`), () => gen.assign(valid, false));
+ gen.try(() => gen.assign(valid, (0, codegen_1._)`${regExpCode}(${schemaCode}, ${u}).test(${data})`), () => gen.assign(valid, false));
cxt.fail$data((0, codegen_1._)`!${valid}`);
} else {
const regExp = (0, code_1.usePattern)(cxt, schema);
@@ -5158,7 +5159,7 @@ var require_limitProperties = __commonJS({
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var codegen_1 = require_codegen();
- var error61 = {
+ var error62 = {
message({ keyword, schemaCode }) {
const comp = keyword === "maxProperties" ? "more" : "fewer";
return (0, codegen_1.str)`must NOT have ${comp} than ${schemaCode} properties`;
@@ -5170,7 +5171,7 @@ var require_limitProperties = __commonJS({
type: "object",
schemaType: "number",
$data: true,
- error: error61,
+ error: error62,
code(cxt) {
const { keyword, data, schemaCode } = cxt;
const op = keyword === "maxProperties" ? codegen_1.operators.GT : codegen_1.operators.LT;
@@ -5189,7 +5190,7 @@ var require_required = __commonJS({
var code_1 = require_code2();
var codegen_1 = require_codegen();
var util_1 = require_util();
- var error61 = {
+ var error62 = {
message: ({ params: { missingProperty } }) => (0, codegen_1.str)`must have required property '${missingProperty}'`,
params: ({ params: { missingProperty } }) => (0, codegen_1._)`{missingProperty: ${missingProperty}}`
};
@@ -5198,7 +5199,7 @@ var require_required = __commonJS({
type: "object",
schemaType: "array",
$data: true,
- error: error61,
+ error: error62,
code(cxt) {
const { gen, schema, schemaCode, data, $data, it } = cxt;
const { opts } = it;
@@ -5269,7 +5270,7 @@ var require_limitItems = __commonJS({
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var codegen_1 = require_codegen();
- var error61 = {
+ var error62 = {
message({ keyword, schemaCode }) {
const comp = keyword === "maxItems" ? "more" : "fewer";
return (0, codegen_1.str)`must NOT have ${comp} than ${schemaCode} items`;
@@ -5281,7 +5282,7 @@ var require_limitItems = __commonJS({
type: "array",
schemaType: "number",
$data: true,
- error: error61,
+ error: error62,
code(cxt) {
const { keyword, data, schemaCode } = cxt;
const op = keyword === "maxItems" ? codegen_1.operators.GT : codegen_1.operators.LT;
@@ -5312,7 +5313,7 @@ var require_uniqueItems = __commonJS({
var codegen_1 = require_codegen();
var util_1 = require_util();
var equal_1 = require_equal();
- var error61 = {
+ var error62 = {
message: ({ params: { i, j: j2 } }) => (0, codegen_1.str)`must NOT have duplicate items (items ## ${j2} and ${i} are identical)`,
params: ({ params: { i, j: j2 } }) => (0, codegen_1._)`{i: ${i}, j: ${j2}}`
};
@@ -5321,7 +5322,7 @@ var require_uniqueItems = __commonJS({
type: "array",
schemaType: "boolean",
$data: true,
- error: error61,
+ error: error62,
code(cxt) {
const { gen, data, $data, schema, parentSchema, schemaCode, it } = cxt;
if (!$data && !schema)
@@ -5378,14 +5379,14 @@ var require_const = __commonJS({
var codegen_1 = require_codegen();
var util_1 = require_util();
var equal_1 = require_equal();
- var error61 = {
+ var error62 = {
message: "must be equal to constant",
params: ({ schemaCode }) => (0, codegen_1._)`{allowedValue: ${schemaCode}}`
};
var def = {
keyword: "const",
$data: true,
- error: error61,
+ error: error62,
code(cxt) {
const { gen, data, $data, schemaCode, schema } = cxt;
if ($data || schema && typeof schema == "object") {
@@ -5407,7 +5408,7 @@ var require_enum = __commonJS({
var codegen_1 = require_codegen();
var util_1 = require_util();
var equal_1 = require_equal();
- var error61 = {
+ var error62 = {
message: "must be equal to one of the allowed values",
params: ({ schemaCode }) => (0, codegen_1._)`{allowedValues: ${schemaCode}}`
};
@@ -5415,7 +5416,7 @@ var require_enum = __commonJS({
keyword: "enum",
schemaType: "array",
$data: true,
- error: error61,
+ error: error62,
code(cxt) {
const { gen, data, $data, schema, schemaCode, it } = cxt;
if (!$data && schema.length === 0)
@@ -5494,7 +5495,7 @@ var require_additionalItems = __commonJS({
exports.validateAdditionalItems = void 0;
var codegen_1 = require_codegen();
var util_1 = require_util();
- var error61 = {
+ var error62 = {
message: ({ params: { len } }) => (0, codegen_1.str)`must NOT have more than ${len} items`,
params: ({ params: { len } }) => (0, codegen_1._)`{limit: ${len}}`
};
@@ -5503,7 +5504,7 @@ var require_additionalItems = __commonJS({
type: "array",
schemaType: ["boolean", "object"],
before: "uniqueItems",
- error: error61,
+ error: error62,
code(cxt) {
const { parentSchema, it } = cxt;
const { items } = parentSchema;
@@ -5583,10 +5584,10 @@ var require_items = __commonJS({
});
function checkStrictTuple(sch) {
const { opts, errSchemaPath } = it;
- const l = schArr.length;
- const fullTuple = l === sch.minItems && (l === sch.maxItems || sch[extraItems] === false);
+ const l3 = schArr.length;
+ const fullTuple = l3 === sch.minItems && (l3 === sch.maxItems || sch[extraItems] === false);
if (opts.strictTuples && !fullTuple) {
- const msg = `"${keyword}" is ${l}-tuple, but minItems or maxItems/${extraItems} are not specified or different at path "${errSchemaPath}"`;
+ const msg = `"${keyword}" is ${l3}-tuple, but minItems or maxItems/${extraItems} are not specified or different at path "${errSchemaPath}"`;
(0, util_1.checkStrictMode)(it, msg, opts.strictTuples);
}
}
@@ -5622,7 +5623,7 @@ var require_items2020 = __commonJS({
var util_1 = require_util();
var code_1 = require_code2();
var additionalItems_1 = require_additionalItems();
- var error61 = {
+ var error62 = {
message: ({ params: { len } }) => (0, codegen_1.str)`must NOT have more than ${len} items`,
params: ({ params: { len } }) => (0, codegen_1._)`{limit: ${len}}`
};
@@ -5631,7 +5632,7 @@ var require_items2020 = __commonJS({
type: "array",
schemaType: ["object", "boolean"],
before: "uniqueItems",
- error: error61,
+ error: error62,
code(cxt) {
const { schema, parentSchema, it } = cxt;
const { prefixItems } = parentSchema;
@@ -5655,7 +5656,7 @@ var require_contains = __commonJS({
Object.defineProperty(exports, "__esModule", { value: true });
var codegen_1 = require_codegen();
var util_1 = require_util();
- var error61 = {
+ var error62 = {
message: ({ params: { min, max } }) => max === void 0 ? (0, codegen_1.str)`must contain at least ${min} valid item(s)` : (0, codegen_1.str)`must contain at least ${min} and no more than ${max} valid item(s)`,
params: ({ params: { min, max } }) => max === void 0 ? (0, codegen_1._)`{minContains: ${min}}` : (0, codegen_1._)`{minContains: ${min}, maxContains: ${max}}`
};
@@ -5665,7 +5666,7 @@ var require_contains = __commonJS({
schemaType: ["object", "boolean"],
before: "uniqueItems",
trackErrors: true,
- error: error61,
+ error: error62,
code(cxt) {
const { gen, schema, parentSchema, data, it } = cxt;
let min;
@@ -5843,7 +5844,7 @@ var require_propertyNames = __commonJS({
Object.defineProperty(exports, "__esModule", { value: true });
var codegen_1 = require_codegen();
var util_1 = require_util();
- var error61 = {
+ var error62 = {
message: "property name must be valid",
params: ({ params }) => (0, codegen_1._)`{propertyName: ${params.propertyName}}`
};
@@ -5851,7 +5852,7 @@ var require_propertyNames = __commonJS({
keyword: "propertyNames",
type: "object",
schemaType: ["object", "boolean"],
- error: error61,
+ error: error62,
code(cxt) {
const { gen, schema, data, it } = cxt;
if ((0, util_1.alwaysValidSchema)(it, schema))
@@ -5888,7 +5889,7 @@ var require_additionalProperties = __commonJS({
var codegen_1 = require_codegen();
var names_1 = require_names();
var util_1 = require_util();
- var error61 = {
+ var error62 = {
message: "must NOT have additional properties",
params: ({ params }) => (0, codegen_1._)`{additionalProperty: ${params.additionalProperty}}`
};
@@ -5898,7 +5899,7 @@ var require_additionalProperties = __commonJS({
schemaType: ["boolean", "object"],
allowUndefined: true,
trackErrors: true,
- error: error61,
+ error: error62,
code(cxt) {
const { gen, schema, parentSchema, data, errsCount, it } = cxt;
if (!errsCount)
@@ -6172,7 +6173,7 @@ var require_oneOf = __commonJS({
Object.defineProperty(exports, "__esModule", { value: true });
var codegen_1 = require_codegen();
var util_1 = require_util();
- var error61 = {
+ var error62 = {
message: "must match exactly one schema in oneOf",
params: ({ params }) => (0, codegen_1._)`{passingSchemas: ${params.passing}}`
};
@@ -6180,7 +6181,7 @@ var require_oneOf = __commonJS({
keyword: "oneOf",
schemaType: "array",
trackErrors: true,
- error: error61,
+ error: error62,
code(cxt) {
const { gen, schema, parentSchema, it } = cxt;
if (!Array.isArray(schema))
@@ -6257,7 +6258,7 @@ var require_if = __commonJS({
Object.defineProperty(exports, "__esModule", { value: true });
var codegen_1 = require_codegen();
var util_1 = require_util();
- var error61 = {
+ var error62 = {
message: ({ params }) => (0, codegen_1.str)`must match "${params.ifClause}" schema`,
params: ({ params }) => (0, codegen_1._)`{failingKeyword: ${params.ifClause}}`
};
@@ -6265,7 +6266,7 @@ var require_if = __commonJS({
keyword: "if",
schemaType: ["object", "boolean"],
trackErrors: true,
- error: error61,
+ error: error62,
code(cxt) {
const { gen, parentSchema, it } = cxt;
if (parentSchema.then === void 0 && parentSchema.else === void 0) {
@@ -6391,7 +6392,7 @@ var require_format = __commonJS({
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var codegen_1 = require_codegen();
- var error61 = {
+ var error62 = {
message: ({ schemaCode }) => (0, codegen_1.str)`must match format "${schemaCode}"`,
params: ({ schemaCode }) => (0, codegen_1._)`{format: ${schemaCode}}`
};
@@ -6400,7 +6401,7 @@ var require_format = __commonJS({
type: ["number", "string"],
schemaType: "string",
$data: true,
- error: error61,
+ error: error62,
code(cxt, ruleType) {
const { gen, data, $data, schema, schemaCode, it } = cxt;
const { opts, errSchemaPath, schemaEnv, self } = it;
@@ -6555,7 +6556,7 @@ var require_discriminator = __commonJS({
var compile_1 = require_compile();
var ref_error_1 = require_ref_error();
var util_1 = require_util();
- var error61 = {
+ var error62 = {
message: ({ params: { discrError, tagName } }) => discrError === types_1.DiscrError.Tag ? `tag "${tagName}" must be string` : `value of tag "${tagName}" must be in oneOf`,
params: ({ params: { discrError, tag, tagName } }) => (0, codegen_1._)`{error: ${discrError}, tag: ${tagName}, tagValue: ${tag}}`
};
@@ -6563,7 +6564,7 @@ var require_discriminator = __commonJS({
keyword: "discriminator",
type: "object",
schemaType: "object",
- error: error61,
+ error: error62,
code(cxt) {
const { gen, data, schema, parentSchema, it } = cxt;
const { oneOf } = parentSchema;
@@ -7095,7 +7096,7 @@ var require_limit = __commonJS({
formatExclusiveMaximum: { okStr: "<", ok: ops.LT, fail: ops.GTE },
formatExclusiveMinimum: { okStr: ">", ok: ops.GT, fail: ops.LTE }
};
- var error61 = {
+ var error62 = {
message: ({ keyword, schemaCode }) => (0, codegen_1.str)`should be ${KWDs[keyword].okStr} ${schemaCode}`,
params: ({ keyword, schemaCode }) => (0, codegen_1._)`{comparison: ${KWDs[keyword].okStr}, limit: ${schemaCode}}`
};
@@ -7104,7 +7105,7 @@ var require_limit = __commonJS({
type: "string",
schemaType: "string",
$data: true,
- error: error61,
+ error: error62,
code(cxt) {
const { gen, data, schemaCode, keyword, it } = cxt;
const { opts, self } = it;
@@ -7226,6 +7227,7 @@ __export(core_exports2, {
$ZodCheckMultipleOf: () => $ZodCheckMultipleOf,
$ZodCheckNumberFormat: () => $ZodCheckNumberFormat,
$ZodCheckOverwrite: () => $ZodCheckOverwrite,
+ $ZodCheckProperties: () => $ZodCheckProperties,
$ZodCheckProperty: () => $ZodCheckProperty,
$ZodCheckRegex: () => $ZodCheckRegex,
$ZodCheckSizeEquals: () => $ZodCheckSizeEquals,
@@ -7250,6 +7252,7 @@ __export(core_exports2, {
$ZodFile: () => $ZodFile,
$ZodFunction: () => $ZodFunction,
$ZodGUID: () => $ZodGUID,
+ $ZodIBAN: () => $ZodIBAN,
$ZodIPv4: () => $ZodIPv4,
$ZodIPv6: () => $ZodIPv6,
$ZodISODate: () => $ZodISODate,
@@ -7351,6 +7354,7 @@ __export(core_exports2, {
_gt: () => _gt,
_gte: () => _gte,
_guid: () => _guid,
+ _iban: () => _iban,
_includes: () => _includes,
_int: () => _int,
_int32: () => _int32,
@@ -7442,6 +7446,9 @@ __export(core_exports2, {
_void: () => _void,
_xid: () => _xid,
_xor: () => _xor,
+ base64Charset: () => base64Charset,
+ base64urlCharset: () => base64urlCharset,
+ canParseURL: () => canParseURL,
clone: () => clone,
compile: () => compile,
compileFn: () => compileFn,
@@ -7468,6 +7475,7 @@ __export(core_exports2, {
isValidBase64URL: () => isValidBase64URL,
isValidCIDRv6: () => isValidCIDRv6,
isValidCreditCard: () => isValidCreditCard,
+ isValidIBAN: () => isValidIBAN,
isValidIPv6: () => isValidIPv6,
isValidJWT: () => isValidJWT,
locales: () => locales_exports,
@@ -7478,7 +7486,8 @@ __export(core_exports2, {
parseAsync: () => parseAsync,
parseURLObject: () => parseURLObject,
prettifyError: () => prettifyError,
- process: () => process2,
+ process: () => processSchema,
+ processSchema: () => processSchema,
regexes: () => regexes_exports,
registry: () => registry,
safeDecode: () => safeDecode,
@@ -7498,7 +7507,9 @@ __export(core_exports2, {
util: () => util_exports,
validate: () => validate,
validateAsync: () => validateAsync,
- version: () => version
+ validateURL: () => validateURL,
+ version: () => version,
+ withParser: () => withParser
});
// node_modules/zod/v4/core/util.js
@@ -7530,6 +7541,7 @@ __export(util_exports, {
createTransparentProxy: () => createTransparentProxy,
defineLazy: () => defineLazy,
defineLazyInternal: () => defineLazyInternal,
+ derived: () => derived,
esc: () => esc,
escapeRegex: () => escapeRegex,
explicitlyAborted: () => explicitlyAborted,
@@ -7567,6 +7579,7 @@ __export(util_exports, {
promiseAllObject: () => promiseAllObject,
propertyKeyTypes: () => propertyKeyTypes,
randomString: () => randomString,
+ rawShape: () => rawShape,
required: () => required,
safeExtend: () => safeExtend,
shallowClone: () => shallowClone,
@@ -7607,18 +7620,22 @@ function jsonStringifyReplacer(_2, value) {
return value.toString();
return value;
}
-function cached(getter) {
- const set2 = false;
- return {
- get value() {
- if (!set2) {
- const value = getter();
- Object.defineProperty(this, "value", { value });
- return value;
- }
- throw new Error("cached value already set");
+var Cached = class {
+ constructor(getter) {
+ this._getter = getter;
+ this._value = void 0;
+ }
+ get value() {
+ const getter = this._getter;
+ if (getter !== void 0) {
+ this._value = getter();
+ this._getter = void 0;
}
- };
+ return this._value;
+ }
+};
+function cached(getter) {
+ return new Cached(getter);
}
function nullish(input2) {
return input2 === null || input2 === void 0;
@@ -7670,6 +7687,56 @@ function assignProp(target, prop, value) {
configurable: true
});
}
+function rawShape(def) {
+ const desc = Object.getOwnPropertyDescriptor(def, "shape");
+ return desc?.get ? desc.get.raw : desc?.value;
+}
+function sourceShape(schema) {
+ return rawShape(schema._zod.def) ?? schema._zod.def.shape;
+}
+function deferProp(target, key, getter) {
+ Object.defineProperty(target, key, {
+ get() {
+ const value = getter();
+ assignProp(this, key, value);
+ return value;
+ },
+ enumerable: true,
+ configurable: true
+ });
+}
+function putProp(target, key, value) {
+ if (key in target)
+ assignProp(target, key, value);
+ else
+ target[key] = value;
+}
+function mirrorShape(target, source, keys, wrap) {
+ const raw = sourceShape(source);
+ for (const key of keys) {
+ const desc = Object.getOwnPropertyDescriptor(raw, key);
+ if (!desc.enumerable)
+ continue;
+ if (desc.get) {
+ deferProp(target, key, () => {
+ const value = source._zod.def.shape[key];
+ return wrap ? wrap(value, key) : value;
+ });
+ } else
+ putProp(target, key, wrap ? wrap(desc.value, key) : desc.value);
+ }
+}
+function mirrorProps(target, source) {
+ for (const key of Reflect.ownKeys(source)) {
+ const desc = Object.getOwnPropertyDescriptor(source, key);
+ if (!desc.enumerable)
+ continue;
+ if (desc.get)
+ deferProp(target, key, () => source[key]);
+ else
+ putProp(target, key, desc.value);
+ }
+}
function mergeDefs(...defs) {
const mergedDescriptors = {};
for (const def of defs) {
@@ -7908,23 +7975,21 @@ function pick(schema, mask) {
if (hasChecks) {
throw new Error(".pick() cannot be used on object schemas containing refinements");
}
- const def = mergeDefs(schema._zod.def, {
- get shape() {
- const newShape = {};
- for (const key of Reflect.ownKeys(mask)) {
- if (!Object.prototype.hasOwnProperty.call(currDef.shape, key)) {
- throw new Error(`Unrecognized key: "${String(key)}"`);
- }
- if (!mask[key])
- continue;
- assignProp(newShape, key, currDef.shape[key]);
- }
- assignProp(this, "shape", newShape);
- return newShape;
- },
- checks: []
- });
- return clone(schema, def);
+ const newShape = {};
+ mirrorShape(newShape, schema, maskedKeys(schema, mask));
+ return clone(schema, mergeDefs(currDef, { shape: newShape, checks: [] }));
+}
+function maskedKeys(schema, mask) {
+ const raw = sourceShape(schema);
+ const keys = [];
+ for (const key of Reflect.ownKeys(mask)) {
+ if (!Object.getOwnPropertyDescriptor(raw, key)?.enumerable) {
+ throw new Error(`Unrecognized key: "${String(key)}"`);
+ }
+ if (mask[key])
+ keys.push(key);
+ }
+ return keys;
}
function omit(schema, mask) {
const currDef = schema._zod.def;
@@ -7933,23 +7998,10 @@ function omit(schema, mask) {
if (hasChecks) {
throw new Error(".omit() cannot be used on object schemas containing refinements");
}
- const def = mergeDefs(schema._zod.def, {
- get shape() {
- const newShape = { ...schema._zod.def.shape };
- for (const key of Reflect.ownKeys(mask)) {
- if (!Object.prototype.hasOwnProperty.call(currDef.shape, key)) {
- throw new Error(`Unrecognized key: "${String(key)}"`);
- }
- if (!mask[key])
- continue;
- delete newShape[key];
- }
- assignProp(this, "shape", newShape);
- return newShape;
- },
- checks: []
- });
- return clone(schema, def);
+ const omitted = new Set(maskedKeys(schema, mask));
+ const newShape = {};
+ mirrorShape(newShape, schema, Reflect.ownKeys(sourceShape(schema)).filter((key) => !omitted.has(key)));
+ return clone(schema, mergeDefs(currDef, { shape: newShape, checks: [] }));
}
function extend(schema, shape) {
if (!isPlainObject(shape)) {
@@ -7958,34 +8010,26 @@ function extend(schema, shape) {
const checks = schema._zod.def.checks;
const hasChecks = checks && checks.length > 0;
if (hasChecks) {
- const existingShape = schema._zod.def.shape;
+ const existingShape = sourceShape(schema);
for (const key of Reflect.ownKeys(shape)) {
if (Object.getOwnPropertyDescriptor(existingShape, key) !== void 0) {
throw new Error("Cannot overwrite keys on object schemas containing refinements. Use `.safeExtend()` instead.");
}
}
}
- const def = mergeDefs(schema._zod.def, {
- get shape() {
- const _shape = { ...schema._zod.def.shape, ...shape };
- assignProp(this, "shape", _shape);
- return _shape;
- }
- });
- return clone(schema, def);
+ return clone(schema, mergeDefs(schema._zod.def, { shape: extended(schema, shape) }));
+}
+function extended(schema, shape) {
+ const newShape = {};
+ mirrorShape(newShape, schema, Reflect.ownKeys(sourceShape(schema)));
+ mirrorProps(newShape, shape);
+ return newShape;
}
function safeExtend(schema, shape) {
if (!isPlainObject(shape)) {
throw new Error("Invalid input to safeExtend: expected a plain object");
}
- const def = mergeDefs(schema._zod.def, {
- get shape() {
- const _shape = { ...schema._zod.def.shape, ...shape };
- assignProp(this, "shape", _shape);
- return _shape;
- }
- });
- return clone(schema, def);
+ return clone(schema, mergeDefs(schema._zod.def, { shape: extended(schema, shape) }));
}
function merge(a, b2) {
if (!b2?._zod?.def) {
@@ -7994,12 +8038,11 @@ function merge(a, b2) {
if (a._zod.def.checks?.length) {
throw new Error(".merge() cannot be used on object schemas containing refinements. Use .safeExtend() instead.");
}
+ const newShape = {};
+ mirrorShape(newShape, a, Reflect.ownKeys(sourceShape(a)));
+ mirrorShape(newShape, b2, Reflect.ownKeys(sourceShape(b2)));
const def = mergeDefs(a._zod.def, {
- get shape() {
- const _shape = { ...a._zod.def.shape, ...b2._zod.def.shape };
- assignProp(this, "shape", _shape);
- return _shape;
- },
+ shape: newShape,
get catchall() {
return b2._zod.def.catchall;
},
@@ -8014,67 +8057,19 @@ function partial(Class2, schema, mask, name = "partial") {
if (hasChecks) {
throw new Error(`.${name}() cannot be used on object schemas containing refinements`);
}
- const def = mergeDefs(schema._zod.def, {
- get shape() {
- const oldShape = schema._zod.def.shape;
- const shape = { ...oldShape };
- if (mask) {
- for (const key of Reflect.ownKeys(mask)) {
- if (!Object.prototype.hasOwnProperty.call(oldShape, key)) {
- throw new Error(`Unrecognized key: "${String(key)}"`);
- }
- if (!mask[key])
- continue;
- shape[key] = Class2 ? new Class2({
- type: "optional",
- innerType: oldShape[key]
- }) : oldShape[key];
- }
- } else {
- for (const key of Reflect.ownKeys(oldShape)) {
- shape[key] = Class2 ? new Class2({
- type: "optional",
- innerType: oldShape[key]
- }) : oldShape[key];
- }
- }
- assignProp(this, "shape", shape);
- return shape;
- },
- checks: []
- });
- return clone(schema, def);
+ const selected = mask ? new Set(maskedKeys(schema, mask)) : void 0;
+ const newShape = {};
+ mirrorShape(newShape, schema, Reflect.ownKeys(sourceShape(schema)), Class2 && ((value, key) => selected && !selected.has(key) ? value : new Class2({ type: "optional", innerType: value })));
+ return clone(schema, mergeDefs(schema._zod.def, { shape: newShape, checks: [] }));
}
function required(Class2, schema, mask) {
- const def = mergeDefs(schema._zod.def, {
- get shape() {
- const oldShape = schema._zod.def.shape;
- const shape = { ...oldShape };
- if (mask) {
- for (const key of Reflect.ownKeys(mask)) {
- if (!Object.prototype.hasOwnProperty.call(shape, key)) {
- throw new Error(`Unrecognized key: "${String(key)}"`);
- }
- if (!mask[key])
- continue;
- shape[key] = new Class2({
- type: "nonoptional",
- innerType: oldShape[key]
- });
- }
- } else {
- for (const key of Reflect.ownKeys(oldShape)) {
- shape[key] = new Class2({
- type: "nonoptional",
- innerType: oldShape[key]
- });
- }
- }
- assignProp(this, "shape", shape);
- return shape;
- }
- });
- return clone(schema, def);
+ const selected = mask ? new Set(maskedKeys(schema, mask)) : void 0;
+ const newShape = {};
+ mirrorShape(newShape, schema, Reflect.ownKeys(sourceShape(schema)), (value, key) => (
+ // overwrite with non-optional
+ selected && !selected.has(key) ? value : new Class2({ type: "nonoptional", innerType: value })
+ ));
+ return clone(schema, mergeDefs(schema._zod.def, { shape: newShape }));
}
function aborted(x2, startIndex = 0) {
if (x2.aborted === true)
@@ -8124,13 +8119,18 @@ function finalizeIssue(iss, ctx, config2) {
}
const schemaError = iss.schema !== iss.inst ? iss.schema?._zod.def?.error : void 0;
const message = iss.message ? iss.message : unwrapMessage(iss.inst?._zod.def?.error?.(iss)) ?? unwrapMessage(schemaError?.(iss)) ?? unwrapMessage(ctx?.error?.(iss)) ?? unwrapMessage(config2.customError?.(iss)) ?? unwrapMessage(config2.localeError?.(iss)) ?? "Invalid input";
- const { inst: _inst, schema: _schema, continue: _continue, input: _input, ...rest } = iss;
- rest.path ?? (rest.path = []);
- rest.message = message;
+ const full = {};
+ for (const k2 of Object.keys(iss)) {
+ if (k2 === "inst" || k2 === "schema" || k2 === "continue" || k2 === "input" || k2 === "__proto__")
+ continue;
+ full[k2] = iss[k2];
+ }
+ full.path ?? (full.path = []);
+ full.message = message;
if (ctx?.reportInput) {
- rest.input = _input;
+ full.input = iss.input;
}
- return rest;
+ return full;
}
function getSizableOrigin(input2) {
if (input2 instanceof Set)
@@ -8257,6 +8257,23 @@ function own(inst, key, value, enumerable = true) {
function hide(inst, key, value) {
return own(inst, key, value, false);
}
+// @__NO_SIDE_EFFECTS__
+function derived(computes, table) {
+ for (const key in computes) {
+ const compute = computes[key];
+ Object.defineProperty(table, key, {
+ configurable: true,
+ enumerable: true,
+ get() {
+ return own(this, key, compute(this));
+ },
+ set(value) {
+ own(this, key, value);
+ }
+ });
+ }
+ return table;
+}
function defineBound(proto, key, fn) {
Object.defineProperty(proto, key, {
configurable: true,
@@ -8384,8 +8401,7 @@ function $constructor(name, initializer3, proto, params) {
} finally {
_zodDesc.value = void 0;
}
- }
- if (inst._zod.traits.has(name)) {
+ } else if (inst._zod.traits.has(name)) {
return;
}
inst._zod.traits.add(name);
@@ -8476,16 +8492,12 @@ var _messageDesc = {
enumerable: true,
configurable: true
};
-var _zodDesc2 = { value: void 0, enumerable: false };
var _issuesDesc = { value: void 0, enumerable: false };
var _installedToString = /* @__PURE__ */ new WeakSet([Object.prototype, Error.prototype]);
var initializer = (inst, def) => {
inst.name = "$ZodError";
- _zodDesc2.value = inst._zod;
- Object.defineProperty(inst, "_zod", _zodDesc2);
_issuesDesc.value = def;
Object.defineProperty(inst, "issues", _issuesDesc);
- _zodDesc2.value = void 0;
_issuesDesc.value = void 0;
Object.defineProperty(inst, "message", _messageDesc);
const proto = Object.getPrototypeOf(inst);
@@ -8519,10 +8531,10 @@ function node(obj, key, make) {
}
return obj[key];
}
-function flattenError(error61, mapper = (issue2) => issue2.message) {
+function flattenError(error62, mapper = (issue2) => issue2.message) {
const fieldErrors = {};
const formErrors = [];
- for (const sub of error61.issues) {
+ for (const sub of error62.issues) {
if (sub.path.length > 0) {
node(fieldErrors, sub.path[0], () => []).push(mapper(sub));
} else {
@@ -8531,10 +8543,10 @@ function flattenError(error61, mapper = (issue2) => issue2.message) {
}
return { formErrors, fieldErrors };
}
-function formatError(error61, mapper = (issue2) => issue2.message) {
+function formatError(error62, mapper = (issue2) => issue2.message) {
const fieldErrors = { _errors: [] };
- const processError = (error62, path3 = []) => {
- for (const issue2 of error62.issues) {
+ const processError = (error63, path3 = []) => {
+ for (const issue2 of error63.issues) {
if (issue2.code === "invalid_union" && issue2.errors.length) {
issue2.errors.map((issues) => processError({ issues }, [...path3, ...issue2.path]));
} else if (issue2.code === "invalid_key") {
@@ -8576,14 +8588,14 @@ function formatError(error61, mapper = (issue2) => issue2.message) {
}
}
};
- processError(error61);
+ processError(error62);
return fieldErrors;
}
-function treeifyError(error61, mapper = (issue2) => issue2.message) {
+function treeifyError(error62, mapper = (issue2) => issue2.message) {
const result = { errors: [] };
- const processError = (error62, path3 = []) => {
+ const processError = (error63, path3 = []) => {
var _a3;
- for (const issue2 of error62.issues) {
+ for (const issue2 of error63.issues) {
if (issue2.code === "invalid_union" && issue2.errors.length) {
issue2.errors.map((issues) => processError({ issues }, [...path3, ...issue2.path]));
} else if (issue2.code === "invalid_key") {
@@ -8625,7 +8637,7 @@ function treeifyError(error61, mapper = (issue2) => issue2.message) {
}
}
};
- processError(error61);
+ processError(error62);
return result;
}
function toDotPath(_path) {
@@ -8646,9 +8658,9 @@ function toDotPath(_path) {
}
return segs.join("");
}
-function prettifyError(error61) {
+function prettifyError(error62) {
const lines = [];
- const issues = [...error61.issues].sort((a, b2) => (a.path ?? []).length - (b2.path ?? []).length);
+ const issues = [...error62.issues].sort((a, b2) => (a.path ?? []).length - (b2.path ?? []).length);
for (const issue2 of issues) {
lines.push(`\u2716 ${issue2.message}`);
if (issue2.path?.length)
@@ -8700,33 +8712,50 @@ var _safeParse = (_Err) => (schema, value, _ctx) => {
if (result instanceof Promise) {
throw new $ZodAsyncError();
}
- return result.issues.length ? {
- success: false,
- error: new (_Err ?? $ZodError)(result.issues.map((iss) => finalizeIssue(iss, ctx, config())))
- } : { success: true, data: result.value };
+ return result.issues.length ? failure(_Err, result.issues, ctx) : { success: true, data: result.value };
};
var safeParse = /* @__PURE__ */ _safeParse($ZodRealError);
+function failure(Err, issues, ctx) {
+ let error62;
+ return {
+ success: false,
+ get error() {
+ if (!error62) {
+ error62 = new Err(issues.map((iss) => finalizeIssue(iss, ctx, config())));
+ issues = void 0;
+ ctx = void 0;
+ }
+ return error62;
+ },
+ set error(e) {
+ error62 = e;
+ issues = void 0;
+ ctx = void 0;
+ }
+ };
+}
var _safeParseAsync = (_Err) => async (schema, value, _ctx) => {
const ctx = _ctx ? { ..._ctx, async: true } : { async: true };
let result = schema._zod.run({ value, issues: [] }, ctx);
if (result instanceof Promise)
result = await result;
- return result.issues.length ? {
- success: false,
- error: new _Err(result.issues.map((iss) => finalizeIssue(iss, ctx, config())))
- } : { success: true, data: result.value };
+ return result.issues.length ? failure(_Err, result.issues, ctx) : { success: true, data: result.value };
};
var safeParseAsync = /* @__PURE__ */ _safeParseAsync($ZodRealError);
var COMPILE_INVALID = /* @__PURE__ */ Symbol.for("zod.compile.invalid");
var COMPILE_FALLBACK = /* @__PURE__ */ Symbol.for("zod.compile.fallback");
var validate = ((schema, value, _ctx) => {
const validator = schema._zod.bag.validator;
- if (validator !== void 0 && validator(value) !== COMPILE_INVALID)
- return true;
+ if (validator !== void 0) {
+ if (validator(value) !== COMPILE_INVALID)
+ return true;
+ if (validator.definite === true && _ctx === void 0)
+ return false;
+ }
return validateFallback(schema, value, _ctx);
});
function validateFallback(schema, value, _ctx) {
- const ctx = _ctx ? { ..._ctx, async: false } : { async: false };
+ const ctx = _ctx ? { ..._ctx, async: false, abortEarly: true } : { async: false, abortEarly: true };
const fallbackRun = schema._zod.bag.fallbackRun;
let result;
if (fallbackRun) {
@@ -8741,7 +8770,7 @@ function validateFallback(schema, value, _ctx) {
return result.issues.length === 0;
}
var validateAsync = async (schema, value, _ctx) => {
- const ctx = _ctx ? { ..._ctx, async: true } : { async: true };
+ const ctx = _ctx ? { ..._ctx, async: true, abortEarly: true } : { async: true, abortEarly: true };
let result = schema._zod.run({ value, issues: [] }, ctx);
if (result instanceof Promise)
result = await result;
@@ -8803,6 +8832,7 @@ var safeDecodeAsync = /* @__PURE__ */ _safeDecodeAsync($ZodRealError);
// node_modules/zod/v4/core/regexes.js
var regexes_exports = {};
__export(regexes_exports, {
+ anyString: () => anyString,
base64: () => base64,
base64url: () => base64url,
bigint: () => bigint,
@@ -8813,6 +8843,7 @@ __export(regexes_exports, {
creditCard: () => creditCard,
cuid: () => cuid,
cuid2: () => cuid2,
+ currencyCode: () => currencyCode,
date: () => date,
datetime: () => datetime,
domain: () => domain,
@@ -8826,6 +8857,7 @@ __export(regexes_exports, {
hostname: () => hostname,
html5Email: () => html5Email,
httpProtocol: () => httpProtocol,
+ iban: () => iban,
idnEmail: () => idnEmail,
integer: () => integer,
ipv4: () => ipv4,
@@ -8885,13 +8917,13 @@ var uuid = (version2) => {
var uuid4 = /* @__PURE__ */ uuid(4);
var uuid6 = /* @__PURE__ */ uuid(6);
var uuid7 = /* @__PURE__ */ uuid(7);
-var email = /^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$/;
+var email = /^(?:[A-Za-z0-9_'+\-]+\.)*[A-Za-z0-9_'+\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$/;
var html5Email = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
var rfc5322Email = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
var unicodeEmail = /^[^\s@"]{1,64}@[^\s@]{1,255}$/u;
var idnEmail = unicodeEmail;
var browserEmail = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
-var _emoji = `^[\\p{Extended_Pictographic}\\p{Emoji_Component}]+$`;
+var _emoji = `^(?=[\\s\\S]*[\\p{Extended_Pictographic}\\p{Regional_Indicator}\\u20E3])[\\p{Extended_Pictographic}\\p{Emoji_Component}]+$`;
function emoji() {
return new RegExp(_emoji, "u");
}
@@ -8904,12 +8936,14 @@ var mac = (delimiter) => {
var cidrv4 = /^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/([0-9]|[1-2][0-9]|3[0-2])$/;
var cidrv6 = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/;
var base64 = /^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$/;
-var base64url = /^[A-Za-z0-9_-]*$/;
+var base64url = /^(?:[A-Za-z0-9_-]{4})*(?:[A-Za-z0-9_-]{2,3})?$/;
var hostname = /^(?=.{1,253}\.?$)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[-0-9a-zA-Z]{0,61}[0-9a-zA-Z])?)*\.?$/;
var domain = /^(?=.{1,253}$)([a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,63}$/;
var httpProtocol = /^https?$/;
var e164 = /^\+[1-9]\d{6,14}$/;
var creditCard = /^\d(?:[ -]?\d){11,18}$/;
+var currencyCode = /^(?:AED|AFN|ALL|AMD|AOA|ARS|AUD|AWG|AZN|BAM|BBD|BDT|BHD|BIF|BMD|BND|BOB|BOV|BRL|BSD|BTN|BWP|BYN|BZD|CAD|CDF|CHE|CHF|CHW|CLF|CLP|CNY|COP|COU|CRC|CUP|CVE|CZK|DJF|DKK|DOP|DZD|EGP|ERN|ETB|EUR|FJD|FKP|GBP|GEL|GHS|GIP|GMD|GNF|GTQ|GYD|HKD|HNL|HTG|HUF|IDR|ILS|INR|IQD|IRR|ISK|JMD|JOD|JPY|KES|KGS|KHR|KMF|KPW|KRW|KWD|KYD|KZT|LAK|LBP|LKR|LRD|LSL|LYD|MAD|MDL|MGA|MKD|MMK|MNT|MOP|MRU|MUR|MVR|MWK|MXN|MXV|MYR|MZN|NAD|NGN|NIO|NOK|NPR|NZD|OMR|PAB|PEN|PGK|PHP|PKR|PLN|PYG|QAR|RON|RSD|RUB|RWF|SAR|SBD|SCR|SDG|SEK|SGD|SHP|SLE|SOS|SRD|SSP|STN|SVC|SYP|SZL|THB|TJS|TMT|TND|TOP|TRY|TTD|TWD|TZS|UAH|UGX|USD|USN|UYI|UYU|UYW|UZS|VED|VES|VND|VUV|WST|XAD|XAF|XAG|XAU|XBA|XBB|XBC|XBD|XCD|XCG|XDR|XOF|XPD|XPF|XPT|XSU|XTS|XUA|XXX|YER|ZAR|ZMW|ZWG)$/;
+var iban = /^[A-Z]{2}(?!00|01|99)\d{2}[A-Z0-9]{11,30}$/;
var dateSource = `(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))`;
function anchor(source) {
return new RegExp(`^${source}$`);
@@ -8931,6 +8965,7 @@ function datetime(args) {
const timeRegex = args.local ? `${qualified}|${timeSource({ precision: args.precision })}` : qualified;
return new RegExp(`^${dateSource}T(?:${timeRegex})$`);
}
+var anyString = /^[\s\S]{0,}$/;
var string = (params) => {
const regex = params ? `[\\s\\S]{${params?.minimum ?? 0},${params?.maximum ?? ""}}` : `[\\s\\S]*`;
return new RegExp(`^${regex}$`);
@@ -8989,16 +9024,6 @@ var numericOriginMap = {
var $ZodCheckLessThan = /* @__PURE__ */ $constructor("$ZodCheckLessThan", (inst, def) => {
$ZodCheck.init(inst, def);
const origin = numericOriginMap[typeof def.value];
- inst._zod.onattach.push((inst2) => {
- const bag = inst2._zod.bag;
- const curr = (def.inclusive ? bag.maximum : bag.exclusiveMaximum) ?? Number.POSITIVE_INFINITY;
- if (def.value < curr) {
- if (def.inclusive)
- bag.maximum = def.value;
- else
- bag.exclusiveMaximum = def.value;
- }
- });
inst._zod.check = (payload) => {
if (def.inclusive ? payload.value <= def.value : payload.value < def.value) {
return;
@@ -9017,16 +9042,6 @@ var $ZodCheckLessThan = /* @__PURE__ */ $constructor("$ZodCheckLessThan", (inst,
var $ZodCheckGreaterThan = /* @__PURE__ */ $constructor("$ZodCheckGreaterThan", (inst, def) => {
$ZodCheck.init(inst, def);
const origin = numericOriginMap[typeof def.value];
- inst._zod.onattach.push((inst2) => {
- const bag = inst2._zod.bag;
- const curr = (def.inclusive ? bag.minimum : bag.exclusiveMinimum) ?? Number.NEGATIVE_INFINITY;
- if (def.value > curr) {
- if (def.inclusive)
- bag.minimum = def.value;
- else
- bag.exclusiveMinimum = def.value;
- }
- });
inst._zod.check = (payload) => {
if (def.inclusive ? payload.value >= def.value : payload.value > def.value) {
return;
@@ -9044,10 +9059,6 @@ var $ZodCheckGreaterThan = /* @__PURE__ */ $constructor("$ZodCheckGreaterThan",
});
var $ZodCheckMultipleOf = /* @__PURE__ */ $constructor("$ZodCheckMultipleOf", (inst, def) => {
$ZodCheck.init(inst, def);
- inst._zod.onattach.push((inst2) => {
- var _a3;
- (_a3 = inst2._zod.bag).multipleOf ?? (_a3.multipleOf = def.value);
- });
inst._zod.check = (payload) => {
if (typeof payload.value !== typeof def.value)
throw new Error("Cannot mix number and bigint in multiple_of check.");
@@ -9073,14 +9084,6 @@ var $ZodCheckNumberFormat = /* @__PURE__ */ $constructor("$ZodCheckNumberFormat"
const isInt = def.format?.includes("int");
const origin = isInt ? "int" : "number";
const [minimum, maximum] = NUMBER_FORMAT_RANGES[def.format];
- inst._zod.onattach.push((inst2) => {
- const bag = inst2._zod.bag;
- bag.format = def.format;
- bag.minimum = minimum;
- bag.maximum = maximum;
- if (isInt)
- bag.pattern = integer;
- });
inst._zod.check = (payload) => {
const input2 = payload.value;
if (isInt) {
@@ -9149,12 +9152,6 @@ var $ZodCheckNumberFormat = /* @__PURE__ */ $constructor("$ZodCheckNumberFormat"
var $ZodCheckBigIntFormat = /* @__PURE__ */ $constructor("$ZodCheckBigIntFormat", (inst, def) => {
$ZodCheck.init(inst, def);
const [minimum, maximum] = BIGINT_FORMAT_RANGES[def.format];
- inst._zod.onattach.push((inst2) => {
- const bag = inst2._zod.bag;
- bag.format = def.format;
- bag.minimum = minimum;
- bag.maximum = maximum;
- });
inst._zod.check = (payload) => {
const input2 = payload.value;
if (input2 < minimum) {
@@ -9185,11 +9182,6 @@ var $ZodCheckMaxSize = /* @__PURE__ */ $constructor("$ZodCheckMaxSize", (inst, d
var _a3;
$ZodCheck.init(inst, def);
(_a3 = inst._zod.def).when ?? (_a3.when = _whenHasSize);
- inst._zod.onattach.push((inst2) => {
- const curr = inst2._zod.bag.maximum ?? Number.POSITIVE_INFINITY;
- if (def.maximum < curr)
- inst2._zod.bag.maximum = def.maximum;
- });
inst._zod.check = (payload) => {
const input2 = payload.value;
const size = input2.size;
@@ -9210,11 +9202,6 @@ var $ZodCheckMinSize = /* @__PURE__ */ $constructor("$ZodCheckMinSize", (inst, d
var _a3;
$ZodCheck.init(inst, def);
(_a3 = inst._zod.def).when ?? (_a3.when = _whenHasSize);
- inst._zod.onattach.push((inst2) => {
- const curr = inst2._zod.bag.minimum ?? Number.NEGATIVE_INFINITY;
- if (def.minimum > curr)
- inst2._zod.bag.minimum = def.minimum;
- });
inst._zod.check = (payload) => {
const input2 = payload.value;
const size = input2.size;
@@ -9235,12 +9222,6 @@ var $ZodCheckSizeEquals = /* @__PURE__ */ $constructor("$ZodCheckSizeEquals", (i
var _a3;
$ZodCheck.init(inst, def);
(_a3 = inst._zod.def).when ?? (_a3.when = _whenHasSize);
- inst._zod.onattach.push((inst2) => {
- const bag = inst2._zod.bag;
- bag.minimum = def.size;
- bag.maximum = def.size;
- bag.size = def.size;
- });
inst._zod.check = (payload) => {
const input2 = payload.value;
const size = input2.size;
@@ -9262,11 +9243,6 @@ var $ZodCheckMaxLength = /* @__PURE__ */ $constructor("$ZodCheckMaxLength", (ins
var _a3;
$ZodCheck.init(inst, def);
(_a3 = inst._zod.def).when ?? (_a3.when = _whenHasLength);
- inst._zod.onattach.push((inst2) => {
- const curr = inst2._zod.bag.maximum ?? Number.POSITIVE_INFINITY;
- if (def.maximum < curr)
- inst2._zod.bag.maximum = def.maximum;
- });
inst._zod.check = (payload) => {
const input2 = payload.value;
const units = input2.length;
@@ -9289,11 +9265,6 @@ var $ZodCheckMinLength = /* @__PURE__ */ $constructor("$ZodCheckMinLength", (ins
var _a3;
$ZodCheck.init(inst, def);
(_a3 = inst._zod.def).when ?? (_a3.when = _whenHasLength);
- inst._zod.onattach.push((inst2) => {
- const curr = inst2._zod.bag.minimum ?? Number.NEGATIVE_INFINITY;
- if (def.minimum > curr)
- inst2._zod.bag.minimum = def.minimum;
- });
inst._zod.check = (payload) => {
const input2 = payload.value;
const units = input2.length;
@@ -9316,12 +9287,6 @@ var $ZodCheckLengthEquals = /* @__PURE__ */ $constructor("$ZodCheckLengthEquals"
var _a3;
$ZodCheck.init(inst, def);
(_a3 = inst._zod.def).when ?? (_a3.when = _whenHasLength);
- inst._zod.onattach.push((inst2) => {
- const bag = inst2._zod.bag;
- bag.minimum = def.length;
- bag.maximum = def.length;
- bag.length = def.length;
- });
inst._zod.check = (payload) => {
const input2 = payload.value;
const units = input2.length;
@@ -9344,14 +9309,6 @@ var $ZodCheckLengthEquals = /* @__PURE__ */ $constructor("$ZodCheckLengthEquals"
var $ZodCheckStringFormat = /* @__PURE__ */ $constructor("$ZodCheckStringFormat", (inst, def) => {
var _a3, _b;
$ZodCheck.init(inst, def);
- inst._zod.onattach.push((inst2) => {
- const bag = inst2._zod.bag;
- bag.format = def.format;
- if (def.pattern) {
- bag.patterns ?? (bag.patterns = /* @__PURE__ */ new Set());
- bag.patterns.add(def.pattern);
- }
- });
if (def.pattern)
(_a3 = inst._zod).check ?? (_a3.check = (payload) => {
def.pattern.lastIndex = 0;
@@ -9401,11 +9358,6 @@ var $ZodCheckIncludes = /* @__PURE__ */ $constructor("$ZodCheckIncludes", (inst,
const escapedRegex = escapeRegex(def.includes);
const pattern = new RegExp(typeof def.position === "number" ? `^.{${def.position},}${escapedRegex}` : escapedRegex);
def.pattern = pattern;
- inst._zod.onattach.push((inst2) => {
- const bag = inst2._zod.bag;
- bag.patterns ?? (bag.patterns = /* @__PURE__ */ new Set());
- bag.patterns.add(pattern);
- });
inst._zod.check = (payload) => {
if (payload.value.includes(def.includes, def.position))
return;
@@ -9424,11 +9376,6 @@ var $ZodCheckStartsWith = /* @__PURE__ */ $constructor("$ZodCheckStartsWith", (i
$ZodCheck.init(inst, def);
const pattern = new RegExp(`^${escapeRegex(def.prefix)}.*`);
def.pattern ?? (def.pattern = pattern);
- inst._zod.onattach.push((inst2) => {
- const bag = inst2._zod.bag;
- bag.patterns ?? (bag.patterns = /* @__PURE__ */ new Set());
- bag.patterns.add(pattern);
- });
inst._zod.check = (payload) => {
if (payload.value.startsWith(def.prefix))
return;
@@ -9447,11 +9394,6 @@ var $ZodCheckEndsWith = /* @__PURE__ */ $constructor("$ZodCheckEndsWith", (inst,
$ZodCheck.init(inst, def);
const pattern = new RegExp(`.*${escapeRegex(def.suffix)}$`);
def.pattern ?? (def.pattern = pattern);
- inst._zod.onattach.push((inst2) => {
- const bag = inst2._zod.bag;
- bag.patterns ?? (bag.patterns = /* @__PURE__ */ new Set());
- bag.patterns.add(pattern);
- });
inst._zod.check = (payload) => {
if (payload.value.endsWith(def.suffix))
return;
@@ -9485,12 +9427,37 @@ var $ZodCheckProperty = /* @__PURE__ */ $constructor("$ZodCheckProperty", (inst,
return;
};
});
+var $ZodCheckProperties = /* @__PURE__ */ $constructor("$ZodCheckProperties", (inst, def) => {
+ $ZodCheck.init(inst, def);
+ hide(inst, Symbol.iterator, function* () {
+ yield inst;
+ });
+ let entries;
+ inst._zod.check = (payload) => {
+ if (payload.value == null) {
+ payload.issues.push({ expected: "object", code: "invalid_type", input: payload.value, inst });
+ return void 0;
+ }
+ entries ?? (entries = Reflect.ownKeys(def.shape).map((key) => [key, def.shape[key]]));
+ const input2 = payload.value;
+ let proms;
+ for (const [key, schema] of entries) {
+ const result = schema._zod.run({ value: input2[key], issues: [] }, {});
+ if (result instanceof Promise) {
+ proms ?? (proms = []);
+ proms.push(result.then((result2) => handleCheckPropertyResult(result2, payload, key)));
+ } else {
+ handleCheckPropertyResult(result, payload, key);
+ }
+ }
+ if (proms)
+ return Promise.all(proms).then(() => void 0);
+ return void 0;
+ };
+});
var $ZodCheckMimeType = /* @__PURE__ */ $constructor("$ZodCheckMimeType", (inst, def) => {
$ZodCheck.init(inst, def);
const mimeSet = new Set(def.mime);
- inst._zod.onattach.push((inst2) => {
- inst2._zod.bag.mime = def.mime;
- });
inst._zod.check = (payload) => {
if (mimeSet.has(payload.value.type))
return;
@@ -9518,10 +9485,14 @@ var Doc = class {
this.args = args;
this.closed = closed;
}
+ // the compiler catches a child's throw and keeps writing into this doc, so the indent has to unwind with it
indented(fn) {
this.indent += 1;
- fn(this);
- this.indent -= 1;
+ try {
+ fn(this);
+ } finally {
+ this.indent -= 1;
+ }
}
write(arg) {
if (typeof arg === "function") {
@@ -9550,8 +9521,8 @@ ${content.join("\n")}
// node_modules/zod/v4/core/versions.js
var version = {
major: 4,
- minor: 5,
- patch: 4
+ minor: 6,
+ patch: 5
};
// node_modules/zod/v4/core/schemas.js
@@ -9664,15 +9635,22 @@ var $ZodType = /* @__PURE__ */ $constructor("$ZodType", (inst, def) => {
own(this, "~standard", value);
}
});
-var toStandardResult = (r) => r.success ? { value: r.data } : { issues: r.error?.issues };
+var toStandardResult = (r, ctx) => r.issues.length ? { issues: r.issues.map((iss) => finalizeIssue(iss, ctx, config())) } : { value: r.value };
+async function validateAsync2(inst, value) {
+ const ctx = { async: true };
+ return toStandardResult(await inst._zod.run({ value, issues: [] }, ctx), ctx);
+}
function standardProps(inst) {
return {
validate: (value) => {
+ const ctx = { async: false };
try {
- return toStandardResult(safeParse(inst, value));
+ const r = inst._zod.run({ value, issues: [] }, ctx);
+ if (!(r instanceof Promise))
+ return toStandardResult(r, ctx);
} catch (_2) {
- return safeParseAsync(inst, value).then(toStandardResult);
}
+ return validateAsync2(inst, value);
},
vendor: "zod",
version: 1
@@ -9680,7 +9658,7 @@ function standardProps(inst) {
}
var $ZodString = /* @__PURE__ */ $constructor("$ZodString", (inst, def) => {
$ZodType.init(inst, def);
- inst._zod.pattern = [...inst?._zod.bag?.patterns ?? []].pop() ?? string(inst._zod.bag);
+ inst._zod.pattern = def.pattern ?? anyString;
inst._zod.parse = (payload, _2) => {
if (def.coerce)
try {
@@ -9732,11 +9710,32 @@ var $ZodEmail = /* @__PURE__ */ $constructor("$ZodEmail", (inst, def) => {
});
var URL_BAD_FORMAT = 1;
var URL_UNPARSEABLE = 2;
+function canParseURL(input2) {
+ try {
+ if (typeof URL !== "undefined" && typeof URL.canParse === "function")
+ return URL.canParse(input2);
+ new URL(input2);
+ return true;
+ } catch {
+ return false;
+ }
+}
+function validateURL(trimmed, def) {
+ if (!("normalize" in def) && !("hostname" in def) && !("protocol" in def)) {
+ return canParseURL(trimmed) || URL_UNPARSEABLE;
+ }
+ return parseURLObject(trimmed, def);
+}
function parseURLObject(trimmed, def) {
if (!def.normalize && def.protocol?.source === httpProtocol.source && !/^https?:\/\//i.test(trimmed)) {
return URL_BAD_FORMAT;
}
try {
+ if (typeof URL !== "undefined") {
+ const URLStatic = URL;
+ if (typeof URLStatic.parse === "function")
+ return URLStatic.parse(trimmed) ?? URL_UNPARSEABLE;
+ }
return new URL(trimmed);
} catch {
return URL_UNPARSEABLE;
@@ -9759,7 +9758,7 @@ var $ZodURL = /* @__PURE__ */ $constructor("$ZodURL", (inst, def) => {
inst._zod.check = (payload) => {
try {
const trimmed = payload.value.trim();
- const url2 = parseURLObject(trimmed, def);
+ const url2 = validateURL(trimmed, def);
if (url2 === URL_BAD_FORMAT) {
payload.issues.push({
code: "invalid_format",
@@ -9781,6 +9780,10 @@ var $ZodURL = /* @__PURE__ */ $constructor("$ZodURL", (inst, def) => {
});
return;
}
+ if (url2 === true) {
+ payload.value = stripTabAndNewline(trimmed);
+ return;
+ }
if (def.hostname && !urlHostnameOk(url2, def.hostname)) {
payload.issues.push({
code: "invalid_format",
@@ -9849,12 +9852,6 @@ var $ZodKSUID = /* @__PURE__ */ $constructor("$ZodKSUID", (inst, def) => {
var $ZodISODateTime = /* @__PURE__ */ $constructor("$ZodISODateTime", (inst, def) => {
def.pattern ?? (def.pattern = datetime(def));
$ZodStringFormat.init(inst, def);
- if (def.local || def.precision === -1) {
- inst._zod.bag.laxFormat = true;
- inst._zod.onattach.push((s) => {
- s._zod.bag.laxFormat = true;
- });
- }
});
var $ZodISODate = /* @__PURE__ */ $constructor("$ZodISODate", (inst, def) => {
def.pattern ?? (def.pattern = date);
@@ -9871,23 +9868,16 @@ var $ZodISODuration = /* @__PURE__ */ $constructor("$ZodISODuration", (inst, def
var $ZodIPv4 = /* @__PURE__ */ $constructor("$ZodIPv4", (inst, def) => {
def.pattern ?? (def.pattern = ipv4);
$ZodStringFormat.init(inst, def);
- inst._zod.bag.format = `ipv4`;
});
var ipv6Alphabet = /^[0-9a-fA-F:.]+$/;
function isValidIPv6(value) {
if (!ipv6Alphabet.test(value))
return false;
- try {
- new URL(`http://[${value}]`);
- return true;
- } catch {
- return false;
- }
+ return canParseURL(`http://[${value}]`);
}
var $ZodIPv6 = /* @__PURE__ */ $constructor("$ZodIPv6", (inst, def) => {
def.pattern ?? (def.pattern = ipv6);
$ZodStringFormat.init(inst, def);
- inst._zod.bag.format = `ipv6`;
inst._zod.check = (payload) => {
if (!isValidIPv6(payload.value)) {
payload.issues.push({
@@ -9903,7 +9893,6 @@ var $ZodIPv6 = /* @__PURE__ */ $constructor("$ZodIPv6", (inst, def) => {
var $ZodMAC = /* @__PURE__ */ $constructor("$ZodMAC", (inst, def) => {
def.pattern ?? (def.pattern = mac(def.delimiter));
$ZodStringFormat.init(inst, def);
- inst._zod.bag.format = `mac`;
});
var $ZodCIDRv4 = /* @__PURE__ */ $constructor("$ZodCIDRv4", (inst, def) => {
def.pattern ?? (def.pattern = cidrv4);
@@ -9952,10 +9941,10 @@ function isValidBase64(data) {
return false;
}
}
+var base64Charset = /^[0-9a-zA-Z+/]*={0,2}$/;
var $ZodBase64 = /* @__PURE__ */ $constructor("$ZodBase64", (inst, def) => {
- def.pattern ?? (def.pattern = base64);
+ def.pattern ?? (def.pattern = base64Charset);
$ZodStringFormat.init(inst, def);
- inst._zod.bag.contentEncoding = "base64";
inst._zod.check = (payload) => {
if (isValidBase64(payload.value))
return;
@@ -9968,17 +9957,17 @@ var $ZodBase64 = /* @__PURE__ */ $constructor("$ZodBase64", (inst, def) => {
});
};
});
+var base64urlCharset = /^[A-Za-z0-9_-]*$/;
function isValidBase64URL(data) {
- if (!base64url.test(data))
+ if (!base64urlCharset.test(data))
return false;
const base643 = data.replace(/[-_]/g, (c) => c === "-" ? "+" : "/");
const padded = base643.padEnd(Math.ceil(base643.length / 4) * 4, "=");
return isValidBase64(padded);
}
var $ZodBase64URL = /* @__PURE__ */ $constructor("$ZodBase64URL", (inst, def) => {
- def.pattern ?? (def.pattern = base64url);
+ def.pattern ?? (def.pattern = base64urlCharset);
$ZodStringFormat.init(inst, def);
- inst._zod.bag.contentEncoding = "base64url";
inst._zod.check = (payload) => {
if (isValidBase64URL(payload.value))
return;
@@ -10001,7 +9990,7 @@ function isLuhnAlgo(digits) {
let bit = 1;
let sum = 0;
while (length) {
- const value = +digits[--length];
+ const value = digits.charCodeAt(--length) - 48;
bit ^= 1;
sum += bit ? [0, 2, 4, 6, 8, 1, 3, 5, 7, 9][value] : value;
}
@@ -10027,6 +10016,39 @@ var $ZodCreditCard = /* @__PURE__ */ $constructor("$ZodCreditCard", (inst, def)
});
};
});
+function isIso7064Mod97(iban3) {
+ let remainder = 0;
+ const len = iban3.length;
+ for (let i = 4; i < len; i++) {
+ const code = iban3.charCodeAt(i);
+ remainder = (code >= 65 ? remainder * 100 + (code - 55) : remainder * 10 + (code - 48)) % 97;
+ }
+ for (let i = 0; i < 4; i++) {
+ const code = iban3.charCodeAt(i);
+ remainder = (code >= 65 ? remainder * 100 + (code - 55) : remainder * 10 + (code - 48)) % 97;
+ }
+ return remainder === 1;
+}
+function isValidIBAN(input2) {
+ if (!iban.test(input2))
+ return false;
+ return isIso7064Mod97(input2);
+}
+var $ZodIBAN = /* @__PURE__ */ $constructor("$ZodIBAN", (inst, def) => {
+ def.pattern ?? (def.pattern = iban);
+ $ZodStringFormat.init(inst, def);
+ inst._zod.check = (payload) => {
+ if (isValidIBAN(payload.value))
+ return;
+ payload.issues.push({
+ code: "invalid_format",
+ format: "iban",
+ input: payload.value,
+ inst,
+ continue: !def.abort
+ });
+ };
+});
function isValidJWT(token, algorithm = null) {
try {
const tokensParts = token.split(".");
@@ -10077,7 +10099,7 @@ var $ZodCustomStringFormat = /* @__PURE__ */ $constructor("$ZodCustomStringForma
});
var $ZodNumber = /* @__PURE__ */ $constructor("$ZodNumber", (inst, def) => {
$ZodType.init(inst, def);
- inst._zod.pattern = inst._zod.bag.pattern ?? number;
+ inst._zod.pattern = number;
inst._zod.parse = (payload, _ctx) => {
if (def.coerce)
try {
@@ -10279,6 +10301,7 @@ var $ZodArray = /* @__PURE__ */ $constructor("$ZodArray", (inst, def) => {
}
payload.value = memo2 ? memo2.alloc(inst, payload, Array(input2.length), ctx) : Array(input2.length);
const proms = [];
+ const abortEarly = ctx?.abortEarly;
for (let i = 0; i < input2.length; i++) {
const item = input2[i];
const result = def.element._zod.run({
@@ -10289,6 +10312,8 @@ var $ZodArray = /* @__PURE__ */ $constructor("$ZodArray", (inst, def) => {
proms.push(result.then((result2) => handleArrayResult(result2, payload, i)));
} else {
handleArrayResult(result, payload, i);
+ if (abortEarly && result.issues.length !== 0 && aborted(result))
+ break;
}
}
if (proms.length) {
@@ -10321,7 +10346,7 @@ function handlePropertyResult(result, final, key, input2, optin, optout) {
return;
}
if (result.value === void 0) {
- if (isPresent) {
+ if (isPresent || optin === "defaulted" && !isOptionalOut) {
final.value[key] = void 0;
}
} else {
@@ -10350,14 +10375,20 @@ function normalizeDef(def) {
optionalKeys: new Set(okeys)
};
}
-function handleCatchall(proms, input2, payload, ctx, def, inst) {
+function handleCatchall(proms, input2, payload, ctx, def, inst, abortEarly) {
const unrecognized = [];
const keySet = def.keySet;
const _catchall = def.catchall._zod;
const t = _catchall.def.type;
const optin = _catchall.optin;
const optout = _catchall.optout;
+ let seen = 0;
for (const key in input2) {
+ if (abortEarly && payload.issues.length !== seen) {
+ if (aborted(payload, seen))
+ break;
+ seen = payload.issues.length;
+ }
if (keySet.has(key))
continue;
if (key === "__proto__") {
@@ -10392,23 +10423,19 @@ function handleCatchall(proms, input2, payload, ctx, def, inst) {
return payload;
});
}
-var propShapes = /* @__PURE__ */ new WeakMap();
var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
$ZodType.init(inst, def);
const desc = Object.getOwnPropertyDescriptor(def, "shape");
- if (!desc?.get) {
- const sh = def.shape;
- propShapes.set(def, sh);
- Object.defineProperty(def, "shape", {
- get: () => {
- const newSh = { ...sh };
- Object.defineProperty(def, "shape", {
- value: newSh
- });
- propShapes.set(def, newSh);
- return newSh;
- }
- });
+ const sh = desc?.get ? desc.get.raw : def.shape ?? {};
+ if (sh) {
+ const get = () => {
+ const newSh = { ...sh };
+ Object.defineProperty(def, "shape", { value: newSh });
+ get.raw = newSh;
+ return newSh;
+ };
+ get.raw = sh;
+ Object.defineProperty(def, "shape", { get });
}
const _normalized = cached(() => normalizeDef(def));
defineLazyInternal(inst, "propValues", (zod) => {
@@ -10448,7 +10475,14 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
payload.value = memo2 ? memo2.alloc(inst, payload, {}, ctx) : {};
const proms = [];
const shape = value.shape;
+ const abortEarly = ctx?.abortEarly;
+ let seen = payload.issues.length;
for (const key of value.allKeys) {
+ if (abortEarly && payload.issues.length !== seen) {
+ if (aborted(payload, seen))
+ break;
+ seen = payload.issues.length;
+ }
if (key === "__proto__")
continue;
const el = shape[key];
@@ -10464,7 +10498,7 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
if (!catchall) {
return proms.length ? Promise.all(proms).then(() => payload) : payload;
}
- return handleCatchall(proms, input2, payload, ctx, _normalized.value, inst);
+ return handleCatchall(proms, input2, payload, ctx, _normalized.value, inst, abortEarly === true);
};
});
var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) => {
@@ -10478,10 +10512,16 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
const doc = new Doc(["payload", "ctx"], { shape, inst, memo: memo2, syms });
const parseStr = (k2) => `shape[${k2}]._zod.run({ value: input[${k2}], issues: [] }, ctx)`;
const prefixStr = (id, k2) => `
+ let ${id}_ab = false;
for (let i = 0; i < ${id}.issues.length; i++) {
const iss = ${id}.issues[i];
iss.path = iss.path ? [${k2}, ...iss.path] : [${k2}];
payload.issues.push(iss);
+ if (iss.continue !== true) ${id}_ab = true;
+ }
+ if (${id}_ab && ctx && ctx.abortEarly) {
+ payload.value = newResult;
+ return payload;
}`;
doc.write(`const input = payload.value;`);
const ids = /* @__PURE__ */ Object.create(null);
@@ -10527,6 +10567,10 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
input: undefined,
path: [${k2}]
});
+ if (ctx && ctx.abortEarly) {
+ payload.value = newResult;
+ return payload;
+ }
}
if (${id}_present) {
@@ -10538,16 +10582,16 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
doc.write(`
if (${id}.issues.length) {${prefixStr(id, k2)}
}
-
- if (${id}.value === undefined) {
- if (${isPresent}) {
- newResult[${k2}] = undefined;
- }
+ `);
+ if (optin === "defaulted") {
+ doc.write(`newResult[${k2}] = ${id}.value;`);
} else {
+ doc.write(`
+ if (${id}.value !== undefined || ${isPresent}) {
newResult[${k2}] = ${id}.value;
}
-
`);
+ }
}
}
doc.write(`payload.value = newResult;`);
@@ -10579,7 +10623,7 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
payload = fastpass(payload, ctx);
if (!catchall)
return payload;
- return handleCatchall([], input2, payload, ctx, value, inst);
+ return handleCatchall([], input2, payload, ctx, value, inst, ctx?.abortEarly === true);
}
return superParse(payload, ctx);
};
@@ -10711,16 +10755,31 @@ function getDiscriminatedOption(union2, value) {
const internals = union2._zod;
let map2 = internals.bag.optionsMap;
if (!map2) {
- map2 = /* @__PURE__ */ new Map();
- const { options, discriminator } = internals.def;
- for (const option of options) {
- for (const v2 of option._zod.propValues?.[discriminator] ?? [])
- if (!map2.has(v2))
- map2.set(v2, option);
- }
+ map2 = discriminatorMap(internals.def);
internals.bag.optionsMap = map2;
}
- return map2.get(value);
+ const option = map2.get(value);
+ if (option === null)
+ throw new Error(`Ambiguous discriminator value "${String(value)}"`);
+ return option;
+}
+function discriminatorMap(def) {
+ const map2 = /* @__PURE__ */ new Map();
+ for (const option of def.options) {
+ const values = option._zod.propValues?.[def.discriminator];
+ if (!values || values.size === 0)
+ throw new Error(`Invalid discriminated union option at index "${def.options.indexOf(option)}"`);
+ for (const value of values) {
+ if (map2.has(value)) {
+ if (value !== void 0)
+ throw new Error(`Duplicate discriminator value "${String(value)}"`);
+ map2.set(value, null);
+ } else {
+ map2.set(value, option);
+ }
+ }
+ }
+ return map2;
}
var $ZodDiscriminatedUnion = /* @__PURE__ */ $constructor("$ZodDiscriminatedUnion", (inst, def) => {
def.inclusive = false;
@@ -10728,10 +10787,13 @@ var $ZodDiscriminatedUnion = /* @__PURE__ */ $constructor("$ZodDiscriminatedUnio
const _super = inst._zod.parse;
defineLazyInternal(inst, "propValues", (zod) => {
const propValues = {};
+ let undefinedCount = 0;
for (const option of zod.def.options) {
const pv = option._zod.propValues;
if (!pv || Object.keys(pv).length === 0)
throw new Error(`Invalid discriminated union option at index "${zod.def.options.indexOf(option)}"`);
+ if (pv[zod.def.discriminator]?.has(void 0))
+ undefinedCount++;
for (const [k2, v2] of Object.entries(pv)) {
if (!Object.prototype.hasOwnProperty.call(propValues, k2)) {
assignProp(propValues, k2, /* @__PURE__ */ new Set());
@@ -10741,30 +10803,17 @@ var $ZodDiscriminatedUnion = /* @__PURE__ */ $constructor("$ZodDiscriminatedUnio
}
}
}
+ if (!zod.def.unionFallback && undefinedCount > 1)
+ propValues[zod.def.discriminator]?.delete(void 0);
return propValues;
});
def.options.forEach((option, i) => {
- const propShape = propShapes.get(option._zod.def);
+ const propShape = rawShape(option._zod.def);
if (propShape && !Object.prototype.hasOwnProperty.call(propShape, def.discriminator)) {
throw new Error(`Invalid discriminated union option at index "${i}"`);
}
});
- const disc = cached(() => {
- const opts = def.options;
- const map2 = /* @__PURE__ */ new Map();
- for (const o of opts) {
- const values = o._zod.propValues?.[def.discriminator];
- if (!values || values.size === 0)
- throw new Error(`Invalid discriminated union option at index "${def.options.indexOf(o)}"`);
- for (const v2 of values) {
- if (map2.has(v2)) {
- throw new Error(`Duplicate discriminator value "${String(v2)}"`);
- }
- map2.set(v2, o);
- }
- }
- return map2;
- });
+ const disc = cached(() => discriminatorMap(def));
inst._zod.parse = (payload, ctx) => {
const input2 = payload.value;
if (!isObject(input2)) {
@@ -10776,8 +10825,9 @@ var $ZodDiscriminatedUnion = /* @__PURE__ */ $constructor("$ZodDiscriminatedUnio
});
return payload;
}
- const opt = disc.value.get(input2?.[def.discriminator]);
- if (opt) {
+ const value = input2?.[def.discriminator];
+ const opt = disc.value.get(value);
+ if (opt && (value !== void 0 || ctx.direction !== "backward")) {
return opt._zod.run(payload, ctx);
}
if (def.unionFallback || ctx.direction === "backward") {
@@ -10788,7 +10838,7 @@ var $ZodDiscriminatedUnion = /* @__PURE__ */ $constructor("$ZodDiscriminatedUnio
errors: [],
note: "No matching discriminator",
discriminator: def.discriminator,
- options: Array.from(disc.value.keys()),
+ options: Array.from(disc.value.keys()).filter((value2) => disc.value.get(value2) !== null),
input: input2,
path: [def.discriminator],
inst
@@ -10954,6 +11004,8 @@ var $ZodTuple = /* @__PURE__ */ $constructor("$ZodTuple", (inst, def) => {
}
}
const itemResults = new Array(items.length);
+ const abortEarly = def.rest ? ctx?.abortEarly : void 0;
+ let itemAborted = false;
for (let i = 0; i < items.length; i++) {
const r = items[i]._zod.run({ value: input2[i], issues: [] }, ctx);
if (r instanceof Promise) {
@@ -10962,12 +11014,20 @@ var $ZodTuple = /* @__PURE__ */ $constructor("$ZodTuple", (inst, def) => {
}));
} else {
itemResults[i] = r;
+ if (abortEarly && !itemAborted && r.issues.length)
+ itemAborted = aborted(r);
}
}
- if (def.rest) {
+ if (def.rest && !itemAborted) {
let i = items.length - 1;
const rest = input2.slice(items.length);
+ let seen = payload.issues.length;
for (const el of rest) {
+ if (abortEarly && payload.issues.length !== seen) {
+ if (aborted(payload, seen))
+ break;
+ seen = payload.issues.length;
+ }
i++;
const result = def.rest._zod.run({ value: el, issues: [] }, ctx);
if (result instanceof Promise) {
@@ -11195,7 +11255,14 @@ var $ZodMap = /* @__PURE__ */ $constructor("$ZodMap", (inst, def) => {
}
const proms = [];
payload.value = memo2 ? memo2.alloc(inst, payload, /* @__PURE__ */ new Map(), ctx) : /* @__PURE__ */ new Map();
+ const abortEarly = ctx?.abortEarly;
+ let seen = payload.issues.length;
for (const [key, value] of input2) {
+ if (abortEarly && payload.issues.length !== seen) {
+ if (aborted(payload, seen))
+ break;
+ seen = payload.issues.length;
+ }
const keyResult = def.keyType._zod.run({ value: key, issues: [] }, ctx);
const valueResult = def.valueType._zod.run({ value, issues: [] }, ctx);
if (keyResult instanceof Promise || valueResult instanceof Promise) {
@@ -11258,7 +11325,14 @@ var $ZodSet = /* @__PURE__ */ $constructor("$ZodSet", (inst, def) => {
}
const proms = [];
payload.value = memo2 ? memo2.alloc(inst, payload, /* @__PURE__ */ new Set(), ctx) : /* @__PURE__ */ new Set();
+ const abortEarly = ctx?.abortEarly;
+ let seen = payload.issues.length;
for (const item of input2) {
+ if (abortEarly && payload.issues.length !== seen) {
+ if (aborted(payload, seen))
+ break;
+ seen = payload.issues.length;
+ }
const result = def.valueType._zod.run({ value: item, issues: [] }, ctx);
if (result instanceof Promise) {
proms.push(result.then((result2) => handleSetResult(result2, payload)));
@@ -11281,8 +11355,10 @@ var $ZodEnum = /* @__PURE__ */ $constructor("$ZodEnum", (inst, def) => {
const values = getEnumValues(def.entries);
const valuesSet = new Set(values);
inst._zod.values = valuesSet;
- const patternValues = values.filter((k2) => propertyKeyTypes.has(typeof k2));
- inst._zod.pattern = new RegExp(patternValues.length ? `^(${patternValues.map((o) => escapeRegex(o.toString())).join("|")})$` : "^[^\\s\\S]$");
+ defineLazyInternal(inst, "pattern", (zod) => {
+ const patternValues = getEnumValues(zod.def.entries).filter((k2) => propertyKeyTypes.has(typeof k2));
+ return new RegExp(patternValues.length ? `^(${patternValues.map((o) => escapeRegex(o.toString())).join("|")})$` : "^[^\\s\\S]$");
+ });
inst._zod.parse = (payload, _ctx) => {
const input2 = payload.value;
if (valuesSet.has(input2)) {
@@ -11301,7 +11377,10 @@ var $ZodLiteral = /* @__PURE__ */ $constructor("$ZodLiteral", (inst, def) => {
$ZodType.init(inst, def);
const values = new Set(def.values);
inst._zod.values = values;
- inst._zod.pattern = new RegExp(def.values.length ? `^(${def.values.map((o) => typeof o === "string" ? escapeRegex(o) : o ? escapeRegex(o.toString()) : String(o)).join("|")})$` : "^[^\\s\\S]$");
+ defineLazyInternal(inst, "pattern", (zod) => {
+ const vals = zod.def.values;
+ return new RegExp(vals.length ? `^(${vals.map((o) => typeof o === "string" ? escapeRegex(o) : o ? escapeRegex(o.toString()) : String(o)).join("|")})$` : "^[^\\s\\S]$");
+ });
inst._zod.parse = (payload, _ctx) => {
const input2 = payload.value;
if (values.has(input2)) {
@@ -11639,20 +11718,62 @@ function handleReadonlyResult(payload) {
payload.value = Object.freeze(payload.value);
return payload;
}
+function leafPattern(schema) {
+ const def = schema._zod.def;
+ let pattern = def.pattern;
+ let isInt = !!def.format?.includes("int");
+ let minimum;
+ let maximum;
+ for (const ch of def.checks ?? []) {
+ const d2 = ch._zod.def;
+ if (d2.pattern)
+ pattern = d2.pattern;
+ isInt || (isInt = !!d2.format?.includes("int"));
+ const lo = d2.minimum ?? d2.length;
+ const hi = d2.maximum ?? d2.length;
+ if (lo !== void 0 && (minimum === void 0 || lo > minimum))
+ minimum = lo;
+ if (hi !== void 0 && (maximum === void 0 || hi < maximum))
+ maximum = hi;
+ }
+ if (pattern)
+ return pattern.source;
+ if (minimum !== void 0 && maximum !== void 0 && minimum > maximum)
+ return "(?!)";
+ if (minimum !== void 0 || maximum !== void 0)
+ return string({ minimum, maximum }).source;
+ const own2 = schema._zod.pattern;
+ return (isInt && own2 === number ? integer : own2)?.source;
+}
+function partPattern(schema) {
+ const def = schema._zod.def;
+ const own2 = schema._zod.pattern?.source;
+ const inner = def.innerType ?? schema._zod.innerType;
+ if (inner) {
+ const before = inner._zod.pattern?.source;
+ const after = partPattern(inner);
+ if (own2 && before && after && after !== before) {
+ return own2.replace(cleanRegex(before), () => cleanRegex(after));
+ }
+ return own2;
+ }
+ if (def.options) {
+ const sources = def.options.map(partPattern);
+ if (sources.every(Boolean))
+ return `^(${sources.map((s) => cleanRegex(s)).join("|")})$`;
+ }
+ return leafPattern(schema);
+}
var $ZodTemplateLiteral = /* @__PURE__ */ $constructor("$ZodTemplateLiteral", (inst, def) => {
$ZodType.init(inst, def);
const regexParts = [];
for (const part of def.parts) {
if (typeof part === "object" && part !== null) {
- if (!part._zod.pattern) {
+ const source = partPattern(part);
+ if (!source) {
throw new Error(`Invalid template literal part, no pattern found: ${[...part._zod.traits].shift()}`);
}
- const source = part._zod.pattern instanceof RegExp ? part._zod.pattern.source : part._zod.pattern;
- if (!source)
- throw new Error(`Invalid template literal part: ${part._zod.traits}`);
- const start = source.startsWith("^") ? 1 : 0;
- const end = source.endsWith("$") ? source.length - 1 : source.length;
- regexParts.push(source.slice(start, end));
+ regexParts.push(cleanRegex(source));
} else if (part === null || primitiveTypes.has(typeof part)) {
regexParts.push(escapeRegex(`${part}`));
} else {
@@ -11827,28 +11948,53 @@ var $ZodCyclicError = class extends Error {
};
var STATE = "~memo";
var NO_ISSUES = [];
+function isRef(value) {
+ return value !== null && typeof value === "object";
+}
function cloneIssues(issues) {
return issues.map((iss) => iss.path ? { ...iss, path: iss.path.slice() } : { ...iss });
}
var recursive = /* @__PURE__ */ new WeakMap();
-function isRecursive(inst, stack) {
+var NONE = 0;
+var ASSUMED = 1;
+var PROVEN = 2;
+function isRecursive(inst, stack, resolve) {
const cached2 = recursive.get(inst);
if (cached2 !== void 0)
- return cached2;
+ return cached2 ? PROVEN : NONE;
if (stack.has(inst))
- return true;
+ return PROVEN;
stack.add(inst);
- let result = false;
+ let result = NONE;
const check2 = (child) => {
- if (!result && child?._zod && isRecursive(child, stack))
- result = true;
+ if (result !== PROVEN && child?._zod) {
+ const answer = isRecursive(child, stack, resolve);
+ if (answer > result)
+ result = answer;
+ }
+ };
+ const shape = (sh, spread) => {
+ let answer = NONE;
+ for (const key of Reflect.ownKeys(sh)) {
+ const desc = Object.getOwnPropertyDescriptor(sh, key);
+ if (spread && !desc.enumerable)
+ continue;
+ const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve) : NONE;
+ if (child > answer)
+ answer = child;
+ }
+ return answer;
+ };
+ const merge2 = (answer) => {
+ if (answer > result)
+ result = answer;
};
const def = inst._zod.def;
const kind = def.type;
switch (kind) {
case "object": {
- for (const key of Reflect.ownKeys(def.shape))
- check2(def.shape[key]);
+ const raw = rawShape(def);
+ merge2(raw ? shape(raw, true) : ASSUMED);
check2(def.catchall);
break;
}
@@ -11895,10 +12041,12 @@ function isRecursive(inst, stack) {
check2(def.input);
check2(def.output);
break;
- // reading `_zod.innerType` resolves the getter once and caches it
- case "lazy":
- check2(inst._zod.innerType);
+ // `$ZodLazy` caches its inner on the def, so a resolved edge is followed exactly
+ case "lazy": {
+ const inner = def._cachedInner ?? (resolve ? inst._zod.innerType : void 0);
+ merge2(inner ? isRecursive(inner, stack, false) : ASSUMED);
break;
+ }
// a leaf by choice: `parts` are regex fragments, not data positions
case "template_literal":
// leaves
@@ -11940,16 +12088,20 @@ function isRecursive(inst, stack) {
}
}
stack.delete(inst);
- recursive.set(inst, result);
- return result;
+ return settle(inst, result);
+}
+function settle(inst, answer) {
+ if (answer !== ASSUMED)
+ recursive.set(inst, answer === PROVEN);
+ return answer;
}
function isRecursiveSchema(inst) {
- return isRecursive(inst, /* @__PURE__ */ new Set());
+ return isRecursive(inst, /* @__PURE__ */ new Set(), true) !== NONE;
}
function bucketFor(state, inst) {
let bucket = state.buckets.get(inst);
if (!bucket) {
- bucket = /* @__PURE__ */ new Map();
+ bucket = /* @__PURE__ */ new WeakMap();
state.buckets.set(inst, bucket);
}
return bucket;
@@ -11985,6 +12137,7 @@ var memo = {
attach(inst) {
var _a3;
let isRecursiveInst;
+ let rechecked = false;
let lastCtx;
let lastBucket;
(_a3 = inst._zod).deferred ?? (_a3.deferred = []);
@@ -11992,20 +12145,24 @@ var memo = {
const base = inst._zod.parse;
const wrapped = (payload, ctx) => {
if (isRecursiveInst === void 0) {
- isRecursiveInst = isRecursive(inst, /* @__PURE__ */ new Set());
- if (!isRecursiveInst) {
+ const walked = isRecursive(inst, /* @__PURE__ */ new Set(), false);
+ if (walked === NONE) {
inst._zod.parse = base;
if (inst._zod.run === wrapped)
inst._zod.run = base;
return base(payload, ctx);
}
+ if (walked === PROVEN || rechecked)
+ isRecursiveInst = true;
+ else
+ rechecked = true;
}
const input2 = payload.value;
- if (input2 === null || typeof input2 !== "object")
+ if (!isRef(input2))
return base(payload, ctx);
let state = ctx[STATE];
if (!state) {
- state = { buckets: /* @__PURE__ */ new Map(), backEdges: void 0 };
+ state = { buckets: /* @__PURE__ */ new WeakMap(), backEdges: void 0 };
ctx[STATE] = state;
}
let bucket;
@@ -12024,7 +12181,7 @@ var memo = {
payload.issues.push(...cloneIssues(hit.issues));
} else {
payload.memo = true;
- state.backEdges ?? (state.backEdges = /* @__PURE__ */ new Set());
+ state.backEdges ?? (state.backEdges = /* @__PURE__ */ new WeakSet());
state.backEdges.add(hit.value);
}
return payload;
@@ -12056,7 +12213,7 @@ function memoizer() {
}
function isBackEdge(ctx, value) {
const backEdges = ctx[STATE]?.backEdges;
- return backEdges !== void 0 && value !== null && typeof value === "object" && backEdges.has(value);
+ return backEdges !== void 0 && isRef(value) && backEdges.has(value);
}
// node_modules/zod/v4/locales/index.js
@@ -12113,6 +12270,7 @@ __export(locales_exports, {
sl: () => sl_default,
sv: () => sv_default,
ta: () => ta_default,
+ tg: () => tg_default,
th: () => th_default,
tk: () => tk_default,
tr: () => tr_default,
@@ -12167,6 +12325,8 @@ var error = () => {
json_string: "\u0646\u064E\u0635 \u0639\u0644\u0649 \u0647\u064A\u0626\u0629 JSON",
e164: "\u0631\u0642\u0645 \u0647\u0627\u062A\u0641 \u0628\u0645\u0639\u064A\u0627\u0631 E.164",
credit_card: "\u0631\u0642\u0645 \u0628\u0637\u0627\u0642\u0629 \u0627\u0644\u0627\u0626\u062A\u0645\u0627\u0646",
+ currency_code: "\u0631\u0645\u0632 \u0627\u0644\u0639\u0645\u0644\u0629",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "\u0645\u062F\u062E\u0644"
};
@@ -12277,6 +12437,8 @@ var error2 = () => {
json_string: "JSON string",
e164: "E.164 number",
credit_card: "kredit kart\u0131 n\xF6mr\u0259si",
+ currency_code: "valyuta kodu",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "input"
};
@@ -12436,6 +12598,8 @@ var error3 = () => {
json_string: "JSON \u0440\u0430\u0434\u043E\u043A",
e164: "\u043D\u0443\u043C\u0430\u0440 E.164",
credit_card: "\u043D\u0443\u043C\u0430\u0440 \u043A\u0440\u044D\u0434\u044B\u0442\u043D\u0430\u0439 \u043A\u0430\u0440\u0442\u044B",
+ currency_code: "\u043A\u043E\u0434 \u0432\u0430\u043B\u044E\u0442\u044B",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "\u0443\u0432\u043E\u0434"
};
@@ -12553,6 +12717,8 @@ var error4 = () => {
json_string: "JSON \u043D\u0438\u0437",
e164: "E.164 \u043D\u043E\u043C\u0435\u0440",
credit_card: "\u043D\u043E\u043C\u0435\u0440 \u043D\u0430 \u043A\u0440\u0435\u0434\u0438\u0442\u043D\u0430 \u043A\u0430\u0440\u0442\u0430",
+ currency_code: "\u043A\u043E\u0434 \u043D\u0430 \u0432\u0430\u043B\u0443\u0442\u0430",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "\u0432\u0445\u043E\u0434"
};
@@ -12677,6 +12843,8 @@ var error5 = () => {
json_string: "JSON \u09B8\u09CD\u099F\u09CD\u09B0\u09BF\u0982",
e164: "E.164 \u09A8\u09AE\u09CD\u09AC\u09B0",
credit_card: "\u0995\u09CD\u09B0\u09C7\u09A1\u09BF\u099F \u0995\u09BE\u09B0\u09CD\u09A1 \u09A8\u09AE\u09CD\u09AC\u09B0",
+ currency_code: "\u09AE\u09C1\u09A6\u09CD\u09B0\u09BE \u0995\u09CB\u09A1",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "\u0987\u09A8\u09AA\u09C1\u099F"
};
@@ -12789,6 +12957,8 @@ var error6 = () => {
json_string: "cadena JSON",
e164: "n\xFAmero E.164",
credit_card: "n\xFAmero de targeta de cr\xE8dit",
+ currency_code: "codi de moneda",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "entrada"
};
@@ -12901,6 +13071,8 @@ var error7 = () => {
json_string: "\u062F\u06D5\u0642\u06CC JSON",
e164: "\u0698\u0645\u0627\u0631\u06D5\u06CC E.164",
credit_card: "\u0698\u0645\u0627\u0631\u06D5\u06CC \u06A9\u0627\u0631\u062A\u06CC \u06A9\u0631\u06CE\u062F\u06CC\u062A",
+ currency_code: "\u06A9\u06C6\u062F\u06CC \u062F\u0631\u0627\u0648",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "\u062A\u06CE\u06A9\u0631\u062F\u06D5"
};
@@ -13032,6 +13204,8 @@ var error8 = () => {
json_string: "\u0159et\u011Bzec ve form\xE1tu JSON",
e164: "\u010D\xEDslo E.164",
credit_card: "\u010D\xEDslo kreditn\xED karty",
+ currency_code: "k\xF3d m\u011Bny",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "vstup"
};
@@ -13147,6 +13321,8 @@ var error9 = () => {
json_string: "JSON-streng",
e164: "E.164-nummer",
credit_card: "kreditkortnummer",
+ currency_code: "valutakode",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "input"
};
@@ -13266,6 +13442,8 @@ var error10 = () => {
json_string: "JSON-String",
e164: "E.164-Nummer",
credit_card: "Kreditkartennummer",
+ currency_code: "W\xE4hrungscode",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "Eingabe"
};
@@ -13378,6 +13556,8 @@ var error11 = () => {
json_string: "\u03C3\u03C5\u03BC\u03B2\u03BF\u03BB\u03BF\u03C3\u03B5\u03B9\u03C1\u03AC JSON",
e164: "\u03B1\u03C1\u03B9\u03B8\u03BC\u03CC\u03C2 E.164",
credit_card: "\u03B1\u03C1\u03B9\u03B8\u03BC\u03CC\u03C2 \u03C0\u03B9\u03C3\u03C4\u03C9\u03C4\u03B9\u03BA\u03AE\u03C2 \u03BA\u03AC\u03C1\u03C4\u03B1\u03C2",
+ currency_code: "\u03BA\u03C9\u03B4\u03B9\u03BA\u03CC\u03C2 \u03BD\u03BF\u03BC\u03AF\u03C3\u03BC\u03B1\u03C4\u03BF\u03C2",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "\u03B5\u03AF\u03C3\u03BF\u03B4\u03BF\u03C2"
};
@@ -13488,7 +13668,9 @@ var error12 = () => {
base64url: "base64url-encoded string",
json_string: "JSON string",
e164: "E.164 number",
+ currency_code: "currency code",
credit_card: "credit card number",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "input"
};
@@ -13612,6 +13794,8 @@ var error13 = () => {
json_string: "JSON-karaktraro",
e164: "E.164-nombro",
credit_card: "kreditkarta numero",
+ currency_code: "valuta kodo",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "enigo"
};
@@ -13724,6 +13908,8 @@ var error14 = () => {
json_string: "cadena JSON",
e164: "n\xFAmero E.164",
credit_card: "n\xFAmero de tarjeta de cr\xE9dito",
+ currency_code: "c\xF3digo de moneda",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "entrada"
};
@@ -13860,6 +14046,8 @@ var error15 = () => {
json_string: "JSON \u0631\u0634\u062A\u0647",
e164: "E.164 \u0639\u062F\u062F",
credit_card: "\u0634\u0645\u0627\u0631\u0647 \u06A9\u0627\u0631\u062A \u0627\u0639\u062A\u0628\u0627\u0631\u06CC",
+ currency_code: "\u06A9\u062F \u0627\u0631\u0632",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "\u0648\u0631\u0648\u062F\u06CC"
};
@@ -13982,6 +14170,8 @@ var error16 = () => {
json_string: "JSON-merkkijono",
e164: "E.164-luku",
credit_card: "luottokortin numero",
+ currency_code: "valuuttakoodi",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "templaattimerkkijono"
};
@@ -14093,6 +14283,8 @@ var error17 = () => {
json_string: "cha\xEEne de caract\xE8res JSON",
e164: "num\xE9ro au format E.164",
credit_card: "num\xE9ro de carte de cr\xE9dit",
+ currency_code: "code de devise",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "entr\xE9e"
};
@@ -14222,6 +14414,8 @@ var error18 = () => {
json_string: "cha\xEEne JSON",
e164: "num\xE9ro E.164",
credit_card: "num\xE9ro de carte de cr\xE9dit",
+ currency_code: "code de devise",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "entr\xE9e"
};
@@ -14333,6 +14527,8 @@ var error19 = () => {
json_string: "JSON \u0AB8\u0ACD\u0A9F\u0ACD\u0AB0\u0ABF\u0A82\u0A97",
e164: "E.164 \u0AA8\u0A82\u0AAC\u0AB0",
credit_card: "\u0A95\u0ACD\u0AB0\u0AC7\u0AA1\u0ABF\u0A9F \u0A95\u0ABE\u0AB0\u0ACD\u0AA1 \u0AA8\u0A82\u0AAC\u0AB0",
+ currency_code: "\u0A9A\u0AB2\u0AA3 \u0A95\u0ACB\u0AA1",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "\u0A87\u0AA8\u0AAA\u0AC1\u0A9F"
};
@@ -14481,6 +14677,8 @@ var error20 = () => {
json_string: { label: "\u05DE\u05D7\u05E8\u05D5\u05D6\u05EA JSON", gender: "f" },
e164: { label: "\u05DE\u05E1\u05E4\u05E8 E.164", gender: "m" },
credit_card: { label: "\u05DE\u05E1\u05E4\u05E8 \u05DB\u05E8\u05D8\u05D9\u05E1 \u05D0\u05E9\u05E8\u05D0\u05D9", gender: "m" },
+ currency_code: { label: "\u05E7\u05D5\u05D3 \u05DE\u05D8\u05D1\u05E2", gender: "m" },
+ iban: { label: "IBAN", gender: "m" },
jwt: { label: "JWT", gender: "m" },
template_literal: { label: "\u05E7\u05DC\u05D8", gender: "m" },
ends_with: { label: "\u05E7\u05DC\u05D8", gender: "m" },
@@ -14645,6 +14843,8 @@ var error21 = () => {
json_string: "JSON \u0938\u094D\u091F\u094D\u0930\u093F\u0902\u0917",
e164: "E.164 \u0938\u0902\u0916\u094D\u092F\u093E",
credit_card: "\u0915\u094D\u0930\u0947\u0921\u093F\u091F \u0915\u093E\u0930\u094D\u0921 \u0938\u0902\u0916\u094D\u092F\u093E",
+ currency_code: "\u092E\u0941\u0926\u094D\u0930\u093E \u0915\u094B\u0921",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "\u0907\u0928\u092A\u0941\u091F"
};
@@ -14754,6 +14954,8 @@ var error22 = () => {
json_string: "JSON tekst",
e164: "E.164 broj",
credit_card: "broj kreditne kartice",
+ currency_code: "kod valute",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "unos"
};
@@ -14880,6 +15082,8 @@ var error23 = () => {
json_string: "JSON string",
e164: "E.164 sz\xE1m",
credit_card: "hitelk\xE1rtyasz\xE1m",
+ currency_code: "p\xE9nznemk\xF3d",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "bemenet"
};
@@ -15032,6 +15236,8 @@ var error24 = () => {
json_string: "JSON \u057F\u0578\u0572",
e164: "E.164 \u0570\u0561\u0574\u0561\u0580",
credit_card: "\u056F\u0580\u0565\u0564\u056B\u057F \u0584\u0561\u0580\u057F\u056B \u0570\u0561\u0574\u0561\u0580",
+ currency_code: "\u0561\u0580\u056A\u0578\u0582\u0575\u0569\u056B \u056F\u0578\u0564",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "\u0574\u0578\u0582\u057F\u0584"
};
@@ -15149,6 +15355,8 @@ var error25 = () => {
json_string: "string JSON",
e164: "angka E.164",
credit_card: "nomor kartu kredit",
+ currency_code: "kode mata uang",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "input"
};
@@ -15259,6 +15467,8 @@ var error26 = () => {
json_string: "JSON strengur",
e164: "E.164 t\xF6lugildi",
credit_card: "kreditkortan\xFAmer",
+ currency_code: "gjaldmi\xF0ilsk\xF3\xF0i",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "gildi"
};
@@ -15372,6 +15582,8 @@ var error27 = () => {
json_string: "stringa JSON",
e164: "numero E.164",
credit_card: "numero di carta di credito",
+ currency_code: "codice valuta",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "input"
};
@@ -15484,6 +15696,8 @@ var error28 = () => {
json_string: "JSON\u6587\u5B57\u5217",
e164: "E.164\u756A\u53F7",
credit_card: "\u30AF\u30EC\u30B8\u30C3\u30C8\u30AB\u30FC\u30C9\u756A\u53F7",
+ currency_code: "\u901A\u8CA8\u30B3\u30FC\u30C9",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "\u5165\u529B\u5024"
};
@@ -15595,6 +15809,8 @@ var error29 = () => {
json_string: "JSON \u10D5\u10D4\u10DA\u10D8",
e164: "E.164 \u10DC\u10DD\u10DB\u10D4\u10E0\u10D8",
credit_card: "\u10E1\u10D0\u10D9\u10E0\u10D4\u10D3\u10D8\u10E2\u10DD \u10D1\u10D0\u10E0\u10D0\u10D7\u10D8\u10E1 \u10DC\u10DD\u10DB\u10D4\u10E0\u10D8",
+ currency_code: "\u10D5\u10D0\u10DA\u10E3\u10E2\u10D8\u10E1 \u10D9\u10DD\u10D3\u10D8",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "\u10E8\u10D4\u10E7\u10D5\u10D0\u10DC\u10D0"
};
@@ -15711,6 +15927,8 @@ var error30 = () => {
json_string: "\u1781\u17D2\u179F\u17C2\u17A2\u1780\u17D2\u179F\u179A JSON",
e164: "\u179B\u17C1\u1781 E.164",
credit_card: "\u179B\u17C1\u1781\u1794\u17D0\u178E\u17D2\u178E\u17A5\u178E\u1791\u17B6\u1793",
+ currency_code: "\u1780\u17BC\u178A\u179A\u17BC\u1794\u17B7\u1799\u1794\u17D0\u178E\u17D2\u178E",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "\u1791\u17B7\u1793\u17D2\u1793\u1793\u17D0\u1799\u1794\u1789\u17D2\u1785\u17BC\u179B"
};
@@ -15830,6 +16048,8 @@ var error31 = () => {
json_string: "JSON\u0CB8\u0CCD\u0C9F\u0CCD\u0CB0\u0CBF\u0C82\u0C97\u0CCD",
e164: "E.164 \u0CB8\u0C82\u0C96\u0CCD\u0CAF\u0CC6",
credit_card: "\u0C95\u0CCD\u0CB0\u0CC6\u0CA1\u0CBF\u0C9F\u0CCD \u0C95\u0CBE\u0CB0\u0CCD\u0CA1\u0CCD \u0CB8\u0C82\u0C96\u0CCD\u0CAF\u0CC6",
+ currency_code: "\u0C95\u0CB0\u0CC6\u0CA8\u0CCD\u0CB8\u0CBF \u0C95\u0CCB\u0CA1\u0CCD",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "\u0C87\u0CA8\u0CCD\u0CAA\u0CC1\u0C9F\u0CCD"
};
@@ -15944,6 +16164,8 @@ var error32 = () => {
json_string: "JSON \uBB38\uC790\uC5F4",
e164: "E.164 \uBC88\uD638",
credit_card: "\uC2E0\uC6A9\uCE74\uB4DC \uBC88\uD638",
+ currency_code: "\uD1B5\uD654 \uCF54\uB4DC",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "\uC785\uB825"
};
@@ -16141,6 +16363,8 @@ var error33 = () => {
json_string: "JSON eilut\u0117",
e164: "E.164 numeris",
credit_card: "kredito kortel\u0117s numeris",
+ currency_code: "valiutos kodas",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "\u012Fvestis"
};
@@ -16265,6 +16489,8 @@ var error34 = () => {
json_string: "JSON \u043D\u0438\u0437\u0430",
e164: "E.164 \u0431\u0440\u043E\u0458",
credit_card: "\u0431\u0440\u043E\u0458 \u043D\u0430 \u043A\u0440\u0435\u0434\u0438\u0442\u043D\u0430 \u043A\u0430\u0440\u0442\u0438\u0447\u043A\u0430",
+ currency_code: "\u043A\u043E\u0434 \u043D\u0430 \u0432\u0430\u043B\u0443\u0442\u0430",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "\u0432\u043D\u0435\u0441"
};
@@ -16378,6 +16604,8 @@ var error35 = () => {
json_string: "string JSON",
e164: "nombor E.164",
credit_card: "nombor kad kredit",
+ currency_code: "kod mata wang",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "input"
};
@@ -16489,6 +16717,8 @@ var error36 = () => {
json_string: "JSON \u0938\u094D\u091F\u094D\u0930\u093F\u0919",
e164: "E.164 \u0928\u092E\u094D\u092C\u0930",
credit_card: "\u0915\u094D\u0930\u0947\u0921\u093F\u091F \u0915\u093E\u0930\u094D\u0921 \u0928\u092E\u094D\u092C\u0930",
+ currency_code: "\u092E\u0941\u0926\u094D\u0930\u093E \u0915\u094B\u0921",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "\u0907\u0928\u092A\u0941\u091F"
};
@@ -16599,6 +16829,8 @@ var error37 = () => {
json_string: "JSON string",
e164: "E.164-nummer",
credit_card: "creditcardnummer",
+ currency_code: "valutacode",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "invoer"
};
@@ -16713,6 +16945,8 @@ var error38 = () => {
json_string: "JSON-streng",
e164: "E.164-nummer",
credit_card: "kredittkortnummer",
+ currency_code: "valutakode",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "input"
};
@@ -16825,6 +17059,8 @@ var error39 = () => {
json_string: "JSON-streng",
e164: "E.164-nummer",
credit_card: "kredittkortnummer",
+ currency_code: "valutakode",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "input"
};
@@ -16937,6 +17173,8 @@ var error40 = () => {
json_string: "JSON metin",
e164: "E.164 say\u0131s\u0131",
credit_card: "i'tib\xE2r kart\u0131 numaras\u0131",
+ currency_code: "para birimi kodu",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "giren"
};
@@ -17050,6 +17288,8 @@ var error41 = () => {
json_string: "JSON \u0645\u062A\u0646",
e164: "\u062F E.164 \u0634\u0645\u06D0\u0631\u0647",
credit_card: "\u062F \u06A9\u0631\u06CC\u0689\u06CC\u067C \u06A9\u0627\u0631\u062A \u0634\u0645\u06CC\u0631\u0647",
+ currency_code: "\u062F \u0627\u0633\u0639\u0627\u0631\u0648 \u06A9\u0648\u0689",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "\u0648\u0631\u0648\u062F\u064A"
};
@@ -17168,6 +17408,8 @@ var error42 = () => {
json_string: "ci\u0105g znak\xF3w w formacie JSON",
e164: "liczba E.164",
credit_card: "numer karty kredytowej",
+ currency_code: "kod waluty",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "wej\u015Bcie"
};
@@ -17281,6 +17523,8 @@ var error43 = () => {
json_string: "o texto JSON",
e164: "o n\xFAmero E.164",
credit_card: "o n\xFAmero de cart\xE3o de cr\xE9dito",
+ currency_code: "o c\xF3digo de moeda",
+ iban: "o IBAN",
jwt: "o JWT",
template_literal: "a entrada"
};
@@ -17358,8 +17602,8 @@ var error43 = () => {
case "not_multiple_of":
return `N\xFAmero inv\xE1lido: deve ser m\xFAltiplo de ${issue2.divisor}`;
case "unrecognized_keys": {
- const plural = issue2.keys.length > 1 ? "s" : "";
- return `Chave${plural} inv\xE1lida${plural}: ${joinValues(issue2.keys, ", ")}`;
+ const plural2 = issue2.keys.length > 1 ? "s" : "";
+ return `Chave${plural2} inv\xE1lida${plural2}: ${joinValues(issue2.keys, ", ")}`;
}
case "invalid_key":
return `Entrada inv\xE1lida n${translateOriginWithArticle(issue2.origin, "definite")}`;
@@ -17423,6 +17667,8 @@ var error44 = () => {
json_string: "o texto JSON",
e164: "o n\xFAmero E.164",
credit_card: "o n\xFAmero de cart\xE3o de cr\xE9dito",
+ currency_code: "o c\xF3digo de moeda",
+ iban: "o IBAN",
jwt: "o JWT",
template_literal: "a entrada"
};
@@ -17501,8 +17747,8 @@ var error44 = () => {
case "not_multiple_of":
return `N\xFAmero inv\xE1lido: deve ser m\xFAltiplo de ${issue2.divisor}`;
case "unrecognized_keys": {
- const plural = issue2.keys.length > 1 ? "s" : "";
- return `Chave${plural} inv\xE1lida${plural}: ${joinValues(issue2.keys, ", ")}`;
+ const plural2 = issue2.keys.length > 1 ? "s" : "";
+ return `Chave${plural2} inv\xE1lida${plural2}: ${joinValues(issue2.keys, ", ")}`;
}
case "invalid_key":
return `Entrada inv\xE1lida n${translateOriginWithArticle(issue2.origin, "definite")}`;
@@ -17566,6 +17812,8 @@ var error45 = () => {
json_string: "\u0219ir JSON",
e164: "num\u0103r E.164",
credit_card: "num\u0103r de card de credit",
+ currency_code: "cod valutar",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "intrare"
};
@@ -17737,6 +17985,8 @@ var error46 = () => {
json_string: "JSON \u0441\u0442\u0440\u043E\u043A\u0430",
e164: "\u043D\u043E\u043C\u0435\u0440 E.164",
credit_card: "\u043D\u043E\u043C\u0435\u0440 \u043A\u0440\u0435\u0434\u0438\u0442\u043D\u043E\u0439 \u043A\u0430\u0440\u0442\u044B",
+ currency_code: "\u043A\u043E\u0434 \u0432\u0430\u043B\u044E\u0442\u044B",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "\u0432\u0432\u043E\u0434"
};
@@ -17854,6 +18104,8 @@ var error47 = () => {
json_string: "re\u0165azec vo form\xE1te JSON",
e164: "\u010D\xEDslo E.164",
credit_card: "\u010D\xEDslo kreditnej karty",
+ currency_code: "k\xF3d meny",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "vstup"
};
@@ -17969,6 +18221,8 @@ var error48 = () => {
json_string: "JSON niz",
e164: "E.164 \u0161tevilka",
credit_card: "\u0161tevilka kreditne kartice",
+ currency_code: "koda valute",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "vnos"
};
@@ -18082,6 +18336,8 @@ var error49 = () => {
json_string: "JSON-str\xE4ng",
e164: "E.164-nummer",
credit_card: "kreditkortsnummer",
+ currency_code: "valutakod",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "mall-literal"
};
@@ -18196,6 +18452,8 @@ var error50 = () => {
json_string: "JSON \u0B9A\u0BB0\u0BAE\u0BCD",
e164: "E.164 \u0B8E\u0BA3\u0BCD",
credit_card: "\u0B95\u0B9F\u0BA9\u0BCD \u0B85\u0B9F\u0BCD\u0B9F\u0BC8 \u0B8E\u0BA3\u0BCD",
+ currency_code: "\u0BA8\u0BBE\u0BA3\u0BAF\u0B95\u0BCD \u0B95\u0BC1\u0BB1\u0BBF\u0BAF\u0BC0\u0B9F\u0BC1",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "input"
};
@@ -18269,23 +18527,23 @@ function ta_default() {
};
}
-// node_modules/zod/v4/locales/th.js
+// node_modules/zod/v4/locales/tg.js
var error51 = () => {
const Sizable = {
- string: { unit: "\u0E15\u0E31\u0E27\u0E2D\u0E31\u0E01\u0E29\u0E23", verb: "\u0E04\u0E27\u0E23\u0E21\u0E35" },
- file: { unit: "\u0E44\u0E1A\u0E15\u0E4C", verb: "\u0E04\u0E27\u0E23\u0E21\u0E35" },
- array: { unit: "\u0E23\u0E32\u0E22\u0E01\u0E32\u0E23", verb: "\u0E04\u0E27\u0E23\u0E21\u0E35" },
- set: { unit: "\u0E23\u0E32\u0E22\u0E01\u0E32\u0E23", verb: "\u0E04\u0E27\u0E23\u0E21\u0E35" },
- map: { unit: "\u0E23\u0E32\u0E22\u0E01\u0E32\u0E23", verb: "\u0E04\u0E27\u0E23\u0E21\u0E35" }
+ string: { unit: "\u0430\u043B\u043E\u043C\u0430\u0442", verb: "\u0434\u043E\u0448\u0442\u0430 \u0431\u043E\u0448\u0430\u0434" },
+ file: { unit: "\u0431\u0430\u0439\u0442", verb: "\u0434\u043E\u0448\u0442\u0430 \u0431\u043E\u0448\u0430\u0434" },
+ array: { unit: "\u0443\u043D\u0441\u0443\u0440", verb: "\u0434\u043E\u0448\u0442\u0430 \u0431\u043E\u0448\u0430\u0434" },
+ set: { unit: "\u0443\u043D\u0441\u0443\u0440", verb: "\u0434\u043E\u0448\u0442\u0430 \u0431\u043E\u0448\u0430\u0434" },
+ map: { unit: "\u0441\u0430\u0431\u0442", verb: "\u0434\u043E\u0448\u0442\u0430 \u0431\u043E\u0448\u0430\u0434" }
};
function getSizing(origin) {
return Sizable[origin] ?? null;
}
const FormatDictionary = {
- regex: "\u0E02\u0E49\u0E2D\u0E21\u0E39\u0E25\u0E17\u0E35\u0E48\u0E1B\u0E49\u0E2D\u0E19",
- email: "\u0E17\u0E35\u0E48\u0E2D\u0E22\u0E39\u0E48\u0E2D\u0E35\u0E40\u0E21\u0E25",
+ regex: "\u0432\u0443\u0440\u0443\u0434",
+ email: "\u0441\u0443\u0440\u043E\u0493\u0430\u0438 email",
url: "URL",
- emoji: "\u0E2D\u0E34\u0E42\u0E21\u0E08\u0E34",
+ emoji: "\u044D\u043C\u043E\u04B7\u0438",
uuid: "UUID",
uuidv4: "UUIDv4",
uuidv6: "UUIDv6",
@@ -18296,28 +18554,147 @@ var error51 = () => {
ulid: "ULID",
xid: "XID",
ksuid: "KSUID",
- datetime: "\u0E27\u0E31\u0E19\u0E17\u0E35\u0E48\u0E40\u0E27\u0E25\u0E32\u0E41\u0E1A\u0E1A ISO",
- date: "\u0E27\u0E31\u0E19\u0E17\u0E35\u0E48\u0E41\u0E1A\u0E1A ISO",
- time: "\u0E40\u0E27\u0E25\u0E32\u0E41\u0E1A\u0E1A ISO",
- duration: "\u0E0A\u0E48\u0E27\u0E07\u0E40\u0E27\u0E25\u0E32\u0E41\u0E1A\u0E1A ISO",
- ipv4: "\u0E17\u0E35\u0E48\u0E2D\u0E22\u0E39\u0E48 IPv4",
- ipv6: "\u0E17\u0E35\u0E48\u0E2D\u0E22\u0E39\u0E48 IPv6",
- mac: "\u0E17\u0E35\u0E48\u0E2D\u0E22\u0E39\u0E48 MAC",
- cidrv4: "\u0E0A\u0E48\u0E27\u0E07 IP \u0E41\u0E1A\u0E1A IPv4",
- cidrv6: "\u0E0A\u0E48\u0E27\u0E07 IP \u0E41\u0E1A\u0E1A IPv6",
- base64: "\u0E02\u0E49\u0E2D\u0E04\u0E27\u0E32\u0E21\u0E41\u0E1A\u0E1A Base64",
- base64url: "\u0E02\u0E49\u0E2D\u0E04\u0E27\u0E32\u0E21\u0E41\u0E1A\u0E1A Base64 \u0E2A\u0E33\u0E2B\u0E23\u0E31\u0E1A URL",
- json_string: "\u0E02\u0E49\u0E2D\u0E04\u0E27\u0E32\u0E21\u0E41\u0E1A\u0E1A JSON",
- e164: "\u0E40\u0E1A\u0E2D\u0E23\u0E4C\u0E42\u0E17\u0E23\u0E28\u0E31\u0E1E\u0E17\u0E4C\u0E23\u0E30\u0E2B\u0E27\u0E48\u0E32\u0E07\u0E1B\u0E23\u0E30\u0E40\u0E17\u0E28 (E.164)",
- credit_card: "\u0E2B\u0E21\u0E32\u0E22\u0E40\u0E25\u0E02\u0E1A\u0E31\u0E15\u0E23\u0E40\u0E04\u0E23\u0E14\u0E34\u0E15",
- jwt: "\u0E42\u0E17\u0E40\u0E04\u0E19 JWT",
- template_literal: "\u0E02\u0E49\u0E2D\u0E21\u0E39\u0E25\u0E17\u0E35\u0E48\u0E1B\u0E49\u0E2D\u0E19"
+ datetime: "\u0441\u0430\u043D\u0430\u0432\u0443 \u0432\u0430\u049B\u0442\u0438 ISO",
+ date: "\u0441\u0430\u043D\u0430\u0438 ISO",
+ time: "\u0432\u0430\u049B\u0442\u0438 ISO",
+ duration: "\u0434\u0430\u0432\u043E\u043C\u043D\u043E\u043A\u0438\u0438 ISO",
+ ipv4: "\u0441\u0443\u0440\u043E\u0493\u0430\u0438 IPv4",
+ ipv6: "\u0441\u0443\u0440\u043E\u0493\u0430\u0438 IPv6",
+ mac: "\u0441\u0443\u0440\u043E\u0493\u0430\u0438 MAC",
+ cidrv4: "\u043C\u0430\u04B3\u0434\u0443\u0434\u0430\u0438 IPv4",
+ cidrv6: "\u043C\u0430\u04B3\u0434\u0443\u0434\u0430\u0438 IPv6",
+ base64: "\u0441\u0430\u0442\u0440\u0438 \u0434\u0430\u0440 \u0444\u043E\u0440\u043C\u0430\u0442\u0438 base64",
+ base64url: "\u0441\u0430\u0442\u0440\u0438 \u0434\u0430\u0440 \u0444\u043E\u0440\u043C\u0430\u0442\u0438 base64url",
+ json_string: "\u0441\u0430\u0442\u0440\u0438 JSON",
+ e164: "\u0440\u0430\u049B\u0430\u043C\u0438 E.164",
+ credit_card: "\u0440\u0430\u049B\u0430\u043C\u0438 \u043A\u043E\u0440\u0442\u0438 \u043A\u0440\u0435\u0434\u0438\u0442\u04E3",
+ currency_code: "\u0440\u0430\u043C\u0437\u0438 \u0430\u0441\u044A\u043E\u0440",
+ iban: "IBAN",
+ jwt: "JWT",
+ template_literal: "\u0432\u0443\u0440\u0443\u0434"
};
const TypeDictionary = {
nan: "NaN",
- number: "\u0E15\u0E31\u0E27\u0E40\u0E25\u0E02",
- array: "\u0E2D\u0E32\u0E23\u0E4C\u0E40\u0E23\u0E22\u0E4C (Array)",
- null: "\u0E44\u0E21\u0E48\u0E21\u0E35\u0E04\u0E48\u0E32 (null)"
+ number: "\u0440\u0430\u049B\u0430\u043C",
+ string: "\u0441\u0430\u0442\u0440",
+ array: "\u043C\u0430\u0441\u0441\u0438\u0432",
+ object: "\u043E\u0431\u044A\u0435\u043A\u0442",
+ date: "\u0441\u0430\u043D\u0430"
+ };
+ return (issue2) => {
+ switch (issue2.code) {
+ case "invalid_type": {
+ const expected = TypeDictionary[issue2.expected] ?? issue2.expected;
+ const receivedType = parsedType(issue2.input);
+ const received = TypeDictionary[receivedType] ?? receivedType;
+ return `\u0412\u0443\u0440\u0443\u0434\u0438 \u043D\u043E\u0434\u0443\u0440\u0443\u0441\u0442: ${expected} \u0438\u043D\u0442\u0438\u0437\u043E\u0440 \u043C\u0435\u0440\u0430\u0444\u0442, ${received} \u0433\u0438\u0440\u0438\u0444\u0442\u0430 \u0448\u0443\u0434`;
+ }
+ case "invalid_value":
+ if (issue2.values.length === 1)
+ return `\u0412\u0443\u0440\u0443\u0434\u0438 \u043D\u043E\u0434\u0443\u0440\u0443\u0441\u0442: ${stringifyPrimitive(issue2.values[0])} \u0438\u043D\u0442\u0438\u0437\u043E\u0440 \u043C\u0435\u0440\u0430\u0444\u0442`;
+ return `\u0418\u043D\u0442\u0438\u0445\u043E\u0431\u0438 \u043D\u043E\u0434\u0443\u0440\u0443\u0441\u0442: \u044F\u043A\u0435 \u0430\u0437 ${joinValues(issue2.values, "|")} \u0438\u043D\u0442\u0438\u0437\u043E\u0440 \u043C\u0435\u0440\u0430\u0444\u0442`;
+ case "too_big": {
+ const adj = issue2.inclusive ? "<=" : "<";
+ const sizing = getSizing(issue2.origin);
+ if (sizing)
+ return `\u0425\u0435\u043B\u0435 \u043A\u0430\u043B\u043E\u043D: ${issue2.origin ?? "\u049B\u0438\u043C\u0430\u0442"} \u0431\u043E\u044F\u0434 ${adj}${issue2.maximum.toString()} ${sizing.unit} ${sizing.verb}`;
+ return `\u0425\u0435\u043B\u0435 \u043A\u0430\u043B\u043E\u043D: ${issue2.origin ?? "\u049B\u0438\u043C\u0430\u0442"} \u0431\u043E\u044F\u0434 ${adj}${issue2.maximum.toString()} \u0431\u043E\u0448\u0430\u0434`;
+ }
+ case "too_small": {
+ const adj = issue2.inclusive ? ">=" : ">";
+ const sizing = getSizing(issue2.origin);
+ if (sizing)
+ return `\u0425\u0435\u043B\u0435 \u0445\u0443\u0440\u0434: ${issue2.origin} \u0431\u043E\u044F\u0434 ${adj}${issue2.minimum.toString()} ${sizing.unit} ${sizing.verb}`;
+ return `\u0425\u0435\u043B\u0435 \u0445\u0443\u0440\u0434: ${issue2.origin} \u0431\u043E\u044F\u0434 ${adj}${issue2.minimum.toString()} \u0431\u043E\u0448\u0430\u0434`;
+ }
+ case "invalid_format": {
+ const _issue = issue2;
+ if (_issue.format === "starts_with")
+ return `\u0421\u0430\u0442\u0440\u0438 \u043D\u043E\u0434\u0443\u0440\u0443\u0441\u0442: \u0431\u043E\u044F\u0434 \u0431\u043E "${_issue.prefix}" \u043E\u0493\u043E\u0437 \u0448\u0430\u0432\u0430\u0434`;
+ if (_issue.format === "ends_with")
+ return `\u0421\u0430\u0442\u0440\u0438 \u043D\u043E\u0434\u0443\u0440\u0443\u0441\u0442: \u0431\u043E\u044F\u0434 \u0431\u043E "${_issue.suffix}" \u0430\u043D\u04B7\u043E\u043C \u0451\u0431\u0430\u0434`;
+ if (_issue.format === "includes")
+ return `\u0421\u0430\u0442\u0440\u0438 \u043D\u043E\u0434\u0443\u0440\u0443\u0441\u0442: \u0431\u043E\u044F\u0434 "${_issue.includes}"-\u0440\u043E \u0434\u0430\u0440 \u0431\u0430\u0440 \u0433\u0438\u0440\u0430\u0434`;
+ if (_issue.format === "regex")
+ return `\u0421\u0430\u0442\u0440\u0438 \u043D\u043E\u0434\u0443\u0440\u0443\u0441\u0442: \u0431\u043E\u044F\u0434 \u0431\u0430 \u043D\u0430\u043C\u0443\u043D\u0430\u0438 ${_issue.pattern} \u043C\u0443\u0432\u043E\u0444\u0438\u049B\u0430\u0442 \u043A\u0443\u043D\u0430\u0434`;
+ return `${FormatDictionary[_issue.format] ?? issue2.format}-\u0438 \u043D\u043E\u0434\u0443\u0440\u0443\u0441\u0442`;
+ }
+ case "not_multiple_of":
+ return `\u0420\u0430\u049B\u0430\u043C\u0438 \u043D\u043E\u0434\u0443\u0440\u0443\u0441\u0442: \u0431\u043E\u044F\u0434 \u0431\u0430 ${issue2.divisor} \u0431\u0435 \u0431\u0430\u049B\u0438\u044F \u0442\u0430\u049B\u0441\u0438\u043C \u0448\u0430\u0432\u0430\u0434`;
+ case "unrecognized_keys":
+ return `\u041A\u0430\u043B\u0438\u0434${issue2.keys.length > 1 ? "\u04B3\u043E\u0438" : "\u0438"} \u043D\u043E\u043C\u0430\u044A\u043B\u0443\u043C: ${joinValues(issue2.keys, ", ")}`;
+ case "invalid_key":
+ return `\u041A\u0430\u043B\u0438\u0434\u0438 \u043D\u043E\u0434\u0443\u0440\u0443\u0441\u0442 \u0434\u0430\u0440 ${issue2.origin}`;
+ case "invalid_union":
+ if (issue2.options && Array.isArray(issue2.options) && issue2.options.length > 0) {
+ const opts = issue2.options.map((o) => `'${o}'`).join(" | ");
+ return `\u049A\u0438\u043C\u0430\u0442\u0438 \u043D\u043E\u0434\u0443\u0440\u0443\u0441\u0442\u0438 \u0434\u0438\u0441\u043A\u0440\u0438\u043C\u0438\u043D\u0430\u0442\u043E\u0440: ${opts} \u0438\u043D\u0442\u0438\u0437\u043E\u0440 \u043C\u0435\u0440\u0430\u0444\u0442`;
+ }
+ return "\u0412\u0443\u0440\u0443\u0434\u0438 \u043D\u043E\u0434\u0443\u0440\u0443\u0441\u0442";
+ case "invalid_element":
+ return `\u049A\u0438\u043C\u0430\u0442\u0438 \u043D\u043E\u0434\u0443\u0440\u0443\u0441\u0442 \u0434\u0430\u0440 ${issue2.origin}`;
+ default:
+ return `\u0412\u0443\u0440\u0443\u0434\u0438 \u043D\u043E\u0434\u0443\u0440\u0443\u0441\u0442`;
+ }
+ };
+};
+function tg_default() {
+ return {
+ localeError: error51()
+ };
+}
+
+// node_modules/zod/v4/locales/th.js
+var error52 = () => {
+ const Sizable = {
+ string: { unit: "\u0E15\u0E31\u0E27\u0E2D\u0E31\u0E01\u0E29\u0E23", verb: "\u0E04\u0E27\u0E23\u0E21\u0E35" },
+ file: { unit: "\u0E44\u0E1A\u0E15\u0E4C", verb: "\u0E04\u0E27\u0E23\u0E21\u0E35" },
+ array: { unit: "\u0E23\u0E32\u0E22\u0E01\u0E32\u0E23", verb: "\u0E04\u0E27\u0E23\u0E21\u0E35" },
+ set: { unit: "\u0E23\u0E32\u0E22\u0E01\u0E32\u0E23", verb: "\u0E04\u0E27\u0E23\u0E21\u0E35" },
+ map: { unit: "\u0E23\u0E32\u0E22\u0E01\u0E32\u0E23", verb: "\u0E04\u0E27\u0E23\u0E21\u0E35" }
+ };
+ function getSizing(origin) {
+ return Sizable[origin] ?? null;
+ }
+ const FormatDictionary = {
+ regex: "\u0E02\u0E49\u0E2D\u0E21\u0E39\u0E25\u0E17\u0E35\u0E48\u0E1B\u0E49\u0E2D\u0E19",
+ email: "\u0E17\u0E35\u0E48\u0E2D\u0E22\u0E39\u0E48\u0E2D\u0E35\u0E40\u0E21\u0E25",
+ url: "URL",
+ emoji: "\u0E2D\u0E34\u0E42\u0E21\u0E08\u0E34",
+ uuid: "UUID",
+ uuidv4: "UUIDv4",
+ uuidv6: "UUIDv6",
+ nanoid: "nanoid",
+ guid: "GUID",
+ cuid: "cuid",
+ cuid2: "cuid2",
+ ulid: "ULID",
+ xid: "XID",
+ ksuid: "KSUID",
+ datetime: "\u0E27\u0E31\u0E19\u0E17\u0E35\u0E48\u0E40\u0E27\u0E25\u0E32\u0E41\u0E1A\u0E1A ISO",
+ date: "\u0E27\u0E31\u0E19\u0E17\u0E35\u0E48\u0E41\u0E1A\u0E1A ISO",
+ time: "\u0E40\u0E27\u0E25\u0E32\u0E41\u0E1A\u0E1A ISO",
+ duration: "\u0E0A\u0E48\u0E27\u0E07\u0E40\u0E27\u0E25\u0E32\u0E41\u0E1A\u0E1A ISO",
+ ipv4: "\u0E17\u0E35\u0E48\u0E2D\u0E22\u0E39\u0E48 IPv4",
+ ipv6: "\u0E17\u0E35\u0E48\u0E2D\u0E22\u0E39\u0E48 IPv6",
+ mac: "\u0E17\u0E35\u0E48\u0E2D\u0E22\u0E39\u0E48 MAC",
+ cidrv4: "\u0E0A\u0E48\u0E27\u0E07 IP \u0E41\u0E1A\u0E1A IPv4",
+ cidrv6: "\u0E0A\u0E48\u0E27\u0E07 IP \u0E41\u0E1A\u0E1A IPv6",
+ base64: "\u0E02\u0E49\u0E2D\u0E04\u0E27\u0E32\u0E21\u0E41\u0E1A\u0E1A Base64",
+ base64url: "\u0E02\u0E49\u0E2D\u0E04\u0E27\u0E32\u0E21\u0E41\u0E1A\u0E1A Base64 \u0E2A\u0E33\u0E2B\u0E23\u0E31\u0E1A URL",
+ json_string: "\u0E02\u0E49\u0E2D\u0E04\u0E27\u0E32\u0E21\u0E41\u0E1A\u0E1A JSON",
+ e164: "\u0E40\u0E1A\u0E2D\u0E23\u0E4C\u0E42\u0E17\u0E23\u0E28\u0E31\u0E1E\u0E17\u0E4C\u0E23\u0E30\u0E2B\u0E27\u0E48\u0E32\u0E07\u0E1B\u0E23\u0E30\u0E40\u0E17\u0E28 (E.164)",
+ credit_card: "\u0E2B\u0E21\u0E32\u0E22\u0E40\u0E25\u0E02\u0E1A\u0E31\u0E15\u0E23\u0E40\u0E04\u0E23\u0E14\u0E34\u0E15",
+ currency_code: "\u0E23\u0E2B\u0E31\u0E2A\u0E2A\u0E01\u0E38\u0E25\u0E40\u0E07\u0E34\u0E19",
+ iban: "IBAN",
+ jwt: "\u0E42\u0E17\u0E40\u0E04\u0E19 JWT",
+ template_literal: "\u0E02\u0E49\u0E2D\u0E21\u0E39\u0E25\u0E17\u0E35\u0E48\u0E1B\u0E49\u0E2D\u0E19"
+ };
+ const TypeDictionary = {
+ nan: "NaN",
+ number: "\u0E15\u0E31\u0E27\u0E40\u0E25\u0E02",
+ array: "\u0E2D\u0E32\u0E23\u0E4C\u0E40\u0E23\u0E22\u0E4C (Array)",
+ null: "\u0E44\u0E21\u0E48\u0E21\u0E35\u0E04\u0E48\u0E32 (null)"
};
return (issue2) => {
switch (issue2.code) {
@@ -18379,12 +18756,12 @@ var error51 = () => {
};
function th_default() {
return {
- localeError: error51()
+ localeError: error52()
};
}
// node_modules/zod/v4/locales/tk.js
-var error52 = () => {
+var error53 = () => {
const Sizable = {
string: { unit: "simwol", verb: "bolmaly" },
file: { unit: "ba\xFDt", verb: "bolmaly" },
@@ -18424,6 +18801,8 @@ var error52 = () => {
json_string: "JSON setiri",
e164: "E.164 nomeri",
credit_card: "kredit kartyny\u0148 nomeri",
+ currency_code: "wal\xFDuta kody",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "\u015Fablon"
};
@@ -18485,12 +18864,12 @@ var error52 = () => {
};
function tk_default() {
return {
- localeError: error52()
+ localeError: error53()
};
}
// node_modules/zod/v4/locales/tr.js
-var error53 = () => {
+var error54 = () => {
const Sizable = {
string: { unit: "karakter", verb: "olmal\u0131" },
file: { unit: "bayt", verb: "olmal\u0131" },
@@ -18530,6 +18909,8 @@ var error53 = () => {
json_string: "JSON dizesi",
e164: "E.164 say\u0131s\u0131",
credit_card: "kredi kart\u0131 numaras\u0131",
+ currency_code: "para birimi kodu",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "\u015Eablon dizesi"
};
@@ -18594,12 +18975,12 @@ var error53 = () => {
};
function tr_default() {
return {
- localeError: error53()
+ localeError: error54()
};
}
// node_modules/zod/v4/locales/uk.js
-var error54 = () => {
+var error55 = () => {
const Sizable = {
string: { unit: "\u0441\u0438\u043C\u0432\u043E\u043B\u0456\u0432", verb: "\u043C\u0430\u0442\u0438\u043C\u0435" },
file: { unit: "\u0431\u0430\u0439\u0442\u0456\u0432", verb: "\u043C\u0430\u0442\u0438\u043C\u0435" },
@@ -18639,6 +19020,8 @@ var error54 = () => {
json_string: "\u0440\u044F\u0434\u043E\u043A JSON",
e164: "\u043D\u043E\u043C\u0435\u0440 E.164",
credit_card: "\u043D\u043E\u043C\u0435\u0440 \u043A\u0440\u0435\u0434\u0438\u0442\u043D\u043E\u0457 \u043A\u0430\u0440\u0442\u043A\u0438",
+ currency_code: "\u043A\u043E\u0434 \u0432\u0430\u043B\u044E\u0442\u0438",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "\u0432\u0445\u0456\u0434\u043D\u0456 \u0434\u0430\u043D\u0456"
};
@@ -18706,7 +19089,7 @@ var error54 = () => {
};
function uk_default() {
return {
- localeError: error54()
+ localeError: error55()
};
}
@@ -18716,7 +19099,7 @@ function ua_default() {
}
// node_modules/zod/v4/locales/ur.js
-var error55 = () => {
+var error56 = () => {
const Sizable = {
string: { unit: "\u062D\u0631\u0648\u0641", verb: "\u06C1\u0648\u0646\u0627" },
file: { unit: "\u0628\u0627\u0626\u0679\u0633", verb: "\u06C1\u0648\u0646\u0627" },
@@ -18756,6 +19139,8 @@ var error55 = () => {
json_string: "\u062C\u06D2 \u0627\u06CC\u0633 \u0627\u0648 \u0627\u06CC\u0646 \u0633\u0679\u0631\u0646\u06AF",
e164: "\u0627\u06CC 164 \u0646\u0645\u0628\u0631",
credit_card: "\u06A9\u0631\u06CC\u0688\u0679 \u06A9\u0627\u0631\u0688 \u0646\u0645\u0628\u0631",
+ currency_code: "\u06A9\u0631\u0646\u0633\u06CC \u06A9\u0648\u0688",
+ iban: "IBAN",
jwt: "\u062C\u06D2 \u0688\u0628\u0644\u06CC\u0648 \u0679\u06CC",
template_literal: "\u0627\u0646 \u067E\u0679"
};
@@ -18825,12 +19210,12 @@ var error55 = () => {
};
function ur_default() {
return {
- localeError: error55()
+ localeError: error56()
};
}
// node_modules/zod/v4/locales/uz.js
-var error56 = () => {
+var error57 = () => {
const Sizable = {
string: { unit: "belgi", verb: "bo\u2018lishi kerak" },
file: { unit: "bayt", verb: "bo\u2018lishi kerak" },
@@ -18870,6 +19255,8 @@ var error56 = () => {
json_string: "JSON satr",
e164: "E.164 raqam",
credit_card: "kredit karta raqami",
+ currency_code: "valyuta kodi",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "kirish"
};
@@ -18937,12 +19324,12 @@ var error56 = () => {
};
function uz_default() {
return {
- localeError: error56()
+ localeError: error57()
};
}
// node_modules/zod/v4/locales/vi.js
-var error57 = () => {
+var error58 = () => {
const Sizable = {
string: { unit: "k\xFD t\u1EF1", verb: "c\xF3" },
file: { unit: "byte", verb: "c\xF3" },
@@ -18982,6 +19369,8 @@ var error57 = () => {
json_string: "chu\u1ED7i JSON",
e164: "s\u1ED1 E.164",
credit_card: "s\u1ED1 th\u1EBB t\xEDn d\u1EE5ng",
+ currency_code: "m\xE3 ti\u1EC1n t\u1EC7",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "\u0111\u1EA7u v\xE0o"
};
@@ -19049,12 +19438,12 @@ var error57 = () => {
};
function vi_default() {
return {
- localeError: error57()
+ localeError: error58()
};
}
// node_modules/zod/v4/locales/zh-CN.js
-var error58 = () => {
+var error59 = () => {
const Sizable = {
string: { unit: "\u5B57\u7B26", verb: "\u5305\u542B" },
file: { unit: "\u5B57\u8282", verb: "\u5305\u542B" },
@@ -19094,6 +19483,8 @@ var error58 = () => {
json_string: "JSON\u5B57\u7B26\u4E32",
e164: "E.164\u53F7\u7801",
credit_card: "\u4FE1\u7528\u5361\u53F7",
+ currency_code: "\u8D27\u5E01\u4EE3\u7801",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "\u8F93\u5165"
};
@@ -19162,12 +19553,12 @@ var error58 = () => {
};
function zh_CN_default() {
return {
- localeError: error58()
+ localeError: error59()
};
}
// node_modules/zod/v4/locales/zh-TW.js
-var error59 = () => {
+var error60 = () => {
const Sizable = {
string: { unit: "\u5B57\u5143", verb: "\u64C1\u6709" },
file: { unit: "\u4F4D\u5143\u7D44", verb: "\u64C1\u6709" },
@@ -19207,6 +19598,8 @@ var error59 = () => {
json_string: "JSON \u5B57\u4E32",
e164: "E.164 \u6578\u503C",
credit_card: "\u4FE1\u7528\u5361\u865F",
+ currency_code: "\u8CA8\u5E63\u4EE3\u78BC",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "\u8F38\u5165"
};
@@ -19273,12 +19666,12 @@ var error59 = () => {
};
function zh_TW_default() {
return {
- localeError: error59()
+ localeError: error60()
};
}
// node_modules/zod/v4/locales/yo.js
-var error60 = () => {
+var error61 = () => {
const Sizable = {
string: { unit: "\xE0mi", verb: "n\xED" },
file: { unit: "bytes", verb: "n\xED" },
@@ -19318,6 +19711,8 @@ var error60 = () => {
json_string: "\u1ECD\u0300r\u1ECD\u0300 JSON",
e164: "n\u1ECD\u0301mb\xE0 E.164",
credit_card: "n\u1ECDmba kaadi gbese",
+ currency_code: "koodu ow\xF3",
+ iban: "IBAN",
jwt: "JWT",
template_literal: "\u1EB9\u0300r\u1ECD \xECb\xE1w\u1ECDl\xE9"
};
@@ -19384,7 +19779,7 @@ var error60 = () => {
};
function yo_default() {
return {
- localeError: error60()
+ localeError: error61()
};
}
@@ -19464,31 +19859,8 @@ function compileValidator(schema, parser) {
function compile(schema, options) {
try {
const parser = compileFn(schema);
- const clone2 = clone(schema);
- const liveRun = schema._zod.run;
- const originalRun = liveRun.__originalRun ?? liveRun;
- const wrapped = (payload, ctx) => {
- if (ctx?.async || ctx?.direction === "backward" || ctx?.skipChecks || ctx?.[FALLBACK_FLAG]) {
- return originalRun(payload, ctx);
- }
- if (ctx && isBackEdge(ctx, payload.value)) {
- return originalRun(payload, ctx);
- }
- const out = parser(payload.value);
- if (out !== INVALID) {
- payload.value = out;
- return payload;
- }
- if (ctx)
- ctx[FALLBACK_FLAG] = true;
- return originalRun(payload, ctx);
- };
- wrapped.__originalRun = originalRun;
- clone2._zod.bag.fallbackRun = originalRun;
+ const clone2 = withParser(schema, parser);
clone2._zod.bag.validator = compileValidator(schema, parser);
- clone2._zod.run = wrapped;
- if (!liveRun.__originalRun)
- installCompiledUserMethods(clone2, schema, parser);
return clone2;
} catch (err) {
if (options?.strict)
@@ -19496,6 +19868,37 @@ function compile(schema, options) {
return schema;
}
}
+function withParser(schema, parser) {
+ if (isRecursiveSchema(schema)) {
+ throw new ZodCompileUnsupportedError("a schema whose subtree contains a reference cycle");
+ }
+ const clone2 = clone(schema);
+ const liveRun = schema._zod.run;
+ const originalRun = liveRun.__originalRun ?? liveRun;
+ const wrapped = (payload, ctx) => {
+ if (ctx?.async || ctx?.direction === "backward" || ctx?.skipChecks || ctx?.[FALLBACK_FLAG]) {
+ return originalRun(payload, ctx);
+ }
+ if (ctx && isBackEdge(ctx, payload.value)) {
+ return originalRun(payload, ctx);
+ }
+ const out = parser(payload.value);
+ if (out !== INVALID) {
+ payload.value = out;
+ return payload;
+ }
+ if (ctx)
+ ctx[FALLBACK_FLAG] = true;
+ return originalRun(payload, ctx);
+ };
+ wrapped.__originalRun = originalRun;
+ clone2._zod.bag.fallbackRun = originalRun;
+ clone2._zod.bag.validator = parser;
+ clone2._zod.run = wrapped;
+ if (!liveRun.__originalRun)
+ installCompiledUserMethods(clone2, schema, parser);
+ return clone2;
+}
function installCompiledUserMethods(target, source, parser) {
const targetAny = target;
const sourceAny = source;
@@ -19532,7 +19935,8 @@ function compileFn(schema, options) {
const ctx = {
constants: /* @__PURE__ */ new Map(),
constantCounter: 0,
- varCounter: 0
+ varCounter: 0,
+ definite: true
};
const doc = new Doc(["input"]);
const outputAccessor = generateCheck(doc, ctx, schema, "input", !options?.assertOnly);
@@ -19556,6 +19960,7 @@ ${code}
if (options?.debug) {
fn.code = fullCode;
}
+ fn.definite = ctx.definite;
return fn;
}
function addConstant(ctx, value) {
@@ -19567,6 +19972,10 @@ function addConstant(ctx, value) {
ctx.constants.set(name, value);
return name;
}
+function addUserConstant(ctx, fn) {
+ ctx.definite = false;
+ return addConstant(ctx, fn);
+}
function newVar(ctx) {
return `v${ctx.varCounter++}`;
}
@@ -19599,6 +20008,7 @@ function compileChild(doc, ctx, schema, accessor, needsValue = true) {
}
}
function emitRuntimeIsland(doc, ctx, schema, accessor) {
+ ctx.definite = false;
const schemaConst = addConstant(ctx, schema);
const runConst = addConstant(ctx, runtimeRun);
const outVar = newVar(ctx);
@@ -19679,6 +20089,9 @@ function generateChecks(doc, ctx, schema, accessor) {
case "property":
generatePropertyCheck(doc, ctx, def, currentAccessor);
break;
+ case "properties":
+ generatePropertiesChecks(doc, ctx, def, currentAccessor);
+ break;
case "overwrite": {
const newAccessor = newVar(ctx);
generateOverwriteCheck(doc, ctx, check2, currentAccessor, newAccessor);
@@ -19787,6 +20200,19 @@ function generateMimeTypeCheck(doc, ctx, def, accessor) {
doc.write(`if (!${mimeSet}.has(${accessor}.type)) return INVALID;`);
}
}
+function generatePropertiesChecks(doc, ctx, def, accessor) {
+ if (def.when) {
+ throw new ZodCompileUnsupportedError(`check with a custom "when" condition`);
+ }
+ doc.write(`if (${accessor} == null) return INVALID;`);
+ const shape = def.shape;
+ for (const key of Reflect.ownKeys(shape)) {
+ const keyExpr = typeof key === "symbol" ? addConstant(ctx, key) : esc(key);
+ const inputVar = newVar(ctx);
+ doc.write(`const ${inputVar} = ${accessor}[${keyExpr}];`);
+ compileChild(doc, ctx, shape[key], inputVar, false);
+ }
+}
function generatePropertyCheck(doc, ctx, def, accessor) {
const propAccessor = `${accessor}[${JSON.stringify(def.property)}]`;
generateCheck(doc, ctx, def.schema, propAccessor);
@@ -19814,7 +20240,7 @@ function generateCustomRefineCheck(doc, ctx, check2, accessor) {
if (isAsyncFunction(def.fn)) {
throw new ZodCompileAsyncError("z.compile: async .refine() predicates are not supported");
}
- const fnConst = addConstant(ctx, def.fn);
+ const fnConst = addUserConstant(ctx, def.fn);
const throwAsyncConst = addConstant(ctx, throwAsync);
const resVar = newVar(ctx);
doc.write(`const ${resVar} = ${fnConst}(${accessor});`);
@@ -19834,7 +20260,7 @@ function generateCustomRefineCheck(doc, ctx, check2, accessor) {
throwAsync();
return fakePayload.issues.length === 0 ? fakePayload.value : INVALID;
};
- const helperConst = addConstant(ctx, helperFn);
+ const helperConst = addUserConstant(ctx, helperFn);
const outVar = newVar(ctx);
doc.write(`const ${outVar} = ${helperConst}(${accessor});`);
doc.write(`if (${outVar} === INVALID) return INVALID;`);
@@ -19868,7 +20294,7 @@ var PATTERN_IS_COMPLETE = /* @__PURE__ */ new Set([
"uuid",
"xid"
]);
-function generateStringFormatCheck(doc, ctx, def, accessor) {
+function generateStringFormatCheck(doc, ctx, def, accessor, needsValue = true) {
const fmt = def.format;
if (fmt === "base64") {
const validator = addConstant(ctx, isValidBase64);
@@ -19901,9 +20327,14 @@ function generateStringFormatCheck(doc, ctx, def, accessor) {
doc.write(`if (!${validator}(${accessor})) return INVALID;`);
return accessor;
}
+ if (fmt === "iban") {
+ const validator = addConstant(ctx, isValidIBAN);
+ doc.write(`if (!${validator}(${accessor})) return INVALID;`);
+ return accessor;
+ }
const formatDef = def;
if (fmt === "url" || fmt === "httpurl" || formatDef.normalize || formatDef.hostname !== void 0 || formatDef.protocol !== void 0) {
- const parseConst = addConstant(ctx, parseURLObject);
+ const parseConst = addConstant(ctx, validateURL);
const defConst = addConstant(ctx, def);
const trimVar = newVar(ctx);
const urlVar = newVar(ctx);
@@ -19918,6 +20349,8 @@ function generateStringFormatCheck(doc, ctx, def, accessor) {
const protocolConst = addConstant(ctx, urlProtocolOk);
doc.write(`if (!${protocolConst}(${urlVar}, ${defConst}.protocol)) return INVALID;`);
}
+ if (!needsValue)
+ return null;
const outputVar = newVar(ctx);
const outputExpr = formatDef.normalize ? `${urlVar}.href` : `${addConstant(ctx, stripTabAndNewline)}(${trimVar})`;
doc.write(`const ${outputVar} = ${outputExpr};`);
@@ -19977,7 +20410,7 @@ function generateCheck(doc, ctx, schema, accessor, needsValue = true) {
let typeAccessor;
switch (type) {
case "string":
- typeAccessor = generateStringCheck(doc, ctx, schema, accessor);
+ typeAccessor = generateStringCheck(doc, ctx, schema, accessor, buildsValue);
break;
case "number":
typeAccessor = generateNumberCheck(doc, schema, accessor);
@@ -20098,12 +20531,12 @@ function generateCheck(doc, ctx, schema, accessor, needsValue = true) {
return null;
return generateChecks(doc, ctx, schema, typeAccessor);
}
-function generateStringCheck(doc, ctx, schema, accessor) {
+function generateStringCheck(doc, ctx, schema, accessor, needsValue = true) {
doc.write(`if (typeof ${accessor} !== "string") return INVALID;`);
const def = schema._zod.def;
if (def.format === void 0)
return accessor;
- return generateStringFormatCheck(doc, ctx, def, accessor);
+ return generateStringFormatCheck(doc, ctx, def, accessor, needsValue);
}
function generateNumberCheck(doc, schema, accessor) {
doc.write(`if (typeof ${accessor} !== "number" || !Number.isFinite(${accessor})) return INVALID;`);
@@ -20221,7 +20654,7 @@ function generateObjectCheck(doc, ctx, schema, accessor, buildsValue = true) {
}
}
const outputVar = newVar(ctx);
- const hasConditionalKeys = allKeys.some((k2) => mayOutputUndefined(propShape[k2]) || dropsWhenAbsent(propShape[k2]));
+ const hasConditionalKeys = allKeys.some((k2) => mayOmitUndefined(propShape[k2]) || dropsWhenAbsent(propShape[k2]));
if (!buildsValue) {
if (unknownKeysMode === "schema") {
const knownSet = keys.length > 0 ? addConstant(ctx, new Set(keys)) : null;
@@ -20248,7 +20681,7 @@ function generateObjectCheck(doc, ctx, schema, accessor, buildsValue = true) {
const out = propOutputs.get(k2);
if (dropsWhenAbsent(propShape[k2])) {
doc.write(`if (${kx} in ${accessor}) ${outputVar}[${kx}] = ${out};`);
- } else if (mayOutputUndefined(propShape[k2])) {
+ } else if (mayOmitUndefined(propShape[k2])) {
doc.write(`if (${out} !== undefined || ${kx} in ${accessor}) ${outputVar}[${kx}] = ${out};`);
} else {
doc.write(`${outputVar}[${kx}] = ${out};`);
@@ -20381,6 +20814,9 @@ function fastPathAcceptsAbsence(schema) {
function dropsWhenAbsent(schema) {
return schema._zod.optin === "optional" && schema._zod.optout === "optional";
}
+function mayOmitUndefined(schema) {
+ return (schema._zod.optin !== "defaulted" || schema._zod.optout === "optional") && mayOutputUndefined(schema);
+}
function mayOutputUndefined(schema) {
const def = schema._zod.def;
switch (def.type) {
@@ -20723,6 +21159,7 @@ function literalEquality(ctx, accessor, value) {
}
function generateIntersectionCheck(doc, ctx, schema, accessor) {
const def = schema._zod.def;
+ ctx.definite = false;
const leftOutput = compileChild(doc, ctx, def.left, accessor);
const rightOutput = compileChild(doc, ctx, def.right, accessor);
const mergeConst = addConstant(ctx, mergeValues);
@@ -20776,14 +21213,13 @@ function generateRecordCheck(doc, ctx, schema, accessor) {
const keyIsBareString = keyDef.type === "string" && keyDef.format === void 0 && !keyDef.coerce && (keyDef.checks?.length ?? 0) === 0;
if (!keyIsBareString) {
const isLoose = def.mode === "loose";
- const keyFast = addConstant(ctx, compileFn(def.keyType));
+ const keyFn = compileFn(def.keyType);
+ if (keyFn.definite === false)
+ ctx.definite = false;
+ const keyFast = addConstant(ctx, keyFn);
const numericConst = addConstant(ctx, number);
- const propIsEnumerableConst = addConstant(ctx, Object.prototype.propertyIsEnumerable);
const outKeyVar = newVar(ctx);
- doc.write(`for (const ${kVar} of Reflect.ownKeys(${accessor})) {`);
- doc.indented((d2) => {
- d2.write(`if (${kVar} === "__proto__") continue;`);
- d2.write(`if (!${propIsEnumerableConst}.call(${accessor}, ${kVar})) continue;`);
+ emitOwnKeys(doc, ctx, accessor, kVar, (d2) => {
d2.write(`let ${outKeyVar} = ${keyFast}(${kVar});`);
d2.write(`if (${outKeyVar} === INVALID && typeof ${kVar} === "string" && ${numericConst}.test(${kVar})) ${outKeyVar} = ${keyFast}(Number(${kVar}));`);
if (isLoose) {
@@ -20797,21 +21233,39 @@ function generateRecordCheck(doc, ctx, schema, accessor) {
const valOutput = compileChild(d2, ctx, def.valueType, valueVar);
d2.write(`${outputVar}[${outKeyVar}] = ${valOutput};`);
});
- doc.write(`}`);
return outputVar;
}
- const propIsEnumerable = addConstant(ctx, Object.prototype.propertyIsEnumerable);
- doc.write(`for (const ${kVar} of Reflect.ownKeys(${accessor})) {`);
- doc.indented((d2) => {
- d2.write(`if (${kVar} === "__proto__") continue;`);
- d2.write(`if (!${propIsEnumerable}.call(${accessor}, ${kVar})) continue;`);
- d2.write(`if (typeof ${kVar} !== "string") return INVALID;`);
+ emitOwnKeys(doc, ctx, accessor, kVar, (d2) => {
d2.write(`const ${valVar} = ${accessor}[${kVar}];`);
const valOutput = compileChild(d2, ctx, def.valueType, valVar);
d2.write(`${outputVar}[${kVar}] = ${valOutput};`);
+ }, `return INVALID;`);
+ return outputVar;
+}
+function emitOwnKeys(doc, ctx, accessor, kVar, body, onSymbol) {
+ const propIsEnumerableConst = addConstant(ctx, Object.prototype.propertyIsEnumerable);
+ const symsVar = newVar(ctx);
+ const keysVar = newVar(ctx);
+ const iVar = newVar(ctx);
+ doc.write(`const ${symsVar} = Object.getOwnPropertySymbols(${accessor});`);
+ doc.write(`const ${keysVar} = Object.getOwnPropertyNames(${accessor});`);
+ doc.write(`for (let ${iVar} = 0; ${iVar} < ${keysVar}.length; ${iVar}++) {`);
+ doc.indented((d2) => {
+ d2.write(`const ${kVar} = ${keysVar}[${iVar}];`);
+ d2.write(`if (${kVar} === "__proto__" || !${propIsEnumerableConst}.call(${accessor}, ${kVar})) continue;`);
+ body(d2);
+ });
+ doc.write(`}`);
+ doc.write(`for (let ${iVar} = 0; ${iVar} < ${symsVar}.length; ${iVar}++) {`);
+ doc.indented((d2) => {
+ d2.write(`const ${kVar} = ${symsVar}[${iVar}];`);
+ d2.write(`if (!${propIsEnumerableConst}.call(${accessor}, ${kVar})) continue;`);
+ if (onSymbol)
+ d2.write(onSymbol);
+ else
+ body(d2);
});
doc.write(`}`);
- return outputVar;
}
function literalPropertyKey(ctx, key) {
if (typeof key === "string")
@@ -20864,7 +21318,7 @@ function generateTemplateLiteralCheck(doc, ctx, schema, accessor) {
}
function generateLazyCheck(doc, ctx, schema, accessor) {
const def = schema._zod.def;
- const getterConst = addConstant(ctx, def.getter);
+ const getterConst = addUserConstant(ctx, def.getter);
const cacheConst = addConstant(ctx, { parser: null });
doc.write(`if (!${cacheConst}.parser) {`);
doc.indented((d2) => {
@@ -20897,7 +21351,7 @@ function generatePipeCheck(doc, ctx, schema, accessor) {
return INVALID;
return fakePayload.issues.length === 0 ? result : INVALID;
};
- const helperConst = addConstant(ctx, helperFn);
+ const helperConst = addUserConstant(ctx, helperFn);
const transformedVar = newVar(ctx);
doc.write(`const ${transformedVar} = ${helperConst}(${inputOutput});`);
doc.write(`if (${transformedVar} === INVALID) return INVALID;`);
@@ -20915,7 +21369,7 @@ function generateCustomCheck(doc, ctx, schema, accessor) {
if (isAsyncFunction(def.fn)) {
throw new ZodCompileAsyncError("z.compile: async custom predicates are not supported");
}
- const fnConst = addConstant(ctx, def.fn);
+ const fnConst = addUserConstant(ctx, def.fn);
const throwAsyncConst = addConstant(ctx, throwAsync);
const resVar = newVar(ctx);
doc.write(`const ${resVar} = ${fnConst}(${accessor});`);
@@ -20948,7 +21402,7 @@ function generateCatchCheck(doc, ctx, schema, accessor) {
});
doc.write(`})();`);
const innerConst = addConstant(ctx, def.innerType);
- const catchConst = addConstant(ctx, def.catchValue);
+ const catchConst = addUserConstant(ctx, def.catchValue);
const catchHelperConst = addConstant(ctx, runtimeCatch);
doc.write(`if (${outputVar} === INVALID) {`);
doc.indented((d2) => {
@@ -20972,7 +21426,7 @@ function generateTransformCheck(doc, ctx, schema, accessor) {
return INVALID;
return fakePayload.issues.length === 0 ? result : INVALID;
};
- const helperConst = addConstant(ctx, helperFn);
+ const helperConst = addUserConstant(ctx, helperFn);
const outputVar = newVar(ctx);
doc.write(`const ${outputVar} = ${helperConst}(${accessor});`);
doc.write(`if (${outputVar} === INVALID) return INVALID;`);
@@ -20982,20 +21436,18 @@ function generateTransformCheck(doc, ctx, schema, accessor) {
}
// node_modules/zod/v4/core/api.js
+function snapshotChecks(def) {
+ if (def.checks)
+ def.checks = [...def.checks];
+ return def;
+}
// @__NO_SIDE_EFFECTS__
function _string(Class2, params) {
- return new Class2({
- type: "string",
- ...normalizeParams(params)
- });
+ return new Class2(snapshotChecks({ type: "string", ...normalizeParams(params) }));
}
// @__NO_SIDE_EFFECTS__
function _coercedString(Class2, params) {
- return new Class2({
- type: "string",
- coerce: true,
- ...normalizeParams(params)
- });
+ return new Class2(snapshotChecks({ type: "string", coerce: true, ...normalizeParams(params) }));
}
// @__NO_SIDE_EFFECTS__
function _email(Class2, params) {
@@ -21231,6 +21683,16 @@ function _creditCard(Class2, params) {
});
}
// @__NO_SIDE_EFFECTS__
+function _iban(Class2, params) {
+ return new Class2({
+ type: "string",
+ format: "iban",
+ check: "string_format",
+ abort: false,
+ ...normalizeParams(params)
+ });
+}
+// @__NO_SIDE_EFFECTS__
function _jwt(Class2, params) {
return new Class2({
type: "string",
@@ -21289,20 +21751,11 @@ function _isoDuration(Class2, params) {
}
// @__NO_SIDE_EFFECTS__
function _number(Class2, params) {
- return new Class2({
- type: "number",
- checks: [],
- ...normalizeParams(params)
- });
+ return new Class2(snapshotChecks({ type: "number", checks: [], ...normalizeParams(params) }));
}
// @__NO_SIDE_EFFECTS__
function _coercedNumber(Class2, params) {
- return new Class2({
- type: "number",
- coerce: true,
- checks: [],
- ...normalizeParams(params)
- });
+ return new Class2(snapshotChecks({ type: "number", coerce: true, checks: [], ...normalizeParams(params) }));
}
// @__NO_SIDE_EFFECTS__
function _int(Class2, params) {
@@ -21644,8 +22097,12 @@ function _property(property, schema, params) {
});
}
// @__NO_SIDE_EFFECTS__
-function _properties(shape) {
- return Object.entries(shape).map(([property, schema]) => new $ZodCheckProperty({ check: "property", property, schema }));
+function _properties(shape, params) {
+ return new $ZodCheckProperties({
+ check: "properties",
+ shape,
+ ...normalizeParams(params)
+ });
}
// @__NO_SIDE_EFFECTS__
function _mime(types, params) {
@@ -22082,7 +22539,7 @@ function handleUnrepresentable(schema, ctx, json2, params, message) {
Object.assign(json2, result);
return true;
}
-function process2(schema, ctx, _params = { path: [], schemaPath: [] }) {
+function processSchema(schema, ctx, _params = { path: [], schemaPath: [] }) {
var _a3;
const def = schema._zod.def;
const seen = ctx.seen.get(schema);
@@ -22121,7 +22578,7 @@ function process2(schema, ctx, _params = { path: [], schemaPath: [] }) {
if (parent) {
if (!result.ref)
result.ref = parent;
- process2(parent, ctx, params);
+ processSchema(parent, ctx, params);
ctx.seen.get(parent).isParent = true;
}
}
@@ -22228,7 +22685,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
if (seen.count > 1) {
if (ctx.reused === "ref") {
extractToDef(entry);
- continue;
}
}
}
@@ -22556,19 +23012,107 @@ function isTransforming(_schema, _ctx) {
}
var createToJSONSchemaMethod = (schema, processors = {}) => (params) => {
const ctx = initializeContext({ ...params, processors });
- process2(schema, ctx);
+ processSchema(schema, ctx);
extractDefs(ctx, schema);
return finalize(ctx, schema);
};
var createStandardJSONSchemaMethod = (schema, io, processors = {}) => (params) => {
const { libraryOptions, target } = params ?? {};
const ctx = initializeContext({ ...libraryOptions ?? {}, target, io, processors });
- process2(schema, ctx);
+ processSchema(schema, ctx);
extractDefs(ctx, schema);
return finalize(ctx, schema);
};
// node_modules/zod/v4/core/json-schema-processors.js
+var narrowMin = (agg, key, value) => {
+ if (agg[key] === void 0 || value > agg[key])
+ agg[key] = value;
+};
+var narrowMax = (agg, key, value) => {
+ if (agg[key] === void 0 || value < agg[key])
+ agg[key] = value;
+};
+var narrowBoth = (agg, value) => {
+ narrowMin(agg, "minimum", value);
+ narrowMax(agg, "maximum", value);
+};
+var addDivisor = (agg, value) => {
+ agg.multipleOf ?? (agg.multipleOf = []);
+ if (!agg.multipleOf.includes(value))
+ agg.multipleOf.push(value);
+};
+var addPattern = (agg, pattern) => {
+ agg.patterns ?? (agg.patterns = /* @__PURE__ */ new Set());
+ agg.patterns.add(pattern);
+};
+var intersectMime = (agg, mime) => {
+ agg.mime = agg.mime ? agg.mime.filter((m2) => mime.includes(m2)) : [...mime];
+};
+var setFormat = (agg, format) => {
+ agg.format = format;
+ if (format.includes("int"))
+ agg.isInt = true;
+};
+var minContributor = (agg, def) => narrowMin(agg, "minimum", def.minimum);
+var maxContributor = (agg, def) => narrowMax(agg, "maximum", def.maximum);
+var formatContributor = (ranges) => (agg, def) => {
+ setFormat(agg, def.format);
+ const [minimum, maximum] = ranges[def.format];
+ narrowMin(agg, "minimum", minimum);
+ narrowMax(agg, "maximum", maximum);
+};
+var contributors = {
+ greater_than: (agg, def) => narrowMin(agg, def.inclusive ? "minimum" : "exclusiveMinimum", def.value),
+ less_than: (agg, def) => narrowMax(agg, def.inclusive ? "maximum" : "exclusiveMaximum", def.value),
+ multiple_of: (agg, def) => addDivisor(agg, def.value),
+ number_format: formatContributor(NUMBER_FORMAT_RANGES),
+ bigint_format: formatContributor(BIGINT_FORMAT_RANGES),
+ min_length: minContributor,
+ max_length: maxContributor,
+ length_equals: (agg, def) => narrowBoth(agg, def.length),
+ min_size: minContributor,
+ max_size: maxContributor,
+ size_equals: (agg, def) => narrowBoth(agg, def.size),
+ string_format: (agg, def) => {
+ setFormat(agg, def.format);
+ if (def.pattern)
+ addPattern(agg, def.pattern);
+ if (def.format === "base64" || def.format === "base64url")
+ agg.contentEncoding = def.format;
+ if (def.local || def.precision === -1)
+ agg.laxFormat = true;
+ },
+ mime_type: (agg, def) => intersectMime(agg, def.mime)
+};
+function aggregateChecks(schema) {
+ const agg = {};
+ const def = schema._zod.def;
+ const list = schema._zod.traits.has("$ZodCheck") ? [schema, ...def.checks ?? []] : def.checks ?? [];
+ for (const ch of list)
+ contributors[ch._zod.def.check]?.(agg, ch._zod.def);
+ const bag = schema._zod.bag;
+ if (bag.minimum !== void 0)
+ narrowMin(agg, "minimum", bag.minimum);
+ if (bag.exclusiveMinimum !== void 0)
+ narrowMin(agg, "exclusiveMinimum", bag.exclusiveMinimum);
+ if (bag.maximum !== void 0)
+ narrowMax(agg, "maximum", bag.maximum);
+ if (bag.exclusiveMaximum !== void 0)
+ narrowMax(agg, "exclusiveMaximum", bag.exclusiveMaximum);
+ if (bag.multipleOf !== void 0)
+ addDivisor(agg, bag.multipleOf);
+ if (bag.format !== void 0) {
+ agg.format ?? (agg.format = bag.format);
+ if (bag.format.includes("int"))
+ agg.isInt = true;
+ }
+ if (bag.mime)
+ intersectMime(agg, bag.mime);
+ for (const pattern of bag.patterns ?? [])
+ addPattern(agg, pattern);
+ return agg;
+}
var formatMap = {
guid: "uuid",
url: "uri",
@@ -22577,10 +23121,15 @@ var formatMap = {
regex: ""
// do not set
};
+var exactPatterns = /* @__PURE__ */ new Map([
+ [base64Charset, base64],
+ [base64urlCharset, base64url]
+]);
+var exactPattern = (p) => exactPatterns.get(p) ?? p;
var stringProcessor = (schema, ctx, _json, _params) => {
const json2 = _json;
json2.type = "string";
- const { minimum, maximum, format, patterns, contentEncoding, laxFormat } = schema._zod.bag;
+ const { minimum, maximum, format, patterns, contentEncoding, laxFormat } = aggregateChecks(schema);
if (typeof minimum === "number")
json2.minLength = minimum;
if (typeof maximum === "number")
@@ -22596,7 +23145,7 @@ var stringProcessor = (schema, ctx, _json, _params) => {
if (contentEncoding)
json2.contentEncoding = contentEncoding;
if (patterns && patterns.size > 0) {
- const patternList = [...patterns];
+ const patternList = [...patterns].map(exactPattern);
if (patternList.length === 1)
json2.pattern = patternList[0].source;
else if (patternList.length > 1) {
@@ -22611,11 +23160,8 @@ var stringProcessor = (schema, ctx, _json, _params) => {
};
var numberProcessor = (schema, ctx, _json, params) => {
const json2 = _json;
- const { minimum, maximum, format, multipleOf, exclusiveMaximum, exclusiveMinimum } = schema._zod.bag;
- if (typeof format === "string" && format.includes("int"))
- json2.type = "integer";
- else
- json2.type = "number";
+ const { minimum, maximum, multipleOf, exclusiveMaximum, exclusiveMinimum, isInt } = aggregateChecks(schema);
+ json2.type = isInt ? "integer" : "number";
const exMin = typeof exclusiveMinimum === "number" && exclusiveMinimum >= (minimum ?? Number.NEGATIVE_INFINITY);
const exMax = typeof exclusiveMaximum === "number" && exclusiveMaximum <= (maximum ?? Number.POSITIVE_INFINITY);
const legacy = ctx.target === "draft-04" || ctx.target === "openapi-3.0";
@@ -22639,11 +23185,19 @@ var numberProcessor = (schema, ctx, _json, params) => {
} else if (typeof maximum === "number") {
json2.maximum = maximum;
}
- if (typeof multipleOf === "number") {
- if (Number.isFinite(multipleOf) && multipleOf !== 0)
- json2.multipleOf = Math.abs(multipleOf);
- else
- handleUnrepresentable(schema, ctx, json2, params, `A multipleOf divisor of ${multipleOf} cannot be represented in JSON Schema`);
+ if (multipleOf) {
+ const divisors = /* @__PURE__ */ new Set();
+ for (const divisor of multipleOf) {
+ if (Number.isFinite(divisor) && divisor !== 0)
+ divisors.add(Math.abs(divisor));
+ else
+ handleUnrepresentable(schema, ctx, json2, params, `A multipleOf divisor of ${divisor} cannot be represented in JSON Schema`);
+ }
+ const [first, ...rest] = divisors;
+ if (first !== void 0)
+ json2.multipleOf = first;
+ if (rest.length)
+ json2.allOf = [...json2.allOf ?? [], ...rest.map((m2) => ({ multipleOf: m2 }))];
}
};
var booleanProcessor = (_schema, _ctx, json2, _params) => {
@@ -22746,27 +23300,22 @@ var templateLiteralProcessor = (schema, _ctx, json2, _params) => {
};
var fileProcessor = (schema, _ctx, json2, _params) => {
const _json = json2;
- const file2 = {
- type: "string",
- format: "binary",
- contentEncoding: "binary"
- };
- const { minimum, maximum, mime } = schema._zod.bag;
+ _json.type = "string";
+ _json.format = "binary";
+ _json.contentEncoding = "binary";
+ const { minimum, maximum, mime } = aggregateChecks(schema);
if (minimum !== void 0)
- file2.minLength = minimum;
+ _json.minLength = minimum;
if (maximum !== void 0)
- file2.maxLength = maximum;
- if (mime) {
- if (mime.length === 1) {
- file2.contentMediaType = mime[0];
- Object.assign(_json, file2);
- } else {
- Object.assign(_json, file2);
- _json.anyOf = mime.map((m2) => ({ contentMediaType: m2 }));
- }
- } else {
- Object.assign(_json, file2);
- }
+ _json.maxLength = maximum;
+ if (!mime)
+ return;
+ if (mime.length === 0)
+ _json.not = {};
+ else if (mime.length === 1)
+ _json.contentMediaType = mime[0];
+ else
+ _json.anyOf = mime.map((m2) => ({ contentMediaType: m2 }));
};
var successProcessor = (_schema, _ctx, json2, _params) => {
json2.type = "boolean";
@@ -22789,13 +23338,13 @@ var setProcessor = (schema, ctx, json2, params) => {
var arrayProcessor = (schema, ctx, _json, params) => {
const json2 = _json;
const def = schema._zod.def;
- const { minimum, maximum } = schema._zod.bag;
+ const { minimum, maximum } = aggregateChecks(schema);
if (typeof minimum === "number")
json2.minItems = minimum;
if (typeof maximum === "number")
json2.maxItems = maximum;
json2.type = "array";
- json2.items = process2(def.element, ctx, {
+ json2.items = processSchema(def.element, ctx, {
...params,
path: [...params.path, "items"]
});
@@ -22821,22 +23370,20 @@ var objectProcessor = (schema, ctx, _json, params) => {
json2.type = "object";
json2.properties = {};
for (const key in shape) {
- assignProp(json2.properties, key, process2(shape[key], ctx, {
+ assignProp(json2.properties, key, processSchema(shape[key], ctx, {
...params,
path: [...params.path, "properties", key]
}));
}
- const allKeys = new Set(Object.keys(shape));
- const requiredKeys = new Set([...allKeys].filter((key) => {
+ const requiredKeys = [];
+ for (const key of Object.keys(shape)) {
const field = def.shape[key];
- if (ctx.io === "input") {
- return inputOptin(field) === void 0;
- } else {
- return field._zod.optout === void 0;
+ if (ctx.io === "input" ? inputOptin(field) === void 0 : field._zod.optout === void 0) {
+ requiredKeys.push(key);
}
- }));
- if (requiredKeys.size > 0) {
- json2.required = Array.from(requiredKeys);
+ }
+ if (requiredKeys.length > 0) {
+ json2.required = requiredKeys;
}
if (def.catchall?._zod.def.type === "never") {
json2.additionalProperties = false;
@@ -22844,7 +23391,7 @@ var objectProcessor = (schema, ctx, _json, params) => {
if (ctx.io === "output")
json2.additionalProperties = false;
} else if (def.catchall) {
- json2.additionalProperties = process2(def.catchall, ctx, {
+ json2.additionalProperties = processSchema(def.catchall, ctx, {
...params,
path: [...params.path, "additionalProperties"]
});
@@ -22853,7 +23400,7 @@ var objectProcessor = (schema, ctx, _json, params) => {
var unionProcessor = (schema, ctx, json2, params) => {
const def = schema._zod.def;
const isExclusive = def.inclusive === false;
- const options = def.options.map((x2, i) => process2(x2, ctx, {
+ const options = def.options.map((x2, i) => processSchema(x2, ctx, {
...params,
path: [...params.path, isExclusive ? "oneOf" : "anyOf", i]
}));
@@ -22865,11 +23412,11 @@ var unionProcessor = (schema, ctx, json2, params) => {
};
var intersectionProcessor = (schema, ctx, json2, params) => {
const def = schema._zod.def;
- const a = process2(def.left, ctx, {
+ const a = processSchema(def.left, ctx, {
...params,
path: [...params.path, "allOf", 0]
});
- const b2 = process2(def.right, ctx, {
+ const b2 = processSchema(def.right, ctx, {
...params,
path: [...params.path, "allOf", 1]
});
@@ -22887,11 +23434,11 @@ var tupleProcessor = (schema, ctx, _json, params) => {
json2.type = "array";
const prefixPath = ctx.target === "draft-2020-12" ? "prefixItems" : "items";
const restPath = ctx.target === "draft-2020-12" ? "items" : ctx.target === "openapi-3.0" ? "items" : "additionalItems";
- const prefixItems = def.items.map((x2, i) => process2(x2, ctx, {
+ const prefixItems = def.items.map((x2, i) => processSchema(x2, ctx, {
...params,
path: [...params.path, prefixPath, i]
}));
- const rest = def.rest ? process2(def.rest, ctx, {
+ const rest = def.rest ? processSchema(def.rest, ctx, {
...params,
path: [...params.path, restPath, ...ctx.target === "openapi-3.0" ? [def.items.length] : []]
}) : null;
@@ -22939,7 +23486,7 @@ var tupleProcessor = (schema, ctx, _json, params) => {
if (isClosed)
json2.maxItems = maxItems;
}
- const { minimum, maximum } = schema._zod.bag;
+ const { minimum, maximum } = aggregateChecks(schema);
if (typeof minimum === "number")
json2.minItems = minimum;
if (typeof maximum === "number")
@@ -23013,20 +23560,19 @@ var recordProcessor = (schema, ctx, _json, params) => {
const def = schema._zod.def;
json2.type = "object";
const keyType = def.keyType;
- const keyBag = keyType._zod.bag;
- const patterns = keyBag?.patterns;
+ const patterns = aggregateChecks(keyType).patterns;
if (def.mode === "loose" && patterns && patterns.size > 0) {
- const valueSchema = process2(def.valueType, ctx, {
+ const valueSchema = processSchema(def.valueType, ctx, {
...params,
path: [...params.path, "patternProperties", "*"]
});
json2.patternProperties = {};
for (const pattern of patterns) {
- assignProp(json2.patternProperties, pattern.source, valueSchema);
+ assignProp(json2.patternProperties, exactPattern(pattern).source, valueSchema);
}
} else {
if (ctx.target === "draft-07" || ctx.target === "draft-2020-12") {
- json2.propertyNames = process2(def.keyType, ctx, {
+ json2.propertyNames = processSchema(def.keyType, ctx, {
...params,
path: [...params.path, "propertyNames"]
});
@@ -23038,7 +23584,7 @@ var recordProcessor = (schema, ctx, _json, params) => {
}
pending.push(schema);
}
- json2.additionalProperties = process2(def.valueType, ctx, {
+ json2.additionalProperties = processSchema(def.valueType, ctx, {
...params,
path: [...params.path, "additionalProperties"]
});
@@ -23054,7 +23600,7 @@ var recordProcessor = (schema, ctx, _json, params) => {
};
var nullableProcessor = (schema, ctx, json2, params) => {
const def = schema._zod.def;
- const inner = process2(def.innerType, ctx, params);
+ const inner = processSchema(def.innerType, ctx, params);
const seen = ctx.seen.get(schema);
if (ctx.target === "openapi-3.0") {
seen.ref = def.innerType;
@@ -23065,7 +23611,7 @@ var nullableProcessor = (schema, ctx, json2, params) => {
};
var nonoptionalProcessor = (schema, ctx, _json, params) => {
const def = schema._zod.def;
- process2(def.innerType, ctx, params);
+ processSchema(def.innerType, ctx, params);
const seen = ctx.seen.get(schema);
seen.ref = def.innerType;
};
@@ -23085,7 +23631,7 @@ function serializeDefaultValue(value, schema, ctx, json2, params) {
}
var defaultProcessor = (schema, ctx, json2, params) => {
const def = schema._zod.def;
- process2(def.innerType, ctx, params);
+ processSchema(def.innerType, ctx, params);
const seen = ctx.seen.get(schema);
seen.ref = def.innerType;
const value = serializeDefaultValue(def.defaultValue, schema, ctx, json2, params);
@@ -23094,7 +23640,7 @@ var defaultProcessor = (schema, ctx, json2, params) => {
};
var prefaultProcessor = (schema, ctx, json2, params) => {
const def = schema._zod.def;
- process2(def.innerType, ctx, params);
+ processSchema(def.innerType, ctx, params);
const seen = ctx.seen.get(schema);
seen.ref = def.innerType;
if (ctx.io !== "input")
@@ -23105,7 +23651,7 @@ var prefaultProcessor = (schema, ctx, json2, params) => {
};
var catchProcessor = (schema, ctx, json2, params) => {
const def = schema._zod.def;
- process2(def.innerType, ctx, params);
+ processSchema(def.innerType, ctx, params);
const seen = ctx.seen.get(schema);
seen.ref = def.innerType;
let catchValue;
@@ -23121,32 +23667,32 @@ var pipeProcessor = (schema, ctx, _json, params) => {
const def = schema._zod.def;
const inIsTransform = def.in._zod.traits.has("$ZodTransform");
const innerType = ctx.io === "input" ? inIsTransform ? def.out : def.in : def.out;
- process2(innerType, ctx, params);
+ processSchema(innerType, ctx, params);
const seen = ctx.seen.get(schema);
seen.ref = innerType;
};
var readonlyProcessor = (schema, ctx, json2, params) => {
const def = schema._zod.def;
- process2(def.innerType, ctx, params);
+ processSchema(def.innerType, ctx, params);
const seen = ctx.seen.get(schema);
seen.ref = def.innerType;
json2.readOnly = true;
};
var promiseProcessor = (schema, ctx, _json, params) => {
const def = schema._zod.def;
- process2(def.innerType, ctx, params);
+ processSchema(def.innerType, ctx, params);
const seen = ctx.seen.get(schema);
seen.ref = def.innerType;
};
var optionalProcessor = (schema, ctx, _json, params) => {
const def = schema._zod.def;
- process2(def.innerType, ctx, params);
+ processSchema(def.innerType, ctx, params);
const seen = ctx.seen.get(schema);
seen.ref = def.innerType;
};
var lazyProcessor = (schema, ctx, _json, params) => {
const innerType = schema._zod.innerType;
- process2(innerType, ctx, params);
+ processSchema(innerType, ctx, params);
const seen = ctx.seen.get(schema);
seen.ref = innerType;
};
@@ -23198,7 +23744,7 @@ function toJSONSchema(input2, params) {
const defs = {};
for (const entry of registry2._idmap.entries()) {
const [_2, schema] = entry;
- process2(schema, ctx2);
+ processSchema(schema, ctx2);
}
const schemas = {};
const external = {
@@ -23221,7 +23767,7 @@ function toJSONSchema(input2, params) {
return { schemas };
}
const ctx = initializeContext({ ...params, processors: allProcessors });
- process2(input2, ctx);
+ processSchema(input2, ctx);
extractDefs(ctx, input2);
return finalize(ctx, input2);
}
@@ -23280,7 +23826,7 @@ var JSONSchemaGenerator = class {
* This must be called before emit().
*/
process(schema, _params = { path: [], schemaPath: [] }) {
- return process2(schema, this.ctx, _params);
+ return processSchema(schema, this.ctx, _params);
}
/**
* Emit the final JSON Schema after processing.
@@ -23479,24 +24025,24 @@ function safeParse2(schema, data) {
function getObjectShape(schema) {
if (!schema)
return void 0;
- let rawShape;
+ let rawShape2;
if (isZ4Schema(schema)) {
const v4Schema = schema;
- rawShape = v4Schema._zod?.def?.shape;
+ rawShape2 = v4Schema._zod?.def?.shape;
} else {
const v3Schema = schema;
- rawShape = v3Schema.shape;
+ rawShape2 = v3Schema.shape;
}
- if (!rawShape)
+ if (!rawShape2)
return void 0;
- if (typeof rawShape === "function") {
+ if (typeof rawShape2 === "function") {
try {
- return rawShape();
+ return rawShape2();
} catch {
return void 0;
}
}
- return rawShape;
+ return rawShape2;
}
function getLiteralValue(schema) {
if (isZ4Schema(schema)) {
@@ -23531,6 +24077,7 @@ __export(external_exports, {
$brand: () => $brand,
$input: () => $input,
$output: () => $output,
+ INVALID: () => INVALID,
NEVER: () => NEVER,
TimePrecision: () => TimePrecision,
ZodAny: () => ZodAny,
@@ -23564,12 +24111,14 @@ __export(external_exports, {
ZodFirstPartyTypeKind: () => ZodFirstPartyTypeKind,
ZodFunction: () => ZodFunction,
ZodGUID: () => ZodGUID,
+ ZodIBAN: () => ZodIBAN,
ZodIPv4: () => ZodIPv4,
ZodIPv6: () => ZodIPv6,
ZodISODate: () => ZodISODate,
ZodISODateTime: () => ZodISODateTime,
ZodISODuration: () => ZodISODuration,
ZodISOTime: () => ZodISOTime,
+ ZodInstanceOf: () => ZodInstanceOf,
ZodIntersection: () => ZodIntersection,
ZodIssueCode: () => ZodIssueCode,
ZodJWT: () => ZodJWT,
@@ -23635,6 +24184,7 @@ __export(external_exports, {
creditCard: () => creditCard2,
cuid: () => cuid3,
cuid2: () => cuid22,
+ currencyCode: () => currencyCode2,
custom: () => custom,
date: () => date2,
decode: () => decode2,
@@ -23667,6 +24217,7 @@ __export(external_exports, {
hex: () => hex2,
hostname: () => hostname2,
httpUrl: () => httpUrl,
+ iban: () => iban2,
includes: () => _includes,
input: () => input,
instanceof: () => _instanceof,
@@ -23778,6 +24329,7 @@ __export(external_exports, {
validate: () => validate,
validateAsync: () => validateAsync,
void: () => _void2,
+ withParser: () => withParser,
xid: () => xid2,
xor: () => xor
});
@@ -23812,12 +24364,14 @@ __export(schemas_exports2, {
ZodFile: () => ZodFile,
ZodFunction: () => ZodFunction,
ZodGUID: () => ZodGUID,
+ ZodIBAN: () => ZodIBAN,
ZodIPv4: () => ZodIPv4,
ZodIPv6: () => ZodIPv6,
ZodISODate: () => ZodISODate,
ZodISODateTime: () => ZodISODateTime,
ZodISODuration: () => ZodISODuration,
ZodISOTime: () => ZodISOTime,
+ ZodInstanceOf: () => ZodInstanceOf,
ZodIntersection: () => ZodIntersection,
ZodJWT: () => ZodJWT,
ZodKSUID: () => ZodKSUID,
@@ -23876,6 +24430,7 @@ __export(schemas_exports2, {
creditCard: () => creditCard2,
cuid: () => cuid3,
cuid2: () => cuid22,
+ currencyCode: () => currencyCode2,
custom: () => custom,
date: () => date2,
describe: () => describe2,
@@ -23894,6 +24449,7 @@ __export(schemas_exports2, {
hex: () => hex2,
hostname: () => hostname2,
httpUrl: () => httpUrl,
+ iban: () => iban2,
instanceof: () => _instanceof,
int: () => int,
int32: () => int32,
@@ -24196,6 +24752,12 @@ var ZodType = /* @__PURE__ */ $constructor("ZodType", (inst, def) => {
set spa(value) {
util_exports.own(this, "spa", value);
},
+ validate(data, params) {
+ return validate(this, data, params);
+ },
+ validateAsync(data, params) {
+ return validateAsync(this, data, params);
+ },
encode: function _encode2(data, params) {
return encode2(this, data, params, { callee: _encode2 });
},
@@ -24232,61 +24794,65 @@ var ZodType = /* @__PURE__ */ $constructor("ZodType", (inst, def) => {
return this._zod.def;
}
});
-var _ZodString = /* @__PURE__ */ $constructor("_ZodString", (inst, def) => {
- $ZodString.init(inst, def);
- ZodType.init(inst, def);
- inst._zod.processJSONSchema = (ctx, json2, params) => stringProcessor(inst, ctx, json2, params);
- const bag = inst._zod.bag;
- inst.format = bag.format ?? null;
- inst.minLength = bag.minimum ?? null;
- inst.maxLength = bag.maximum ?? null;
-}, {
- regex(...args) {
- return this.check(_regex(...args));
- },
- includes(...args) {
- return this.check(_includes(...args));
- },
- startsWith(...args) {
- return this.check(_startsWith(...args));
- },
- endsWith(...args) {
- return this.check(_endsWith(...args));
- },
- min(...args) {
- return this.check(_minLength(...args));
+var _ZodString = /* @__PURE__ */ $constructor(
+ "_ZodString",
+ (inst, def) => {
+ $ZodString.init(inst, def);
+ ZodType.init(inst, def);
+ inst._zod.processJSONSchema = (ctx, json2, params) => stringProcessor(inst, ctx, json2, params);
},
- max(...args) {
- return this.check(_maxLength(...args));
- },
- length(...args) {
- return this.check(_length(...args));
- },
- nonempty(...args) {
- return this.check(_minLength(1, ...args));
- },
- lowercase(params) {
- return this.check(_lowercase(params));
- },
- uppercase(params) {
- return this.check(_uppercase(params));
- },
- trim() {
- return this.check(_trim());
- },
- normalize(...args) {
- return this.check(_normalize(...args));
- },
- toLowerCase() {
- return this.check(_toLowerCase());
- },
- toUpperCase() {
- return this.check(_toUpperCase());
- },
- slugify() {
- return this.check(_slugify());
- }
-});
+ /* @__PURE__ */ util_exports.derived({
+ format: (inst) => aggregateChecks(inst).format ?? null,
+ minLength: (inst) => aggregateChecks(inst).minimum ?? null,
+ maxLength: (inst) => aggregateChecks(inst).maximum ?? null
+ }, {
+ regex(...args) {
+ return this.check(_regex(...args));
+ },
+ includes(...args) {
+ return this.check(_includes(...args));
+ },
+ startsWith(...args) {
+ return this.check(_startsWith(...args));
+ },
+ endsWith(...args) {
+ return this.check(_endsWith(...args));
+ },
+ min(...args) {
+ return this.check(_minLength(...args));
+ },
+ max(...args) {
+ return this.check(_maxLength(...args));
+ },
+ length(...args) {
+ return this.check(_length(...args));
+ },
+ nonempty(...args) {
+ return this.check(_minLength(1, ...args));
+ },
+ lowercase(params) {
+ return this.check(_lowercase(params));
+ },
+ uppercase(params) {
+ return this.check(_uppercase(params));
+ },
+ trim() {
+ return this.check(_trim());
+ },
+ normalize(...args) {
+ return this.check(_normalize(...args));
+ },
+ toLowerCase() {
+ return this.check(_toLowerCase());
+ },
+ toUpperCase() {
+ return this.check(_toUpperCase());
+ },
+ slugify() {
+ return this.check(_slugify());
+ }
+ })
+);
var ZodString = /* @__PURE__ */ $constructor("ZodString", (inst, def) => {
$ZodString.init(inst, def);
_ZodString.init(inst, def);
@@ -24432,8 +24998,8 @@ function url(params) {
}
function httpUrl(params) {
return _url(ZodURL, {
- protocol: regexes_exports.httpProtocol,
- hostname: regexes_exports.domain,
+ protocol: httpProtocol,
+ hostname: domain,
...util_exports.normalizeParams(params)
});
}
@@ -24549,6 +25115,13 @@ var ZodCreditCard = /* @__PURE__ */ $constructor("ZodCreditCard", (inst, def) =>
function creditCard2(params) {
return _creditCard(ZodCreditCard, params);
}
+var ZodIBAN = /* @__PURE__ */ $constructor("ZodIBAN", (inst, def) => {
+ $ZodIBAN.init(inst, def);
+ ZodStringFormat.init(inst, def);
+});
+function iban2(params) {
+ return _iban(ZodIBAN, params);
+}
var ZodJWT = /* @__PURE__ */ $constructor("ZodJWT", (inst, def) => {
$ZodJWT.init(inst, def);
ZodStringFormat.init(inst, def);
@@ -24564,10 +25137,13 @@ function stringFormat(format, fnOrRegex, _params = {}) {
return _stringFormat(ZodCustomStringFormat, format, fnOrRegex, _params);
}
function hostname2(_params) {
- return _stringFormat(ZodCustomStringFormat, "hostname", regexes_exports.hostname, _params);
+ return _stringFormat(ZodCustomStringFormat, "hostname", hostname, _params);
}
function hex2(_params) {
- return _stringFormat(ZodCustomStringFormat, "hex", regexes_exports.hex, _params);
+ return _stringFormat(ZodCustomStringFormat, "hex", hex, _params);
+}
+function currencyCode2(_params) {
+ return _stringFormat(ZodCustomStringFormat, "currency_code", currencyCode, _params);
}
function hash(alg, params) {
const enc = params?.enc ?? "hex";
@@ -24577,63 +25153,76 @@ function hash(alg, params) {
throw new Error(`Unrecognized hash format: ${format}`);
return _stringFormat(ZodCustomStringFormat, format, regex, params);
}
-var ZodNumber = /* @__PURE__ */ $constructor("ZodNumber", (inst, def) => {
- $ZodNumber.init(inst, def);
- ZodType.init(inst, def);
- inst._zod.processJSONSchema = (ctx, json2, params) => numberProcessor(inst, ctx, json2, params);
- const bag = inst._zod.bag;
- inst.minValue = Math.max(bag.minimum ?? Number.NEGATIVE_INFINITY, bag.exclusiveMinimum ?? Number.NEGATIVE_INFINITY) ?? null;
- inst.maxValue = Math.min(bag.maximum ?? Number.POSITIVE_INFINITY, bag.exclusiveMaximum ?? Number.POSITIVE_INFINITY) ?? null;
- inst.isInt = (bag.format ?? "").includes("int") || Number.isSafeInteger(bag.multipleOf ?? 0.5);
- inst.isFinite = true;
- inst.format = bag.format ?? null;
-}, {
- gt(value, params) {
- return this.check(_gt(value, params));
- },
- gte(value, params) {
- return this.check(_gte(value, params));
- },
- min(value, params) {
- return this.check(_gte(value, params));
- },
- lt(value, params) {
- return this.check(_lt(value, params));
- },
- lte(value, params) {
- return this.check(_lte(value, params));
- },
- max(value, params) {
- return this.check(_lte(value, params));
- },
- int(params) {
- return this.check(int(params));
- },
- safe(params) {
- return this.check(int(params));
+var ZodNumber = /* @__PURE__ */ $constructor(
+ "ZodNumber",
+ (inst, def) => {
+ $ZodNumber.init(inst, def);
+ ZodType.init(inst, def);
+ inst._zod.processJSONSchema = (ctx, json2, params) => numberProcessor(inst, ctx, json2, params);
+ inst.isFinite = true;
},
- positive(params) {
- return this.check(_gt(0, params));
- },
- nonnegative(params) {
- return this.check(_gte(0, params));
- },
- negative(params) {
- return this.check(_lt(0, params));
- },
- nonpositive(params) {
- return this.check(_lte(0, params));
- },
- multipleOf(value, params) {
- return this.check(_multipleOf(value, params));
- },
- step(value, params) {
- return this.check(_multipleOf(value, params));
- },
- finite() {
- return this;
- }
-});
+ /* @__PURE__ */ util_exports.derived({
+ minValue: (inst) => {
+ const { minimum, exclusiveMinimum } = aggregateChecks(inst);
+ return Math.max(minimum ?? Number.NEGATIVE_INFINITY, exclusiveMinimum ?? Number.NEGATIVE_INFINITY);
+ },
+ maxValue: (inst) => {
+ const { maximum, exclusiveMaximum } = aggregateChecks(inst);
+ return Math.min(maximum ?? Number.POSITIVE_INFINITY, exclusiveMaximum ?? Number.POSITIVE_INFINITY);
+ },
+ isInt: (inst) => {
+ const { isInt, multipleOf } = aggregateChecks(inst);
+ return !!isInt || !!multipleOf?.some(Number.isSafeInteger);
+ },
+ format: (inst) => aggregateChecks(inst).format ?? null
+ }, {
+ gt(value, params) {
+ return this.check(_gt(value, params));
+ },
+ gte(value, params) {
+ return this.check(_gte(value, params));
+ },
+ min(value, params) {
+ return this.check(_gte(value, params));
+ },
+ lt(value, params) {
+ return this.check(_lt(value, params));
+ },
+ lte(value, params) {
+ return this.check(_lte(value, params));
+ },
+ max(value, params) {
+ return this.check(_lte(value, params));
+ },
+ int(params) {
+ return this.check(int(params));
+ },
+ safe(params) {
+ return this.check(int(params));
+ },
+ positive(params) {
+ return this.check(_gt(0, params));
+ },
+ nonnegative(params) {
+ return this.check(_gte(0, params));
+ },
+ negative(params) {
+ return this.check(_lt(0, params));
+ },
+ nonpositive(params) {
+ return this.check(_lte(0, params));
+ },
+ multipleOf(value, params) {
+ return this.check(_multipleOf(value, params));
+ },
+ step(value, params) {
+ return this.check(_multipleOf(value, params));
+ },
+ finite() {
+ return this;
+ }
+ })
+);
function number2(params) {
return _number(ZodNumber, params);
}
@@ -24664,49 +25253,53 @@ var ZodBoolean = /* @__PURE__ */ $constructor("ZodBoolean", (inst, def) => {
function boolean2(params) {
return _boolean(ZodBoolean, params);
}
-var ZodBigInt = /* @__PURE__ */ $constructor("ZodBigInt", (inst, def) => {
- $ZodBigInt.init(inst, def);
- ZodType.init(inst, def);
- inst._zod.processJSONSchema = (ctx, json2, params) => bigintProcessor(inst, ctx, json2, params);
- const bag = inst._zod.bag;
- inst.minValue = bag.minimum ?? null;
- inst.maxValue = bag.maximum ?? null;
- inst.format = bag.format ?? null;
-}, {
- gte(value, params) {
- return this.check(_gte(value, params));
- },
- min(value, params) {
- return this.check(_gte(value, params));
- },
- gt(value, params) {
- return this.check(_gt(value, params));
- },
- lt(value, params) {
- return this.check(_lt(value, params));
+var ZodBigInt = /* @__PURE__ */ $constructor(
+ "ZodBigInt",
+ (inst, def) => {
+ $ZodBigInt.init(inst, def);
+ ZodType.init(inst, def);
+ inst._zod.processJSONSchema = (ctx, json2, params) => bigintProcessor(inst, ctx, json2, params);
},
- lte(value, params) {
- return this.check(_lte(value, params));
- },
- max(value, params) {
- return this.check(_lte(value, params));
- },
- positive(params) {
- return this.check(_gt(BigInt(0), params));
- },
- negative(params) {
- return this.check(_lt(BigInt(0), params));
- },
- nonpositive(params) {
- return this.check(_lte(BigInt(0), params));
- },
- nonnegative(params) {
- return this.check(_gte(BigInt(0), params));
- },
- multipleOf(value, params) {
- return this.check(_multipleOf(value, params));
- }
-});
+ /* @__PURE__ */ util_exports.derived({
+ minValue: (inst) => aggregateChecks(inst).minimum ?? null,
+ maxValue: (inst) => aggregateChecks(inst).maximum ?? null,
+ format: (inst) => aggregateChecks(inst).format ?? null
+ }, {
+ gte(value, params) {
+ return this.check(_gte(value, params));
+ },
+ min(value, params) {
+ return this.check(_gte(value, params));
+ },
+ gt(value, params) {
+ return this.check(_gt(value, params));
+ },
+ lt(value, params) {
+ return this.check(_lt(value, params));
+ },
+ lte(value, params) {
+ return this.check(_lte(value, params));
+ },
+ max(value, params) {
+ return this.check(_lte(value, params));
+ },
+ positive(params) {
+ return this.check(_gt(BigInt(0), params));
+ },
+ negative(params) {
+ return this.check(_lt(BigInt(0), params));
+ },
+ nonpositive(params) {
+ return this.check(_lte(BigInt(0), params));
+ },
+ nonnegative(params) {
+ return this.check(_gte(BigInt(0), params));
+ },
+ multipleOf(value, params) {
+ return this.check(_multipleOf(value, params));
+ }
+ })
+);
function bigint2(params) {
return _bigint(ZodBigInt, params);
}
@@ -24776,16 +25369,26 @@ var ZodVoid = /* @__PURE__ */ $constructor("ZodVoid", (inst, def) => {
function _void2(params) {
return _void(ZodVoid, params);
}
-var ZodDate = /* @__PURE__ */ $constructor("ZodDate", (inst, def) => {
- $ZodDate.init(inst, def);
- ZodType.init(inst, def);
- inst._zod.processJSONSchema = (ctx, json2, params) => dateProcessor(inst, ctx, json2, params);
- inst.min = (value, params) => inst.check(_gte(value, params));
- inst.max = (value, params) => inst.check(_lte(value, params));
- const c = inst._zod.bag;
- inst.minDate = c.minimum ? new Date(c.minimum) : null;
- inst.maxDate = c.maximum ? new Date(c.maximum) : null;
-});
+var ZodDate = /* @__PURE__ */ $constructor(
+ "ZodDate",
+ (inst, def) => {
+ $ZodDate.init(inst, def);
+ ZodType.init(inst, def);
+ inst._zod.processJSONSchema = (ctx, json2, params) => dateProcessor(inst, ctx, json2, params);
+ inst.min = (value, params) => inst.check(_gte(value, params));
+ inst.max = (value, params) => inst.check(_lte(value, params));
+ },
+ /* @__PURE__ */ util_exports.derived({
+ minDate: (inst) => {
+ const { minimum } = aggregateChecks(inst);
+ return minimum ? new Date(minimum) : null;
+ },
+ maxDate: (inst) => {
+ const { maximum } = aggregateChecks(inst);
+ return maximum ? new Date(maximum) : null;
+ }
+ }, {})
+);
function date2(params) {
return _date(ZodDate, params);
}
@@ -24830,19 +25433,19 @@ var ZodObject = /* @__PURE__ */ $constructor("ZodObject", (inst, def) => {
return _enum2(Object.keys(this._zod.def.shape));
},
catchall(catchall) {
- return this.clone({ ...this._zod.def, catchall });
+ return this.clone(util_exports.mergeDefs(this._zod.def, { catchall }));
},
passthrough() {
- return this.clone({ ...this._zod.def, catchall: unknown() });
+ return this.clone(util_exports.mergeDefs(this._zod.def, { catchall: unknown() }));
},
loose() {
- return this.clone({ ...this._zod.def, catchall: unknown() });
+ return this.clone(util_exports.mergeDefs(this._zod.def, { catchall: unknown() }));
},
strict() {
- return this.clone({ ...this._zod.def, catchall: never() });
+ return this.clone(util_exports.mergeDefs(this._zod.def, { catchall: never() }));
},
strip() {
- return this.clone({ ...this._zod.def, catchall: void 0 });
+ return this.clone(util_exports.mergeDefs(this._zod.def, { catchall: void 0 }));
},
extend(incoming) {
return util_exports.extend(this, incoming);
@@ -25061,7 +25664,7 @@ var ZodEnum = /* @__PURE__ */ $constructor("ZodEnum", (inst, def) => {
ZodType.init(inst, def);
inst._zod.processJSONSchema = (ctx, json2, params) => enumProcessor(inst, ctx, json2, params);
inst.enum = def.entries;
- inst.options = Object.values(def.entries);
+ inst.options = [...inst._zod.values];
const keys = new Set(Object.keys(def.entries));
inst.extract = (values, params) => {
const newEntries = {};
@@ -25424,8 +26027,15 @@ function superRefine(fn, params) {
}
var describe2 = describe;
var meta2 = meta;
+var ZodInstanceOf = /* @__PURE__ */ $constructor("ZodInstanceOf", (inst, def) => {
+ ZodCustom.init(inst, def);
+}, {
+ properties(shape, params) {
+ return this.check(_properties(shape, params));
+ }
+});
function _instanceof(cls, params = {}) {
- const inst = new ZodCustom({
+ const inst = new ZodInstanceOf({
type: "custom",
check: "custom",
fn: (data) => data instanceof cls,
@@ -25630,27 +26240,188 @@ function resolveRef(ref, ctx) {
}
throw new Error(`Reference not found: ${ref}`);
}
-function checkPropertyNames(objectSchema, keySchema) {
+function checkObjectGuards(objectSchema, guards) {
const guard = z.transform((value) => value).check((payload) => {
const value = payload.value;
if (typeof value !== "object" || value === null || Array.isArray(value))
return;
- for (const key of Object.getOwnPropertyNames(value)) {
- const result = keySchema.safeParse(key);
- if (result.success)
- continue;
+ const keys = Object.getOwnPropertyNames(value);
+ if (guards.minProperties !== void 0 && keys.length < guards.minProperties) {
payload.issues.push({
- code: "invalid_key",
- origin: "record",
- issues: result.error.issues,
- input: key,
- path: [key],
+ origin: "object",
+ code: "too_small",
+ minimum: guards.minProperties,
+ inclusive: true,
+ message: `Too small: expected object to have >=${guards.minProperties} properties`,
+ input: value,
+ inst: objectSchema,
+ continue: true
+ });
+ }
+ if (guards.maxProperties !== void 0 && keys.length > guards.maxProperties) {
+ payload.issues.push({
+ origin: "object",
+ code: "too_big",
+ maximum: guards.maxProperties,
+ inclusive: true,
+ message: `Too big: expected object to have <=${guards.maxProperties} properties`,
+ input: value,
+ inst: objectSchema,
continue: true
});
}
+ if (guards.keySchema) {
+ for (const key of keys) {
+ const result = guards.keySchema.safeParse(key);
+ if (result.success)
+ continue;
+ payload.issues.push({
+ code: "invalid_key",
+ origin: "record",
+ issues: result.error.issues,
+ input: key,
+ path: [key],
+ continue: true
+ });
+ }
+ }
});
return guard.pipe(objectSchema);
}
+function canonicalKey(value, seen) {
+ if (value === null)
+ return "z";
+ const type = typeof value;
+ if (type !== "object") {
+ if (type === "number" && Number.isNaN(value))
+ return null;
+ const raw = String(value);
+ return `${type[0]}${raw.length}:${raw}`;
+ }
+ if (seen.has(value))
+ return null;
+ seen.add(value);
+ try {
+ if (Array.isArray(value)) {
+ const parts2 = [];
+ for (const item of value) {
+ const key = canonicalKey(item, seen);
+ if (key === null)
+ return null;
+ parts2.push(key);
+ }
+ return `a${parts2.length}:[${parts2.join(",")}]`;
+ }
+ const keys = Object.keys(value).sort();
+ const parts = [];
+ for (const k2 of keys) {
+ const key = canonicalKey(value[k2], seen);
+ if (key === null)
+ return null;
+ parts.push(`${k2.length}:${k2}=${key}`);
+ }
+ return `o${parts.length}:{${parts.join(",")}}`;
+ } finally {
+ seen.delete(value);
+ }
+}
+var SCHEMA_KEYWORDS = /* @__PURE__ */ new Set([
+ "items",
+ "prefixItems",
+ "additionalItems",
+ "additionalProperties",
+ "contains",
+ "propertyNames",
+ "not",
+ "if",
+ "then",
+ "else",
+ "allOf",
+ "anyOf",
+ "oneOf",
+ "unevaluatedItems",
+ "unevaluatedProperties",
+ "contentSchema"
+]);
+var SCHEMA_MAP_KEYWORDS = /* @__PURE__ */ new Set([
+ "properties",
+ "patternProperties",
+ "dependentSchemas",
+ "dependencies",
+ "$defs",
+ "definitions"
+]);
+function containsRef(value) {
+ if (typeof value !== "object" || value === null)
+ return false;
+ if (Array.isArray(value))
+ return value.some(containsRef);
+ if (typeof value.$ref === "string")
+ return true;
+ return Object.entries(value).some(([key, sub]) => {
+ if (SCHEMA_KEYWORDS.has(key))
+ return containsRef(sub);
+ if (!SCHEMA_MAP_KEYWORDS.has(key) || typeof sub !== "object" || sub === null)
+ return false;
+ return Object.values(sub).some(containsRef);
+ });
+}
+function plural(n) {
+ return n === 1 ? "element" : "elements";
+}
+function checkArrayGuards(arraySchema, guards) {
+ const guard = z.transform((value) => value).check((payload) => {
+ const items = payload.value;
+ if (!Array.isArray(items))
+ return;
+ if (guards.uniqueItems === true) {
+ const firstSeen = /* @__PURE__ */ new Map();
+ for (let i = 0; i < items.length; i++) {
+ const key = canonicalKey(items[i], /* @__PURE__ */ new Set());
+ if (key === null)
+ continue;
+ const first = firstSeen.get(key);
+ if (first === void 0) {
+ firstSeen.set(key, i);
+ continue;
+ }
+ payload.issues.push({
+ code: "custom",
+ message: `Array items must be unique: element at index ${i} duplicates the one at index ${first}`,
+ input: items,
+ path: [i],
+ continue: true
+ });
+ }
+ }
+ if (guards.containsSchema) {
+ const minContains = guards.minContains ?? 1;
+ const ceiling = guards.maxContains !== void 0 ? guards.maxContains + 1 : Number.POSITIVE_INFINITY;
+ let matches = 0;
+ for (const item of items) {
+ if (guards.containsSchema.safeParse(item).success && ++matches >= ceiling)
+ break;
+ }
+ if (matches < minContains) {
+ payload.issues.push({
+ code: "custom",
+ message: `Array must contain at least ${minContains} matching ${plural(minContains)}; found ${matches}`,
+ input: items,
+ continue: true
+ });
+ }
+ if (guards.maxContains !== void 0 && matches > guards.maxContains) {
+ payload.issues.push({
+ code: "custom",
+ message: `Array must contain at most ${guards.maxContains} matching ${plural(guards.maxContains)}`,
+ input: items,
+ continue: true
+ });
+ }
+ }
+ });
+ return guard.pipe(arraySchema);
+}
function getTupleRest(restSchema, ctx) {
if (restSchema === false) {
return void 0;
@@ -25780,6 +26551,8 @@ function convertBaseSchema(schema, ctx) {
stringSchema = stringSchema.check(z.e164());
} else if (format === "credit_card") {
stringSchema = stringSchema.check(z.creditCard());
+ } else if (format === "iban") {
+ stringSchema = stringSchema.check(z.iban());
} else if (format === "jwt") {
stringSchema = stringSchema.check(z.jwt());
} else if (format === "emoji") {
@@ -25912,9 +26685,16 @@ function convertBaseSchema(schema, ctx) {
zodSchema = objectSchema.passthrough();
}
}
- if (schema.propertyNames !== void 0 && schema.propertyNames !== true) {
- const keyJSONSchema = typeof schema.propertyNames === "object" && schema.propertyNames.type === void 0 ? { type: "string", ...schema.propertyNames } : schema.propertyNames;
- zodSchema = checkPropertyNames(zodSchema, convertSchema(keyJSONSchema, ctx));
+ const hasKeyGuard = schema.propertyNames !== void 0 && schema.propertyNames !== true;
+ const minProperties = typeof schema.minProperties === "number" ? schema.minProperties : void 0;
+ const maxProperties = typeof schema.maxProperties === "number" ? schema.maxProperties : void 0;
+ if (hasKeyGuard || minProperties !== void 0 || maxProperties !== void 0) {
+ let keySchema;
+ if (hasKeyGuard) {
+ const keyJSONSchema = typeof schema.propertyNames === "object" && schema.propertyNames.type === void 0 ? { type: "string", ...schema.propertyNames } : schema.propertyNames;
+ keySchema = convertSchema(keyJSONSchema, ctx);
+ }
+ zodSchema = checkObjectGuards(zodSchema, { keySchema, minProperties, maxProperties });
}
break;
}
@@ -25960,6 +26740,14 @@ function convertBaseSchema(schema, ctx) {
} else {
zodSchema = z.array(z.any());
}
+ if (schema.uniqueItems === true || schema.contains !== void 0) {
+ zodSchema = checkArrayGuards(zodSchema, {
+ uniqueItems: schema.uniqueItems === true,
+ containsSchema: schema.contains !== void 0 ? convertSchema(schema.contains, ctx) : void 0,
+ minContains: typeof schema.minContains === "number" ? schema.minContains : void 0,
+ maxContains: typeof schema.maxContains === "number" ? schema.maxContains : void 0
+ });
+ }
break;
}
default:
@@ -26017,8 +26805,23 @@ function convertSchema(schema, ctx) {
extraMeta[key] = schema[key];
}
}
- if (schema.propertyNames !== void 0 && schema.type === "object" && schema.$ref === void 0) {
- extraMeta.propertyNames = schema.propertyNames;
+ if (schema.type === "object" && schema.$ref === void 0) {
+ if (schema.propertyNames !== void 0 && !containsRef(schema.propertyNames)) {
+ extraMeta.propertyNames = schema.propertyNames;
+ }
+ for (const key of ["minProperties", "maxProperties"]) {
+ if (schema[key] !== void 0)
+ extraMeta[key] = schema[key];
+ }
+ }
+ if (schema.type === "array" && schema.$ref === void 0) {
+ if (schema.contains !== void 0 && !containsRef(schema.contains)) {
+ extraMeta.contains = schema.contains;
+ }
+ for (const key of ["uniqueItems", "minContains", "maxContains"]) {
+ if (schema[key] !== void 0)
+ extraMeta[key] = schema[key];
+ }
}
for (const key of Object.keys(schema)) {
if (!RECOGNIZED_KEYS.has(key)) {
@@ -27715,6 +28518,9 @@ var Protocol = class {
this.setRequestHandler(GetTaskPayloadRequestSchema, async (request, extra) => {
const handleTaskResult = async () => {
const taskId = request.params.taskId;
+ if (!await this._taskStore.getTask(taskId, extra.sessionId)) {
+ throw new McpError(ErrorCode.InvalidParams, `Task not found: ${taskId}`);
+ }
if (this._taskMessageQueue) {
let queuedMessage;
while (queuedMessage = await this._taskMessageQueue.dequeue(taskId, extra.sessionId)) {
@@ -27728,8 +28534,8 @@ var Protocol = class {
resolver(message);
} else {
const errorMessage = message;
- const error61 = new McpError(errorMessage.error.code, errorMessage.error.message, errorMessage.error.data);
- resolver(error61);
+ const error62 = new McpError(errorMessage.error.code, errorMessage.error.message, errorMessage.error.data);
+ resolver(error62);
}
} else {
const messageType = queuedMessage.type === "response" ? "Response" : "Error";
@@ -27745,12 +28551,12 @@ var Protocol = class {
throw new McpError(ErrorCode.InvalidParams, `Task not found: ${taskId}`);
}
if (!isTerminal(task.status)) {
- await this._waitForTaskUpdate(taskId, extra.signal);
+ await this._waitForTaskUpdate(taskId, extra.signal, extra.sessionId);
return await handleTaskResult();
}
if (isTerminal(task.status)) {
const result = await this._taskStore.getTaskResult(taskId, extra.sessionId);
- this._clearTaskQueue(taskId);
+ this._clearTaskQueue(taskId, extra.sessionId);
return {
...result,
_meta: {
@@ -27773,8 +28579,8 @@ var Protocol = class {
nextCursor,
_meta: {}
};
- } catch (error61) {
- throw new McpError(ErrorCode.InvalidParams, `Failed to list tasks: ${error61 instanceof Error ? error61.message : String(error61)}`);
+ } catch (error62) {
+ throw new McpError(ErrorCode.InvalidParams, `Failed to list tasks: ${error62 instanceof Error ? error62.message : String(error62)}`);
}
});
this.setRequestHandler(CancelTaskRequestSchema, async (request, extra) => {
@@ -27787,7 +28593,7 @@ var Protocol = class {
throw new McpError(ErrorCode.InvalidParams, `Cannot cancel task in terminal status: ${task.status}`);
}
await this._taskStore.updateTaskStatus(request.params.taskId, "cancelled", "Client cancelled task execution.", extra.sessionId);
- this._clearTaskQueue(request.params.taskId);
+ this._clearTaskQueue(request.params.taskId, extra.sessionId);
const cancelledTask = await this._taskStore.getTask(request.params.taskId, extra.sessionId);
if (!cancelledTask) {
throw new McpError(ErrorCode.InvalidParams, `Task not found after cancellation: ${request.params.taskId}`);
@@ -27796,11 +28602,11 @@ var Protocol = class {
_meta: {},
...cancelledTask
};
- } catch (error61) {
- if (error61 instanceof McpError) {
- throw error61;
+ } catch (error62) {
+ if (error62 instanceof McpError) {
+ throw error62;
}
- throw new McpError(ErrorCode.InvalidRequest, `Failed to cancel task: ${error61 instanceof Error ? error61.message : String(error61)}`);
+ throw new McpError(ErrorCode.InvalidRequest, `Failed to cancel task: ${error62 instanceof Error ? error62.message : String(error62)}`);
}
});
}
@@ -27861,9 +28667,9 @@ var Protocol = class {
this._onclose();
};
const _onerror = this.transport?.onerror;
- this._transport.onerror = (error61) => {
- _onerror?.(error61);
- this._onerror(error61);
+ this._transport.onerror = (error62) => {
+ _onerror?.(error62);
+ this._onerror(error62);
};
const _onmessage = this._transport?.onmessage;
this._transport.onmessage = (message, extra) => {
@@ -27894,27 +28700,40 @@ var Protocol = class {
controller.abort();
}
this._requestHandlerAbortControllers.clear();
- const error61 = McpError.fromError(ErrorCode.ConnectionClosed, "Connection closed");
+ const error62 = McpError.fromError(ErrorCode.ConnectionClosed, "Connection closed");
this._transport = void 0;
this.onclose?.();
for (const handler of responseHandlers.values()) {
- handler(error61);
+ handler(error62);
}
}
- _onerror(error61) {
- this.onerror?.(error61);
+ _onerror(error62) {
+ this.onerror?.(error62);
}
_onnotification(notification) {
const handler = this._notificationHandlers.get(notification.method) ?? this.fallbackNotificationHandler;
if (handler === void 0) {
return;
}
- Promise.resolve().then(() => handler(notification)).catch((error61) => this._onerror(new Error(`Uncaught error in notification handler: ${error61}`)));
+ Promise.resolve().then(() => handler(notification)).catch((error62) => this._onerror(new Error(`Uncaught error in notification handler: ${error62}`)));
}
_onrequest(request, extra) {
const handler = this._requestHandlers.get(request.method) ?? this.fallbackRequestHandler;
const capturedTransport = this._transport;
const relatedTaskId = request.params?._meta?.[RELATED_TASK_META_KEY]?.taskId;
+ const sessionId = capturedTransport?.sessionId;
+ const store = this._taskStore;
+ let relatedTaskFound = true;
+ let relatedTaskLookup;
+ if (relatedTaskId && store && this._taskMessageQueue && sessionId !== void 0) {
+ relatedTaskFound = false;
+ relatedTaskLookup = (async () => {
+ if (!await store.getTask(relatedTaskId, sessionId)) {
+ throw new McpError(ErrorCode.InvalidParams, `Task not found: ${relatedTaskId}`);
+ }
+ relatedTaskFound = true;
+ })();
+ }
if (handler === void 0) {
const errorResponse = {
jsonrpc: "2.0",
@@ -27924,14 +28743,17 @@ var Protocol = class {
message: "Method not found"
}
};
- if (relatedTaskId && this._taskMessageQueue) {
+ if (relatedTaskId && relatedTaskLookup) {
+ const queuedError = { type: "error", message: errorResponse, timestamp: Date.now() };
+ relatedTaskLookup.then(() => this._enqueueTaskMessage(relatedTaskId, queuedError, sessionId), () => capturedTransport?.send(errorResponse)).catch((error62) => this._onerror(new Error(`Failed to send an error response: ${error62}`)));
+ } else if (relatedTaskId && this._taskMessageQueue) {
this._enqueueTaskMessage(relatedTaskId, {
type: "error",
message: errorResponse,
timestamp: Date.now()
- }, capturedTransport?.sessionId).catch((error61) => this._onerror(new Error(`Failed to enqueue error response: ${error61}`)));
+ }, capturedTransport?.sessionId).catch((error62) => this._onerror(new Error(`Failed to enqueue error response: ${error62}`)));
} else {
- capturedTransport?.send(errorResponse).catch((error61) => this._onerror(new Error(`Failed to send an error response: ${error61}`)));
+ capturedTransport?.send(errorResponse).catch((error62) => this._onerror(new Error(`Failed to send an error response: ${error62}`)));
}
return;
}
@@ -27975,7 +28797,10 @@ var Protocol = class {
closeSSEStream: extra?.closeSSEStream,
closeStandaloneSSEStream: extra?.closeStandaloneSSEStream
};
- Promise.resolve().then(() => {
+ (relatedTaskLookup ?? Promise.resolve()).then(() => {
+ if (relatedTaskLookup && abortController.signal.aborted) {
+ throw new McpError(ErrorCode.ConnectionClosed, "Request was cancelled");
+ }
if (taskCreationParams) {
this.assertTaskHandlerCapability(request.method);
}
@@ -27997,7 +28822,7 @@ var Protocol = class {
} else {
await capturedTransport?.send(response);
}
- }, async (error61) => {
+ }, async (error62) => {
if (abortController.signal.aborted) {
return;
}
@@ -28005,12 +28830,12 @@ var Protocol = class {
jsonrpc: "2.0",
id: request.id,
error: {
- code: Number.isSafeInteger(error61["code"]) ? error61["code"] : ErrorCode.InternalError,
- message: error61.message ?? "Internal error",
- ...error61["data"] !== void 0 && { data: error61["data"] }
+ code: Number.isSafeInteger(error62["code"]) ? error62["code"] : ErrorCode.InternalError,
+ message: error62.message ?? "Internal error",
+ ...error62["data"] !== void 0 && { data: error62["data"] }
}
};
- if (relatedTaskId && this._taskMessageQueue) {
+ if (relatedTaskId && this._taskMessageQueue && relatedTaskFound) {
await this._enqueueTaskMessage(relatedTaskId, {
type: "error",
message: errorResponse,
@@ -28019,7 +28844,7 @@ var Protocol = class {
} else {
await capturedTransport?.send(errorResponse);
}
- }).catch((error61) => this._onerror(new Error(`Failed to send response: ${error61}`))).finally(() => {
+ }).catch((error62) => this._onerror(new Error(`Failed to send response: ${error62}`))).finally(() => {
if (this._requestHandlerAbortControllers.get(request.id) === abortController) {
this._requestHandlerAbortControllers.delete(request.id);
}
@@ -28038,11 +28863,11 @@ var Protocol = class {
if (timeoutInfo && responseHandler && timeoutInfo.resetTimeoutOnProgress) {
try {
this._resetTimeout(messageId);
- } catch (error61) {
+ } catch (error62) {
this._responseHandlers.delete(messageId);
this._progressHandlers.delete(messageId);
this._cleanupTimeout(messageId);
- responseHandler(error61);
+ responseHandler(error62);
return;
}
}
@@ -28056,8 +28881,8 @@ var Protocol = class {
if (isJSONRPCResultResponse(response)) {
resolver(response);
} else {
- const error61 = new McpError(response.error.code, response.error.message, response.error.data);
- resolver(error61);
+ const error62 = new McpError(response.error.code, response.error.message, response.error.data);
+ resolver(error62);
}
return;
}
@@ -28085,8 +28910,8 @@ var Protocol = class {
if (isJSONRPCResultResponse(response)) {
handler(response);
} else {
- const error61 = McpError.fromError(response.error.code, response.error.message, response.error.data);
- handler(error61);
+ const error62 = McpError.fromError(response.error.code, response.error.message, response.error.data);
+ handler(error62);
}
}
get transport() {
@@ -28131,10 +28956,10 @@ var Protocol = class {
try {
const result = await this.request(request, resultSchema, options);
yield { type: "result", result };
- } catch (error61) {
+ } catch (error62) {
yield {
type: "error",
- error: error61 instanceof McpError ? error61 : new McpError(ErrorCode.InternalError, String(error61))
+ error: error62 instanceof McpError ? error62 : new McpError(ErrorCode.InternalError, String(error62))
};
}
return;
@@ -28177,10 +29002,10 @@ var Protocol = class {
await new Promise((resolve) => setTimeout(resolve, pollInterval));
options?.signal?.throwIfAborted();
}
- } catch (error61) {
+ } catch (error62) {
yield {
type: "error",
- error: error61 instanceof McpError ? error61 : new McpError(ErrorCode.InternalError, String(error61))
+ error: error62 instanceof McpError ? error62 : new McpError(ErrorCode.InternalError, String(error62))
};
}
}
@@ -28192,8 +29017,8 @@ var Protocol = class {
request(request, resultSchema, options) {
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
return new Promise((resolve, reject) => {
- const earlyReject = (error61) => {
- reject(error61);
+ const earlyReject = (error62) => {
+ reject(error62);
};
if (!this._transport) {
earlyReject(new Error("Not connected"));
@@ -28253,9 +29078,9 @@ var Protocol = class {
requestId: messageId,
reason: String(reason)
}
- }, { relatedRequestId, resumptionToken, onresumptiontoken }).catch((error62) => this._onerror(new Error(`Failed to send cancellation: ${error62}`)));
- const error61 = reason instanceof McpError ? reason : new McpError(ErrorCode.RequestTimeout, String(reason));
- reject(error61);
+ }, { relatedRequestId, resumptionToken, onresumptiontoken }).catch((error63) => this._onerror(new Error(`Failed to send cancellation: ${error63}`)));
+ const error62 = reason instanceof McpError ? reason : new McpError(ErrorCode.RequestTimeout, String(reason));
+ reject(error62);
};
this._responseHandlers.set(messageId, (response) => {
if (options?.signal?.aborted) {
@@ -28271,8 +29096,8 @@ var Protocol = class {
} else {
resolve(parseResult.data);
}
- } catch (error61) {
- reject(error61);
+ } catch (error62) {
+ reject(error62);
}
});
options?.signal?.addEventListener("abort", () => {
@@ -28296,14 +29121,14 @@ var Protocol = class {
type: "request",
message: jsonrpcRequest,
timestamp: Date.now()
- }).catch((error61) => {
+ }).catch((error62) => {
this._cleanupTimeout(messageId);
- reject(error61);
+ reject(error62);
});
} else {
- this._transport.send(jsonrpcRequest, { relatedRequestId, resumptionToken, onresumptiontoken }).catch((error61) => {
+ this._transport.send(jsonrpcRequest, { relatedRequestId, resumptionToken, onresumptiontoken }).catch((error62) => {
this._cleanupTimeout(messageId);
- reject(error61);
+ reject(error62);
});
}
});
@@ -28396,7 +29221,7 @@ var Protocol = class {
}
};
}
- this._transport?.send(jsonrpcNotification2, options).catch((error61) => this._onerror(error61));
+ this._transport?.send(jsonrpcNotification2, options).catch((error62) => this._onerror(error62));
});
return;
}
@@ -28490,7 +29315,7 @@ var Protocol = class {
throw new Error("Cannot enqueue task message: taskStore and taskMessageQueue are not configured");
}
const maxQueueSize = this._options?.maxTaskQueueSize;
- await this._taskMessageQueue.enqueue(taskId, message, sessionId, maxQueueSize);
+ await this._taskMessageQueue.enqueue(taskId, message, sessionId ?? this._transport?.sessionId, maxQueueSize);
}
/**
* Clears the message queue for a task and rejects any pending request resolvers.
@@ -28519,12 +29344,13 @@ var Protocol = class {
* Uses polling to check for updates at the task's configured poll interval.
* @param taskId The task ID to wait for
* @param signal Abort signal to cancel the wait
+ * @param sessionId Session of the request that waits, passed to the task store
* @returns Promise that resolves when an update occurs or rejects if aborted
*/
- async _waitForTaskUpdate(taskId, signal) {
+ async _waitForTaskUpdate(taskId, signal, sessionId) {
let interval = this._options?.defaultTaskPollInterval ?? 1e3;
try {
- const task = await this._taskStore?.getTask(taskId);
+ const task = await this._taskStore?.getTask(taskId, sessionId);
if (task?.pollInterval) {
interval = task.pollInterval;
}
@@ -29249,11 +30075,11 @@ var Server = class extends Protocol {
if (!validationResult.valid) {
throw new McpError(ErrorCode.InvalidParams, `Elicitation response content does not match requested schema: ${validationResult.errorMessage}`);
}
- } catch (error61) {
- if (error61 instanceof McpError) {
- throw error61;
+ } catch (error62) {
+ if (error62 instanceof McpError) {
+ throw error62;
}
- throw new McpError(ErrorCode.InternalError, `Error validating elicitation response: ${error61 instanceof Error ? error61.message : String(error61)}`);
+ throw new McpError(ErrorCode.InternalError, `Error validating elicitation response: ${error62 instanceof Error ? error62.message : String(error62)}`);
}
}
return result;
@@ -29316,7 +30142,7 @@ var Server = class extends Protocol {
};
// node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
-import process3 from "node:process";
+import process2 from "node:process";
// node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js
var STDIO_DEFAULT_MAX_BUFFER_SIZE = 10 * 1024 * 1024;
@@ -29357,7 +30183,7 @@ function serializeMessage(message) {
// node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
var StdioServerTransport = class {
- constructor(_stdin = process3.stdin, _stdout = process3.stdout, options) {
+ constructor(_stdin = process2.stdin, _stdout = process2.stdout, options) {
this._stdin = _stdin;
this._stdout = _stdout;
this._started = false;
@@ -29365,14 +30191,14 @@ var StdioServerTransport = class {
try {
this._readBuffer.append(chunk);
this.processReadBuffer();
- } catch (error61) {
- this.onerror?.(error61);
+ } catch (error62) {
+ this.onerror?.(error62);
this.close().catch(() => {
});
}
};
- this._onerror = (error61) => {
- this.onerror?.(error61);
+ this._onerror = (error62) => {
+ this.onerror?.(error62);
};
this._readBuffer = new ReadBuffer({ maxBufferSize: options?.maxBufferSize });
}
@@ -29395,8 +30221,8 @@ var StdioServerTransport = class {
break;
}
this.onmessage?.(message);
- } catch (error61) {
- this.onerror?.(error61);
+ } catch (error62) {
+ this.onerror?.(error62);
}
}
}
@@ -29454,6 +30280,16 @@ function getSuperpowersDir() {
}
return ensureDir(dir);
}
+function getModelCacheDir() {
+ const override = process.env.EPISODIC_MEMORY_MODEL_CACHE_DIR;
+ if (override) {
+ if (!path.isAbsolute(override)) {
+ throw new Error("EPISODIC_MEMORY_MODEL_CACHE_DIR must be an absolute path");
+ }
+ return ensureDir(override);
+ }
+ return ensureDir(path.join(getSuperpowersDir(), "models"));
+}
function getIndexDir() {
return ensureDir(path.join(getSuperpowersDir(), "conversation-index"));
}
@@ -29652,16 +30488,20 @@ var EmbeddingsUnavailableError = class extends Error {
};
async function initEmbeddings() {
if (embeddingPipeline) return;
+ const modelCacheDir = getModelCacheDir();
+ const offline = process.env.EPISODIC_MEMORY_OFFLINE === "1";
let pipeline;
try {
const transformers = await import("@huggingface/transformers");
+ transformers.env.cacheDir = modelCacheDir;
transformers.env.allowLocalModels = true;
+ transformers.env.allowRemoteModels = !offline;
transformers.env.useBrowserCache = false;
pipeline = transformers.pipeline;
- } catch (error61) {
+ } catch (error62) {
throw new EmbeddingsUnavailableError(
- `Failed to load the embedding backend (@huggingface/transformers). This usually means the native "sharp" binding could not load libvips; semantic search and indexing are unavailable until it is fixed. Underlying error: ${error61 instanceof Error ? error61.message : String(error61)}`,
- { cause: error61 }
+ `Failed to load the embedding backend (@huggingface/transformers). This usually means the native "sharp" binding could not load libvips; semantic search and indexing are unavailable until it is fixed. Underlying error: ${error62 instanceof Error ? error62.message : String(error62)}`,
+ { cause: error62 }
);
}
console.error("Loading embedding model (first run may take time)...");
@@ -29677,7 +30517,12 @@ async function initEmbeddings() {
interOpNumThreads: 1
};
}
- embeddingPipeline = await pipeline("feature-extraction", MODEL_ID, options);
+ try {
+ embeddingPipeline = await pipeline("feature-extraction", MODEL_ID, options);
+ } catch (error62) {
+ const message = offline ? "Embedding model unavailable in the local cache while EPISODIC_MEMORY_OFFLINE=1; pre-seed the model cache or disable offline mode." : "Embedding model unavailable; check the model cache and remote model access.";
+ throw new EmbeddingsUnavailableError(message, { cause: error62 });
+ }
console.error("Embedding model loaded");
}
async function generateEmbedding(text) {
@@ -29913,7 +30758,7 @@ async function countLines(filePath) {
if (line.trim()) count++;
}
return count;
- } catch (error61) {
+ } catch (error62) {
return 0;
}
}
@@ -29921,7 +30766,7 @@ function getFileSizeInKB(filePath) {
try {
const stats = fs3.statSync(filePath);
return Math.round(stats.size / 1024 * 10) / 10;
- } catch (error61) {
+ } catch (error62) {
return 0;
}
}
@@ -30046,140 +30891,147 @@ function L() {
return { async: false, breaks: false, extensions: null, gfm: true, hooks: null, pedantic: false, renderer: null, silent: false, tokenizer: null, walkTokens: null };
}
var T = L();
-function G(u3) {
- T = u3;
+function G(l3) {
+ T = l3;
}
-var I = { exec: () => null };
-function d(u3, e = "") {
- let t = typeof u3 == "string" ? u3 : u3.source, n = { replace: (r, i) => {
+var E = { exec: () => null };
+function d(l3, e = "") {
+ let t = typeof l3 == "string" ? l3 : l3.source, n = { replace: (r, i) => {
let s = typeof i == "string" ? i : i.source;
return s = s.replace(m.caret, "$1"), t = t.replace(r, s), n;
}, getRegex: () => new RegExp(t, e) };
return n;
}
-var m = { codeRemoveIndent: /^(?: {1,4}| {0,3}\t)/gm, outputLinkReplace: /\\([\[\]])/g, indentCodeCompensation: /^(\s+)(?:```)/, beginningSpace: /^\s+/, endingHash: /#$/, startingSpaceChar: /^ /, endingSpaceChar: / $/, nonSpaceChar: /[^ ]/, newLineCharGlobal: /\n/g, tabCharGlobal: /\t/g, multipleSpaceGlobal: /\s+/g, blankLine: /^[ \t]*$/, doubleBlankLine: /\n[ \t]*\n[ \t]*$/, blockquoteStart: /^ {0,3}>/, blockquoteSetextReplace: /\n {0,3}((?:=+|-+) *)(?=\n|$)/g, blockquoteSetextReplace2: /^ {0,3}>[ \t]?/gm, listReplaceTabs: /^\t+/, listReplaceNesting: /^ {1,4}(?=( {4})*[^ ])/g, listIsTask: /^\[[ xX]\] /, listReplaceTask: /^\[[ xX]\] +/, anyLine: /\n.*\n/, hrefBrackets: /^<(.*)>$/, tableDelimiter: /[:|]/, tableAlignChars: /^\||\| *$/g, tableRowBlankLine: /\n[ \t]*$/, tableAlignRight: /^ *-+: *$/, tableAlignCenter: /^ *:-+: *$/, tableAlignLeft: /^ *:-+ *$/, startATag: /^/i, startPreScriptTag: /^<(pre|code|kbd|script)(\s|>)/i, endPreScriptTag: /^<\/(pre|code|kbd|script)(\s|>)/i, startAngleBracket: /^, endAngleBracket: />$/, pedanticHrefTitle: /^([^'"]*[^\s])\s+(['"])(.*)\2/, unicodeAlphaNumeric: /[\p{L}\p{N}]/u, escapeTest: /[&<>"']/, escapeReplace: /[&<>"']/g, escapeTestNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/, escapeReplaceNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g, unescapeTest: /&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig, caret: /(^|[^\[])\^/g, percentDecode: /%25/g, findPipe: /\|/g, splitPipe: / \|/, slashPipe: /\\\|/g, carriageReturn: /\r\n|\r/g, spaceLine: /^ +$/gm, notSpaceStart: /^\S*/, endingNewline: /\n$/, listItemRegex: (u3) => new RegExp(`^( {0,3}${u3})((?:[ ][^\\n]*)?(?:\\n|$))`), nextBulletRegex: (u3) => new RegExp(`^ {0,${Math.min(3, u3 - 1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ ][^\\n]*)?(?:\\n|$))`), hrRegex: (u3) => new RegExp(`^ {0,${Math.min(3, u3 - 1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`), fencesBeginRegex: (u3) => new RegExp(`^ {0,${Math.min(3, u3 - 1)}}(?:\`\`\`|~~~)`), headingBeginRegex: (u3) => new RegExp(`^ {0,${Math.min(3, u3 - 1)}}#`), htmlBeginRegex: (u3) => new RegExp(`^ {0,${Math.min(3, u3 - 1)}}<(?:[a-z].*>|!--)`, "i") };
-var be = /^(?:[ \t]*(?:\n|$))+/;
-var Re = /^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/;
-var Te = /^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/;
-var E = /^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/;
-var Oe = /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/;
+var be = (() => {
+ try {
+ return !!new RegExp("(?<=1)(?/, blockquoteSetextReplace: /\n {0,3}((?:=+|-+) *)(?=\n|$)/g, blockquoteSetextReplace2: /^ {0,3}>[ \t]?/gm, listReplaceTabs: /^\t+/, listReplaceNesting: /^ {1,4}(?=( {4})*[^ ])/g, listIsTask: /^\[[ xX]\] /, listReplaceTask: /^\[[ xX]\] +/, anyLine: /\n.*\n/, hrefBrackets: /^<(.*)>$/, tableDelimiter: /[:|]/, tableAlignChars: /^\||\| *$/g, tableRowBlankLine: /\n[ \t]*$/, tableAlignRight: /^ *-+: *$/, tableAlignCenter: /^ *:-+: *$/, tableAlignLeft: /^ *:-+ *$/, startATag: /^/i, startPreScriptTag: /^<(pre|code|kbd|script)(\s|>)/i, endPreScriptTag: /^<\/(pre|code|kbd|script)(\s|>)/i, startAngleBracket: /^, endAngleBracket: />$/, pedanticHrefTitle: /^([^'"]*[^\s])\s+(['"])(.*)\2/, unicodeAlphaNumeric: /[\p{L}\p{N}]/u, escapeTest: /[&<>"']/, escapeReplace: /[&<>"']/g, escapeTestNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/, escapeReplaceNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g, unescapeTest: /&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig, caret: /(^|[^\[])\^/g, percentDecode: /%25/g, findPipe: /\|/g, splitPipe: / \|/, slashPipe: /\\\|/g, carriageReturn: /\r\n|\r/g, spaceLine: /^ +$/gm, notSpaceStart: /^\S*/, endingNewline: /\n$/, listItemRegex: (l3) => new RegExp(`^( {0,3}${l3})((?:[ ][^\\n]*)?(?:\\n|$))`), nextBulletRegex: (l3) => new RegExp(`^ {0,${Math.min(3, l3 - 1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ ][^\\n]*)?(?:\\n|$))`), hrRegex: (l3) => new RegExp(`^ {0,${Math.min(3, l3 - 1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`), fencesBeginRegex: (l3) => new RegExp(`^ {0,${Math.min(3, l3 - 1)}}(?:\`\`\`|~~~)`), headingBeginRegex: (l3) => new RegExp(`^ {0,${Math.min(3, l3 - 1)}}#`), htmlBeginRegex: (l3) => new RegExp(`^ {0,${Math.min(3, l3 - 1)}}<(?:[a-z].*>|!--)`, "i") };
+var Re = /^(?:[ \t]*(?:\n|$))+/;
+var Te = /^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/;
+var Oe = /^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/;
+var I = /^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/;
+var we = /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/;
var F = /(?:[*+-]|\d{1,9}[.)])/;
var ie = /^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\n {0,3}(=+|-+) *(?:\n+|$)/;
var oe = d(ie).replace(/bull/g, F).replace(/blockCode/g, /(?: {4}| {0,3}\t)/).replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g, / {0,3}>/).replace(/heading/g, / {0,3}#{1,6}/).replace(/html/g, / {0,3}<[^\n>]+>\n/).replace(/\|table/g, "").getRegex();
-var we = d(ie).replace(/bull/g, F).replace(/blockCode/g, /(?: {4}| {0,3}\t)/).replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g, / {0,3}>/).replace(/heading/g, / {0,3}#{1,6}/).replace(/html/g, / {0,3}<[^\n>]+>\n/).replace(/table/g, / {0,3}\|?(?:[:\- ]*\|)+[\:\- ]*\n/).getRegex();
+var ye = d(ie).replace(/bull/g, F).replace(/blockCode/g, /(?: {4}| {0,3}\t)/).replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g, / {0,3}>/).replace(/heading/g, / {0,3}#{1,6}/).replace(/html/g, / {0,3}<[^\n>]+>\n/).replace(/table/g, / {0,3}\|?(?:[:\- ]*\|)+[\:\- ]*\n/).getRegex();
var j = /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/;
-var ye = /^[^\n]+/;
+var Pe = /^[^\n]+/;
var Q = /(?!\s*\])(?:\\[\s\S]|[^\[\]\\])+/;
-var Pe = d(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/).replace("label", Q).replace("title", /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex();
-var Se = d(/^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/).replace(/bull/g, F).getRegex();
+var Se = d(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/).replace("label", Q).replace("title", /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex();
+var $e = d(/^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/).replace(/bull/g, F).getRegex();
var v = "address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul";
var U = /|$))/;
-var $e = d("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:\\1>[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|\\n*|$)|\\n*|$)|?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|(?!script|pre|style|textarea)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$))", "i").replace("comment", U).replace("tag", v).replace("attribute", / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex();
-var ae = d(j).replace("hr", E).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("|lheading", "").replace("|table", "").replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", "?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", v).getRegex();
-var _e = d(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph", ae).getRegex();
-var K = { blockquote: _e, code: Re, def: Pe, fences: Te, heading: Oe, hr: E, html: $e, lheading: oe, list: Se, newline: be, paragraph: ae, table: I, text: ye };
-var re = d("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr", E).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("blockquote", " {0,3}>").replace("code", "(?: {4}| {0,3} )[^\\n]").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", "?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", v).getRegex();
-var Le = { ...K, lheading: we, table: re, paragraph: d(j).replace("hr", E).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("|lheading", "").replace("table", re).replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", "?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", v).getRegex() };
-var Me = { ...K, html: d(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+?\\1> *(?:\\n{2,}|\\s*$)|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace("comment", U).replace(/tag/g, "(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(), def: /^ *\[([^\]]+)\]: *([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/, heading: /^(#{1,6})(.*)(?:\n+|$)/, fences: I, lheading: /^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/, paragraph: d(j).replace("hr", E).replace("heading", ` *#{1,6} *[^
+var _e = d("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:\\1>[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|\\n*|$)|\\n*|$)|?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|(?!script|pre|style|textarea)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$))", "i").replace("comment", U).replace("tag", v).replace("attribute", / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex();
+var ae = d(j).replace("hr", I).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("|lheading", "").replace("|table", "").replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", "?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", v).getRegex();
+var Le = d(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph", ae).getRegex();
+var K = { blockquote: Le, code: Te, def: Se, fences: Oe, heading: we, hr: I, html: _e, lheading: oe, list: $e, newline: Re, paragraph: ae, table: E, text: Pe };
+var re = d("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr", I).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("blockquote", " {0,3}>").replace("code", "(?: {4}| {0,3} )[^\\n]").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", "?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", v).getRegex();
+var Me = { ...K, lheading: ye, table: re, paragraph: d(j).replace("hr", I).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("|lheading", "").replace("table", re).replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", "?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", v).getRegex() };
+var ze = { ...K, html: d(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+?\\1> *(?:\\n{2,}|\\s*$)|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace("comment", U).replace(/tag/g, "(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(), def: /^ *\[([^\]]+)\]: *([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/, heading: /^(#{1,6})(.*)(?:\n+|$)/, fences: E, lheading: /^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/, paragraph: d(j).replace("hr", I).replace("heading", ` *#{1,6} *[^
]`).replace("lheading", oe).replace("|table", "").replace("blockquote", " {0,3}>").replace("|fences", "").replace("|list", "").replace("|html", "").replace("|tag", "").getRegex() };
-var ze = /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/;
-var Ae = /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/;
+var Ae = /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/;
+var Ee = /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/;
var le = /^( {2,}|\\)\n(?!\s*$)/;
var Ie = /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\]*?>/g;
+var Be = /(?!~)[\s\p{P}\p{S}]/u;
+var qe = /(?:[^\s\p{P}\p{S}]|~)/u;
+var ve = d(/link|precode-code|html/, "g").replace("link", /\[(?:[^\[\]`]|(?`+)[^`]+\k(?!`))*?\]\((?:\\[\s\S]|[^\\\(\)]|\((?:\\[\s\S]|[^\\\(\)])*\))*\)/).replace("precode-", be ? "(?`+)[^`]+\k(?!`)/).replace("html", /<(?! )[^<>]*?>/).getRegex();
var ce = /^(?:\*+(?:((?!\*)punct)|[^\s*]))|^_+(?:((?!_)punct)|([^\s_]))/;
-var ve = d(ce, "u").replace(/punct/g, D).getRegex();
-var De = d(ce, "u").replace(/punct/g, pe).getRegex();
+var De = d(ce, "u").replace(/punct/g, D).getRegex();
+var He = d(ce, "u").replace(/punct/g, pe).getRegex();
var he = "^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|notPunctSpace(\\*+)(?=notPunctSpace)";
-var He = d(he, "gu").replace(/notPunctSpace/g, ue).replace(/punctSpace/g, W).replace(/punct/g, D).getRegex();
-var Ze = d(he, "gu").replace(/notPunctSpace/g, Be).replace(/punctSpace/g, Ce).replace(/punct/g, pe).getRegex();
-var Ge = d("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)", "gu").replace(/notPunctSpace/g, ue).replace(/punctSpace/g, W).replace(/punct/g, D).getRegex();
-var Ne = d(/\\(punct)/, "gu").replace(/punct/g, D).getRegex();
-var Fe = d(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme", /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email", /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex();
-var je = d(U).replace("(?:-->|$)", "-->").getRegex();
-var Qe = d("^comment|^[a-zA-Z][\\w:-]*\\s*>|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^|^").replace("comment", je).replace("attribute", /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex();
+var Ze = d(he, "gu").replace(/notPunctSpace/g, ue).replace(/punctSpace/g, W).replace(/punct/g, D).getRegex();
+var Ge = d(he, "gu").replace(/notPunctSpace/g, qe).replace(/punctSpace/g, Be).replace(/punct/g, pe).getRegex();
+var Ne = d("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)", "gu").replace(/notPunctSpace/g, ue).replace(/punctSpace/g, W).replace(/punct/g, D).getRegex();
+var Fe = d(/\\(punct)/, "gu").replace(/punct/g, D).getRegex();
+var je = d(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme", /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email", /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex();
+var Qe = d(U).replace("(?:-->|$)", "-->").getRegex();
+var Ue = d("^comment|^[a-zA-Z][\\w:-]*\\s*>|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^|^").replace("comment", Qe).replace("attribute", /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex();
var q = /(?:\[(?:\\[\s\S]|[^\[\]\\])*\]|\\[\s\S]|`+[^`]*?`+(?!`)|[^\[\]\\`])*?/;
-var Ue = d(/^!?\[(label)\]\(\s*(href)(?:(?:[ \t]*(?:\n[ \t]*)?)(title))?\s*\)/).replace("label", q).replace("href", /<(?:\\.|[^\n<>\\])+>|[^ \t\n\x00-\x1f]*/).replace("title", /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex();
+var Ke = d(/^!?\[(label)\]\(\s*(href)(?:(?:[ \t]*(?:\n[ \t]*)?)(title))?\s*\)/).replace("label", q).replace("href", /<(?:\\.|[^\n<>\\])+>|[^ \t\n\x00-\x1f]*/).replace("title", /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex();
var de = d(/^!?\[(label)\]\[(ref)\]/).replace("label", q).replace("ref", Q).getRegex();
var ke = d(/^!?\[(ref)\](?:\[\])?/).replace("ref", Q).getRegex();
-var Ke = d("reflink|nolink(?!\\()", "g").replace("reflink", de).replace("nolink", ke).getRegex();
+var We = d("reflink|nolink(?!\\()", "g").replace("reflink", de).replace("nolink", ke).getRegex();
var se = /[hH][tT][tT][pP][sS]?|[fF][tT][pP]/;
-var X = { _backpedal: I, anyPunctuation: Ne, autolink: Fe, blockSkip: qe, br: le, code: Ae, del: I, emStrongLDelim: ve, emStrongRDelimAst: He, emStrongRDelimUnd: Ge, escape: ze, link: Ue, nolink: ke, punctuation: Ee, reflink: de, reflinkSearch: Ke, tag: Qe, text: Ie, url: I };
-var We = { ...X, link: d(/^!?\[(label)\]\((.*?)\)/).replace("label", q).getRegex(), reflink: d(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label", q).getRegex() };
-var N = { ...X, emStrongRDelimAst: Ze, emStrongLDelim: De, url: d(/^((?:protocol):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/).replace("protocol", se).replace("email", /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(), _backpedal: /(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/, del: /^(~~?)(?=[^\s~])((?:\\[\s\S]|[^\\])*?(?:\\[\s\S]|[^\s~\\]))\1(?=[^~]|$)/, text: d(/^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\": ">", '"': """, "'": "'" };
-var ge = (u3) => Je[u3];
-function w(u3, e) {
+var X = { _backpedal: E, anyPunctuation: Fe, autolink: je, blockSkip: ve, br: le, code: Ee, del: E, emStrongLDelim: De, emStrongRDelimAst: Ze, emStrongRDelimUnd: Ne, escape: Ae, link: Ke, nolink: ke, punctuation: Ce, reflink: de, reflinkSearch: We, tag: Ue, text: Ie, url: E };
+var Xe = { ...X, link: d(/^!?\[(label)\]\((.*?)\)/).replace("label", q).getRegex(), reflink: d(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label", q).getRegex() };
+var N = { ...X, emStrongRDelimAst: Ge, emStrongLDelim: He, url: d(/^((?:protocol):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/).replace("protocol", se).replace("email", /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(), _backpedal: /(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/, del: /^(~~?)(?=[^\s~])((?:\\[\s\S]|[^\\])*?(?:\\[\s\S]|[^\s~\\]))\1(?=[^~]|$)/, text: d(/^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\": ">", '"': """, "'": "'" };
+var ge = (l3) => Ve[l3];
+function w(l3, e) {
if (e) {
- if (m.escapeTest.test(u3)) return u3.replace(m.escapeReplace, ge);
- } else if (m.escapeTestNoEncode.test(u3)) return u3.replace(m.escapeReplaceNoEncode, ge);
- return u3;
+ if (m.escapeTest.test(l3)) return l3.replace(m.escapeReplace, ge);
+ } else if (m.escapeTestNoEncode.test(l3)) return l3.replace(m.escapeReplaceNoEncode, ge);
+ return l3;
}
-function J(u3) {
+function J(l3) {
try {
- u3 = encodeURI(u3).replace(m.percentDecode, "%");
+ l3 = encodeURI(l3).replace(m.percentDecode, "%");
} catch {
return null;
}
- return u3;
+ return l3;
}
-function V(u3, e) {
- let t = u3.replace(m.findPipe, (i, s, o) => {
- let a = false, l = s;
- for (; --l >= 0 && o[l] === "\\"; ) a = !a;
- return a ? "|" : " |";
+function V(l3, e) {
+ let t = l3.replace(m.findPipe, (i, s, a) => {
+ let o = false, p = s;
+ for (; --p >= 0 && a[p] === "\\"; ) o = !o;
+ return o ? "|" : " |";
}), n = t.split(m.splitPipe), r = 0;
if (n[0].trim() || n.shift(), n.length > 0 && !n.at(-1)?.trim() && n.pop(), e) if (n.length > e) n.splice(e);
else for (; n.length < e; ) n.push("");
for (; r < n.length; r++) n[r] = n[r].trim().replace(m.slashPipe, "|");
return n;
}
-function z2(u3, e, t) {
- let n = u3.length;
+function z2(l3, e, t) {
+ let n = l3.length;
if (n === 0) return "";
let r = 0;
for (; r < n; ) {
- let i = u3.charAt(n - r - 1);
+ let i = l3.charAt(n - r - 1);
if (i === e && !t) r++;
else if (i !== e && t) r++;
else break;
}
- return u3.slice(0, n - r);
+ return l3.slice(0, n - r);
}
-function fe(u3, e) {
- if (u3.indexOf(e[1]) === -1) return -1;
+function fe(l3, e) {
+ if (l3.indexOf(e[1]) === -1) return -1;
let t = 0;
- for (let n = 0; n < u3.length; n++) if (u3[n] === "\\") n++;
- else if (u3[n] === e[0]) t++;
- else if (u3[n] === e[1] && (t--, t < 0)) return n;
+ for (let n = 0; n < l3.length; n++) if (l3[n] === "\\") n++;
+ else if (l3[n] === e[0]) t++;
+ else if (l3[n] === e[1] && (t--, t < 0)) return n;
return t > 0 ? -2 : -1;
}
-function me(u3, e, t, n, r) {
- let i = e.href, s = e.title || null, o = u3[1].replace(r.other.outputLinkReplace, "$1");
+function me(l3, e, t, n, r) {
+ let i = e.href, s = e.title || null, a = l3[1].replace(r.other.outputLinkReplace, "$1");
n.state.inLink = true;
- let a = { type: u3[0].charAt(0) === "!" ? "image" : "link", raw: t, href: i, title: s, text: o, tokens: n.inlineTokens(o) };
- return n.state.inLink = false, a;
+ let o = { type: l3[0].charAt(0) === "!" ? "image" : "link", raw: t, href: i, title: s, text: a, tokens: n.inlineTokens(a) };
+ return n.state.inLink = false, o;
}
-function Ve(u3, e, t) {
- let n = u3.match(t.other.indentCodeCompensation);
+function Ye(l3, e, t) {
+ let n = l3.match(t.other.indentCodeCompensation);
if (n === null) return e;
let r = n[1];
return e.split(`
`).map((i) => {
let s = i.match(t.other.beginningSpace);
if (s === null) return i;
- let [o] = s;
- return o.length >= r.length ? i.slice(r.length) : i;
+ let [a] = s;
+ return a.length >= r.length ? i.slice(r.length) : i;
}).join(`
`);
}
@@ -30205,7 +31057,7 @@ var y = class {
fences(e) {
let t = this.rules.block.fences.exec(e);
if (t) {
- let n = t[0], r = Ve(n, t[3] || "", this.rules);
+ let n = t[0], r = Ye(n, t[3] || "", this.rules);
return { type: "code", raw: n, lang: t[2] ? t[2].trim().replace(this.rules.inline.anyPunctuation, "$1") : t[2], text: r };
}
}
@@ -30232,19 +31084,19 @@ var y = class {
`).split(`
`), r = "", i = "", s = [];
for (; n.length > 0; ) {
- let o = false, a = [], l;
- for (l = 0; l < n.length; l++) if (this.rules.other.blockquoteStart.test(n[l])) a.push(n[l]), o = true;
- else if (!o) a.push(n[l]);
+ let a = false, o = [], p;
+ for (p = 0; p < n.length; p++) if (this.rules.other.blockquoteStart.test(n[p])) o.push(n[p]), a = true;
+ else if (!a) o.push(n[p]);
else break;
- n = n.slice(l);
- let c = a.join(`
-`), p = c.replace(this.rules.other.blockquoteSetextReplace, `
+ n = n.slice(p);
+ let u = o.join(`
+`), c = u.replace(this.rules.other.blockquoteSetextReplace, `
$1`).replace(this.rules.other.blockquoteSetextReplace2, "");
r = r ? `${r}
-${c}` : c, i = i ? `${i}
-${p}` : p;
+${u}` : u, i = i ? `${i}
+${c}` : c;
let g = this.lexer.state.top;
- if (this.lexer.state.top = true, this.lexer.blockTokens(p, s, true), this.lexer.state.top = g, n.length === 0) break;
+ if (this.lexer.state.top = true, this.lexer.blockTokens(c, s, true), this.lexer.state.top = g, n.length === 0) break;
let h = s.at(-1);
if (h?.type === "code") break;
if (h?.type === "blockquote") {
@@ -30270,45 +31122,45 @@ ${p}` : p;
if (t) {
let n = t[1].trim(), r = n.length > 1, i = { type: "list", raw: "", ordered: r, start: r ? +n.slice(0, -1) : "", loose: false, items: [] };
n = r ? `\\d{1,9}\\${n.slice(-1)}` : `\\${n}`, this.options.pedantic && (n = r ? n : "[*+-]");
- let s = this.rules.other.listItemRegex(n), o = false;
+ let s = this.rules.other.listItemRegex(n), a = false;
for (; e; ) {
- let l = false, c = "", p = "";
+ let p = false, u = "", c = "";
if (!(t = s.exec(e)) || this.rules.block.hr.test(e)) break;
- c = t[0], e = e.substring(c.length);
+ u = t[0], e = e.substring(u.length);
let g = t[2].split(`
`, 1)[0].replace(this.rules.other.listReplaceTabs, (H) => " ".repeat(3 * H.length)), h = e.split(`
`, 1)[0], R = !g.trim(), f = 0;
- if (this.options.pedantic ? (f = 2, p = g.trimStart()) : R ? f = t[1].length + 1 : (f = t[2].search(this.rules.other.nonSpaceChar), f = f > 4 ? 1 : f, p = g.slice(f), f += t[1].length), R && this.rules.other.blankLine.test(h) && (c += h + `
-`, e = e.substring(h.length + 1), l = true), !l) {
+ if (this.options.pedantic ? (f = 2, c = g.trimStart()) : R ? f = t[1].length + 1 : (f = t[2].search(this.rules.other.nonSpaceChar), f = f > 4 ? 1 : f, c = g.slice(f), f += t[1].length), R && this.rules.other.blankLine.test(h) && (u += h + `
+`, e = e.substring(h.length + 1), p = true), !p) {
let H = this.rules.other.nextBulletRegex(f), ee = this.rules.other.hrRegex(f), te = this.rules.other.fencesBeginRegex(f), ne = this.rules.other.headingBeginRegex(f), xe = this.rules.other.htmlBeginRegex(f);
for (; e; ) {
let Z = e.split(`
`, 1)[0], A;
if (h = Z, this.options.pedantic ? (h = h.replace(this.rules.other.listReplaceNesting, " "), A = h) : A = h.replace(this.rules.other.tabCharGlobal, " "), te.test(h) || ne.test(h) || xe.test(h) || H.test(h) || ee.test(h)) break;
- if (A.search(this.rules.other.nonSpaceChar) >= f || !h.trim()) p += `
+ if (A.search(this.rules.other.nonSpaceChar) >= f || !h.trim()) c += `
` + A.slice(f);
else {
if (R || g.replace(this.rules.other.tabCharGlobal, " ").search(this.rules.other.nonSpaceChar) >= 4 || te.test(g) || ne.test(g) || ee.test(g)) break;
- p += `
+ c += `
` + h;
}
- !R && !h.trim() && (R = true), c += Z + `
+ !R && !h.trim() && (R = true), u += Z + `
`, e = e.substring(Z.length + 1), g = A.slice(f);
}
}
- i.loose || (o ? i.loose = true : this.rules.other.doubleBlankLine.test(c) && (o = true));
+ i.loose || (a ? i.loose = true : this.rules.other.doubleBlankLine.test(u) && (a = true));
let O = null, Y;
- this.options.gfm && (O = this.rules.other.listIsTask.exec(p), O && (Y = O[0] !== "[ ] ", p = p.replace(this.rules.other.listReplaceTask, ""))), i.items.push({ type: "list_item", raw: c, task: !!O, checked: Y, loose: false, text: p, tokens: [] }), i.raw += c;
+ this.options.gfm && (O = this.rules.other.listIsTask.exec(c), O && (Y = O[0] !== "[ ] ", c = c.replace(this.rules.other.listReplaceTask, ""))), i.items.push({ type: "list_item", raw: u, task: !!O, checked: Y, loose: false, text: c, tokens: [] }), i.raw += u;
}
- let a = i.items.at(-1);
- if (a) a.raw = a.raw.trimEnd(), a.text = a.text.trimEnd();
+ let o = i.items.at(-1);
+ if (o) o.raw = o.raw.trimEnd(), o.text = o.text.trimEnd();
else return;
i.raw = i.raw.trimEnd();
- for (let l = 0; l < i.items.length; l++) if (this.lexer.state.top = false, i.items[l].tokens = this.lexer.blockTokens(i.items[l].text, []), !i.loose) {
- let c = i.items[l].tokens.filter((g) => g.type === "space"), p = c.length > 0 && c.some((g) => this.rules.other.anyLine.test(g.raw));
- i.loose = p;
+ for (let p = 0; p < i.items.length; p++) if (this.lexer.state.top = false, i.items[p].tokens = this.lexer.blockTokens(i.items[p].text, []), !i.loose) {
+ let u = i.items[p].tokens.filter((g) => g.type === "space"), c = u.length > 0 && u.some((g) => this.rules.other.anyLine.test(g.raw));
+ i.loose = c;
}
- if (i.loose) for (let l = 0; l < i.items.length; l++) i.items[l].loose = true;
+ if (i.loose) for (let p = 0; p < i.items.length; p++) i.items[p].loose = true;
return i;
}
}
@@ -30329,9 +31181,9 @@ ${p}` : p;
let n = V(t[1]), r = t[2].replace(this.rules.other.tableAlignChars, "").split("|"), i = t[3]?.trim() ? t[3].replace(this.rules.other.tableRowBlankLine, "").split(`
`) : [], s = { type: "table", raw: t[0], header: [], align: [], rows: [] };
if (n.length === r.length) {
- for (let o of r) this.rules.other.tableAlignRight.test(o) ? s.align.push("right") : this.rules.other.tableAlignCenter.test(o) ? s.align.push("center") : this.rules.other.tableAlignLeft.test(o) ? s.align.push("left") : s.align.push(null);
- for (let o = 0; o < n.length; o++) s.header.push({ text: n[o], tokens: this.lexer.inline(n[o]), header: true, align: s.align[o] });
- for (let o of i) s.rows.push(V(o, s.header.length).map((a, l) => ({ text: a, tokens: this.lexer.inline(a), header: false, align: s.align[l] })));
+ for (let a of r) this.rules.other.tableAlignRight.test(a) ? s.align.push("right") : this.rules.other.tableAlignCenter.test(a) ? s.align.push("center") : this.rules.other.tableAlignLeft.test(a) ? s.align.push("left") : s.align.push(null);
+ for (let a = 0; a < n.length; a++) s.header.push({ text: n[a], tokens: this.lexer.inline(n[a]), header: true, align: s.align[a] });
+ for (let a of i) s.rows.push(V(a, s.header.length).map((o, p) => ({ text: o, tokens: this.lexer.inline(o), header: false, align: s.align[p] })));
return s;
}
}
@@ -30371,8 +31223,8 @@ ${p}` : p;
let s = fe(t[2], "()");
if (s === -2) return;
if (s > -1) {
- let a = (t[0].indexOf("!") === 0 ? 5 : 4) + t[1].length + s;
- t[2] = t[2].substring(0, s), t[0] = t[0].substring(0, a).trim(), t[3] = "";
+ let o = (t[0].indexOf("!") === 0 ? 5 : 4) + t[1].length + s;
+ t[2] = t[2].substring(0, s), t[0] = t[0].substring(0, o).trim(), t[3] = "";
}
}
let r = t[2], i = "";
@@ -30398,20 +31250,20 @@ ${p}` : p;
let r = this.rules.inline.emStrongLDelim.exec(e);
if (!r || r[3] && n.match(this.rules.other.unicodeAlphaNumeric)) return;
if (!(r[1] || r[2] || "") || !n || this.rules.inline.punctuation.exec(n)) {
- let s = [...r[0]].length - 1, o, a, l = s, c = 0, p = r[0][0] === "*" ? this.rules.inline.emStrongRDelimAst : this.rules.inline.emStrongRDelimUnd;
- for (p.lastIndex = 0, t = t.slice(-1 * e.length + s); (r = p.exec(t)) != null; ) {
- if (o = r[1] || r[2] || r[3] || r[4] || r[5] || r[6], !o) continue;
- if (a = [...o].length, r[3] || r[4]) {
- l += a;
+ let s = [...r[0]].length - 1, a, o, p = s, u = 0, c = r[0][0] === "*" ? this.rules.inline.emStrongRDelimAst : this.rules.inline.emStrongRDelimUnd;
+ for (c.lastIndex = 0, t = t.slice(-1 * e.length + s); (r = c.exec(t)) != null; ) {
+ if (a = r[1] || r[2] || r[3] || r[4] || r[5] || r[6], !a) continue;
+ if (o = [...a].length, r[3] || r[4]) {
+ p += o;
continue;
- } else if ((r[5] || r[6]) && s % 3 && !((s + a) % 3)) {
- c += a;
+ } else if ((r[5] || r[6]) && s % 3 && !((s + o) % 3)) {
+ u += o;
continue;
}
- if (l -= a, l > 0) continue;
- a = Math.min(a, a + l + c);
- let g = [...r[0]][0].length, h = e.slice(0, s + r.index + g + a);
- if (Math.min(s, a) % 2) {
+ if (p -= o, p > 0) continue;
+ o = Math.min(o, o + p + u);
+ let g = [...r[0]][0].length, h = e.slice(0, s + r.index + g + o);
+ if (Math.min(s, o) % 2) {
let f = h.slice(1, -1);
return { type: "em", raw: h, text: f, tokens: this.lexer.inlineTokens(f) };
}
@@ -30465,7 +31317,7 @@ ${p}` : p;
}
}
};
-var x = class u {
+var x = class l {
tokens;
options;
state;
@@ -30480,10 +31332,10 @@ var x = class u {
return { block: C, inline: M };
}
static lex(e, t) {
- return new u(t).lex(e);
+ return new l(t).lex(e);
}
static lexInline(e, t) {
- return new u(t).inlineTokens(e);
+ return new l(t).inlineTokens(e);
}
lex(e) {
e = e.replace(m.carriageReturn, `
@@ -30557,9 +31409,9 @@ var x = class u {
}
let i = e;
if (this.options.extensions?.startBlock) {
- let s = 1 / 0, o = e.slice(1), a;
- this.options.extensions.startBlock.forEach((l) => {
- a = l.call({ lexer: this }, o), typeof a == "number" && a >= 0 && (s = Math.min(s, a));
+ let s = 1 / 0, a = e.slice(1), o;
+ this.options.extensions.startBlock.forEach((p) => {
+ o = p.call({ lexer: this }, a), typeof o == "number" && o >= 0 && (s = Math.min(s, o));
}), s < 1 / 0 && s >= 0 && (i = e.substring(0, s + 1));
}
if (this.state.top && (r = this.tokenizer.paragraph(i))) {
@@ -30599,13 +31451,14 @@ var x = class u {
if (o.length > 0) for (; (r = this.tokenizer.rules.inline.reflinkSearch.exec(n)) != null; ) o.includes(r[0].slice(r[0].lastIndexOf("[") + 1, -1)) && (n = n.slice(0, r.index) + "[" + "a".repeat(r[0].length - 2) + "]" + n.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex));
}
for (; (r = this.tokenizer.rules.inline.anyPunctuation.exec(n)) != null; ) n = n.slice(0, r.index) + "++" + n.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);
- for (; (r = this.tokenizer.rules.inline.blockSkip.exec(n)) != null; ) n = n.slice(0, r.index) + "[" + "a".repeat(r[0].length - 2) + "]" + n.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);
+ let i;
+ for (; (r = this.tokenizer.rules.inline.blockSkip.exec(n)) != null; ) i = r[2] ? r[2].length : 0, n = n.slice(0, r.index + i) + "[" + "a".repeat(r[0].length - i - 2) + "]" + n.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);
n = this.options.hooks?.emStrongMask?.call({ lexer: this }, n) ?? n;
- let i = false, s = "";
+ let s = false, a = "";
for (; e; ) {
- i || (s = ""), i = false;
+ s || (a = ""), s = false;
let o;
- if (this.options.extensions?.inline?.some((l) => (o = l.call({ lexer: this }, e, t)) ? (e = e.substring(o.raw.length), t.push(o), true) : false)) continue;
+ if (this.options.extensions?.inline?.some((u) => (o = u.call({ lexer: this }, e, t)) ? (e = e.substring(o.raw.length), t.push(o), true) : false)) continue;
if (o = this.tokenizer.escape(e)) {
e = e.substring(o.raw.length), t.push(o);
continue;
@@ -30620,11 +31473,11 @@ var x = class u {
}
if (o = this.tokenizer.reflink(e, this.tokens.links)) {
e = e.substring(o.raw.length);
- let l = t.at(-1);
- o.type === "text" && l?.type === "text" ? (l.raw += o.raw, l.text += o.text) : t.push(o);
+ let u = t.at(-1);
+ o.type === "text" && u?.type === "text" ? (u.raw += o.raw, u.text += o.text) : t.push(o);
continue;
}
- if (o = this.tokenizer.emStrong(e, n, s)) {
+ if (o = this.tokenizer.emStrong(e, n, a)) {
e = e.substring(o.raw.length), t.push(o);
continue;
}
@@ -30648,25 +31501,25 @@ var x = class u {
e = e.substring(o.raw.length), t.push(o);
continue;
}
- let a = e;
+ let p = e;
if (this.options.extensions?.startInline) {
- let l = 1 / 0, c = e.slice(1), p;
- this.options.extensions.startInline.forEach((g) => {
- p = g.call({ lexer: this }, c), typeof p == "number" && p >= 0 && (l = Math.min(l, p));
- }), l < 1 / 0 && l >= 0 && (a = e.substring(0, l + 1));
- }
- if (o = this.tokenizer.inlineText(a)) {
- e = e.substring(o.raw.length), o.raw.slice(-1) !== "_" && (s = o.raw.slice(-1)), i = true;
- let l = t.at(-1);
- l?.type === "text" ? (l.raw += o.raw, l.text += o.text) : t.push(o);
+ let u = 1 / 0, c = e.slice(1), g;
+ this.options.extensions.startInline.forEach((h) => {
+ g = h.call({ lexer: this }, c), typeof g == "number" && g >= 0 && (u = Math.min(u, g));
+ }), u < 1 / 0 && u >= 0 && (p = e.substring(0, u + 1));
+ }
+ if (o = this.tokenizer.inlineText(p)) {
+ e = e.substring(o.raw.length), o.raw.slice(-1) !== "_" && (a = o.raw.slice(-1)), s = true;
+ let u = t.at(-1);
+ u?.type === "text" ? (u.raw += o.raw, u.text += o.text) : t.push(o);
continue;
}
if (e) {
- let l = "Infinite loop on byte: " + e.charCodeAt(0);
+ let u = "Infinite loop on byte: " + e.charCodeAt(0);
if (this.options.silent) {
- console.error(l);
+ console.error(u);
break;
- } else throw new Error(l);
+ } else throw new Error(u);
}
}
return t;
@@ -30709,9 +31562,9 @@ ${this.parser.parse(e)}
}
list(e) {
let t = e.ordered, n = e.start, r = "";
- for (let o = 0; o < e.items.length; o++) {
- let a = e.items[o];
- r += this.listitem(a);
+ for (let a = 0; a < e.items.length; a++) {
+ let o = e.items[a];
+ r += this.listitem(o);
}
let i = t ? "ol" : "ul", s = t && n !== 1 ? ' start="' + n + '"' : "";
return "<" + i + s + `>
@@ -30742,7 +31595,7 @@ ${this.parser.parse(e)}
for (let i = 0; i < e.rows.length; i++) {
let s = e.rows[i];
n = "";
- for (let o = 0; o < s.length; o++) n += this.tablecell(s[o]);
+ for (let a = 0; a < s.length; a++) n += this.tablecell(s[a]);
r += this.tablerow({ text: n });
}
return r && (r = `${r}`), `
@@ -30824,7 +31677,7 @@ var $ = class {
return "";
}
};
-var b = class u2 {
+var b = class l2 {
options;
renderer;
textRenderer;
@@ -30832,19 +31685,19 @@ var b = class u2 {
this.options = e || T, this.options.renderer = this.options.renderer || new P(), this.renderer = this.options.renderer, this.renderer.options = this.options, this.renderer.parser = this, this.textRenderer = new $();
}
static parse(e, t) {
- return new u2(t).parse(e);
+ return new l2(t).parse(e);
}
static parseInline(e, t) {
- return new u2(t).parseInline(e);
+ return new l2(t).parseInline(e);
}
parse(e, t = true) {
let n = "";
for (let r = 0; r < e.length; r++) {
let i = e[r];
if (this.options.extensions?.renderers?.[i.type]) {
- let o = i, a = this.options.extensions.renderers[o.type].call({ parser: this }, o);
- if (a !== false || !["space", "hr", "heading", "code", "table", "blockquote", "list", "html", "def", "paragraph", "text"].includes(o.type)) {
- n += a || "";
+ let a = i, o = this.options.extensions.renderers[a.type].call({ parser: this }, a);
+ if (o !== false || !["space", "hr", "heading", "code", "table", "blockquote", "list", "html", "def", "paragraph", "text"].includes(a.type)) {
+ n += o || "";
continue;
}
}
@@ -30891,16 +31744,16 @@ var b = class u2 {
continue;
}
case "text": {
- let o = s, a = this.renderer.text(o);
- for (; r + 1 < e.length && e[r + 1].type === "text"; ) o = e[++r], a += `
-` + this.renderer.text(o);
- t ? n += this.renderer.paragraph({ type: "paragraph", raw: a, text: a, tokens: [{ type: "text", raw: a, text: a, escaped: true }] }) : n += a;
+ let a = s, o = this.renderer.text(a);
+ for (; r + 1 < e.length && e[r + 1].type === "text"; ) a = e[++r], o += `
+` + this.renderer.text(a);
+ t ? n += this.renderer.paragraph({ type: "paragraph", raw: o, text: o, tokens: [{ type: "text", raw: o, text: o, escaped: true }] }) : n += o;
continue;
}
default: {
- let o = 'Token with "' + s.type + '" type was not found.';
- if (this.options.silent) return console.error(o), "";
- throw new Error(o);
+ let a = 'Token with "' + s.type + '" type was not found.';
+ if (this.options.silent) return console.error(a), "";
+ throw new Error(a);
}
}
}
@@ -30911,9 +31764,9 @@ var b = class u2 {
for (let r = 0; r < e.length; r++) {
let i = e[r];
if (this.options.extensions?.renderers?.[i.type]) {
- let o = this.options.extensions.renderers[i.type].call({ parser: this }, i);
- if (o !== false || !["escape", "html", "link", "image", "strong", "em", "codespan", "br", "del", "text"].includes(i.type)) {
- n += o || "";
+ let a = this.options.extensions.renderers[i.type].call({ parser: this }, i);
+ if (a !== false || !["escape", "html", "link", "image", "strong", "em", "codespan", "br", "del", "text"].includes(i.type)) {
+ n += a || "";
continue;
}
}
@@ -30960,9 +31813,9 @@ var b = class u2 {
break;
}
default: {
- let o = 'Token with "' + s.type + '" type was not found.';
- if (this.options.silent) return console.error(o), "";
- throw new Error(o);
+ let a = 'Token with "' + s.type + '" type was not found.';
+ if (this.options.silent) return console.error(a), "";
+ throw new Error(a);
}
}
}
@@ -31016,7 +31869,7 @@ var B = class {
case "table": {
let i = r;
for (let s of i.header) n = n.concat(this.walkTokens(s.tokens, t));
- for (let s of i.rows) for (let o of s) n = n.concat(this.walkTokens(o.tokens, t));
+ for (let s of i.rows) for (let a of s) n = n.concat(this.walkTokens(a.tokens, t));
break;
}
case "list": {
@@ -31027,8 +31880,8 @@ var B = class {
default: {
let i = r;
this.defaults.extensions?.childTokens?.[i.type] ? this.defaults.extensions.childTokens[i.type].forEach((s) => {
- let o = i[s].flat(1 / 0);
- n = n.concat(this.walkTokens(o, t));
+ let a = i[s].flat(1 / 0);
+ n = n.concat(this.walkTokens(a, t));
}) : i.tokens && (n = n.concat(this.walkTokens(i.tokens, t)));
}
}
@@ -31042,9 +31895,9 @@ var B = class {
if (!i.name) throw new Error("extension name required");
if ("renderer" in i) {
let s = t.renderers[i.name];
- s ? t.renderers[i.name] = function(...o) {
- let a = i.renderer.apply(this, o);
- return a === false && (a = s.apply(this, o)), a;
+ s ? t.renderers[i.name] = function(...a) {
+ let o = i.renderer.apply(this, a);
+ return o === false && (o = s.apply(this, a)), o;
} : t.renderers[i.name] = i.renderer;
}
if ("tokenizer" in i) {
@@ -31058,10 +31911,10 @@ var B = class {
for (let s in n.renderer) {
if (!(s in i)) throw new Error(`renderer '${s}' does not exist`);
if (["options", "parser"].includes(s)) continue;
- let o = s, a = n.renderer[o], l = i[o];
- i[o] = (...c) => {
- let p = a.apply(i, c);
- return p === false && (p = l.apply(i, c)), p || "";
+ let a = s, o = n.renderer[a], p = i[a];
+ i[a] = (...u) => {
+ let c = o.apply(i, u);
+ return c === false && (c = p.apply(i, u)), c || "";
};
}
r.renderer = i;
@@ -31071,10 +31924,10 @@ var B = class {
for (let s in n.tokenizer) {
if (!(s in i)) throw new Error(`tokenizer '${s}' does not exist`);
if (["options", "rules", "lexer"].includes(s)) continue;
- let o = s, a = n.tokenizer[o], l = i[o];
- i[o] = (...c) => {
- let p = a.apply(i, c);
- return p === false && (p = l.apply(i, c)), p;
+ let a = s, o = n.tokenizer[a], p = i[a];
+ i[a] = (...u) => {
+ let c = o.apply(i, u);
+ return c === false && (c = p.apply(i, u)), c;
};
}
r.tokenizer = i;
@@ -31084,30 +31937,30 @@ var B = class {
for (let s in n.hooks) {
if (!(s in i)) throw new Error(`hook '${s}' does not exist`);
if (["options", "block"].includes(s)) continue;
- let o = s, a = n.hooks[o], l = i[o];
- S.passThroughHooks.has(s) ? i[o] = (c) => {
+ let a = s, o = n.hooks[a], p = i[a];
+ S.passThroughHooks.has(s) ? i[a] = (u) => {
if (this.defaults.async && S.passThroughHooksRespectAsync.has(s)) return (async () => {
- let g = await a.call(i, c);
- return l.call(i, g);
+ let g = await o.call(i, u);
+ return p.call(i, g);
})();
- let p = a.call(i, c);
- return l.call(i, p);
- } : i[o] = (...c) => {
+ let c = o.call(i, u);
+ return p.call(i, c);
+ } : i[a] = (...u) => {
if (this.defaults.async) return (async () => {
- let g = await a.apply(i, c);
- return g === false && (g = await l.apply(i, c)), g;
+ let g = await o.apply(i, u);
+ return g === false && (g = await p.apply(i, u)), g;
})();
- let p = a.apply(i, c);
- return p === false && (p = l.apply(i, c)), p;
+ let c = o.apply(i, u);
+ return c === false && (c = p.apply(i, u)), c;
};
}
r.hooks = i;
}
if (n.walkTokens) {
let i = this.defaults.walkTokens, s = n.walkTokens;
- r.walkTokens = function(o) {
- let a = [];
- return a.push(s.call(this, o)), i && (a = a.concat(i.call(this, o))), a;
+ r.walkTokens = function(a) {
+ let o = [];
+ return o.push(s.call(this, a)), i && (o = o.concat(i.call(this, a))), o;
};
}
this.defaults = { ...this.defaults, ...r };
@@ -31124,24 +31977,24 @@ var B = class {
}
parseMarkdown(e) {
return (n, r) => {
- let i = { ...r }, s = { ...this.defaults, ...i }, o = this.onError(!!s.silent, !!s.async);
- if (this.defaults.async === true && i.async === false) return o(new Error("marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise."));
- if (typeof n > "u" || n === null) return o(new Error("marked(): input parameter is undefined or null"));
- if (typeof n != "string") return o(new Error("marked(): input parameter is of type " + Object.prototype.toString.call(n) + ", string expected"));
+ let i = { ...r }, s = { ...this.defaults, ...i }, a = this.onError(!!s.silent, !!s.async);
+ if (this.defaults.async === true && i.async === false) return a(new Error("marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise."));
+ if (typeof n > "u" || n === null) return a(new Error("marked(): input parameter is undefined or null"));
+ if (typeof n != "string") return a(new Error("marked(): input parameter is of type " + Object.prototype.toString.call(n) + ", string expected"));
if (s.hooks && (s.hooks.options = s, s.hooks.block = e), s.async) return (async () => {
- let a = s.hooks ? await s.hooks.preprocess(n) : n, c = await (s.hooks ? await s.hooks.provideLexer() : e ? x.lex : x.lexInline)(a, s), p = s.hooks ? await s.hooks.processAllTokens(c) : c;
- s.walkTokens && await Promise.all(this.walkTokens(p, s.walkTokens));
- let h = await (s.hooks ? await s.hooks.provideParser() : e ? b.parse : b.parseInline)(p, s);
+ let o = s.hooks ? await s.hooks.preprocess(n) : n, u = await (s.hooks ? await s.hooks.provideLexer() : e ? x.lex : x.lexInline)(o, s), c = s.hooks ? await s.hooks.processAllTokens(u) : u;
+ s.walkTokens && await Promise.all(this.walkTokens(c, s.walkTokens));
+ let h = await (s.hooks ? await s.hooks.provideParser() : e ? b.parse : b.parseInline)(c, s);
return s.hooks ? await s.hooks.postprocess(h) : h;
- })().catch(o);
+ })().catch(a);
try {
s.hooks && (n = s.hooks.preprocess(n));
- let l = (s.hooks ? s.hooks.provideLexer() : e ? x.lex : x.lexInline)(n, s);
- s.hooks && (l = s.hooks.processAllTokens(l)), s.walkTokens && this.walkTokens(l, s.walkTokens);
- let p = (s.hooks ? s.hooks.provideParser() : e ? b.parse : b.parseInline)(l, s);
- return s.hooks && (p = s.hooks.postprocess(p)), p;
- } catch (a) {
- return o(a);
+ let p = (s.hooks ? s.hooks.provideLexer() : e ? x.lex : x.lexInline)(n, s);
+ s.hooks && (p = s.hooks.processAllTokens(p)), s.walkTokens && this.walkTokens(p, s.walkTokens);
+ let c = (s.hooks ? s.hooks.provideParser() : e ? b.parse : b.parseInline)(p, s);
+ return s.hooks && (c = s.hooks.postprocess(c)), c;
+ } catch (o) {
+ return a(o);
}
};
}
@@ -31158,19 +32011,19 @@ Please report this to https://github.com/markedjs/marked.`, e) {
}
};
var _ = new B();
-function k(u3, e) {
- return _.parse(u3, e);
+function k(l3, e) {
+ return _.parse(l3, e);
}
-k.options = k.setOptions = function(u3) {
- return _.setOptions(u3), k.defaults = _.defaults, G(k.defaults), k;
+k.options = k.setOptions = function(l3) {
+ return _.setOptions(l3), k.defaults = _.defaults, G(k.defaults), k;
};
k.getDefaults = L;
k.defaults = T;
-k.use = function(...u3) {
- return _.use(...u3), k.defaults = _.defaults, G(k.defaults), k;
+k.use = function(...l3) {
+ return _.use(...l3), k.defaults = _.defaults, G(k.defaults), k;
};
-k.walkTokens = function(u3, e) {
- return _.walkTokens(u3, e);
+k.walkTokens = function(l3, e) {
+ return _.walkTokens(l3, e);
};
k.parseInline = _.parseInline;
k.Parser = b;
@@ -31182,13 +32035,13 @@ k.lexer = x.lex;
k.Tokenizer = y;
k.Hooks = S;
k.parse = k;
-var Ht = k.options;
-var Zt = k.setOptions;
-var Gt = k.use;
-var Nt = k.walkTokens;
-var Ft = k.parseInline;
-var Qt = b.parse;
-var Ut = x.lex;
+var Zt = k.options;
+var Gt = k.setOptions;
+var Nt = k.use;
+var Ft = k.walkTokens;
+var jt = k.parseInline;
+var Ut = b.parse;
+var Kt = x.lex;
// src/show.ts
function formatConversationAsMarkdown(jsonl, startLine, endLine) {
@@ -31892,11 +32745,11 @@ var ShowConversationInputSchema = external_exports.object({
startLine: external_exports.number().int().min(1).optional().describe("Starting line number (1-indexed, inclusive). Omit to start from beginning."),
endLine: external_exports.number().int().min(1).optional().describe("Ending line number (1-indexed, inclusive). Omit to read to end.")
}).strict();
-function handleError(error61) {
- if (error61 instanceof Error) {
- return `Error: ${error61.message}`;
+function handleError(error62) {
+ if (error62 instanceof Error) {
+ return `Error: ${error62.message}`;
}
- return `Error: ${String(error61)}`;
+ return `Error: ${String(error62)}`;
}
var server = new Server(
{
@@ -32059,12 +32912,12 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
};
}
throw new Error(`Unknown tool: ${name}`);
- } catch (error61) {
+ } catch (error62) {
return {
content: [
{
type: "text",
- text: handleError(error61)
+ text: handleError(error62)
}
],
isError: true
@@ -32076,7 +32929,7 @@ async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
}
-main().catch((error61) => {
- console.error("Server error:", error61);
+main().catch((error62) => {
+ console.error("Server error:", error62);
process.exit(1);
});
diff --git a/dist/parser.js b/dist/parser.js
index dcc1c270..7a2108f8 100644
--- a/dist/parser.js
+++ b/dist/parser.js
@@ -71,6 +71,16 @@ export async function parseConversation(filePath, projectName, archivePath) {
}
return parseClaudeConversation(filePath, projectName, archivePath);
}
+// Channel-bridge plugins (Discord, Slack, ...) deliver the user's own words as
+// isMeta:true user lines with origin.kind === "channel" (anthropics/claude-code#44828),
+// so isMeta alone does not mean "not the user's input"; provenance is in origin.kind.
+const HUMAN_ORIGIN_KINDS = new Set(['channel', 'human']);
+function isInjectedMetaLine(msg) {
+ if (msg.isMeta !== true)
+ return false;
+ const kind = msg.origin?.kind;
+ return !(typeof kind === 'string' && HUMAN_ORIGIN_KINDS.has(kind));
+}
async function parseClaudeConversation(filePath, projectName, archivePath) {
const exchanges = [];
const fileStream = fs.createReadStream(filePath);
@@ -129,6 +139,19 @@ async function parseClaudeConversation(filePath, projectName, archivePath) {
if (!parsed.message) {
continue;
}
+ // Harness-injected user lines carry isMeta:true: image-paste placeholders
+ // ("[Image: source: ...]"), Skill tool bodies, task/system notifications,
+ // local-command caveats, coordinator messages, "Continue from where you
+ // left off.". They are not the user's words, so while an exchange is open
+ // they must not start a new one: a pasted image yields the real prompt line
+ // followed by an isMeta placeholder line with no assistant reply between,
+ // and finalizeExchange() would drop the real prompt. Their text is not
+ // indexed; the assistant lines that follow attach to the open exchange.
+ // With no exchange open (a session that opens with a notification) the
+ // line still starts one, so no assistant text is ever lost.
+ if (parsed.message.role === 'user' && currentExchange && isInjectedMetaLine(parsed)) {
+ continue;
+ }
// Extract text from message content
let text = '';
const toolCalls = [];
@@ -630,6 +653,50 @@ async function parseOmpConversation(filePath, projectName, archivePath) {
finalizeExchange();
return exchanges;
}
+// Codex injects system context as ordinary user-role message items with no field
+// that tells them apart from typed prompts. The only safe content signal is a
+// COMPLETE canonical fragment: an input_text block that is exactly one wrapper
+// element, or the AGENTS.md instructions block. A prefix is not enough — a typed
+// prompt may open with an XML snippet or a look-alike heading. Only wrappers
+// that Codex emits with role "user" are listed: observed in rollouts
+// (, , , "# AGENTS.md
+// instructions" + ) or defined with role user in codex-rs
+// (legacy , ). Developer-role wrappers
+// (, , ...) never reach the user branch.
+const CODEX_INJECTED_OPEN = /^<(environment_context|recommended_plugins|skill|user_instructions|subagent_notification)(?:\s[^>]*)?>/;
+const CODEX_AGENTS_MD_OPEN = /^# AGENTS\.md instructions(?: for [^\n]*)?\n\n\n/;
+// Exactly one wrapper element: the block opens with the tag and the FIRST matching
+// closing tag is the very end of the block — so ".. question
+// .." (text between elements, or several elements) is user text.
+function endsAtFirstClose(text, closing) {
+ const close = text.indexOf(closing);
+ return close !== -1 && close + closing.length === text.length;
+}
+function isCodexInjectedBlock(text) {
+ const trimmed = text.trim();
+ if (CODEX_AGENTS_MD_OPEN.test(trimmed)) {
+ return endsAtFirstClose(trimmed, '');
+ }
+ const open = CODEX_INJECTED_OPEN.exec(trimmed);
+ return open !== null && endsAtFirstClose(trimmed, '' + open[1] + '>');
+}
+// Split a Codex user item into the user's own text and the number of injected
+// blocks it carried — block by block, so a real request that shares an item with
+// an injected block is kept.
+function splitCodexUserContent(content) {
+ const blocks = typeof content === 'string'
+ ? [{ type: 'input_text', text: content }]
+ : Array.isArray(content) ? content : [];
+ let injected = 0;
+ const kept = blocks.filter(block => {
+ if (block && typeof block.text === 'string' && isCodexInjectedBlock(block.text)) {
+ injected++;
+ return false;
+ }
+ return true;
+ });
+ return { userText: extractTextFromContent(kept), injected };
+}
async function parseCodexConversation(filePath, projectName, archivePath) {
const exchanges = [];
const fileStream = fs.createReadStream(filePath);
@@ -645,6 +712,11 @@ async function parseCodexConversation(filePath, projectName, archivePath) {
let model;
let modelProvider;
let currentExchange = null;
+ // A user item from which injected blocks were removed: either held back entirely
+ // (injected-only, while an exchange was open) or trimmed to its remaining text.
+ // If the very next event vouches for the ORIGINAL text as a typed UserMessage,
+ // the full authored prompt is restored.
+ let pendingInjected = null;
const toolCallsByCallId = new Map();
const currentProject = () => projectFromCwd(cwd) || projectName;
const applyMetadataToCurrentExchange = () => {
@@ -692,14 +764,14 @@ async function parseCodexConversation(filePath, projectName, archivePath) {
currentExchange = null;
toolCallsByCallId.clear();
};
- const startExchange = (text, timestamp) => {
+ const startExchange = (text, timestamp, line = lineNumber) => {
finalizeExchange();
currentExchange = {
project: currentProject(),
userMessage: text,
- userLine: lineNumber,
+ userLine: line,
assistantMessages: [],
- lastAssistantLine: lineNumber,
+ lastAssistantLine: line,
timestamp,
harness: 'codex',
sessionId,
@@ -777,16 +849,62 @@ async function parseCodexConversation(filePath, projectName, archivePath) {
applyMetadataToCurrentExchange();
continue;
}
+ // Positive provenance (newer rollouts): each typed prompt is followed by an
+ // item_completed UserMessage event (legacy: a user_message event). If one
+ // vouches for the item we just held back as injected, it was typed after all.
+ if (parsed.type === 'event_msg' && payload && pendingInjected) {
+ let vouched;
+ if (payload.type === 'item_completed' && payload.item?.type === 'UserMessage') {
+ vouched = extractTextFromContent(payload.item.content);
+ }
+ else if (payload.type === 'user_message' && typeof payload.message === 'string') {
+ vouched = payload.message;
+ }
+ if (vouched !== undefined && (!vouched.trim() || vouched.trim() === pendingInjected.text.trim())) {
+ if (pendingInjected.held) {
+ startExchange(pendingInjected.text, pendingInjected.timestamp, pendingInjected.line);
+ }
+ else {
+ // Trimmed item: the exchange it started is the current one.
+ const exchange = currentExchange;
+ if (exchange && exchange.userLine === pendingInjected.line) {
+ exchange.userMessage = pendingInjected.text;
+ }
+ }
+ pendingInjected = null;
+ }
+ continue;
+ }
if (parsed.type !== 'response_item' || !payload) {
continue;
}
+ pendingInjected = null;
if (payload.type === 'message') {
const text = extractTextFromContent(payload.content);
if (!text.trim()) {
continue;
}
if (payload.role === 'user') {
- startExchange(text, timestamp);
+ const { userText, injected } = splitCodexUserContent(payload.content);
+ if (userText.trim()) {
+ // The user's own words; injected blocks in the same item are dropped, but
+ // the original text is kept so a UserMessage event can restore it.
+ startExchange(userText, timestamp);
+ if (injected > 0) {
+ pendingInjected = { text, line: lineNumber, timestamp, held: false };
+ }
+ }
+ else if (injected > 0 && currentExchange) {
+ // Injected-only item while an exchange is open: it must not split the
+ // exchange; the reply attaches to the typed prompt. Held back in case
+ // the next event proves it was typed.
+ pendingInjected = { text, line: lineNumber, timestamp, held: true };
+ }
+ else {
+ // Nothing open yet (a rollout that starts with injected context):
+ // unchanged behavior, the item starts an exchange.
+ startExchange(text, timestamp);
+ }
}
else if (payload.role === 'assistant') {
const exchange = currentExchange;
@@ -1036,13 +1154,10 @@ async function parseCursorConversation(filePath, projectName, archivePath) {
* Extracts project name from the file path and returns exchanges with metadata
*/
export async function parseConversationFile(filePath) {
- // Extract project name from path (directory name before the .jsonl file)
- const pathParts = filePath.split('/');
- let project = 'unknown';
- // Find the parent directory name (second to last part)
- if (pathParts.length >= 2) {
- project = pathParts[pathParts.length - 2];
- }
+ // Extract project name from path (directory name before the .jsonl file).
+ // path.dirname uses the platform's separators, so Windows paths with `\` work too.
+ const parentDir = path.basename(path.dirname(filePath));
+ const project = parentDir && parentDir !== '.' ? parentDir : 'unknown';
const exchanges = await parseConversation(filePath, project, filePath);
return {
project,
diff --git a/dist/paths.d.ts b/dist/paths.d.ts
index 6cee3813..2e83417f 100644
--- a/dist/paths.d.ts
+++ b/dist/paths.d.ts
@@ -82,6 +82,12 @@ export declare function getSuperpowersDir(): string;
* Get conversation archive directory
*/
export declare function getArchiveDir(): string;
+/**
+ * Keep downloaded embedding models outside npm-owned node_modules so plugin
+ * upgrades do not discard the cache. An explicit override supports shared or
+ * pre-seeded caches on hosts without model-network access.
+ */
+export declare function getModelCacheDir(): string;
/**
* Get conversation index directory
*/
diff --git a/dist/paths.js b/dist/paths.js
index e80076b1..d4d1df09 100644
--- a/dist/paths.js
+++ b/dist/paths.js
@@ -190,6 +190,21 @@ export function getArchiveDir() {
}
return ensureDir(path.join(getSuperpowersDir(), 'conversation-archive'));
}
+/**
+ * Keep downloaded embedding models outside npm-owned node_modules so plugin
+ * upgrades do not discard the cache. An explicit override supports shared or
+ * pre-seeded caches on hosts without model-network access.
+ */
+export function getModelCacheDir() {
+ const override = process.env.EPISODIC_MEMORY_MODEL_CACHE_DIR;
+ if (override) {
+ if (!path.isAbsolute(override)) {
+ throw new Error('EPISODIC_MEMORY_MODEL_CACHE_DIR must be an absolute path');
+ }
+ return ensureDir(override);
+ }
+ return ensureDir(path.join(getSuperpowersDir(), 'models'));
+}
/**
* Get conversation index directory
*/
diff --git a/dist/sync-cli.js b/dist/sync-cli.js
index 26172c70..e444fd81 100644
--- a/dist/sync-cli.js
+++ b/dist/sync-cli.js
@@ -203,7 +203,7 @@ async function syncAll() {
totals.summarized += result.summarized;
totals.errors.push(...result.errors);
}
- console.log(`\n✅ Sync complete!`);
+ console.log(totals.errors.length > 0 ? '\n⚠️ Sync finished with errors.' : '\n✅ Sync complete!');
console.log(` Copied: ${totals.copied}`);
console.log(` Skipped: ${totals.skipped}`);
console.log(` Indexed: ${totals.indexed}`);
diff --git a/package.json b/package.json
index 58e050c9..8bc858cd 100644
--- a/package.json
+++ b/package.json
@@ -19,7 +19,7 @@
"./package.json": "./package.json"
},
"allowScripts": {
- "better-sqlite3": true,
+ "better-sqlite3": false,
"onnxruntime-node": true,
"sharp": false
},
@@ -35,7 +35,7 @@
"build": "tsc && npm run bundle",
"bundle": "esbuild src/mcp-server.ts --bundle --platform=node --format=esm --outfile=dist/mcp-server.js --external:fsevents --external:@anthropic-ai/claude-agent-sdk --external:sharp --external:onnxruntime-node --external:better-sqlite3 --external:@huggingface/transformers --external:sqlite-vec --external:proper-lockfile",
"postinstall": "node scripts/postinstall.js",
- "pretest": "npm run generate-version",
+ "pretest": "npm run generate-version && tsx scripts/prepare-test-model.ts",
"test": "vitest run",
"test:claude-e2e": "node scripts/claude-e2e.js",
"test:codex-e2e": "node scripts/codex-e2e.js",
@@ -58,9 +58,9 @@
"type": "module",
"dependencies": {
"@anthropic-ai/claude-agent-sdk": "^0.2.126",
- "@huggingface/transformers": "^4.2.0",
+ "@huggingface/transformers": "4.2.0",
"@modelcontextprotocol/sdk": "^1.20.0",
- "better-sqlite3": "^12.4.1",
+ "better-sqlite3": "^13.0.3",
"marked": "^16.4.0",
"proper-lockfile": "^4.1.2",
"sqlite-vec": "^0.1.7-alpha.2",
diff --git a/scripts/postinstall.js b/scripts/postinstall.js
index b60431bb..f9dc2347 100644
--- a/scripts/postinstall.js
+++ b/scripts/postinstall.js
@@ -1,7 +1,7 @@
#!/usr/bin/env node
/**
- * Cross-platform postinstall: get better-sqlite3's native binding into a state
- * where it actually loads, and refuse to report success until it does.
+ * Cross-platform postinstall: verify that better-sqlite3 and sqlite-vec work
+ * together, and refuse to report success until they do.
*
* Replaces the unix-only shell idiom that lived in package.json:
*
@@ -11,59 +11,43 @@
* and `|| true` doesn't behave the same — which makes `npm install` exit
* non-zero even when every dependency installed correctly (#95).
*
- * Why the exit status of `npm rebuild` cannot be trusted (#100)
- * ------------------------------------------------------------
- * `npm rebuild better-sqlite3` does not reliably run better-sqlite3's own
- * install script (`prebuild-install || node-gyp rebuild --release`). On the npm
- * shipped with recent Node it prints "rebuilt dependencies successfully",
- * exits 0, and builds nothing. Separately, better-sqlite3 publishes prebuilds
- * only for the Node versions in its `engines` range, so on a newer host Node
- * `prebuild-install` can leave a binary compiled for an older ABI in place.
+ * Why this no longer rebuilds better-sqlite3 (#100)
+ * -------------------------------------------------
+ * better-sqlite3 13.x ships N-API platform binaries in the npm package. They
+ * are not tied to a single Node module ABI and do not need an install script.
+ * Rebuilding the old 12.x addon was both unreliable and unsafe: a rebuild with
+ * Node 24.19-24.21 headers could produce a binding that loaded successfully but
+ * later aborted during statement garbage collection.
*
- * Both failures look identical from the outside: a clean install, and a plugin
- * whose search silently returns nothing because the MCP server dies loading the
- * binding — in a log nobody reads.
+ * A broken or partial install still looks like a clean install from the
+ * outside, while the MCP server dies loading the binding in a log nobody reads.
*
- * So this script does three things `status !== 0` cannot:
+ * So this script verifies behavior rather than trusting package-manager status:
*
* 1. Verifies by INSTANTIATING a database, not by requiring the module.
* `require('better-sqlite3')` succeeds with no binding at all, because the
* addon is loaded lazily inside `new Database()` (#100).
- * 2. Verifies in a CHILD process. A native addon cannot be un-loaded, so a
- * failed load poisons the module cache and an in-process re-check after a
- * repair attempt would be meaningless.
- * 3. On failure, falls back to better-sqlite3's real build path
- * (`npm run build-release` = `node-gyp rebuild --release`) and re-verifies,
- * rather than printing a recovery hint naming the command that just failed.
+ * 2. Loads sqlite-vec and performs a real vec0 insert plus nearest-neighbor
+ * query, rather than stopping at `vec_version()`.
+ * 3. Verifies in a CHILD process so native failures cannot poison the
+ * postinstall process.
*
- * Exit code reflects the binding, not the tooling: a noisy `npm rebuild` whose
- * binding nevertheless loads is NOT fatal (that is the #95 false alarm), and a
- * clean `npm rebuild` that leaves an unloadable binding IS.
+ * There is deliberately no automatic source-build fallback. If the bundled
+ * N-API binary cannot run, failing closed preserves the original evidence and
+ * avoids replacing it with a runtime-specific local build.
*/
import { spawnSync } from 'child_process';
-import { existsSync } from 'fs';
import { dirname, join } from 'path';
import { fileURLToPath } from 'url';
const PLUGIN_ROOT = dirname(dirname(fileURLToPath(import.meta.url)));
-const BETTER_SQLITE3_DIR = join(PLUGIN_ROOT, 'node_modules', 'better-sqlite3');
-
-const isWindows = process.platform === 'win32';
-const npmBin = isWindows ? 'npm.cmd' : 'npm';
-
-function npm(args, cwd) {
- return spawnSync(npmBin, args, {
- cwd,
- stdio: ['ignore', 'inherit', 'inherit'],
- shell: isWindows,
- });
-}
/**
- * Load the native stack the way the MCP server will — instantiate a database,
- * then load sqlite-vec into it — in a throwaway child process.
+ * Load the native stack the way the MCP server will: instantiate a database,
+ * load sqlite-vec, write a vector, and run a nearest-neighbor query.
*
- * Returns null on success, or { stderr } describing the failure.
+ * Returns the installed better-sqlite3 version on success, or a failure with
+ * stderr on error.
*
* sqlite-vec is only fatal when it is actually installed; during some install
* orderings it is not resolvable yet, which is a dependency problem the
@@ -74,12 +58,23 @@ function verifyNativeStack() {
const script = `
const { createRequire } = require('module');
const req = createRequire(${pkgJson});
+ const version = req('better-sqlite3/package.json').version;
const Database = req('better-sqlite3');
const db = new Database(':memory:');
let vec = null;
try { vec = req('sqlite-vec'); } catch (e) { vec = null; }
- if (vec) { vec.load(db); db.prepare('select vec_version()').get(); }
+ if (vec) {
+ vec.load(db);
+ db.exec('CREATE VIRTUAL TABLE native_probe USING vec0(id TEXT PRIMARY KEY, embedding FLOAT[2])');
+ const embedding = Buffer.from(new Float32Array([1, 0]).buffer);
+ db.prepare('INSERT INTO native_probe (id, embedding) VALUES (?, ?)').run('probe', embedding);
+ const row = db.prepare(
+ 'SELECT id FROM native_probe WHERE embedding MATCH ? AND k = 1'
+ ).get(embedding);
+ if (!row || row.id !== 'probe') throw new Error('sqlite-vec query returned the wrong row');
+ }
db.close();
+ process.stdout.write(version);
`;
const result = spawnSync(process.execPath, ['-e', script], {
@@ -87,44 +82,28 @@ function verifyNativeStack() {
encoding: 'utf-8',
});
- if (result.status === 0) return null;
- return { stderr: (result.stderr || '').trim() || `child exited ${result.status}` };
+ if (result.status === 0) {
+ return { version: (result.stdout || '').trim() || 'unknown', failure: null };
+ }
+ return {
+ version: null,
+ failure: (result.stderr || '').trim() || `child exited ${result.status}`,
+ };
}
-// Attempt 1: the cheap path that works on most hosts.
-const rebuild = npm(['rebuild', 'better-sqlite3'], PLUGIN_ROOT);
-let failure = verifyNativeStack();
+const verification = verifyNativeStack();
+const failure = verification.failure;
-// Attempt 2: better-sqlite3's real build path. `npm rebuild` frequently does
-// not run it, and it is the step that actually compiles for this Node's ABI.
-let fallback = null;
-if (failure && existsSync(BETTER_SQLITE3_DIR)) {
+if (!failure) {
console.error(
- 'episodic-memory: better-sqlite3 binding did not load after `npm rebuild`; ' +
- 'compiling from source with `npm run build-release`...'
+ `episodic-memory: native stack verified (better-sqlite3 ${verification.version}, ` +
+ `${process.version}, N-API ${process.versions.napi}).`
);
- fallback = npm(['run', 'build-release'], BETTER_SQLITE3_DIR);
- failure = verifyNativeStack();
- if (!failure) {
- console.error('episodic-memory: source build succeeded — native binding loads.');
- }
-}
-
-if (!failure) {
- if (rebuild.status !== 0 && !fallback) {
- // Rebuild complained but the binding loads — the #95 false-alarm case.
- console.error(
- `episodic-memory: 'npm rebuild better-sqlite3' exited ${rebuild.status}, ` +
- 'but the native binding loads correctly for this Node ' +
- `(${process.version}, NODE_MODULE_VERSION ${process.versions.modules}). ` +
- 'Continuing.'
- );
- }
process.exit(0);
}
-const compiledFor = /NODE_MODULE_VERSION (\d+)/.exec(failure.stderr);
-const noBindings = /Could not locate the bindings file/.test(failure.stderr);
+const compiledFor = /NODE_MODULE_VERSION (\d+)/.exec(failure);
+const noBindings = /Could not locate the bindings file/.test(failure);
console.error('');
console.error('='.repeat(72));
@@ -137,21 +116,15 @@ if (compiledFor) {
if (noBindings) {
console.error(' binary : missing entirely (nothing was compiled)');
}
-console.error(` npm rebuild exit : ${rebuild.status}`);
-if (fallback) {
- console.error(` source build exit: ${fallback.status}`);
-}
console.error('');
console.error(' underlying error:');
-for (const line of failure.stderr.split('\n').slice(0, 12)) {
+for (const line of failure.split('\n').slice(0, 12)) {
console.error(` ${line}`);
}
console.error('');
-console.error(' A source build needs a working toolchain: Xcode Command Line Tools on');
-console.error(' macOS, build-essential + python3 on Linux, VS Build Tools on Windows.');
-console.error('');
-console.error(' Recover with:');
-console.error(` cd "${BETTER_SQLITE3_DIR}" && npm run build-release`);
+console.error(' better-sqlite3 13.x includes N-API platform binaries; do not compile');
+console.error(' the old 12.x addon as a fallback. Reinstall episodic-memory with the');
+console.error(' same package manifest, then rerun this check.');
console.error('');
console.error(' Failing the install deliberately: passing silently here is what lets');
console.error(' search disappear without anyone noticing.');
diff --git a/scripts/prepare-test-model.ts b/scripts/prepare-test-model.ts
new file mode 100644
index 00000000..d7c61ce2
--- /dev/null
+++ b/scripts/prepare-test-model.ts
@@ -0,0 +1,12 @@
+import { initEmbeddings } from '../src/embeddings.js';
+import { testModelCacheDir } from '../test/test-model-cache.js';
+
+process.env.EPISODIC_MEMORY_MODEL_CACHE_DIR = testModelCacheDir;
+
+try {
+ await initEmbeddings();
+} catch (error) {
+ const message = error instanceof Error ? error.message : String(error);
+ console.error(`Test embedding model preparation failed: ${message}`);
+ process.exitCode = 1;
+}
diff --git a/src/embeddings.ts b/src/embeddings.ts
index 131f9e40..b55fadf4 100644
--- a/src/embeddings.ts
+++ b/src/embeddings.ts
@@ -1,4 +1,5 @@
import type { FeatureExtractionPipeline } from '@huggingface/transformers';
+import { getModelCacheDir } from './paths.js';
/**
* Embedding model configuration.
@@ -70,6 +71,8 @@ export class EmbeddingsUnavailableError extends Error {
export async function initEmbeddings(): Promise {
if (embeddingPipeline) return;
+ const modelCacheDir = getModelCacheDir();
+ const offline = process.env.EPISODIC_MEMORY_OFFLINE === '1';
// Load @huggingface/transformers lazily. Its module graph eagerly requires
// `sharp`, so a static top-level import would crash *every* consumer of this
@@ -79,9 +82,11 @@ export async function initEmbeddings(): Promise {
let pipeline: typeof import('@huggingface/transformers').pipeline;
try {
const transformers = await import('@huggingface/transformers');
- // Disable progress callbacks / remote cache to prevent stdout pollution in
- // MCP context, where stdout is reserved for JSON-RPC communication.
+ // Keep model files in durable operator-owned state. Offline mode is an
+ // explicit choice; a fresh default install can still fetch its model.
+ transformers.env.cacheDir = modelCacheDir;
transformers.env.allowLocalModels = true;
+ transformers.env.allowRemoteModels = !offline;
transformers.env.useBrowserCache = false;
pipeline = transformers.pipeline;
} catch (error) {
@@ -106,7 +111,14 @@ export async function initEmbeddings(): Promise {
interOpNumThreads: 1,
};
}
- embeddingPipeline = await pipeline('feature-extraction', MODEL_ID, options);
+ try {
+ embeddingPipeline = await pipeline('feature-extraction', MODEL_ID, options);
+ } catch (error) {
+ const message = offline
+ ? 'Embedding model unavailable in the local cache while EPISODIC_MEMORY_OFFLINE=1; pre-seed the model cache or disable offline mode.'
+ : 'Embedding model unavailable; check the model cache and remote model access.';
+ throw new EmbeddingsUnavailableError(message, { cause: error });
+ }
console.error('Embedding model loaded');
}
diff --git a/src/parser.ts b/src/parser.ts
index a416a113..5cc32e93 100644
--- a/src/parser.ts
+++ b/src/parser.ts
@@ -15,6 +15,8 @@ interface JSONLMessage {
uuid?: string;
parentUuid?: string;
isSidechain?: boolean;
+ isMeta?: boolean;
+ origin?: { kind?: string; [key: string]: unknown };
sessionId?: string;
cwd?: string;
gitBranch?: string;
@@ -169,6 +171,17 @@ export async function parseConversation(
return parseClaudeConversation(filePath, projectName, archivePath);
}
+// Channel-bridge plugins (Discord, Slack, ...) deliver the user's own words as
+// isMeta:true user lines with origin.kind === "channel" (anthropics/claude-code#44828),
+// so isMeta alone does not mean "not the user's input"; provenance is in origin.kind.
+const HUMAN_ORIGIN_KINDS = new Set(['channel', 'human']);
+
+function isInjectedMetaLine(msg: JSONLMessage): boolean {
+ if (msg.isMeta !== true) return false;
+ const kind = msg.origin?.kind;
+ return !(typeof kind === 'string' && HUMAN_ORIGIN_KINDS.has(kind));
+}
+
async function parseClaudeConversation(
filePath: string,
projectName: string,
@@ -240,6 +253,20 @@ async function parseClaudeConversation(
continue;
}
+ // Harness-injected user lines carry isMeta:true: image-paste placeholders
+ // ("[Image: source: ...]"), Skill tool bodies, task/system notifications,
+ // local-command caveats, coordinator messages, "Continue from where you
+ // left off.". They are not the user's words, so while an exchange is open
+ // they must not start a new one: a pasted image yields the real prompt line
+ // followed by an isMeta placeholder line with no assistant reply between,
+ // and finalizeExchange() would drop the real prompt. Their text is not
+ // indexed; the assistant lines that follow attach to the open exchange.
+ // With no exchange open (a session that opens with a notification) the
+ // line still starts one, so no assistant text is ever lost.
+ if (parsed.message.role === 'user' && currentExchange && isInjectedMetaLine(parsed)) {
+ continue;
+ }
+
// Extract text from message content
let text = '';
const toolCalls: ToolCall[] = [];
@@ -805,6 +832,54 @@ async function parseOmpConversation(
return exchanges;
}
+// Codex injects system context as ordinary user-role message items with no field
+// that tells them apart from typed prompts. The only safe content signal is a
+// COMPLETE canonical fragment: an input_text block that is exactly one wrapper
+// element, or the AGENTS.md instructions block. A prefix is not enough — a typed
+// prompt may open with an XML snippet or a look-alike heading. Only wrappers
+// that Codex emits with role "user" are listed: observed in rollouts
+// (, , , "# AGENTS.md
+// instructions" + ) or defined with role user in codex-rs
+// (legacy , ). Developer-role wrappers
+// (, , ...) never reach the user branch.
+const CODEX_INJECTED_OPEN = /^<(environment_context|recommended_plugins|skill|user_instructions|subagent_notification)(?:\s[^>]*)?>/;
+const CODEX_AGENTS_MD_OPEN = /^# AGENTS\.md instructions(?: for [^\n]*)?\n\n\n/;
+
+// Exactly one wrapper element: the block opens with the tag and the FIRST matching
+// closing tag is the very end of the block — so ".. question
+// .." (text between elements, or several elements) is user text.
+function endsAtFirstClose(text: string, closing: string): boolean {
+ const close = text.indexOf(closing);
+ return close !== -1 && close + closing.length === text.length;
+}
+
+function isCodexInjectedBlock(text: string): boolean {
+ const trimmed = text.trim();
+ if (CODEX_AGENTS_MD_OPEN.test(trimmed)) {
+ return endsAtFirstClose(trimmed, '');
+ }
+ const open = CODEX_INJECTED_OPEN.exec(trimmed);
+ return open !== null && endsAtFirstClose(trimmed, '' + open[1] + '>');
+}
+
+// Split a Codex user item into the user's own text and the number of injected
+// blocks it carried — block by block, so a real request that shares an item with
+// an injected block is kept.
+function splitCodexUserContent(content: unknown): { userText: string; injected: number } {
+ const blocks: any[] = typeof content === 'string'
+ ? [{ type: 'input_text', text: content }]
+ : Array.isArray(content) ? content : [];
+ let injected = 0;
+ const kept = blocks.filter(block => {
+ if (block && typeof block.text === 'string' && isCodexInjectedBlock(block.text)) {
+ injected++;
+ return false;
+ }
+ return true;
+ });
+ return { userText: extractTextFromContent(kept), injected };
+}
+
async function parseCodexConversation(
filePath: string,
projectName: string,
@@ -825,6 +900,11 @@ async function parseCodexConversation(
let model: string | undefined;
let modelProvider: string | undefined;
let currentExchange: ExchangeBuilder | null = null;
+ // A user item from which injected blocks were removed: either held back entirely
+ // (injected-only, while an exchange was open) or trimmed to its remaining text.
+ // If the very next event vouches for the ORIGINAL text as a typed UserMessage,
+ // the full authored prompt is restored.
+ let pendingInjected: { text: string; line: number; timestamp: string; held: boolean } | null = null;
const toolCallsByCallId = new Map();
const currentProject = () => projectFromCwd(cwd) || projectName;
@@ -878,14 +958,14 @@ async function parseCodexConversation(
toolCallsByCallId.clear();
};
- const startExchange = (text: string, timestamp: string) => {
+ const startExchange = (text: string, timestamp: string, line: number = lineNumber) => {
finalizeExchange();
currentExchange = {
project: currentProject(),
userMessage: text,
- userLine: lineNumber,
+ userLine: line,
assistantMessages: [],
- lastAssistantLine: lineNumber,
+ lastAssistantLine: line,
timestamp,
harness: 'codex',
sessionId,
@@ -971,9 +1051,35 @@ async function parseCodexConversation(
continue;
}
+ // Positive provenance (newer rollouts): each typed prompt is followed by an
+ // item_completed UserMessage event (legacy: a user_message event). If one
+ // vouches for the item we just held back as injected, it was typed after all.
+ if (parsed.type === 'event_msg' && payload && pendingInjected) {
+ let vouched: string | undefined;
+ if (payload.type === 'item_completed' && payload.item?.type === 'UserMessage') {
+ vouched = extractTextFromContent(payload.item.content);
+ } else if (payload.type === 'user_message' && typeof payload.message === 'string') {
+ vouched = payload.message;
+ }
+ if (vouched !== undefined && (!vouched.trim() || vouched.trim() === pendingInjected.text.trim())) {
+ if (pendingInjected.held) {
+ startExchange(pendingInjected.text, pendingInjected.timestamp, pendingInjected.line);
+ } else {
+ // Trimmed item: the exchange it started is the current one.
+ const exchange = currentExchange as ExchangeBuilder | null;
+ if (exchange && exchange.userLine === pendingInjected.line) {
+ exchange.userMessage = pendingInjected.text;
+ }
+ }
+ pendingInjected = null;
+ }
+ continue;
+ }
+
if (parsed.type !== 'response_item' || !payload) {
continue;
}
+ pendingInjected = null;
if (payload.type === 'message') {
const text = extractTextFromContent(payload.content);
@@ -982,7 +1088,24 @@ async function parseCodexConversation(
}
if (payload.role === 'user') {
- startExchange(text, timestamp);
+ const { userText, injected } = splitCodexUserContent(payload.content);
+ if (userText.trim()) {
+ // The user's own words; injected blocks in the same item are dropped, but
+ // the original text is kept so a UserMessage event can restore it.
+ startExchange(userText, timestamp);
+ if (injected > 0) {
+ pendingInjected = { text, line: lineNumber, timestamp, held: false };
+ }
+ } else if (injected > 0 && currentExchange) {
+ // Injected-only item while an exchange is open: it must not split the
+ // exchange; the reply attaches to the typed prompt. Held back in case
+ // the next event proves it was typed.
+ pendingInjected = { text, line: lineNumber, timestamp, held: true };
+ } else {
+ // Nothing open yet (a rollout that starts with injected context):
+ // unchanged behavior, the item starts an exchange.
+ startExchange(text, timestamp);
+ }
} else if (payload.role === 'assistant') {
const exchange = currentExchange as ExchangeBuilder | null;
if (exchange) {
@@ -1261,14 +1384,10 @@ export async function parseConversationFile(filePath: string): Promise<{
project: string;
exchanges: ConversationExchange[];
}> {
- // Extract project name from path (directory name before the .jsonl file)
- const pathParts = filePath.split('/');
- let project = 'unknown';
-
- // Find the parent directory name (second to last part)
- if (pathParts.length >= 2) {
- project = pathParts[pathParts.length - 2];
- }
+ // Extract project name from path (directory name before the .jsonl file).
+ // path.dirname uses the platform's separators, so Windows paths with `\` work too.
+ const parentDir = path.basename(path.dirname(filePath));
+ const project = parentDir && parentDir !== '.' ? parentDir : 'unknown';
const exchanges = await parseConversation(filePath, project, filePath);
diff --git a/src/paths.ts b/src/paths.ts
index 4a08f2fe..8a02a510 100644
--- a/src/paths.ts
+++ b/src/paths.ts
@@ -204,6 +204,22 @@ export function getArchiveDir(): string {
return ensureDir(path.join(getSuperpowersDir(), 'conversation-archive'));
}
+/**
+ * Keep downloaded embedding models outside npm-owned node_modules so plugin
+ * upgrades do not discard the cache. An explicit override supports shared or
+ * pre-seeded caches on hosts without model-network access.
+ */
+export function getModelCacheDir(): string {
+ const override = process.env.EPISODIC_MEMORY_MODEL_CACHE_DIR;
+ if (override) {
+ if (!path.isAbsolute(override)) {
+ throw new Error('EPISODIC_MEMORY_MODEL_CACHE_DIR must be an absolute path');
+ }
+ return ensureDir(override);
+ }
+ return ensureDir(path.join(getSuperpowersDir(), 'models'));
+}
+
/**
* Get conversation index directory
*/
diff --git a/src/sync-cli.ts b/src/sync-cli.ts
index 297b20f8..bc629f20 100644
--- a/src/sync-cli.ts
+++ b/src/sync-cli.ts
@@ -224,7 +224,7 @@ async function syncAll() {
totals.errors.push(...result.errors);
}
- console.log(`\n✅ Sync complete!`);
+ console.log(totals.errors.length > 0 ? '\n⚠️ Sync finished with errors.' : '\n✅ Sync complete!');
console.log(` Copied: ${totals.copied}`);
console.log(` Skipped: ${totals.skipped}`);
console.log(` Indexed: ${totals.indexed}`);
diff --git a/test/allow-scripts.test.ts b/test/allow-scripts.test.ts
index 6f5c2e83..7c4cc942 100644
--- a/test/allow-scripts.test.ts
+++ b/test/allow-scripts.test.ts
@@ -5,17 +5,16 @@ import { join } from 'path';
const REPO_ROOT = join(import.meta.dirname, '..');
describe('package.json allowScripts (npm 12 install-script gating, #162)', () => {
- it('approves the native-binding installs indexing depends on', () => {
+ it('allows only the native install scripts indexing still needs', () => {
const pkg = JSON.parse(readFileSync(join(REPO_ROOT, 'package.json'), 'utf-8'));
// Under npm 12 (and npm 11.16+ with blocking opted in), a dependency's
// install/postinstall script is skipped unless the ROOT package's
- // allowScripts explicitly permits it. Without this, `npm install`
- // exits 0 while better-sqlite3 and onnxruntime-node silently ship
- // with no native binding, and indexing/search fail forever with
- // nothing surfacing the problem to the user.
+ // allowScripts explicitly permits it. onnxruntime-node still needs that
+ // permission; better-sqlite3 13.x bundles N-API binaries and must not fall
+ // back to a runtime-specific source build.
expect(pkg.allowScripts).toBeDefined();
- expect(pkg.allowScripts['better-sqlite3']).toBe(true);
+ expect(pkg.allowScripts['better-sqlite3']).toBe(false);
expect(pkg.allowScripts['onnxruntime-node']).toBe(true);
// Bare package names, not pinned versions: a pinned key (e.g.
@@ -26,6 +25,16 @@ describe('package.json allowScripts (npm 12 install-script gating, #162)', () =>
}
});
+ it('uses the N-API better-sqlite3 line that works across Node ABIs', () => {
+ const pkg = JSON.parse(readFileSync(join(REPO_ROOT, 'package.json'), 'utf-8'));
+ const postinstall = readFileSync(join(REPO_ROOT, 'scripts', 'postinstall.js'), 'utf-8');
+
+ expect(pkg.dependencies['better-sqlite3']).toBe('^13.0.3');
+ expect(postinstall).not.toContain("npm(['rebuild', 'better-sqlite3']");
+ expect(postinstall).not.toContain("npm(['run', 'build-release']");
+ expect(postinstall).not.toContain('failure.stderr');
+ });
+
it('explicitly denies sharp\'s postinstall (#102)', () => {
const pkg = JSON.parse(readFileSync(join(REPO_ROOT, 'package.json'), 'utf-8'));
diff --git a/test/codex-plugin.test.ts b/test/codex-plugin.test.ts
index 8c6cd2a5..9de5df81 100644
--- a/test/codex-plugin.test.ts
+++ b/test/codex-plugin.test.ts
@@ -40,6 +40,8 @@ describe('Codex plugin packaging', () => {
'PERSONAL_SUPERPOWERS_DIR',
'XDG_CONFIG_HOME',
'EPISODIC_MEMORY_DB_PATH',
+ 'EPISODIC_MEMORY_MODEL_CACHE_DIR',
+ 'EPISODIC_MEMORY_OFFLINE',
'CONVERSATION_SEARCH_EXCLUDE_PROJECTS'
]
}
diff --git a/test/codex-transcripts.test.ts b/test/codex-transcripts.test.ts
index 9b39c58c..3da09217 100644
--- a/test/codex-transcripts.test.ts
+++ b/test/codex-transcripts.test.ts
@@ -305,3 +305,224 @@ describe('Codex transcript support', () => {
db.close();
});
});
+
+describe('Codex transcripts - injected system items must not split an exchange', () => {
+ let dir: string;
+ beforeEach(() => { dir = mkdtempSync(join(tmpdir(), 'episodic-memory-codex-injected-')); });
+ afterEach(() => { rmSync(dir, { recursive: true, force: true }); });
+
+ const meta = {
+ timestamp: '2026-09-10T13:34:21.000Z',
+ type: 'session_meta',
+ payload: {
+ id: '01a08b18-ea48-7e83-8503-3e21d476d9fa',
+ timestamp: '2026-09-10T13:34:21.000Z',
+ cwd: '/Users/testuser/Documents/GitHub/example-project',
+ originator: 'codex_cli_rs',
+ cli_version: '0.153.4',
+ source: 'cli',
+ model_provider: 'openai'
+ }
+ };
+ const user = (text: string, ts: string) => ({
+ timestamp: ts,
+ type: 'response_item',
+ payload: { type: 'message', role: 'user', content: [{ type: 'input_text', text }] }
+ });
+ const userBlocks = (texts: string[], ts: string) => ({
+ timestamp: ts,
+ type: 'response_item',
+ payload: { type: 'message', role: 'user', content: texts.map(text => ({ type: 'input_text', text })) }
+ });
+ const assistant = (text: string, ts: string) => ({
+ timestamp: ts,
+ type: 'response_item',
+ payload: { type: 'message', role: 'assistant', content: [{ type: 'output_text', text }] }
+ });
+ // Newer Codex builds log each typed prompt as an item_completed UserMessage event
+ const userEvent = (text: string, ts: string) => ({
+ timestamp: ts,
+ type: 'event_msg',
+ payload: { type: 'item_completed', item: { id: 'item_user_1', type: 'UserMessage', content: [{ type: 'text', text }] } }
+ });
+ const agentsMd = '# AGENTS.md instructions\n\n\n# Standing rules\nNothing leaves this machine.\n';
+ const envContext = (cwd: string) => `\n ${cwd}\n zsh\n`;
+ const plugins = '\nHere is a list of plugins the user may find useful.\n';
+ const skillBody = '\nagent-chat\n/Users/testuser/.codex/skills/agent-chat/SKILL.md\n---\nname: agent-chat\n---\n# Agent Chat\nCommands: register, send, read.\n';
+
+ async function parse(lines: unknown[]) {
+ const file = join(dir, 'rollout-2026-09-10T13-34-21-01a08b18-ea48-7e83-8503-3e21d476d9fa.jsonl');
+ writeJsonl(file, lines);
+ return parseConversation(file, '2026', file);
+ }
+
+ it('keeps the typed prompt when a body is injected before the reply (real rollout shape)', async () => {
+ const exchanges = await parse([
+ meta,
+ user(agentsMd, '2026-09-10T13:34:21.100Z'),
+ user(envContext('/Users/testuser/Documents/GitHub/example-project'), '2026-09-10T13:34:21.200Z'),
+ user('register in agent-chat as episodic-codex', '2026-09-10T13:34:30.000Z'),
+ userEvent('register in agent-chat as episodic-codex', '2026-09-10T13:34:30.100Z'),
+ user(skillBody, '2026-09-10T13:34:31.000Z'),
+ assistant('Registered as episodic-codex in the project room.', '2026-09-10T13:34:40.000Z')
+ ]);
+
+ expect(exchanges).toHaveLength(1);
+ expect(exchanges[0].userMessage).toBe('register in agent-chat as episodic-codex');
+ expect(exchanges[0].assistantMessage).toBe('Registered as episodic-codex in the project room.');
+ expect(exchanges[0].lineStart).toBe(4);
+ expect(exchanges[0].lineEnd).toBe(7);
+ expect(exchanges[0].harness).toBe('codex');
+ });
+
+ it('ignores user-role context re-injected between turns (single and multi-block items)', async () => {
+ const exchanges = await parse([
+ meta,
+ user('First question.', '2026-09-10T14:00:00.000Z'),
+ assistant('First answer.', '2026-09-10T14:00:05.000Z'),
+ userBlocks([plugins, envContext('/Users/testuser/Documents/GitHub/example-project')], '2026-09-10T14:01:00.000Z'),
+ user('Second question.', '2026-09-10T14:01:01.000Z'),
+ assistant('Second answer.', '2026-09-10T14:01:06.000Z')
+ ]);
+
+ expect(exchanges.map(e => [e.userMessage, e.assistantMessage])).toEqual([
+ ['First question.', 'First answer.'],
+ ['Second question.', 'Second answer.']
+ ]);
+ expect(exchanges[1].lineStart).toBe(5);
+ });
+
+ it('keeps a real request that shares an item with an injected block', async () => {
+ const exchanges = await parse([
+ meta,
+ user('Warm-up.', '2026-09-10T14:10:00.000Z'),
+ assistant('Ready.', '2026-09-10T14:10:02.000Z'),
+ userBlocks([envContext('/Users/testuser/x'), 'Please rename the config loader.'], '2026-09-10T14:11:00.000Z'),
+ assistant('Renamed.', '2026-09-10T14:11:04.000Z')
+ ]);
+
+ expect(exchanges).toHaveLength(2);
+ expect(exchanges[1].userMessage).toBe('Please rename the config loader.');
+ expect(exchanges[1].assistantMessage).toBe('Renamed.');
+ });
+
+ it('does not mistake typed text for an injected item on its opening prefix alone', async () => {
+ const exchanges = await parse([
+ meta,
+ user('Here is my pom.', '2026-09-10T14:20:00.000Z'),
+ assistant('Go on.', '2026-09-10T14:20:02.000Z'),
+ // A typed Maven snippet that opens like a wrapper tag, followed by the question
+ user('\n maven-surefire-plugin\n\nWhy are my tests skipped?', '2026-09-10T14:21:00.000Z'),
+ assistant('Because skipTests is set.', '2026-09-10T14:21:05.000Z'),
+ // A heading that merely resembles the AGENTS.md header
+ user('# AGENTS.md instructions need cleanup\nPlease remove the obsolete setup instructions.', '2026-09-10T14:22:00.000Z'),
+ assistant('Removed them.', '2026-09-10T14:22:05.000Z'),
+ // A complete -like element the user pasted, but with trailing text
+ user('\nx\n\nIs this the right skill format?', '2026-09-10T14:23:00.000Z'),
+ assistant('Yes.', '2026-09-10T14:23:03.000Z')
+ ]);
+
+ expect(exchanges.map(e => e.userMessage)).toEqual([
+ 'Here is my pom.',
+ '\n maven-surefire-plugin\n\nWhy are my tests skipped?',
+ '# AGENTS.md instructions need cleanup\nPlease remove the obsolete setup instructions.',
+ '\nx\n\nIs this the right skill format?'
+ ]);
+ });
+
+ it('trusts a UserMessage event over the content heuristic', async () => {
+ const pasted = envContext('/Users/testuser/y'); // user pasted a complete wrapper block verbatim
+ const exchanges = await parse([
+ meta,
+ user('Look at this.', '2026-09-10T14:30:00.000Z'),
+ assistant('Looking.', '2026-09-10T14:30:02.000Z'),
+ user(pasted, '2026-09-10T14:31:00.000Z'),
+ userEvent(pasted, '2026-09-10T14:31:00.100Z'),
+ assistant('That is an environment block.', '2026-09-10T14:31:05.000Z')
+ ]);
+
+ expect(exchanges).toHaveLength(2);
+ expect(exchanges[1].userMessage).toBe(pasted);
+ expect(exchanges[1].lineStart).toBe(4);
+ expect(exchanges[1].assistantMessage).toBe('That is an environment block.');
+ });
+
+ it('still treats user-input wrappers and image captions as prompts', async () => {
+ const exchanges = await parse([
+ meta,
+ user('Look at the config.', '2026-09-10T15:00:00.000Z'),
+ assistant('Looking.', '2026-09-10T15:00:03.000Z'),
+ user('ls src', '2026-09-10T15:00:10.000Z'),
+ assistant('parser.ts show.ts', '2026-09-10T15:00:12.000Z'),
+ {
+ timestamp: '2026-09-10T15:01:00.000Z',
+ type: 'response_item',
+ payload: { type: 'message', role: 'user', content: [
+ { type: 'input_text', text: ' ' },
+ { type: 'input_image', image_url: 'data:image/png;base64,iVBORw0KGgo=' },
+ { type: 'input_text', text: '' },
+ { type: 'input_text', text: '[Image #1] please enable experimental context management.' }
+ ] }
+ },
+ assistant('Enabled.', '2026-09-10T15:01:04.000Z')
+ ]);
+
+ expect(exchanges).toHaveLength(3);
+ expect(exchanges[1].userMessage).toContain('ls src');
+ expect(exchanges[2].userMessage).toContain('please enable experimental context management');
+ });
+
+ it('treats several wrapper elements, or text between them, as user text (single-fragment rule)', async () => {
+ const twoSkills = 'old\nWhich definition should I keep?\nnew';
+ const exchanges = await parse([
+ meta,
+ user('Compare these.', '2026-09-10T14:40:00.000Z'),
+ assistant('Paste them.', '2026-09-10T14:40:02.000Z'),
+ user(twoSkills, '2026-09-10T14:41:00.000Z'),
+ assistant('Keep the new definition.', '2026-09-10T14:41:05.000Z')
+ ]);
+
+ expect(exchanges).toHaveLength(2);
+ expect(exchanges[1].userMessage).toBe(twoSkills);
+ expect(exchanges[1].assistantMessage).toBe('Keep the new definition.');
+ expect(exchanges[0].assistantMessage).toBe('Paste them.');
+ });
+
+ it('restores the full authored prompt of a mixed item when a UserMessage event vouches for it', async () => {
+ const env = envContext('/Users/testuser/wrong-dir');
+ const question = 'Why is this pointing at the wrong directory?';
+ const exchanges = await parse([
+ meta,
+ user('Hi.', '2026-09-10T14:50:00.000Z'),
+ assistant('Hello.', '2026-09-10T14:50:02.000Z'),
+ userBlocks([env, question], '2026-09-10T14:51:00.000Z'),
+ {
+ timestamp: '2026-09-10T14:51:00.100Z',
+ type: 'event_msg',
+ payload: { type: 'item_completed', item: { id: 'item_user_2', type: 'UserMessage', content: [
+ { type: 'text', text: env }, { type: 'text', text: question }
+ ] } }
+ },
+ assistant('Because cwd is stale.', '2026-09-10T14:51:05.000Z')
+ ]);
+
+ expect(exchanges).toHaveLength(2);
+ expect(exchanges[1].userMessage).toBe(`${env}\n${question}`);
+ expect(exchanges[1].lineStart).toBe(4);
+ expect(exchanges[1].assistantMessage).toBe('Because cwd is stale.');
+ });
+
+ it('lets an injected item open a session that has no prompt yet (unchanged behavior)', async () => {
+ const exchanges = await parse([
+ meta,
+ user(envContext('/Users/testuser/x'), '2026-09-10T16:00:00.000Z'),
+ assistant('Ready.', '2026-09-10T16:00:02.000Z'),
+ user('Now the real prompt.', '2026-09-10T16:00:10.000Z'),
+ assistant('Real answer.', '2026-09-10T16:00:14.000Z')
+ ]);
+
+ expect(exchanges).toHaveLength(2);
+ expect(exchanges[0].userMessage).toContain('');
+ expect(exchanges[1].userMessage).toBe('Now the real prompt.');
+ });
+});
diff --git a/test/file-lock.test.ts b/test/file-lock.test.ts
index d01f776b..a1383309 100644
--- a/test/file-lock.test.ts
+++ b/test/file-lock.test.ts
@@ -66,7 +66,9 @@ describe('file-lock — proper-lockfile wrapper (#97)', () => {
expect(readLockHolder(lockPath)).toBeNull();
});
- it('propagates unexpected I/O errors instead of masking them as "lock contention"', () => {
+ // POSIX only: Windows ignores directory mode bits, so the chmod below can't
+ // make the directory unwritable.
+ it.skipIf(process.platform === 'win32')('propagates unexpected I/O errors instead of masking them as "lock contention"', () => {
// chmod the directory read-only so openSync('a') hits EACCES on the lock
// target. The wrapper must throw rather than return null — otherwise sync
// would report "already running" for what's actually a disk problem.
diff --git a/test/fixtures/channel-plugin-conversation.jsonl b/test/fixtures/channel-plugin-conversation.jsonl
new file mode 100644
index 00000000..e636f8ce
--- /dev/null
+++ b/test/fixtures/channel-plugin-conversation.jsonl
@@ -0,0 +1,4 @@
+{"parentUuid":null,"isSidechain":false,"userType":"external","cwd":"/Users/testuser/Documents/GitHub/example-project","sessionId":"3fa92c26-0000-4000-8000-000000000003","version":"2.1.267","gitBranch":"main","type":"user","message":{"role":"user","content":"List the files in src."},"uuid":"c0000000-0000-4000-8000-000000000001","timestamp":"2026-09-10T11:00:00.000Z"}
+{"parentUuid":"c0000000-0000-4000-8000-000000000001","isSidechain":false,"userType":"external","cwd":"/Users/testuser/Documents/GitHub/example-project","sessionId":"3fa92c26-0000-4000-8000-000000000003","version":"2.1.267","gitBranch":"main","message":{"id":"msg_01Chan0000000000000000001","type":"message","role":"assistant","model":"claude-opus-4-1-20250805","content":[{"type":"text","text":"parser.ts and show.ts."}],"stop_reason":"end_turn","usage":{"input_tokens":500,"output_tokens":8}},"requestId":"req_chan_000001","type":"assistant","uuid":"c0000000-0000-4000-8000-000000000002","timestamp":"2026-09-10T11:00:05.000Z"}
+{"parentUuid":"c0000000-0000-4000-8000-000000000002","isSidechain":false,"userType":"external","cwd":"/Users/testuser/Documents/GitHub/example-project","sessionId":"3fa92c26-0000-4000-8000-000000000003","version":"2.1.267","gitBranch":"main","type":"user","message":{"role":"user","content":[{"type":"text","text":"Please explain the retry policy."}]},"isMeta":true,"origin":{"kind":"channel","server":"plugin:discord:discord"},"uuid":"c0000000-0000-4000-8000-000000000003","timestamp":"2026-09-10T11:02:00.000Z"}
+{"parentUuid":"c0000000-0000-4000-8000-000000000003","isSidechain":false,"userType":"external","cwd":"/Users/testuser/Documents/GitHub/example-project","sessionId":"3fa92c26-0000-4000-8000-000000000003","version":"2.1.267","gitBranch":"main","message":{"id":"msg_01Chan0000000000000000002","type":"message","role":"assistant","model":"claude-opus-4-1-20250805","content":[{"type":"text","text":"Retries use exponential backoff with a cap of five attempts."}],"stop_reason":"end_turn","usage":{"input_tokens":700,"output_tokens":14}},"requestId":"req_chan_000002","type":"assistant","uuid":"c0000000-0000-4000-8000-000000000004","timestamp":"2026-09-10T11:02:06.000Z"}
diff --git a/test/fixtures/image-paste-conversation.jsonl b/test/fixtures/image-paste-conversation.jsonl
new file mode 100644
index 00000000..23e47844
--- /dev/null
+++ b/test/fixtures/image-paste-conversation.jsonl
@@ -0,0 +1,3 @@
+{"parentUuid":null,"isSidechain":false,"userType":"external","cwd":"/Users/testuser/Documents/GitHub/example-project","sessionId":"1fa92c26-0000-4000-8000-000000000001","version":"2.1.267","gitBranch":"main","type":"user","message":{"role":"user","content":[{"type":"text","text":"[Image #1] I want to make Codex not ask any questions about permissions - can you help me with configuring it?"},{"type":"image","source":{"type":"base64","media_type":"image/png","data":"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg=="}}]},"uuid":"a0000000-0000-4000-8000-000000000001","timestamp":"2026-09-09T16:56:10.000Z","thinkingMetadata":{"level":"high","disabled":false,"triggers":[]}}
+{"parentUuid":"a0000000-0000-4000-8000-000000000001","isSidechain":false,"userType":"external","cwd":"/Users/testuser/Documents/GitHub/example-project","sessionId":"1fa92c26-0000-4000-8000-000000000001","version":"2.1.267","gitBranch":"main","type":"user","message":{"role":"user","content":[{"type":"text","text":"[Image: source: /Users/testuser/Downloads/Image 09-09-2026 at 18.56.jpg]"}]},"isMeta":true,"uuid":"a0000000-0000-4000-8000-000000000002","timestamp":"2026-09-09T16:56:10.100Z"}
+{"parentUuid":"a0000000-0000-4000-8000-000000000002","isSidechain":false,"userType":"external","cwd":"/Users/testuser/Documents/GitHub/example-project","sessionId":"1fa92c26-0000-4000-8000-000000000001","version":"2.1.267","gitBranch":"main","message":{"id":"msg_01Image0000000000000000001","type":"message","role":"assistant","model":"claude-opus-4-1-20250805","content":[{"type":"text","text":"Yes. Codex reads its approval policy from ~/.codex/config.toml. Set approval_policy = \"never\" and sandbox_mode = \"danger-full-access\" to stop the permission prompts."}],"stop_reason":"end_turn","usage":{"input_tokens":1200,"output_tokens":60}},"requestId":"req_image_000001","type":"assistant","uuid":"a0000000-0000-4000-8000-000000000003","timestamp":"2026-09-09T16:56:20.000Z"}
diff --git a/test/fixtures/meta-first-conversation.jsonl b/test/fixtures/meta-first-conversation.jsonl
new file mode 100644
index 00000000..38f02960
--- /dev/null
+++ b/test/fixtures/meta-first-conversation.jsonl
@@ -0,0 +1,4 @@
+{"parentUuid":null,"isSidechain":false,"userType":"external","cwd":"/Users/testuser/Documents/GitHub/example-project","sessionId":"4fa92c26-0000-4000-8000-000000000004","version":"2.1.267","gitBranch":"main","type":"user","message":{"role":"user","content":"[SYSTEM NOTIFICATION - NOT USER INPUT]\nThis is an automated background-task event.\nb1completed"},"isMeta":true,"origin":{"kind":"task-notification"},"uuid":"d0000000-0000-4000-8000-000000000001","timestamp":"2026-09-10T12:00:00.000Z"}
+{"parentUuid":"d0000000-0000-4000-8000-000000000001","isSidechain":false,"userType":"external","cwd":"/Users/testuser/Documents/GitHub/example-project","sessionId":"4fa92c26-0000-4000-8000-000000000004","version":"2.1.267","gitBranch":"main","message":{"id":"msg_01Meta0000000000000000001","type":"message","role":"assistant","model":"claude-opus-4-1-20250805","content":[{"type":"text","text":"The background task finished; nothing else is pending."}],"stop_reason":"end_turn","usage":{"input_tokens":300,"output_tokens":12}},"requestId":"req_meta_000001","type":"assistant","uuid":"d0000000-0000-4000-8000-000000000002","timestamp":"2026-09-10T12:00:04.000Z"}
+{"parentUuid":"d0000000-0000-4000-8000-000000000002","isSidechain":false,"userType":"external","cwd":"/Users/testuser/Documents/GitHub/example-project","sessionId":"4fa92c26-0000-4000-8000-000000000004","version":"2.1.267","gitBranch":"main","type":"user","message":{"role":"user","content":"Now summarize what changed."},"uuid":"d0000000-0000-4000-8000-000000000003","timestamp":"2026-09-10T12:01:00.000Z"}
+{"parentUuid":"d0000000-0000-4000-8000-000000000003","isSidechain":false,"userType":"external","cwd":"/Users/testuser/Documents/GitHub/example-project","sessionId":"4fa92c26-0000-4000-8000-000000000004","version":"2.1.267","gitBranch":"main","message":{"id":"msg_01Meta0000000000000000002","type":"message","role":"assistant","model":"claude-opus-4-1-20250805","content":[{"type":"text","text":"Two files changed: parser.ts and show.ts."}],"stop_reason":"end_turn","usage":{"input_tokens":420,"output_tokens":10}},"requestId":"req_meta_000002","type":"assistant","uuid":"d0000000-0000-4000-8000-000000000004","timestamp":"2026-09-10T12:01:05.000Z"}
diff --git a/test/fixtures/skill-invocation-conversation.jsonl b/test/fixtures/skill-invocation-conversation.jsonl
new file mode 100644
index 00000000..9f542e1d
--- /dev/null
+++ b/test/fixtures/skill-invocation-conversation.jsonl
@@ -0,0 +1,8 @@
+{"parentUuid":null,"isSidechain":false,"userType":"external","cwd":"/Users/testuser/Documents/GitHub/example-project","sessionId":"2fa92c26-0000-4000-8000-000000000002","version":"2.1.267","gitBranch":"main","type":"user","message":{"role":"user","content":"register as summarizer in agent-chat"},"uuid":"b0000000-0000-4000-8000-000000000001","timestamp":"2026-09-10T10:00:00.000Z","thinkingMetadata":{"level":"high","disabled":false,"triggers":[]}}
+{"parentUuid":"b0000000-0000-4000-8000-000000000001","isSidechain":false,"userType":"external","cwd":"/Users/testuser/Documents/GitHub/example-project","sessionId":"2fa92c26-0000-4000-8000-000000000002","version":"2.1.267","gitBranch":"main","message":{"id":"msg_01Skill000000000000000000","type":"message","role":"assistant","model":"claude-opus-4-1-20250805","content":[{"type":"text","text":"I'll load the agent-chat skill to register under that name."}],"stop_reason":"end_turn","usage":{"input_tokens":880,"output_tokens":15}},"requestId":"req_skill_000000","type":"assistant","uuid":"b0000000-0000-4000-8000-000000000010","timestamp":"2026-09-10T10:00:03.000Z"}
+{"parentUuid":"b0000000-0000-4000-8000-000000000010","isSidechain":false,"userType":"external","cwd":"/Users/testuser/Documents/GitHub/example-project","sessionId":"2fa92c26-0000-4000-8000-000000000002","version":"2.1.267","gitBranch":"main","message":{"id":"msg_01Skill000000000000000001","type":"message","role":"assistant","model":"claude-opus-4-1-20250805","content":[{"type":"tool_use","id":"toolu_01skill0001","name":"Skill","input":{"skill":"agent-chat","args":"register as summarizer"}}],"stop_reason":"tool_use","usage":{"input_tokens":900,"output_tokens":40}},"requestId":"req_skill_000001","type":"assistant","uuid":"b0000000-0000-4000-8000-000000000002","timestamp":"2026-09-10T10:00:05.000Z"}
+{"parentUuid":"b0000000-0000-4000-8000-000000000002","isSidechain":false,"userType":"external","cwd":"/Users/testuser/Documents/GitHub/example-project","sessionId":"2fa92c26-0000-4000-8000-000000000002","version":"2.1.267","gitBranch":"main","type":"user","message":{"role":"user","content":[{"tool_use_id":"toolu_01skill0001","type":"tool_result","content":"Launching skill: agent-chat"}]},"uuid":"b0000000-0000-4000-8000-000000000003","timestamp":"2026-09-10T10:00:05.200Z"}
+{"parentUuid":"b0000000-0000-4000-8000-000000000003","isSidechain":false,"userType":"external","cwd":"/Users/testuser/Documents/GitHub/example-project","sessionId":"2fa92c26-0000-4000-8000-000000000002","version":"2.1.267","gitBranch":"main","type":"user","message":{"role":"user","content":[{"type":"text","text":"Base directory for this skill: /Users/testuser/.claude/skills/agent-chat\n\n# Agent Chat\n\nServerless chat for concurrent sessions. Commands: register, send, read, who.\n\nARGUMENTS: register as summarizer"}]},"isMeta":true,"uuid":"b0000000-0000-4000-8000-000000000004","timestamp":"2026-09-10T10:00:05.300Z"}
+{"parentUuid":"b0000000-0000-4000-8000-000000000004","isSidechain":false,"userType":"external","cwd":"/Users/testuser/Documents/GitHub/example-project","sessionId":"2fa92c26-0000-4000-8000-000000000002","version":"2.1.267","gitBranch":"main","message":{"id":"msg_01Skill000000000000000002","type":"message","role":"assistant","model":"claude-opus-4-1-20250805","content":[{"type":"text","text":"Registered as summarizer in the project room."}],"stop_reason":"end_turn","usage":{"input_tokens":1500,"output_tokens":20}},"requestId":"req_skill_000002","type":"assistant","uuid":"b0000000-0000-4000-8000-000000000005","timestamp":"2026-09-10T10:00:12.000Z"}
+{"parentUuid":"b0000000-0000-4000-8000-000000000005","isSidechain":false,"userType":"external","cwd":"/Users/testuser/Documents/GitHub/example-project","sessionId":"2fa92c26-0000-4000-8000-000000000002","version":"2.1.267","gitBranch":"main","type":"user","message":{"role":"user","content":"Continue from where you left off."},"isMeta":true,"uuid":"b0000000-0000-4000-8000-000000000006","timestamp":"2026-09-10T10:00:13.000Z"}
+{"parentUuid":"b0000000-0000-4000-8000-000000000006","isSidechain":false,"userType":"external","cwd":"/Users/testuser/Documents/GitHub/example-project","sessionId":"2fa92c26-0000-4000-8000-000000000002","version":"2.1.267","gitBranch":"main","message":{"id":"msg_01Skill000000000000000003","type":"message","role":"assistant","model":"claude-opus-4-1-20250805","content":[{"type":"text","text":"No unread messages. Standing by."}],"stop_reason":"end_turn","usage":{"input_tokens":1600,"output_tokens":10}},"requestId":"req_skill_000003","type":"assistant","uuid":"b0000000-0000-4000-8000-000000000007","timestamp":"2026-09-10T10:00:15.000Z"}
diff --git a/test/mcp-install-runner.test.ts b/test/mcp-install-runner.test.ts
index 28cc4140..93c9e800 100644
--- a/test/mcp-install-runner.test.ts
+++ b/test/mcp-install-runner.test.ts
@@ -149,7 +149,10 @@ describe('install-runner — runNpmInstall termination handling (#161)', () => {
});
});
-describe('mcp-server-wrapper — real spawn, orphan prevention on SIGTERM (#161)', () => {
+// POSIX only: the stub `npm` is an extensionless shebang script, which Windows
+// can't run from PATH, and Windows has no catchable SIGTERM for the wrapper to
+// handle.
+describe.skipIf(process.platform === 'win32')('mcp-server-wrapper — real spawn, orphan prevention on SIGTERM (#161)', () => {
let root: string;
let binDir: string;
diff --git a/test/mcp-server.test.ts b/test/mcp-server.test.ts
index 47382c96..566decfb 100644
--- a/test/mcp-server.test.ts
+++ b/test/mcp-server.test.ts
@@ -5,6 +5,8 @@ import { existsSync, mkdirSync, mkdtempSync, rmSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { fileURLToPath } from 'node:url';
+import { indexTestFiles } from './test-indexer.js';
+import { getFixturePath } from './test-utils.js';
const serverPath = fileURLToPath(new URL('../dist/mcp-server.js', import.meta.url));
@@ -65,6 +67,18 @@ describe('MCP search tool', () => {
mkdirSync(join(testDir, 'archive'), { recursive: true });
mkdirSync(join(testDir, 'projects'), { recursive: true });
+ const previousDbPath = process.env.TEST_DB_PATH;
+ process.env.TEST_DB_PATH = testDbPath;
+ try {
+ await indexTestFiles([getFixturePath('short-conversation.jsonl')]);
+ } finally {
+ if (previousDbPath === undefined) {
+ delete process.env.TEST_DB_PATH;
+ } else {
+ process.env.TEST_DB_PATH = previousDbPath;
+ }
+ }
+
client = new Client({ name: 'episodic-memory-test', version: '1.0.0' }, { capabilities: {} });
transport = new StdioClientTransport({
command: process.execPath,
@@ -121,4 +135,45 @@ describe('MCP search tool', () => {
});
expect(existsSync(testDbPath)).toBe(true);
});
+
+ it('completes the real MCP text, vector, and archive-read path', async () => {
+ const tools = await client.listTools();
+ expect(tools.tools.map((tool) => tool.name)).toEqual(expect.arrayContaining(['search', 'read']));
+
+ const textResult = await client.callTool({
+ name: 'search',
+ arguments: {
+ query: 'Employee class',
+ mode: 'text',
+ limit: 1,
+ response_format: 'json',
+ },
+ });
+ expect(textResult.isError).toBeFalsy();
+ const textPayload = JSON.parse(getTextContent(textResult.content as ToolContent[]));
+ expect(textPayload.count).toBeGreaterThan(0);
+
+ const vectorResult = await client.callTool({
+ name: 'search',
+ arguments: {
+ query: 'Python employee data design',
+ mode: 'vector',
+ limit: 1,
+ response_format: 'json',
+ },
+ });
+ expect(vectorResult.isError).toBeFalsy();
+
+ const vectorPayload = JSON.parse(getTextContent(vectorResult.content as ToolContent[]));
+ expect(vectorPayload.count).toBeGreaterThan(0);
+ const archivePath = vectorPayload.results[0].exchange.archivePath;
+ expect(archivePath).toBe(getFixturePath('short-conversation.jsonl'));
+
+ const readResult = await client.callTool({
+ name: 'read',
+ arguments: { path: archivePath, startLine: 1, endLine: 3 },
+ });
+ expect(readResult.isError).toBeFalsy();
+ expect(getTextContent(readResult.content as ToolContent[])).toBeTruthy();
+ });
});
diff --git a/test/model-cache-policy.test.ts b/test/model-cache-policy.test.ts
new file mode 100644
index 00000000..359aa024
--- /dev/null
+++ b/test/model-cache-policy.test.ts
@@ -0,0 +1,77 @@
+import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
+import fs from 'node:fs';
+import os from 'node:os';
+import path from 'node:path';
+
+vi.mock('@huggingface/transformers', () => ({
+ env: { cacheDir: 'package-cache', allowLocalModels: false, allowRemoteModels: true, useBrowserCache: true },
+ pipeline: vi.fn(async () => async () => ({ data: new Float32Array(384) })),
+}));
+
+describe('embedding model cache and network policy', () => {
+ let directory: string;
+ let previous: NodeJS.ProcessEnv;
+
+ beforeEach(() => {
+ previous = { ...process.env };
+ directory = fs.mkdtempSync(path.join(os.tmpdir(), 'episodic-model-policy-'));
+ process.env.EPISODIC_MEMORY_CONFIG_DIR = path.join(directory, 'config');
+ delete process.env.EPISODIC_MEMORY_MODEL_CACHE_DIR;
+ delete process.env.EPISODIC_MEMORY_OFFLINE;
+ vi.resetModules();
+ });
+
+ afterEach(() => {
+ process.env = previous;
+ fs.rmSync(directory, { recursive: true, force: true });
+ });
+
+ async function loadPolicy() {
+ const transformers = await import('@huggingface/transformers');
+ const { initEmbeddings } = await import('../src/embeddings.js');
+ await initEmbeddings();
+ return transformers.env;
+ }
+
+ it('keeps the model cache in the durable configuration directory by default', async () => {
+ const env = await loadPolicy();
+ expect(env.cacheDir).toBe(path.join(directory, 'config', 'models'));
+ expect(fs.statSync(env.cacheDir).isDirectory()).toBe(true);
+ });
+
+ it('accepts an explicit cache directory without a machine-specific default', async () => {
+ const modelCache = path.join(directory, 'shared-models');
+ process.env.EPISODIC_MEMORY_MODEL_CACHE_DIR = modelCache;
+ const env = await loadPolicy();
+ expect(env.cacheDir).toBe(modelCache);
+ });
+
+ it('rejects a relative cache override whose meaning depends on cwd', async () => {
+ process.env.EPISODIC_MEMORY_MODEL_CACHE_DIR = 'relative-model-cache';
+ const { getModelCacheDir } = await import('../src/paths.js');
+ expect(() => getModelCacheDir()).toThrow(/absolute path/);
+ });
+
+ it('blocks remote model loading only when offline mode is explicit', async () => {
+ process.env.EPISODIC_MEMORY_OFFLINE = '1';
+ const env = await loadPolicy();
+ expect(env.allowRemoteModels).toBe(false);
+ });
+
+ it('retains first-install model download behavior by default', async () => {
+ const env = await loadPolicy();
+ expect(env.allowRemoteModels).toBe(true);
+ });
+
+ it('reports an unavailable pre-seeded model clearly in offline mode', async () => {
+ process.env.EPISODIC_MEMORY_OFFLINE = '1';
+ const transformers = await import('@huggingface/transformers');
+ vi.mocked(transformers.pipeline).mockRejectedValueOnce(new Error('model files not found'));
+ const { initEmbeddings, EmbeddingsUnavailableError } = await import('../src/embeddings.js');
+
+ let failure: unknown;
+ try { await initEmbeddings(); } catch (error) { failure = error; }
+ expect(failure).toBeInstanceOf(EmbeddingsUnavailableError);
+ expect((failure as Error).message).toMatch(/offline|cache/i);
+ });
+});
diff --git a/test/parser.test.ts b/test/parser.test.ts
index 003d15b8..5d375175 100644
--- a/test/parser.test.ts
+++ b/test/parser.test.ts
@@ -139,3 +139,92 @@ describe('Parser - Real Conversation Data', () => {
});
});
});
+
+describe('Parser - isMeta user lines (harness-injected vs. human provenance)', () => {
+ describe('Image paste: real prompt + isMeta "[Image: source: ...]" placeholder', () => {
+ const fixturePath = getFixturePath('image-paste-conversation.jsonl');
+
+ it('keeps the real prompt as the user message, not the placeholder', async () => {
+ const result = await parseConversationFile(fixturePath);
+ expect(result.exchanges).toHaveLength(1);
+
+ const [exchange] = result.exchanges;
+ expect(exchange.userMessage).toBe(
+ '[Image #1] I want to make Codex not ask any questions about permissions - can you help me with configuring it?'
+ );
+ expect(exchange.userMessage).not.toContain('[Image: source:');
+ expect(exchange.assistantMessage).toContain('approval_policy');
+ });
+
+ it('anchors the exchange at the real prompt line', async () => {
+ const result = await parseConversationFile(fixturePath);
+ const [exchange] = result.exchanges;
+ expect(exchange.lineStart).toBe(1);
+ expect(exchange.lineEnd).toBe(3);
+ // First-line metadata comes from the real prompt, not the placeholder
+ expect(exchange.thinkingLevel).toBe('high');
+ });
+ });
+
+ describe('Skill invocation: isMeta skill body and "Continue" line inside one turn', () => {
+ const fixturePath = getFixturePath('skill-invocation-conversation.jsonl');
+
+ it('does not split an already-populated turn at the injected skill body', async () => {
+ const result = await parseConversationFile(fixturePath);
+ expect(result.exchanges).toHaveLength(1);
+
+ const [exchange] = result.exchanges;
+ expect(exchange.userMessage).toBe('register as summarizer in agent-chat');
+ expect(exchange.userMessage).not.toContain('Base directory for this skill');
+ expect(exchange.assistantMessage).not.toContain('Base directory for this skill');
+ // The assistant text that preceded the Skill tool call is kept
+ expect(exchange.assistantMessage).toContain("I'll load the agent-chat skill");
+ });
+
+ it('accumulates replies across isMeta lines into the same exchange', async () => {
+ const result = await parseConversationFile(fixturePath);
+ const [exchange] = result.exchanges;
+ expect(exchange.assistantMessage).toContain('Registered as summarizer');
+ expect(exchange.assistantMessage).toContain('Standing by');
+ expect(exchange.lineStart).toBe(1);
+ expect(exchange.lineEnd).toBe(8);
+ expect(exchange.toolCalls?.map(tc => tc.toolName)).toEqual(['Skill']);
+ });
+ });
+
+ describe('Channel-bridge prompt: isMeta but origin.kind === "channel" (claude-code#44828)', () => {
+ const fixturePath = getFixturePath('channel-plugin-conversation.jsonl');
+
+ it('treats the channel message as a real prompt and starts a new exchange', async () => {
+ const result = await parseConversationFile(fixturePath);
+ expect(result.exchanges).toHaveLength(2);
+
+ const [typed, channel] = result.exchanges;
+ expect(typed.userMessage).toBe('List the files in src.');
+ expect(typed.assistantMessage).toBe('parser.ts and show.ts.');
+ expect(typed.lineEnd).toBe(2);
+
+ expect(channel.userMessage).toContain('Please explain the retry policy.');
+ expect(channel.assistantMessage).toContain('exponential backoff');
+ expect(channel.lineStart).toBe(3);
+ expect(channel.lineEnd).toBe(4);
+ });
+ });
+
+ describe('Session that opens with an injected notification (no exchange open yet)', () => {
+ const fixturePath = getFixturePath('meta-first-conversation.jsonl');
+
+ it('still starts an exchange so the assistant reply is not lost', async () => {
+ const result = await parseConversationFile(fixturePath);
+ expect(result.exchanges).toHaveLength(2);
+
+ const [notice, typed] = result.exchanges;
+ expect(notice.userMessage).toContain('[SYSTEM NOTIFICATION - NOT USER INPUT]');
+ expect(notice.assistantMessage).toContain('background task finished');
+ expect(notice.lineStart).toBe(1);
+
+ expect(typed.userMessage).toBe('Now summarize what changed.');
+ expect(typed.lineStart).toBe(3);
+ });
+ });
+});
diff --git a/test/postinstall-native-check.test.ts b/test/postinstall-native-check.test.ts
new file mode 100644
index 00000000..9718c173
--- /dev/null
+++ b/test/postinstall-native-check.test.ts
@@ -0,0 +1,47 @@
+import { afterEach, describe, expect, it } from 'vitest';
+import { copyFileSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
+import { tmpdir } from 'node:os';
+import { join } from 'node:path';
+import { spawnSync } from 'node:child_process';
+
+const REPO_ROOT = join(import.meta.dirname, '..');
+
+describe('postinstall native-stack verification', () => {
+ let testDir: string | undefined;
+
+ afterEach(() => {
+ if (testDir) rmSync(testDir, { recursive: true, force: true });
+ });
+
+ it('reports an ABI mismatch without attempting a source rebuild', () => {
+ testDir = mkdtempSync(join(tmpdir(), 'episodic-memory-postinstall-'));
+ const scriptsDir = join(testDir, 'scripts');
+ const packageDir = join(testDir, 'node_modules', 'better-sqlite3');
+ mkdirSync(scriptsDir, { recursive: true });
+ mkdirSync(packageDir, { recursive: true });
+ copyFileSync(join(REPO_ROOT, 'scripts', 'postinstall.js'), join(scriptsDir, 'postinstall.js'));
+ writeFileSync(join(testDir, 'package.json'), JSON.stringify({ type: 'module' }));
+ writeFileSync(
+ join(packageDir, 'package.json'),
+ JSON.stringify({ name: 'better-sqlite3', version: '13.0.3', main: 'index.js' })
+ );
+ writeFileSync(
+ join(packageDir, 'index.js'),
+ `module.exports = class Database {
+ constructor() {
+ throw new Error('compiled using NODE_MODULE_VERSION 147; this Node requires NODE_MODULE_VERSION 137');
+ }
+ };`
+ );
+
+ const result = spawnSync(process.execPath, [join(scriptsDir, 'postinstall.js')], {
+ encoding: 'utf-8',
+ });
+
+ expect(result.status).toBe(1);
+ expect(result.stderr).toContain('NATIVE BINDING IS BROKEN');
+ expect(result.stderr).toContain('binary built for : NODE_MODULE_VERSION 147');
+ expect(result.stderr).not.toContain('TypeError');
+ expect(result.stderr).not.toContain('build-release');
+ });
+});
diff --git a/test/setup-isolated-config.ts b/test/setup-isolated-config.ts
index 71b3e795..9394c438 100644
--- a/test/setup-isolated-config.ts
+++ b/test/setup-isolated-config.ts
@@ -1,6 +1,7 @@
import { mkdtempSync } from 'fs';
import { tmpdir } from 'os';
import { join } from 'path';
+import { testModelCacheDir } from './test-model-cache.js';
/**
* Isolate every test run from the developer's real ~/.config/superpowers.
@@ -13,6 +14,9 @@ const isolatedRoot = mkdtempSync(join(tmpdir(), 'episodic-memory-vitest-'));
process.env.EPISODIC_MEMORY_CONFIG_DIR = join(isolatedRoot, 'superpowers');
process.env.CLAUDE_CONFIG_DIR = join(isolatedRoot, 'claude');
process.env.CODEX_HOME = join(isolatedRoot, 'codex');
+process.env.OMP_HOME = join(isolatedRoot, 'omp');
+process.env.EPISODIC_MEMORY_MODEL_CACHE_DIR = testModelCacheDir;
+process.env.EPISODIC_MEMORY_OFFLINE = '1';
// Clear any ambient summarizer-billing signals so tests get deterministic
// cost-guard (#104) and timeout (#160) behavior regardless of the developer's
diff --git a/test/sync-cli-single-instance.test.ts b/test/sync-cli-single-instance.test.ts
index b1505559..32010a76 100644
--- a/test/sync-cli-single-instance.test.ts
+++ b/test/sync-cli-single-instance.test.ts
@@ -70,6 +70,8 @@ describe('sync-cli single-instance lock (#97)', () => {
TEST_ARCHIVE_DIR: join(testDir, 'archive'),
TEST_DB_PATH: join(testDir, 'test.db'),
EPISODIC_MEMORY_CONFIG_DIR: join(testDir, 'config'),
+ EPISODIC_MEMORY_OPENCODE_DB_PATH: join(testDir, 'opencode-missing.db'),
+ EPISODIC_MEMORY_OPENCODE_TRANSCRIPT_DIR: join(testDir, 'opencode-transcripts'),
};
});
@@ -103,6 +105,24 @@ describe('sync-cli single-instance lock (#97)', () => {
expect(result.stdout).toMatch(/Sync complete/);
});
+ it('does not print a green completion headline when the offline model is unavailable', () => {
+ const transcript = join(testDir, 'projects', 'project-a', '00000000-0000-0000-0000-000000000001.jsonl');
+ writeFileSync(transcript, [
+ JSON.stringify({ type: 'user', uuid: 'user-1', parentUuid: null,
+ timestamp: '2026-01-01T00:00:00Z', message: { role: 'user', content: 'What changed?' } }),
+ JSON.stringify({ type: 'assistant', uuid: 'assistant-1', parentUuid: 'user-1',
+ timestamp: '2026-01-01T00:00:01Z', message: { role: 'assistant', content: [{ type: 'text', text: 'The build changed.' }] } })
+ ].join('\n'));
+
+ const result = runWith({ ...envOverrides,
+ EPISODIC_MEMORY_MODEL_CACHE_DIR: join(testDir, 'empty-model-cache'),
+ EPISODIC_MEMORY_OFFLINE: '1', EPISODIC_MEMORY_SKIP_SUMMARIES: '1' });
+ expect(result.status).toBe(0);
+ expect(result.stdout).toContain('Sync finished with errors');
+ expect(result.stdout).not.toContain('✅ Sync complete!');
+ expect(result.stdout).toContain('Indexed: 0');
+ });
+
it('releases the lock on normal exit — a subsequent run is not skipped', () => {
const first = runWith(envOverrides);
expect(first.status).toBe(0);
diff --git a/test/test-model-cache.ts b/test/test-model-cache.ts
new file mode 100644
index 00000000..a48f8c23
--- /dev/null
+++ b/test/test-model-cache.ts
@@ -0,0 +1,6 @@
+import path from 'node:path';
+import { fileURLToPath } from 'node:url';
+
+export const testModelCacheDir = path.join(
+ path.dirname(fileURLToPath(import.meta.url)), '..', 'tmp', 'test-model-cache'
+);
diff --git a/test/test-runtime-isolation.test.ts b/test/test-runtime-isolation.test.ts
new file mode 100644
index 00000000..1fc72625
--- /dev/null
+++ b/test/test-runtime-isolation.test.ts
@@ -0,0 +1,18 @@
+import { describe, expect, it } from 'vitest';
+import path from 'node:path';
+import { fileURLToPath } from 'node:url';
+
+const projectRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
+
+describe('test runtime isolation', () => {
+ it('uses a repository-owned model cache and disables worker downloads', () => {
+ expect(process.env.EPISODIC_MEMORY_MODEL_CACHE_DIR).toBe(path.join(projectRoot, 'tmp', 'test-model-cache'));
+ expect(process.env.EPISODIC_MEMORY_OFFLINE).toBe('1');
+ });
+
+ it('does not discover ambient OMP sessions', () => {
+ const configDir = process.env.EPISODIC_MEMORY_CONFIG_DIR;
+ expect(configDir).toBeDefined();
+ expect(process.env.OMP_HOME).toBe(path.join(path.dirname(configDir!), 'omp'));
+ });
+});